diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index fbc2362d13e3..8a7d8a79a7be 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -2126,6 +2126,17 @@ xlog_recover_validate_buf_type( | |||
2126 | __uint16_t magic16; | 2126 | __uint16_t magic16; |
2127 | __uint16_t magicda; | 2127 | __uint16_t magicda; |
2128 | 2128 | ||
2129 | /* | ||
2130 | * We can only do post recovery validation on items on CRC enabled | ||
2131 | * fielsystems as we need to know when the buffer was written to be able | ||
2132 | * to determine if we should have replayed the item. If we replay old | ||
2133 | * metadata over a newer buffer, then it will enter a temporarily | ||
2134 | * inconsistent state resulting in verification failures. Hence for now | ||
2135 | * just avoid the verification stage for non-crc filesystems | ||
2136 | */ | ||
2137 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
2138 | return; | ||
2139 | |||
2129 | magic32 = be32_to_cpu(*(__be32 *)bp->b_addr); | 2140 | magic32 = be32_to_cpu(*(__be32 *)bp->b_addr); |
2130 | magic16 = be16_to_cpu(*(__be16*)bp->b_addr); | 2141 | magic16 = be16_to_cpu(*(__be16*)bp->b_addr); |
2131 | magicda = be16_to_cpu(info->magic); | 2142 | magicda = be16_to_cpu(info->magic); |
@@ -2163,8 +2174,6 @@ xlog_recover_validate_buf_type( | |||
2163 | bp->b_ops = &xfs_agf_buf_ops; | 2174 | bp->b_ops = &xfs_agf_buf_ops; |
2164 | break; | 2175 | break; |
2165 | case XFS_BLFT_AGFL_BUF: | 2176 | case XFS_BLFT_AGFL_BUF: |
2166 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
2167 | break; | ||
2168 | if (magic32 != XFS_AGFL_MAGIC) { | 2177 | if (magic32 != XFS_AGFL_MAGIC) { |
2169 | xfs_warn(mp, "Bad AGFL block magic!"); | 2178 | xfs_warn(mp, "Bad AGFL block magic!"); |
2170 | ASSERT(0); | 2179 | ASSERT(0); |
@@ -2197,10 +2206,6 @@ xlog_recover_validate_buf_type( | |||
2197 | #endif | 2206 | #endif |
2198 | break; | 2207 | break; |
2199 | case XFS_BLFT_DINO_BUF: | 2208 | case XFS_BLFT_DINO_BUF: |
2200 | /* | ||
2201 | * we get here with inode allocation buffers, not buffers that | ||
2202 | * track unlinked list changes. | ||
2203 | */ | ||
2204 | if (magic16 != XFS_DINODE_MAGIC) { | 2209 | if (magic16 != XFS_DINODE_MAGIC) { |
2205 | xfs_warn(mp, "Bad INODE block magic!"); | 2210 | xfs_warn(mp, "Bad INODE block magic!"); |
2206 | ASSERT(0); | 2211 | ASSERT(0); |
@@ -2280,8 +2285,6 @@ xlog_recover_validate_buf_type( | |||
2280 | bp->b_ops = &xfs_attr3_leaf_buf_ops; | 2285 | bp->b_ops = &xfs_attr3_leaf_buf_ops; |
2281 | break; | 2286 | break; |
2282 | case XFS_BLFT_ATTR_RMT_BUF: | 2287 | case XFS_BLFT_ATTR_RMT_BUF: |
2283 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
2284 | break; | ||
2285 | if (magic32 != XFS_ATTR3_RMT_MAGIC) { | 2288 | if (magic32 != XFS_ATTR3_RMT_MAGIC) { |
2286 | xfs_warn(mp, "Bad attr remote magic!"); | 2289 | xfs_warn(mp, "Bad attr remote magic!"); |
2287 | ASSERT(0); | 2290 | ASSERT(0); |
@@ -2388,16 +2391,7 @@ xlog_recover_do_reg_buffer( | |||
2388 | /* Shouldn't be any more regions */ | 2391 | /* Shouldn't be any more regions */ |
2389 | ASSERT(i == item->ri_total); | 2392 | ASSERT(i == item->ri_total); |
2390 | 2393 | ||
2391 | /* | 2394 | xlog_recover_validate_buf_type(mp, bp, buf_f); |
2392 | * We can only do post recovery validation on items on CRC enabled | ||
2393 | * fielsystems as we need to know when the buffer was written to be able | ||
2394 | * to determine if we should have replayed the item. If we replay old | ||
2395 | * metadata over a newer buffer, then it will enter a temporarily | ||
2396 | * inconsistent state resulting in verification failures. Hence for now | ||
2397 | * just avoid the verification stage for non-crc filesystems | ||
2398 | */ | ||
2399 | if (xfs_sb_version_hascrc(&mp->m_sb)) | ||
2400 | xlog_recover_validate_buf_type(mp, bp, buf_f); | ||
2401 | } | 2395 | } |
2402 | 2396 | ||
2403 | /* | 2397 | /* |
@@ -2505,12 +2499,29 @@ xlog_recover_buffer_pass2( | |||
2505 | } | 2499 | } |
2506 | 2500 | ||
2507 | /* | 2501 | /* |
2508 | * recover the buffer only if we get an LSN from it and it's less than | 2502 | * Recover the buffer only if we get an LSN from it and it's less than |
2509 | * the lsn of the transaction we are replaying. | 2503 | * the lsn of the transaction we are replaying. |
2504 | * | ||
2505 | * Note that we have to be extremely careful of readahead here. | ||
2506 | * Readahead does not attach verfiers to the buffers so if we don't | ||
2507 | * actually do any replay after readahead because of the LSN we found | ||
2508 | * in the buffer if more recent than that current transaction then we | ||
2509 | * need to attach the verifier directly. Failure to do so can lead to | ||
2510 | * future recovery actions (e.g. EFI and unlinked list recovery) can | ||
2511 | * operate on the buffers and they won't get the verifier attached. This | ||
2512 | * can lead to blocks on disk having the correct content but a stale | ||
2513 | * CRC. | ||
2514 | * | ||
2515 | * It is safe to assume these clean buffers are currently up to date. | ||
2516 | * If the buffer is dirtied by a later transaction being replayed, then | ||
2517 | * the verifier will be reset to match whatever recover turns that | ||
2518 | * buffer into. | ||
2510 | */ | 2519 | */ |
2511 | lsn = xlog_recover_get_buf_lsn(mp, bp); | 2520 | lsn = xlog_recover_get_buf_lsn(mp, bp); |
2512 | if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) | 2521 | if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) { |
2522 | xlog_recover_validate_buf_type(mp, bp, buf_f); | ||
2513 | goto out_release; | 2523 | goto out_release; |
2524 | } | ||
2514 | 2525 | ||
2515 | if (buf_f->blf_flags & XFS_BLF_INODE_BUF) { | 2526 | if (buf_f->blf_flags & XFS_BLF_INODE_BUF) { |
2516 | error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); | 2527 | error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); |