X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/e5568f75972dfc723778653c11cb6b4dc825716a..c0fea4742e91338fffdcf79f86a7c1d5e2b97eb1:/bsd/nfs/nfs_srvcache.c diff --git a/bsd/nfs/nfs_srvcache.c b/bsd/nfs/nfs_srvcache.c index 9e7007ddb..c15362dad 100644 --- a/bsd/nfs/nfs_srvcache.c +++ b/bsd/nfs/nfs_srvcache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -67,14 +67,15 @@ */ #include #include -#include +#include #include #include #include -#include +#include #include #include #include /* for dup_sockaddr */ +#include #include #if ISO @@ -96,8 +97,10 @@ LIST_HEAD(nfsrvhash, nfsrvcache) *nfsrvhashtbl; TAILQ_HEAD(nfsrvlru, nfsrvcache) nfsrvlruhead; u_long nfsrvhash; -#define TRUE 1 -#define FALSE 0 +lck_grp_t *nfsrv_reqcache_lck_grp; +lck_grp_attr_t *nfsrv_reqcache_lck_grp_attr; +lck_attr_t *nfsrv_reqcache_lck_attr; +lck_mtx_t *nfsrv_reqcache_mutex; #define NETFAMILY(rp) \ (((rp)->rc_flag & RC_INETADDR) ? AF_INET : AF_ISO) @@ -129,9 +132,6 @@ static int nonidempotent[NFS_NPROCS] = { FALSE, FALSE, FALSE, - FALSE, - FALSE, - FALSE, }; /* True iff the rpc reply is an nfs status ONLY! */ @@ -162,6 +162,11 @@ static int nfsv2_repstat[NFS_NPROCS] = { void nfsrv_initcache() { + /* init nfs server request cache mutex */ + nfsrv_reqcache_lck_grp_attr = lck_grp_attr_alloc_init(); + nfsrv_reqcache_lck_grp = lck_grp_alloc_init("nfsrv_reqcache", nfsrv_reqcache_lck_grp_attr); + nfsrv_reqcache_lck_attr = lck_attr_alloc_init(); + nfsrv_reqcache_mutex = lck_mtx_alloc_init(nfsrv_reqcache_lck_grp, nfsrv_reqcache_lck_attr); nfsrvhashtbl = hashinit(desirednfsrvcache, M_NFSD, &nfsrvhash); TAILQ_INIT(&nfsrvlruhead); @@ -183,15 +188,15 @@ nfsrv_initcache() */ int nfsrv_getcache(nd, slp, repp) - register struct nfsrv_descript *nd; + struct nfsrv_descript *nd; struct nfssvc_sock *slp; - struct mbuf **repp; + mbuf_t *repp; { - register struct nfsrvcache *rp; - struct mbuf *mb; + struct nfsrvcache *rp; + mbuf_t mb; struct sockaddr_in *saddr; caddr_t bpos; - int ret; + int ret, error; /* * Don't cache recent requests for reliable transport protocols. @@ -199,12 +204,12 @@ nfsrv_getcache(nd, slp, repp) */ if (!nd->nd_nam2) return (RC_DOIT); + lck_mtx_lock(nfsrv_reqcache_mutex); loop: for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0; rp = rp->rc_hash.le_next) { if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc && netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) { - NFS_DPF(RC, ("H%03x", rp->rc_xid & 0xfff)); if ((rp->rc_flag & RC_LOCKED) != 0) { rp->rc_flag |= RC_WANTED; (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0); @@ -219,20 +224,23 @@ loop: if (rp->rc_state == RC_UNUSED) panic("nfsrv cache"); if (rp->rc_state == RC_INPROG) { - nfsstats.srvcache_inproghits++; + OSAddAtomic(1, (SInt32*)&nfsstats.srvcache_inproghits); ret = RC_DROPIT; } else if (rp->rc_flag & RC_REPSTATUS) { - nfsstats.srvcache_nonidemdonehits++; - nfs_rephead(0, nd, slp, rp->rc_status, - 0, (u_quad_t *)0, repp, &mb, &bpos); + OSAddAtomic(1, (SInt32*)&nfsstats.srvcache_nonidemdonehits); + nfs_rephead(0, nd, slp, rp->rc_status, repp, &mb, &bpos); ret = RC_REPLY; } else if (rp->rc_flag & RC_REPMBUF) { - nfsstats.srvcache_nonidemdonehits++; - *repp = m_copym(rp->rc_reply, 0, M_COPYALL, - M_WAIT); - ret = RC_REPLY; + OSAddAtomic(1, (SInt32*)&nfsstats.srvcache_nonidemdonehits); + error = mbuf_copym(rp->rc_reply, 0, MBUF_COPYALL, MBUF_WAITOK, repp); + if (error) { + printf("nfsrv cache: reply copym failed for nonidem request hit\n"); + ret = RC_DROPIT; + } else { + ret = RC_REPLY; + } } else { - nfsstats.srvcache_idemdonehits++; + OSAddAtomic(1, (SInt32*)&nfsstats.srvcache_idemdonehits); rp->rc_state = RC_INPROG; ret = RC_DOIT; } @@ -241,18 +249,31 @@ loop: rp->rc_flag &= ~RC_WANTED; wakeup((caddr_t)rp); } + lck_mtx_unlock(nfsrv_reqcache_mutex); return (ret); } } - nfsstats.srvcache_misses++; - NFS_DPF(RC, ("M%03x", nd->nd_retxid & 0xfff)); + OSAddAtomic(1, (SInt32*)&nfsstats.srvcache_misses); if (numnfsrvcache < desirednfsrvcache) { + /* try to allocate a new entry */ MALLOC(rp, struct nfsrvcache *, sizeof *rp, M_NFSD, M_WAITOK); - bzero((char *)rp, sizeof *rp); - numnfsrvcache++; - rp->rc_flag = RC_LOCKED; + if (rp) { + bzero((char *)rp, sizeof *rp); + numnfsrvcache++; + rp->rc_flag = RC_LOCKED; + } } else { + rp = NULL; + } + if (!rp) { + /* try to reuse the least recently used entry */ rp = nfsrvlruhead.tqh_first; + if (!rp) { + /* no entry to reuse? */ + /* OK, we just won't be able to cache this request */ + lck_mtx_unlock(nfsrv_reqcache_mutex); + return (RC_DOIT); + } while ((rp->rc_flag & RC_LOCKED) != 0) { rp->rc_flag |= RC_WANTED; (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0); @@ -262,15 +283,15 @@ loop: LIST_REMOVE(rp, rc_hash); TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru); if (rp->rc_flag & RC_REPMBUF) - m_freem(rp->rc_reply); + mbuf_freem(rp->rc_reply); if (rp->rc_flag & RC_NAM) - MFREE(rp->rc_nam, mb); + mbuf_freem(rp->rc_nam); rp->rc_flag &= (RC_LOCKED | RC_WANTED); } TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru); rp->rc_state = RC_INPROG; rp->rc_xid = nd->nd_retxid; - saddr = mtod(nd->nd_nam, struct sockaddr_in *); + saddr = mbuf_data(nd->nd_nam); switch (saddr->sin_family) { case AF_INET: rp->rc_flag |= RC_INETADDR; @@ -278,8 +299,11 @@ loop: break; case AF_ISO: default: - rp->rc_flag |= RC_NAM; - rp->rc_nam = m_copym(nd->nd_nam, 0, M_COPYALL, M_WAIT); + error = mbuf_copym(nd->nd_nam, 0, MBUF_COPYALL, MBUF_WAITOK, &rp->rc_nam); + if (error) + printf("nfsrv cache: nam copym failed\n"); + else + rp->rc_flag |= RC_NAM; break; }; rp->rc_proc = nd->nd_procnum; @@ -289,6 +313,7 @@ loop: rp->rc_flag &= ~RC_WANTED; wakeup((caddr_t)rp); } + lck_mtx_unlock(nfsrv_reqcache_mutex); return (RC_DOIT); } @@ -297,20 +322,21 @@ loop: */ void nfsrv_updatecache(nd, repvalid, repmbuf) - register struct nfsrv_descript *nd; + struct nfsrv_descript *nd; int repvalid; - struct mbuf *repmbuf; + mbuf_t repmbuf; { - register struct nfsrvcache *rp; + struct nfsrvcache *rp; + int error; if (!nd->nd_nam2) return; + lck_mtx_lock(nfsrv_reqcache_mutex); loop: for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0; rp = rp->rc_hash.le_next) { if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc && netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) { - NFS_DPF(RC, ("U%03x", rp->rc_xid & 0xfff)); if ((rp->rc_flag & RC_LOCKED) != 0) { rp->rc_flag |= RC_WANTED; (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0); @@ -328,9 +354,9 @@ loop: rp->rc_status = nd->nd_repstat; rp->rc_flag |= RC_REPSTATUS; } else { - rp->rc_reply = m_copym(repmbuf, - 0, M_COPYALL, M_WAIT); - rp->rc_flag |= RC_REPMBUF; + error = mbuf_copym(repmbuf, 0, MBUF_COPYALL, MBUF_WAITOK, &rp->rc_reply); + if (!error) + rp->rc_flag |= RC_REPMBUF; } } rp->rc_flag &= ~RC_LOCKED; @@ -338,10 +364,11 @@ loop: rp->rc_flag &= ~RC_WANTED; wakeup((caddr_t)rp); } + lck_mtx_unlock(nfsrv_reqcache_mutex); return; } } - NFS_DPF(RC, ("L%03x", nd->nd_retxid & 0xfff)); + lck_mtx_unlock(nfsrv_reqcache_mutex); } /* @@ -350,8 +377,9 @@ loop: void nfsrv_cleancache() { - register struct nfsrvcache *rp, *nextrp; + struct nfsrvcache *rp, *nextrp; + lck_mtx_lock(nfsrv_reqcache_mutex); for (rp = nfsrvlruhead.tqh_first; rp != 0; rp = nextrp) { nextrp = rp->rc_lru.tqe_next; LIST_REMOVE(rp, rc_hash); @@ -359,6 +387,7 @@ nfsrv_cleancache() _FREE(rp, M_NFSD); } numnfsrvcache = 0; + lck_mtx_unlock(nfsrv_reqcache_mutex); } #endif /* NFS_NOSERVER */