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(
STATIC void
xfs_bmap_count_leaves(
struct xfs_ifork *ifp,
int *count)
xfs_extnum_t *numrecs,
xfs_filblks_t *count)
{
xfs_extnum_t i;
xfs_extnum_t nr_exts = xfs_iext_count(ifp);
......@@ -233,6 +234,7 @@ xfs_bmap_count_leaves(
for (i = 0; i < nr_exts; i++) {
xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, i);
if (!isnullstartblock(xfs_bmbt_get_startblock(frp))) {
(*numrecs)++;
*count += xfs_bmbt_get_blockcount(frp);
}
}
......@@ -247,7 +249,7 @@ xfs_bmap_disk_count_leaves(
struct xfs_mount *mp,
struct xfs_btree_block *block,
int numrecs,
int *count)
xfs_filblks_t *count)
{
int b;
xfs_bmbt_rec_t *frp;
......@@ -262,17 +264,18 @@ xfs_bmap_disk_count_leaves(
* Recursively walks each level of a btree
* to count total fsblocks in use.
*/
STATIC int /* error */
STATIC int
xfs_bmap_count_tree(
xfs_mount_t *mp, /* file system mount point */
xfs_trans_t *tp, /* transaction pointer */
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_fsblock_t blockno, /* file system block number */
int levelin, /* level in btree */
int *count) /* Count of blocks */
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;
xfs_buf_t *bp, *nbp;
struct xfs_buf *bp, *nbp;
int level = levelin;
__be64 *pp;
xfs_fsblock_t bno = blockno;
......@@ -305,8 +308,9 @@ xfs_bmap_count_tree(
/* Dive to the next level */
pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
bno = be64_to_cpu(*pp);
if (unlikely((error =
xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
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);
......@@ -318,6 +322,7 @@ xfs_bmap_count_tree(
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)
......@@ -339,26 +344,39 @@ xfs_bmap_count_tree(
* Count fsblocks of the given fork. Delayed allocation extents are
* not counted towards the totals.
*/
static int /* error */
int
xfs_bmap_count_blocks(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *ip, /* incore inode */
int whichfork, /* data or attr fork */
int *count) /* out: count of blocks */
struct xfs_trans *tp,
struct xfs_inode *ip,
int whichfork,
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" */
xfs_ifork_t *ifp; /* fork structure */
int level; /* btree level, for checking */
xfs_mount_t *mp; /* file system mount structure */
__be64 *pp; /* pointer to block address */
int error;
bno = NULLFSBLOCK;
mp = ip->i_mount;
*nextents = 0;
*count = 0;
ifp = XFS_IFORK_PTR(ip, whichfork);
if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
xfs_bmap_count_leaves(ifp, count);
if (!ifp)
return 0;
switch (XFS_IFORK_FORMAT(ip, whichfork)) {
case XFS_DINODE_FMT_EXTENTS:
xfs_bmap_count_leaves(ifp, nextents, count);
return 0;
case XFS_DINODE_FMT_BTREE:
if (!(ifp->if_flags & XFS_IFEXTENTS)) {
error = xfs_iread_extents(tp, ip, whichfork);
if (error)
return error;
}
/*
......@@ -373,11 +391,15 @@ xfs_bmap_count_blocks(
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)) {
XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
mp);
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;
}
......@@ -1792,8 +1814,9 @@ xfs_swap_extent_forks(
int *target_log_flags)
{
struct xfs_ifork tempifp, *ifp, *tifp;
int aforkblks = 0;
int taforkblks = 0;
xfs_filblks_t aforkblks = 0;
xfs_filblks_t taforkblks = 0;
xfs_extnum_t junk;
xfs_extnum_t nextents;
uint64_t tmp;
int error;
......@@ -1803,14 +1826,14 @@ xfs_swap_extent_forks(
*/
if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
(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);
if (error)
return error;
}
if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
(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);
if (error)
return error;
......
......@@ -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);
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__ */
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