btrfs: simplify code flow in btrfs_ioctl_balance
authorNikolay Borisov <nborisov@suse.com>
Wed, 30 Mar 2022 09:14:07 +0000 (12:14 +0300)
committerDavid Sterba <dsterba@suse.com>
Mon, 16 May 2022 15:03:10 +0000 (17:03 +0200)
Move code in btrfs_ioctl_balance to simplify its flow. This is
possible thanks to the removal of balance v1 ioctl and ensuring 'arg'
argument is always present. First move the code duplicating the
userspace arg to the kernel 'barg'. This makes the out_unlock label
redundant.  Secondly, check the validity of bargs::flags before copying
to the dynamically allocated 'bctl'. This removes the need for the
out_bctl label.

Reviewed-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ioctl.c

index 95e47e6f8d411a93a66fd35f4bd579837ebf3c59..d1e1edd73b806379f3af4a1da6b2d358dc1b5778 100644 (file)
@@ -4353,6 +4353,13 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        if (ret)
                return ret;
 
+       bargs = memdup_user(arg, sizeof(*bargs));
+       if (IS_ERR(bargs)) {
+               ret = PTR_ERR(bargs);
+               bargs = NULL;
+               goto out;
+       }
+
 again:
        if (btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) {
                mutex_lock(&fs_info->balance_mutex);
@@ -4400,17 +4407,10 @@ again:
        }
 
 locked:
-
-       bargs = memdup_user(arg, sizeof(*bargs));
-       if (IS_ERR(bargs)) {
-               ret = PTR_ERR(bargs);
-               goto out_unlock;
-       }
-
        if (bargs->flags & BTRFS_BALANCE_RESUME) {
                if (!fs_info->balance_ctl) {
                        ret = -ENOTCONN;
-                       goto out_bargs;
+                       goto out_unlock;
                }
 
                bctl = fs_info->balance_ctl;
@@ -4422,15 +4422,20 @@ locked:
                goto do_balance;
        }
 
+       if (bargs->flags & ~(BTRFS_BALANCE_ARGS_MASK | BTRFS_BALANCE_TYPE_MASK)) {
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
        if (fs_info->balance_ctl) {
                ret = -EINPROGRESS;
-               goto out_bargs;
+               goto out_unlock;
        }
 
        bctl = kzalloc(sizeof(*bctl), GFP_KERNEL);
        if (!bctl) {
                ret = -ENOMEM;
-               goto out_bargs;
+               goto out_unlock;
        }
 
        memcpy(&bctl->data, &bargs->data, sizeof(bctl->data));
@@ -4438,12 +4443,6 @@ locked:
        memcpy(&bctl->sys, &bargs->sys, sizeof(bctl->sys));
 
        bctl->flags = bargs->flags;
-
-       if (bctl->flags & ~(BTRFS_BALANCE_ARGS_MASK | BTRFS_BALANCE_TYPE_MASK)) {
-               ret = -EINVAL;
-               goto out_bctl;
-       }
-
 do_balance:
        /*
         * Ownership of bctl and exclusive operation goes to btrfs_balance.
@@ -4461,16 +4460,14 @@ do_balance:
                        ret = -EFAULT;
        }
 
-out_bctl:
        kfree(bctl);
-out_bargs:
-       kfree(bargs);
 out_unlock:
        mutex_unlock(&fs_info->balance_mutex);
        if (need_unlock)
                btrfs_exclop_finish(fs_info);
 out:
        mnt_drop_write_file(file);
+       kfree(bargs);
        return ret;
 }