xfs_trans_agblocks_delta(tp, len);
        if (unlikely(be32_to_cpu(agf->agf_freeblks) >
                     be32_to_cpu(agf->agf_length))) {
-               xfs_buf_corruption_error(agbp);
+               xfs_buf_mark_corrupt(agbp);
                return -EFSCORRUPTED;
        }
 
 
        xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
        entries = xfs_attr3_leaf_entryp(leaf);
        if (ichdr.count >= args->geo->blksize / 8) {
-               xfs_buf_corruption_error(bp);
+               xfs_buf_mark_corrupt(bp);
                return -EFSCORRUPTED;
        }
 
                        break;
        }
        if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) {
-               xfs_buf_corruption_error(bp);
+               xfs_buf_mark_corrupt(bp);
                return -EFSCORRUPTED;
        }
        if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) {
-               xfs_buf_corruption_error(bp);
+               xfs_buf_mark_corrupt(bp);
                return -EFSCORRUPTED;
        }
 
 
 
 out_bad:
        *blkp = NULL;
-       xfs_buf_corruption_error(bp);
+       xfs_buf_mark_corrupt(bp);
        xfs_trans_brelse(cur->bc_tp, bp);
        return -EFSCORRUPTED;
 }
 
        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);
+                       xfs_buf_mark_corrupt(oldblk->bp);
                        error = -EFSCORRUPTED;
                        goto out;
                }
        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);
+                       xfs_buf_mark_corrupt(oldblk->bp);
                        error = -EFSCORRUPTED;
                        goto out;
                }
                }
 
                if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) {
-                       xfs_buf_corruption_error(blk->bp);
+                       xfs_buf_mark_corrupt(blk->bp);
                        return -EFSCORRUPTED;
                }
 
 
                /* Tree taller than we can handle; bail out! */
                if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) {
-                       xfs_buf_corruption_error(blk->bp);
+                       xfs_buf_mark_corrupt(blk->bp);
                        return -EFSCORRUPTED;
                }
 
                if (blkno == args->geo->leafblk)
                        expected_level = nodehdr.level - 1;
                else if (expected_level != nodehdr.level) {
-                       xfs_buf_corruption_error(blk->bp);
+                       xfs_buf_mark_corrupt(blk->bp);
                        return -EFSCORRUPTED;
                } else
                        expected_level--;
 
        ltp = xfs_dir2_leaf_tail_p(geo, leaf);
        bestsp = xfs_dir2_leaf_bests_p(ltp);
        if (be16_to_cpu(bestsp[db]) != oldbest) {
-               xfs_buf_corruption_error(lbp);
+               xfs_buf_mark_corrupt(lbp);
                return -EFSCORRUPTED;
        }
        /*
 
        ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
        if (be32_to_cpu(ltp->bestcount) >
                                (uint)dp->i_d.di_size / args->geo->blksize) {
-               xfs_buf_corruption_error(lbp);
+               xfs_buf_mark_corrupt(lbp);
                return -EFSCORRUPTED;
        }
 
         * into other peoples memory
         */
        if (index < 0) {
-               xfs_buf_corruption_error(bp);
+               xfs_buf_mark_corrupt(bp);
                return -EFSCORRUPTED;
        }
 
 
        xfs_dir3_leaf_check(dp, bp);
        if (leafhdr.count <= 0) {
-               xfs_buf_corruption_error(bp);
+               xfs_buf_mark_corrupt(bp);
                return -EFSCORRUPTED;
        }
 
 
         * Since this code is recursive (gasp!) we must protect ourselves.
         */
        if (level > XFS_DA_NODE_MAXDEPTH) {
-               xfs_buf_corruption_error(bp);
+               xfs_buf_mark_corrupt(bp);
                xfs_trans_brelse(*trans, bp);   /* no locks for later trans */
                return -EFSCORRUPTED;
        }
                        error = xfs_attr3_leaf_inactive(trans, dp, child_bp);
                        break;
                default:
-                       xfs_buf_corruption_error(child_bp);
+                       xfs_buf_mark_corrupt(child_bp);
                        xfs_trans_brelse(*trans, child_bp);
                        error = -EFSCORRUPTED;
                        break;
                break;
        default:
                error = -EFSCORRUPTED;
-               xfs_buf_corruption_error(bp);
+               xfs_buf_mark_corrupt(bp);
                xfs_trans_brelse(*trans, bp);
                break;
        }
 
        return 0;
 
 out_corruptbuf:
-       xfs_buf_corruption_error(bp);
+       xfs_buf_mark_corrupt(bp);
        xfs_trans_brelse(tp, bp);
        return -EFSCORRUPTED;
 }
 
        }
 }
 
+/*
+ * Log a message about and stale a buffer that a caller has decided is corrupt.
+ *
+ * This function should be called for the kinds of metadata corruption that
+ * cannot be detect from a verifier, such as incorrect inter-block relationship
+ * data.  Do /not/ call this function from a verifier function.
+ *
+ * The buffer must be XBF_DONE prior to the call.  Afterwards, the buffer will
+ * be marked stale, but b_error will not be set.  The caller is responsible for
+ * releasing the buffer or fixing it.
+ */
+void
+__xfs_buf_mark_corrupt(
+       struct xfs_buf          *bp,
+       xfs_failaddr_t          fa)
+{
+       ASSERT(bp->b_flags & XBF_DONE);
+
+       xfs_buf_corruption_error(bp);
+       xfs_buf_stale(bp);
+}
+
 /*
  *     Handling of buffer targets (buftargs).
  */
 
 }
 
 void xfs_buf_zero(struct xfs_buf *bp, size_t boff, size_t bsize);
+void __xfs_buf_mark_corrupt(struct xfs_buf *bp, xfs_failaddr_t fa);
+#define xfs_buf_mark_corrupt(bp) __xfs_buf_mark_corrupt((bp), __this_address)
 
 /* Buffer Utility Routines */
 extern void *xfs_buf_offset(struct xfs_buf *, size_t);
 
  * 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.
+ *
+ * Call xfs_buf_mark_corrupt, not this function.
  */
 void
 xfs_buf_corruption_error(
 
         * head of the list.
         */
        if (old_value == new_agino) {
-               xfs_buf_corruption_error(agibp);
+               xfs_buf_mark_corrupt(agibp);
                return -EFSCORRUPTED;
        }
 
        next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
        if (next_agino == agino ||
            !xfs_verify_agino_or_null(mp, agno, next_agino)) {
-               xfs_buf_corruption_error(agibp);
+               xfs_buf_mark_corrupt(agibp);
                return -EFSCORRUPTED;
        }