This source file includes following definitions.
- sys_nfssvc
- nfssvc_addsock
- nfssvc_nfsd
- nfsrv_zapsock
- nfsrv_slpderef
- nfsrv_init
- nfsd_rt
- nfssvc_iod
- start_nfsio
- nfs_getset_niothreads
- nfs_getauth
- nfs_getnickauth
- nfs_savenickauth
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
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
114
115
116
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
125
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
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
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
189
190 return (error);
191 }
192
193 #ifdef NFSSERVER
194
195
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
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
233
234
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
277
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
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
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
427
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
468
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
513
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);
541 return (error);
542 }
543
544
545
546
547
548
549
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
597
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
611
612
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();
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
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
686
687 #ifdef NFSCLIENT
688
689
690
691
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
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
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
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
732
733
734
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
749
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
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
812
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;
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
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
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
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
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
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
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