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