btrfs-progs: extent-tree: Introduce btrfs_free_block_group function

This function will be used to free a empty chunk.

This provides the basis for later temp chunk cleanup.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
master
Qu Wenruo 2015-07-07 16:15:27 +08:00 committed by David Sterba
parent 00827cad8e
commit 80fc1e0fc6
2 changed files with 82 additions and 0 deletions

View File

@ -2275,6 +2275,8 @@ int btrfs_record_file_extent(struct btrfs_trans_handle *trans,
struct btrfs_inode_item *inode,
u64 file_pos, u64 disk_bytenr,
u64 num_bytes);
int btrfs_free_block_group(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr, u64 len);
/* ctree.c */
int btrfs_comp_cpu_keys(struct btrfs_key *k1, struct btrfs_key *k2);
int btrfs_del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,

View File

@ -3743,6 +3743,86 @@ out:
return ret;
}
int btrfs_free_block_group(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr, u64 len)
{
struct btrfs_root *extent_root = fs_info->extent_root;
struct btrfs_path *path;
struct btrfs_block_group_item *bgi;
struct btrfs_key key;
int ret = 0;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
key.objectid = bytenr;
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
key.offset = len;
/* Double check the block group to ensure it's empty */
ret = btrfs_search_slot(trans, extent_root, &key, path, 0, 0);
if (ret > 0) {
ret = -ENONET;
goto out;
}
if (ret < 0)
goto out;
bgi = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_block_group_item);
if (btrfs_disk_block_group_used(path->nodes[0], bgi)) {
fprintf(stderr,
"WARNING: block group [%llu,%llu) is not empty\n",
bytenr, bytenr + len);
ret = -EINVAL;
goto out;
}
btrfs_release_path(path);
/*
* Now pin all space in the block group, to prevent further transaction
* allocate space from it.
* Every operation needs a transaction must be in the range.
*/
btrfs_pin_extent(fs_info, bytenr, len);
/* delete block group item and chunk item */
ret = free_block_group_item(trans, fs_info, bytenr, len);
if (ret < 0) {
fprintf(stderr,
"failed to free block group item for [%llu,%llu)\n",
bytenr, bytenr + len);
btrfs_unpin_extent(fs_info, bytenr, len);
goto out;
}
ret = free_chunk_dev_extent_items(trans, fs_info, bytenr);
if (ret < 0) {
fprintf(stderr,
"failed to dev extents belongs to [%llu,%llu)\n",
bytenr, bytenr + len);
btrfs_unpin_extent(fs_info, bytenr, len);
goto out;
}
ret = free_chunk_item(trans, fs_info, bytenr, len);
if (ret < 0) {
fprintf(stderr,
"failed to free chunk for [%llu,%llu)\n",
bytenr, bytenr + len);
btrfs_unpin_extent(fs_info, bytenr, len);
goto out;
}
/* Now release the block_group_cache */
ret = free_block_group_cache(trans, fs_info, bytenr, len);
btrfs_unpin_extent(fs_info, bytenr, len);
out:
btrfs_free_path(path);
return ret;
}
/*
* Fixup block accounting. The initial block accounting created by
* make_block_groups isn't accuracy in this case.