xfs: add CRC checks to the AGI
[linux-2.6-block.git] / fs / xfs / xfs_log_recover.c
index 96fcbb85ff835d0223e292125f501482626bc60c..6778a7943db435386be4c5e23052763c0f1fc7ea 100644 (file)
@@ -29,6 +29,7 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
+#include "xfs_btree.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
@@ -1442,9 +1443,8 @@ xlog_recover_find_tid(
        xlog_tid_t              tid)
 {
        xlog_recover_t          *trans;
-       struct hlist_node       *n;
 
-       hlist_for_each_entry(trans, n, head, r_list) {
+       hlist_for_each_entry(trans, head, r_list) {
                if (trans->r_log_tid == tid)
                        return trans;
        }
@@ -1929,6 +1929,59 @@ xlog_recover_do_reg_buffer(
 
        /* Shouldn't be any more regions */
        ASSERT(i == item->ri_total);
+
+       switch (buf_f->blf_flags & XFS_BLF_TYPE_MASK) {
+       case XFS_BLF_BTREE_BUF:
+               switch (be32_to_cpu(*(__be32 *)bp->b_addr)) {
+               case XFS_ABTB_CRC_MAGIC:
+               case XFS_ABTC_CRC_MAGIC:
+               case XFS_ABTB_MAGIC:
+               case XFS_ABTC_MAGIC:
+                       bp->b_ops = &xfs_allocbt_buf_ops;
+                       break;
+               case XFS_IBT_CRC_MAGIC:
+               case XFS_IBT_MAGIC:
+                       bp->b_ops = &xfs_inobt_buf_ops;
+                       break;
+               case XFS_BMAP_CRC_MAGIC:
+               case XFS_BMAP_MAGIC:
+                       bp->b_ops = &xfs_bmbt_buf_ops;
+                       break;
+               default:
+                       xfs_warn(mp, "Bad btree block magic!");
+                       ASSERT(0);
+                       break;
+               }
+               break;
+       case XFS_BLF_AGF_BUF:
+               if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGF_MAGIC)) {
+                       xfs_warn(mp, "Bad AGF block magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_agf_buf_ops;
+               break;
+       case XFS_BLF_AGFL_BUF:
+               if (!xfs_sb_version_hascrc(&mp->m_sb))
+                       break;
+               if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGFL_MAGIC)) {
+                       xfs_warn(mp, "Bad AGFL block magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_agfl_buf_ops;
+               break;
+       case XFS_BLF_AGI_BUF:
+               if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGI_MAGIC)) {
+                       xfs_warn(mp, "Bad AGI block magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_agi_buf_ops;
+               break;
+       default:
+               break;
+       }
 }
 
 /*
@@ -2949,6 +3002,7 @@ xlog_recover_process_efi(
                         * This will pull the EFI from the AIL and
                         * free the memory associated with it.
                         */
+                       set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
                        xfs_efi_release(efip, efip->efi_format.efi_nextents);
                        return XFS_ERROR(EIO);
                }