summaryrefslogtreecommitdiff
path: root/fs/xfs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:15:44 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-12-15 17:29:10 -0800
commita7925d8050c98f58d0e4b3095a5203da5c8907e3 (patch)
tree2aef304c4e94de7355f8c30cd113a06fd9c7754d /fs/xfs
parent3e3238df208f95b40fd3cd8e7464e4061853afa3 (diff)
xfs: support leaves in the incore btree root block in xfs_iroot_realloc
Add some logic to xfs_iroot_realloc so that we can handle leaf records in the btree root block correctly. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c4
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.h5
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.c12
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.h5
-rw-r--r--fs/xfs/scrub/bmap_repair.c2
5 files changed, 18 insertions, 10 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 9c58d2a8369c..2499807ab295 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -522,6 +522,7 @@ xfs_bmbt_broot_move(
size_t dst_bytes,
struct xfs_btree_block *src_broot,
size_t src_bytes,
+ unsigned int level,
unsigned int numrecs)
{
struct xfs_mount *mp = ip->i_mount;
@@ -529,6 +530,7 @@ xfs_bmbt_broot_move(
void *sptr;
ASSERT(xfs_bmap_bmdr_space(src_broot) <= XFS_IFORK_SIZE(ip, whichfork));
+ ASSERT(level > 0);
/*
* We always have to move the pointers because they are not butted
@@ -841,7 +843,7 @@ xfs_bmbt_iroot_alloc(
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
xfs_iroot_alloc(ip, whichfork,
- xfs_bmap_broot_space_calc(ip->i_mount, 1));
+ xfs_bmap_broot_space_calc(ip->i_mount, 1, 1));
/* Fill in the root. */
xfs_btree_init_block_int(ip->i_mount, ifp->if_broot,
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
index a9ddc9b42e61..d20321bfe2f6 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.h
+++ b/fs/xfs/libxfs/xfs_bmap_btree.h
@@ -161,8 +161,11 @@ xfs_bmap_broot_ptr_addr(
static inline size_t
xfs_bmap_broot_space_calc(
struct xfs_mount *mp,
+ unsigned int level,
unsigned int nrecs)
{
+ ASSERT(level > 0);
+
/*
* If the bmbt root block is empty, we should be converting the fork
* to extents format. Hence, the size is zero.
@@ -183,7 +186,7 @@ xfs_bmap_broot_space(
struct xfs_mount *mp,
struct xfs_bmdr_block *bb)
{
- return xfs_bmap_broot_space_calc(mp, be16_to_cpu(bb->bb_numrecs));
+ return xfs_bmap_broot_space_calc(mp, 1, be16_to_cpu(bb->bb_numrecs));
}
/* Compute the space required for the ondisk root block. */
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 3daa3fd9ea4f..4cb6d51aa31e 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -390,6 +390,7 @@ xfs_iroot_realloc(
struct xfs_btree_block *new_broot;
size_t new_size;
size_t old_size = ifp->if_broot_bytes;
+ unsigned int level;
int cur_max;
int new_max;
@@ -404,16 +405,17 @@ xfs_iroot_realloc(
if (old_size == 0) {
ASSERT(rec_diff > 0);
- new_size = ops->size(mp, rec_diff);
+ new_size = ops->size(mp, 0, rec_diff);
xfs_iroot_alloc(ip, whichfork, new_size);
return;
}
/* Compute the new and old record count and space requirements. */
- cur_max = ops->maxrecs(mp, old_size, false);
+ level = be16_to_cpu(ifp->if_broot->bb_level);
+ cur_max = ops->maxrecs(mp, old_size, level == 0);
new_max = cur_max + rec_diff;
ASSERT(new_max >= 0);
- new_size = ops->size(mp, new_max);
+ new_size = ops->size(mp, level, new_max);
if (rec_diff > 0) {
/*
@@ -425,7 +427,7 @@ xfs_iroot_realloc(
GFP_NOFS | __GFP_NOFAIL);
ifp->if_broot_bytes = new_size;
ops->move(ip, whichfork, ifp->if_broot, new_size,
- ifp->if_broot, old_size, cur_max);
+ ifp->if_broot, old_size, level, cur_max);
return;
}
@@ -442,7 +444,7 @@ xfs_iroot_realloc(
/* Reallocate the btree root and move the contents. */
new_broot = kmem_alloc(new_size, KM_NOFS);
ops->move(ip, whichfork, new_broot, new_size, ifp->if_broot,
- ifp->if_broot_bytes, new_max);
+ ifp->if_broot_bytes, level, new_max);
kmem_free(ifp->if_broot);
ifp->if_broot = new_broot;
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index a20c4590087c..8e4bea9a7094 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -248,7 +248,8 @@ struct xfs_ifork_broot_ops {
bool leaf);
/* Calculate the bytes required for the incore btree root block. */
- size_t (*size)(struct xfs_mount *mp, unsigned int nrecs);
+ size_t (*size)(struct xfs_mount *mp, unsigned int level,
+ unsigned int nrecs);
/*
* Move an incore btree root from one buffer to another. Note that
@@ -258,7 +259,7 @@ struct xfs_ifork_broot_ops {
void (*move)(struct xfs_inode *ip, int whichfork,
struct xfs_btree_block *dst_broot, size_t dst_bytes,
struct xfs_btree_block *src_broot, size_t src_bytes,
- unsigned int numrecs);
+ unsigned int level, unsigned int numrecs);
};
void xfs_iroot_realloc(struct xfs_inode *ip, int whichfork,
diff --git a/fs/xfs/scrub/bmap_repair.c b/fs/xfs/scrub/bmap_repair.c
index b4d0cddbbdba..188370660efc 100644
--- a/fs/xfs/scrub/bmap_repair.c
+++ b/fs/xfs/scrub/bmap_repair.c
@@ -328,7 +328,7 @@ xrep_bmap_iroot_size(
{
ASSERT(level > 0);
- return xfs_bmap_broot_space_calc(cur->bc_mp, nr_this_level);
+ return xfs_bmap_broot_space_calc(cur->bc_mp, level, nr_this_level);
}
/* Update the inode counters. */