btrfs: do an allocation earlier during snapshot creation
authorDavid Sterba <dsterba@suse.com>
Tue, 10 Nov 2015 17:53:56 +0000 (18:53 +0100)
committerDavid Sterba <dsterba@suse.com>
Thu, 7 Jan 2016 14:20:54 +0000 (15:20 +0100)
We can allocate pending_snapshot earlier and do not have to do cleanup
in case of failure.

Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ioctl.c

index 6e896415a73461aeda6db64491df61799116a605..fa25091e10abca15b9dba318e61fc9850e51a319 100644 (file)
@@ -655,22 +655,20 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
        if (!test_bit(BTRFS_ROOT_REF_COWS, &root->state))
                return -EINVAL;
 
+       pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
+       if (!pending_snapshot)
+               return -ENOMEM;
+
        atomic_inc(&root->will_be_snapshoted);
        smp_mb__after_atomic();
        btrfs_wait_for_no_snapshoting_writes(root);
 
        ret = btrfs_start_delalloc_inodes(root, 0);
        if (ret)
-               goto out;
+               goto dec_and_free;
 
        btrfs_wait_ordered_extents(root, -1);
 
-       pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
-       if (!pending_snapshot) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
        btrfs_init_block_rsv(&pending_snapshot->block_rsv,
                             BTRFS_BLOCK_RSV_TEMP);
        /*
@@ -686,7 +684,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
                                        &pending_snapshot->qgroup_reserved,
                                        false);
        if (ret)
-               goto free;
+               goto dec_and_free;
 
        pending_snapshot->dentry = dentry;
        pending_snapshot->root = root;
@@ -737,11 +735,11 @@ fail:
        btrfs_subvolume_release_metadata(BTRFS_I(dir)->root,
                                         &pending_snapshot->block_rsv,
                                         pending_snapshot->qgroup_reserved);
-free:
-       kfree(pending_snapshot);
-out:
+dec_and_free:
        if (atomic_dec_and_test(&root->will_be_snapshoted))
                wake_up_atomic_t(&root->will_be_snapshoted);
+       kfree(pending_snapshot);
+
        return ret;
 }