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