aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-11-12 06:54:06 -0500
committerBen Myers <bpm@sgi.com>2012-11-15 22:34:14 -0500
commitbb80c6d79a3b0f9b6c3236a4bec021c72615bfd1 (patch)
tree0ec09465d786ed816c1ab6c9179723ae525366f2 /fs/xfs
parent3702ce6ed71cd60451ab278088863456dcb0dd99 (diff)
xfs: verify AGFL blocks as they are read from disk
Add an AGFL block verify callback function and pass it into the buffer read functions. While this commit adds verification code to the AGFL, it cannot be used reliably until the CRC format change comes along as mkfs does not initialise the full AGFL. Hence it can be full of garbage at the first mount and will fail verification right now. CRC enabled filesystems won't have this problem, so leave the code that has already been written ifdef'd out until the proper time. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Phil White <pwhite@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_alloc.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index c9eb955a49c7..38b4ab8957ff 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -430,6 +430,43 @@ xfs_alloc_fixup_trees(
430 return 0; 430 return 0;
431} 431}
432 432
433void
434xfs_agfl_read_verify(
435 struct xfs_buf *bp)
436{
437#ifdef WHEN_CRCS_COME_ALONG
438 /*
439 * we cannot actually do any verification of the AGFL because mkfs does
440 * not initialise the AGFL to zero or NULL. Hence the only valid part of
441 * the AGFL is what the AGF says is active. We can't get to the AGF, so
442 * we can't verify just those entries are valid.
443 *
444 * This problem goes away when the CRC format change comes along as that
445 * requires the AGFL to be initialised by mkfs. At that point, we can
446 * verify the blocks in the agfl -active or not- lie within the bounds
447 * of the AG. Until then, just leave this check ifdef'd out.
448 */
449 struct xfs_mount *mp = bp->b_target->bt_mount;
450 struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp);
451 int agfl_ok = 1;
452
453 int i;
454
455 for (i = 0; i < XFS_AGFL_SIZE(mp); i++) {
456 if (be32_to_cpu(agfl->agfl_bno[i]) == NULLAGBLOCK ||
457 be32_to_cpu(agfl->agfl_bno[i]) >= mp->m_sb.sb_agblocks)
458 agfl_ok = 0;
459 }
460
461 if (!agfl_ok) {
462 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agfl);
463 xfs_buf_ioerror(bp, EFSCORRUPTED);
464 }
465#endif
466 bp->b_iodone = NULL;
467 xfs_buf_ioend(bp, 0);
468}
469
433/* 470/*
434 * Read in the allocation group free block array. 471 * Read in the allocation group free block array.
435 */ 472 */
@@ -447,7 +484,7 @@ xfs_alloc_read_agfl(
447 error = xfs_trans_read_buf( 484 error = xfs_trans_read_buf(
448 mp, tp, mp->m_ddev_targp, 485 mp, tp, mp->m_ddev_targp,
449 XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), 486 XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
450 XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL); 487 XFS_FSS_TO_BB(mp, 1), 0, &bp, xfs_agfl_read_verify);
451 if (error) 488 if (error)
452 return error; 489 return error;
453 ASSERT(!xfs_buf_geterror(bp)); 490 ASSERT(!xfs_buf_geterror(bp));