xfs: tidy up xfs_iroot_realloc

Tidy up this function a bit before we start refactoring the memory
handling and move the function to the bmbt code.

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:12 -08:00
parent 1aacd3fac2
commit 4f13f0a3fc

View File

@ -382,33 +382,32 @@ xfs_iformat_attr_fork(
*/
void
xfs_iroot_realloc(
xfs_inode_t *ip,
struct xfs_inode *ip,
int rec_diff,
int whichfork)
{
struct xfs_mount *mp = ip->i_mount;
int cur_max;
struct xfs_ifork *ifp;
struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
struct xfs_btree_block *new_broot;
int new_max;
size_t new_size;
char *np;
char *op;
size_t new_size;
short old_size = ifp->if_broot_bytes;
int cur_max;
int new_max;
/*
* Handle the degenerate case quietly.
*/
if (rec_diff == 0) {
if (rec_diff == 0)
return;
}
ifp = xfs_ifork_ptr(ip, whichfork);
if (rec_diff > 0) {
/*
* If there wasn't any memory allocated before, just
* allocate it now and get out.
*/
if (ifp->if_broot_bytes == 0) {
if (old_size == 0) {
new_size = xfs_bmap_broot_space_calc(mp, rec_diff);
ifp->if_broot = kmalloc(new_size,
GFP_KERNEL | __GFP_NOFAIL);
@ -422,13 +421,13 @@ xfs_iroot_realloc(
* location. The records don't change location because
* they are kept butted up against the btree block header.
*/
cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, false);
cur_max = xfs_bmbt_maxrecs(mp, old_size, false);
new_max = cur_max + rec_diff;
new_size = xfs_bmap_broot_space_calc(mp, new_max);
ifp->if_broot = krealloc(ifp->if_broot, new_size,
GFP_KERNEL | __GFP_NOFAIL);
op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
ifp->if_broot_bytes);
old_size);
np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
(int)new_size);
ifp->if_broot_bytes = (int)new_size;
@ -443,52 +442,50 @@ xfs_iroot_realloc(
* if_broot buffer. It must already exist. If we go to zero
* records, just get rid of the root and clear the status bit.
*/
ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, false);
ASSERT(ifp->if_broot != NULL && old_size > 0);
cur_max = xfs_bmbt_maxrecs(mp, old_size, false);
new_max = cur_max + rec_diff;
ASSERT(new_max >= 0);
if (new_max > 0)
new_size = xfs_bmap_broot_space_calc(mp, new_max);
else
new_size = 0;
if (new_size > 0) {
new_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL);
/*
* First copy over the btree block header.
*/
memcpy(new_broot, ifp->if_broot,
xfs_bmbt_block_len(ip->i_mount));
} else {
new_broot = NULL;
if (new_size == 0) {
ifp->if_broot = NULL;
ifp->if_broot_bytes = 0;
return;
}
/*
* Only copy the keys and pointers if there are any.
* Shrink the btree root by allocating a smaller object and copying the
* fields from the old object to the new object. krealloc does nothing
* if we realloc downwards.
*/
if (new_max > 0) {
/*
* First copy the keys.
*/
op = (char *)xfs_bmbt_key_addr(mp, ifp->if_broot, 1);
np = (char *)xfs_bmbt_key_addr(mp, new_broot, 1);
memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_key_t));
new_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL);
/*
* First copy over the btree block header.
*/
memcpy(new_broot, ifp->if_broot, xfs_bmbt_block_len(ip->i_mount));
/*
* First copy the keys.
*/
op = (char *)xfs_bmbt_key_addr(mp, ifp->if_broot, 1);
np = (char *)xfs_bmbt_key_addr(mp, new_broot, 1);
memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_key_t));
/*
* Then copy the pointers.
*/
op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size);
np = (char *)xfs_bmap_broot_ptr_addr(mp, new_broot, 1, (int)new_size);
memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
/*
* Then copy the pointers.
*/
op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
ifp->if_broot_bytes);
np = (char *)xfs_bmap_broot_ptr_addr(mp, new_broot, 1,
(int)new_size);
memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
}
kfree(ifp->if_broot);
ifp->if_broot = new_broot;
ifp->if_broot_bytes = (int)new_size;
if (ifp->if_broot)
ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <=
xfs_inode_fork_size(ip, whichfork));
return;
ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <=
xfs_inode_fork_size(ip, whichfork));
}