|
@@ -101,6 +101,11 @@ static int comp_entry(struct btrfs_delayed_ref_node *ref2,
|
|
|
return -1;
|
|
|
if (ref1->type > ref2->type)
|
|
|
return 1;
|
|
|
+ /* merging of sequenced refs is not allowed */
|
|
|
+ if (ref1->seq < ref2->seq)
|
|
|
+ return -1;
|
|
|
+ if (ref1->seq > ref2->seq)
|
|
|
+ return 1;
|
|
|
if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY ||
|
|
|
ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) {
|
|
|
return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2),
|
|
@@ -209,6 +214,24 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+int btrfs_check_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
|
|
|
+ u64 seq)
|
|
|
+{
|
|
|
+ struct seq_list *elem;
|
|
|
+
|
|
|
+ assert_spin_locked(&delayed_refs->lock);
|
|
|
+ if (list_empty(&delayed_refs->seq_head))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ elem = list_first_entry(&delayed_refs->seq_head, struct seq_list, list);
|
|
|
+ if (seq >= elem->seq) {
|
|
|
+ pr_debug("holding back delayed_ref %llu, lowest is %llu (%p)\n",
|
|
|
+ seq, elem->seq, delayed_refs);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans,
|
|
|
struct list_head *cluster, u64 start)
|
|
|
{
|
|
@@ -438,6 +461,7 @@ static noinline int add_delayed_ref_head(struct btrfs_fs_info *fs_info,
|
|
|
ref->action = 0;
|
|
|
ref->is_head = 1;
|
|
|
ref->in_tree = 1;
|
|
|
+ ref->seq = 0;
|
|
|
|
|
|
head_ref = btrfs_delayed_node_to_head(ref);
|
|
|
head_ref->must_insert_reserved = must_insert_reserved;
|
|
@@ -479,6 +503,7 @@ static noinline int add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
|
|
|
struct btrfs_delayed_ref_node *existing;
|
|
|
struct btrfs_delayed_tree_ref *full_ref;
|
|
|
struct btrfs_delayed_ref_root *delayed_refs;
|
|
|
+ u64 seq = 0;
|
|
|
|
|
|
if (action == BTRFS_ADD_DELAYED_EXTENT)
|
|
|
action = BTRFS_ADD_DELAYED_REF;
|
|
@@ -494,6 +519,10 @@ static noinline int add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
|
|
|
ref->is_head = 0;
|
|
|
ref->in_tree = 1;
|
|
|
|
|
|
+ if (need_ref_seq(for_cow, ref_root))
|
|
|
+ seq = inc_delayed_seq(delayed_refs);
|
|
|
+ ref->seq = seq;
|
|
|
+
|
|
|
full_ref = btrfs_delayed_node_to_tree_ref(ref);
|
|
|
full_ref->parent = parent;
|
|
|
full_ref->root = ref_root;
|
|
@@ -534,6 +563,7 @@ static noinline int add_delayed_data_ref(struct btrfs_fs_info *fs_info,
|
|
|
struct btrfs_delayed_ref_node *existing;
|
|
|
struct btrfs_delayed_data_ref *full_ref;
|
|
|
struct btrfs_delayed_ref_root *delayed_refs;
|
|
|
+ u64 seq = 0;
|
|
|
|
|
|
if (action == BTRFS_ADD_DELAYED_EXTENT)
|
|
|
action = BTRFS_ADD_DELAYED_REF;
|
|
@@ -549,6 +579,10 @@ static noinline int add_delayed_data_ref(struct btrfs_fs_info *fs_info,
|
|
|
ref->is_head = 0;
|
|
|
ref->in_tree = 1;
|
|
|
|
|
|
+ if (need_ref_seq(for_cow, ref_root))
|
|
|
+ seq = inc_delayed_seq(delayed_refs);
|
|
|
+ ref->seq = seq;
|
|
|
+
|
|
|
full_ref = btrfs_delayed_node_to_data_ref(ref);
|
|
|
full_ref->parent = parent;
|
|
|
full_ref->root = ref_root;
|