Commit e7f5d5ca authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: refactor the ifork block counting function

Refactor the inode fork block counting function to count extents for us
at the same time.  This will be used by the bmbt scrubber function.
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent d29cb3e4
...@@ -225,7 +225,8 @@ xfs_bmap_eof( ...@@ -225,7 +225,8 @@ xfs_bmap_eof(
STATIC void STATIC void
xfs_bmap_count_leaves( xfs_bmap_count_leaves(
struct xfs_ifork *ifp, struct xfs_ifork *ifp,
int *count) xfs_extnum_t *numrecs,
xfs_filblks_t *count)
{ {
xfs_extnum_t i; xfs_extnum_t i;
xfs_extnum_t nr_exts = xfs_iext_count(ifp); xfs_extnum_t nr_exts = xfs_iext_count(ifp);
...@@ -233,6 +234,7 @@ xfs_bmap_count_leaves( ...@@ -233,6 +234,7 @@ xfs_bmap_count_leaves(
for (i = 0; i < nr_exts; i++) { for (i = 0; i < nr_exts; i++) {
xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, i); xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, i);
if (!isnullstartblock(xfs_bmbt_get_startblock(frp))) { if (!isnullstartblock(xfs_bmbt_get_startblock(frp))) {
(*numrecs)++;
*count += xfs_bmbt_get_blockcount(frp); *count += xfs_bmbt_get_blockcount(frp);
} }
} }
...@@ -247,7 +249,7 @@ xfs_bmap_disk_count_leaves( ...@@ -247,7 +249,7 @@ xfs_bmap_disk_count_leaves(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_btree_block *block, struct xfs_btree_block *block,
int numrecs, int numrecs,
int *count) xfs_filblks_t *count)
{ {
int b; int b;
xfs_bmbt_rec_t *frp; xfs_bmbt_rec_t *frp;
...@@ -262,17 +264,18 @@ xfs_bmap_disk_count_leaves( ...@@ -262,17 +264,18 @@ xfs_bmap_disk_count_leaves(
* Recursively walks each level of a btree * Recursively walks each level of a btree
* to count total fsblocks in use. * to count total fsblocks in use.
*/ */
STATIC int /* error */ STATIC int
xfs_bmap_count_tree( xfs_bmap_count_tree(
xfs_mount_t *mp, /* file system mount point */ struct xfs_mount *mp,
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_ifork_t *ifp, /* inode fork pointer */ struct xfs_ifork *ifp,
xfs_fsblock_t blockno, /* file system block number */ xfs_fsblock_t blockno,
int levelin, /* level in btree */ int levelin,
int *count) /* Count of blocks */ xfs_extnum_t *nextents,
xfs_filblks_t *count)
{ {
int error; int error;
xfs_buf_t *bp, *nbp; struct xfs_buf *bp, *nbp;
int level = levelin; int level = levelin;
__be64 *pp; __be64 *pp;
xfs_fsblock_t bno = blockno; xfs_fsblock_t bno = blockno;
...@@ -305,8 +308,9 @@ xfs_bmap_count_tree( ...@@ -305,8 +308,9 @@ xfs_bmap_count_tree(
/* Dive to the next level */ /* Dive to the next level */
pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
bno = be64_to_cpu(*pp); bno = be64_to_cpu(*pp);
if (unlikely((error = error = xfs_bmap_count_tree(mp, tp, ifp, bno, level, nextents,
xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) { count);
if (error) {
xfs_trans_brelse(tp, bp); xfs_trans_brelse(tp, bp);
XFS_ERROR_REPORT("xfs_bmap_count_tree(1)", XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
XFS_ERRLEVEL_LOW, mp); XFS_ERRLEVEL_LOW, mp);
...@@ -318,6 +322,7 @@ xfs_bmap_count_tree( ...@@ -318,6 +322,7 @@ xfs_bmap_count_tree(
for (;;) { for (;;) {
nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
numrecs = be16_to_cpu(block->bb_numrecs); numrecs = be16_to_cpu(block->bb_numrecs);
(*nextents) += numrecs;
xfs_bmap_disk_count_leaves(mp, block, numrecs, count); xfs_bmap_disk_count_leaves(mp, block, numrecs, count);
xfs_trans_brelse(tp, bp); xfs_trans_brelse(tp, bp);
if (nextbno == NULLFSBLOCK) if (nextbno == NULLFSBLOCK)
...@@ -339,44 +344,61 @@ xfs_bmap_count_tree( ...@@ -339,44 +344,61 @@ xfs_bmap_count_tree(
* Count fsblocks of the given fork. Delayed allocation extents are * Count fsblocks of the given fork. Delayed allocation extents are
* not counted towards the totals. * not counted towards the totals.
*/ */
static int /* error */ int
xfs_bmap_count_blocks( xfs_bmap_count_blocks(
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_inode_t *ip, /* incore inode */ struct xfs_inode *ip,
int whichfork, /* data or attr fork */ int whichfork,
int *count) /* out: count of 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_btree_block *block; /* current btree block */
struct xfs_ifork *ifp; /* fork structure */
xfs_fsblock_t bno; /* block # of "block" */ xfs_fsblock_t bno; /* block # of "block" */
xfs_ifork_t *ifp; /* fork structure */
int level; /* btree level, for checking */ int level; /* btree level, for checking */
xfs_mount_t *mp; /* file system mount structure */ int error;
__be64 *pp; /* pointer to block address */
bno = NULLFSBLOCK; bno = NULLFSBLOCK;
mp = ip->i_mount; mp = ip->i_mount;
*nextents = 0;
*count = 0;
ifp = XFS_IFORK_PTR(ip, whichfork); ifp = XFS_IFORK_PTR(ip, whichfork);
if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) { if (!ifp)
xfs_bmap_count_leaves(ifp, count);
return 0; return 0;
}
/* switch (XFS_IFORK_FORMAT(ip, whichfork)) {
* Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out. case XFS_DINODE_FMT_EXTENTS:
*/ xfs_bmap_count_leaves(ifp, nextents, count);
block = ifp->if_broot; return 0;
level = be16_to_cpu(block->bb_level); case XFS_DINODE_FMT_BTREE:
ASSERT(level > 0); if (!(ifp->if_flags & XFS_IFEXTENTS)) {
pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); error = xfs_iread_extents(tp, ip, whichfork);
bno = be64_to_cpu(*pp); if (error)
ASSERT(bno != NULLFSBLOCK); return error;
ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount); }
ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
/*
if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) { * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW, */
mp); block = ifp->if_broot;
return -EFSCORRUPTED; 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);
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;
} }
return 0; return 0;
...@@ -1792,8 +1814,9 @@ xfs_swap_extent_forks( ...@@ -1792,8 +1814,9 @@ xfs_swap_extent_forks(
int *target_log_flags) int *target_log_flags)
{ {
struct xfs_ifork tempifp, *ifp, *tifp; struct xfs_ifork tempifp, *ifp, *tifp;
int aforkblks = 0; xfs_filblks_t aforkblks = 0;
int taforkblks = 0; xfs_filblks_t taforkblks = 0;
xfs_extnum_t junk;
xfs_extnum_t nextents; xfs_extnum_t nextents;
uint64_t tmp; uint64_t tmp;
int error; int error;
...@@ -1803,14 +1826,14 @@ xfs_swap_extent_forks( ...@@ -1803,14 +1826,14 @@ xfs_swap_extent_forks(
*/ */
if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) && if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
&aforkblks); &aforkblks);
if (error) if (error)
return error; return error;
} }
if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) && if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
(tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
&taforkblks); &taforkblks);
if (error) if (error)
return error; return error;
......
...@@ -70,4 +70,8 @@ int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip, ...@@ -70,4 +70,8 @@ int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,
xfs_daddr_t xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb); xfs_daddr_t xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb);
int xfs_bmap_count_blocks(struct xfs_trans *tp, struct xfs_inode *ip,
int whichfork, xfs_extnum_t *nextents,
xfs_filblks_t *count);
#endif /* __XFS_BMAP_UTIL_H__ */ #endif /* __XFS_BMAP_UTIL_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment