When a page fault wants to make a folio writable but the folio belongs to a different netfs group (e.g. a ceph snap context) than the one the write is being made under, netfs_page_mkwrite() flushes the folio and retries the fault. It does so with: filemap_fdatawrite_range(mapping, folio_pos(folio), folio_next_pos(folio)); filemap_fdatawrite_range() takes an inclusive end offset, but folio_next_pos() is the position of the first byte of the following folio. The range therefore covers one byte too many, and writeback is also run on whichever folio contains that byte. filemap_fdatawrite_range() is a WB_SYNC_ALL operation documented as waiting upon dirty or in-writeback pages in the range, so the faulting task can stall behind I/O on a neighbouring folio that has nothing to do with the fault, and a neighbouring dirty folio is written out early. The off-by-one dates from the original implementation, which passed folio_pos(folio) + folio_size(folio) as the end of a filemap_fdatawait_range() call, which also takes an inclusive end. It was carried over when the call was changed to filemap_fdatawrite_range(). The flush of the faulting folio itself is unaffected, so this does not cause data loss or incorrect results, only unneeded writeback and latency. Fix it by passing folio_next_pos(folio) - 1, as the flush_content path in netfs_perform_write() already does with fpos + flen - 1. Assisted-by: LLM Fixes: 102a7e2c598c ("netfs: Allow buffered shared-writeable mmap through netfs_page_mkwrite()") Signed-off-by: Fredric Cover --- fs/netfs/buffered_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index ecf119b4f9166..b398c3bef6f3c 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -579,7 +579,7 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr folio_unlock(folio); err = filemap_fdatawrite_range(mapping, folio_pos(folio), - folio_next_pos(folio)); + folio_next_pos(folio) - 1); switch (err) { case 0: ret = VM_FAULT_RETRY; -- 2.53.0