1 /*- 2 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 3 * Authors: Doug Rabson <dfr@rabson.org> 4 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include "opt_inet6.h" 29 #include "opt_nfs.h" 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/fcntl.h> 36 #include <sys/kernel.h> 37 #include <sys/kthread.h> 38 #include <sys/lockf.h> 39 #include <sys/malloc.h> 40 #include <sys/mount.h> 41 #if __FreeBSD_version >= 700000 42 #include <sys/priv.h> 43 #endif 44 #include <sys/proc.h> 45 #include <sys/socket.h> 46 #include <sys/socketvar.h> 47 #include <sys/syscall.h> 48 #include <sys/sysctl.h> 49 #include <sys/sysent.h> 50 #include <sys/sysproto.h> 51 #include <sys/systm.h> 52 #include <sys/taskqueue.h> 53 #include <sys/unistd.h> 54 #include <sys/vnode.h> 55 56 #include <nfs/nfsproto.h> 57 #include <nfsclient/nfs.h> 58 #include <nfsclient/nfsnode.h> 59 60 #include <nlm/nlm_prot.h> 61 #include <nlm/sm_inter.h> 62 #include <nlm/nlm.h> 63 #include <rpc/rpc_com.h> 64 #include <rpc/rpcb_prot.h> 65 66 MALLOC_DEFINE(M_NLM, "NLM", "Network Lock Manager"); 67 68 /* 69 * If a host is inactive (and holds no locks) for this amount of 70 * seconds, we consider it idle and stop tracking it. 71 */ 72 #define NLM_IDLE_TIMEOUT 30 73 74 /* 75 * We check the host list for idle every few seconds. 76 */ 77 #define NLM_IDLE_PERIOD 5 78 79 /* 80 * Support for sysctl vfs.nlm.sysid 81 */ 82 SYSCTL_NODE(_vfs, OID_AUTO, nlm, CTLFLAG_RW, NULL, "Network Lock Manager"); 83 SYSCTL_NODE(_vfs_nlm, OID_AUTO, sysid, CTLFLAG_RW, NULL, ""); 84 85 /* 86 * Syscall hooks 87 */ 88 static int nlm_syscall_offset = SYS_nlm_syscall; 89 static struct sysent nlm_syscall_prev_sysent; 90 #if __FreeBSD_version < 700000 91 static struct sysent nlm_syscall_sysent = { 92 (sizeof(struct nlm_syscall_args) / sizeof(register_t)) | SYF_MPSAFE, 93 (sy_call_t *) nlm_syscall 94 }; 95 #else 96 MAKE_SYSENT(nlm_syscall); 97 #endif 98 static bool_t nlm_syscall_registered = FALSE; 99 100 /* 101 * Debug level passed in from userland. We also support a sysctl hook 102 * so that it can be changed on a live system. 103 */ 104 static int nlm_debug_level; 105 SYSCTL_INT(_debug, OID_AUTO, nlm_debug, CTLFLAG_RW, &nlm_debug_level, 0, ""); 106 107 /* 108 * Grace period handling. The value of nlm_grace_threshold is the 109 * value of time_uptime after which we are serving requests normally. 110 */ 111 static time_t nlm_grace_threshold; 112 113 /* 114 * We check for idle hosts if time_uptime is greater than 115 * nlm_next_idle_check, 116 */ 117 static time_t nlm_next_idle_check; 118 119 /* 120 * A socket to use for RPC - shared by all IPv4 RPC clients. 121 */ 122 static struct socket *nlm_socket; 123 124 #ifdef INET6 125 126 /* 127 * A socket to use for RPC - shared by all IPv6 RPC clients. 128 */ 129 static struct socket *nlm_socket6; 130 131 #endif 132 133 /* 134 * An RPC client handle that can be used to communicate with the local 135 * NSM. 136 */ 137 static CLIENT *nlm_nsm; 138 139 /* 140 * An AUTH handle for the server's creds. 141 */ 142 static AUTH *nlm_auth; 143 144 /* 145 * A zero timeval for sending async RPC messages. 146 */ 147 struct timeval nlm_zero_tv = { 0, 0 }; 148 149 /* 150 * The local NSM state number 151 */ 152 int nlm_nsm_state; 153 154 155 /* 156 * A lock to protect the host list and waiting lock list. 157 */ 158 static struct mtx nlm_global_lock; 159 160 /* 161 * Locks: 162 * (l) locked by nh_lock 163 * (s) only accessed via server RPC which is single threaded 164 * (g) locked by nlm_global_lock 165 * (c) const until freeing 166 * (a) modified using atomic ops 167 */ 168 169 /* 170 * A pending client-side lock request, stored on the nlm_waiting_locks 171 * list. 172 */ 173 struct nlm_waiting_lock { 174 TAILQ_ENTRY(nlm_waiting_lock) nw_link; /* (g) */ 175 bool_t nw_waiting; /* (g) */ 176 nlm4_lock nw_lock; /* (c) */ 177 union nfsfh nw_fh; /* (c) */ 178 struct vnode *nw_vp; /* (c) */ 179 }; 180 TAILQ_HEAD(nlm_waiting_lock_list, nlm_waiting_lock); 181 182 struct nlm_waiting_lock_list nlm_waiting_locks; /* (g) */ 183 184 /* 185 * A pending server-side asynchronous lock request, stored on the 186 * nh_pending list of the NLM host. 187 */ 188 struct nlm_async_lock { 189 TAILQ_ENTRY(nlm_async_lock) af_link; /* (l) host's list of locks */ 190 struct task af_task; /* (c) async callback details */ 191 void *af_cookie; /* (l) lock manager cancel token */ 192 struct vnode *af_vp; /* (l) vnode to lock */ 193 struct flock af_fl; /* (c) lock details */ 194 struct nlm_host *af_host; /* (c) host which is locking */ 195 CLIENT *af_rpc; /* (c) rpc client to send message */ 196 nlm4_testargs af_granted; /* (c) notification details */ 197 }; 198 TAILQ_HEAD(nlm_async_lock_list, nlm_async_lock); 199 200 /* 201 * NLM host. 202 */ 203 enum nlm_host_state { 204 NLM_UNMONITORED, 205 NLM_MONITORED, 206 NLM_MONITOR_FAILED, 207 NLM_RECOVERING 208 }; 209 210 struct nlm_rpc { 211 CLIENT *nr_client; /* (l) RPC client handle */ 212 time_t nr_create_time; /* (l) when client was created */ 213 }; 214 215 struct nlm_host { 216 struct mtx nh_lock; 217 volatile u_int nh_refs; /* (a) reference count */ 218 TAILQ_ENTRY(nlm_host) nh_link; /* (g) global list of hosts */ 219 char nh_caller_name[MAXNAMELEN]; /* (c) printable name of host */ 220 uint32_t nh_sysid; /* (c) our allocaed system ID */ 221 char nh_sysid_string[10]; /* (c) string rep. of sysid */ 222 struct sockaddr_storage nh_addr; /* (s) remote address of host */ 223 struct nlm_rpc nh_srvrpc; /* (l) RPC for server replies */ 224 struct nlm_rpc nh_clntrpc; /* (l) RPC for client requests */ 225 rpcvers_t nh_vers; /* (s) NLM version of host */ 226 int nh_state; /* (s) last seen NSM state of host */ 227 enum nlm_host_state nh_monstate; /* (l) local NSM monitoring state */ 228 time_t nh_idle_timeout; /* (s) Time at which host is idle */ 229 struct sysctl_ctx_list nh_sysctl; /* (c) vfs.nlm.sysid nodes */ 230 struct nlm_async_lock_list nh_pending; /* (l) pending async locks */ 231 struct nlm_async_lock_list nh_finished; /* (l) finished async locks */ 232 }; 233 TAILQ_HEAD(nlm_host_list, nlm_host); 234 235 static struct nlm_host_list nlm_hosts; /* (g) */ 236 static uint32_t nlm_next_sysid = 1; /* (g) */ 237 238 static void nlm_host_unmonitor(struct nlm_host *); 239 240 /**********************************************************************/ 241 242 /* 243 * Initialise NLM globals. 244 */ 245 static void 246 nlm_init(void *dummy) 247 { 248 int error; 249 250 mtx_init(&nlm_global_lock, "nlm_global_lock", NULL, MTX_DEF); 251 TAILQ_INIT(&nlm_waiting_locks); 252 TAILQ_INIT(&nlm_hosts); 253 254 error = syscall_register(&nlm_syscall_offset, &nlm_syscall_sysent, 255 &nlm_syscall_prev_sysent); 256 if (error) 257 printf("Can't register NLM syscall\n"); 258 else 259 nlm_syscall_registered = TRUE; 260 } 261 SYSINIT(nlm_init, SI_SUB_LOCK, SI_ORDER_FIRST, nlm_init, NULL); 262 263 static void 264 nlm_uninit(void *dummy) 265 { 266 267 if (nlm_syscall_registered) 268 syscall_deregister(&nlm_syscall_offset, 269 &nlm_syscall_prev_sysent); 270 } 271 SYSUNINIT(nlm_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, nlm_uninit, NULL); 272 273 /* 274 * Copy a struct netobj. 275 */ 276 void 277 nlm_copy_netobj(struct netobj *dst, struct netobj *src, 278 struct malloc_type *type) 279 { 280 281 dst->n_len = src->n_len; 282 dst->n_bytes = malloc(src->n_len, type, M_WAITOK); 283 memcpy(dst->n_bytes, src->n_bytes, src->n_len); 284 } 285 286 /* 287 * Create an RPC client handle for the given (address,prog,vers) 288 * triple using UDP. 289 */ 290 static CLIENT * 291 nlm_get_rpc(struct sockaddr *sa, rpcprog_t prog, rpcvers_t vers) 292 { 293 char *wchan = "nlmrcv"; 294 const char* protofmly; 295 struct sockaddr_storage ss; 296 struct socket *so; 297 CLIENT *rpcb; 298 struct timeval timo; 299 RPCB parms; 300 char *uaddr; 301 enum clnt_stat stat = RPC_SUCCESS; 302 int rpcvers = RPCBVERS4; 303 bool_t do_tcp = FALSE; 304 struct portmap mapping; 305 u_short port = 0; 306 307 /* 308 * First we need to contact the remote RPCBIND service to find 309 * the right port. 310 */ 311 memcpy(&ss, sa, sa->sa_len); 312 switch (ss.ss_family) { 313 case AF_INET: 314 ((struct sockaddr_in *)&ss)->sin_port = htons(111); 315 protofmly = "inet"; 316 so = nlm_socket; 317 break; 318 319 #ifdef INET6 320 case AF_INET6: 321 ((struct sockaddr_in6 *)&ss)->sin6_port = htons(111); 322 protofmly = "inet6"; 323 so = nlm_socket6; 324 break; 325 #endif 326 327 default: 328 /* 329 * Unsupported address family - fail. 330 */ 331 return (NULL); 332 } 333 334 rpcb = clnt_dg_create(so, (struct sockaddr *)&ss, 335 RPCBPROG, rpcvers, 0, 0); 336 if (!rpcb) 337 return (NULL); 338 339 try_tcp: 340 parms.r_prog = prog; 341 parms.r_vers = vers; 342 if (do_tcp) 343 parms.r_netid = "tcp"; 344 else 345 parms.r_netid = "udp"; 346 parms.r_addr = ""; 347 parms.r_owner = ""; 348 349 /* 350 * Use the default timeout. 351 */ 352 timo.tv_sec = 25; 353 timo.tv_usec = 0; 354 again: 355 switch (rpcvers) { 356 case RPCBVERS4: 357 case RPCBVERS: 358 /* 359 * Try RPCBIND 4 then 3. 360 */ 361 uaddr = NULL; 362 stat = CLNT_CALL(rpcb, (rpcprog_t) RPCBPROC_GETADDR, 363 (xdrproc_t) xdr_rpcb, &parms, 364 (xdrproc_t) xdr_wrapstring, &uaddr, timo); 365 if (stat == RPC_PROGVERSMISMATCH) { 366 if (rpcvers == RPCBVERS4) 367 rpcvers = RPCBVERS; 368 else if (rpcvers == RPCBVERS) 369 rpcvers = PMAPVERS; 370 CLNT_CONTROL(rpcb, CLSET_VERS, &rpcvers); 371 goto again; 372 } else if (stat == RPC_SUCCESS) { 373 /* 374 * We have a reply from the remote RPCBIND - turn it 375 * into an appropriate address and make a new client 376 * that can talk to the remote NLM. 377 * 378 * XXX fixup IPv6 scope ID. 379 */ 380 struct netbuf *a; 381 a = __rpc_uaddr2taddr_af(ss.ss_family, uaddr); 382 if (!a) { 383 CLNT_DESTROY(rpcb); 384 return (NULL); 385 } 386 memcpy(&ss, a->buf, a->len); 387 free(a->buf, M_RPC); 388 free(a, M_RPC); 389 xdr_free((xdrproc_t) xdr_wrapstring, &uaddr); 390 } 391 break; 392 case PMAPVERS: 393 /* 394 * Try portmap. 395 */ 396 mapping.pm_prog = parms.r_prog; 397 mapping.pm_vers = parms.r_vers; 398 mapping.pm_prot = do_tcp ? IPPROTO_TCP : IPPROTO_UDP; 399 mapping.pm_port = 0; 400 401 stat = CLNT_CALL(rpcb, (rpcprog_t) PMAPPROC_GETPORT, 402 (xdrproc_t) xdr_portmap, &mapping, 403 (xdrproc_t) xdr_u_short, &port, timo); 404 405 if (stat == RPC_SUCCESS) { 406 switch (ss.ss_family) { 407 case AF_INET: 408 ((struct sockaddr_in *)&ss)->sin_port = 409 htons(port); 410 break; 411 412 #ifdef INET6 413 case AF_INET6: 414 ((struct sockaddr_in6 *)&ss)->sin6_port = 415 htons(port); 416 break; 417 #endif 418 } 419 } 420 break; 421 default: 422 panic("invalid rpcvers %d", rpcvers); 423 } 424 /* 425 * We may have a positive response from the portmapper, but the NLM 426 * service was not found. Make sure we received a valid port. 427 */ 428 switch (ss.ss_family) { 429 case AF_INET: 430 port = ((struct sockaddr_in *)&ss)->sin_port; 431 break; 432 #ifdef INET6 433 case AF_INET6: 434 port = ((struct sockaddr_in6 *)&ss)->sin6_port; 435 break; 436 #endif 437 } 438 if (stat != RPC_SUCCESS || !port) { 439 /* 440 * If we were able to talk to rpcbind or portmap, but the udp 441 * variant wasn't available, ask about tcp. 442 * 443 * XXX - We could also check for a TCP portmapper, but 444 * if the host is running a portmapper at all, we should be able 445 * to hail it over UDP. 446 */ 447 if (stat == RPC_SUCCESS && !do_tcp) { 448 do_tcp = TRUE; 449 goto try_tcp; 450 } 451 452 /* Otherwise, bad news. */ 453 printf("NLM: failed to contact remote rpcbind, " 454 "stat = %d, port = %d\n", 455 (int) stat, port); 456 CLNT_DESTROY(rpcb); 457 return (NULL); 458 } 459 460 if (do_tcp) { 461 /* 462 * Destroy the UDP client we used to speak to rpcbind and 463 * recreate as a TCP client. 464 */ 465 struct netconfig *nconf = NULL; 466 467 CLNT_DESTROY(rpcb); 468 469 switch (ss.ss_family) { 470 case AF_INET: 471 nconf = getnetconfigent("tcp"); 472 break; 473 #ifdef INET6 474 case AF_INET6: 475 nconf = getnetconfigent("tcp6"); 476 break; 477 #endif 478 } 479 480 rpcb = clnt_reconnect_create(nconf, (struct sockaddr *)&ss, 481 prog, vers, 0, 0); 482 CLNT_CONTROL(rpcb, CLSET_WAITCHAN, wchan); 483 rpcb->cl_auth = nlm_auth; 484 485 } else { 486 /* 487 * Re-use the client we used to speak to rpcbind. 488 */ 489 CLNT_CONTROL(rpcb, CLSET_SVC_ADDR, &ss); 490 CLNT_CONTROL(rpcb, CLSET_PROG, &prog); 491 CLNT_CONTROL(rpcb, CLSET_VERS, &vers); 492 CLNT_CONTROL(rpcb, CLSET_WAITCHAN, wchan); 493 rpcb->cl_auth = nlm_auth; 494 } 495 496 return (rpcb); 497 } 498 499 /* 500 * This async callback after when an async lock request has been 501 * granted. We notify the host which initiated the request. 502 */ 503 static void 504 nlm_lock_callback(void *arg, int pending) 505 { 506 struct nlm_async_lock *af = (struct nlm_async_lock *) arg; 507 struct rpc_callextra ext; 508 509 if (nlm_debug_level >= 2) 510 printf("NLM: async lock %p for %s (sysid %d) granted\n", 511 af, af->af_host->nh_caller_name, 512 af->af_host->nh_sysid); 513 514 /* 515 * Send the results back to the host. 516 * 517 * Note: there is a possible race here with nlm_host_notify 518 * destroying the RPC client. To avoid problems, the first 519 * thing nlm_host_notify does is to cancel pending async lock 520 * requests. 521 */ 522 memset(&ext, 0, sizeof(ext)); 523 ext.rc_auth = nlm_auth; 524 if (af->af_host->nh_vers == NLM_VERS4) { 525 nlm4_granted_msg_4(&af->af_granted, 526 NULL, af->af_rpc, &ext, nlm_zero_tv); 527 } else { 528 /* 529 * Back-convert to legacy protocol 530 */ 531 nlm_testargs granted; 532 granted.cookie = af->af_granted.cookie; 533 granted.exclusive = af->af_granted.exclusive; 534 granted.alock.caller_name = 535 af->af_granted.alock.caller_name; 536 granted.alock.fh = af->af_granted.alock.fh; 537 granted.alock.oh = af->af_granted.alock.oh; 538 granted.alock.svid = af->af_granted.alock.svid; 539 granted.alock.l_offset = 540 af->af_granted.alock.l_offset; 541 granted.alock.l_len = 542 af->af_granted.alock.l_len; 543 544 nlm_granted_msg_1(&granted, 545 NULL, af->af_rpc, &ext, nlm_zero_tv); 546 } 547 548 /* 549 * Move this entry to the nh_finished list. Someone else will 550 * free it later - its too hard to do it here safely without 551 * racing with cancel. 552 * 553 * XXX possibly we should have a third "granted sent but not 554 * ack'ed" list so that we can re-send the granted message. 555 */ 556 mtx_lock(&af->af_host->nh_lock); 557 TAILQ_REMOVE(&af->af_host->nh_pending, af, af_link); 558 TAILQ_INSERT_TAIL(&af->af_host->nh_finished, af, af_link); 559 mtx_unlock(&af->af_host->nh_lock); 560 } 561 562 /* 563 * Free an async lock request. The request must have been removed from 564 * any list. 565 */ 566 static void 567 nlm_free_async_lock(struct nlm_async_lock *af) 568 { 569 /* 570 * Free an async lock. 571 */ 572 if (af->af_rpc) 573 CLNT_RELEASE(af->af_rpc); 574 xdr_free((xdrproc_t) xdr_nlm4_testargs, &af->af_granted); 575 if (af->af_vp) 576 vrele(af->af_vp); 577 free(af, M_NLM); 578 } 579 580 /* 581 * Cancel our async request - this must be called with 582 * af->nh_host->nh_lock held. This is slightly complicated by a 583 * potential race with our own callback. If we fail to cancel the 584 * lock, it must already have been granted - we make sure our async 585 * task has completed by calling taskqueue_drain in this case. 586 */ 587 static int 588 nlm_cancel_async_lock(struct nlm_async_lock *af) 589 { 590 struct nlm_host *host = af->af_host; 591 int error; 592 593 mtx_assert(&host->nh_lock, MA_OWNED); 594 595 mtx_unlock(&host->nh_lock); 596 597 error = VOP_ADVLOCKASYNC(af->af_vp, NULL, F_CANCEL, &af->af_fl, 598 F_REMOTE, NULL, &af->af_cookie); 599 600 if (error) { 601 /* 602 * We failed to cancel - make sure our callback has 603 * completed before we continue. 604 */ 605 taskqueue_drain(taskqueue_thread, &af->af_task); 606 } 607 608 mtx_lock(&host->nh_lock); 609 610 if (!error) { 611 if (nlm_debug_level >= 2) 612 printf("NLM: async lock %p for %s (sysid %d) " 613 "cancelled\n", 614 af, host->nh_caller_name, host->nh_sysid); 615 616 /* 617 * Remove from the nh_pending list and free now that 618 * we are safe from the callback. 619 */ 620 TAILQ_REMOVE(&host->nh_pending, af, af_link); 621 mtx_unlock(&host->nh_lock); 622 nlm_free_async_lock(af); 623 mtx_lock(&host->nh_lock); 624 } 625 626 return (error); 627 } 628 629 static void 630 nlm_free_finished_locks(struct nlm_host *host) 631 { 632 struct nlm_async_lock *af; 633 634 mtx_lock(&host->nh_lock); 635 while ((af = TAILQ_FIRST(&host->nh_finished)) != NULL) { 636 TAILQ_REMOVE(&host->nh_finished, af, af_link); 637 mtx_unlock(&host->nh_lock); 638 nlm_free_async_lock(af); 639 mtx_lock(&host->nh_lock); 640 } 641 mtx_unlock(&host->nh_lock); 642 } 643 644 /* 645 * Free resources used by a host. This is called after the reference 646 * count has reached zero so it doesn't need to worry about locks. 647 */ 648 static void 649 nlm_host_destroy(struct nlm_host *host) 650 { 651 652 mtx_lock(&nlm_global_lock); 653 TAILQ_REMOVE(&nlm_hosts, host, nh_link); 654 mtx_unlock(&nlm_global_lock); 655 656 if (host->nh_srvrpc.nr_client) 657 CLNT_RELEASE(host->nh_srvrpc.nr_client); 658 if (host->nh_clntrpc.nr_client) 659 CLNT_RELEASE(host->nh_clntrpc.nr_client); 660 mtx_destroy(&host->nh_lock); 661 sysctl_ctx_free(&host->nh_sysctl); 662 free(host, M_NLM); 663 } 664 665 #ifdef NFSCLIENT 666 667 /* 668 * Thread start callback for client lock recovery 669 */ 670 static void 671 nlm_client_recovery_start(void *arg) 672 { 673 struct nlm_host *host = (struct nlm_host *) arg; 674 675 if (nlm_debug_level >= 1) 676 printf("NLM: client lock recovery for %s started\n", 677 host->nh_caller_name); 678 679 nlm_client_recovery(host); 680 681 if (nlm_debug_level >= 1) 682 printf("NLM: client lock recovery for %s completed\n", 683 host->nh_caller_name); 684 685 host->nh_monstate = NLM_MONITORED; 686 nlm_host_release(host); 687 688 kthread_exit(); 689 } 690 691 #endif 692 693 /* 694 * This is called when we receive a host state change notification. We 695 * unlock any active locks owned by the host. When rpc.lockd is 696 * shutting down, this function is called with newstate set to zero 697 * which allows us to cancel any pending async locks and clear the 698 * locking state. 699 */ 700 static void 701 nlm_host_notify(struct nlm_host *host, int newstate) 702 { 703 struct nlm_async_lock *af; 704 705 if (newstate) { 706 if (nlm_debug_level >= 1) 707 printf("NLM: host %s (sysid %d) rebooted, new " 708 "state is %d\n", 709 host->nh_caller_name, host->nh_sysid, newstate); 710 } 711 712 /* 713 * Cancel any pending async locks for this host. 714 */ 715 mtx_lock(&host->nh_lock); 716 while ((af = TAILQ_FIRST(&host->nh_pending)) != NULL) { 717 /* 718 * nlm_cancel_async_lock will remove the entry from 719 * nh_pending and free it. 720 */ 721 nlm_cancel_async_lock(af); 722 } 723 mtx_unlock(&host->nh_lock); 724 nlm_free_finished_locks(host); 725 726 /* 727 * The host just rebooted - trash its locks. 728 */ 729 lf_clearremotesys(host->nh_sysid); 730 host->nh_state = newstate; 731 732 #ifdef NFSCLIENT 733 /* 734 * If we have any remote locks for this host (i.e. it 735 * represents a remote NFS server that our local NFS client 736 * has locks for), start a recovery thread. 737 */ 738 if (newstate != 0 739 && host->nh_monstate != NLM_RECOVERING 740 && lf_countlocks(NLM_SYSID_CLIENT | host->nh_sysid) > 0) { 741 struct thread *td; 742 host->nh_monstate = NLM_RECOVERING; 743 refcount_acquire(&host->nh_refs); 744 kthread_add(nlm_client_recovery_start, host, curproc, &td, 0, 0, 745 "NFS lock recovery for %s", host->nh_caller_name); 746 } 747 #endif 748 } 749 750 /* 751 * Sysctl handler to count the number of locks for a sysid. 752 */ 753 static int 754 nlm_host_lock_count_sysctl(SYSCTL_HANDLER_ARGS) 755 { 756 struct nlm_host *host; 757 int count; 758 759 host = oidp->oid_arg1; 760 count = lf_countlocks(host->nh_sysid); 761 return sysctl_handle_int(oidp, &count, 0, req); 762 } 763 764 /* 765 * Sysctl handler to count the number of client locks for a sysid. 766 */ 767 static int 768 nlm_host_client_lock_count_sysctl(SYSCTL_HANDLER_ARGS) 769 { 770 struct nlm_host *host; 771 int count; 772 773 host = oidp->oid_arg1; 774 count = lf_countlocks(NLM_SYSID_CLIENT | host->nh_sysid); 775 return sysctl_handle_int(oidp, &count, 0, req); 776 } 777 778 /* 779 * Create a new NLM host. 780 */ 781 static struct nlm_host * 782 nlm_create_host(const char* caller_name) 783 { 784 struct nlm_host *host; 785 struct sysctl_oid *oid; 786 787 mtx_assert(&nlm_global_lock, MA_OWNED); 788 789 if (nlm_debug_level >= 1) 790 printf("NLM: new host %s (sysid %d)\n", 791 caller_name, nlm_next_sysid); 792 host = malloc(sizeof(struct nlm_host), M_NLM, M_NOWAIT|M_ZERO); 793 if (!host) 794 return (NULL); 795 mtx_init(&host->nh_lock, "nh_lock", NULL, MTX_DEF); 796 host->nh_refs = 1; 797 strlcpy(host->nh_caller_name, caller_name, MAXNAMELEN); 798 host->nh_sysid = nlm_next_sysid++; 799 snprintf(host->nh_sysid_string, sizeof(host->nh_sysid_string), 800 "%d", host->nh_sysid); 801 host->nh_vers = 0; 802 host->nh_state = 0; 803 host->nh_monstate = NLM_UNMONITORED; 804 TAILQ_INIT(&host->nh_pending); 805 TAILQ_INIT(&host->nh_finished); 806 TAILQ_INSERT_TAIL(&nlm_hosts, host, nh_link); 807 808 mtx_unlock(&nlm_global_lock); 809 810 sysctl_ctx_init(&host->nh_sysctl); 811 oid = SYSCTL_ADD_NODE(&host->nh_sysctl, 812 SYSCTL_STATIC_CHILDREN(_vfs_nlm_sysid), 813 OID_AUTO, host->nh_sysid_string, CTLFLAG_RD, NULL, ""); 814 SYSCTL_ADD_STRING(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO, 815 "hostname", CTLFLAG_RD, host->nh_caller_name, 0, ""); 816 SYSCTL_ADD_INT(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO, 817 "version", CTLFLAG_RD, &host->nh_vers, 0, ""); 818 SYSCTL_ADD_INT(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO, 819 "monitored", CTLFLAG_RD, &host->nh_monstate, 0, ""); 820 SYSCTL_ADD_PROC(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO, 821 "lock_count", CTLTYPE_INT | CTLFLAG_RD, host, 0, 822 nlm_host_lock_count_sysctl, "I", ""); 823 SYSCTL_ADD_PROC(&host->nh_sysctl, SYSCTL_CHILDREN(oid), OID_AUTO, 824 "client_lock_count", CTLTYPE_INT | CTLFLAG_RD, host, 0, 825 nlm_host_client_lock_count_sysctl, "I", ""); 826 827 mtx_lock(&nlm_global_lock); 828 829 return (host); 830 } 831 832 /* 833 * Return non-zero if the address parts of the two sockaddrs are the 834 * same. 835 */ 836 static int 837 nlm_compare_addr(const struct sockaddr *a, const struct sockaddr *b) 838 { 839 const struct sockaddr_in *a4, *b4; 840 #ifdef INET6 841 const struct sockaddr_in6 *a6, *b6; 842 #endif 843 844 if (a->sa_family != b->sa_family) 845 return (FALSE); 846 847 switch (a->sa_family) { 848 case AF_INET: 849 a4 = (const struct sockaddr_in *) a; 850 b4 = (const struct sockaddr_in *) b; 851 return !memcmp(&a4->sin_addr, &b4->sin_addr, 852 sizeof(a4->sin_addr)); 853 #ifdef INET6 854 case AF_INET6: 855 a6 = (const struct sockaddr_in6 *) a; 856 b6 = (const struct sockaddr_in6 *) b; 857 return !memcmp(&a6->sin6_addr, &b6->sin6_addr, 858 sizeof(a6->sin6_addr)); 859 #endif 860 } 861 862 return (0); 863 } 864 865 /* 866 * Check for idle hosts and stop monitoring them. We could also free 867 * the host structure here, possibly after a larger timeout but that 868 * would require some care to avoid races with 869 * e.g. nlm_host_lock_count_sysctl. 870 */ 871 static void 872 nlm_check_idle(void) 873 { 874 struct nlm_host *host; 875 876 mtx_assert(&nlm_global_lock, MA_OWNED); 877 878 if (time_uptime <= nlm_next_idle_check) 879 return; 880 881 nlm_next_idle_check = time_uptime + NLM_IDLE_PERIOD; 882 883 TAILQ_FOREACH(host, &nlm_hosts, nh_link) { 884 if (host->nh_monstate == NLM_MONITORED 885 && time_uptime > host->nh_idle_timeout) { 886 mtx_unlock(&nlm_global_lock); 887 if (lf_countlocks(host->nh_sysid) > 0 888 || lf_countlocks(NLM_SYSID_CLIENT 889 + host->nh_sysid)) { 890 host->nh_idle_timeout = 891 time_uptime + NLM_IDLE_TIMEOUT; 892 mtx_lock(&nlm_global_lock); 893 continue; 894 } 895 nlm_host_unmonitor(host); 896 mtx_lock(&nlm_global_lock); 897 } 898 } 899 } 900 901 /* 902 * Search for an existing NLM host that matches the given name 903 * (typically the caller_name element of an nlm4_lock). If none is 904 * found, create a new host. If 'addr' is non-NULL, record the remote 905 * address of the host so that we can call it back for async 906 * responses. If 'vers' is greater than zero then record the NLM 907 * program version to use to communicate with this client. 908 */ 909 struct nlm_host * 910 nlm_find_host_by_name(const char *name, const struct sockaddr *addr, 911 rpcvers_t vers) 912 { 913 struct nlm_host *host; 914 915 mtx_lock(&nlm_global_lock); 916 917 /* 918 * The remote host is determined by caller_name. 919 */ 920 TAILQ_FOREACH(host, &nlm_hosts, nh_link) { 921 if (!strcmp(host->nh_caller_name, name)) 922 break; 923 } 924 925 if (!host) { 926 host = nlm_create_host(name); 927 if (!host) { 928 mtx_unlock(&nlm_global_lock); 929 return (NULL); 930 } 931 } 932 refcount_acquire(&host->nh_refs); 933 934 host->nh_idle_timeout = time_uptime + NLM_IDLE_TIMEOUT; 935 936 /* 937 * If we have an address for the host, record it so that we 938 * can send async replies etc. 939 */ 940 if (addr) { 941 942 KASSERT(addr->sa_len < sizeof(struct sockaddr_storage), 943 ("Strange remote transport address length")); 944 945 /* 946 * If we have seen an address before and we currently 947 * have an RPC client handle, make sure the address is 948 * the same, otherwise discard the client handle. 949 */ 950 if (host->nh_addr.ss_len && host->nh_srvrpc.nr_client) { 951 if (!nlm_compare_addr( 952 (struct sockaddr *) &host->nh_addr, 953 addr) 954 || host->nh_vers != vers) { 955 CLIENT *client; 956 mtx_lock(&host->nh_lock); 957 client = host->nh_srvrpc.nr_client; 958 host->nh_srvrpc.nr_client = NULL; 959 mtx_unlock(&host->nh_lock); 960 if (client) { 961 CLNT_RELEASE(client); 962 } 963 } 964 } 965 memcpy(&host->nh_addr, addr, addr->sa_len); 966 host->nh_vers = vers; 967 } 968 969 nlm_check_idle(); 970 971 mtx_unlock(&nlm_global_lock); 972 973 return (host); 974 } 975 976 /* 977 * Search for an existing NLM host that matches the given remote 978 * address. If none is found, create a new host with the requested 979 * address and remember 'vers' as the NLM protocol version to use for 980 * that host. 981 */ 982 struct nlm_host * 983 nlm_find_host_by_addr(const struct sockaddr *addr, int vers) 984 { 985 /* 986 * Fake up a name using inet_ntop. This buffer is 987 * large enough for an IPv6 address. 988 */ 989 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; 990 struct nlm_host *host; 991 992 switch (addr->sa_family) { 993 case AF_INET: 994 __rpc_inet_ntop(AF_INET, 995 &((const struct sockaddr_in *) addr)->sin_addr, 996 tmp, sizeof tmp); 997 break; 998 #ifdef INET6 999 case AF_INET6: 1000 __rpc_inet_ntop(AF_INET6, 1001 &((const struct sockaddr_in6 *) addr)->sin6_addr, 1002 tmp, sizeof tmp); 1003 break; 1004 #endif 1005 default: 1006 strcmp(tmp, "<unknown>"); 1007 } 1008 1009 1010 mtx_lock(&nlm_global_lock); 1011 1012 /* 1013 * The remote host is determined by caller_name. 1014 */ 1015 TAILQ_FOREACH(host, &nlm_hosts, nh_link) { 1016 if (nlm_compare_addr(addr, 1017 (const struct sockaddr *) &host->nh_addr)) 1018 break; 1019 } 1020 1021 if (!host) { 1022 host = nlm_create_host(tmp); 1023 if (!host) { 1024 mtx_unlock(&nlm_global_lock); 1025 return (NULL); 1026 } 1027 memcpy(&host->nh_addr, addr, addr->sa_len); 1028 host->nh_vers = vers; 1029 } 1030 refcount_acquire(&host->nh_refs); 1031 1032 host->nh_idle_timeout = time_uptime + NLM_IDLE_TIMEOUT; 1033 1034 nlm_check_idle(); 1035 1036 mtx_unlock(&nlm_global_lock); 1037 1038 return (host); 1039 } 1040 1041 /* 1042 * Find the NLM host that matches the value of 'sysid'. If none 1043 * exists, return NULL. 1044 */ 1045 static struct nlm_host * 1046 nlm_find_host_by_sysid(int sysid) 1047 { 1048 struct nlm_host *host; 1049 1050 TAILQ_FOREACH(host, &nlm_hosts, nh_link) { 1051 if (host->nh_sysid == sysid) { 1052 refcount_acquire(&host->nh_refs); 1053 return (host); 1054 } 1055 } 1056 1057 return (NULL); 1058 } 1059 1060 void nlm_host_release(struct nlm_host *host) 1061 { 1062 if (refcount_release(&host->nh_refs)) { 1063 /* 1064 * Free the host 1065 */ 1066 nlm_host_destroy(host); 1067 } 1068 } 1069 1070 /* 1071 * Unregister this NLM host with the local NSM due to idleness. 1072 */ 1073 static void 1074 nlm_host_unmonitor(struct nlm_host *host) 1075 { 1076 mon_id smmonid; 1077 sm_stat_res smstat; 1078 struct timeval timo; 1079 enum clnt_stat stat; 1080 1081 if (nlm_debug_level >= 1) 1082 printf("NLM: unmonitoring %s (sysid %d)\n", 1083 host->nh_caller_name, host->nh_sysid); 1084 1085 /* 1086 * We put our assigned system ID value in the priv field to 1087 * make it simpler to find the host if we are notified of a 1088 * host restart. 1089 */ 1090 smmonid.mon_name = host->nh_caller_name; 1091 smmonid.my_id.my_name = "localhost"; 1092 smmonid.my_id.my_prog = NLM_PROG; 1093 smmonid.my_id.my_vers = NLM_SM; 1094 smmonid.my_id.my_proc = NLM_SM_NOTIFY; 1095 1096 timo.tv_sec = 25; 1097 timo.tv_usec = 0; 1098 stat = CLNT_CALL(nlm_nsm, SM_UNMON, 1099 (xdrproc_t) xdr_mon, &smmonid, 1100 (xdrproc_t) xdr_sm_stat, &smstat, timo); 1101 1102 if (stat != RPC_SUCCESS) { 1103 printf("Failed to contact local NSM - rpc error %d\n", stat); 1104 return; 1105 } 1106 if (smstat.res_stat == stat_fail) { 1107 printf("Local NSM refuses to unmonitor %s\n", 1108 host->nh_caller_name); 1109 return; 1110 } 1111 1112 host->nh_monstate = NLM_UNMONITORED; 1113 } 1114 1115 /* 1116 * Register this NLM host with the local NSM so that we can be 1117 * notified if it reboots. 1118 */ 1119 void 1120 nlm_host_monitor(struct nlm_host *host, int state) 1121 { 1122 mon smmon; 1123 sm_stat_res smstat; 1124 struct timeval timo; 1125 enum clnt_stat stat; 1126 1127 if (state && !host->nh_state) { 1128 /* 1129 * This is the first time we have seen an NSM state 1130 * value for this host. We record it here to help 1131 * detect host reboots. 1132 */ 1133 host->nh_state = state; 1134 if (nlm_debug_level >= 1) 1135 printf("NLM: host %s (sysid %d) has NSM state %d\n", 1136 host->nh_caller_name, host->nh_sysid, state); 1137 } 1138 1139 mtx_lock(&host->nh_lock); 1140 if (host->nh_monstate != NLM_UNMONITORED) { 1141 mtx_unlock(&host->nh_lock); 1142 return; 1143 } 1144 host->nh_monstate = NLM_MONITORED; 1145 mtx_unlock(&host->nh_lock); 1146 1147 if (nlm_debug_level >= 1) 1148 printf("NLM: monitoring %s (sysid %d)\n", 1149 host->nh_caller_name, host->nh_sysid); 1150 1151 /* 1152 * We put our assigned system ID value in the priv field to 1153 * make it simpler to find the host if we are notified of a 1154 * host restart. 1155 */ 1156 smmon.mon_id.mon_name = host->nh_caller_name; 1157 smmon.mon_id.my_id.my_name = "localhost"; 1158 smmon.mon_id.my_id.my_prog = NLM_PROG; 1159 smmon.mon_id.my_id.my_vers = NLM_SM; 1160 smmon.mon_id.my_id.my_proc = NLM_SM_NOTIFY; 1161 memcpy(smmon.priv, &host->nh_sysid, sizeof(host->nh_sysid)); 1162 1163 timo.tv_sec = 25; 1164 timo.tv_usec = 0; 1165 stat = CLNT_CALL(nlm_nsm, SM_MON, 1166 (xdrproc_t) xdr_mon, &smmon, 1167 (xdrproc_t) xdr_sm_stat, &smstat, timo); 1168 1169 if (stat != RPC_SUCCESS) { 1170 printf("Failed to contact local NSM - rpc error %d\n", stat); 1171 return; 1172 } 1173 if (smstat.res_stat == stat_fail) { 1174 printf("Local NSM refuses to monitor %s\n", 1175 host->nh_caller_name); 1176 mtx_lock(&host->nh_lock); 1177 host->nh_monstate = NLM_MONITOR_FAILED; 1178 mtx_unlock(&host->nh_lock); 1179 return; 1180 } 1181 1182 host->nh_monstate = NLM_MONITORED; 1183 } 1184 1185 /* 1186 * Return an RPC client handle that can be used to talk to the NLM 1187 * running on the given host. 1188 */ 1189 CLIENT * 1190 nlm_host_get_rpc(struct nlm_host *host, bool_t isserver) 1191 { 1192 struct nlm_rpc *rpc; 1193 CLIENT *client; 1194 1195 mtx_lock(&host->nh_lock); 1196 1197 if (isserver) 1198 rpc = &host->nh_srvrpc; 1199 else 1200 rpc = &host->nh_clntrpc; 1201 1202 /* 1203 * We can't hold onto RPC handles for too long - the async 1204 * call/reply protocol used by some NLM clients makes it hard 1205 * to tell when they change port numbers (e.g. after a 1206 * reboot). Note that if a client reboots while it isn't 1207 * holding any locks, it won't bother to notify us. We 1208 * expire the RPC handles after two minutes. 1209 */ 1210 if (rpc->nr_client && time_uptime > rpc->nr_create_time + 2*60) { 1211 client = rpc->nr_client; 1212 rpc->nr_client = NULL; 1213 mtx_unlock(&host->nh_lock); 1214 CLNT_RELEASE(client); 1215 mtx_lock(&host->nh_lock); 1216 } 1217 1218 if (!rpc->nr_client) { 1219 mtx_unlock(&host->nh_lock); 1220 client = nlm_get_rpc((struct sockaddr *)&host->nh_addr, 1221 NLM_PROG, host->nh_vers); 1222 mtx_lock(&host->nh_lock); 1223 1224 if (client) { 1225 if (rpc->nr_client) { 1226 mtx_unlock(&host->nh_lock); 1227 CLNT_DESTROY(client); 1228 mtx_lock(&host->nh_lock); 1229 } else { 1230 rpc->nr_client = client; 1231 rpc->nr_create_time = time_uptime; 1232 } 1233 } 1234 } 1235 1236 client = rpc->nr_client; 1237 if (client) 1238 CLNT_ACQUIRE(client); 1239 mtx_unlock(&host->nh_lock); 1240 1241 return (client); 1242 1243 } 1244 1245 int nlm_host_get_sysid(struct nlm_host *host) 1246 { 1247 1248 return (host->nh_sysid); 1249 } 1250 1251 int 1252 nlm_host_get_state(struct nlm_host *host) 1253 { 1254 1255 return (host->nh_state); 1256 } 1257 1258 void * 1259 nlm_register_wait_lock(struct nlm4_lock *lock, struct vnode *vp) 1260 { 1261 struct nlm_waiting_lock *nw; 1262 1263 nw = malloc(sizeof(struct nlm_waiting_lock), M_NLM, M_WAITOK); 1264 nw->nw_lock = *lock; 1265 memcpy(&nw->nw_fh.fh_bytes, nw->nw_lock.fh.n_bytes, 1266 nw->nw_lock.fh.n_len); 1267 nw->nw_lock.fh.n_bytes = nw->nw_fh.fh_bytes; 1268 nw->nw_waiting = TRUE; 1269 nw->nw_vp = vp; 1270 mtx_lock(&nlm_global_lock); 1271 TAILQ_INSERT_TAIL(&nlm_waiting_locks, nw, nw_link); 1272 mtx_unlock(&nlm_global_lock); 1273 1274 return nw; 1275 } 1276 1277 void 1278 nlm_deregister_wait_lock(void *handle) 1279 { 1280 struct nlm_waiting_lock *nw = handle; 1281 1282 mtx_lock(&nlm_global_lock); 1283 TAILQ_REMOVE(&nlm_waiting_locks, nw, nw_link); 1284 mtx_unlock(&nlm_global_lock); 1285 1286 free(nw, M_NLM); 1287 } 1288 1289 int 1290 nlm_wait_lock(void *handle, int timo) 1291 { 1292 struct nlm_waiting_lock *nw = handle; 1293 int error; 1294 1295 /* 1296 * If the granted message arrived before we got here, 1297 * nw->nw_waiting will be FALSE - in that case, don't sleep. 1298 */ 1299 mtx_lock(&nlm_global_lock); 1300 error = 0; 1301 if (nw->nw_waiting) 1302 error = msleep(nw, &nlm_global_lock, PCATCH, "nlmlock", timo); 1303 TAILQ_REMOVE(&nlm_waiting_locks, nw, nw_link); 1304 if (error) { 1305 /* 1306 * The granted message may arrive after the 1307 * interrupt/timeout but before we manage to lock the 1308 * mutex. Detect this by examining nw_lock. 1309 */ 1310 if (!nw->nw_waiting) 1311 error = 0; 1312 } else { 1313 /* 1314 * If nlm_cancel_wait is called, then error will be 1315 * zero but nw_waiting will still be TRUE. We 1316 * translate this into EINTR. 1317 */ 1318 if (nw->nw_waiting) 1319 error = EINTR; 1320 } 1321 mtx_unlock(&nlm_global_lock); 1322 1323 free(nw, M_NLM); 1324 1325 return (error); 1326 } 1327 1328 void 1329 nlm_cancel_wait(struct vnode *vp) 1330 { 1331 struct nlm_waiting_lock *nw; 1332 1333 mtx_lock(&nlm_global_lock); 1334 TAILQ_FOREACH(nw, &nlm_waiting_locks, nw_link) { 1335 if (nw->nw_vp == vp) { 1336 wakeup(nw); 1337 } 1338 } 1339 mtx_unlock(&nlm_global_lock); 1340 } 1341 1342 1343 /**********************************************************************/ 1344 1345 /* 1346 * Syscall interface with userland. 1347 */ 1348 1349 extern void nlm_prog_0(struct svc_req *rqstp, SVCXPRT *transp); 1350 extern void nlm_prog_1(struct svc_req *rqstp, SVCXPRT *transp); 1351 extern void nlm_prog_3(struct svc_req *rqstp, SVCXPRT *transp); 1352 extern void nlm_prog_4(struct svc_req *rqstp, SVCXPRT *transp); 1353 1354 static int 1355 nlm_register_services(SVCPOOL *pool, int addr_count, char **addrs) 1356 { 1357 static rpcvers_t versions[] = { 1358 NLM_SM, NLM_VERS, NLM_VERSX, NLM_VERS4 1359 }; 1360 static void (*dispatchers[])(struct svc_req *, SVCXPRT *) = { 1361 nlm_prog_0, nlm_prog_1, nlm_prog_3, nlm_prog_4 1362 }; 1363 static const int version_count = sizeof(versions) / sizeof(versions[0]); 1364 1365 SVCXPRT **xprts; 1366 char netid[16]; 1367 char uaddr[128]; 1368 struct netconfig *nconf; 1369 int i, j, error; 1370 1371 if (!addr_count) { 1372 printf("NLM: no service addresses given - can't start server"); 1373 return (EINVAL); 1374 } 1375 1376 xprts = malloc(addr_count * sizeof(SVCXPRT *), M_NLM, M_WAITOK); 1377 for (i = 0; i < version_count; i++) { 1378 for (j = 0; j < addr_count; j++) { 1379 /* 1380 * Create transports for the first version and 1381 * then just register everything else to the 1382 * same transports. 1383 */ 1384 if (i == 0) { 1385 char *up; 1386 1387 error = copyin(&addrs[2*j], &up, 1388 sizeof(char*)); 1389 if (error) 1390 goto out; 1391 error = copyinstr(up, netid, sizeof(netid), 1392 NULL); 1393 if (error) 1394 goto out; 1395 error = copyin(&addrs[2*j+1], &up, 1396 sizeof(char*)); 1397 if (error) 1398 goto out; 1399 error = copyinstr(up, uaddr, sizeof(uaddr), 1400 NULL); 1401 if (error) 1402 goto out; 1403 nconf = getnetconfigent(netid); 1404 if (!nconf) { 1405 printf("Can't lookup netid %s\n", 1406 netid); 1407 error = EINVAL; 1408 goto out; 1409 } 1410 xprts[j] = svc_tp_create(pool, dispatchers[i], 1411 NLM_PROG, versions[i], uaddr, nconf); 1412 if (!xprts[j]) { 1413 printf("NLM: unable to create " 1414 "(NLM_PROG, %d).\n", versions[i]); 1415 error = EINVAL; 1416 goto out; 1417 } 1418 freenetconfigent(nconf); 1419 } else { 1420 nconf = getnetconfigent(xprts[j]->xp_netid); 1421 rpcb_unset(NLM_PROG, versions[i], nconf); 1422 if (!svc_reg(xprts[j], NLM_PROG, versions[i], 1423 dispatchers[i], nconf)) { 1424 printf("NLM: can't register " 1425 "(NLM_PROG, %d)\n", versions[i]); 1426 error = EINVAL; 1427 goto out; 1428 } 1429 } 1430 } 1431 } 1432 error = 0; 1433 out: 1434 free(xprts, M_NLM); 1435 return (error); 1436 } 1437 1438 /* 1439 * Main server entry point. Contacts the local NSM to get its current 1440 * state and send SM_UNMON_ALL. Registers the NLM services and then 1441 * services requests. Does not return until the server is interrupted 1442 * by a signal. 1443 */ 1444 static int 1445 nlm_server_main(int addr_count, char **addrs) 1446 { 1447 struct thread *td = curthread; 1448 int error; 1449 SVCPOOL *pool = NULL; 1450 struct sockopt opt; 1451 int portlow; 1452 #ifdef INET6 1453 struct sockaddr_in6 sin6; 1454 #endif 1455 struct sockaddr_in sin; 1456 my_id id; 1457 sm_stat smstat; 1458 struct timeval timo; 1459 enum clnt_stat stat; 1460 struct nlm_host *host, *nhost; 1461 struct nlm_waiting_lock *nw; 1462 #ifdef NFSCLIENT 1463 vop_advlock_t *old_nfs_advlock; 1464 vop_reclaim_t *old_nfs_reclaim; 1465 #endif 1466 int v4_used; 1467 #ifdef INET6 1468 int v6_used; 1469 #endif 1470 1471 if (nlm_socket) { 1472 printf("NLM: can't start server - it appears to be running already\n"); 1473 return (EPERM); 1474 } 1475 1476 memset(&opt, 0, sizeof(opt)); 1477 1478 nlm_socket = NULL; 1479 error = socreate(AF_INET, &nlm_socket, SOCK_DGRAM, 0, 1480 td->td_ucred, td); 1481 if (error) { 1482 printf("NLM: can't create IPv4 socket - error %d\n", error); 1483 return (error); 1484 } 1485 opt.sopt_dir = SOPT_SET; 1486 opt.sopt_level = IPPROTO_IP; 1487 opt.sopt_name = IP_PORTRANGE; 1488 portlow = IP_PORTRANGE_LOW; 1489 opt.sopt_val = &portlow; 1490 opt.sopt_valsize = sizeof(portlow); 1491 sosetopt(nlm_socket, &opt); 1492 1493 #ifdef INET6 1494 nlm_socket6 = NULL; 1495 error = socreate(AF_INET6, &nlm_socket6, SOCK_DGRAM, 0, 1496 td->td_ucred, td); 1497 if (error) { 1498 printf("NLM: can't create IPv6 socket - error %d\n", error); 1499 goto out; 1500 return (error); 1501 } 1502 opt.sopt_dir = SOPT_SET; 1503 opt.sopt_level = IPPROTO_IPV6; 1504 opt.sopt_name = IPV6_PORTRANGE; 1505 portlow = IPV6_PORTRANGE_LOW; 1506 opt.sopt_val = &portlow; 1507 opt.sopt_valsize = sizeof(portlow); 1508 sosetopt(nlm_socket6, &opt); 1509 #endif 1510 1511 nlm_auth = authunix_create(curthread->td_ucred); 1512 1513 #ifdef INET6 1514 memset(&sin6, 0, sizeof(sin6)); 1515 sin6.sin6_len = sizeof(sin6); 1516 sin6.sin6_family = AF_INET6; 1517 sin6.sin6_addr = in6addr_loopback; 1518 nlm_nsm = nlm_get_rpc((struct sockaddr *) &sin6, SM_PROG, SM_VERS); 1519 if (!nlm_nsm) { 1520 #endif 1521 memset(&sin, 0, sizeof(sin)); 1522 sin.sin_len = sizeof(sin); 1523 sin.sin_family = AF_INET; 1524 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1525 nlm_nsm = nlm_get_rpc((struct sockaddr *) &sin, SM_PROG, 1526 SM_VERS); 1527 #ifdef INET6 1528 } 1529 #endif 1530 1531 if (!nlm_nsm) { 1532 printf("Can't start NLM - unable to contact NSM\n"); 1533 error = EINVAL; 1534 goto out; 1535 } 1536 1537 pool = svcpool_create("NLM", NULL); 1538 1539 error = nlm_register_services(pool, addr_count, addrs); 1540 if (error) 1541 goto out; 1542 1543 memset(&id, 0, sizeof(id)); 1544 id.my_name = "NFS NLM"; 1545 1546 timo.tv_sec = 25; 1547 timo.tv_usec = 0; 1548 stat = CLNT_CALL(nlm_nsm, SM_UNMON_ALL, 1549 (xdrproc_t) xdr_my_id, &id, 1550 (xdrproc_t) xdr_sm_stat, &smstat, timo); 1551 1552 if (stat != RPC_SUCCESS) { 1553 struct rpc_err err; 1554 1555 CLNT_GETERR(nlm_nsm, &err); 1556 printf("NLM: unexpected error contacting NSM, stat=%d, errno=%d\n", 1557 stat, err.re_errno); 1558 error = EINVAL; 1559 goto out; 1560 } 1561 1562 if (nlm_debug_level >= 1) 1563 printf("NLM: local NSM state is %d\n", smstat.state); 1564 nlm_nsm_state = smstat.state; 1565 1566 #ifdef NFSCLIENT 1567 old_nfs_advlock = nfs_advlock_p; 1568 nfs_advlock_p = nlm_advlock; 1569 old_nfs_reclaim = nfs_reclaim_p; 1570 nfs_reclaim_p = nlm_reclaim; 1571 #endif 1572 1573 svc_run(pool); 1574 error = 0; 1575 1576 #ifdef NFSCLIENT 1577 nfs_advlock_p = old_nfs_advlock; 1578 nfs_reclaim_p = old_nfs_reclaim; 1579 #endif 1580 1581 out: 1582 if (pool) 1583 svcpool_destroy(pool); 1584 1585 /* 1586 * We are finished communicating with the NSM. 1587 */ 1588 if (nlm_nsm) { 1589 CLNT_RELEASE(nlm_nsm); 1590 nlm_nsm = NULL; 1591 } 1592 1593 /* 1594 * Trash all the existing state so that if the server 1595 * restarts, it gets a clean slate. This is complicated by the 1596 * possibility that there may be other threads trying to make 1597 * client locking requests. 1598 * 1599 * First we fake a client reboot notification which will 1600 * cancel any pending async locks and purge remote lock state 1601 * from the local lock manager. We release the reference from 1602 * nlm_hosts to the host (which may remove it from the list 1603 * and free it). After this phase, the only entries in the 1604 * nlm_host list should be from other threads performing 1605 * client lock requests. We arrange to defer closing the 1606 * sockets until the last RPC client handle is released. 1607 */ 1608 v4_used = 0; 1609 #ifdef INET6 1610 v6_used = 0; 1611 #endif 1612 mtx_lock(&nlm_global_lock); 1613 TAILQ_FOREACH(nw, &nlm_waiting_locks, nw_link) { 1614 wakeup(nw); 1615 } 1616 TAILQ_FOREACH_SAFE(host, &nlm_hosts, nh_link, nhost) { 1617 mtx_unlock(&nlm_global_lock); 1618 nlm_host_notify(host, 0); 1619 nlm_host_release(host); 1620 mtx_lock(&nlm_global_lock); 1621 } 1622 TAILQ_FOREACH_SAFE(host, &nlm_hosts, nh_link, nhost) { 1623 mtx_lock(&host->nh_lock); 1624 if (host->nh_srvrpc.nr_client 1625 || host->nh_clntrpc.nr_client) { 1626 if (host->nh_addr.ss_family == AF_INET) 1627 v4_used++; 1628 #ifdef INET6 1629 if (host->nh_addr.ss_family == AF_INET6) 1630 v6_used++; 1631 #endif 1632 /* 1633 * Note that the rpc over udp code copes 1634 * correctly with the fact that a socket may 1635 * be used by many rpc handles. 1636 */ 1637 if (host->nh_srvrpc.nr_client) 1638 CLNT_CONTROL(host->nh_srvrpc.nr_client, 1639 CLSET_FD_CLOSE, 0); 1640 if (host->nh_clntrpc.nr_client) 1641 CLNT_CONTROL(host->nh_clntrpc.nr_client, 1642 CLSET_FD_CLOSE, 0); 1643 } 1644 mtx_unlock(&host->nh_lock); 1645 } 1646 mtx_unlock(&nlm_global_lock); 1647 1648 AUTH_DESTROY(nlm_auth); 1649 1650 if (!v4_used) 1651 soclose(nlm_socket); 1652 nlm_socket = NULL; 1653 #ifdef INET6 1654 if (!v6_used) 1655 soclose(nlm_socket6); 1656 nlm_socket6 = NULL; 1657 #endif 1658 1659 return (error); 1660 } 1661 1662 int 1663 nlm_syscall(struct thread *td, struct nlm_syscall_args *uap) 1664 { 1665 int error; 1666 1667 #if __FreeBSD_version >= 700000 1668 error = priv_check(td, PRIV_NFS_LOCKD); 1669 #else 1670 error = suser(td); 1671 #endif 1672 if (error) 1673 return (error); 1674 1675 nlm_debug_level = uap->debug_level; 1676 nlm_grace_threshold = time_uptime + uap->grace_period; 1677 nlm_next_idle_check = time_uptime + NLM_IDLE_PERIOD; 1678 1679 return nlm_server_main(uap->addr_count, uap->addrs); 1680 } 1681 1682 /**********************************************************************/ 1683 1684 /* 1685 * NLM implementation details, called from the RPC stubs. 1686 */ 1687 1688 1689 void 1690 nlm_sm_notify(struct nlm_sm_status *argp) 1691 { 1692 uint32_t sysid; 1693 struct nlm_host *host; 1694 1695 if (nlm_debug_level >= 3) 1696 printf("nlm_sm_notify(): mon_name = %s\n", argp->mon_name); 1697 memcpy(&sysid, &argp->priv, sizeof(sysid)); 1698 host = nlm_find_host_by_sysid(sysid); 1699 if (host) { 1700 nlm_host_notify(host, argp->state); 1701 nlm_host_release(host); 1702 } 1703 } 1704 1705 static void 1706 nlm_convert_to_fhandle_t(fhandle_t *fhp, struct netobj *p) 1707 { 1708 memcpy(fhp, p->n_bytes, sizeof(fhandle_t)); 1709 } 1710 1711 struct vfs_state { 1712 struct mount *vs_mp; 1713 struct vnode *vs_vp; 1714 int vs_vfslocked; 1715 int vs_vnlocked; 1716 }; 1717 1718 static int 1719 nlm_get_vfs_state(struct nlm_host *host, struct svc_req *rqstp, 1720 fhandle_t *fhp, struct vfs_state *vs) 1721 { 1722 int error, exflags; 1723 struct ucred *cred = NULL, *credanon; 1724 1725 memset(vs, 0, sizeof(*vs)); 1726 1727 vs->vs_mp = vfs_getvfs(&fhp->fh_fsid); 1728 if (!vs->vs_mp) { 1729 return (ESTALE); 1730 } 1731 vs->vs_vfslocked = VFS_LOCK_GIANT(vs->vs_mp); 1732 1733 error = VFS_CHECKEXP(vs->vs_mp, (struct sockaddr *)&host->nh_addr, 1734 &exflags, &credanon, NULL, NULL); 1735 if (error) 1736 goto out; 1737 1738 if (exflags & MNT_EXRDONLY || (vs->vs_mp->mnt_flag & MNT_RDONLY)) { 1739 error = EROFS; 1740 goto out; 1741 } 1742 1743 error = VFS_FHTOVP(vs->vs_mp, &fhp->fh_fid, &vs->vs_vp); 1744 if (error) 1745 goto out; 1746 vs->vs_vnlocked = TRUE; 1747 1748 if (!svc_getcred(rqstp, &cred, NULL)) { 1749 error = EINVAL; 1750 goto out; 1751 } 1752 if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { 1753 crfree(cred); 1754 cred = crhold(credanon); 1755 } 1756 1757 /* 1758 * Check cred. 1759 */ 1760 error = VOP_ACCESS(vs->vs_vp, VWRITE, cred, curthread); 1761 if (error) 1762 goto out; 1763 1764 #if __FreeBSD_version < 800011 1765 VOP_UNLOCK(vs->vs_vp, 0, curthread); 1766 #else 1767 VOP_UNLOCK(vs->vs_vp, 0); 1768 #endif 1769 vs->vs_vnlocked = FALSE; 1770 1771 out: 1772 if (cred) 1773 crfree(cred); 1774 1775 return (error); 1776 } 1777 1778 static void 1779 nlm_release_vfs_state(struct vfs_state *vs) 1780 { 1781 1782 if (vs->vs_vp) { 1783 if (vs->vs_vnlocked) 1784 vput(vs->vs_vp); 1785 else 1786 vrele(vs->vs_vp); 1787 } 1788 if (vs->vs_mp) 1789 vfs_rel(vs->vs_mp); 1790 VFS_UNLOCK_GIANT(vs->vs_vfslocked); 1791 } 1792 1793 static nlm4_stats 1794 nlm_convert_error(int error) 1795 { 1796 1797 if (error == ESTALE) 1798 return nlm4_stale_fh; 1799 else if (error == EROFS) 1800 return nlm4_rofs; 1801 else 1802 return nlm4_failed; 1803 } 1804 1805 int 1806 nlm_do_test(nlm4_testargs *argp, nlm4_testres *result, struct svc_req *rqstp, 1807 CLIENT **rpcp) 1808 { 1809 fhandle_t fh; 1810 struct vfs_state vs; 1811 struct nlm_host *host, *bhost; 1812 int error, sysid; 1813 struct flock fl; 1814 1815 memset(result, 0, sizeof(*result)); 1816 memset(&vs, 0, sizeof(vs)); 1817 1818 host = nlm_find_host_by_name(argp->alock.caller_name, 1819 svc_getrpccaller(rqstp), rqstp->rq_vers); 1820 if (!host) { 1821 result->stat.stat = nlm4_denied_nolocks; 1822 return (ENOMEM); 1823 } 1824 1825 if (nlm_debug_level >= 3) 1826 printf("nlm_do_test(): caller_name = %s (sysid = %d)\n", 1827 host->nh_caller_name, host->nh_sysid); 1828 1829 nlm_free_finished_locks(host); 1830 sysid = host->nh_sysid; 1831 1832 nlm_convert_to_fhandle_t(&fh, &argp->alock.fh); 1833 nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC); 1834 1835 if (time_uptime < nlm_grace_threshold) { 1836 result->stat.stat = nlm4_denied_grace_period; 1837 goto out; 1838 } 1839 1840 error = nlm_get_vfs_state(host, rqstp, &fh, &vs); 1841 if (error) { 1842 result->stat.stat = nlm_convert_error(error); 1843 goto out; 1844 } 1845 1846 fl.l_start = argp->alock.l_offset; 1847 fl.l_len = argp->alock.l_len; 1848 fl.l_pid = argp->alock.svid; 1849 fl.l_sysid = sysid; 1850 fl.l_whence = SEEK_SET; 1851 if (argp->exclusive) 1852 fl.l_type = F_WRLCK; 1853 else 1854 fl.l_type = F_RDLCK; 1855 error = VOP_ADVLOCK(vs.vs_vp, NULL, F_GETLK, &fl, F_REMOTE); 1856 if (error) { 1857 result->stat.stat = nlm4_failed; 1858 goto out; 1859 } 1860 1861 if (fl.l_type == F_UNLCK) { 1862 result->stat.stat = nlm4_granted; 1863 } else { 1864 result->stat.stat = nlm4_denied; 1865 result->stat.nlm4_testrply_u.holder.exclusive = 1866 (fl.l_type == F_WRLCK); 1867 result->stat.nlm4_testrply_u.holder.svid = fl.l_pid; 1868 bhost = nlm_find_host_by_sysid(fl.l_sysid); 1869 if (bhost) { 1870 /* 1871 * We don't have any useful way of recording 1872 * the value of oh used in the original lock 1873 * request. Ideally, the test reply would have 1874 * a space for the owning host's name allowing 1875 * our caller's NLM to keep track. 1876 * 1877 * As far as I can see, Solaris uses an eight 1878 * byte structure for oh which contains a four 1879 * byte pid encoded in local byte order and 1880 * the first four bytes of the host 1881 * name. Linux uses a variable length string 1882 * 'pid@hostname' in ascii but doesn't even 1883 * return that in test replies. 1884 * 1885 * For the moment, return nothing in oh 1886 * (already zero'ed above). 1887 */ 1888 nlm_host_release(bhost); 1889 } 1890 result->stat.nlm4_testrply_u.holder.l_offset = fl.l_start; 1891 result->stat.nlm4_testrply_u.holder.l_len = fl.l_len; 1892 } 1893 1894 out: 1895 nlm_release_vfs_state(&vs); 1896 if (rpcp) 1897 *rpcp = nlm_host_get_rpc(host, TRUE); 1898 nlm_host_release(host); 1899 return (0); 1900 } 1901 1902 int 1903 nlm_do_lock(nlm4_lockargs *argp, nlm4_res *result, struct svc_req *rqstp, 1904 bool_t monitor, CLIENT **rpcp) 1905 { 1906 fhandle_t fh; 1907 struct vfs_state vs; 1908 struct nlm_host *host; 1909 int error, sysid; 1910 struct flock fl; 1911 1912 memset(result, 0, sizeof(*result)); 1913 memset(&vs, 0, sizeof(vs)); 1914 1915 host = nlm_find_host_by_name(argp->alock.caller_name, 1916 svc_getrpccaller(rqstp), rqstp->rq_vers); 1917 if (!host) { 1918 result->stat.stat = nlm4_denied_nolocks; 1919 return (ENOMEM); 1920 } 1921 1922 if (nlm_debug_level >= 3) 1923 printf("nlm_do_lock(): caller_name = %s (sysid = %d)\n", 1924 host->nh_caller_name, host->nh_sysid); 1925 1926 if (monitor && host->nh_state && argp->state 1927 && host->nh_state != argp->state) { 1928 /* 1929 * The host rebooted without telling us. Trash its 1930 * locks. 1931 */ 1932 nlm_host_notify(host, argp->state); 1933 } 1934 1935 nlm_free_finished_locks(host); 1936 sysid = host->nh_sysid; 1937 1938 nlm_convert_to_fhandle_t(&fh, &argp->alock.fh); 1939 nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC); 1940 1941 if (time_uptime < nlm_grace_threshold && !argp->reclaim) { 1942 result->stat.stat = nlm4_denied_grace_period; 1943 goto out; 1944 } 1945 1946 error = nlm_get_vfs_state(host, rqstp, &fh, &vs); 1947 if (error) { 1948 result->stat.stat = nlm_convert_error(error); 1949 goto out; 1950 } 1951 1952 fl.l_start = argp->alock.l_offset; 1953 fl.l_len = argp->alock.l_len; 1954 fl.l_pid = argp->alock.svid; 1955 fl.l_sysid = sysid; 1956 fl.l_whence = SEEK_SET; 1957 if (argp->exclusive) 1958 fl.l_type = F_WRLCK; 1959 else 1960 fl.l_type = F_RDLCK; 1961 if (argp->block) { 1962 struct nlm_async_lock *af; 1963 CLIENT *client; 1964 1965 /* 1966 * First, make sure we can contact the host's NLM. 1967 */ 1968 client = nlm_host_get_rpc(host, TRUE); 1969 if (!client) { 1970 result->stat.stat = nlm4_failed; 1971 goto out; 1972 } 1973 1974 /* 1975 * First we need to check and see if there is an 1976 * existing blocked lock that matches. This could be a 1977 * badly behaved client or an RPC re-send. If we find 1978 * one, just return nlm4_blocked. 1979 */ 1980 mtx_lock(&host->nh_lock); 1981 TAILQ_FOREACH(af, &host->nh_pending, af_link) { 1982 if (af->af_fl.l_start == fl.l_start 1983 && af->af_fl.l_len == fl.l_len 1984 && af->af_fl.l_pid == fl.l_pid 1985 && af->af_fl.l_type == fl.l_type) { 1986 break; 1987 } 1988 } 1989 mtx_unlock(&host->nh_lock); 1990 if (af) { 1991 CLNT_RELEASE(client); 1992 result->stat.stat = nlm4_blocked; 1993 goto out; 1994 } 1995 1996 af = malloc(sizeof(struct nlm_async_lock), M_NLM, 1997 M_WAITOK|M_ZERO); 1998 TASK_INIT(&af->af_task, 0, nlm_lock_callback, af); 1999 af->af_vp = vs.vs_vp; 2000 af->af_fl = fl; 2001 af->af_host = host; 2002 af->af_rpc = client; 2003 /* 2004 * We use M_RPC here so that we can xdr_free the thing 2005 * later. 2006 */ 2007 af->af_granted.exclusive = argp->exclusive; 2008 af->af_granted.alock.caller_name = 2009 strdup(argp->alock.caller_name, M_RPC); 2010 nlm_copy_netobj(&af->af_granted.alock.fh, 2011 &argp->alock.fh, M_RPC); 2012 nlm_copy_netobj(&af->af_granted.alock.oh, 2013 &argp->alock.oh, M_RPC); 2014 af->af_granted.alock.svid = argp->alock.svid; 2015 af->af_granted.alock.l_offset = argp->alock.l_offset; 2016 af->af_granted.alock.l_len = argp->alock.l_len; 2017 2018 /* 2019 * Put the entry on the pending list before calling 2020 * VOP_ADVLOCKASYNC. We do this in case the lock 2021 * request was blocked (returning EINPROGRESS) but 2022 * then granted before we manage to run again. The 2023 * client may receive the granted message before we 2024 * send our blocked reply but thats their problem. 2025 */ 2026 mtx_lock(&host->nh_lock); 2027 TAILQ_INSERT_TAIL(&host->nh_pending, af, af_link); 2028 mtx_unlock(&host->nh_lock); 2029 2030 error = VOP_ADVLOCKASYNC(vs.vs_vp, NULL, F_SETLK, &fl, F_REMOTE, 2031 &af->af_task, &af->af_cookie); 2032 2033 /* 2034 * If the lock completed synchronously, just free the 2035 * tracking structure now. 2036 */ 2037 if (error != EINPROGRESS) { 2038 CLNT_RELEASE(af->af_rpc); 2039 mtx_lock(&host->nh_lock); 2040 TAILQ_REMOVE(&host->nh_pending, af, af_link); 2041 mtx_unlock(&host->nh_lock); 2042 xdr_free((xdrproc_t) xdr_nlm4_testargs, 2043 &af->af_granted); 2044 free(af, M_NLM); 2045 } else { 2046 if (nlm_debug_level >= 2) 2047 printf("NLM: pending async lock %p for %s " 2048 "(sysid %d)\n", 2049 af, host->nh_caller_name, sysid); 2050 /* 2051 * Don't vrele the vnode just yet - this must 2052 * wait until either the async callback 2053 * happens or the lock is cancelled. 2054 */ 2055 vs.vs_vp = NULL; 2056 } 2057 } else { 2058 error = VOP_ADVLOCK(vs.vs_vp, NULL, F_SETLK, &fl, F_REMOTE); 2059 } 2060 2061 if (error) { 2062 if (error == EINPROGRESS) { 2063 result->stat.stat = nlm4_blocked; 2064 } else if (error == EDEADLK) { 2065 result->stat.stat = nlm4_deadlck; 2066 } else if (error == EAGAIN) { 2067 result->stat.stat = nlm4_denied; 2068 } else { 2069 result->stat.stat = nlm4_failed; 2070 } 2071 } else { 2072 if (monitor) 2073 nlm_host_monitor(host, argp->state); 2074 result->stat.stat = nlm4_granted; 2075 } 2076 2077 out: 2078 nlm_release_vfs_state(&vs); 2079 if (rpcp) 2080 *rpcp = nlm_host_get_rpc(host, TRUE); 2081 nlm_host_release(host); 2082 return (0); 2083 } 2084 2085 int 2086 nlm_do_cancel(nlm4_cancargs *argp, nlm4_res *result, struct svc_req *rqstp, 2087 CLIENT **rpcp) 2088 { 2089 fhandle_t fh; 2090 struct vfs_state vs; 2091 struct nlm_host *host; 2092 int error, sysid; 2093 struct flock fl; 2094 struct nlm_async_lock *af; 2095 2096 memset(result, 0, sizeof(*result)); 2097 memset(&vs, 0, sizeof(vs)); 2098 2099 host = nlm_find_host_by_name(argp->alock.caller_name, 2100 svc_getrpccaller(rqstp), rqstp->rq_vers); 2101 if (!host) { 2102 result->stat.stat = nlm4_denied_nolocks; 2103 return (ENOMEM); 2104 } 2105 2106 if (nlm_debug_level >= 3) 2107 printf("nlm_do_cancel(): caller_name = %s (sysid = %d)\n", 2108 host->nh_caller_name, host->nh_sysid); 2109 2110 nlm_free_finished_locks(host); 2111 sysid = host->nh_sysid; 2112 2113 nlm_convert_to_fhandle_t(&fh, &argp->alock.fh); 2114 nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC); 2115 2116 if (time_uptime < nlm_grace_threshold) { 2117 result->stat.stat = nlm4_denied_grace_period; 2118 goto out; 2119 } 2120 2121 error = nlm_get_vfs_state(host, rqstp, &fh, &vs); 2122 if (error) { 2123 result->stat.stat = nlm_convert_error(error); 2124 goto out; 2125 } 2126 2127 fl.l_start = argp->alock.l_offset; 2128 fl.l_len = argp->alock.l_len; 2129 fl.l_pid = argp->alock.svid; 2130 fl.l_sysid = sysid; 2131 fl.l_whence = SEEK_SET; 2132 if (argp->exclusive) 2133 fl.l_type = F_WRLCK; 2134 else 2135 fl.l_type = F_RDLCK; 2136 2137 /* 2138 * First we need to try and find the async lock request - if 2139 * there isn't one, we give up and return nlm4_denied. 2140 */ 2141 mtx_lock(&host->nh_lock); 2142 2143 TAILQ_FOREACH(af, &host->nh_pending, af_link) { 2144 if (af->af_fl.l_start == fl.l_start 2145 && af->af_fl.l_len == fl.l_len 2146 && af->af_fl.l_pid == fl.l_pid 2147 && af->af_fl.l_type == fl.l_type) { 2148 break; 2149 } 2150 } 2151 2152 if (!af) { 2153 mtx_unlock(&host->nh_lock); 2154 result->stat.stat = nlm4_denied; 2155 goto out; 2156 } 2157 2158 error = nlm_cancel_async_lock(af); 2159 2160 if (error) { 2161 result->stat.stat = nlm4_denied; 2162 } else { 2163 result->stat.stat = nlm4_granted; 2164 } 2165 2166 mtx_unlock(&host->nh_lock); 2167 2168 out: 2169 nlm_release_vfs_state(&vs); 2170 if (rpcp) 2171 *rpcp = nlm_host_get_rpc(host, TRUE); 2172 nlm_host_release(host); 2173 return (0); 2174 } 2175 2176 int 2177 nlm_do_unlock(nlm4_unlockargs *argp, nlm4_res *result, struct svc_req *rqstp, 2178 CLIENT **rpcp) 2179 { 2180 fhandle_t fh; 2181 struct vfs_state vs; 2182 struct nlm_host *host; 2183 int error, sysid; 2184 struct flock fl; 2185 2186 memset(result, 0, sizeof(*result)); 2187 memset(&vs, 0, sizeof(vs)); 2188 2189 host = nlm_find_host_by_name(argp->alock.caller_name, 2190 svc_getrpccaller(rqstp), rqstp->rq_vers); 2191 if (!host) { 2192 result->stat.stat = nlm4_denied_nolocks; 2193 return (ENOMEM); 2194 } 2195 2196 if (nlm_debug_level >= 3) 2197 printf("nlm_do_unlock(): caller_name = %s (sysid = %d)\n", 2198 host->nh_caller_name, host->nh_sysid); 2199 2200 nlm_free_finished_locks(host); 2201 sysid = host->nh_sysid; 2202 2203 nlm_convert_to_fhandle_t(&fh, &argp->alock.fh); 2204 nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC); 2205 2206 if (time_uptime < nlm_grace_threshold) { 2207 result->stat.stat = nlm4_denied_grace_period; 2208 goto out; 2209 } 2210 2211 error = nlm_get_vfs_state(host, rqstp, &fh, &vs); 2212 if (error) { 2213 result->stat.stat = nlm_convert_error(error); 2214 goto out; 2215 } 2216 2217 fl.l_start = argp->alock.l_offset; 2218 fl.l_len = argp->alock.l_len; 2219 fl.l_pid = argp->alock.svid; 2220 fl.l_sysid = sysid; 2221 fl.l_whence = SEEK_SET; 2222 fl.l_type = F_UNLCK; 2223 error = VOP_ADVLOCK(vs.vs_vp, NULL, F_UNLCK, &fl, F_REMOTE); 2224 2225 /* 2226 * Ignore the error - there is no result code for failure, 2227 * only for grace period. 2228 */ 2229 result->stat.stat = nlm4_granted; 2230 2231 out: 2232 nlm_release_vfs_state(&vs); 2233 if (rpcp) 2234 *rpcp = nlm_host_get_rpc(host, TRUE); 2235 nlm_host_release(host); 2236 return (0); 2237 } 2238 2239 int 2240 nlm_do_granted(nlm4_testargs *argp, nlm4_res *result, struct svc_req *rqstp, 2241 2242 CLIENT **rpcp) 2243 { 2244 struct nlm_host *host; 2245 struct nlm_waiting_lock *nw; 2246 2247 memset(result, 0, sizeof(*result)); 2248 2249 host = nlm_find_host_by_addr(svc_getrpccaller(rqstp), rqstp->rq_vers); 2250 if (!host) { 2251 result->stat.stat = nlm4_denied_nolocks; 2252 return (ENOMEM); 2253 } 2254 2255 nlm_copy_netobj(&result->cookie, &argp->cookie, M_RPC); 2256 result->stat.stat = nlm4_denied; 2257 2258 mtx_lock(&nlm_global_lock); 2259 TAILQ_FOREACH(nw, &nlm_waiting_locks, nw_link) { 2260 if (!nw->nw_waiting) 2261 continue; 2262 if (argp->alock.svid == nw->nw_lock.svid 2263 && argp->alock.l_offset == nw->nw_lock.l_offset 2264 && argp->alock.l_len == nw->nw_lock.l_len 2265 && argp->alock.fh.n_len == nw->nw_lock.fh.n_len 2266 && !memcmp(argp->alock.fh.n_bytes, nw->nw_lock.fh.n_bytes, 2267 nw->nw_lock.fh.n_len)) { 2268 nw->nw_waiting = FALSE; 2269 wakeup(nw); 2270 result->stat.stat = nlm4_granted; 2271 break; 2272 } 2273 } 2274 mtx_unlock(&nlm_global_lock); 2275 if (rpcp) 2276 *rpcp = nlm_host_get_rpc(host, TRUE); 2277 nlm_host_release(host); 2278 return (0); 2279 } 2280 2281 void 2282 nlm_do_free_all(nlm4_notify *argp) 2283 { 2284 struct nlm_host *host, *thost; 2285 2286 TAILQ_FOREACH_SAFE(host, &nlm_hosts, nh_link, thost) { 2287 if (!strcmp(host->nh_caller_name, argp->name)) 2288 nlm_host_notify(host, argp->state); 2289 } 2290 } 2291 2292 /* 2293 * Kernel module glue 2294 */ 2295 static int 2296 nfslockd_modevent(module_t mod, int type, void *data) 2297 { 2298 2299 return (0); 2300 } 2301 static moduledata_t nfslockd_mod = { 2302 "nfslockd", 2303 nfslockd_modevent, 2304 NULL, 2305 }; 2306 DECLARE_MODULE(nfslockd, nfslockd_mod, SI_SUB_VFS, SI_ORDER_ANY); 2307 2308 /* So that loader and kldload(2) can find us, wherever we are.. */ 2309 MODULE_DEPEND(nfslockd, krpc, 1, 1, 1); 2310 MODULE_DEPEND(nfslockd, nfs, 1, 1, 1); 2311 MODULE_VERSION(nfslockd, 1); 2312