Merge branch 'xfs-verifier-cleanup' into for-next

This commit is contained in:
Dave Chinner 2014-03-13 19:12:33 +11:00
commit 49ae4b97d7
25 changed files with 202 additions and 155 deletions

View file

@ -89,6 +89,8 @@ typedef struct xfs_agf {
/* structure must be padded to 64 bit alignment */ /* structure must be padded to 64 bit alignment */
} xfs_agf_t; } xfs_agf_t;
#define XFS_AGF_CRC_OFF offsetof(struct xfs_agf, agf_crc)
#define XFS_AGF_MAGICNUM 0x00000001 #define XFS_AGF_MAGICNUM 0x00000001
#define XFS_AGF_VERSIONNUM 0x00000002 #define XFS_AGF_VERSIONNUM 0x00000002
#define XFS_AGF_SEQNO 0x00000004 #define XFS_AGF_SEQNO 0x00000004
@ -167,6 +169,8 @@ typedef struct xfs_agi {
/* structure must be padded to 64 bit alignment */ /* structure must be padded to 64 bit alignment */
} xfs_agi_t; } xfs_agi_t;
#define XFS_AGI_CRC_OFF offsetof(struct xfs_agi, agi_crc)
#define XFS_AGI_MAGICNUM 0x00000001 #define XFS_AGI_MAGICNUM 0x00000001
#define XFS_AGI_VERSIONNUM 0x00000002 #define XFS_AGI_VERSIONNUM 0x00000002
#define XFS_AGI_SEQNO 0x00000004 #define XFS_AGI_SEQNO 0x00000004
@ -222,6 +226,8 @@ typedef struct xfs_agfl {
__be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */ __be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */
} xfs_agfl_t; } xfs_agfl_t;
#define XFS_AGFL_CRC_OFF offsetof(struct xfs_agfl, agfl_crc)
/* /*
* tags for inode radix tree * tags for inode radix tree
*/ */

View file

@ -474,7 +474,6 @@ xfs_agfl_read_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
int agfl_ok = 1;
/* /*
* There is no verification of non-crc AGFLs because mkfs does not * There is no verification of non-crc AGFLs because mkfs does not
@ -485,15 +484,13 @@ xfs_agfl_read_verify(
if (!xfs_sb_version_hascrc(&mp->m_sb)) if (!xfs_sb_version_hascrc(&mp->m_sb))
return; return;
agfl_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), if (!xfs_buf_verify_cksum(bp, XFS_AGFL_CRC_OFF))
offsetof(struct xfs_agfl, agfl_crc)); xfs_buf_ioerror(bp, EFSBADCRC);
else if (!xfs_agfl_verify(bp))
agfl_ok = agfl_ok && xfs_agfl_verify(bp);
if (!agfl_ok) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
static void static void
@ -508,16 +505,15 @@ xfs_agfl_write_verify(
return; return;
if (!xfs_agfl_verify(bp)) { if (!xfs_agfl_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
if (bip) if (bip)
XFS_BUF_TO_AGFL(bp)->agfl_lsn = cpu_to_be64(bip->bli_item.li_lsn); XFS_BUF_TO_AGFL(bp)->agfl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), xfs_buf_update_cksum(bp, XFS_AGFL_CRC_OFF);
offsetof(struct xfs_agfl, agfl_crc));
} }
const struct xfs_buf_ops xfs_agfl_buf_ops = { const struct xfs_buf_ops xfs_agfl_buf_ops = {
@ -2238,19 +2234,17 @@ xfs_agf_read_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
int agf_ok = 1;
if (xfs_sb_version_hascrc(&mp->m_sb)) if (xfs_sb_version_hascrc(&mp->m_sb) &&
agf_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), !xfs_buf_verify_cksum(bp, XFS_AGF_CRC_OFF))
offsetof(struct xfs_agf, agf_crc)); xfs_buf_ioerror(bp, EFSBADCRC);
else if (XFS_TEST_ERROR(!xfs_agf_verify(mp, bp), mp,
agf_ok = agf_ok && xfs_agf_verify(mp, bp); XFS_ERRTAG_ALLOC_READ_AGF,
XFS_RANDOM_ALLOC_READ_AGF))
if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF,
XFS_RANDOM_ALLOC_READ_AGF))) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
static void static void
@ -2261,8 +2255,8 @@ xfs_agf_write_verify(
struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_buf_log_item *bip = bp->b_fspriv;
if (!xfs_agf_verify(mp, bp)) { if (!xfs_agf_verify(mp, bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -2272,8 +2266,7 @@ xfs_agf_write_verify(
if (bip) if (bip)
XFS_BUF_TO_AGF(bp)->agf_lsn = cpu_to_be64(bip->bli_item.li_lsn); XFS_BUF_TO_AGF(bp)->agf_lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), xfs_buf_update_cksum(bp, XFS_AGF_CRC_OFF);
offsetof(struct xfs_agf, agf_crc));
} }
const struct xfs_buf_ops xfs_agf_buf_ops = { const struct xfs_buf_ops xfs_agf_buf_ops = {

View file

@ -355,12 +355,14 @@ static void
xfs_allocbt_read_verify( xfs_allocbt_read_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
if (!(xfs_btree_sblock_verify_crc(bp) && if (!xfs_btree_sblock_verify_crc(bp))
xfs_allocbt_verify(bp))) { xfs_buf_ioerror(bp, EFSBADCRC);
trace_xfs_btree_corrupt(bp, _RET_IP_); else if (!xfs_allocbt_verify(bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
bp->b_target->bt_mount, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
if (bp->b_error) {
trace_xfs_btree_corrupt(bp, _RET_IP_);
xfs_verifier_error(bp);
} }
} }
@ -370,9 +372,9 @@ xfs_allocbt_write_verify(
{ {
if (!xfs_allocbt_verify(bp)) { if (!xfs_allocbt_verify(bp)) {
trace_xfs_btree_corrupt(bp, _RET_IP_); trace_xfs_btree_corrupt(bp, _RET_IP_);
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
bp->b_target->bt_mount, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return;
} }
xfs_btree_sblock_calc_crc(bp); xfs_btree_sblock_calc_crc(bp);

View file

@ -213,8 +213,8 @@ xfs_attr3_leaf_write_verify(
struct xfs_attr3_leaf_hdr *hdr3 = bp->b_addr; struct xfs_attr3_leaf_hdr *hdr3 = bp->b_addr;
if (!xfs_attr3_leaf_verify(bp)) { if (!xfs_attr3_leaf_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -224,7 +224,7 @@ xfs_attr3_leaf_write_verify(
if (bip) if (bip)
hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_ATTR3_LEAF_CRC_OFF); xfs_buf_update_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF);
} }
/* /*
@ -239,13 +239,14 @@ xfs_attr3_leaf_read_verify(
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
if ((xfs_sb_version_hascrc(&mp->m_sb) && if (xfs_sb_version_hascrc(&mp->m_sb) &&
!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), !xfs_buf_verify_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF))
XFS_ATTR3_LEAF_CRC_OFF)) || xfs_buf_ioerror(bp, EFSBADCRC);
!xfs_attr3_leaf_verify(bp)) { else if (!xfs_attr3_leaf_verify(bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = { const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = {

View file

@ -125,7 +125,6 @@ xfs_attr3_rmt_read_verify(
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
char *ptr; char *ptr;
int len; int len;
bool corrupt = false;
xfs_daddr_t bno; xfs_daddr_t bno;
/* no verification of non-crc buffers */ /* no verification of non-crc buffers */
@ -140,11 +139,11 @@ xfs_attr3_rmt_read_verify(
while (len > 0) { while (len > 0) {
if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp), if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp),
XFS_ATTR3_RMT_CRC_OFF)) { XFS_ATTR3_RMT_CRC_OFF)) {
corrupt = true; xfs_buf_ioerror(bp, EFSBADCRC);
break; break;
} }
if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) { if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
corrupt = true; xfs_buf_ioerror(bp, EFSCORRUPTED);
break; break;
} }
len -= XFS_LBSIZE(mp); len -= XFS_LBSIZE(mp);
@ -152,10 +151,9 @@ xfs_attr3_rmt_read_verify(
bno += mp->m_bsize; bno += mp->m_bsize;
} }
if (corrupt) { if (bp->b_error)
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); xfs_verifier_error(bp);
xfs_buf_ioerror(bp, EFSCORRUPTED); else
} else
ASSERT(len == 0); ASSERT(len == 0);
} }
@ -180,9 +178,8 @@ xfs_attr3_rmt_write_verify(
while (len > 0) { while (len > 0) {
if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) { if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
XFS_CORRUPTION_ERROR(__func__,
XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
if (bip) { if (bip) {

View file

@ -780,12 +780,14 @@ static void
xfs_bmbt_read_verify( xfs_bmbt_read_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
if (!(xfs_btree_lblock_verify_crc(bp) && if (!xfs_btree_lblock_verify_crc(bp))
xfs_bmbt_verify(bp))) { xfs_buf_ioerror(bp, EFSBADCRC);
trace_xfs_btree_corrupt(bp, _RET_IP_); else if (!xfs_bmbt_verify(bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
bp->b_target->bt_mount, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
if (bp->b_error) {
trace_xfs_btree_corrupt(bp, _RET_IP_);
xfs_verifier_error(bp);
} }
} }
@ -794,11 +796,9 @@ xfs_bmbt_write_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
if (!xfs_bmbt_verify(bp)) { if (!xfs_bmbt_verify(bp)) {
xfs_warn(bp->b_target->bt_mount, "bmbt daddr 0x%llx failed", bp->b_bn);
trace_xfs_btree_corrupt(bp, _RET_IP_); trace_xfs_btree_corrupt(bp, _RET_IP_);
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
bp->b_target->bt_mount, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
xfs_btree_lblock_calc_crc(bp); xfs_btree_lblock_calc_crc(bp);

View file

@ -234,8 +234,7 @@ xfs_btree_lblock_calc_crc(
return; return;
if (bip) if (bip)
block->bb_u.l.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn); block->bb_u.l.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), xfs_buf_update_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF);
XFS_BTREE_LBLOCK_CRC_OFF);
} }
bool bool
@ -243,8 +242,8 @@ xfs_btree_lblock_verify_crc(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb))
return xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), return xfs_buf_verify_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF);
XFS_BTREE_LBLOCK_CRC_OFF);
return true; return true;
} }
@ -267,8 +266,7 @@ xfs_btree_sblock_calc_crc(
return; return;
if (bip) if (bip)
block->bb_u.s.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn); block->bb_u.s.bb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), xfs_buf_update_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
XFS_BTREE_SBLOCK_CRC_OFF);
} }
bool bool
@ -276,8 +274,8 @@ xfs_btree_sblock_verify_crc(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb))
return xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
XFS_BTREE_SBLOCK_CRC_OFF);
return true; return true;
} }

View file

@ -369,6 +369,20 @@ static inline void xfs_buf_relse(xfs_buf_t *bp)
xfs_buf_rele(bp); xfs_buf_rele(bp);
} }
static inline int
xfs_buf_verify_cksum(struct xfs_buf *bp, unsigned long cksum_offset)
{
return xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
cksum_offset);
}
static inline void
xfs_buf_update_cksum(struct xfs_buf *bp, unsigned long cksum_offset)
{
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
cksum_offset);
}
/* /*
* Handling of buftargs. * Handling of buftargs.
*/ */

View file

@ -185,8 +185,8 @@ xfs_da3_node_write_verify(
struct xfs_da3_node_hdr *hdr3 = bp->b_addr; struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
if (!xfs_da3_node_verify(bp)) { if (!xfs_da3_node_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -196,7 +196,7 @@ xfs_da3_node_write_verify(
if (bip) if (bip)
hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DA3_NODE_CRC_OFF); xfs_buf_update_cksum(bp, XFS_DA3_NODE_CRC_OFF);
} }
/* /*
@ -209,18 +209,20 @@ static void
xfs_da3_node_read_verify( xfs_da3_node_read_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
struct xfs_mount *mp = bp->b_target->bt_mount;
struct xfs_da_blkinfo *info = bp->b_addr; struct xfs_da_blkinfo *info = bp->b_addr;
switch (be16_to_cpu(info->magic)) { switch (be16_to_cpu(info->magic)) {
case XFS_DA3_NODE_MAGIC: case XFS_DA3_NODE_MAGIC:
if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), if (!xfs_buf_verify_cksum(bp, XFS_DA3_NODE_CRC_OFF)) {
XFS_DA3_NODE_CRC_OFF)) xfs_buf_ioerror(bp, EFSBADCRC);
break; break;
}
/* fall through */ /* fall through */
case XFS_DA_NODE_MAGIC: case XFS_DA_NODE_MAGIC:
if (!xfs_da3_node_verify(bp)) if (!xfs_da3_node_verify(bp)) {
xfs_buf_ioerror(bp, EFSCORRUPTED);
break; break;
}
return; return;
case XFS_ATTR_LEAF_MAGIC: case XFS_ATTR_LEAF_MAGIC:
case XFS_ATTR3_LEAF_MAGIC: case XFS_ATTR3_LEAF_MAGIC:
@ -237,8 +239,7 @@ xfs_da3_node_read_verify(
} }
/* corrupt block */ /* corrupt block */
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); xfs_verifier_error(bp);
xfs_buf_ioerror(bp, EFSCORRUPTED);
} }
const struct xfs_buf_ops xfs_da3_node_buf_ops = { const struct xfs_buf_ops xfs_da3_node_buf_ops = {

View file

@ -89,6 +89,8 @@ typedef struct xfs_dinode {
/* structure must be padded to 64 bit alignment */ /* structure must be padded to 64 bit alignment */
} xfs_dinode_t; } xfs_dinode_t;
#define XFS_DINODE_CRC_OFF offsetof(struct xfs_dinode, di_crc)
#define DI_MAX_FLUSH 0xffff #define DI_MAX_FLUSH 0xffff
/* /*

View file

@ -89,13 +89,14 @@ xfs_dir3_block_read_verify(
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
if ((xfs_sb_version_hascrc(&mp->m_sb) && if (xfs_sb_version_hascrc(&mp->m_sb) &&
!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
XFS_DIR3_DATA_CRC_OFF)) || xfs_buf_ioerror(bp, EFSBADCRC);
!xfs_dir3_block_verify(bp)) { else if (!xfs_dir3_block_verify(bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
static void static void
@ -107,8 +108,8 @@ xfs_dir3_block_write_verify(
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
if (!xfs_dir3_block_verify(bp)) { if (!xfs_dir3_block_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -118,7 +119,7 @@ xfs_dir3_block_write_verify(
if (bip) if (bip)
hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_DATA_CRC_OFF); xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);
} }
const struct xfs_buf_ops xfs_dir3_block_buf_ops = { const struct xfs_buf_ops xfs_dir3_block_buf_ops = {

View file

@ -241,7 +241,6 @@ static void
xfs_dir3_data_reada_verify( xfs_dir3_data_reada_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
struct xfs_mount *mp = bp->b_target->bt_mount;
struct xfs_dir2_data_hdr *hdr = bp->b_addr; struct xfs_dir2_data_hdr *hdr = bp->b_addr;
switch (hdr->magic) { switch (hdr->magic) {
@ -255,8 +254,8 @@ xfs_dir3_data_reada_verify(
xfs_dir3_data_verify(bp); xfs_dir3_data_verify(bp);
return; return;
default: default:
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
break; break;
} }
} }
@ -267,13 +266,14 @@ xfs_dir3_data_read_verify(
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
if ((xfs_sb_version_hascrc(&mp->m_sb) && if (xfs_sb_version_hascrc(&mp->m_sb) &&
!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
XFS_DIR3_DATA_CRC_OFF)) || xfs_buf_ioerror(bp, EFSBADCRC);
!xfs_dir3_data_verify(bp)) { else if (!xfs_dir3_data_verify(bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
static void static void
@ -285,8 +285,8 @@ xfs_dir3_data_write_verify(
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
if (!xfs_dir3_data_verify(bp)) { if (!xfs_dir3_data_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -296,7 +296,7 @@ xfs_dir3_data_write_verify(
if (bip) if (bip)
hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_DATA_CRC_OFF); xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);
} }
const struct xfs_buf_ops xfs_dir3_data_buf_ops = { const struct xfs_buf_ops xfs_dir3_data_buf_ops = {

View file

@ -179,13 +179,14 @@ __read_verify(
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
if ((xfs_sb_version_hascrc(&mp->m_sb) && if (xfs_sb_version_hascrc(&mp->m_sb) &&
!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), !xfs_buf_verify_cksum(bp, XFS_DIR3_LEAF_CRC_OFF))
XFS_DIR3_LEAF_CRC_OFF)) || xfs_buf_ioerror(bp, EFSBADCRC);
!xfs_dir3_leaf_verify(bp, magic)) { else if (!xfs_dir3_leaf_verify(bp, magic))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
static void static void
@ -198,8 +199,8 @@ __write_verify(
struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr; struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr;
if (!xfs_dir3_leaf_verify(bp, magic)) { if (!xfs_dir3_leaf_verify(bp, magic)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -209,7 +210,7 @@ __write_verify(
if (bip) if (bip)
hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_LEAF_CRC_OFF); xfs_buf_update_cksum(bp, XFS_DIR3_LEAF_CRC_OFF);
} }
static void static void

View file

@ -115,13 +115,14 @@ xfs_dir3_free_read_verify(
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
if ((xfs_sb_version_hascrc(&mp->m_sb) && if (xfs_sb_version_hascrc(&mp->m_sb) &&
!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), !xfs_buf_verify_cksum(bp, XFS_DIR3_FREE_CRC_OFF))
XFS_DIR3_FREE_CRC_OFF)) || xfs_buf_ioerror(bp, EFSBADCRC);
!xfs_dir3_free_verify(bp)) { else if (!xfs_dir3_free_verify(bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
static void static void
@ -133,8 +134,8 @@ xfs_dir3_free_write_verify(
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
if (!xfs_dir3_free_verify(bp)) { if (!xfs_dir3_free_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -144,7 +145,7 @@ xfs_dir3_free_write_verify(
if (bip) if (bip)
hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF); xfs_buf_update_cksum(bp, XFS_DIR3_FREE_CRC_OFF);
} }
const struct xfs_buf_ops xfs_dir3_free_buf_ops = { const struct xfs_buf_ops xfs_dir3_free_buf_ops = {

View file

@ -257,10 +257,13 @@ xfs_dquot_buf_read_verify(
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) { if (!xfs_dquot_buf_verify_crc(mp, bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); xfs_buf_ioerror(bp, EFSBADCRC);
else if (!xfs_dquot_buf_verify(mp, bp))
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
/* /*
@ -275,8 +278,8 @@ xfs_dquot_buf_write_verify(
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
if (!xfs_dquot_buf_verify(mp, bp)) { if (!xfs_dquot_buf_verify(mp, bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
} }

View file

@ -156,7 +156,7 @@ xfs_error_report(
{ {
if (level <= xfs_error_level) { if (level <= xfs_error_level) {
xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT,
"Internal error %s at line %d of file %s. Caller 0x%p", "Internal error %s at line %d of file %s. Caller %pF",
tag, linenum, filename, ra); tag, linenum, filename, ra);
xfs_stack_trace(); xfs_stack_trace();
@ -178,3 +178,28 @@ xfs_corruption_error(
xfs_error_report(tag, level, mp, filename, linenum, ra); xfs_error_report(tag, level, mp, filename, linenum, ra);
xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair"); xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
} }
/*
* Warnings specifically for verifier errors. Differentiate CRC vs. invalid
* values, and omit the stack trace unless the error level is tuned high.
*/
void
xfs_verifier_error(
struct xfs_buf *bp)
{
struct xfs_mount *mp = bp->b_target->bt_mount;
xfs_alert(mp, "Metadata %s detected at %pF, block 0x%llx",
bp->b_error == EFSBADCRC ? "CRC error" : "corruption",
__return_address, bp->b_bn);
xfs_alert(mp, "Unmount and run xfs_repair");
if (xfs_error_level >= XFS_ERRLEVEL_LOW) {
xfs_alert(mp, "First 64 bytes of corrupted metadata buffer:");
xfs_hex_dump(xfs_buf_offset(bp, 0), 64);
}
if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
xfs_stack_trace();
}

View file

@ -34,6 +34,7 @@ extern void xfs_error_report(const char *tag, int level, struct xfs_mount *mp,
extern void xfs_corruption_error(const char *tag, int level, extern void xfs_corruption_error(const char *tag, int level,
struct xfs_mount *mp, void *p, const char *filename, struct xfs_mount *mp, void *p, const char *filename,
int linenum, inst_t *ra); int linenum, inst_t *ra);
extern void xfs_verifier_error(struct xfs_buf *bp);
#define XFS_ERROR_REPORT(e, lvl, mp) \ #define XFS_ERROR_REPORT(e, lvl, mp) \
xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address) xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)

View file

@ -145,6 +145,8 @@ struct xfs_dsymlink_hdr {
__be64 sl_lsn; __be64 sl_lsn;
}; };
#define XFS_SYMLINK_CRC_OFF offsetof(struct xfs_dsymlink_hdr, sl_crc)
/* /*
* The maximum pathlen is 1024 bytes. Since the minimum file system * The maximum pathlen is 1024 bytes. Since the minimum file system
* blocksize is 512 bytes, we can get a max of 3 extents back from * blocksize is 512 bytes, we can get a max of 3 extents back from

View file

@ -1568,18 +1568,17 @@ xfs_agi_read_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
struct xfs_mount *mp = bp->b_target->bt_mount; struct xfs_mount *mp = bp->b_target->bt_mount;
int agi_ok = 1;
if (xfs_sb_version_hascrc(&mp->m_sb)) if (xfs_sb_version_hascrc(&mp->m_sb) &&
agi_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), !xfs_buf_verify_cksum(bp, XFS_AGI_CRC_OFF))
offsetof(struct xfs_agi, agi_crc)); xfs_buf_ioerror(bp, EFSBADCRC);
agi_ok = agi_ok && xfs_agi_verify(bp); else if (XFS_TEST_ERROR(!xfs_agi_verify(bp), mp,
XFS_ERRTAG_IALLOC_READ_AGI,
if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI, XFS_RANDOM_IALLOC_READ_AGI))
XFS_RANDOM_IALLOC_READ_AGI))) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
static void static void
@ -1590,8 +1589,8 @@ xfs_agi_write_verify(
struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_buf_log_item *bip = bp->b_fspriv;
if (!xfs_agi_verify(bp)) { if (!xfs_agi_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -1600,8 +1599,7 @@ xfs_agi_write_verify(
if (bip) if (bip)
XFS_BUF_TO_AGI(bp)->agi_lsn = cpu_to_be64(bip->bli_item.li_lsn); XFS_BUF_TO_AGI(bp)->agi_lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), xfs_buf_update_cksum(bp, XFS_AGI_CRC_OFF);
offsetof(struct xfs_agi, agi_crc));
} }
const struct xfs_buf_ops xfs_agi_buf_ops = { const struct xfs_buf_ops xfs_agi_buf_ops = {

View file

@ -243,12 +243,14 @@ static void
xfs_inobt_read_verify( xfs_inobt_read_verify(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
if (!(xfs_btree_sblock_verify_crc(bp) && if (!xfs_btree_sblock_verify_crc(bp))
xfs_inobt_verify(bp))) { xfs_buf_ioerror(bp, EFSBADCRC);
trace_xfs_btree_corrupt(bp, _RET_IP_); else if (!xfs_inobt_verify(bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
bp->b_target->bt_mount, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
if (bp->b_error) {
trace_xfs_btree_corrupt(bp, _RET_IP_);
xfs_verifier_error(bp);
} }
} }
@ -258,9 +260,9 @@ xfs_inobt_write_verify(
{ {
if (!xfs_inobt_verify(bp)) { if (!xfs_inobt_verify(bp)) {
trace_xfs_btree_corrupt(bp, _RET_IP_); trace_xfs_btree_corrupt(bp, _RET_IP_);
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
bp->b_target->bt_mount, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return;
} }
xfs_btree_sblock_calc_crc(bp); xfs_btree_sblock_calc_crc(bp);

View file

@ -102,8 +102,7 @@ xfs_inode_buf_verify(
} }
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH, xfs_verifier_error(bp);
mp, dip);
#ifdef DEBUG #ifdef DEBUG
xfs_alert(mp, xfs_alert(mp,
"bad inode magic/vsn daddr %lld #%d (magic=%x)", "bad inode magic/vsn daddr %lld #%d (magic=%x)",
@ -306,7 +305,7 @@ xfs_dinode_verify(
if (!xfs_sb_version_hascrc(&mp->m_sb)) if (!xfs_sb_version_hascrc(&mp->m_sb))
return false; return false;
if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize, if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
offsetof(struct xfs_dinode, di_crc))) XFS_DINODE_CRC_OFF))
return false; return false;
if (be64_to_cpu(dip->di_ino) != ip->i_ino) if (be64_to_cpu(dip->di_ino) != ip->i_ino)
return false; return false;
@ -327,7 +326,7 @@ xfs_dinode_calc_crc(
ASSERT(xfs_sb_version_hascrc(&mp->m_sb)); ASSERT(xfs_sb_version_hascrc(&mp->m_sb));
crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize, crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize,
offsetof(struct xfs_dinode, di_crc)); XFS_DINODE_CRC_OFF);
dip->di_crc = xfs_end_cksum(crc); dip->di_crc = xfs_end_cksum(crc);
} }

View file

@ -119,6 +119,7 @@ typedef __uint64_t __psunsigned_t;
#include "xfs_iops.h" #include "xfs_iops.h"
#include "xfs_aops.h" #include "xfs_aops.h"
#include "xfs_super.h" #include "xfs_super.h"
#include "xfs_cksum.h"
#include "xfs_buf.h" #include "xfs_buf.h"
#include "xfs_message.h" #include "xfs_message.h"
@ -178,6 +179,7 @@ typedef __uint64_t __psunsigned_t;
#define ENOATTR ENODATA /* Attribute not found */ #define ENOATTR ENODATA /* Attribute not found */
#define EWRONGFS EINVAL /* Mount with wrong filesystem type */ #define EWRONGFS EINVAL /* Mount with wrong filesystem type */
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
#define EFSBADCRC EBADMSG /* Bad CRC detected */
#define SYNCHRONIZE() barrier() #define SYNCHRONIZE() barrier()
#define __return_address __builtin_return_address(0) #define __return_address __builtin_return_address(0)

View file

@ -611,12 +611,11 @@ xfs_sb_read_verify(
XFS_SB_VERSION_5) || XFS_SB_VERSION_5) ||
dsb->sb_crc != 0)) { dsb->sb_crc != 0)) {
if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), if (!xfs_buf_verify_cksum(bp, XFS_SB_CRC_OFF)) {
offsetof(struct xfs_sb, sb_crc))) {
/* Only fail bad secondaries on a known V5 filesystem */ /* Only fail bad secondaries on a known V5 filesystem */
if (bp->b_bn == XFS_SB_DADDR || if (bp->b_bn == XFS_SB_DADDR ||
xfs_sb_version_hascrc(&mp->m_sb)) { xfs_sb_version_hascrc(&mp->m_sb)) {
error = EFSCORRUPTED; error = EFSBADCRC;
goto out_error; goto out_error;
} }
} }
@ -625,10 +624,9 @@ xfs_sb_read_verify(
out_error: out_error:
if (error) { if (error) {
if (error == EFSCORRUPTED)
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
mp, bp->b_addr);
xfs_buf_ioerror(bp, error); xfs_buf_ioerror(bp, error);
if (error == EFSCORRUPTED || error == EFSBADCRC)
xfs_verifier_error(bp);
} }
} }
@ -663,9 +661,8 @@ xfs_sb_write_verify(
error = xfs_sb_verify(bp, false); error = xfs_sb_verify(bp, false);
if (error) { if (error) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
mp, bp->b_addr);
xfs_buf_ioerror(bp, error); xfs_buf_ioerror(bp, error);
xfs_verifier_error(bp);
return; return;
} }
@ -675,8 +672,7 @@ xfs_sb_write_verify(
if (bip) if (bip)
XFS_BUF_TO_SBP(bp)->sb_lsn = cpu_to_be64(bip->bli_item.li_lsn); XFS_BUF_TO_SBP(bp)->sb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), xfs_buf_update_cksum(bp, XFS_SB_CRC_OFF);
offsetof(struct xfs_sb, sb_crc));
} }
const struct xfs_buf_ops xfs_sb_buf_ops = { const struct xfs_buf_ops xfs_sb_buf_ops = {

View file

@ -182,6 +182,8 @@ typedef struct xfs_sb {
/* must be padded to 64 bit alignment */ /* must be padded to 64 bit alignment */
} xfs_sb_t; } xfs_sb_t;
#define XFS_SB_CRC_OFF offsetof(struct xfs_sb, sb_crc)
/* /*
* Superblock - on disk version. Must match the in core version above. * Superblock - on disk version. Must match the in core version above.
* Must be padded to 64 bit alignment. * Must be padded to 64 bit alignment.

View file

@ -133,12 +133,13 @@ xfs_symlink_read_verify(
if (!xfs_sb_version_hascrc(&mp->m_sb)) if (!xfs_sb_version_hascrc(&mp->m_sb))
return; return;
if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), if (!xfs_buf_verify_cksum(bp, XFS_SYMLINK_CRC_OFF))
offsetof(struct xfs_dsymlink_hdr, sl_crc)) || xfs_buf_ioerror(bp, EFSBADCRC);
!xfs_symlink_verify(bp)) { else if (!xfs_symlink_verify(bp))
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
}
if (bp->b_error)
xfs_verifier_error(bp);
} }
static void static void
@ -153,8 +154,8 @@ xfs_symlink_write_verify(
return; return;
if (!xfs_symlink_verify(bp)) { if (!xfs_symlink_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED); xfs_buf_ioerror(bp, EFSCORRUPTED);
xfs_verifier_error(bp);
return; return;
} }
@ -162,8 +163,7 @@ xfs_symlink_write_verify(
struct xfs_dsymlink_hdr *dsl = bp->b_addr; struct xfs_dsymlink_hdr *dsl = bp->b_addr;
dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn); dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
} }
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), xfs_buf_update_cksum(bp, XFS_SYMLINK_CRC_OFF);
offsetof(struct xfs_dsymlink_hdr, sl_crc));
} }
const struct xfs_buf_ops xfs_symlink_buf_ops = { const struct xfs_buf_ops xfs_symlink_buf_ops = {