Commit 4e9779ba authored by Stephen Lord's avatar Stephen Lord

Merge kernel.bkbits.net:/home/repos/linux-2.5

into kernel.bkbits.net:/home/lord/xfs-2.5
parents 3b822c88 9417522a
...@@ -803,7 +803,7 @@ page_state_convert( ...@@ -803,7 +803,7 @@ page_state_convert(
bh = bh->b_this_page; bh = bh->b_this_page;
} while (offset < end_offset); } while (offset < end_offset);
if (uptodate) if (uptodate && bh == head)
SetPageUptodate(page); SetPageUptodate(page);
if (startio) if (startio)
......
...@@ -262,7 +262,11 @@ linvfs_readdir( ...@@ -262,7 +262,11 @@ linvfs_readdir(
uio.uio_iov = &iov; uio.uio_iov = &iov;
uio.uio_fmode = filp->f_mode; uio.uio_fmode = filp->f_mode;
uio.uio_segflg = UIO_SYSSPACE; uio.uio_segflg = UIO_SYSSPACE;
curr_offset = uio.uio_offset = filp->f_pos; curr_offset = filp->f_pos;
if (filp->f_pos != 0x7fffffff)
uio.uio_offset = filp->f_pos;
else
uio.uio_offset = 0xffffffff;
while (!eof) { while (!eof) {
uio.uio_resid = iov.iov_len = rlen; uio.uio_resid = iov.iov_len = rlen;
...@@ -283,13 +287,13 @@ linvfs_readdir( ...@@ -283,13 +287,13 @@ linvfs_readdir(
namelen = strlen(dbp->d_name); namelen = strlen(dbp->d_name);
if (filldir(dirent, dbp->d_name, namelen, if (filldir(dirent, dbp->d_name, namelen,
(loff_t) curr_offset, (loff_t) curr_offset & 0x7fffffff,
(ino_t) dbp->d_ino, (ino_t) dbp->d_ino,
DT_UNKNOWN)) { DT_UNKNOWN)) {
goto done; goto done;
} }
size -= dbp->d_reclen; size -= dbp->d_reclen;
curr_offset = (loff_t)dbp->d_off & 0x7fffffff; curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
dbp = nextdp(dbp); dbp = nextdp(dbp);
} }
} }
......
...@@ -506,6 +506,24 @@ linvfs_write_super( ...@@ -506,6 +506,24 @@ linvfs_write_super(
sb->s_dirt = 0; sb->s_dirt = 0;
} }
STATIC int
linvfs_sync_super(
struct super_block *sb,
int wait)
{
vfs_t *vfsp = LINVFS_GET_VFS(sb);
int error;
int flags = SYNC_FSDATA;
if (wait)
flags |= SYNC_WAIT;
VFS_SYNC(vfsp, flags, NULL, error);
sb->s_dirt = 0;
return -error;
}
STATIC int STATIC int
linvfs_statfs( linvfs_statfs(
struct super_block *sb, struct super_block *sb,
...@@ -798,6 +816,7 @@ STATIC struct super_operations linvfs_sops = { ...@@ -798,6 +816,7 @@ STATIC struct super_operations linvfs_sops = {
.clear_inode = linvfs_clear_inode, .clear_inode = linvfs_clear_inode,
.put_super = linvfs_put_super, .put_super = linvfs_put_super,
.write_super = linvfs_write_super, .write_super = linvfs_write_super,
.sync_fs = linvfs_sync_super,
.write_super_lockfs = linvfs_freeze_fs, .write_super_lockfs = linvfs_freeze_fs,
.unlockfs = linvfs_unfreeze_fs, .unlockfs = linvfs_unfreeze_fs,
.statfs = linvfs_statfs, .statfs = linvfs_statfs,
......
...@@ -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;
......
...@@ -64,7 +64,7 @@ struct xfs_trans; ...@@ -64,7 +64,7 @@ struct xfs_trans;
* Offset in data space of a data entry. * Offset in data space of a data entry.
*/ */
typedef __uint32_t xfs_dir2_dataptr_t; typedef __uint32_t xfs_dir2_dataptr_t;
#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0x7fffffff) #define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff)
#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0) #define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0)
/* /*
......
...@@ -560,14 +560,7 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp, ...@@ -560,14 +560,7 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
*/ */
if (sbp->seqno == 0 || sbp == sbuf) if (sbp->seqno == 0 || sbp == sbuf)
lastresid = uio->uio_resid; lastresid = uio->uio_resid;
/* XFS_PUT_COOKIE(p.cook, mp, 0, sbp[1].seqno, sbp[1].hash);
* NOTE! Linux "filldir" semantics require that the
* offset "cookie" be for this entry, not the
* next; all the actual shuffling to make it
* "look right" to the user is done in filldir.
*/
XFS_PUT_COOKIE(p.cook, mp, 0, sbp->seqno, sbp->hash);
#if XFS_BIG_FILESYSTEMS #if XFS_BIG_FILESYSTEMS
p.ino = sbp->ino + mp->m_inoadd; p.ino = sbp->ino + mp->m_inoadd;
#else #else
...@@ -575,9 +568,7 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp, ...@@ -575,9 +568,7 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
#endif #endif
p.name = sbp->name; p.name = sbp->name;
p.namelen = sbp->namelen; p.namelen = sbp->namelen;
retval = p.put(&p); retval = p.put(&p);
if (!p.done) { if (!p.done) {
uio->uio_offset = uio->uio_offset =
XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash); XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash);
...@@ -586,20 +577,12 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp, ...@@ -586,20 +577,12 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
xfs_dir_trace_g_du("sf: E-O-B", dp, uio); xfs_dir_trace_g_du("sf: E-O-B", dp, uio);
return retval; return retval;
} }
sbp++; sbp++;
} }
kmem_free(sbuf, sbsize); kmem_free(sbuf, sbsize);
XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH);
uio->uio_offset = p.cook.o; uio->uio_offset = p.cook.o;
*eofp = 1; *eofp = 1;
xfs_dir_trace_g_du("sf: E-O-F", dp, uio); xfs_dir_trace_g_du("sf: E-O-F", dp, uio);
return 0; return 0;
} }
...@@ -2070,16 +2053,6 @@ xfs_dir_leaf_getdents_int( ...@@ -2070,16 +2053,6 @@ xfs_dir_leaf_getdents_int(
return XFS_ERROR(EFSCORRUPTED); return XFS_ERROR(EFSCORRUPTED);
} }
thishash = INT_GET(entry->hashval, ARCH_CONVERT);
/*
* NOTE! Linux "filldir" semantics require that the
* offset "cookie" be for this entry, not the
* next; all the actual shuffling to make it
* "look right" to the user is done in filldir.
*/
XFS_PUT_COOKIE(p.cook, mp, bno, entno, thishash);
xfs_dir_trace_g_duc("leaf: middle cookie ", xfs_dir_trace_g_duc("leaf: middle cookie ",
dp, uio, p.cook.o); dp, uio, p.cook.o);
...@@ -2090,17 +2063,19 @@ xfs_dir_leaf_getdents_int( ...@@ -2090,17 +2063,19 @@ xfs_dir_leaf_getdents_int(
nextentno = entno + 1; nextentno = entno + 1;
else else
nextentno = 0; nextentno = 0;
XFS_PUT_COOKIE(p.cook, mp, bno, nextentno, nexthash);
xfs_dir_trace_g_duc("leaf: middle cookie ",
dp, uio, p.cook.o);
} else if (INT_GET(leaf->hdr.info.forw, ARCH_CONVERT)) { } else if ((thishash = INT_GET(leaf->hdr.info.forw,
ARCH_CONVERT))) {
xfs_dabuf_t *bp2; xfs_dabuf_t *bp2;
xfs_dir_leafblock_t *leaf2; xfs_dir_leafblock_t *leaf2;
ASSERT(nextda != -1); ASSERT(nextda != -1);
retval = xfs_da_read_buf(dp->i_transp, dp, retval = xfs_da_read_buf(dp->i_transp, dp, thishash,
INT_GET(leaf->hdr.info.forw, nextda, &bp2, XFS_DATA_FORK);
ARCH_CONVERT), nextda,
&bp2, XFS_DATA_FORK);
if (retval) if (retval)
return(retval); return(retval);
...@@ -2124,13 +2099,13 @@ xfs_dir_leaf_getdents_int( ...@@ -2124,13 +2099,13 @@ xfs_dir_leaf_getdents_int(
nexthash = INT_GET(leaf2->entries[0].hashval, nexthash = INT_GET(leaf2->entries[0].hashval,
ARCH_CONVERT); ARCH_CONVERT);
nextentno = -1; nextentno = -1;
XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash);
xfs_da_brelse(dp->i_transp, bp2); xfs_da_brelse(dp->i_transp, bp2);
xfs_dir_trace_g_duc("leaf: next blk cookie", xfs_dir_trace_g_duc("leaf: next blk cookie",
dp, uio, p.cook.o); dp, uio, p.cook.o);
} else { } else {
nextentno = -1; nextentno = -1;
nexthash = XFS_DA_MAXHASH; XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH);
} }
/* /*
...@@ -2147,7 +2122,8 @@ xfs_dir_leaf_getdents_int( ...@@ -2147,7 +2122,8 @@ xfs_dir_leaf_getdents_int(
* provided is big enough to handle it (see pv763517). * provided is big enough to handle it (see pv763517).
*/ */
#if (BITS_PER_LONG == 32) #if (BITS_PER_LONG == 32)
if (INT_GET(entry->hashval, ARCH_CONVERT) != lasthash) { if ((thishash = INT_GET(entry->hashval, ARCH_CONVERT))
!= lasthash) {
XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
lastresid = uio->uio_resid; lastresid = uio->uio_resid;
lasthash = thishash; lasthash = thishash;
...@@ -2156,6 +2132,7 @@ xfs_dir_leaf_getdents_int( ...@@ -2156,6 +2132,7 @@ xfs_dir_leaf_getdents_int(
dp, uio, p.cook.o); dp, uio, p.cook.o);
} }
#else #else
thishash = INT_GET(entry->hashval, ARCH_CONVERT);
XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
lastresid = uio->uio_resid; lastresid = uio->uio_resid;
#endif /* BITS_PER_LONG == 32 */ #endif /* BITS_PER_LONG == 32 */
...@@ -2187,8 +2164,6 @@ xfs_dir_leaf_getdents_int( ...@@ -2187,8 +2164,6 @@ xfs_dir_leaf_getdents_int(
} }
} }
XFS_PUT_COOKIE(p.cook, mp, 0, 0, nexthash);
uio->uio_offset = p.cook.o; uio->uio_offset = p.cook.o;
*eobp = 0; *eobp = 0;
......
...@@ -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)) {
......
...@@ -1506,7 +1506,7 @@ xfs_syncsub( ...@@ -1506,7 +1506,7 @@ xfs_syncsub(
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
error = xfs_trans_commit(tp, 0, NULL); error = xfs_trans_commit(tp, 0, NULL);
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE); xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
} }
/* /*
......
...@@ -3730,9 +3730,7 @@ xfs_inode_flush( ...@@ -3730,9 +3730,7 @@ xfs_inode_flush(
int flags) int flags)
{ {
xfs_inode_t *ip; xfs_inode_t *ip;
xfs_dinode_t *dip;
xfs_mount_t *mp; xfs_mount_t *mp;
xfs_buf_t *bp;
int error = 0; int error = 0;
ip = XFS_BHVTOI(bdp); ip = XFS_BHVTOI(bdp);
...@@ -3778,44 +3776,30 @@ xfs_inode_flush( ...@@ -3778,44 +3776,30 @@ xfs_inode_flush(
* now, they get caught later by xfs_sync. * now, they get caught later by xfs_sync.
*/ */
if (flags & FLUSH_INODE) { if (flags & FLUSH_INODE) {
if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
if ((xfs_ipincount(ip) == 0) && xfs_iflock_nowait(ip)) {
int flush_flags; int flush_flags;
#if 0 if (xfs_ipincount(ip))
/* not turning this on until some
* performance analysis is done
*/
if (flags & FLUSH_SYNC)
flush_flags = XFS_IFLUSH_SYNC;
else
#endif
flush_flags = XFS_IFLUSH_DELWRI_ELSE_ASYNC;
xfs_ifunlock(ip);
xfs_iunlock(ip, XFS_ILOCK_SHARED);
error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0);
if (error)
return error;
xfs_buf_relse(bp);
if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED) == 0)
return EAGAIN; return EAGAIN;
if (xfs_ipincount(ip) || if (flags & FLUSH_SYNC) {
!xfs_iflock_nowait(ip)) { xfs_ilock(ip, XFS_ILOCK_SHARED);
xfs_iflock(ip);
} else if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) {
xfs_iunlock(ip, XFS_ILOCK_SHARED); xfs_iunlock(ip, XFS_ILOCK_SHARED);
return EAGAIN; return EAGAIN;
} }
error = xfs_iflush(ip, flush_flags);
} else { } else {
error = EAGAIN; return EAGAIN;
} }
if (flags & FLUSH_SYNC)
flush_flags = XFS_IFLUSH_SYNC;
else
flush_flags = XFS_IFLUSH_ASYNC;
error = xfs_iflush(ip, flush_flags);
xfs_iunlock(ip, XFS_ILOCK_SHARED); xfs_iunlock(ip, XFS_ILOCK_SHARED);
} else {
error = EAGAIN;
}
} }
return error; return error;
......
...@@ -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