aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_ialloc.c56
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
1475static void
1476xfs_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