]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/nfsserver/nfs_syscalls.c
This commit was generated by cvs2svn to compensate for changes in r92109,
[FreeBSD/FreeBSD.git] / sys / nfsserver / nfs_syscalls.c
1 /*
2  * Copyright (c) 1989, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *      @(#)nfs_syscalls.c      8.5 (Berkeley) 3/30/95
37  * $FreeBSD$
38  */
39
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/sysproto.h>
46 #include <sys/kernel.h>
47 #include <sys/sysctl.h>
48 #include <sys/file.h>
49 #include <sys/filedesc.h>
50 #include <sys/vnode.h>
51 #include <sys/malloc.h>
52 #include <sys/mount.h>
53 #include <sys/proc.h>
54 #include <sys/bio.h>
55 #include <sys/buf.h>
56 #include <sys/mbuf.h>
57 #include <sys/socket.h>
58 #include <sys/socketvar.h>
59 #include <sys/domain.h>
60 #include <sys/protosw.h>
61 #include <sys/namei.h>
62 #include <sys/fcntl.h>
63 #include <sys/lockf.h>
64
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>
70 #include <nfsserver/nfs.h>
71 #include <nfsserver/nfsm_subs.h>
72 #include <nfsserver/nfsrvcache.h>
73
74 static MALLOC_DEFINE(M_NFSSVC, "NFS srvsock", "Nfs server structure");
75
76 MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor");
77 MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure");
78
79
80 #define TRUE    1
81 #define FALSE   0
82
83 SYSCTL_DECL(_vfs_nfsrv);
84
85 int             nfsd_waiting = 0;
86 static int      nfs_numnfsd = 0;
87 static int      notstarted = 1;
88
89 static int      nfs_privport = 0;
90 SYSCTL_INT(_vfs_nfsrv, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW,
91             &nfs_privport, 0, "");
92 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay, CTLFLAG_RW,
93             &nfsrvw_procrastinate, 0, "");
94 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay_v3, CTLFLAG_RW,
95             &nfsrvw_procrastinate_v3, 0, "");
96
97 static int      nfssvc_addsock(struct file *, struct sockaddr *,
98                     struct thread *);
99 static void     nfsrv_zapsock(struct nfssvc_sock *slp);
100 static int      nfssvc_nfsd(struct nfsd_srvargs *, caddr_t, struct thread *);
101
102 /*
103  * NFS server system calls
104  */
105
106 /*
107  * Nfs server psuedo system call for the nfsd's
108  * Based on the flag value it either:
109  * - adds a socket to the selection list
110  * - remains in the kernel as an nfsd
111  * - remains in the kernel as an nfsiod
112  */
113 #ifndef _SYS_SYSPROTO_H_
114 struct nfssvc_args {
115         int flag;
116         caddr_t argp;
117 };
118 #endif
119 /*
120  * MPSAFE
121  */
122 int
123 nfssvc(struct thread *td, struct nfssvc_args *uap)
124 {
125         struct file *fp;
126         struct sockaddr *nam;
127         struct nfsd_args nfsdarg;
128         struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs;
129         int error;
130
131         mtx_lock(&Giant);
132         error = suser_td(td);
133         if (error)
134                 goto done2;
135         while (nfssvc_sockhead_flag & SLP_INIT) {
136                  nfssvc_sockhead_flag |= SLP_WANTINIT;
137                 (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0);
138         }
139         if (uap->flag & NFSSVC_ADDSOCK) {
140                 error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg));
141                 if (error)
142                         goto done2;
143                 if ((error = fget(td, nfsdarg.sock, &fp)) != 0)
144                         goto done2;
145                 if (fp->f_type != DTYPE_SOCKET) {
146                         fdrop(fp, td);
147                         goto done2;
148                 }
149                 /*
150                  * Get the client address for connected sockets.
151                  */
152                 if (nfsdarg.name == NULL || nfsdarg.namelen == 0)
153                         nam = (struct sockaddr *)0;
154                 else {
155                         error = getsockaddr(&nam, nfsdarg.name,
156                                             nfsdarg.namelen);
157                         if (error) {
158                                 fdrop(fp, td);
159                                 goto done2;
160                         }
161                 }
162                 error = nfssvc_addsock(fp, nam, td);
163                 fdrop(fp, td);
164         } else if (uap->flag & NFSSVC_NFSD) {
165                 error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd));
166                 if (error)
167                         return (error);
168                 error = nfssvc_nfsd(nsd, uap->argp, td);
169         } else {
170                 error = ENXIO;
171         }
172         if (error == EINTR || error == ERESTART)
173                 error = 0;
174 done2:
175         mtx_unlock(&Giant);
176         return (error);
177 }
178
179 /*
180  * Adds a socket to the list for servicing by nfsds.
181  */
182 static int
183 nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td)
184 {
185         int siz;
186         struct nfssvc_sock *slp;
187         struct socket *so;
188         int error, s;
189
190         so = (struct socket *)fp->f_data;
191 #if 0
192         tslp = (struct nfssvc_sock *)0;
193         /*
194          * Add it to the list, as required.
195          */
196         if (so->so_proto->pr_protocol == IPPROTO_UDP) {
197                 tslp = nfs_udpsock;
198                 if (tslp->ns_flag & SLP_VALID) {
199                         if (mynam != NULL)
200                                 FREE(mynam, M_SONAME);
201                         return (EPERM);
202                 }
203         }
204 #endif
205         if (so->so_type == SOCK_STREAM)
206                 siz = NFS_MAXPACKET + sizeof (u_long);
207         else
208                 siz = NFS_MAXPACKET;
209         error = soreserve(so, siz, siz);
210         if (error) {
211                 if (mynam != NULL)
212                         FREE(mynam, M_SONAME);
213                 return (error);
214         }
215
216         /*
217          * Set protocol specific options { for now TCP only } and
218          * reserve some space. For datagram sockets, this can get called
219          * repeatedly for the same socket, but that isn't harmful.
220          */
221         if (so->so_type == SOCK_STREAM) {
222                 struct sockopt sopt;
223                 int val;
224
225                 bzero(&sopt, sizeof sopt);
226                 sopt.sopt_level = SOL_SOCKET;
227                 sopt.sopt_name = SO_KEEPALIVE;
228                 sopt.sopt_val = &val;
229                 sopt.sopt_valsize = sizeof val;
230                 val = 1;
231                 sosetopt(so, &sopt);
232         }
233         if (so->so_proto->pr_domain->dom_family == AF_INET &&
234             so->so_proto->pr_protocol == IPPROTO_TCP) {
235                 struct sockopt sopt;
236                 int val;
237
238                 bzero(&sopt, sizeof sopt);
239                 sopt.sopt_level = IPPROTO_TCP;
240                 sopt.sopt_name = TCP_NODELAY;
241                 sopt.sopt_val = &val;
242                 sopt.sopt_valsize = sizeof val;
243                 val = 1;
244                 sosetopt(so, &sopt);
245         }
246         so->so_rcv.sb_flags &= ~SB_NOINTR;
247         so->so_rcv.sb_timeo = 0;
248         so->so_snd.sb_flags &= ~SB_NOINTR;
249         so->so_snd.sb_timeo = 0;
250
251         slp = (struct nfssvc_sock *)
252                 malloc(sizeof (struct nfssvc_sock), M_NFSSVC,
253                 M_WAITOK | M_ZERO);
254         STAILQ_INIT(&slp->ns_rec);
255         TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
256
257         slp->ns_so = so;
258         slp->ns_nam = mynam;
259         fp->f_count++;
260         slp->ns_fp = fp;
261         s = splnet();
262         so->so_upcallarg = (caddr_t)slp;
263         so->so_upcall = nfsrv_rcv;
264         so->so_rcv.sb_flags |= SB_UPCALL;
265         slp->ns_flag = (SLP_VALID | SLP_NEEDQ);
266         nfsrv_wakenfsd(slp);
267         splx(s);
268         return (0);
269 }
270
271 /*
272  * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
273  * until it is killed by a signal.
274  */
275 static int
276 nfssvc_nfsd(struct nfsd_srvargs *nsd, caddr_t argp, struct thread *td)
277 {
278         int siz;
279         struct nfssvc_sock *slp;
280         struct nfsd *nfsd = nsd->nsd_nfsd;
281         struct nfsrv_descript *nd = NULL;
282         struct mbuf *m, *mreq;
283         int error = 0, cacherep, s, sotype, writes_todo;
284         int procrastinate;
285         u_quad_t cur_usec;
286
287 #ifndef nolint
288         cacherep = RC_DOIT;
289         writes_todo = 0;
290 #endif
291         if (nfsd == (struct nfsd *)0) {
292                 nsd->nsd_nfsd = nfsd = (struct nfsd *)
293                         malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK | M_ZERO);
294                 s = splnet();
295                 nfsd->nfsd_td = td;
296                 TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
297                 nfs_numnfsd++;
298         } else
299                 s = splnet();
300
301         /*
302          * Loop getting rpc requests until SIGKILL.
303          */
304         for (;;) {
305                 if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
306                         while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
307                             (nfsd_head_flag & NFSD_CHECKSLP) == 0) {
308                                 nfsd->nfsd_flag |= NFSD_WAITING;
309                                 nfsd_waiting++;
310                                 error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
311                                     "nfsd", 0);
312                                 nfsd_waiting--;
313                                 if (error)
314                                         goto done;
315                         }
316                         if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
317                             (nfsd_head_flag & NFSD_CHECKSLP) != 0) {
318                                 TAILQ_FOREACH(slp, &nfssvc_sockhead, ns_chain) {
319                                     if ((slp->ns_flag & (SLP_VALID | SLP_DOREC))
320                                         == (SLP_VALID | SLP_DOREC)) {
321                                             slp->ns_flag &= ~SLP_DOREC;
322                                             slp->ns_sref++;
323                                             nfsd->nfsd_slp = slp;
324                                             break;
325                                     }
326                                 }
327                                 if (slp == 0)
328                                         nfsd_head_flag &= ~NFSD_CHECKSLP;
329                         }
330                         if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
331                                 continue;
332                         if (slp->ns_flag & SLP_VALID) {
333                                 if (slp->ns_flag & SLP_DISCONN)
334                                         nfsrv_zapsock(slp);
335                                 else if (slp->ns_flag & SLP_NEEDQ) {
336                                         slp->ns_flag &= ~SLP_NEEDQ;
337                                         (void) nfs_slplock(slp, 1);
338                                         nfsrv_rcv(slp->ns_so, (caddr_t)slp,
339                                                 M_TRYWAIT);
340                                         nfs_slpunlock(slp);
341                                 }
342                                 error = nfsrv_dorec(slp, nfsd, &nd);
343                                 cur_usec = nfs_curusec();
344                                 if (error && LIST_FIRST(&slp->ns_tq) &&
345                                     LIST_FIRST(&slp->ns_tq)->nd_time <= cur_usec) {
346                                         error = 0;
347                                         cacherep = RC_DOIT;
348                                         writes_todo = 1;
349                                 } else
350                                         writes_todo = 0;
351                                 nfsd->nfsd_flag |= NFSD_REQINPROG;
352                         }
353                 } else {
354                         error = 0;
355                         slp = nfsd->nfsd_slp;
356                 }
357                 if (error || (slp->ns_flag & SLP_VALID) == 0) {
358                         if (nd) {
359                                 free((caddr_t)nd, M_NFSRVDESC);
360                                 nd = NULL;
361                         }
362                         nfsd->nfsd_slp = (struct nfssvc_sock *)0;
363                         nfsd->nfsd_flag &= ~NFSD_REQINPROG;
364                         nfsrv_slpderef(slp);
365                         continue;
366                 }
367                 splx(s);
368                 sotype = slp->ns_so->so_type;
369                 if (nd) {
370                     getmicrotime(&nd->nd_starttime);
371                     if (nd->nd_nam2)
372                         nd->nd_nam = nd->nd_nam2;
373                     else
374                         nd->nd_nam = slp->ns_nam;
375
376                     /*
377                      * Check to see if authorization is needed.
378                      */
379                     cacherep = nfsrv_getcache(nd, &mreq);
380
381                     if (nfs_privport) {
382                         /* Check if source port is privileged */
383                         u_short port;
384                         struct sockaddr *nam = nd->nd_nam;
385                         struct sockaddr_in *sin;
386
387                         sin = (struct sockaddr_in *)nam;
388                         port = ntohs(sin->sin_port);
389                         if (port >= IPPORT_RESERVED &&
390                             nd->nd_procnum != NFSPROC_NULL) {
391                             nd->nd_procnum = NFSPROC_NOOP;
392                             nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
393                             cacherep = RC_DOIT;
394                             printf("NFS request from unprivileged port (%s:%d)\n",
395                                    inet_ntoa(sin->sin_addr), port);
396                         }
397                     }
398
399                 }
400
401                 /*
402                  * Loop to get all the write rpc relies that have been
403                  * gathered together.
404                  */
405                 do {
406                     switch (cacherep) {
407                     case RC_DOIT:
408                         if (nd && (nd->nd_flag & ND_NFSV3))
409                             procrastinate = nfsrvw_procrastinate_v3;
410                         else
411                             procrastinate = nfsrvw_procrastinate;
412                         if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
413                             procrastinate > 0 && !notstarted))
414                             error = nfsrv_writegather(&nd, slp,
415                                 nfsd->nfsd_td, &mreq);
416                         else
417                             error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
418                                 slp, nfsd->nfsd_td, &mreq);
419                         if (mreq == NULL)
420                                 break;
421                         if (error != 0 && error != NFSERR_RETVOID) {
422                                 nfsrvstats.srv_errs++;
423                                 nfsrv_updatecache(nd, FALSE, mreq);
424                                 if (nd->nd_nam2)
425                                         FREE(nd->nd_nam2, M_SONAME);
426                                 break;
427                         }
428                         nfsrvstats.srvrpccnt[nd->nd_procnum]++;
429                         nfsrv_updatecache(nd, TRUE, mreq);
430                         nd->nd_mrep = (struct mbuf *)0;
431                     case RC_REPLY:
432                         m = mreq;
433                         siz = 0;
434                         while (m) {
435                                 siz += m->m_len;
436                                 m = m->m_next;
437                         }
438                         if (siz <= 0 || siz > NFS_MAXPACKET) {
439                                 printf("mbuf siz=%d\n",siz);
440                                 panic("Bad nfs svc reply");
441                         }
442                         m = mreq;
443                         m->m_pkthdr.len = siz;
444                         m->m_pkthdr.rcvif = (struct ifnet *)0;
445                         /*
446                          * For stream protocols, prepend a Sun RPC
447                          * Record Mark.
448                          */
449                         if (sotype == SOCK_STREAM) {
450                                 M_PREPEND(m, NFSX_UNSIGNED, M_TRYWAIT);
451                                 *mtod(m, u_int32_t *) = htonl(0x80000000 | siz);
452                         }
453                         if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
454                                 (void) nfs_slplock(slp, 1);
455                         if (slp->ns_flag & SLP_VALID)
456                             error = nfsrv_send(slp->ns_so, nd->nd_nam2, m);
457                         else {
458                             error = EPIPE;
459                             m_freem(m);
460                         }
461                         if (nd->nd_nam2)
462                                 FREE(nd->nd_nam2, M_SONAME);
463                         if (nd->nd_mrep)
464                                 m_freem(nd->nd_mrep);
465                         if (error == EPIPE)
466                                 nfsrv_zapsock(slp);
467                         if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
468                                 nfs_slpunlock(slp);
469                         if (error == EINTR || error == ERESTART) {
470                                 free((caddr_t)nd, M_NFSRVDESC);
471                                 nfsrv_slpderef(slp);
472                                 s = splnet();
473                                 goto done;
474                         }
475                         break;
476                     case RC_DROPIT:
477                         m_freem(nd->nd_mrep);
478                         if (nd->nd_nam2)
479                                 FREE(nd->nd_nam2, M_SONAME);
480                         break;
481                     };
482                     if (nd) {
483                         FREE((caddr_t)nd, M_NFSRVDESC);
484                         nd = NULL;
485                     }
486
487                     /*
488                      * Check to see if there are outstanding writes that
489                      * need to be serviced.
490                      */
491                     cur_usec = nfs_curusec();
492                     s = splsoftclock();
493                     if (LIST_FIRST(&slp->ns_tq) &&
494                         LIST_FIRST(&slp->ns_tq)->nd_time <= cur_usec) {
495                         cacherep = RC_DOIT;
496                         writes_todo = 1;
497                     } else
498                         writes_todo = 0;
499                     splx(s);
500                 } while (writes_todo);
501                 s = splnet();
502                 if (nfsrv_dorec(slp, nfsd, &nd)) {
503                         nfsd->nfsd_flag &= ~NFSD_REQINPROG;
504                         nfsd->nfsd_slp = NULL;
505                         nfsrv_slpderef(slp);
506                 }
507         }
508 done:
509         TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
510         splx(s);
511         free((caddr_t)nfsd, M_NFSD);
512         nsd->nsd_nfsd = (struct nfsd *)0;
513         if (--nfs_numnfsd == 0)
514                 nfsrv_init(TRUE);       /* Reinitialize everything */
515         return (error);
516 }
517
518 /*
519  * Shut down a socket associated with an nfssvc_sock structure.
520  * Should be called with the send lock set, if required.
521  * The trick here is to increment the sref at the start, so that the nfsds
522  * will stop using it and clear ns_flag at the end so that it will not be
523  * reassigned during cleanup.
524  */
525 static void
526 nfsrv_zapsock(struct nfssvc_sock *slp)
527 {
528         struct nfsrv_descript *nwp, *nnwp;
529         struct socket *so;
530         struct file *fp;
531         struct nfsrv_rec *rec;
532         int s;
533
534         slp->ns_flag &= ~SLP_ALLFLAGS;
535         fp = slp->ns_fp;
536         if (fp) {
537                 slp->ns_fp = (struct file *)0;
538                 so = slp->ns_so;
539                 so->so_rcv.sb_flags &= ~SB_UPCALL;
540                 so->so_upcall = NULL;
541                 so->so_upcallarg = NULL;
542                 soshutdown(so, 2);
543                 closef(fp, (struct thread *)0);
544                 if (slp->ns_nam)
545                         FREE(slp->ns_nam, M_SONAME);
546                 m_freem(slp->ns_raw);
547                 while ((rec = STAILQ_FIRST(&slp->ns_rec)) != NULL) {
548                         STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link);
549                         if (rec->nr_address)
550                                 FREE(rec->nr_address, M_SONAME);
551                         m_freem(rec->nr_packet);
552                         free(rec, M_NFSRVDESC);
553                 }
554                 s = splsoftclock();
555                 for (nwp = LIST_FIRST(&slp->ns_tq); nwp; nwp = nnwp) {
556                         nnwp = LIST_NEXT(nwp, nd_tq);
557                         LIST_REMOVE(nwp, nd_tq);
558                         free((caddr_t)nwp, M_NFSRVDESC);
559                 }
560                 LIST_INIT(&slp->ns_tq);
561                 splx(s);
562         }
563 }
564
565 /*
566  * Derefence a server socket structure. If it has no more references and
567  * is no longer valid, you can throw it away.
568  */
569 void
570 nfsrv_slpderef(struct nfssvc_sock *slp)
571 {
572
573         if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {
574                 TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
575                 free((caddr_t)slp, M_NFSSVC);
576         }
577 }
578
579 /*
580  * Lock a socket against others.
581  */
582 int
583 nfs_slplock(struct nfssvc_sock *slp, int wait)
584 {
585         int *statep = &slp->ns_solock;
586
587         if (!wait && (*statep & NFSRV_SNDLOCK))
588                 return(0);      /* already locked, fail */
589         while (*statep & NFSRV_SNDLOCK) {
590                 *statep |= NFSRV_WANTSND;
591                 (void) tsleep((caddr_t)statep, PZERO - 1, "nfsslplck", 0);
592         }
593         *statep |= NFSRV_SNDLOCK;
594         return (1);
595 }
596
597 /*
598  * Unlock the stream socket for others.
599  */
600 void
601 nfs_slpunlock(struct nfssvc_sock *slp)
602 {
603         int *statep = &slp->ns_solock;
604
605         if ((*statep & NFSRV_SNDLOCK) == 0)
606                 panic("nfs slpunlock");
607         *statep &= ~NFSRV_SNDLOCK;
608         if (*statep & NFSRV_WANTSND) {
609                 *statep &= ~NFSRV_WANTSND;
610                 wakeup((caddr_t)statep);
611         }
612 }
613
614 /*
615  * Initialize the data structures for the server.
616  * Handshake with any new nfsds starting up to avoid any chance of
617  * corruption.
618  */
619 void
620 nfsrv_init(int terminating)
621 {
622         struct nfssvc_sock *slp, *nslp;
623
624         if (nfssvc_sockhead_flag & SLP_INIT)
625                 panic("nfsd init");
626         nfssvc_sockhead_flag |= SLP_INIT;
627         if (terminating) {
628                 for (slp = TAILQ_FIRST(&nfssvc_sockhead); slp != 0; slp = nslp){
629                         nslp = TAILQ_NEXT(slp, ns_chain);
630                         if (slp->ns_flag & SLP_VALID)
631                                 nfsrv_zapsock(slp);
632                         TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
633                         free((caddr_t)slp, M_NFSSVC);
634                 }
635                 nfsrv_cleancache();     /* And clear out server cache */
636         } else
637                 nfs_pub.np_valid = 0;
638
639         TAILQ_INIT(&nfssvc_sockhead);
640         nfssvc_sockhead_flag &= ~SLP_INIT;
641         if (nfssvc_sockhead_flag & SLP_WANTINIT) {
642                 nfssvc_sockhead_flag &= ~SLP_WANTINIT;
643                 wakeup((caddr_t)&nfssvc_sockhead);
644         }
645
646         TAILQ_INIT(&nfsd_head);
647         nfsd_head_flag &= ~NFSD_CHECKSLP;
648
649 #if 0
650         nfs_udpsock = (struct nfssvc_sock *)
651             malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
652         STAILQ_INIT(&nfs_udpsock->ns_rec);
653         TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
654
655         nfs_cltpsock = (struct nfssvc_sock *)
656             malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
657         STAILQ_INIT(&nfs_cltpsock->ns_rec);
658         TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
659 #endif
660 }