diff options
Diffstat (limited to 'fs/xfs/xfs_ialloc.c')
-rw-r--r-- | fs/xfs/xfs_ialloc.c | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 445bf1aef31c..a815412eab80 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -200,7 +200,8 @@ xfs_ialloc_inode_init( | |||
200 | */ | 200 | */ |
201 | d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster)); | 201 | d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster)); |
202 | fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, | 202 | fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, |
203 | mp->m_bsize * blks_per_cluster, 0); | 203 | mp->m_bsize * blks_per_cluster, |
204 | XBF_UNMAPPED); | ||
204 | if (!fbuf) | 205 | if (!fbuf) |
205 | return ENOMEM; | 206 | return ENOMEM; |
206 | /* | 207 | /* |
@@ -210,6 +211,7 @@ xfs_ialloc_inode_init( | |||
210 | * to log a whole cluster of inodes instead of all the | 211 | * to log a whole cluster of inodes instead of all the |
211 | * individual transactions causing a lot of log traffic. | 212 | * individual transactions causing a lot of log traffic. |
212 | */ | 213 | */ |
214 | fbuf->b_ops = &xfs_inode_buf_ops; | ||
213 | xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog); | 215 | xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog); |
214 | for (i = 0; i < ninodes; i++) { | 216 | for (i = 0; i < ninodes; i++) { |
215 | int ioffset = i << mp->m_sb.sb_inodelog; | 217 | int ioffset = i << mp->m_sb.sb_inodelog; |
@@ -250,6 +252,7 @@ xfs_ialloc_ag_alloc( | |||
250 | /* boundary */ | 252 | /* boundary */ |
251 | struct xfs_perag *pag; | 253 | struct xfs_perag *pag; |
252 | 254 | ||
255 | memset(&args, 0, sizeof(args)); | ||
253 | args.tp = tp; | 256 | args.tp = tp; |
254 | args.mp = tp->t_mountp; | 257 | args.mp = tp->t_mountp; |
255 | 258 | ||
@@ -876,9 +879,9 @@ error0: | |||
876 | * This function is designed to be called twice if it has to do an allocation | 879 | * This function is designed to be called twice if it has to do an allocation |
877 | * to make more free inodes. On the first call, *IO_agbp should be set to NULL. | 880 | * to make more free inodes. On the first call, *IO_agbp should be set to NULL. |
878 | * If an inode is available without having to performn an allocation, an inode | 881 | * If an inode is available without having to performn an allocation, an inode |
879 | * number is returned. In this case, *IO_agbp would be NULL. If an allocation | 882 | * number is returned. In this case, *IO_agbp is set to NULL. If an allocation |
880 | * needes to be done, xfs_dialloc would return the current AGI buffer in | 883 | * needs to be done, xfs_dialloc returns the current AGI buffer in *IO_agbp. |
881 | * *IO_agbp. The caller should then commit the current transaction, allocate a | 884 | * The caller should then commit the current transaction, allocate a |
882 | * new transaction, and call xfs_dialloc() again, passing in the previous value | 885 | * new transaction, and call xfs_dialloc() again, passing in the previous value |
883 | * of *IO_agbp. IO_agbp should be held across the transactions. Since the AGI | 886 | * of *IO_agbp. IO_agbp should be held across the transactions. Since the AGI |
884 | * buffer is locked across the two calls, the second call is guaranteed to have | 887 | * buffer is locked across the two calls, the second call is guaranteed to have |
@@ -1471,6 +1474,57 @@ xfs_check_agi_unlinked( | |||
1471 | #define xfs_check_agi_unlinked(agi) | 1474 | #define xfs_check_agi_unlinked(agi) |
1472 | #endif | 1475 | #endif |
1473 | 1476 | ||
1477 | static void | ||
1478 | xfs_agi_verify( | ||
1479 | struct xfs_buf *bp) | ||
1480 | { | ||
1481 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
1482 | struct xfs_agi *agi = XFS_BUF_TO_AGI(bp); | ||
1483 | int agi_ok; | ||
1484 | |||
1485 | /* | ||
1486 | * Validate the magic number of the agi block. | ||
1487 | */ | ||
1488 | agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) && | ||
1489 | XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)); | ||
1490 | |||
1491 | /* | ||
1492 | * during growfs operations, the perag is not fully initialised, | ||
1493 | * so we can't use it for any useful checking. growfs ensures we can't | ||
1494 | * use it by using uncached buffers that don't have the perag attached | ||
1495 | * so we can detect and avoid this problem. | ||
1496 | */ | ||
1497 | if (bp->b_pag) | ||
1498 | agi_ok = agi_ok && be32_to_cpu(agi->agi_seqno) == | ||
1499 | bp->b_pag->pag_agno; | ||
1500 | |||
1501 | if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI, | ||
1502 | XFS_RANDOM_IALLOC_READ_AGI))) { | ||
1503 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agi); | ||
1504 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
1505 | } | ||
1506 | xfs_check_agi_unlinked(agi); | ||
1507 | } | ||
1508 | |||
1509 | static void | ||
1510 | xfs_agi_read_verify( | ||
1511 | struct xfs_buf *bp) | ||
1512 | { | ||
1513 | xfs_agi_verify(bp); | ||
1514 | } | ||
1515 | |||
1516 | static void | ||
1517 | xfs_agi_write_verify( | ||
1518 | struct xfs_buf *bp) | ||
1519 | { | ||
1520 | xfs_agi_verify(bp); | ||
1521 | } | ||
1522 | |||
1523 | const struct xfs_buf_ops xfs_agi_buf_ops = { | ||
1524 | .verify_read = xfs_agi_read_verify, | ||
1525 | .verify_write = xfs_agi_write_verify, | ||
1526 | }; | ||
1527 | |||
1474 | /* | 1528 | /* |
1475 | * Read in the allocation group header (inode allocation section) | 1529 | * Read in the allocation group header (inode allocation section) |
1476 | */ | 1530 | */ |
@@ -1481,38 +1535,18 @@ xfs_read_agi( | |||
1481 | xfs_agnumber_t agno, /* allocation group number */ | 1535 | xfs_agnumber_t agno, /* allocation group number */ |
1482 | struct xfs_buf **bpp) /* allocation group hdr buf */ | 1536 | struct xfs_buf **bpp) /* allocation group hdr buf */ |
1483 | { | 1537 | { |
1484 | struct xfs_agi *agi; /* allocation group header */ | ||
1485 | int agi_ok; /* agi is consistent */ | ||
1486 | int error; | 1538 | int error; |
1487 | 1539 | ||
1488 | ASSERT(agno != NULLAGNUMBER); | 1540 | ASSERT(agno != NULLAGNUMBER); |
1489 | 1541 | ||
1490 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, | 1542 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, |
1491 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), | 1543 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), |
1492 | XFS_FSS_TO_BB(mp, 1), 0, bpp); | 1544 | XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops); |
1493 | if (error) | 1545 | if (error) |
1494 | return error; | 1546 | return error; |
1495 | 1547 | ||
1496 | ASSERT(!xfs_buf_geterror(*bpp)); | 1548 | ASSERT(!xfs_buf_geterror(*bpp)); |
1497 | agi = XFS_BUF_TO_AGI(*bpp); | ||
1498 | |||
1499 | /* | ||
1500 | * Validate the magic number of the agi block. | ||
1501 | */ | ||
1502 | agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) && | ||
1503 | XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)) && | ||
1504 | be32_to_cpu(agi->agi_seqno) == agno; | ||
1505 | if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI, | ||
1506 | XFS_RANDOM_IALLOC_READ_AGI))) { | ||
1507 | XFS_CORRUPTION_ERROR("xfs_read_agi", XFS_ERRLEVEL_LOW, | ||
1508 | mp, agi); | ||
1509 | xfs_trans_brelse(tp, *bpp); | ||
1510 | return XFS_ERROR(EFSCORRUPTED); | ||
1511 | } | ||
1512 | |||
1513 | xfs_buf_set_ref(*bpp, XFS_AGI_REF); | 1549 | xfs_buf_set_ref(*bpp, XFS_AGI_REF); |
1514 | |||
1515 | xfs_check_agi_unlinked(agi); | ||
1516 | return 0; | 1550 | return 0; |
1517 | } | 1551 | } |
1518 | 1552 | ||