From owner-svn-src-all@FreeBSD.ORG Fri Mar 20 21:12:39 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 45226106566C; Fri, 20 Mar 2009 21:12:39 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 31F1C8FC1E; Fri, 20 Mar 2009 21:12:39 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n2KLCdlL013625; Fri, 20 Mar 2009 21:12:39 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n2KLCcMo013621; Fri, 20 Mar 2009 21:12:38 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200903202112.n2KLCcMo013621@svn.freebsd.org> From: John Baldwin Date: Fri, 20 Mar 2009 21:12:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r190176 - in head/sys: nfs4client nfsclient X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 20 Mar 2009 21:12:40 -0000 Author: jhb Date: Fri Mar 20 21:12:38 2009 New Revision: 190176 URL: http://svn.freebsd.org/changeset/base/190176 Log: Expand the per-node access cache to cache permissions for multiple users. The number of entries in the cache defaults to 8 but is easily changed in nfsclient/nfs.h. When the cache is filled, the oldest cache entry is evicted when space is needed. I mirrored the changes to the NFSv[23] client in the NFSv4 client to fix compile breakage. However, the NFSv4 client doesn't actually use the access cache currently. Submitted by: rmacklem Modified: head/sys/nfs4client/nfs4_vnops.c head/sys/nfsclient/nfs.h head/sys/nfsclient/nfs_vnops.c head/sys/nfsclient/nfsnode.h Modified: head/sys/nfs4client/nfs4_vnops.c ============================================================================== --- head/sys/nfs4client/nfs4_vnops.c Fri Mar 20 20:55:57 2009 (r190175) +++ head/sys/nfs4client/nfs4_vnops.c Fri Mar 20 21:12:38 2009 (r190176) @@ -241,11 +241,11 @@ SYSCTL_INT(_vfs_nfs4, OID_AUTO, access_c | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP) static int nfs4_v3_access_otw(struct vnode *vp, int wmode, struct thread *td, - struct ucred *cred) + struct ucred *cred, uint32_t *retmode) { const int v3 = 1; u_int32_t *tl; - int error = 0, attrflag; + int error = 0, attrflag, i, lrupos; return (0); @@ -264,11 +264,26 @@ nfs4_v3_access_otw(struct vnode *vp, int nfsm_request(vp, NFSPROC_ACCESS, td, cred); nfsm_postop_attr(vp, attrflag); if (!error) { + lrupos = 0; tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); rmode = fxdr_unsigned(u_int32_t, *tl); - np->n_mode = rmode; - np->n_modeuid = cred->cr_uid; - np->n_modestamp = time_second; + for (i = 0; i < NFS_ACCESSCACHESIZE; i++) { + if (np->n_accesscache[i].uid == cred->cr_uid) { + np->n_accesscache[i].mode = rmode; + np->n_accesscache[i].stamp = time_second; + break; + } + if (i > 0 && np->n_accesscache[i].stamp < + np->n_accesscache[lrupos].stamp) + lrupos = i; + } + if (i == NFS_ACCESSCACHESIZE) { + np->n_accesscache[lrupos].uid = cred->cr_uid; + np->n_accesscache[lrupos].mode = rmode; + np->n_accesscache[lrupos].stamp = time_second; + } + if (retmode != NULL) + *retmode = rmode; } m_freem(mrep); nfsmout: @@ -285,8 +300,8 @@ static int nfs4_access(struct vop_access_args *ap) { struct vnode *vp = ap->a_vp; - int error = 0; - u_int32_t mode, wmode; + int error = 0, i, gotahit; + u_int32_t mode, rmode, wmode; int v3 = NFS_ISV3(vp); /* v3 \in v4 */ struct nfsnode *np = VTONFS(vp); caddr_t bpos, dpos; @@ -350,19 +365,27 @@ nfs4_access(struct vop_access_args *ap) * Does our cached result allow us to give a definite yes to * this request? */ - if (time_second < np->n_modestamp + nfs4_access_cache_timeout && - ap->a_cred->cr_uid == np->n_modeuid && - (np->n_mode & mode) == mode) { - nfsstats.accesscache_hits++; - } else { + gotahit = 0; + for (i = 0; i < NFS_ACCESSCACHESIZE; i++) { + if (ap->a_cred->cr_uid == np->n_accesscache[i].uid) { + if (time_second < (np->n_accesscache[i].stamp + + nfs4_access_cache_timeout) && + (np->n_accesscache[i].mode & mode) == mode) { + nfsstats.accesscache_hits++; + gotahit = 1; + } + break; + } + } + if (gotahit == 0) { /* * Either a no, or a don't know. Go to the wire. */ nfsstats.accesscache_misses++; error = nfs4_v3_access_otw(vp, wmode, ap->a_td, - ap->a_cred); + ap->a_cred, &rmode); if (error == 0) { - if ((np->n_mode & mode) != mode) + if ((rmode & mode) != mode) error = EACCES; } } Modified: head/sys/nfsclient/nfs.h ============================================================================== --- head/sys/nfsclient/nfs.h Fri Mar 20 20:55:57 2009 (r190175) +++ head/sys/nfsclient/nfs.h Fri Mar 20 21:12:38 2009 (r190176) @@ -68,6 +68,9 @@ #ifndef NFS_MAXDIRATTRTIMO #define NFS_MAXDIRATTRTIMO 60 #endif +#ifndef NFS_ACCESSCACHESIZE +#define NFS_ACCESSCACHESIZE 8 /* Per-node access cache entries */ +#endif #define NFS_WSIZE 8192 /* Def. write data size <= 8192 */ #define NFS_RSIZE 8192 /* Def. read data size <= 8192 */ #define NFS_READDIRSIZE 8192 /* Def. readdir size */ Modified: head/sys/nfsclient/nfs_vnops.c ============================================================================== --- head/sys/nfsclient/nfs_vnops.c Fri Mar 20 20:55:57 2009 (r190175) +++ head/sys/nfsclient/nfs_vnops.c Fri Mar 20 21:12:38 2009 (r190176) @@ -270,11 +270,11 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, access_ca static int nfs3_access_otw(struct vnode *vp, int wmode, struct thread *td, - struct ucred *cred) + struct ucred *cred, uint32_t *retmode) { const int v3 = 1; u_int32_t *tl; - int error = 0, attrflag; + int error = 0, attrflag, i, lrupos; struct mbuf *mreq, *mrep, *md, *mb; caddr_t bpos, dpos; @@ -291,13 +291,28 @@ nfs3_access_otw(struct vnode *vp, int wm nfsm_request(vp, NFSPROC_ACCESS, td, cred); nfsm_postop_attr(vp, attrflag); if (!error) { + lrupos = 0; tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); rmode = fxdr_unsigned(u_int32_t, *tl); mtx_lock(&np->n_mtx); - np->n_mode = rmode; - np->n_modeuid = cred->cr_uid; - np->n_modestamp = time_second; + for (i = 0; i < NFS_ACCESSCACHESIZE; i++) { + if (np->n_accesscache[i].uid == cred->cr_uid) { + np->n_accesscache[i].mode = rmode; + np->n_accesscache[i].stamp = time_second; + break; + } + if (i > 0 && np->n_accesscache[i].stamp < + np->n_accesscache[lrupos].stamp) + lrupos = i; + } + if (i == NFS_ACCESSCACHESIZE) { + np->n_accesscache[lrupos].uid = cred->cr_uid; + np->n_accesscache[lrupos].mode = rmode; + np->n_accesscache[lrupos].stamp = time_second; + } mtx_unlock(&np->n_mtx); + if (retmode != NULL) + *retmode = rmode; } m_freem(mrep); nfsmout: @@ -314,8 +329,8 @@ static int nfs_access(struct vop_access_args *ap) { struct vnode *vp = ap->a_vp; - int error = 0; - u_int32_t mode, wmode; + int error = 0, i, gotahit; + u_int32_t mode, rmode, wmode; int v3 = NFS_ISV3(vp); struct nfsnode *np = VTONFS(vp); @@ -372,26 +387,32 @@ nfs_access(struct vop_access_args *ap) * Does our cached result allow us to give a definite yes to * this request? */ + gotahit = 0; mtx_lock(&np->n_mtx); - if ((time_second < (np->n_modestamp + nfsaccess_cache_timeout)) && - (ap->a_cred->cr_uid == np->n_modeuid) && - ((np->n_mode & mode) == mode)) { - nfsstats.accesscache_hits++; - } else { + for (i = 0; i < NFS_ACCESSCACHESIZE; i++) { + if (ap->a_cred->cr_uid == np->n_accesscache[i].uid) { + if (time_second < (np->n_accesscache[i].stamp + + nfsaccess_cache_timeout) && + (np->n_accesscache[i].mode & mode) == mode) { + nfsstats.accesscache_hits++; + gotahit = 1; + } + break; + } + } + mtx_unlock(&np->n_mtx); + if (gotahit == 0) { /* * Either a no, or a don't know. Go to the wire. */ nfsstats.accesscache_misses++; - mtx_unlock(&np->n_mtx); - error = nfs3_access_otw(vp, wmode, ap->a_td,ap->a_cred); - mtx_lock(&np->n_mtx); + error = nfs3_access_otw(vp, wmode, ap->a_td, ap->a_cred, + &rmode); if (!error) { - if ((np->n_mode & mode) != mode) { + if ((rmode & mode) != mode) error = EACCES; - } } } - mtx_unlock(&np->n_mtx); return (error); } else { if ((error = nfsspec_access(ap)) != 0) { @@ -651,7 +672,7 @@ nfs_getattr(struct vop_getattr_args *ap) goto nfsmout; if (v3 && nfs_prime_access_cache && nfsaccess_cache_timeout > 0) { nfsstats.accesscache_misses++; - nfs3_access_otw(vp, NFSV3ACCESS_ALL, td, ap->a_cred); + nfs3_access_otw(vp, NFSV3ACCESS_ALL, td, ap->a_cred, NULL); if (nfs_getattrcache(vp, &vattr) == 0) goto nfsmout; } @@ -810,7 +831,7 @@ nfs_setattrrpc(struct vnode *vp, struct struct nfsnode *np = VTONFS(vp); caddr_t bpos, dpos; u_int32_t *tl; - int error = 0, wccflag = NFSV3_WCCRATTR; + int error = 0, i, wccflag = NFSV3_WCCRATTR; struct mbuf *mreq, *mrep, *md, *mb; int v3 = NFS_ISV3(vp); @@ -843,7 +864,10 @@ nfs_setattrrpc(struct vnode *vp, struct } nfsm_request(vp, NFSPROC_SETATTR, curthread, cred); if (v3) { - np->n_modestamp = 0; + mtx_lock(&np->n_mtx); + for (i = 0; i < NFS_ACCESSCACHESIZE; i++) + np->n_accesscache[i].stamp = 0; + mtx_unlock(&np->n_mtx); nfsm_wcc_data(vp, wccflag); } else nfsm_loadattr(vp, NULL); Modified: head/sys/nfsclient/nfsnode.h ============================================================================== --- head/sys/nfsclient/nfsnode.h Fri Mar 20 20:55:57 2009 (r190175) +++ head/sys/nfsclient/nfsnode.h Fri Mar 20 21:12:38 2009 (r190176) @@ -84,6 +84,12 @@ struct nfs_attrcache_timestamp { unsigned long nfs_ac_ts_syscalls; }; +struct nfs_accesscache { + u_int32_t mode; /* ACCESS mode cache */ + uid_t uid; /* credentials having mode */ + time_t stamp; /* mode cache timestamp */ +}; + /* * The nfsnode is the nfs equivalent to ufs's inode. Any similarity * is purely coincidental. @@ -104,9 +110,7 @@ struct nfsnode { u_quad_t n_lrev; /* Modify rev for lease */ struct vattr n_vattr; /* Vnode attribute cache */ time_t n_attrstamp; /* Attr. cache timestamp */ - u_int32_t n_mode; /* ACCESS mode cache */ - uid_t n_modeuid; /* credentials having mode */ - time_t n_modestamp; /* mode cache timestamp */ + struct nfs_accesscache n_accesscache[NFS_ACCESSCACHESIZE]; struct timespec n_mtime; /* Prev modify time. */ time_t n_ctime; /* Prev create time. */ time_t n_dmtime; /* Prev dir modify time. */