diff options
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 74 |
1 files changed, 60 insertions, 14 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index dabda9521b4b..39797490a1f1 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1585,6 +1585,7 @@ xlog_recover_add_to_trans( | |||
1585 | "bad number of regions (%d) in inode log format", | 1585 | "bad number of regions (%d) in inode log format", |
1586 | in_f->ilf_size); | 1586 | in_f->ilf_size); |
1587 | ASSERT(0); | 1587 | ASSERT(0); |
1588 | kmem_free(ptr); | ||
1588 | return XFS_ERROR(EIO); | 1589 | return XFS_ERROR(EIO); |
1589 | } | 1590 | } |
1590 | 1591 | ||
@@ -1970,6 +1971,13 @@ xlog_recover_do_inode_buffer( | |||
1970 | * magic number. If we don't recognise the magic number in the buffer, then | 1971 | * magic number. If we don't recognise the magic number in the buffer, then |
1971 | * return a LSN of -1 so that the caller knows it was an unrecognised block and | 1972 | * return a LSN of -1 so that the caller knows it was an unrecognised block and |
1972 | * so can recover the buffer. | 1973 | * so can recover the buffer. |
1974 | * | ||
1975 | * Note: we cannot rely solely on magic number matches to determine that the | ||
1976 | * buffer has a valid LSN - we also need to verify that it belongs to this | ||
1977 | * filesystem, so we need to extract the object's LSN and compare it to that | ||
1978 | * which we read from the superblock. If the UUIDs don't match, then we've got a | ||
1979 | * stale metadata block from an old filesystem instance that we need to recover | ||
1980 | * over the top of. | ||
1973 | */ | 1981 | */ |
1974 | static xfs_lsn_t | 1982 | static xfs_lsn_t |
1975 | xlog_recover_get_buf_lsn( | 1983 | xlog_recover_get_buf_lsn( |
@@ -1980,6 +1988,8 @@ xlog_recover_get_buf_lsn( | |||
1980 | __uint16_t magic16; | 1988 | __uint16_t magic16; |
1981 | __uint16_t magicda; | 1989 | __uint16_t magicda; |
1982 | void *blk = bp->b_addr; | 1990 | void *blk = bp->b_addr; |
1991 | uuid_t *uuid; | ||
1992 | xfs_lsn_t lsn = -1; | ||
1983 | 1993 | ||
1984 | /* v4 filesystems always recover immediately */ | 1994 | /* v4 filesystems always recover immediately */ |
1985 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 1995 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
@@ -1992,43 +2002,79 @@ xlog_recover_get_buf_lsn( | |||
1992 | case XFS_ABTB_MAGIC: | 2002 | case XFS_ABTB_MAGIC: |
1993 | case XFS_ABTC_MAGIC: | 2003 | case XFS_ABTC_MAGIC: |
1994 | case XFS_IBT_CRC_MAGIC: | 2004 | case XFS_IBT_CRC_MAGIC: |
1995 | case XFS_IBT_MAGIC: | 2005 | case XFS_IBT_MAGIC: { |
1996 | return be64_to_cpu( | 2006 | struct xfs_btree_block *btb = blk; |
1997 | ((struct xfs_btree_block *)blk)->bb_u.s.bb_lsn); | 2007 | |
2008 | lsn = be64_to_cpu(btb->bb_u.s.bb_lsn); | ||
2009 | uuid = &btb->bb_u.s.bb_uuid; | ||
2010 | break; | ||
2011 | } | ||
1998 | case XFS_BMAP_CRC_MAGIC: | 2012 | case XFS_BMAP_CRC_MAGIC: |
1999 | case XFS_BMAP_MAGIC: | 2013 | case XFS_BMAP_MAGIC: { |
2000 | return be64_to_cpu( | 2014 | struct xfs_btree_block *btb = blk; |
2001 | ((struct xfs_btree_block *)blk)->bb_u.l.bb_lsn); | 2015 | |
2016 | lsn = be64_to_cpu(btb->bb_u.l.bb_lsn); | ||
2017 | uuid = &btb->bb_u.l.bb_uuid; | ||
2018 | break; | ||
2019 | } | ||
2002 | case XFS_AGF_MAGIC: | 2020 | case XFS_AGF_MAGIC: |
2003 | return be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn); | 2021 | lsn = be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn); |
2022 | uuid = &((struct xfs_agf *)blk)->agf_uuid; | ||
2023 | break; | ||
2004 | case XFS_AGFL_MAGIC: | 2024 | case XFS_AGFL_MAGIC: |
2005 | return be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn); | 2025 | lsn = be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn); |
2026 | uuid = &((struct xfs_agfl *)blk)->agfl_uuid; | ||
2027 | break; | ||
2006 | case XFS_AGI_MAGIC: | 2028 | case XFS_AGI_MAGIC: |
2007 | return be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn); | 2029 | lsn = be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn); |
2030 | uuid = &((struct xfs_agi *)blk)->agi_uuid; | ||
2031 | break; | ||
2008 | case XFS_SYMLINK_MAGIC: | 2032 | case XFS_SYMLINK_MAGIC: |
2009 | return be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn); | 2033 | lsn = be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn); |
2034 | uuid = &((struct xfs_dsymlink_hdr *)blk)->sl_uuid; | ||
2035 | break; | ||
2010 | case XFS_DIR3_BLOCK_MAGIC: | 2036 | case XFS_DIR3_BLOCK_MAGIC: |
2011 | case XFS_DIR3_DATA_MAGIC: | 2037 | case XFS_DIR3_DATA_MAGIC: |
2012 | case XFS_DIR3_FREE_MAGIC: | 2038 | case XFS_DIR3_FREE_MAGIC: |
2013 | return be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn); | 2039 | lsn = be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn); |
2040 | uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid; | ||
2041 | break; | ||
2014 | case XFS_ATTR3_RMT_MAGIC: | 2042 | case XFS_ATTR3_RMT_MAGIC: |
2015 | return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); | 2043 | lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); |
2044 | uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid; | ||
2045 | break; | ||
2016 | case XFS_SB_MAGIC: | 2046 | case XFS_SB_MAGIC: |
2017 | return be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); | 2047 | lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); |
2048 | uuid = &((struct xfs_dsb *)blk)->sb_uuid; | ||
2049 | break; | ||
2018 | default: | 2050 | default: |
2019 | break; | 2051 | break; |
2020 | } | 2052 | } |
2021 | 2053 | ||
2054 | if (lsn != (xfs_lsn_t)-1) { | ||
2055 | if (!uuid_equal(&mp->m_sb.sb_uuid, uuid)) | ||
2056 | goto recover_immediately; | ||
2057 | return lsn; | ||
2058 | } | ||
2059 | |||
2022 | magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic); | 2060 | magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic); |
2023 | switch (magicda) { | 2061 | switch (magicda) { |
2024 | case XFS_DIR3_LEAF1_MAGIC: | 2062 | case XFS_DIR3_LEAF1_MAGIC: |
2025 | case XFS_DIR3_LEAFN_MAGIC: | 2063 | case XFS_DIR3_LEAFN_MAGIC: |
2026 | case XFS_DA3_NODE_MAGIC: | 2064 | case XFS_DA3_NODE_MAGIC: |
2027 | return be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn); | 2065 | lsn = be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn); |
2066 | uuid = &((struct xfs_da3_blkinfo *)blk)->uuid; | ||
2067 | break; | ||
2028 | default: | 2068 | default: |
2029 | break; | 2069 | break; |
2030 | } | 2070 | } |
2031 | 2071 | ||
2072 | if (lsn != (xfs_lsn_t)-1) { | ||
2073 | if (!uuid_equal(&mp->m_sb.sb_uuid, uuid)) | ||
2074 | goto recover_immediately; | ||
2075 | return lsn; | ||
2076 | } | ||
2077 | |||
2032 | /* | 2078 | /* |
2033 | * We do individual object checks on dquot and inode buffers as they | 2079 | * We do individual object checks on dquot and inode buffers as they |
2034 | * have their own individual LSN records. Also, we could have a stale | 2080 | * have their own individual LSN records. Also, we could have a stale |