diff options
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
-rw-r--r-- | fs/xfs/xfs_alloc.c | 119 |
1 files changed, 78 insertions, 41 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index c34f799aa92e..40d3d576f473 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -432,53 +432,84 @@ xfs_alloc_fixup_trees( | |||
432 | return 0; | 432 | return 0; |
433 | } | 433 | } |
434 | 434 | ||
435 | static void | 435 | static bool |
436 | xfs_agfl_verify( | 436 | xfs_agfl_verify( |
437 | struct xfs_buf *bp) | 437 | struct xfs_buf *bp) |
438 | { | 438 | { |
439 | #ifdef WHEN_CRCS_COME_ALONG | ||
440 | /* | ||
441 | * we cannot actually do any verification of the AGFL because mkfs does | ||
442 | * not initialise the AGFL to zero or NULL. Hence the only valid part of | ||
443 | * the AGFL is what the AGF says is active. We can't get to the AGF, so | ||
444 | * we can't verify just those entries are valid. | ||
445 | * | ||
446 | * This problem goes away when the CRC format change comes along as that | ||
447 | * requires the AGFL to be initialised by mkfs. At that point, we can | ||
448 | * verify the blocks in the agfl -active or not- lie within the bounds | ||
449 | * of the AG. Until then, just leave this check ifdef'd out. | ||
450 | */ | ||
451 | struct xfs_mount *mp = bp->b_target->bt_mount; | 439 | struct xfs_mount *mp = bp->b_target->bt_mount; |
452 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); | 440 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); |
453 | int agfl_ok = 1; | ||
454 | |||
455 | int i; | 441 | int i; |
456 | 442 | ||
443 | if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid)) | ||
444 | return false; | ||
445 | if (be32_to_cpu(agfl->agfl_magicnum) != XFS_AGFL_MAGIC) | ||
446 | return false; | ||
447 | /* | ||
448 | * during growfs operations, the perag is not fully initialised, | ||
449 | * so we can't use it for any useful checking. growfs ensures we can't | ||
450 | * use it by using uncached buffers that don't have the perag attached | ||
451 | * so we can detect and avoid this problem. | ||
452 | */ | ||
453 | if (bp->b_pag && be32_to_cpu(agfl->agfl_seqno) != bp->b_pag->pag_agno) | ||
454 | return false; | ||
455 | |||
457 | for (i = 0; i < XFS_AGFL_SIZE(mp); i++) { | 456 | for (i = 0; i < XFS_AGFL_SIZE(mp); i++) { |
458 | if (be32_to_cpu(agfl->agfl_bno[i]) == NULLAGBLOCK || | 457 | if (be32_to_cpu(agfl->agfl_bno[i]) != NULLAGBLOCK && |
459 | be32_to_cpu(agfl->agfl_bno[i]) >= mp->m_sb.sb_agblocks) | 458 | be32_to_cpu(agfl->agfl_bno[i]) >= mp->m_sb.sb_agblocks) |
460 | agfl_ok = 0; | 459 | return false; |
461 | } | 460 | } |
461 | return true; | ||
462 | } | ||
463 | |||
464 | static void | ||
465 | xfs_agfl_read_verify( | ||
466 | struct xfs_buf *bp) | ||
467 | { | ||
468 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
469 | int agfl_ok = 1; | ||
470 | |||
471 | /* | ||
472 | * There is no verification of non-crc AGFLs because mkfs does not | ||
473 | * initialise the AGFL to zero or NULL. Hence the only valid part of the | ||
474 | * AGFL is what the AGF says is active. We can't get to the AGF, so we | ||
475 | * can't verify just those entries are valid. | ||
476 | */ | ||
477 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
478 | return; | ||
479 | |||
480 | agfl_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
481 | offsetof(struct xfs_agfl, agfl_crc)); | ||
482 | |||
483 | agfl_ok = agfl_ok && xfs_agfl_verify(bp); | ||
462 | 484 | ||
463 | if (!agfl_ok) { | 485 | if (!agfl_ok) { |
464 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agfl); | 486 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); |
465 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 487 | xfs_buf_ioerror(bp, EFSCORRUPTED); |
466 | } | 488 | } |
467 | #endif | ||
468 | } | 489 | } |
469 | 490 | ||
470 | static void | 491 | static void |
471 | xfs_agfl_write_verify( | 492 | xfs_agfl_write_verify( |
472 | struct xfs_buf *bp) | 493 | struct xfs_buf *bp) |
473 | { | 494 | { |
474 | xfs_agfl_verify(bp); | 495 | struct xfs_mount *mp = bp->b_target->bt_mount; |
475 | } | 496 | struct xfs_buf_log_item *bip = bp->b_fspriv; |
476 | 497 | ||
477 | static void | 498 | /* no verification of non-crc AGFLs */ |
478 | xfs_agfl_read_verify( | 499 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
479 | struct xfs_buf *bp) | 500 | return; |
480 | { | 501 | |
481 | xfs_agfl_verify(bp); | 502 | if (!xfs_agfl_verify(bp)) { |
503 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
504 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
505 | return; | ||
506 | } | ||
507 | |||
508 | if (bip) | ||
509 | XFS_BUF_TO_AGFL(bp)->agfl_lsn = cpu_to_be64(bip->bli_item.li_lsn); | ||
510 | |||
511 | xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
512 | offsetof(struct xfs_agfl, agfl_crc)); | ||
482 | } | 513 | } |
483 | 514 | ||
484 | const struct xfs_buf_ops xfs_agfl_buf_ops = { | 515 | const struct xfs_buf_ops xfs_agfl_buf_ops = { |
@@ -1984,18 +2015,18 @@ xfs_alloc_get_freelist( | |||
1984 | int btreeblk) /* destination is a AGF btree */ | 2015 | int btreeblk) /* destination is a AGF btree */ |
1985 | { | 2016 | { |
1986 | xfs_agf_t *agf; /* a.g. freespace structure */ | 2017 | xfs_agf_t *agf; /* a.g. freespace structure */ |
1987 | xfs_agfl_t *agfl; /* a.g. freelist structure */ | ||
1988 | xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */ | 2018 | xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */ |
1989 | xfs_agblock_t bno; /* block number returned */ | 2019 | xfs_agblock_t bno; /* block number returned */ |
2020 | __be32 *agfl_bno; | ||
1990 | int error; | 2021 | int error; |
1991 | int logflags; | 2022 | int logflags; |
1992 | xfs_mount_t *mp; /* mount structure */ | 2023 | xfs_mount_t *mp = tp->t_mountp; |
1993 | xfs_perag_t *pag; /* per allocation group data */ | 2024 | xfs_perag_t *pag; /* per allocation group data */ |
1994 | 2025 | ||
1995 | agf = XFS_BUF_TO_AGF(agbp); | ||
1996 | /* | 2026 | /* |
1997 | * Freelist is empty, give up. | 2027 | * Freelist is empty, give up. |
1998 | */ | 2028 | */ |
2029 | agf = XFS_BUF_TO_AGF(agbp); | ||
1999 | if (!agf->agf_flcount) { | 2030 | if (!agf->agf_flcount) { |
2000 | *bnop = NULLAGBLOCK; | 2031 | *bnop = NULLAGBLOCK; |
2001 | return 0; | 2032 | return 0; |
@@ -2003,15 +2034,17 @@ xfs_alloc_get_freelist( | |||
2003 | /* | 2034 | /* |
2004 | * Read the array of free blocks. | 2035 | * Read the array of free blocks. |
2005 | */ | 2036 | */ |
2006 | mp = tp->t_mountp; | 2037 | error = xfs_alloc_read_agfl(mp, tp, be32_to_cpu(agf->agf_seqno), |
2007 | if ((error = xfs_alloc_read_agfl(mp, tp, | 2038 | &agflbp); |
2008 | be32_to_cpu(agf->agf_seqno), &agflbp))) | 2039 | if (error) |
2009 | return error; | 2040 | return error; |
2010 | agfl = XFS_BUF_TO_AGFL(agflbp); | 2041 | |
2042 | |||
2011 | /* | 2043 | /* |
2012 | * Get the block number and update the data structures. | 2044 | * Get the block number and update the data structures. |
2013 | */ | 2045 | */ |
2014 | bno = be32_to_cpu(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)]); | 2046 | agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); |
2047 | bno = be32_to_cpu(agfl_bno[be32_to_cpu(agf->agf_flfirst)]); | ||
2015 | be32_add_cpu(&agf->agf_flfirst, 1); | 2048 | be32_add_cpu(&agf->agf_flfirst, 1); |
2016 | xfs_trans_brelse(tp, agflbp); | 2049 | xfs_trans_brelse(tp, agflbp); |
2017 | if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp)) | 2050 | if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp)) |
@@ -2104,12 +2137,13 @@ xfs_alloc_put_freelist( | |||
2104 | int btreeblk) /* block came from a AGF btree */ | 2137 | int btreeblk) /* block came from a AGF btree */ |
2105 | { | 2138 | { |
2106 | xfs_agf_t *agf; /* a.g. freespace structure */ | 2139 | xfs_agf_t *agf; /* a.g. freespace structure */ |
2107 | xfs_agfl_t *agfl; /* a.g. free block array */ | ||
2108 | __be32 *blockp;/* pointer to array entry */ | 2140 | __be32 *blockp;/* pointer to array entry */ |
2109 | int error; | 2141 | int error; |
2110 | int logflags; | 2142 | int logflags; |
2111 | xfs_mount_t *mp; /* mount structure */ | 2143 | xfs_mount_t *mp; /* mount structure */ |
2112 | xfs_perag_t *pag; /* per allocation group data */ | 2144 | xfs_perag_t *pag; /* per allocation group data */ |
2145 | __be32 *agfl_bno; | ||
2146 | int startoff; | ||
2113 | 2147 | ||
2114 | agf = XFS_BUF_TO_AGF(agbp); | 2148 | agf = XFS_BUF_TO_AGF(agbp); |
2115 | mp = tp->t_mountp; | 2149 | mp = tp->t_mountp; |
@@ -2117,7 +2151,6 @@ xfs_alloc_put_freelist( | |||
2117 | if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp, | 2151 | if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp, |
2118 | be32_to_cpu(agf->agf_seqno), &agflbp))) | 2152 | be32_to_cpu(agf->agf_seqno), &agflbp))) |
2119 | return error; | 2153 | return error; |
2120 | agfl = XFS_BUF_TO_AGFL(agflbp); | ||
2121 | be32_add_cpu(&agf->agf_fllast, 1); | 2154 | be32_add_cpu(&agf->agf_fllast, 1); |
2122 | if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp)) | 2155 | if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp)) |
2123 | agf->agf_fllast = 0; | 2156 | agf->agf_fllast = 0; |
@@ -2138,13 +2171,17 @@ xfs_alloc_put_freelist( | |||
2138 | xfs_alloc_log_agf(tp, agbp, logflags); | 2171 | xfs_alloc_log_agf(tp, agbp, logflags); |
2139 | 2172 | ||
2140 | ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)); | 2173 | ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)); |
2141 | blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)]; | 2174 | |
2175 | agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); | ||
2176 | blockp = &agfl_bno[be32_to_cpu(agf->agf_fllast)]; | ||
2142 | *blockp = cpu_to_be32(bno); | 2177 | *blockp = cpu_to_be32(bno); |
2178 | startoff = (char *)blockp - (char *)agflbp->b_addr; | ||
2179 | |||
2143 | xfs_alloc_log_agf(tp, agbp, logflags); | 2180 | xfs_alloc_log_agf(tp, agbp, logflags); |
2144 | xfs_trans_log_buf(tp, agflbp, | 2181 | |
2145 | (int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl), | 2182 | xfs_trans_buf_set_type(tp, agflbp, XFS_BLF_AGFL_BUF); |
2146 | (int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl + | 2183 | xfs_trans_log_buf(tp, agflbp, startoff, |
2147 | sizeof(xfs_agblock_t) - 1)); | 2184 | startoff + sizeof(xfs_agblock_t) - 1); |
2148 | return 0; | 2185 | return 0; |
2149 | } | 2186 | } |
2150 | 2187 | ||