diff options
-rw-r--r-- | fs/xfs/xfs_ialloc.c | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 12e3dead439d..5bd255e5f7b8 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -1472,6 +1472,40 @@ xfs_check_agi_unlinked( | |||
1472 | #define xfs_check_agi_unlinked(agi) | 1472 | #define xfs_check_agi_unlinked(agi) |
1473 | #endif | 1473 | #endif |
1474 | 1474 | ||
1475 | static void | ||
1476 | xfs_agi_read_verify( | ||
1477 | struct xfs_buf *bp) | ||
1478 | { | ||
1479 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
1480 | struct xfs_agi *agi = XFS_BUF_TO_AGI(bp); | ||
1481 | int agi_ok; | ||
1482 | |||
1483 | /* | ||
1484 | * Validate the magic number of the agi block. | ||
1485 | */ | ||
1486 | agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) && | ||
1487 | XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)); | ||
1488 | |||
1489 | /* | ||
1490 | * during growfs operations, the perag is not fully initialised, | ||
1491 | * so we can't use it for any useful checking. growfs ensures we can't | ||
1492 | * use it by using uncached buffers that don't have the perag attached | ||
1493 | * so we can detect and avoid this problem. | ||
1494 | */ | ||
1495 | if (bp->b_pag) | ||
1496 | agi_ok = agi_ok && be32_to_cpu(agi->agi_seqno) == | ||
1497 | bp->b_pag->pag_agno; | ||
1498 | |||
1499 | if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI, | ||
1500 | XFS_RANDOM_IALLOC_READ_AGI))) { | ||
1501 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agi); | ||
1502 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
1503 | } | ||
1504 | xfs_check_agi_unlinked(agi); | ||
1505 | bp->b_iodone = NULL; | ||
1506 | xfs_buf_ioend(bp, 0); | ||
1507 | } | ||
1508 | |||
1475 | /* | 1509 | /* |
1476 | * Read in the allocation group header (inode allocation section) | 1510 | * Read in the allocation group header (inode allocation section) |
1477 | */ | 1511 | */ |
@@ -1482,38 +1516,18 @@ xfs_read_agi( | |||
1482 | xfs_agnumber_t agno, /* allocation group number */ | 1516 | xfs_agnumber_t agno, /* allocation group number */ |
1483 | struct xfs_buf **bpp) /* allocation group hdr buf */ | 1517 | struct xfs_buf **bpp) /* allocation group hdr buf */ |
1484 | { | 1518 | { |
1485 | struct xfs_agi *agi; /* allocation group header */ | ||
1486 | int agi_ok; /* agi is consistent */ | ||
1487 | int error; | 1519 | int error; |
1488 | 1520 | ||
1489 | ASSERT(agno != NULLAGNUMBER); | 1521 | ASSERT(agno != NULLAGNUMBER); |
1490 | 1522 | ||
1491 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, | 1523 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, |
1492 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), | 1524 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), |
1493 | XFS_FSS_TO_BB(mp, 1), 0, bpp, NULL); | 1525 | XFS_FSS_TO_BB(mp, 1), 0, bpp, xfs_agi_read_verify); |
1494 | if (error) | 1526 | if (error) |
1495 | return error; | 1527 | return error; |
1496 | 1528 | ||
1497 | ASSERT(!xfs_buf_geterror(*bpp)); | 1529 | ASSERT(!xfs_buf_geterror(*bpp)); |
1498 | agi = XFS_BUF_TO_AGI(*bpp); | ||
1499 | |||
1500 | /* | ||
1501 | * Validate the magic number of the agi block. | ||
1502 | */ | ||
1503 | agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) && | ||
1504 | XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)) && | ||
1505 | be32_to_cpu(agi->agi_seqno) == agno; | ||
1506 | if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI, | ||
1507 | XFS_RANDOM_IALLOC_READ_AGI))) { | ||
1508 | XFS_CORRUPTION_ERROR("xfs_read_agi", XFS_ERRLEVEL_LOW, | ||
1509 | mp, agi); | ||
1510 | xfs_trans_brelse(tp, *bpp); | ||
1511 | return XFS_ERROR(EFSCORRUPTED); | ||
1512 | } | ||
1513 | |||
1514 | xfs_buf_set_ref(*bpp, XFS_AGI_REF); | 1530 | xfs_buf_set_ref(*bpp, XFS_AGI_REF); |
1515 | |||
1516 | xfs_check_agi_unlinked(agi); | ||
1517 | return 0; | 1531 | return 0; |
1518 | } | 1532 | } |
1519 | 1533 | ||