Subject: Re: nfs between -current and netbsd-3
To: None <tech-net@netbsd.org>
From: Christos Zoulas <christos@astron.com>
List: tech-net
Date: 09/12/2005 15:29:21
In article <20050912134746.GA8322@spathi.chuq.com>,
Chuck Silvers  <chuq@chuq.com> wrote:
>-=-=-=-=-=-
>
>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

How about this?

Index: fs/msdosfs/denode.h
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/denode.h,v
retrieving revision 1.7
diff -u -u -r1.7 denode.h
--- fs/msdosfs/denode.h	29 Aug 2005 23:57:35 -0000	1.7
+++ fs/msdosfs/denode.h	12 Sep 2005 15:23:18 -0000
@@ -225,20 +225,8 @@
 #define	DETOV(de)	((de)->de_vnode)
 
 #define	DETIMES(dep, acc, mod, cre, gmtoff) \
-	if ((dep)->de_flag & (DE_UPDATE | DE_CREATE | DE_ACCESS)) { \
-		(dep)->de_flag |= DE_MODIFIED; \
-		if ((dep)->de_flag & DE_UPDATE) { \
-			unix2dostime((mod), gmtoff, &(dep)->de_MDate, &(dep)->de_MTime, NULL); \
-			(dep)->de_Attributes |= ATTR_ARCHIVE; \
-		} \
-		if (!((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95)) { \
-			if ((dep)->de_flag & DE_ACCESS) \
-				unix2dostime((acc), gmtoff, &(dep)->de_ADate, NULL, NULL); \
-			if ((dep)->de_flag & DE_CREATE) \
-				unix2dostime((cre), gmtoff, &(dep)->de_CDate, &(dep)->de_CTime, &(dep)->de_CHun); \
-		} \
-		(dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \
-	}
+	while ((dep)->de_flag & (DE_UPDATE | DE_CREATE | DE_ACCESS)) \
+		msdosfs_detimes(dep, acc, mod, cre, gmtoff)
 
 /*
  * This overlays the fid structure (see mount.h)
@@ -313,4 +301,6 @@
 int findwin95(struct denode *);
 int msdosfs_gop_alloc(struct vnode *, off_t, off_t, int, struct ucred *);
 void msdosfs_gop_markupdate(struct vnode *, int);
+void msdosfs_detimes(struct denode *, const struct timespec *,
+    const struct timespec *, const struct timespec *, int);
 #endif	/* _KERNEL */
Index: fs/msdosfs/direntry.h
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/direntry.h,v
retrieving revision 1.3
diff -u -u -r1.3 direntry.h
--- fs/msdosfs/direntry.h	29 Aug 2005 23:57:35 -0000	1.3
+++ fs/msdosfs/direntry.h	12 Sep 2005 15:23:18 -0000
@@ -119,7 +119,7 @@
 #define DD_YEAR_SHIFT		9
 
 #ifdef _KERNEL
-void	unix2dostime(struct timespec *tsp, int gmtoff, u_int16_t *ddp,
+void	unix2dostime(const struct timespec *tsp, int gmtoff, u_int16_t *ddp,
 	    u_int16_t *dtp, u_int8_t *dhp);
 void	dos2unixtime(u_int dd, u_int dt, u_int dh, int gmtoff,
 	    struct timespec *tsp);
Index: fs/msdosfs/msdosfs_conv.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_conv.c,v
retrieving revision 1.3
diff -u -u -r1.3 msdosfs_conv.c
--- fs/msdosfs/msdosfs_conv.c	26 Feb 2005 22:58:55 -0000	1.3
+++ fs/msdosfs/msdosfs_conv.c	12 Sep 2005 15:23:18 -0000
@@ -97,7 +97,7 @@
  */
 void
 unix2dostime(tsp, gmtoff, ddp, dtp, dhp)
-	struct timespec *tsp;
+	const struct timespec *tsp;
 	int gmtoff;
 	u_int16_t *ddp;
 	u_int16_t *dtp;
Index: fs/msdosfs/msdosfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_vnops.c,v
retrieving revision 1.19
diff -u -u -r1.19 msdosfs_vnops.c
--- fs/msdosfs/msdosfs_vnops.c	10 Sep 2005 18:35:56 -0000	1.19
+++ fs/msdosfs/msdosfs_vnops.c	12 Sep 2005 15:23:18 -0000
@@ -116,7 +116,6 @@
 	struct denode *dep;
 	struct denode *pdep = VTODE(ap->a_dvp);
 	int error;
-	struct timespec ts;
 
 #ifdef MSDOSFS_DEBUG
 	printf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap);
@@ -155,8 +154,7 @@
 	ndirent.de_devvp = pdep->de_devvp;
 	ndirent.de_pmp = pdep->de_pmp;
 	ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE;
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
-	DETIMES(&ndirent, &ts, &ts, &ts, pdep->de_pmp->pm_gmtoff);
+	DETIMES(&ndirent, NULL, NULL, NULL, pdep->de_pmp->pm_gmtoff);
 	if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0)
 		goto bad;
 	if ((cnp->cn_flags & SAVESTART) == 0)
@@ -216,12 +214,10 @@
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 	struct denode *dep = VTODE(vp);
-	struct timespec ts;
 
 	simple_lock(&vp->v_interlock);
 	if (vp->v_usecount > 1) {
-		TIMEVAL_TO_TIMESPEC(&time, &ts);
-		DETIMES(dep, &ts, &ts, &ts, dep->de_pmp->pm_gmtoff);
+		DETIMES(dep, NULL, NULL, NULL, dep->de_pmp->pm_gmtoff);
 	}
 	simple_unlock(&vp->v_interlock);
 	return (0);
@@ -282,12 +278,10 @@
 	struct msdosfsmount *pmp = dep->de_pmp;
 	struct vattr *vap = ap->a_vap;
 	mode_t mode;
-	struct timespec ts;
 	u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry);
 	ino_t fileid;
 
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
-	DETIMES(dep, &ts, &ts, &ts, pmp->pm_gmtoff);
+	DETIMES(dep, NULL, NULL, NULL, pmp->pm_gmtoff);
 	vap->va_fsid = dep->de_dev;
 	/*
 	 * The following computation of the fileid must be the same as that
@@ -708,15 +702,11 @@
 	struct direntry *dirp;
 	struct denode *dep;
 	int error;
-	struct timespec ts;
 
 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
 		return (0);
 	dep = VTODE(ap->a_vp);
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
-	DETIMES(dep,
-	    ap->a_access ? ap->a_access : &ts,
-	    ap->a_modify ? ap->a_modify : &ts, &ts, dep->de_pmp->pm_gmtoff);
+	DETIMES(dep, ap->a_access, ap->a_modify, NULL, dep->de_pmp->pm_gmtoff);
 	if ((dep->de_flag & DE_MODIFIED) == 0)
 		return (0);
 	dep->de_flag &= ~DE_MODIFIED;
@@ -1216,7 +1206,6 @@
 	struct direntry *denp;
 	struct msdosfsmount *pmp = pdep->de_pmp;
 	struct buf *bp;
-	struct timespec ts;
 	int async = pdep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC;
 
 	/*
@@ -1240,8 +1229,7 @@
 	memset(&ndirent, 0, sizeof(ndirent));
 	ndirent.de_pmp = pmp;
 	ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE;
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
-	DETIMES(&ndirent, &ts, &ts, &ts, pmp->pm_gmtoff);
+	DETIMES(&ndirent, NULL, NULL, NULL, pmp->pm_gmtoff);
 
 	/*
 	 * Now fill the cluster with the "." and ".." entries. And write
@@ -1852,6 +1840,37 @@
 	/* NOTREACHED */
 }
 
+void
+msdosfs_detimes(struct denode *dep, const struct timespec *acc,
+    const struct timespec *mod, const struct timespec *cre, int gmtoff)
+{
+	struct timespec *ts = NULL, tsb;
+
+	KASSERT(dep->de_flag & (DE_UPDATE | DE_CREATE | DE_ACCESS));
+	dep->de_flag |= DE_MODIFIED;
+	if (dep->de_flag & DE_UPDATE) {
+		if (mod == NULL)
+			mod = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+		unix2dostime(mod, gmtoff, &dep->de_MDate, &dep->de_MTime, NULL);
+		dep->de_Attributes |= ATTR_ARCHIVE;
+	}
+	if ((dep->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0) {
+		if (dep->de_flag & DE_ACCESS)  {
+			if (acc == NULL)
+				acc = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+			unix2dostime(acc, gmtoff, &dep->de_ADate, NULL, NULL);
+		}
+		if (dep->de_flag & DE_CREATE) {
+			if (cre == NULL)
+				cre = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+			unix2dostime(cre, gmtoff, &dep->de_CDate,
+			    &dep->de_CTime, &dep->de_CHun);
+		}
+	}
+
+	dep->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS);
+}
+
 /* Global vfs data structures for msdosfs */
 int (**msdosfs_vnodeop_p)(void *);
 const struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = {
Index: ufs/ext2fs/ext2fs_extern.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_extern.h,v
retrieving revision 1.26
diff -u -u -r1.26 ext2fs_extern.h
--- ufs/ext2fs/ext2fs_extern.h	30 Aug 2005 22:01:12 -0000	1.26
+++ ufs/ext2fs/ext2fs_extern.h	12 Sep 2005 15:23:18 -0000
@@ -129,6 +129,8 @@
 /* ext2fs_subr.c */
 int ext2fs_blkatoff(void *);
 void ext2fs_fragacct(struct m_ext2fs *, int, int32_t[], int);
+void ext2fs_itimes(struct inode *, const struct timespec *,
+    const struct timespec *, const struct timespec *);
 #ifdef DIAGNOSTIC
 void	ext2fs_checkoverlap(struct buf *, struct inode *);
 #endif
Index: ufs/ext2fs/ext2fs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_inode.c,v
retrieving revision 1.47
diff -u -u -r1.47 ext2fs_inode.c
--- ufs/ext2fs/ext2fs_inode.c	30 Aug 2005 22:01:12 -0000	1.47
+++ ufs/ext2fs/ext2fs_inode.c	12 Sep 2005 15:23:18 -0000
@@ -206,17 +206,13 @@
 	struct buf *bp;
 	struct inode *ip;
 	int error;
-	struct timespec ts;
 	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);
-	EXT2FS_ITIMES(ip,
-	    ap->a_access ? ap->a_access : &ts,
-	    ap->a_modify ? ap->a_modify : &ts, &ts);
+	EXT2FS_ITIMES(ip, ap->a_access, ap->a_modify, NULL);
 	if (ap->a_flags & UPDATE_CLOSE)
 		flags = ip->i_flag & (IN_MODIFIED | IN_ACCESSED);
 	else
Index: ufs/ext2fs/ext2fs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_subr.c,v
retrieving revision 1.14
diff -u -u -r1.14 ext2fs_subr.c
--- ufs/ext2fs/ext2fs_subr.c	30 Aug 2005 22:01:12 -0000	1.14
+++ ufs/ext2fs/ext2fs_subr.c	12 Sep 2005 15:23:18 -0000
@@ -111,6 +111,35 @@
 	return (0);
 }
 
+void
+ext2fs_itimes(struct inode *ip, const struct timespec *acc,
+    const struct timespec *mod, const struct timespec *cre)
+{
+	struct timespec *ts = NULL, tsb;
+
+	if (ip->i_flag & IN_ACCESS) {
+		if (acc == NULL)
+			acc = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+		ip->i_e2fs_atime = acc->tv_sec;
+	}
+	if (ip->i_flag & (IN_UPDATE | IN_MODIFY)) {
+		if (mod == NULL)
+			mod = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+		ip->i_e2fs_mtime = mod->tv_sec;
+		ip->i_modrev++;
+	}
+	if (ip->i_flag & (IN_CHANGE | IN_MODIFY)) {
+		if (cre == NULL)
+			cre = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+		ip->i_e2fs_ctime = cre->tv_sec;
+	}
+	if (ip->i_flag & (IN_ACCESS | IN_MODIFY))
+		ip->i_flag |= IN_ACCESSED;
+	if (ip->i_flag & (IN_UPDATE | IN_CHANGE))
+		ip->i_flag |= IN_MODIFIED;
+	ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY);
+}
+
 #ifdef DIAGNOSTIC
 void
 ext2fs_checkoverlap(struct buf *bp, struct inode *ip)
Index: ufs/ext2fs/ext2fs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vnops.c,v
retrieving revision 1.61
diff -u -u -r1.61 ext2fs_vnops.c
--- ufs/ext2fs/ext2fs_vnops.c	30 Aug 2005 22:01:12 -0000	1.61
+++ ufs/ext2fs/ext2fs_vnops.c	12 Sep 2005 15:23:18 -0000
@@ -276,10 +276,8 @@
 	struct vnode *vp = ap->a_vp;
 	struct inode *ip = VTOI(vp);
 	struct vattr *vap = ap->a_vap;
-	struct timespec ts;
 
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
-	EXT2FS_ITIMES(ip, &ts, &ts, &ts);
+	EXT2FS_ITIMES(ip, NULL, NULL, NULL);
 	/*
 	 * Copy from inode table
 	 */
Index: ufs/ffs/ffs_extern.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_extern.h,v
retrieving revision 1.45
diff -u -u -r1.45 ffs_extern.h
--- ufs/ffs/ffs_extern.h	9 Sep 2005 15:00:39 -0000	1.45
+++ ufs/ffs/ffs_extern.h	12 Sep 2005 15:23:18 -0000
@@ -99,7 +99,9 @@
 void	ffs_sb_swap(struct fs*, struct fs *);
 void	ffs_dinode1_swap(struct ufs1_dinode *, struct ufs1_dinode *);
 void	ffs_dinode2_swap(struct ufs2_dinode *, struct ufs2_dinode *);
+struct csum;
 void	ffs_csum_swap(struct csum *, struct csum *, int);
+struct csum_total;
 void	ffs_csumtotal_swap(struct csum_total *, struct csum_total *);
 void	ffs_cg_swap(struct cg *, struct cg *, struct fs *);
 
@@ -119,6 +121,8 @@
 int	ffs_isfreeblock(struct fs *, u_char *, int32_t);
 void	ffs_clrblock(struct fs *, u_char *, int32_t);
 void	ffs_setblock(struct fs *, u_char *, int32_t);
+void	ffs_itimes(struct inode *, const struct timespec *,
+    const struct timespec *, const struct timespec *);
 
 /* ffs_vfsops.c */
 void	ffs_init(void);
@@ -142,6 +146,7 @@
 int	ffs_cgupdate(struct ufsmount *, int);
 
 /* ffs_appleufs.c */
+struct appleufslabel;
 u_int16_t ffs_appleufs_cksum(const struct appleufslabel *);
 int	ffs_appleufs_validate(const char*, const struct appleufslabel *,
 			      struct appleufslabel *);
Index: ufs/ffs/ffs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_inode.c,v
retrieving revision 1.72
diff -u -u -r1.72 ffs_inode.c
--- ufs/ffs/ffs_inode.c	15 Jul 2005 05:01:16 -0000	1.72
+++ ufs/ffs/ffs_inode.c	12 Sep 2005 15:23:18 -0000
@@ -87,17 +87,13 @@
 	struct buf *bp;
 	struct inode *ip;
 	int error;
-	struct timespec ts;
 	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);
-	FFS_ITIMES(ip,
-	    ap->a_access ? ap->a_access : &ts,
-	    ap->a_modify ? ap->a_modify : &ts, &ts);
+	FFS_ITIMES(ip, ap->a_access, ap->a_modify, NULL);
 	if (ap->a_flags & UPDATE_CLOSE)
 		flags = ip->i_flag & (IN_MODIFIED | IN_ACCESSED);
 	else
Index: ufs/ffs/ffs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_subr.c,v
retrieving revision 1.35
diff -u -u -r1.35 ffs_subr.c
--- ufs/ffs/ffs_subr.c	30 Aug 2005 22:01:12 -0000	1.35
+++ ufs/ffs/ffs_subr.c	12 Sep 2005 15:23:18 -0000
@@ -326,3 +326,36 @@
 		    (int)fs->fs_fragshift);
 	}
 }
+
+void
+ffs_itimes(struct inode *ip, const struct timespec *acc,
+    const struct timespec *mod, const struct timespec *cre)
+{
+	struct timespec *ts = NULL, tsb;
+	if (ip->i_flag & IN_ACCESS) {
+		if (acc == NULL)
+			acc = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+		DIP_ASSIGN(ip, atime, acc->tv_sec);
+		DIP_ASSIGN(ip, atimensec, acc->tv_nsec);
+	}
+	if (ip->i_flag & (IN_UPDATE | IN_MODIFY)) {
+		if ((ip->i_flags & SF_SNAPSHOT) == 0) {
+			if (mod == NULL)
+				mod = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+			DIP_ASSIGN(ip, mtime, mod->tv_sec);
+			DIP_ASSIGN(ip, mtimensec, mod->tv_nsec);
+		}
+		ip->i_modrev++;
+	}
+	if (ip->i_flag & (IN_CHANGE | IN_MODIFY)) {
+		if (cre == NULL)
+			cre = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+		DIP_ASSIGN(ip, ctime, cre->tv_sec);
+		DIP_ASSIGN(ip, ctimensec, cre->tv_nsec);
+	}
+	if (ip->i_flag & (IN_ACCESS | IN_MODIFY))
+		ip->i_flag |= IN_ACCESSED;
+	if (ip->i_flag & (IN_UPDATE | IN_CHANGE))
+		ip->i_flag |= IN_MODIFIED;
+	ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY);
+}
Index: ufs/lfs/lfs.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs.h,v
retrieving revision 1.92
diff -u -u -r1.92 lfs.h
--- ufs/lfs/lfs.h	23 Aug 2005 08:05:13 -0000	1.92
+++ ufs/lfs/lfs.h	12 Sep 2005 15:23:18 -0000
@@ -325,44 +325,9 @@
 	simple_unlock(&(ip)->i_lfs->lfs_interlock);			\
 } while (0)
 
-#define LFS_ITIMES(ip, acc, mod, cre)  do {				\
-	struct lfs *_fs = (ip)->i_lfs;					\
-									\
-	if ((ip)->i_flag & IN_ACCESS) {					\
-		(ip)->i_ffs1_atime = (acc)->tv_sec;			\
-		(ip)->i_ffs1_atimensec = (acc)->tv_nsec;		\
-		if ((ip)->i_lfs->lfs_version > 1) {			\
-			struct buf *_ibp;				\
-			IFILE *_ifp;					\
-									\
-			LFS_IENTRY(_ifp, ip->i_lfs, ip->i_number, _ibp); \
-			_ifp->if_atime_sec = (acc)->tv_sec;		\
-			_ifp->if_atime_nsec = (acc)->tv_nsec;		\
-			LFS_BWRITE_LOG(_ibp);				\
-			simple_lock(&_fs->lfs_interlock);		\
-			_fs->lfs_flags |= LFS_IFDIRTY;			\
-			simple_unlock(&_fs->lfs_interlock);		\
-		} else {						\
-			LFS_SET_UINO(ip, IN_ACCESSED);			\
-		}							\
-	}								\
-	if ((ip)->i_flag & (IN_CHANGE | IN_UPDATE | IN_MODIFY)) {	\
-		if ((ip)->i_flag & (IN_UPDATE | IN_MODIFY)) {		\
-			(ip)->i_ffs1_mtime = (mod)->tv_sec;		\
-			(ip)->i_ffs1_mtimensec = (mod)->tv_nsec;	\
-			(ip)->i_modrev++;				\
-		}							\
-		if ((ip)->i_flag & (IN_CHANGE | IN_MODIFY)) {		\
-			(ip)->i_ffs1_ctime = (cre)->tv_sec;		\
-			(ip)->i_ffs1_ctimensec = (cre)->tv_nsec;	\
-		}							\
-		if ((ip)->i_flag & (IN_CHANGE | IN_UPDATE))		\
-			LFS_SET_UINO(ip, IN_MODIFIED);			\
-		if ((ip)->i_flag & IN_MODIFY)				\
-			LFS_SET_UINO(ip, IN_ACCESSED);			\
-	}								\
-	(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY);\
-} while (0)
+#define LFS_ITIMES(ip, acc, mod, cre) \
+	while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
+		lfs_itimes(ip, acc, mod, cre)
 
 /*
  * "struct vnode" associated definitions
Index: ufs/lfs/lfs_extern.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_extern.h,v
retrieving revision 1.69
diff -u -u -r1.69 lfs_extern.h
--- ufs/lfs/lfs_extern.h	28 Jun 2005 09:30:38 -0000	1.69
+++ ufs/lfs/lfs_extern.h	12 Sep 2005 15:23:18 -0000
@@ -236,8 +236,8 @@
 /* lfs_vnops.c */
 void lfs_mark_vnode(struct vnode *);
 void lfs_unmark_vnode(struct vnode *);
-void lfs_itimes(struct inode *, struct timespec *, struct timespec *,
-		struct timespec *);
+void lfs_itimes(struct inode *, const struct timespec *,
+    const struct timespec *, const struct timespec *);
 int lfs_gop_alloc(struct vnode *, off_t, off_t, int, struct ucred *);
 void lfs_gop_size(struct vnode *, off_t, off_t *, int);
 int lfs_putpages_ext(void *, int);
Index: ufs/lfs/lfs_inode.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_inode.c,v
retrieving revision 1.96
diff -u -u -r1.96 lfs_inode.c
--- ufs/lfs/lfs_inode.c	29 May 2005 21:25:24 -0000	1.96
+++ ufs/lfs/lfs_inode.c	12 Sep 2005 15:23:18 -0000
@@ -138,7 +138,6 @@
 				  } */ *ap = v;
 	struct inode *ip;
 	struct vnode *vp = ap->a_vp;
-	struct timespec ts;
 	struct lfs *fs = VFSTOUFS(vp->v_mount)->um_lfs;
 	int s;
 	int flags;
@@ -165,10 +164,7 @@
 	}
 	simple_unlock(&vp->v_interlock);
 	splx(s);
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
-	LFS_ITIMES(ip,
-		   ap->a_access ? ap->a_access : &ts,
-		   ap->a_modify ? ap->a_modify : &ts, &ts);
+	LFS_ITIMES(ip, ap->a_access, ap->a_modify, NULL);
 	if (ap->a_flags & UPDATE_CLOSE)
 		flags = ip->i_flag & (IN_MODIFIED | IN_ACCESSED | IN_CLEANING);
 	else
Index: ufs/lfs/lfs_segment.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_segment.c,v
retrieving revision 1.165
diff -u -u -r1.165 lfs_segment.c
--- ufs/lfs/lfs_segment.c	19 Aug 2005 02:04:09 -0000	1.165
+++ ufs/lfs/lfs_segment.c	12 Sep 2005 15:23:18 -0000
@@ -833,7 +833,6 @@
 	ino_t ino;
 	int error, i, ndx, fsb = 0;
 	int redo_ifile = 0;
-	struct timespec ts;
 	int gotblk = 0;
 
 	ASSERT_SEGLOCK(fs);
@@ -872,10 +871,9 @@
 	}
 
 	/* Update the inode times and copy the inode onto the inode page. */
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
 	/* XXX kludge --- don't redirty the ifile just to put times on it */
 	if (ip->i_number != LFS_IFILE_INUM)
-		LFS_ITIMES(ip, &ts, &ts, &ts);
+		LFS_ITIMES(ip, NULL, NULL, NULL);
 
 	/*
 	 * If this is the Ifile, and we've already written the Ifile in this
Index: ufs/lfs/lfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_vnops.c,v
retrieving revision 1.153
diff -u -u -r1.153 lfs_vnops.c
--- ufs/lfs/lfs_vnops.c	19 Aug 2005 02:04:09 -0000	1.153
+++ ufs/lfs/lfs_vnops.c	12 Sep 2005 15:23:19 -0000
@@ -268,13 +268,55 @@
 
 static int check_dirty(struct lfs *, struct vnode *, off_t, off_t, off_t, int, int);
 
-/*
- * A function version of LFS_ITIMES, for the UFS functions which call ITIMES
- */
 void
-lfs_itimes(struct inode *ip, struct timespec *acc, struct timespec *mod, struct timespec *cre)
+lfs_itimes(struct inode *ip, const struct timespec *acc,
+    const struct timespec *mod, const struct timespec *cre)
 {
-	LFS_ITIMES(ip, acc, mod, cre);
+	struct timespec *ts = NULL, tsb;
+
+	KASSERT(ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY));
+
+	if (ip->i_flag & IN_ACCESS) {
+		if (acc == NULL)
+			acc = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+		ip->i_ffs1_atime = acc->tv_sec;
+		ip->i_ffs1_atimensec = acc->tv_nsec;
+		if (ip->i_lfs->lfs_version > 1) {
+			struct lfs *fs = ip->i_lfs;
+			struct buf *ibp;
+			IFILE *ifp;
+
+			LFS_IENTRY(ifp, ip->i_lfs, ip->i_number, ibp);
+			ifp->if_atime_sec = acc->tv_sec;
+			ifp->if_atime_nsec = acc->tv_nsec;
+			LFS_BWRITE_LOG(ibp);
+			simple_lock(&fs->lfs_interlock);
+			fs->lfs_flags |= LFS_IFDIRTY;
+			simple_unlock(&fs->lfs_interlock);
+		} else {
+			LFS_SET_UINO(ip, IN_ACCESSED);
+		}
+	}
+	if (ip->i_flag & (IN_CHANGE | IN_UPDATE | IN_MODIFY)) {
+		if (ip->i_flag & (IN_UPDATE | IN_MODIFY)) {
+			if (mod == NULL)
+				mod = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+			ip->i_ffs1_mtime = mod->tv_sec;
+			ip->i_ffs1_mtimensec = mod->tv_nsec;
+			ip->i_modrev++;
+		}
+		if (ip->i_flag & (IN_CHANGE | IN_MODIFY)) {
+			if (cre == NULL)
+				cre = ts == NULL ? (ts = nanotime(&tsb)) : ts;
+			ip->i_ffs1_ctime = cre->tv_sec;
+			ip->i_ffs1_ctimensec = cre->tv_nsec;
+		}
+		if (ip->i_flag & (IN_CHANGE | IN_UPDATE))
+			LFS_SET_UINO(ip, IN_MODIFIED);
+		if (ip->i_flag & IN_MODIFY)
+			LFS_SET_UINO(ip, IN_ACCESSED);
+	}
+	ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY);
 }
 
 #define	LFS_READWRITE
@@ -954,15 +996,13 @@
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 	struct inode *ip = VTOI(vp);
-	struct timespec ts;
 
 	if (vp == ip->i_lfs->lfs_ivnode &&
 	    vp->v_mount->mnt_iflag & IMNT_UNMOUNT)
 		return 0;
 
 	if (vp->v_usecount > 1 && vp != ip->i_lfs->lfs_ivnode) {
-		TIMEVAL_TO_TIMESPEC(&time, &ts);
-		LFS_ITIMES(ip, &ts, &ts, &ts);
+		LFS_ITIMES(ip, NULL, NULL, NULL);
 	}
 	return (0);
 }
@@ -983,13 +1023,11 @@
 	} */ *ap = v;
 	struct vnode	*vp;
 	struct inode	*ip;
-	struct timespec	ts;
 
 	vp = ap->a_vp;
 	ip = VTOI(vp);
 	if (vp->v_usecount > 1) {
-		TIMEVAL_TO_TIMESPEC(&time, &ts);
-		LFS_ITIMES(ip, &ts, &ts, &ts);
+		LFS_ITIMES(ip, NULL, NULL, NULL);
 	}
 	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
 }
@@ -1010,13 +1048,11 @@
 	} */ *ap = v;
 	struct vnode	*vp;
 	struct inode	*ip;
-	struct timespec	ts;
 
 	vp = ap->a_vp;
 	ip = VTOI(vp);
 	if (ap->a_vp->v_usecount > 1) {
-		TIMEVAL_TO_TIMESPEC(&time, &ts);
-		LFS_ITIMES(ip, &ts, &ts, &ts);
+		LFS_ITIMES(ip, NULL, NULL, NULL);
 	}
 	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
 }
Index: ufs/ufs/inode.h
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/inode.h,v
retrieving revision 1.42
diff -u -u -r1.42 inode.h
--- ufs/ufs/inode.h	19 Aug 2005 02:04:09 -0000	1.42
+++ ufs/ufs/inode.h	12 Sep 2005 15:23:19 -0000
@@ -266,57 +266,19 @@
 #define	VTOI(vp)	((struct inode *)(vp)->v_data)
 #define	ITOV(ip)	((ip)->i_vnode)
 
-#define	FFS_ITIMES(ip, acc, mod, cre) {					\
-	if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) {\
-		if ((ip)->i_flag & IN_ACCESS) {				\
-			DIP_ASSIGN(ip, atime, (acc)->tv_sec);		\
-			DIP_ASSIGN(ip, atimensec, (acc)->tv_nsec);	\
-		}							\
-		if ((ip)->i_flag & (IN_UPDATE | IN_MODIFY)) {		\
-			if (((ip)->i_flags & SF_SNAPSHOT) == 0) {	\
-				DIP_ASSIGN(ip, mtime, (mod)->tv_sec);	\
-				DIP_ASSIGN(ip, mtimensec, (mod)->tv_nsec); \
-			}						\
-			(ip)->i_modrev++;				\
-		}							\
-		if ((ip)->i_flag & (IN_CHANGE | IN_MODIFY)) {		\
-			DIP_ASSIGN(ip, ctime, (cre)->tv_sec);		\
-			DIP_ASSIGN(ip, ctimensec, (cre)->tv_nsec);	\
-		}							\
-		if ((ip)->i_flag & (IN_ACCESS | IN_MODIFY))		\
-			ip->i_flag |= IN_ACCESSED;			\
-		if ((ip)->i_flag & (IN_UPDATE | IN_CHANGE))		\
-			ip->i_flag |= IN_MODIFIED;			\
-		(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY);	\
-	}								\
-}
+#define	FFS_ITIMES(ip, acc, mod, cre) \
+	while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
+		ffs_itimes(ip, acc, mod, cre)
 
-#define	EXT2FS_ITIMES(ip, acc, mod, cre) {				\
-	if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) {\
-		if ((ip)->i_flag & IN_ACCESS) {				\
-			(ip)->i_e2fs_atime = (acc)->tv_sec;		\
-		}							\
-		if ((ip)->i_flag & (IN_UPDATE | IN_MODIFY)) {		\
-			(ip)->i_e2fs_mtime = (mod)->tv_sec;		\
-			(ip)->i_modrev++;				\
-		}							\
-		if ((ip)->i_flag & (IN_CHANGE | IN_MODIFY)) {		\
-			(ip)->i_e2fs_ctime = (cre)->tv_sec;		\
-		}							\
-		if ((ip)->i_flag & (IN_ACCESS | IN_MODIFY))		\
-			(ip)->i_flag |= IN_ACCESSED;			\
-		if ((ip)->i_flag & (IN_UPDATE | IN_CHANGE))		\
-			(ip)->i_flag |= IN_MODIFIED;			\
-		(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY);	\
-	}								\
-}
+#define	EXT2FS_ITIMES(ip, acc, mod, cre) \
+	while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
+		ext2fs_itimes(ip, acc, mod, cre)
 
-#define	ITIMES(ip, acc, mod, cre) {			\
-	if (IS_EXT2_VNODE((ip)->i_vnode))		\
-		EXT2FS_ITIMES(ip, acc, mod, cre)	\
-	else						\
-		FFS_ITIMES(ip, acc, mod, cre)		\
-}
+#define	ITIMES(ip, acc, mod, cre) \
+	while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
+		IS_EXT2_VNODE((ip)->i_vnode) ? \
+			ext2fs_itimes(ip, acc, mod, cre) : \
+			ffs_itimes(ip, acc, mod, cre)
 
 /* Determine if soft dependencies are being done */
 #define	DOINGSOFTDEP(vp)	((vp)->v_mount->mnt_flag & MNT_SOFTDEP)
Index: ufs/ufs/ufs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.132
diff -u -u -r1.132 ufs_vnops.c
--- ufs/ufs/ufs_vnops.c	23 Aug 2005 12:27:47 -0000	1.132
+++ ufs/ufs/ufs_vnops.c	12 Sep 2005 15:23:19 -0000
@@ -73,6 +73,7 @@
 #include <ufs/ufs/dirhash.h>
 #endif
 #include <ufs/ext2fs/ext2fs_extern.h>
+#include <ufs/ffs/ffs_extern.h>
 #include <ufs/lfs/lfs_extern.h>
 
 #include <uvm/uvm.h>
@@ -214,15 +215,12 @@
 	} */ *ap = v;
 	struct vnode	*vp;
 	struct inode	*ip;
-	struct timespec	ts;
 
 	vp = ap->a_vp;
 	ip = VTOI(vp);
 	simple_lock(&vp->v_interlock);
-	if (vp->v_usecount > 1) {
-		TIMEVAL_TO_TIMESPEC(&time, &ts);
-		ITIMES(ip, &ts, &ts, &ts);
-	}
+	if (vp->v_usecount > 1)
+		ITIMES(ip, NULL, NULL, NULL);
 	simple_unlock(&vp->v_interlock);
 	return (0);
 }
@@ -295,13 +293,11 @@
 	struct vnode	*vp;
 	struct inode	*ip;
 	struct vattr	*vap;
-	struct timespec	ts;
 
 	vp = ap->a_vp;
 	ip = VTOI(vp);
 	vap = ap->a_vap;
-	TIMEVAL_TO_TIMESPEC(&time, &ts);
-	ITIMES(ip, &ts, &ts, &ts);
+	ITIMES(ip, NULL, NULL, NULL);
 
 	/*
 	 * Copy from inode table
@@ -1836,15 +1832,12 @@
 	} */ *ap = v;
 	struct vnode	*vp;
 	struct inode	*ip;
-	struct timespec	ts;
 
 	vp = ap->a_vp;
 	ip = VTOI(vp);
 	simple_lock(&vp->v_interlock);
-	if (vp->v_usecount > 1) {
-		TIMEVAL_TO_TIMESPEC(&time, &ts);
-		ITIMES(ip, &ts, &ts, &ts);
-	}
+	if (vp->v_usecount > 1)
+		ITIMES(ip, NULL, NULL, NULL);
 	simple_unlock(&vp->v_interlock);
 	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
 }
@@ -1905,15 +1898,12 @@
 	} */ *ap = v;
 	struct vnode	*vp;
 	struct inode	*ip;
-	struct timespec	ts;
 
 	vp = ap->a_vp;
 	ip = VTOI(vp);
 	simple_lock(&vp->v_interlock);
-	if (ap->a_vp->v_usecount > 1) {
-		TIMEVAL_TO_TIMESPEC(&time, &ts);
-		ITIMES(ip, &ts, &ts, &ts);
-	}
+	if (ap->a_vp->v_usecount > 1)
+		ITIMES(ip, NULL, NULL, NULL);
 	simple_unlock(&vp->v_interlock);
 	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
 }
Index: kern/kern_clock.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_clock.c,v
retrieving revision 1.94
diff -u -u -r1.94 kern_clock.c
--- kern/kern_clock.c	2 Mar 2005 11:05:34 -0000	1.94
+++ kern/kern_clock.c	12 Sep 2005 15:23:19 -0000
@@ -1431,3 +1431,16 @@
 }
 #endif /* PPS_SYNC */
 #endif /* NTP  */
+
+/*
+ * XXX: Until all md code has it.
+ */
+struct timespec *
+nanotime(struct timespec *ts)
+{
+	struct timeval tv;
+
+	microtime(&tv);
+	TIMEVAL_TO_TIMESPEC(&tv, ts);
+	return ts;
+}
Index: sys/time.h
===================================================================
RCS file: /cvsroot/src/sys/sys/time.h,v
retrieving revision 1.49
diff -u -u -r1.49 time.h
--- sys/time.h	23 Jul 2005 19:43:01 -0000	1.49
+++ sys/time.h	12 Sep 2005 15:23:19 -0000
@@ -212,7 +212,8 @@
 int	itimerfix(struct timeval *tv);
 int	itimerdecr(struct ptimer *, int);
 void	itimerfire(struct ptimer *);
-void	microtime(struct timeval *tv);
+void	microtime(struct timeval *);
+struct timespec	*nanotime(struct timespec *);
 int	settime(struct timeval *);
 int	ratecheck(struct timeval *, const struct timeval *);
 int	ppsratecheck(struct timeval *, int *, int);