summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/nfsclient/nfs_vfsops.c24
-rw-r--r--sys/nfsclient/nfs_vnops.c11
-rw-r--r--sys/nfsclient/nfsmount.h5
-rw-r--r--sys/nfsclient/nfsnode.h1
4 files changed, 33 insertions, 8 deletions
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 2346d41..72ca2ce 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -114,7 +114,7 @@ static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
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", "nfs_args",
"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, int flags)
*/
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 mount *mp, struct sockaddr *nam,
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;
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 7d6bb30..c74a6be 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -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
diff --git a/sys/nfsclient/nfsmount.h b/sys/nfsclient/nfsmount.h
index 47d7ef3..d47957c 100644
--- a/sys/nfsclient/nfsmount.h
+++ b/sys/nfsclient/nfsmount.h
@@ -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
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index 29198d8..402fc79 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -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 */
OpenPOWER on IntegriCloud