1 /* $NetBSD: nfs_syscalls.c,v 1.152 2009/12/31 19:38:16 christos Exp $ */
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: nfs_syscalls.c,v 1.152 2009/12/31 19:38:16 christos Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
45 #include <sys/vnode.h>
46 #include <sys/mount.h>
49 #include <sys/malloc.h>
53 #include <sys/socket.h>
54 #include <sys/socketvar.h>
55 #include <sys/signalvar.h>
56 #include <sys/domain.h>
57 #include <sys/protosw.h>
58 #include <sys/namei.h>
59 #include <sys/syslog.h>
60 #include <sys/filedesc.h>
61 #include <sys/kthread.h>
62 #include <sys/kauth.h>
63 #include <sys/syscallargs.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <nfs/xdr_subs.h>
68 #include <nfs/rpcv2.h>
69 #include <nfs/nfsproto.h>
71 #include <nfs/nfsm_subs.h>
72 #include <nfs/nfsrvcache.h>
73 #include <nfs/nfsmount.h>
74 #include <nfs/nfsnode.h>
75 #include <nfs/nfsrtt.h>
76 #include <nfs/nfs_var.h>
78 extern int32_t (*nfsrv3_procs
[NFS_NPROCS
])(struct nfsrv_descript
*,
80 struct lwp
*, struct mbuf
**);
81 extern int nfsrvw_procrastinate
;
82 extern int nuidhash_max
;
84 static int nfs_numnfsd
= 0;
85 static struct nfsdrt nfsdrt
;
87 struct nfssvc_sockhead nfssvc_sockhead
;
88 kcondvar_t nfsd_initcv
;
89 struct nfssvc_sockhead nfssvc_sockpending
;
90 struct nfsdhead nfsd_head
;
91 struct nfsdidlehead nfsd_idle_head
;
93 int nfssvc_sockhead_flag
;
96 struct nfssvc_sock
*nfs_udpsock
;
97 struct nfssvc_sock
*nfs_udp6sock
;
99 static struct nfssvc_sock
*nfsrv_sockalloc(void);
100 static void nfsrv_sockfree(struct nfssvc_sock
*);
101 static void nfsd_rt(int, struct nfsrv_descript
*, int);
104 * NFS server system calls
109 * Nfs server pseudo system call for the nfsd's
110 * Based on the flag value it either:
111 * - adds a socket to the selection list
112 * - remains in the kernel as an nfsd
113 * - remains in the kernel as an nfsiod
116 sys_nfssvc(struct lwp
*l
, const struct sys_nfssvc_args
*uap
, register_t
*retval
)
119 syscallarg(int) flag;
120 syscallarg(void *) argp;
125 struct nfsd_args nfsdarg
;
126 struct nfsd_srvargs nfsd_srvargs
, *nsd
= &nfsd_srvargs
;
128 struct nfssvc_sock
*slp
;
129 struct nfsuid
*nuidp
;
131 error
= kauth_authorize_network(l
->l_cred
, KAUTH_NETWORK_NFS
,
132 KAUTH_REQ_NETWORK_NFS_SVC
, NULL
, NULL
, NULL
);
136 mutex_enter(&nfsd_lock
);
137 while (nfssvc_sockhead_flag
& SLP_INIT
) {
138 cv_wait(&nfsd_initcv
, &nfsd_lock
);
140 mutex_exit(&nfsd_lock
);
142 if (SCARG(uap
, flag
) & NFSSVC_BIOD
) {
143 /* Dummy implementation of nfsios for 1.4 and earlier. */
144 error
= kpause("nfsbiod", true, 0, NULL
);
145 } else if (SCARG(uap
, flag
) & NFSSVC_MNTD
) {
147 } else if (SCARG(uap
, flag
) & NFSSVC_ADDSOCK
) {
148 error
= copyin(SCARG(uap
, argp
), (void *)&nfsdarg
,
152 /* getsock() will use the descriptor for us */
153 if ((fp
= fd_getfile(nfsdarg
.sock
)) == NULL
)
155 if (fp
->f_type
!= DTYPE_SOCKET
) {
156 fd_putfile(nfsdarg
.sock
);
160 * Get the client address for connected sockets.
162 if (nfsdarg
.name
== NULL
|| nfsdarg
.namelen
== 0)
163 nam
= (struct mbuf
*)0;
165 error
= sockargs(&nam
, nfsdarg
.name
, nfsdarg
.namelen
,
168 fd_putfile(nfsdarg
.sock
);
172 error
= nfssvc_addsock(fp
, nam
);
173 fd_putfile(nfsdarg
.sock
);
174 } else if (SCARG(uap
, flag
) & NFSSVC_SETEXPORTSLIST
) {
175 struct export_args
*args
;
176 struct mountd_exports_list mel
;
178 error
= copyin(SCARG(uap
, argp
), &mel
, sizeof(mel
));
182 args
= (struct export_args
*)malloc(mel
.mel_nexports
*
183 sizeof(struct export_args
), M_TEMP
, M_WAITOK
);
184 error
= copyin(mel
.mel_exports
, args
, mel
.mel_nexports
*
185 sizeof(struct export_args
));
190 mel
.mel_exports
= args
;
192 error
= mountd_set_exports_list(&mel
, l
, NULL
);
196 error
= copyin(SCARG(uap
, argp
), (void *)nsd
, sizeof (*nsd
));
199 if ((SCARG(uap
, flag
) & NFSSVC_AUTHIN
) &&
200 ((nfsd
= nsd
->nsd_nfsd
)) != NULL
&&
201 (nfsd
->nfsd_slp
->ns_flags
& SLP_VALID
)) {
202 slp
= nfsd
->nfsd_slp
;
205 * First check to see if another nfsd has already
206 * added this credential.
208 LIST_FOREACH(nuidp
, NUIDHASH(slp
, nsd
->nsd_cr
.cr_uid
),
210 if (kauth_cred_geteuid(nuidp
->nu_cr
) ==
211 nsd
->nsd_cr
.cr_uid
&&
212 (!nfsd
->nfsd_nd
->nd_nam2
||
213 netaddr_match(NU_NETFAM(nuidp
),
214 &nuidp
->nu_haddr
, nfsd
->nfsd_nd
->nd_nam2
)))
218 kauth_cred_hold(nuidp
->nu_cr
);
219 nfsd
->nfsd_nd
->nd_cr
= nuidp
->nu_cr
;
220 nfsd
->nfsd_nd
->nd_flag
|= ND_KERBFULL
;
225 if (slp
->ns_numuids
< nuidhash_max
) {
227 nuidp
= kmem_alloc(sizeof(*nuidp
), KM_SLEEP
);
229 nuidp
= (struct nfsuid
*)0;
230 if ((slp
->ns_flags
& SLP_VALID
) == 0) {
232 kmem_free(nuidp
, sizeof(*nuidp
));
234 if (nuidp
== (struct nfsuid
*)0) {
235 nuidp
= TAILQ_FIRST(&slp
->ns_uidlruhead
);
236 LIST_REMOVE(nuidp
, nu_hash
);
237 TAILQ_REMOVE(&slp
->ns_uidlruhead
, nuidp
,
239 if (nuidp
->nu_flag
& NU_NAM
)
240 m_freem(nuidp
->nu_nam
);
243 kauth_uucred_to_cred(nuidp
->nu_cr
,
245 nuidp
->nu_timestamp
= nsd
->nsd_timestamp
;
246 nuidp
->nu_expire
= time_second
+ nsd
->nsd_ttl
;
248 * and save the session key in nu_key.
250 memcpy(nuidp
->nu_key
, nsd
->nsd_key
,
251 sizeof(nsd
->nsd_key
));
252 if (nfsd
->nfsd_nd
->nd_nam2
) {
253 struct sockaddr_in
*saddr
;
255 saddr
= mtod(nfsd
->nfsd_nd
->nd_nam2
,
256 struct sockaddr_in
*);
257 switch (saddr
->sin_family
) {
259 nuidp
->nu_flag
|= NU_INETADDR
;
261 saddr
->sin_addr
.s_addr
;
264 nuidp
->nu_flag
|= NU_NAM
;
265 nuidp
->nu_nam
= m_copym(
266 nfsd
->nfsd_nd
->nd_nam2
, 0,
273 TAILQ_INSERT_TAIL(&slp
->ns_uidlruhead
, nuidp
,
275 LIST_INSERT_HEAD(NUIDHASH(slp
, nsd
->nsd_uid
),
277 kauth_cred_hold(nuidp
->nu_cr
);
278 nfsd
->nfsd_nd
->nd_cr
= nuidp
->nu_cr
;
279 nfsd
->nfsd_nd
->nd_flag
|= ND_KERBFULL
;
283 if ((SCARG(uap
, flag
) & NFSSVC_AUTHINFAIL
) &&
284 (nfsd
= nsd
->nsd_nfsd
))
285 nfsd
->nfsd_flag
|= NFSD_AUTHFAIL
;
286 error
= nfssvc_nfsd(nsd
, SCARG(uap
, argp
), l
);
288 if (error
== EINTR
|| error
== ERESTART
)
293 static struct nfssvc_sock
*
294 nfsrv_sockalloc(void)
296 struct nfssvc_sock
*slp
;
298 slp
= kmem_alloc(sizeof(*slp
), KM_SLEEP
);
299 memset(slp
, 0, sizeof (struct nfssvc_sock
));
300 mutex_init(&slp
->ns_lock
, MUTEX_DRIVER
, IPL_SOFTNET
);
301 mutex_init(&slp
->ns_alock
, MUTEX_DRIVER
, IPL_SOFTNET
);
302 cv_init(&slp
->ns_cv
, "nfsdsock");
303 TAILQ_INIT(&slp
->ns_uidlruhead
);
304 LIST_INIT(&slp
->ns_tq
);
305 SIMPLEQ_INIT(&slp
->ns_sendq
);
306 mutex_enter(&nfsd_lock
);
307 TAILQ_INSERT_TAIL(&nfssvc_sockhead
, slp
, ns_chain
);
308 mutex_exit(&nfsd_lock
);
314 nfsrv_sockfree(struct nfssvc_sock
*slp
)
317 KASSERT(slp
->ns_so
== NULL
);
318 KASSERT(slp
->ns_fp
== NULL
);
319 KASSERT((slp
->ns_flags
& SLP_VALID
) == 0);
320 mutex_destroy(&slp
->ns_lock
);
321 mutex_destroy(&slp
->ns_alock
);
322 cv_destroy(&slp
->ns_cv
);
323 kmem_free(slp
, sizeof(*slp
));
327 * Adds a socket to the list for servicing by nfsds.
330 nfssvc_addsock(file_t
*fp
, struct mbuf
*mynam
)
333 struct nfssvc_sock
*slp
;
335 struct nfssvc_sock
*tslp
;
339 so
= (struct socket
*)fp
->f_data
;
340 tslp
= (struct nfssvc_sock
*)0;
342 * Add it to the list, as required.
344 if (so
->so_proto
->pr_protocol
== IPPROTO_UDP
) {
345 if (so
->so_proto
->pr_domain
->dom_family
== AF_INET6
)
349 if (tslp
->ns_flags
& SLP_VALID
) {
355 if (so
->so_type
== SOCK_STREAM
)
356 siz
= NFS_MAXPACKET
+ sizeof (u_long
);
360 error
= soreserve(so
, siz
, siz
);
368 * Set protocol specific options { for now TCP only } and
369 * reserve some space. For datagram sockets, this can get called
370 * repeatedly for the same socket, but that isn't harmful.
372 if (so
->so_type
== SOCK_STREAM
) {
374 so_setsockopt(NULL
, so
, SOL_SOCKET
, SO_KEEPALIVE
, &val
,
377 if ((so
->so_proto
->pr_domain
->dom_family
== AF_INET
||
378 so
->so_proto
->pr_domain
->dom_family
== AF_INET6
) &&
379 so
->so_proto
->pr_protocol
== IPPROTO_TCP
) {
381 so_setsockopt(NULL
, so
, IPPROTO_TCP
, TCP_NODELAY
, &val
,
385 so
->so_rcv
.sb_flags
&= ~SB_NOINTR
;
386 so
->so_rcv
.sb_timeo
= 0;
387 so
->so_snd
.sb_flags
&= ~SB_NOINTR
;
388 so
->so_snd
.sb_timeo
= 0;
393 slp
= nfsrv_sockalloc();
397 mutex_enter(&fp
->f_lock
);
399 mutex_exit(&fp
->f_lock
);
401 slp
->ns_flags
= SLP_VALID
;
402 slp
->ns_aflags
= SLP_A_NEEDQ
;
406 so
->so_upcallarg
= (void *)slp
;
407 so
->so_upcall
= nfsrv_soupcall
;
408 so
->so_rcv
.sb_flags
|= SB_UPCALL
;
415 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
416 * until it is killed by a signal.
419 nfssvc_nfsd(struct nfsd_srvargs
*nsd
, void *argp
, struct lwp
*l
)
423 struct nfssvc_sock
*slp
;
424 struct nfsd
*nfsd
= nsd
->nsd_nfsd
;
425 struct nfsrv_descript
*nd
= NULL
;
428 int error
= 0, cacherep
, siz
, sotype
, writes_todo
;
429 struct proc
*p
= l
->l_proc
;
437 nsd
->nsd_nfsd
= nfsd
= kmem_alloc(sizeof(*nfsd
), KM_SLEEP
);
438 memset(nfsd
, 0, sizeof (struct nfsd
));
439 cv_init(&nfsd
->nfsd_cv
, "nfsd");
440 nfsd
->nfsd_procp
= p
;
441 mutex_enter(&nfsd_lock
);
442 while ((nfssvc_sockhead_flag
& SLP_INIT
) != 0) {
443 KASSERT(nfs_numnfsd
== 0);
444 cv_wait(&nfsd_initcv
, &nfsd_lock
);
446 TAILQ_INSERT_TAIL(&nfsd_head
, nfsd
, nfsd_chain
);
448 mutex_exit(&nfsd_lock
);
451 * Loop getting rpc requests until SIGKILL.
456 if ((curcpu()->ci_schedstate
.spc_flags
& SPCF_SHOULDYIELD
)
460 if (nfsd
->nfsd_slp
== NULL
) {
461 mutex_enter(&nfsd_lock
);
462 while (nfsd
->nfsd_slp
== NULL
&&
463 (nfsd_head_flag
& NFSD_CHECKSLP
) == 0) {
464 SLIST_INSERT_HEAD(&nfsd_idle_head
, nfsd
,
466 error
= cv_wait_sig(&nfsd
->nfsd_cv
, &nfsd_lock
);
468 slp
= nfsd
->nfsd_slp
;
469 nfsd
->nfsd_slp
= NULL
;
471 SLIST_REMOVE(&nfsd_idle_head
,
472 nfsd
, nfsd
, nfsd_idle
);
473 mutex_exit(&nfsd_lock
);
481 if (nfsd
->nfsd_slp
== NULL
&&
482 (nfsd_head_flag
& NFSD_CHECKSLP
) != 0) {
483 slp
= TAILQ_FIRST(&nfssvc_sockpending
);
485 KASSERT((slp
->ns_gflags
& SLP_G_DOREC
)
487 TAILQ_REMOVE(&nfssvc_sockpending
, slp
,
489 slp
->ns_gflags
&= ~SLP_G_DOREC
;
491 nfsd
->nfsd_slp
= slp
;
493 nfsd_head_flag
&= ~NFSD_CHECKSLP
;
495 KASSERT(nfsd
->nfsd_slp
== NULL
||
496 nfsd
->nfsd_slp
->ns_sref
> 0);
497 mutex_exit(&nfsd_lock
);
498 if ((slp
= nfsd
->nfsd_slp
) == NULL
)
500 if (slp
->ns_flags
& SLP_VALID
) {
503 if (nfsdsock_testbits(slp
, SLP_A_NEEDQ
)) {
506 if (nfsdsock_testbits(slp
, SLP_A_DISCONN
)) {
509 error
= nfsrv_dorec(slp
, nfsd
, &nd
, &more
);
511 cur_usec
= (u_quad_t
)tv
.tv_sec
* 1000000 +
512 (u_quad_t
)tv
.tv_usec
;
515 struct nfsrv_descript
*nd2
;
517 mutex_enter(&nfsd_lock
);
518 nd2
= LIST_FIRST(&slp
->ns_tq
);
520 nd2
->nd_time
<= cur_usec
) {
525 mutex_exit(&nfsd_lock
);
527 if (error
== 0 && more
) {
533 slp
= nfsd
->nfsd_slp
;
535 KASSERT(slp
!= NULL
);
536 KASSERT(nfsd
->nfsd_slp
== slp
);
537 if (error
|| (slp
->ns_flags
& SLP_VALID
) == 0) {
542 nfsd
->nfsd_slp
= NULL
;
546 sotype
= slp
->ns_so
->so_type
;
548 getmicrotime(&nd
->nd_starttime
);
550 nd
->nd_nam
= nd
->nd_nam2
;
552 nd
->nd_nam
= slp
->ns_nam
;
555 * Check to see if authorization is needed.
557 if (nfsd
->nfsd_flag
& NFSD_NEEDAUTH
) {
558 nfsd
->nfsd_flag
&= ~NFSD_NEEDAUTH
;
559 nsd
->nsd_haddr
= mtod(nd
->nd_nam
,
560 struct sockaddr_in
*)->sin_addr
.s_addr
;
561 nsd
->nsd_authlen
= nfsd
->nfsd_authlen
;
562 nsd
->nsd_verflen
= nfsd
->nfsd_verflen
;
563 if (!copyout(nfsd
->nfsd_authstr
,
564 nsd
->nsd_authstr
, nfsd
->nfsd_authlen
) &&
565 !copyout(nfsd
->nfsd_verfstr
,
566 nsd
->nsd_verfstr
, nfsd
->nfsd_verflen
) &&
567 !copyout(nsd
, argp
, sizeof (*nsd
))) {
570 cacherep
= RC_DROPIT
;
572 cacherep
= nfsrv_getcache(nd
, slp
, &mreq
);
574 if (nfsd
->nfsd_flag
& NFSD_AUTHFAIL
) {
575 nfsd
->nfsd_flag
&= ~NFSD_AUTHFAIL
;
576 nd
->nd_procnum
= NFSPROC_NOOP
;
578 (NFSERR_AUTHERR
| AUTH_TOOWEAK
);
584 * Loop to get all the write rpc relies that have been
592 if (writes_todo
|| nd
== NULL
||
593 (!(nd
->nd_flag
& ND_NFSV3
) &&
594 nd
->nd_procnum
== NFSPROC_WRITE
&&
595 nfsrvw_procrastinate
> 0))
596 error
= nfsrv_writegather(&nd
, slp
,
600 (*(nfsrv3_procs
[nd
->nd_procnum
]))
602 netexport_rdunlock();
612 nfsrv_updatecache(nd
, false, mreq
);
614 m_freem(nd
->nd_nam2
);
617 nfsstats
.srvrpccnt
[nd
->nd_procnum
]++;
618 nfsrv_updatecache(nd
, true, mreq
);
619 nd
->nd_mrep
= (struct mbuf
*)0;
627 if (siz
<= 0 || siz
> NFS_MAXPACKET
) {
628 printf("mbuf siz=%d\n",siz
);
629 panic("Bad nfs svc reply");
632 m
->m_pkthdr
.len
= siz
;
633 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
635 * For stream protocols, prepend a Sun RPC
638 if (sotype
== SOCK_STREAM
) {
639 M_PREPEND(m
, NFSX_UNSIGNED
, M_WAIT
);
640 *mtod(m
, u_int32_t
*) =
641 htonl(0x80000000 | siz
);
645 nfsd_rt(slp
->ns_so
->so_type
, nd
,
648 error
= nfsdsock_sendreply(slp
, nd
);
652 if (error
== EINTR
|| error
== ERESTART
) {
653 nfsd
->nfsd_slp
= NULL
;
660 nfsd_rt(sotype
, nd
, cacherep
);
661 m_freem(nd
->nd_mrep
);
662 m_freem(nd
->nd_nam2
);
671 * Check to see if there are outstanding writes that
672 * need to be serviced.
675 cur_usec
= (u_quad_t
)tv
.tv_sec
* 1000000 +
676 (u_quad_t
)tv
.tv_usec
;
677 mutex_enter(&nfsd_lock
);
678 if (LIST_FIRST(&slp
->ns_tq
) &&
679 LIST_FIRST(&slp
->ns_tq
)->nd_time
<= cur_usec
) {
684 mutex_exit(&nfsd_lock
);
685 } while (writes_todo
);
686 if (nfsrv_dorec(slp
, nfsd
, &nd
, &dummy
)) {
687 nfsd
->nfsd_slp
= NULL
;
692 mutex_enter(&nfsd_lock
);
693 TAILQ_REMOVE(&nfsd_head
, nfsd
, nfsd_chain
);
694 doreinit
= --nfs_numnfsd
== 0;
696 nfssvc_sockhead_flag
|= SLP_INIT
;
697 mutex_exit(&nfsd_lock
);
698 cv_destroy(&nfsd
->nfsd_cv
);
699 kmem_free(nfsd
, sizeof(*nfsd
));
700 nsd
->nsd_nfsd
= NULL
;
702 nfsrv_init(true); /* Reinitialize everything */
707 * Shut down a socket associated with an nfssvc_sock structure.
708 * Should be called with the send lock set, if required.
709 * The trick here is to increment the sref at the start, so that the nfsds
710 * will stop using it and clear ns_flag at the end so that it will not be
711 * reassigned during cleanup.
713 * called at splsoftnet.
716 nfsrv_zapsock(struct nfssvc_sock
*slp
)
718 struct nfsuid
*nuidp
, *nnuidp
;
719 struct nfsrv_descript
*nwp
;
723 if (nfsdsock_drain(slp
)) {
726 mutex_enter(&nfsd_lock
);
727 if (slp
->ns_gflags
& SLP_G_DOREC
) {
728 TAILQ_REMOVE(&nfssvc_sockpending
, slp
, ns_pending
);
729 slp
->ns_gflags
&= ~SLP_G_DOREC
;
731 mutex_exit(&nfsd_lock
);
736 so
->so_upcall
= NULL
;
737 so
->so_upcallarg
= NULL
;
738 so
->so_rcv
.sb_flags
&= ~SB_UPCALL
;
739 soshutdown(so
, SHUT_RDWR
);
742 m_freem(slp
->ns_raw
);
751 /* XXX what about freeing ns_frag ? */
752 for (nuidp
= TAILQ_FIRST(&slp
->ns_uidlruhead
); nuidp
!= 0;
754 nnuidp
= TAILQ_NEXT(nuidp
, nu_lru
);
755 LIST_REMOVE(nuidp
, nu_hash
);
756 TAILQ_REMOVE(&slp
->ns_uidlruhead
, nuidp
, nu_lru
);
757 if (nuidp
->nu_flag
& NU_NAM
)
758 m_freem(nuidp
->nu_nam
);
759 kmem_free(nuidp
, sizeof(*nuidp
));
761 mutex_enter(&nfsd_lock
);
762 while ((nwp
= LIST_FIRST(&slp
->ns_tq
)) != NULL
) {
763 LIST_REMOVE(nwp
, nd_tq
);
764 mutex_exit(&nfsd_lock
);
766 mutex_enter(&nfsd_lock
);
768 mutex_exit(&nfsd_lock
);
772 * Derefence a server socket structure. If it has no more references and
773 * is no longer valid, you can throw it away.
776 nfsrv_slpderef(struct nfssvc_sock
*slp
)
780 mutex_enter(&nfsd_lock
);
781 KASSERT(slp
->ns_sref
> 0);
782 ref
= --slp
->ns_sref
;
783 if (ref
== 0 && (slp
->ns_flags
& SLP_VALID
) == 0) {
786 KASSERT((slp
->ns_gflags
& SLP_G_DOREC
) == 0);
787 TAILQ_REMOVE(&nfssvc_sockhead
, slp
, ns_chain
);
788 mutex_exit(&nfsd_lock
);
794 KASSERT(fp
->f_data
== slp
->ns_so
);
795 KASSERT(fp
->f_count
> 0);
804 mutex_exit(&nfsd_lock
);
808 * Initialize the data structures for the server.
809 * Handshake with any new nfsds starting up to avoid any chance of
813 nfsrv_init(int terminating
)
815 struct nfssvc_sock
*slp
;
818 mutex_init(&nfsd_lock
, MUTEX_DRIVER
, IPL_SOFTNET
);
819 cv_init(&nfsd_initcv
, "nfsdinit");
822 mutex_enter(&nfsd_lock
);
823 if (!terminating
&& (nfssvc_sockhead_flag
& SLP_INIT
) != 0)
825 nfssvc_sockhead_flag
|= SLP_INIT
;
828 KASSERT(SLIST_EMPTY(&nfsd_idle_head
));
829 KASSERT(TAILQ_EMPTY(&nfsd_head
));
830 while ((slp
= TAILQ_FIRST(&nfssvc_sockhead
)) != NULL
) {
831 mutex_exit(&nfsd_lock
);
832 KASSERT(slp
->ns_sref
== 0);
836 mutex_enter(&nfsd_lock
);
838 KASSERT(TAILQ_EMPTY(&nfssvc_sockpending
));
839 mutex_exit(&nfsd_lock
);
840 nfsrv_cleancache(); /* And clear out server cache */
842 mutex_exit(&nfsd_lock
);
843 nfs_pub
.np_valid
= 0;
846 TAILQ_INIT(&nfssvc_sockhead
);
847 TAILQ_INIT(&nfssvc_sockpending
);
849 TAILQ_INIT(&nfsd_head
);
850 SLIST_INIT(&nfsd_idle_head
);
851 nfsd_head_flag
&= ~NFSD_CHECKSLP
;
853 nfs_udpsock
= nfsrv_sockalloc();
854 nfs_udp6sock
= nfsrv_sockalloc();
856 mutex_enter(&nfsd_lock
);
857 nfssvc_sockhead_flag
&= ~SLP_INIT
;
858 cv_broadcast(&nfsd_initcv
);
859 mutex_exit(&nfsd_lock
);
867 cv_destroy(&nfsd_initcv
);
868 mutex_destroy(&nfsd_lock
);
872 * Add entries to the server monitor log.
875 nfsd_rt(int sotype
, struct nfsrv_descript
*nd
, int cacherep
)
880 rt
= &nfsdrt
.drt
[nfsdrt
.pos
];
881 if (cacherep
== RC_DOIT
)
883 else if (cacherep
== RC_REPLY
)
884 rt
->flag
= DRT_CACHEREPLY
;
886 rt
->flag
= DRT_CACHEDROP
;
887 if (sotype
== SOCK_STREAM
)
889 if (nd
->nd_flag
& ND_NFSV3
)
890 rt
->flag
|= DRT_NFSV3
;
891 rt
->proc
= nd
->nd_procnum
;
892 if (mtod(nd
->nd_nam
, struct sockaddr
*)->sa_family
== AF_INET
)
893 rt
->ipadr
= mtod(nd
->nd_nam
, struct sockaddr_in
*)->sin_addr
.s_addr
;
895 rt
->ipadr
= INADDR_ANY
;
897 rt
->resptime
= ((tv
.tv_sec
- nd
->nd_starttime
.tv_sec
) * 1000000) +
898 (tv
.tv_usec
- nd
->nd_starttime
.tv_usec
);
900 nfsdrt
.pos
= (nfsdrt
.pos
+ 1) % NFSRTTLOGSIZ
;