]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fuse: simplify logic in fuse_notify_store() and fuse_retrieve()
authorJoanne Koong <joannelkoong@gmail.com>
Tue, 20 Jan 2026 22:44:47 +0000 (14:44 -0800)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 3 Mar 2026 16:43:26 +0000 (17:43 +0100)
Simplify the folio parsing logic in fuse_notify_store() and
fuse_retrieve().

In particular, calculate the index by tracking pos, which allows us to
remove calculating nr_pages, and use "pos" in place of outarg's offset
field.

Suggested-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dev.c

index 8e23ec84ec8a9ab6465b421276a53ec9fb3ef091..18622bf805d6fdd2d01fd15461de0814f3f694e2 100644 (file)
@@ -1767,10 +1767,9 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
        struct address_space *mapping;
        u64 nodeid;
        int err;
-       pgoff_t index;
-       unsigned int offset;
        unsigned int num;
        loff_t file_size;
+       loff_t pos;
        loff_t end;
 
        if (size < sizeof(outarg))
@@ -1787,7 +1786,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
                return -EINVAL;
 
        nodeid = outarg.nodeid;
-       num = min(outarg.size, MAX_LFS_FILESIZE - outarg.offset);
+       pos = outarg.offset;
+       num = min(outarg.size, MAX_LFS_FILESIZE - pos);
 
        down_read(&fc->killsb);
 
@@ -1797,10 +1797,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
                goto out_up_killsb;
 
        mapping = inode->i_mapping;
-       index = outarg.offset >> PAGE_SHIFT;
-       offset = outarg.offset & ~PAGE_MASK;
        file_size = i_size_read(inode);
-       end = outarg.offset + num;
+       end = pos + num;
        if (end > file_size) {
                file_size = end;
                fuse_write_update_attr(inode, file_size, num);
@@ -1810,19 +1808,18 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
                struct folio *folio;
                unsigned int folio_offset;
                unsigned int nr_bytes;
-               unsigned int nr_pages;
+               pgoff_t index = pos >> PAGE_SHIFT;
 
                folio = filemap_grab_folio(mapping, index);
                err = PTR_ERR(folio);
                if (IS_ERR(folio))
                        goto out_iput;
 
-               folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset;
+               folio_offset = offset_in_folio(folio, pos);
                nr_bytes = min(num, folio_size(folio) - folio_offset);
-               nr_pages = (offset + nr_bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
                err = fuse_copy_folio(cs, &folio, folio_offset, nr_bytes, 0);
-               if (!folio_test_uptodate(folio) && !err && offset == 0 &&
+               if (!folio_test_uptodate(folio) && !err && folio_offset == 0 &&
                    (nr_bytes == folio_size(folio) || file_size == end)) {
                        folio_zero_segment(folio, nr_bytes, folio_size(folio));
                        folio_mark_uptodate(folio);
@@ -1833,9 +1830,8 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
                if (err)
                        goto out_iput;
 
+               pos += nr_bytes;
                num -= nr_bytes;
-               offset = 0;
-               index += nr_pages;
        }
 
        err = 0;
@@ -1867,7 +1863,6 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
 {
        int err;
        struct address_space *mapping = inode->i_mapping;
-       pgoff_t index;
        loff_t file_size;
        unsigned int num;
        unsigned int offset;
@@ -1878,15 +1873,16 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
        size_t args_size = sizeof(*ra);
        struct fuse_args_pages *ap;
        struct fuse_args *args;
+       loff_t pos = outarg->offset;
 
-       offset = outarg->offset & ~PAGE_MASK;
+       offset = offset_in_page(pos);
        file_size = i_size_read(inode);
 
        num = min(outarg->size, fc->max_write);
-       if (outarg->offset > file_size)
+       if (pos > file_size)
                num = 0;
-       else if (num > file_size - outarg->offset)
-               num = file_size - outarg->offset;
+       else if (num > file_size - pos)
+               num = file_size - pos;
 
        num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
        num_pages = min(num_pages, fc->max_pages);
@@ -1909,31 +1905,27 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
        args->in_pages = true;
        args->end = fuse_retrieve_end;
 
-       index = outarg->offset >> PAGE_SHIFT;
-
        while (num && ap->num_folios < num_pages) {
                struct folio *folio;
                unsigned int folio_offset;
                unsigned int nr_bytes;
-               unsigned int nr_pages;
+               pgoff_t index = pos >> PAGE_SHIFT;
 
                folio = filemap_get_folio(mapping, index);
                if (IS_ERR(folio))
                        break;
 
-               folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset;
+               folio_offset = offset_in_folio(folio, pos);
                nr_bytes = min(folio_size(folio) - folio_offset, num);
-               nr_pages = (offset + nr_bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
                ap->folios[ap->num_folios] = folio;
                ap->descs[ap->num_folios].offset = folio_offset;
                ap->descs[ap->num_folios].length = nr_bytes;
                ap->num_folios++;
 
-               offset = 0;
+               pos += nr_bytes;
                num -= nr_bytes;
                total_len += nr_bytes;
-               index += nr_pages;
        }
        ra->inarg.offset = outarg->offset;
        ra->inarg.size = total_len;