mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 02:09:42 +00:00
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: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com>
This commit is contained in:
parent
d29cb3e45e
commit
e7f5d5ca36
2 changed files with 71 additions and 44 deletions
|
@ -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,44 +344,61 @@ 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_btree_block *block; /* current btree block */
|
||||
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 */
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
return -EFSCORRUPTED;
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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__ */
|
||||
|
|
Loading…
Reference in a new issue