]> git.hungrycats.org Git - linux/commitdiff
Revert "Btrfs: fix regression when running delayed references"
authorZygo Blaxell <zblaxell@thirteen.furryterror.org>
Tue, 29 Dec 2015 03:37:54 +0000 (22:37 -0500)
committerZygo Blaxell <zblaxell@thirteen.furryterror.org>
Tue, 29 Dec 2015 03:37:54 +0000 (22:37 -0500)
This reverts commit 9c8e68b346ba16dc10cc15f098986aa069d3afef.

fs/btrfs/delayed-ref.c
fs/btrfs/extent-tree.c

index 04eafb0e7a967096f4250ea28be6c5aee2662f85..8f8ed7d20bac5f4e058fc693d0fdc24fde7abeda 100644 (file)
@@ -277,50 +277,36 @@ static inline void drop_delayed_ref(struct btrfs_trans_handle *trans,
                trans->delayed_ref_updates--;
 }
 
-static bool merge_ref(struct btrfs_trans_handle *trans,
-                     struct btrfs_delayed_ref_root *delayed_refs,
-                     struct btrfs_delayed_ref_head *head,
-                     struct btrfs_delayed_ref_node *ref,
-                     u64 seq)
+static int merge_ref(struct btrfs_trans_handle *trans,
+                    struct btrfs_delayed_ref_root *delayed_refs,
+                    struct btrfs_delayed_ref_head *head,
+                    struct btrfs_delayed_ref_node *ref, u64 seq)
 {
-       struct btrfs_delayed_ref_node *next;
-       bool done = false;
+       struct rb_node *node;
+       int mod = 0;
+       int done = 0;
 
-       next = list_first_entry(&head->ref_list, struct btrfs_delayed_ref_node,
-                               list);
-       while (!done && &next->list != &head->ref_list) {
-               int mod;
-               struct btrfs_delayed_ref_node *next2;
-
-               next2 = list_next_entry(next, list);
-
-               if (next == ref)
-                       goto next;
+       node = rb_next(&ref->rb_node);
+       while (!done && node) {
+               struct btrfs_delayed_ref_node *next;
 
+               next = rb_entry(node, struct btrfs_delayed_ref_node, rb_node);
+               node = rb_next(node);
                if (seq && next->seq >= seq)
-                       goto next;
-
-               if (next->type != ref->type || next->no_quota != ref->no_quota)
-                       goto next;
-
-               if ((ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
-                    ref->type == BTRFS_SHARED_BLOCK_REF_KEY) &&
-                   comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref),
-                                  btrfs_delayed_node_to_tree_ref(next),
-                                  ref->type))
-                       goto next;
-               if ((ref->type == BTRFS_EXTENT_DATA_REF_KEY ||
-                    ref->type == BTRFS_SHARED_DATA_REF_KEY) &&
-                   comp_data_refs(btrfs_delayed_node_to_data_ref(ref),
-                                  btrfs_delayed_node_to_data_ref(next)))
-                       goto next;
+                       break;
+               if (comp_entry(ref, next, 0))
+                       continue;
 
                if (ref->action == next->action) {
                        mod = next->ref_mod;
                } else {
                        if (ref->ref_mod < next->ref_mod) {
-                               swap(ref, next);
-                               done = true;
+                               struct btrfs_delayed_ref_node *tmp;
+
+                               tmp = ref;
+                               ref = next;
+                               next = tmp;
+                               done = 1;
                        }
                        mod = -next->ref_mod;
                }
@@ -329,18 +315,16 @@ static bool merge_ref(struct btrfs_trans_handle *trans,
                ref->ref_mod += mod;
                if (ref->ref_mod == 0) {
                        drop_delayed_ref(trans, delayed_refs, head, ref);
-                       done = true;
+                       done = 1;
                } else {
                        /*
-                        * Can't have multiples of the same ref on a tree block.
+                        * You can't have multiples of the same ref on a tree
+                        * block.
                         */
                        WARN_ON(ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
                                ref->type == BTRFS_SHARED_BLOCK_REF_KEY);
                }
-next:
-               next = next2;
        }
-
        return done;
 }
 
@@ -349,15 +333,14 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
                              struct btrfs_delayed_ref_root *delayed_refs,
                              struct btrfs_delayed_ref_head *head)
 {
-       struct btrfs_delayed_ref_node *ref;
+       struct rb_node *node;
        u64 seq = 0;
 
        assert_spin_locked(&head->lock);
-
-       if (list_empty(&head->ref_list))
-               return;
-
-       /* We don't have too many refs to merge for data. */
+       /*
+        * We don't have too much refs to merge in the case of delayed data
+        * refs.
+        */
        if (head->is_data)
                return;
 
@@ -371,22 +354,19 @@ void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
        }
        spin_unlock(&fs_info->tree_mod_seq_lock);
 
-       ref = list_first_entry(&head->ref_list, struct btrfs_delayed_ref_node,
-                              list);
-       while (&ref->list != &head->ref_list) {
+       node = rb_first(&head->ref_root);
+       while (node) {
+               struct btrfs_delayed_ref_node *ref;
+
+               ref = rb_entry(node, struct btrfs_delayed_ref_node,
+                              rb_node);
+               /* We can't merge refs that are outside of our seq count */
                if (seq && ref->seq >= seq)
-                       goto next;
-
-               if (merge_ref(trans, delayed_refs, head, ref, seq)) {
-                       if (list_empty(&head->ref_list))
-                               break;
-                       ref = list_first_entry(&head->ref_list,
-                                              struct btrfs_delayed_ref_node,
-                                              list);
-                       continue;
-               }
-next:
-               ref = list_next_entry(ref, list);
+                       break;
+               if (merge_ref(trans, delayed_refs, head, ref, seq))
+                       node = rb_first(&head->ref_root);
+               else
+                       node = rb_next(&ref->rb_node);
        }
 }
 
index 6a09b0a139c578a68602df0bb51d1c32269e30c4..f25e041cd3ee653befbd3edf7021517117482716 100644 (file)
@@ -2475,11 +2475,6 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                 * and then it being added back again before the drop can
                 * finish.  If we merged anything we need to re-loop so we can
                 * get a good ref.
-                * Or we can get node references of the same type that weren't
-                * merged when created due to bumps in the tree mod seq, and
-                * we need to merge them to prevent adding an inline extent
-                * backref before dropping it (triggering a BUG_ON at
-                * insert_inline_extent_backref()).
                 */
                spin_lock(&locked_ref->lock);
                btrfs_merge_delayed_refs(trans, fs_info, delayed_refs,