xfs: hoist the node iroot update code out of xfs_btree_kill_iroot

In preparation for allowing records in an inode btree root, hoist the
code that copies keyptrs from an existing node child into the root block
to a separate function.  Remove some unnecessary conditionals and clean
up a few function calls in the new function.  Note that this change
reorders the ->free_block call with respect to the change in bc_nlevels
to make it easier to support inode root leaf blocks in the next patch.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong
2024-11-20 16:20:17 -08:00
parent 7708951ae5
commit 505248719f

View File

@@ -3726,6 +3726,60 @@ xfs_btree_insert(
return error;
}
/*
* Move the keyptrs from a child node block to the root block.
*
* Since the keyptr size does not change, all we have to do is increase the
* tree height, copy the keyptrs to the new internal node (cblock), shrink
* the root, and copy the pointers there.
*/
STATIC int
xfs_btree_demote_node_child(
struct xfs_btree_cur *cur,
struct xfs_btree_block *cblock,
int level,
int numrecs)
{
struct xfs_btree_block *block;
union xfs_btree_key *ckp;
union xfs_btree_key *kp;
union xfs_btree_ptr *cpp;
union xfs_btree_ptr *pp;
int i;
int error;
/*
* Adjust the root btree node size and the record count to match the
* doomed child so that we can copy the keyptrs ahead of changing the
* tree shape.
*/
block = cur->bc_ops->broot_realloc(cur, numrecs);
xfs_btree_set_numrecs(block, numrecs);
ASSERT(block->bb_numrecs == cblock->bb_numrecs);
/* Copy keys from the doomed block. */
kp = xfs_btree_key_addr(cur, 1, block);
ckp = xfs_btree_key_addr(cur, 1, cblock);
xfs_btree_copy_keys(cur, kp, ckp, numrecs);
/* Copy pointers from the doomed block. */
pp = xfs_btree_ptr_addr(cur, 1, block);
cpp = xfs_btree_ptr_addr(cur, 1, cblock);
for (i = 0; i < numrecs; i++) {
error = xfs_btree_debug_check_ptr(cur, cpp, i, level - 1);
if (error)
return error;
}
xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
/* Decrease tree height, adjusting the root block level to match. */
cur->bc_levels[level - 1].bp = NULL;
be16_add_cpu(&block->bb_level, -1);
cur->bc_nlevels--;
return 0;
}
/*
* Try to merge a non-leaf block back into the inode root.
*
@@ -3741,10 +3795,6 @@ xfs_btree_kill_iroot(
struct xfs_inode *ip = cur->bc_ino.ip;
struct xfs_btree_block *block;
struct xfs_btree_block *cblock;
union xfs_btree_key *kp;
union xfs_btree_key *ckp;
union xfs_btree_ptr *pp;
union xfs_btree_ptr *cpp;
struct xfs_buf *cbp;
int level;
int numrecs;
@@ -3752,7 +3802,6 @@ xfs_btree_kill_iroot(
#ifdef DEBUG
union xfs_btree_ptr ptr;
#endif
int i;
ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE);
ASSERT(cur->bc_nlevels > 1);
@@ -3792,35 +3841,16 @@ xfs_btree_kill_iroot(
ASSERT(xfs_btree_ptr_is_null(cur, &ptr));
#endif
block = cur->bc_ops->broot_realloc(cur, numrecs);
block->bb_numrecs = be16_to_cpu(numrecs);
ASSERT(block->bb_numrecs == cblock->bb_numrecs);
kp = xfs_btree_key_addr(cur, 1, block);
ckp = xfs_btree_key_addr(cur, 1, cblock);
xfs_btree_copy_keys(cur, kp, ckp, numrecs);
pp = xfs_btree_ptr_addr(cur, 1, block);
cpp = xfs_btree_ptr_addr(cur, 1, cblock);
for (i = 0; i < numrecs; i++) {
error = xfs_btree_debug_check_ptr(cur, cpp, i, level - 1);
if (error)
return error;
}
xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
error = xfs_btree_demote_node_child(cur, cblock, level, numrecs);
if (error)
return error;
error = xfs_btree_free_block(cur, cbp);
if (error)
return error;
cur->bc_levels[level - 1].bp = NULL;
be16_add_cpu(&block->bb_level, -1);
xfs_trans_log_inode(cur->bc_tp, ip,
XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_ino.whichfork));
cur->bc_nlevels--;
out0:
return 0;
}