diff options
author | 2025-01-29 10:17:56 -0800 | |
---|---|---|
committer | 2025-04-15 10:41:35 +0200 | |
commit | faa794dd2e17e74cc0c8fdb6742dfb6ca3c182d0 (patch) | |
tree | c35719578c9ba0395358bed84b32023551edb71e | |
parent | fuse: change 'unsigned' to 'unsigned int' (diff) | |
download | wireguard-linux-faa794dd2e17e74cc0c8fdb6742dfb6ca3c182d0.tar.xz wireguard-linux-faa794dd2e17e74cc0c8fdb6742dfb6ca3c182d0.zip |
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 <dave.hansen@linux.intel.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r-- | fs/fuse/file.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 754378dd9f71..70dacbe5eae7 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; } |