From: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> Prefaulting the write source buffer incurs an extra userspace access in the common fast path. Make fuse_fill_write_pages() consistent with generic_perform_write(): only touch userspace an extra time when copy_folio_from_iter_atomic() has failed to make progress. Signed-off-by: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> Cc: Miklos Szeredi <miklos@xxxxxxxxxx> --- b/fs/fuse/file.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff -puN fs/fuse/file.c~fuse-postfault fs/fuse/file.c --- a/fs/fuse/file.c~fuse-postfault 2025-01-29 09:03:34.515555724 -0800 +++ b/fs/fuse/file.c 2025-01-29 09:03:34.523556390 -0800 @@ -1234,10 +1234,6 @@ static ssize_t fuse_fill_write_pages(str bytes = min_t(size_t, bytes, fc->max_write - count); again: - err = -EFAULT; - if (fault_in_iov_iter_readable(ii, bytes)) - break; - folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, mapping_gfp_mask(mapping)); if (IS_ERR(folio)) { @@ -1254,6 +1250,16 @@ static ssize_t fuse_fill_write_pages(str if (!tmp) { folio_unlock(folio); folio_put(folio); + + /* + * Ensure forward progress by faulting in + * while not holding the folio lock: + */ + if (fault_in_iov_iter_readable(ii, bytes)) { + err = -EFAULT; + break; + } + goto again; } _