diff options
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
-rw-r--r-- | fs/xfs/xfs_alloc.c | 201 |
1 files changed, 135 insertions, 66 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 0ad23253e8b1..5673bcfda2f0 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -33,7 +33,9 @@ | |||
33 | #include "xfs_alloc.h" | 33 | #include "xfs_alloc.h" |
34 | #include "xfs_extent_busy.h" | 34 | #include "xfs_extent_busy.h" |
35 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
36 | #include "xfs_cksum.h" | ||
36 | #include "xfs_trace.h" | 37 | #include "xfs_trace.h" |
38 | #include "xfs_buf_item.h" | ||
37 | 39 | ||
38 | struct workqueue_struct *xfs_alloc_wq; | 40 | struct workqueue_struct *xfs_alloc_wq; |
39 | 41 | ||
@@ -430,53 +432,84 @@ xfs_alloc_fixup_trees( | |||
430 | return 0; | 432 | return 0; |
431 | } | 433 | } |
432 | 434 | ||
433 | static void | 435 | static bool |
434 | xfs_agfl_verify( | 436 | xfs_agfl_verify( |
435 | struct xfs_buf *bp) | 437 | struct xfs_buf *bp) |
436 | { | 438 | { |
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; | 439 | struct xfs_mount *mp = bp->b_target->bt_mount; |
450 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); | 440 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); |
451 | int agfl_ok = 1; | ||
452 | |||
453 | int i; | 441 | int i; |
454 | 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 | |||
455 | for (i = 0; i < XFS_AGFL_SIZE(mp); i++) { | 456 | for (i = 0; i < XFS_AGFL_SIZE(mp); i++) { |
456 | if (be32_to_cpu(agfl->agfl_bno[i]) == NULLAGBLOCK || | 457 | if (be32_to_cpu(agfl->agfl_bno[i]) != NULLAGBLOCK && |
457 | 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) |
458 | agfl_ok = 0; | 459 | return false; |
459 | } | 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); | ||
460 | 484 | ||
461 | if (!agfl_ok) { | 485 | if (!agfl_ok) { |
462 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agfl); | 486 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); |
463 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 487 | xfs_buf_ioerror(bp, EFSCORRUPTED); |
464 | } | 488 | } |
465 | #endif | ||
466 | } | 489 | } |
467 | 490 | ||
468 | static void | 491 | static void |
469 | xfs_agfl_write_verify( | 492 | xfs_agfl_write_verify( |
470 | struct xfs_buf *bp) | 493 | struct xfs_buf *bp) |
471 | { | 494 | { |
472 | xfs_agfl_verify(bp); | 495 | struct xfs_mount *mp = bp->b_target->bt_mount; |
473 | } | 496 | struct xfs_buf_log_item *bip = bp->b_fspriv; |
474 | 497 | ||
475 | static void | 498 | /* no verification of non-crc AGFLs */ |
476 | xfs_agfl_read_verify( | 499 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
477 | struct xfs_buf *bp) | 500 | return; |
478 | { | 501 | |
479 | 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)); | ||
480 | } | 513 | } |
481 | 514 | ||
482 | const struct xfs_buf_ops xfs_agfl_buf_ops = { | 515 | const struct xfs_buf_ops xfs_agfl_buf_ops = { |
@@ -842,7 +875,7 @@ xfs_alloc_ag_vextent_near( | |||
842 | */ | 875 | */ |
843 | int dofirst; /* set to do first algorithm */ | 876 | int dofirst; /* set to do first algorithm */ |
844 | 877 | ||
845 | dofirst = random32() & 1; | 878 | dofirst = prandom_u32() & 1; |
846 | #endif | 879 | #endif |
847 | 880 | ||
848 | restart: | 881 | restart: |
@@ -1982,18 +2015,18 @@ xfs_alloc_get_freelist( | |||
1982 | int btreeblk) /* destination is a AGF btree */ | 2015 | int btreeblk) /* destination is a AGF btree */ |
1983 | { | 2016 | { |
1984 | xfs_agf_t *agf; /* a.g. freespace structure */ | 2017 | xfs_agf_t *agf; /* a.g. freespace structure */ |
1985 | xfs_agfl_t *agfl; /* a.g. freelist structure */ | ||
1986 | xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */ | 2018 | xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */ |
1987 | xfs_agblock_t bno; /* block number returned */ | 2019 | xfs_agblock_t bno; /* block number returned */ |
2020 | __be32 *agfl_bno; | ||
1988 | int error; | 2021 | int error; |
1989 | int logflags; | 2022 | int logflags; |
1990 | xfs_mount_t *mp; /* mount structure */ | 2023 | xfs_mount_t *mp = tp->t_mountp; |
1991 | xfs_perag_t *pag; /* per allocation group data */ | 2024 | xfs_perag_t *pag; /* per allocation group data */ |
1992 | 2025 | ||
1993 | agf = XFS_BUF_TO_AGF(agbp); | ||
1994 | /* | 2026 | /* |
1995 | * Freelist is empty, give up. | 2027 | * Freelist is empty, give up. |
1996 | */ | 2028 | */ |
2029 | agf = XFS_BUF_TO_AGF(agbp); | ||
1997 | if (!agf->agf_flcount) { | 2030 | if (!agf->agf_flcount) { |
1998 | *bnop = NULLAGBLOCK; | 2031 | *bnop = NULLAGBLOCK; |
1999 | return 0; | 2032 | return 0; |
@@ -2001,15 +2034,17 @@ xfs_alloc_get_freelist( | |||
2001 | /* | 2034 | /* |
2002 | * Read the array of free blocks. | 2035 | * Read the array of free blocks. |
2003 | */ | 2036 | */ |
2004 | mp = tp->t_mountp; | 2037 | error = xfs_alloc_read_agfl(mp, tp, be32_to_cpu(agf->agf_seqno), |
2005 | if ((error = xfs_alloc_read_agfl(mp, tp, | 2038 | &agflbp); |
2006 | be32_to_cpu(agf->agf_seqno), &agflbp))) | 2039 | if (error) |
2007 | return error; | 2040 | return error; |
2008 | agfl = XFS_BUF_TO_AGFL(agflbp); | 2041 | |
2042 | |||
2009 | /* | 2043 | /* |
2010 | * Get the block number and update the data structures. | 2044 | * Get the block number and update the data structures. |
2011 | */ | 2045 | */ |
2012 | 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)]); | ||
2013 | be32_add_cpu(&agf->agf_flfirst, 1); | 2048 | be32_add_cpu(&agf->agf_flfirst, 1); |
2014 | xfs_trans_brelse(tp, agflbp); | 2049 | xfs_trans_brelse(tp, agflbp); |
2015 | if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp)) | 2050 | if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp)) |
@@ -2058,11 +2093,14 @@ xfs_alloc_log_agf( | |||
2058 | offsetof(xfs_agf_t, agf_freeblks), | 2093 | offsetof(xfs_agf_t, agf_freeblks), |
2059 | offsetof(xfs_agf_t, agf_longest), | 2094 | offsetof(xfs_agf_t, agf_longest), |
2060 | offsetof(xfs_agf_t, agf_btreeblks), | 2095 | offsetof(xfs_agf_t, agf_btreeblks), |
2096 | offsetof(xfs_agf_t, agf_uuid), | ||
2061 | sizeof(xfs_agf_t) | 2097 | sizeof(xfs_agf_t) |
2062 | }; | 2098 | }; |
2063 | 2099 | ||
2064 | trace_xfs_agf(tp->t_mountp, XFS_BUF_TO_AGF(bp), fields, _RET_IP_); | 2100 | trace_xfs_agf(tp->t_mountp, XFS_BUF_TO_AGF(bp), fields, _RET_IP_); |
2065 | 2101 | ||
2102 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGF_BUF); | ||
2103 | |||
2066 | xfs_btree_offsets(fields, offsets, XFS_AGF_NUM_BITS, &first, &last); | 2104 | xfs_btree_offsets(fields, offsets, XFS_AGF_NUM_BITS, &first, &last); |
2067 | xfs_trans_log_buf(tp, bp, (uint)first, (uint)last); | 2105 | xfs_trans_log_buf(tp, bp, (uint)first, (uint)last); |
2068 | } | 2106 | } |
@@ -2099,12 +2137,13 @@ xfs_alloc_put_freelist( | |||
2099 | int btreeblk) /* block came from a AGF btree */ | 2137 | int btreeblk) /* block came from a AGF btree */ |
2100 | { | 2138 | { |
2101 | xfs_agf_t *agf; /* a.g. freespace structure */ | 2139 | xfs_agf_t *agf; /* a.g. freespace structure */ |
2102 | xfs_agfl_t *agfl; /* a.g. free block array */ | ||
2103 | __be32 *blockp;/* pointer to array entry */ | 2140 | __be32 *blockp;/* pointer to array entry */ |
2104 | int error; | 2141 | int error; |
2105 | int logflags; | 2142 | int logflags; |
2106 | xfs_mount_t *mp; /* mount structure */ | 2143 | xfs_mount_t *mp; /* mount structure */ |
2107 | xfs_perag_t *pag; /* per allocation group data */ | 2144 | xfs_perag_t *pag; /* per allocation group data */ |
2145 | __be32 *agfl_bno; | ||
2146 | int startoff; | ||
2108 | 2147 | ||
2109 | agf = XFS_BUF_TO_AGF(agbp); | 2148 | agf = XFS_BUF_TO_AGF(agbp); |
2110 | mp = tp->t_mountp; | 2149 | mp = tp->t_mountp; |
@@ -2112,7 +2151,6 @@ xfs_alloc_put_freelist( | |||
2112 | if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp, | 2151 | if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp, |
2113 | be32_to_cpu(agf->agf_seqno), &agflbp))) | 2152 | be32_to_cpu(agf->agf_seqno), &agflbp))) |
2114 | return error; | 2153 | return error; |
2115 | agfl = XFS_BUF_TO_AGFL(agflbp); | ||
2116 | be32_add_cpu(&agf->agf_fllast, 1); | 2154 | be32_add_cpu(&agf->agf_fllast, 1); |
2117 | if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp)) | 2155 | if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp)) |
2118 | agf->agf_fllast = 0; | 2156 | agf->agf_fllast = 0; |
@@ -2133,32 +2171,38 @@ xfs_alloc_put_freelist( | |||
2133 | xfs_alloc_log_agf(tp, agbp, logflags); | 2171 | xfs_alloc_log_agf(tp, agbp, logflags); |
2134 | 2172 | ||
2135 | ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)); | 2173 | ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)); |
2136 | 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)]; | ||
2137 | *blockp = cpu_to_be32(bno); | 2177 | *blockp = cpu_to_be32(bno); |
2178 | startoff = (char *)blockp - (char *)agflbp->b_addr; | ||
2179 | |||
2138 | xfs_alloc_log_agf(tp, agbp, logflags); | 2180 | xfs_alloc_log_agf(tp, agbp, logflags); |
2139 | xfs_trans_log_buf(tp, agflbp, | 2181 | |
2140 | (int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl), | 2182 | xfs_trans_buf_set_type(tp, agflbp, XFS_BLFT_AGFL_BUF); |
2141 | (int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl + | 2183 | xfs_trans_log_buf(tp, agflbp, startoff, |
2142 | sizeof(xfs_agblock_t) - 1)); | 2184 | startoff + sizeof(xfs_agblock_t) - 1); |
2143 | return 0; | 2185 | return 0; |
2144 | } | 2186 | } |
2145 | 2187 | ||
2146 | static void | 2188 | static bool |
2147 | xfs_agf_verify( | 2189 | xfs_agf_verify( |
2190 | struct xfs_mount *mp, | ||
2148 | struct xfs_buf *bp) | 2191 | struct xfs_buf *bp) |
2149 | { | 2192 | { |
2150 | struct xfs_mount *mp = bp->b_target->bt_mount; | 2193 | struct xfs_agf *agf = XFS_BUF_TO_AGF(bp); |
2151 | struct xfs_agf *agf; | ||
2152 | int agf_ok; | ||
2153 | 2194 | ||
2154 | agf = XFS_BUF_TO_AGF(bp); | 2195 | if (xfs_sb_version_hascrc(&mp->m_sb) && |
2196 | !uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_uuid)) | ||
2197 | return false; | ||
2155 | 2198 | ||
2156 | agf_ok = agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) && | 2199 | if (!(agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) && |
2157 | XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) && | 2200 | XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) && |
2158 | be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) && | 2201 | be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) && |
2159 | be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) && | 2202 | be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) && |
2160 | be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) && | 2203 | be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) && |
2161 | be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp); | 2204 | be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp))) |
2205 | return false; | ||
2162 | 2206 | ||
2163 | /* | 2207 | /* |
2164 | * during growfs operations, the perag is not fully initialised, | 2208 | * during growfs operations, the perag is not fully initialised, |
@@ -2166,33 +2210,58 @@ xfs_agf_verify( | |||
2166 | * use it by using uncached buffers that don't have the perag attached | 2210 | * use it by using uncached buffers that don't have the perag attached |
2167 | * so we can detect and avoid this problem. | 2211 | * so we can detect and avoid this problem. |
2168 | */ | 2212 | */ |
2169 | if (bp->b_pag) | 2213 | if (bp->b_pag && be32_to_cpu(agf->agf_seqno) != bp->b_pag->pag_agno) |
2170 | agf_ok = agf_ok && be32_to_cpu(agf->agf_seqno) == | 2214 | return false; |
2171 | bp->b_pag->pag_agno; | ||
2172 | 2215 | ||
2173 | if (xfs_sb_version_haslazysbcount(&mp->m_sb)) | 2216 | if (xfs_sb_version_haslazysbcount(&mp->m_sb) && |
2174 | agf_ok = agf_ok && be32_to_cpu(agf->agf_btreeblks) <= | 2217 | be32_to_cpu(agf->agf_btreeblks) > be32_to_cpu(agf->agf_length)) |
2175 | be32_to_cpu(agf->agf_length); | 2218 | return false; |
2219 | |||
2220 | return true;; | ||
2176 | 2221 | ||
2177 | if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF, | ||
2178 | XFS_RANDOM_ALLOC_READ_AGF))) { | ||
2179 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agf); | ||
2180 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
2181 | } | ||
2182 | } | 2222 | } |
2183 | 2223 | ||
2184 | static void | 2224 | static void |
2185 | xfs_agf_read_verify( | 2225 | xfs_agf_read_verify( |
2186 | struct xfs_buf *bp) | 2226 | struct xfs_buf *bp) |
2187 | { | 2227 | { |
2188 | xfs_agf_verify(bp); | 2228 | struct xfs_mount *mp = bp->b_target->bt_mount; |
2229 | int agf_ok = 1; | ||
2230 | |||
2231 | if (xfs_sb_version_hascrc(&mp->m_sb)) | ||
2232 | agf_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
2233 | offsetof(struct xfs_agf, agf_crc)); | ||
2234 | |||
2235 | agf_ok = agf_ok && xfs_agf_verify(mp, bp); | ||
2236 | |||
2237 | if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF, | ||
2238 | XFS_RANDOM_ALLOC_READ_AGF))) { | ||
2239 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
2240 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
2241 | } | ||
2189 | } | 2242 | } |
2190 | 2243 | ||
2191 | static void | 2244 | static void |
2192 | xfs_agf_write_verify( | 2245 | xfs_agf_write_verify( |
2193 | struct xfs_buf *bp) | 2246 | struct xfs_buf *bp) |
2194 | { | 2247 | { |
2195 | xfs_agf_verify(bp); | 2248 | struct xfs_mount *mp = bp->b_target->bt_mount; |
2249 | struct xfs_buf_log_item *bip = bp->b_fspriv; | ||
2250 | |||
2251 | if (!xfs_agf_verify(mp, bp)) { | ||
2252 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
2253 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
2254 | return; | ||
2255 | } | ||
2256 | |||
2257 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
2258 | return; | ||
2259 | |||
2260 | if (bip) | ||
2261 | XFS_BUF_TO_AGF(bp)->agf_lsn = cpu_to_be64(bip->bli_item.li_lsn); | ||
2262 | |||
2263 | xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
2264 | offsetof(struct xfs_agf, agf_crc)); | ||
2196 | } | 2265 | } |
2197 | 2266 | ||
2198 | const struct xfs_buf_ops xfs_agf_buf_ops = { | 2267 | const struct xfs_buf_ops xfs_agf_buf_ops = { |