btrfs: reflow btrfs_free_tree_block
[sfrench/cifs-2.6.git] / fs / btrfs / extent-tree.c
index 99f98767e201a3fcff40e0117d8113f981dd7b6f..f396aba92c579641d1cce38b48e7e7cd4febc510 100644 (file)
@@ -3447,6 +3447,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_ref generic_ref = { 0 };
+       struct btrfs_block_group *bg;
        int ret;
 
        btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF,
@@ -3460,64 +3461,64 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
                BUG_ON(ret); /* -ENOMEM */
        }
 
-       if (last_ref && btrfs_header_generation(buf) == trans->transid) {
-               struct btrfs_block_group *cache;
-               bool must_pin = false;
-
-               if (root_id != BTRFS_TREE_LOG_OBJECTID) {
-                       ret = check_ref_cleanup(trans, buf->start);
-                       if (!ret)
-                               goto out;
-               }
+       if (!last_ref)
+               return;
 
-               cache = btrfs_lookup_block_group(fs_info, buf->start);
+       if (btrfs_header_generation(buf) != trans->transid)
+               goto out;
 
-               if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
-                       pin_down_extent(trans, cache, buf->start, buf->len, 1);
-                       btrfs_put_block_group(cache);
+       if (root_id != BTRFS_TREE_LOG_OBJECTID) {
+               ret = check_ref_cleanup(trans, buf->start);
+               if (!ret)
                        goto out;
-               }
+       }
 
-               /*
-                * If there are tree mod log users we may have recorded mod log
-                * operations for this node.  If we re-allocate this node we
-                * could replay operations on this node that happened when it
-                * existed in a completely different root.  For example if it
-                * was part of root A, then was reallocated to root B, and we
-                * are doing a btrfs_old_search_slot(root b), we could replay
-                * operations that happened when the block was part of root A,
-                * giving us an inconsistent view of the btree.
-                *
-                * We are safe from races here because at this point no other
-                * node or root points to this extent buffer, so if after this
-                * check a new tree mod log user joins we will not have an
-                * existing log of operations on this node that we have to
-                * contend with.
-                */
-               if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
-                       must_pin = true;
+       bg = btrfs_lookup_block_group(fs_info, buf->start);
 
-               if (must_pin || btrfs_is_zoned(fs_info)) {
-                       pin_down_extent(trans, cache, buf->start, buf->len, 1);
-                       btrfs_put_block_group(cache);
-                       goto out;
-               }
+       if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
+               pin_down_extent(trans, bg, buf->start, buf->len, 1);
+               btrfs_put_block_group(bg);
+               goto out;
+       }
 
-               WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
+       /*
+        * If there are tree mod log users we may have recorded mod log
+        * operations for this node.  If we re-allocate this node we
+        * could replay operations on this node that happened when it
+        * existed in a completely different root.  For example if it
+        * was part of root A, then was reallocated to root B, and we
+        * are doing a btrfs_old_search_slot(root b), we could replay
+        * operations that happened when the block was part of root A,
+        * giving us an inconsistent view of the btree.
+        *
+        * We are safe from races here because at this point no other
+        * node or root points to this extent buffer, so if after this
+        * check a new tree mod log user joins we will not have an
+        * existing log of operations on this node that we have to
+        * contend with.
+        */
 
-               btrfs_add_free_space(cache, buf->start, buf->len);
-               btrfs_free_reserved_bytes(cache, buf->len, 0);
-               btrfs_put_block_group(cache);
-               trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len);
+       if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags)
+                    || btrfs_is_zoned(fs_info)) {
+               pin_down_extent(trans, bg, buf->start, buf->len, 1);
+               btrfs_put_block_group(bg);
+               goto out;
        }
+
+       WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
+
+       btrfs_add_free_space(bg, buf->start, buf->len);
+       btrfs_free_reserved_bytes(bg, buf->len, 0);
+       btrfs_put_block_group(bg);
+       trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len);
+
 out:
-       if (last_ref) {
-               /*
-                * Deleting the buffer, clear the corrupt flag since it doesn't
-                * matter anymore.
-                */
-               clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags);
-       }
+
+       /*
+        * Deleting the buffer, clear the corrupt flag since it doesn't
+        * matter anymore.
+        */
+       clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags);
 }
 
 /* Can return -ENOMEM */