When inode attribute flags is set through FS_IOC_SETFLAGS ioctl, there is a bit of duplicate codes, the following things happens twice - start/end_transaction, inode_inc_iversion(), current_time update to inode->i_ctime, and btrfs_update_inode(). These are updated both at btrfs_ioctl_setflags() and btrfs_set_props() as well. (RFC: So inode version and the generation number should have increased by +2, but I don't see that in the test case below ran without this patch)
This patch merges these two duplicate codes at btrfs_ioctl_setflags(). $ cat a mkfs.btrfs -fq /dev/sdb || exit mount /dev/sdb /btrfs touch /btrfs/file1 sync echo before: btrfs in dump-super /dev/sdb | grep ^generation btrfs in dump-tree /dev/sdb | grep -A4 "257 XATTR_ITEM" btrfs in dump-tree /dev/sdb | grep -A4 "257 INODE_ITEM 0) item" echo echo "chattr +Ac /btrfs/file1" chattr +Ac /btrfs/file1 sync echo after: btrfs in dump-super /dev/sdb | grep ^generation btrfs in dump-tree /dev/sdb | grep -A4 "257 XATTR_ITEM" btrfs in dump-tree /dev/sdb | grep -A4 "257 INODE_ITEM 0) item" $ umount /btrfs; ./a before: generation 6 item 4 key (257 INODE_ITEM 0) itemoff 15881 itemsize 160 generation 6 transid 6 size 0 nbytes 0 block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0 sequence 19 flags 0x0(none) chattr +Ac /btrfs/file1 after: generation 7 item 6 key (257 XATTR_ITEM 550297449) itemoff 15815 itemsize 51 location key (0 UNKNOWN.0 0) type XATTR transid 7 data_len 4 name_len 17 name: btrfs.compression data zlib item 4 key (257 INODE_ITEM 0) itemoff 15881 itemsize 160 generation 6 transid 7 size 0 nbytes 0 block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0 sequence 21 flags 0xa00(NOATIME|COMPRESS) Signed-off-by: Anand Jain <anand.j...@oracle.com> --- fs/btrfs/ioctl.c | 38 ++++++++++++++++++-------------------- fs/btrfs/props.c | 6 +++--- fs/btrfs/props.h | 3 +++ 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 63e6e2f5b659..82772523bb87 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -192,6 +192,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) u64 old_flags; unsigned int old_i_flags; umode_t mode; + const char *comp = NULL; if (!inode_owner_or_capable(inode)) return -EPERM; @@ -283,14 +284,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) if (fsflags & FS_NOCOMP_FL) { binode->flags &= ~BTRFS_INODE_COMPRESS; binode->flags |= BTRFS_INODE_NOCOMPRESS; - - /* set no-compression no need to validate prop here */ - ret = btrfs_set_prop_trans(inode, "btrfs.compression", NULL, - 0, 0); - if (ret && ret != -ENODATA) - goto out_drop; } else if (fsflags & FS_COMPR_FL) { - const char *comp; if (IS_SWAPFILE(inode)) { ret = -ETXTBSY; @@ -300,36 +294,40 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) binode->flags |= BTRFS_INODE_COMPRESS; binode->flags &= ~BTRFS_INODE_NOCOMPRESS; - /* compress_type is already validated during mount options */ comp = btrfs_compress_type2str(fs_info->compress_type); if (!comp || comp[0] == 0) comp = btrfs_compress_type2str(BTRFS_COMPRESS_ZLIB); - - ret = btrfs_set_prop_trans(inode, "btrfs.compression", comp, - strlen(comp), 0); - if (ret) - goto out_drop; - } else { - /* reset prop, no need of validate prop here */ - ret = btrfs_set_prop_trans(inode, "btrfs.compression", NULL, - 0, 0); - if (ret && ret != -ENODATA) - goto out_drop; binode->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS); } - trans = btrfs_start_transaction(root, 1); + trans = btrfs_start_transaction(root, 3); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out_drop; } + if (comp) { + ret = btrfs_set_prop(trans, inode, "btrfs.compression", comp, + strlen(comp), 0); + if (ret) + goto out_abort; + set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags); + } else { + ret = btrfs_set_prop(trans, inode, "btrfs.compression", NULL, + 0, 0); + if (ret && ret != -ENODATA) + goto out_abort; + } + btrfs_sync_inode_flags_to_i_flags(inode); inode_inc_iversion(inode); inode->i_ctime = current_time(inode); ret = btrfs_update_inode(trans, root, inode); + out_abort: + if (ret) + btrfs_abort_transaction(trans, ret); btrfs_end_transaction(trans); out_drop: if (ret) { diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c index e356dd2a0f73..aedf5a7d69c9 100644 --- a/fs/btrfs/props.c +++ b/fs/btrfs/props.c @@ -72,9 +72,9 @@ int btrfs_validate_prop(const char *name, const char *value, size_t value_len) return handler->validate(value, value_len); } -static int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode, - const char *name, const char *value, size_t value_len, - int flags) +int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode, + const char *name, const char *value, size_t value_len, + int flags) { const struct prop_handler *handler; int ret; diff --git a/fs/btrfs/props.h b/fs/btrfs/props.h index 01d2c1899bc7..30b99348977d 100644 --- a/fs/btrfs/props.h +++ b/fs/btrfs/props.h @@ -12,6 +12,9 @@ void __init btrfs_props_init(void); int btrfs_set_prop_trans(struct inode *inode, const char *name, const char *value, size_t value_len, int flags); +int btrfs_set_prop(struct btrfs_trans_handle *trans, struct inode *inode, + const char *name, const char *value, size_t value_len, + int flags); int btrfs_validate_prop(const char *name, const char *value, size_t value_len); int btrfs_load_inode_props(struct inode *inode, struct btrfs_path *path); -- 2.17.1