Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Sep 2010 19:59:08 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r212930 - in stable/7/sys: nfs4client nfsclient
Message-ID:  <201009201959.o8KJx8aI065841@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Mon Sep 20 19:59:08 2010
New Revision: 212930
URL: http://svn.freebsd.org/changeset/base/212930

Log:
  MFC 212293:
  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.
  
  To preserve the ABI of 'struct nfsnode', the existing timestamp fields
  are left with 'n_unusedX' placeholders along with the unused 'n_expiry'
  field.  The larger n_ctime and n_dmtime fields are added to the end of
  the structure.

Modified:
  stable/7/sys/nfs4client/nfs4_vnops.c
  stable/7/sys/nfsclient/nfs_vnops.c
  stable/7/sys/nfsclient/nfsnode.h
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/nfs4client/nfs4_vnops.c
==============================================================================
--- stable/7/sys/nfs4client/nfs4_vnops.c	Mon Sep 20 19:58:50 2010	(r212929)
+++ stable/7/sys/nfs4client/nfs4_vnops.c	Mon Sep 20 19:59:08 2010	(r212930)
@@ -965,8 +965,8 @@ nfs4_lookup(struct vop_lookup_args *ap)
 		struct vattr vattr;
 
 		newvp = *vpp;
-		if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td)
-		 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
+		if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td) == 0 &&
+		    timespeccmp(&vattr.va_ctime, &VTONFS(newvp)->n_ctime, ==)) {
 		     nfsstats.lookupcache_hits++;
 		     if (cnp->cn_nameiop != LOOKUP &&
 			 (flags & ISLASTCN))
@@ -1081,7 +1081,7 @@ nfs4_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;

Modified: stable/7/sys/nfsclient/nfs_vnops.c
==============================================================================
--- stable/7/sys/nfsclient/nfs_vnops.c	Mon Sep 20 19:58:50 2010	(r212929)
+++ stable/7/sys/nfsclient/nfs_vnops.c	Mon Sep 20 19:59:08 2010	(r212930)
@@ -861,7 +861,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 	struct vnode *dvp = ap->a_dvp;
 	struct vnode **vpp = ap->a_vpp;
 	struct vattr vattr;
-	time_t dmtime;
+	struct timespec dmtime;
 	int flags = cnp->cn_flags;
 	struct vnode *newvp;
 	struct nfsmount *nmp;
@@ -914,7 +914,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 			mtx_unlock(&newnp->n_mtx);
 		}
 		if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td) == 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))
@@ -938,13 +938,13 @@ nfs_lookup(struct vop_lookup_args *ap)
 		 */
 		if ((u_int)(ticks - np->n_dmtime_ticks) < (negnametimeo * hz) &&
 		    VOP_GETATTR(dvp, &vattr, cnp->cn_cred, td) == 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);
 	}
 
@@ -959,7 +959,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++;
@@ -1046,7 +1046,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;
@@ -1092,8 +1092,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;
 				}
@@ -2550,8 +2550,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: stable/7/sys/nfsclient/nfsnode.h
==============================================================================
--- stable/7/sys/nfsclient/nfsnode.h	Mon Sep 20 19:58:50 2010	(r212929)
+++ stable/7/sys/nfsclient/nfsnode.h	Mon Sep 20 19:59:08 2010	(r212930)
@@ -104,10 +104,10 @@ struct nfsnode {
 	uid_t			n_modeuid;	/* credentials having mode */
 	time_t			n_modestamp;	/* mode cache timestamp */
 	struct timespec		n_mtime;	/* Prev modify time. */
-	time_t			n_ctime;	/* Prev create time. */
-	time_t			n_dmtime;	/* Prev dir modify time. */
+	time_t			n_unused0;
+	time_t			n_unused1;
 	int			n_dmtime_ticks;	/* Tick of -ve cache entry */
-	time_t			n_expiry;	/* Lease expiry time */
+	time_t			n_unused2;
 	nfsfh_t			*n_fhp;		/* NFS File Handle */
 	struct vnode		*n_vnode;	/* associated vnode */
 	struct vnode		*n_dvp;		/* parent vnode */
@@ -135,6 +135,8 @@ struct nfsnode {
 	int			n_directio_opens;
 	int                     n_directio_asyncwr;
 	struct nfs_attrcache_timestamp n_unused;
+	struct timespec		n_ctime;	/* Prev create time. */
+	struct timespec		n_dmtime;	/* Prev dir modify time. */
 };
 
 #define n_atim		n_un1.nf_atim



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009201959.o8KJx8aI065841>