Re: [PATCH] netfs: fix ENOMEM handling in netfs_writepages() to drain all dirty folios
"Zhou, Yun" <[email protected]> Sun, 19 Jul 2026 20:32:20 +0800
| Newsgroups | dev.linux.lists.netfs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Friendly ping. On 7/7/2026 1:25 PM, Yun Zhou wrote: > When netfs_create_write_req() fails with -ENOMEM in netfs_writepages(), > the couldnt_start error path redirties and unlocks the first folio, then > calls writeback_iter() expecting it to return NULL. However, if the > mapping contains multiple dirty folios, writeback_iter() returns the > next one, triggering WARN_ON_ONCE(folio != NULL). > > This can be reproduced via 9p (cache=loose) with shared mmap writes and > fault injection (fail_nth), where v9fs_mmap_vm_close() triggers > writeback on a mapping with multiple dirty folios during mmap overlap. > > Fix this by looping over all remaining dirty folios in the ENOMEM path, > redirtying and unlocking each one. This ensures all folios taken by the > writeback iterator are properly released, and they will be retried on > the next writeback cycle when memory is available. > > Reported-by: [email protected] > Closes: https://syzkaller.appspot.com/bug?extid=0da43efa72f88bd3a8af > Fixes: ac5f95ac5d6d ("netfs: Fix writeback error handling") > Signed-off-by: Yun Zhou <[email protected]> > --- > fs/netfs/write_issue.c | 9 +++++---- > 1 file changed, 5 insertions(+), 4 deletions(-) > > diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c > index f2761c99795a..5aa47128f7e7 100644 > --- a/fs/netfs/write_issue.c > +++ b/fs/netfs/write_issue.c > @@ -597,10 +597,11 @@ int netfs_writepages(struct address_space *mapping, > > couldnt_start: > if (error == -ENOMEM) { > - folio_redirty_for_writepage(wbc, folio); > - folio_unlock(folio); > - folio = writeback_iter(mapping, wbc, folio, &error); > - WARN_ON_ONCE(folio != NULL); > + /* Redirty all dirty folios and let writeback retry later. */ > + do { > + folio_redirty_for_writepage(wbc, folio); > + folio_unlock(folio); > + } while ((folio = writeback_iter(mapping, wbc, folio, &error))); > } else { > netfs_kill_dirty_pages(mapping, wbc, folio); > }