With fuse using iomap, which relies on inode->i_blkbits for its internal bitmap tracking, disallow fuse servers from dynamically changing the inode blocksize. "attr->blksize = sx->blksize;" is retained in fuse_statx_to_attr() so that any attempts by the server to change the blksize through the statx reply is surfaced to dmesg. Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> Fixes: ef7e7cbb32 ("fuse: use iomap for writeback") --- fs/fuse/dir.c | 9 +-------- fs/fuse/inode.c | 6 ++---- include/uapi/linux/fuse.h | 4 ++-- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 45b4c3cc1396..df8fda289c5f 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1180,7 +1180,6 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, static void fuse_fillattr(struct mnt_idmap *idmap, struct inode *inode, struct fuse_attr *attr, struct kstat *stat) { - unsigned int blkbits; struct fuse_conn *fc = get_fuse_conn(inode); vfsuid_t vfsuid = make_vfsuid(idmap, fc->user_ns, make_kuid(fc->user_ns, attr->uid)); @@ -1202,13 +1201,7 @@ static void fuse_fillattr(struct mnt_idmap *idmap, struct inode *inode, stat->ctime.tv_nsec = attr->ctimensec; stat->size = attr->size; stat->blocks = attr->blocks; - - if (attr->blksize != 0) - blkbits = ilog2(attr->blksize); - else - blkbits = inode->i_sb->s_blocksize_bits; - - stat->blksize = 1 << blkbits; + stat->blksize = 1 << inode->i_sb->s_blocksize_bits; } static void fuse_statx_to_attr(struct fuse_statx *sx, struct fuse_attr *attr) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index bfe8d8af46f3..280896d4fd44 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -285,10 +285,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, } } - if (attr->blksize != 0) - inode->i_blkbits = ilog2(attr->blksize); - else - inode->i_blkbits = inode->i_sb->s_blocksize_bits; + if (attr->blksize && attr->blksize != inode->i_sb->s_blocksize) + pr_warn_ratelimited("changing blksize attribute is a no-op\n"); /* * Don't set the sticky bit in i_mode, unless we want the VFS diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 122d6586e8d4..4ceb6f736f4e 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -293,7 +293,7 @@ struct fuse_attr { uint32_t uid; uint32_t gid; uint32_t rdev; - uint32_t blksize; + uint32_t blksize; /* not used */ uint32_t flags; }; @@ -309,7 +309,7 @@ struct fuse_sx_time { struct fuse_statx { uint32_t mask; - uint32_t blksize; + uint32_t blksize; /* not used */ uint64_t attributes; uint32_t nlink; uint32_t uid; -- 2.47.3