Commit 79569946 authored by Joanne Koong's avatar Joanne Koong Committed by Miklos Szeredi
Browse files

fuse: reflect cached blocksize if blocksize was changed

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/

 [1]

Fixes: 542ede09 ("fuse: keep inode->i_blkbits constant")
Signed-off-by: default avatarJoanne Koong <joannelkoong@gmail.com>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 1e08938c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1377,6 +1377,7 @@ static int fuse_update_get_attr(struct mnt_idmap *idmap, struct inode *inode,
		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;
+6 −0
Original line number Diff line number Diff line
@@ -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 */
+5 −0
Original line number Diff line number Diff line
@@ -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