示例#1
0
void extent_io_tree_cleanup(struct extent_io_tree *tree)
{
	struct extent_state *es;
	struct extent_buffer *eb;
	struct cache_extent *cache;

	while(!list_empty(&tree->lru)) {
		eb = list_entry(tree->lru.next, struct extent_buffer, lru);
		if (eb->refs != 1) {
			fprintf(stderr, "extent buffer leak: "
				"start %llu len %u\n",
				(unsigned long long)eb->start, eb->len);
			eb->refs = 1;
		}
		free_extent_buffer(eb);
	}
	while (1) {
		cache = find_first_cache_extent(&tree->state, 0);
		if (!cache)
			break;
		es = container_of(cache, struct extent_state, cache_node);
		remove_cache_extent(&tree->state, &es->cache_node);
		free_extent_state(es);
	}
}
示例#2
0
int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
			  u64 *start_ret, u64 *end_ret, int bits)
{
	struct cache_extent *node;
	struct extent_state *state;
	int ret = 1;

	/*
	 * this search will find all the extents that end after
	 * our range starts.
	 */
	node = find_first_cache_extent(&tree->state, start);
	if (!node)
		goto out;

	while(1) {
		state = container_of(node, struct extent_state, cache_node);
		if (state->end >= start && (state->state & bits)) {
			*start_ret = state->start;
			*end_ret = state->end;
			ret = 0;
			break;
		}
		node = next_cache_extent(node);
		if (!node)
			break;
	}
out:
	return ret;
}
示例#3
0
static int free_fs_roots(struct btrfs_fs_info *fs_info)
{
	struct cache_extent *cache;
	struct btrfs_root *root;

	while (1) {
		cache = find_first_cache_extent(&fs_info->fs_root_cache, 0);
		if (!cache)
			break;
		root = container_of(cache, struct btrfs_root, cache);
		remove_cache_extent(&fs_info->fs_root_cache, cache);
		btrfs_free_fs_root(fs_info, root);
	}
	return 0;
}
示例#4
0
int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end,
		   int bits, int filled)
{
	struct extent_state *state = NULL;
	struct cache_extent *node;
	int bitset = 0;

	node = find_first_cache_extent(&tree->state, start);
	while (node && start <= end) {
		state = container_of(node, struct extent_state, cache_node);

		if (filled && state->start > start) {
			bitset = 0;
			break;
		}
		if (state->start > end)
			break;
		if (state->state & bits) {
			bitset = 1;
			if (!filled)
				break;
		} else if (filled) {
			bitset = 0;
			break;
		}
		start = state->end + 1;
		if (start > end)
			break;
		node = next_cache_extent(node);
		if (!node) {
			if (filled)
				bitset = 0;
			break;
		}
	}
	return bitset;
}
示例#5
0
/*
 * set some bits on a range in the tree.
 */
int set_extent_bits(struct extent_io_tree *tree, u64 start,
		    u64 end, int bits, gfp_t mask)
{
	struct extent_state *state;
	struct extent_state *prealloc = NULL;
	struct cache_extent *node;
	int err = 0;
	u64 last_start;
	u64 last_end;
again:
	if (!prealloc) {
		prealloc = alloc_extent_state();
		if (!prealloc)
			return -ENOMEM;
	}

	/*
	 * this search will find the extents that end after
	 * our range starts
	 */
	node = find_first_cache_extent(&tree->state, start);
	if (!node) {
		err = insert_state(tree, prealloc, start, end, bits);
		BUG_ON(err == -EEXIST);
		prealloc = NULL;
		goto out;
	}

	state = container_of(node, struct extent_state, cache_node);
	last_start = state->start;
	last_end = state->end;

	/*
	 * | ---- desired range ---- |
	 * | state |
	 *
	 * Just lock what we found and keep going
	 */
	if (state->start == start && state->end <= end) {
		state->state |= bits;
		merge_state(tree, state);
		if (last_end == (u64)-1)
			goto out;
		start = last_end + 1;
		goto search_again;
	}
	/*
	 *     | ---- desired range ---- |
	 * | state |
	 *   or
	 * | ------------- state -------------- |
	 *
	 * We need to split the extent we found, and may flip bits on
	 * second half.
	 *
	 * If the extent we found extends past our
	 * range, we just split and search again.  It'll get split
	 * again the next time though.
	 *
	 * If the extent we found is inside our range, we set the
	 * desired bit on it.
	 */
	if (state->start < start) {
		err = split_state(tree, state, prealloc, start);
		BUG_ON(err == -EEXIST);
		prealloc = NULL;
		if (err)
			goto out;
		if (state->end <= end) {
			state->state |= bits;
			start = state->end + 1;
			merge_state(tree, state);
			if (last_end == (u64)-1)
				goto out;
			start = last_end + 1;
		} else {
			start = state->start;
		}
		goto search_again;
	}
	/*
	 * | ---- desired range ---- |
	 *     | state | or               | state |
	 *
	 * There's a hole, we need to insert something in it and
	 * ignore the extent we found.
	 */
	if (state->start > start) {
		u64 this_end;
		if (end < last_start)
			this_end = end;
		else
			this_end = last_start -1;
		err = insert_state(tree, prealloc, start, this_end,
				bits);
		BUG_ON(err == -EEXIST);
		prealloc = NULL;
		if (err)
			goto out;
		start = this_end + 1;
		goto search_again;
	}
	/*
	 * | ---- desired range ---- |
	 * | ---------- state ---------- |
	 * We need to split the extent, and set the bit
	 * on the first half
	 */
	err = split_state(tree, state, prealloc, end + 1);
	BUG_ON(err == -EEXIST);

	state->state |= bits;
	merge_state(tree, prealloc);
	prealloc = NULL;
out:
	if (prealloc)
		free_extent_state(prealloc);
	return err;
search_again:
	if (start > end)
		goto out;
	goto again;
}
示例#6
0
/*
 * set some bits on a range in the tree.
 */
int clear_extent_bits(struct extent_io_tree *tree, u64 start,
		      u64 end, int bits, gfp_t mask)
{
	struct extent_state *state;
	struct extent_state *prealloc = NULL;
	struct cache_extent *node;
	u64 last_end;
	int err;
	int set = 0;

again:
	prealloc = alloc_extent_state();
	if (!prealloc)
		return -ENOMEM;

	/*
	 * this search will find the extents that end after
	 * our range starts
	 */
	node = find_first_cache_extent(&tree->state, start);
	if (!node)
		goto out;
	state = container_of(node, struct extent_state, cache_node);
	if (state->start > end)
		goto out;
	last_end = state->end;

	/*
	 *     | ---- desired range ---- |
	 *  | state | or
	 *  | ------------- state -------------- |
	 *
	 * We need to split the extent we found, and may flip
	 * bits on second half.
	 *
	 * If the extent we found extends past our range, we
	 * just split and search again.  It'll get split again
	 * the next time though.
	 *
	 * If the extent we found is inside our range, we clear
	 * the desired bit on it.
	 */
	if (state->start < start) {
		err = split_state(tree, state, prealloc, start);
		BUG_ON(err == -EEXIST);
		prealloc = NULL;
		if (err)
			goto out;
		if (state->end <= end) {
			set |= clear_state_bit(tree, state, bits);
			if (last_end == (u64)-1)
				goto out;
			start = last_end + 1;
		} else {
			start = state->start;
		}
		goto search_again;
	}
	/*
	 * | ---- desired range ---- |
	 *                        | state |
	 * We need to split the extent, and clear the bit
	 * on the first half
	 */
	if (state->start <= end && state->end > end) {
		err = split_state(tree, state, prealloc, end + 1);
		BUG_ON(err == -EEXIST);

		set |= clear_state_bit(tree, prealloc, bits);
		prealloc = NULL;
		goto out;
	}

	start = state->end + 1;
	set |= clear_state_bit(tree, state, bits);
	if (last_end == (u64)-1)
		goto out;
	start = last_end + 1;
	goto search_again;
out:
	if (prealloc)
		free_extent_state(prealloc);
	return set;

search_again:
	if (start > end)
		goto out;
	goto again;
}
示例#7
0
		if (!node) {
			if (filled)
				bitset = 0;
			break;
		}
	}
	return bitset;
}

int set_state_private(struct extent_io_tree *tree, u64 start, u64 private)
{
	struct cache_extent *node;
	struct extent_state *state;
	int ret = 0;

	node = find_first_cache_extent(&tree->state, start);
	if (!node) {
		ret = -ENOENT;
		goto out;
	}
	state = container_of(node, struct extent_state, cache_node);
	if (state->start != start) {
		ret = -ENOENT;
		goto out;
	}
	state->xprivate = private;
out:
	return ret;
}

int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private)