On Sun, Nov 03, 2019 at 02:24:02PM -0800, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > Make sure we log something to dmesg whenever we return -EFSCORRUPTED up > the call stack. > > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Reviewed-by: Carlos Maiolino <cmaiolino@xxxxxxxxxx> > --- > fs/xfs/libxfs/xfs_alloc.c | 9 +++++++-- > fs/xfs/libxfs/xfs_attr_leaf.c | 12 +++++++++--- > fs/xfs/libxfs/xfs_bmap.c | 8 +++++++- > fs/xfs/libxfs/xfs_btree.c | 5 ++++- > fs/xfs/libxfs/xfs_da_btree.c | 24 ++++++++++++++++++------ > fs/xfs/libxfs/xfs_dir2.c | 4 +++- > fs/xfs/libxfs/xfs_dir2_leaf.c | 4 +++- > fs/xfs/libxfs/xfs_dir2_node.c | 12 +++++++++--- > fs/xfs/libxfs/xfs_inode_fork.c | 6 ++++++ > fs/xfs/libxfs/xfs_refcount.c | 4 +++- > fs/xfs/libxfs/xfs_rtbitmap.c | 6 ++++-- > fs/xfs/xfs_acl.c | 15 ++++++++++++--- > fs/xfs/xfs_attr_inactive.c | 6 +++++- > fs/xfs/xfs_attr_list.c | 5 ++++- > fs/xfs/xfs_bmap_item.c | 3 ++- > fs/xfs/xfs_error.c | 21 +++++++++++++++++++++ > fs/xfs/xfs_error.h | 1 + > fs/xfs/xfs_extfree_item.c | 3 ++- > fs/xfs/xfs_inode.c | 15 ++++++++++++--- > fs/xfs/xfs_inode_item.c | 5 ++++- > fs/xfs/xfs_iops.c | 10 +++++++--- > fs/xfs/xfs_log_recover.c | 23 ++++++++++++++++++----- > fs/xfs/xfs_qm.c | 13 +++++++++++-- > fs/xfs/xfs_refcount_item.c | 3 ++- > fs/xfs/xfs_rmap_item.c | 7 +++++-- > 25 files changed, 179 insertions(+), 45 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c > index b8d48d5fa6a5..f7a4b54c5bc2 100644 > --- a/fs/xfs/libxfs/xfs_alloc.c > +++ b/fs/xfs/libxfs/xfs_alloc.c > @@ -702,8 +702,10 @@ xfs_alloc_update_counters( > > xfs_trans_agblocks_delta(tp, len); > if (unlikely(be32_to_cpu(agf->agf_freeblks) > > - be32_to_cpu(agf->agf_length))) > + be32_to_cpu(agf->agf_length))) { > + xfs_buf_corruption_error(agbp); > return -EFSCORRUPTED; > + } > > xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); > return 0; > @@ -1048,6 +1050,7 @@ xfs_alloc_ag_vextent_small( > > bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno); > if (!bp) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->mp); > error = -EFSCORRUPTED; > goto error; > } > @@ -2215,8 +2218,10 @@ xfs_free_agfl_block( > return error; > > bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno); > - if (!bp) > + if (!bp) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, tp->t_mountp); > return -EFSCORRUPTED; > + } > xfs_trans_binval(tp, bp); > > return 0; > diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c > index 56e62b3d9bb7..dca8840496ea 100644 > --- a/fs/xfs/libxfs/xfs_attr_leaf.c > +++ b/fs/xfs/libxfs/xfs_attr_leaf.c > @@ -2346,8 +2346,10 @@ xfs_attr3_leaf_lookup_int( > leaf = bp->b_addr; > xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); > entries = xfs_attr3_leaf_entryp(leaf); > - if (ichdr.count >= args->geo->blksize / 8) > + if (ichdr.count >= args->geo->blksize / 8) { > + xfs_buf_corruption_error(bp); > return -EFSCORRUPTED; > + } > > /* > * Binary search. (note: small blocks will skip this loop) > @@ -2363,10 +2365,14 @@ xfs_attr3_leaf_lookup_int( > else > break; > } > - if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) > + if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) { > + xfs_buf_corruption_error(bp); > return -EFSCORRUPTED; > - if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) > + } > + if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) { > + xfs_buf_corruption_error(bp); > return -EFSCORRUPTED; > + } > > /* > * Since we may have duplicate hashval's, find the first matching > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c > index bbabbb41e9d8..64f623d07f82 100644 > --- a/fs/xfs/libxfs/xfs_bmap.c > +++ b/fs/xfs/libxfs/xfs_bmap.c > @@ -730,6 +730,7 @@ xfs_bmap_extents_to_btree( > xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L); > abp = xfs_btree_get_bufl(mp, tp, args.fsbno); > if (!abp) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); > error = -EFSCORRUPTED; > goto out_unreserve_dquot; > } > @@ -1085,6 +1086,7 @@ xfs_bmap_add_attrfork( > if (XFS_IFORK_Q(ip)) > goto trans_cancel; > if (ip->i_d.di_anextents != 0) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); > error = -EFSCORRUPTED; > goto trans_cancel; > } > @@ -1338,6 +1340,7 @@ xfs_bmap_last_before( > case XFS_DINODE_FMT_EXTENTS: > break; > default: > + ASSERT(0); > return -EFSCORRUPTED; > } > > @@ -1438,8 +1441,10 @@ xfs_bmap_last_offset( > return 0; > > if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && > - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) > + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) { > + ASSERT(0); > return -EFSCORRUPTED; > + } > > error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty); > if (error || is_empty) > @@ -5830,6 +5835,7 @@ xfs_bmap_insert_extents( > del_cursor); > > if (stop_fsb >= got.br_startoff + got.br_blockcount) { > + ASSERT(0); > error = -EFSCORRUPTED; > goto del_cursor; > } > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 4fd89c80c821..98843f1258b8 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -1820,6 +1820,7 @@ xfs_btree_lookup_get_block( > > out_bad: > *blkp = NULL; > + xfs_buf_corruption_error(bp); > xfs_trans_brelse(cur->bc_tp, bp); > return -EFSCORRUPTED; > } > @@ -1867,8 +1868,10 @@ xfs_btree_lookup( > XFS_BTREE_STATS_INC(cur, lookup); > > /* No such thing as a zero-level tree. */ > - if (cur->bc_nlevels == 0) > + if (cur->bc_nlevels == 0) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp); > return -EFSCORRUPTED; > + } > > block = NULL; > keyno = 0; > diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c > index 4fd1223c1bd5..1e2dc65adeb8 100644 > --- a/fs/xfs/libxfs/xfs_da_btree.c > +++ b/fs/xfs/libxfs/xfs_da_btree.c > @@ -504,6 +504,7 @@ xfs_da3_split( > node = oldblk->bp->b_addr; > if (node->hdr.info.forw) { > if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) { > + xfs_buf_corruption_error(oldblk->bp); > error = -EFSCORRUPTED; > goto out; > } > @@ -516,6 +517,7 @@ xfs_da3_split( > node = oldblk->bp->b_addr; > if (node->hdr.info.back) { > if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) { > + xfs_buf_corruption_error(oldblk->bp); > error = -EFSCORRUPTED; > goto out; > } > @@ -1541,8 +1543,10 @@ xfs_da3_node_lookup_int( > break; > } > > - if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) > + if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) { > + xfs_buf_corruption_error(blk->bp); > return -EFSCORRUPTED; > + } > > blk->magic = XFS_DA_NODE_MAGIC; > > @@ -1554,15 +1558,18 @@ xfs_da3_node_lookup_int( > btree = dp->d_ops->node_tree_p(node); > > /* Tree taller than we can handle; bail out! */ > - if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) > + if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) { > + xfs_buf_corruption_error(blk->bp); > return -EFSCORRUPTED; > + } > > /* Check the level from the root. */ > if (blkno == args->geo->leafblk) > expected_level = nodehdr.level - 1; > - else if (expected_level != nodehdr.level) > + else if (expected_level != nodehdr.level) { > + xfs_buf_corruption_error(blk->bp); > return -EFSCORRUPTED; > - else > + } else > expected_level--; > > max = nodehdr.count; > @@ -1612,12 +1619,17 @@ xfs_da3_node_lookup_int( > } > > /* We can't point back to the root. */ > - if (blkno == args->geo->leafblk) > + if (blkno == args->geo->leafblk) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, > + dp->i_mount); > return -EFSCORRUPTED; > + } > } > > - if (expected_level != 0) > + if (expected_level != 0) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, dp->i_mount); > return -EFSCORRUPTED; > + } > > /* > * A leaf block that ends in the hashval that we are interested in > diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c > index 867c5dee0751..452d04ae10ce 100644 > --- a/fs/xfs/libxfs/xfs_dir2.c > +++ b/fs/xfs/libxfs/xfs_dir2.c > @@ -600,8 +600,10 @@ xfs_dir2_isblock( > if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) > return rval; > rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; > - if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) > + if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount); > return -EFSCORRUPTED; > + } > *vp = rval; > return 0; > } > diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c > index a53e4585a2f3..388b5da12228 100644 > --- a/fs/xfs/libxfs/xfs_dir2_leaf.c > +++ b/fs/xfs/libxfs/xfs_dir2_leaf.c > @@ -1343,8 +1343,10 @@ xfs_dir2_leaf_removename( > oldbest = be16_to_cpu(bf[0].length); > ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); > bestsp = xfs_dir2_leaf_bests_p(ltp); > - if (be16_to_cpu(bestsp[db]) != oldbest) > + if (be16_to_cpu(bestsp[db]) != oldbest) { > + xfs_buf_corruption_error(lbp); > return -EFSCORRUPTED; > + } > /* > * Mark the former data entry unused. > */ > diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c > index 705c4f562758..72d7ed17eef5 100644 > --- a/fs/xfs/libxfs/xfs_dir2_node.c > +++ b/fs/xfs/libxfs/xfs_dir2_node.c > @@ -373,8 +373,10 @@ xfs_dir2_leaf_to_node( > leaf = lbp->b_addr; > ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); > if (be32_to_cpu(ltp->bestcount) > > - (uint)dp->i_d.di_size / args->geo->blksize) > + (uint)dp->i_d.di_size / args->geo->blksize) { > + xfs_buf_corruption_error(lbp); > return -EFSCORRUPTED; > + } > > /* > * Copy freespace entries from the leaf block to the new block. > @@ -445,8 +447,10 @@ xfs_dir2_leafn_add( > * Quick check just to make sure we are not going to index > * into other peoples memory > */ > - if (index < 0) > + if (index < 0) { > + xfs_buf_corruption_error(bp); > return -EFSCORRUPTED; > + } > > /* > * If there are already the maximum number of leaf entries in > @@ -739,8 +743,10 @@ xfs_dir2_leafn_lookup_for_entry( > ents = dp->d_ops->leaf_ents_p(leaf); > > xfs_dir3_leaf_check(dp, bp); > - if (leafhdr.count <= 0) > + if (leafhdr.count <= 0) { > + xfs_buf_corruption_error(bp); > return -EFSCORRUPTED; > + } > > /* > * Look up the hash value in the leaf entries. > diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c > index 8fdd0424070e..15d6f947620f 100644 > --- a/fs/xfs/libxfs/xfs_inode_fork.c > +++ b/fs/xfs/libxfs/xfs_inode_fork.c > @@ -75,11 +75,15 @@ xfs_iformat_fork( > error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK); > break; > default: > + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, > + dip, sizeof(*dip), __this_address); > return -EFSCORRUPTED; > } > break; > > default: > + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, > + sizeof(*dip), __this_address); > return -EFSCORRUPTED; > } > if (error) > @@ -110,6 +114,8 @@ xfs_iformat_fork( > error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK); > break; > default: > + xfs_inode_verifier_error(ip, error, __func__, dip, > + sizeof(*dip), __this_address); > error = -EFSCORRUPTED; > break; > } > diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c > index 9a7fadb1361c..78236bd6c64f 100644 > --- a/fs/xfs/libxfs/xfs_refcount.c > +++ b/fs/xfs/libxfs/xfs_refcount.c > @@ -1591,8 +1591,10 @@ xfs_refcount_recover_extent( > struct list_head *debris = priv; > struct xfs_refcount_recovery *rr; > > - if (be32_to_cpu(rec->refc.rc_refcount) != 1) > + if (be32_to_cpu(rec->refc.rc_refcount) != 1) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp); > return -EFSCORRUPTED; > + } > > rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0); > xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec); > diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c > index 8ea1efc97b41..d8aaa1de921c 100644 > --- a/fs/xfs/libxfs/xfs_rtbitmap.c > +++ b/fs/xfs/libxfs/xfs_rtbitmap.c > @@ -15,7 +15,7 @@ > #include "xfs_bmap.h" > #include "xfs_trans.h" > #include "xfs_rtalloc.h" > - > +#include "xfs_error.h" > > /* > * Realtime allocator bitmap functions shared with userspace. > @@ -70,8 +70,10 @@ xfs_rtbuf_get( > if (error) > return error; > > - if (nmap == 0 || !xfs_bmap_is_real_extent(&map)) > + if (nmap == 0 || !xfs_bmap_is_real_extent(&map)) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); > return -EFSCORRUPTED; > + } > > ASSERT(map.br_startblock != NULLFSBLOCK); > error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, > diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c > index 96d7071cfa46..3f2292c7835c 100644 > --- a/fs/xfs/xfs_acl.c > +++ b/fs/xfs/xfs_acl.c > @@ -12,6 +12,7 @@ > #include "xfs_inode.h" > #include "xfs_attr.h" > #include "xfs_trace.h" > +#include "xfs_error.h" > #include <linux/posix_acl_xattr.h> > > > @@ -23,6 +24,7 @@ > > STATIC struct posix_acl * > xfs_acl_from_disk( > + struct xfs_mount *mp, > const struct xfs_acl *aclp, > int len, > int max_entries) > @@ -32,11 +34,18 @@ xfs_acl_from_disk( > const struct xfs_acl_entry *ace; > unsigned int count, i; > > - if (len < sizeof(*aclp)) > + if (len < sizeof(*aclp)) { > + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp, > + len); > return ERR_PTR(-EFSCORRUPTED); > + } > + > count = be32_to_cpu(aclp->acl_cnt); > - if (count > max_entries || XFS_ACL_SIZE(count) != len) > + if (count > max_entries || XFS_ACL_SIZE(count) != len) { > + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp, > + len); > return ERR_PTR(-EFSCORRUPTED); > + } > > acl = posix_acl_alloc(count, GFP_KERNEL); > if (!acl) > @@ -145,7 +154,7 @@ xfs_get_acl(struct inode *inode, int type) > if (error != -ENOATTR) > acl = ERR_PTR(error); > } else { > - acl = xfs_acl_from_disk(xfs_acl, len, > + acl = xfs_acl_from_disk(ip->i_mount, xfs_acl, len, > XFS_ACL_MAX_ENTRIES(ip->i_mount)); > kmem_free(xfs_acl); > } > diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c > index f83f11d929e4..43ae392992e7 100644 > --- a/fs/xfs/xfs_attr_inactive.c > +++ b/fs/xfs/xfs_attr_inactive.c > @@ -22,6 +22,7 @@ > #include "xfs_attr_leaf.h" > #include "xfs_quota.h" > #include "xfs_dir2.h" > +#include "xfs_error.h" > > /* > * Look at all the extents for this logical region, > @@ -209,6 +210,7 @@ xfs_attr3_node_inactive( > */ > if (level > XFS_DA_NODE_MAXDEPTH) { > xfs_trans_brelse(*trans, bp); /* no locks for later trans */ > + xfs_buf_corruption_error(bp); > return -EFSCORRUPTED; > } > > @@ -258,8 +260,9 @@ xfs_attr3_node_inactive( > error = xfs_attr3_leaf_inactive(trans, dp, child_bp); > break; > default: > - error = -EFSCORRUPTED; > + xfs_buf_corruption_error(child_bp); > xfs_trans_brelse(*trans, child_bp); > + error = -EFSCORRUPTED; > break; > } > if (error) > @@ -342,6 +345,7 @@ xfs_attr3_root_inactive( > break; > default: > error = -EFSCORRUPTED; > + xfs_buf_corruption_error(bp); > xfs_trans_brelse(*trans, bp); > break; > } > diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c > index c02f22d50e45..64f6ceba9254 100644 > --- a/fs/xfs/xfs_attr_list.c > +++ b/fs/xfs/xfs_attr_list.c > @@ -269,8 +269,10 @@ xfs_attr_node_list_lookup( > return 0; > > /* We can't point back to the root. */ > - if (cursor->blkno == 0) > + if (cursor->blkno == 0) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); > return -EFSCORRUPTED; > + } > } > > if (expected_level != 0) > @@ -280,6 +282,7 @@ xfs_attr_node_list_lookup( > return 0; > > out_corruptbuf: > + xfs_buf_corruption_error(bp); > xfs_trans_brelse(tp, bp); > return -EFSCORRUPTED; > } > diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c > index 83d24e983d4c..26c87fd9ac9f 100644 > --- a/fs/xfs/xfs_bmap_item.c > +++ b/fs/xfs/xfs_bmap_item.c > @@ -21,7 +21,7 @@ > #include "xfs_icache.h" > #include "xfs_bmap_btree.h" > #include "xfs_trans_space.h" > - > +#include "xfs_error.h" > > kmem_zone_t *xfs_bui_zone; > kmem_zone_t *xfs_bud_zone; > @@ -525,6 +525,7 @@ xfs_bui_recover( > type = bui_type; > break; > default: > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); > error = -EFSCORRUPTED; > goto err_inode; > } > diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c > index 0b156cc88108..d8cdb27fe6ed 100644 > --- a/fs/xfs/xfs_error.c > +++ b/fs/xfs/xfs_error.c > @@ -341,6 +341,27 @@ xfs_corruption_error( > xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair"); > } > > +/* > + * Complain about the kinds of metadata corruption that we can't detect from a > + * verifier, such as incorrect inter-block relationship data. Does not set > + * bp->b_error. > + */ > +void > +xfs_buf_corruption_error( > + struct xfs_buf *bp) > +{ > + struct xfs_mount *mp = bp->b_mount; > + > + xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR, > + "Metadata corruption detected at %pS, %s block 0x%llx", > + __return_address, bp->b_ops->name, bp->b_bn); > + > + xfs_alert(mp, "Unmount and run xfs_repair"); > + > + if (xfs_error_level >= XFS_ERRLEVEL_HIGH) > + xfs_stack_trace(); > +} > + > /* > * Warnings specifically for verifier errors. Differentiate CRC vs. invalid > * values, and omit the stack trace unless the error level is tuned high. > diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h > index e6a22cfb542f..c319379f7d1a 100644 > --- a/fs/xfs/xfs_error.h > +++ b/fs/xfs/xfs_error.h > @@ -15,6 +15,7 @@ extern void xfs_corruption_error(const char *tag, int level, > struct xfs_mount *mp, const void *buf, size_t bufsize, > const char *filename, int linenum, > xfs_failaddr_t failaddr); > +void xfs_buf_corruption_error(struct xfs_buf *bp); > extern void xfs_buf_verifier_error(struct xfs_buf *bp, int error, > const char *name, const void *buf, size_t bufsz, > xfs_failaddr_t failaddr); > diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c > index e44efc41a041..a6f6acc8fbb7 100644 > --- a/fs/xfs/xfs_extfree_item.c > +++ b/fs/xfs/xfs_extfree_item.c > @@ -21,7 +21,7 @@ > #include "xfs_alloc.h" > #include "xfs_bmap.h" > #include "xfs_trace.h" > - > +#include "xfs_error.h" > > kmem_zone_t *xfs_efi_zone; > kmem_zone_t *xfs_efd_zone; > @@ -228,6 +228,7 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) > } > return 0; > } > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); > return -EFSCORRUPTED; > } > > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c > index e9e4f444f8ce..a92d4521748d 100644 > --- a/fs/xfs/xfs_inode.c > +++ b/fs/xfs/xfs_inode.c > @@ -2136,8 +2136,10 @@ xfs_iunlink_update_bucket( > * passed in because either we're adding or removing ourselves from the > * head of the list. > */ > - if (old_value == new_agino) > + if (old_value == new_agino) { > + xfs_buf_corruption_error(agibp); > return -EFSCORRUPTED; > + } > > agi->agi_unlinked[bucket_index] = cpu_to_be32(new_agino); > offset = offsetof(struct xfs_agi, agi_unlinked) + > @@ -2200,6 +2202,8 @@ xfs_iunlink_update_inode( > /* Make sure the old pointer isn't garbage. */ > old_value = be32_to_cpu(dip->di_next_unlinked); > if (!xfs_verify_agino_or_null(mp, agno, old_value)) { > + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, > + sizeof(*dip), __this_address); > error = -EFSCORRUPTED; > goto out; > } > @@ -2211,8 +2215,11 @@ xfs_iunlink_update_inode( > */ > *old_next_agino = old_value; > if (old_value == next_agino) { > - if (next_agino != NULLAGINO) > + if (next_agino != NULLAGINO) { > + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, > + dip, sizeof(*dip), __this_address); > error = -EFSCORRUPTED; > + } > goto out; > } > > @@ -2263,8 +2270,10 @@ xfs_iunlink( > */ > next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); > if (next_agino == agino || > - !xfs_verify_agino_or_null(mp, agno, next_agino)) > + !xfs_verify_agino_or_null(mp, agno, next_agino)) { > + xfs_buf_corruption_error(agibp); > return -EFSCORRUPTED; > + } > > if (next_agino != NULLAGINO) { > struct xfs_perag *pag; > diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c > index bb8f076805b9..726aa3bfd6e8 100644 > --- a/fs/xfs/xfs_inode_item.c > +++ b/fs/xfs/xfs_inode_item.c > @@ -17,6 +17,7 @@ > #include "xfs_trans_priv.h" > #include "xfs_buf_item.h" > #include "xfs_log.h" > +#include "xfs_error.h" > > #include <linux/iversion.h> > > @@ -828,8 +829,10 @@ xfs_inode_item_format_convert( > { > struct xfs_inode_log_format_32 *in_f32 = buf->i_addr; > > - if (buf->i_len != sizeof(*in_f32)) > + if (buf->i_len != sizeof(*in_f32)) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); > return -EFSCORRUPTED; > + } > > in_f->ilf_type = in_f32->ilf_type; > in_f->ilf_size = in_f32->ilf_size; > diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c > index 18e45e3a3f9f..4c7962ccb0c4 100644 > --- a/fs/xfs/xfs_iops.c > +++ b/fs/xfs/xfs_iops.c > @@ -20,6 +20,7 @@ > #include "xfs_symlink.h" > #include "xfs_dir2.h" > #include "xfs_iomap.h" > +#include "xfs_error.h" > > #include <linux/xattr.h> > #include <linux/posix_acl.h> > @@ -470,17 +471,20 @@ xfs_vn_get_link_inline( > struct inode *inode, > struct delayed_call *done) > { > + struct xfs_inode *ip = XFS_I(inode); > char *link; > > - ASSERT(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE); > + ASSERT(ip->i_df.if_flags & XFS_IFINLINE); > > /* > * The VFS crashes on a NULL pointer, so return -EFSCORRUPTED if > * if_data is junk. > */ > - link = XFS_I(inode)->i_df.if_u1.if_data; > - if (!link) > + link = ip->i_df.if_u1.if_data; > + if (!link) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, ip->i_mount); > return ERR_PTR(-EFSCORRUPTED); > + } > return link; > } > > diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c > index c1a514ffff55..648d5ecafd91 100644 > --- a/fs/xfs/xfs_log_recover.c > +++ b/fs/xfs/xfs_log_recover.c > @@ -3537,6 +3537,7 @@ xfs_cui_copy_format( > memcpy(dst_cui_fmt, src_cui_fmt, len); > return 0; > } > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); > return -EFSCORRUPTED; > } > > @@ -3601,8 +3602,10 @@ xlog_recover_cud_pass2( > struct xfs_ail *ailp = log->l_ailp; > > cud_formatp = item->ri_buf[0].i_addr; > - if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format)) > + if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format)) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp); > return -EFSCORRUPTED; > + } > cui_id = cud_formatp->cud_cui_id; > > /* > @@ -3654,6 +3657,7 @@ xfs_bui_copy_format( > memcpy(dst_bui_fmt, src_bui_fmt, len); > return 0; > } > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); > return -EFSCORRUPTED; > } > > @@ -3677,8 +3681,10 @@ xlog_recover_bui_pass2( > > bui_formatp = item->ri_buf[0].i_addr; > > - if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) > + if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp); > return -EFSCORRUPTED; > + } > buip = xfs_bui_init(mp); > error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format); > if (error) { > @@ -3720,8 +3726,10 @@ xlog_recover_bud_pass2( > struct xfs_ail *ailp = log->l_ailp; > > bud_formatp = item->ri_buf[0].i_addr; > - if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) > + if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp); > return -EFSCORRUPTED; > + } > bui_id = bud_formatp->bud_bui_id; > > /* > @@ -5172,8 +5180,10 @@ xlog_recover_process( > * If the filesystem is CRC enabled, this mismatch becomes a > * fatal log corruption failure. > */ > - if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) > + if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp); > return -EFSCORRUPTED; > + } > } > > xlog_unpack_data(rhead, dp, log); > @@ -5296,8 +5306,11 @@ xlog_do_recovery_pass( > "invalid iclog size (%d bytes), using lsunit (%d bytes)", > h_size, log->l_mp->m_logbsize); > h_size = log->l_mp->m_logbsize; > - } else > + } else { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, > + log->l_mp); > return -EFSCORRUPTED; > + } > } > > if ((be32_to_cpu(rhead->h_version) & XLOG_VERSION_2) && > diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c > index ecd8ce152ab1..66ea8e4fca86 100644 > --- a/fs/xfs/xfs_qm.c > +++ b/fs/xfs/xfs_qm.c > @@ -22,6 +22,7 @@ > #include "xfs_qm.h" > #include "xfs_trace.h" > #include "xfs_icache.h" > +#include "xfs_error.h" > > /* > * The global quota manager. There is only one of these for the entire > @@ -754,11 +755,19 @@ xfs_qm_qino_alloc( > if ((flags & XFS_QMOPT_PQUOTA) && > (mp->m_sb.sb_gquotino != NULLFSINO)) { > ino = mp->m_sb.sb_gquotino; > - ASSERT(mp->m_sb.sb_pquotino == NULLFSINO); > + if (mp->m_sb.sb_pquotino != NULLFSINO) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, > + mp); > + return -EFSCORRUPTED; > + } > } else if ((flags & XFS_QMOPT_GQUOTA) && > (mp->m_sb.sb_pquotino != NULLFSINO)) { > ino = mp->m_sb.sb_pquotino; > - ASSERT(mp->m_sb.sb_gquotino == NULLFSINO); > + if (mp->m_sb.sb_gquotino != NULLFSINO) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, > + mp); > + return -EFSCORRUPTED; > + } > } > if (ino != NULLFSINO) { > error = xfs_iget(mp, NULL, ino, 0, 0, ip); > diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c > index 2328268e6245..576f59fe370e 100644 > --- a/fs/xfs/xfs_refcount_item.c > +++ b/fs/xfs/xfs_refcount_item.c > @@ -17,7 +17,7 @@ > #include "xfs_refcount_item.h" > #include "xfs_log.h" > #include "xfs_refcount.h" > - > +#include "xfs_error.h" > > kmem_zone_t *xfs_cui_zone; > kmem_zone_t *xfs_cud_zone; > @@ -536,6 +536,7 @@ xfs_cui_recover( > type = refc_type; > break; > default: > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); > error = -EFSCORRUPTED; > goto abort_error; > } > diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c > index 8939e0ea09cd..1d72e4b3ebf1 100644 > --- a/fs/xfs/xfs_rmap_item.c > +++ b/fs/xfs/xfs_rmap_item.c > @@ -17,7 +17,7 @@ > #include "xfs_rmap_item.h" > #include "xfs_log.h" > #include "xfs_rmap.h" > - > +#include "xfs_error.h" > > kmem_zone_t *xfs_rui_zone; > kmem_zone_t *xfs_rud_zone; > @@ -171,8 +171,10 @@ xfs_rui_copy_format( > src_rui_fmt = buf->i_addr; > len = xfs_rui_log_format_sizeof(src_rui_fmt->rui_nextents); > > - if (buf->i_len != len) > + if (buf->i_len != len) { > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); > return -EFSCORRUPTED; > + } > > memcpy(dst_rui_fmt, src_rui_fmt, len); > return 0; > @@ -581,6 +583,7 @@ xfs_rui_recover( > type = XFS_RMAP_FREE; > break; > default: > + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); > error = -EFSCORRUPTED; > goto abort_error; > } > -- Carlos