nfs_commonkrpc.c revision 306663
1/*- 2 * Copyright (c) 1989, 1991, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: stable/10/sys/fs/nfs/nfs_commonkrpc.c 306663 2016-10-03 23:17:57Z rmacklem $"); 36 37/* 38 * Socket operations for use by nfs 39 */ 40 41#include "opt_kdtrace.h" 42#include "opt_kgssapi.h" 43#include "opt_nfs.h" 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/kernel.h> 48#include <sys/limits.h> 49#include <sys/lock.h> 50#include <sys/malloc.h> 51#include <sys/mbuf.h> 52#include <sys/mount.h> 53#include <sys/mutex.h> 54#include <sys/proc.h> 55#include <sys/signalvar.h> 56#include <sys/syscallsubr.h> 57#include <sys/sysctl.h> 58#include <sys/syslog.h> 59#include <sys/vnode.h> 60 61#include <rpc/rpc.h> 62#include <rpc/krpc.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 71dtrace_nfsclient_nfs23_start_probe_func_t 72 dtrace_nfscl_nfs234_start_probe; 73 74dtrace_nfsclient_nfs23_done_probe_func_t 75 dtrace_nfscl_nfs234_done_probe; 76 77/* 78 * Registered probes by RPC type. 79 */ 80uint32_t nfscl_nfs2_start_probes[NFSV41_NPROCS + 1]; 81uint32_t nfscl_nfs2_done_probes[NFSV41_NPROCS + 1]; 82 83uint32_t nfscl_nfs3_start_probes[NFSV41_NPROCS + 1]; 84uint32_t nfscl_nfs3_done_probes[NFSV41_NPROCS + 1]; 85 86uint32_t nfscl_nfs4_start_probes[NFSV41_NPROCS + 1]; 87uint32_t nfscl_nfs4_done_probes[NFSV41_NPROCS + 1]; 88#endif 89 90NFSSTATESPINLOCK; 91NFSREQSPINLOCK; 92NFSDLOCKMUTEX; 93extern struct nfsstats newnfsstats; 94extern struct nfsreqhead nfsd_reqq; 95extern int nfscl_ticks; 96extern void (*ncl_call_invalcaches)(struct vnode *); 97extern int nfs_numnfscbd; 98extern int nfscl_debuglevel; 99 100SVCPOOL *nfscbd_pool; 101static int nfsrv_gsscallbackson = 0; 102static int nfs_bufpackets = 4; 103static int nfs_reconnects; 104static int nfs3_jukebox_delay = 10; 105static int nfs_skip_wcc_data_onerr = 1; 106 107SYSCTL_DECL(_vfs_nfs); 108 109SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0, 110 "Buffer reservation size 2 < x < 64"); 111SYSCTL_INT(_vfs_nfs, OID_AUTO, reconnects, CTLFLAG_RD, &nfs_reconnects, 0, 112 "Number of times the nfs client has had to reconnect"); 113SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs3_jukebox_delay, CTLFLAG_RW, &nfs3_jukebox_delay, 0, 114 "Number of seconds to delay a retry after receiving EJUKEBOX"); 115SYSCTL_INT(_vfs_nfs, OID_AUTO, skip_wcc_data_onerr, CTLFLAG_RW, &nfs_skip_wcc_data_onerr, 0, 116 "Disable weak cache consistency checking when server returns an error"); 117 118static void nfs_down(struct nfsmount *, struct thread *, const char *, 119 int, int); 120static void nfs_up(struct nfsmount *, struct thread *, const char *, 121 int, int); 122static int nfs_msg(struct thread *, const char *, const char *, int); 123 124struct nfs_cached_auth { 125 int ca_refs; /* refcount, including 1 from the cache */ 126 uid_t ca_uid; /* uid that corresponds to this auth */ 127 AUTH *ca_auth; /* RPC auth handle */ 128}; 129 130static int nfsv2_procid[NFS_V3NPROCS] = { 131 NFSV2PROC_NULL, 132 NFSV2PROC_GETATTR, 133 NFSV2PROC_SETATTR, 134 NFSV2PROC_LOOKUP, 135 NFSV2PROC_NOOP, 136 NFSV2PROC_READLINK, 137 NFSV2PROC_READ, 138 NFSV2PROC_WRITE, 139 NFSV2PROC_CREATE, 140 NFSV2PROC_MKDIR, 141 NFSV2PROC_SYMLINK, 142 NFSV2PROC_CREATE, 143 NFSV2PROC_REMOVE, 144 NFSV2PROC_RMDIR, 145 NFSV2PROC_RENAME, 146 NFSV2PROC_LINK, 147 NFSV2PROC_READDIR, 148 NFSV2PROC_NOOP, 149 NFSV2PROC_STATFS, 150 NFSV2PROC_NOOP, 151 NFSV2PROC_NOOP, 152 NFSV2PROC_NOOP, 153}; 154 155/* 156 * Initialize sockets and congestion for a new NFS connection. 157 * We do not free the sockaddr if error. 158 */ 159int 160newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp, 161 struct ucred *cred, NFSPROC_T *p, int callback_retry_mult) 162{ 163 int rcvreserve, sndreserve; 164 int pktscale; 165 struct sockaddr *saddr; 166 struct ucred *origcred; 167 CLIENT *client; 168 struct netconfig *nconf; 169 struct socket *so; 170 int one = 1, retries, error = 0; 171 struct thread *td = curthread; 172 SVCXPRT *xprt; 173 struct timeval timo; 174 175 /* 176 * We need to establish the socket using the credentials of 177 * the mountpoint. Some parts of this process (such as 178 * sobind() and soconnect()) will use the curent thread's 179 * credential instead of the socket credential. To work 180 * around this, temporarily change the current thread's 181 * credential to that of the mountpoint. 182 * 183 * XXX: It would be better to explicitly pass the correct 184 * credential to sobind() and soconnect(). 185 */ 186 origcred = td->td_ucred; 187 188 /* 189 * Use the credential in nr_cred, if not NULL. 190 */ 191 if (nrp->nr_cred != NULL) 192 td->td_ucred = nrp->nr_cred; 193 else 194 td->td_ucred = cred; 195 saddr = nrp->nr_nam; 196 197 if (saddr->sa_family == AF_INET) 198 if (nrp->nr_sotype == SOCK_DGRAM) 199 nconf = getnetconfigent("udp"); 200 else 201 nconf = getnetconfigent("tcp"); 202 else 203 if (nrp->nr_sotype == SOCK_DGRAM) 204 nconf = getnetconfigent("udp6"); 205 else 206 nconf = getnetconfigent("tcp6"); 207 208 pktscale = nfs_bufpackets; 209 if (pktscale < 2) 210 pktscale = 2; 211 if (pktscale > 64) 212 pktscale = 64; 213 /* 214 * soreserve() can fail if sb_max is too small, so shrink pktscale 215 * and try again if there is an error. 216 * Print a log message suggesting increasing sb_max. 217 * Creating a socket and doing this is necessary since, if the 218 * reservation sizes are too large and will make soreserve() fail, 219 * the connection will work until a large send is attempted and 220 * then it will loop in the krpc code. 221 */ 222 so = NULL; 223 saddr = NFSSOCKADDR(nrp->nr_nam, struct sockaddr *); 224 error = socreate(saddr->sa_family, &so, nrp->nr_sotype, 225 nrp->nr_soproto, td->td_ucred, td); 226 if (error) { 227 td->td_ucred = origcred; 228 goto out; 229 } 230 do { 231 if (error != 0 && pktscale > 2) 232 pktscale--; 233 if (nrp->nr_sotype == SOCK_DGRAM) { 234 if (nmp != NULL) { 235 sndreserve = (NFS_MAXDGRAMDATA + NFS_MAXPKTHDR) * 236 pktscale; 237 rcvreserve = (NFS_MAXDGRAMDATA + NFS_MAXPKTHDR) * 238 pktscale; 239 } else { 240 sndreserve = rcvreserve = 1024 * pktscale; 241 } 242 } else { 243 if (nrp->nr_sotype != SOCK_STREAM) 244 panic("nfscon sotype"); 245 if (nmp != NULL) { 246 sndreserve = (NFS_MAXBSIZE + NFS_MAXPKTHDR + 247 sizeof (u_int32_t)) * pktscale; 248 rcvreserve = (NFS_MAXBSIZE + NFS_MAXPKTHDR + 249 sizeof (u_int32_t)) * pktscale; 250 } else { 251 sndreserve = rcvreserve = 1024 * pktscale; 252 } 253 } 254 error = soreserve(so, sndreserve, rcvreserve); 255 } while (error != 0 && pktscale > 2); 256 soclose(so); 257 if (error) { 258 td->td_ucred = origcred; 259 goto out; 260 } 261 262 client = clnt_reconnect_create(nconf, saddr, nrp->nr_prog, 263 nrp->nr_vers, sndreserve, rcvreserve); 264 CLNT_CONTROL(client, CLSET_WAITCHAN, "newnfsreq"); 265 if (nmp != NULL) { 266 if ((nmp->nm_flag & NFSMNT_INT)) 267 CLNT_CONTROL(client, CLSET_INTERRUPTIBLE, &one); 268 if ((nmp->nm_flag & NFSMNT_RESVPORT)) 269 CLNT_CONTROL(client, CLSET_PRIVPORT, &one); 270 if (NFSHASSOFT(nmp)) { 271 if (nmp->nm_sotype == SOCK_DGRAM) 272 /* 273 * For UDP, the large timeout for a reconnect 274 * will be set to "nm_retry * nm_timeo / 2", so 275 * we only want to do 2 reconnect timeout 276 * retries. 277 */ 278 retries = 2; 279 else 280 retries = nmp->nm_retry; 281 } else 282 retries = INT_MAX; 283 if (NFSHASNFSV4N(nmp)) { 284 /* 285 * Make sure the nfscbd_pool doesn't get destroyed 286 * while doing this. 287 */ 288 NFSD_LOCK(); 289 if (nfs_numnfscbd > 0) { 290 nfs_numnfscbd++; 291 NFSD_UNLOCK(); 292 xprt = svc_vc_create_backchannel(nfscbd_pool); 293 CLNT_CONTROL(client, CLSET_BACKCHANNEL, xprt); 294 NFSD_LOCK(); 295 nfs_numnfscbd--; 296 if (nfs_numnfscbd == 0) 297 wakeup(&nfs_numnfscbd); 298 } 299 NFSD_UNLOCK(); 300 } 301 } else { 302 /* 303 * Three cases: 304 * - Null RPC callback to client 305 * - Non-Null RPC callback to client, wait a little longer 306 * - upcalls to nfsuserd and gssd (clp == NULL) 307 */ 308 if (callback_retry_mult == 0) { 309 retries = NFSV4_UPCALLRETRY; 310 CLNT_CONTROL(client, CLSET_PRIVPORT, &one); 311 } else { 312 retries = NFSV4_CALLBACKRETRY * callback_retry_mult; 313 } 314 } 315 CLNT_CONTROL(client, CLSET_RETRIES, &retries); 316 317 if (nmp != NULL) { 318 /* 319 * For UDP, there are 2 timeouts: 320 * - CLSET_RETRY_TIMEOUT sets the initial timeout for the timer 321 * that does a retransmit of an RPC request using the same 322 * socket and xid. This is what you normally want to do, 323 * since NFS servers depend on "same xid" for their 324 * Duplicate Request Cache. 325 * - timeout specified in CLNT_CALL_MBUF(), which specifies when 326 * retransmits on the same socket should fail and a fresh 327 * socket created. Each of these timeouts counts as one 328 * CLSET_RETRIES as set above. 329 * Set the initial retransmit timeout for UDP. This timeout 330 * doesn't exist for TCP and the following call just fails, 331 * which is ok. 332 */ 333 timo.tv_sec = nmp->nm_timeo / NFS_HZ; 334 timo.tv_usec = (nmp->nm_timeo % NFS_HZ) * 1000000 / NFS_HZ; 335 CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, &timo); 336 } 337 338 mtx_lock(&nrp->nr_mtx); 339 if (nrp->nr_client != NULL) { 340 mtx_unlock(&nrp->nr_mtx); 341 /* 342 * Someone else already connected. 343 */ 344 CLNT_RELEASE(client); 345 } else { 346 nrp->nr_client = client; 347 /* 348 * Protocols that do not require connections may be optionally 349 * left unconnected for servers that reply from a port other 350 * than NFS_PORT. 351 */ 352 if (nmp == NULL || (nmp->nm_flag & NFSMNT_NOCONN) == 0) { 353 mtx_unlock(&nrp->nr_mtx); 354 CLNT_CONTROL(client, CLSET_CONNECT, &one); 355 } else 356 mtx_unlock(&nrp->nr_mtx); 357 } 358 359 360 /* Restore current thread's credentials. */ 361 td->td_ucred = origcred; 362 363out: 364 NFSEXITCODE(error); 365 return (error); 366} 367 368/* 369 * NFS disconnect. Clean up and unlink. 370 */ 371void 372newnfs_disconnect(struct nfssockreq *nrp) 373{ 374 CLIENT *client; 375 376 mtx_lock(&nrp->nr_mtx); 377 if (nrp->nr_client != NULL) { 378 client = nrp->nr_client; 379 nrp->nr_client = NULL; 380 mtx_unlock(&nrp->nr_mtx); 381 rpc_gss_secpurge_call(client); 382 CLNT_CLOSE(client); 383 CLNT_RELEASE(client); 384 } else { 385 mtx_unlock(&nrp->nr_mtx); 386 } 387} 388 389static AUTH * 390nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal, 391 char *srv_principal, gss_OID mech_oid, struct ucred *cred) 392{ 393 rpc_gss_service_t svc; 394 AUTH *auth; 395 396 switch (secflavour) { 397 case RPCSEC_GSS_KRB5: 398 case RPCSEC_GSS_KRB5I: 399 case RPCSEC_GSS_KRB5P: 400 if (!mech_oid) { 401 if (!rpc_gss_mech_to_oid_call("kerberosv5", &mech_oid)) 402 return (NULL); 403 } 404 if (secflavour == RPCSEC_GSS_KRB5) 405 svc = rpc_gss_svc_none; 406 else if (secflavour == RPCSEC_GSS_KRB5I) 407 svc = rpc_gss_svc_integrity; 408 else 409 svc = rpc_gss_svc_privacy; 410 411 if (clnt_principal == NULL) 412 auth = rpc_gss_secfind_call(nrp->nr_client, cred, 413 srv_principal, mech_oid, svc); 414 else { 415 auth = rpc_gss_seccreate_call(nrp->nr_client, cred, 416 clnt_principal, srv_principal, "kerberosv5", 417 svc, NULL, NULL, NULL); 418 return (auth); 419 } 420 if (auth != NULL) 421 return (auth); 422 /* fallthrough */ 423 case AUTH_SYS: 424 default: 425 return (authunix_create(cred)); 426 427 } 428} 429 430/* 431 * Callback from the RPC code to generate up/down notifications. 432 */ 433 434struct nfs_feedback_arg { 435 struct nfsmount *nf_mount; 436 int nf_lastmsg; /* last tprintf */ 437 int nf_tprintfmsg; 438 struct thread *nf_td; 439}; 440 441static void 442nfs_feedback(int type, int proc, void *arg) 443{ 444 struct nfs_feedback_arg *nf = (struct nfs_feedback_arg *) arg; 445 struct nfsmount *nmp = nf->nf_mount; 446 time_t now; 447 448 switch (type) { 449 case FEEDBACK_REXMIT2: 450 case FEEDBACK_RECONNECT: 451 now = NFSD_MONOSEC; 452 if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now) { 453 nfs_down(nmp, nf->nf_td, 454 "not responding", 0, NFSSTA_TIMEO); 455 nf->nf_tprintfmsg = TRUE; 456 nf->nf_lastmsg = now; 457 } 458 break; 459 460 case FEEDBACK_OK: 461 nfs_up(nf->nf_mount, nf->nf_td, 462 "is alive again", NFSSTA_TIMEO, nf->nf_tprintfmsg); 463 break; 464 } 465} 466 467/* 468 * newnfs_request - goes something like this 469 * - does the rpc by calling the krpc layer 470 * - break down rpc header and return with nfs reply 471 * nb: always frees up nd_mreq mbuf list 472 */ 473int 474newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp, 475 struct nfsclient *clp, struct nfssockreq *nrp, vnode_t vp, 476 struct thread *td, struct ucred *cred, u_int32_t prog, u_int32_t vers, 477 u_char *retsum, int toplevel, u_int64_t *xidp, struct nfsclsession *sep) 478{ 479 u_int32_t retseq, retval, *tl; 480 time_t waituntil; 481 int i = 0, j = 0, opcnt, set_sigset = 0, slot; 482 int trycnt, error = 0, usegssname = 0, secflavour = AUTH_SYS; 483 int freeslot, timeo; 484 u_int16_t procnum; 485 u_int trylater_delay = 1; 486 struct nfs_feedback_arg nf; 487 struct timeval timo; 488 AUTH *auth; 489 struct rpc_callextra ext; 490 enum clnt_stat stat; 491 struct nfsreq *rep = NULL; 492 char *srv_principal = NULL, *clnt_principal = NULL; 493 sigset_t oldset; 494 struct ucred *authcred; 495 496 if (xidp != NULL) 497 *xidp = 0; 498 /* Reject requests while attempting a forced unmount. */ 499 if (nmp != NULL && (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)) { 500 m_freem(nd->nd_mreq); 501 return (ESTALE); 502 } 503 504 /* 505 * Set authcred, which is used to acquire RPC credentials to 506 * the cred argument, by default. The crhold() should not be 507 * necessary, but will ensure that some future code change 508 * doesn't result in the credential being free'd prematurely. 509 */ 510 authcred = crhold(cred); 511 512 /* For client side interruptible mounts, mask off the signals. */ 513 if (nmp != NULL && td != NULL && NFSHASINT(nmp)) { 514 newnfs_set_sigmask(td, &oldset); 515 set_sigset = 1; 516 } 517 518 /* 519 * XXX if not already connected call nfs_connect now. Longer 520 * term, change nfs_mount to call nfs_connect unconditionally 521 * and let clnt_reconnect_create handle reconnects. 522 */ 523 if (nrp->nr_client == NULL) 524 newnfs_connect(nmp, nrp, cred, td, 0); 525 526 /* 527 * For a client side mount, nmp is != NULL and clp == NULL. For 528 * server calls (callbacks or upcalls), nmp == NULL. 529 */ 530 if (clp != NULL) { 531 NFSLOCKSTATE(); 532 if ((clp->lc_flags & LCL_GSS) && nfsrv_gsscallbackson) { 533 secflavour = RPCSEC_GSS_KRB5; 534 if (nd->nd_procnum != NFSPROC_NULL) { 535 if (clp->lc_flags & LCL_GSSINTEGRITY) 536 secflavour = RPCSEC_GSS_KRB5I; 537 else if (clp->lc_flags & LCL_GSSPRIVACY) 538 secflavour = RPCSEC_GSS_KRB5P; 539 } 540 } 541 NFSUNLOCKSTATE(); 542 } else if (nmp != NULL && NFSHASKERB(nmp) && 543 nd->nd_procnum != NFSPROC_NULL) { 544 if (NFSHASALLGSSNAME(nmp) && nmp->nm_krbnamelen > 0) 545 nd->nd_flag |= ND_USEGSSNAME; 546 if ((nd->nd_flag & ND_USEGSSNAME) != 0) { 547 /* 548 * If there is a client side host based credential, 549 * use that, otherwise use the system uid, if set. 550 * The system uid is in the nmp->nm_sockreq.nr_cred 551 * credentials. 552 */ 553 if (nmp->nm_krbnamelen > 0) { 554 usegssname = 1; 555 clnt_principal = nmp->nm_krbname; 556 } else if (nmp->nm_uid != (uid_t)-1) { 557 KASSERT(nmp->nm_sockreq.nr_cred != NULL, 558 ("newnfs_request: NULL nr_cred")); 559 crfree(authcred); 560 authcred = crhold(nmp->nm_sockreq.nr_cred); 561 } 562 } else if (nmp->nm_krbnamelen == 0 && 563 nmp->nm_uid != (uid_t)-1 && cred->cr_uid == (uid_t)0) { 564 /* 565 * If there is no host based principal name and 566 * the system uid is set and this is root, use the 567 * system uid, since root won't have user 568 * credentials in a credentials cache file. 569 * The system uid is in the nmp->nm_sockreq.nr_cred 570 * credentials. 571 */ 572 KASSERT(nmp->nm_sockreq.nr_cred != NULL, 573 ("newnfs_request: NULL nr_cred")); 574 crfree(authcred); 575 authcred = crhold(nmp->nm_sockreq.nr_cred); 576 } 577 if (NFSHASINTEGRITY(nmp)) 578 secflavour = RPCSEC_GSS_KRB5I; 579 else if (NFSHASPRIVACY(nmp)) 580 secflavour = RPCSEC_GSS_KRB5P; 581 else 582 secflavour = RPCSEC_GSS_KRB5; 583 srv_principal = NFSMNT_SRVKRBNAME(nmp); 584 } else if (nmp != NULL && !NFSHASKERB(nmp) && 585 nd->nd_procnum != NFSPROC_NULL && 586 (nd->nd_flag & ND_USEGSSNAME) != 0) { 587 /* 588 * Use the uid that did the mount when the RPC is doing 589 * NFSv4 system operations, as indicated by the 590 * ND_USEGSSNAME flag, for the AUTH_SYS case. 591 * The credentials in nm_sockreq.nr_cred were used for the 592 * mount. 593 */ 594 KASSERT(nmp->nm_sockreq.nr_cred != NULL, 595 ("newnfs_request: NULL nr_cred")); 596 crfree(authcred); 597 authcred = crhold(nmp->nm_sockreq.nr_cred); 598 } 599 600 if (nmp != NULL) { 601 bzero(&nf, sizeof(struct nfs_feedback_arg)); 602 nf.nf_mount = nmp; 603 nf.nf_td = td; 604 nf.nf_lastmsg = NFSD_MONOSEC - 605 ((nmp->nm_tprintf_delay)-(nmp->nm_tprintf_initial_delay)); 606 } 607 608 if (nd->nd_procnum == NFSPROC_NULL) 609 auth = authnone_create(); 610 else if (usegssname) { 611 /* 612 * For this case, the authenticator is held in the 613 * nfssockreq structure, so don't release the reference count 614 * held on it. --> Don't AUTH_DESTROY() it in this function. 615 */ 616 if (nrp->nr_auth == NULL) 617 nrp->nr_auth = nfs_getauth(nrp, secflavour, 618 clnt_principal, srv_principal, NULL, authcred); 619 else 620 rpc_gss_refresh_auth_call(nrp->nr_auth); 621 auth = nrp->nr_auth; 622 } else 623 auth = nfs_getauth(nrp, secflavour, NULL, 624 srv_principal, NULL, authcred); 625 crfree(authcred); 626 if (auth == NULL) { 627 m_freem(nd->nd_mreq); 628 if (set_sigset) 629 newnfs_restore_sigmask(td, &oldset); 630 return (EACCES); 631 } 632 bzero(&ext, sizeof(ext)); 633 ext.rc_auth = auth; 634 if (nmp != NULL) { 635 ext.rc_feedback = nfs_feedback; 636 ext.rc_feedback_arg = &nf; 637 } 638 639 procnum = nd->nd_procnum; 640 if ((nd->nd_flag & ND_NFSV4) && 641 nd->nd_procnum != NFSPROC_NULL && 642 nd->nd_procnum != NFSV4PROC_CBCOMPOUND) 643 procnum = NFSV4PROC_COMPOUND; 644 645 if (nmp != NULL) { 646 NFSINCRGLOBAL(newnfsstats.rpcrequests); 647 648 /* Map the procnum to the old NFSv2 one, as required. */ 649 if ((nd->nd_flag & ND_NFSV2) != 0) { 650 if (nd->nd_procnum < NFS_V3NPROCS) 651 procnum = nfsv2_procid[nd->nd_procnum]; 652 else 653 procnum = NFSV2PROC_NOOP; 654 } 655 656 /* 657 * Now only used for the R_DONTRECOVER case, but until that is 658 * supported within the krpc code, I need to keep a queue of 659 * outstanding RPCs for nfsv4 client requests. 660 */ 661 if ((nd->nd_flag & ND_NFSV4) && procnum == NFSV4PROC_COMPOUND) 662 MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), 663 M_NFSDREQ, M_WAITOK); 664#ifdef KDTRACE_HOOKS 665 if (dtrace_nfscl_nfs234_start_probe != NULL) { 666 uint32_t probe_id; 667 int probe_procnum; 668 669 if (nd->nd_flag & ND_NFSV4) { 670 probe_id = 671 nfscl_nfs4_start_probes[nd->nd_procnum]; 672 probe_procnum = nd->nd_procnum; 673 } else if (nd->nd_flag & ND_NFSV3) { 674 probe_id = nfscl_nfs3_start_probes[procnum]; 675 probe_procnum = procnum; 676 } else { 677 probe_id = 678 nfscl_nfs2_start_probes[nd->nd_procnum]; 679 probe_procnum = procnum; 680 } 681 if (probe_id != 0) 682 (dtrace_nfscl_nfs234_start_probe) 683 (probe_id, vp, nd->nd_mreq, cred, 684 probe_procnum); 685 } 686#endif 687 } 688 trycnt = 0; 689 freeslot = -1; /* Set to slot that needs to be free'd */ 690tryagain: 691 slot = -1; /* Slot that needs a sequence# increment. */ 692 /* 693 * This timeout specifies when a new socket should be created, 694 * along with new xid values. For UDP, this should be done 695 * infrequently, since retransmits of RPC requests should normally 696 * use the same xid. 697 */ 698 if (nmp == NULL) { 699 timo.tv_usec = 0; 700 if (clp == NULL) 701 timo.tv_sec = NFSV4_UPCALLTIMEO; 702 else 703 timo.tv_sec = NFSV4_CALLBACKTIMEO; 704 } else { 705 if (nrp->nr_sotype != SOCK_DGRAM) { 706 timo.tv_usec = 0; 707 if ((nmp->nm_flag & NFSMNT_NFSV4)) 708 timo.tv_sec = INT_MAX; 709 else 710 timo.tv_sec = NFS_TCPTIMEO; 711 } else { 712 if (NFSHASSOFT(nmp)) { 713 /* 714 * CLSET_RETRIES is set to 2, so this should be 715 * half of the total timeout required. 716 */ 717 timeo = nmp->nm_retry * nmp->nm_timeo / 2; 718 if (timeo < 1) 719 timeo = 1; 720 timo.tv_sec = timeo / NFS_HZ; 721 timo.tv_usec = (timeo % NFS_HZ) * 1000000 / 722 NFS_HZ; 723 } else { 724 /* For UDP hard mounts, use a large value. */ 725 timo.tv_sec = NFS_MAXTIMEO / NFS_HZ; 726 timo.tv_usec = 0; 727 } 728 } 729 730 if (rep != NULL) { 731 rep->r_flags = 0; 732 rep->r_nmp = nmp; 733 /* 734 * Chain request into list of outstanding requests. 735 */ 736 NFSLOCKREQ(); 737 TAILQ_INSERT_TAIL(&nfsd_reqq, rep, r_chain); 738 NFSUNLOCKREQ(); 739 } 740 } 741 742 nd->nd_mrep = NULL; 743 if (clp != NULL && sep != NULL) 744 stat = clnt_bck_call(nrp->nr_client, &ext, procnum, 745 nd->nd_mreq, &nd->nd_mrep, timo, sep->nfsess_xprt); 746 else 747 stat = CLNT_CALL_MBUF(nrp->nr_client, &ext, procnum, 748 nd->nd_mreq, &nd->nd_mrep, timo); 749 750 if (rep != NULL) { 751 /* 752 * RPC done, unlink the request. 753 */ 754 NFSLOCKREQ(); 755 TAILQ_REMOVE(&nfsd_reqq, rep, r_chain); 756 NFSUNLOCKREQ(); 757 } 758 759 /* 760 * If there was a successful reply and a tprintf msg. 761 * tprintf a response. 762 */ 763 if (stat == RPC_SUCCESS) { 764 error = 0; 765 } else if (stat == RPC_TIMEDOUT) { 766 NFSINCRGLOBAL(newnfsstats.rpctimeouts); 767 error = ETIMEDOUT; 768 } else if (stat == RPC_VERSMISMATCH) { 769 NFSINCRGLOBAL(newnfsstats.rpcinvalid); 770 error = EOPNOTSUPP; 771 } else if (stat == RPC_PROGVERSMISMATCH) { 772 NFSINCRGLOBAL(newnfsstats.rpcinvalid); 773 error = EPROTONOSUPPORT; 774 } else if (stat == RPC_INTR) { 775 error = EINTR; 776 } else { 777 NFSINCRGLOBAL(newnfsstats.rpcinvalid); 778 error = EACCES; 779 } 780 if (error) { 781 m_freem(nd->nd_mreq); 782 if (usegssname == 0) 783 AUTH_DESTROY(auth); 784 if (rep != NULL) 785 FREE((caddr_t)rep, M_NFSDREQ); 786 if (set_sigset) 787 newnfs_restore_sigmask(td, &oldset); 788 return (error); 789 } 790 791 KASSERT(nd->nd_mrep != NULL, ("mrep shouldn't be NULL if no error\n")); 792 793 /* 794 * Search for any mbufs that are not a multiple of 4 bytes long 795 * or with m_data not longword aligned. 796 * These could cause pointer alignment problems, so copy them to 797 * well aligned mbufs. 798 */ 799 newnfs_realign(&nd->nd_mrep, M_WAITOK); 800 nd->nd_md = nd->nd_mrep; 801 nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t); 802 nd->nd_repstat = 0; 803 if (nd->nd_procnum != NFSPROC_NULL && 804 nd->nd_procnum != NFSV4PROC_CBNULL) { 805 /* If sep == NULL, set it to the default in nmp. */ 806 if (sep == NULL && nmp != NULL) 807 sep = NFSMNT_MDSSESSION(nmp); 808 /* 809 * and now the actual NFS xdr. 810 */ 811 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 812 nd->nd_repstat = fxdr_unsigned(u_int32_t, *tl); 813 if (nd->nd_repstat >= 10000) 814 NFSCL_DEBUG(1, "proc=%d reps=%d\n", (int)nd->nd_procnum, 815 (int)nd->nd_repstat); 816 817 /* 818 * Get rid of the tag, return count and SEQUENCE result for 819 * NFSv4. 820 */ 821 if ((nd->nd_flag & ND_NFSV4) != 0) { 822 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 823 i = fxdr_unsigned(int, *tl); 824 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 825 if (error) 826 goto nfsmout; 827 NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 828 opcnt = fxdr_unsigned(int, *tl++); 829 i = fxdr_unsigned(int, *tl++); 830 j = fxdr_unsigned(int, *tl); 831 if (j >= 10000) 832 NFSCL_DEBUG(1, "fop=%d fst=%d\n", i, j); 833 /* 834 * If the first op is Sequence, free up the slot. 835 */ 836 if ((nmp != NULL && i == NFSV4OP_SEQUENCE && j != 0) || 837 (clp != NULL && i == NFSV4OP_CBSEQUENCE && j != 0)) 838 NFSCL_DEBUG(1, "failed seq=%d\n", j); 839 if ((nmp != NULL && i == NFSV4OP_SEQUENCE && j == 0) || 840 (clp != NULL && i == NFSV4OP_CBSEQUENCE && j == 0) 841 ) { 842 if (i == NFSV4OP_SEQUENCE) 843 NFSM_DISSECT(tl, uint32_t *, 844 NFSX_V4SESSIONID + 845 5 * NFSX_UNSIGNED); 846 else 847 NFSM_DISSECT(tl, uint32_t *, 848 NFSX_V4SESSIONID + 849 4 * NFSX_UNSIGNED); 850 mtx_lock(&sep->nfsess_mtx); 851 tl += NFSX_V4SESSIONID / NFSX_UNSIGNED; 852 retseq = fxdr_unsigned(uint32_t, *tl++); 853 slot = fxdr_unsigned(int, *tl++); 854 freeslot = slot; 855 if (retseq != sep->nfsess_slotseq[slot]) 856 printf("retseq diff 0x%x\n", retseq); 857 retval = fxdr_unsigned(uint32_t, *++tl); 858 if ((retval + 1) < sep->nfsess_foreslots) 859 sep->nfsess_foreslots = (retval + 1); 860 else if ((retval + 1) > sep->nfsess_foreslots) 861 sep->nfsess_foreslots = (retval < 64) ? 862 (retval + 1) : 64; 863 mtx_unlock(&sep->nfsess_mtx); 864 865 /* Grab the op and status for the next one. */ 866 if (opcnt > 1) { 867 NFSM_DISSECT(tl, uint32_t *, 868 2 * NFSX_UNSIGNED); 869 i = fxdr_unsigned(int, *tl++); 870 j = fxdr_unsigned(int, *tl); 871 } 872 } 873 } 874 if (nd->nd_repstat != 0) { 875 if (((nd->nd_repstat == NFSERR_DELAY || 876 nd->nd_repstat == NFSERR_GRACE) && 877 (nd->nd_flag & ND_NFSV4) && 878 nd->nd_procnum != NFSPROC_DELEGRETURN && 879 nd->nd_procnum != NFSPROC_SETATTR && 880 nd->nd_procnum != NFSPROC_READ && 881 nd->nd_procnum != NFSPROC_READDS && 882 nd->nd_procnum != NFSPROC_WRITE && 883 nd->nd_procnum != NFSPROC_WRITEDS && 884 nd->nd_procnum != NFSPROC_OPEN && 885 nd->nd_procnum != NFSPROC_CREATE && 886 nd->nd_procnum != NFSPROC_OPENCONFIRM && 887 nd->nd_procnum != NFSPROC_OPENDOWNGRADE && 888 nd->nd_procnum != NFSPROC_CLOSE && 889 nd->nd_procnum != NFSPROC_LOCK && 890 nd->nd_procnum != NFSPROC_LOCKU) || 891 (nd->nd_repstat == NFSERR_DELAY && 892 (nd->nd_flag & ND_NFSV4) == 0) || 893 nd->nd_repstat == NFSERR_RESOURCE) { 894 if (trylater_delay > NFS_TRYLATERDEL) 895 trylater_delay = NFS_TRYLATERDEL; 896 waituntil = NFSD_MONOSEC + trylater_delay; 897 while (NFSD_MONOSEC < waituntil) 898 (void) nfs_catnap(PZERO, 0, "nfstry"); 899 trylater_delay *= 2; 900 if (slot != -1) { 901 mtx_lock(&sep->nfsess_mtx); 902 sep->nfsess_slotseq[slot]++; 903 *nd->nd_slotseq = txdr_unsigned( 904 sep->nfsess_slotseq[slot]); 905 mtx_unlock(&sep->nfsess_mtx); 906 } 907 m_freem(nd->nd_mrep); 908 nd->nd_mrep = NULL; 909 goto tryagain; 910 } 911 912 /* 913 * If the File Handle was stale, invalidate the 914 * lookup cache, just in case. 915 * (vp != NULL implies a client side call) 916 */ 917 if (nd->nd_repstat == ESTALE && vp != NULL) { 918 cache_purge(vp); 919 if (ncl_call_invalcaches != NULL) 920 (*ncl_call_invalcaches)(vp); 921 } 922 } 923 if ((nd->nd_flag & ND_NFSV4) != 0) { 924 /* Free the slot, as required. */ 925 if (freeslot != -1) 926 nfsv4_freeslot(sep, freeslot); 927 /* 928 * If this op is Putfh, throw its results away. 929 */ 930 if (j >= 10000) 931 NFSCL_DEBUG(1, "nop=%d nst=%d\n", i, j); 932 if (nmp != NULL && i == NFSV4OP_PUTFH && j == 0) { 933 NFSM_DISSECT(tl,u_int32_t *,2 * NFSX_UNSIGNED); 934 i = fxdr_unsigned(int, *tl++); 935 j = fxdr_unsigned(int, *tl); 936 if (j >= 10000) 937 NFSCL_DEBUG(1, "n2op=%d n2st=%d\n", i, 938 j); 939 /* 940 * All Compounds that do an Op that must 941 * be in sequence consist of NFSV4OP_PUTFH 942 * followed by one of these. As such, we 943 * can determine if the seqid# should be 944 * incremented, here. 945 */ 946 if ((i == NFSV4OP_OPEN || 947 i == NFSV4OP_OPENCONFIRM || 948 i == NFSV4OP_OPENDOWNGRADE || 949 i == NFSV4OP_CLOSE || 950 i == NFSV4OP_LOCK || 951 i == NFSV4OP_LOCKU) && 952 (j == 0 || 953 (j != NFSERR_STALECLIENTID && 954 j != NFSERR_STALESTATEID && 955 j != NFSERR_BADSTATEID && 956 j != NFSERR_BADSEQID && 957 j != NFSERR_BADXDR && 958 j != NFSERR_RESOURCE && 959 j != NFSERR_NOFILEHANDLE))) 960 nd->nd_flag |= ND_INCRSEQID; 961 } 962 /* 963 * If this op's status is non-zero, mark 964 * that there is no more data to process. 965 */ 966 if (j) 967 nd->nd_flag |= ND_NOMOREDATA; 968 969 /* 970 * If R_DONTRECOVER is set, replace the stale error 971 * reply, so that recovery isn't initiated. 972 */ 973 if ((nd->nd_repstat == NFSERR_STALECLIENTID || 974 nd->nd_repstat == NFSERR_BADSESSION || 975 nd->nd_repstat == NFSERR_STALESTATEID) && 976 rep != NULL && (rep->r_flags & R_DONTRECOVER)) 977 nd->nd_repstat = NFSERR_STALEDONTRECOVER; 978 } 979 } 980 981#ifdef KDTRACE_HOOKS 982 if (nmp != NULL && dtrace_nfscl_nfs234_done_probe != NULL) { 983 uint32_t probe_id; 984 int probe_procnum; 985 986 if (nd->nd_flag & ND_NFSV4) { 987 probe_id = nfscl_nfs4_done_probes[nd->nd_procnum]; 988 probe_procnum = nd->nd_procnum; 989 } else if (nd->nd_flag & ND_NFSV3) { 990 probe_id = nfscl_nfs3_done_probes[procnum]; 991 probe_procnum = procnum; 992 } else { 993 probe_id = nfscl_nfs2_done_probes[nd->nd_procnum]; 994 probe_procnum = procnum; 995 } 996 if (probe_id != 0) 997 (dtrace_nfscl_nfs234_done_probe)(probe_id, vp, 998 nd->nd_mreq, cred, probe_procnum, 0); 999 } 1000#endif 1001 1002 m_freem(nd->nd_mreq); 1003 if (usegssname == 0) 1004 AUTH_DESTROY(auth); 1005 if (rep != NULL) 1006 FREE((caddr_t)rep, M_NFSDREQ); 1007 if (set_sigset) 1008 newnfs_restore_sigmask(td, &oldset); 1009 return (0); 1010nfsmout: 1011 mbuf_freem(nd->nd_mrep); 1012 mbuf_freem(nd->nd_mreq); 1013 if (usegssname == 0) 1014 AUTH_DESTROY(auth); 1015 if (rep != NULL) 1016 FREE((caddr_t)rep, M_NFSDREQ); 1017 if (set_sigset) 1018 newnfs_restore_sigmask(td, &oldset); 1019 return (error); 1020} 1021 1022/* 1023 * Mark all of an nfs mount's outstanding requests with R_SOFTTERM and 1024 * wait for all requests to complete. This is used by forced unmounts 1025 * to terminate any outstanding RPCs. 1026 */ 1027int 1028newnfs_nmcancelreqs(struct nfsmount *nmp) 1029{ 1030 1031 if (nmp->nm_sockreq.nr_client != NULL) 1032 CLNT_CLOSE(nmp->nm_sockreq.nr_client); 1033 return (0); 1034} 1035 1036/* 1037 * Any signal that can interrupt an NFS operation in an intr mount 1038 * should be added to this set. SIGSTOP and SIGKILL cannot be masked. 1039 */ 1040int newnfs_sig_set[] = { 1041 SIGINT, 1042 SIGTERM, 1043 SIGHUP, 1044 SIGKILL, 1045 SIGQUIT 1046}; 1047 1048/* 1049 * Check to see if one of the signals in our subset is pending on 1050 * the process (in an intr mount). 1051 */ 1052static int 1053nfs_sig_pending(sigset_t set) 1054{ 1055 int i; 1056 1057 for (i = 0 ; i < sizeof(newnfs_sig_set)/sizeof(int) ; i++) 1058 if (SIGISMEMBER(set, newnfs_sig_set[i])) 1059 return (1); 1060 return (0); 1061} 1062 1063/* 1064 * The set/restore sigmask functions are used to (temporarily) overwrite 1065 * the thread td_sigmask during an RPC call (for example). These are also 1066 * used in other places in the NFS client that might tsleep(). 1067 */ 1068void 1069newnfs_set_sigmask(struct thread *td, sigset_t *oldset) 1070{ 1071 sigset_t newset; 1072 int i; 1073 struct proc *p; 1074 1075 SIGFILLSET(newset); 1076 if (td == NULL) 1077 td = curthread; /* XXX */ 1078 p = td->td_proc; 1079 /* Remove the NFS set of signals from newset */ 1080 PROC_LOCK(p); 1081 mtx_lock(&p->p_sigacts->ps_mtx); 1082 for (i = 0 ; i < sizeof(newnfs_sig_set)/sizeof(int) ; i++) { 1083 /* 1084 * But make sure we leave the ones already masked 1085 * by the process, ie. remove the signal from the 1086 * temporary signalmask only if it wasn't already 1087 * in p_sigmask. 1088 */ 1089 if (!SIGISMEMBER(td->td_sigmask, newnfs_sig_set[i]) && 1090 !SIGISMEMBER(p->p_sigacts->ps_sigignore, newnfs_sig_set[i])) 1091 SIGDELSET(newset, newnfs_sig_set[i]); 1092 } 1093 mtx_unlock(&p->p_sigacts->ps_mtx); 1094 kern_sigprocmask(td, SIG_SETMASK, &newset, oldset, 1095 SIGPROCMASK_PROC_LOCKED); 1096 PROC_UNLOCK(p); 1097} 1098 1099void 1100newnfs_restore_sigmask(struct thread *td, sigset_t *set) 1101{ 1102 if (td == NULL) 1103 td = curthread; /* XXX */ 1104 kern_sigprocmask(td, SIG_SETMASK, set, NULL, 0); 1105} 1106 1107/* 1108 * NFS wrapper to msleep(), that shoves a new p_sigmask and restores the 1109 * old one after msleep() returns. 1110 */ 1111int 1112newnfs_msleep(struct thread *td, void *ident, struct mtx *mtx, int priority, char *wmesg, int timo) 1113{ 1114 sigset_t oldset; 1115 int error; 1116 struct proc *p; 1117 1118 if ((priority & PCATCH) == 0) 1119 return msleep(ident, mtx, priority, wmesg, timo); 1120 if (td == NULL) 1121 td = curthread; /* XXX */ 1122 newnfs_set_sigmask(td, &oldset); 1123 error = msleep(ident, mtx, priority, wmesg, timo); 1124 newnfs_restore_sigmask(td, &oldset); 1125 p = td->td_proc; 1126 return (error); 1127} 1128 1129/* 1130 * Test for a termination condition pending on the process. 1131 * This is used for NFSMNT_INT mounts. 1132 */ 1133int 1134newnfs_sigintr(struct nfsmount *nmp, struct thread *td) 1135{ 1136 struct proc *p; 1137 sigset_t tmpset; 1138 1139 /* Terminate all requests while attempting a forced unmount. */ 1140 if (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF) 1141 return (EIO); 1142 if (!(nmp->nm_flag & NFSMNT_INT)) 1143 return (0); 1144 if (td == NULL) 1145 return (0); 1146 p = td->td_proc; 1147 PROC_LOCK(p); 1148 tmpset = p->p_siglist; 1149 SIGSETOR(tmpset, td->td_siglist); 1150 SIGSETNAND(tmpset, td->td_sigmask); 1151 mtx_lock(&p->p_sigacts->ps_mtx); 1152 SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore); 1153 mtx_unlock(&p->p_sigacts->ps_mtx); 1154 if ((SIGNOTEMPTY(p->p_siglist) || SIGNOTEMPTY(td->td_siglist)) 1155 && nfs_sig_pending(tmpset)) { 1156 PROC_UNLOCK(p); 1157 return (EINTR); 1158 } 1159 PROC_UNLOCK(p); 1160 return (0); 1161} 1162 1163static int 1164nfs_msg(struct thread *td, const char *server, const char *msg, int error) 1165{ 1166 struct proc *p; 1167 1168 p = td ? td->td_proc : NULL; 1169 if (error) { 1170 tprintf(p, LOG_INFO, "newnfs server %s: %s, error %d\n", 1171 server, msg, error); 1172 } else { 1173 tprintf(p, LOG_INFO, "newnfs server %s: %s\n", server, msg); 1174 } 1175 return (0); 1176} 1177 1178static void 1179nfs_down(struct nfsmount *nmp, struct thread *td, const char *msg, 1180 int error, int flags) 1181{ 1182 if (nmp == NULL) 1183 return; 1184 mtx_lock(&nmp->nm_mtx); 1185 if ((flags & NFSSTA_TIMEO) && !(nmp->nm_state & NFSSTA_TIMEO)) { 1186 nmp->nm_state |= NFSSTA_TIMEO; 1187 mtx_unlock(&nmp->nm_mtx); 1188 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid, 1189 VQ_NOTRESP, 0); 1190 } else 1191 mtx_unlock(&nmp->nm_mtx); 1192 mtx_lock(&nmp->nm_mtx); 1193 if ((flags & NFSSTA_LOCKTIMEO) && !(nmp->nm_state & NFSSTA_LOCKTIMEO)) { 1194 nmp->nm_state |= NFSSTA_LOCKTIMEO; 1195 mtx_unlock(&nmp->nm_mtx); 1196 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid, 1197 VQ_NOTRESPLOCK, 0); 1198 } else 1199 mtx_unlock(&nmp->nm_mtx); 1200 nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, error); 1201} 1202 1203static void 1204nfs_up(struct nfsmount *nmp, struct thread *td, const char *msg, 1205 int flags, int tprintfmsg) 1206{ 1207 if (nmp == NULL) 1208 return; 1209 if (tprintfmsg) { 1210 nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, 0); 1211 } 1212 1213 mtx_lock(&nmp->nm_mtx); 1214 if ((flags & NFSSTA_TIMEO) && (nmp->nm_state & NFSSTA_TIMEO)) { 1215 nmp->nm_state &= ~NFSSTA_TIMEO; 1216 mtx_unlock(&nmp->nm_mtx); 1217 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid, 1218 VQ_NOTRESP, 1); 1219 } else 1220 mtx_unlock(&nmp->nm_mtx); 1221 1222 mtx_lock(&nmp->nm_mtx); 1223 if ((flags & NFSSTA_LOCKTIMEO) && (nmp->nm_state & NFSSTA_LOCKTIMEO)) { 1224 nmp->nm_state &= ~NFSSTA_LOCKTIMEO; 1225 mtx_unlock(&nmp->nm_mtx); 1226 vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid, 1227 VQ_NOTRESPLOCK, 1); 1228 } else 1229 mtx_unlock(&nmp->nm_mtx); 1230} 1231 1232