Insert an extra VOP_ACCESS check in nfs_lookup, to avoid cached access

mishaps for lookup and getattr. Closes PR 8884.

While at it, cache access RPCs.
This commit is contained in:
fvdl 1999-11-29 23:34:00 +00:00
parent 35c835cfe4
commit 5a7300902c
3 changed files with 58 additions and 17 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_node.c,v 1.29 1999/07/08 01:06:03 wrstuden Exp $ */
/* $NetBSD: nfs_node.c,v 1.30 1999/11/29 23:34:00 fvdl Exp $ */
/*
* Copyright (c) 1989, 1993
@ -160,6 +160,7 @@ loop:
np->n_fhp = &np->n_fh;
memcpy((caddr_t)np->n_fhp, (caddr_t)fhp, fhsize);
np->n_fhsize = fhsize;
np->n_accstamp = -1;
np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK);
memset(np->n_vattr, 0, sizeof (struct vattr));
lockmgr(&nfs_hashlock, LK_RELEASE, 0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_vnops.c,v 1.107 1999/11/15 18:49:12 fvdl Exp $ */
/* $NetBSD: nfs_vnops.c,v 1.108 1999/11/29 23:34:00 fvdl Exp $ */
/*
* Copyright (c) 1989, 1993
@ -301,10 +301,22 @@ nfs_access(v)
register caddr_t cp;
register int32_t t1, t2;
caddr_t bpos, dpos, cp2;
int error = 0, attrflag;
int error = 0, attrflag, cachevalid;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
u_int32_t mode, rmode;
int v3 = NFS_ISV3(vp);
struct nfsnode *np = VTONFS(vp);
cachevalid = (np->n_accstamp != -1 &&
(time.tv_sec - np->n_accstamp) < NFS_ATTRTIMEO(np) &&
np->n_accuid == ap->a_cred->cr_uid);
/*
* Check access cache first. If this request has been made for this
* uid shortly before, use the cached result.
*/
if (cachevalid && ((np->n_accmode & ap->a_mode) == ap->a_mode))
return np->n_accerror;
/*
* For nfs v3, do an access rpc, otherwise you are stuck emulating
@ -350,8 +362,6 @@ nfs_access(v)
error = EACCES;
}
nfsm_reqdone;
if (error)
return (error);
} else
return (nfsspec_access(ap));
/*
@ -359,17 +369,35 @@ nfs_access(v)
* unless the file is a socket, fifo, or a block or character
* device resident on the filesystem.
*/
if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
if (!error && (ap->a_mode & VWRITE) &&
(vp->v_mount->mnt_flag & MNT_RDONLY)) {
switch (vp->v_type) {
case VREG:
case VDIR:
case VLNK:
return (EROFS);
error = EROFS;
default:
break;
}
}
return (0);
if (!error || error == EACCES) {
/*
* If we got the same result as for a previous,
* different request, OR it in. Don't update
* the timestamp in that case.
*/
if (cachevalid && error == np->n_accerror)
np->n_accmode |= ap->a_mode;
else {
np->n_accstamp = time.tv_sec;
np->n_accuid = ap->a_cred->cr_uid;
np->n_accmode = ap->a_mode;
np->n_accerror = error;
}
}
return (error);
}
/*
@ -748,6 +776,7 @@ nfs_lookup(v)
return (EROFS);
if (dvp->v_type != VDIR)
return (ENOTDIR);
lockparent = flags & LOCKPARENT;
wantparent = flags & (LOCKPARENT|WANTPARENT);
nmp = VFSTONFS(dvp->v_mount);
@ -764,6 +793,18 @@ nfs_lookup(v)
*/
if ((error = cache_lookup(dvp, vpp, cnp)) >= 0) {
struct vattr vattr;
int err2;
if (error && error != ENOENT) {
*vpp = NULLVP;
return (error);
}
err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
if (err2) {
*vpp = NULLVP;
return (err2);
}
if (error == ENOENT) {
if (!VOP_GETATTR(dvp, &vattr, cnp->cn_cred,
@ -773,9 +814,10 @@ nfs_lookup(v)
cache_purge(dvp);
np->n_nctime = 0;
goto dorpc;
}
else if (error > 0)
} else if (error > 0) {
*vpp = NULLVP;
return error;
}
newvp = *vpp;
if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc)

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfsnode.h,v 1.27 1998/08/10 08:11:13 matthias Exp $ */
/* $NetBSD: nfsnode.h,v 1.28 1999/11/29 23:34:01 fvdl Exp $ */
/*
* Copyright (c) 1989, 1993
@ -94,12 +94,6 @@ struct nfsdircache {
* There is a unique nfsnode allocated for each active file,
* each current directory, each mounted-on file, text file, and the root.
* An nfsnode is 'named' by its file handle. (nget/nfs_node.c)
* If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
* type definitions), file handles of > 32 bytes should probably be split out
* into a separate MALLOC()'d data structure. (Reduce the size of nfsfh_t by
* changing the definition in nfsproto.h of NFS_SMALLFH.)
* NB: Hopefully the current order of the fields is such that everything will
* be well aligned and, therefore, tightly packed.
*/
struct nfsnode {
u_quad_t n_size; /* Current size of file */
@ -136,6 +130,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; /* Mode last requested */
int n_accerror; /* Error last returned */
};
#define n_atim n_un1.nf_atim