diff options
-rw-r--r-- | fs/xfs/xfs_buf_item.h | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 51 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_buf.c | 1 |
3 files changed, 54 insertions, 3 deletions
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index d7e136143066..fa25b7dcc6c3 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h | |||
@@ -52,6 +52,11 @@ typedef struct xfs_buf_log_format_t { | |||
52 | #define XFS_BLI_UDQUOT_BUF 0x4 | 52 | #define XFS_BLI_UDQUOT_BUF 0x4 |
53 | #define XFS_BLI_PDQUOT_BUF 0x8 | 53 | #define XFS_BLI_PDQUOT_BUF 0x8 |
54 | #define XFS_BLI_GDQUOT_BUF 0x10 | 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 | #define XFS_BLI_CHUNK 128 | 61 | #define XFS_BLI_CHUNK 128 |
57 | #define XFS_BLI_SHIFT 7 | 62 | #define XFS_BLI_SHIFT 7 |
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); |
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 60b6b898022b..95fff6872a2f 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -966,6 +966,7 @@ xfs_trans_inode_alloc_buf( | |||
966 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 966 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
967 | 967 | ||
968 | bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; | 968 | bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; |
969 | bip->bli_format.blf_flags |= XFS_BLI_INODE_NEW_BUF; | ||
969 | } | 970 | } |
970 | 971 | ||
971 | 972 | ||