diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:15:44 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-10-22 16:40:53 -0700 |
commit | b77e454582eb2cc69a1db776b664ecea9f0e75ca (patch) | |
tree | 460c0b7e70edfd6ae83686f228e600aad44c8b99 | |
parent | 23d77e3a004d43ca1e6053d805fa31f672ea91d7 (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>
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap_btree.c | 4 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap_btree.h | 5 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_fork.c | 12 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_fork.h | 5 | ||||
-rw-r--r-- | fs/xfs/scrub/bmap_repair.c | 2 |
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 ce1a738dbfed..ce7f0e34a121 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 @@ -796,7 +798,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 13920e1acb53..aa5e48826dd4 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 1326db84b833..801a6f7dbd0c 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 89aad41a8832..cf82be263b48 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 2b50b6873d7f..000a6818a28c 100644 --- a/fs/xfs/scrub/bmap_repair.c +++ b/fs/xfs/scrub/bmap_repair.c @@ -334,7 +334,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. */ |