]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fuse: remove fuse_readpages_end() null mapping check
authorJoanne Koong <joannelkoong@gmail.com>
Fri, 29 Aug 2025 23:56:27 +0000 (16:56 -0700)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 2 Sep 2025 09:14:15 +0000 (11:14 +0200)
Remove extra logic in fuse_readpages_end() that checks against null
folio mappings. This was added in commit ce534fb05292 ("fuse: allow
splice to move pages"):

"Since the remove_from_page_cache() + add_to_page_cache_locked()
are non-atomic it is possible that the page cache is repopulated in
between the two and add_to_page_cache_locked() will fail.  This
could be fixed by creating a new atomic replace_page_cache_page()
function.

fuse_readpages_end() needed to be reworked so it works even if
page->mapping is NULL for some or all pages which can happen if the
add_to_page_cache_locked() failed."

Commit ef6a3c63112e ("mm: add replace_page_cache_page() function") added
atomic page cache replacement, which means the check against null
mappings can be removed.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/file.c

index 0698bcb2f992372f20aae646a502b05a73d5211f..54786f62a9d8b27bb5b1ce4a347aa4519b77316f 100644 (file)
@@ -865,22 +865,20 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
        struct fuse_args_pages *ap = &ia->ap;
        size_t count = ia->read.in.size;
        size_t num_read = args->out_args[0].size;
-       struct address_space *mapping = NULL;
-
-       for (i = 0; mapping == NULL && i < ap->num_folios; i++)
-               mapping = ap->folios[i]->mapping;
+       struct address_space *mapping;
+       struct inode *inode;
 
-       if (mapping) {
-               struct inode *inode = mapping->host;
+       WARN_ON_ONCE(!ap->num_folios);
+       mapping = ap->folios[0]->mapping;
+       inode = mapping->host;
 
-               /*
-                * Short read means EOF. If file size is larger, truncate it
-                */
-               if (!err && num_read < count)
-                       fuse_short_read(inode, ia->read.attr_ver, num_read, ap);
+       /*
+        * Short read means EOF. If file size is larger, truncate it
+        */
+       if (!err && num_read < count)
+               fuse_short_read(inode, ia->read.attr_ver, num_read, ap);
 
-               fuse_invalidate_atime(inode);
-       }
+       fuse_invalidate_atime(inode);
 
        for (i = 0; i < ap->num_folios; i++) {
                folio_end_read(ap->folios[i], !err);