xfs: refactor xfs_bmap_count_blocks using newer btree helpers

Currently, this function open-codes walking a bmbt to count the extents
and blocks in use by a particular inode fork.  Since we now have a
function to tally extent records from the incore extent tree and a btree
helper to count every block in a btree, replace all that with calls to
the helpers.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong 2019-10-28 16:12:35 -07:00
parent c2414ad6e6
commit fec40e220f

View File

@ -229,106 +229,6 @@ xfs_bmap_count_leaves(
return numrecs;
}
/*
* Count leaf blocks given a range of extent records originally
* in btree format.
*/
STATIC void
xfs_bmap_disk_count_leaves(
struct xfs_mount *mp,
struct xfs_btree_block *block,
int numrecs,
xfs_filblks_t *count)
{
int b;
xfs_bmbt_rec_t *frp;
for (b = 1; b <= numrecs; b++) {
frp = XFS_BMBT_REC_ADDR(mp, block, b);
*count += xfs_bmbt_disk_get_blockcount(frp);
}
}
/*
* Recursively walks each level of a btree
* to count total fsblocks in use.
*/
STATIC int
xfs_bmap_count_tree(
struct xfs_mount *mp,
struct xfs_trans *tp,
struct xfs_ifork *ifp,
xfs_fsblock_t blockno,
int levelin,
xfs_extnum_t *nextents,
xfs_filblks_t *count)
{
int error;
struct xfs_buf *bp, *nbp;
int level = levelin;
__be64 *pp;
xfs_fsblock_t bno = blockno;
xfs_fsblock_t nextbno;
struct xfs_btree_block *block, *nextblock;
int numrecs;
error = xfs_btree_read_bufl(mp, tp, bno, &bp, XFS_BMAP_BTREE_REF,
&xfs_bmbt_buf_ops);
if (error)
return error;
*count += 1;
block = XFS_BUF_TO_BLOCK(bp);
if (--level) {
/* Not at node above leaves, count this level of nodes */
nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
while (nextbno != NULLFSBLOCK) {
error = xfs_btree_read_bufl(mp, tp, nextbno, &nbp,
XFS_BMAP_BTREE_REF,
&xfs_bmbt_buf_ops);
if (error)
return error;
*count += 1;
nextblock = XFS_BUF_TO_BLOCK(nbp);
nextbno = be64_to_cpu(nextblock->bb_u.l.bb_rightsib);
xfs_trans_brelse(tp, nbp);
}
/* Dive to the next level */
pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
bno = be64_to_cpu(*pp);
error = xfs_bmap_count_tree(mp, tp, ifp, bno, level, nextents,
count);
if (error) {
xfs_trans_brelse(tp, bp);
XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
XFS_ERRLEVEL_LOW, mp);
return -EFSCORRUPTED;
}
xfs_trans_brelse(tp, bp);
} else {
/* count all level 1 nodes and their leaves */
for (;;) {
nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
numrecs = be16_to_cpu(block->bb_numrecs);
(*nextents) += numrecs;
xfs_bmap_disk_count_leaves(mp, block, numrecs, count);
xfs_trans_brelse(tp, bp);
if (nextbno == NULLFSBLOCK)
break;
bno = nextbno;
error = xfs_btree_read_bufl(mp, tp, bno, &bp,
XFS_BMAP_BTREE_REF,
&xfs_bmbt_buf_ops);
if (error)
return error;
*count += 1;
block = XFS_BUF_TO_BLOCK(bp);
}
}
return 0;
}
/*
* Count fsblocks of the given fork. Delayed allocation extents are
* not counted towards the totals.
@ -341,26 +241,19 @@ xfs_bmap_count_blocks(
xfs_extnum_t *nextents,
xfs_filblks_t *count)
{
struct xfs_mount *mp; /* file system mount structure */
__be64 *pp; /* pointer to block address */
struct xfs_btree_block *block; /* current btree block */
struct xfs_ifork *ifp; /* fork structure */
xfs_fsblock_t bno; /* block # of "block" */
int level; /* btree level, for checking */
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
struct xfs_btree_cur *cur;
xfs_extlen_t btblocks = 0;
int error;
bno = NULLFSBLOCK;
mp = ip->i_mount;
*nextents = 0;
*count = 0;
ifp = XFS_IFORK_PTR(ip, whichfork);
if (!ifp)
return 0;
switch (XFS_IFORK_FORMAT(ip, whichfork)) {
case XFS_DINODE_FMT_EXTENTS:
*nextents = xfs_bmap_count_leaves(ifp, count);
return 0;
case XFS_DINODE_FMT_BTREE:
if (!(ifp->if_flags & XFS_IFEXTENTS)) {
error = xfs_iread_extents(tp, ip, whichfork);
@ -368,26 +261,23 @@ xfs_bmap_count_blocks(
return error;
}
/*
* Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
*/
block = ifp->if_broot;
level = be16_to_cpu(block->bb_level);
ASSERT(level > 0);
pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
bno = be64_to_cpu(*pp);
ASSERT(bno != NULLFSBLOCK);
ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
error = xfs_btree_count_blocks(cur, &btblocks);
xfs_btree_del_cursor(cur, error);
if (error)
return error;
error = xfs_bmap_count_tree(mp, tp, ifp, bno, level,
nextents, count);
if (error) {
XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)",
XFS_ERRLEVEL_LOW, mp);
return -EFSCORRUPTED;
}
return 0;
/*
* xfs_btree_count_blocks includes the root block contained in
* the inode fork in @btblocks, so subtract one because we're
* only interested in allocated disk blocks.
*/
*count += btblocks - 1;
/* fall through */
case XFS_DINODE_FMT_EXTENTS:
*nextents = xfs_bmap_count_leaves(ifp, count);
break;
}
return 0;