|
@@ -2126,6 +2126,17 @@ xlog_recover_validate_buf_type(
|
|
|
__uint16_t magic16;
|
|
|
__uint16_t magicda;
|
|
|
|
|
|
+ /*
|
|
|
+ * We can only do post recovery validation on items on CRC enabled
|
|
|
+ * fielsystems as we need to know when the buffer was written to be able
|
|
|
+ * to determine if we should have replayed the item. If we replay old
|
|
|
+ * metadata over a newer buffer, then it will enter a temporarily
|
|
|
+ * inconsistent state resulting in verification failures. Hence for now
|
|
|
+ * just avoid the verification stage for non-crc filesystems
|
|
|
+ */
|
|
|
+ if (!xfs_sb_version_hascrc(&mp->m_sb))
|
|
|
+ return;
|
|
|
+
|
|
|
magic32 = be32_to_cpu(*(__be32 *)bp->b_addr);
|
|
|
magic16 = be16_to_cpu(*(__be16*)bp->b_addr);
|
|
|
magicda = be16_to_cpu(info->magic);
|
|
@@ -2163,8 +2174,6 @@ xlog_recover_validate_buf_type(
|
|
|
bp->b_ops = &xfs_agf_buf_ops;
|
|
|
break;
|
|
|
case XFS_BLFT_AGFL_BUF:
|
|
|
- if (!xfs_sb_version_hascrc(&mp->m_sb))
|
|
|
- break;
|
|
|
if (magic32 != XFS_AGFL_MAGIC) {
|
|
|
xfs_warn(mp, "Bad AGFL block magic!");
|
|
|
ASSERT(0);
|
|
@@ -2197,10 +2206,6 @@ xlog_recover_validate_buf_type(
|
|
|
#endif
|
|
|
break;
|
|
|
case XFS_BLFT_DINO_BUF:
|
|
|
- /*
|
|
|
- * we get here with inode allocation buffers, not buffers that
|
|
|
- * track unlinked list changes.
|
|
|
- */
|
|
|
if (magic16 != XFS_DINODE_MAGIC) {
|
|
|
xfs_warn(mp, "Bad INODE block magic!");
|
|
|
ASSERT(0);
|
|
@@ -2280,8 +2285,6 @@ xlog_recover_validate_buf_type(
|
|
|
bp->b_ops = &xfs_attr3_leaf_buf_ops;
|
|
|
break;
|
|
|
case XFS_BLFT_ATTR_RMT_BUF:
|
|
|
- if (!xfs_sb_version_hascrc(&mp->m_sb))
|
|
|
- break;
|
|
|
if (magic32 != XFS_ATTR3_RMT_MAGIC) {
|
|
|
xfs_warn(mp, "Bad attr remote magic!");
|
|
|
ASSERT(0);
|
|
@@ -2388,16 +2391,7 @@ xlog_recover_do_reg_buffer(
|
|
|
/* Shouldn't be any more regions */
|
|
|
ASSERT(i == item->ri_total);
|
|
|
|
|
|
- /*
|
|
|
- * We can only do post recovery validation on items on CRC enabled
|
|
|
- * fielsystems as we need to know when the buffer was written to be able
|
|
|
- * to determine if we should have replayed the item. If we replay old
|
|
|
- * metadata over a newer buffer, then it will enter a temporarily
|
|
|
- * inconsistent state resulting in verification failures. Hence for now
|
|
|
- * just avoid the verification stage for non-crc filesystems
|
|
|
- */
|
|
|
- if (xfs_sb_version_hascrc(&mp->m_sb))
|
|
|
- xlog_recover_validate_buf_type(mp, bp, buf_f);
|
|
|
+ xlog_recover_validate_buf_type(mp, bp, buf_f);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2505,12 +2499,29 @@ xlog_recover_buffer_pass2(
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * recover the buffer only if we get an LSN from it and it's less than
|
|
|
+ * Recover the buffer only if we get an LSN from it and it's less than
|
|
|
* the lsn of the transaction we are replaying.
|
|
|
+ *
|
|
|
+ * Note that we have to be extremely careful of readahead here.
|
|
|
+ * Readahead does not attach verfiers to the buffers so if we don't
|
|
|
+ * actually do any replay after readahead because of the LSN we found
|
|
|
+ * in the buffer if more recent than that current transaction then we
|
|
|
+ * need to attach the verifier directly. Failure to do so can lead to
|
|
|
+ * future recovery actions (e.g. EFI and unlinked list recovery) can
|
|
|
+ * operate on the buffers and they won't get the verifier attached. This
|
|
|
+ * can lead to blocks on disk having the correct content but a stale
|
|
|
+ * CRC.
|
|
|
+ *
|
|
|
+ * It is safe to assume these clean buffers are currently up to date.
|
|
|
+ * If the buffer is dirtied by a later transaction being replayed, then
|
|
|
+ * the verifier will be reset to match whatever recover turns that
|
|
|
+ * buffer into.
|
|
|
*/
|
|
|
lsn = xlog_recover_get_buf_lsn(mp, bp);
|
|
|
- if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0)
|
|
|
+ if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {
|
|
|
+ xlog_recover_validate_buf_type(mp, bp, buf_f);
|
|
|
goto out_release;
|
|
|
+ }
|
|
|
|
|
|
if (buf_f->blf_flags & XFS_BLF_INODE_BUF) {
|
|
|
error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
|