Commit b394e43e authored by Lachlan McIlroy's avatar Lachlan McIlroy Committed by Tim Shimmin

[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: default avatarLachlan McIlroy <lachlan@sgi.com>
Signed-off-by: default avatarDavid Chinner <dgc@sgi.com>
Signed-off-by: default avatarTim Shimmin <tes@sgi.com>
parent 776a75fa
...@@ -52,6 +52,11 @@ typedef struct xfs_buf_log_format_t { ...@@ -52,6 +52,11 @@ typedef struct xfs_buf_log_format_t {
#define XFS_BLI_UDQUOT_BUF 0x4 #define XFS_BLI_UDQUOT_BUF 0x4
#define XFS_BLI_PDQUOT_BUF 0x8 #define XFS_BLI_PDQUOT_BUF 0x8
#define XFS_BLI_GDQUOT_BUF 0x10 #define XFS_BLI_GDQUOT_BUF 0x10
/*
* This flag indicates that the buffer contains newly allocated
* inodes.
*/
#define XFS_BLI_INODE_NEW_BUF 0x20
#define XFS_BLI_CHUNK 128 #define XFS_BLI_CHUNK 128
#define XFS_BLI_SHIFT 7 #define XFS_BLI_SHIFT 7
......
...@@ -1874,6 +1874,7 @@ xlog_recover_do_inode_buffer( ...@@ -1874,6 +1874,7 @@ xlog_recover_do_inode_buffer(
/*ARGSUSED*/ /*ARGSUSED*/
STATIC void STATIC void
xlog_recover_do_reg_buffer( xlog_recover_do_reg_buffer(
xfs_mount_t *mp,
xlog_recover_item_t *item, xlog_recover_item_t *item,
xfs_buf_t *bp, xfs_buf_t *bp,
xfs_buf_log_format_t *buf_f) xfs_buf_log_format_t *buf_f)
...@@ -1884,6 +1885,50 @@ xlog_recover_do_reg_buffer( ...@@ -1884,6 +1885,50 @@ xlog_recover_do_reg_buffer(
unsigned int *data_map = NULL; unsigned int *data_map = NULL;
unsigned int map_size = 0; unsigned int map_size = 0;
int error; int error;
int stale_buf = 1;
/*
* Scan through the on-disk inode buffer and attempt to
* determine if it has been written to since it was logged.
*
* - If any of the magic numbers are incorrect then the buffer is stale
* - If any of the modes are non-zero then the buffer is not stale
* - If all of the modes are zero and at least one of the generation
* counts is non-zero then the buffer is stale
*
* If the end result is a stale buffer then the log buffer is replayed
* otherwise it is skipped.
*
* This heuristic is not perfect. It can be improved by scanning the
* entire inode chunk for evidence that any of the inode clusters have
* been updated. To fix this problem completely we will need a major
* architectural change to the logging system.
*/
if (buf_f->blf_flags & XFS_BLI_INODE_NEW_BUF) {
xfs_dinode_t *dip;
int inodes_per_buf;
int mode_count = 0;
int gen_count = 0;
stale_buf = 0;
inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog;
for (i = 0; i < inodes_per_buf; i++) {
dip = (xfs_dinode_t *)xfs_buf_offset(bp,
i * mp->m_sb.sb_inodesize);
if (be16_to_cpu(dip->di_core.di_magic) !=
XFS_DINODE_MAGIC) {
stale_buf = 1;
break;
}
if (be16_to_cpu(dip->di_core.di_mode))
mode_count++;
if (be16_to_cpu(dip->di_core.di_gen))
gen_count++;
}
if (!mode_count && gen_count)
stale_buf = 1;
}
switch (buf_f->blf_type) { switch (buf_f->blf_type) {
case XFS_LI_BUF: case XFS_LI_BUF:
...@@ -1917,7 +1962,7 @@ xlog_recover_do_reg_buffer( ...@@ -1917,7 +1962,7 @@ xlog_recover_do_reg_buffer(
-1, 0, XFS_QMOPT_DOWARN, -1, 0, XFS_QMOPT_DOWARN,
"dquot_buf_recover"); "dquot_buf_recover");
} }
if (!error) if (!error && stale_buf)
memcpy(xfs_buf_offset(bp, memcpy(xfs_buf_offset(bp,
(uint)bit << XFS_BLI_SHIFT), /* dest */ (uint)bit << XFS_BLI_SHIFT), /* dest */
item->ri_buf[i].i_addr, /* source */ item->ri_buf[i].i_addr, /* source */
...@@ -2089,7 +2134,7 @@ xlog_recover_do_dquot_buffer( ...@@ -2089,7 +2134,7 @@ xlog_recover_do_dquot_buffer(
if (log->l_quotaoffs_flag & type) if (log->l_quotaoffs_flag & type)
return; return;
xlog_recover_do_reg_buffer(item, bp, buf_f); xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
} }
/* /*
...@@ -2190,7 +2235,7 @@ xlog_recover_do_buffer_trans( ...@@ -2190,7 +2235,7 @@ xlog_recover_do_buffer_trans(
(XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
} else { } else {
xlog_recover_do_reg_buffer(item, bp, buf_f); xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
} }
if (error) if (error)
return XFS_ERROR(error); return XFS_ERROR(error);
......
...@@ -966,6 +966,7 @@ xfs_trans_inode_alloc_buf( ...@@ -966,6 +966,7 @@ xfs_trans_inode_alloc_buf(
ASSERT(atomic_read(&bip->bli_refcount) > 0); ASSERT(atomic_read(&bip->bli_refcount) > 0);
bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;
bip->bli_format.blf_flags |= XFS_BLI_INODE_NEW_BUF;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment