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);
>   	}