Subject: Re: nfs between -current and netbsd-3
To: Rui Paulo <rpaulo@netbsd.org>
From: Chuck Silvers <chuq@chuq.com>
List: tech-net
Date: 09/12/2005 06:47:46
--EVF5PPMfhYS0aIcm
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

hi,

this is because netbsd's file systems do not always change a file's mtime
when that file's contents are modified.  the mtime is updated using the
global variable "time" rather via than some more precise mechanism like
microtime().  if a file is modified twice in the same clock tick, the
second update to the file's mtime will be set it to the same value as
the first, so NFS clients cannot use the mtime to reliably detect that
a file's contents have changed.

as part of the NFS cache coherency improvements that yamt and I did earlier
this year, he added some code to our NFS client to detect this deficiency
in an NFS server and work around the problem, and the message is just saying
that the problem has been detected and the work-around activated.

I had intended to change netbsd's file systems to use microtime() instead
of "time" for updating file mtimes, but I got busy and didn't get back to it.
looking at it again yesterday, I realized that it's not as complicated as
I thought it was.  the attached patch is sort of the right idea, except that
it would be good to avoid calling microtime() if we aren't going to use
the result (ie. if none of the timestamp-update flags is set).

-Chuck


On Sun, Sep 11, 2005 at 07:36:46PM +0100, Rui Paulo wrote:
> Hi,
> I'm getting some nfs debug messages on my desktop when talking to a
> NetBSD 3.0_BETA nfs server. My desktop -current (some days late).
> 
> % dmesg | grep wcc                                                          [~]
> quanta:/srv/nfs: inaccurate wcc data (mtime) detected, disabling wcc
> quanta:/srv/nfs: inaccurate wcc data (mtime) detected, disabling wcc
> 
> The time skew between the NFS server and my desktop is ~30s.
> 
> I have no idea why this is happening and the comments on nfs_subs.c
> say:
> 	/*
> 	 * despite of the fact that we've updated the file,
> 	 * timestamps of the file were not updated as we
> 	 * expected.
> 	 * it means that the server has incompatible
> 	 * semantics of timestamps or (more likely)
> 	 * the server time is not precise enough to
> 	 * track each modifications.
> 	 * in that case, we disable wcc processing.
> 	 * ...
> 	 */
> 
> So what could be happening here ? My desktop is faster than my NFS
> server is it because of that ? How can the timestamps be incompatible
> between two not-very-distant NetBSD versions (assuming that's the
> problem) ? How can the server be "not precise enough" ?
> 
> Thanks,
> 		-- Rui Paulo



--EVF5PPMfhYS0aIcm
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.fsts"

Index: src/sys/fs/msdosfs/msdosfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_vnops.c,v
retrieving revision 1.19
diff -u -p -r1.19 msdosfs_vnops.c
--- src/sys/fs/msdosfs/msdosfs_vnops.c	10 Sep 2005 18:35:56 -0000	1.19
+++ src/sys/fs/msdosfs/msdosfs_vnops.c	12 Sep 2005 00:15:08 -0000
@@ -283,12 +283,15 @@ msdosfs_getattr(v)
 	struct vattr *vap = ap->a_vap;
 	mode_t mode;
 	struct timespec ts;
+	struct timeval tv;
 	u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry);
 	ino_t fileid;
 
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
+	microtime(&tv);
+	TIMEVAL_TO_TIMESPEC(&tv, &ts);
 	DETIMES(dep, &ts, &ts, &ts, pmp->pm_gmtoff);
 	vap->va_fsid = dep->de_dev;
+
 	/*
 	 * The following computation of the fileid must be the same as that
 	 * used in msdosfs_readdir() to compute d_fileno. If not, pwd
@@ -707,13 +710,15 @@ msdosfs_update(v)
 	struct buf *bp;
 	struct direntry *dirp;
 	struct denode *dep;
-	int error;
 	struct timespec ts;
+	struct timeval tv;
+	int error;
 
 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
 		return (0);
 	dep = VTODE(ap->a_vp);
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
+	microtime(&tv);
+	TIMEVAL_TO_TIMESPEC(&tv, &ts);
 	DETIMES(dep,
 	    ap->a_access ? ap->a_access : &ts,
 	    ap->a_modify ? ap->a_modify : &ts, &ts, dep->de_pmp->pm_gmtoff);
Index: src/sys/ufs/ext2fs/ext2fs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_inode.c,v
retrieving revision 1.47
diff -u -p -r1.47 ext2fs_inode.c
--- src/sys/ufs/ext2fs/ext2fs_inode.c	30 Aug 2005 22:01:12 -0000	1.47
+++ src/sys/ufs/ext2fs/ext2fs_inode.c	12 Sep 2005 00:15:08 -0000
@@ -207,13 +207,15 @@ ext2fs_update(void *v)
 	struct inode *ip;
 	int error;
 	struct timespec ts;
+	struct timeval tv;
 	caddr_t cp;
 	int flags;
 
 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
 		return (0);
 	ip = VTOI(ap->a_vp);
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
+	microtime(&tv);
+	TIMEVAL_TO_TIMESPEC(&tv, &ts);
 	EXT2FS_ITIMES(ip,
 	    ap->a_access ? ap->a_access : &ts,
 	    ap->a_modify ? ap->a_modify : &ts, &ts);
Index: src/sys/ufs/ffs/ffs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_inode.c,v
retrieving revision 1.72
diff -u -p -r1.72 ffs_inode.c
--- src/sys/ufs/ffs/ffs_inode.c	15 Jul 2005 05:01:16 -0000	1.72
+++ src/sys/ufs/ffs/ffs_inode.c	12 Sep 2005 00:15:09 -0000
@@ -88,13 +88,15 @@ ffs_update(void *v)
 	struct inode *ip;
 	int error;
 	struct timespec ts;
+	struct timeval tv;
 	caddr_t cp;
 	int waitfor, flags;
 
 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
 		return (0);
 	ip = VTOI(ap->a_vp);
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
+	microtime(&tv);
+	TIMEVAL_TO_TIMESPEC(&tv, &ts);
 	FFS_ITIMES(ip,
 	    ap->a_access ? ap->a_access : &ts,
 	    ap->a_modify ? ap->a_modify : &ts, &ts);
Index: src/sys/ufs/lfs/lfs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_inode.c,v
retrieving revision 1.96
diff -u -p -r1.96 lfs_inode.c
--- src/sys/ufs/lfs/lfs_inode.c	29 May 2005 21:25:24 -0000	1.96
+++ src/sys/ufs/lfs/lfs_inode.c	12 Sep 2005 00:15:09 -0000
@@ -139,6 +139,7 @@ lfs_update(void *v)
 	struct inode *ip;
 	struct vnode *vp = ap->a_vp;
 	struct timespec ts;
+	struct timeval tv;
 	struct lfs *fs = VFSTOUFS(vp->v_mount)->um_lfs;
 	int s;
 	int flags;
@@ -165,7 +166,8 @@ lfs_update(void *v)
 	}
 	simple_unlock(&vp->v_interlock);
 	splx(s);
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
+	microtime(&tv);
+	TIMEVAL_TO_TIMESPEC(&tv, &ts);
 	LFS_ITIMES(ip,
 		   ap->a_access ? ap->a_access : &ts,
 		   ap->a_modify ? ap->a_modify : &ts, &ts);
Index: src/sys/ufs/ufs/ufs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.132
diff -u -p -r1.132 ufs_vnops.c
--- src/sys/ufs/ufs/ufs_vnops.c	23 Aug 2005 12:27:47 -0000	1.132
+++ src/sys/ufs/ufs/ufs_vnops.c	12 Sep 2005 00:15:12 -0000
@@ -296,11 +296,13 @@ ufs_getattr(void *v)
 	struct inode	*ip;
 	struct vattr	*vap;
 	struct timespec	ts;
+	struct timeval	tv;
 
 	vp = ap->a_vp;
 	ip = VTOI(vp);
 	vap = ap->a_vap;
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
+	microtime(&tv);
+	TIMEVAL_TO_TIMESPEC(&tv, &ts);
 	ITIMES(ip, &ts, &ts, &ts);
 
 	/*

--EVF5PPMfhYS0aIcm--