summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfsclient')
-rw-r--r--sys/nfsclient/nfs_subs.c8
-rw-r--r--sys/nfsclient/nfs_vnops.c114
-rw-r--r--sys/nfsclient/nfsm_subs.h13
-rw-r--r--sys/nfsclient/nfsnode.h3
4 files changed, 65 insertions, 73 deletions
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index 19fde06..d00a025 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -978,8 +978,8 @@ nfsm_loadattr_xx(struct vnode **v, struct vattr *va, struct mbuf **md,
}
int
-nfsm_postop_attr_xx(struct vnode **v, int *f, struct mbuf **md,
- caddr_t *dpos)
+nfsm_postop_attr_xx(struct vnode **v, int *f, struct vattr *va,
+ struct mbuf **md, caddr_t *dpos)
{
u_int32_t *tl;
int t1;
@@ -990,7 +990,7 @@ nfsm_postop_attr_xx(struct vnode **v, int *f, struct mbuf **md,
return EBADRPC;
*f = fxdr_unsigned(int, *tl);
if (*f != 0) {
- t1 = nfs_loadattrcache(&ttvp, md, dpos, NULL, 1);
+ t1 = nfs_loadattrcache(&ttvp, md, dpos, va, 1);
if (t1 != 0) {
*f = 0;
return t1;
@@ -1020,7 +1020,7 @@ nfsm_wcc_data_xx(struct vnode **v, int *f, struct mbuf **md, caddr_t *dpos)
VTONFS(*v)->n_mtime.tv_nsec == fxdr_unsigned(u_int32_t, *(tl + 3)));
mtx_unlock(&(VTONFS(*v))->n_mtx);
}
- t1 = nfsm_postop_attr_xx(v, &ttattrf, md, dpos);
+ t1 = nfsm_postop_attr_xx(v, &ttattrf, NULL, md, dpos);
if (t1)
return t1;
if (*f)
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index a9f746d..a39b29b 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -913,7 +913,7 @@ nfs_lookup(struct vop_lookup_args *ap)
struct vnode **vpp = ap->a_vpp;
struct mount *mp = dvp->v_mount;
struct vattr vattr;
- struct timespec dmtime;
+ struct timespec nctime;
int flags = cnp->cn_flags;
struct vnode *newvp;
struct nfsmount *nmp;
@@ -922,7 +922,7 @@ nfs_lookup(struct vop_lookup_args *ap)
long len;
nfsfh_t *fhp;
struct nfsnode *np, *newnp;
- int error = 0, attrflag, fhsize, ltype;
+ int error = 0, attrflag, dattrflag, fhsize, ltype, ncticks;
int v3 = NFS_ISV3(dvp);
struct thread *td = cnp->cn_thread;
@@ -938,11 +938,24 @@ nfs_lookup(struct vop_lookup_args *ap)
*vpp = NULLVP;
return (error);
}
- error = cache_lookup(dvp, vpp, cnp);
+ error = cache_lookup_times(dvp, vpp, cnp, &nctime, &ncticks);
if (error > 0 && error != ENOENT)
return (error);
if (error == -1) {
/*
+ * Lookups of "." are special and always return the
+ * current directory. cache_lookup() already handles
+ * associated locking bookkeeping, etc.
+ */
+ if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
+ /* XXX: Is this really correct? */
+ if (cnp->cn_nameiop != LOOKUP &&
+ (flags & ISLASTCN))
+ cnp->cn_flags |= SAVENAME;
+ return (0);
+ }
+
+ /*
* 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
@@ -968,7 +981,7 @@ nfs_lookup(struct vop_lookup_args *ap)
mtx_unlock(&newnp->n_mtx);
}
if (VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
- timespeccmp(&vattr.va_ctime, &newnp->n_ctime, ==)) {
+ timespeccmp(&vattr.va_ctime, &nctime, ==)) {
nfsstats.lookupcache_hits++;
if (cnp->cn_nameiop != LOOKUP &&
(flags & ISLASTCN))
@@ -987,36 +1000,22 @@ nfs_lookup(struct vop_lookup_args *ap)
/*
* 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. We also
- * only trust -ve cache entries for less than
- * nm_negative_namecache_timeout seconds.
+ * the cached copy in the name cache entry.
+ * Otherwise, we discard all of the negative cache
+ * entries for this directory. We also only trust
+ * negative cache entries for up to nm_negnametimeo
+ * seconds.
*/
- if ((u_int)(ticks - np->n_dmtime_ticks) <
- (nmp->nm_negnametimeo * hz) &&
+ if ((u_int)(ticks - ncticks) < (nmp->nm_negnametimeo * hz) &&
VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 &&
- timespeccmp(&vattr.va_mtime, &np->n_dmtime, ==)) {
+ timespeccmp(&vattr.va_mtime, &nctime, ==)) {
nfsstats.lookupcache_hits++;
return (ENOENT);
}
cache_purge_negative(dvp);
- mtx_lock(&np->n_mtx);
- timespecclear(&np->n_dmtime);
- mtx_unlock(&np->n_mtx);
}
- /*
- * Cache the modification time of the parent directory in case
- * the lookup fails and results in adding the first negative
- * name cache entry for the directory. Since this is reading
- * a single time_t, don't bother with locking. The
- * modification time may be a bit stale, but it must be read
- * before performing the lookup RPC to prevent a race where
- * another lookup updates the timestamp on the directory after
- * the lookup RPC has been performed on the server but before
- * n_dmtime is set at the end of this function.
- */
- dmtime = np->n_vattr.va_mtime;
+ attrflag = dattrflag = 0;
error = 0;
newvp = NULLVP;
nfsstats.lookupcache_misses++;
@@ -1031,7 +1030,7 @@ nfs_lookup(struct vop_lookup_args *ap)
nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_thread, cnp->cn_cred);
if (error) {
if (v3) {
- nfsm_postop_attr(dvp, attrflag);
+ nfsm_postop_attr_va(dvp, dattrflag, &vattr);
m_freem(mrep);
}
goto nfsmout;
@@ -1127,16 +1126,17 @@ nfs_lookup(struct vop_lookup_args *ap)
}
}
if (v3) {
- nfsm_postop_attr(newvp, attrflag);
- nfsm_postop_attr(dvp, attrflag);
- } else
- nfsm_loadattr(newvp, NULL);
+ nfsm_postop_attr_va(newvp, attrflag, &vattr);
+ nfsm_postop_attr(dvp, dattrflag);
+ } else {
+ nfsm_loadattr(newvp, &vattr);
+ attrflag = 1;
+ }
if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
cnp->cn_flags |= SAVENAME;
if ((cnp->cn_flags & MAKEENTRY) &&
- (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
- np->n_ctime = np->n_vattr.va_ctime;
- cache_enter(dvp, newvp, cnp);
+ (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) && attrflag) {
+ cache_enter_time(dvp, newvp, cnp, &vattr.va_ctime);
}
*vpp = newvp;
m_freem(mrep);
@@ -1164,30 +1164,22 @@ nfsmout:
return (EJUSTRETURN);
}
- if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) {
+ if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE &&
+ dattrflag) {
/*
- * Maintain n_dmtime as the modification time
- * of the parent directory when the oldest -ve
- * name cache entry for this directory was
- * added. If a -ve cache entry has already
- * been added with a newer modification time
- * by a concurrent lookup, then don't bother
- * adding a cache entry. The modification
- * time of the directory might have changed
- * due to the file this lookup failed to find
- * being created. In that case a subsequent
- * lookup would incorrectly use the entry
- * added here instead of doing an extra
- * lookup.
+ * Cache the modification time of the parent
+ * directory from the post-op attributes in
+ * the name cache entry. The negative cache
+ * entry will be ignored once the directory
+ * has changed. Don't bother adding the entry
+ * if the directory has already changed.
*/
mtx_lock(&np->n_mtx);
- if (timespeccmp(&np->n_dmtime, &dmtime, <=)) {
- if (!timespecisset(&np->n_dmtime)) {
- np->n_dmtime = dmtime;
- np->n_dmtime_ticks = ticks;
- }
+ if (timespeccmp(&np->n_vattr.va_mtime,
+ &vattr.va_mtime, ==)) {
mtx_unlock(&np->n_mtx);
- cache_enter(dvp, NULL, cnp);
+ cache_enter_time(dvp, NULL, cnp,
+ &vattr.va_mtime);
} else
mtx_unlock(&np->n_mtx);
}
@@ -2473,6 +2465,7 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
nfsuint64 cookie;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
struct nfsnode *dnp = VTONFS(vp), *np;
+ struct vattr vattr;
nfsfh_t *fhp;
u_quad_t fileno;
int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
@@ -2653,18 +2646,13 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
dpos = dpossav1;
mdsav2 = md;
md = mdsav1;
- nfsm_loadattr(newvp, NULL);
+ nfsm_loadattr(newvp, &vattr);
dpos = dpossav2;
md = mdsav2;
- dp->d_type =
- IFTODT(VTTOIF(np->n_vattr.va_type));
+ dp->d_type = IFTODT(VTTOIF(vattr.va_type));
ndp->ni_vp = newvp;
- /*
- * Update n_ctime so subsequent lookup
- * doesn't purge entry.
- */
- np->n_ctime = np->n_vattr.va_ctime;
- cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
+ cache_enter_time(ndp->ni_dvp, ndp->ni_vp, cnp,
+ &vattr.va_ctime);
}
} else {
/* Just skip over the file handle */
diff --git a/sys/nfsclient/nfsm_subs.h b/sys/nfsclient/nfsm_subs.h
index 583aec1..c12badd 100644
--- a/sys/nfsclient/nfsm_subs.h
+++ b/sys/nfsclient/nfsm_subs.h
@@ -152,8 +152,8 @@ int nfsm_getfh_xx(nfsfh_t **f, int *s, int v3, struct mbuf **md,
caddr_t *dpos);
int nfsm_loadattr_xx(struct vnode **v, struct vattr *va, struct mbuf **md,
caddr_t *dpos);
-int nfsm_postop_attr_xx(struct vnode **v, int *f, struct mbuf **md,
- caddr_t *dpos);
+int nfsm_postop_attr_xx(struct vnode **v, int *f, struct vattr *va,
+ struct mbuf **md, caddr_t *dpos);
int nfsm_wcc_data_xx(struct vnode **v, int *f, struct mbuf **md,
caddr_t *dpos);
@@ -181,7 +181,14 @@ do { \
#define nfsm_postop_attr(v, f) \
do { \
int32_t t1; \
- t1 = nfsm_postop_attr_xx(&v, &f, &md, &dpos); \
+ t1 = nfsm_postop_attr_xx(&v, &f, NULL, &md, &dpos); \
+ nfsm_dcheck(t1, mrep); \
+} while (0)
+
+#define nfsm_postop_attr_va(v, f, va) \
+do { \
+ int32_t t1; \
+ t1 = nfsm_postop_attr_xx(&v, &f, va, &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index 8e35fdd..60e5613 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -104,9 +104,6 @@ struct nfsnode {
time_t n_attrstamp; /* Attr. cache timestamp */
struct nfs_accesscache n_accesscache[NFS_ACCESSCACHESIZE];
struct timespec n_mtime; /* Prev modify time. */
- struct timespec n_ctime; /* Prev create time. */
- struct timespec n_dmtime; /* Prev dir modify time. */
- int n_dmtime_ticks; /* Tick of -ve cache entry */
nfsfh_t *n_fhp; /* NFS File Handle */
struct vnode *n_vnode; /* associated vnode */
struct vnode *n_dvp; /* parent vnode */
OpenPOWER on IntegriCloud