Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce5028cf authored by Eric Sandeen's avatar Eric Sandeen Committed by Dave Chinner
Browse files

xfs: modify verifiers to differentiate CRC from other errors



Modify all read & write verifiers to differentiate
between CRC errors and other inconsistencies.

This sets the appropriate error number on bp->b_error,
and then calls xfs_verifier_error() if something went
wrong.  That function will issue the appropriate message
to the user.

Signed-off-by: default avatarEric Sandeen <sandeen@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent db9355c2
Loading
Loading
Loading
Loading
+17 −20
Original line number Diff line number Diff line
@@ -474,7 +474,6 @@ xfs_agfl_read_verify(
	struct xfs_buf	*bp)
{
	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
@@ -485,14 +484,13 @@ xfs_agfl_read_verify(
	if (!xfs_sb_version_hascrc(&mp->m_sb))
		return;

	agfl_ok = xfs_buf_verify_cksum(bp, XFS_AGFL_CRC_OFF);

	agfl_ok = agfl_ok && xfs_agfl_verify(bp);

	if (!agfl_ok) {
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
	if (!xfs_buf_verify_cksum(bp, XFS_AGFL_CRC_OFF))
		xfs_buf_ioerror(bp, EFSBADCRC);
	else if (!xfs_agfl_verify(bp))
		xfs_buf_ioerror(bp, EFSCORRUPTED);
	}

	if (bp->b_error)
		xfs_verifier_error(bp);
}

static void
@@ -507,8 +505,8 @@ xfs_agfl_write_verify(
		return;

	if (!xfs_agfl_verify(bp)) {
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
		xfs_buf_ioerror(bp, EFSCORRUPTED);
		xfs_verifier_error(bp);
		return;
	}

@@ -2236,18 +2234,17 @@ xfs_agf_read_verify(
	struct xfs_buf	*bp)
{
	struct xfs_mount *mp = bp->b_target->bt_mount;
	int		agf_ok = 1;

	if (xfs_sb_version_hascrc(&mp->m_sb))
		agf_ok = xfs_buf_verify_cksum(bp, XFS_AGF_CRC_OFF);

	agf_ok = agf_ok && xfs_agf_verify(mp, bp);

	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);
	if (xfs_sb_version_hascrc(&mp->m_sb) &&
	    !xfs_buf_verify_cksum(bp, XFS_AGF_CRC_OFF))
		xfs_buf_ioerror(bp, EFSBADCRC);
	else if (XFS_TEST_ERROR(!xfs_agf_verify(mp, bp), mp,
				XFS_ERRTAG_ALLOC_READ_AGF,
				XFS_RANDOM_ALLOC_READ_AGF))
		xfs_buf_ioerror(bp, EFSCORRUPTED);
	}

	if (bp->b_error)
		xfs_verifier_error(bp);
}

static void
@@ -2258,8 +2255,8 @@ xfs_agf_write_verify(
	struct xfs_buf_log_item	*bip = bp->b_fspriv;

	if (!xfs_agf_verify(mp, bp)) {
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
		xfs_buf_ioerror(bp, EFSCORRUPTED);
		xfs_verifier_error(bp);
		return;
	}

+8 −7
Original line number Diff line number Diff line
@@ -355,12 +355,14 @@ static void
xfs_allocbt_read_verify(
	struct xfs_buf	*bp)
{
	if (!(xfs_btree_sblock_verify_crc(bp) &&
	      xfs_allocbt_verify(bp))) {
		trace_xfs_btree_corrupt(bp, _RET_IP_);
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
				     bp->b_target->bt_mount, bp->b_addr);
	if (!xfs_btree_sblock_verify_crc(bp))
		xfs_buf_ioerror(bp, EFSBADCRC);
	else if (!xfs_allocbt_verify(bp))
		xfs_buf_ioerror(bp, EFSCORRUPTED);

	if (bp->b_error) {
		trace_xfs_btree_corrupt(bp, _RET_IP_);
		xfs_verifier_error(bp);
	}
}

@@ -370,9 +372,8 @@ xfs_allocbt_write_verify(
{
	if (!xfs_allocbt_verify(bp)) {
		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_verifier_error(bp);
		return;
	}
	xfs_btree_sblock_calc_crc(bp);
+8 −6
Original line number Diff line number Diff line
@@ -213,8 +213,8 @@ xfs_attr3_leaf_write_verify(
	struct xfs_attr3_leaf_hdr *hdr3 = bp->b_addr;

	if (!xfs_attr3_leaf_verify(bp)) {
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
		xfs_buf_ioerror(bp, EFSCORRUPTED);
		xfs_verifier_error(bp);
		return;
	}

@@ -239,12 +239,14 @@ xfs_attr3_leaf_read_verify(
{
	struct xfs_mount	*mp = bp->b_target->bt_mount;

	if ((xfs_sb_version_hascrc(&mp->m_sb) &&
	     !xfs_buf_verify_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF)) ||
	    !xfs_attr3_leaf_verify(bp)) {
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
	if (xfs_sb_version_hascrc(&mp->m_sb) &&
	     !xfs_buf_verify_cksum(bp, XFS_ATTR3_LEAF_CRC_OFF))
		xfs_buf_ioerror(bp, EFSBADCRC);
	else if (!xfs_attr3_leaf_verify(bp))
		xfs_buf_ioerror(bp, EFSCORRUPTED);
	}

	if (bp->b_error)
		xfs_verifier_error(bp);
}

const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = {
+6 −9
Original line number Diff line number Diff line
@@ -125,7 +125,6 @@ xfs_attr3_rmt_read_verify(
	struct xfs_mount *mp = bp->b_target->bt_mount;
	char		*ptr;
	int		len;
	bool		corrupt = false;
	xfs_daddr_t	bno;

	/* no verification of non-crc buffers */
@@ -140,11 +139,11 @@ xfs_attr3_rmt_read_verify(
	while (len > 0) {
		if (!xfs_verify_cksum(ptr, XFS_LBSIZE(mp),
				      XFS_ATTR3_RMT_CRC_OFF)) {
			corrupt = true;
			xfs_buf_ioerror(bp, EFSBADCRC);
			break;
		}
		if (!xfs_attr3_rmt_verify(mp, ptr, XFS_LBSIZE(mp), bno)) {
			corrupt = true;
			xfs_buf_ioerror(bp, EFSCORRUPTED);
			break;
		}
		len -= XFS_LBSIZE(mp);
@@ -152,10 +151,9 @@ xfs_attr3_rmt_read_verify(
		bno += mp->m_bsize;
	}

	if (corrupt) {
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
		xfs_buf_ioerror(bp, EFSCORRUPTED);
	} else
	if (bp->b_error)
		xfs_verifier_error(bp);
	else
		ASSERT(len == 0);
}

@@ -180,9 +178,8 @@ xfs_attr3_rmt_write_verify(

	while (len > 0) {
		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_verifier_error(bp);
			return;
		}
		if (bip) {
+8 −8
Original line number Diff line number Diff line
@@ -780,12 +780,14 @@ static void
xfs_bmbt_read_verify(
	struct xfs_buf	*bp)
{
	if (!(xfs_btree_lblock_verify_crc(bp) &&
	      xfs_bmbt_verify(bp))) {
		trace_xfs_btree_corrupt(bp, _RET_IP_);
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
				     bp->b_target->bt_mount, bp->b_addr);
	if (!xfs_btree_lblock_verify_crc(bp))
		xfs_buf_ioerror(bp, EFSBADCRC);
	else if (!xfs_bmbt_verify(bp))
		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)
{
	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_);
		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
				     bp->b_target->bt_mount, bp->b_addr);
		xfs_buf_ioerror(bp, EFSCORRUPTED);
		xfs_verifier_error(bp);
		return;
	}
	xfs_btree_lblock_calc_crc(bp);
Loading