Annotation of sys/nfs/nfs_syscalls.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: nfs_syscalls.c,v 1.55 2007/06/25 20:40:00 thib Exp $ */
2: /* $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $ */
3:
4: /*
5: * Copyright (c) 1989, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * Rick Macklem at The University of Guelph.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
35: * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
36: */
37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
40: #include <sys/kernel.h>
41: #include <sys/file.h>
42: #include <sys/stat.h>
43: #include <sys/vnode.h>
44: #include <sys/mount.h>
45: #include <sys/proc.h>
46: #include <sys/uio.h>
47: #include <sys/malloc.h>
48: #include <sys/buf.h>
49: #include <sys/mbuf.h>
50: #include <sys/socket.h>
51: #include <sys/socketvar.h>
52: #include <sys/domain.h>
53: #include <sys/protosw.h>
54: #include <sys/namei.h>
55: #include <sys/syslog.h>
56: #include <sys/filedesc.h>
57: #include <sys/signalvar.h>
58: #include <sys/kthread.h>
59:
60: #include <sys/syscallargs.h>
61:
62: #include <netinet/in.h>
63: #include <netinet/tcp.h>
64: #include <nfs/xdr_subs.h>
65: #include <nfs/rpcv2.h>
66: #include <nfs/nfsproto.h>
67: #include <nfs/nfs.h>
68: #include <nfs/nfsm_subs.h>
69: #include <nfs/nfsrvcache.h>
70: #include <nfs/nfsmount.h>
71: #include <nfs/nfsnode.h>
72: #include <nfs/nfsrtt.h>
73: #include <nfs/nfs_var.h>
74:
75: void nfsrv_zapsock(struct nfssvc_sock *);
76:
77: /* Global defs. */
78: extern int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *,
79: struct nfssvc_sock *,
80: struct proc *, struct mbuf **);
81: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
82: extern int nfs_numasync;
83: extern int nfsrtton;
84: extern struct nfsstats nfsstats;
85: extern int nfsrvw_procrastinate;
86: struct nfssvc_sock *nfs_udpsock;
87: int nuidhash_max = NFS_MAXUIDHASH;
88: int nfsd_waiting = 0;
89: #ifdef NFSSERVER
90: static int nfs_numnfsd = 0;
91: static struct nfsdrt nfsdrt;
92: #endif
93:
94: struct nfssvc_sockhead nfssvc_sockhead;
95: struct nfsdhead nfsd_head;
96:
97: int nfssvc_sockhead_flag;
98: int nfsd_head_flag;
99:
100: #define TRUE 1
101: #define FALSE 0
102:
103: #ifdef NFSCLIENT
104: struct proc *nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
105: int nfs_niothreads = -1;
106: #endif
107:
108: #ifdef NFSSERVER
109: static void nfsd_rt(int, struct nfsrv_descript *, int);
110: #endif
111:
112: /*
113: * NFS server pseudo system call for the nfsd's
114: * Based on the flag value it either:
115: * - adds a socket to the selection list
116: * - remains in the kernel as an nfsd
117: */
118: int
119: sys_nfssvc(struct proc *p, void *v, register_t *retval)
120: {
121: int error = 0;
122: #ifdef NFSSERVER
123: struct sys_nfssvc_args /* {
124: syscallarg(int) flag;
125: syscallarg(caddr_t) argp;
126: } */ *uap = v;
127: int flags = SCARG(uap, flag);
128: struct file *fp;
129: struct mbuf *nam;
130: struct nfsd_args nfsdarg;
131: struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs;
132: #endif
133:
134: /* Must be super user */
135: error = suser(p, 0);
136: if (error)
137: return (error);
138:
139: #ifndef NFSSERVER
140: error = ENOSYS;
141: #else
142:
143: while (nfssvc_sockhead_flag & SLP_INIT) {
144: nfssvc_sockhead_flag |= SLP_WANTINIT;
145: tsleep(&nfssvc_sockhead, PSOCK, "nfsd init", 0);
146: }
147:
148: switch (flags) {
149: case NFSSVC_ADDSOCK:
150: error = copyin(SCARG(uap, argp), &nfsdarg, sizeof(nfsdarg));
151: if (error)
152: return (error);
153:
154: error = getsock(p->p_fd, nfsdarg.sock, &fp);
155: if (error)
156: return (error);
157:
158: /*
159: * Get the client address for connected sockets.
160: */
161: if (nfsdarg.name == NULL || nfsdarg.namelen == 0)
162: nam = NULL;
163: else {
164: error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen,
165: MT_SONAME);
166: if (error) {
167: FRELE(fp);
168: return (error);
169: }
170: }
171: error = nfssvc_addsock(fp, nam);
172: FRELE(fp);
173: break;
174: case NFSSVC_NFSD:
175: error = copyin(SCARG(uap, argp), nsd, sizeof(*nsd));
176: if (error)
177: return (error);
178:
179: error = nfssvc_nfsd(nsd, SCARG(uap, argp), p);
180: break;
181: default:
182: error = EINVAL;
183: break;
184: }
185:
186: if (error == EINTR || error == ERESTART)
187: error = 0;
188: #endif /* !NFSSERVER */
189:
190: return (error);
191: }
192:
193: #ifdef NFSSERVER
194: /*
195: * Adds a socket to the list for servicing by nfsds.
196: */
197: int
198: nfssvc_addsock(fp, mynam)
199: struct file *fp;
200: struct mbuf *mynam;
201: {
202: struct mbuf *m;
203: int siz;
204: struct nfssvc_sock *slp;
205: struct socket *so;
206: struct nfssvc_sock *tslp;
207: int error, s;
208:
209: so = (struct socket *)fp->f_data;
210: tslp = (struct nfssvc_sock *)0;
211: /*
212: * Add it to the list, as required.
213: */
214: if (so->so_proto->pr_protocol == IPPROTO_UDP) {
215: tslp = nfs_udpsock;
216: if (tslp->ns_flag & SLP_VALID) {
217: m_freem(mynam);
218: return (EPERM);
219: }
220: }
221: if (so->so_type == SOCK_STREAM)
222: siz = NFS_MAXPACKET + sizeof (u_long);
223: else
224: siz = NFS_MAXPACKET;
225: error = soreserve(so, siz, siz);
226: if (error) {
227: m_freem(mynam);
228: return (error);
229: }
230:
231: /*
232: * Set protocol specific options { for now TCP only } and
233: * reserve some space. For datagram sockets, this can get called
234: * repeatedly for the same socket, but that isn't harmful.
235: */
236: if (so->so_type == SOCK_STREAM) {
237: MGET(m, M_WAIT, MT_SOOPTS);
238: *mtod(m, int32_t *) = 1;
239: m->m_len = sizeof(int32_t);
240: sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m);
241: }
242: if (so->so_proto->pr_domain->dom_family == AF_INET &&
243: so->so_proto->pr_protocol == IPPROTO_TCP) {
244: MGET(m, M_WAIT, MT_SOOPTS);
245: *mtod(m, int32_t *) = 1;
246: m->m_len = sizeof(int32_t);
247: sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m);
248: }
249: so->so_rcv.sb_flags &= ~SB_NOINTR;
250: so->so_rcv.sb_timeo = 0;
251: so->so_snd.sb_flags &= ~SB_NOINTR;
252: so->so_snd.sb_timeo = 0;
253: if (tslp)
254: slp = tslp;
255: else {
256: slp = (struct nfssvc_sock *)
257: malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
258: bzero((caddr_t)slp, sizeof (struct nfssvc_sock));
259: TAILQ_INIT(&slp->ns_uidlruhead);
260: TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
261: }
262: slp->ns_so = so;
263: slp->ns_nam = mynam;
264: fp->f_count++;
265: slp->ns_fp = fp;
266: s = splsoftnet();
267: so->so_upcallarg = (caddr_t)slp;
268: so->so_upcall = nfsrv_rcv;
269: slp->ns_flag = (SLP_VALID | SLP_NEEDQ);
270: nfsrv_wakenfsd(slp);
271: splx(s);
272: return (0);
273: }
274:
275: /*
276: * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
277: * until it is killed by a signal.
278: */
279: int
280: nfssvc_nfsd(nsd, argp, p)
281: struct nfsd_srvargs *nsd;
282: caddr_t argp;
283: struct proc *p;
284: {
285: struct mbuf *m;
286: int siz;
287: struct nfssvc_sock *slp;
288: struct socket *so;
289: int *solockp;
290: struct nfsd *nfsd = nsd->nsd_nfsd;
291: struct nfsrv_descript *nd = NULL;
292: struct mbuf *mreq;
293: int error = 0, cacherep, s, sotype, writes_todo;
294: u_quad_t cur_usec;
295: struct timeval tv;
296:
297: #ifndef nolint
298: cacherep = RC_DOIT;
299: writes_todo = 0;
300: #endif
301: s = splsoftnet();
302: if (nfsd == (struct nfsd *)0) {
303: nsd->nsd_nfsd = nfsd = (struct nfsd *)
304: malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
305: bzero((caddr_t)nfsd, sizeof (struct nfsd));
306: nfsd->nfsd_procp = p;
307: TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
308: nfs_numnfsd++;
309: }
310: /*
311: * Loop getting rpc requests until SIGKILL.
312: */
313: for (;;) {
314: if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
315: while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
316: (nfsd_head_flag & NFSD_CHECKSLP) == 0) {
317: nfsd->nfsd_flag |= NFSD_WAITING;
318: nfsd_waiting++;
319: error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
320: "nfsd", 0);
321: nfsd_waiting--;
322: if (error)
323: goto done;
324: }
325: if (nfsd->nfsd_slp == NULL &&
326: (nfsd_head_flag & NFSD_CHECKSLP) != 0) {
327: for (slp = TAILQ_FIRST(&nfssvc_sockhead);
328: slp != 0; slp = TAILQ_NEXT(slp, ns_chain)) {
329: if ((slp->ns_flag & (SLP_VALID | SLP_DOREC))
330: == (SLP_VALID | SLP_DOREC)) {
331: slp->ns_flag &= ~SLP_DOREC;
332: slp->ns_sref++;
333: nfsd->nfsd_slp = slp;
334: break;
335: }
336: }
337: if (slp == 0)
338: nfsd_head_flag &= ~NFSD_CHECKSLP;
339: }
340: if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
341: continue;
342: if (slp->ns_flag & SLP_VALID) {
343: struct timeval tv;
344:
345: if (slp->ns_flag & SLP_DISCONN)
346: nfsrv_zapsock(slp);
347: else if (slp->ns_flag & SLP_NEEDQ) {
348: slp->ns_flag &= ~SLP_NEEDQ;
349: (void) nfs_sndlock(&slp->ns_solock,
350: (struct nfsreq *)0);
351: nfsrv_rcv(slp->ns_so, (caddr_t)slp,
352: M_WAIT);
353: nfs_sndunlock(&slp->ns_solock);
354: }
355: error = nfsrv_dorec(slp, nfsd, &nd);
356: getmicrotime(&tv);
357: cur_usec = (u_quad_t)tv.tv_sec * 1000000 +
358: (u_quad_t)tv.tv_usec;
359: if (error && LIST_FIRST(&slp->ns_tq) &&
360: LIST_FIRST(&slp->ns_tq)->nd_time
361: <= cur_usec) {
362: error = 0;
363: cacherep = RC_DOIT;
364: writes_todo = 1;
365: } else
366: writes_todo = 0;
367: nfsd->nfsd_flag |= NFSD_REQINPROG;
368: }
369: } else {
370: error = 0;
371: slp = nfsd->nfsd_slp;
372: }
373: if (error || (slp->ns_flag & SLP_VALID) == 0) {
374: if (nd) {
375: free((caddr_t)nd, M_NFSRVDESC);
376: nd = NULL;
377: }
378: nfsd->nfsd_slp = (struct nfssvc_sock *)0;
379: nfsd->nfsd_flag &= ~NFSD_REQINPROG;
380: nfsrv_slpderef(slp);
381: continue;
382: }
383: splx(s);
384: so = slp->ns_so;
385: sotype = so->so_type;
386: if (so->so_proto->pr_flags & PR_CONNREQUIRED)
387: solockp = &slp->ns_solock;
388: else
389: solockp = (int *)0;
390: if (nd) {
391: getmicrotime(&nd->nd_starttime);
392: if (nd->nd_nam2)
393: nd->nd_nam = nd->nd_nam2;
394: else
395: nd->nd_nam = slp->ns_nam;
396:
397: /*
398: * Check to see if authorization is needed.
399: */
400: if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
401: nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
402: nsd->nsd_haddr = mtod(nd->nd_nam,
403: struct sockaddr_in *)->sin_addr.s_addr;
404: nsd->nsd_authlen = nfsd->nfsd_authlen;
405: nsd->nsd_verflen = nfsd->nfsd_verflen;
406: if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
407: nfsd->nfsd_authlen) &&
408: !copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
409: nfsd->nfsd_verflen) &&
410: !copyout((caddr_t)nsd, argp, sizeof (*nsd))) {
411: return (ENEEDAUTH);
412: }
413: cacherep = RC_DROPIT;
414: } else
415: cacherep = nfsrv_getcache(nd, slp, &mreq);
416:
417: if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
418: nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
419: nd->nd_procnum = NFSPROC_NOOP;
420: nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
421: cacherep = RC_DOIT;
422: }
423: }
424:
425: /*
426: * Loop to get all the write rpc relies that have been
427: * gathered together.
428: */
429: do {
430: switch (cacherep) {
431: case RC_DOIT:
432: if (writes_todo || (!(nd->nd_flag & ND_NFSV3) &&
433: nd->nd_procnum == NFSPROC_WRITE &&
434: nfsrvw_procrastinate > 0))
435: error = nfsrv_writegather(&nd, slp,
436: nfsd->nfsd_procp, &mreq);
437: else
438: error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
439: slp, nfsd->nfsd_procp, &mreq);
440: if (mreq == NULL)
441: break;
442: if (error) {
443: nfsstats.srv_errs++;
444: nfsrv_updatecache(nd, FALSE, mreq);
445: if (nd->nd_nam2)
446: m_freem(nd->nd_nam2);
447: break;
448: }
449: nfsstats.srvrpccnt[nd->nd_procnum]++;
450: nfsrv_updatecache(nd, TRUE, mreq);
451: nd->nd_mrep = (struct mbuf *)0;
452: case RC_REPLY:
453: m = mreq;
454: siz = 0;
455: while (m) {
456: siz += m->m_len;
457: m = m->m_next;
458: }
459: if (siz <= 0 || siz > NFS_MAXPACKET) {
460: printf("mbuf siz=%d\n",siz);
461: panic("Bad nfs svc reply");
462: }
463: m = mreq;
464: m->m_pkthdr.len = siz;
465: m->m_pkthdr.rcvif = (struct ifnet *)0;
466: /*
467: * For stream protocols, prepend a Sun RPC
468: * Record Mark.
469: */
470: if (sotype == SOCK_STREAM) {
471: M_PREPEND(m, NFSX_UNSIGNED, M_WAIT);
472: *mtod(m, u_int32_t *) = htonl(0x80000000 | siz);
473: }
474: if (solockp)
475: (void) nfs_sndlock(solockp, (struct nfsreq *)0);
476: if (slp->ns_flag & SLP_VALID)
477: error = nfs_send(so, nd->nd_nam2, m, NULL);
478: else {
479: error = EPIPE;
480: m_freem(m);
481: }
482: if (nfsrtton)
483: nfsd_rt(sotype, nd, cacherep);
484: if (nd->nd_nam2)
485: MFREE(nd->nd_nam2, m);
486: if (nd->nd_mrep)
487: m_freem(nd->nd_mrep);
488: if (error == EPIPE)
489: nfsrv_zapsock(slp);
490: if (solockp)
491: nfs_sndunlock(solockp);
492: if (error == EINTR || error == ERESTART) {
493: free((caddr_t)nd, M_NFSRVDESC);
494: nfsrv_slpderef(slp);
495: s = splsoftnet();
496: goto done;
497: }
498: break;
499: case RC_DROPIT:
500: if (nfsrtton)
501: nfsd_rt(sotype, nd, cacherep);
502: m_freem(nd->nd_mrep);
503: m_freem(nd->nd_nam2);
504: break;
505: };
506: if (nd) {
507: FREE((caddr_t)nd, M_NFSRVDESC);
508: nd = NULL;
509: }
510:
511: /*
512: * Check to see if there are outstanding writes that
513: * need to be serviced.
514: */
515: getmicrotime(&tv);
516: cur_usec = (u_quad_t)tv.tv_sec * 1000000 +
517: (u_quad_t)tv.tv_usec;
518: s = splsoftclock();
519: if (LIST_FIRST(&slp->ns_tq) &&
520: LIST_FIRST(&slp->ns_tq)->nd_time <= cur_usec) {
521: cacherep = RC_DOIT;
522: writes_todo = 1;
523: } else
524: writes_todo = 0;
525: splx(s);
526: } while (writes_todo);
527: s = splsoftnet();
528: if (nfsrv_dorec(slp, nfsd, &nd)) {
529: nfsd->nfsd_flag &= ~NFSD_REQINPROG;
530: nfsd->nfsd_slp = NULL;
531: nfsrv_slpderef(slp);
532: }
533: }
534: done:
535: TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
536: splx(s);
537: free((caddr_t)nfsd, M_NFSD);
538: nsd->nsd_nfsd = (struct nfsd *)0;
539: if (--nfs_numnfsd == 0)
540: nfsrv_init(TRUE); /* Reinitialize everything */
541: return (error);
542: }
543:
544: /*
545: * Shut down a socket associated with an nfssvc_sock structure.
546: * Should be called with the send lock set, if required.
547: * The trick here is to increment the sref at the start, so that the nfsds
548: * will stop using it and clear ns_flag at the end so that it will not be
549: * reassigned during cleanup.
550: */
551: void
552: nfsrv_zapsock(slp)
553: struct nfssvc_sock *slp;
554: {
555: struct nfsuid *nuidp, *nnuidp;
556: struct nfsrv_descript *nwp, *nnwp;
557: struct socket *so;
558: struct file *fp;
559: struct mbuf *m;
560: int s;
561:
562: slp->ns_flag &= ~SLP_ALLFLAGS;
563: fp = slp->ns_fp;
564: if (fp) {
565: FREF(fp);
566: slp->ns_fp = NULL;
567: so = slp->ns_so;
568: so->so_upcall = NULL;
569: soshutdown(so, SHUT_RDWR);
570: closef(fp, NULL);
571: if (slp->ns_nam)
572: MFREE(slp->ns_nam, m);
573: m_freem(slp->ns_raw);
574: m_freem(slp->ns_rec);
575: for (nuidp = TAILQ_FIRST(&slp->ns_uidlruhead); nuidp != NULL;
576: nuidp = nnuidp) {
577: nnuidp = TAILQ_NEXT(nuidp, nu_lru);
578: LIST_REMOVE(nuidp, nu_hash);
579: TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
580: if (nuidp->nu_flag & NU_NAM)
581: m_freem(nuidp->nu_nam);
582: free((caddr_t)nuidp, M_NFSUID);
583: }
584: s = splsoftclock();
585: for (nwp = LIST_FIRST(&slp->ns_tq); nwp != NULL; nwp = nnwp) {
586: nnwp = LIST_NEXT(nwp, nd_tq);
587: LIST_REMOVE(nwp, nd_tq);
588: free((caddr_t)nwp, M_NFSRVDESC);
589: }
590: LIST_INIT(&slp->ns_tq);
591: splx(s);
592: }
593: }
594:
595: /*
596: * Derefence a server socket structure. If it has no more references and
597: * is no longer valid, you can throw it away.
598: */
599: void
600: nfsrv_slpderef(slp)
601: struct nfssvc_sock *slp;
602: {
603: if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {
604: TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
605: free((caddr_t)slp, M_NFSSVC);
606: }
607: }
608:
609: /*
610: * Initialize the data structures for the server.
611: * Handshake with any new nfsds starting up to avoid any chance of
612: * corruption.
613: */
614: void
615: nfsrv_init(terminating)
616: int terminating;
617: {
618: struct nfssvc_sock *slp, *nslp;
619:
620: if (nfssvc_sockhead_flag & SLP_INIT)
621: panic("nfsd init");
622: nfssvc_sockhead_flag |= SLP_INIT;
623: if (terminating) {
624: for (slp = TAILQ_FIRST(&nfssvc_sockhead); slp != NULL;
625: slp = nslp) {
626: nslp = TAILQ_NEXT(slp, ns_chain);
627: if (slp->ns_flag & SLP_VALID)
628: nfsrv_zapsock(slp);
629: TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
630: free((caddr_t)slp, M_NFSSVC);
631: }
632: nfsrv_cleancache(); /* And clear out server cache */
633: }
634:
635: TAILQ_INIT(&nfssvc_sockhead);
636: nfssvc_sockhead_flag &= ~SLP_INIT;
637: if (nfssvc_sockhead_flag & SLP_WANTINIT) {
638: nfssvc_sockhead_flag &= ~SLP_WANTINIT;
639: wakeup((caddr_t)&nfssvc_sockhead);
640: }
641:
642: TAILQ_INIT(&nfsd_head);
643: nfsd_head_flag &= ~NFSD_CHECKSLP;
644:
645: nfs_udpsock = (struct nfssvc_sock *)
646: malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
647: bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));
648: TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
649: TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
650: }
651:
652: /*
653: * Add entries to the server monitor log.
654: */
655: static void
656: nfsd_rt(sotype, nd, cacherep)
657: int sotype;
658: struct nfsrv_descript *nd;
659: int cacherep;
660: {
661: struct drt *rt;
662:
663: rt = &nfsdrt.drt[nfsdrt.pos];
664: if (cacherep == RC_DOIT)
665: rt->flag = 0;
666: else if (cacherep == RC_REPLY)
667: rt->flag = DRT_CACHEREPLY;
668: else
669: rt->flag = DRT_CACHEDROP;
670: if (sotype == SOCK_STREAM)
671: rt->flag |= DRT_TCP;
672: else if (nd->nd_flag & ND_NFSV3)
673: rt->flag |= DRT_NFSV3;
674: rt->proc = nd->nd_procnum;
675: if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET)
676: rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr;
677: else
678: rt->ipadr = INADDR_ANY;
679: getmicrotime(&rt->tstamp);
680: rt->resptime =
681: ((rt->tstamp.tv_sec - nd->nd_starttime.tv_sec) * 1000000) +
682: (rt->tstamp.tv_usec - nd->nd_starttime.tv_usec);
683: nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
684: }
685: #endif /* NFSSERVER */
686:
687: #ifdef NFSCLIENT
688: /*
689: * Asynchronous I/O threads for client nfs.
690: * They do read-ahead and write-behind operations on the block I/O cache.
691: * Never returns unless it fails or gets killed.
692: */
693: int
694: nfssvc_iod(p)
695: struct proc *p;
696: {
697: struct buf *bp, *nbp;
698: int i, myiod;
699: struct vnode *vp;
700: int error = 0, s;
701:
702: /*
703: * Assign my position or return error if too many already running
704: */
705: myiod = -1;
706: for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
707: if (nfs_asyncdaemon[i] == NULL) {
708: myiod = i;
709: break;
710: }
711: if (myiod == -1)
712: return (EBUSY);
713: nfs_asyncdaemon[myiod] = p;
714: nfs_numasync++;
715: /*
716: * Just loop around doin our stuff until SIGKILL
717: */
718: for (;;) {
719: while (TAILQ_FIRST(&nfs_bufq) == NULL && error == 0) {
720: nfs_iodwant[myiod] = p;
721: error = tsleep((caddr_t)&nfs_iodwant[myiod],
722: PWAIT | PCATCH, "nfsidl", 0);
723: }
724: while ((bp = TAILQ_FIRST(&nfs_bufq)) != NULL) {
725: /* Take one off the front of the list */
726: TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
727: if (bp->b_flags & B_READ)
728: (void) nfs_doio(bp, NULL);
729: else do {
730: /*
731: * Look for a delayed write for the same vnode, so I can do
732: * it now. We must grab it before calling nfs_doio() to
733: * avoid any risk of the vnode getting vclean()'d while
734: * we are doing the write rpc.
735: */
736: vp = bp->b_vp;
737: s = splbio();
738: for (nbp = LIST_FIRST(&vp->v_dirtyblkhd); nbp != NULL;
739: nbp = LIST_NEXT(nbp, b_vnbufs)) {
740: if ((nbp->b_flags &
741: (B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI)
742: continue;
743: bremfree(nbp);
744: nbp->b_flags |= (B_BUSY|B_ASYNC);
745: break;
746: }
747: /*
748: * For the delayed write, do the first part of nfs_bwrite()
749: * up to, but not including nfs_strategy().
750: */
751: if (nbp) {
752: nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
753: buf_undirty(nbp);
754: nbp->b_vp->v_numoutput++;
755: }
756: splx(s);
757:
758: (void) nfs_doio(bp, NULL);
759: } while ((bp = nbp) != NULL);
760: }
761: if (error) {
762: nfs_asyncdaemon[myiod] = NULL;
763: nfs_numasync--;
764: return (error);
765: }
766: }
767: }
768:
769: void
770: start_nfsio(arg)
771: void *arg;
772: {
773: nfssvc_iod(curproc);
774:
775: kthread_exit(0);
776: }
777:
778: void
779: nfs_getset_niothreads(set)
780: int set;
781: {
782: int i, have, start;
783:
784: for (have = 0, i = 0; i < NFS_MAXASYNCDAEMON; i++)
785: if (nfs_asyncdaemon[i] != NULL)
786: have++;
787:
788: if (set) {
789: /* clamp to sane range */
790: nfs_niothreads = max(0, min(nfs_niothreads, NFS_MAXASYNCDAEMON));
791:
792: start = nfs_niothreads - have;
793:
794: while (start > 0) {
795: kthread_create(start_nfsio, NULL, NULL, "nfsio");
796: start--;
797: }
798:
799: for (i = 0; (start < 0) && (i < NFS_MAXASYNCDAEMON); i++)
800: if (nfs_asyncdaemon[i] != NULL) {
801: psignal(nfs_asyncdaemon[i], SIGKILL);
802: start++;
803: }
804: } else {
805: if (nfs_niothreads >= 0)
806: nfs_niothreads = have;
807: }
808: }
809:
810: /*
811: * Get an authorization string for the uid by having the mount_nfs sitting
812: * on this mount point porpoise out of the kernel and do it.
813: */
814: int
815: nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
816: struct nfsmount *nmp;
817: struct nfsreq *rep;
818: struct ucred *cred;
819: char **auth_str;
820: int *auth_len;
821: char *verf_str;
822: int *verf_len;
823: NFSKERBKEY_T key; /* return session key */
824: {
825: int error = 0;
826:
827: while ((nmp->nm_flag & NFSMNT_WAITAUTH) == 0) {
828: nmp->nm_flag |= NFSMNT_WANTAUTH;
829: (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK,
830: "nfsauth1", 2 * hz);
831: error = nfs_sigintr(nmp, rep, rep->r_procp);
832: if (error) {
833: nmp->nm_flag &= ~NFSMNT_WANTAUTH;
834: return (error);
835: }
836: }
837: nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);
838: nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
839: nmp->nm_authlen = RPCAUTH_MAXSIZ;
840: nmp->nm_verfstr = verf_str;
841: nmp->nm_verflen = *verf_len;
842: nmp->nm_authuid = cred->cr_uid;
843: wakeup((caddr_t)&nmp->nm_authstr);
844:
845: /*
846: * And wait for mount_nfs to do its stuff.
847: */
848: while ((nmp->nm_flag & NFSMNT_HASAUTH) == 0 && error == 0) {
849: (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK,
850: "nfsauth2", 2 * hz);
851: error = nfs_sigintr(nmp, rep, rep->r_procp);
852: }
853: if (nmp->nm_flag & NFSMNT_AUTHERR) {
854: nmp->nm_flag &= ~NFSMNT_AUTHERR;
855: error = EAUTH;
856: }
857: if (error)
858: free((caddr_t)*auth_str, M_TEMP);
859: else {
860: *auth_len = nmp->nm_authlen;
861: *verf_len = nmp->nm_verflen;
862: bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (NFSKERBKEY_T));
863: }
864: nmp->nm_flag &= ~NFSMNT_HASAUTH;
865: nmp->nm_flag |= NFSMNT_WAITAUTH;
866: if (nmp->nm_flag & NFSMNT_WANTAUTH) {
867: nmp->nm_flag &= ~NFSMNT_WANTAUTH;
868: wakeup((caddr_t)&nmp->nm_authtype);
869: }
870: return (error);
871: }
872:
873: /*
874: * Get a nickname authenticator and verifier.
875: */
876: int
877: nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
878: struct nfsmount *nmp;
879: struct ucred *cred;
880: char **auth_str;
881: int *auth_len;
882: char *verf_str;
883: int verf_len;
884: {
885: struct nfsuid *nuidp;
886: u_int32_t *nickp, *verfp;
887: struct timeval ktvin, ktvout;
888: struct timeval tv;
889:
890: #ifdef DIAGNOSTIC
891: if (verf_len < (4 * NFSX_UNSIGNED))
892: panic("nfs_getnickauth verf too small");
893: #endif
894: LIST_FOREACH(nuidp, NMUIDHASH(nmp, cred->cr_uid), nu_hash) {
895: if (nuidp->nu_cr.cr_uid == cred->cr_uid)
896: break;
897: }
898: if (!nuidp || nuidp->nu_expire < time_second)
899: return (EACCES);
900:
901: /*
902: * Move to the end of the lru list (end of lru == most recently used).
903: */
904: TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
905: TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
906:
907: nickp = (u_int32_t *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
908: *nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
909: *nickp = txdr_unsigned(nuidp->nu_nickname);
910: *auth_str = (char *)nickp;
911: *auth_len = 2 * NFSX_UNSIGNED;
912:
913: /*
914: * Now we must encrypt the verifier and package it up.
915: */
916: verfp = (u_int32_t *)verf_str;
917: *verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
918: getmicrotime(&tv);
919: if (tv.tv_sec > nuidp->nu_timestamp.tv_sec ||
920: (tv.tv_sec == nuidp->nu_timestamp.tv_sec &&
921: tv.tv_usec > nuidp->nu_timestamp.tv_usec))
922: nuidp->nu_timestamp = tv;
923: else
924: nuidp->nu_timestamp.tv_usec++;
925: ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
926: ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
927:
928: *verfp++ = ktvout.tv_sec;
929: *verfp++ = ktvout.tv_usec;
930: *verfp = 0;
931: return (0);
932: }
933:
934: /*
935: * Save the current nickname in a hash list entry on the mount point.
936: */
937: int
938: nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
939: struct nfsmount *nmp;
940: struct ucred *cred;
941: int len;
942: NFSKERBKEY_T key;
943: struct mbuf **mdp;
944: char **dposp;
945: struct mbuf *mrep;
946: {
947: struct nfsuid *nuidp;
948: u_int32_t *tl;
949: int32_t t1;
950: struct mbuf *md = *mdp;
951: struct timeval ktvin, ktvout;
952: u_int32_t nick;
953: char *dpos = *dposp, *cp2;
954: int deltasec, error = 0;
955:
956: if (len == (3 * NFSX_UNSIGNED)) {
957: nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
958: ktvin.tv_sec = *tl++;
959: ktvin.tv_usec = *tl++;
960: nick = fxdr_unsigned(u_int32_t, *tl);
961:
962: ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
963: ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
964: deltasec = time_second - ktvout.tv_sec;
965: if (deltasec < 0)
966: deltasec = -deltasec;
967: /*
968: * If ok, add it to the hash list for the mount point.
969: */
970: if (deltasec <= NFS_KERBCLOCKSKEW) {
971: if (nmp->nm_numuids < nuidhash_max) {
972: nmp->nm_numuids++;
973: nuidp = (struct nfsuid *)
974: malloc(sizeof (struct nfsuid), M_NFSUID,
975: M_WAITOK);
976: } else {
977: nuidp = TAILQ_FIRST(&nmp->nm_uidlruhead);
978: LIST_REMOVE(nuidp, nu_hash);
979: TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
980: nu_lru);
981: }
982: nuidp->nu_flag = 0;
983: nuidp->nu_cr.cr_uid = cred->cr_uid;
984: nuidp->nu_expire = time_second + NFS_KERBTTL;
985: nuidp->nu_timestamp = ktvout;
986: nuidp->nu_nickname = nick;
987: bcopy(key, nuidp->nu_key, sizeof (NFSKERBKEY_T));
988: TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
989: nu_lru);
990: LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
991: nuidp, nu_hash);
992: }
993: } else
994: nfsm_adv(nfsm_rndup(len));
995: nfsmout:
996: *mdp = md;
997: *dposp = dpos;
998: return (error);
999: }
1000: #endif /* NFSCLIENT */
CVSweb