1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
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 */
35
36 #include <sys/cdefs.h>
37 /*
38 * Socket operations for use by nfs
39 */
40
41 #include "opt_kgssapi.h"
42 #include "opt_nfs.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/limits.h>
48 #include <sys/lock.h>
49 #include <sys/malloc.h>
50 #include <sys/mbuf.h>
51 #include <sys/mount.h>
52 #include <sys/mutex.h>
53 #include <sys/proc.h>
54 #include <sys/signalvar.h>
55 #include <sys/syscallsubr.h>
56 #include <sys/sysctl.h>
57 #include <sys/syslog.h>
58 #include <sys/vnode.h>
59
60 #include <rpc/rpc.h>
61 #include <rpc/krpc.h>
62 #include <rpc/clntrdma.h>
63
64 #include <kgssapi/krb5/kcrypto.h>
65
66 #include <fs/nfs/nfsport.h>
67
68 #ifdef KDTRACE_HOOKS
69 #include <sys/dtrace_bsd.h>
70
71 dtrace_nfsclient_nfs23_start_probe_func_t
72 dtrace_nfscl_nfs234_start_probe;
73
74 dtrace_nfsclient_nfs23_done_probe_func_t
75 dtrace_nfscl_nfs234_done_probe;
76
77 /*
78 * Registered probes by RPC type.
79 */
80 uint32_t nfscl_nfs2_start_probes[NFSV41_NPROCS + 1];
81 uint32_t nfscl_nfs2_done_probes[NFSV41_NPROCS + 1];
82
83 uint32_t nfscl_nfs3_start_probes[NFSV41_NPROCS + 1];
84 uint32_t nfscl_nfs3_done_probes[NFSV41_NPROCS + 1];
85
86 uint32_t nfscl_nfs4_start_probes[NFSV41_NPROCS + 1];
87 uint32_t nfscl_nfs4_done_probes[NFSV41_NPROCS + 1];
88 #endif
89
90 NFSSTATESPINLOCK;
91 NFSREQSPINLOCK;
92 NFSDLOCKMUTEX;
93 NFSCLSTATEMUTEX;
94 extern struct nfsstatsv1 nfsstatsv1;
95 extern struct nfsreqhead nfsd_reqq;
96 extern int nfscl_ticks;
97 extern void (*ncl_call_invalcaches)(struct vnode *);
98 extern int nfs_numnfscbd;
99 extern int nfscl_debuglevel;
100 extern int nfsrv_lease;
101
102 SVCPOOL *nfscbd_pool;
103 int nfs_bufpackets = 4;
104 static int nfsrv_gsscallbackson = 0;
105 static int nfs_reconnects;
106 static int nfs3_jukebox_delay = 10;
107 static int nfs_skip_wcc_data_onerr = 1;
108 static int nfs_dsretries = 2;
109 static struct timespec nfs_trylater_max = {
110 .tv_sec = NFS_TRYLATERDEL,
111 .tv_nsec = 0,
112 };
113
114 SYSCTL_DECL(_vfs_nfs);
115
116 SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0,
117 "Buffer reservation size 2 < x < 64");
118 SYSCTL_INT(_vfs_nfs, OID_AUTO, reconnects, CTLFLAG_RD, &nfs_reconnects, 0,
119 "Number of times the nfs client has had to reconnect");
120 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs3_jukebox_delay, CTLFLAG_RW, &nfs3_jukebox_delay, 0,
121 "Number of seconds to delay a retry after receiving EJUKEBOX");
122 SYSCTL_INT(_vfs_nfs, OID_AUTO, skip_wcc_data_onerr, CTLFLAG_RW, &nfs_skip_wcc_data_onerr, 0,
123 "Disable weak cache consistency checking when server returns an error");
124 SYSCTL_INT(_vfs_nfs, OID_AUTO, dsretries, CTLFLAG_RW, &nfs_dsretries, 0,
125 "Number of retries for a DS RPC before failure");
126
127 static void nfs_down(struct nfsmount *, struct thread *, const char *,
128 int, int);
129 static void nfs_up(struct nfsmount *, struct thread *, const char *,
130 int, int);
131 static int nfs_msg(struct thread *, const char *, const char *, int);
132
133 struct nfs_cached_auth {
134 int ca_refs; /* refcount, including 1 from the cache */
135 uid_t ca_uid; /* uid that corresponds to this auth */
136 AUTH *ca_auth; /* RPC auth handle */
137 };
138
139 static int nfsv2_procid[NFS_V3NPROCS] = {
140 NFSV2PROC_NULL,
141 NFSV2PROC_GETATTR,
142 NFSV2PROC_SETATTR,
143 NFSV2PROC_LOOKUP,
144 NFSV2PROC_NOOP,
145 NFSV2PROC_READLINK,
146 NFSV2PROC_READ,
147 NFSV2PROC_WRITE,
148 NFSV2PROC_CREATE,
149 NFSV2PROC_MKDIR,
150 NFSV2PROC_SYMLINK,
151 NFSV2PROC_CREATE,
152 NFSV2PROC_REMOVE,
153 NFSV2PROC_RMDIR,
154 NFSV2PROC_RENAME,
155 NFSV2PROC_LINK,
156 NFSV2PROC_READDIR,
157 NFSV2PROC_NOOP,
158 NFSV2PROC_STATFS,
159 NFSV2PROC_NOOP,
160 NFSV2PROC_NOOP,
161 NFSV2PROC_NOOP,
162 };
163
164 /*
165 * This static array indicates that a NFSv4 RPC should use
166 * RPCSEC_GSS, if the mount indicates that via sec=krb5[ip].
167 * System RPCs that do not use file handles will be false
168 * in this array so that they will use AUTH_SYS when the
169 * "syskrb5" mount option is specified, along with
170 * "sec=krb5[ip]".
171 */
172 static bool nfscl_use_gss[NFSV42_NPROCS] = {
173 true,
174 true,
175 true,
176 true,
177 true,
178 true,
179 true,
180 true,
181 true,
182 true,
183 true,
184 true,
185 true,
186 true,
187 true,
188 true,
189 true,
190 true,
191 true,
192 true,
193 true,
194 true,
195 true,
196 false, /* SetClientID */
197 false, /* SetClientIDConfirm */
198 true,
199 true,
200 true,
201 true,
202 true,
203 true,
204 true,
205 false, /* Renew */
206 true,
207 false, /* ReleaseLockOwn */
208 true,
209 true,
210 true,
211 true,
212 true,
213 true,
214 false, /* ExchangeID */
215 false, /* CreateSession */
216 false, /* DestroySession */
217 false, /* DestroyClientID */
218 false, /* FreeStateID */
219 true,
220 true,
221 true,
222 true,
223 false, /* ReclaimComplete */
224 true,
225 true,
226 true,
227 true,
228 true,
229 true,
230 true,
231 true,
232 true,
233 true,
234 true,
235 true,
236 true,
237 true,
238 false, /* BindConnectionToSession */
239 true,
240 true,
241 true,
242 true,
243 true,
244 };
245
246 /*
247 * Initialize sockets and congestion for a new NFS connection.
248 * We do not free the sockaddr if error.
249 * Which arguments are set to NULL indicate what kind of call it is.
250 * cred == NULL --> a call to connect to a pNFS DS
251 * nmp == NULL --> indicates an upcall to userland or a NFSv4.0 callback
252 */
253 int
newnfs_connect(struct nfsmount * nmp,struct nfssockreq * nrp,struct ucred * cred,NFSPROC_T * p,int callback_retry_mult,bool dotls,struct __rpc_client ** clipp)254 newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
255 struct ucred *cred, NFSPROC_T *p, int callback_retry_mult, bool dotls,
256 struct __rpc_client **clipp)
257 {
258 int rcvreserve, sndreserve;
259 int pktscale, pktscalesav;
260 struct sockaddr *saddr;
261 struct ucred *origcred;
262 CLIENT *client;
263 struct netconfig *nconf;
264 struct socket *so;
265 int one = 1, retries, error = 0, val;
266 struct thread *td = curthread;
267 SVCXPRT *xprt;
268 struct timeval timo;
269 uint64_t tval;
270
271 /*
272 * We need to establish the socket using the credentials of
273 * the mountpoint. Some parts of this process (such as
274 * sobind() and soconnect()) will use the curent thread's
275 * credential instead of the socket credential. To work
276 * around this, temporarily change the current thread's
277 * credential to that of the mountpoint.
278 *
279 * XXX: It would be better to explicitly pass the correct
280 * credential to sobind() and soconnect().
281 */
282 origcred = td->td_ucred;
283
284 /*
285 * Use the credential in nr_cred, if not NULL.
286 */
287 if (nrp->nr_cred != NULL)
288 td->td_ucred = nrp->nr_cred;
289 else
290 td->td_ucred = cred;
291 saddr = nrp->nr_nam;
292
293 if (saddr->sa_family == AF_INET) {
294 if (nmp != NULL && NFSHASRDMA(nmp))
295 nconf = getnetconfigent("rdma");
296 else if (nrp->nr_sotype == SOCK_DGRAM)
297 nconf = getnetconfigent("udp");
298 else
299 nconf = getnetconfigent("tcp");
300 } else {
301 if (nmp != NULL && NFSHASRDMA(nmp))
302 nconf = getnetconfigent("rdma6");
303 else if (nrp->nr_sotype == SOCK_DGRAM)
304 nconf = getnetconfigent("udp6");
305 else
306 nconf = getnetconfigent("tcp6");
307 }
308
309 sndreserve = rcvreserve = 0;
310 if (nmp == NULL || !NFSHASRDMA(nmp)) {
311 pktscale = nfs_bufpackets;
312 if (pktscale < 2)
313 pktscale = 2;
314 if (pktscale > 64)
315 pktscale = 64;
316 pktscalesav = pktscale;
317 /*
318 * soreserve() can fail if sb_max is too small, so shrink
319 * pktscale and try again if there is an error.
320 * Print a log message suggesting increasing sb_max.
321 * Creating a socket and doing this is necessary since, if the
322 * reservation sizes are too large and will make soreserve()
323 * fail, the connection will work until a large send is
324 * attempted and then it will loop in the krpc code.
325 */
326 so = NULL;
327 saddr = NFSSOCKADDR(nrp->nr_nam, struct sockaddr *);
328 error = socreate(saddr->sa_family, &so, nrp->nr_sotype,
329 nrp->nr_soproto, td->td_ucred, td);
330 if (error != 0)
331 goto out;
332 do {
333 if (error != 0 && pktscale > 2) {
334 if (nmp != NULL && nrp->nr_sotype == SOCK_STREAM &&
335 pktscale == pktscalesav) {
336 /*
337 * Suggest vfs.nfs.bufpackets * maximum RPC message,
338 * adjusted for the sb_max->sb_max_adj conversion of
339 * MCLBYTES / (MSIZE + MCLBYTES) as the minimum
340 * setting for kern.ipc.maxsockbuf.
341 */
342 tval = (NFS_MAXBSIZE + NFS_MAXXDR) * nfs_bufpackets;
343 tval *= MSIZE + MCLBYTES;
344 tval += MCLBYTES - 1; /* Round up divide. */
345 tval /= MCLBYTES;
346 printf("Consider increasing kern.ipc.maxsockbuf to "
347 "a minimum of %ju to support %ubyte NFS I/O\n",
348 (uintmax_t)tval, NFS_MAXBSIZE);
349 }
350 pktscale--;
351 }
352 if (nrp->nr_sotype == SOCK_DGRAM) {
353 if (nmp != NULL) {
354 sndreserve = (NFS_MAXDGRAMDATA +
355 NFS_MAXPKTHDR) * pktscale;
356 rcvreserve = (NFS_MAXDGRAMDATA +
357 NFS_MAXPKTHDR) * pktscale;
358 } else {
359 sndreserve = rcvreserve = 1024 * pktscale;
360 }
361 } else {
362 if (nrp->nr_sotype != SOCK_STREAM)
363 panic("nfscon sotype");
364 if (nmp != NULL) {
365 sndreserve = (NFS_MAXBSIZE + NFS_MAXXDR) *
366 pktscale;
367 rcvreserve = (NFS_MAXBSIZE + NFS_MAXXDR) *
368 pktscale;
369 } else {
370 sndreserve = rcvreserve = 1024 * pktscale;
371 }
372 }
373 error = soreserve(so, sndreserve, rcvreserve);
374 if (error != 0 && nmp != NULL &&
375 nrp->nr_sotype == SOCK_STREAM && pktscale <= 2)
376 printf("Must increase kern.ipc.maxsockbuf or reduce"
377 " rsize, wsize\n");
378 } while (error != 0 && pktscale > 2);
379 soclose(so);
380 }
381 if (error != 0)
382 goto out;
383
384 client = clnt_reconnect_create(nconf, saddr, nrp->nr_prog,
385 nrp->nr_vers, sndreserve, rcvreserve);
386 CLNT_CONTROL(client, CLSET_WAITCHAN, "nfsreq");
387 if (nmp != NULL && !NFSHASRDMA(nmp)) {
388 if ((nmp->nm_flag & NFSMNT_INT))
389 CLNT_CONTROL(client, CLSET_INTERRUPTIBLE, &one);
390 if ((nmp->nm_flag & NFSMNT_RESVPORT))
391 CLNT_CONTROL(client, CLSET_PRIVPORT, &one);
392 if (NFSHASTLS(nmp)) {
393 CLNT_CONTROL(client, CLSET_TLS, &one);
394 if (nmp->nm_tlscertname != NULL)
395 CLNT_CONTROL(client, CLSET_TLSCERTNAME,
396 nmp->nm_tlscertname);
397 }
398 if (NFSHASSOFT(nmp)) {
399 if (nmp->nm_sotype == SOCK_DGRAM)
400 /*
401 * For UDP, the large timeout for a reconnect
402 * will be set to "nm_retry * nm_timeo / 2", so
403 * we only want to do 2 reconnect timeout
404 * retries.
405 */
406 retries = 2;
407 else
408 retries = nmp->nm_retry;
409 } else
410 retries = INT_MAX;
411 if (NFSHASNFSV4N(nmp)) {
412 if (cred != NULL) {
413 if (NFSHASSOFT(nmp)) {
414 /*
415 * This should be a DS mount.
416 * Use CLSET_TIMEOUT to set the timeout
417 * for connections to DSs instead of
418 * specifying a timeout on each RPC.
419 * This is done so that SO_SNDTIMEO
420 * is set on the TCP socket as well
421 * as specifying a time limit when
422 * waiting for an RPC reply. Useful
423 * if the send queue for the TCP
424 * connection has become constipated,
425 * due to a failed DS.
426 * The choice of lease_duration / 4 is
427 * fairly arbitrary, but seems to work
428 * ok, with a lower bound of 10sec.
429 */
430 timo.tv_sec = nfsrv_lease / 4;
431 if (timo.tv_sec < 10)
432 timo.tv_sec = 10;
433 timo.tv_usec = 0;
434 CLNT_CONTROL(client, CLSET_TIMEOUT,
435 &timo);
436 }
437 /*
438 * Make sure the nfscbd_pool doesn't get
439 * destroyed while doing this.
440 */
441 NFSD_LOCK();
442 if (nfs_numnfscbd > 0) {
443 nfs_numnfscbd++;
444 NFSD_UNLOCK();
445 xprt = svc_vc_create_backchannel(
446 nfscbd_pool);
447 CLNT_CONTROL(client, CLSET_BACKCHANNEL,
448 xprt);
449 NFSD_LOCK();
450 nfs_numnfscbd--;
451 if (nfs_numnfscbd == 0)
452 wakeup(&nfs_numnfscbd);
453 }
454 NFSD_UNLOCK();
455 } else {
456 /*
457 * cred == NULL for a DS connect.
458 * For connects to a DS, set a retry limit
459 * so that failed DSs will be detected.
460 * This is ok for NFSv4.1, since a DS does
461 * not maintain open/lock state and is the
462 * only case where using a "soft" mount is
463 * recommended for NFSv4.
464 * For mounts from the MDS to DS, this is done
465 * via mount options, but that is not the case
466 * here. The retry limit here can be adjusted
467 * via the sysctl vfs.nfs.dsretries.
468 * See the comment above w.r.t. timeout.
469 */
470 timo.tv_sec = nfsrv_lease / 4;
471 if (timo.tv_sec < 10)
472 timo.tv_sec = 10;
473 timo.tv_usec = 0;
474 CLNT_CONTROL(client, CLSET_TIMEOUT, &timo);
475 retries = nfs_dsretries;
476 }
477 }
478 } else if (nmp == NULL) {
479 /*
480 * Three cases:
481 * - Null RPC callback to client
482 * - Non-Null RPC callback to client, wait a little longer
483 * - upcalls to nfsuserd and gssd (clp == NULL)
484 */
485 if (callback_retry_mult == 0) {
486 retries = NFSV4_UPCALLRETRY;
487 CLNT_CONTROL(client, CLSET_PRIVPORT, &one);
488 } else {
489 retries = NFSV4_CALLBACKRETRY * callback_retry_mult;
490 }
491 if (dotls)
492 CLNT_CONTROL(client, CLSET_TLS, &one);
493 } else {
494 /* RDMA. */
495 if (NFSHASNFSV4N(nmp) && cred != NULL &&
496 svc_rdma_create_backchannel_call != NULL) {
497 /*
498 * Set up the backchannel.
499 */
500 /*
501 * Make sure the nfscbd_pool doesn't get
502 * destroyed while doing this.
503 */
504 NFSD_LOCK();
505 if (nfs_numnfscbd > 0) {
506 nfs_numnfscbd++;
507 NFSD_UNLOCK();
508 xprt = svc_rdma_create_backchannel_call(
509 nfscbd_pool);
510 CLNT_CONTROL(client, CLSET_BACKCHANNEL, xprt);
511 NFSD_LOCK();
512 nfs_numnfscbd--;
513 if (nfs_numnfscbd == 0)
514 wakeup(&nfs_numnfscbd);
515 }
516 NFSD_UNLOCK();
517 }
518
519 /* Set the small reply size for a Readdir. */
520 val = NFS_DIRBLKSIZ + PAGE_SIZE;
521 CLNT_CONTROL(client, CLSET_RDMASMALL_REPLY, &val);
522 val = NFSV4_CBSLOTS;
523 CLNT_CONTROL(client, CLSET_RDMA_CBSLOTS, &val);
524 if (NFSHASSOFT(nmp))
525 retries = nmp->nm_retry;
526 else
527 retries = INT_MAX;
528 }
529 CLNT_CONTROL(client, CLSET_RETRIES, &retries);
530
531 if (nmp != NULL) {
532 /*
533 * For UDP, there are 2 timeouts:
534 * - CLSET_RETRY_TIMEOUT sets the initial timeout for the timer
535 * that does a retransmit of an RPC request using the same
536 * socket and xid. This is what you normally want to do,
537 * since NFS servers depend on "same xid" for their
538 * Duplicate Request Cache.
539 * - timeout specified in CLNT_CALL_MBUF(), which specifies when
540 * retransmits on the same socket should fail and a fresh
541 * socket created. Each of these timeouts counts as one
542 * CLSET_RETRIES as set above.
543 * Set the initial retransmit timeout for UDP. This timeout
544 * doesn't exist for TCP and the following call just fails,
545 * which is ok.
546 */
547 timo.tv_sec = nmp->nm_timeo / NFS_HZ;
548 timo.tv_usec = (nmp->nm_timeo % NFS_HZ) * 1000000 / NFS_HZ;
549 CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, &timo);
550 }
551
552 /*
553 * *clipp is &nrp->nr_client or &nm_aconn[nmp->nm_nextaconn].
554 * The latter case is for additional connections specified by the
555 * "nconnect" mount option. nr_mtx etc is used for these additional
556 * connections, as well as nr_client in the nfssockreq
557 * structure for the mount.
558 */
559 mtx_lock(&nrp->nr_mtx);
560 if (*clipp != NULL) {
561 mtx_unlock(&nrp->nr_mtx);
562 /*
563 * Someone else already connected.
564 */
565 CLNT_RELEASE(client);
566 } else {
567 *clipp = client;
568 /*
569 * Protocols that do not require connections may be optionally
570 * left unconnected for servers that reply from a port other
571 * than NFS_PORT.
572 */
573 if (nmp == NULL || (nmp->nm_flag & NFSMNT_NOCONN) == 0) {
574 mtx_unlock(&nrp->nr_mtx);
575 CLNT_CONTROL(client, CLSET_CONNECT, &one);
576 } else
577 mtx_unlock(&nrp->nr_mtx);
578 }
579
580 out:
581 /* Restore current thread's credentials. */
582 td->td_ucred = origcred;
583
584 NFSEXITCODE(error);
585 return (error);
586 }
587
588 /*
589 * NFS disconnect. Clean up and unlink.
590 */
591 void
newnfs_disconnect(struct nfsmount * nmp,struct nfssockreq * nrp)592 newnfs_disconnect(struct nfsmount *nmp, struct nfssockreq *nrp)
593 {
594 CLIENT *client, *aconn[NFS_MAXNCONN - 1];
595 int i;
596
597 mtx_lock(&nrp->nr_mtx);
598 if (nrp->nr_client != NULL) {
599 client = nrp->nr_client;
600 nrp->nr_client = NULL;
601 if (nmp != NULL && nmp->nm_aconnect > 0) {
602 for (i = 0; i < nmp->nm_aconnect; i++) {
603 aconn[i] = nmp->nm_aconn[i];
604 nmp->nm_aconn[i] = NULL;
605 }
606 }
607 mtx_unlock(&nrp->nr_mtx);
608 CURVNET_SET_QUIET(CRED_TO_VNET(nrp->nr_cred));
609 rpc_gss_secpurge_call(client);
610 CURVNET_RESTORE();
611 CLNT_CLOSE(client);
612 CLNT_RELEASE(client);
613 if (nmp != NULL && nmp->nm_aconnect > 0) {
614 for (i = 0; i < nmp->nm_aconnect; i++) {
615 if (aconn[i] != NULL) {
616 rpc_gss_secpurge_call(aconn[i]);
617 CLNT_CLOSE(aconn[i]);
618 CLNT_RELEASE(aconn[i]);
619 }
620 }
621 }
622 } else {
623 mtx_unlock(&nrp->nr_mtx);
624 }
625 }
626
627 static AUTH *
nfs_getauth(struct nfssockreq * nrp,int secflavour,char * clnt_principal,char * srv_principal,gss_OID mech_oid,struct ucred * cred)628 nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal,
629 char *srv_principal, gss_OID mech_oid, struct ucred *cred)
630 {
631 rpc_gss_service_t svc;
632 AUTH *auth;
633
634 switch (secflavour) {
635 case RPCSEC_GSS_KRB5:
636 case RPCSEC_GSS_KRB5I:
637 case RPCSEC_GSS_KRB5P:
638 if (!mech_oid) {
639 if (!rpc_gss_mech_to_oid_call("kerberosv5", &mech_oid))
640 return (NULL);
641 }
642 if (secflavour == RPCSEC_GSS_KRB5)
643 svc = rpc_gss_svc_none;
644 else if (secflavour == RPCSEC_GSS_KRB5I)
645 svc = rpc_gss_svc_integrity;
646 else
647 svc = rpc_gss_svc_privacy;
648
649 if (clnt_principal == NULL) {
650 NFSCL_DEBUG(1, "nfs_getauth: clnt princ=NULL, "
651 "srv princ=%s\n", srv_principal);
652 auth = rpc_gss_secfind_call(nrp->nr_client, cred,
653 srv_principal, mech_oid, svc);
654 } else {
655 NFSCL_DEBUG(1, "nfs_getauth: clnt princ=%s "
656 "srv princ=%s\n", clnt_principal, srv_principal);
657 auth = rpc_gss_seccreate_call(nrp->nr_client, cred,
658 clnt_principal, srv_principal, "kerberosv5",
659 svc, NULL, NULL, NULL);
660 return (auth);
661 }
662 if (auth != NULL)
663 return (auth);
664 /* fallthrough */
665 case AUTH_SYS:
666 default:
667 return (authunix_create(cred));
668 }
669 }
670
671 /*
672 * Callback from the RPC code to generate up/down notifications.
673 */
674
675 struct nfs_feedback_arg {
676 struct nfsmount *nf_mount;
677 int nf_lastmsg; /* last tprintf */
678 int nf_tprintfmsg;
679 struct thread *nf_td;
680 };
681
682 static void
nfs_feedback(int type,int proc,void * arg)683 nfs_feedback(int type, int proc, void *arg)
684 {
685 struct nfs_feedback_arg *nf = (struct nfs_feedback_arg *) arg;
686 struct nfsmount *nmp = nf->nf_mount;
687 time_t now;
688
689 switch (type) {
690 case FEEDBACK_REXMIT2:
691 case FEEDBACK_RECONNECT:
692 now = NFSD_MONOSEC;
693 if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now) {
694 nfs_down(nmp, nf->nf_td,
695 "not responding", 0, NFSSTA_TIMEO);
696 nf->nf_tprintfmsg = TRUE;
697 nf->nf_lastmsg = now;
698 }
699 break;
700
701 case FEEDBACK_OK:
702 nfs_up(nf->nf_mount, nf->nf_td,
703 "is alive again", NFSSTA_TIMEO, nf->nf_tprintfmsg);
704 break;
705 }
706 }
707
708 /*
709 * newnfs_request - goes something like this
710 * - does the rpc by calling the krpc layer
711 * - break down rpc header and return with nfs reply
712 * nb: always frees up nd_mreq mbuf list
713 */
714 int
newnfs_request(struct nfsrv_descript * nd,struct nfsmount * nmp,struct nfsclient * clp,struct nfssockreq * nrp,vnode_t vp,struct thread * td,struct ucred * cred,u_int32_t prog,u_int32_t vers,u_char * retsum,int toplevel,u_int64_t * xidp,struct nfsclsession * dssep)715 newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
716 struct nfsclient *clp, struct nfssockreq *nrp, vnode_t vp,
717 struct thread *td, struct ucred *cred, u_int32_t prog, u_int32_t vers,
718 u_char *retsum, int toplevel, u_int64_t *xidp, struct nfsclsession *dssep)
719 {
720 uint32_t retseq, retval, retval0, slotseq, *tl;
721 int i = 0, j = 0, opcnt, set_sigset = 0, slot;
722 int error = 0, usegssname = 0, secflavour = AUTH_SYS;
723 int freeslot, maxslot, reterr, slotpos, timeo;
724 u_int16_t procnum;
725 u_int nextconn;
726 struct nfs_feedback_arg nf;
727 struct timeval timo;
728 AUTH *auth;
729 struct rpc_callextra ext;
730 enum clnt_stat stat;
731 struct nfsreq *rep = NULL;
732 char *srv_principal = NULL, *clnt_principal = NULL;
733 sigset_t oldset;
734 struct ucred *authcred, *savcred;
735 struct nfsclsession *sep;
736 uint8_t sessionid[NFSX_V4SESSIONID];
737 bool nextconn_set, has_mreduce;
738 struct timespec trylater_delay, ts, waituntil;
739
740 /* Initially 1msec. */
741 trylater_delay.tv_sec = 0;
742 trylater_delay.tv_nsec = 1000000;
743 sep = dssep;
744 if (xidp != NULL)
745 *xidp = 0;
746 /* Reject requests while attempting a forced unmount. */
747 if (nmp != NULL && NFSCL_FORCEDISM(nmp->nm_mountp)) {
748 m_freem(nd->nd_mreq);
749 return (ESTALE);
750 }
751
752 has_mreduce = false;
753 if (nmp != NULL && NFSHASRDMA(nmp) &&
754 (nd->nd_mreq->m_flags & M_PROTO11) != 0)
755 has_mreduce = true;
756 /*
757 * Set authcred, which is used to acquire RPC credentials to
758 * the cred argument, by default. The crhold() should not be
759 * necessary, but will ensure that some future code change
760 * doesn't result in the credential being free'd prematurely.
761 */
762 authcred = crhold(cred);
763
764 /* For client side interruptible mounts, mask off the signals. */
765 if (nmp != NULL && td != NULL && NFSHASINT(nmp)) {
766 newnfs_set_sigmask(td, &oldset);
767 set_sigset = 1;
768 }
769
770 /*
771 * If not already connected call newnfs_connect now.
772 */
773 if (nrp->nr_client == NULL)
774 newnfs_connect(nmp, nrp, cred, td, 0, false, &nrp->nr_client);
775
776 /*
777 * If the "nconnect" mount option was specified and this RPC is
778 * one that can have a large RPC message and is being done through
779 * the NFS/MDS server, use an additional connection. (When the RPC is
780 * being done through the server/MDS, nrp == &nmp->nm_sockreq.)
781 * The "nconnect" mount option normally has minimal effect when the
782 * "pnfs" mount option is specified, since only Readdir RPCs are
783 * normally done through the NFS/MDS server.
784 */
785 nextconn_set = false;
786 if (nmp != NULL && nmp->nm_aconnect > 0 && nrp == &nmp->nm_sockreq &&
787 (nd->nd_procnum == NFSPROC_READ ||
788 nd->nd_procnum == NFSPROC_READDIR ||
789 nd->nd_procnum == NFSPROC_READDIRPLUS ||
790 nd->nd_procnum == NFSPROC_WRITE)) {
791 nextconn = atomic_fetchadd_int(&nmp->nm_nextaconn, 1);
792 nextconn %= nmp->nm_aconnect;
793 nextconn_set = true;
794 if (nmp->nm_aconn[nextconn] == NULL)
795 newnfs_connect(nmp, nrp, cred, td, 0, false,
796 &nmp->nm_aconn[nextconn]);
797 }
798
799 /*
800 * For a client side mount, nmp is != NULL and clp == NULL. For
801 * server calls (callbacks or upcalls), nmp == NULL.
802 */
803 if (clp != NULL) {
804 NFSLOCKSTATE();
805 if ((clp->lc_flags & LCL_GSS) && nfsrv_gsscallbackson) {
806 secflavour = RPCSEC_GSS_KRB5;
807 if (nd->nd_procnum != NFSPROC_NULL) {
808 if (clp->lc_flags & LCL_GSSINTEGRITY)
809 secflavour = RPCSEC_GSS_KRB5I;
810 else if (clp->lc_flags & LCL_GSSPRIVACY)
811 secflavour = RPCSEC_GSS_KRB5P;
812 }
813 }
814 NFSUNLOCKSTATE();
815 } else if (nmp != NULL && NFSHASKERB(nmp) &&
816 nd->nd_procnum != NFSPROC_NULL && (!NFSHASSYSKRB5(nmp) ||
817 nfscl_use_gss[nd->nd_procnum])) {
818 if (NFSHASALLGSSNAME(nmp) && nmp->nm_krbnamelen > 0)
819 nd->nd_flag |= ND_USEGSSNAME;
820 if ((nd->nd_flag & ND_USEGSSNAME) != 0) {
821 /*
822 * If there is a client side host based credential,
823 * use that, otherwise use the system uid, if set.
824 * The system uid is in the nmp->nm_sockreq.nr_cred
825 * credentials.
826 */
827 if (nmp->nm_krbnamelen > 0) {
828 usegssname = 1;
829 clnt_principal = nmp->nm_krbname;
830 } else if (nmp->nm_uid != (uid_t)-1) {
831 KASSERT(nmp->nm_sockreq.nr_cred != NULL,
832 ("newnfs_request: NULL nr_cred"));
833 crfree(authcred);
834 authcred = crhold(nmp->nm_sockreq.nr_cred);
835 }
836 } else if (nmp->nm_krbnamelen == 0 &&
837 nmp->nm_uid != (uid_t)-1 && cred->cr_uid == (uid_t)0) {
838 /*
839 * If there is no host based principal name and
840 * the system uid is set and this is root, use the
841 * system uid, since root won't have user
842 * credentials in a credentials cache file.
843 * The system uid is in the nmp->nm_sockreq.nr_cred
844 * credentials.
845 */
846 KASSERT(nmp->nm_sockreq.nr_cred != NULL,
847 ("newnfs_request: NULL nr_cred"));
848 crfree(authcred);
849 authcred = crhold(nmp->nm_sockreq.nr_cred);
850 }
851 if (NFSHASINTEGRITY(nmp))
852 secflavour = RPCSEC_GSS_KRB5I;
853 else if (NFSHASPRIVACY(nmp))
854 secflavour = RPCSEC_GSS_KRB5P;
855 else
856 secflavour = RPCSEC_GSS_KRB5;
857 if (nrp->nr_srvprinc[0] == '\0')
858 srv_principal = NFSMNT_SRVKRBNAME(nmp);
859 else
860 srv_principal = nrp->nr_srvprinc;
861 } else if (nmp != NULL && (!NFSHASKERB(nmp) || NFSHASSYSKRB5(nmp)) &&
862 nd->nd_procnum != NFSPROC_NULL &&
863 (nd->nd_flag & ND_USEGSSNAME) != 0) {
864 /*
865 * Use the uid that did the mount when the RPC is doing
866 * NFSv4 system operations, as indicated by the
867 * ND_USEGSSNAME flag, for the AUTH_SYS case.
868 * The credentials in nm_sockreq.nr_cred were used for the
869 * mount.
870 */
871 KASSERT(nmp->nm_sockreq.nr_cred != NULL,
872 ("newnfs_request: NULL nr_cred"));
873 crfree(authcred);
874 authcred = crhold(nmp->nm_sockreq.nr_cred);
875 }
876
877 if (nmp != NULL) {
878 bzero(&nf, sizeof(struct nfs_feedback_arg));
879 nf.nf_mount = nmp;
880 nf.nf_td = td;
881 nf.nf_lastmsg = NFSD_MONOSEC -
882 ((nmp->nm_tprintf_delay)-(nmp->nm_tprintf_initial_delay));
883 }
884
885 /*
886 * For Kerberos, the upcall needs to be done to the gssd daemon
887 * running in the correct vnet.
888 */
889 CURVNET_SET_QUIET(CRED_TO_VNET(authcred));
890 if (nd->nd_procnum == NFSPROC_NULL)
891 auth = authnone_create();
892 else if (usegssname) {
893 /*
894 * For this case, the authenticator is held in the
895 * nfssockreq structure, so don't release the reference count
896 * held on it. --> Don't AUTH_DESTROY() it in this function.
897 */
898 if (nrp->nr_auth == NULL)
899 nrp->nr_auth = nfs_getauth(nrp, secflavour,
900 clnt_principal, srv_principal, NULL, authcred);
901 else
902 rpc_gss_refresh_auth_call(nrp->nr_auth);
903 auth = nrp->nr_auth;
904 } else
905 auth = nfs_getauth(nrp, secflavour, NULL,
906 srv_principal, NULL, authcred);
907 CURVNET_RESTORE();
908 if (auth == NULL) {
909 crfree(authcred);
910 m_freem(nd->nd_mreq);
911 if (set_sigset)
912 newnfs_restore_sigmask(td, &oldset);
913 return (EACCES);
914 }
915 bzero(&ext, sizeof(ext));
916 ext.rc_auth = auth;
917 if (nmp != NULL) {
918 ext.rc_feedback = nfs_feedback;
919 ext.rc_feedback_arg = &nf;
920 }
921
922 procnum = nd->nd_procnum;
923 if ((nd->nd_flag & ND_NFSV4) &&
924 nd->nd_procnum != NFSPROC_NULL &&
925 nd->nd_procnum != NFSV4PROC_CBCOMPOUND)
926 procnum = NFSV4PROC_COMPOUND;
927
928 if (nmp != NULL) {
929 NFSINCRGLOBAL(nfsstatsv1.rpcrequests);
930
931 /* Map the procnum to the old NFSv2 one, as required. */
932 if ((nd->nd_flag & ND_NFSV2) != 0) {
933 if (nd->nd_procnum < NFS_V3NPROCS)
934 procnum = nfsv2_procid[nd->nd_procnum];
935 else
936 procnum = NFSV2PROC_NOOP;
937 }
938
939 /*
940 * Now only used for the R_DONTRECOVER case, but until that is
941 * supported within the krpc code, I need to keep a queue of
942 * outstanding RPCs for nfsv4 client requests.
943 */
944 if ((nd->nd_flag & ND_NFSV4) && procnum == NFSV4PROC_COMPOUND)
945 rep = malloc(sizeof(struct nfsreq),
946 M_NFSDREQ, M_WAITOK);
947 #ifdef KDTRACE_HOOKS
948 if (dtrace_nfscl_nfs234_start_probe != NULL) {
949 uint32_t probe_id;
950 int probe_procnum;
951
952 if (nd->nd_flag & ND_NFSV4) {
953 probe_id =
954 nfscl_nfs4_start_probes[nd->nd_procnum];
955 probe_procnum = nd->nd_procnum;
956 } else if (nd->nd_flag & ND_NFSV3) {
957 probe_id = nfscl_nfs3_start_probes[procnum];
958 probe_procnum = procnum;
959 } else {
960 probe_id =
961 nfscl_nfs2_start_probes[nd->nd_procnum];
962 probe_procnum = procnum;
963 }
964 if (probe_id != 0)
965 (dtrace_nfscl_nfs234_start_probe)
966 (probe_id, vp, nd->nd_mreq, cred,
967 probe_procnum);
968 }
969 #endif
970 }
971 freeslot = -1; /* Set to slot that needs to be free'd */
972 tryagain:
973 slot = -1; /* Slot that needs a sequence# increment. */
974 /*
975 * This timeout specifies when a new socket should be created,
976 * along with new xid values. For UDP, this should be done
977 * infrequently, since retransmits of RPC requests should normally
978 * use the same xid.
979 */
980 if (nmp == NULL) {
981 if (clp == NULL) {
982 timo.tv_sec = NFSV4_UPCALLTIMEO;
983 timo.tv_usec = 0;
984 } else {
985 timo.tv_sec = NFSV4_CALLBACKTIMEO / 1000;
986 timo.tv_usec = NFSV4_CALLBACKTIMEO * 1000;
987 }
988 } else {
989 if (nrp->nr_sotype != SOCK_DGRAM) {
990 timo.tv_usec = 0;
991 if ((nmp->nm_flag & NFSMNT_NFSV4))
992 timo.tv_sec = INT_MAX;
993 else
994 timo.tv_sec = NFS_TCPTIMEO;
995 } else {
996 if (NFSHASSOFT(nmp)) {
997 /*
998 * CLSET_RETRIES is set to 2, so this should be
999 * half of the total timeout required.
1000 */
1001 timeo = nmp->nm_retry * nmp->nm_timeo / 2;
1002 if (timeo < 1)
1003 timeo = 1;
1004 timo.tv_sec = timeo / NFS_HZ;
1005 timo.tv_usec = (timeo % NFS_HZ) * 1000000 /
1006 NFS_HZ;
1007 } else {
1008 /* For UDP hard mounts, use a large value. */
1009 timo.tv_sec = NFS_MAXTIMEO / NFS_HZ;
1010 timo.tv_usec = 0;
1011 }
1012 }
1013
1014 if (rep != NULL) {
1015 rep->r_flags = 0;
1016 rep->r_nmp = nmp;
1017 /*
1018 * Chain request into list of outstanding requests.
1019 */
1020 NFSLOCKREQ();
1021 TAILQ_INSERT_TAIL(&nfsd_reqq, rep, r_chain);
1022 NFSUNLOCKREQ();
1023 }
1024 }
1025
1026 /*
1027 * In case CLNT_CALL_MBUF()/clnt_bck_call() does an AUTH_REFRESH(),
1028 * the thread's credentials need to be set to authcred, so that the
1029 * correct vnet will be set.
1030 */
1031 savcred = curthread->td_ucred;
1032 curthread->td_ucred = authcred;
1033 nd->nd_mrep = NULL;
1034 if (clp != NULL && sep != NULL)
1035 stat = clnt_bck_call(nrp->nr_client, &ext, procnum,
1036 nd->nd_mreq, &nd->nd_mrep, timo, sep->nfsess_xprt);
1037 else if (nextconn_set)
1038 /*
1039 * When there are multiple TCP connections, send the
1040 * RPCs with large messages on the alternate TCP
1041 * connection(s) in a round robin fashion.
1042 * The small RPC messages are sent on the default
1043 * TCP connection because they do not require much
1044 * network bandwidth and separating them from the
1045 * large RPC messages avoids them getting "log jammed"
1046 * behind several large RPC messages.
1047 */
1048 stat = CLNT_CALL_MBUF(nmp->nm_aconn[nextconn],
1049 &ext, procnum, nd->nd_mreq, &nd->nd_mrep, timo);
1050 else
1051 stat = CLNT_CALL_MBUF(nrp->nr_client, &ext, procnum,
1052 nd->nd_mreq, &nd->nd_mrep, timo);
1053 NFSCL_DEBUG(2, "clnt call=%d\n", stat);
1054 curthread->td_ucred = savcred;
1055
1056 if (rep != NULL) {
1057 /*
1058 * RPC done, unlink the request.
1059 */
1060 NFSLOCKREQ();
1061 TAILQ_REMOVE(&nfsd_reqq, rep, r_chain);
1062 NFSUNLOCKREQ();
1063 }
1064
1065 /*
1066 * If there was a successful reply and a tprintf msg.
1067 * tprintf a response.
1068 */
1069 if (stat == RPC_SUCCESS) {
1070 error = 0;
1071 } else if (stat == RPC_TIMEDOUT) {
1072 NFSINCRGLOBAL(nfsstatsv1.rpctimeouts);
1073 error = ETIMEDOUT;
1074 } else if (stat == RPC_VERSMISMATCH) {
1075 NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
1076 error = EOPNOTSUPP;
1077 } else if (stat == RPC_PROGVERSMISMATCH) {
1078 NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
1079 error = EPROTONOSUPPORT;
1080 } else if (stat == RPC_CANTSEND || stat == RPC_CANTRECV ||
1081 stat == RPC_SYSTEMERROR || stat == RPC_INTR) {
1082 /* Check for a session slot that needs to be free'd. */
1083 if ((nd->nd_flag & (ND_NFSV41 | ND_HASSLOTID)) ==
1084 (ND_NFSV41 | ND_HASSLOTID) && nmp != NULL &&
1085 nd->nd_procnum != NFSPROC_NULL) {
1086 /*
1087 * This should only occur when either the MDS or
1088 * a client has an RPC against a DS fail.
1089 * This happens because these cases use "soft"
1090 * connections that can time out and fail.
1091 * The slot used for this RPC is now in a
1092 * non-deterministic state, but if the slot isn't
1093 * free'd, threads can get stuck waiting for a slot.
1094 */
1095 if (sep == NULL)
1096 sep = nfsmnt_mdssession(nmp);
1097 /*
1098 * Bump the sequence# out of range, so that reuse of
1099 * this slot will result in an NFSERR_SEQMISORDERED
1100 * error and not a bogus cached RPC reply.
1101 */
1102 mtx_lock(&sep->nfsess_mtx);
1103 sep->nfsess_slotseq[nd->nd_slotid] += 10;
1104 sep->nfsess_badslots |= (0x1ULL << nd->nd_slotid);
1105 mtx_unlock(&sep->nfsess_mtx);
1106 /* And free the slot. */
1107 nfsv4_freeslot(sep, nd->nd_slotid, true);
1108 }
1109 if (stat == RPC_INTR)
1110 error = EINTR;
1111 else {
1112 NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
1113 error = ENXIO;
1114 }
1115 } else if (stat == RPC_AUTHERROR) {
1116 /* Check for a session slot that needs to be free'd. */
1117 if ((nd->nd_flag & (ND_NFSV41 | ND_HASSLOTID)) ==
1118 (ND_NFSV41 | ND_HASSLOTID) && nmp != NULL &&
1119 nd->nd_procnum != NFSPROC_NULL) {
1120 /*
1121 * This can occur when a Kerberos/RPCSEC_GSS session
1122 * expires, due to TGT expiration.
1123 * Free the slot, resetting the slot's sequence#.
1124 */
1125 if (sep == NULL)
1126 sep = nfsmnt_mdssession(nmp);
1127 nfsv4_freeslot(sep, nd->nd_slotid, true);
1128 }
1129 NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
1130 error = EACCES;
1131 } else {
1132 NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
1133 error = EACCES;
1134 }
1135 if (error) {
1136 crfree(authcred);
1137 m_freem(nd->nd_mreq);
1138 if (usegssname == 0)
1139 AUTH_DESTROY(auth);
1140 if (rep != NULL)
1141 free(rep, M_NFSDREQ);
1142 if (set_sigset)
1143 newnfs_restore_sigmask(td, &oldset);
1144 return (error);
1145 }
1146
1147 KASSERT(nd->nd_mrep != NULL, ("mrep shouldn't be NULL if no error\n"));
1148
1149 /*
1150 * Search for any mbufs that are not a multiple of 4 bytes long
1151 * or with m_data not longword aligned.
1152 * These could cause pointer alignment problems, so copy them to
1153 * well aligned mbufs.
1154 */
1155 newnfs_realign(&nd->nd_mrep, M_WAITOK);
1156 nd->nd_md = nd->nd_mrep;
1157 nd->nd_dpos = mtod(nd->nd_md, caddr_t);
1158 nd->nd_repstat = 0;
1159 if (nd->nd_procnum != NFSPROC_NULL &&
1160 nd->nd_procnum != NFSV4PROC_CBNULL) {
1161 /* If sep == NULL, set it to the default in nmp. */
1162 if (sep == NULL && nmp != NULL)
1163 sep = nfsmnt_mdssession(nmp);
1164 /*
1165 * and now the actual NFS xdr.
1166 */
1167 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1168 nd->nd_repstat = fxdr_unsigned(u_int32_t, *tl);
1169 if (nd->nd_repstat >= 10000)
1170 NFSCL_DEBUG(1, "proc=%d reps=%d\n", (int)nd->nd_procnum,
1171 (int)nd->nd_repstat);
1172
1173 /*
1174 * Get rid of the tag, return count and SEQUENCE result for
1175 * NFSv4.
1176 */
1177 if ((nd->nd_flag & ND_NFSV4) != 0 && nd->nd_repstat !=
1178 NFSERR_MINORVERMISMATCH) {
1179 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1180 i = fxdr_unsigned(int, *tl);
1181 error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
1182 if (error)
1183 goto nfsmout;
1184 NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
1185 opcnt = fxdr_unsigned(int, *tl++);
1186 i = fxdr_unsigned(int, *tl++);
1187 j = fxdr_unsigned(int, *tl);
1188 if (j >= 10000)
1189 NFSCL_DEBUG(1, "fop=%d fst=%d\n", i, j);
1190 /*
1191 * If the first op is Sequence, free up the slot.
1192 */
1193 if ((nmp != NULL && i == NFSV4OP_SEQUENCE && j != 0) ||
1194 (clp != NULL && i == NFSV4OP_CBSEQUENCE && j != 0)) {
1195 NFSCL_DEBUG(1, "failed seq=%d\n", j);
1196 KASSERT(slot == -1, ("newnfs_request: slot not"
1197 " -1"));
1198 /*
1199 * RFC8881 (unlike RFC5661) specifies that a
1200 * NFSERR_DELAY reply to SEQUENCE is handled
1201 * by a retry with same slot/sequence#.
1202 * (Although not explicit, I will assume this
1203 * applies to CB_SEQUENCE as well.)
1204 */
1205 if (j == NFSERR_DELAY) {
1206 nd->nd_repstat =
1207 NFSERR_RETRYUNCACHEDREP;
1208 } else if (sep != NULL &&
1209 i == NFSV4OP_SEQUENCE &&
1210 j == NFSERR_SEQMISORDERED) {
1211 mtx_lock(&sep->nfsess_mtx);
1212 sep->nfsess_badslots |=
1213 (0x1ULL << nd->nd_slotid);
1214 mtx_unlock(&sep->nfsess_mtx);
1215 }
1216 }
1217 if (((nmp != NULL && i == NFSV4OP_SEQUENCE && j == 0) ||
1218 (clp != NULL && i == NFSV4OP_CBSEQUENCE &&
1219 j == 0)) && sep != NULL) {
1220 if (i == NFSV4OP_SEQUENCE)
1221 NFSM_DISSECT(tl, uint32_t *,
1222 NFSX_V4SESSIONID +
1223 5 * NFSX_UNSIGNED);
1224 else
1225 NFSM_DISSECT(tl, uint32_t *,
1226 NFSX_V4SESSIONID +
1227 4 * NFSX_UNSIGNED);
1228 mtx_lock(&sep->nfsess_mtx);
1229 if (bcmp(tl, sep->nfsess_sessionid,
1230 NFSX_V4SESSIONID) == 0) {
1231 tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
1232 retseq = fxdr_unsigned(uint32_t, *tl++);
1233 slot = fxdr_unsigned(int, *tl++);
1234 if ((nd->nd_flag & ND_HASSLOTID) != 0) {
1235 if (slot >= NFSV4_SLOTS ||
1236 (i == NFSV4OP_CBSEQUENCE &&
1237 slot >= NFSV4_CBSLOTS)) {
1238 printf("newnfs_request:"
1239 " Bogus slot\n");
1240 slot = nd->nd_slotid;
1241 } else if (slot !=
1242 nd->nd_slotid) {
1243 printf("newnfs_request:"
1244 " Wrong session "
1245 "srvslot=%d "
1246 "slot=%d\n", slot,
1247 nd->nd_slotid);
1248 if (i == NFSV4OP_SEQUENCE) {
1249 /*
1250 * Mark both slots as
1251 * bad, because we do
1252 * not know if the
1253 * server has advanced
1254 * the sequence# for
1255 * either of them.
1256 */
1257 sep->nfsess_badslots |=
1258 (0x1ULL << slot);
1259 sep->nfsess_badslots |=
1260 (0x1ULL <<
1261 nd->nd_slotid);
1262 }
1263 slot = nd->nd_slotid;
1264 }
1265 freeslot = slot;
1266 } else if (slot != 0) {
1267 printf("newnfs_request: Bad "
1268 "session slot=%d\n", slot);
1269 slot = 0;
1270 }
1271 if (retseq != sep->nfsess_slotseq[slot])
1272 printf("retseq diff 0x%x\n",
1273 retseq);
1274 retval0 = fxdr_unsigned(uint32_t,*tl++);
1275 retval = fxdr_unsigned(uint32_t, *tl);
1276 if ((retval + 1) < sep->nfsess_foreslots
1277 ) {
1278 sep->nfsess_foreslots = (retval
1279 + 1);
1280 nfs_resetslots(sep);
1281 } else if ((retval + 1) >
1282 sep->nfsess_foreslots) {
1283 if (retval0 > retval)
1284 printf("Sess:highest > "
1285 "target_highest\n");
1286 sep->nfsess_foreslots =
1287 (retval < NFSV4_SLOTS) ?
1288 (retval + 1) : NFSV4_SLOTS;
1289 }
1290 }
1291 mtx_unlock(&sep->nfsess_mtx);
1292
1293 /* Grab the op and status for the next one. */
1294 if (opcnt > 1) {
1295 NFSM_DISSECT(tl, uint32_t *,
1296 2 * NFSX_UNSIGNED);
1297 i = fxdr_unsigned(int, *tl++);
1298 j = fxdr_unsigned(int, *tl);
1299 }
1300 }
1301 }
1302 if (nd->nd_repstat != 0) {
1303 if (nd->nd_repstat == NFSERR_BADSESSION &&
1304 nmp != NULL && dssep == NULL &&
1305 (nd->nd_flag & ND_NFSV41) != 0) {
1306 /*
1307 * If this is a client side MDS RPC, mark
1308 * the MDS session defunct and initiate
1309 * recovery, as required.
1310 * The nfsess_defunct field is protected by
1311 * the NFSLOCKMNT()/nm_mtx lock and not the
1312 * nfsess_mtx lock to simplify its handling,
1313 * for the MDS session. This lock is also
1314 * sufficient for nfsess_sessionid, since it
1315 * never changes in the structure.
1316 */
1317 NFSCL_DEBUG(1, "Got badsession\n");
1318 NFSLOCKCLSTATE();
1319 NFSLOCKMNT(nmp);
1320 if (TAILQ_EMPTY(&nmp->nm_sess)) {
1321 NFSUNLOCKMNT(nmp);
1322 NFSUNLOCKCLSTATE();
1323 printf("If server has not rebooted, "
1324 "check NFS clients for unique "
1325 "/etc/hostid's\n");
1326 goto out;
1327 }
1328 sep = NFSMNT_MDSSESSION(nmp);
1329 if (bcmp(sep->nfsess_sessionid,
1330 nd->nd_sessionid, NFSX_V4SESSIONID) == 0) {
1331 /*
1332 * Initiate recovery. Even if
1333 * nfsess_defunct is already set,
1334 * another recovery may be needed.
1335 * NFSCLFLAGS_RECVRINPRG |
1336 * NFSCLFLAGS_RECOVER should avoid
1337 * recovery storms.
1338 */
1339 sep->nfsess_defunct = 1;
1340 NFSCL_DEBUG(1, "Marked defunct\n");
1341 if (nmp->nm_clp != NULL &&
1342 (nmp->nm_clp->nfsc_flags &
1343 (NFSCLFLAGS_RECVRINPROG |
1344 NFSCLFLAGS_RECOVER)) == 0) {
1345 nmp->nm_clp->nfsc_flags |=
1346 NFSCLFLAGS_RECOVER;
1347 wakeup(nmp->nm_clp);
1348 printf("Initiate recovery. If "
1349 "server has not rebooted, "
1350 "check NFS clients for "
1351 "unique /etc/hostid's\n");
1352 }
1353 }
1354 NFSUNLOCKCLSTATE();
1355 /*
1356 * Sleep for up to 1sec waiting for a new
1357 * session.
1358 */
1359 mtx_sleep(&nmp->nm_sess, &nmp->nm_mtx, PZERO,
1360 "nfsbadsess", hz);
1361 /*
1362 * Get the session again, in case a new one
1363 * has been created during the sleep.
1364 */
1365 sep = NFSMNT_MDSSESSION(nmp);
1366 NFSUNLOCKMNT(nmp);
1367 if ((nd->nd_flag & ND_LOOPBADSESS) != 0) {
1368 reterr = nfsv4_sequencelookup(nmp, sep,
1369 &slotpos, &maxslot, &slotseq,
1370 sessionid, true);
1371 if (reterr == 0) {
1372 /* Fill in new session info. */
1373 NFSCL_DEBUG(1,
1374 "Filling in new sequence\n");
1375 tl = nd->nd_sequence;
1376 bcopy(sessionid, tl,
1377 NFSX_V4SESSIONID);
1378 tl += NFSX_V4SESSIONID /
1379 NFSX_UNSIGNED;
1380 *tl++ = txdr_unsigned(slotseq);
1381 *tl++ = txdr_unsigned(slotpos);
1382 *tl = txdr_unsigned(maxslot);
1383 nd->nd_slotid = slotpos;
1384 nd->nd_flag |= ND_HASSLOTID;
1385 }
1386 if (reterr == NFSERR_BADSESSION ||
1387 reterr == 0) {
1388 NFSCL_DEBUG(1,
1389 "Badsession looping\n");
1390 m_freem(nd->nd_mrep);
1391 nd->nd_mrep = NULL;
1392 goto tryagain;
1393 }
1394 nd->nd_repstat = reterr;
1395 NFSCL_DEBUG(1, "Got err=%d\n", reterr);
1396 }
1397 }
1398 /*
1399 * When clp != NULL, it is a callback and all
1400 * callback operations can be retried for NFSERR_DELAY.
1401 */
1402 if (((nd->nd_repstat == NFSERR_DELAY ||
1403 nd->nd_repstat == NFSERR_GRACE) &&
1404 (nd->nd_flag & ND_NFSV4) && (clp != NULL ||
1405 (nd->nd_procnum != NFSPROC_DELEGRETURN &&
1406 nd->nd_procnum != NFSPROC_SETATTR &&
1407 nd->nd_procnum != NFSPROC_READ &&
1408 nd->nd_procnum != NFSPROC_READDS &&
1409 nd->nd_procnum != NFSPROC_WRITE &&
1410 nd->nd_procnum != NFSPROC_WRITEDS &&
1411 nd->nd_procnum != NFSPROC_OPEN &&
1412 nd->nd_procnum != NFSPROC_OPENLAYGET &&
1413 nd->nd_procnum != NFSPROC_CREATE &&
1414 nd->nd_procnum != NFSPROC_CREATELAYGET &&
1415 nd->nd_procnum != NFSPROC_OPENCONFIRM &&
1416 nd->nd_procnum != NFSPROC_OPENDOWNGRADE &&
1417 nd->nd_procnum != NFSPROC_CLOSE &&
1418 nd->nd_procnum != NFSPROC_LOCK &&
1419 nd->nd_procnum != NFSPROC_LOCKU))) ||
1420 (nd->nd_repstat == NFSERR_DELAY &&
1421 (nd->nd_flag & ND_NFSV4) == 0) ||
1422 nd->nd_repstat == NFSERR_RESOURCE ||
1423 nd->nd_repstat == NFSERR_RETRYUNCACHEDREP) {
1424 /* Clip at NFS_TRYLATERDEL. */
1425 if (timespeccmp(&trylater_delay,
1426 &nfs_trylater_max, >))
1427 trylater_delay = nfs_trylater_max;
1428 getnanouptime(&waituntil);
1429 timespecadd(&waituntil, &trylater_delay,
1430 &waituntil);
1431 do {
1432 nfs_catnap(PZERO, 0, "nfstry");
1433 getnanouptime(&ts);
1434 } while (timespeccmp(&ts, &waituntil, <));
1435 timespecadd(&trylater_delay, &trylater_delay,
1436 &trylater_delay); /* Double each time. */
1437 if (slot != -1) {
1438 mtx_lock(&sep->nfsess_mtx);
1439 sep->nfsess_slotseq[slot]++;
1440 *nd->nd_slotseq = txdr_unsigned(
1441 sep->nfsess_slotseq[slot]);
1442 mtx_unlock(&sep->nfsess_mtx);
1443 }
1444 m_freem(nd->nd_mrep);
1445 nd->nd_mrep = NULL;
1446 goto tryagain;
1447 }
1448
1449 /*
1450 * If the File Handle was stale, invalidate the
1451 * lookup cache, just in case.
1452 * (vp != NULL implies a client side call)
1453 */
1454 if (nd->nd_repstat == ESTALE && vp != NULL) {
1455 cache_purge(vp);
1456 if (ncl_call_invalcaches != NULL)
1457 (*ncl_call_invalcaches)(vp);
1458 }
1459 }
1460 if ((nd->nd_flag & ND_NFSV4) != 0) {
1461 /* Free the slot, as required. */
1462 if (freeslot != -1)
1463 nfsv4_freeslot(sep, freeslot, false);
1464 /*
1465 * If this op is Putfh, throw its results away.
1466 */
1467 if (j >= 10000)
1468 NFSCL_DEBUG(1, "nop=%d nst=%d\n", i, j);
1469 if (nmp != NULL && i == NFSV4OP_PUTFH && j == 0) {
1470 NFSM_DISSECT(tl,u_int32_t *,2 * NFSX_UNSIGNED);
1471 i = fxdr_unsigned(int, *tl++);
1472 j = fxdr_unsigned(int, *tl);
1473 if (j >= 10000)
1474 NFSCL_DEBUG(1, "n2op=%d n2st=%d\n", i,
1475 j);
1476 /*
1477 * All Compounds that do an Op that must
1478 * be in sequence consist of NFSV4OP_PUTFH
1479 * followed by one of these. As such, we
1480 * can determine if the seqid# should be
1481 * incremented, here.
1482 */
1483 if ((i == NFSV4OP_OPEN ||
1484 i == NFSV4OP_OPENCONFIRM ||
1485 i == NFSV4OP_OPENDOWNGRADE ||
1486 i == NFSV4OP_CLOSE ||
1487 i == NFSV4OP_LOCK ||
1488 i == NFSV4OP_LOCKU) &&
1489 (j == 0 ||
1490 (j != NFSERR_STALECLIENTID &&
1491 j != NFSERR_STALESTATEID &&
1492 j != NFSERR_BADSTATEID &&
1493 j != NFSERR_BADSEQID &&
1494 j != NFSERR_BADXDR &&
1495 j != NFSERR_RESOURCE &&
1496 j != NFSERR_NOFILEHANDLE)))
1497 nd->nd_flag |= ND_INCRSEQID;
1498 }
1499 /*
1500 * If this op's status is non-zero, mark
1501 * that there is no more data to process.
1502 * The exception is Setattr, which always has xdr
1503 * when it has failed.
1504 */
1505 if (j != 0 && i != NFSV4OP_SETATTR)
1506 nd->nd_flag |= ND_NOMOREDATA;
1507
1508 /*
1509 * If R_DONTRECOVER is set, replace the stale error
1510 * reply, so that recovery isn't initiated.
1511 */
1512 if ((nd->nd_repstat == NFSERR_STALECLIENTID ||
1513 nd->nd_repstat == NFSERR_BADSESSION ||
1514 nd->nd_repstat == NFSERR_STALESTATEID) &&
1515 rep != NULL && (rep->r_flags & R_DONTRECOVER))
1516 nd->nd_repstat = NFSERR_STALEDONTRECOVER;
1517 }
1518 }
1519 out:
1520 crfree(authcred);
1521
1522 #ifdef KDTRACE_HOOKS
1523 if (nmp != NULL && dtrace_nfscl_nfs234_done_probe != NULL) {
1524 uint32_t probe_id;
1525 int probe_procnum;
1526
1527 if (nd->nd_flag & ND_NFSV4) {
1528 probe_id = nfscl_nfs4_done_probes[nd->nd_procnum];
1529 probe_procnum = nd->nd_procnum;
1530 } else if (nd->nd_flag & ND_NFSV3) {
1531 probe_id = nfscl_nfs3_done_probes[procnum];
1532 probe_procnum = procnum;
1533 } else {
1534 probe_id = nfscl_nfs2_done_probes[nd->nd_procnum];
1535 probe_procnum = procnum;
1536 }
1537 if (probe_id != 0)
1538 (dtrace_nfscl_nfs234_done_probe)(probe_id, vp,
1539 nd->nd_mreq, cred, probe_procnum, 0);
1540 }
1541 #endif
1542
1543 if (has_mreduce)
1544 rpc_remove_mreduce(nd->nd_mreq, false);
1545 m_freem(nd->nd_mreq);
1546 if (usegssname == 0)
1547 AUTH_DESTROY(auth);
1548 if (rep != NULL)
1549 free(rep, M_NFSDREQ);
1550 if (set_sigset)
1551 newnfs_restore_sigmask(td, &oldset);
1552 return (0);
1553 nfsmout:
1554 crfree(authcred);
1555 m_freem(nd->nd_mrep);
1556 m_freem(nd->nd_mreq);
1557 if (usegssname == 0)
1558 AUTH_DESTROY(auth);
1559 if (rep != NULL)
1560 free(rep, M_NFSDREQ);
1561 if (set_sigset)
1562 newnfs_restore_sigmask(td, &oldset);
1563 return (error);
1564 }
1565
1566 /*
1567 * Reset slots above nfsess_foreslots that are not busy.
1568 */
1569 void
nfs_resetslots(struct nfsclsession * sep)1570 nfs_resetslots(struct nfsclsession *sep)
1571 {
1572 int i;
1573 uint64_t bitval;
1574
1575 mtx_assert(&sep->nfsess_mtx, MA_OWNED);
1576 bitval = (1 << sep->nfsess_foreslots);
1577 for (i = sep->nfsess_foreslots; i < NFSV4_SLOTS; i++) {
1578 if ((sep->nfsess_slots & bitval) == 0 &&
1579 (sep->nfsess_badslots & bitval) == 0)
1580 sep->nfsess_slotseq[i] = 0;
1581 bitval <<= 1;
1582 }
1583 }
1584
1585 /*
1586 * Mark all of an nfs mount's outstanding requests with R_SOFTTERM and
1587 * wait for all requests to complete. This is used by forced unmounts
1588 * to terminate any outstanding RPCs.
1589 */
1590 int
newnfs_nmcancelreqs(struct nfsmount * nmp)1591 newnfs_nmcancelreqs(struct nfsmount *nmp)
1592 {
1593 struct nfsclds *dsp;
1594 struct __rpc_client *cl;
1595 int i;
1596
1597 if (nmp->nm_sockreq.nr_client != NULL)
1598 CLNT_CLOSE(nmp->nm_sockreq.nr_client);
1599 for (i = 0; i < nmp->nm_aconnect; i++)
1600 if (nmp->nm_aconn[i] != NULL)
1601 CLNT_CLOSE(nmp->nm_aconn[i]);
1602 lookformore:
1603 NFSLOCKMNT(nmp);
1604 TAILQ_FOREACH(dsp, &nmp->nm_sess, nfsclds_list) {
1605 NFSLOCKDS(dsp);
1606 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1607 (dsp->nfsclds_flags & NFSCLDS_CLOSED) == 0 &&
1608 dsp->nfsclds_sockp != NULL &&
1609 dsp->nfsclds_sockp->nr_client != NULL) {
1610 dsp->nfsclds_flags |= NFSCLDS_CLOSED;
1611 cl = dsp->nfsclds_sockp->nr_client;
1612 NFSUNLOCKDS(dsp);
1613 NFSUNLOCKMNT(nmp);
1614 CLNT_CLOSE(cl);
1615 goto lookformore;
1616 }
1617 NFSUNLOCKDS(dsp);
1618 }
1619 NFSUNLOCKMNT(nmp);
1620 return (0);
1621 }
1622
1623 /*
1624 * Any signal that can interrupt an NFS operation in an intr mount
1625 * should be added to this set. SIGSTOP and SIGKILL cannot be masked.
1626 */
1627 int newnfs_sig_set[] = {
1628 SIGINT,
1629 SIGTERM,
1630 SIGHUP,
1631 SIGKILL,
1632 SIGQUIT
1633 };
1634
1635 /*
1636 * Check to see if one of the signals in our subset is pending on
1637 * the process (in an intr mount).
1638 */
1639 static int
nfs_sig_pending(sigset_t set)1640 nfs_sig_pending(sigset_t set)
1641 {
1642 int i;
1643
1644 for (i = 0 ; i < nitems(newnfs_sig_set); i++)
1645 if (SIGISMEMBER(set, newnfs_sig_set[i]))
1646 return (1);
1647 return (0);
1648 }
1649
1650 /*
1651 * The set/restore sigmask functions are used to (temporarily) overwrite
1652 * the thread td_sigmask during an RPC call (for example). These are also
1653 * used in other places in the NFS client that might tsleep().
1654 */
1655 void
newnfs_set_sigmask(struct thread * td,sigset_t * oldset)1656 newnfs_set_sigmask(struct thread *td, sigset_t *oldset)
1657 {
1658 sigset_t newset;
1659 int i;
1660 struct proc *p;
1661
1662 SIGFILLSET(newset);
1663 if (td == NULL)
1664 td = curthread; /* XXX */
1665 p = td->td_proc;
1666 /* Remove the NFS set of signals from newset */
1667 PROC_LOCK(p);
1668 mtx_lock(&p->p_sigacts->ps_mtx);
1669 for (i = 0 ; i < nitems(newnfs_sig_set); i++) {
1670 /*
1671 * But make sure we leave the ones already masked
1672 * by the process, ie. remove the signal from the
1673 * temporary signalmask only if it wasn't already
1674 * in p_sigmask.
1675 */
1676 if (!SIGISMEMBER(td->td_sigmask, newnfs_sig_set[i]) &&
1677 !SIGISMEMBER(p->p_sigacts->ps_sigignore, newnfs_sig_set[i]))
1678 SIGDELSET(newset, newnfs_sig_set[i]);
1679 }
1680 mtx_unlock(&p->p_sigacts->ps_mtx);
1681 kern_sigprocmask(td, SIG_SETMASK, &newset, oldset,
1682 SIGPROCMASK_PROC_LOCKED);
1683 PROC_UNLOCK(p);
1684 }
1685
1686 void
newnfs_restore_sigmask(struct thread * td,sigset_t * set)1687 newnfs_restore_sigmask(struct thread *td, sigset_t *set)
1688 {
1689 if (td == NULL)
1690 td = curthread; /* XXX */
1691 kern_sigprocmask(td, SIG_SETMASK, set, NULL, 0);
1692 }
1693
1694 /*
1695 * NFS wrapper to msleep(), that shoves a new p_sigmask and restores the
1696 * old one after msleep() returns.
1697 */
1698 int
newnfs_msleep(struct thread * td,void * ident,struct mtx * mtx,int priority,char * wmesg,int timo)1699 newnfs_msleep(struct thread *td, void *ident, struct mtx *mtx, int priority, char *wmesg, int timo)
1700 {
1701 sigset_t oldset;
1702 int error;
1703
1704 if ((priority & PCATCH) == 0)
1705 return msleep(ident, mtx, priority, wmesg, timo);
1706 if (td == NULL)
1707 td = curthread; /* XXX */
1708 newnfs_set_sigmask(td, &oldset);
1709 error = msleep(ident, mtx, priority, wmesg, timo);
1710 newnfs_restore_sigmask(td, &oldset);
1711 return (error);
1712 }
1713
1714 /*
1715 * Test for a termination condition pending on the process.
1716 * This is used for NFSMNT_INT mounts.
1717 */
1718 int
newnfs_sigintr(struct nfsmount * nmp,struct thread * td)1719 newnfs_sigintr(struct nfsmount *nmp, struct thread *td)
1720 {
1721 struct proc *p;
1722 sigset_t tmpset;
1723
1724 /* Terminate all requests while attempting a forced unmount. */
1725 if (NFSCL_FORCEDISM(nmp->nm_mountp))
1726 return (EIO);
1727 if (!(nmp->nm_flag & NFSMNT_INT))
1728 return (0);
1729 if (td == NULL)
1730 return (0);
1731 p = td->td_proc;
1732 PROC_LOCK(p);
1733 tmpset = p->p_siglist;
1734 SIGSETOR(tmpset, td->td_siglist);
1735 SIGSETNAND(tmpset, td->td_sigmask);
1736 mtx_lock(&p->p_sigacts->ps_mtx);
1737 SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore);
1738 mtx_unlock(&p->p_sigacts->ps_mtx);
1739 if ((SIGNOTEMPTY(p->p_siglist) || SIGNOTEMPTY(td->td_siglist))
1740 && nfs_sig_pending(tmpset)) {
1741 PROC_UNLOCK(p);
1742 return (EINTR);
1743 }
1744 PROC_UNLOCK(p);
1745 return (0);
1746 }
1747
1748 static int
nfs_msg(struct thread * td,const char * server,const char * msg,int error)1749 nfs_msg(struct thread *td, const char *server, const char *msg, int error)
1750 {
1751 struct proc *p;
1752
1753 p = td ? td->td_proc : NULL;
1754 if (error) {
1755 tprintf(p, LOG_INFO, "nfs server %s: %s, error %d\n",
1756 server, msg, error);
1757 } else {
1758 tprintf(p, LOG_INFO, "nfs server %s: %s\n", server, msg);
1759 }
1760 return (0);
1761 }
1762
1763 static void
nfs_down(struct nfsmount * nmp,struct thread * td,const char * msg,int error,int flags)1764 nfs_down(struct nfsmount *nmp, struct thread *td, const char *msg,
1765 int error, int flags)
1766 {
1767 if (nmp == NULL)
1768 return;
1769 mtx_lock(&nmp->nm_mtx);
1770 if ((flags & NFSSTA_TIMEO) && !(nmp->nm_state & NFSSTA_TIMEO)) {
1771 nmp->nm_state |= NFSSTA_TIMEO;
1772 mtx_unlock(&nmp->nm_mtx);
1773 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
1774 VQ_NOTRESP, 0);
1775 } else
1776 mtx_unlock(&nmp->nm_mtx);
1777 mtx_lock(&nmp->nm_mtx);
1778 if ((flags & NFSSTA_LOCKTIMEO) && !(nmp->nm_state & NFSSTA_LOCKTIMEO)) {
1779 nmp->nm_state |= NFSSTA_LOCKTIMEO;
1780 mtx_unlock(&nmp->nm_mtx);
1781 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
1782 VQ_NOTRESPLOCK, 0);
1783 } else
1784 mtx_unlock(&nmp->nm_mtx);
1785 nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, error);
1786 }
1787
1788 static void
nfs_up(struct nfsmount * nmp,struct thread * td,const char * msg,int flags,int tprintfmsg)1789 nfs_up(struct nfsmount *nmp, struct thread *td, const char *msg,
1790 int flags, int tprintfmsg)
1791 {
1792 if (nmp == NULL)
1793 return;
1794 if (tprintfmsg) {
1795 nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, 0);
1796 }
1797
1798 mtx_lock(&nmp->nm_mtx);
1799 if ((flags & NFSSTA_TIMEO) && (nmp->nm_state & NFSSTA_TIMEO)) {
1800 nmp->nm_state &= ~NFSSTA_TIMEO;
1801 mtx_unlock(&nmp->nm_mtx);
1802 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
1803 VQ_NOTRESP, 1);
1804 } else
1805 mtx_unlock(&nmp->nm_mtx);
1806
1807 mtx_lock(&nmp->nm_mtx);
1808 if ((flags & NFSSTA_LOCKTIMEO) && (nmp->nm_state & NFSSTA_LOCKTIMEO)) {
1809 nmp->nm_state &= ~NFSSTA_LOCKTIMEO;
1810 mtx_unlock(&nmp->nm_mtx);
1811 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
1812 VQ_NOTRESPLOCK, 1);
1813 } else
1814 mtx_unlock(&nmp->nm_mtx);
1815 }
1816