diff options
author | jhb <jhb@FreeBSD.org> | 2012-01-25 20:05:58 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2012-01-25 20:05:58 +0000 |
commit | 768a468c15a95c443b29381081ac318debea4846 (patch) | |
tree | 5f8bcbc509dcfba24c232996c7826a9b95d20dca /sys/fs/nfsclient | |
parent | ee48ed5fd372f596d4901253bcca015ab3c75fcf (diff) | |
download | FreeBSD-src-768a468c15a95c443b29381081ac318debea4846.zip FreeBSD-src-768a468c15a95c443b29381081ac318debea4846.tar.gz |
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.
Reviewed by: rmacklem
MFC after: 1 week
Diffstat (limited to 'sys/fs/nfsclient')
-rw-r--r-- | sys/fs/nfsclient/nfs_clvfsops.c | 29 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfs_clvnops.c | 6 | ||||
-rw-r--r-- | sys/fs/nfsclient/nfsmount.h | 5 |
3 files changed, 29 insertions, 11 deletions
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c index 5ddfa27..e6d146f 100644 --- a/sys/fs/nfsclient/nfs_clvfsops.c +++ b/sys/fs/nfsclient/nfs_clvfsops.c @@ -104,7 +104,7 @@ static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp, 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 *); @@ -520,7 +520,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); } @@ -715,7 +716,7 @@ static const char *nfs_opts[] = { "from", "nfs_args", "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 }; /* @@ -760,6 +761,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; @@ -968,6 +970,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); @@ -1126,7 +1136,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); @@ -1170,7 +1180,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; @@ -1237,13 +1247,14 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, } 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; diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 2747191..183491e 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1063,7 +1063,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 @@ -1085,7 +1086,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 && diff --git a/sys/fs/nfsclient/nfsmount.h b/sys/fs/nfsclient/nfsmount.h index b62a430..8068c28 100644 --- a/sys/fs/nfsclient/nfsmount.h +++ b/sys/fs/nfsclient/nfsmount.h @@ -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 |