From: Zygo Blaxell Date: Sun, 17 Aug 2025 02:50:20 +0000 (-0400) Subject: btrfs: preserve btrfs.compression when setting inode flags X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9305ee44e25b5ca8cdba4dbfe98d395039b45344;p=linux btrfs: preserve btrfs.compression when setting inode flags Any call to FS_IOC_SETFLAGS (e.g. via chattr), even when no flag bits change, and even for flags unrelated to compression, overwrites the btrfs.compression property with the mount default compression type. Example: # mount ... -o compress=zstd ... $ touch zero $ setfattr -n btrfs.compression -v zlib zero $ getfattr -n btrfs.compression zero | grep = btrfs.compression="zlib" $ lsattr zero --------c------------- zero $ chattr +A zero $ lsattr zero -------Ac------------- zero $ getfattr -n btrfs.compression zero | grep = btrfs.compression="zstd" Here, `+A` modifies only the atime flag, but the compression property was silently replaced. The same happens even if the ioctl writes back the same flags value that was already set. The problem is that btrfs_fileattr_set unconditionally regenerates the compression string from fs_info->compress_type (or falls back to "zlib") and overwrites any existing property. Fix this by first checking for an existing per-inode compression property and using it if present. Only fall back to fs_info->compress_type or zlib when no property has been set. This ensures that inode-flag updates no longer clobber user-configured compression settings. Fixes: 63541927c8d1 ("Btrfs: add support for inode properties") Signed-off-by: Zygo Blaxell --- diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b702f625c753b..5039db10a47e8 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -365,7 +365,9 @@ int btrfs_fileattr_set(struct mnt_idmap *idmap, inode_flags |= BTRFS_INODE_COMPRESS; inode_flags &= ~BTRFS_INODE_NOCOMPRESS; - comp = btrfs_compress_type2str(fs_info->compress_type); + comp = btrfs_compress_type2str(inode->prop_compress); + if (!comp || comp[0] == 0) + comp = btrfs_compress_type2str(fs_info->compress_type); if (!comp || comp[0] == 0) comp = btrfs_compress_type2str(BTRFS_COMPRESS_ZLIB); } else {