use mutex and condvar.

This commit is contained in:
yamt 2007-06-01 11:56:03 +00:00
parent 61131eb130
commit 05aaff39ff
5 changed files with 125 additions and 144 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs.h,v 1.64 2007/04/30 23:10:55 yamt Exp $ */ /* $NetBSD: nfs.h,v 1.65 2007/06/01 11:56:03 yamt Exp $ */
/* /*
* Copyright (c) 1989, 1993, 1995 * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
@ -433,7 +433,8 @@ struct nfsuid {
#endif #endif
struct nfssvc_sock { struct nfssvc_sock {
struct simplelock ns_lock; kmutex_t ns_lock;
kcondvar_t ns_cv;
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */ TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
TAILQ_ENTRY(nfssvc_sock) ns_pending; /* List of pending sockets */ TAILQ_ENTRY(nfssvc_sock) ns_pending; /* List of pending sockets */
TAILQ_HEAD(, nfsuid) ns_uidlruhead; TAILQ_HEAD(, nfsuid) ns_uidlruhead;
@ -463,7 +464,6 @@ struct nfssvc_sock {
#define SLP_NEEDQ 0x04 #define SLP_NEEDQ 0x04
#define SLP_DISCONN 0x08 #define SLP_DISCONN 0x08
#define SLP_BUSY 0x10 #define SLP_BUSY 0x10
#define SLP_WANT 0x20
#define SLP_LASTFRAG 0x40 #define SLP_LASTFRAG 0x40
#define SLP_SENDING 0x80 #define SLP_SENDING 0x80
@ -471,7 +471,6 @@ extern TAILQ_HEAD(nfssvc_sockhead, nfssvc_sock) nfssvc_sockhead;
extern struct nfssvc_sockhead nfssvc_sockpending; extern struct nfssvc_sockhead nfssvc_sockpending;
extern int nfssvc_sockhead_flag; extern int nfssvc_sockhead_flag;
#define SLP_INIT 0x01 #define SLP_INIT 0x01
#define SLP_WANTINIT 0x02
/* /*
* One of these structures is allocated for each nfsd. * One of these structures is allocated for each nfsd.
@ -479,6 +478,7 @@ extern int nfssvc_sockhead_flag;
struct nfsd { struct nfsd {
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */ TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
SLIST_ENTRY(nfsd) nfsd_idle; /* List of idle nfsd's */ SLIST_ENTRY(nfsd) nfsd_idle; /* List of idle nfsd's */
kcondvar_t nfsd_cv;
int nfsd_flag; /* NFSD_ flags */ int nfsd_flag; /* NFSD_ flags */
struct nfssvc_sock *nfsd_slp; /* Current socket */ struct nfssvc_sock *nfsd_slp; /* Current socket */
int nfsd_authlen; /* Authenticator len */ int nfsd_authlen; /* Authenticator len */
@ -545,7 +545,8 @@ struct nfsrv_descript {
#define ND_KERBFULL 0x40 #define ND_KERBFULL 0x40
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL) #define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
extern struct simplelock nfsd_slock; extern kmutex_t nfsd_lock;
extern kcondvar_t nfsd_initcv;
extern TAILQ_HEAD(nfsdhead, nfsd) nfsd_head; extern TAILQ_HEAD(nfsdhead, nfsd) nfsd_head;
extern SLIST_HEAD(nfsdidlehead, nfsd) nfsd_idle_head; extern SLIST_HEAD(nfsdidlehead, nfsd) nfsd_idle_head;
extern int nfsd_head_flag; extern int nfsd_head_flag;

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_socket.c,v 1.156 2007/06/01 11:38:44 yamt Exp $ */ /* $NetBSD: nfs_socket.c,v 1.157 2007/06/01 11:56:03 yamt Exp $ */
/* /*
* Copyright (c) 1989, 1991, 1993, 1995 * Copyright (c) 1989, 1991, 1993, 1995
@ -39,7 +39,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_socket.c,v 1.156 2007/06/01 11:38:44 yamt Exp $"); __KERNEL_RCSID(0, "$NetBSD: nfs_socket.c,v 1.157 2007/06/01 11:56:03 yamt Exp $");
#include "fs_nfs.h" #include "fs_nfs.h"
#include "opt_nfs.h" #include "opt_nfs.h"
@ -2183,9 +2183,9 @@ nfsrv_rcv(so, arg, waitflag)
goto dorecs; goto dorecs;
} }
#endif #endif
simple_lock(&slp->ns_lock); mutex_enter(&slp->ns_lock);
slp->ns_flag &= ~SLP_NEEDQ; slp->ns_flag &= ~SLP_NEEDQ;
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
if (so->so_type == SOCK_STREAM) { if (so->so_type == SOCK_STREAM) {
#ifndef NFS_TEST_HEAVY #ifndef NFS_TEST_HEAVY
/* /*
@ -2274,9 +2274,9 @@ dorecs_unlocked:
* Now try and process the request records, non-blocking. * Now try and process the request records, non-blocking.
*/ */
if (setflags) { if (setflags) {
simple_lock(&slp->ns_lock); mutex_enter(&slp->ns_lock);
slp->ns_flag |= setflags; slp->ns_flag |= setflags;
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
} }
if (waitflag == M_DONTWAIT && if (waitflag == M_DONTWAIT &&
(slp->ns_rec || (slp->ns_flag & (SLP_DISCONN | SLP_NEEDQ)) != 0)) { (slp->ns_rec || (slp->ns_flag & (SLP_DISCONN | SLP_NEEDQ)) != 0)) {
@ -2288,21 +2288,21 @@ int
nfsdsock_lock(struct nfssvc_sock *slp, bool waitok) nfsdsock_lock(struct nfssvc_sock *slp, bool waitok)
{ {
simple_lock(&slp->ns_lock); mutex_enter(&slp->ns_lock);
while ((~slp->ns_flag & (SLP_BUSY|SLP_VALID)) == 0) { while ((~slp->ns_flag & (SLP_BUSY|SLP_VALID)) == 0) {
if (!waitok) { if (!waitok) {
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
return EWOULDBLOCK; return EWOULDBLOCK;
} }
slp->ns_flag |= SLP_WANT; cv_wait(&slp->ns_cv, &slp->ns_lock);
ltsleep(&slp->ns_flag, PSOCK, "nslock", 0, &slp->ns_lock);
} }
if ((slp->ns_flag & SLP_VALID) == 0) { if ((slp->ns_flag & SLP_VALID) == 0) {
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
return EINVAL; return EINVAL;
} }
KASSERT((slp->ns_flag & SLP_BUSY) == 0);
slp->ns_flag |= SLP_BUSY; slp->ns_flag |= SLP_BUSY;
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
return 0; return 0;
} }
@ -2311,14 +2311,11 @@ void
nfsdsock_unlock(struct nfssvc_sock *slp) nfsdsock_unlock(struct nfssvc_sock *slp)
{ {
mutex_enter(&slp->ns_lock);
KASSERT((slp->ns_flag & SLP_BUSY) != 0); KASSERT((slp->ns_flag & SLP_BUSY) != 0);
cv_broadcast(&slp->ns_cv);
simple_lock(&slp->ns_lock); slp->ns_flag &= ~SLP_BUSY;
if ((slp->ns_flag & SLP_WANT) != 0) { mutex_exit(&slp->ns_lock);
wakeup(&slp->ns_flag);
}
slp->ns_flag &= ~(SLP_BUSY|SLP_WANT);
simple_unlock(&slp->ns_lock);
} }
int int
@ -2326,18 +2323,17 @@ nfsdsock_drain(struct nfssvc_sock *slp)
{ {
int error = 0; int error = 0;
simple_lock(&slp->ns_lock); mutex_enter(&slp->ns_lock);
if ((slp->ns_flag & SLP_VALID) == 0) { if ((slp->ns_flag & SLP_VALID) == 0) {
error = EINVAL; error = EINVAL;
goto done; goto done;
} }
slp->ns_flag &= ~SLP_VALID; slp->ns_flag &= ~SLP_VALID;
while ((slp->ns_flag & SLP_BUSY) != 0) { while ((slp->ns_flag & SLP_BUSY) != 0) {
slp->ns_flag |= SLP_WANT; cv_wait(&slp->ns_cv, &slp->ns_lock);
ltsleep(&slp->ns_flag, PSOCK, "nsdrain", 0, &slp->ns_lock);
} }
done: done:
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
return error; return error;
} }
@ -2357,6 +2353,7 @@ nfsrv_getstream(slp, waitflag)
u_int32_t recmark; u_int32_t recmark;
int error = 0; int error = 0;
KASSERT((slp->ns_flag & SLP_BUSY) != 0);
for (;;) { for (;;) {
if (slp->ns_reclen == 0) { if (slp->ns_reclen == 0) {
if (slp->ns_cc < NFSX_UNSIGNED) { if (slp->ns_cc < NFSX_UNSIGNED) {
@ -2489,27 +2486,25 @@ nfsrv_wakenfsd(slp)
if ((slp->ns_flag & SLP_VALID) == 0) if ((slp->ns_flag & SLP_VALID) == 0)
return; return;
simple_lock(&nfsd_slock); mutex_enter(&nfsd_lock);
if (slp->ns_flag & SLP_DOREC) { if (slp->ns_flag & SLP_DOREC) {
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
return; return;
} }
nd = SLIST_FIRST(&nfsd_idle_head); nd = SLIST_FIRST(&nfsd_idle_head);
if (nd) { if (nd) {
SLIST_REMOVE_HEAD(&nfsd_idle_head, nfsd_idle); SLIST_REMOVE_HEAD(&nfsd_idle_head, nfsd_idle);
simple_unlock(&nfsd_slock);
if (nd->nfsd_slp) if (nd->nfsd_slp)
panic("nfsd wakeup"); panic("nfsd wakeup");
slp->ns_sref++; slp->ns_sref++;
nd->nfsd_slp = slp; nd->nfsd_slp = slp;
wakeup(nd); cv_signal(&nd->nfsd_cv);
return; } else {
slp->ns_flag |= SLP_DOREC;
nfsd_head_flag |= NFSD_CHECKSLP;
TAILQ_INSERT_TAIL(&nfssvc_sockpending, slp, ns_pending);
} }
slp->ns_flag |= SLP_DOREC; mutex_exit(&nfsd_lock);
nfsd_head_flag |= NFSD_CHECKSLP;
TAILQ_INSERT_TAIL(&nfssvc_sockpending, slp, ns_pending);
simple_unlock(&nfsd_slock);
} }
int int
@ -2522,15 +2517,15 @@ nfsdsock_sendreply(struct nfssvc_sock *slp, struct nfsrv_descript *nd)
nd->nd_mrep = NULL; nd->nd_mrep = NULL;
} }
simple_lock(&slp->ns_lock); mutex_enter(&slp->ns_lock);
if ((slp->ns_flag & SLP_SENDING) != 0) { if ((slp->ns_flag & SLP_SENDING) != 0) {
SIMPLEQ_INSERT_TAIL(&slp->ns_sendq, nd, nd_sendq); SIMPLEQ_INSERT_TAIL(&slp->ns_sendq, nd, nd_sendq);
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
return 0; return 0;
} }
KASSERT(SIMPLEQ_EMPTY(&slp->ns_sendq)); KASSERT(SIMPLEQ_EMPTY(&slp->ns_sendq));
slp->ns_flag |= SLP_SENDING; slp->ns_flag |= SLP_SENDING;
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
again: again:
error = nfs_send(slp->ns_so, nd->nd_nam2, nd->nd_mreq, NULL, curlwp); error = nfs_send(slp->ns_so, nd->nd_nam2, nd->nd_mreq, NULL, curlwp);
@ -2539,16 +2534,16 @@ again:
} }
nfsdreq_free(nd); nfsdreq_free(nd);
simple_lock(&slp->ns_lock); mutex_enter(&slp->ns_lock);
KASSERT((slp->ns_flag & SLP_SENDING) != 0); KASSERT((slp->ns_flag & SLP_SENDING) != 0);
nd = SIMPLEQ_FIRST(&slp->ns_sendq); nd = SIMPLEQ_FIRST(&slp->ns_sendq);
if (nd != NULL) { if (nd != NULL) {
SIMPLEQ_REMOVE_HEAD(&slp->ns_sendq, nd_sendq); SIMPLEQ_REMOVE_HEAD(&slp->ns_sendq, nd_sendq);
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
goto again; goto again;
} }
slp->ns_flag &= ~SLP_SENDING; slp->ns_flag &= ~SLP_SENDING;
simple_unlock(&slp->ns_lock); mutex_exit(&slp->ns_lock);
return error; return error;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_srvcache.c,v 1.39 2007/03/12 18:18:36 ad Exp $ */ /* $NetBSD: nfs_srvcache.c,v 1.40 2007/06/01 11:56:03 yamt Exp $ */
/* /*
* Copyright (c) 1989, 1993 * Copyright (c) 1989, 1993
@ -41,12 +41,13 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_srvcache.c,v 1.39 2007/03/12 18:18:36 ad Exp $"); __KERNEL_RCSID(0, "$NetBSD: nfs_srvcache.c,v 1.40 2007/06/01 11:56:03 yamt Exp $");
#include "opt_iso.h" #include "opt_iso.h"
#include <sys/param.h> #include <sys/param.h>
#include <sys/vnode.h> #include <sys/vnode.h>
#include <sys/condvar.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -55,6 +56,7 @@ __KERNEL_RCSID(0, "$NetBSD: nfs_srvcache.c,v 1.39 2007/03/12 18:18:36 ad Exp $")
#include <sys/pool.h> #include <sys/pool.h>
#include <sys/mbuf.h> #include <sys/mbuf.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/socketvar.h> #include <sys/socketvar.h>
@ -78,7 +80,7 @@ struct pool nfs_reqcache_pool;
(&nfsrvhashtbl[((xid) + ((xid) >> 24)) & nfsrvhash]) (&nfsrvhashtbl[((xid) + ((xid) >> 24)) & nfsrvhash])
LIST_HEAD(nfsrvhash, nfsrvcache) *nfsrvhashtbl; LIST_HEAD(nfsrvhash, nfsrvcache) *nfsrvhashtbl;
TAILQ_HEAD(nfsrvlru, nfsrvcache) nfsrvlruhead; TAILQ_HEAD(nfsrvlru, nfsrvcache) nfsrvlruhead;
struct simplelock nfsrv_reqcache_lock = SIMPLELOCK_INITIALIZER; kmutex_t nfsrv_reqcache_lock;
u_long nfsrvhash; u_long nfsrvhash;
#if defined(MBUFTRACE) #if defined(MBUFTRACE)
@ -162,6 +164,7 @@ void
nfsrv_initcache() nfsrv_initcache()
{ {
mutex_init(&nfsrv_reqcache_lock, MUTEX_DRIVER, IPL_NONE);
nfsrvhashtbl = hashinit(desirednfsrvcache, HASH_LIST, M_NFSD, nfsrvhashtbl = hashinit(desirednfsrvcache, HASH_LIST, M_NFSD,
M_WAITOK, &nfsrvhash); M_WAITOK, &nfsrvhash);
TAILQ_INIT(&nfsrvlruhead); TAILQ_INIT(&nfsrvlruhead);
@ -179,7 +182,7 @@ nfsrv_lookupcache(nd)
{ {
struct nfsrvcache *rp; struct nfsrvcache *rp;
LOCK_ASSERT(simple_lock_held(&nfsrv_reqcache_lock)); KASSERT(mutex_owned(&nfsrv_reqcache_lock));
loop: loop:
LIST_FOREACH(rp, NFSRCHASH(nd->nd_retxid), rc_hash) { LIST_FOREACH(rp, NFSRCHASH(nd->nd_retxid), rc_hash) {
@ -187,9 +190,7 @@ loop:
nd->nd_procnum == rp->rc_proc && nd->nd_procnum == rp->rc_proc &&
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) { netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
if ((rp->rc_flag & RC_LOCKED) != 0) { if ((rp->rc_flag & RC_LOCKED) != 0) {
rp->rc_flag |= RC_WANTED; cv_wait(&rp->rc_cv, &nfsrv_reqcache_lock);
(void) ltsleep(rp, PZERO - 1, "nfsrc", 0,
&nfsrv_reqcache_lock);
goto loop; goto loop;
} }
rp->rc_flag |= RC_LOCKED; rp->rc_flag |= RC_LOCKED;
@ -208,13 +209,10 @@ nfsrv_unlockcache(rp)
struct nfsrvcache *rp; struct nfsrvcache *rp;
{ {
LOCK_ASSERT(simple_lock_held(&nfsrv_reqcache_lock)); KASSERT(mutex_owned(&nfsrv_reqcache_lock));
rp->rc_flag &= ~RC_LOCKED; rp->rc_flag &= ~RC_LOCKED;
if (rp->rc_flag & RC_WANTED) { cv_broadcast(&rp->rc_cv);
rp->rc_flag &= ~RC_WANTED;
wakeup(rp);
}
} }
/* /*
@ -243,17 +241,17 @@ nfsrv_getcache(nd, slp, repp)
char *bpos; char *bpos;
int ret; int ret;
simple_lock(&nfsrv_reqcache_lock); mutex_enter(&nfsrv_reqcache_lock);
rp = nfsrv_lookupcache(nd); rp = nfsrv_lookupcache(nd);
if (rp) { if (rp) {
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
found: found:
/* If not at end of LRU chain, move it there */ /* If not at end of LRU chain, move it there */
if (TAILQ_NEXT(rp, rc_lru)) { /* racy but ok */ if (TAILQ_NEXT(rp, rc_lru)) { /* racy but ok */
simple_lock(&nfsrv_reqcache_lock); mutex_enter(&nfsrv_reqcache_lock);
TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru); TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru); TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
} }
if (rp->rc_state == RC_UNUSED) if (rp->rc_state == RC_UNUSED)
panic("nfsrv cache"); panic("nfsrv cache");
@ -275,30 +273,30 @@ found:
rp->rc_state = RC_INPROG; rp->rc_state = RC_INPROG;
ret = RC_DOIT; ret = RC_DOIT;
} }
simple_lock(&nfsrv_reqcache_lock); mutex_enter(&nfsrv_reqcache_lock);
nfsrv_unlockcache(rp); nfsrv_unlockcache(rp);
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
return ret; return ret;
} }
nfsstats.srvcache_misses++; nfsstats.srvcache_misses++;
if (numnfsrvcache < desirednfsrvcache) { if (numnfsrvcache < desirednfsrvcache) {
numnfsrvcache++; numnfsrvcache++;
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
rp = pool_get(&nfs_reqcache_pool, PR_WAITOK); rp = pool_get(&nfs_reqcache_pool, PR_WAITOK);
memset(rp, 0, sizeof *rp); memset(rp, 0, sizeof *rp);
cv_init(&rp->rc_cv, "nfsdrc");
rp->rc_flag = RC_LOCKED; rp->rc_flag = RC_LOCKED;
} else { } else {
rp = TAILQ_FIRST(&nfsrvlruhead); rp = TAILQ_FIRST(&nfsrvlruhead);
while ((rp->rc_flag & RC_LOCKED) != 0) { while ((rp->rc_flag & RC_LOCKED) != 0) {
rp->rc_flag |= RC_WANTED; rp->rc_flag |= RC_WANTED;
(void) ltsleep(rp, PZERO-1, "nfsrc", 0, cv_wait(&rp->rc_cv, &nfsrv_reqcache_lock);
&nfsrv_reqcache_lock);
rp = TAILQ_FIRST(&nfsrvlruhead); rp = TAILQ_FIRST(&nfsrvlruhead);
} }
rp->rc_flag |= RC_LOCKED; rp->rc_flag |= RC_LOCKED;
LIST_REMOVE(rp, rc_hash); LIST_REMOVE(rp, rc_hash);
TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru); TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
cleanentry(rp); cleanentry(rp);
rp->rc_flag &= (RC_LOCKED | RC_WANTED); rp->rc_flag &= (RC_LOCKED | RC_WANTED);
} }
@ -318,13 +316,14 @@ found:
break; break;
}; };
rp->rc_proc = nd->nd_procnum; rp->rc_proc = nd->nd_procnum;
simple_lock(&nfsrv_reqcache_lock); mutex_enter(&nfsrv_reqcache_lock);
rpdup = nfsrv_lookupcache(nd); rpdup = nfsrv_lookupcache(nd);
if (rpdup != NULL) { if (rpdup != NULL) {
/* /*
* other thread made duplicate cache entry. * other thread made duplicate cache entry.
*/ */
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
cv_destroy(&rp->rc_cv);
pool_put(&nfs_reqcache_pool, rp); pool_put(&nfs_reqcache_pool, rp);
rp = rpdup; rp = rpdup;
goto found; goto found;
@ -332,7 +331,7 @@ found:
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru); TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
LIST_INSERT_HEAD(NFSRCHASH(nd->nd_retxid), rp, rc_hash); LIST_INSERT_HEAD(NFSRCHASH(nd->nd_retxid), rp, rc_hash);
nfsrv_unlockcache(rp); nfsrv_unlockcache(rp);
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
return RC_DOIT; return RC_DOIT;
} }
@ -347,9 +346,9 @@ nfsrv_updatecache(nd, repvalid, repmbuf)
{ {
struct nfsrvcache *rp; struct nfsrvcache *rp;
simple_lock(&nfsrv_reqcache_lock); mutex_enter(&nfsrv_reqcache_lock);
rp = nfsrv_lookupcache(nd); rp = nfsrv_lookupcache(nd);
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
if (rp) { if (rp) {
cleanentry(rp); cleanentry(rp);
rp->rc_state = RC_DONE; rp->rc_state = RC_DONE;
@ -369,9 +368,9 @@ nfsrv_updatecache(nd, repvalid, repmbuf)
rp->rc_flag |= RC_REPMBUF; rp->rc_flag |= RC_REPMBUF;
} }
} }
simple_lock(&nfsrv_reqcache_lock); mutex_enter(&nfsrv_reqcache_lock);
nfsrv_unlockcache(rp); nfsrv_unlockcache(rp);
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
} }
} }
@ -383,15 +382,16 @@ nfsrv_cleancache()
{ {
struct nfsrvcache *rp, *nextrp; struct nfsrvcache *rp, *nextrp;
simple_lock(&nfsrv_reqcache_lock); mutex_enter(&nfsrv_reqcache_lock);
for (rp = TAILQ_FIRST(&nfsrvlruhead); rp != 0; rp = nextrp) { for (rp = TAILQ_FIRST(&nfsrvlruhead); rp != 0; rp = nextrp) {
nextrp = TAILQ_NEXT(rp, rc_lru); nextrp = TAILQ_NEXT(rp, rc_lru);
LIST_REMOVE(rp, rc_hash); LIST_REMOVE(rp, rc_hash);
TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru); TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
KASSERT((rp->rc_flag & (RC_LOCKED|RC_WANTED)) == 0); KASSERT((rp->rc_flag & (RC_LOCKED|RC_WANTED)) == 0);
cleanentry(rp); cleanentry(rp);
cv_destroy(&rp->rc_cv);
pool_put(&nfs_reqcache_pool, rp); pool_put(&nfs_reqcache_pool, rp);
} }
numnfsrvcache = 0; numnfsrvcache = 0;
simple_unlock(&nfsrv_reqcache_lock); mutex_exit(&nfsrv_reqcache_lock);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_syscalls.c,v 1.110 2007/04/30 10:30:51 yamt Exp $ */ /* $NetBSD: nfs_syscalls.c,v 1.111 2007/06/01 11:56:03 yamt Exp $ */
/* /*
* Copyright (c) 1989, 1993 * Copyright (c) 1989, 1993
@ -35,7 +35,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_syscalls.c,v 1.110 2007/04/30 10:30:51 yamt Exp $"); __KERNEL_RCSID(0, "$NetBSD: nfs_syscalls.c,v 1.111 2007/06/01 11:56:03 yamt Exp $");
#include "fs_nfs.h" #include "fs_nfs.h"
#include "opt_nfs.h" #include "opt_nfs.h"
@ -98,15 +98,15 @@ struct nfssvc_sock *nfs_cltpsock;
struct nfssvc_sock *nfs_udp6sock; struct nfssvc_sock *nfs_udp6sock;
#endif #endif
int nuidhash_max = NFS_MAXUIDHASH; int nuidhash_max = NFS_MAXUIDHASH;
int nfsd_waiting = 0;
#ifdef NFSSERVER #ifdef NFSSERVER
static int nfs_numnfsd = 0; static int nfs_numnfsd = 0;
static struct nfsdrt nfsdrt; static struct nfsdrt nfsdrt;
#endif #endif
#ifdef NFSSERVER #ifdef NFSSERVER
struct simplelock nfsd_slock = SIMPLELOCK_INITIALIZER; kmutex_t nfsd_lock;
struct nfssvc_sockhead nfssvc_sockhead; struct nfssvc_sockhead nfssvc_sockhead;
kcondvar_t nfsd_initcv;
struct nfssvc_sockhead nfssvc_sockpending; struct nfssvc_sockhead nfssvc_sockpending;
struct nfsdhead nfsd_head; struct nfsdhead nfsd_head;
struct nfsdidlehead nfsd_idle_head; struct nfsdidlehead nfsd_idle_head;
@ -149,7 +149,6 @@ sys_nfssvc(struct lwp *l, void *v, register_t *retval)
} */ *uap = v; } */ *uap = v;
int error; int error;
#ifdef NFSSERVER #ifdef NFSSERVER
int s;
struct file *fp; struct file *fp;
struct mbuf *nam; struct mbuf *nam;
struct nfsd_args nfsdarg; struct nfsd_args nfsdarg;
@ -171,15 +170,11 @@ sys_nfssvc(struct lwp *l, void *v, register_t *retval)
nfs_init(); nfs_init();
#ifdef NFSSERVER #ifdef NFSSERVER
s = splsoftnet(); mutex_enter(&nfsd_lock);
simple_lock(&nfsd_slock);
while (nfssvc_sockhead_flag & SLP_INIT) { while (nfssvc_sockhead_flag & SLP_INIT) {
nfssvc_sockhead_flag |= SLP_WANTINIT; cv_wait(&nfsd_initcv, &nfsd_lock);
(void) ltsleep(&nfssvc_sockhead, PSOCK, "nfsd init", 0,
&nfsd_slock);
} }
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
splx(s);
#endif #endif
if (SCARG(uap, flag) & NFSSVC_BIOD) { if (SCARG(uap, flag) & NFSSVC_BIOD) {
#if defined(NFS) && defined(COMPAT_14) #if defined(NFS) && defined(COMPAT_14)
@ -353,20 +348,18 @@ static struct nfssvc_sock *
nfsrv_sockalloc() nfsrv_sockalloc()
{ {
struct nfssvc_sock *slp; struct nfssvc_sock *slp;
int s;
slp = (struct nfssvc_sock *) slp = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
memset(slp, 0, sizeof (struct nfssvc_sock)); memset(slp, 0, sizeof (struct nfssvc_sock));
simple_lock_init(&slp->ns_lock); mutex_init(&slp->ns_lock, MUTEX_DRIVER, IPL_SOFTNET);
cv_init(&slp->ns_cv, "nfsdsock");
TAILQ_INIT(&slp->ns_uidlruhead); TAILQ_INIT(&slp->ns_uidlruhead);
LIST_INIT(&slp->ns_tq); LIST_INIT(&slp->ns_tq);
SIMPLEQ_INIT(&slp->ns_sendq); SIMPLEQ_INIT(&slp->ns_sendq);
s = splsoftnet(); mutex_enter(&nfsd_lock);
simple_lock(&nfsd_slock);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain); TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
splx(s);
return slp; return slp;
} }
@ -378,6 +371,8 @@ nfsrv_sockfree(struct nfssvc_sock *slp)
KASSERT(slp->ns_so == NULL); KASSERT(slp->ns_so == NULL);
KASSERT(slp->ns_fp == NULL); KASSERT(slp->ns_fp == NULL);
KASSERT((slp->ns_flag & SLP_VALID) == 0); KASSERT((slp->ns_flag & SLP_VALID) == 0);
mutex_destroy(&slp->ns_lock);
cv_destroy(&slp->ns_cv);
free(slp, M_NFSSVC); free(slp, M_NFSSVC);
} }
@ -459,9 +454,9 @@ nfssvc_addsock(fp, mynam)
so->so_rcv.sb_timeo = 0; so->so_rcv.sb_timeo = 0;
so->so_snd.sb_flags &= ~SB_NOINTR; so->so_snd.sb_flags &= ~SB_NOINTR;
so->so_snd.sb_timeo = 0; so->so_snd.sb_timeo = 0;
if (tslp) if (tslp) {
slp = tslp; slp = tslp;
else { } else {
slp = nfsrv_sockalloc(); slp = nfsrv_sockalloc();
} }
slp->ns_so = so; slp->ns_so = so;
@ -472,7 +467,7 @@ nfssvc_addsock(fp, mynam)
so->so_upcallarg = (void *)slp; so->so_upcallarg = (void *)slp;
so->so_upcall = nfsrv_rcv; so->so_upcall = nfsrv_rcv;
so->so_rcv.sb_flags |= SB_UPCALL; so->so_rcv.sb_flags |= SB_UPCALL;
slp->ns_flag = (SLP_VALID | SLP_NEEDQ); slp->ns_flag = SLP_VALID | SLP_NEEDQ;
nfsrv_wakenfsd(slp); nfsrv_wakenfsd(slp);
splx(s); splx(s);
return (0); return (0);
@ -495,23 +490,24 @@ nfssvc_nfsd(nsd, argp, l)
struct nfsrv_descript *nd = NULL; struct nfsrv_descript *nd = NULL;
struct mbuf *mreq; struct mbuf *mreq;
u_quad_t cur_usec; u_quad_t cur_usec;
int error = 0, cacherep, s, siz, sotype, writes_todo; int error = 0, cacherep, siz, sotype, writes_todo;
struct proc *p = l->l_proc; struct proc *p = l->l_proc;
int s;
#ifndef nolint #ifndef nolint
cacherep = RC_DOIT; cacherep = RC_DOIT;
writes_todo = 0; writes_todo = 0;
#endif #endif
s = splsoftnet(); if (nfsd == NULL) {
if (nfsd == (struct nfsd *)0) { nsd->nsd_nfsd = nfsd =
nsd->nsd_nfsd = nfsd = (struct nfsd *)
malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK); malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
memset((void *)nfsd, 0, sizeof (struct nfsd)); memset(nfsd, 0, sizeof (struct nfsd));
cv_init(&nfsd->nfsd_cv, "nfsd");
nfsd->nfsd_procp = p; nfsd->nfsd_procp = p;
simple_lock(&nfsd_slock); mutex_enter(&nfsd_lock);
TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain); TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
nfs_numnfsd++; nfs_numnfsd++;
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
} }
PHOLD(l); PHOLD(l);
/* /*
@ -519,22 +515,19 @@ nfssvc_nfsd(nsd, argp, l)
*/ */
for (;;) { for (;;) {
if (nfsd->nfsd_slp == NULL) { if (nfsd->nfsd_slp == NULL) {
simple_lock(&nfsd_slock); mutex_enter(&nfsd_lock);
while (nfsd->nfsd_slp == NULL && while (nfsd->nfsd_slp == NULL &&
(nfsd_head_flag & NFSD_CHECKSLP) == 0) { (nfsd_head_flag & NFSD_CHECKSLP) == 0) {
SLIST_INSERT_HEAD(&nfsd_idle_head, nfsd, SLIST_INSERT_HEAD(&nfsd_idle_head, nfsd,
nfsd_idle); nfsd_idle);
nfsd_waiting++; error = cv_wait_sig(&nfsd->nfsd_cv, &nfsd_lock);
error = ltsleep(nfsd, PSOCK | PCATCH, "nfsd",
0, &nfsd_slock);
nfsd_waiting--;
if (error) { if (error) {
slp = nfsd->nfsd_slp; slp = nfsd->nfsd_slp;
nfsd->nfsd_slp = NULL; nfsd->nfsd_slp = NULL;
if (!slp) if (!slp)
SLIST_REMOVE(&nfsd_idle_head, SLIST_REMOVE(&nfsd_idle_head,
nfsd, nfsd, nfsd_idle); nfsd, nfsd, nfsd_idle);
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
if (slp) { if (slp) {
nfsrv_wakenfsd(slp); nfsrv_wakenfsd(slp);
nfsrv_slpderef(slp); nfsrv_slpderef(slp);
@ -557,7 +550,7 @@ nfssvc_nfsd(nsd, argp, l)
} else } else
nfsd_head_flag &= ~NFSD_CHECKSLP; nfsd_head_flag &= ~NFSD_CHECKSLP;
} }
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
if ((slp = nfsd->nfsd_slp) == NULL) if ((slp = nfsd->nfsd_slp) == NULL)
continue; continue;
if (slp->ns_flag & SLP_VALID) { if (slp->ns_flag & SLP_VALID) {
@ -596,7 +589,6 @@ nfssvc_nfsd(nsd, argp, l)
nfsrv_slpderef(slp); nfsrv_slpderef(slp);
continue; continue;
} }
splx(s);
sotype = slp->ns_so->so_type; sotype = slp->ns_so->so_type;
if (nd) { if (nd) {
getmicrotime(&nd->nd_starttime); getmicrotime(&nd->nd_starttime);
@ -736,7 +728,6 @@ nfssvc_nfsd(nsd, argp, l)
nfsd_rt(slp->ns_so->so_type, nd, nfsd_rt(slp->ns_so->so_type, nd,
cacherep); cacherep);
} }
s = splsoftnet();
error = nfsdsock_sendreply(slp, nd); error = nfsdsock_sendreply(slp, nd);
nd = NULL; nd = NULL;
if (error == EPIPE) if (error == EPIPE)
@ -745,7 +736,6 @@ nfssvc_nfsd(nsd, argp, l)
nfsrv_slpderef(slp); nfsrv_slpderef(slp);
goto done; goto done;
} }
splx(s);
break; break;
case RC_DROPIT: case RC_DROPIT:
if (nfsrtton) if (nfsrtton)
@ -775,7 +765,6 @@ nfssvc_nfsd(nsd, argp, l)
writes_todo = 0; writes_todo = 0;
splx(s); splx(s);
} while (writes_todo); } while (writes_todo);
s = splsoftnet();
if (nfsrv_dorec(slp, nfsd, &nd)) { if (nfsrv_dorec(slp, nfsd, &nd)) {
nfsd->nfsd_slp = NULL; nfsd->nfsd_slp = NULL;
nfsrv_slpderef(slp); nfsrv_slpderef(slp);
@ -783,12 +772,12 @@ nfssvc_nfsd(nsd, argp, l)
} }
done: done:
PRELE(l); PRELE(l);
simple_lock(&nfsd_slock); mutex_enter(&nfsd_lock);
TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain); TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
splx(s); cv_destroy(&nfsd->nfsd_cv);
free((void *)nfsd, M_NFSD); free(nfsd, M_NFSD);
nsd->nsd_nfsd = (struct nfsd *)0; nsd->nsd_nfsd = NULL;
if (--nfs_numnfsd == 0) if (--nfs_numnfsd == 0)
nfsrv_init(true); /* Reinitialize everything */ nfsrv_init(true); /* Reinitialize everything */
return (error); return (error);
@ -816,11 +805,11 @@ nfsrv_zapsock(slp)
if (nfsdsock_drain(slp)) { if (nfsdsock_drain(slp)) {
return; return;
} }
simple_lock(&nfsd_slock); mutex_enter(&nfsd_lock);
if (slp->ns_flag & SLP_DOREC) { if (slp->ns_flag & SLP_DOREC) {
TAILQ_REMOVE(&nfssvc_sockpending, slp, ns_pending); TAILQ_REMOVE(&nfssvc_sockpending, slp, ns_pending);
} }
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
so = slp->ns_so; so = slp->ns_so;
KASSERT(so != NULL); KASSERT(so != NULL);
@ -866,15 +855,13 @@ void
nfsrv_slpderef(slp) nfsrv_slpderef(slp)
struct nfssvc_sock *slp; struct nfssvc_sock *slp;
{ {
LOCK_ASSERT(!simple_lock_held(&nfsd_slock));
if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) { if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {
struct file *fp; struct file *fp;
int s = splsoftnet();
simple_lock(&nfsd_slock); mutex_enter(&nfsd_lock);
TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
splx(s);
fp = slp->ns_fp; fp = slp->ns_fp;
if (fp != NULL) { if (fp != NULL) {
@ -901,35 +888,35 @@ nfsrv_init(terminating)
int terminating; int terminating;
{ {
struct nfssvc_sock *slp; struct nfssvc_sock *slp;
int s;
s = splsoftnet(); if (!terminating) {
simple_lock(&nfsd_slock); mutex_init(&nfsd_lock, MUTEX_DRIVER, IPL_SOFTNET);
cv_init(&nfsd_initcv, "nfsdinit");
}
mutex_enter(&nfsd_lock);
if (nfssvc_sockhead_flag & SLP_INIT) if (nfssvc_sockhead_flag & SLP_INIT)
panic("nfsd init"); panic("nfsd init");
nfssvc_sockhead_flag |= SLP_INIT; nfssvc_sockhead_flag |= SLP_INIT;
if (terminating) { if (terminating) {
while ((slp = TAILQ_FIRST(&nfssvc_sockhead)) != NULL) { while ((slp = TAILQ_FIRST(&nfssvc_sockhead)) != NULL) {
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
KASSERT(slp->ns_sref == 0); KASSERT(slp->ns_sref == 0);
slp->ns_sref++; slp->ns_sref++;
nfsrv_zapsock(slp); nfsrv_zapsock(slp);
nfsrv_slpderef(slp); nfsrv_slpderef(slp);
simple_lock(&nfsd_slock); mutex_enter(&nfsd_lock);
} }
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
splx(s);
nfsrv_cleancache(); /* And clear out server cache */ nfsrv_cleancache(); /* And clear out server cache */
} else { } else {
simple_unlock(&nfsd_slock); mutex_exit(&nfsd_lock);
splx(s);
nfs_pub.np_valid = 0; nfs_pub.np_valid = 0;
} }
TAILQ_INIT(&nfssvc_sockhead); TAILQ_INIT(&nfssvc_sockhead);
TAILQ_INIT(&nfssvc_sockpending); TAILQ_INIT(&nfssvc_sockpending);
nfssvc_sockhead_flag &= ~SLP_INIT;
TAILQ_INIT(&nfsd_head); TAILQ_INIT(&nfsd_head);
SLIST_INIT(&nfsd_idle_head); SLIST_INIT(&nfsd_idle_head);
@ -945,13 +932,10 @@ nfsrv_init(terminating)
nfs_cltpsock = nfsrv_sockalloc(); nfs_cltpsock = nfsrv_sockalloc();
#endif #endif
simple_lock(&nfsd_slock); mutex_enter(&nfsd_lock);
if (nfssvc_sockhead_flag & SLP_WANTINIT) { nfssvc_sockhead_flag &= ~SLP_INIT;
nfssvc_sockhead_flag &= ~SLP_WANTINIT; cv_broadcast(&nfsd_initcv);
wakeup(&nfssvc_sockhead); mutex_exit(&nfsd_lock);
}
simple_unlock(&nfsd_slock);
splx(s);
} }
/* /*

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfsrvcache.h,v 1.14 2006/12/28 00:39:03 yamt Exp $ */ /* $NetBSD: nfsrvcache.h,v 1.15 2007/06/01 11:56:04 yamt Exp $ */
/* /*
* Copyright (c) 1989, 1993 * Copyright (c) 1989, 1993
@ -45,6 +45,7 @@
#define NFSRVCACHESIZ 64 #define NFSRVCACHESIZ 64
struct nfsrvcache { struct nfsrvcache {
kcondvar_t rc_cv;
TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */ TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */
LIST_ENTRY(nfsrvcache) rc_hash; /* Hash chain */ LIST_ENTRY(nfsrvcache) rc_hash; /* Hash chain */
u_int32_t rc_xid; /* rpc id number */ u_int32_t rc_xid; /* rpc id number */