|
@@ -85,6 +85,34 @@ static int comp_data_refs(struct btrfs_delayed_data_ref *ref1,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int comp_refs(struct btrfs_delayed_ref_node *ref1,
|
|
|
|
+ struct btrfs_delayed_ref_node *ref2,
|
|
|
|
+ bool check_seq)
|
|
|
|
+{
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ if (ref1->type < ref2->type)
|
|
|
|
+ return -1;
|
|
|
|
+ if (ref1->type > ref2->type)
|
|
|
|
+ return 1;
|
|
|
|
+ if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY ||
|
|
|
|
+ ref1->type == BTRFS_SHARED_BLOCK_REF_KEY)
|
|
|
|
+ ret = comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref1),
|
|
|
|
+ btrfs_delayed_node_to_tree_ref(ref2));
|
|
|
|
+ else
|
|
|
|
+ ret = comp_data_refs(btrfs_delayed_node_to_data_ref(ref1),
|
|
|
|
+ btrfs_delayed_node_to_data_ref(ref2));
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ if (check_seq) {
|
|
|
|
+ if (ref1->seq < ref2->seq)
|
|
|
|
+ return -1;
|
|
|
|
+ if (ref1->seq > ref2->seq)
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/* insert a new ref to head ref rbtree */
|
|
/* insert a new ref to head ref rbtree */
|
|
static struct btrfs_delayed_ref_head *htree_insert(struct rb_root *root,
|
|
static struct btrfs_delayed_ref_head *htree_insert(struct rb_root *root,
|
|
struct rb_node *node)
|
|
struct rb_node *node)
|
|
@@ -217,18 +245,7 @@ static bool merge_ref(struct btrfs_trans_handle *trans,
|
|
if (seq && next->seq >= seq)
|
|
if (seq && next->seq >= seq)
|
|
goto next;
|
|
goto next;
|
|
|
|
|
|
- if (next->type != ref->type)
|
|
|
|
- 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)))
|
|
|
|
- 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)))
|
|
|
|
|
|
+ if (comp_refs(ref, next, false))
|
|
goto next;
|
|
goto next;
|
|
|
|
|
|
if (ref->action == next->action) {
|
|
if (ref->action == next->action) {
|
|
@@ -402,18 +419,7 @@ add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans,
|
|
exist = list_entry(href->ref_list.prev, struct btrfs_delayed_ref_node,
|
|
exist = list_entry(href->ref_list.prev, struct btrfs_delayed_ref_node,
|
|
list);
|
|
list);
|
|
/* No need to compare bytenr nor is_head */
|
|
/* No need to compare bytenr nor is_head */
|
|
- if (exist->type != ref->type || exist->seq != ref->seq)
|
|
|
|
- goto add_tail;
|
|
|
|
-
|
|
|
|
- if ((exist->type == BTRFS_TREE_BLOCK_REF_KEY ||
|
|
|
|
- exist->type == BTRFS_SHARED_BLOCK_REF_KEY) &&
|
|
|
|
- comp_tree_refs(btrfs_delayed_node_to_tree_ref(exist),
|
|
|
|
- btrfs_delayed_node_to_tree_ref(ref)))
|
|
|
|
- goto add_tail;
|
|
|
|
- if ((exist->type == BTRFS_EXTENT_DATA_REF_KEY ||
|
|
|
|
- exist->type == BTRFS_SHARED_DATA_REF_KEY) &&
|
|
|
|
- comp_data_refs(btrfs_delayed_node_to_data_ref(exist),
|
|
|
|
- btrfs_delayed_node_to_data_ref(ref)))
|
|
|
|
|
|
+ if (comp_refs(exist, ref, true))
|
|
goto add_tail;
|
|
goto add_tail;
|
|
|
|
|
|
/* Now we are sure we can merge */
|
|
/* Now we are sure we can merge */
|