Btrfs: attach delayed ref updates to delayed ref heads
[profile/ivi/kernel-x86-ivi.git] / fs / btrfs / backref.c
index 3775947..34a8952 100644 (file)
@@ -538,14 +538,13 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
        if (extent_op && extent_op->update_key)
                btrfs_disk_key_to_cpu(&op_key, &extent_op->key);
 
-       while ((n = rb_prev(n))) {
+       spin_lock(&head->lock);
+       n = rb_first(&head->ref_root);
+       while (n) {
                struct btrfs_delayed_ref_node *node;
                node = rb_entry(n, struct btrfs_delayed_ref_node,
                                rb_node);
-               if (node->bytenr != head->node.bytenr)
-                       break;
-               WARN_ON(node->is_head);
-
+               n = rb_next(n);
                if (node->seq > seq)
                        continue;
 
@@ -612,10 +611,10 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq,
                        WARN_ON(1);
                }
                if (ret)
-                       return ret;
+                       break;
        }
-
-       return 0;
+       spin_unlock(&head->lock);
+       return ret;
 }
 
 /*
@@ -882,15 +881,15 @@ again:
                                btrfs_put_delayed_ref(&head->node);
                                goto again;
                        }
+                       spin_unlock(&delayed_refs->lock);
                        ret = __add_delayed_refs(head, time_seq,
                                                 &prefs_delayed);
                        mutex_unlock(&head->mutex);
-                       if (ret) {
-                               spin_unlock(&delayed_refs->lock);
+                       if (ret)
                                goto out;
-                       }
+               } else {
+                       spin_unlock(&delayed_refs->lock);
                }
-               spin_unlock(&delayed_refs->lock);
        }
 
        if (path->slots[0]) {
@@ -1107,38 +1106,6 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-
-static int __inode_info(u64 inum, u64 ioff, u8 key_type,
-                       struct btrfs_root *fs_root, struct btrfs_path *path,
-                       struct btrfs_key *found_key)
-{
-       int ret;
-       struct btrfs_key key;
-       struct extent_buffer *eb;
-
-       key.type = key_type;
-       key.objectid = inum;
-       key.offset = ioff;
-
-       ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0);
-       if (ret < 0)
-               return ret;
-
-       eb = path->nodes[0];
-       if (ret && path->slots[0] >= btrfs_header_nritems(eb)) {
-               ret = btrfs_next_leaf(fs_root, path);
-               if (ret)
-                       return ret;
-               eb = path->nodes[0];
-       }
-
-       btrfs_item_key_to_cpu(eb, found_key, path->slots[0]);
-       if (found_key->type != key.type || found_key->objectid != key.objectid)
-               return 1;
-
-       return 0;
-}
-
 /*
  * this makes the path point to (inum INODE_ITEM ioff)
  */
@@ -1146,16 +1113,16 @@ int inode_item_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
                        struct btrfs_path *path)
 {
        struct btrfs_key key;
-       return __inode_info(inum, ioff, BTRFS_INODE_ITEM_KEY, fs_root, path,
-                               &key);
+       return btrfs_find_item(fs_root, path, inum, ioff,
+                       BTRFS_INODE_ITEM_KEY, &key);
 }
 
 static int inode_ref_info(u64 inum, u64 ioff, struct btrfs_root *fs_root,
                                struct btrfs_path *path,
                                struct btrfs_key *found_key)
 {
-       return __inode_info(inum, ioff, BTRFS_INODE_REF_KEY, fs_root, path,
-                               found_key);
+       return btrfs_find_item(fs_root, path, inum, ioff,
+                       BTRFS_INODE_REF_KEY, found_key);
 }
 
 int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
@@ -1601,7 +1568,6 @@ static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root,
        struct btrfs_key found_key;
 
        while (!ret) {
-               path->leave_spinning = 1;
                ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path,
                                     &found_key);
                if (ret < 0)
@@ -1614,9 +1580,12 @@ static int iterate_inode_refs(u64 inum, struct btrfs_root *fs_root,
 
                parent = found_key.offset;
                slot = path->slots[0];
-               eb = path->nodes[0];
-               /* make sure we can use eb after releasing the path */
-               atomic_inc(&eb->refs);
+               eb = btrfs_clone_extent_buffer(path->nodes[0]);
+               if (!eb) {
+                       ret = -ENOMEM;
+                       break;
+               }
+               extent_buffer_get(eb);
                btrfs_tree_read_lock(eb);
                btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
                btrfs_release_path(path);
@@ -1674,17 +1643,20 @@ static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root,
                ++found;
 
                slot = path->slots[0];
-               eb = path->nodes[0];
-               /* make sure we can use eb after releasing the path */
-               atomic_inc(&eb->refs);
+               eb = btrfs_clone_extent_buffer(path->nodes[0]);
+               if (!eb) {
+                       ret = -ENOMEM;
+                       break;
+               }
+               extent_buffer_get(eb);
 
                btrfs_tree_read_lock(eb);
                btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
                btrfs_release_path(path);
 
                leaf = path->nodes[0];
-               item_size = btrfs_item_size_nr(leaf, path->slots[0]);
-               ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
+               item_size = btrfs_item_size_nr(leaf, slot);
+               ptr = btrfs_item_ptr_offset(leaf, slot);
                cur_offset = 0;
 
                while (cur_offset < item_size) {