]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fuse: Move prefaulting out of hot write path
authorDave Hansen <dave.hansen@linux.intel.com>
Wed, 29 Jan 2025 18:17:56 +0000 (10:17 -0800)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 15 Apr 2025 08:41:35 +0000 (10:41 +0200)
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>
fs/fuse/file.c

index 754378dd9f7159f20fde6376962d45c4c706b868..70dacbe5eae7edc46da69532783e6ce60a6426af 100644 (file)
@@ -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;
                }