1
0

write_collect.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Network filesystem write subrequest result collection, assessment
  3. * and retrying.
  4. *
  5. * Copyright (C) 2024 Red Hat, Inc. All Rights Reserved.
  6. * Written by David Howells (dhowells@redhat.com)
  7. */
  8. #include <linux/export.h>
  9. #include <linux/fs.h>
  10. #include <linux/mm.h>
  11. #include <linux/pagemap.h>
  12. #include <linux/slab.h>
  13. #include "internal.h"
  14. /* Notes made in the collector */
  15. #define HIT_PENDING 0x01 /* A front op was still pending */
  16. #define NEED_REASSESS 0x02 /* Need to loop round and reassess */
  17. #define MADE_PROGRESS 0x04 /* Made progress cleaning up a stream or the folio set */
  18. #define NEED_UNLOCK 0x08 /* The pagecache needs unlocking */
  19. #define NEED_RETRY 0x10 /* A front op requests retrying */
  20. #define SAW_FAILURE 0x20 /* One stream or hit a permanent failure */
  21. static void netfs_dump_request(const struct netfs_io_request *rreq)
  22. {
  23. pr_err("Request R=%08x r=%d fl=%lx or=%x e=%ld\n",
  24. rreq->debug_id, refcount_read(&rreq->ref), rreq->flags,
  25. rreq->origin, rreq->error);
  26. pr_err(" st=%llx tsl=%zx/%llx/%llx\n",
  27. rreq->start, rreq->transferred, rreq->submitted, rreq->len);
  28. pr_err(" cci=%llx/%llx/%llx\n",
  29. rreq->cleaned_to, rreq->collected_to, atomic64_read(&rreq->issued_to));
  30. pr_err(" iw=%pSR\n", rreq->netfs_ops->issue_write);
  31. for (int i = 0; i < NR_IO_STREAMS; i++) {
  32. const struct netfs_io_subrequest *sreq;
  33. const struct netfs_io_stream *s = &rreq->io_streams[i];
  34. pr_err(" str[%x] s=%x e=%d acnf=%u,%u,%u,%u\n",
  35. s->stream_nr, s->source, s->error,
  36. s->avail, s->active, s->need_retry, s->failed);
  37. pr_err(" str[%x] ct=%llx t=%zx\n",
  38. s->stream_nr, s->collected_to, s->transferred);
  39. list_for_each_entry(sreq, &s->subrequests, rreq_link) {
  40. pr_err(" sreq[%x:%x] sc=%u s=%llx t=%zx/%zx r=%d f=%lx\n",
  41. sreq->stream_nr, sreq->debug_index, sreq->source,
  42. sreq->start, sreq->transferred, sreq->len,
  43. refcount_read(&sreq->ref), sreq->flags);
  44. }
  45. }
  46. }
  47. /*
  48. * Successful completion of write of a folio to the server and/or cache. Note
  49. * that we are not allowed to lock the folio here on pain of deadlocking with
  50. * truncate.
  51. */
  52. int netfs_folio_written_back(struct folio *folio)
  53. {
  54. enum netfs_folio_trace why = netfs_folio_trace_clear;
  55. struct netfs_inode *ictx = netfs_inode(folio->mapping->host);
  56. struct netfs_folio *finfo;
  57. struct netfs_group *group = NULL;
  58. int gcount = 0;
  59. if ((finfo = netfs_folio_info(folio))) {
  60. /* Streaming writes cannot be redirtied whilst under writeback,
  61. * so discard the streaming record.
  62. */
  63. unsigned long long fend;
  64. fend = folio_pos(folio) + finfo->dirty_offset + finfo->dirty_len;
  65. if (fend > ictx->zero_point)
  66. ictx->zero_point = fend;
  67. folio_detach_private(folio);
  68. group = finfo->netfs_group;
  69. gcount++;
  70. kfree(finfo);
  71. why = netfs_folio_trace_clear_s;
  72. goto end_wb;
  73. }
  74. if ((group = netfs_folio_group(folio))) {
  75. if (group == NETFS_FOLIO_COPY_TO_CACHE) {
  76. why = netfs_folio_trace_clear_cc;
  77. folio_detach_private(folio);
  78. goto end_wb;
  79. }
  80. /* Need to detach the group pointer if the page didn't get
  81. * redirtied. If it has been redirtied, then it must be within
  82. * the same group.
  83. */
  84. why = netfs_folio_trace_redirtied;
  85. if (!folio_test_dirty(folio)) {
  86. folio_detach_private(folio);
  87. gcount++;
  88. why = netfs_folio_trace_clear_g;
  89. }
  90. }
  91. end_wb:
  92. trace_netfs_folio(folio, why);
  93. folio_end_writeback(folio);
  94. return gcount;
  95. }
  96. /*
  97. * Unlock any folios we've finished with.
  98. */
  99. static void netfs_writeback_unlock_folios(struct netfs_io_request *wreq,
  100. unsigned int *notes)
  101. {
  102. struct folio_queue *folioq = wreq->buffer.tail;
  103. unsigned long long collected_to = wreq->collected_to;
  104. unsigned int slot = wreq->buffer.first_tail_slot;
  105. if (WARN_ON_ONCE(!folioq)) {
  106. pr_err("[!] Writeback unlock found empty rolling buffer!\n");
  107. netfs_dump_request(wreq);
  108. return;
  109. }
  110. if (wreq->origin == NETFS_PGPRIV2_COPY_TO_CACHE) {
  111. if (netfs_pgpriv2_unlock_copied_folios(wreq))
  112. *notes |= MADE_PROGRESS;
  113. return;
  114. }
  115. if (slot >= folioq_nr_slots(folioq)) {
  116. folioq = rolling_buffer_delete_spent(&wreq->buffer);
  117. if (!folioq)
  118. return;
  119. slot = 0;
  120. }
  121. for (;;) {
  122. struct folio *folio;
  123. struct netfs_folio *finfo;
  124. unsigned long long fpos, fend;
  125. size_t fsize, flen;
  126. folio = folioq_folio(folioq, slot);
  127. if (WARN_ONCE(!folio_test_writeback(folio),
  128. "R=%08x: folio %lx is not under writeback\n",
  129. wreq->debug_id, folio->index))
  130. trace_netfs_folio(folio, netfs_folio_trace_not_under_wback);
  131. fpos = folio_pos(folio);
  132. fsize = folio_size(folio);
  133. finfo = netfs_folio_info(folio);
  134. flen = finfo ? finfo->dirty_offset + finfo->dirty_len : fsize;
  135. fend = min_t(unsigned long long, fpos + flen, wreq->i_size);
  136. trace_netfs_collect_folio(wreq, folio, fend, collected_to);
  137. /* Unlock any folio we've transferred all of. */
  138. if (collected_to < fend)
  139. break;
  140. wreq->nr_group_rel += netfs_folio_written_back(folio);
  141. wreq->cleaned_to = fpos + fsize;
  142. *notes |= MADE_PROGRESS;
  143. /* Clean up the head folioq. If we clear an entire folioq, then
  144. * we can get rid of it provided it's not also the tail folioq
  145. * being filled by the issuer.
  146. */
  147. folioq_clear(folioq, slot);
  148. slot++;
  149. if (slot >= folioq_nr_slots(folioq)) {
  150. folioq = rolling_buffer_delete_spent(&wreq->buffer);
  151. if (!folioq)
  152. goto done;
  153. slot = 0;
  154. }
  155. if (fpos + fsize >= collected_to)
  156. break;
  157. }
  158. wreq->buffer.tail = folioq;
  159. done:
  160. wreq->buffer.first_tail_slot = slot;
  161. }
  162. /*
  163. * Collect and assess the results of various write subrequests. We may need to
  164. * retry some of the results - or even do an RMW cycle for content crypto.
  165. *
  166. * Note that we have a number of parallel, overlapping lists of subrequests,
  167. * one to the server and one to the local cache for example, which may not be
  168. * the same size or starting position and may not even correspond in boundary
  169. * alignment.
  170. */
  171. static void netfs_collect_write_results(struct netfs_io_request *wreq)
  172. {
  173. struct netfs_io_subrequest *front, *remove;
  174. struct netfs_io_stream *stream;
  175. unsigned long long collected_to, issued_to;
  176. unsigned int notes;
  177. int s;
  178. _enter("%llx-%llx", wreq->start, wreq->start + wreq->len);
  179. trace_netfs_collect(wreq);
  180. trace_netfs_rreq(wreq, netfs_rreq_trace_collect);
  181. reassess_streams:
  182. issued_to = atomic64_read(&wreq->issued_to);
  183. smp_rmb();
  184. collected_to = ULLONG_MAX;
  185. if (wreq->origin == NETFS_WRITEBACK ||
  186. wreq->origin == NETFS_WRITETHROUGH ||
  187. wreq->origin == NETFS_PGPRIV2_COPY_TO_CACHE)
  188. notes = NEED_UNLOCK;
  189. else
  190. notes = 0;
  191. /* Remove completed subrequests from the front of the streams and
  192. * advance the completion point on each stream. We stop when we hit
  193. * something that's in progress. The issuer thread may be adding stuff
  194. * to the tail whilst we're doing this.
  195. */
  196. for (s = 0; s < NR_IO_STREAMS; s++) {
  197. stream = &wreq->io_streams[s];
  198. /* Read active flag before list pointers */
  199. if (!smp_load_acquire(&stream->active))
  200. continue;
  201. front = list_first_entry_or_null(&stream->subrequests,
  202. struct netfs_io_subrequest, rreq_link);
  203. while (front) {
  204. trace_netfs_collect_sreq(wreq, front);
  205. //_debug("sreq [%x] %llx %zx/%zx",
  206. // front->debug_index, front->start, front->transferred, front->len);
  207. if (stream->collected_to < front->start) {
  208. trace_netfs_collect_gap(wreq, stream, issued_to, 'F');
  209. stream->collected_to = front->start;
  210. }
  211. /* Stall if the front is still undergoing I/O. */
  212. if (netfs_check_subreq_in_progress(front)) {
  213. notes |= HIT_PENDING;
  214. break;
  215. }
  216. smp_rmb(); /* Read counters after I-P flag. */
  217. if (stream->failed) {
  218. stream->collected_to = front->start + front->len;
  219. notes |= MADE_PROGRESS | SAW_FAILURE;
  220. goto cancel;
  221. }
  222. if (front->start + front->transferred > stream->collected_to) {
  223. stream->collected_to = front->start + front->transferred;
  224. stream->transferred = stream->collected_to - wreq->start;
  225. stream->transferred_valid = true;
  226. notes |= MADE_PROGRESS;
  227. }
  228. if (test_bit(NETFS_SREQ_FAILED, &front->flags)) {
  229. stream->failed = true;
  230. stream->error = front->error;
  231. if (stream->source == NETFS_UPLOAD_TO_SERVER)
  232. mapping_set_error(wreq->mapping, front->error);
  233. notes |= NEED_REASSESS | SAW_FAILURE;
  234. break;
  235. }
  236. if (front->transferred < front->len) {
  237. stream->need_retry = true;
  238. notes |= NEED_RETRY | MADE_PROGRESS;
  239. break;
  240. }
  241. cancel:
  242. /* Remove if completely consumed. */
  243. spin_lock(&wreq->lock);
  244. remove = front;
  245. list_del_init(&front->rreq_link);
  246. front = list_first_entry_or_null(&stream->subrequests,
  247. struct netfs_io_subrequest, rreq_link);
  248. spin_unlock(&wreq->lock);
  249. netfs_put_subrequest(remove,
  250. notes & SAW_FAILURE ?
  251. netfs_sreq_trace_put_cancel :
  252. netfs_sreq_trace_put_done);
  253. }
  254. /* If we have an empty stream, we need to jump it forward
  255. * otherwise the collection point will never advance.
  256. */
  257. if (!front && issued_to > stream->collected_to) {
  258. trace_netfs_collect_gap(wreq, stream, issued_to, 'E');
  259. stream->collected_to = issued_to;
  260. }
  261. if (stream->collected_to < collected_to)
  262. collected_to = stream->collected_to;
  263. }
  264. if (collected_to != ULLONG_MAX && collected_to > wreq->collected_to)
  265. wreq->collected_to = collected_to;
  266. for (s = 0; s < NR_IO_STREAMS; s++) {
  267. stream = &wreq->io_streams[s];
  268. if (stream->active)
  269. trace_netfs_collect_stream(wreq, stream);
  270. }
  271. trace_netfs_collect_state(wreq, wreq->collected_to, notes);
  272. /* Unlock any folios that we have now finished with. */
  273. if (notes & NEED_UNLOCK) {
  274. if (wreq->cleaned_to < wreq->collected_to)
  275. netfs_writeback_unlock_folios(wreq, &notes);
  276. } else {
  277. wreq->cleaned_to = wreq->collected_to;
  278. }
  279. // TODO: Discard encryption buffers
  280. if (notes & NEED_RETRY)
  281. goto need_retry;
  282. if (notes & MADE_PROGRESS) {
  283. netfs_wake_rreq_flag(wreq, NETFS_RREQ_PAUSE, netfs_rreq_trace_unpause);
  284. //cond_resched();
  285. goto reassess_streams;
  286. }
  287. if (notes & NEED_REASSESS) {
  288. //cond_resched();
  289. goto reassess_streams;
  290. }
  291. out:
  292. netfs_put_group_many(wreq->group, wreq->nr_group_rel);
  293. wreq->nr_group_rel = 0;
  294. _leave(" = %x", notes);
  295. return;
  296. need_retry:
  297. /* Okay... We're going to have to retry one or both streams. Note
  298. * that any partially completed op will have had any wholly transferred
  299. * folios removed from it.
  300. */
  301. _debug("retry");
  302. netfs_retry_writes(wreq);
  303. goto out;
  304. }
  305. /*
  306. * Perform the collection of subrequests, folios and encryption buffers.
  307. */
  308. bool netfs_write_collection(struct netfs_io_request *wreq)
  309. {
  310. struct netfs_inode *ictx = netfs_inode(wreq->inode);
  311. size_t transferred;
  312. bool transferred_valid = false;
  313. int s;
  314. _enter("R=%x", wreq->debug_id);
  315. netfs_collect_write_results(wreq);
  316. /* We're done when the app thread has finished posting subreqs and all
  317. * the queues in all the streams are empty.
  318. */
  319. if (!test_bit(NETFS_RREQ_ALL_QUEUED, &wreq->flags))
  320. return false;
  321. smp_rmb(); /* Read ALL_QUEUED before lists. */
  322. transferred = LONG_MAX;
  323. for (s = 0; s < NR_IO_STREAMS; s++) {
  324. struct netfs_io_stream *stream = &wreq->io_streams[s];
  325. if (!stream->active)
  326. continue;
  327. if (!list_empty(&stream->subrequests))
  328. return false;
  329. if (stream->transferred_valid &&
  330. stream->transferred < transferred) {
  331. transferred = stream->transferred;
  332. transferred_valid = true;
  333. }
  334. }
  335. /* Okay, declare that all I/O is complete. */
  336. if (transferred_valid)
  337. wreq->transferred = transferred;
  338. trace_netfs_rreq(wreq, netfs_rreq_trace_write_done);
  339. if (wreq->io_streams[1].active &&
  340. wreq->io_streams[1].failed &&
  341. ictx->ops->invalidate_cache) {
  342. /* Cache write failure doesn't prevent writeback completion
  343. * unless we're in disconnected mode.
  344. */
  345. ictx->ops->invalidate_cache(wreq);
  346. }
  347. _debug("finished");
  348. netfs_wake_rreq_flag(wreq, NETFS_RREQ_IN_PROGRESS, netfs_rreq_trace_wake_ip);
  349. /* As we cleared NETFS_RREQ_IN_PROGRESS, we acquired its ref. */
  350. if (wreq->iocb) {
  351. size_t written = min(wreq->transferred, wreq->len);
  352. wreq->iocb->ki_pos += written;
  353. if (wreq->iocb->ki_complete) {
  354. trace_netfs_rreq(wreq, netfs_rreq_trace_ki_complete);
  355. wreq->iocb->ki_complete(
  356. wreq->iocb, wreq->error ? wreq->error : written);
  357. }
  358. wreq->iocb = VFS_PTR_POISON;
  359. }
  360. netfs_clear_subrequests(wreq);
  361. return true;
  362. }
  363. void netfs_write_collection_worker(struct work_struct *work)
  364. {
  365. struct netfs_io_request *rreq = container_of(work, struct netfs_io_request, work);
  366. netfs_see_request(rreq, netfs_rreq_trace_see_work);
  367. if (netfs_check_rreq_in_progress(rreq)) {
  368. if (netfs_write_collection(rreq))
  369. /* Drop the ref from the IN_PROGRESS flag. */
  370. netfs_put_request(rreq, netfs_rreq_trace_put_work_ip);
  371. else
  372. netfs_see_request(rreq, netfs_rreq_trace_see_work_complete);
  373. }
  374. }
  375. /**
  376. * netfs_write_subrequest_terminated - Note the termination of a write operation.
  377. * @_op: The I/O request that has terminated.
  378. * @transferred_or_error: The amount of data transferred or an error code.
  379. *
  380. * This tells the library that a contributory write I/O operation has
  381. * terminated, one way or another, and that it should collect the results.
  382. *
  383. * The caller indicates in @transferred_or_error the outcome of the operation,
  384. * supplying a positive value to indicate the number of bytes transferred or a
  385. * negative error code. The library will look after reissuing I/O operations
  386. * as appropriate and writing downloaded data to the cache.
  387. *
  388. * When this is called, ownership of the subrequest is transferred back to the
  389. * library, along with a ref.
  390. *
  391. * Note that %_op is a void* so that the function can be passed to
  392. * kiocb::term_func without the need for a casting wrapper.
  393. */
  394. void netfs_write_subrequest_terminated(void *_op, ssize_t transferred_or_error)
  395. {
  396. struct netfs_io_subrequest *subreq = _op;
  397. struct netfs_io_request *wreq = subreq->rreq;
  398. _enter("%x[%x] %zd", wreq->debug_id, subreq->debug_index, transferred_or_error);
  399. switch (subreq->source) {
  400. case NETFS_UPLOAD_TO_SERVER:
  401. netfs_stat(&netfs_n_wh_upload_done);
  402. break;
  403. case NETFS_WRITE_TO_CACHE:
  404. netfs_stat(&netfs_n_wh_write_done);
  405. break;
  406. default:
  407. BUG();
  408. }
  409. if (IS_ERR_VALUE(transferred_or_error)) {
  410. subreq->error = transferred_or_error;
  411. /* if need retry is set, error should not matter */
  412. if (!test_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) {
  413. set_bit(NETFS_SREQ_FAILED, &subreq->flags);
  414. trace_netfs_failure(wreq, subreq, transferred_or_error, netfs_fail_write);
  415. }
  416. switch (subreq->source) {
  417. case NETFS_WRITE_TO_CACHE:
  418. netfs_stat(&netfs_n_wh_write_failed);
  419. break;
  420. case NETFS_UPLOAD_TO_SERVER:
  421. netfs_stat(&netfs_n_wh_upload_failed);
  422. break;
  423. default:
  424. break;
  425. }
  426. trace_netfs_rreq(wreq, netfs_rreq_trace_set_pause);
  427. set_bit(NETFS_RREQ_PAUSE, &wreq->flags);
  428. } else {
  429. if (WARN(transferred_or_error > subreq->len - subreq->transferred,
  430. "Subreq excess write: R=%x[%x] %zd > %zu - %zu",
  431. wreq->debug_id, subreq->debug_index,
  432. transferred_or_error, subreq->len, subreq->transferred))
  433. transferred_or_error = subreq->len - subreq->transferred;
  434. subreq->error = 0;
  435. subreq->transferred += transferred_or_error;
  436. if (subreq->transferred < subreq->len)
  437. set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
  438. }
  439. trace_netfs_sreq(subreq, netfs_sreq_trace_terminated);
  440. netfs_subreq_clear_in_progress(subreq);
  441. netfs_put_subrequest(subreq, netfs_sreq_trace_put_terminated);
  442. }
  443. EXPORT_SYMBOL(netfs_write_subrequest_terminated);