Commit a23f6ef8 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Lachlan McIlroy

[XFS] refactor btree validation helpers

Move the various btree validation helpers around in xfs_btree.c so that
they are close to each other and in common #ifdef DEBUG sections.

Also add a new xfs_btree_check_ptr helper to check a btree ptr that can be
either long or short form.

Split out from a bigger patch from Dave Chinner with various small changes
applied by me.

SGI-PV: 985583

SGI-Modid: xfs-linux-melb:xfs-kern:32183a
Signed-off-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
Signed-off-by: default avatarBill O'Donnell <billodo@sgi.com>
Signed-off-by: default avatarDavid Chinner <david@fromorbit.com>
parent b524bfee
...@@ -80,24 +80,6 @@ xfs_btree_maxrecs( ...@@ -80,24 +80,6 @@ xfs_btree_maxrecs(
*/ */
#ifdef DEBUG #ifdef DEBUG
/*
* Debug routine: check that block header is ok.
*/
void
xfs_btree_check_block(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_block_t *block, /* generic btree block pointer */
int level, /* level of the btree block */
xfs_buf_t *bp) /* buffer containing block, if any */
{
if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
xfs_btree_check_lblock(cur, (xfs_btree_lblock_t *)block, level,
bp);
else
xfs_btree_check_sblock(cur, (xfs_btree_sblock_t *)block, level,
bp);
}
/* /*
* Debug routine: check that keys are in the right order. * Debug routine: check that keys are in the right order.
*/ */
...@@ -150,65 +132,7 @@ xfs_btree_check_key( ...@@ -150,65 +132,7 @@ xfs_btree_check_key(
ASSERT(0); ASSERT(0);
} }
} }
#endif /* DEBUG */
/*
* Checking routine: check that long form block header is ok.
*/
/* ARGSUSED */
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lblock(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_lblock_t *block, /* btree long form block pointer */
int level, /* level of the btree block */
xfs_buf_t *bp) /* buffer for block, if any */
{
int lblock_ok; /* block passes checks */
xfs_mount_t *mp; /* file system mount point */
mp = cur->bc_mp;
lblock_ok =
be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
be16_to_cpu(block->bb_level) == level &&
be16_to_cpu(block->bb_numrecs) <=
xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
block->bb_leftsib &&
(be64_to_cpu(block->bb_leftsib) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) &&
block->bb_rightsib &&
(be64_to_cpu(block->bb_rightsib) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib)));
if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK,
XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
if (bp)
xfs_buftrace("LBTREE ERROR", bp);
XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW,
mp);
return XFS_ERROR(EFSCORRUPTED);
}
return 0;
}
/*
* Checking routine: check that (long) pointer is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lptr(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_dfsbno_t ptr, /* btree block disk address */
int level) /* btree block level */
{
xfs_mount_t *mp; /* file system mount point */
mp = cur->bc_mp;
XFS_WANT_CORRUPTED_RETURN(
level > 0 &&
ptr != NULLDFSBNO &&
XFS_FSB_SANITY_CHECK(mp, ptr));
return 0;
}
#ifdef DEBUG
/* /*
* Debug routine: check that records are in the right order. * Debug routine: check that records are in the right order.
*/ */
...@@ -268,19 +192,49 @@ xfs_btree_check_rec( ...@@ -268,19 +192,49 @@ xfs_btree_check_rec(
} }
#endif /* DEBUG */ #endif /* DEBUG */
/* int /* error (0 or EFSCORRUPTED) */
* Checking routine: check that block header is ok. xfs_btree_check_lblock(
*/ struct xfs_btree_cur *cur, /* btree cursor */
/* ARGSUSED */ struct xfs_btree_lblock *block, /* btree long form block pointer */
int level, /* level of the btree block */
struct xfs_buf *bp) /* buffer for block, if any */
{
int lblock_ok; /* block passes checks */
struct xfs_mount *mp; /* file system mount point */
mp = cur->bc_mp;
lblock_ok =
be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
be16_to_cpu(block->bb_level) == level &&
be16_to_cpu(block->bb_numrecs) <=
xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
block->bb_leftsib &&
(be64_to_cpu(block->bb_leftsib) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) &&
block->bb_rightsib &&
(be64_to_cpu(block->bb_rightsib) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib)));
if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp,
XFS_ERRTAG_BTREE_CHECK_LBLOCK,
XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
if (bp)
xfs_buftrace("LBTREE ERROR", bp);
XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW,
mp);
return XFS_ERROR(EFSCORRUPTED);
}
return 0;
}
int /* error (0 or EFSCORRUPTED) */ int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sblock( xfs_btree_check_sblock(
xfs_btree_cur_t *cur, /* btree cursor */ struct xfs_btree_cur *cur, /* btree cursor */
xfs_btree_sblock_t *block, /* btree short form block pointer */ struct xfs_btree_sblock *block, /* btree short form block pointer */
int level, /* level of the btree block */ int level, /* level of the btree block */
xfs_buf_t *bp) /* buffer containing block */ struct xfs_buf *bp) /* buffer containing block */
{ {
xfs_buf_t *agbp; /* buffer for ag. freespace struct */ struct xfs_buf *agbp; /* buffer for ag. freespace struct */
xfs_agf_t *agf; /* ag. freespace structure */ struct xfs_agf *agf; /* ag. freespace structure */
xfs_agblock_t agflen; /* native ag. freespace length */ xfs_agblock_t agflen; /* native ag. freespace length */
int sblock_ok; /* block passes checks */ int sblock_ok; /* block passes checks */
...@@ -311,26 +265,78 @@ xfs_btree_check_sblock( ...@@ -311,26 +265,78 @@ xfs_btree_check_sblock(
} }
/* /*
* Checking routine: check that (short) pointer is ok. * Debug routine: check that block header is ok.
*/
int
xfs_btree_check_block(
struct xfs_btree_cur *cur, /* btree cursor */
struct xfs_btree_block *block, /* generic btree block pointer */
int level, /* level of the btree block */
struct xfs_buf *bp) /* buffer containing block, if any */
{
if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
return xfs_btree_check_lblock(cur,
(struct xfs_btree_lblock *)block, level, bp);
} else {
return xfs_btree_check_sblock(cur,
(struct xfs_btree_sblock *)block, level, bp);
}
}
/*
* Check that (long) pointer is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lptr(
struct xfs_btree_cur *cur, /* btree cursor */
xfs_dfsbno_t bno, /* btree block disk address */
int level) /* btree block level */
{
XFS_WANT_CORRUPTED_RETURN(
level > 0 &&
bno != NULLDFSBNO &&
XFS_FSB_SANITY_CHECK(cur->bc_mp, bno));
return 0;
}
/*
* Check that (short) pointer is ok.
*/ */
int /* error (0 or EFSCORRUPTED) */ int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sptr( xfs_btree_check_sptr(
xfs_btree_cur_t *cur, /* btree cursor */ struct xfs_btree_cur *cur, /* btree cursor */
xfs_agblock_t ptr, /* btree block disk address */ xfs_agblock_t bno, /* btree block disk address */
int level) /* btree block level */ int level) /* btree block level */
{ {
xfs_buf_t *agbp; /* buffer for ag. freespace struct */ xfs_agblock_t agblocks = cur->bc_mp->m_sb.sb_agblocks;
xfs_agf_t *agf; /* ag. freespace structure */
agbp = cur->bc_private.a.agbp;
agf = XFS_BUF_TO_AGF(agbp);
XFS_WANT_CORRUPTED_RETURN( XFS_WANT_CORRUPTED_RETURN(
level > 0 && level > 0 &&
ptr != NULLAGBLOCK && ptr != 0 && bno != NULLAGBLOCK &&
ptr < be32_to_cpu(agf->agf_length)); bno != 0 &&
bno < agblocks);
return 0; return 0;
} }
/*
* Check that block ptr is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_ptr(
struct xfs_btree_cur *cur, /* btree cursor */
union xfs_btree_ptr *ptr, /* btree block disk address */
int index, /* offset from ptr to check */
int level) /* btree block level */
{
if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
return xfs_btree_check_lptr(cur,
be64_to_cpu((&ptr->l)[index]), level);
} else {
return xfs_btree_check_sptr(cur,
be32_to_cpu((&ptr->s)[index]), level);
}
}
/* /*
* Delete the btree cursor. * Delete the btree cursor.
*/ */
......
...@@ -215,81 +215,92 @@ typedef struct xfs_btree_cur ...@@ -215,81 +215,92 @@ typedef struct xfs_btree_cur
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifdef DEBUG
/* /*
* Debug routine: check that block header is ok. * Check that long form block header is ok.
*/ */
void int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_block( xfs_btree_check_lblock(
xfs_btree_cur_t *cur, /* btree cursor */ struct xfs_btree_cur *cur, /* btree cursor */
xfs_btree_block_t *block, /* generic btree block pointer */ struct xfs_btree_lblock *block, /* btree long form block pointer */
int level, /* level of the btree block */ int level, /* level of the btree block */
struct xfs_buf *bp); /* buffer containing block, if any */ struct xfs_buf *bp); /* buffer containing block, if any */
/* /*
* Debug routine: check that keys are in the right order. * Check that short form block header is ok.
*/ */
void int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_key( xfs_btree_check_sblock(
xfs_btnum_t btnum, /* btree identifier */ struct xfs_btree_cur *cur, /* btree cursor */
void *ak1, /* pointer to left (lower) key */ struct xfs_btree_sblock *block, /* btree short form block pointer */
void *ak2); /* pointer to right (higher) key */ int level, /* level of the btree block */
struct xfs_buf *bp); /* buffer containing block */
/*
* Debug routine: check that records are in the right order.
*/
void
xfs_btree_check_rec(
xfs_btnum_t btnum, /* btree identifier */
void *ar1, /* pointer to left (lower) record */
void *ar2); /* pointer to right (higher) record */
#else
#define xfs_btree_check_block(a,b,c,d)
#define xfs_btree_check_key(a,b,c)
#define xfs_btree_check_rec(a,b,c)
#endif /* DEBUG */
/* /*
* Checking routine: check that long form block header is ok. * Check that block header is ok.
*/ */
int /* error (0 or EFSCORRUPTED) */ int
xfs_btree_check_lblock( xfs_btree_check_block(
xfs_btree_cur_t *cur, /* btree cursor */ struct xfs_btree_cur *cur, /* btree cursor */
xfs_btree_lblock_t *block, /* btree long form block pointer */ struct xfs_btree_block *block, /* generic btree block pointer */
int level, /* level of the btree block */ int level, /* level of the btree block */
struct xfs_buf *bp); /* buffer containing block, if any */ struct xfs_buf *bp); /* buffer containing block, if any */
/* /*
* Checking routine: check that (long) pointer is ok. * Check that (long) pointer is ok.
*/ */
int /* error (0 or EFSCORRUPTED) */ int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lptr( xfs_btree_check_lptr(
xfs_btree_cur_t *cur, /* btree cursor */ struct xfs_btree_cur *cur, /* btree cursor */
xfs_dfsbno_t ptr, /* btree block disk address */ xfs_dfsbno_t ptr, /* btree block disk address */
int level); /* btree block level */ int level); /* btree block level */
#define xfs_btree_check_lptr_disk(cur, ptr, level) \ #define xfs_btree_check_lptr_disk(cur, ptr, level) \
xfs_btree_check_lptr(cur, be64_to_cpu(ptr), level) xfs_btree_check_lptr(cur, be64_to_cpu(ptr), level)
/* /*
* Checking routine: check that short form block header is ok. * Check that (short) pointer is ok.
*/ */
int /* error (0 or EFSCORRUPTED) */ int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sblock( xfs_btree_check_sptr(
xfs_btree_cur_t *cur, /* btree cursor */ struct xfs_btree_cur *cur, /* btree cursor */
xfs_btree_sblock_t *block, /* btree short form block pointer */ xfs_agblock_t ptr, /* btree block disk address */
int level, /* level of the btree block */ int level); /* btree block level */
struct xfs_buf *bp); /* buffer containing block */
/* /*
* Checking routine: check that (short) pointer is ok. * Check that (short) pointer is ok.
*/ */
int /* error (0 or EFSCORRUPTED) */ int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sptr( xfs_btree_check_ptr(
xfs_btree_cur_t *cur, /* btree cursor */ struct xfs_btree_cur *cur, /* btree cursor */
xfs_agblock_t ptr, /* btree block disk address */ union xfs_btree_ptr *ptr, /* btree block disk address */
int index, /* offset from ptr to check */
int level); /* btree block level */ int level); /* btree block level */
#ifdef DEBUG
/*
* Debug routine: check that keys are in the right order.
*/
void
xfs_btree_check_key(
xfs_btnum_t btnum, /* btree identifier */
void *ak1, /* pointer to left (lower) key */
void *ak2); /* pointer to right (higher) key */
/*
* Debug routine: check that records are in the right order.
*/
void
xfs_btree_check_rec(
xfs_btnum_t btnum, /* btree identifier */
void *ar1, /* pointer to left (lower) record */
void *ar2); /* pointer to right (higher) record */
#else
#define xfs_btree_check_key(a, b, c)
#define xfs_btree_check_rec(a, b, c)
#endif /* DEBUG */
/* /*
* Delete the btree cursor. * Delete the btree cursor.
*/ */
......
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