/* * entries in the rb tree are ordered by the byte number of the extent, * type of the delayed backrefs and content of delayed backrefs. */ static int comp_entry(struct btrfs_delayed_ref_node *ref2, struct btrfs_delayed_ref_node *ref1) { if (ref1->bytenr < ref2->bytenr) return -1; if (ref1->bytenr > ref2->bytenr) return 1; if (ref1->is_head && ref2->is_head) return 0; if (ref2->is_head) return -1; if (ref1->is_head) return 1; 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) { return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2), btrfs_delayed_node_to_tree_ref(ref1)); } else if (ref1->type == BTRFS_EXTENT_DATA_REF_KEY || ref1->type == BTRFS_SHARED_DATA_REF_KEY) { return comp_data_refs(btrfs_delayed_node_to_data_ref(ref2), btrfs_delayed_node_to_data_ref(ref1)); } BUG(); 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; }
/* * entries in the rb tree are ordered by the byte number of the extent, * type of the delayed backrefs and content of delayed backrefs. */ static int comp_entry(struct btrfs_delayed_ref_node *ref2, struct btrfs_delayed_ref_node *ref1, bool compare_seq) { if (ref1->bytenr < ref2->bytenr) return -1; if (ref1->bytenr > ref2->bytenr) return 1; if (ref1->is_head && ref2->is_head) return 0; if (ref2->is_head) return -1; if (ref1->is_head) return 1; if (ref1->type < ref2->type) return -1; if (ref1->type > ref2->type) return 1; /* merging of sequenced refs is not allowed */ if (compare_seq) { 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), btrfs_delayed_node_to_tree_ref(ref1), ref1->type); } else if (ref1->type == BTRFS_EXTENT_DATA_REF_KEY || ref1->type == BTRFS_SHARED_DATA_REF_KEY) { return comp_data_refs(btrfs_delayed_node_to_data_ref(ref2), btrfs_delayed_node_to_data_ref(ref1)); } BUG(); return 0; }
/* * add all currently queued delayed refs from this head whose seq nr is * smaller or equal that seq to the list */ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, struct list_head *prefs) { struct btrfs_delayed_extent_op *extent_op = head->extent_op; struct rb_node *n = &head->node.rb_node; struct btrfs_key key; struct btrfs_key op_key = {0}; int sgn; int ret = 0; if (extent_op && extent_op->update_key) btrfs_disk_key_to_cpu(&op_key, &extent_op->key); while ((n = rb_prev(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); if (node->seq > seq) continue; switch (node->action) { case BTRFS_ADD_DELAYED_EXTENT: case BTRFS_UPDATE_DELAYED_HEAD: WARN_ON(1); continue; case BTRFS_ADD_DELAYED_REF: sgn = 1; break; case BTRFS_DROP_DELAYED_REF: sgn = -1; break; default: BUG_ON(1); } switch (node->type) { case BTRFS_TREE_BLOCK_REF_KEY: { struct btrfs_delayed_tree_ref *ref; ref = btrfs_delayed_node_to_tree_ref(node); ret = __add_prelim_ref(prefs, ref->root, &op_key, ref->level + 1, 0, node->bytenr, node->ref_mod * sgn); break; } case BTRFS_SHARED_BLOCK_REF_KEY: { struct btrfs_delayed_tree_ref *ref; ref = btrfs_delayed_node_to_tree_ref(node); ret = __add_prelim_ref(prefs, ref->root, NULL, ref->level + 1, ref->parent, node->bytenr, node->ref_mod * sgn); break; } case BTRFS_EXTENT_DATA_REF_KEY: { struct btrfs_delayed_data_ref *ref; ref = btrfs_delayed_node_to_data_ref(node); key.objectid = ref->objectid; key.type = BTRFS_EXTENT_DATA_KEY; key.offset = ref->offset; ret = __add_prelim_ref(prefs, ref->root, &key, 0, 0, node->bytenr, node->ref_mod * sgn); break; } case BTRFS_SHARED_DATA_REF_KEY: { struct btrfs_delayed_data_ref *ref; ref = btrfs_delayed_node_to_data_ref(node); key.objectid = ref->objectid; key.type = BTRFS_EXTENT_DATA_KEY; key.offset = ref->offset; ret = __add_prelim_ref(prefs, ref->root, &key, 0, ref->parent, node->bytenr, node->ref_mod * sgn); break; } default: WARN_ON(1); } if (ret) return ret; } return 0; }