Skip to content

Commit 8bfb4e9

Browse files
SaltyKitkatkdave
authored andcommitted
btrfs: extract root promotion logic into promote_child_to_root()
The balance_level() function is overly long and contains a cold code path that handles promoting a child node to root when the root has only one item. This code has distinct logic that is clearer and more maintainable when isolated in its own function. No functional change. Signed-off-by: Sun YangKai <sunk67188@gmail.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 7e97749 commit 8bfb4e9

File tree

1 file changed

+71
-45
lines changed

1 file changed

+71
-45
lines changed

fs/btrfs/ctree.c

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,76 @@ struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent,
861861
return eb;
862862
}
863863

864+
/*
865+
* Promote a child node to become the new tree root.
866+
*
867+
* This helper is called during rebalancing when the root node contains only
868+
* a single item (nritems == 1). We can reduce the tree height by promoting
869+
* that child to become the new root and freeing the old root node. The path
870+
* locks and references are updated accordingly.
871+
*
872+
* @trans: Transaction handle
873+
* @root: Tree root structure to update
874+
* @path: Path holding nodes and locks
875+
* @level: Level of the parent (old root)
876+
* @parent: The parent (old root) with exactly one item
877+
*
878+
* Return: 0 on success, negative errno on failure. The transaction is aborted
879+
* on critical errors.
880+
*/
881+
static noinline int promote_child_to_root(struct btrfs_trans_handle *trans,
882+
struct btrfs_root *root,
883+
struct btrfs_path *path,
884+
int level,
885+
struct extent_buffer *parent)
886+
{
887+
struct extent_buffer *child;
888+
int ret = 0;
889+
890+
ASSERT(btrfs_header_nritems(parent) == 1);
891+
892+
child = btrfs_read_node_slot(parent, 0);
893+
if (IS_ERR(child))
894+
return PTR_ERR(child);
895+
896+
btrfs_tree_lock(child);
897+
ret = btrfs_cow_block(trans, root, child, parent, 0, &child,
898+
BTRFS_NESTING_COW);
899+
if (ret) {
900+
btrfs_tree_unlock(child);
901+
free_extent_buffer(child);
902+
return ret;
903+
}
904+
905+
ret = btrfs_tree_mod_log_insert_root(root->node, child, true);
906+
if (unlikely(ret < 0)) {
907+
btrfs_tree_unlock(child);
908+
free_extent_buffer(child);
909+
btrfs_abort_transaction(trans, ret);
910+
return ret;
911+
}
912+
rcu_assign_pointer(root->node, child);
913+
914+
add_root_to_dirty_list(root);
915+
btrfs_tree_unlock(child);
916+
917+
path->locks[level] = 0;
918+
path->nodes[level] = NULL;
919+
btrfs_clear_buffer_dirty(trans, parent);
920+
btrfs_tree_unlock(parent);
921+
/* once for the path */
922+
free_extent_buffer(parent);
923+
924+
root_sub_used_bytes(root);
925+
ret = btrfs_free_tree_block(trans, btrfs_root_id(root), parent, 0, 1);
926+
/* once for the root ptr */
927+
free_extent_buffer_stale(parent);
928+
if (unlikely(ret < 0)) {
929+
btrfs_abort_transaction(trans, ret);
930+
return ret;
931+
}
932+
return 0;
933+
}
864934
/*
865935
* node level balancing, used to make sure nodes are in proper order for
866936
* item deletion. We balance from the top down, so we have to make sure
@@ -900,55 +970,11 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
900970
* by promoting the node below to a root
901971
*/
902972
if (!parent) {
903-
struct extent_buffer *child;
904-
905973
if (btrfs_header_nritems(mid) != 1)
906974
return 0;
907975

908976
/* promote the child to a root */
909-
child = btrfs_read_node_slot(mid, 0);
910-
if (IS_ERR(child)) {
911-
ret = PTR_ERR(child);
912-
goto out;
913-
}
914-
915-
btrfs_tree_lock(child);
916-
ret = btrfs_cow_block(trans, root, child, mid, 0, &child,
917-
BTRFS_NESTING_COW);
918-
if (ret) {
919-
btrfs_tree_unlock(child);
920-
free_extent_buffer(child);
921-
goto out;
922-
}
923-
924-
ret = btrfs_tree_mod_log_insert_root(root->node, child, true);
925-
if (unlikely(ret < 0)) {
926-
btrfs_tree_unlock(child);
927-
free_extent_buffer(child);
928-
btrfs_abort_transaction(trans, ret);
929-
goto out;
930-
}
931-
rcu_assign_pointer(root->node, child);
932-
933-
add_root_to_dirty_list(root);
934-
btrfs_tree_unlock(child);
935-
936-
path->locks[level] = 0;
937-
path->nodes[level] = NULL;
938-
btrfs_clear_buffer_dirty(trans, mid);
939-
btrfs_tree_unlock(mid);
940-
/* once for the path */
941-
free_extent_buffer(mid);
942-
943-
root_sub_used_bytes(root);
944-
ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
945-
/* once for the root ptr */
946-
free_extent_buffer_stale(mid);
947-
if (unlikely(ret < 0)) {
948-
btrfs_abort_transaction(trans, ret);
949-
goto out;
950-
}
951-
return 0;
977+
return promote_child_to_root(trans, root, path, level, mid);
952978
}
953979
if (btrfs_header_nritems(mid) >
954980
BTRFS_NODEPTRS_PER_BLOCK(fs_info) / 4)

0 commit comments

Comments
 (0)