From faa794dd2e17e74cc0c8fdb6742dfb6ca3c182d0 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Wed, 29 Jan 2025 10:17:56 -0800 Subject: [PATCH] fuse: Move prefaulting out of hot write path 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 Signed-off-by: Miklos Szeredi --- fs/fuse/file.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 754378dd9f715..70dacbe5eae7e 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1243,10 +1243,6 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, 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)) { @@ -1263,6 +1259,16 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, 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; } -- 2.47.2