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