Btrfs: Free free_space item properly in btrfs_trim_block_group()
[linux-2.6.git] / fs / btrfs / delayed-ref.c
index 84e6781..bce28f6 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/slab.h>
 #include <linux/sort.h>
 #include "ctree.h"
 #include "delayed-ref.h"
@@ -318,107 +319,6 @@ out:
 }
 
 /*
- * helper function to lookup reference count and flags of extent.
- *
- * the head node for delayed ref is used to store the sum of all the
- * reference count modifications queued up in the rbtree. the head
- * node may also store the extent flags to set. This way you can check
- * to see what the reference count and extent flags would be if all of
- * the delayed refs are not processed.
- */
-int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
-                            struct btrfs_root *root, u64 bytenr,
-                            u64 num_bytes, u64 *refs, u64 *flags)
-{
-       struct btrfs_delayed_ref_node *ref;
-       struct btrfs_delayed_ref_head *head;
-       struct btrfs_delayed_ref_root *delayed_refs;
-       struct btrfs_path *path;
-       struct btrfs_extent_item *ei;
-       struct extent_buffer *leaf;
-       struct btrfs_key key;
-       u32 item_size;
-       u64 num_refs;
-       u64 extent_flags;
-       int ret;
-
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
-
-       key.objectid = bytenr;
-       key.type = BTRFS_EXTENT_ITEM_KEY;
-       key.offset = num_bytes;
-       delayed_refs = &trans->transaction->delayed_refs;
-again:
-       ret = btrfs_search_slot(trans, root->fs_info->extent_root,
-                               &key, path, 0, 0);
-       if (ret < 0)
-               goto out;
-
-       if (ret == 0) {
-               leaf = path->nodes[0];
-               item_size = btrfs_item_size_nr(leaf, path->slots[0]);
-               if (item_size >= sizeof(*ei)) {
-                       ei = btrfs_item_ptr(leaf, path->slots[0],
-                                           struct btrfs_extent_item);
-                       num_refs = btrfs_extent_refs(leaf, ei);
-                       extent_flags = btrfs_extent_flags(leaf, ei);
-               } else {
-#ifdef BTRFS_COMPAT_EXTENT_TREE_V0
-                       struct btrfs_extent_item_v0 *ei0;
-                       BUG_ON(item_size != sizeof(*ei0));
-                       ei0 = btrfs_item_ptr(leaf, path->slots[0],
-                                            struct btrfs_extent_item_v0);
-                       num_refs = btrfs_extent_refs_v0(leaf, ei0);
-                       /* FIXME: this isn't correct for data */
-                       extent_flags = BTRFS_BLOCK_FLAG_FULL_BACKREF;
-#else
-                       BUG();
-#endif
-               }
-               BUG_ON(num_refs == 0);
-       } else {
-               num_refs = 0;
-               extent_flags = 0;
-               ret = 0;
-       }
-
-       spin_lock(&delayed_refs->lock);
-       ref = find_ref_head(&delayed_refs->root, bytenr, NULL);
-       if (ref) {
-               head = btrfs_delayed_node_to_head(ref);
-               if (!mutex_trylock(&head->mutex)) {
-                       atomic_inc(&ref->refs);
-                       spin_unlock(&delayed_refs->lock);
-
-                       btrfs_release_path(root->fs_info->extent_root, path);
-
-                       mutex_lock(&head->mutex);
-                       mutex_unlock(&head->mutex);
-                       btrfs_put_delayed_ref(ref);
-                       goto again;
-               }
-               if (head->extent_op && head->extent_op->update_flags)
-                       extent_flags |= head->extent_op->flags_to_set;
-               else
-                       BUG_ON(num_refs == 0);
-
-               num_refs += ref->ref_mod;
-               mutex_unlock(&head->mutex);
-       }
-       WARN_ON(num_refs == 0);
-       if (refs)
-               *refs = num_refs;
-       if (flags)
-               *flags = extent_flags;
-out:
-       spin_unlock(&delayed_refs->lock);
-       btrfs_free_path(path);
-       return ret;
-}
-
-/*
  * helper function to update an extent delayed ref in the
  * rbtree.  existing and update must both have the same
  * bytenr and parent
@@ -583,6 +483,8 @@ static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans,
        INIT_LIST_HEAD(&head_ref->cluster);
        mutex_init(&head_ref->mutex);
 
+       trace_btrfs_delayed_ref_head(ref, head_ref, action);
+
        existing = tree_insert(&delayed_refs->root, &ref->rb_node);
 
        if (existing) {
@@ -637,6 +539,8 @@ static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans,
        }
        full_ref->level = level;
 
+       trace_btrfs_delayed_tree_ref(ref, full_ref, action);
+
        existing = tree_insert(&delayed_refs->root, &ref->rb_node);
 
        if (existing) {
@@ -691,6 +595,8 @@ static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans,
        full_ref->objectid = owner;
        full_ref->offset = offset;
 
+       trace_btrfs_delayed_data_ref(ref, full_ref, action);
+
        existing = tree_insert(&delayed_refs->root, &ref->rb_node);
 
        if (existing) {