summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-10-25 17:16:10 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2020-10-26 18:32:33 -0700
commitaa892cc6842258464334295e6a3656a962c28c69 (patch)
tree561f7e1c11048de86e0b5baee0919cd9546c6b0e /fs
parent89ab00538d737dc65f40478a7ec458b92d14060b (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 <darrick.wong@oracle.com>
Diffstat (limited to 'fs')
-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 31652174556f..1ac85c44d65c 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -520,6 +520,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;
@@ -527,6 +528,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
@@ -798,7 +800,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 6356e377f25c..61cff8474edb 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.h
+++ b/fs/xfs/libxfs/xfs_bmap_btree.h
@@ -156,8 +156,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.
@@ -178,7 +181,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 1e52ad127a0e..6b162b304c27 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -383,6 +383,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;
@@ -397,16 +398,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) {
/*
@@ -418,7 +420,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;
}
@@ -435,7 +437,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 db038dce8124..6c1542f5c14a 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -184,7 +184,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
@@ -194,7 +195,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 d750e693fc7f..417882991e1f 100644
--- a/fs/xfs/scrub/bmap_repair.c
+++ b/fs/xfs/scrub/bmap_repair.c
@@ -262,7 +262,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. */