btrfs: Refactor transaction handling in received subvolume ioctl
[sfrench/cifs-2.6.git] / fs / btrfs / ioctl.c
index 6c7a49faf4e0636e67c9f818893975dc48d7436a..dfc5b4862289025bcf631db091495e4e13733404 100644 (file)
@@ -609,23 +609,6 @@ fail_free:
        return ret;
 }
 
-static void btrfs_wait_for_no_snapshotting_writes(struct btrfs_root *root)
-{
-       s64 writers;
-       DEFINE_WAIT(wait);
-
-       do {
-               prepare_to_wait(&root->subv_writers->wait, &wait,
-                               TASK_UNINTERRUPTIBLE);
-
-               writers = percpu_counter_sum(&root->subv_writers->counter);
-               if (writers)
-                       schedule();
-
-               finish_wait(&root->subv_writers->wait, &wait);
-       } while (writers);
-}
-
 static int create_snapshot(struct btrfs_root *root, struct inode *dir,
                           struct dentry *dentry,
                           u64 *async_transid, bool readonly,
@@ -654,7 +637,9 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
 
        atomic_inc(&root->will_be_snapshotted);
        smp_mb__after_atomic();
-       btrfs_wait_for_no_snapshotting_writes(root);
+       /* wait for no snapshot writes */
+       wait_event(root->subv_writers->wait,
+                  percpu_counter_sum(&root->subv_writers->counter) == 0);
 
        ret = btrfs_start_delalloc_inodes(root, 0);
        if (ret)
@@ -1842,8 +1827,13 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
 
        ret = btrfs_update_root(trans, fs_info->tree_root,
                                &root->root_key, &root->root_item);
+       if (ret < 0) {
+               btrfs_end_transaction(trans);
+               goto out_reset;
+       }
+
+       ret = btrfs_commit_transaction(trans);
 
-       btrfs_commit_transaction(trans);
 out_reset:
        if (ret)
                btrfs_set_root_flags(&root->root_item, root_flags);
@@ -2179,7 +2169,7 @@ static noinline int btrfs_ioctl_tree_search_v2(struct file *file,
 
        inode = file_inode(file);
        ret = search_ioctl(inode, &args.key, &buf_size,
-                          (char *)(&uarg->buf[0]));
+                          (char __user *)(&uarg->buf[0]));
        if (ret == 0 && copy_to_user(&uarg->key, &args.key, sizeof(args.key)))
                ret = -EFAULT;
        else if (ret == -EOVERFLOW &&
@@ -4129,10 +4119,12 @@ static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info,
        struct btrfs_ioctl_space_info *dest_orig;
        struct btrfs_ioctl_space_info __user *user_dest;
        struct btrfs_space_info *info;
-       u64 types[] = {BTRFS_BLOCK_GROUP_DATA,
-                      BTRFS_BLOCK_GROUP_SYSTEM,
-                      BTRFS_BLOCK_GROUP_METADATA,
-                      BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA};
+       static const u64 types[] = {
+               BTRFS_BLOCK_GROUP_DATA,
+               BTRFS_BLOCK_GROUP_SYSTEM,
+               BTRFS_BLOCK_GROUP_METADATA,
+               BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA
+       };
        int num_types = 4;
        int alloc_size;
        int ret = 0;
@@ -4504,8 +4496,8 @@ static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
                ipath->fspath->val[i] = rel_ptr;
        }
 
-       ret = copy_to_user((void *)(unsigned long)ipa->fspath,
-                          (void *)(unsigned long)ipath->fspath, size);
+       ret = copy_to_user((void __user *)(unsigned long)ipa->fspath,
+                          ipath->fspath, size);
        if (ret) {
                ret = -EFAULT;
                goto out;
@@ -4576,8 +4568,8 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
        if (ret < 0)
                goto out;
 
-       ret = copy_to_user((void *)(unsigned long)loi->inodes,
-                          (void *)(unsigned long)inodes, size);
+       ret = copy_to_user((void __user *)(unsigned long)loi->inodes, inodes,
+                          size);
        if (ret)
                ret = -EFAULT;
 
@@ -5160,15 +5152,11 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file,
                                          root->root_key.objectid);
                if (ret < 0 && ret != -EEXIST) {
                        btrfs_abort_transaction(trans, ret);
+                       btrfs_end_transaction(trans);
                        goto out;
                }
        }
        ret = btrfs_commit_transaction(trans);
-       if (ret < 0) {
-               btrfs_abort_transaction(trans, ret);
-               goto out;
-       }
-
 out:
        up_write(&fs_info->subvol_sem);
        mnt_drop_write_file(file);