Commit b394e43e995d08821588a22561c6a71a63b4ff27
Committed by
Tim Shimmin
1 parent
776a75fa5c
Exists in
master
and in
7 other branches
[XFS] Avoid replaying inode buffer initialisation log items if on-disk version is newer.
SGI-PV: 969656 SGI-Modid: xfs-linux-melb:xfs-kern:29676a Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
Showing 3 changed files with 54 additions and 3 deletions Side-by-side Diff
fs/xfs/xfs_buf_item.h
... | ... | @@ -52,6 +52,11 @@ |
52 | 52 | #define XFS_BLI_UDQUOT_BUF 0x4 |
53 | 53 | #define XFS_BLI_PDQUOT_BUF 0x8 |
54 | 54 | #define XFS_BLI_GDQUOT_BUF 0x10 |
55 | +/* | |
56 | + * This flag indicates that the buffer contains newly allocated | |
57 | + * inodes. | |
58 | + */ | |
59 | +#define XFS_BLI_INODE_NEW_BUF 0x20 | |
55 | 60 | |
56 | 61 | #define XFS_BLI_CHUNK 128 |
57 | 62 | #define XFS_BLI_SHIFT 7 |
fs/xfs/xfs_log_recover.c
... | ... | @@ -1874,6 +1874,7 @@ |
1874 | 1874 | /*ARGSUSED*/ |
1875 | 1875 | STATIC void |
1876 | 1876 | xlog_recover_do_reg_buffer( |
1877 | + xfs_mount_t *mp, | |
1877 | 1878 | xlog_recover_item_t *item, |
1878 | 1879 | xfs_buf_t *bp, |
1879 | 1880 | xfs_buf_log_format_t *buf_f) |
1880 | 1881 | |
... | ... | @@ -1884,7 +1885,51 @@ |
1884 | 1885 | unsigned int *data_map = NULL; |
1885 | 1886 | unsigned int map_size = 0; |
1886 | 1887 | int error; |
1888 | + int stale_buf = 1; | |
1887 | 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 | + } | |
1932 | + | |
1888 | 1933 | switch (buf_f->blf_type) { |
1889 | 1934 | case XFS_LI_BUF: |
1890 | 1935 | data_map = buf_f->blf_data_map; |
... | ... | @@ -1917,7 +1962,7 @@ |
1917 | 1962 | -1, 0, XFS_QMOPT_DOWARN, |
1918 | 1963 | "dquot_buf_recover"); |
1919 | 1964 | } |
1920 | - if (!error) | |
1965 | + if (!error && stale_buf) | |
1921 | 1966 | memcpy(xfs_buf_offset(bp, |
1922 | 1967 | (uint)bit << XFS_BLI_SHIFT), /* dest */ |
1923 | 1968 | item->ri_buf[i].i_addr, /* source */ |
... | ... | @@ -2089,7 +2134,7 @@ |
2089 | 2134 | if (log->l_quotaoffs_flag & type) |
2090 | 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 @@ |
2190 | 2235 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { |
2191 | 2236 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); |
2192 | 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 | 2240 | if (error) |
2196 | 2241 | return XFS_ERROR(error); |