summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/nfs/nfs_node.c3
-rw-r--r--sys/nfs/nfs_subs.c14
-rw-r--r--sys/nfs/nfs_var.h3
-rw-r--r--sys/nfs/nfs_vnops.c88
-rw-r--r--sys/nfs/nfsnode.h6
5 files changed, 96 insertions, 18 deletions
diff --git a/sys/nfs/nfs_node.c b/sys/nfs/nfs_node.c
index 43e7acdd2ab..26af6c2ceea 100644
--- a/sys/nfs/nfs_node.c
+++ b/sys/nfs/nfs_node.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_node.c,v 1.37 2007/12/13 22:32:55 thib Exp $ */
+/* $OpenBSD: nfs_node.c,v 1.38 2008/06/10 22:59:09 thib Exp $ */
/* $NetBSD: nfs_node.c,v 1.16 1996/02/18 11:53:42 fvdl Exp $ */
/*
@@ -150,6 +150,7 @@ loop:
np->n_fhp = &np->n_fh;
bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
np->n_fhsize = fhsize;
+ np->n_accstamp = -1;
rw_exit(&nfs_hashlock);
*npp = np;
return (0);
diff --git a/sys/nfs/nfs_subs.c b/sys/nfs/nfs_subs.c
index ec707792590..a4104f7571a 100644
--- a/sys/nfs/nfs_subs.c
+++ b/sys/nfs/nfs_subs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_subs.c,v 1.76 2008/06/09 22:49:15 djm Exp $ */
+/* $OpenBSD: nfs_subs.c,v 1.77 2008/06/10 22:59:09 thib Exp $ */
/* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */
/*
@@ -1015,6 +1015,8 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
struct timespec mtime;
struct vnode *nvp;
int v3 = NFS_ISV3(vp);
+ uid_t uid;
+ gid_t gid;
md = *mdp;
t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
@@ -1091,6 +1093,15 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
vap->va_rdev = (dev_t)rdev;
vap->va_mtime = mtime;
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
+
+ uid = fxdr_unsigned(uid_t, fp->fa_uid);
+ gid = fxdr_unsigned(gid_t, fp->fa_gid);
+ /* Invalidate access cache if uid, gid or mode changed. */
+ if (np->n_accstamp != -1 &&
+ (gid != vap->va_gid || uid != vap->va_uid ||
+ vmode != vap->va_mode))
+ np->n_accstamp = -1;
+
switch (vtyp) {
case VBLK:
vap->va_blocksize = BLKDEV_IOSIZE;
@@ -1132,6 +1143,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
vap->va_filerev = 0;
}
+
if (vap->va_size != np->n_size) {
if (vap->va_type == VREG) {
if (np->n_flag & NMODIFIED) {
diff --git a/sys/nfs/nfs_var.h b/sys/nfs/nfs_var.h
index ff9c405c8ac..e6a6f8ca527 100644
--- a/sys/nfs/nfs_var.h
+++ b/sys/nfs/nfs_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_var.h,v 1.37 2008/06/09 22:49:15 djm Exp $ */
+/* $OpenBSD: nfs_var.h,v 1.38 2008/06/10 22:59:09 thib Exp $ */
/* $NetBSD: nfs_var.h,v 1.3 1996/02/18 11:53:54 fvdl Exp $ */
/*
@@ -249,6 +249,7 @@ int nfsm_disct(struct mbuf **, caddr_t *, int, int, caddr_t *);
int nfs_adv(struct mbuf **, caddr_t *, int, int);
int nfsm_strtmbuf(struct mbuf **, char **, char *, long);
int nfs_vfs_init(struct vfsconf *);
+int nfs_attrtimeo(struct nfsnode *);
int nfs_loadattrcache(struct vnode **, struct mbuf **, caddr_t *,
struct vattr *);
int nfs_getattrcache(struct vnode *, struct vattr *);
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c
index d26824f8b0e..0c2806acedd 100644
--- a/sys/nfs/nfs_vnops.c
+++ b/sys/nfs/nfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_vnops.c,v 1.85 2008/06/10 20:14:37 beck Exp $ */
+/* $OpenBSD: nfs_vnops.c,v 1.86 2008/06/10 22:59:09 thib Exp $ */
/* $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $ */
/*
@@ -82,6 +82,8 @@
#define TRUE 1
#define FALSE 0
+void nfs_cache_enter(struct vnode *, struct vnode *, struct componentname *);
+
/*
* Global vfs data structures for nfs
*/
@@ -186,6 +188,24 @@ extern nfstype nfsv3_type[9];
struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
int nfs_numasync = 0;
+
+void
+nfs_cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
+{
+ struct nfsnode *np;
+
+ if (vp != NULL) {
+ np = VTONFS(vp);
+ np->n_ctime = np->n_vattr.va_ctime.tv_sec;
+ } else {
+ np = VTONFS(dvp);
+ if (!np->n_ctime)
+ np->n_ctime = np->n_vattr.va_mtime.tv_sec;
+ }
+
+ cache_enter(dvp, vp, cnp);
+}
+
/*
* nfs null call from vfs.
*/
@@ -226,6 +246,9 @@ nfs_access(v)
struct mbuf *mreq, *mrep, *md, *mb;
u_int32_t mode, rmode;
int v3 = NFS_ISV3(vp);
+ int cachevalid;
+
+ struct nfsnode *np = VTONFS(vp);
/*
* Disallow write attempts on filesystems mounted read-only;
@@ -242,6 +265,23 @@ nfs_access(v)
break;
}
}
+
+ /*
+ * Check access cache first. If a request has been made for this uid
+ * shortly before, use the cached result.
+ */
+ cachevalid = (np->n_accstamp != -1 &&
+ (time_second - np->n_accstamp) < nfs_attrtimeo(np) &&
+ np->n_accuid == ap->a_cred->cr_uid);
+
+ if (cachevalid) {
+ if (!np->n_accerror) {
+ if ((np->n_accmode & ap->a_mode) == ap->a_mode)
+ return (np->n_accerror);
+ } else if ((np->n_accmode & ap->a_mode) == np->n_accmode)
+ return (np->n_accerror);
+ }
+
/*
* For nfs v3, do an access rpc, otherwise you are stuck emulating
* ufs_access() locally using the vattr. This may not be correct,
@@ -285,11 +325,33 @@ nfs_access(v)
if ((rmode & mode) != mode)
error = EACCES;
}
- m_freem(mrep);
-nfsmout:
- return (error);
+ m_freem(mrep);
} else
return (nfsspec_access(ap));
+
+
+ /*
+ * If we got the same result as for a previous, different request, OR
+ * it in. Don't update the timestamp in that case.
+ */
+ if (!error || error == EACCES) {
+ if (cachevalid && np->n_accstamp != -1 &&
+ error == np->n_accerror) {
+ if (!error)
+ np->n_accmode |= ap->a_mode;
+ else {
+ if ((np->n_accmode & ap->a_mode) == ap->a_mode)
+ np->n_accmode = ap->a_mode;
+ }
+ } else {
+ np->n_accstamp = time_second;
+ np->n_accuid = ap->a_cred->cr_uid;
+ np->n_accmode = ap->a_mode;
+ np->n_accerror = error;
+ }
+ }
+nfsmout:
+ return (error);
}
/*
@@ -813,8 +875,7 @@ dorpc:
cnp->cn_flags |= SAVENAME;
if ((cnp->cn_flags & MAKEENTRY) &&
(cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
- np->n_ctime = np->n_vattr.va_ctime.tv_sec;
- cache_enter(dvp, newvp, cnp);
+ nfs_cache_enter(dvp, newvp, cnp);
}
*vpp = newvp;
m_freem(mrep);
@@ -828,10 +889,7 @@ nfsmout:
*/
if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) &&
cnp->cn_nameiop != CREATE) {
- if (VTONFS(dvp)->n_ctime == 0)
- VTONFS(dvp)->n_ctime =
- VTONFS(dvp)->n_vattr.va_mtime.tv_sec;
- cache_enter(dvp, NULL, cnp);
+ nfs_cache_enter(dvp, NULL, cnp);
}
if (newvp != NULLVP) {
vrele(newvp);
@@ -1170,7 +1228,7 @@ nfsmout:
vrele(newvp);
} else {
if (cnp->cn_flags & MAKEENTRY)
- cache_enter(dvp, newvp, cnp);
+ nfs_cache_enter(dvp, newvp, cnp);
*vpp = newvp;
}
pool_put(&namei_pool, cnp->cn_pnbuf);
@@ -1294,7 +1352,7 @@ nfsmout:
error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
if (!error) {
if (cnp->cn_flags & MAKEENTRY)
- cache_enter(dvp, newvp, cnp);
+ nfs_cache_enter(dvp, newvp, cnp);
*ap->a_vpp = newvp;
}
pool_put(&namei_pool, cnp->cn_pnbuf);
@@ -1738,6 +1796,8 @@ nfsmout:
vrele(newvp);
} else {
VN_KNOTE(dvp, NOTE_WRITE|NOTE_LINK);
+ if (cnp->cn_flags & MAKEENTRY)
+ nfs_cache_enter(dvp, newvp, cnp);
*ap->a_vpp = newvp;
}
pool_put(&namei_pool, cnp->cn_pnbuf);
@@ -1788,7 +1848,6 @@ nfsmout:
VN_KNOTE(dvp, NOTE_WRITE|NOTE_LINK);
VN_KNOTE(vp, NOTE_DELETE);
- cache_purge(dvp);
cache_purge(vp);
vrele(vp);
vrele(dvp);
@@ -2320,7 +2379,8 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
cnp->cn_hash =
hash32_str(cnp->cn_nameptr,
HASHINIT);
- cache_enter(ndp->ni_dvp, ndp->ni_vp,
+ cache_purge(ndp->ni_dvp);
+ nfs_cache_enter(ndp->ni_dvp, ndp->ni_vp,
cnp);
}
}
diff --git a/sys/nfs/nfsnode.h b/sys/nfs/nfsnode.h
index ab4a64d5e06..c20e0542ee1 100644
--- a/sys/nfs/nfsnode.h
+++ b/sys/nfs/nfsnode.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfsnode.h,v 1.29 2007/12/13 22:32:55 thib Exp $ */
+/* $OpenBSD: nfsnode.h,v 1.30 2008/06/10 22:59:09 thib Exp $ */
/* $NetBSD: nfsnode.h,v 1.16 1996/02/18 11:54:04 fvdl Exp $ */
/*
@@ -92,6 +92,10 @@ struct nfsnode {
short n_fhsize; /* size in bytes, of fh */
short n_flag; /* Flag for locking.. */
nfsfh_t n_fh; /* Small File Handle */
+ time_t n_accstamp; /* Access cache timestamp */
+ uid_t n_accuid; /* Last access requester */
+ int n_accmode; /* Last mode requested */
+ int n_accerror; /* Last returned error */
struct ucred *n_rcred;
struct ucred *n_wcred;