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 /* 29 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 30 * Copyright (c) 2012 by Delphix. All rights reserved. 31 * Copyright (c) 2014, Joyent, Inc. All rights reserved. 32 */ 33 34 /* 35 * Client-side support for (NFS) VOP_FRLOCK, VOP_SHRLOCK. 36 * (called via klmops.c: lm_frlock, lm4_frlock) 37 * 38 * Source code derived from FreeBSD nlm_advlock.c 39 */ 40 41 #include <sys/param.h> 42 #include <sys/fcntl.h> 43 #include <sys/lock.h> 44 #include <sys/flock.h> 45 #include <sys/mount.h> 46 #include <sys/mutex.h> 47 #include <sys/proc.h> 48 #include <sys/share.h> 49 #include <sys/syslog.h> 50 #include <sys/systm.h> 51 #include <sys/unistd.h> 52 #include <sys/vnode.h> 53 #include <sys/queue.h> 54 #include <sys/sdt.h> 55 #include <netinet/in.h> 56 57 #include <fs/fs_subr.h> 58 #include <rpcsvc/nlm_prot.h> 59 60 #include <nfs/nfs.h> 61 #include <nfs/nfs_clnt.h> 62 #include <nfs/export.h> 63 #include <nfs/rnode.h> 64 #include <nfs/lm.h> 65 66 #include "nlm_impl.h" 67 68 /* Extra flags for nlm_call_lock() - xflags */ 69 #define NLM_X_RECLAIM 1 70 #define NLM_X_BLOCKING 2 71 72 /* 73 * Max. number of retries nlm_call_cancel() does 74 * when NLM server is in grace period or doesn't 75 * respond correctly. 76 */ 77 #define NLM_CANCEL_NRETRS 5 78 79 /* 80 * Determines wether given lock "flp" is safe. 81 * The lock is considered to be safe when it 82 * acquires the whole file (i.e. its start 83 * and len are zeroes). 84 */ 85 #define NLM_FLOCK_IS_SAFE(flp) \ 86 ((flp)->l_start == 0 && (flp)->l_len == 0) 87 88 static volatile uint32_t nlm_xid = 1; 89 90 static int nlm_init_fh_by_vp(vnode_t *, struct netobj *, rpcvers_t *); 91 static int nlm_map_status(nlm4_stats); 92 static int nlm_map_clnt_stat(enum clnt_stat); 93 static void nlm_send_siglost(pid_t); 94 95 static int nlm_frlock_getlk(struct nlm_host *, vnode_t *, 96 struct flock64 *, int, u_offset_t, struct netobj *, int); 97 98 static int nlm_frlock_setlk(struct nlm_host *, vnode_t *, 99 struct flock64 *, int, u_offset_t, struct netobj *, 100 struct flk_callback *, int, bool_t); 101 102 static int nlm_reclaim_lock(struct nlm_host *, vnode_t *, 103 struct flock64 *, int32_t); 104 105 static void nlm_init_lock(struct nlm4_lock *, 106 const struct flock64 *, struct netobj *, 107 struct nlm_owner_handle *); 108 109 static int nlm_call_lock(vnode_t *, struct flock64 *, 110 struct nlm_host *, struct netobj *, 111 struct flk_callback *, int, int); 112 static int nlm_call_unlock(struct flock64 *, struct nlm_host *, 113 struct netobj *, int); 114 static int nlm_call_test(struct flock64 *, struct nlm_host *, 115 struct netobj *, int); 116 static int nlm_call_cancel(struct nlm4_lockargs *, 117 struct nlm_host *, int); 118 119 static int nlm_local_getlk(vnode_t *, struct flock64 *, int); 120 static int nlm_local_setlk(vnode_t *, struct flock64 *, int); 121 static void nlm_local_cancelk(vnode_t *, struct flock64 *); 122 123 static void nlm_init_share(struct nlm4_share *, 124 const struct shrlock *, struct netobj *); 125 126 static int nlm_call_share(struct shrlock *, struct nlm_host *, 127 struct netobj *, int, int); 128 static int nlm_call_unshare(struct shrlock *, struct nlm_host *, 129 struct netobj *, int); 130 static int nlm_reclaim_share(struct nlm_host *, vnode_t *, 131 struct shrlock *, uint32_t); 132 static int nlm_local_shrlock(vnode_t *, struct shrlock *, int, int); 133 static void nlm_local_shrcancel(vnode_t *, struct shrlock *); 134 135 /* 136 * Reclaim locks/shares acquired by the client side 137 * on the given server represented by hostp. 138 * The function is called from a dedicated thread 139 * when server reports us that it's entered grace 140 * period. 141 */ 142 void 143 nlm_reclaim_client(struct nlm_globals *g, struct nlm_host *hostp) 144 { 145 int32_t state; 146 int error, sysid; 147 struct locklist *llp_head, *llp; 148 struct nlm_shres *nsp_head, *nsp; 149 bool_t restart; 150 151 sysid = hostp->nh_sysid | LM_SYSID_CLIENT; 152 do { 153 error = 0; 154 restart = FALSE; 155 state = nlm_host_get_state(hostp); 156 157 DTRACE_PROBE3(reclaim__iter, struct nlm_globals *, g, 158 struct nlm_host *, hostp, int, state); 159 160 /* 161 * We cancel all sleeping locks that were 162 * done by the host, because we don't allow 163 * reclamation of sleeping locks. The reason 164 * we do this is that allowing of sleeping locks 165 * reclamation can potentially break locks recovery 166 * order. 167 * 168 * Imagine that we have two client machines A and B 169 * and an NLM server machine. A adds a non sleeping 170 * lock to the file F and aquires this file. Machine 171 * B in its turn adds sleeping lock to the file 172 * F and blocks because F is already aquired by 173 * the machine A. Then server crashes and after the 174 * reboot it notifies its clients about the crash. 175 * If we would allow sleeping locks reclamation, 176 * there would be possible that machine B recovers 177 * its lock faster than machine A (by some reason). 178 * So that B aquires the file F after server crash and 179 * machine A (that by some reason recovers slower) fails 180 * to recover its non sleeping lock. Thus the original 181 * locks order becames broken. 182 */ 183 nlm_host_cancel_slocks(g, hostp); 184 185 /* 186 * Try to reclaim all active locks we have 187 */ 188 llp_head = llp = flk_get_active_locks(sysid, NOPID); 189 while (llp != NULL) { 190 error = nlm_reclaim_lock(hostp, llp->ll_vp, 191 &llp->ll_flock, state); 192 193 if (error == 0) { 194 llp = llp->ll_next; 195 continue; 196 } else if (error == ERESTART) { 197 restart = TRUE; 198 break; 199 } else { 200 /* 201 * Critical error occurred, the lock 202 * can not be recovered, just take it away. 203 */ 204 nlm_local_cancelk(llp->ll_vp, &llp->ll_flock); 205 } 206 207 llp = llp->ll_next; 208 } 209 210 flk_free_locklist(llp_head); 211 if (restart) { 212 /* 213 * Lock reclamation fucntion reported us that 214 * the server state was changed (again), so 215 * try to repeat the whole reclamation process. 216 */ 217 continue; 218 } 219 220 nsp_head = nsp = nlm_get_active_shres(hostp); 221 while (nsp != NULL) { 222 error = nlm_reclaim_share(hostp, nsp->ns_vp, 223 nsp->ns_shr, state); 224 225 if (error == 0) { 226 nsp = nsp->ns_next; 227 continue; 228 } else if (error == ERESTART) { 229 break; 230 } else { 231 /* Failed to reclaim share */ 232 nlm_shres_untrack(hostp, nsp->ns_vp, 233 nsp->ns_shr); 234 nlm_local_shrcancel(nsp->ns_vp, 235 nsp->ns_shr); 236 } 237 238 nsp = nsp->ns_next; 239 } 240 241 nlm_free_shrlist(nsp_head); 242 } while (state != nlm_host_get_state(hostp)); 243 } 244 245 /* 246 * nlm_frlock -- 247 * NFS advisory byte-range locks. 248 * Called in klmops.c 249 * 250 * Note that the local locking code (os/flock.c) is used to 251 * keep track of remote locks granted by some server, so we 252 * can reclaim those locks after a server restarts. We can 253 * also sometimes use this as a cache of lock information. 254 * 255 * Was: nlm_advlock() 256 */ 257 /* ARGSUSED */ 258 int 259 nlm_frlock(struct vnode *vp, int cmd, struct flock64 *flkp, 260 int flags, u_offset_t offset, struct cred *crp, 261 struct netobj *fhp, struct flk_callback *flcb, int vers) 262 { 263 mntinfo_t *mi; 264 servinfo_t *sv; 265 const char *netid; 266 struct nlm_host *hostp; 267 int error; 268 struct nlm_globals *g; 269 270 mi = VTOMI(vp); 271 sv = mi->mi_curr_serv; 272 273 netid = nlm_knc_to_netid(sv->sv_knconf); 274 if (netid == NULL) { 275 NLM_ERR("nlm_frlock: unknown NFS netid"); 276 return (ENOSYS); 277 } 278 279 g = zone_getspecific(nlm_zone_key, curzone); 280 hostp = nlm_host_findcreate(g, sv->sv_hostname, netid, &sv->sv_addr); 281 if (hostp == NULL) 282 return (ENOSYS); 283 284 /* 285 * Purge cached attributes in order to make sure that 286 * future calls of convoff()/VOP_GETATTR() will get the 287 * latest data. 288 */ 289 if (flkp->l_whence == SEEK_END) 290 PURGE_ATTRCACHE(vp); 291 292 /* Now flk0 is the zero-based lock request. */ 293 switch (cmd) { 294 case F_GETLK: 295 error = nlm_frlock_getlk(hostp, vp, flkp, flags, 296 offset, fhp, vers); 297 break; 298 299 case F_SETLK: 300 case F_SETLKW: 301 error = nlm_frlock_setlk(hostp, vp, flkp, flags, 302 offset, fhp, flcb, vers, (cmd == F_SETLKW)); 303 if (error == 0) 304 nlm_host_monitor(g, hostp, 0); 305 break; 306 307 default: 308 error = EINVAL; 309 break; 310 } 311 312 nlm_host_release(g, hostp); 313 return (error); 314 } 315 316 static int 317 nlm_frlock_getlk(struct nlm_host *hostp, vnode_t *vp, 318 struct flock64 *flkp, int flags, u_offset_t offset, 319 struct netobj *fhp, int vers) 320 { 321 struct flock64 flk0; 322 int error; 323 324 /* 325 * Check local (cached) locks first. 326 * If we find one, no need for RPC. 327 */ 328 flk0 = *flkp; 329 flk0.l_pid = curproc->p_pid; 330 error = nlm_local_getlk(vp, &flk0, flags); 331 if (error != 0) 332 return (error); 333 if (flk0.l_type != F_UNLCK) { 334 *flkp = flk0; 335 return (0); 336 } 337 338 /* Not found locally. Try remote. */ 339 flk0 = *flkp; 340 flk0.l_pid = curproc->p_pid; 341 error = convoff(vp, &flk0, 0, (offset_t)offset); 342 if (error != 0) 343 return (error); 344 345 error = nlm_call_test(&flk0, hostp, fhp, vers); 346 if (error != 0) 347 return (error); 348 349 if (flk0.l_type == F_UNLCK) { 350 /* 351 * Update the caller's *flkp with information 352 * on the conflicting lock (or lack thereof). 353 */ 354 flkp->l_type = F_UNLCK; 355 } else { 356 /* 357 * Found a conflicting lock. Set the 358 * caller's *flkp with the info, first 359 * converting to the caller's whence. 360 */ 361 (void) convoff(vp, &flk0, flkp->l_whence, (offset_t)offset); 362 *flkp = flk0; 363 } 364 365 return (0); 366 } 367 368 static int 369 nlm_frlock_setlk(struct nlm_host *hostp, vnode_t *vp, 370 struct flock64 *flkp, int flags, u_offset_t offset, 371 struct netobj *fhp, struct flk_callback *flcb, 372 int vers, bool_t do_block) 373 { 374 int error, xflags; 375 376 error = convoff(vp, flkp, 0, (offset_t)offset); 377 if (error != 0) 378 return (error); 379 380 /* 381 * NFS v2 clients should not request locks where any part 382 * of the lock range is beyond 0xffffffff. The NFS code 383 * checks that (see nfs_frlock, flk_check_lock_data), but 384 * as that's outside this module, let's check here too. 385 * This check ensures that we will be able to convert this 386 * lock request into 32-bit form without change, and that 387 * (more importantly) when the granted call back arrives, 388 * it's unchanged when converted back into 64-bit form. 389 * If this lock range were to change in any way during 390 * either of those conversions, the "granted" call back 391 * from the NLM server would not find our sleeping lock. 392 */ 393 if (vers < NLM4_VERS) { 394 if (flkp->l_start > MAX_UOFF32 || 395 flkp->l_start + flkp->l_len > MAX_UOFF32 + 1) 396 return (EINVAL); 397 } 398 399 /* 400 * Fill in l_sysid for the local locking calls. 401 * Also, let's not trust the caller's l_pid. 402 */ 403 flkp->l_sysid = hostp->nh_sysid | LM_SYSID_CLIENT; 404 flkp->l_pid = curproc->p_pid; 405 406 if (flkp->l_type == F_UNLCK) { 407 /* 408 * Purge local (cached) lock information first, 409 * then clear the remote lock. 410 */ 411 (void) nlm_local_setlk(vp, flkp, flags); 412 error = nlm_call_unlock(flkp, hostp, fhp, vers); 413 414 return (error); 415 } 416 417 if (!do_block) { 418 /* 419 * This is a non-blocking "set" request, 420 * so we can check locally first, and 421 * sometimes avoid an RPC call. 422 */ 423 struct flock64 flk0; 424 425 flk0 = *flkp; 426 error = nlm_local_getlk(vp, &flk0, flags); 427 if (error != 0 && flk0.l_type != F_UNLCK) { 428 /* Found a conflicting lock. */ 429 return (EAGAIN); 430 } 431 432 xflags = 0; 433 } else { 434 xflags = NLM_X_BLOCKING; 435 } 436 437 nfs_add_locking_id(vp, curproc->p_pid, RLMPL_PID, 438 (char *)&curproc->p_pid, sizeof (pid_t)); 439 440 error = nlm_call_lock(vp, flkp, hostp, fhp, flcb, vers, xflags); 441 if (error != 0) 442 return (error); 443 444 /* 445 * Save the lock locally. This should not fail, 446 * because the server is authoritative about locks 447 * and it just told us we have the lock! 448 */ 449 error = nlm_local_setlk(vp, flkp, flags); 450 if (error != 0) { 451 /* 452 * That's unexpected situation. Just ignore the error. 453 */ 454 NLM_WARN("nlm_frlock_setlk: Failed to set local lock. " 455 "[err=%d]\n", error); 456 error = 0; 457 } 458 459 return (error); 460 } 461 462 /* 463 * Cancel all client side remote locks/shares on the 464 * given host. Report to the processes that own 465 * cancelled locks that they are removed by force 466 * by sending SIGLOST. 467 */ 468 void 469 nlm_client_cancel_all(struct nlm_globals *g, struct nlm_host *hostp) 470 { 471 struct locklist *llp_head, *llp; 472 struct nlm_shres *nsp_head, *nsp; 473 struct netobj lm_fh; 474 rpcvers_t vers; 475 int error, sysid; 476 477 sysid = hostp->nh_sysid | LM_SYSID_CLIENT; 478 nlm_host_cancel_slocks(g, hostp); 479 480 /* 481 * Destroy all active locks 482 */ 483 llp_head = llp = flk_get_active_locks(sysid, NOPID); 484 while (llp != NULL) { 485 llp->ll_flock.l_type = F_UNLCK; 486 487 error = nlm_init_fh_by_vp(llp->ll_vp, &lm_fh, &vers); 488 if (error == 0) 489 (void) nlm_call_unlock(&llp->ll_flock, hostp, 490 &lm_fh, vers); 491 492 nlm_local_cancelk(llp->ll_vp, &llp->ll_flock); 493 llp = llp->ll_next; 494 } 495 496 flk_free_locklist(llp_head); 497 498 /* 499 * Destroy all active share reservations 500 */ 501 nsp_head = nsp = nlm_get_active_shres(hostp); 502 while (nsp != NULL) { 503 error = nlm_init_fh_by_vp(nsp->ns_vp, &lm_fh, &vers); 504 if (error == 0) 505 (void) nlm_call_unshare(nsp->ns_shr, hostp, 506 &lm_fh, vers); 507 508 nlm_local_shrcancel(nsp->ns_vp, nsp->ns_shr); 509 nlm_shres_untrack(hostp, nsp->ns_vp, nsp->ns_shr); 510 nsp = nsp->ns_next; 511 } 512 513 nlm_free_shrlist(nsp_head); 514 } 515 516 /* 517 * The function determines whether the lock "fl" can 518 * be safely applied to the file vnode "vp" corresponds to. 519 * The lock can be "safely" applied if all the conditions 520 * above are held: 521 * - It's not a mandatory lock 522 * - The vnode wasn't mapped by anyone 523 * - The vnode was mapped, but it hasn't any locks on it. 524 * - The vnode was mapped and all locks it has occupies 525 * the whole file. 526 */ 527 int 528 nlm_safelock(vnode_t *vp, const struct flock64 *fl, cred_t *cr) 529 { 530 rnode_t *rp = VTOR(vp); 531 struct vattr va; 532 int err; 533 534 if ((rp->r_mapcnt > 0) && (fl->l_start != 0 || fl->l_len != 0)) 535 return (0); 536 537 va.va_mask = AT_MODE; 538 err = VOP_GETATTR(vp, &va, 0, cr, NULL); 539 if (err != 0) 540 return (0); 541 542 /* NLM4 doesn't allow mandatory file locking */ 543 if (MANDLOCK(vp, va.va_mode)) 544 return (0); 545 546 return (1); 547 } 548 549 /* 550 * The function determines whether it's safe to map 551 * a file correspoding to vnode vp. 552 * The mapping is considered to be "safe" if file 553 * either has no any locks on it or all locks it 554 * has occupy the whole file. 555 */ 556 int 557 nlm_safemap(const vnode_t *vp) 558 { 559 struct locklist *llp, *llp_next; 560 struct nlm_slock *nslp; 561 struct nlm_globals *g; 562 int safe = 1; 563 564 /* Check active locks at first */ 565 llp = flk_active_locks_for_vp(vp); 566 while (llp != NULL) { 567 if ((llp->ll_vp == vp) && 568 !NLM_FLOCK_IS_SAFE(&llp->ll_flock)) 569 safe = 0; 570 571 llp_next = llp->ll_next; 572 VN_RELE(llp->ll_vp); 573 kmem_free(llp, sizeof (*llp)); 574 llp = llp_next; 575 } 576 if (!safe) 577 return (safe); 578 579 /* Then check sleeping locks if any */ 580 g = zone_getspecific(nlm_zone_key, curzone); 581 mutex_enter(&g->lock); 582 TAILQ_FOREACH(nslp, &g->nlm_slocks, nsl_link) { 583 if (nslp->nsl_state == NLM_SL_BLOCKED && 584 nslp->nsl_vp == vp && 585 (nslp->nsl_lock.l_offset != 0 || 586 nslp->nsl_lock.l_len != 0)) { 587 safe = 0; 588 break; 589 } 590 } 591 592 mutex_exit(&g->lock); 593 return (safe); 594 } 595 596 int 597 nlm_has_sleep(const vnode_t *vp) 598 { 599 struct nlm_globals *g; 600 struct nlm_slock *nslp; 601 int has_slocks = FALSE; 602 603 g = zone_getspecific(nlm_zone_key, curzone); 604 mutex_enter(&g->lock); 605 TAILQ_FOREACH(nslp, &g->nlm_slocks, nsl_link) { 606 if (nslp->nsl_state == NLM_SL_BLOCKED && 607 nslp->nsl_vp == vp) { 608 has_slocks = TRUE; 609 break; 610 } 611 } 612 613 mutex_exit(&g->lock); 614 return (has_slocks); 615 } 616 617 void 618 nlm_register_lock_locally(struct vnode *vp, struct nlm_host *hostp, 619 struct flock64 *flk, int flags, u_offset_t offset) 620 { 621 struct nlm_globals *g = NULL; 622 int sysid = 0; 623 624 if (hostp == NULL) { 625 mntinfo_t *mi; 626 servinfo_t *sv; 627 const char *netid; 628 629 mi = VTOMI(vp); 630 sv = mi->mi_curr_serv; 631 netid = nlm_knc_to_netid(sv->sv_knconf); 632 633 if (netid != NULL) { 634 g = zone_getspecific(nlm_zone_key, curzone); 635 hostp = nlm_host_findcreate(g, sv->sv_hostname, 636 netid, &sv->sv_addr); 637 } 638 } 639 640 if (hostp != NULL) { 641 sysid = hostp->nh_sysid | LM_SYSID_CLIENT; 642 643 if (g != NULL) 644 nlm_host_release(g, hostp); 645 } 646 647 flk->l_sysid = sysid; 648 (void) convoff(vp, flk, 0, (offset_t)offset); 649 (void) nlm_local_setlk(vp, flk, flags); 650 } 651 652 653 /* 654 * The BSD code had functions here to "reclaim" (destroy) 655 * remote locks when a vnode is being forcibly destroyed. 656 * We just keep vnodes around until statd tells us the 657 * client has gone away. 658 */ 659 660 static int 661 nlm_reclaim_lock(struct nlm_host *hostp, vnode_t *vp, 662 struct flock64 *flp, int32_t orig_state) 663 { 664 struct netobj lm_fh; 665 int error, state; 666 rpcvers_t vers; 667 668 /* 669 * If the remote NSM state changes during recovery, the host 670 * must have rebooted a second time. In that case, we must 671 * restart the recovery. 672 */ 673 state = nlm_host_get_state(hostp); 674 if (state != orig_state) 675 return (ERESTART); 676 677 error = nlm_init_fh_by_vp(vp, &lm_fh, &vers); 678 if (error != 0) 679 return (error); 680 681 return (nlm_call_lock(vp, flp, hostp, &lm_fh, 682 NULL, vers, NLM_X_RECLAIM)); 683 } 684 685 /* 686 * Get local lock information for some NFS server. 687 * 688 * This gets (checks for) a local conflicting lock. 689 * Note: Modifies passed flock, if a conflict is found, 690 * but the caller expects that. 691 */ 692 static int 693 nlm_local_getlk(vnode_t *vp, struct flock64 *fl, int flags) 694 { 695 VERIFY(fl->l_whence == SEEK_SET); 696 return (reclock(vp, fl, 0, flags, 0, NULL)); 697 } 698 699 /* 700 * Set local lock information for some NFS server. 701 * 702 * Called after a lock request (set or clear) succeeded. We record the 703 * details in the local lock manager. Note that since the remote 704 * server has granted the lock, we can be sure that it doesn't 705 * conflict with any other locks we have in the local lock manager. 706 * 707 * Since it is possible that host may also make NLM client requests to 708 * our NLM server, we use a different sysid value to record our own 709 * client locks. 710 * 711 * Note that since it is possible for us to receive replies from the 712 * server in a different order than the locks were granted (e.g. if 713 * many local threads are contending for the same lock), we must use a 714 * blocking operation when registering with the local lock manager. 715 * We expect that any actual wait will be rare and short hence we 716 * ignore signals for this. 717 */ 718 static int 719 nlm_local_setlk(vnode_t *vp, struct flock64 *fl, int flags) 720 { 721 VERIFY(fl->l_whence == SEEK_SET); 722 return (reclock(vp, fl, SETFLCK, flags, 0, NULL)); 723 } 724 725 /* 726 * Cancel local lock and send send SIGLOST signal 727 * to the lock owner. 728 * 729 * NOTE: modifies flp 730 */ 731 static void 732 nlm_local_cancelk(vnode_t *vp, struct flock64 *flp) 733 { 734 flp->l_type = F_UNLCK; 735 (void) nlm_local_setlk(vp, flp, FREAD | FWRITE); 736 nlm_send_siglost(flp->l_pid); 737 } 738 739 /* 740 * Do NLM_LOCK call. 741 * Was: nlm_setlock() 742 * 743 * NOTE: nlm_call_lock() function should care about locking/unlocking 744 * of rnode->r_lkserlock which should be released before nlm_call_lock() 745 * sleeps on waiting lock and acquired when it wakes up. 746 */ 747 static int 748 nlm_call_lock(vnode_t *vp, struct flock64 *flp, 749 struct nlm_host *hostp, struct netobj *fhp, 750 struct flk_callback *flcb, int vers, int xflags) 751 { 752 struct nlm4_lockargs args; 753 struct nlm_owner_handle oh; 754 struct nlm_globals *g; 755 rnode_t *rnp = VTOR(vp); 756 struct nlm_slock *nslp = NULL; 757 uint32_t xid; 758 int error = 0; 759 760 bzero(&args, sizeof (args)); 761 g = zone_getspecific(nlm_zone_key, curzone); 762 nlm_init_lock(&args.alock, flp, fhp, &oh); 763 764 args.exclusive = (flp->l_type == F_WRLCK); 765 args.reclaim = xflags & NLM_X_RECLAIM; 766 args.state = g->nsm_state; 767 args.cookie.n_len = sizeof (xid); 768 args.cookie.n_bytes = (char *)&xid; 769 770 oh.oh_sysid = hostp->nh_sysid; 771 xid = atomic_inc_32_nv(&nlm_xid); 772 773 if (xflags & NLM_X_BLOCKING) { 774 args.block = TRUE; 775 nslp = nlm_slock_register(g, hostp, &args.alock, vp); 776 } 777 778 for (;;) { 779 nlm_rpc_t *rpcp; 780 enum clnt_stat stat; 781 struct nlm4_res res; 782 enum nlm4_stats nlm_err; 783 784 error = nlm_host_get_rpc(hostp, vers, &rpcp); 785 if (error != 0) { 786 error = ENOLCK; 787 goto out; 788 } 789 790 bzero(&res, sizeof (res)); 791 stat = nlm_lock_rpc(&args, &res, rpcp->nr_handle, vers); 792 nlm_host_rele_rpc(hostp, rpcp); 793 794 error = nlm_map_clnt_stat(stat); 795 if (error != 0) { 796 if (error == EAGAIN) 797 continue; 798 799 goto out; 800 } 801 802 DTRACE_PROBE1(lock__res, enum nlm4_stats, res.stat.stat); 803 nlm_err = res.stat.stat; 804 xdr_free((xdrproc_t)xdr_nlm4_res, (void *)&res); 805 if (nlm_err == nlm4_denied_grace_period) { 806 if (args.reclaim) { 807 error = ENOLCK; 808 goto out; 809 } 810 811 error = nlm_host_wait_grace(hostp); 812 if (error != 0) 813 goto out; 814 815 continue; 816 } 817 818 switch (nlm_err) { 819 case nlm4_granted: 820 case nlm4_blocked: 821 error = 0; 822 break; 823 824 case nlm4_denied: 825 if (nslp != NULL) { 826 NLM_WARN("nlm_call_lock: got nlm4_denied for " 827 "blocking lock\n"); 828 } 829 830 error = EAGAIN; 831 break; 832 833 default: 834 error = nlm_map_status(nlm_err); 835 } 836 837 /* 838 * If we deal with either non-blocking lock or 839 * with a blocking locks that wasn't blocked on 840 * the server side (by some reason), our work 841 * is finished. 842 */ 843 if (nslp == NULL || 844 nlm_err != nlm4_blocked || 845 error != 0) 846 goto out; 847 848 /* 849 * Before releasing the r_lkserlock of rnode, we should 850 * check whether the new lock is "safe". If it's not 851 * safe, disable caching for the given vnode. That is done 852 * for sleeping locks only that are waiting for a GRANT reply 853 * from the NLM server. 854 * 855 * NOTE: the vnode cache can be enabled back later if an 856 * unsafe lock will be merged with existent locks so that 857 * it will become safe. This condition is checked in the 858 * NFSv3 code (see nfs_lockcompletion). 859 */ 860 if (!NLM_FLOCK_IS_SAFE(flp)) { 861 mutex_enter(&vp->v_lock); 862 vp->v_flag &= ~VNOCACHE; 863 mutex_exit(&vp->v_lock); 864 } 865 866 /* 867 * The server should call us back with a 868 * granted message when the lock succeeds. 869 * In order to deal with broken servers, 870 * lost granted messages, or server reboots, 871 * we will also re-try every few seconds. 872 * 873 * Note: We're supposed to call these 874 * flk_invoke_callbacks when blocking. 875 * Take care on rnode->r_lkserlock, we should 876 * release it before going to sleep. 877 */ 878 (void) flk_invoke_callbacks(flcb, FLK_BEFORE_SLEEP); 879 nfs_rw_exit(&rnp->r_lkserlock); 880 881 error = nlm_slock_wait(g, nslp, g->retrans_tmo); 882 883 /* 884 * NFS expects that we return with rnode->r_lkserlock 885 * locked on write, lock it back. 886 * 887 * NOTE: nfs_rw_enter_sig() can be either interruptible 888 * or not. It depends on options of NFS mount. Here 889 * we're _always_ uninterruptible (independently of mount 890 * options), because nfs_frlock/nfs3_frlock expects that 891 * we return with rnode->r_lkserlock acquired. So we don't 892 * want our lock attempt to be interrupted by a signal. 893 */ 894 (void) nfs_rw_enter_sig(&rnp->r_lkserlock, RW_WRITER, 0); 895 (void) flk_invoke_callbacks(flcb, FLK_AFTER_SLEEP); 896 897 if (error == 0) { 898 break; 899 } else if (error == EINTR) { 900 /* 901 * We need to call the server to cancel our 902 * lock request. 903 */ 904 DTRACE_PROBE1(cancel__lock, int, error); 905 (void) nlm_call_cancel(&args, hostp, vers); 906 break; 907 } else { 908 /* 909 * Timeout happened, resend the lock request to 910 * the server. Well, we're a bit paranoid here, 911 * but keep in mind previous request could lost 912 * (especially with conectionless transport). 913 */ 914 915 ASSERT(error == ETIMEDOUT); 916 continue; 917 } 918 } 919 920 /* 921 * We could disable the vnode cache for the given _sleeping_ 922 * (codition: nslp != NULL) lock if it was unsafe. Normally, 923 * nfs_lockcompletion() function can enable the vnode cache 924 * back if the lock becomes safe after activativation. But it 925 * will not happen if any error occurs on the locking path. 926 * 927 * Here we enable the vnode cache back if the error occurred 928 * and if there aren't any unsafe locks on the given vnode. 929 * Note that if error happened, sleeping lock was derigistered. 930 */ 931 if (error != 0 && nslp != NULL && nlm_safemap(vp)) { 932 mutex_enter(&vp->v_lock); 933 vp->v_flag |= VNOCACHE; 934 mutex_exit(&vp->v_lock); 935 } 936 937 out: 938 if (nslp != NULL) 939 nlm_slock_unregister(g, nslp); 940 941 return (error); 942 } 943 944 /* 945 * Do NLM_CANCEL call. 946 * Helper for nlm_call_lock() error recovery. 947 */ 948 static int 949 nlm_call_cancel(struct nlm4_lockargs *largs, 950 struct nlm_host *hostp, int vers) 951 { 952 nlm4_cancargs cargs; 953 uint32_t xid; 954 int error, retries; 955 956 bzero(&cargs, sizeof (cargs)); 957 958 xid = atomic_inc_32_nv(&nlm_xid); 959 cargs.cookie.n_len = sizeof (xid); 960 cargs.cookie.n_bytes = (char *)&xid; 961 cargs.block = largs->block; 962 cargs.exclusive = largs->exclusive; 963 cargs.alock = largs->alock; 964 965 /* 966 * Unlike all other nlm_call_* functions, nlm_call_cancel 967 * doesn't spin forever until it gets reasonable response 968 * from NLM server. It makes limited number of retries and 969 * if server doesn't send a reasonable reply, it returns an 970 * error. It behaves like that because it's called from nlm_call_lock 971 * with blocked signals and thus it can not be interrupted from 972 * user space. 973 */ 974 for (retries = 0; retries < NLM_CANCEL_NRETRS; retries++) { 975 nlm_rpc_t *rpcp; 976 enum clnt_stat stat; 977 struct nlm4_res res; 978 979 error = nlm_host_get_rpc(hostp, vers, &rpcp); 980 if (error != 0) 981 return (ENOLCK); 982 983 bzero(&res, sizeof (res)); 984 stat = nlm_cancel_rpc(&cargs, &res, rpcp->nr_handle, vers); 985 nlm_host_rele_rpc(hostp, rpcp); 986 987 DTRACE_PROBE1(cancel__rloop_end, enum clnt_stat, stat); 988 error = nlm_map_clnt_stat(stat); 989 if (error != 0) { 990 if (error == EAGAIN) 991 continue; 992 993 return (error); 994 } 995 996 DTRACE_PROBE1(cancel__res, enum nlm4_stats, res.stat.stat); 997 switch (res.stat.stat) { 998 /* 999 * There was nothing to cancel. We are going to go ahead 1000 * and assume we got the lock. 1001 */ 1002 case nlm_denied: 1003 /* 1004 * The server has recently rebooted. Treat this as a 1005 * successful cancellation. 1006 */ 1007 case nlm4_denied_grace_period: 1008 /* 1009 * We managed to cancel. 1010 */ 1011 case nlm4_granted: 1012 error = 0; 1013 break; 1014 1015 default: 1016 /* 1017 * Broken server implementation. Can't really do 1018 * anything here. 1019 */ 1020 error = EIO; 1021 break; 1022 } 1023 1024 xdr_free((xdrproc_t)xdr_nlm4_res, (void *)&res); 1025 break; 1026 } 1027 1028 return (error); 1029 } 1030 1031 /* 1032 * Do NLM_UNLOCK call. 1033 * Was: nlm_clearlock 1034 */ 1035 static int 1036 nlm_call_unlock(struct flock64 *flp, struct nlm_host *hostp, 1037 struct netobj *fhp, int vers) 1038 { 1039 struct nlm4_unlockargs args; 1040 struct nlm_owner_handle oh; 1041 enum nlm4_stats nlm_err; 1042 uint32_t xid; 1043 int error; 1044 1045 bzero(&args, sizeof (args)); 1046 nlm_init_lock(&args.alock, flp, fhp, &oh); 1047 1048 oh.oh_sysid = hostp->nh_sysid; 1049 xid = atomic_inc_32_nv(&nlm_xid); 1050 args.cookie.n_len = sizeof (xid); 1051 args.cookie.n_bytes = (char *)&xid; 1052 1053 for (;;) { 1054 nlm_rpc_t *rpcp; 1055 struct nlm4_res res; 1056 enum clnt_stat stat; 1057 1058 error = nlm_host_get_rpc(hostp, vers, &rpcp); 1059 if (error != 0) 1060 return (ENOLCK); 1061 1062 bzero(&res, sizeof (res)); 1063 stat = nlm_unlock_rpc(&args, &res, rpcp->nr_handle, vers); 1064 nlm_host_rele_rpc(hostp, rpcp); 1065 1066 error = nlm_map_clnt_stat(stat); 1067 if (error != 0) { 1068 if (error == EAGAIN) 1069 continue; 1070 1071 return (error); 1072 } 1073 1074 DTRACE_PROBE1(unlock__res, enum nlm4_stats, res.stat.stat); 1075 nlm_err = res.stat.stat; 1076 xdr_free((xdrproc_t)xdr_nlm4_res, (void *)&res); 1077 if (nlm_err == nlm4_denied_grace_period) { 1078 error = nlm_host_wait_grace(hostp); 1079 if (error != 0) 1080 return (error); 1081 1082 continue; 1083 } 1084 1085 break; 1086 } 1087 1088 /* special cases */ 1089 switch (nlm_err) { 1090 case nlm4_denied: 1091 error = EINVAL; 1092 break; 1093 default: 1094 error = nlm_map_status(nlm_err); 1095 break; 1096 } 1097 1098 return (error); 1099 } 1100 1101 /* 1102 * Do NLM_TEST call. 1103 * Was: nlm_getlock() 1104 */ 1105 static int 1106 nlm_call_test(struct flock64 *flp, struct nlm_host *hostp, 1107 struct netobj *fhp, int vers) 1108 { 1109 struct nlm4_testargs args; 1110 struct nlm4_holder h; 1111 struct nlm_owner_handle oh; 1112 enum nlm4_stats nlm_err; 1113 uint32_t xid; 1114 int error; 1115 1116 bzero(&args, sizeof (args)); 1117 nlm_init_lock(&args.alock, flp, fhp, &oh); 1118 1119 args.exclusive = (flp->l_type == F_WRLCK); 1120 oh.oh_sysid = hostp->nh_sysid; 1121 xid = atomic_inc_32_nv(&nlm_xid); 1122 args.cookie.n_len = sizeof (xid); 1123 args.cookie.n_bytes = (char *)&xid; 1124 1125 for (;;) { 1126 nlm_rpc_t *rpcp; 1127 struct nlm4_testres res; 1128 enum clnt_stat stat; 1129 1130 error = nlm_host_get_rpc(hostp, vers, &rpcp); 1131 if (error != 0) 1132 return (ENOLCK); 1133 1134 bzero(&res, sizeof (res)); 1135 stat = nlm_test_rpc(&args, &res, rpcp->nr_handle, vers); 1136 nlm_host_rele_rpc(hostp, rpcp); 1137 1138 error = nlm_map_clnt_stat(stat); 1139 if (error != 0) { 1140 if (error == EAGAIN) 1141 continue; 1142 1143 return (error); 1144 } 1145 1146 DTRACE_PROBE1(test__res, enum nlm4_stats, res.stat.stat); 1147 nlm_err = res.stat.stat; 1148 bcopy(&res.stat.nlm4_testrply_u.holder, &h, sizeof (h)); 1149 xdr_free((xdrproc_t)xdr_nlm4_testres, (void *)&res); 1150 if (nlm_err == nlm4_denied_grace_period) { 1151 error = nlm_host_wait_grace(hostp); 1152 if (error != 0) 1153 return (error); 1154 1155 continue; 1156 } 1157 1158 break; 1159 } 1160 1161 switch (nlm_err) { 1162 case nlm4_granted: 1163 flp->l_type = F_UNLCK; 1164 error = 0; 1165 break; 1166 1167 case nlm4_denied: 1168 flp->l_start = h.l_offset; 1169 flp->l_len = h.l_len; 1170 flp->l_pid = h.svid; 1171 flp->l_type = (h.exclusive) ? F_WRLCK : F_RDLCK; 1172 flp->l_whence = SEEK_SET; 1173 flp->l_sysid = 0; 1174 error = 0; 1175 break; 1176 1177 default: 1178 error = nlm_map_status(nlm_err); 1179 break; 1180 } 1181 1182 return (error); 1183 } 1184 1185 1186 static void 1187 nlm_init_lock(struct nlm4_lock *lock, 1188 const struct flock64 *fl, struct netobj *fh, 1189 struct nlm_owner_handle *oh) 1190 { 1191 1192 /* Caller converts to zero-base. */ 1193 VERIFY(fl->l_whence == SEEK_SET); 1194 bzero(lock, sizeof (*lock)); 1195 bzero(oh, sizeof (*oh)); 1196 1197 lock->caller_name = uts_nodename(); 1198 lock->fh.n_len = fh->n_len; 1199 lock->fh.n_bytes = fh->n_bytes; 1200 lock->oh.n_len = sizeof (*oh); 1201 lock->oh.n_bytes = (void *)oh; 1202 lock->svid = fl->l_pid; 1203 lock->l_offset = fl->l_start; 1204 lock->l_len = fl->l_len; 1205 } 1206 1207 /* ************************************************************** */ 1208 1209 int 1210 nlm_shrlock(struct vnode *vp, int cmd, struct shrlock *shr, 1211 int flags, struct netobj *fh, int vers) 1212 { 1213 struct shrlock shlk; 1214 mntinfo_t *mi; 1215 servinfo_t *sv; 1216 const char *netid; 1217 struct nlm_host *host = NULL; 1218 int error; 1219 struct nlm_globals *g; 1220 1221 mi = VTOMI(vp); 1222 sv = mi->mi_curr_serv; 1223 1224 netid = nlm_knc_to_netid(sv->sv_knconf); 1225 if (netid == NULL) { 1226 NLM_ERR("nlm_shrlock: unknown NFS netid\n"); 1227 return (ENOSYS); 1228 } 1229 1230 g = zone_getspecific(nlm_zone_key, curzone); 1231 host = nlm_host_findcreate(g, sv->sv_hostname, netid, &sv->sv_addr); 1232 if (host == NULL) 1233 return (ENOSYS); 1234 1235 /* 1236 * Fill in s_sysid for the local locking calls. 1237 * Also, let's not trust the caller's l_pid. 1238 */ 1239 shlk = *shr; 1240 shlk.s_sysid = host->nh_sysid | LM_SYSID_CLIENT; 1241 shlk.s_pid = curproc->p_pid; 1242 1243 if (cmd == F_UNSHARE) { 1244 /* 1245 * Purge local (cached) share information first, 1246 * then clear the remote share. 1247 */ 1248 (void) nlm_local_shrlock(vp, &shlk, cmd, flags); 1249 nlm_shres_untrack(host, vp, &shlk); 1250 error = nlm_call_unshare(&shlk, host, fh, vers); 1251 goto out; 1252 } 1253 1254 nfs_add_locking_id(vp, curproc->p_pid, RLMPL_OWNER, 1255 shr->s_owner, shr->s_own_len); 1256 1257 error = nlm_call_share(&shlk, host, fh, vers, FALSE); 1258 if (error != 0) 1259 goto out; 1260 1261 /* 1262 * Save the share locally. This should not fail, 1263 * because the server is authoritative about shares 1264 * and it just told us we have the share reservation! 1265 */ 1266 error = nlm_local_shrlock(vp, shr, cmd, flags); 1267 if (error != 0) { 1268 /* 1269 * Oh oh, we really don't expect an error here. 1270 */ 1271 NLM_WARN("nlm_shrlock: set locally, err %d\n", error); 1272 error = 0; 1273 } 1274 1275 nlm_shres_track(host, vp, &shlk); 1276 nlm_host_monitor(g, host, 0); 1277 1278 out: 1279 nlm_host_release(g, host); 1280 1281 return (error); 1282 } 1283 1284 static int 1285 nlm_reclaim_share(struct nlm_host *hostp, vnode_t *vp, 1286 struct shrlock *shr, uint32_t orig_state) 1287 { 1288 struct netobj lm_fh; 1289 int error, state; 1290 rpcvers_t vers; 1291 1292 state = nlm_host_get_state(hostp); 1293 if (state != orig_state) { 1294 /* 1295 * It seems that NLM server rebooted while 1296 * we were busy with recovery. 1297 */ 1298 return (ERESTART); 1299 } 1300 1301 error = nlm_init_fh_by_vp(vp, &lm_fh, &vers); 1302 if (error != 0) 1303 return (error); 1304 1305 return (nlm_call_share(shr, hostp, &lm_fh, vers, 1)); 1306 } 1307 1308 /* 1309 * Set local share information for some NFS server. 1310 * 1311 * Called after a share request (set or clear) succeeded. We record 1312 * the details in the local lock manager. Note that since the remote 1313 * server has granted the share, we can be sure that it doesn't 1314 * conflict with any other shares we have in the local lock manager. 1315 * 1316 * Since it is possible that host may also make NLM client requests to 1317 * our NLM server, we use a different sysid value to record our own 1318 * client shares. 1319 */ 1320 int 1321 nlm_local_shrlock(vnode_t *vp, struct shrlock *shr, int cmd, int flags) 1322 { 1323 return (fs_shrlock(vp, cmd, shr, flags, CRED(), NULL)); 1324 } 1325 1326 static void 1327 nlm_local_shrcancel(vnode_t *vp, struct shrlock *shr) 1328 { 1329 (void) nlm_local_shrlock(vp, shr, F_UNSHARE, FREAD | FWRITE); 1330 nlm_send_siglost(shr->s_pid); 1331 } 1332 1333 /* 1334 * Do NLM_SHARE call. 1335 * Was: nlm_setshare() 1336 */ 1337 static int 1338 nlm_call_share(struct shrlock *shr, struct nlm_host *host, 1339 struct netobj *fh, int vers, int reclaim) 1340 { 1341 struct nlm4_shareargs args; 1342 enum nlm4_stats nlm_err; 1343 uint32_t xid; 1344 int error; 1345 1346 bzero(&args, sizeof (args)); 1347 nlm_init_share(&args.share, shr, fh); 1348 1349 args.reclaim = reclaim; 1350 xid = atomic_inc_32_nv(&nlm_xid); 1351 args.cookie.n_len = sizeof (xid); 1352 args.cookie.n_bytes = (char *)&xid; 1353 1354 1355 for (;;) { 1356 nlm_rpc_t *rpcp; 1357 struct nlm4_shareres res; 1358 enum clnt_stat stat; 1359 1360 error = nlm_host_get_rpc(host, vers, &rpcp); 1361 if (error != 0) 1362 return (ENOLCK); 1363 1364 bzero(&res, sizeof (res)); 1365 stat = nlm_share_rpc(&args, &res, rpcp->nr_handle, vers); 1366 nlm_host_rele_rpc(host, rpcp); 1367 1368 error = nlm_map_clnt_stat(stat); 1369 if (error != 0) { 1370 if (error == EAGAIN) 1371 continue; 1372 1373 return (error); 1374 } 1375 1376 DTRACE_PROBE1(share__res, enum nlm4_stats, res.stat); 1377 nlm_err = res.stat; 1378 xdr_free((xdrproc_t)xdr_nlm4_shareres, (void *)&res); 1379 if (nlm_err == nlm4_denied_grace_period) { 1380 if (args.reclaim) 1381 return (ENOLCK); 1382 1383 error = nlm_host_wait_grace(host); 1384 if (error != 0) 1385 return (error); 1386 1387 continue; 1388 } 1389 1390 break; 1391 } 1392 1393 switch (nlm_err) { 1394 case nlm4_granted: 1395 error = 0; 1396 break; 1397 case nlm4_blocked: 1398 case nlm4_denied: 1399 error = EAGAIN; 1400 break; 1401 case nlm4_denied_nolocks: 1402 case nlm4_deadlck: 1403 error = ENOLCK; 1404 break; 1405 default: 1406 error = EINVAL; 1407 break; 1408 } 1409 1410 return (error); 1411 } 1412 1413 /* 1414 * Do NLM_UNSHARE call. 1415 */ 1416 static int 1417 nlm_call_unshare(struct shrlock *shr, struct nlm_host *host, 1418 struct netobj *fh, int vers) 1419 { 1420 struct nlm4_shareargs args; 1421 enum nlm4_stats nlm_err; 1422 uint32_t xid; 1423 int error; 1424 1425 bzero(&args, sizeof (args)); 1426 nlm_init_share(&args.share, shr, fh); 1427 1428 xid = atomic_inc_32_nv(&nlm_xid); 1429 args.cookie.n_len = sizeof (xid); 1430 args.cookie.n_bytes = (char *)&xid; 1431 1432 for (;;) { 1433 nlm_rpc_t *rpcp; 1434 struct nlm4_shareres res; 1435 enum clnt_stat stat; 1436 1437 error = nlm_host_get_rpc(host, vers, &rpcp); 1438 if (error != 0) 1439 return (ENOLCK); 1440 1441 bzero(&res, sizeof (res)); 1442 stat = nlm_unshare_rpc(&args, &res, rpcp->nr_handle, vers); 1443 nlm_host_rele_rpc(host, rpcp); 1444 1445 error = nlm_map_clnt_stat(stat); 1446 if (error != 0) { 1447 if (error == EAGAIN) 1448 continue; 1449 1450 return (error); 1451 } 1452 1453 DTRACE_PROBE1(unshare__res, enum nlm4_stats, res.stat); 1454 nlm_err = res.stat; 1455 xdr_free((xdrproc_t)xdr_nlm4_res, (void *)&res); 1456 if (nlm_err == nlm4_denied_grace_period) { 1457 error = nlm_host_wait_grace(host); 1458 if (error != 0) 1459 return (error); 1460 1461 continue; 1462 } 1463 1464 break; 1465 } 1466 1467 switch (nlm_err) { 1468 case nlm4_granted: 1469 error = 0; 1470 break; 1471 case nlm4_denied: 1472 error = EAGAIN; 1473 break; 1474 case nlm4_denied_nolocks: 1475 error = ENOLCK; 1476 break; 1477 default: 1478 error = EINVAL; 1479 break; 1480 } 1481 1482 return (error); 1483 } 1484 1485 static void 1486 nlm_init_share(struct nlm4_share *args, 1487 const struct shrlock *shr, struct netobj *fh) 1488 { 1489 1490 bzero(args, sizeof (*args)); 1491 1492 args->caller_name = uts_nodename(); 1493 args->fh.n_len = fh->n_len; 1494 args->fh.n_bytes = fh->n_bytes; 1495 args->oh.n_len = shr->s_own_len; 1496 args->oh.n_bytes = (void *)shr->s_owner; 1497 1498 switch (shr->s_deny) { 1499 default: 1500 case F_NODNY: 1501 args->mode = fsm_DN; 1502 break; 1503 case F_RDDNY: 1504 args->mode = fsm_DR; 1505 break; 1506 case F_WRDNY: 1507 args->mode = fsm_DW; 1508 break; 1509 case F_RWDNY: 1510 args->mode = fsm_DRW; 1511 break; 1512 } 1513 1514 switch (shr->s_access) { 1515 default: 1516 case 0: /* seen with F_UNSHARE */ 1517 args->access = fsa_NONE; 1518 break; 1519 case F_RDACC: 1520 args->access = fsa_R; 1521 break; 1522 case F_WRACC: 1523 args->access = fsa_W; 1524 break; 1525 case F_RWACC: 1526 args->access = fsa_RW; 1527 break; 1528 } 1529 } 1530 1531 /* 1532 * Initialize filehandle according to the version 1533 * of NFS vnode was created on. The version of 1534 * NLM that can be used with given NFS version 1535 * is saved to lm_vers. 1536 */ 1537 static int 1538 nlm_init_fh_by_vp(vnode_t *vp, struct netobj *fh, rpcvers_t *lm_vers) 1539 { 1540 mntinfo_t *mi = VTOMI(vp); 1541 1542 /* 1543 * Too bad the NFS code doesn't just carry the FH 1544 * in a netobj or a netbuf. 1545 */ 1546 switch (mi->mi_vers) { 1547 case NFS_V3: 1548 /* See nfs3_frlock() */ 1549 *lm_vers = NLM4_VERS; 1550 fh->n_len = VTOFH3(vp)->fh3_length; 1551 fh->n_bytes = (char *)&(VTOFH3(vp)->fh3_u.data); 1552 break; 1553 1554 case NFS_VERSION: 1555 /* See nfs_frlock() */ 1556 *lm_vers = NLM_VERS; 1557 fh->n_len = sizeof (fhandle_t); 1558 /* LINTED E_BAD_PTR_CAST_ALIGN */ 1559 fh->n_bytes = (char *)VTOFH(vp); 1560 break; 1561 default: 1562 return (ENOSYS); 1563 } 1564 1565 return (0); 1566 } 1567 1568 /* 1569 * Send SIGLOST to the process identified by pid. 1570 * NOTE: called when NLM decides to remove lock 1571 * or share reservation ownder by the process 1572 * by force. 1573 */ 1574 static void 1575 nlm_send_siglost(pid_t pid) 1576 { 1577 proc_t *p; 1578 1579 mutex_enter(&pidlock); 1580 p = prfind(pid); 1581 if (p != NULL) 1582 psignal(p, SIGLOST); 1583 1584 mutex_exit(&pidlock); 1585 } 1586 1587 static int 1588 nlm_map_clnt_stat(enum clnt_stat stat) 1589 { 1590 switch (stat) { 1591 case RPC_SUCCESS: 1592 return (0); 1593 1594 case RPC_TIMEDOUT: 1595 case RPC_PROGUNAVAIL: 1596 return (EAGAIN); 1597 1598 case RPC_INTR: 1599 return (EINTR); 1600 1601 default: 1602 return (EINVAL); 1603 } 1604 } 1605 1606 static int 1607 nlm_map_status(enum nlm4_stats stat) 1608 { 1609 switch (stat) { 1610 case nlm4_granted: 1611 return (0); 1612 1613 case nlm4_denied: 1614 return (EAGAIN); 1615 1616 case nlm4_denied_nolocks: 1617 return (ENOLCK); 1618 1619 case nlm4_blocked: 1620 return (EAGAIN); 1621 1622 case nlm4_denied_grace_period: 1623 return (EAGAIN); 1624 1625 case nlm4_deadlck: 1626 return (EDEADLK); 1627 1628 case nlm4_rofs: 1629 return (EROFS); 1630 1631 case nlm4_stale_fh: 1632 return (ESTALE); 1633 1634 case nlm4_fbig: 1635 return (EFBIG); 1636 1637 case nlm4_failed: 1638 return (EACCES); 1639 1640 default: 1641 return (EINVAL); 1642 } 1643 } 1644