Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Mar 2012 21:08:14 +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-8@freebsd.org
Subject:   svn commit: r233327 - in stable/8: sbin/mount_nfs sys/fs/nfsclient sys/i386/conf sys/nfsclient
Message-ID:  <201203222108.q2ML8EDG041520@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Thu Mar 22 21:08:14 2012
New Revision: 233327
URL: http://svn.freebsd.org/changeset/base/233327

Log:
  MFC 230547:
  Add a timeout on positive name cache entries in the NFS client.  That is,
  we will only trust a positive name cache entry for a specified amount of
  time before falling back to a LOOKUP RPC, even if the ctime for the file
  handle matches the cached copy in the name cache entry.  The timeout is
  configured via a new 'nametimeo' mount option and defaults to 60 seconds.
  It may be set to zero to disable positive name caching entirely.

Modified:
  stable/8/sbin/mount_nfs/mount_nfs.8
  stable/8/sys/fs/nfsclient/nfs_clvfsops.c
  stable/8/sys/fs/nfsclient/nfs_clvnops.c
  stable/8/sys/fs/nfsclient/nfsmount.h
  stable/8/sys/nfsclient/nfs_vfsops.c
  stable/8/sys/nfsclient/nfs_vnops.c
  stable/8/sys/nfsclient/nfsmount.h
Directory Properties:
  stable/8/sbin/mount_nfs/   (props changed)
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/boot/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/e1000/   (props changed)
  stable/8/sys/i386/conf/XENHVM   (props changed)

Modified: stable/8/sbin/mount_nfs/mount_nfs.8
==============================================================================
--- stable/8/sbin/mount_nfs/mount_nfs.8	Thu Mar 22 21:07:54 2012	(r233326)
+++ stable/8/sbin/mount_nfs/mount_nfs.8	Thu Mar 22 21:08:14 2012	(r233327)
@@ -151,6 +151,10 @@ Force the mount protocol to use UDP tran
 (Necessary for some old
 .Bx
 servers.)
+.It Cm nametimeo Ns = Ns Aq Ar value
+Override the default of NFS_DEFAULT_NAMETIMEO for the timeout (in seconds)
+for positive name cache entries.
+If this is set to 0 it disables positive name caching for the mount point.
 .It Cm negnametimeo Ns = Ns Aq Ar value
 Override the default of NFS_DEFAULT_NEGNAMETIMEO for the timeout (in seconds)
 for negative name cache entries. If this is set to 0 it disables negative

Modified: stable/8/sys/fs/nfsclient/nfs_clvfsops.c
==============================================================================
--- stable/8/sys/fs/nfsclient/nfs_clvfsops.c	Thu Mar 22 21:07:54 2012	(r233326)
+++ stable/8/sys/fs/nfsclient/nfs_clvfsops.c	Thu Mar 22 21:08:14 2012	(r233327)
@@ -104,7 +104,7 @@ static void	nfs_decode_args(struct mount
 static int	mountnfs(struct nfs_args *, struct mount *,
 		    struct sockaddr *, char *, u_char *, int, u_char *, int,
 		    u_char *, int, struct vnode **, struct ucred *,
-		    struct thread *, int);
+		    struct thread *, int, int);
 static void	nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
 		    struct sockaddr_storage *, int *, off_t *,
 		    struct timeval *);
@@ -516,7 +516,8 @@ nfs_mountdiskless(char *path,
 		dirlen = 0;
 	nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
 	if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
-	    NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
+	    NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO, 
+	    NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
 		printf("nfs_mountroot: mount %s on /: %d\n", path, error);
 		return (error);
 	}
@@ -711,7 +712,7 @@ static const char *nfs_opts[] = { "from"
     "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
     "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
     "principal", "nfsv4", "gssname", "allgssname", "dirpath",
-    "negnametimeo", "nocto", "wcommitsize",
+    "nametimeo", "negnametimeo", "nocto", "wcommitsize",
     NULL };
 
 /*
@@ -756,6 +757,7 @@ nfs_mount(struct mount *mp)
 	char hst[MNAMELEN];
 	u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
 	char *opt, *name, *secname;
+	int nametimeo = NFS_DEFAULT_NAMETIMEO;
 	int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
 	int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
 	size_t hstlen;
@@ -964,6 +966,14 @@ nfs_mount(struct mount *mp)
 		}
 		args.flags |= NFSMNT_TIMEO;
 	}
+	if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &nametimeo);
+		if (ret != 1 || nametimeo < 0) {
+			vfs_mount_error(mp, "illegal nametimeo: %s", opt);
+			error = EINVAL;
+			goto out;
+		}
+	}
 	if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
 	    == 0) {
 		ret = sscanf(opt, "%d", &negnametimeo);
@@ -1118,7 +1128,7 @@ nfs_mount(struct mount *mp)
 	args.fh = nfh;
 	error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
 	    dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
-	    negnametimeo);
+	    nametimeo, negnametimeo);
 out:
 	if (!error) {
 		MNT_ILOCK(mp);
@@ -1162,7 +1172,7 @@ static int
 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
     char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
     u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
-    struct ucred *cred, struct thread *td, int negnametimeo)
+    struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo)
 {
 	struct nfsmount *nmp;
 	struct nfsnode *np;
@@ -1229,13 +1239,14 @@ mountnfs(struct nfs_args *argp, struct m
 	}
 	vfs_getnewfsid(mp);
 	nmp->nm_mountp = mp;
-	mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);			
+	mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
 
 	/*
-	 * Since nfs_decode_args() might optionally set them, these need to
-	 * set to defaults before the call, so that the optional settings
-	 * aren't overwritten.
+	 * Since nfs_decode_args() might optionally set them, these
+	 * need to be set to defaults before the call, so that the
+	 * optional settings aren't overwritten.
 	 */
+	nmp->nm_nametimeo = nametimeo;
 	nmp->nm_negnametimeo = negnametimeo;
 	nmp->nm_timeo = NFS_TIMEO;
 	nmp->nm_retry = NFS_RETRANS;

Modified: stable/8/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- stable/8/sys/fs/nfsclient/nfs_clvnops.c	Thu Mar 22 21:07:54 2012	(r233326)
+++ stable/8/sys/fs/nfsclient/nfs_clvnops.c	Thu Mar 22 21:08:14 2012	(r233327)
@@ -1026,7 +1026,8 @@ nfs_lookup(struct vop_lookup_args *ap)
 		 * 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.
+		 * to doing a lookup RPC.  We also only trust cache
+		 * entries for less than nm_nametimeo seconds.
 		 *
 		 * To better handle stale file handles and attributes,
 		 * clear the attribute cache of this node if it is a
@@ -1047,7 +1048,8 @@ nfs_lookup(struct vop_lookup_args *ap)
 			mtx_unlock(&newnp->n_mtx);
 		}
 		if (nfscl_nodeleg(newvp, 0) == 0 ||
-		    (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
+		    ((u_int)(ticks - ncticks) < (nmp->nm_nametimeo * hz) &&
+		    VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
 		    timespeccmp(&vattr.va_ctime, &nctime, ==))) {
 			NFSINCRGLOBAL(newnfsstats.lookupcache_hits);
 			if (cnp->cn_nameiop != LOOKUP &&

Modified: stable/8/sys/fs/nfsclient/nfsmount.h
==============================================================================
--- stable/8/sys/fs/nfsclient/nfsmount.h	Thu Mar 22 21:07:54 2012	(r233326)
+++ stable/8/sys/fs/nfsclient/nfsmount.h	Thu Mar 22 21:08:14 2012	(r233327)
@@ -66,6 +66,7 @@ struct	nfsmount {
 	u_int64_t nm_maxfilesize;	/* maximum file size */
 	int	nm_tprintf_initial_delay; /* initial delay */
 	int	nm_tprintf_delay;	/* interval for messages */
+	int	nm_nametimeo;		/* timeout for +ve entries (sec) */
 	int	nm_negnametimeo;	/* timeout for -ve entries (sec) */
 
 	/* Newnfs additions */
@@ -106,6 +107,10 @@ struct	nfsmount {
  */
 #define	VFSTONFS(mp)	((struct nfsmount *)((mp)->mnt_data))
 
+#ifndef NFS_DEFAULT_NAMETIMEO
+#define NFS_DEFAULT_NAMETIMEO		60
+#endif
+
 #ifndef NFS_DEFAULT_NEGNAMETIMEO
 #define NFS_DEFAULT_NEGNAMETIMEO	60
 #endif

Modified: stable/8/sys/nfsclient/nfs_vfsops.c
==============================================================================
--- stable/8/sys/nfsclient/nfs_vfsops.c	Thu Mar 22 21:07:54 2012	(r233326)
+++ stable/8/sys/nfsclient/nfs_vfsops.c	Thu Mar 22 21:08:14 2012	(r233327)
@@ -116,7 +116,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, int);
+		    struct ucred *cred, int, int);
 static void	nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
 		    struct sockaddr_storage *, int *, off_t *,
 		    struct timeval *);
@@ -558,8 +558,8 @@ nfs_mountdiskless(char *path,
 	int error;
 
 	nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
-	if ((error = mountnfs(args, mp, nam, path, vpp,
-	    td->td_ucred, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
+	if ((error = mountnfs(args, mp, nam, path, vpp, td->td_ucred,
+	    NFS_DEFAULT_NAMETIMEO, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
 		printf("nfs_mountroot: mount %s on /: %d\n", path, error);
 		return (error);
 	}
@@ -787,6 +787,7 @@ static const char *nfs_opts[] = { "from"
     "wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin",
     "acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
     "sec", "maxgroups", "principal", "negnametimeo", "nocto", "wcommitsize",
+    "nametimeo",
     NULL };
 
 /*
@@ -835,6 +836,7 @@ nfs_mount(struct mount *mp)
 	size_t len;
 	u_char nfh[NFSX_V3FHMAX];
 	char *opt;
+	int nametimeo = NFS_DEFAULT_NAMETIMEO;
 	int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
 
 	has_nfs_args_opt = 0;
@@ -1057,6 +1059,14 @@ nfs_mount(struct mount *mp)
 		}
 		args.flags |= NFSMNT_MAXGRPS;
 	}
+	if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
+		ret = sscanf(opt, "%d", &nametimeo);
+		if (ret != 1 || nametimeo < 0) {
+			vfs_mount_error(mp, "illegal nametimeo: %s", opt);
+			error = EINVAL;
+			goto out;
+		}
+	}
 	if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
 	    == 0) {
 		ret = sscanf(opt, "%d", &negnametimeo);
@@ -1177,7 +1187,7 @@ nfs_mount(struct mount *mp)
 		goto out;
 	}
 	error = mountnfs(&args, mp, nam, args.hostname, &vp,
-	    curthread->td_ucred, negnametimeo);
+	    curthread->td_ucred, nametimeo, negnametimeo);
 out:
 	if (!error) {
 		MNT_ILOCK(mp);
@@ -1219,7 +1229,8 @@ 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, int negnametimeo)
+    char *hst, struct vnode **vpp, struct ucred *cred, int nametimeo,
+    int negnametimeo)
 {
 	struct nfsmount *nmp;
 	struct nfsnode *np;
@@ -1269,6 +1280,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_nametimeo = nametimeo;
 	nmp->nm_negnametimeo = negnametimeo;
 	nmp->nm_tprintf_delay = nfs_tprintf_delay;
 	if (nmp->nm_tprintf_delay < 0)

Modified: stable/8/sys/nfsclient/nfs_vnops.c
==============================================================================
--- stable/8/sys/nfsclient/nfs_vnops.c	Thu Mar 22 21:07:54 2012	(r233326)
+++ stable/8/sys/nfsclient/nfs_vnops.c	Thu Mar 22 21:08:14 2012	(r233327)
@@ -960,7 +960,8 @@ nfs_lookup(struct vop_lookup_args *ap)
 		 * 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.
+		 * to doing a lookup RPC.  We also only trust cache
+		 * entries for less than nm_nametimeo seconds.
 		 *
 		 * To better handle stale file handles and attributes,
 		 * clear the attribute cache of this node if it is a
@@ -981,7 +982,8 @@ nfs_lookup(struct vop_lookup_args *ap)
 			KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
 			mtx_unlock(&newnp->n_mtx);
 		}
-		if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
+		if ((u_int)(ticks - ncticks) < (nmp->nm_nametimeo * hz) &&
+		    VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
 		    timespeccmp(&vattr.va_ctime, &nctime, ==)) {
 			nfsstats.lookupcache_hits++;
 			if (cnp->cn_nameiop != LOOKUP &&

Modified: stable/8/sys/nfsclient/nfsmount.h
==============================================================================
--- stable/8/sys/nfsclient/nfsmount.h	Thu Mar 22 21:07:54 2012	(r233326)
+++ stable/8/sys/nfsclient/nfsmount.h	Thu Mar 22 21:08:14 2012	(r233327)
@@ -83,6 +83,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_nametimeo;		/* timeout for +ve entries (sec) */
 	int	nm_negnametimeo;	/* timeout for -ve entries (sec) */
 
 	/* NFSv4 */
@@ -116,6 +117,10 @@ struct	nfsmount {
 #define NFS_TPRINTF_DELAY               30
 #endif
 
+#ifndef NFS_DEFAULT_NAMETIMEO
+#define NFS_DEFAULT_NAMETIMEO		60
+#endif
+
 #ifndef NFS_DEFAULT_NEGNAMETIMEO
 #define NFS_DEFAULT_NEGNAMETIMEO	60
 #endif



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