nfs_socket.c revision 1.170.2.7 1 /* $NetBSD: nfs_socket.c,v 1.170.2.7 2010/03/11 15:04:31 yamt Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1991, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
21 *
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
32 * SUCH DAMAGE.
33 *
34 * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
35 */
36
37 /*
38 * Socket operations for use by nfs
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: nfs_socket.c,v 1.170.2.7 2010/03/11 15:04:31 yamt Exp $");
43
44 #ifdef _KERNEL_OPT
45 #include "opt_nfs.h"
46 #include "opt_mbuftrace.h"
47 #endif
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/evcnt.h>
52 #include <sys/callout.h>
53 #include <sys/proc.h>
54 #include <sys/mount.h>
55 #include <sys/kernel.h>
56 #include <sys/kmem.h>
57 #include <sys/mbuf.h>
58 #include <sys/vnode.h>
59 #include <sys/domain.h>
60 #include <sys/protosw.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/syslog.h>
64 #include <sys/tprintf.h>
65 #include <sys/namei.h>
66 #include <sys/signal.h>
67 #include <sys/signalvar.h>
68 #include <sys/kauth.h>
69
70 #include <netinet/in.h>
71 #include <netinet/tcp.h>
72
73 #include <nfs/rpcv2.h>
74 #include <nfs/nfsproto.h>
75 #include <nfs/nfs.h>
76 #include <nfs/xdr_subs.h>
77 #include <nfs/nfsm_subs.h>
78 #include <nfs/nfsmount.h>
79 #include <nfs/nfsnode.h>
80 #include <nfs/nfsrtt.h>
81 #include <nfs/nfs_var.h>
82
83 #ifdef MBUFTRACE
84 struct mowner nfs_mowner = MOWNER_INIT("nfs","");
85 #endif
86
87 /*
88 * Estimate rto for an nfs rpc sent via. an unreliable datagram.
89 * Use the mean and mean deviation of rtt for the appropriate type of rpc
90 * for the frequent rpcs and a default for the others.
91 * The justification for doing "other" this way is that these rpcs
92 * happen so infrequently that timer est. would probably be stale.
93 * Also, since many of these rpcs are
94 * non-idempotent, a conservative timeout is desired.
95 * getattr, lookup - A+2D
96 * read, write - A+4D
97 * other - nm_timeo
98 */
99 #define NFS_RTO(n, t) \
100 ((t) == 0 ? (n)->nm_timeo : \
101 ((t) < 3 ? \
102 (((((n)->nm_srtt[t-1] + 3) >> 2) + (n)->nm_sdrtt[t-1] + 1) >> 1) : \
103 ((((n)->nm_srtt[t-1] + 7) >> 3) + (n)->nm_sdrtt[t-1] + 1)))
104 #define NFS_SRTT(r) (r)->r_nmp->nm_srtt[nfs_proct[(r)->r_procnum] - 1]
105 #define NFS_SDRTT(r) (r)->r_nmp->nm_sdrtt[nfs_proct[(r)->r_procnum] - 1]
106
107 /*
108 * Defines which timer to use for the procnum.
109 * 0 - default
110 * 1 - getattr
111 * 2 - lookup
112 * 3 - read
113 * 4 - write
114 */
115 const int nfs_proct[NFS_NPROCS] = {
116 [NFSPROC_NULL] = 0,
117 [NFSPROC_GETATTR] = 1,
118 [NFSPROC_SETATTR] = 0,
119 [NFSPROC_LOOKUP] = 2,
120 [NFSPROC_ACCESS] = 1,
121 [NFSPROC_READLINK] = 3,
122 [NFSPROC_READ] = 3,
123 [NFSPROC_WRITE] = 4,
124 [NFSPROC_CREATE] = 0,
125 [NFSPROC_MKDIR] = 0,
126 [NFSPROC_SYMLINK] = 0,
127 [NFSPROC_MKNOD] = 0,
128 [NFSPROC_REMOVE] = 0,
129 [NFSPROC_RMDIR] = 0,
130 [NFSPROC_RENAME] = 0,
131 [NFSPROC_LINK] = 0,
132 [NFSPROC_READDIR] = 3,
133 [NFSPROC_READDIRPLUS] = 3,
134 [NFSPROC_FSSTAT] = 0,
135 [NFSPROC_FSINFO] = 0,
136 [NFSPROC_PATHCONF] = 0,
137 [NFSPROC_COMMIT] = 0,
138 [NFSPROC_NOOP] = 0,
139 };
140
141 #ifdef DEBUG
142 /*
143 * Avoid spamming the console with debugging messages. We only print
144 * the nfs timer and reply error debugs every 10 seconds.
145 */
146 const struct timeval nfs_err_interval = { 10, 0 };
147 struct timeval nfs_reply_last_err_time;
148 struct timeval nfs_timer_last_err_time;
149 #endif
150
151 /*
152 * There is a congestion window for outstanding rpcs maintained per mount
153 * point. The cwnd size is adjusted in roughly the way that:
154 * Van Jacobson, Congestion avoidance and Control, In "Proceedings of
155 * SIGCOMM '88". ACM, August 1988.
156 * describes for TCP. The cwnd size is chopped in half on a retransmit timeout
157 * and incremented by 1/cwnd when each rpc reply is received and a full cwnd
158 * of rpcs is in progress.
159 * (The sent count and cwnd are scaled for integer arith.)
160 * Variants of "slow start" were tried and were found to be too much of a
161 * performance hit (ave. rtt 3 times larger),
162 * I suspect due to the large rtt that nfs rpcs have.
163 */
164 int nfsrtton = 0;
165 struct nfsrtt nfsrtt;
166 static const int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, };
167 kmutex_t nfs_reqq_lock;
168 struct nfsreqhead nfs_reqq;
169 static callout_t nfs_timer_ch;
170 static struct evcnt nfs_timer_ev;
171 static struct evcnt nfs_timer_start_ev;
172 static struct evcnt nfs_timer_stop_ev;
173 static kmutex_t nfs_timer_lock;
174 static bool (*nfs_timer_srvvec)(void);
175
176 /*
177 * Initialize sockets and congestion for a new NFS connection.
178 * We do not free the sockaddr if error.
179 */
180 int
181 nfs_connect(struct nfsmount *nmp, struct nfsreq *rep, struct lwp *l)
182 {
183 struct socket *so;
184 int error, rcvreserve, sndreserve;
185 struct sockaddr *saddr;
186 struct sockaddr_in *sin;
187 struct sockaddr_in6 *sin6;
188 struct mbuf *m;
189 int val;
190
191 KASSERT(rw_write_held(&nmp->nm_solock));
192 KASSERT(nmp->nm_so == NULL);
193
194 saddr = mtod(nmp->nm_nam, struct sockaddr *);
195 error = socreate(saddr->sa_family, &nmp->nm_so,
196 nmp->nm_sotype, nmp->nm_soproto, l, NULL);
197 if (error)
198 goto bad;
199 so = nmp->nm_so;
200 #ifdef MBUFTRACE
201 so->so_mowner = &nfs_mowner;
202 so->so_rcv.sb_mowner = &nfs_mowner;
203 so->so_snd.sb_mowner = &nfs_mowner;
204 #endif
205 nmp->nm_soflags = so->so_proto->pr_flags;
206
207 /*
208 * Some servers require that the client port be a reserved port number.
209 */
210 if (saddr->sa_family == AF_INET && (nmp->nm_flag & NFSMNT_RESVPORT)) {
211 val = IP_PORTRANGE_LOW;
212
213 if ((error = so_setsockopt(NULL, so, IPPROTO_IP, IP_PORTRANGE,
214 &val, sizeof(val))))
215 goto bad;
216 m = m_get(M_WAIT, MT_SONAME);
217 MCLAIM(m, so->so_mowner);
218 sin = mtod(m, struct sockaddr_in *);
219 sin->sin_len = m->m_len = sizeof (struct sockaddr_in);
220 sin->sin_family = AF_INET;
221 sin->sin_addr.s_addr = INADDR_ANY;
222 sin->sin_port = 0;
223 error = sobind(so, m, &lwp0);
224 m_freem(m);
225 if (error)
226 goto bad;
227 }
228 if (saddr->sa_family == AF_INET6 && (nmp->nm_flag & NFSMNT_RESVPORT)) {
229 val = IPV6_PORTRANGE_LOW;
230
231 if ((error = so_setsockopt(NULL, so, IPPROTO_IPV6,
232 IPV6_PORTRANGE, &val, sizeof(val))))
233 goto bad;
234 m = m_get(M_WAIT, MT_SONAME);
235 MCLAIM(m, so->so_mowner);
236 sin6 = mtod(m, struct sockaddr_in6 *);
237 memset(sin6, 0, sizeof(*sin6));
238 sin6->sin6_len = m->m_len = sizeof (struct sockaddr_in6);
239 sin6->sin6_family = AF_INET6;
240 error = sobind(so, m, &lwp0);
241 m_freem(m);
242 if (error)
243 goto bad;
244 }
245
246 /*
247 * Protocols that do not require connections may be optionally left
248 * unconnected for servers that reply from a port other than NFS_PORT.
249 */
250 solock(so);
251 if (nmp->nm_flag & NFSMNT_NOCONN) {
252 if (nmp->nm_soflags & PR_CONNREQUIRED) {
253 sounlock(so);
254 error = ENOTCONN;
255 goto bad;
256 }
257 } else {
258 error = soconnect(so, nmp->nm_nam, l);
259 if (error) {
260 sounlock(so);
261 goto bad;
262 }
263
264 /*
265 * Wait for the connection to complete. Cribbed from the
266 * connect system call but with the wait timing out so
267 * that interruptible mounts don't hang here for a long time.
268 */
269 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
270 (void)sowait(so, false, 2 * hz);
271 if ((so->so_state & SS_ISCONNECTING) &&
272 so->so_error == 0 && rep &&
273 (error = nfs_sigintr(nmp, rep, rep->r_lwp)) != 0){
274 so->so_state &= ~SS_ISCONNECTING;
275 sounlock(so);
276 goto bad;
277 }
278 }
279 if (so->so_error) {
280 error = so->so_error;
281 so->so_error = 0;
282 sounlock(so);
283 goto bad;
284 }
285 }
286 if (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_INT)) {
287 so->so_rcv.sb_timeo = (5 * hz);
288 so->so_snd.sb_timeo = (5 * hz);
289 } else {
290 /*
291 * enable receive timeout to detect server crash and reconnect.
292 * otherwise, we can be stuck in soreceive forever.
293 */
294 so->so_rcv.sb_timeo = (5 * hz);
295 so->so_snd.sb_timeo = 0;
296 }
297 if (nmp->nm_sotype == SOCK_DGRAM) {
298 sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * 2;
299 rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
300 NFS_MAXPKTHDR) * 2;
301 } else if (nmp->nm_sotype == SOCK_SEQPACKET) {
302 sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * 2;
303 rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
304 NFS_MAXPKTHDR) * 2;
305 } else {
306 sounlock(so);
307 if (nmp->nm_sotype != SOCK_STREAM)
308 panic("nfscon sotype");
309 if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
310 val = 1;
311 so_setsockopt(NULL, so, SOL_SOCKET, SO_KEEPALIVE, &val,
312 sizeof(val));
313 }
314 if (so->so_proto->pr_protocol == IPPROTO_TCP) {
315 val = 1;
316 so_setsockopt(NULL, so, IPPROTO_TCP, TCP_NODELAY, &val,
317 sizeof(val));
318 }
319 sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR +
320 sizeof (u_int32_t)) * 2;
321 rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR +
322 sizeof (u_int32_t)) * 2;
323 solock(so);
324 }
325 error = soreserve(so, sndreserve, rcvreserve);
326 if (error) {
327 sounlock(so);
328 goto bad;
329 }
330 so->so_rcv.sb_flags |= SB_NOINTR;
331 so->so_snd.sb_flags |= SB_NOINTR;
332 sounlock(so);
333
334 /* Initialize other non-zero congestion variables */
335 mutex_enter(&nfs_reqq_lock);
336 nmp->nm_srtt[0] = nmp->nm_srtt[1] = nmp->nm_srtt[2] = nmp->nm_srtt[3] =
337 NFS_TIMEO << 3;
338 nmp->nm_sdrtt[0] = nmp->nm_sdrtt[1] = nmp->nm_sdrtt[2] =
339 nmp->nm_sdrtt[3] = 0;
340 nmp->nm_cwnd = NFS_MAXCWND / 2; /* Initial send window */
341 nmp->nm_timeouts = 0;
342 mutex_exit(&nfs_reqq_lock);
343 return (0);
344
345 bad:
346 nfs_disconnect(nmp);
347 return (error);
348 }
349
350 /*
351 * Reconnect routine:
352 * Called when a connection is broken on a reliable protocol.
353 * - clean up the old socket
354 * - nfs_connect() again
355 * - set R_MUSTRESEND for all outstanding requests on mount point
356 * If this fails the mount point is DEAD!
357 */
358 int
359 nfs_reconnect(struct nfsreq *rep)
360 {
361 struct nfsmount *nmp = rep->r_nmp;
362 int error;
363
364 KASSERT(rep->r_nmp->nm_rcvlwp == curlwp);
365 if (!rw_tryupgrade(&nmp->nm_solock)) {
366 return EAGAIN;
367 }
368 nfs_disconnect(nmp);
369 while ((error = nfs_connect(nmp, rep, &lwp0)) != 0) {
370 if (error == EINTR || error == ERESTART) {
371 rw_downgrade(&nmp->nm_solock);
372 return EINTR;
373 }
374 kpause("nfscn2", false, hz, NULL);
375 }
376
377 rw_downgrade(&nmp->nm_solock);
378 return 0;
379 }
380
381 /*
382 * NFS disconnect. Clean up and unlink.
383 */
384 void
385 nfs_disconnect(struct nfsmount *nmp)
386 {
387 struct nfsreq *rp;
388 struct socket *so;
389 int drain = 0;
390
391 KASSERT(rw_write_held(&nmp->nm_solock));
392 if (nmp->nm_so) {
393 so = nmp->nm_so;
394 nmp->nm_so = NULL;
395 solock(so);
396 soshutdown(so, SHUT_RDWR);
397 sounlock(so);
398 drain = (nmp->nm_iflag & NFSMNT_DISMNT) != 0;
399 if (drain) {
400 /*
401 * soshutdown() above should wake up the current
402 * listener.
403 * Now wake up those waiting for the receive lock, and
404 * wait for them to go away unhappy, to prevent *nmp
405 * from evaporating while they're sleeping.
406 */
407 mutex_enter(&nmp->nm_lock);
408 while (nmp->nm_waiters > 0) {
409 cv_broadcast(&nmp->nm_rcvcv);
410 cv_broadcast(&nmp->nm_sndcv);
411 cv_wait(&nmp->nm_disconcv, &nmp->nm_lock);
412 }
413 mutex_exit(&nmp->nm_lock);
414 }
415 soclose(so);
416 }
417
418 #ifdef DIAGNOSTIC
419 if (drain && (nmp->nm_waiters > 0))
420 panic("nfs_disconnect: waiters left after drain?");
421 #endif
422
423 /*
424 * Loop through outstanding request list and fix up all requests
425 * on old socket.
426 */
427 mutex_enter(&nfs_reqq_lock);
428 TAILQ_FOREACH(rp, &nfs_reqq, r_chain) {
429 if (rp->r_nmp == nmp) {
430 if ((rp->r_flags & R_MUSTRESEND) == 0)
431 rp->r_flags |= R_MUSTRESEND | R_REXMITTED;
432 rp->r_rexmit = 0;
433 if ((rp->r_rflags & RR_SENT) != 0) {
434 KASSERT(nmp->nm_sent >= NFS_CWNDSCALE);
435 rp->r_rflags &= ~RR_SENT;
436 nmp->nm_sent -= NFS_CWNDSCALE;
437 }
438 }
439 }
440 KASSERT(nmp->nm_sent == 0);
441 mutex_exit(&nfs_reqq_lock);
442 }
443
444 void
445 nfs_safedisconnect(struct nfsmount *nmp)
446 {
447
448 KASSERT(rw_write_held(&nmp->nm_solock));
449
450 nfs_rcvlock(nmp, NULL); /* XXX ignored error return */
451 nfs_disconnect(nmp);
452 nfs_rcvunlock(nmp);
453 }
454
455 /*
456 * This is the nfs send routine.
457 * "rep == NULL" indicates that it has been called from a server.
458 * For the client side:
459 * - return EINTR if the RPC is terminated, 0 otherwise
460 * - set R_MUSTRESEND if the send fails for any reason
461 * - do any cleanup required by recoverable socket errors (? ? ?)
462 * For the server side:
463 * - return EINTR or ERESTART if interrupted by a signal
464 * - return EPIPE if a connection is lost for connection based sockets (TCP...)
465 * - do any cleanup required by recoverable socket errors (? ? ?)
466 */
467 int
468 nfs_send(struct socket *so, struct mbuf *nam, struct mbuf *top,
469 struct nfsreq *rep)
470 {
471 struct mbuf *sendnam;
472 int error, soflags, flags;
473
474 if (rep) {
475 KASSERT(rw_read_held(&rep->r_nmp->nm_solock));
476 if (rep->r_flags & R_SOFTTERM) {
477 m_freem(top);
478 return (EINTR);
479 }
480 if ((so = rep->r_nmp->nm_so) == NULL) {
481 rep->r_flags |= R_MUSTRESEND;
482 m_freem(top);
483 return (0);
484 }
485 rep->r_flags &= ~R_MUSTRESEND;
486 soflags = rep->r_nmp->nm_soflags;
487 } else
488 soflags = so->so_proto->pr_flags;
489 if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
490 sendnam = NULL;
491 else
492 sendnam = nam;
493 if (so->so_type == SOCK_SEQPACKET)
494 flags = MSG_EOR;
495 else
496 flags = 0;
497
498 error = (*so->so_send)(so, sendnam, NULL, top, NULL, flags, curlwp);
499 if (error) {
500 if (rep) {
501 if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
502 /*
503 * We're too fast for the network/driver,
504 * and UDP isn't flowcontrolled.
505 * We need to resend. This is not fatal,
506 * just try again.
507 *
508 * Could be smarter here by doing some sort
509 * of a backoff, but this is rare.
510 */
511 rep->r_flags |= R_MUSTRESEND;
512 } else {
513 if (error != EPIPE)
514 log(LOG_INFO,
515 "nfs send error %d for %s\n",
516 error,
517 rep->r_nmp->nm_mountp->
518 mnt_stat.f_mntfromname);
519 /*
520 * Deal with errors for the client side.
521 */
522 if (rep->r_flags & R_SOFTTERM)
523 error = EINTR;
524 else if (error != EMSGSIZE)
525 rep->r_flags |= R_MUSTRESEND;
526 }
527 } else {
528 /*
529 * See above. This error can happen under normal
530 * circumstances and the log is too noisy.
531 * The error will still show up in nfsstat.
532 */
533 if (error != ENOBUFS || so->so_type != SOCK_DGRAM)
534 log(LOG_INFO, "nfsd send error %d\n", error);
535 }
536
537 /*
538 * Handle any recoverable (soft) socket errors here. (? ? ?)
539 */
540 if (error != EINTR && error != ERESTART &&
541 error != EWOULDBLOCK && error != EPIPE &&
542 error != EMSGSIZE)
543 error = 0;
544 }
545 return (error);
546 }
547
548 /*
549 * Generate the rpc reply header
550 * siz arg. is used to decide if adding a cluster is worthwhile
551 */
552 int
553 nfs_rephead(int siz, struct nfsrv_descript *nd, struct nfssvc_sock *slp, int err, int cache, u_quad_t *frev, struct mbuf **mrq, struct mbuf **mbp, char **bposp)
554 {
555 u_int32_t *tl;
556 struct mbuf *mreq;
557 char *bpos;
558 struct mbuf *mb;
559
560 mreq = m_gethdr(M_WAIT, MT_DATA);
561 MCLAIM(mreq, &nfs_mowner);
562 mb = mreq;
563 /*
564 * If this is a big reply, use a cluster else
565 * try and leave leading space for the lower level headers.
566 */
567 siz += RPC_REPLYSIZ;
568 if (siz >= max_datalen) {
569 m_clget(mreq, M_WAIT);
570 } else
571 mreq->m_data += max_hdr;
572 tl = mtod(mreq, u_int32_t *);
573 mreq->m_len = 6 * NFSX_UNSIGNED;
574 bpos = ((char *)tl) + mreq->m_len;
575 *tl++ = txdr_unsigned(nd->nd_retxid);
576 *tl++ = rpc_reply;
577 if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
578 *tl++ = rpc_msgdenied;
579 if (err & NFSERR_AUTHERR) {
580 *tl++ = rpc_autherr;
581 *tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
582 mreq->m_len -= NFSX_UNSIGNED;
583 bpos -= NFSX_UNSIGNED;
584 } else {
585 *tl++ = rpc_mismatch;
586 *tl++ = txdr_unsigned(RPC_VER2);
587 *tl = txdr_unsigned(RPC_VER2);
588 }
589 } else {
590 *tl++ = rpc_msgaccepted;
591
592 /*
593 * For Kerberos authentication, we must send the nickname
594 * verifier back, otherwise just RPCAUTH_NULL.
595 */
596 if (nd->nd_flag & ND_KERBFULL) {
597 struct nfsuid *nuidp;
598 struct timeval ktvin, ktvout;
599
600 memset(&ktvout, 0, sizeof ktvout); /* XXX gcc */
601
602 LIST_FOREACH(nuidp,
603 NUIDHASH(slp, kauth_cred_geteuid(nd->nd_cr)),
604 nu_hash) {
605 if (kauth_cred_geteuid(nuidp->nu_cr) ==
606 kauth_cred_geteuid(nd->nd_cr) &&
607 (!nd->nd_nam2 || netaddr_match(
608 NU_NETFAM(nuidp), &nuidp->nu_haddr,
609 nd->nd_nam2)))
610 break;
611 }
612 if (nuidp) {
613 ktvin.tv_sec =
614 txdr_unsigned(nuidp->nu_timestamp.tv_sec
615 - 1);
616 ktvin.tv_usec =
617 txdr_unsigned(nuidp->nu_timestamp.tv_usec);
618
619 /*
620 * Encrypt the timestamp in ecb mode using the
621 * session key.
622 */
623 #ifdef NFSKERB
624 XXX
625 #endif
626
627 *tl++ = rpc_auth_kerb;
628 *tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
629 *tl = ktvout.tv_sec;
630 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
631 *tl++ = ktvout.tv_usec;
632 *tl++ = txdr_unsigned(
633 kauth_cred_geteuid(nuidp->nu_cr));
634 } else {
635 *tl++ = 0;
636 *tl++ = 0;
637 }
638 } else {
639 *tl++ = 0;
640 *tl++ = 0;
641 }
642 switch (err) {
643 case EPROGUNAVAIL:
644 *tl = txdr_unsigned(RPC_PROGUNAVAIL);
645 break;
646 case EPROGMISMATCH:
647 *tl = txdr_unsigned(RPC_PROGMISMATCH);
648 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
649 *tl++ = txdr_unsigned(2);
650 *tl = txdr_unsigned(3);
651 break;
652 case EPROCUNAVAIL:
653 *tl = txdr_unsigned(RPC_PROCUNAVAIL);
654 break;
655 case EBADRPC:
656 *tl = txdr_unsigned(RPC_GARBAGE);
657 break;
658 default:
659 *tl = 0;
660 if (err != NFSERR_RETVOID) {
661 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
662 if (err)
663 *tl = txdr_unsigned(nfsrv_errmap(nd, err));
664 else
665 *tl = 0;
666 }
667 break;
668 };
669 }
670
671 if (mrq != NULL)
672 *mrq = mreq;
673 *mbp = mb;
674 *bposp = bpos;
675 if (err != 0 && err != NFSERR_RETVOID)
676 nfsstats.srvrpc_errs++;
677 return (0);
678 }
679
680 static void
681 nfs_timer_schedule(void)
682 {
683
684 callout_schedule(&nfs_timer_ch, nfs_ticks);
685 }
686
687 void
688 nfs_timer_start(void)
689 {
690
691 if (callout_pending(&nfs_timer_ch))
692 return;
693
694 nfs_timer_start_ev.ev_count++;
695 nfs_timer_schedule();
696 }
697
698 void
699 nfs_timer_init(void)
700 {
701
702 mutex_init(&nfs_timer_lock, MUTEX_DEFAULT, IPL_NONE);
703 callout_init(&nfs_timer_ch, CALLOUT_MPSAFE);
704 callout_setfunc(&nfs_timer_ch, nfs_timer, NULL);
705 evcnt_attach_dynamic(&nfs_timer_ev, EVCNT_TYPE_MISC, NULL,
706 "nfs", "timer");
707 evcnt_attach_dynamic(&nfs_timer_start_ev, EVCNT_TYPE_MISC, NULL,
708 "nfs", "timer start");
709 evcnt_attach_dynamic(&nfs_timer_stop_ev, EVCNT_TYPE_MISC, NULL,
710 "nfs", "timer stop");
711 }
712
713 void
714 nfs_timer_fini(void)
715 {
716
717 callout_halt(&nfs_timer_ch, NULL);
718 callout_destroy(&nfs_timer_ch);
719 mutex_destroy(&nfs_timer_lock);
720 evcnt_detach(&nfs_timer_ev);
721 evcnt_detach(&nfs_timer_start_ev);
722 evcnt_detach(&nfs_timer_stop_ev);
723 }
724
725 void
726 nfs_timer_srvinit(bool (*func)(void))
727 {
728
729 nfs_timer_srvvec = func;
730 }
731
732 void
733 nfs_timer_srvfini(void)
734 {
735
736 mutex_enter(&nfs_timer_lock);
737 nfs_timer_srvvec = NULL;
738 mutex_exit(&nfs_timer_lock);
739 }
740
741
742 /*
743 * Nfs timer routine
744 * Scan the nfsreq list and retranmit any requests that have timed out
745 * To avoid retransmission attempts on STREAM sockets (in the future) make
746 * sure to set the r_retry field to 0 (implies nm_retry == 0).
747 */
748 void
749 nfs_timer(void *arg)
750 {
751 struct nfsreq *rep;
752 struct mbuf *m;
753 struct socket *so;
754 struct nfsmount *nmp;
755 int timeo;
756 int error;
757 bool more = false;
758
759 nfs_timer_ev.ev_count++;
760
761 mutex_enter(&nfs_reqq_lock);
762 TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
763 more = true;
764 nmp = rep->r_nmp;
765 if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
766 continue;
767 if (nfs_sigintr(nmp, rep, rep->r_lwp)) {
768 rep->r_flags |= R_SOFTTERM;
769 continue;
770 }
771 if (rep->r_rtt >= 0) {
772 rep->r_rtt++;
773 if (nmp->nm_flag & NFSMNT_DUMBTIMR)
774 timeo = nmp->nm_timeo;
775 else
776 timeo = NFS_RTO(nmp, nfs_proct[rep->r_procnum]);
777 if (nmp->nm_timeouts > 0)
778 timeo *= nfs_backoff[nmp->nm_timeouts - 1];
779 if (timeo > NFS_MAXTIMEO)
780 timeo = NFS_MAXTIMEO;
781 if (rep->r_rtt <= timeo)
782 continue;
783 if (nmp->nm_timeouts <
784 (sizeof(nfs_backoff) / sizeof(nfs_backoff[0])))
785 nmp->nm_timeouts++;
786 }
787 /*
788 * Check for server not responding
789 */
790 if ((rep->r_flags & R_TPRINTFMSG) == 0 &&
791 rep->r_rexmit > nmp->nm_deadthresh) {
792 nfs_msg(rep->r_lwp,
793 nmp->nm_mountp->mnt_stat.f_mntfromname,
794 "not responding");
795 rep->r_flags |= R_TPRINTFMSG;
796 }
797 if (rep->r_rexmit >= rep->r_retry) { /* too many */
798 nfsstats.rpctimeouts++;
799 rep->r_flags |= R_SOFTTERM;
800 continue;
801 }
802 if (nmp->nm_sotype != SOCK_DGRAM) {
803 if (++rep->r_rexmit > NFS_MAXREXMIT)
804 rep->r_rexmit = NFS_MAXREXMIT;
805 continue;
806 }
807 if (!rw_tryenter(&nmp->nm_solock, RW_READER)) {
808 printf("%s: rw_trylock failed\n", __func__);
809 continue;
810 }
811 if ((so = nmp->nm_so) == NULL) {
812 rw_exit(&nmp->nm_solock);
813 continue;
814 }
815
816 /*
817 * If there is enough space and the window allows..
818 * Resend it
819 * Set r_rtt to -1 in case we fail to send it now.
820 */
821 solock(so);
822 rep->r_rtt = -1;
823 if (sbspace(&so->so_snd) >= rep->r_mreq->m_pkthdr.len &&
824 ((nmp->nm_flag & NFSMNT_DUMBTIMR) ||
825 (rep->r_rflags & RR_SENT) ||
826 nmp->nm_sent < nmp->nm_cwnd) &&
827 (m = m_copym(rep->r_mreq, 0, M_COPYALL, M_DONTWAIT))) {
828 if (so->so_state & SS_ISCONNECTED)
829 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND,
830 m, NULL, NULL, NULL);
831 else
832 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND,
833 m, nmp->nm_nam, NULL, NULL);
834 if (error) {
835 if (NFSIGNORE_SOERROR(nmp->nm_soflags, error)) {
836 #ifdef DEBUG
837 if (ratecheck(&nfs_timer_last_err_time,
838 &nfs_err_interval))
839 printf("%s: ignoring error "
840 "%d\n", __func__, error);
841 #endif
842 so->so_error = 0;
843 }
844 } else {
845 /*
846 * Iff first send, start timing
847 * else turn timing off, backoff timer
848 * and divide congestion window by 2.
849 */
850 if (rep->r_rflags & RR_SENT) {
851 rep->r_flags &= ~R_TIMING;
852 if (++rep->r_rexmit > NFS_MAXREXMIT)
853 rep->r_rexmit = NFS_MAXREXMIT;
854 nmp->nm_cwnd >>= 1;
855 if (nmp->nm_cwnd < NFS_CWNDSCALE)
856 nmp->nm_cwnd = NFS_CWNDSCALE;
857 nfsstats.rpcretries++;
858 } else {
859 rep->r_rflags |= RR_SENT;
860 nmp->nm_sent += NFS_CWNDSCALE;
861 }
862 rep->r_rtt = 0;
863 }
864 }
865 sounlock(so);
866 rw_exit(&nmp->nm_solock);
867 }
868 mutex_exit(&nfs_reqq_lock);
869
870 mutex_enter(&nfs_timer_lock);
871 if (nfs_timer_srvvec != NULL) {
872 more |= (*nfs_timer_srvvec)();
873 }
874 mutex_exit(&nfs_timer_lock);
875
876 if (more) {
877 nfs_timer_schedule();
878 } else {
879 nfs_timer_stop_ev.ev_count++;
880 }
881 }
882
883 /*
884 * Test for a termination condition pending on the process.
885 * This is used for NFSMNT_INT mounts.
886 */
887 int
888 nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct lwp *l)
889 {
890 sigset_t ss;
891
892 if (rep && (rep->r_flags & R_SOFTTERM))
893 return (EINTR);
894 if (!(nmp->nm_flag & NFSMNT_INT))
895 return (0);
896 if (l) {
897 sigpending1(l, &ss);
898 #if 0
899 sigminusset(&l->l_proc->p_sigctx.ps_sigignore, &ss);
900 #endif
901 if (sigismember(&ss, SIGINT) || sigismember(&ss, SIGTERM) ||
902 sigismember(&ss, SIGKILL) || sigismember(&ss, SIGHUP) ||
903 sigismember(&ss, SIGQUIT))
904 return (EINTR);
905 }
906 return (0);
907 }
908
909 int
910 nfs_rcvlock(struct nfsmount *nmp, struct nfsreq *rep)
911 {
912 int slptimeo = 0;
913 bool catch;
914 int error = 0;
915
916 KASSERT(rep == NULL || nmp == rep->r_nmp);
917
918 catch = (nmp->nm_flag & NFSMNT_INT) != 0;
919 mutex_enter(&nmp->nm_lock);
920 while (/* CONSTCOND */ true) {
921 KASSERT(nmp->nm_rcvlwp != curlwp);
922 if (nmp->nm_iflag & NFSMNT_DISMNT) {
923 cv_signal(&nmp->nm_disconcv);
924 error = EIO;
925 break;
926 }
927 /* If our reply was received while we were sleeping,
928 * then just return without taking the lock to avoid a
929 * situation where a single iod could 'capture' the
930 * receive lock.
931 */
932 if (rep != NULL) {
933 if (rep->r_mrep != NULL) {
934 error = EALREADY;
935 break;
936 }
937 if (nfs_sigintr(rep->r_nmp, rep, rep->r_lwp)) {
938 error = EINTR;
939 break;
940 }
941 }
942 if (nmp->nm_rcvlwp == NULL) {
943 nmp->nm_rcvlwp = curlwp;
944 break;
945 }
946 if (catch) {
947 cv_timedwait_sig(&nmp->nm_rcvcv, &nmp->nm_lock,
948 slptimeo);
949 } else {
950 cv_timedwait(&nmp->nm_rcvcv, &nmp->nm_lock,
951 slptimeo);
952 }
953 if (catch) {
954 catch = false;
955 slptimeo = 2 * hz;
956 }
957 }
958 mutex_exit(&nmp->nm_lock);
959 return error;
960 }
961
962 /*
963 * Unlock the stream socket for others.
964 */
965 void
966 nfs_rcvunlock(struct nfsmount *nmp)
967 {
968
969 mutex_enter(&nmp->nm_lock);
970 if (nmp->nm_rcvlwp != curlwp)
971 panic("nfs rcvunlock");
972 nmp->nm_rcvlwp = NULL;
973 cv_broadcast(&nmp->nm_rcvcv);
974 mutex_exit(&nmp->nm_lock);
975 }
976
977 /*
978 * Parse an RPC request
979 * - verify it
980 * - allocate and fill in the cred.
981 */
982 int
983 nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
984 {
985 int len, i;
986 u_int32_t *tl;
987 int32_t t1;
988 struct uio uio;
989 struct iovec iov;
990 char *dpos, *cp2, *cp;
991 u_int32_t nfsvers, auth_type;
992 uid_t nickuid;
993 int error = 0, ticklen;
994 struct mbuf *mrep, *md;
995 struct nfsuid *nuidp;
996 struct timeval tvin, tvout;
997
998 memset(&tvout, 0, sizeof tvout); /* XXX gcc */
999
1000 KASSERT(nd->nd_cr == NULL);
1001 mrep = nd->nd_mrep;
1002 md = nd->nd_md;
1003 dpos = nd->nd_dpos;
1004 if (has_header) {
1005 nfsm_dissect(tl, u_int32_t *, 10 * NFSX_UNSIGNED);
1006 nd->nd_retxid = fxdr_unsigned(u_int32_t, *tl++);
1007 if (*tl++ != rpc_call) {
1008 m_freem(mrep);
1009 return (EBADRPC);
1010 }
1011 } else
1012 nfsm_dissect(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
1013 nd->nd_repstat = 0;
1014 nd->nd_flag = 0;
1015 if (*tl++ != rpc_vers) {
1016 nd->nd_repstat = ERPCMISMATCH;
1017 nd->nd_procnum = NFSPROC_NOOP;
1018 return (0);
1019 }
1020 if (*tl != nfs_prog) {
1021 nd->nd_repstat = EPROGUNAVAIL;
1022 nd->nd_procnum = NFSPROC_NOOP;
1023 return (0);
1024 }
1025 tl++;
1026 nfsvers = fxdr_unsigned(u_int32_t, *tl++);
1027 if (nfsvers < NFS_VER2 || nfsvers > NFS_VER3) {
1028 nd->nd_repstat = EPROGMISMATCH;
1029 nd->nd_procnum = NFSPROC_NOOP;
1030 return (0);
1031 }
1032 if (nfsvers == NFS_VER3)
1033 nd->nd_flag = ND_NFSV3;
1034 nd->nd_procnum = fxdr_unsigned(u_int32_t, *tl++);
1035 if (nd->nd_procnum == NFSPROC_NULL)
1036 return (0);
1037 if (nd->nd_procnum > NFSPROC_COMMIT ||
1038 (!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
1039 nd->nd_repstat = EPROCUNAVAIL;
1040 nd->nd_procnum = NFSPROC_NOOP;
1041 return (0);
1042 }
1043 if ((nd->nd_flag & ND_NFSV3) == 0)
1044 nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
1045 auth_type = *tl++;
1046 len = fxdr_unsigned(int, *tl++);
1047 if (len < 0 || len > RPCAUTH_MAXSIZ) {
1048 m_freem(mrep);
1049 return (EBADRPC);
1050 }
1051
1052 nd->nd_flag &= ~ND_KERBAUTH;
1053 /*
1054 * Handle auth_unix or auth_kerb.
1055 */
1056 if (auth_type == rpc_auth_unix) {
1057 uid_t uid;
1058 gid_t gid;
1059
1060 nd->nd_cr = kauth_cred_alloc();
1061 len = fxdr_unsigned(int, *++tl);
1062 if (len < 0 || len > NFS_MAXNAMLEN) {
1063 m_freem(mrep);
1064 error = EBADRPC;
1065 goto errout;
1066 }
1067 nfsm_adv(nfsm_rndup(len));
1068 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
1069
1070 uid = fxdr_unsigned(uid_t, *tl++);
1071 gid = fxdr_unsigned(gid_t, *tl++);
1072 kauth_cred_setuid(nd->nd_cr, uid);
1073 kauth_cred_seteuid(nd->nd_cr, uid);
1074 kauth_cred_setsvuid(nd->nd_cr, uid);
1075 kauth_cred_setgid(nd->nd_cr, gid);
1076 kauth_cred_setegid(nd->nd_cr, gid);
1077 kauth_cred_setsvgid(nd->nd_cr, gid);
1078
1079 len = fxdr_unsigned(int, *tl);
1080 if (len < 0 || len > RPCAUTH_UNIXGIDS) {
1081 m_freem(mrep);
1082 error = EBADRPC;
1083 goto errout;
1084 }
1085 nfsm_dissect(tl, u_int32_t *, (len + 2) * NFSX_UNSIGNED);
1086
1087 if (len > 0) {
1088 size_t grbuf_size = min(len, NGROUPS) * sizeof(gid_t);
1089 gid_t *grbuf = kmem_alloc(grbuf_size, KM_SLEEP);
1090
1091 for (i = 0; i < len; i++) {
1092 if (i < NGROUPS) /* XXX elad */
1093 grbuf[i] = fxdr_unsigned(gid_t, *tl++);
1094 else
1095 tl++;
1096 }
1097 kauth_cred_setgroups(nd->nd_cr, grbuf,
1098 min(len, NGROUPS), -1, UIO_SYSSPACE);
1099 kmem_free(grbuf, grbuf_size);
1100 }
1101
1102 len = fxdr_unsigned(int, *++tl);
1103 if (len < 0 || len > RPCAUTH_MAXSIZ) {
1104 m_freem(mrep);
1105 error = EBADRPC;
1106 goto errout;
1107 }
1108 if (len > 0)
1109 nfsm_adv(nfsm_rndup(len));
1110 } else if (auth_type == rpc_auth_kerb) {
1111 switch (fxdr_unsigned(int, *tl++)) {
1112 case RPCAKN_FULLNAME:
1113 ticklen = fxdr_unsigned(int, *tl);
1114 *((u_int32_t *)nfsd->nfsd_authstr) = *tl;
1115 uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
1116 nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
1117 if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
1118 m_freem(mrep);
1119 error = EBADRPC;
1120 goto errout;
1121 }
1122 uio.uio_offset = 0;
1123 uio.uio_iov = &iov;
1124 uio.uio_iovcnt = 1;
1125 UIO_SETUP_SYSSPACE(&uio);
1126 iov.iov_base = (void *)&nfsd->nfsd_authstr[4];
1127 iov.iov_len = RPCAUTH_MAXSIZ - 4;
1128 nfsm_mtouio(&uio, uio.uio_resid);
1129 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1130 if (*tl++ != rpc_auth_kerb ||
1131 fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
1132 printf("Bad kerb verifier\n");
1133 nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
1134 nd->nd_procnum = NFSPROC_NOOP;
1135 return (0);
1136 }
1137 nfsm_dissect(cp, void *, 4 * NFSX_UNSIGNED);
1138 tl = (u_int32_t *)cp;
1139 if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
1140 printf("Not fullname kerb verifier\n");
1141 nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
1142 nd->nd_procnum = NFSPROC_NOOP;
1143 return (0);
1144 }
1145 cp += NFSX_UNSIGNED;
1146 memcpy(nfsd->nfsd_verfstr, cp, 3 * NFSX_UNSIGNED);
1147 nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
1148 nd->nd_flag |= ND_KERBFULL;
1149 nfsd->nfsd_flag |= NFSD_NEEDAUTH;
1150 break;
1151 case RPCAKN_NICKNAME:
1152 if (len != 2 * NFSX_UNSIGNED) {
1153 printf("Kerb nickname short\n");
1154 nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
1155 nd->nd_procnum = NFSPROC_NOOP;
1156 return (0);
1157 }
1158 nickuid = fxdr_unsigned(uid_t, *tl);
1159 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1160 if (*tl++ != rpc_auth_kerb ||
1161 fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
1162 printf("Kerb nick verifier bad\n");
1163 nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
1164 nd->nd_procnum = NFSPROC_NOOP;
1165 return (0);
1166 }
1167 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
1168 tvin.tv_sec = *tl++;
1169 tvin.tv_usec = *tl;
1170
1171 LIST_FOREACH(nuidp, NUIDHASH(nfsd->nfsd_slp, nickuid),
1172 nu_hash) {
1173 if (kauth_cred_geteuid(nuidp->nu_cr) == nickuid &&
1174 (!nd->nd_nam2 ||
1175 netaddr_match(NU_NETFAM(nuidp),
1176 &nuidp->nu_haddr, nd->nd_nam2)))
1177 break;
1178 }
1179 if (!nuidp) {
1180 nd->nd_repstat =
1181 (NFSERR_AUTHERR|AUTH_REJECTCRED);
1182 nd->nd_procnum = NFSPROC_NOOP;
1183 return (0);
1184 }
1185
1186 /*
1187 * Now, decrypt the timestamp using the session key
1188 * and validate it.
1189 */
1190 #ifdef NFSKERB
1191 XXX
1192 #endif
1193
1194 tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
1195 tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
1196 if (nuidp->nu_expire < time_second ||
1197 nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
1198 (nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
1199 nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
1200 nuidp->nu_expire = 0;
1201 nd->nd_repstat =
1202 (NFSERR_AUTHERR|AUTH_REJECTVERF);
1203 nd->nd_procnum = NFSPROC_NOOP;
1204 return (0);
1205 }
1206 kauth_cred_hold(nuidp->nu_cr);
1207 nd->nd_cr = nuidp->nu_cr;
1208 nd->nd_flag |= ND_KERBNICK;
1209 }
1210 } else {
1211 nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
1212 nd->nd_procnum = NFSPROC_NOOP;
1213 return (0);
1214 }
1215
1216 nd->nd_md = md;
1217 nd->nd_dpos = dpos;
1218 KASSERT((nd->nd_cr == NULL && (nfsd->nfsd_flag & NFSD_NEEDAUTH) != 0)
1219 || (nd->nd_cr != NULL && (nfsd->nfsd_flag & NFSD_NEEDAUTH) == 0));
1220 return (0);
1221 nfsmout:
1222 errout:
1223 KASSERT(error != 0);
1224 if (nd->nd_cr != NULL) {
1225 kauth_cred_free(nd->nd_cr);
1226 nd->nd_cr = NULL;
1227 }
1228 return (error);
1229 }
1230
1231 int
1232 nfs_msg(struct lwp *l, const char *server, const char *msg)
1233 {
1234 tpr_t tpr;
1235
1236 #if 0 /* XXX nfs_timer can't block on proc_lock */
1237 if (l)
1238 tpr = tprintf_open(l->l_proc);
1239 else
1240 #endif
1241 tpr = NULL;
1242 tprintf(tpr, "nfs server %s: %s\n", server, msg);
1243 tprintf_close(tpr);
1244 return (0);
1245 }
1246
1247 static struct pool nfs_srvdesc_pool;
1248
1249 void
1250 nfsdreq_init(void)
1251 {
1252
1253 pool_init(&nfs_srvdesc_pool, sizeof(struct nfsrv_descript),
1254 0, 0, 0, "nfsrvdescpl", &pool_allocator_nointr, IPL_NONE);
1255 }
1256
1257 void
1258 nfsdreq_fini(void)
1259 {
1260
1261 pool_destroy(&nfs_srvdesc_pool);
1262 }
1263
1264 struct nfsrv_descript *
1265 nfsdreq_alloc(void)
1266 {
1267 struct nfsrv_descript *nd;
1268
1269 nd = pool_get(&nfs_srvdesc_pool, PR_WAITOK);
1270 nd->nd_cr = NULL;
1271 return nd;
1272 }
1273
1274 void
1275 nfsdreq_free(struct nfsrv_descript *nd)
1276 {
1277 kauth_cred_t cr;
1278
1279 cr = nd->nd_cr;
1280 if (cr != NULL) {
1281 kauth_cred_free(cr);
1282 }
1283 pool_put(&nfs_srvdesc_pool, nd);
1284 }
1285
1286 #if defined(NFS)
1287 void nfs_reqq_dump(void);
1288
1289 void
1290 nfs_reqq_dump(void)
1291 {
1292 struct nfsreq *r;
1293
1294 TAILQ_FOREACH(r, &nfs_reqq, r_chain) {
1295 printf("%p: proc=%" PRId32 ", lwp=%p, nmp=%p\n"
1296 "\tflags=0x%x, rflags=0x%x\n"
1297 "\treq=%p, rep=%p, xid=0x%" PRIx32 "\n"
1298 "\tretry=%d, rexmit=%d, timer=%d, rtt=%d\n",
1299 r, r->r_procnum, r->r_lwp, r->r_nmp,
1300 r->r_flags, r->r_rflags,
1301 r->r_mreq, r->r_mrep, r->r_xid,
1302 r->r_retry, r->r_rexmit, r->r_timer, r->r_rtt);
1303 }
1304 }
1305 #endif /* defined(NFS) */
1306