diff options
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 254 |
1 files changed, 180 insertions, 74 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index d1292fd1112a..00727bc4a9b0 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -45,7 +45,14 @@ | |||
45 | #include "xfs_cksum.h" | 45 | #include "xfs_cksum.h" |
46 | #include "xfs_trace.h" | 46 | #include "xfs_trace.h" |
47 | #include "xfs_icache.h" | 47 | #include "xfs_icache.h" |
48 | |||
49 | /* Need all the magic numbers and buffer ops structures from these headers */ | ||
48 | #include "xfs_symlink.h" | 50 | #include "xfs_symlink.h" |
51 | #include "xfs_da_btree.h" | ||
52 | #include "xfs_dir2_format.h" | ||
53 | #include "xfs_dir2_priv.h" | ||
54 | #include "xfs_attr_leaf.h" | ||
55 | #include "xfs_attr_remote.h" | ||
49 | 56 | ||
50 | STATIC int | 57 | STATIC int |
51 | xlog_find_zeroed( | 58 | xlog_find_zeroed( |
@@ -1860,81 +1867,30 @@ xlog_recover_do_inode_buffer( | |||
1860 | } | 1867 | } |
1861 | 1868 | ||
1862 | /* | 1869 | /* |
1863 | * Perform a 'normal' buffer recovery. Each logged region of the | 1870 | * Validate the recovered buffer is of the correct type and attach the |
1864 | * buffer should be copied over the corresponding region in the | 1871 | * appropriate buffer operations to them for writeback. Magic numbers are in a |
1865 | * given buffer. The bitmap in the buf log format structure indicates | 1872 | * few places: |
1866 | * where to place the logged data. | 1873 | * the first 16 bits of the buffer (inode buffer, dquot buffer), |
1874 | * the first 32 bits of the buffer (most blocks), | ||
1875 | * inside a struct xfs_da_blkinfo at the start of the buffer. | ||
1867 | */ | 1876 | */ |
1868 | STATIC void | 1877 | static void |
1869 | xlog_recover_do_reg_buffer( | 1878 | xlog_recovery_validate_buf_type( |
1870 | struct xfs_mount *mp, | 1879 | struct xfs_mount *mp, |
1871 | xlog_recover_item_t *item, | ||
1872 | struct xfs_buf *bp, | 1880 | struct xfs_buf *bp, |
1873 | xfs_buf_log_format_t *buf_f) | 1881 | xfs_buf_log_format_t *buf_f) |
1874 | { | 1882 | { |
1875 | int i; | 1883 | struct xfs_da_blkinfo *info = bp->b_addr; |
1876 | int bit; | 1884 | __uint32_t magic32; |
1877 | int nbits; | 1885 | __uint16_t magic16; |
1878 | int error; | 1886 | __uint16_t magicda; |
1879 | 1887 | ||
1880 | trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f); | 1888 | magic32 = be32_to_cpu(*(__be32 *)bp->b_addr); |
1881 | 1889 | magic16 = be16_to_cpu(*(__be16*)bp->b_addr); | |
1882 | bit = 0; | 1890 | magicda = be16_to_cpu(info->magic); |
1883 | i = 1; /* 0 is the buf format structure */ | ||
1884 | while (1) { | ||
1885 | bit = xfs_next_bit(buf_f->blf_data_map, | ||
1886 | buf_f->blf_map_size, bit); | ||
1887 | if (bit == -1) | ||
1888 | break; | ||
1889 | nbits = xfs_contig_bits(buf_f->blf_data_map, | ||
1890 | buf_f->blf_map_size, bit); | ||
1891 | ASSERT(nbits > 0); | ||
1892 | ASSERT(item->ri_buf[i].i_addr != NULL); | ||
1893 | ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0); | ||
1894 | ASSERT(BBTOB(bp->b_io_length) >= | ||
1895 | ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT)); | ||
1896 | |||
1897 | /* | ||
1898 | * Do a sanity check if this is a dquot buffer. Just checking | ||
1899 | * the first dquot in the buffer should do. XXXThis is | ||
1900 | * probably a good thing to do for other buf types also. | ||
1901 | */ | ||
1902 | error = 0; | ||
1903 | if (buf_f->blf_flags & | ||
1904 | (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { | ||
1905 | if (item->ri_buf[i].i_addr == NULL) { | ||
1906 | xfs_alert(mp, | ||
1907 | "XFS: NULL dquot in %s.", __func__); | ||
1908 | goto next; | ||
1909 | } | ||
1910 | if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) { | ||
1911 | xfs_alert(mp, | ||
1912 | "XFS: dquot too small (%d) in %s.", | ||
1913 | item->ri_buf[i].i_len, __func__); | ||
1914 | goto next; | ||
1915 | } | ||
1916 | error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr, | ||
1917 | -1, 0, XFS_QMOPT_DOWARN, | ||
1918 | "dquot_buf_recover"); | ||
1919 | if (error) | ||
1920 | goto next; | ||
1921 | } | ||
1922 | |||
1923 | memcpy(xfs_buf_offset(bp, | ||
1924 | (uint)bit << XFS_BLF_SHIFT), /* dest */ | ||
1925 | item->ri_buf[i].i_addr, /* source */ | ||
1926 | nbits<<XFS_BLF_SHIFT); /* length */ | ||
1927 | next: | ||
1928 | i++; | ||
1929 | bit += nbits; | ||
1930 | } | ||
1931 | |||
1932 | /* Shouldn't be any more regions */ | ||
1933 | ASSERT(i == item->ri_total); | ||
1934 | |||
1935 | switch (buf_f->blf_flags & XFS_BLF_TYPE_MASK) { | 1891 | switch (buf_f->blf_flags & XFS_BLF_TYPE_MASK) { |
1936 | case XFS_BLF_BTREE_BUF: | 1892 | case XFS_BLF_BTREE_BUF: |
1937 | switch (be32_to_cpu(*(__be32 *)bp->b_addr)) { | 1893 | switch (magic32) { |
1938 | case XFS_ABTB_CRC_MAGIC: | 1894 | case XFS_ABTB_CRC_MAGIC: |
1939 | case XFS_ABTC_CRC_MAGIC: | 1895 | case XFS_ABTC_CRC_MAGIC: |
1940 | case XFS_ABTB_MAGIC: | 1896 | case XFS_ABTB_MAGIC: |
@@ -1956,7 +1912,7 @@ xlog_recover_do_reg_buffer( | |||
1956 | } | 1912 | } |
1957 | break; | 1913 | break; |
1958 | case XFS_BLF_AGF_BUF: | 1914 | case XFS_BLF_AGF_BUF: |
1959 | if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGF_MAGIC)) { | 1915 | if (magic32 != XFS_AGF_MAGIC) { |
1960 | xfs_warn(mp, "Bad AGF block magic!"); | 1916 | xfs_warn(mp, "Bad AGF block magic!"); |
1961 | ASSERT(0); | 1917 | ASSERT(0); |
1962 | break; | 1918 | break; |
@@ -1966,7 +1922,7 @@ xlog_recover_do_reg_buffer( | |||
1966 | case XFS_BLF_AGFL_BUF: | 1922 | case XFS_BLF_AGFL_BUF: |
1967 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 1923 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
1968 | break; | 1924 | break; |
1969 | if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGFL_MAGIC)) { | 1925 | if (magic32 != XFS_AGFL_MAGIC) { |
1970 | xfs_warn(mp, "Bad AGFL block magic!"); | 1926 | xfs_warn(mp, "Bad AGFL block magic!"); |
1971 | ASSERT(0); | 1927 | ASSERT(0); |
1972 | break; | 1928 | break; |
@@ -1974,7 +1930,7 @@ xlog_recover_do_reg_buffer( | |||
1974 | bp->b_ops = &xfs_agfl_buf_ops; | 1930 | bp->b_ops = &xfs_agfl_buf_ops; |
1975 | break; | 1931 | break; |
1976 | case XFS_BLF_AGI_BUF: | 1932 | case XFS_BLF_AGI_BUF: |
1977 | if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGI_MAGIC)) { | 1933 | if (magic32 != XFS_AGI_MAGIC) { |
1978 | xfs_warn(mp, "Bad AGI block magic!"); | 1934 | xfs_warn(mp, "Bad AGI block magic!"); |
1979 | ASSERT(0); | 1935 | ASSERT(0); |
1980 | break; | 1936 | break; |
@@ -1984,7 +1940,7 @@ xlog_recover_do_reg_buffer( | |||
1984 | case XFS_BLF_UDQUOT_BUF: | 1940 | case XFS_BLF_UDQUOT_BUF: |
1985 | case XFS_BLF_PDQUOT_BUF: | 1941 | case XFS_BLF_PDQUOT_BUF: |
1986 | case XFS_BLF_GDQUOT_BUF: | 1942 | case XFS_BLF_GDQUOT_BUF: |
1987 | if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DQUOT_MAGIC)) { | 1943 | if (magic16 != XFS_DQUOT_MAGIC) { |
1988 | xfs_warn(mp, "Bad DQUOT block magic!"); | 1944 | xfs_warn(mp, "Bad DQUOT block magic!"); |
1989 | ASSERT(0); | 1945 | ASSERT(0); |
1990 | break; | 1946 | break; |
@@ -1996,7 +1952,7 @@ xlog_recover_do_reg_buffer( | |||
1996 | * we get here with inode allocation buffers, not buffers that | 1952 | * we get here with inode allocation buffers, not buffers that |
1997 | * track unlinked list changes. | 1953 | * track unlinked list changes. |
1998 | */ | 1954 | */ |
1999 | if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DINODE_MAGIC)) { | 1955 | if (magic16 != XFS_DINODE_MAGIC) { |
2000 | xfs_warn(mp, "Bad INODE block magic!"); | 1956 | xfs_warn(mp, "Bad INODE block magic!"); |
2001 | ASSERT(0); | 1957 | ASSERT(0); |
2002 | break; | 1958 | break; |
@@ -2004,19 +1960,169 @@ xlog_recover_do_reg_buffer( | |||
2004 | bp->b_ops = &xfs_inode_buf_ops; | 1960 | bp->b_ops = &xfs_inode_buf_ops; |
2005 | break; | 1961 | break; |
2006 | case XFS_BLF_SYMLINK_BUF: | 1962 | case XFS_BLF_SYMLINK_BUF: |
2007 | if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_SYMLINK_MAGIC)) { | 1963 | if (magic32 != XFS_SYMLINK_MAGIC) { |
2008 | xfs_warn(mp, "Bad symlink block magic!"); | 1964 | xfs_warn(mp, "Bad symlink block magic!"); |
2009 | ASSERT(0); | 1965 | ASSERT(0); |
2010 | break; | 1966 | break; |
2011 | } | 1967 | } |
2012 | bp->b_ops = &xfs_symlink_buf_ops; | 1968 | bp->b_ops = &xfs_symlink_buf_ops; |
2013 | break; | 1969 | break; |
1970 | case XFS_BLF_DIR_BLOCK_BUF: | ||
1971 | if (magic32 != XFS_DIR2_BLOCK_MAGIC && | ||
1972 | magic32 != XFS_DIR3_BLOCK_MAGIC) { | ||
1973 | xfs_warn(mp, "Bad dir block magic!"); | ||
1974 | ASSERT(0); | ||
1975 | break; | ||
1976 | } | ||
1977 | bp->b_ops = &xfs_dir3_block_buf_ops; | ||
1978 | break; | ||
1979 | case XFS_BLF_DIR_DATA_BUF: | ||
1980 | if (magic32 != XFS_DIR2_DATA_MAGIC && | ||
1981 | magic32 != XFS_DIR3_DATA_MAGIC) { | ||
1982 | xfs_warn(mp, "Bad dir data magic!"); | ||
1983 | ASSERT(0); | ||
1984 | break; | ||
1985 | } | ||
1986 | bp->b_ops = &xfs_dir3_data_buf_ops; | ||
1987 | break; | ||
1988 | case XFS_BLF_DIR_FREE_BUF: | ||
1989 | if (magic32 != XFS_DIR2_FREE_MAGIC && | ||
1990 | magic32 != XFS_DIR3_FREE_MAGIC) { | ||
1991 | xfs_warn(mp, "Bad dir3 free magic!"); | ||
1992 | ASSERT(0); | ||
1993 | break; | ||
1994 | } | ||
1995 | bp->b_ops = &xfs_dir3_free_buf_ops; | ||
1996 | break; | ||
1997 | case XFS_BLF_DIR_LEAF1_BUF: | ||
1998 | if (magicda != XFS_DIR2_LEAF1_MAGIC && | ||
1999 | magicda != XFS_DIR3_LEAF1_MAGIC) { | ||
2000 | xfs_warn(mp, "Bad dir leaf1 magic!"); | ||
2001 | ASSERT(0); | ||
2002 | break; | ||
2003 | } | ||
2004 | bp->b_ops = &xfs_dir3_leaf1_buf_ops; | ||
2005 | break; | ||
2006 | case XFS_BLF_DIR_LEAFN_BUF: | ||
2007 | if (magicda != XFS_DIR2_LEAFN_MAGIC && | ||
2008 | magicda != XFS_DIR3_LEAFN_MAGIC) { | ||
2009 | xfs_warn(mp, "Bad dir leafn magic!"); | ||
2010 | ASSERT(0); | ||
2011 | break; | ||
2012 | } | ||
2013 | bp->b_ops = &xfs_dir3_leafn_buf_ops; | ||
2014 | break; | ||
2015 | case XFS_BLF_DA_NODE_BUF: | ||
2016 | if (magicda != XFS_DA_NODE_MAGIC && | ||
2017 | magicda != XFS_DA3_NODE_MAGIC) { | ||
2018 | xfs_warn(mp, "Bad da node magic!"); | ||
2019 | ASSERT(0); | ||
2020 | break; | ||
2021 | } | ||
2022 | bp->b_ops = &xfs_da3_node_buf_ops; | ||
2023 | break; | ||
2024 | case XFS_BLF_ATTR_LEAF_BUF: | ||
2025 | if (magicda != XFS_ATTR_LEAF_MAGIC && | ||
2026 | magicda != XFS_ATTR3_LEAF_MAGIC) { | ||
2027 | xfs_warn(mp, "Bad attr leaf magic!"); | ||
2028 | ASSERT(0); | ||
2029 | break; | ||
2030 | } | ||
2031 | bp->b_ops = &xfs_attr3_leaf_buf_ops; | ||
2032 | break; | ||
2033 | case XFS_BLF_ATTR_RMT_BUF: | ||
2034 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
2035 | break; | ||
2036 | if (magicda != XFS_ATTR3_RMT_MAGIC) { | ||
2037 | xfs_warn(mp, "Bad attr remote magic!"); | ||
2038 | ASSERT(0); | ||
2039 | break; | ||
2040 | } | ||
2041 | bp->b_ops = &xfs_attr3_rmt_buf_ops; | ||
2042 | break; | ||
2014 | default: | 2043 | default: |
2015 | break; | 2044 | break; |
2016 | } | 2045 | } |
2017 | } | 2046 | } |
2018 | 2047 | ||
2019 | /* | 2048 | /* |
2049 | * Perform a 'normal' buffer recovery. Each logged region of the | ||
2050 | * buffer should be copied over the corresponding region in the | ||
2051 | * given buffer. The bitmap in the buf log format structure indicates | ||
2052 | * where to place the logged data. | ||
2053 | */ | ||
2054 | STATIC void | ||
2055 | xlog_recover_do_reg_buffer( | ||
2056 | struct xfs_mount *mp, | ||
2057 | xlog_recover_item_t *item, | ||
2058 | struct xfs_buf *bp, | ||
2059 | xfs_buf_log_format_t *buf_f) | ||
2060 | { | ||
2061 | int i; | ||
2062 | int bit; | ||
2063 | int nbits; | ||
2064 | int error; | ||
2065 | |||
2066 | trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f); | ||
2067 | |||
2068 | bit = 0; | ||
2069 | i = 1; /* 0 is the buf format structure */ | ||
2070 | while (1) { | ||
2071 | bit = xfs_next_bit(buf_f->blf_data_map, | ||
2072 | buf_f->blf_map_size, bit); | ||
2073 | if (bit == -1) | ||
2074 | break; | ||
2075 | nbits = xfs_contig_bits(buf_f->blf_data_map, | ||
2076 | buf_f->blf_map_size, bit); | ||
2077 | ASSERT(nbits > 0); | ||
2078 | ASSERT(item->ri_buf[i].i_addr != NULL); | ||
2079 | ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0); | ||
2080 | ASSERT(BBTOB(bp->b_io_length) >= | ||
2081 | ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT)); | ||
2082 | |||
2083 | /* | ||
2084 | * Do a sanity check if this is a dquot buffer. Just checking | ||
2085 | * the first dquot in the buffer should do. XXXThis is | ||
2086 | * probably a good thing to do for other buf types also. | ||
2087 | */ | ||
2088 | error = 0; | ||
2089 | if (buf_f->blf_flags & | ||
2090 | (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { | ||
2091 | if (item->ri_buf[i].i_addr == NULL) { | ||
2092 | xfs_alert(mp, | ||
2093 | "XFS: NULL dquot in %s.", __func__); | ||
2094 | goto next; | ||
2095 | } | ||
2096 | if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) { | ||
2097 | xfs_alert(mp, | ||
2098 | "XFS: dquot too small (%d) in %s.", | ||
2099 | item->ri_buf[i].i_len, __func__); | ||
2100 | goto next; | ||
2101 | } | ||
2102 | error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr, | ||
2103 | -1, 0, XFS_QMOPT_DOWARN, | ||
2104 | "dquot_buf_recover"); | ||
2105 | if (error) | ||
2106 | goto next; | ||
2107 | } | ||
2108 | |||
2109 | memcpy(xfs_buf_offset(bp, | ||
2110 | (uint)bit << XFS_BLF_SHIFT), /* dest */ | ||
2111 | item->ri_buf[i].i_addr, /* source */ | ||
2112 | nbits<<XFS_BLF_SHIFT); /* length */ | ||
2113 | next: | ||
2114 | i++; | ||
2115 | bit += nbits; | ||
2116 | } | ||
2117 | |||
2118 | /* Shouldn't be any more regions */ | ||
2119 | ASSERT(i == item->ri_total); | ||
2120 | |||
2121 | xlog_recovery_validate_buf_type(mp, bp, buf_f); | ||
2122 | |||
2123 | } | ||
2124 | |||
2125 | /* | ||
2020 | * Do some primitive error checking on ondisk dquot data structures. | 2126 | * Do some primitive error checking on ondisk dquot data structures. |
2021 | */ | 2127 | */ |
2022 | int | 2128 | int |