/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*/
#include <sys/param.h>
#include <sys/vnode.h>
-#include <sys/mount.h>
+#include <sys/mount_internal.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/proc.h>
-#include <sys/mbuf.h>
+#include <sys/kpi_mbuf.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/socketvar.h> /* for dup_sockaddr */
+#include <libkern/OSAtomic.h>
#include <netinet/in.h>
#if ISO
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)
FALSE,
FALSE,
FALSE,
- FALSE,
- FALSE,
- FALSE,
};
/* True iff the rpc reply is an nfs status ONLY! */
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);
*/
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.
*/
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);
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;
}
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);
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;
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;
rp->rc_flag &= ~RC_WANTED;
wakeup((caddr_t)rp);
}
+ lck_mtx_unlock(nfsrv_reqcache_mutex);
return (RC_DOIT);
}
*/
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);
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;
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);
}
/*
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);
_FREE(rp, M_NFSD);
}
numnfsrvcache = 0;
+ lck_mtx_unlock(nfsrv_reqcache_mutex);
}
#endif /* NFS_NOSERVER */