Commit 3f25b9a3 authored by Stephen Lord's avatar Stephen Lord

[XFS] Add versioning to the on disk inode which we increment on each

flush call. This is used during recovery to avoid replaying an
older copy of the inode from the log. We can do this without
versioning the filesystem as the pad space we borrowed was
always zero and will be ignored by old kernels.

SGI Modid: 2.5.x-xfs:slinx:155189a
parent 254d4828
...@@ -72,7 +72,8 @@ typedef struct xfs_dinode_core ...@@ -72,7 +72,8 @@ typedef struct xfs_dinode_core
__uint32_t di_gid; /* owner's group id */ __uint32_t di_gid; /* owner's group id */
__uint32_t di_nlink; /* number of links to file */ __uint32_t di_nlink; /* number of links to file */
__uint16_t di_projid; /* owner's project id */ __uint16_t di_projid; /* owner's project id */
__uint8_t di_pad[10]; /* unused, zeroed space */ __uint8_t di_pad[8]; /* unused, zeroed space */
__uint16_t di_flushiter; /* incremented on flush */
xfs_timestamp_t di_atime; /* time last accessed */ xfs_timestamp_t di_atime; /* time last accessed */
xfs_timestamp_t di_mtime; /* time last modified */ xfs_timestamp_t di_mtime; /* time last modified */
xfs_timestamp_t di_ctime; /* time created/inode modified */ xfs_timestamp_t di_ctime; /* time created/inode modified */
...@@ -89,6 +90,8 @@ typedef struct xfs_dinode_core ...@@ -89,6 +90,8 @@ typedef struct xfs_dinode_core
__uint32_t di_gen; /* generation number */ __uint32_t di_gen; /* generation number */
} xfs_dinode_core_t; } xfs_dinode_core_t;
#define DI_MAX_FLUSH 0xffff
typedef struct xfs_dinode typedef struct xfs_dinode
{ {
xfs_dinode_core_t di_core; xfs_dinode_core_t di_core;
......
...@@ -825,6 +825,8 @@ xfs_xlate_dinode_core( ...@@ -825,6 +825,8 @@ xfs_xlate_dinode_core(
sizeof(buf_core->di_pad)); sizeof(buf_core->di_pad));
} }
INT_XLATE(buf_core->di_flushiter, mem_core->di_flushiter, dir, arch);
INT_XLATE(buf_core->di_atime.t_sec, mem_core->di_atime.t_sec, INT_XLATE(buf_core->di_atime.t_sec, mem_core->di_atime.t_sec,
dir, arch); dir, arch);
INT_XLATE(buf_core->di_atime.t_nsec, mem_core->di_atime.t_nsec, INT_XLATE(buf_core->di_atime.t_nsec, mem_core->di_atime.t_nsec,
...@@ -956,6 +958,7 @@ xfs_iread( ...@@ -956,6 +958,7 @@ xfs_iread(
ip->i_d.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT); ip->i_d.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
ip->i_d.di_version = INT_GET(dip->di_core.di_version, ARCH_CONVERT); ip->i_d.di_version = INT_GET(dip->di_core.di_version, ARCH_CONVERT);
ip->i_d.di_gen = INT_GET(dip->di_core.di_gen, ARCH_CONVERT); ip->i_d.di_gen = INT_GET(dip->di_core.di_gen, ARCH_CONVERT);
ip->i_d.di_flushiter = INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT);
/* /*
* Make sure to pull in the mode here as well in * Make sure to pull in the mode here as well in
* case the inode is released without being used. * case the inode is released without being used.
...@@ -3232,6 +3235,13 @@ xfs_iflush_int( ...@@ -3232,6 +3235,13 @@ xfs_iflush_int(
ip->i_ino, ip->i_d.di_forkoff, ip); ip->i_ino, ip->i_d.di_forkoff, ip);
goto corrupt_out; goto corrupt_out;
} }
/*
* bump the flush iteration count, used to detect flushes which
* postdate a log record during recovery.
*/
ip->i_d.di_flushiter++;
/* /*
* Copy the dirty parts of the inode into the on-disk * Copy the dirty parts of the inode into the on-disk
* inode. We always copy out the core of the inode, * inode. We always copy out the core of the inode,
...@@ -3241,6 +3251,10 @@ xfs_iflush_int( ...@@ -3241,6 +3251,10 @@ xfs_iflush_int(
xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d), xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d),
-1, ARCH_CONVERT); -1, ARCH_CONVERT);
/* Wrap, we never let the log put out DI_MAX_FLUSH */
if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
ip->i_d.di_flushiter = 0;
/* /*
* If this is really an old format inode and the superblock version * If this is really an old format inode and the superblock version
* has not been updated to support only new format inodes, then * has not been updated to support only new format inodes, then
......
...@@ -2326,6 +2326,26 @@ xlog_recover_do_inode_trans( ...@@ -2326,6 +2326,26 @@ xlog_recover_do_inode_trans(
XFS_ERRLEVEL_LOW, mp); XFS_ERRLEVEL_LOW, mp);
return XFS_ERROR(EFSCORRUPTED); return XFS_ERROR(EFSCORRUPTED);
} }
/* Skip replay when the on disk inode is newer than the log one */
if (dicp->di_flushiter <
INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)) {
/*
* Deal with the wrap case, DI_MAX_FLUSH is less
* than smaller numbers
*/
if ((INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)
== DI_MAX_FLUSH) &&
(dicp->di_flushiter < (DI_MAX_FLUSH>>1))) {
/* do nothing */
} else {
xfs_buf_relse(bp);
return 0;
}
}
/* Take the opportunity to reset the flush iteration count */
dicp->di_flushiter = 0;
if (unlikely((dicp->di_mode & IFMT) == IFREG)) { if (unlikely((dicp->di_mode & IFMT) == IFREG)) {
if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
(dicp->di_format != XFS_DINODE_FMT_BTREE)) { (dicp->di_format != XFS_DINODE_FMT_BTREE)) {
......
...@@ -3033,11 +3033,12 @@ xfs_prdinode_core(xfs_dinode_core_t *dip, int convert) ...@@ -3033,11 +3033,12 @@ xfs_prdinode_core(xfs_dinode_core_t *dip, int convert)
INT_GET(dip->di_format, convert), INT_GET(dip->di_format, convert),
xfs_fmtformat( xfs_fmtformat(
(xfs_dinode_fmt_t)INT_GET(dip->di_format, convert))); (xfs_dinode_fmt_t)INT_GET(dip->di_format, convert)));
kdb_printf("nlink 0x%x uid 0x%x gid 0x%x projid 0x%x\n", kdb_printf("nlink %d uid %d gid %d projid %d flushiter %u\n",
INT_GET(dip->di_nlink, convert), INT_GET(dip->di_nlink, convert),
INT_GET(dip->di_uid, convert), INT_GET(dip->di_uid, convert),
INT_GET(dip->di_gid, convert), INT_GET(dip->di_gid, convert),
(uint)INT_GET(dip->di_projid, convert)); (uint)INT_GET(dip->di_projid, convert),
(uint)INT_GET(dip->di_flushiter, convert));
kdb_printf("atime 0x%x:%x mtime 0x%x:%x ctime 0x%x:%x\n", kdb_printf("atime 0x%x:%x mtime 0x%x:%x ctime 0x%x:%x\n",
INT_GET(dip->di_atime.t_sec, convert), INT_GET(dip->di_atime.t_sec, convert),
INT_GET(dip->di_atime.t_nsec, convert), INT_GET(dip->di_atime.t_nsec, convert),
......
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