]> www.infradead.org Git - users/hch/misc.git/commitdiff
fuse: reflect cached blocksize if blocksize was changed
authorJoanne Koong <joannelkoong@gmail.com>
Fri, 15 Aug 2025 18:25:38 +0000 (11:25 -0700)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 26 Aug 2025 10:43:31 +0000 (12:43 +0200)
As pointed out by Miklos[1], in the fuse_update_get_attr() path, the
attributes returned to stat may be cached values instead of fresh ones
fetched from the server. In the case where the server returned a
modified blocksize value, we need to cache it and reflect it back to
stat if values are not re-fetched since we now no longer directly change
inode->i_blkbits.

Link: https://lore.kernel.org/linux-fsdevel/CAJfpeguCOxeVX88_zPd1hqziB_C+tmfuDhZP5qO2nKmnb-dTUA@mail.gmail.com/
Fixes: 542ede096e48 ("fuse: keep inode->i_blkbits constant")
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dir.c
fs/fuse/fuse_i.h
fs/fuse/inode.c

index 2d817d7cab2649c5384affd5a9e99462e6af320e..ebee7e0b1cd37ad12a5624ee4547e8fa9d88e387 100644 (file)
@@ -1377,6 +1377,7 @@ retry:
                generic_fillattr(idmap, request_mask, inode, stat);
                stat->mode = fi->orig_i_mode;
                stat->ino = fi->orig_ino;
+               stat->blksize = 1 << fi->cached_i_blkbits;
                if (test_bit(FUSE_I_BTIME, &fi->state)) {
                        stat->btime = fi->i_btime;
                        stat->result_mask |= STATX_BTIME;
index ec248d13c8bfd95082a2ae8301484f45cd729030..1647eb7ca6fa6bd018b6a3dd12bd2281d3cbe8c5 100644 (file)
@@ -210,6 +210,12 @@ struct fuse_inode {
        /** Reference to backing file in passthrough mode */
        struct fuse_backing *fb;
 #endif
+
+       /*
+        * The underlying inode->i_blkbits value will not be modified,
+        * so preserve the blocksize specified by the server.
+        */
+       u8 cached_i_blkbits;
 };
 
 /** FUSE inode state bits */
index 67c2318bfc42941602345ca6b626801845241417..3bfd83469d9f9df1e102c91048ac2ad4790f4946 100644 (file)
@@ -289,6 +289,11 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
                }
        }
 
+       if (attr->blksize)
+               fi->cached_i_blkbits = ilog2(attr->blksize);
+       else
+               fi->cached_i_blkbits = inode->i_sb->s_blocksize_bits;
+
        /*
         * Don't set the sticky bit in i_mode, unless we want the VFS
         * to check permissions.  This prevents failures due to the