Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jan 2010 20:57:25 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r202767 - head/sys/nfsclient
Message-ID:  <201001212057.o0LKvPkD043256@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Thu Jan 21 20:57:25 2010
New Revision: 202767
URL: http://svn.freebsd.org/changeset/base/202767

Log:
  Add a timeout for the negative name cache entries in the NFS client.
  This avoids a bogus negative name cache entry from persisting forever
  when another client creates an entry with the same name within the
  same NFS server time of day clock tick. The mount option negnametimeo
  can be used to override the default timeout interval on a
  per-mount-point basis. Setting negnametimeo to 0 disables negative
  name caching for the mount point.
  I also fixed one obvious typo where args.timeo should be
  args.maxgrouplist.
  
  Submitted by:	jhb (earlier version)
  Reviewed by:	jhb
  MFC after:	2 weeks

Modified:
  head/sys/nfsclient/nfs_vfsops.c
  head/sys/nfsclient/nfs_vnops.c
  head/sys/nfsclient/nfsmount.h
  head/sys/nfsclient/nfsnode.h

Modified: head/sys/nfsclient/nfs_vfsops.c
==============================================================================
--- head/sys/nfsclient/nfs_vfsops.c	Thu Jan 21 20:56:18 2010	(r202766)
+++ head/sys/nfsclient/nfs_vfsops.c	Thu Jan 21 20:57:25 2010	(r202767)
@@ -114,7 +114,7 @@ static void	nfs_decode_args(struct mount
 		    struct nfs_args *argp, const char *hostname);
 static int	mountnfs(struct nfs_args *, struct mount *,
 		    struct sockaddr *, char *, struct vnode **,
-		    struct ucred *cred);
+		    struct ucred *cred, int);
 static vfs_mount_t nfs_mount;
 static vfs_cmount_t nfs_cmount;
 static vfs_unmount_t nfs_unmount;
@@ -551,7 +551,7 @@ nfs_mountdiskless(char *path,
 
 	nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
 	if ((error = mountnfs(args, mp, nam, path, vpp,
-	    td->td_ucred)) != 0) {
+	    td->td_ucred, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
 		printf("nfs_mountroot: mount %s on /: %d\n", path, error);
 		return (error);
 	}
@@ -778,7 +778,7 @@ static const char *nfs_opts[] = { "from"
     "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
     "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", 
     "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
-    "maxgroups", "principal",
+    "maxgroups", "principal", "negnametimeo",
     NULL };
 
 /*
@@ -827,6 +827,7 @@ nfs_mount(struct mount *mp)
 	size_t len;
 	u_char nfh[NFSX_V3FHMAX];
 	char *opt;
+	int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
 
 	has_nfs_args_opt = 0;
 	has_addr_opt = 0;
@@ -1029,7 +1030,7 @@ nfs_mount(struct mount *mp)
 	}
 	if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
 		ret = sscanf(opt, "%d", &args.maxgrouplist);
-		if (ret != 1 || args.timeo <= 0) {
+		if (ret != 1 || args.maxgrouplist <= 0) {
 			vfs_mount_error(mp, "illegal maxgroups: %s",
 			    opt);
 			error = EINVAL;
@@ -1037,6 +1038,16 @@ nfs_mount(struct mount *mp)
 		}
 		args.flags |= NFSMNT_MAXGRPS;
 	}
+	if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
+	    == 0) {
+		ret = sscanf(opt, "%d", &negnametimeo);
+		if (ret != 1 || negnametimeo < 0) {
+			vfs_mount_error(mp, "illegal negnametimeo: %s",
+			    opt);
+			error = EINVAL;
+			goto out;
+		}
+	}
 	if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
 		&args.addrlen) == 0) {
 		has_addr_opt = 1;
@@ -1125,7 +1136,7 @@ nfs_mount(struct mount *mp)
 		}
 	}
 	error = mountnfs(&args, mp, nam, args.hostname, &vp,
-	    curthread->td_ucred);
+	    curthread->td_ucred, negnametimeo);
 out:
 	if (!error) {
 		MNT_ILOCK(mp);
@@ -1167,7 +1178,7 @@ nfs_cmount(struct mntarg *ma, void *data
  */
 static int
 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
-    char *hst, struct vnode **vpp, struct ucred *cred)
+    char *hst, struct vnode **vpp, struct ucred *cred, int negnametimeo)
 {
 	struct nfsmount *nmp;
 	struct nfsnode *np;
@@ -1217,6 +1228,7 @@ mountnfs(struct nfs_args *argp, struct m
 	nmp->nm_numgrps = NFS_MAXGRPS;
 	nmp->nm_readahead = NFS_DEFRAHEAD;
 	nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
+	nmp->nm_negnametimeo = negnametimeo;
 	nmp->nm_tprintf_delay = nfs_tprintf_delay;
 	if (nmp->nm_tprintf_delay < 0)
 		nmp->nm_tprintf_delay = 0;

Modified: head/sys/nfsclient/nfs_vnops.c
==============================================================================
--- head/sys/nfsclient/nfs_vnops.c	Thu Jan 21 20:56:18 2010	(r202766)
+++ head/sys/nfsclient/nfs_vnops.c	Thu Jan 21 20:57:25 2010	(r202767)
@@ -982,8 +982,13 @@ nfs_lookup(struct vop_lookup_args *ap)
 		 * modification time of the parent directory matches
 		 * our cached copy.  Otherwise, we discard all of the
 		 * negative cache entries for this directory.
+		 * negative cache entries for this directory. We also
+		 * only trust -ve cache entries for less than
+		 * nm_negative_namecache_timeout seconds.
 		 */
-		if (VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 &&
+		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) {
 			nfsstats.lookupcache_hits++;
 			return (ENOENT);
@@ -1157,8 +1162,10 @@ nfsmout:
 			 */
 			mtx_lock(&np->n_mtx);
 			if (np->n_dmtime <= dmtime) {
-				if (np->n_dmtime == 0)
+				if (np->n_dmtime == 0) {
 					np->n_dmtime = dmtime;
+					np->n_dmtime_ticks = ticks;
+				}
 				mtx_unlock(&np->n_mtx);
 				cache_enter(dvp, NULL, cnp);
 			} else

Modified: head/sys/nfsclient/nfsmount.h
==============================================================================
--- head/sys/nfsclient/nfsmount.h	Thu Jan 21 20:56:18 2010	(r202766)
+++ head/sys/nfsclient/nfsmount.h	Thu Jan 21 20:57:25 2010	(r202767)
@@ -85,6 +85,7 @@ struct	nfsmount {
 	struct rpc_timers nm_timers[NFS_MAX_TIMER]; /* RTT Timers for rpcs */
 	char	nm_principal[MNAMELEN];	/* GSS-API principal of server */
 	gss_OID	nm_mech_oid;		/* OID of selected GSS-API mechanism */
+	int	nm_negnametimeo;	/* timeout for -ve entries (sec) */
 
 	/* NFSv4 */
 	uint64_t nm_clientid;
@@ -107,6 +108,10 @@ struct	nfsmount {
 #define NFS_TPRINTF_DELAY               30
 #endif
 
+#ifndef NFS_DEFAULT_NEGNAMETIMEO
+#define NFS_DEFAULT_NEGNAMETIMEO	60
+#endif
+
 #define	NFS_PCATCH	(PCATCH | PBDRY)
 
 #endif

Modified: head/sys/nfsclient/nfsnode.h
==============================================================================
--- head/sys/nfsclient/nfsnode.h	Thu Jan 21 20:56:18 2010	(r202766)
+++ head/sys/nfsclient/nfsnode.h	Thu Jan 21 20:57:25 2010	(r202767)
@@ -114,6 +114,7 @@ struct nfsnode {
 	struct timespec		n_mtime;	/* Prev modify time. */
 	time_t			n_ctime;	/* Prev create time. */
 	time_t			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 */



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