svn commit: r212293 - in head/sys: fs/nfsclient nfsclient

John Baldwin jhb at FreeBSD.org
Tue Sep 7 14:29:45 UTC 2010


Author: jhb
Date: Tue Sep  7 14:29:45 2010
New Revision: 212293
URL: http://svn.freebsd.org/changeset/base/212293

Log:
  Store the full timestamp when caching timestamps of files and
  directories for purposes of validating name cache entries.  This
  closes races where two updates to a file or directory within the same
  second could result in stale entries in the name cache.  While here,
  remove the 'n_expiry' field as it is no longer used.
  
  Reviewed by:	rmacklem
  MFC after:	1 week

Modified:
  head/sys/fs/nfsclient/nfs_clrpcops.c
  head/sys/fs/nfsclient/nfs_clvnops.c
  head/sys/fs/nfsclient/nfsnode.h
  head/sys/nfsclient/nfs_vnops.c
  head/sys/nfsclient/nfsnode.h

Modified: head/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clrpcops.c	Tue Sep  7 13:50:02 2010	(r212292)
+++ head/sys/fs/nfsclient/nfs_clrpcops.c	Tue Sep  7 14:29:45 2010	(r212293)
@@ -3293,8 +3293,7 @@ nfsrpc_readdirplus(vnode_t vp, struct ui
 				    ndp->ni_vp = newvp;
 				    NFSCNHASH(cnp, HASHINIT);
 				    if (cnp->cn_namelen <= NCHNAMLEN) {
-					np->n_ctime =
-					  np->n_vattr.na_ctime.tv_sec;
+					np->n_ctime = np->n_vattr.na_ctime;
 					cache_enter(ndp->ni_dvp,ndp->ni_vp,cnp);
 				    }
 				    if (unlocknewvp)

Modified: head/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clvnops.c	Tue Sep  7 13:50:02 2010	(r212292)
+++ head/sys/fs/nfsclient/nfs_clvnops.c	Tue Sep  7 14:29:45 2010	(r212293)
@@ -988,7 +988,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 	struct nfsfh *nfhp;
 	struct nfsvattr dnfsva, nfsva;
 	struct vattr vattr;
-	time_t dmtime;
+	struct timespec dmtime;
 	
 	*vpp = NULLVP;
 	if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) &&
@@ -1038,7 +1038,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 		}
 		if (nfscl_nodeleg(newvp, 0) == 0 ||
 		    (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
-		    vattr.va_ctime.tv_sec == newnp->n_ctime)) {
+		    timespeccmp(&vattr.va_ctime, &newnp->n_ctime, ==))) {
 			NFSINCRGLOBAL(newnfsstats.lookupcache_hits);
 			if (cnp->cn_nameiop != LOOKUP &&
 			    (flags & ISLASTCN))
@@ -1065,13 +1065,13 @@ nfs_lookup(struct vop_lookup_args *ap)
 		if ((u_int)(ticks - np->n_dmtime_ticks) <
 		    (nmp->nm_negnametimeo * hz) &&
 		    VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 &&
-		    vattr.va_mtime.tv_sec == np->n_dmtime) {
+		    timespeccmp(&vattr.va_mtime, &np->n_dmtime, ==)) {
 			NFSINCRGLOBAL(newnfsstats.lookupcache_hits);
 			return (ENOENT);
 		}
 		cache_purge_negative(dvp);
 		mtx_lock(&np->n_mtx);
-		np->n_dmtime = 0;
+		timespecclear(&np->n_dmtime);
 		mtx_unlock(&np->n_mtx);
 	}
 
@@ -1086,7 +1086,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 	 * the lookup RPC has been performed on the server but before
 	 * n_dmtime is set at the end of this function.
 	 */
-	dmtime = np->n_vattr.na_mtime.tv_sec;
+	dmtime = np->n_vattr.na_mtime;
 	error = 0;
 	newvp = NULLVP;
 	NFSINCRGLOBAL(newnfsstats.lookupcache_misses);
@@ -1139,8 +1139,8 @@ nfs_lookup(struct vop_lookup_args *ap)
 			 * lookup.
 			 */
 			mtx_lock(&np->n_mtx);
-			if (np->n_dmtime <= dmtime) {
-				if (np->n_dmtime == 0) {
+			if (timespeccmp(&np->n_dmtime, &dmtime, <=)) {
+				if (!timespecisset(&np->n_dmtime)) {
 					np->n_dmtime = dmtime;
 					np->n_dmtime_ticks = ticks;
 				}
@@ -1241,7 +1241,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 		cnp->cn_flags |= SAVENAME;
 	if ((cnp->cn_flags & MAKEENTRY) &&
 	    (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
-		np->n_ctime = np->n_vattr.na_vattr.va_ctime.tv_sec;
+		np->n_ctime = np->n_vattr.na_vattr.va_ctime;
 		cache_enter(dvp, newvp, cnp);
 	}
 	*vpp = newvp;

Modified: head/sys/fs/nfsclient/nfsnode.h
==============================================================================
--- head/sys/fs/nfsclient/nfsnode.h	Tue Sep  7 13:50:02 2010	(r212292)
+++ head/sys/fs/nfsclient/nfsnode.h	Tue Sep  7 14:29:45 2010	(r212293)
@@ -96,10 +96,9 @@ struct nfsnode {
 	time_t			n_attrstamp;	/* Attr. cache timestamp */
 	struct nfs_accesscache	n_accesscache[NFS_ACCESSCACHESIZE];
 	struct timespec		n_mtime;	/* Prev modify time. */
-	time_t			n_ctime;	/* Prev create time. */
-	time_t			n_dmtime;	/* Prev dir modify time. */
+	struct timespec		n_ctime;	/* Prev create time. */
+	struct timespec		n_dmtime;	/* Prev dir modify time. */
 	int			n_dmtime_ticks;	/* Tick of -ve cache entry */
-	time_t			n_expiry;	/* Lease expiry time */
 	struct nfsfh		*n_fhp;		/* NFS File Handle */
 	struct vnode		*n_vnode;	/* associated vnode */
 	struct vnode		*n_dvp;		/* parent vnode */

Modified: head/sys/nfsclient/nfs_vnops.c
==============================================================================
--- head/sys/nfsclient/nfs_vnops.c	Tue Sep  7 13:50:02 2010	(r212292)
+++ head/sys/nfsclient/nfs_vnops.c	Tue Sep  7 14:29:45 2010	(r212293)
@@ -916,7 +916,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 	struct vnode **vpp = ap->a_vpp;
 	struct mount *mp = dvp->v_mount;
 	struct vattr vattr;
-	time_t dmtime;
+	struct timespec dmtime;
 	int flags = cnp->cn_flags;
 	struct vnode *newvp;
 	struct nfsmount *nmp;
@@ -970,7 +970,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 			mtx_unlock(&newnp->n_mtx);
 		}
 		if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
-		    vattr.va_ctime.tv_sec == newnp->n_ctime) {
+		    timespeccmp(&vattr.va_ctime, &newnp->n_ctime, ==)) {
 			nfsstats.lookupcache_hits++;
 			if (cnp->cn_nameiop != LOOKUP &&
 			    (flags & ISLASTCN))
@@ -997,13 +997,13 @@ nfs_lookup(struct vop_lookup_args *ap)
 		if ((u_int)(ticks - np->n_dmtime_ticks) <
 		    (nmp->nm_negnametimeo * hz) &&
 		    VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 &&
-		    vattr.va_mtime.tv_sec == np->n_dmtime) {
+		    timespeccmp(&vattr.va_mtime, &np->n_dmtime, ==)) {
 			nfsstats.lookupcache_hits++;
 			return (ENOENT);
 		}
 		cache_purge_negative(dvp);
 		mtx_lock(&np->n_mtx);
-		np->n_dmtime = 0;
+		timespecclear(&np->n_dmtime);
 		mtx_unlock(&np->n_mtx);
 	}
 
@@ -1018,7 +1018,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 	 * the lookup RPC has been performed on the server but before
 	 * n_dmtime is set at the end of this function.
 	 */
-	dmtime = np->n_vattr.va_mtime.tv_sec;
+	dmtime = np->n_vattr.va_mtime;
 	error = 0;
 	newvp = NULLVP;
 	nfsstats.lookupcache_misses++;
@@ -1137,7 +1137,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 		cnp->cn_flags |= SAVENAME;
 	if ((cnp->cn_flags & MAKEENTRY) &&
 	    (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
-		np->n_ctime = np->n_vattr.va_ctime.tv_sec;
+		np->n_ctime = np->n_vattr.va_ctime;
 		cache_enter(dvp, newvp, cnp);
 	}
 	*vpp = newvp;
@@ -1183,8 +1183,8 @@ nfsmout:
 			 * lookup.
 			 */
 			mtx_lock(&np->n_mtx);
-			if (np->n_dmtime <= dmtime) {
-				if (np->n_dmtime == 0) {
+			if (timespeccmp(&np->n_dmtime, &dmtime, <=)) {
+				if (!timespecisset(&np->n_dmtime)) {
 					np->n_dmtime = dmtime;
 					np->n_dmtime_ticks = ticks;
 				}
@@ -2657,8 +2657,11 @@ nfs_readdirplusrpc(struct vnode *vp, str
 				dp->d_type =
 				    IFTODT(VTTOIF(np->n_vattr.va_type));
 				ndp->ni_vp = newvp;
-				/* Update n_ctime, so subsequent lookup doesn't purge entry */
-				np->n_ctime = np->n_vattr.va_ctime.tv_sec;
+				/*
+				 * Update n_ctime so subsequent lookup
+				 * doesn't purge entry.
+				 */
+				np->n_ctime = np->n_vattr.va_ctime;
 			        cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
 			    }
 			} else {

Modified: head/sys/nfsclient/nfsnode.h
==============================================================================
--- head/sys/nfsclient/nfsnode.h	Tue Sep  7 13:50:02 2010	(r212292)
+++ head/sys/nfsclient/nfsnode.h	Tue Sep  7 14:29:45 2010	(r212293)
@@ -102,10 +102,9 @@ struct nfsnode {
 	time_t			n_attrstamp;	/* Attr. cache timestamp */
 	struct nfs_accesscache	n_accesscache[NFS_ACCESSCACHESIZE];
 	struct timespec		n_mtime;	/* Prev modify time. */
-	time_t			n_ctime;	/* Prev create time. */
-	time_t			n_dmtime;	/* Prev dir modify time. */
+	struct timespec		n_ctime;	/* Prev create time. */
+	struct timespec		n_dmtime;	/* Prev dir modify time. */
 	int			n_dmtime_ticks;	/* Tick of -ve cache entry */
-	time_t			n_expiry;	/* Lease expiry time */
 	nfsfh_t			*n_fhp;		/* NFS File Handle */
 	struct vnode		*n_vnode;	/* associated vnode */
 	struct vnode		*n_dvp;		/* parent vnode */


More information about the svn-src-head mailing list