diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 3f9263ddeff8..87b473dcdd52 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,47 @@ 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); + /* + * 1 for inode item + * 2 for properties + */ + 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) { + btrfs_abort_transaction(trans, ret); + goto out_end_trans; + } + 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) { + btrfs_abort_transaction(trans, ret); + goto out_end_trans; + } + } + 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_end_trans: btrfs_end_transaction(trans); out_drop: if (ret) {