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:
parent
35c835cfe4
commit
5a7300902c
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue