xref: /freebsd/sys/fs/nfs/nfs_commonkrpc.c (revision 77535f91f623ec5bda9d45de878165cb6b3cdba1)
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