btrfs: fix race between quota disable and quota assign ioctls
[platform/kernel/linux-rpi.git] / fs / btrfs / ioctl.c
index 143c246..f417329 100644 (file)
@@ -3415,13 +3415,10 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
        di_args->bytes_used = btrfs_device_get_bytes_used(dev);
        di_args->total_bytes = btrfs_device_get_total_bytes(dev);
        memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
-       if (dev->name) {
-               strncpy(di_args->path, rcu_str_deref(dev->name),
-                               sizeof(di_args->path) - 1);
-               di_args->path[sizeof(di_args->path) - 1] = 0;
-       } else {
+       if (dev->name)
+               strscpy(di_args->path, rcu_str_deref(dev->name), sizeof(di_args->path));
+       else
                di_args->path[0] = '\0';
-       }
 
 out:
        rcu_read_unlock();
@@ -3946,21 +3943,20 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
                size = min_t(u32, loi->size, SZ_16M);
        }
 
-       path = btrfs_alloc_path();
-       if (!path) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
        inodes = init_data_container(size);
        if (IS_ERR(inodes)) {
                ret = PTR_ERR(inodes);
-               inodes = NULL;
-               goto out;
+               goto out_loi;
        }
 
+       path = btrfs_alloc_path();
+       if (!path) {
+               ret = -ENOMEM;
+               goto out;
+       }
        ret = iterate_inodes_from_logical(loi->logical, fs_info, path,
                                          inodes, ignore_offset);
+       btrfs_free_path(path);
        if (ret == -EINVAL)
                ret = -ENOENT;
        if (ret < 0)
@@ -3972,7 +3968,6 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
                ret = -EFAULT;
 
 out:
-       btrfs_free_path(path);
        kvfree(inodes);
 out_loi:
        kfree(loi);
@@ -4272,7 +4267,9 @@ static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)
        }
 
        /* update qgroup status and info */
+       mutex_lock(&fs_info->qgroup_ioctl_lock);
        err = btrfs_run_qgroups(trans);
+       mutex_unlock(&fs_info->qgroup_ioctl_lock);
        if (err < 0)
                btrfs_handle_fs_error(fs_info, err,
                                      "failed to update qgroup status and info");