diff options
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 8ae6e8e5f3db..dacb19739cc2 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1874,6 +1874,7 @@ xlog_recover_do_inode_buffer( | |||
1874 | /*ARGSUSED*/ | 1874 | /*ARGSUSED*/ |
1875 | STATIC void | 1875 | STATIC void |
1876 | xlog_recover_do_reg_buffer( | 1876 | xlog_recover_do_reg_buffer( |
1877 | xfs_mount_t *mp, | ||
1877 | xlog_recover_item_t *item, | 1878 | xlog_recover_item_t *item, |
1878 | xfs_buf_t *bp, | 1879 | xfs_buf_t *bp, |
1879 | xfs_buf_log_format_t *buf_f) | 1880 | xfs_buf_log_format_t *buf_f) |
@@ -1884,6 +1885,50 @@ xlog_recover_do_reg_buffer( | |||
1884 | unsigned int *data_map = NULL; | 1885 | unsigned int *data_map = NULL; |
1885 | unsigned int map_size = 0; | 1886 | unsigned int map_size = 0; |
1886 | int error; | 1887 | int error; |
1888 | int stale_buf = 1; | ||
1889 | |||
1890 | /* | ||
1891 | * Scan through the on-disk inode buffer and attempt to | ||
1892 | * determine if it has been written to since it was logged. | ||
1893 | * | ||
1894 | * - If any of the magic numbers are incorrect then the buffer is stale | ||
1895 | * - If any of the modes are non-zero then the buffer is not stale | ||
1896 | * - If all of the modes are zero and at least one of the generation | ||
1897 | * counts is non-zero then the buffer is stale | ||
1898 | * | ||
1899 | * If the end result is a stale buffer then the log buffer is replayed | ||
1900 | * otherwise it is skipped. | ||
1901 | * | ||
1902 | * This heuristic is not perfect. It can be improved by scanning the | ||
1903 | * entire inode chunk for evidence that any of the inode clusters have | ||
1904 | * been updated. To fix this problem completely we will need a major | ||
1905 | * architectural change to the logging system. | ||
1906 | */ | ||
1907 | if (buf_f->blf_flags & XFS_BLI_INODE_NEW_BUF) { | ||
1908 | xfs_dinode_t *dip; | ||
1909 | int inodes_per_buf; | ||
1910 | int mode_count = 0; | ||
1911 | int gen_count = 0; | ||
1912 | |||
1913 | stale_buf = 0; | ||
1914 | inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog; | ||
1915 | for (i = 0; i < inodes_per_buf; i++) { | ||
1916 | dip = (xfs_dinode_t *)xfs_buf_offset(bp, | ||
1917 | i * mp->m_sb.sb_inodesize); | ||
1918 | if (be16_to_cpu(dip->di_core.di_magic) != | ||
1919 | XFS_DINODE_MAGIC) { | ||
1920 | stale_buf = 1; | ||
1921 | break; | ||
1922 | } | ||
1923 | if (be16_to_cpu(dip->di_core.di_mode)) | ||
1924 | mode_count++; | ||
1925 | if (be16_to_cpu(dip->di_core.di_gen)) | ||
1926 | gen_count++; | ||
1927 | } | ||
1928 | |||
1929 | if (!mode_count && gen_count) | ||
1930 | stale_buf = 1; | ||
1931 | } | ||
1887 | 1932 | ||
1888 | switch (buf_f->blf_type) { | 1933 | switch (buf_f->blf_type) { |
1889 | case XFS_LI_BUF: | 1934 | case XFS_LI_BUF: |
@@ -1917,7 +1962,7 @@ xlog_recover_do_reg_buffer( | |||
1917 | -1, 0, XFS_QMOPT_DOWARN, | 1962 | -1, 0, XFS_QMOPT_DOWARN, |
1918 | "dquot_buf_recover"); | 1963 | "dquot_buf_recover"); |
1919 | } | 1964 | } |
1920 | if (!error) | 1965 | if (!error && stale_buf) |
1921 | memcpy(xfs_buf_offset(bp, | 1966 | memcpy(xfs_buf_offset(bp, |
1922 | (uint)bit << XFS_BLI_SHIFT), /* dest */ | 1967 | (uint)bit << XFS_BLI_SHIFT), /* dest */ |
1923 | item->ri_buf[i].i_addr, /* source */ | 1968 | item->ri_buf[i].i_addr, /* source */ |
@@ -2089,7 +2134,7 @@ xlog_recover_do_dquot_buffer( | |||
2089 | if (log->l_quotaoffs_flag & type) | 2134 | if (log->l_quotaoffs_flag & type) |
2090 | return; | 2135 | return; |
2091 | 2136 | ||
2092 | xlog_recover_do_reg_buffer(item, bp, buf_f); | 2137 | xlog_recover_do_reg_buffer(mp, item, bp, buf_f); |
2093 | } | 2138 | } |
2094 | 2139 | ||
2095 | /* | 2140 | /* |
@@ -2190,7 +2235,7 @@ xlog_recover_do_buffer_trans( | |||
2190 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { | 2235 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { |
2191 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); | 2236 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); |
2192 | } else { | 2237 | } else { |
2193 | xlog_recover_do_reg_buffer(item, bp, buf_f); | 2238 | xlog_recover_do_reg_buffer(mp, item, bp, buf_f); |
2194 | } | 2239 | } |
2195 | if (error) | 2240 | if (error) |
2196 | return XFS_ERROR(error); | 2241 | return XFS_ERROR(error); |