]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blobdiff - fs/btrfs/ioctl.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[mirror_ubuntu-focal-kernel.git] / fs / btrfs / ioctl.c
index e1c15a2ac785aa3ddc9ee8e260538908a9fbe96e..d6715c2bcdc472d567bab9fd617e808fbcbd480f 100644 (file)
@@ -296,8 +296,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
 
                if (fs_info->compress_type == BTRFS_COMPRESS_LZO)
                        comp = "lzo";
-               else
+               else if (fs_info->compress_type == BTRFS_COMPRESS_ZLIB)
                        comp = "zlib";
+               else
+                       comp = "zstd";
                ret = btrfs_set_prop(inode, "btrfs.compression",
                                     comp, strlen(comp), 0);
                if (ret)
@@ -1255,6 +1257,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
        unsigned long cluster = max_cluster;
        u64 new_align = ~((u64)SZ_128K - 1);
        struct page **pages = NULL;
+       bool do_compress = range->flags & BTRFS_DEFRAG_RANGE_COMPRESS;
 
        if (isize == 0)
                return 0;
@@ -1262,7 +1265,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
        if (range->start >= isize)
                return -EINVAL;
 
-       if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) {
+       if (do_compress) {
                if (range->compress_type > BTRFS_COMPRESS_TYPES)
                        return -EINVAL;
                if (range->compress_type)
@@ -1341,8 +1344,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
 
                if (!should_defrag_range(inode, (u64)i << PAGE_SHIFT,
                                         extent_thresh, &last_len, &skip,
-                                        &defrag_end, range->flags &
-                                        BTRFS_DEFRAG_RANGE_COMPRESS)) {
+                                        &defrag_end, do_compress)){
                        unsigned long next;
                        /*
                         * the should_defrag function tells us how much to skip
@@ -1370,8 +1372,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
                }
 
                inode_lock(inode);
-               if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)
-                       BTRFS_I(inode)->prop_compress = compress_type;
+               if (do_compress)
+                       BTRFS_I(inode)->defrag_compress = compress_type;
                ret = cluster_pages_for_defrag(inode, pages, i, cluster);
                if (ret < 0) {
                        inode_unlock(inode);
@@ -1418,7 +1420,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
                        filemap_flush(inode->i_mapping);
        }
 
-       if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) {
+       if (do_compress) {
                /* the filemap_flush will queue IO into the worker threads, but
                 * we have to make sure the IO is actually started and that
                 * ordered extents get created before we return
@@ -1435,14 +1437,16 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
 
        if (range->compress_type == BTRFS_COMPRESS_LZO) {
                btrfs_set_fs_incompat(fs_info, COMPRESS_LZO);
+       } else if (range->compress_type == BTRFS_COMPRESS_ZSTD) {
+               btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD);
        }
 
        ret = defrag_count;
 
 out_ra:
-       if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) {
+       if (do_compress) {
                inode_lock(inode);
-               BTRFS_I(inode)->prop_compress = BTRFS_COMPRESS_NONE;
+               BTRFS_I(inode)->defrag_compress = BTRFS_COMPRESS_NONE;
                inode_unlock(inode);
        }
        if (!file)
@@ -2169,9 +2173,6 @@ static noinline int btrfs_ioctl_tree_search_v2(struct file *file,
 
        buf_size = args.buf_size;
 
-       if (buf_size < sizeof(struct btrfs_ioctl_search_header))
-               return -EOVERFLOW;
-
        /* limit result size to 16MB */
        if (buf_size > buf_limit)
                buf_size = buf_limit;
@@ -3966,6 +3967,7 @@ static long btrfs_ioctl_trans_start(struct file *file)
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
+       struct btrfs_file_private *private;
        int ret;
        static bool warned = false;
 
@@ -3984,8 +3986,16 @@ static long btrfs_ioctl_trans_start(struct file *file)
        }
 
        ret = -EINPROGRESS;
-       if (file->private_data)
+       private = file->private_data;
+       if (private && private->trans)
                goto out;
+       if (!private) {
+               private = kzalloc(sizeof(struct btrfs_file_private),
+                                 GFP_KERNEL);
+               if (!private)
+                       return -ENOMEM;
+               file->private_data = private;
+       }
 
        ret = -EROFS;
        if (btrfs_root_readonly(root))
@@ -4002,7 +4012,7 @@ static long btrfs_ioctl_trans_start(struct file *file)
        if (IS_ERR(trans))
                goto out_drop;
 
-       file->private_data = trans;
+       private->trans = trans;
        return 0;
 
 out_drop:
@@ -4257,14 +4267,13 @@ long btrfs_ioctl_trans_end(struct file *file)
 {
        struct inode *inode = file_inode(file);
        struct btrfs_root *root = BTRFS_I(inode)->root;
-       struct btrfs_trans_handle *trans;
+       struct btrfs_file_private *private = file->private_data;
 
-       trans = file->private_data;
-       if (!trans)
+       if (!private || !private->trans)
                return -EINVAL;
-       file->private_data = NULL;
 
-       btrfs_end_transaction(trans);
+       btrfs_end_transaction(private->trans);
+       private->trans = NULL;
 
        atomic_dec(&root->fs_info->open_ioctl_trans);
 
@@ -4417,7 +4426,7 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info,
 
        switch (p->cmd) {
        case BTRFS_IOCTL_DEV_REPLACE_CMD_START:
-               if (fs_info->sb->s_flags & MS_RDONLY) {
+               if (sb_rdonly(fs_info->sb)) {
                        ret = -EROFS;
                        goto out;
                }