Skip to content

Commit 1ca4169

Browse files
dhowellsbrauner
authored andcommitted
netfs: Fix missing wakeup after issuing writes
After dividing up a proposed write into subrequests, netfslib sets NETFS_RREQ_ALL_QUEUED to indicate to the collector that it can move on to the final cleanup once it has emptied the subrequest queues. Now, whilst the collector will normally end up running at least once after this bit is set just because it takes a while to process all the write subrequests before the collector runs out of subrequests, there exists the possibility that the issuing thread will be forced to sleep and the collector thread will clean up all the subrequests before ALL_QUEUED gets set. In such a case, the collector thread will not get triggered again and will never clear NETFS_RREQ_IN_PROGRESS thus leaving a request uncompleted and causing a potential futute hang. Fix this by scheduling the write collector if all the subrequest queues are empty (and thus no writes pending issuance). Note that we'd do this ideally before queuing the subrequest, but in the case of buffered writeback, at least, we can't find out that we've run out of folios until after we've called writeback_iter() and it has returned NULL - at which point we might not actually have any subrequests still under construction. Fixes: 288ace2 ("netfs: New writeback implementation") Signed-off-by: David Howells <[email protected]> Link: https://lore.kernel.org/r/[email protected] cc: Jeff Layton <[email protected]> cc: [email protected] cc: [email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent 59d39b9 commit 1ca4169

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

fs/netfs/write_issue.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,30 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
508508
return 0;
509509
}
510510

511+
/*
512+
* End the issuing of writes, letting the collector know we're done.
513+
*/
514+
static void netfs_end_issue_write(struct netfs_io_request *wreq)
515+
{
516+
bool needs_poke = true;
517+
518+
smp_wmb(); /* Write subreq lists before ALL_QUEUED. */
519+
set_bit(NETFS_RREQ_ALL_QUEUED, &wreq->flags);
520+
521+
for (int s = 0; s < NR_IO_STREAMS; s++) {
522+
struct netfs_io_stream *stream = &wreq->io_streams[s];
523+
524+
if (!stream->active)
525+
continue;
526+
if (!list_empty(&stream->subrequests))
527+
needs_poke = false;
528+
netfs_issue_write(wreq, stream);
529+
}
530+
531+
if (needs_poke)
532+
netfs_wake_write_collector(wreq, false);
533+
}
534+
511535
/*
512536
* Write some of the pending data back to the server
513537
*/
@@ -559,10 +583,7 @@ int netfs_writepages(struct address_space *mapping,
559583
break;
560584
} while ((folio = writeback_iter(mapping, wbc, folio, &error)));
561585

562-
for (int s = 0; s < NR_IO_STREAMS; s++)
563-
netfs_issue_write(wreq, &wreq->io_streams[s]);
564-
smp_wmb(); /* Write lists before ALL_QUEUED. */
565-
set_bit(NETFS_RREQ_ALL_QUEUED, &wreq->flags);
586+
netfs_end_issue_write(wreq);
566587

567588
mutex_unlock(&ictx->wb_lock);
568589

@@ -650,10 +671,7 @@ int netfs_end_writethrough(struct netfs_io_request *wreq, struct writeback_contr
650671
if (writethrough_cache)
651672
netfs_write_folio(wreq, wbc, writethrough_cache);
652673

653-
netfs_issue_write(wreq, &wreq->io_streams[0]);
654-
netfs_issue_write(wreq, &wreq->io_streams[1]);
655-
smp_wmb(); /* Write lists before ALL_QUEUED. */
656-
set_bit(NETFS_RREQ_ALL_QUEUED, &wreq->flags);
674+
netfs_end_issue_write(wreq);
657675

658676
mutex_unlock(&ictx->wb_lock);
659677

@@ -699,13 +717,7 @@ int netfs_unbuffered_write(struct netfs_io_request *wreq, bool may_wait, size_t
699717
break;
700718
}
701719

702-
netfs_issue_write(wreq, upload);
703-
704-
smp_wmb(); /* Write lists before ALL_QUEUED. */
705-
set_bit(NETFS_RREQ_ALL_QUEUED, &wreq->flags);
706-
if (list_empty(&upload->subrequests))
707-
netfs_wake_write_collector(wreq, false);
708-
720+
netfs_end_issue_write(wreq);
709721
_leave(" = %d", error);
710722
return error;
711723
}

0 commit comments

Comments
 (0)