Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
[cascardo/linux.git] / fs / btrfs / transaction.c
index be8eae8..b6031ce 100644 (file)
@@ -75,6 +75,23 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
                        list_del_init(&em->list);
                        free_extent_map(em);
                }
+               /*
+                * If any block groups are found in ->deleted_bgs then it's
+                * because the transaction was aborted and a commit did not
+                * happen (things failed before writing the new superblock
+                * and calling btrfs_finish_extent_commit()), so we can not
+                * discard the physical locations of the block groups.
+                */
+               while (!list_empty(&transaction->deleted_bgs)) {
+                       struct btrfs_block_group_cache *cache;
+
+                       cache = list_first_entry(&transaction->deleted_bgs,
+                                                struct btrfs_block_group_cache,
+                                                bg_list);
+                       list_del_init(&cache->bg_list);
+                       btrfs_put_block_group_trimming(cache);
+                       btrfs_put_block_group(cache);
+               }
                kmem_cache_free(btrfs_transaction_cachep, transaction);
        }
 }
@@ -634,17 +651,20 @@ struct btrfs_trans_handle *btrfs_start_transaction_lflush(
 
 struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root)
 {
-       return start_transaction(root, 0, TRANS_JOIN, 0);
+       return start_transaction(root, 0, TRANS_JOIN,
+                                BTRFS_RESERVE_NO_FLUSH);
 }
 
 struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root)
 {
-       return start_transaction(root, 0, TRANS_JOIN_NOLOCK, 0);
+       return start_transaction(root, 0, TRANS_JOIN_NOLOCK,
+                                BTRFS_RESERVE_NO_FLUSH);
 }
 
 struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root)
 {
-       return start_transaction(root, 0, TRANS_USERSPACE, 0);
+       return start_transaction(root, 0, TRANS_USERSPACE,
+                                BTRFS_RESERVE_NO_FLUSH);
 }
 
 /*
@@ -662,7 +682,8 @@ struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root
  */
 struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root)
 {
-       return start_transaction(root, 0, TRANS_ATTACH, 0);
+       return start_transaction(root, 0, TRANS_ATTACH,
+                                BTRFS_RESERVE_NO_FLUSH);
 }
 
 /*
@@ -677,7 +698,8 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root)
 {
        struct btrfs_trans_handle *trans;
 
-       trans = start_transaction(root, 0, TRANS_ATTACH, 0);
+       trans = start_transaction(root, 0, TRANS_ATTACH,
+                                 BTRFS_RESERVE_NO_FLUSH);
        if (IS_ERR(trans) && PTR_ERR(trans) == -ENOENT)
                btrfs_wait_for_commit(root, 0);
 
@@ -1319,17 +1341,11 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        u64 root_flags;
        uuid_le new_uuid;
 
-       path = btrfs_alloc_path();
-       if (!path) {
-               pending->error = -ENOMEM;
-               return 0;
-       }
+       ASSERT(pending->path);
+       path = pending->path;
 
-       new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
-       if (!new_root_item) {
-               pending->error = -ENOMEM;
-               goto root_item_alloc_fail;
-       }
+       ASSERT(pending->root_item);
+       new_root_item = pending->root_item;
 
        pending->error = btrfs_find_free_objectid(tree_root, &objectid);
        if (pending->error)
@@ -1562,8 +1578,10 @@ clear_skip_qgroup:
        btrfs_clear_skip_qgroup(trans);
 no_free_objectid:
        kfree(new_root_item);
-root_item_alloc_fail:
+       pending->root_item = NULL;
        btrfs_free_path(path);
+       pending->path = NULL;
+
        return ret;
 }