aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r--fs/xfs/xfs_log_recover.c51
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*/
1875STATIC void 1875STATIC void
1876xlog_recover_do_reg_buffer( 1876xlog_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);