/*
 * find an head entry based on bytenr. This returns the delayed ref
 * head if it was able to find one, or NULL if nothing was in that spot
 */
static struct btrfs_delayed_ref_node *find_ref_head(struct rb_root *root,
				  u64 bytenr,
				  struct btrfs_delayed_ref_node **last)
{
	struct rb_node *n = root->rb_node;
	struct btrfs_delayed_ref_node *entry;
	int cmp;

	while (n) {
		entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node);
		WARN_ON(!entry->in_tree);
		if (last)
			*last = entry;

		if (bytenr < entry->bytenr)
			cmp = -1;
		else if (bytenr > entry->bytenr)
			cmp = 1;
		else if (!btrfs_delayed_ref_is_head(entry))
			cmp = 1;
		else
			cmp = 0;

		if (cmp < 0)
			n = n->rb_left;
		else if (cmp > 0)
			n = n->rb_right;
		else
			return entry;
	}
	return NULL;
}
Example #2
0
/*
 * find an head entry based on bytenr. This returns the delayed ref
 * head if it was able to find one, or NULL if nothing was in that spot.
 * If return_bigger is given, the next bigger entry is returned if no exact
 * match is found.
 */
static struct btrfs_delayed_ref_node *find_ref_head(struct rb_root *root,
				  u64 bytenr,
				  struct btrfs_delayed_ref_node **last,
				  int return_bigger)
{
	struct rb_node *n;
	struct btrfs_delayed_ref_node *entry;
	int cmp = 0;

again:
	n = root->rb_node;
	entry = NULL;
	while (n) {
		entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node);
		WARN_ON(!entry->in_tree);
		if (last)
			*last = entry;

		if (bytenr < entry->bytenr)
			cmp = -1;
		else if (bytenr > entry->bytenr)
			cmp = 1;
		else if (!btrfs_delayed_ref_is_head(entry))
			cmp = 1;
		else
			cmp = 0;

		if (cmp < 0)
			n = n->rb_left;
		else if (cmp > 0)
			n = n->rb_right;
		else
			return entry;
	}
	if (entry && return_bigger) {
		if (cmp > 0) {
			n = rb_next(&entry->rb_node);
			if (!n)
				n = rb_first(root);
			entry = rb_entry(n, struct btrfs_delayed_ref_node,
					 rb_node);
			bytenr = entry->bytenr;
			return_bigger = 0;
			goto again;
		}
		return entry;
	}