Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 May 2009 20:36:54 +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: r192156 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern nfsclient sys
Message-ID:  <200905152036.n4FKashg033833@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Fri May 15 20:36:54 2009
New Revision: 192156
URL: http://svn.freebsd.org/changeset/base/192156

Log:
  MFC: Add caching of -ve lookups to the NFS client.  To prevent clients from
  not noticing new files created by another client for a "long" time, reduce
  the default timeout for caching attributes of directories from 30 seconds
  to 3 seconds.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/kern/vfs_cache.c
  stable/7/sys/nfsclient/nfs.h
  stable/7/sys/nfsclient/nfs_vnops.c
  stable/7/sys/nfsclient/nfsnode.h
  stable/7/sys/sys/vnode.h

Modified: stable/7/sys/kern/vfs_cache.c
==============================================================================
--- stable/7/sys/kern/vfs_cache.c	Fri May 15 20:13:15 2009	(r192155)
+++ stable/7/sys/kern/vfs_cache.c	Fri May 15 20:36:54 2009	(r192156)
@@ -700,6 +700,24 @@ cache_purge(vp)
 }
 
 /*
+ * Invalidate all negative entries for a particular directory vnode.
+ */
+void
+cache_purge_negative(vp)
+	struct vnode *vp;
+{
+	struct namecache *cp, *ncp;
+
+	CTR1(KTR_VFS, "cache_purge_negative(%p)", vp);
+	CACHE_LOCK();
+	LIST_FOREACH_SAFE(cp, &vp->v_cache_src, nc_src, ncp) {
+		if (cp->nc_vp == NULL)
+			cache_zap(cp);
+	}
+	CACHE_UNLOCK();
+}
+
+/*
  * Flush all entries referencing a particular filesystem.
  */
 void

Modified: stable/7/sys/nfsclient/nfs.h
==============================================================================
--- stable/7/sys/nfsclient/nfs.h	Fri May 15 20:13:15 2009	(r192155)
+++ stable/7/sys/nfsclient/nfs.h	Fri May 15 20:36:54 2009	(r192156)
@@ -63,7 +63,7 @@
 #define	NFS_MAXATTRTIMO 60
 #endif
 #ifndef NFS_MINDIRATTRTIMO
-#define	NFS_MINDIRATTRTIMO 30		/* VDIR attrib cache timeout in sec */
+#define	NFS_MINDIRATTRTIMO 3		/* VDIR attrib cache timeout in sec */
 #endif
 #ifndef NFS_MAXDIRATTRTIMO
 #define	NFS_MAXDIRATTRTIMO 60

Modified: stable/7/sys/nfsclient/nfs_vnops.c
==============================================================================
--- stable/7/sys/nfsclient/nfs_vnops.c	Fri May 15 20:13:15 2009	(r192155)
+++ stable/7/sys/nfsclient/nfs_vnops.c	Fri May 15 20:36:54 2009	(r192156)
@@ -862,6 +862,7 @@ nfs_lookup(struct vop_lookup_args *ap)
 	struct componentname *cnp = ap->a_cnp;
 	struct vnode *dvp = ap->a_dvp;
 	struct vnode **vpp = ap->a_vpp;
+	struct vattr vattr;
 	int flags = cnp->cn_flags;
 	struct vnode *newvp;
 	struct nfsmount *nmp;
@@ -890,16 +891,20 @@ nfs_lookup(struct vop_lookup_args *ap)
 	if (error > 0 && error != ENOENT)
 		return (error);
 	if (error == -1) {
-		struct vattr vattr;
-
+		/*
+		 * We only accept a positive hit in the cache if the
+		 * change time of the file matches our cached copy.
+		 * Otherwise, we discard the cache entry and fallback
+		 * to doing a lookup RPC.
+		 */
 		newvp = *vpp;
 		if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td)
-		 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
-		     nfsstats.lookupcache_hits++;
-		     if (cnp->cn_nameiop != LOOKUP &&
-			 (flags & ISLASTCN))
-			     cnp->cn_flags |= SAVENAME;
-		     return (0);
+		    && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
+			nfsstats.lookupcache_hits++;
+			if (cnp->cn_nameiop != LOOKUP &&
+			    (flags & ISLASTCN))
+				cnp->cn_flags |= SAVENAME;
+			return (0);
 		}
 		cache_purge(newvp);
 		if (dvp != newvp)
@@ -907,6 +912,22 @@ nfs_lookup(struct vop_lookup_args *ap)
 		else 
 			vrele(newvp);
 		*vpp = NULLVP;
+	} else if (error == ENOENT) {
+		/*
+		 * We only accept a negative hit in the cache if the
+		 * modification time of the parent directory matches
+		 * our cached copy.  Otherwise, we discard all of the
+		 * negative cache entries for this directory.
+		 */
+		if (VOP_GETATTR(dvp, &vattr, cnp->cn_cred, td) == 0 &&
+		    vattr.va_mtime.tv_sec == np->n_dmtime) {
+			nfsstats.lookupcache_hits++;
+			return (ENOENT);
+		}
+		cache_purge_negative(dvp);
+		mtx_lock(&np->n_mtx);
+		np->n_dmtime = 0;
+		mtx_unlock(&np->n_mtx);
 	}
 	error = 0;
 	newvp = NULLVP;
@@ -992,16 +1013,40 @@ nfsmout:
 			vput(newvp);
 			*vpp = NULLVP;
 		}
+
+		if (error != ENOENT)
+			goto done;
+
+		/* The requested file was not found. */
 		if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
-		    (flags & ISLASTCN) && error == ENOENT) {
+		    (flags & ISLASTCN)) {
+			/*
+			 * XXX: UFS does a full VOP_ACCESS(dvp,
+			 * VWRITE) here instead of just checking
+			 * MNT_RDONLY.
+			 */
 			if (dvp->v_mount->mnt_flag & MNT_RDONLY)
-				error = EROFS;
-			else
-				error = EJUSTRETURN;
-		}
-		if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
+				return (EROFS);
 			cnp->cn_flags |= SAVENAME;
+			return (EJUSTRETURN);
+		}
+
+		if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
+			/*
+			 * Maintain n_dmtime as the modification time
+			 * of the parent directory when the oldest -ve
+			 * name cache entry for this directory was
+			 * added.
+			 */
+			mtx_lock(&np->n_mtx);
+			if (np->n_dmtime == 0)
+				np->n_dmtime = np->n_vattr.va_mtime.tv_sec;
+			mtx_unlock(&np->n_mtx);
+			cache_enter(dvp, NULL, cnp);
+		}
+		return (ENOENT);
 	}
+done:
 	return (error);
 }
 

Modified: stable/7/sys/nfsclient/nfsnode.h
==============================================================================
--- stable/7/sys/nfsclient/nfsnode.h	Fri May 15 20:13:15 2009	(r192155)
+++ stable/7/sys/nfsclient/nfsnode.h	Fri May 15 20:36:54 2009	(r192156)
@@ -109,6 +109,7 @@ struct nfsnode {
 	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_expiry;	/* Lease expiry time */
 	nfsfh_t			*n_fhp;		/* NFS File Handle */
 	struct vnode		*n_vnode;	/* associated vnode */

Modified: stable/7/sys/sys/vnode.h
==============================================================================
--- stable/7/sys/sys/vnode.h	Fri May 15 20:13:15 2009	(r192155)
+++ stable/7/sys/sys/vnode.h	Fri May 15 20:36:54 2009	(r192156)
@@ -564,6 +564,7 @@ void	cache_enter(struct vnode *dvp, stru
 int	cache_lookup(struct vnode *dvp, struct vnode **vpp,
 	    struct componentname *cnp);
 void	cache_purge(struct vnode *vp);
+void	cache_purge_negative(struct vnode *vp);
 void	cache_purgevfs(struct mount *mp);
 int	change_dir(struct vnode *vp, struct thread *td);
 int	change_root(struct vnode *vp, struct thread *td);



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