Example #1
0
int remove_from_free_space_tree(struct btrfs_trans_handle *trans,
				u64 start, u64 size)
{
	struct btrfs_block_group_cache *block_group;
	struct btrfs_path *path;
	int ret;

	if (!btrfs_fs_compat_ro(trans->fs_info, FREE_SPACE_TREE))
		return 0;

	path = btrfs_alloc_path();
	if (!path) {
		ret = -ENOMEM;
		goto out;
	}

	block_group = btrfs_lookup_block_group(trans->fs_info, start);
	if (!block_group) {
		ASSERT(0);
		ret = -ENOENT;
		goto out;
	}

	mutex_lock(&block_group->free_space_lock);
	ret = __remove_from_free_space_tree(trans, block_group, path, start,
					    size);
	mutex_unlock(&block_group->free_space_lock);

	btrfs_put_block_group(block_group);
out:
	btrfs_free_path(path);
	if (ret)
		btrfs_abort_transaction(trans, ret);
	return ret;
}
Example #2
0
static int custom_alloc_extent(struct btrfs_root *root, u64 num_bytes,
			       u64 hint_byte, struct btrfs_key *ins)
{
	u64 start;
	u64 end;
	u64 last = hint_byte;
	int ret;
	int wrapped = 0;
	struct btrfs_block_group_cache *cache;

	while (1) {
		ret = find_first_extent_bit(&root->fs_info->free_space_cache,
					    last, &start, &end, EXTENT_DIRTY);
		if (ret) {
			if (wrapped++ == 0) {
				last = 0;
				continue;
			} else {
				goto fail;
			}
		}

		start = max(last, start);
		last = end + 1;
		if (last - start < num_bytes)
			continue;

		last = start + num_bytes;
		if (test_range_bit(&root->fs_info->pinned_extents,
				   start, last - 1, EXTENT_DIRTY, 0))
			continue;

		cache = btrfs_lookup_block_group(root->fs_info, start);
		BUG_ON(!cache);
		if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM ||
		    last > cache->key.objectid + cache->key.offset) {
			last = cache->key.objectid + cache->key.offset;
			continue;
		}

		if (cache->flags & (BTRFS_BLOCK_GROUP_SYSTEM |
			    BTRFS_BLOCK_GROUP_METADATA)) {
			last = cache->key.objectid + cache->key.offset;
			continue;
		}

		clear_extent_dirty(&root->fs_info->free_space_cache,
				   start, start + num_bytes - 1, 0);

		ins->objectid = start;
		ins->offset = num_bytes;
		ins->type = BTRFS_EXTENT_ITEM_KEY;
		return 0;
	}
fail:
	fprintf(stderr, "not enough free space\n");
	return -ENOSPC;
}