Skip to content

Commit

Permalink
btrfs-progs: add a helper for clearing all the items in a tree
Browse files Browse the repository at this point in the history
Used in clear_free_space_tree, this is a totally generic operation.
It will also be used for clearing the qgroup tree from btrfstune.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Boris Burkov <boris@bur.io>
[ Make remove_all_tree_items() to use btrfs_clear_tree() ]
Signed-off-by: Qu Wenruo <wqu@suse.com>
  • Loading branch information
boryas authored and adam900710 committed Jan 5, 2025
1 parent f8dc5ab commit c997cc1
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 76 deletions.
43 changes: 7 additions & 36 deletions common/root-tree-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,6 @@ int btrfs_link_subvolume(struct btrfs_trans_handle *trans,
static int remove_all_tree_items(struct btrfs_root *root)
{
struct btrfs_trans_handle *trans;
struct btrfs_path path = { 0 };
struct btrfs_key key = { 0 };
int ret;

trans = btrfs_start_transaction(root, 1);
Expand All @@ -239,40 +237,13 @@ static int remove_all_tree_items(struct btrfs_root *root)
root->root_key.objectid);
return ret;
}
while (true) {
int nr_items;

ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
if (ret < 0) {
errno = -ret;
error("failed to locate the first key of root %lld: %m",
root->root_key.objectid);
btrfs_abort_transaction(trans, ret);
return ret;
}
if (ret == 0) {
ret = -EUCLEAN;
errno = -ret;
error("unexpected all zero key found in root %lld",
root->root_key.objectid);
btrfs_abort_transaction(trans, ret);
return ret;
}
nr_items = btrfs_header_nritems(path.nodes[0]);
/* The tree is empty. */
if (nr_items == 0) {
btrfs_release_path(&path);
break;
}
ret = btrfs_del_items(trans, root, &path, 0, nr_items);
btrfs_release_path(&path);
if (ret < 0) {
errno = -ret;
error("failed to empty the first leaf of root %lld: %m",
root->root_key.objectid);
btrfs_abort_transaction(trans, ret);
return ret;
}
ret = btrfs_clear_tree(trans, root);
if (ret < 0) {
errno = -ret;
error("failed to empty root %lld: %m",
root->root_key.objectid);
btrfs_abort_transaction(trans, ret);
return ret;
}
ret = btrfs_commit_transaction(trans, root);
if (ret < 0) {
Expand Down
39 changes: 39 additions & 0 deletions kernel-shared/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2342,6 +2342,45 @@ static bool is_global_root(struct btrfs_root *root)
return true;
return false;
}

int btrfs_clear_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
struct btrfs_path *path;
struct btrfs_key key;
struct extent_buffer *leaf = NULL;
int ret;
int nr = 0;

path = btrfs_alloc_path();
if (!path)
return -ENOMEM;

key.objectid = 0;
key.offset = 0;
key.type = 0;

while (1) {
ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
if (ret < 0)
goto out;
leaf = path->nodes[0];
nr = btrfs_header_nritems(leaf);
if (!nr)
break;
path->slots[0] = 0;
ret = btrfs_del_items(trans, root, path, 0, nr);
if (ret)
goto out;

btrfs_release_path(path);
}
ret = 0;
out:
btrfs_free_path(path);
return ret;
}

int btrfs_delete_and_free_root(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
Expand Down
2 changes: 2 additions & 0 deletions kernel-shared/disk-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ int write_tree_block(struct btrfs_trans_handle *trans,
int btrfs_fs_roots_compare_roots(const struct rb_node *node1, const struct rb_node *node2);
struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
struct btrfs_key *key);
int btrfs_clear_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
int btrfs_delete_and_free_root(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info, u64 bytenr);
Expand Down
42 changes: 2 additions & 40 deletions kernel-shared/free-space-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1228,44 +1228,6 @@ int remove_block_group_free_space(struct btrfs_trans_handle *trans,
btrfs_abort_transaction(trans, ret);
return ret;
}
static int clear_free_space_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
struct btrfs_path *path;
struct btrfs_key key;
int nr;
int ret;

path = btrfs_alloc_path();
if (!path)
return -ENOMEM;

key.objectid = 0;
key.type = 0;
key.offset = 0;

while (1) {
ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
if (ret < 0)
goto out;

nr = btrfs_header_nritems(path->nodes[0]);
if (!nr)
break;

path->slots[0] = 0;
ret = btrfs_del_items(trans, root, path, 0, nr);
if (ret)
goto out;

btrfs_release_path(path);
}

ret = 0;
out:
btrfs_free_path(path);
return ret;
}

int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
{
Expand All @@ -1288,7 +1250,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)

while (key.offset < fs_info->nr_global_roots) {
free_space_root = btrfs_global_root(fs_info, &key);
ret = clear_free_space_tree(trans, free_space_root);
ret = btrfs_clear_tree(trans, free_space_root);
if (ret)
goto abort;
key.offset++;
Expand All @@ -1299,7 +1261,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
btrfs_set_super_compat_ro_flags(fs_info->super_copy, features);

ret = clear_free_space_tree(trans, free_space_root);
ret = btrfs_clear_tree(trans, free_space_root);
if (ret)
goto abort;

Expand Down

0 comments on commit c997cc1

Please sign in to comment.