xfs: refactor btree pointer checks

Refactor the btree pointer checks so that we can call them from the
scrub code without logging errors to dmesg.  Preserve the existing error
reporting for regular operations.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
This commit is contained in:
Darrick J. Wong 2017-10-17 21:37:33 -07:00
parent 21ec54168b
commit f135761a73
3 changed files with 48 additions and 45 deletions

View file

@ -646,8 +646,8 @@ xfs_bmap_btree_to_extents(
cbno = be64_to_cpu(*pp); cbno = be64_to_cpu(*pp);
*logflagsp = 0; *logflagsp = 0;
#ifdef DEBUG #ifdef DEBUG
if ((error = xfs_btree_check_lptr(cur, cbno, 1))) XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
return error; xfs_btree_check_lptr(cur, cbno, 1));
#endif #endif
error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp, XFS_BMAP_BTREE_REF, error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp, XFS_BMAP_BTREE_REF,
&xfs_bmbt_buf_ops); &xfs_bmbt_buf_ops);

View file

@ -177,59 +177,53 @@ xfs_btree_check_block(
return xfs_btree_check_sblock(cur, block, level, bp); return xfs_btree_check_sblock(cur, block, level, bp);
} }
/* /* Check that this long pointer is valid and points within the fs. */
* Check that (long) pointer is ok. bool
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lptr( xfs_btree_check_lptr(
struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_btree_cur *cur,
xfs_fsblock_t bno, /* btree block disk address */ xfs_fsblock_t fsbno,
int level) /* btree block level */ int level)
{ {
XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, if (level <= 0)
level > 0 && return false;
bno != NULLFSBLOCK && return xfs_verify_fsbno(cur->bc_mp, fsbno);
XFS_FSB_SANITY_CHECK(cur->bc_mp, bno)); }
return 0;
/* Check that this short pointer is valid and points within the AG. */
bool
xfs_btree_check_sptr(
struct xfs_btree_cur *cur,
xfs_agblock_t agbno,
int level)
{
if (level <= 0)
return false;
return xfs_verify_agbno(cur->bc_mp, cur->bc_private.a.agno, agbno);
} }
#ifdef DEBUG #ifdef DEBUG
/* /*
* Check that (short) pointer is ok. * Check that a given (indexed) btree pointer at a certain level of a
* btree is valid and doesn't point past where it should.
*/ */
STATIC int /* error (0 or EFSCORRUPTED) */ int
xfs_btree_check_sptr(
struct xfs_btree_cur *cur, /* btree cursor */
xfs_agblock_t bno, /* btree block disk address */
int level) /* btree block level */
{
xfs_agblock_t agblocks = cur->bc_mp->m_sb.sb_agblocks;
XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
level > 0 &&
bno != NULLAGBLOCK &&
bno != 0 &&
bno < agblocks);
return 0;
}
/*
* Check that block ptr is ok.
*/
STATIC int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_ptr( xfs_btree_check_ptr(
struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_btree_cur *cur,
union xfs_btree_ptr *ptr, /* btree block disk address */ union xfs_btree_ptr *ptr,
int index, /* offset from ptr to check */ int index,
int level) /* btree block level */ int level)
{ {
if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
return xfs_btree_check_lptr(cur, XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
be64_to_cpu((&ptr->l)[index]), level); xfs_btree_check_lptr(cur,
be64_to_cpu((&ptr->l)[index]), level));
} else { } else {
return xfs_btree_check_sptr(cur, XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
be32_to_cpu((&ptr->s)[index]), level); xfs_btree_check_sptr(cur,
be32_to_cpu((&ptr->s)[index]), level));
} }
return 0;
} }
#endif #endif

View file

@ -269,10 +269,19 @@ xfs_btree_check_block(
/* /*
* Check that (long) pointer is ok. * Check that (long) pointer is ok.
*/ */
int /* error (0 or EFSCORRUPTED) */ bool /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lptr( xfs_btree_check_lptr(
struct xfs_btree_cur *cur, /* btree cursor */ struct xfs_btree_cur *cur, /* btree cursor */
xfs_fsblock_t ptr, /* btree block disk address */ xfs_fsblock_t fsbno, /* btree block disk address */
int level); /* btree block level */
/*
* Check that (short) pointer is ok.
*/
bool /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sptr(
struct xfs_btree_cur *cur, /* btree cursor */
xfs_agblock_t agbno, /* btree block disk address */
int level); /* btree block level */ int level); /* btree block level */
/* /*