1/* 2 * Copyright (c) 2002-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/*- 29 * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 1. Redistributions of source code must retain the above copyright 35 * notice, this list of conditions and the following disclaimer. 36 * 2. Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditions and the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * 3. Berkeley Software Design Inc's name may not be used to endorse or 40 * promote products derived from this software without specific prior 41 * written permission. 42 * 43 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND 44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE 47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 * 55 * from BSDI nfs_lock.c,v 2.4 1998/12/14 23:49:56 jch Exp 56 */ 57 58#include <sys/cdefs.h> 59#include <sys/param.h> 60#include <sys/systm.h> 61#include <sys/fcntl.h> 62#include <sys/kernel.h> /* for hz */ 63#include <sys/file_internal.h> 64#include <sys/malloc.h> 65#include <sys/lockf.h> /* for hz */ /* Must come after sys/malloc.h */ 66#include <sys/kpi_mbuf.h> 67#include <sys/mount_internal.h> 68#include <sys/proc_internal.h> /* for p_start */ 69#include <sys/kauth.h> 70#include <sys/resourcevar.h> 71#include <sys/socket.h> 72#include <sys/unistd.h> 73#include <sys/user.h> 74#include <sys/vnode_internal.h> 75 76#include <kern/thread.h> 77#include <kern/host.h> 78 79#include <machine/limits.h> 80 81#include <net/if.h> 82 83#include <nfs/rpcv2.h> 84#include <nfs/nfsproto.h> 85#include <nfs/nfs.h> 86#include <nfs/nfs_gss.h> 87#include <nfs/nfsmount.h> 88#include <nfs/nfsnode.h> 89#include <nfs/nfs_lock.h> 90 91#include <mach/host_priv.h> 92#include <mach/mig_errors.h> 93#include <mach/host_special_ports.h> 94#include <lockd/lockd_mach.h> 95 96extern void ipc_port_release_send(ipc_port_t); 97 98/* 99 * pending lock request messages are kept in this queue which is 100 * kept sorted by transaction ID (xid). 101 */ 102static uint64_t nfs_lockxid = 0; 103static LOCKD_MSG_QUEUE nfs_pendlockq; 104 105/* list of mounts that are (potentially) making lockd requests */ 106TAILQ_HEAD(nfs_lockd_mount_list,nfsmount) nfs_lockd_mount_list; 107 108static lck_grp_t *nfs_lock_lck_grp; 109static lck_mtx_t *nfs_lock_mutex; 110 111void nfs_lockdmsg_enqueue(LOCKD_MSG_REQUEST *); 112void nfs_lockdmsg_dequeue(LOCKD_MSG_REQUEST *); 113int nfs_lockdmsg_compare_to_answer(LOCKD_MSG_REQUEST *, struct lockd_ans *); 114LOCKD_MSG_REQUEST *nfs_lockdmsg_find_by_answer(struct lockd_ans *); 115LOCKD_MSG_REQUEST *nfs_lockdmsg_find_by_xid(uint64_t); 116uint64_t nfs_lockxid_get(void); 117int nfs_lockd_send_request(LOCKD_MSG *, int); 118 119/* 120 * initialize global nfs lock state 121 */ 122void 123nfs_lockinit(void) 124{ 125 TAILQ_INIT(&nfs_pendlockq); 126 TAILQ_INIT(&nfs_lockd_mount_list); 127 128 nfs_lock_lck_grp = lck_grp_alloc_init("nfs_lock", LCK_GRP_ATTR_NULL); 129 nfs_lock_mutex = lck_mtx_alloc_init(nfs_lock_lck_grp, LCK_ATTR_NULL); 130} 131 132/* 133 * Register a mount as (potentially) making lockd requests. 134 */ 135void 136nfs_lockd_mount_register(struct nfsmount *nmp) 137{ 138 lck_mtx_lock(nfs_lock_mutex); 139 TAILQ_INSERT_HEAD(&nfs_lockd_mount_list, nmp, nm_ldlink); 140 nfs_lockd_mounts++; 141 lck_mtx_unlock(nfs_lock_mutex); 142} 143 144/* 145 * Unregister a mount as (potentially) making lockd requests. 146 * 147 * When the lockd mount count drops to zero, then send a shutdown request to 148 * lockd if we've sent any requests to it. 149 */ 150void 151nfs_lockd_mount_unregister(struct nfsmount *nmp) 152{ 153 int send_shutdown; 154 mach_port_t lockd_port = IPC_PORT_NULL; 155 kern_return_t kr; 156 157 lck_mtx_lock(nfs_lock_mutex); 158 if (nmp->nm_ldlink.tqe_next == NFSNOLIST) { 159 lck_mtx_unlock(nfs_lock_mutex); 160 return; 161 } 162 163 TAILQ_REMOVE(&nfs_lockd_mount_list, nmp, nm_ldlink); 164 nmp->nm_ldlink.tqe_next = NFSNOLIST; 165 166 nfs_lockd_mounts--; 167 168 /* send a shutdown request if there are no more lockd mounts */ 169 send_shutdown = ((nfs_lockd_mounts == 0) && nfs_lockd_request_sent); 170 if (send_shutdown) 171 nfs_lockd_request_sent = 0; 172 173 lck_mtx_unlock(nfs_lock_mutex); 174 175 if (!send_shutdown) 176 return; 177 178 /* 179 * Let lockd know that it is no longer needed for any NFS mounts 180 */ 181 kr = host_get_lockd_port(host_priv_self(), &lockd_port); 182 if ((kr != KERN_SUCCESS) || !IPC_PORT_VALID(lockd_port)) { 183 printf("nfs_lockd_mount_change: shutdown couldn't get port, kr %d, port %s\n", 184 kr, (lockd_port == IPC_PORT_NULL) ? "NULL" : 185 (lockd_port == IPC_PORT_DEAD) ? "DEAD" : "VALID"); 186 return; 187 } 188 189 kr = lockd_shutdown(lockd_port); 190 if (kr != KERN_SUCCESS) 191 printf("nfs_lockd_mount_change: shutdown %d\n", kr); 192 193 ipc_port_release_send(lockd_port); 194} 195 196/* 197 * insert a lock request message into the pending queue 198 * (nfs_lock_mutex must be held) 199 */ 200void 201nfs_lockdmsg_enqueue(LOCKD_MSG_REQUEST *msgreq) 202{ 203 LOCKD_MSG_REQUEST *mr; 204 205 mr = TAILQ_LAST(&nfs_pendlockq, nfs_lock_msg_queue); 206 if (!mr || (msgreq->lmr_msg.lm_xid > mr->lmr_msg.lm_xid)) { 207 /* fast path: empty queue or new largest xid */ 208 TAILQ_INSERT_TAIL(&nfs_pendlockq, msgreq, lmr_next); 209 return; 210 } 211 /* slow path: need to walk list to find insertion point */ 212 while (mr && (msgreq->lmr_msg.lm_xid > mr->lmr_msg.lm_xid)) { 213 mr = TAILQ_PREV(mr, nfs_lock_msg_queue, lmr_next); 214 } 215 if (mr) { 216 TAILQ_INSERT_AFTER(&nfs_pendlockq, mr, msgreq, lmr_next); 217 } else { 218 TAILQ_INSERT_HEAD(&nfs_pendlockq, msgreq, lmr_next); 219 } 220} 221 222/* 223 * remove a lock request message from the pending queue 224 * (nfs_lock_mutex must be held) 225 */ 226void 227nfs_lockdmsg_dequeue(LOCKD_MSG_REQUEST *msgreq) 228{ 229 TAILQ_REMOVE(&nfs_pendlockq, msgreq, lmr_next); 230} 231 232/* 233 * find a pending lock request message by xid 234 * 235 * We search from the head of the list assuming that the message we're 236 * looking for is for an older request (because we have an answer to it). 237 * This assumes that lock request will be answered primarily in FIFO order. 238 * However, this may not be the case if there are blocked requests. We may 239 * want to move blocked requests to a separate queue (but that'll complicate 240 * duplicate xid checking). 241 * 242 * (nfs_lock_mutex must be held) 243 */ 244LOCKD_MSG_REQUEST * 245nfs_lockdmsg_find_by_xid(uint64_t lockxid) 246{ 247 LOCKD_MSG_REQUEST *mr; 248 249 TAILQ_FOREACH(mr, &nfs_pendlockq, lmr_next) { 250 if (mr->lmr_msg.lm_xid == lockxid) 251 return mr; 252 if (mr->lmr_msg.lm_xid > lockxid) 253 return NULL; 254 } 255 return mr; 256} 257 258/* 259 * Because we can't depend on nlm_granted messages containing the same 260 * cookie we sent with the original lock request, we need code to test 261 * if an nlm_granted answer matches the lock request. We also need code 262 * that can find a lockd message based solely on the nlm_granted answer. 263 */ 264 265/* 266 * compare lockd message to answer 267 * 268 * returns 0 on equality and 1 if different 269 */ 270int 271nfs_lockdmsg_compare_to_answer(LOCKD_MSG_REQUEST *msgreq, struct lockd_ans *ansp) 272{ 273 if (!(ansp->la_flags & LOCKD_ANS_LOCK_INFO)) 274 return 1; 275 if (msgreq->lmr_msg.lm_fl.l_pid != ansp->la_pid) 276 return 1; 277 if (msgreq->lmr_msg.lm_fl.l_start != ansp->la_start) 278 return 1; 279 if (msgreq->lmr_msg.lm_fl.l_len != ansp->la_len) 280 return 1; 281 if (msgreq->lmr_msg.lm_fh_len != ansp->la_fh_len) 282 return 1; 283 if (bcmp(msgreq->lmr_msg.lm_fh, ansp->la_fh, ansp->la_fh_len)) 284 return 1; 285 return 0; 286} 287 288/* 289 * find a pending lock request message based on the lock info provided 290 * in the lockd_ans/nlm_granted data. We need this because we can't 291 * depend on nlm_granted messages containing the same cookie we sent 292 * with the original lock request. 293 * 294 * We search from the head of the list assuming that the message we're 295 * looking for is for an older request (because we have an answer to it). 296 * This assumes that lock request will be answered primarily in FIFO order. 297 * However, this may not be the case if there are blocked requests. We may 298 * want to move blocked requests to a separate queue (but that'll complicate 299 * duplicate xid checking). 300 * 301 * (nfs_lock_mutex must be held) 302 */ 303LOCKD_MSG_REQUEST * 304nfs_lockdmsg_find_by_answer(struct lockd_ans *ansp) 305{ 306 LOCKD_MSG_REQUEST *mr; 307 308 if (!(ansp->la_flags & LOCKD_ANS_LOCK_INFO)) 309 return NULL; 310 TAILQ_FOREACH(mr, &nfs_pendlockq, lmr_next) { 311 if (!nfs_lockdmsg_compare_to_answer(mr, ansp)) 312 break; 313 } 314 return mr; 315} 316 317/* 318 * return the next unique lock request transaction ID 319 * (nfs_lock_mutex must be held) 320 */ 321uint64_t 322nfs_lockxid_get(void) 323{ 324 LOCKD_MSG_REQUEST *mr; 325 326 /* derive initial lock xid from system time */ 327 if (!nfs_lockxid) { 328 /* 329 * Note: it's OK if this code inits nfs_lockxid to 0 (for example, 330 * due to a broken clock) because we immediately increment it 331 * and we guarantee to never use xid 0. So, nfs_lockxid should only 332 * ever be 0 the first time this function is called. 333 */ 334 struct timeval tv; 335 microtime(&tv); 336 nfs_lockxid = (uint64_t)tv.tv_sec << 12; 337 } 338 339 /* make sure we get a unique xid */ 340 do { 341 /* Skip zero xid if it should ever happen. */ 342 if (++nfs_lockxid == 0) 343 nfs_lockxid++; 344 if (!(mr = TAILQ_LAST(&nfs_pendlockq, nfs_lock_msg_queue)) || 345 (mr->lmr_msg.lm_xid < nfs_lockxid)) { 346 /* fast path: empty queue or new largest xid */ 347 break; 348 } 349 /* check if xid is already in use */ 350 } while (nfs_lockdmsg_find_by_xid(nfs_lockxid)); 351 352 return nfs_lockxid; 353} 354 355#define MACH_MAX_TRIES 3 356 357int 358nfs_lockd_send_request(LOCKD_MSG *msg, int interruptable) 359{ 360 kern_return_t kr; 361 int retries = 0; 362 mach_port_t lockd_port = IPC_PORT_NULL; 363 364 kr = host_get_lockd_port(host_priv_self(), &lockd_port); 365 if (kr != KERN_SUCCESS || !IPC_PORT_VALID(lockd_port)) 366 return (ENOTSUP); 367 368 do { 369 /* In the kernel all mach messaging is interruptable */ 370 do { 371 kr = lockd_request( 372 lockd_port, 373 msg->lm_version, 374 msg->lm_flags, 375 msg->lm_xid, 376 msg->lm_fl.l_start, 377 msg->lm_fl.l_len, 378 msg->lm_fl.l_pid, 379 msg->lm_fl.l_type, 380 msg->lm_fl.l_whence, 381 (uint32_t *)&msg->lm_addr, 382 (uint32_t *)&msg->lm_cred, 383 msg->lm_fh_len, 384 msg->lm_fh); 385 if (kr != KERN_SUCCESS) 386 printf("lockd_request received %d!\n", kr); 387 } while (!interruptable && kr == MACH_SEND_INTERRUPTED); 388 } while (kr == MIG_SERVER_DIED && retries++ < MACH_MAX_TRIES); 389 390 ipc_port_release_send(lockd_port); 391 switch (kr) { 392 case MACH_SEND_INTERRUPTED: 393 return (EINTR); 394 default: 395 /* 396 * Other MACH or MIG errors we will retry. Eventually 397 * we will call nfs_down and allow the user to disable 398 * locking. 399 */ 400 return (EAGAIN); 401 } 402 return (kr); 403} 404 405 406/* 407 * NFS advisory byte-level locks (client) 408 */ 409int 410nfs3_lockd_request( 411 nfsnode_t np, 412 int type, 413 LOCKD_MSG_REQUEST *msgreq, 414 int flags, 415 thread_t thd) 416{ 417 LOCKD_MSG *msg = &msgreq->lmr_msg; 418 int error, error2; 419 int interruptable, slpflag; 420 struct nfsmount *nmp; 421 struct timeval now; 422 int timeo, starttime, endtime, lastmsg, wentdown = 0; 423 struct timespec ts; 424 struct sockaddr *saddr; 425 426 nmp = NFSTONMP(np); 427 if (!nmp || !nmp->nm_saddr) 428 return (ENXIO); 429 430 lck_mtx_lock(&nmp->nm_lock); 431 saddr = nmp->nm_saddr; 432 bcopy(saddr, &msg->lm_addr, min(sizeof msg->lm_addr, saddr->sa_len)); 433 if (nmp->nm_vers == NFS_VER3) 434 msg->lm_flags |= LOCKD_MSG_NFSV3; 435 436 if (nmp->nm_sotype != SOCK_DGRAM) 437 msg->lm_flags |= LOCKD_MSG_TCP; 438 439 microuptime(&now); 440 starttime = now.tv_sec; 441 lastmsg = now.tv_sec - ((nmp->nm_tprintf_delay) - (nmp->nm_tprintf_initial_delay)); 442 interruptable = NMFLAG(nmp, INTR); 443 lck_mtx_unlock(&nmp->nm_lock); 444 445 lck_mtx_lock(nfs_lock_mutex); 446 447 /* allocate unique xid */ 448 msg->lm_xid = nfs_lockxid_get(); 449 nfs_lockdmsg_enqueue(msgreq); 450 451 timeo = 4; 452 453 for (;;) { 454 nfs_lockd_request_sent = 1; 455 456 /* need to drop nfs_lock_mutex while calling nfs_lockd_send_request() */ 457 lck_mtx_unlock(nfs_lock_mutex); 458 error = nfs_lockd_send_request(msg, interruptable); 459 lck_mtx_lock(nfs_lock_mutex); 460 if (error && error != EAGAIN) 461 break; 462 463 /* 464 * Always wait for an answer. Not waiting for unlocks could 465 * cause a lock to be left if the unlock request gets dropped. 466 */ 467 468 /* 469 * Retry if it takes too long to get a response. 470 * 471 * The timeout numbers were picked out of thin air... they start 472 * at 4 and double each timeout with a max of 30 seconds. 473 * 474 * In order to maintain responsiveness, we pass a small timeout 475 * to msleep and calculate the timeouts ourselves. This allows 476 * us to pick up on mount changes quicker. 477 */ 478wait_for_granted: 479 error = EWOULDBLOCK; 480 slpflag = (interruptable && (type != F_UNLCK)) ? PCATCH : 0; 481 ts.tv_sec = 2; 482 ts.tv_nsec = 0; 483 microuptime(&now); 484 endtime = now.tv_sec + timeo; 485 while (now.tv_sec < endtime) { 486 error = error2 = 0; 487 if (!msgreq->lmr_answered) { 488 error = msleep(msgreq, nfs_lock_mutex, slpflag | PUSER, "lockd", &ts); 489 slpflag = 0; 490 } 491 if (msgreq->lmr_answered) { 492 /* 493 * Note: it's possible to have a lock granted at 494 * essentially the same time that we get interrupted. 495 * Since the lock may be granted, we can't return an 496 * error from this request or we might not unlock the 497 * lock that's been granted. 498 */ 499 nmp = NFSTONMP(np); 500 if ((msgreq->lmr_errno == ENOTSUP) && nmp && 501 (nmp->nm_state & NFSSTA_LOCKSWORK)) { 502 /* 503 * We have evidence that locks work, yet lockd 504 * returned ENOTSUP. This is probably because 505 * it was unable to contact the server's lockd 506 * to send it the request. 507 * 508 * Because we know locks work, we'll consider 509 * this failure to be a timeout. 510 */ 511 error = EWOULDBLOCK; 512 } else { 513 error = 0; 514 } 515 break; 516 } 517 if (error != EWOULDBLOCK) 518 break; 519 /* check that we still have our mount... */ 520 /* ...and that we still support locks */ 521 /* ...and that there isn't a recovery pending */ 522 nmp = NFSTONMP(np); 523 if ((error2 = nfs_sigintr(nmp, NULL, NULL, 0))) { 524 error = error2; 525 if (type == F_UNLCK) 526 printf("nfs3_lockd_request: aborting unlock request, error %d\n", error); 527 break; 528 } 529 lck_mtx_lock(&nmp->nm_lock); 530 if (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED) { 531 lck_mtx_unlock(&nmp->nm_lock); 532 break; 533 } 534 if ((nmp->nm_state & NFSSTA_RECOVER) && !(flags & R_RECOVER)) { 535 /* recovery pending... return an error that'll get this operation restarted */ 536 error = NFSERR_GRACE; 537 lck_mtx_unlock(&nmp->nm_lock); 538 break; 539 } 540 interruptable = NMFLAG(nmp, INTR); 541 lck_mtx_unlock(&nmp->nm_lock); 542 microuptime(&now); 543 } 544 if (error) { 545 /* check that we still have our mount... */ 546 nmp = NFSTONMP(np); 547 if ((error2 = nfs_sigintr(nmp, NULL, NULL, 0))) { 548 error = error2; 549 if (error2 != EINTR) { 550 if (type == F_UNLCK) 551 printf("nfs3_lockd_request: aborting unlock request, error %d\n", error); 552 break; 553 } 554 } 555 /* ...and that we still support locks */ 556 lck_mtx_lock(&nmp->nm_lock); 557 if (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED) { 558 if (error == EWOULDBLOCK) 559 error = ENOTSUP; 560 lck_mtx_unlock(&nmp->nm_lock); 561 break; 562 } 563 /* ...and that there isn't a recovery pending */ 564 if ((error == EWOULDBLOCK) && (nmp->nm_state & NFSSTA_RECOVER) && !(flags & R_RECOVER)) { 565 /* recovery pending... return to allow recovery to occur */ 566 error = NFSERR_DENIED; 567 lck_mtx_unlock(&nmp->nm_lock); 568 break; 569 } 570 interruptable = NMFLAG(nmp, INTR); 571 if ((error != EWOULDBLOCK) || 572 ((nmp->nm_state & NFSSTA_RECOVER) && !(flags & R_RECOVER)) || 573 ((flags & R_RECOVER) && ((now.tv_sec - starttime) > 30))) { 574 if ((error == EWOULDBLOCK) && (flags & R_RECOVER)) { 575 /* give up if this is for recovery and taking too long */ 576 error = ETIMEDOUT; 577 } else if ((nmp->nm_state & NFSSTA_RECOVER) && !(flags & R_RECOVER)) { 578 /* recovery pending... return an error that'll get this operation restarted */ 579 error = NFSERR_GRACE; 580 } 581 lck_mtx_unlock(&nmp->nm_lock); 582 /* 583 * We're going to bail on this request. 584 * If we were a blocked lock request, send a cancel. 585 */ 586 if ((msgreq->lmr_errno == EINPROGRESS) && 587 !(msg->lm_flags & LOCKD_MSG_CANCEL)) { 588 /* set this request up as a cancel */ 589 msg->lm_flags |= LOCKD_MSG_CANCEL; 590 nfs_lockdmsg_dequeue(msgreq); 591 msg->lm_xid = nfs_lockxid_get(); 592 nfs_lockdmsg_enqueue(msgreq); 593 msgreq->lmr_saved_errno = error; 594 msgreq->lmr_errno = 0; 595 msgreq->lmr_answered = 0; 596 /* reset timeout */ 597 timeo = 2; 598 /* send cancel request */ 599 continue; 600 } 601 break; 602 } 603 604 /* warn if we're not getting any response */ 605 microuptime(&now); 606 if ((msgreq->lmr_errno != EINPROGRESS) && 607 !(msg->lm_flags & LOCKD_MSG_DENIED_GRACE) && 608 (nmp->nm_tprintf_initial_delay != 0) && 609 ((lastmsg + nmp->nm_tprintf_delay) < now.tv_sec)) { 610 lck_mtx_unlock(&nmp->nm_lock); 611 lastmsg = now.tv_sec; 612 nfs_down(nmp, thd, 0, NFSSTA_LOCKTIMEO, "lockd not responding", 0); 613 wentdown = 1; 614 } else 615 lck_mtx_unlock(&nmp->nm_lock); 616 617 if (msgreq->lmr_errno == EINPROGRESS) { 618 /* 619 * We've got a blocked lock request that we are 620 * going to retry. First, we'll want to try to 621 * send a cancel for the previous request. 622 * 623 * Clear errno so if we don't get a response 624 * to the resend we'll call nfs_down(). 625 * Also reset timeout because we'll expect a 626 * quick response to the cancel/resend (even if 627 * it is NLM_BLOCKED). 628 */ 629 msg->lm_flags |= LOCKD_MSG_CANCEL; 630 nfs_lockdmsg_dequeue(msgreq); 631 msg->lm_xid = nfs_lockxid_get(); 632 nfs_lockdmsg_enqueue(msgreq); 633 msgreq->lmr_saved_errno = msgreq->lmr_errno; 634 msgreq->lmr_errno = 0; 635 msgreq->lmr_answered = 0; 636 timeo = 2; 637 /* send cancel then resend request */ 638 continue; 639 } 640 641 /* 642 * We timed out, so we will resend the request. 643 */ 644 if (!(flags & R_RECOVER)) 645 timeo *= 2; 646 if (timeo > 30) 647 timeo = 30; 648 /* resend request */ 649 continue; 650 } 651 652 /* we got a reponse, so the server's lockd is OK */ 653 nfs_up(NFSTONMP(np), thd, NFSSTA_LOCKTIMEO, 654 wentdown ? "lockd alive again" : NULL); 655 wentdown = 0; 656 657 if (msgreq->lmr_answered && (msg->lm_flags & LOCKD_MSG_DENIED_GRACE)) { 658 /* 659 * The lock request was denied because the server lockd is 660 * still in its grace period. So, we need to try the 661 * request again in a little bit. Return the GRACE error so 662 * the higher levels can perform the retry. 663 */ 664 msgreq->lmr_saved_errno = msgreq->lmr_errno = error = NFSERR_GRACE; 665 } 666 667 if (msgreq->lmr_errno == EINPROGRESS) { 668 /* got NLM_BLOCKED response */ 669 /* need to wait for NLM_GRANTED */ 670 timeo = 30; 671 msgreq->lmr_answered = 0; 672 goto wait_for_granted; 673 } 674 675 if ((msg->lm_flags & LOCKD_MSG_CANCEL) && 676 (msgreq->lmr_saved_errno == EINPROGRESS)) { 677 /* 678 * We just got a successful reply to the 679 * cancel of the previous blocked lock request. 680 * Now, go ahead and return a DENIED error so the 681 * higher levels can resend the request. 682 */ 683 msg->lm_flags &= ~LOCKD_MSG_CANCEL; 684 nfs_lockdmsg_dequeue(msgreq); 685 error = NFSERR_DENIED; 686 break; 687 } 688 689 /* 690 * If the blocked lock request was cancelled. 691 * Restore the error condition from when we 692 * originally bailed on the request. 693 */ 694 if (msg->lm_flags & LOCKD_MSG_CANCEL) { 695 msg->lm_flags &= ~LOCKD_MSG_CANCEL; 696 error = msgreq->lmr_saved_errno; 697 } else { 698 error = msgreq->lmr_errno; 699 } 700 701 nmp = NFSTONMP(np); 702 if ((error == ENOTSUP) && nmp && !(nmp->nm_state & NFSSTA_LOCKSWORK)) { 703 /* 704 * We have NO evidence that locks work and lockd 705 * returned ENOTSUP. Let's take this as a hint 706 * that locks aren't supported and disable them 707 * for this mount. 708 */ 709 nfs_lockdmsg_dequeue(msgreq); 710 lck_mtx_unlock(nfs_lock_mutex); 711 lck_mtx_lock(&nmp->nm_lock); 712 if (nmp->nm_lockmode == NFS_LOCK_MODE_ENABLED) { 713 nmp->nm_lockmode = NFS_LOCK_MODE_DISABLED; 714 nfs_lockd_mount_unregister(nmp); 715 } 716 nmp->nm_state &= ~NFSSTA_LOCKTIMEO; 717 lck_mtx_unlock(&nmp->nm_lock); 718 printf("lockd returned ENOTSUP, disabling locks for nfs server: %s\n", 719 vfs_statfs(nmp->nm_mountp)->f_mntfromname); 720 return (error); 721 } 722 if (!error) { 723 /* record that NFS file locking has worked on this mount */ 724 if (nmp) { 725 lck_mtx_lock(&nmp->nm_lock); 726 if (!(nmp->nm_state & NFSSTA_LOCKSWORK)) 727 nmp->nm_state |= NFSSTA_LOCKSWORK; 728 lck_mtx_unlock(&nmp->nm_lock); 729 } 730 } 731 break; 732 } 733 734 nfs_lockdmsg_dequeue(msgreq); 735 736 lck_mtx_unlock(nfs_lock_mutex); 737 738 return (error); 739} 740 741/* 742 * Send an NLM LOCK message to the server 743 */ 744int 745nfs3_setlock_rpc( 746 nfsnode_t np, 747 struct nfs_open_file *nofp, 748 struct nfs_file_lock *nflp, 749 int reclaim, 750 int flags, 751 thread_t thd, 752 kauth_cred_t cred) 753{ 754 struct nfs_lock_owner *nlop = nflp->nfl_owner; 755 struct nfsmount *nmp; 756 int error; 757 LOCKD_MSG_REQUEST msgreq; 758 LOCKD_MSG *msg; 759 760 nmp = NFSTONMP(np); 761 if (nfs_mount_gone(nmp)) 762 return (ENXIO); 763 764 if (!nlop->nlo_open_owner) { 765 nfs_open_owner_ref(nofp->nof_owner); 766 nlop->nlo_open_owner = nofp->nof_owner; 767 } 768 if ((error = nfs_lock_owner_set_busy(nlop, thd))) 769 return (error); 770 771 /* set up lock message request structure */ 772 bzero(&msgreq, sizeof(msgreq)); 773 msg = &msgreq.lmr_msg; 774 msg->lm_version = LOCKD_MSG_VERSION; 775 if ((nflp->nfl_flags & NFS_FILE_LOCK_WAIT) && !reclaim) 776 msg->lm_flags |= LOCKD_MSG_BLOCK; 777 if (reclaim) 778 msg->lm_flags |= LOCKD_MSG_RECLAIM; 779 msg->lm_fh_len = (nmp->nm_vers == NFS_VER2) ? NFSX_V2FH : np->n_fhsize; 780 bcopy(np->n_fhp, msg->lm_fh, msg->lm_fh_len); 781 cru2x(cred, &msg->lm_cred); 782 783 msg->lm_fl.l_whence = SEEK_SET; 784 msg->lm_fl.l_start = nflp->nfl_start; 785 msg->lm_fl.l_len = NFS_FLOCK_LENGTH(nflp->nfl_start, nflp->nfl_end); 786 msg->lm_fl.l_type = nflp->nfl_type; 787 msg->lm_fl.l_pid = nlop->nlo_pid; 788 789 error = nfs3_lockd_request(np, 0, &msgreq, flags, thd); 790 791 nfs_lock_owner_clear_busy(nlop); 792 return (error); 793} 794 795/* 796 * Send an NLM UNLOCK message to the server 797 */ 798int 799nfs3_unlock_rpc( 800 nfsnode_t np, 801 struct nfs_lock_owner *nlop, 802 __unused int type, 803 uint64_t start, 804 uint64_t end, 805 int flags, 806 thread_t thd, 807 kauth_cred_t cred) 808{ 809 struct nfsmount *nmp; 810 LOCKD_MSG_REQUEST msgreq; 811 LOCKD_MSG *msg; 812 813 nmp = NFSTONMP(np); 814 if (!nmp) 815 return (ENXIO); 816 817 /* set up lock message request structure */ 818 bzero(&msgreq, sizeof(msgreq)); 819 msg = &msgreq.lmr_msg; 820 msg->lm_version = LOCKD_MSG_VERSION; 821 msg->lm_fh_len = (nmp->nm_vers == NFS_VER2) ? NFSX_V2FH : np->n_fhsize; 822 bcopy(np->n_fhp, msg->lm_fh, msg->lm_fh_len); 823 cru2x(cred, &msg->lm_cred); 824 825 msg->lm_fl.l_whence = SEEK_SET; 826 msg->lm_fl.l_start = start; 827 msg->lm_fl.l_len = NFS_FLOCK_LENGTH(start, end); 828 msg->lm_fl.l_type = F_UNLCK; 829 msg->lm_fl.l_pid = nlop->nlo_pid; 830 831 return (nfs3_lockd_request(np, F_UNLCK, &msgreq, flags, thd)); 832} 833 834/* 835 * Send an NLM LOCK TEST message to the server 836 */ 837int 838nfs3_getlock_rpc( 839 nfsnode_t np, 840 struct nfs_lock_owner *nlop, 841 struct flock *fl, 842 uint64_t start, 843 uint64_t end, 844 vfs_context_t ctx) 845{ 846 struct nfsmount *nmp; 847 int error; 848 LOCKD_MSG_REQUEST msgreq; 849 LOCKD_MSG *msg; 850 851 nmp = NFSTONMP(np); 852 if (nfs_mount_gone(nmp)) 853 return (ENXIO); 854 855 /* set up lock message request structure */ 856 bzero(&msgreq, sizeof(msgreq)); 857 msg = &msgreq.lmr_msg; 858 msg->lm_version = LOCKD_MSG_VERSION; 859 msg->lm_flags |= LOCKD_MSG_TEST; 860 msg->lm_fh_len = (nmp->nm_vers == NFS_VER2) ? NFSX_V2FH : np->n_fhsize; 861 bcopy(np->n_fhp, msg->lm_fh, msg->lm_fh_len); 862 cru2x(vfs_context_ucred(ctx), &msg->lm_cred); 863 864 msg->lm_fl.l_whence = SEEK_SET; 865 msg->lm_fl.l_start = start; 866 msg->lm_fl.l_len = NFS_FLOCK_LENGTH(start, end); 867 msg->lm_fl.l_type = fl->l_type; 868 msg->lm_fl.l_pid = nlop->nlo_pid; 869 870 error = nfs3_lockd_request(np, 0, &msgreq, 0, vfs_context_thread(ctx)); 871 872 if (!error && (msg->lm_flags & LOCKD_MSG_TEST) && !msgreq.lmr_errno) { 873 if (msg->lm_fl.l_type != F_UNLCK) { 874 fl->l_type = msg->lm_fl.l_type; 875 fl->l_pid = msg->lm_fl.l_pid; 876 fl->l_start = msg->lm_fl.l_start; 877 fl->l_len = msg->lm_fl.l_len; 878 fl->l_whence = SEEK_SET; 879 } else 880 fl->l_type = F_UNLCK; 881 } 882 883 return (error); 884} 885 886/* 887 * nfslockdans -- 888 * NFS advisory byte-level locks answer from the lock daemon. 889 */ 890int 891nfslockdans(proc_t p, struct lockd_ans *ansp) 892{ 893 LOCKD_MSG_REQUEST *msgreq; 894 int error; 895 896 /* Let root make this call. */ 897 error = proc_suser(p); 898 if (error) 899 return (error); 900 901 /* the version should match, or we're out of sync */ 902 if (ansp->la_version != LOCKD_ANS_VERSION) 903 return (EINVAL); 904 905 lck_mtx_lock(nfs_lock_mutex); 906 907 /* try to find the lockd message by transaction id (cookie) */ 908 msgreq = nfs_lockdmsg_find_by_xid(ansp->la_xid); 909 if (ansp->la_flags & LOCKD_ANS_GRANTED) { 910 /* 911 * We can't depend on the granted message having our cookie, 912 * so we check the answer against the lockd message found. 913 * If no message was found or it doesn't match the answer, 914 * we look for the lockd message by the answer's lock info. 915 */ 916 if (!msgreq || nfs_lockdmsg_compare_to_answer(msgreq, ansp)) 917 msgreq = nfs_lockdmsg_find_by_answer(ansp); 918 /* 919 * We need to make sure this request isn't being cancelled 920 * If it is, we don't want to accept the granted message. 921 */ 922 if (msgreq && (msgreq->lmr_msg.lm_flags & LOCKD_MSG_CANCEL)) 923 msgreq = NULL; 924 } 925 if (!msgreq) { 926 lck_mtx_unlock(nfs_lock_mutex); 927 return (EPIPE); 928 } 929 930 msgreq->lmr_errno = ansp->la_errno; 931 if ((msgreq->lmr_msg.lm_flags & LOCKD_MSG_TEST) && msgreq->lmr_errno == 0) { 932 if (ansp->la_flags & LOCKD_ANS_LOCK_INFO) { 933 if (ansp->la_flags & LOCKD_ANS_LOCK_EXCL) 934 msgreq->lmr_msg.lm_fl.l_type = F_WRLCK; 935 else 936 msgreq->lmr_msg.lm_fl.l_type = F_RDLCK; 937 msgreq->lmr_msg.lm_fl.l_pid = ansp->la_pid; 938 msgreq->lmr_msg.lm_fl.l_start = ansp->la_start; 939 msgreq->lmr_msg.lm_fl.l_len = ansp->la_len; 940 } else { 941 msgreq->lmr_msg.lm_fl.l_type = F_UNLCK; 942 } 943 } 944 if (ansp->la_flags & LOCKD_ANS_DENIED_GRACE) 945 msgreq->lmr_msg.lm_flags |= LOCKD_MSG_DENIED_GRACE; 946 947 msgreq->lmr_answered = 1; 948 lck_mtx_unlock(nfs_lock_mutex); 949 wakeup(msgreq); 950 951 return (0); 952} 953 954/* 955 * nfslockdnotify -- 956 * NFS host restart notification from the lock daemon. 957 * 958 * Used to initiate reclaiming of held locks when a server we 959 * have mounted reboots. 960 */ 961int 962nfslockdnotify(proc_t p, user_addr_t argp) 963{ 964 int error, i, headsize; 965 struct lockd_notify ln; 966 struct nfsmount *nmp; 967 struct sockaddr *saddr; 968 969 /* Let root make this call. */ 970 error = proc_suser(p); 971 if (error) 972 return (error); 973 974 headsize = (char*)&ln.ln_addr[0] - (char*)&ln.ln_version; 975 error = copyin(argp, &ln, headsize); 976 if (error) 977 return (error); 978 if (ln.ln_version != LOCKD_NOTIFY_VERSION) 979 return (EINVAL); 980 if ((ln.ln_addrcount < 1) || (ln.ln_addrcount > 128)) 981 return (EINVAL); 982 argp += headsize; 983 saddr = (struct sockaddr *)&ln.ln_addr[0]; 984 985 lck_mtx_lock(nfs_lock_mutex); 986 987 for (i=0; i < ln.ln_addrcount; i++) { 988 error = copyin(argp, &ln.ln_addr[0], sizeof(ln.ln_addr[0])); 989 if (error) 990 break; 991 argp += sizeof(ln.ln_addr[0]); 992 /* scan lockd mount list for match to this address */ 993 TAILQ_FOREACH(nmp, &nfs_lockd_mount_list, nm_ldlink) { 994 /* check if address matches this mount's server address */ 995 if (!nmp->nm_saddr || nfs_sockaddr_cmp(saddr, nmp->nm_saddr)) 996 continue; 997 /* We have a match! Mark it as needing recovery. */ 998 lck_mtx_lock(&nmp->nm_lock); 999 nfs_need_recover(nmp, 0); 1000 lck_mtx_unlock(&nmp->nm_lock); 1001 } 1002 } 1003 1004 lck_mtx_unlock(nfs_lock_mutex); 1005 1006 return (error); 1007} 1008 1009