1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27/* 28 * Portions Copyright 2007-2011 Apple Inc. 29 */ 30 31#include <mach/task.h> 32#include <mach/host_priv.h> 33#include <mach/host_special_ports.h> 34 35#include <sys/types.h> 36#include <sys/proc.h> 37#include <sys/malloc.h> 38#include <sys/mount.h> 39#include <sys/vnode.h> 40#include <sys/kauth.h> 41#include <sys/time.h> 42#include <sys/errno.h> 43#include <sys/queue.h> 44 45#include <kern/host.h> 46#include <kern/locks.h> 47 48#include <IOKit/IOLib.h> 49 50#include "autofs.h" 51#include "autofs_protUser.h" 52#include "triggers.h" 53#include "triggers_priv.h" 54 55static lck_grp_t *triggers_lck_grp; 56 57__private_extern__ int triggers_start(kmod_info_t *, void *); 58__private_extern__ int triggers_stop(kmod_info_t *, void *); 59 60/* XXX Get rid of this as soon as sys/malloc.h can be updated to define a real M_AUTOFS */ 61#define M_TRIGGERS M_TEMP 62 63/* 64 * TRUE if two fsids are equal. 65 */ 66#define FSIDS_EQUAL(fsid1, fsid2) \ 67 ((fsid1).val[0] == (fsid2).val[0] && \ 68 (fsid1).val[1] == (fsid2).val[1]) 69 70static lck_rw_t *resolved_triggers_rwlock; 71static TAILQ_HEAD(resolved_triggers, trigger_info) resolved_triggers = 72 TAILQ_HEAD_INITIALIZER(resolved_triggers); 73 74/* 75 * Timeout for unmounts. 76 */ 77static int mount_to; 78 79/* 80 * Set the mount timeout. 81 */ 82void 83trigger_set_mount_to(int newval) 84{ 85 mount_to = newval; 86} 87 88/* 89 * Unmount a file system by fsid. 90 * 91 * XXX - do this with an automountd upcall, so it doesn't try to unmount 92 * from a dead server? 93 */ 94static int 95unmount_triggered_mount(fsid_t *fsidp, int flags, vfs_context_t ctx) 96{ 97 return (vfs_unmountbyfsid(fsidp, flags | MNT_NOBLOCK, ctx)); 98} 99 100/* 101 * We've unmounted whatever was mounted atop this trigger, so 102 * remove it from the list of resolved triggers, bump its 103 * sequence number, and return a "this was unresolved" 104 * resolver_result_t for that. 105 * 106 * Must be called with the mutex held on ti. 107 */ 108static resolver_result_t 109trigger_make_unresolved(trigger_info_t *ti) 110{ 111 /* 112 * Remove this from the list of resolved triggers. 113 */ 114 if (ti->ti_flags & TF_RESOLVED) { 115 lck_rw_lock_exclusive(resolved_triggers_rwlock); 116 TAILQ_REMOVE(&resolved_triggers, ti, ti_entries); 117 lck_rw_unlock_exclusive(resolved_triggers_rwlock); 118 ti->ti_flags &= ~TF_RESOLVED; 119 } 120 121 /* 122 * The status of the trigger has changed, so bump the 123 * sequence number. 124 */ 125 ti->ti_seq++; 126 return (vfs_resolver_result(ti->ti_seq, RESOLVER_UNRESOLVED, 0)); 127} 128 129/* 130 * Sets the TF_INPROG flag on this trigger. 131 * ti->ti_lock should be held before this macro is called. 132 */ 133#define TRIGGER_BLOCK_OTHERS(ti) { \ 134 lck_mtx_assert((ti)->ti_lock, LCK_MTX_ASSERT_OWNED); \ 135 assert(!((ti)->ti_flags & TF_INPROG)); \ 136 (ti)->ti_flags |= TF_INPROG; \ 137} 138 139#define TRIGGER_UNBLOCK_OTHERS(ti) { \ 140 trigger_unblock_others(ti); \ 141} 142 143/* 144 * Clears the TF_INPROG flag, and wakes up those threads sleeping on 145 * fn_flags if TF_WAITING is set. 146 */ 147static void 148trigger_unblock_others(trigger_info_t *ti) 149{ 150 ti->ti_flags &= ~TF_INPROG; 151 if (ti->ti_flags & TF_WAITING) { 152 ti->ti_flags &= ~TF_WAITING; 153 wakeup(&ti->ti_flags); 154 } 155} 156 157static int 158trigger_do_mount_url(void *arg) 159{ 160 struct mount_url_callargs *argsp = arg; 161 mach_port_t automount_port; 162 int error; 163 kern_return_t ret; 164 165 error = auto_get_automountd_port(&automount_port); 166 if (error) 167 goto done; 168 169 ret = autofs_mount_url(automount_port, argsp->muc_url, 170 argsp->muc_mountpoint, argsp->muc_opts, argsp->muc_this_fsid, 171 argsp->muc_uid, argsp->muc_asid, 172 &argsp->muc_mounted_fsid, &argsp->muc_retflags, &error); 173 auto_release_port(automount_port); 174 if (ret != KERN_SUCCESS) { 175 IOLog("autofs: autofs_mount_url failed, status 0x%08x\n", ret); 176 error = EIO; /* XXX - process Mach errors */ 177 } 178 179done: 180 return (error); 181} 182 183/* 184 * Starting point for thread to handle mount requests with automountd. 185 */ 186static void 187trigger_mount_thread(void *arg) 188{ 189 struct trigger_callargs *argsp = arg; 190 vnode_t vp; 191 trigger_info_t *ti; 192 int error; 193 struct timeval now; 194 195 vp = argsp->tc_vp; 196 ti = argsp->tc_ti; 197 198 /* 199 * Make the appropriate upcall, and do whatever work is 200 * necessary to process its results. 201 */ 202 error = (*ti->ti_do_mount)(arg); 203 204 lck_mtx_lock(ti->ti_lock); 205 ti->ti_error = error; 206 207 /* 208 * If the mount succeeded, bump the sequence number, as this is 209 * a trigger state change, add this mount to the list of 210 * triggered mounts, and notify the VFS layer that the trigger 211 * has been resolved. 212 */ 213 if (error == 0) { 214 /* 215 * Grab an exclusive lock, so that if we get 216 * this unmounted out from under us before 217 * we add it to the list, the attempt to 218 * remove it from the list won't happen until 219 * after we've added it to the list (so we 220 * don't do a remove before the add, which will 221 * do nothing as it won't find the item to 222 * remove, leaving an orphaned entry). 223 * 224 * XXX - shouldn't the mutex on this entry suffice 225 * to serialize operations on this entry? 226 */ 227 lck_rw_lock_exclusive(resolved_triggers_rwlock); 228 229 /* 230 * Fill in the fsid of the mounted file system, and 231 * various flags, from the out parameters for the call. 232 */ 233 ti->ti_mounted_fsid = argsp->tc_mounted_fsid; 234 if (argsp->tc_retflags & MOUNT_RETF_DONTUNMOUNT) 235 ti->ti_flags |= TF_DONTUNMOUNT; 236 else 237 ti->ti_flags &= ~TF_DONTUNMOUNT; 238 if (argsp->tc_retflags & MOUNT_RETF_DONTPREUNMOUNT) 239 ti->ti_flags |= TF_DONTPREUNMOUNT; 240 else 241 ti->ti_flags &= ~TF_DONTPREUNMOUNT; 242 243 /* 244 * Mark it as having been referenced. 245 */ 246 microtime(&now); 247 ti->ti_ref_time = now.tv_sec; 248 249 /* 250 * Put it the end of the list of resolved triggers, 251 * and note that it's resolved. 252 * 253 * XXX - if it's already marked as resolved, note 254 * that? I.e., is that a "can't happen"? 255 * 256 * XXX - remove on unresolve, rearm, or both? 257 */ 258 if (!(ti->ti_flags & TF_RESOLVED)) { 259 ti->ti_flags |= TF_RESOLVED; 260 TAILQ_INSERT_TAIL(&resolved_triggers, ti, 261 ti_entries); 262 } 263 264 lck_rw_unlock_exclusive(resolved_triggers_rwlock); 265 266 ti->ti_seq++; 267 vnode_trigger_update(vp, 268 vfs_resolver_result(ti->ti_seq, RESOLVER_RESOLVED, 0)); 269 } 270 271 /* 272 * Notify threads waiting for mount that 273 * it's done. 274 */ 275 TRIGGER_UNBLOCK_OTHERS(ti); 276 lck_mtx_unlock(ti->ti_lock); 277 278 vnode_rele(vp); /* release usecount from trigger_resolve() */ 279 280 (*ti->ti_rel_mount_args)(argsp); 281 282 /* 283 * Release the iocount from trigger_resolve(); we can't 284 * do that until we're done with *ti, as, if the vnode 285 * gets deadfsed, *ti will be freed. 286 */ 287 vnode_put(vp); 288 289 thread_terminate(current_thread()); 290 /* NOTREACHED */ 291} 292 293static int trigger_thr_success = 0; 294 295/* 296 * As the name indicates, this must be called with ti locked. 297 */ 298static int 299wait_for_mount_locked(trigger_info_t *ti) 300{ 301 int error; 302 303 /* 304 * OK, we should wait. 305 */ 306 while (ti->ti_flags & TF_INPROG) { 307 ti->ti_flags |= TF_WAITING; 308 309 /* 310 * This wait is interruptable, so you can ^C out of 311 * a mount that's taking a long time. 312 */ 313 error = msleep(&ti->ti_flags, ti->ti_lock, PSOCK|PCATCH, 314 "triggered_mount", NULL); 315 if (error == EINTR || error == ERESTART) { 316 /* 317 * Decided not to wait for operation to 318 * finish after all. 319 */ 320 return (EINTR); 321 } 322 } 323 324 /* 325 * The mount operation finished; return the status with which 326 * it finished. 327 */ 328 return (ti->ti_error); 329} 330 331/* 332 * Resolve this trigger. 333 */ 334static resolver_result_t 335trigger_resolve(vnode_t vp, const struct componentname *cnp, 336 enum path_operation pop, __unused int flags, void *data, vfs_context_t ctx) 337{ 338 trigger_info_t *ti = data; 339 resolver_result_t result; 340 int pid = vfs_context_pid(ctx); 341 int error; 342 struct trigger_callargs *argsp; 343 kern_return_t ret; 344 345 /* 346 * If this is the last component, is the operation being done 347 * supposed to trigger a mount? 348 * (If it's not the last component, we'll be doing a lookup 349 * in it, so it must always trigger a mount, so we can do the 350 * lookup in the directory mounted on it.) 351 */ 352 if (cnp->cn_flags & ISLASTCN) { 353 switch (pop) { 354 355 case OP_MOUNT: 356 /* 357 * We're trying to mount something on this, which 358 * probably means somebody else already triggered 359 * the mount and we're trying to do the mount for 360 * them. Triggering a mount is thus pointless. 361 * 362 * XXX - do that only if there's a mount in progress? 363 * XXX - need to protect access to ti_seq with 364 * the mutex? 365 */ 366 return (vfs_resolver_result(ti->ti_seq, 367 RESOLVER_NOCHANGE, 0)); 368 369 case OP_UNMOUNT: 370 /* 371 * We don't care. 372 */ 373 return (vfs_resolver_result(ti->ti_seq, 374 RESOLVER_NOCHANGE, 0)); 375 376 case OP_LOOKUP: 377 /* 378 * Inappropriate on last component 379 */ 380 return (vfs_resolver_result(ti->ti_seq, 381 RESOLVER_NOCHANGE, 0)); 382 383 case OP_STATFS: 384 /* 385 * Don't trigger unless this is a "force a mount" 386 * node. 387 */ 388 if (!(ti->ti_flags & TF_FORCEMOUNT)) { 389 return (vfs_resolver_result(ti->ti_seq, 390 RESOLVER_NOCHANGE, 0)); 391 } 392 break; 393 394 case OP_ACCESS: 395 /* 396 * Various bits of file-management code in OS X love 397 * to try to get access permissions for everything 398 * they see. Don't trigger a mount on that, unless 399 * this is a "force a mount" node, so that we don't 400 * get mount storms. 401 */ 402 if (!(ti->ti_flags & TF_FORCEMOUNT)) { 403 return (vfs_resolver_result(ti->ti_seq, 404 RESOLVER_NOCHANGE, 0)); 405 } 406 break; 407 408 case OP_GETATTR: 409 /* 410 * stat(), etc. shouldn't trigger mounts, unless this 411 * is a "force a mount" node, so that "ls -l", the 412 * Finder, etc. won't cause mount storms. 413 */ 414 if (!(ti->ti_flags & TF_FORCEMOUNT)) { 415 return (vfs_resolver_result(ti->ti_seq, 416 RESOLVER_NOCHANGE, 0)); 417 } 418 break; 419 420 case OP_LISTXATTR: 421 /* 422 * Don't trigger on this, either. 423 */ 424 if (!(ti->ti_flags & TF_FORCEMOUNT)) { 425 return (vfs_resolver_result(ti->ti_seq, 426 RESOLVER_NOCHANGE, 0)); 427 } 428 break; 429 430 case OP_MKNOD: 431 case OP_MKFIFO: 432 case OP_SYMLINK: 433 case OP_LINK: 434 case OP_MKDIR: 435 /* 436 * For create operations: don't trigger mount on the 437 * last component of the pathname. If the target name 438 * doesn't exist, there's nothing to trigger. If 439 * it does exist and there's something mounted 440 * there, there's nothing to trigger. If it does 441 * exist but there's nothing mounted there, either 442 * somebody mounts something there before the next 443 * reference (e.g., the home directory mechanism), 444 * in which case we don't want any mounts triggered 445 * for it, or somebody refers to it before a mount 446 * is done on it, in which case we trigger the mount 447 * *then*. 448 */ 449 if (!(ti->ti_flags & TF_FORCEMOUNT)) { 450 return (vfs_resolver_result(ti->ti_seq, 451 RESOLVER_NOCHANGE, 0)); 452 } 453 break; 454 455 case OP_UNLINK: 456 case OP_RMDIR: 457 /* 458 * For delete operations: don't trigger mount on the 459 * last component of the pathname. We don't allow 460 * removal of autofs objects. 461 */ 462 if (!(ti->ti_flags & TF_FORCEMOUNT)) { 463 return (vfs_resolver_result(ti->ti_seq, 464 RESOLVER_NOCHANGE, 0)); 465 } 466 break; 467 468 case OP_RENAME: 469 /* 470 * For renames: don't trigger mount on the last 471 * component of the pathname. We don't allow 472 * renames of autofs objects. 473 */ 474 if (!(ti->ti_flags & TF_FORCEMOUNT)) { 475 return (vfs_resolver_result(ti->ti_seq, 476 RESOLVER_NOCHANGE, 0)); 477 } 478 break; 479 480 case OP_FSCTL: 481 /* 482 * Check whether we should trigger a mount for 483 * this; a home directory mounter process should 484 * not do so, so that it can use fsctl() to mark 485 * an autofs trigger as having a home directory mount 486 * in progress on it. 487 */ 488 if (ti->ti_check_homedirmounter_process != NULL && 489 (*ti->ti_check_homedirmounter_process)(NULL, pid)) { 490 /* 491 * No. 492 */ 493 return (vfs_resolver_result(ti->ti_seq, 494 RESOLVER_NOCHANGE, 0)); 495 } 496 break; 497 498 default: 499 break; 500 } 501 } 502 503 lck_mtx_lock(ti->ti_lock); 504 505top: 506 /* 507 * Is something already mounted here? If so, we don't need 508 * to do a mount to resolve this (we can't mount something 509 * atop the vnode, we could only mount something atop the 510 * tower of stuff already mounted atop the vnode, which 511 * would not be what's intended, and if something's mounted 512 * here and we didn't mount it, it's probably an AFP or SMB 513 * home directory, so it's probably what's supposed to be 514 * mounted there, just authenticated for the user whose home 515 * directory it is). 516 */ 517 if (vnode_mountedhere(vp) != NULL) { 518 /* 519 * The VFS layer thinks we're unresolved, so bump the 520 * sequence number to let them know that's not the 521 * case. 522 */ 523 ti->ti_seq++; 524 result = vfs_resolver_result(ti->ti_seq, RESOLVER_RESOLVED, 0); 525 lck_mtx_unlock(ti->ti_lock); 526 return (result); 527 } 528 529 /* 530 * Is this file marked as having a home directory mount in 531 * progress? 532 */ 533 if (ti->ti_check_homedirmount != NULL && 534 (*ti->ti_check_homedirmount)(vp)) { 535 /* 536 * Are we the home directory mounter for this vnode? 537 * 538 * If so, don't trigger a mount, but return success, so 539 * we can manipulate the mount point (e.g., changing 540 * its ownership so the mount can be done as the user 541 * by the NetAuth agent). 542 * 543 * If not, don't trigger a mount and return ENOENT, so 544 * that nobody else forces an automount while a home 545 * directory mount is in progress. (If somebody needs 546 * that mount to occur, THEY SHOULD WAIT FOR THE HOME 547 * DIRECTORY MOUNT TO FINISH FIRST, as they probably 548 * need the mount done as the user.) 549 */ 550 if (ti->ti_check_homedirmounter_process != NULL && 551 (*ti->ti_check_homedirmounter_process)(vp, pid)) { 552 result = vfs_resolver_result(ti->ti_seq, 553 RESOLVER_RESOLVED, 0); 554 } else { 555 result = vfs_resolver_result(ti->ti_seq, 556 RESOLVER_ERROR, ENOENT); 557 } 558 lck_mtx_unlock(ti->ti_lock); 559 return (result); 560 } 561 562 /* 563 * Are we a process that should not trigger mounts? If so, 564 * don't trigger, just succeed. 565 */ 566 if (ti->ti_check_notrigger_process != NULL) { 567 if ((*ti->ti_check_notrigger_process)(pid)) { 568 /* 569 * Don't trigger anything, just return 570 * success. 571 */ 572 result = vfs_resolver_result(ti->ti_seq, 573 RESOLVER_NOCHANGE, 0); 574 lck_mtx_unlock(ti->ti_lock); 575 return (result); 576 } 577 } 578 579 /* 580 * We need to do a mount in order to resolve this. 581 * Is there already a mount in progress on this vnode? 582 */ 583 if (!(ti->ti_flags & TF_INPROG)) { 584 /* 585 * No - do the mount. 586 * 587 * First, mark that we have a mount in progress, 588 * preventing anybody else from driving through 589 * and starting a mount. 590 */ 591 TRIGGER_BLOCK_OTHERS(ti); 592 ti->ti_error = 0; 593 lck_mtx_unlock(ti->ti_lock); 594 595 /* 596 * Now attempt to grab an iocount on the vnode on which 597 * we're supposed to do a mount. We need an iocount 598 * to ensure that it doesn't get deadfsed out from 599 * under the mount thread; we have an iocount on it 600 * now, but if we get interrupted while we're waiting 601 * for the mount to complete, we'll drop our iocount. 602 */ 603 error = vnode_get(vp); /* released at end of trigger_mount_url_thread */ 604 if (error != 0) 605 goto fail; 606 607 /* 608 * Now attempt to grab a usecount on the vnode on which 609 * we're supposed to do a mount. We want a usecount 610 * to ensure that a non-forced unmount attempt on the 611 * file system with the trigger will fail, rather than 612 * grabbing a write lock on the file system and blocking 613 * the mount and then doing a vflush() that waits for 614 * the mount point's iocount to be released - which won't 615 * happen until the mount either completes or fails, and 616 * that won't happen until the write lock is released.... 617 */ 618 error = vnode_ref(vp); /* released at end of trigger_mount_url_thread */ 619 if (error != 0) { 620 vnode_put(vp); /* release iocount */ 621 goto fail; 622 } 623 624 /* 625 * Allocate the argument structure, and get the arguments 626 * that are specific to our client. 627 */ 628 argsp = (*ti->ti_get_mount_args)(vp, ctx, &error); 629 if (argsp == NULL) { 630 vnode_rele(vp); /* release usecount from above */ 631 vnode_put(vp); /* release iocount from above */ 632 goto fail; 633 } 634 635 /* 636 * Fill in the arguments common to all clients. 637 */ 638 argsp->tc_vp = vp; 639 argsp->tc_this_fsid = vfs_statfs(vnode_mount(vp))->f_fsid; 640 argsp->tc_ti = ti; 641 argsp->tc_origin = current_thread(); 642 643#define kauth_cred_getasid(cred) ((cred)->cr_audit.as_aia_p->ai_asid) 644 645 argsp->tc_uid = kauth_cred_getuid(vfs_context_ucred(ctx)); 646 argsp->tc_asid = kauth_cred_getasid(vfs_context_ucred(ctx)); 647 648 /* These are "out" arguments; just initialize them */ 649 memset(&argsp->tc_mounted_fsid, 0, sizeof (argsp->tc_mounted_fsid)); 650 argsp->tc_retflags = 0; /* until shown otherwise */ 651 652 /* 653 * Now attempt to create a new thread which calls 654 * trigger_mount_thread; that thread does the bulk 655 * of the work of calling automountd and dealing 656 * with its results, with the help of our client's 657 * do_mount routine. 658 */ 659 ret = auto_new_thread(trigger_mount_thread, argsp); 660 if (ret != KERN_SUCCESS) { 661 IOLog("trigger_resolve: can't start new mounter thread, status 0x%08x", 662 ret); 663 error = EIO; 664 goto fail_thread; 665 } 666 trigger_thr_success++; 667 668 /* 669 * Put the lock back, and fall through. 670 */ 671 lck_mtx_lock(ti->ti_lock); 672 } 673 674 /* 675 * At this point, either there was already a mount in progress 676 * or we've created a thread to do the mount; in either case, 677 * we are now simply another thread waiting for the mount to 678 * complete. 679 */ 680 681 /* 682 * Should we wait for the mount to complete, or just drive 683 * through? 684 */ 685 if (ti->ti_check_nowait_process != NULL) { 686 if ((*ti->ti_check_nowait_process)(pid)) { 687 /* 688 * Drive through, return ENOENT. 689 */ 690 result = vfs_resolver_result(ti->ti_seq, RESOLVER_ERROR, 691 ENOENT); 692 lck_mtx_unlock(ti->ti_lock); 693 return (result); 694 } 695 } 696 697 /* 698 * OK, we should wait for it. 699 */ 700 error = wait_for_mount_locked(ti); 701 if (error == 0) { 702 /* 703 * Mount succeeded. The sequence number has already been 704 * incremented, and the status of the trigger updated, by 705 * trigger_mount_url_thread(), so this won't change the 706 * status of the trigger - which is as it should be. 707 */ 708 result = vfs_resolver_result(ti->ti_seq, RESOLVER_RESOLVED, 0); 709 } else if (error == EAGAIN) { 710 /* 711 * It wasn't that a mount that was in progress, it was 712 * that unmount_tree() was working on this fnnode. 713 * Go back and see whether we need to do the mount. 714 */ 715 goto top; 716 } else { 717 /* 718 * Mount failed, or we got interrupted by a signal before 719 * the mount finished. The sequence number hasn't been 720 * changed, so this won't change the status of the trigger, 721 * it'll just hand an error up. 722 */ 723 result = vfs_resolver_result(ti->ti_seq, RESOLVER_ERROR, 724 error); 725 } 726 lck_mtx_unlock(ti->ti_lock); 727 return (result); 728 729fail_thread: 730 vnode_rele(vp); /* release usecount from above */ 731 vnode_put(vp); /* release iocount from above */ 732 (*ti->ti_rel_mount_args)(argsp); 733 734fail: 735 lck_mtx_lock(ti->ti_lock); 736 ti->ti_error = error; 737 TRIGGER_UNBLOCK_OTHERS(ti); 738 result = vfs_resolver_result(ti->ti_seq, RESOLVER_ERROR, error); 739 lck_mtx_unlock(ti->ti_lock); 740 return (result); 741} 742 743/* 744 * "Un-resolve" this trigger, for which read "unmount the file system". 745 */ 746static resolver_result_t 747trigger_unresolve(__unused vnode_t vp, int flags, void *data, vfs_context_t ctx) 748{ 749 trigger_info_t *ti = data; 750 int error; 751 resolver_result_t result; 752 753 /* 754 * Lock the trigger. 755 */ 756 lck_mtx_lock(ti->ti_lock); 757 758 /* 759 * Unmount whatever we last mounted on that trigger, unless 760 * this is a "never auto-unmount this" mount. 761 * 762 * If that's not mounted there, that's OK; what we mounted 763 * there was probably unmounted by hand, and what was then 764 * mounted there is something that was mounted by hand, 765 * probably a mount containing a network home directory, 766 * and it shouldn't be auto-unmounted as we might not be 767 * able to correctly re-auto-mount it. 768 */ 769 if (ti->ti_flags & TF_DONTUNMOUNT) 770 error = EBUSY; /* pretend it's always busy */ 771 else 772 error = unmount_triggered_mount(&ti->ti_mounted_fsid, flags, 773 ctx); 774 if (error == 0) 775 result = trigger_make_unresolved(ti); 776 else { 777 /* 778 * The status of the resolver *hasn't* changed, so don't 779 * change the sequence number. 780 */ 781 result = vfs_resolver_result(ti->ti_seq, RESOLVER_ERROR, 782 error); 783 } 784 lck_mtx_unlock(ti->ti_lock); 785 return (result); 786} 787 788/* 789 * We've been asked to rearm this trigger. 790 * 791 * If the file system using us has a rearm function, first call it to 792 * perform whatever actions it wants to do. 793 * 794 * Then, if nothing is mounted atop this, we set the trigger's state 795 * to unresolved, otherwise we tell our caller that it's resolved. 796 * 797 * XXX - this is only called if somebody else unmounts something from 798 * atop this trigger, not if the VFS layer called the unresolve routine 799 * to do the unmount, right? 800 */ 801static resolver_result_t 802trigger_rearm(vnode_t vp, __unused int flags, void *data, vfs_context_t ctx) 803{ 804 trigger_info_t *ti = data; 805 resolver_result_t result; 806 807 lck_mtx_lock(ti->ti_lock); 808 809 if (ti->ti_rearm != NULL) 810 (*ti->ti_rearm)(vp, vfs_context_pid(ctx)); 811 812 if (vnode_mountedhere(vp) != NULL) { 813 /* 814 * Something's mounted on it, so call it resolved. 815 * 816 * XXX - should we do this? 817 */ 818 ti->ti_seq++; 819 result = vfs_resolver_result(ti->ti_seq, RESOLVER_RESOLVED, 820 0); 821 } else { 822 /* 823 * Nothing's mounted on it, so call it unresolved. 824 */ 825 result = trigger_make_unresolved(ti); 826 } 827 lck_mtx_unlock(ti->ti_lock); 828 return (result); 829} 830 831/* 832 * Reclaim, i.e. free, any data associated with this trigger. 833 */ 834static void 835trigger_reclaim(__unused vnode_t vp, void *data) 836{ 837 trigger_info_t *ti = data; 838 839 /* 840 * If we have a routine to call on a release, do so, passing 841 * it the private data pointer. 842 */ 843 if (ti->ti_reclaim != NULL) 844 (*ti->ti_reclaim)(ti->ti_private); 845 trigger_free(ti); 846} 847 848/* 849 * Allocate and initialize a new trigger info structure. Fill in 850 * the trigger-related fields of a "struct vnode_trigger_param" 851 * appropriately. Return a pointer to the structure. 852 */ 853trigger_info_t * 854trigger_new_autofs(struct vnode_trigger_param *vnt, 855 u_int flags, 856 int (*check_notrigger_process)(int), 857 int (*check_nowait_process)(int), 858 int (*check_homedirmounter_process)(vnode_t, int), 859 int (*check_homedirmount)(vnode_t), 860 void *(*get_mount_args)(vnode_t, vfs_context_t, int *), 861 int (*do_mount)(void *), 862 void (*rel_mount_args)(void *), 863 void (*rearm)(vnode_t, int), 864 void (*reclaim)(void *), 865 void *private) 866{ 867 struct timeval now; 868 trigger_info_t *ti; 869 870 microtime(&now); 871 872 MALLOC(ti, trigger_info_t *, sizeof (*ti), M_TRIGGERS, M_WAITOK); 873 ti->ti_lock = lck_mtx_alloc_init(triggers_lck_grp, NULL); 874 ti->ti_seq = 0; 875 ti->ti_flags = flags; 876 ti->ti_error = 0; 877 ti->ti_ref_time = now.tv_sec; 878 ti->ti_check_notrigger_process = check_notrigger_process; 879 ti->ti_check_nowait_process = check_nowait_process; 880 ti->ti_check_homedirmounter_process = check_homedirmounter_process; 881 ti->ti_check_homedirmount = check_homedirmount; 882 ti->ti_get_mount_args = get_mount_args; 883 ti->ti_do_mount = do_mount; 884 ti->ti_rel_mount_args = rel_mount_args; 885 ti->ti_rearm = rearm; 886 ti->ti_reclaim = reclaim; 887 ti->ti_private = private; 888 889 vnt->vnt_resolve_func = trigger_resolve; 890 vnt->vnt_unresolve_func = trigger_unresolve; 891 vnt->vnt_rearm_func = trigger_rearm; 892 vnt->vnt_reclaim_func = trigger_reclaim; 893 vnt->vnt_data = ti; 894 vnt->vnt_flags = VNT_AUTO_REARM; 895 896 return (ti); 897} 898 899/* 900 * For use outside autofs - shouldn't need to change if autofs changes. 901 */ 902 903trigger_info_t * 904trigger_new(struct vnode_trigger_param *vnt, 905 void *(*get_mount_args)(vnode_t, vfs_context_t, int *), 906 void (*rel_mount_args)(void *)) 907{ 908 return (trigger_new_autofs(vnt, 0, NULL, NULL, NULL, NULL, 909 get_mount_args, trigger_do_mount_url, rel_mount_args, 910 NULL, NULL, NULL)); 911} 912 913void 914trigger_free(trigger_info_t *ti) 915{ 916 /* 917 * Remove this from whatever list it's on. 918 * 919 * XXX - should this ever be on the list of resolved triggers 920 * if it's being freed? 921 */ 922 lck_rw_lock_exclusive(resolved_triggers_rwlock); 923 if (ti->ti_flags & TF_RESOLVED) 924 TAILQ_REMOVE(&resolved_triggers, ti, ti_entries); 925 lck_rw_unlock_exclusive(resolved_triggers_rwlock); 926 lck_mtx_free(ti->ti_lock, triggers_lck_grp); 927 FREE(ti, M_TRIGGERS); 928} 929 930int 931SMBRemountServer(const void *ptr, size_t len, au_asid_t asid) 932{ 933 mach_port_t automount_port; 934 int error; 935 kern_return_t ret; 936 vm_offset_t kmem_buf; 937 vm_size_t tbuflen; 938 vm_map_copy_t copy; 939 940 error = auto_get_automountd_port(&automount_port); 941 if (error) 942 return (error); 943 944 /* 945 * The blob has unbounded variable length. Mach RPC does 946 * not pass the token in-line. Instead it uses page mapping 947 * to handle these parameters. We allocate a VM buffer 948 * to hold the token for an upcall and copies the token 949 * (received from the client) into it. The VM buffer is 950 * marked with a src_destroy flag so that the upcall will 951 * automatically de-allocate the buffer when the upcall is 952 * complete. 953 */ 954 tbuflen = round_page(len); 955 ret = vm_allocate(ipc_kernel_map, &kmem_buf, tbuflen, 956 VM_FLAGS_ANYWHERE); 957 if (ret != KERN_SUCCESS) { 958 IOLog("autofs: vm_allocate failed, status 0x%08x\n", ret); 959 /* XXX - deal with Mach errors */ 960 auto_release_port(automount_port); 961 return (EIO); 962 } 963 ret = vm_map_wire(ipc_kernel_map, vm_map_trunc_page(kmem_buf, vm_map_page_mask(ipc_kernel_map)), 964 vm_map_round_page(kmem_buf + tbuflen, vm_map_page_mask(ipc_kernel_map)), 965 VM_PROT_READ|VM_PROT_WRITE, FALSE); 966 if (ret != KERN_SUCCESS) { 967 IOLog("autofs: vm_map_wire failed, status 0x%08x\n", ret); 968 /* XXX - deal with Mach errors */ 969 vm_deallocate(ipc_kernel_map, kmem_buf, tbuflen); 970 auto_release_port(automount_port); 971 return (EIO); 972 } 973 bcopy(ptr, (void *)kmem_buf, len); 974 ret = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(kmem_buf, vm_map_page_mask(ipc_kernel_map)), 975 vm_map_round_page(kmem_buf + tbuflen, vm_map_page_mask(ipc_kernel_map)), FALSE); 976 if (ret != KERN_SUCCESS) { 977 IOLog("autofs: vm_map_wire failed, status 0x%08x\n", ret); 978 /* XXX - deal with Mach errors */ 979 vm_deallocate(ipc_kernel_map, kmem_buf, tbuflen); 980 auto_release_port(automount_port); 981 return (EIO); 982 } 983 ret = vm_map_copyin(ipc_kernel_map, (vm_map_address_t) kmem_buf, 984 (vm_map_size_t) tbuflen, TRUE, ©); 985 if (ret != KERN_SUCCESS) { 986 IOLog("autofs: vm_map_copyin failed, status 0x%08x\n", ret); 987 /* XXX - deal with Mach errors */ 988 vm_deallocate(ipc_kernel_map, kmem_buf, tbuflen); 989 auto_release_port(automount_port); 990 return (EIO); 991 } 992 993 /* 994 * If you've passed us a blob whose size won't fit in a 995 * mach_msg_type_number_t, you've made a mistake. Don't 996 * make mistakes. 997 */ 998 ret = autofs_smb_remount_server(automount_port, (byte_buffer) copy, 999 (mach_msg_type_number_t)len, asid); 1000 auto_release_port(automount_port); 1001 if (ret != KERN_SUCCESS) { 1002 IOLog("autofs: autofs_smb_remount_server failed, status 0x%08x\n", 1003 ret); 1004 vm_map_copy_discard(copy); 1005 return (EIO); /* XXX - process Mach errors */ 1006 } 1007 1008 return (0); 1009} 1010 1011int 1012auto_get_automountd_port(mach_port_t *automount_port) 1013{ 1014 kern_return_t ret; 1015 1016 *automount_port = MACH_PORT_NULL; 1017 ret = host_get_automountd_port(host_priv_self(), automount_port); 1018 if (ret != KERN_SUCCESS) { 1019 IOLog("autofs: can't get automountd port, status 0x%08x\n", 1020 ret); 1021 return (ECONNREFUSED); 1022 } 1023 if (!IPC_PORT_VALID(*automount_port)) { 1024 IOLog("autofs: automountd port not valid\n"); 1025 return (ECONNRESET); 1026 } 1027 return (0); 1028} 1029 1030void 1031auto_release_port(mach_port_t port) 1032{ 1033 extern void ipc_port_release_send(ipc_port_t); 1034 1035 ipc_port_release_send(port); 1036} 1037 1038/* 1039 * Utility routine to create a new thread. 1040 * This should really be in xnu, and exported by it. 1041 */ 1042kern_return_t 1043auto_new_thread(void (*start)(void *), void *arg) 1044{ 1045 kern_return_t result; 1046 thread_t thread; 1047 1048 result = kernel_thread_start((thread_continue_t)start, arg, &thread); 1049 if (result != KERN_SUCCESS) 1050 return (result); 1051 1052 thread_deallocate(thread); 1053 1054 return (KERN_SUCCESS); 1055} 1056 1057static void 1058trigger_update_ref_time(fsid_t *fsidp, time_t now) 1059{ 1060 trigger_info_t *ti; 1061 1062 lck_rw_lock_shared(resolved_triggers_rwlock); 1063 1064 /* 1065 * Look for an entry with the specified fsid and, 1066 * if we find it, update it. 1067 */ 1068 TAILQ_FOREACH(ti, &resolved_triggers, ti_entries) { 1069 if (FSIDS_EQUAL(ti->ti_mounted_fsid, *fsidp)) { 1070 ti->ti_ref_time = now; 1071 break; 1072 } 1073 } 1074 1075 lck_rw_unlock_shared(resolved_triggers_rwlock); 1076} 1077 1078/* 1079 * Item in the information copied from the list of resolved triggers. 1080 */ 1081struct triggered_mount_info { 1082 fsid_t this_fsid; 1083 fsid_t mounted_fsid; 1084 time_t ref_time; 1085 u_int flags; 1086}; 1087 1088/* 1089 * Look at all triggered mounts, and, for each mount, if it is an 1090 * unconditional operation or if it hasn't been referred to recently, 1091 * unmount it. 1092 */ 1093void 1094unmount_triggered_mounts(int unconditional) 1095{ 1096 trigger_info_t *ti; 1097 int nmounts, i, j; 1098 struct triggered_mount_info *mounts; 1099 struct timeval now; 1100 int error; 1101 fsid_t search_fsid; 1102 1103 /* 1104 * Make sure the list of resolved triggers doesn't change out 1105 * from under us while we scan it. 1106 */ 1107 lck_rw_lock_shared(resolved_triggers_rwlock); 1108 1109 /* 1110 * Count how many resolved triggers we have. 1111 */ 1112 nmounts = 0; 1113 TAILQ_FOREACH_REVERSE(ti, &resolved_triggers, resolved_triggers, 1114 ti_entries) { 1115 nmounts++; 1116 } 1117 1118 /* 1119 * Allocate an array of fsids and timeout information for 1120 * all those mounts. 1121 */ 1122 MALLOC(mounts, struct triggered_mount_info *, sizeof (*mounts)*nmounts, 1123 M_TRIGGERS, M_WAITOK); 1124 1125 /* 1126 * Make a copy of the mount information for all the triggered 1127 * mounts. 1128 */ 1129 i = 0; 1130 TAILQ_FOREACH_REVERSE(ti, &resolved_triggers, resolved_triggers, 1131 ti_entries) { 1132 if (i >= nmounts) { 1133 /* 1134 * This "cannot happen". 1135 */ 1136 IOLog("unmount_triggers: resolved_triggers changed out from under us!\n"); 1137 break; 1138 } 1139 1140 mounts[i].this_fsid = ti->ti_this_fsid; 1141 mounts[i].mounted_fsid = ti->ti_mounted_fsid; 1142 1143 /* 1144 * We want the last referenced time for the trigger 1145 * for this. 1146 */ 1147 mounts[i].ref_time = ti->ti_ref_time; 1148 mounts[i].flags = ti->ti_flags; 1149 i++; 1150 } 1151 1152 /* 1153 * We can now release the rwlock, as we're done looking at 1154 * the list of triggered mounts. Unmounts we do might change 1155 * it out from under us - as might other unmounts done while 1156 * we're working. 1157 */ 1158 lck_rw_unlock_shared(resolved_triggers_rwlock); 1159 1160 /* 1161 * Now work on the snapshot we took of the triggered mounts. 1162 * If something gets unmounted before we look at it, 1163 * that fsid will no longer have a file system corresponding 1164 * to it, and there's nothing to unmount. If something gets 1165 * mounted after we took the snapshot, we miss it; short of 1166 * blocking all mounts while we're doing the unmount, there's 1167 * not much we can do about that, and even if we do block all 1168 * mounts while we're doing the unmount, something might get 1169 * mounted after we're done. 1170 */ 1171 microtime(&now); 1172 for (i = nmounts - 1; i >= 0; i--) { 1173 /* 1174 * If this is an autofs mount, don't unmount it; 1175 * that'll happen automatically if we unmount what it's 1176 * mounted on. 1177 */ 1178 if (mounts[i].flags & TF_AUTOFS) 1179 continue; 1180 1181 error = 0; /* assume we will be unmounting this */ 1182 if (mounts[i].flags & TF_DONTUNMOUNT) { 1183 /* 1184 * This is a "don't ever auto-unmount this" 1185 * mount; skip it. 1186 */ 1187 error = EBUSY; 1188 } else { 1189 if (unconditional) { 1190 /* 1191 * This is a "preemptively unmount 1192 * everything you can" unmount; 1193 * if this is a "don't preemptively 1194 * unmount this" mount, skip it. 1195 */ 1196 if (mounts[i].flags & TF_DONTPREUNMOUNT) 1197 error = EBUSY; 1198 } else { 1199 /* 1200 * This is an auto-unmount; skip it 1201 * if it's been referenced recently. 1202 */ 1203 if (mounts[i].ref_time + mount_to > now.tv_sec) 1204 error = EBUSY; 1205 } 1206 } 1207 if (error == 0) { 1208 /* 1209 * OK, we should at least try to unmount this. 1210 */ 1211 error = unmount_triggered_mount(&mounts[i].mounted_fsid, 1212 0, vfs_context_current()); 1213 if (error == EBUSY) { 1214 /* 1215 * The file system is apparently still 1216 * in use, so update its reference 1217 * time. 1218 */ 1219 trigger_update_ref_time(&mounts[i].mounted_fsid, 1220 now.tv_sec); 1221 } 1222 } 1223 1224 if (error == EBUSY || error == EIO) { 1225 /* 1226 * We deemed that file system to be "recently 1227 * used" (either referred to recently or currently 1228 * in use), or concluded that it shouldn't be 1229 * unmounted, so, if it's mounted (directly or 1230 * indirectly) atop another triggered mount, mark 1231 * that mount as "recently used", so we don't 1232 * try to unmount it (which will cause the 1233 * VFS layer to try to unmount everything 1234 * mounted atop it). 1235 * 1236 * We scan all triggered mounts below this one 1237 * to find one that has a mounted-on fsid equal 1238 * to the fsid of this mount. If that's not 1239 * an autofs mount, we've found it, otherwise 1240 * we keep searching backwards, now looking 1241 * for one with a mounted-on fsid equal to the 1242 * fsid of the autofs mount. 1243 */ 1244 search_fsid = mounts[i].this_fsid; 1245 for (j = i - 1; j >= 0; j--) { 1246 if (FSIDS_EQUAL(mounts[j].mounted_fsid, 1247 search_fsid)) { 1248 if (mounts[j].flags & TF_AUTOFS) { 1249 /* 1250 * OK, what's *this* mounted 1251 * on? 1252 */ 1253 search_fsid = mounts[j].mounted_fsid; 1254 } else { 1255 mounts[j].ref_time = now.tv_sec; 1256 break; 1257 } 1258 } 1259 } 1260 } 1261 } 1262 1263 /* 1264 * Release the Kraken^Wcopy. 1265 */ 1266 FREE(mounts, M_TRIGGERS); 1267} 1268 1269static lck_mtx_t *unmount_threads_lock; 1270static int unmount_threads; 1271static thread_call_t unmounter_thread_call; 1272static int shutting_down; 1273 1274/* 1275 * max number of unmount threads running 1276 */ 1277static int max_unmount_threads = 5; 1278 1279static void 1280decrement_unmount_thread_count(void) 1281{ 1282 lck_mtx_lock(unmount_threads_lock); 1283 unmount_threads--; 1284 1285 /* 1286 * If we have no more threads running, and we're shutting 1287 * down, wake up anybody waiting for us to run out of 1288 * unmount threads. 1289 */ 1290 if (shutting_down && unmount_threads == 0) 1291 wakeup(&unmount_threads); 1292 lck_mtx_unlock(unmount_threads_lock); 1293} 1294 1295/* 1296 * Time between unmount_triggered_mounts() calls, in seconds. 1297 */ 1298#define UNMOUNT_TRIGGERED_MOUNTS_TIMER 120 /* 2 minutes */ 1299 1300static void 1301triggers_unmount_thread(__unused void *arg) 1302{ 1303 unmount_triggered_mounts(0); 1304 decrement_unmount_thread_count(); 1305 1306 thread_terminate(current_thread()); 1307 /* NOTREACHED */ 1308} 1309 1310static void 1311triggers_do_unmount(__unused void *dummy1, __unused void *dummy2) 1312{ 1313 kern_return_t result; 1314 AbsoluteTime deadline; 1315 1316 /* 1317 * If we don't already have too many unmount threads running, 1318 * and if we aren't trying to shut down the triggers kext, 1319 * attempt an unmount, otherwise just quit. 1320 * 1321 * We attempt the unmount in a separate thread, so as not to 1322 * block the thread doing thread calls. 1323 */ 1324 lck_mtx_lock(unmount_threads_lock); 1325 if (!shutting_down && unmount_threads < max_unmount_threads) { 1326 unmount_threads++; 1327 lck_mtx_unlock(unmount_threads_lock); 1328 1329 result = auto_new_thread(triggers_unmount_thread, NULL); 1330 if (result != KERN_SUCCESS) { 1331 IOLog("triggers_do_unmount: Couldn't start unmount thread, status 0x%08x\n", 1332 result); 1333 1334 /* 1335 * Undo the thread count increment, as the 1336 * thread wasn't created. 1337 */ 1338 decrement_unmount_thread_count(); 1339 } 1340 } else 1341 lck_mtx_unlock(unmount_threads_lock); 1342 1343 /* 1344 * Schedule the next unmount attempt for UNMOUNT_TRIGGERED_MOUNTS_TIMER 1345 * seconds from now. 1346 */ 1347 clock_interval_to_deadline(UNMOUNT_TRIGGERED_MOUNTS_TIMER, NSEC_PER_SEC, 1348 &deadline); 1349 thread_call_enter_delayed(unmounter_thread_call, deadline); 1350} 1351 1352/* 1353 * Initialize the module 1354 */ 1355__private_extern__ int 1356triggers_start(__unused kmod_info_t *ki, __unused void *data) 1357{ 1358 AbsoluteTime deadline; 1359 1360 /* 1361 * Set up the lock group. 1362 */ 1363 triggers_lck_grp = lck_grp_alloc_init("triggers", NULL); 1364 if (triggers_lck_grp == NULL) { 1365 IOLog("triggers_start: Couldn't create triggers lock group\n"); 1366 goto fail; 1367 } 1368 1369 resolved_triggers_rwlock = lck_rw_alloc_init(triggers_lck_grp, NULL); 1370 if (resolved_triggers_rwlock == NULL) { 1371 IOLog("triggers_start: Couldn't create resolved triggers list lock\n"); 1372 goto fail; 1373 } 1374 1375 shutting_down = 0; 1376 1377 unmount_threads_lock = lck_mtx_alloc_init(triggers_lck_grp, LCK_ATTR_NULL); 1378 if (unmount_threads_lock == NULL) { 1379 IOLog("triggers_start: Couldn't create unmount threads lock\n"); 1380 goto fail; 1381 } 1382 unmount_threads = 0; 1383 unmounter_thread_call = thread_call_allocate(triggers_do_unmount, NULL); 1384 if (unmounter_thread_call == NULL) { 1385 IOLog("triggers_start: Couldn't create thread_call_t for unmounter thread\n"); 1386 goto fail; 1387 } 1388 1389 TAILQ_INIT(&resolved_triggers); 1390 1391 /* 1392 * Schedule the unmounter thread to run UNMOUNT_TRIGGERED_MOUNTS_TIMER 1393 * seconds from now. 1394 */ 1395 clock_interval_to_deadline(UNMOUNT_TRIGGERED_MOUNTS_TIMER, NSEC_PER_SEC, 1396 &deadline); 1397 thread_call_enter_delayed(unmounter_thread_call, deadline); 1398 1399 return (KERN_SUCCESS); 1400 1401fail: 1402 if (unmounter_thread_call != NULL) 1403 thread_call_free(unmounter_thread_call); 1404 if (unmount_threads_lock != NULL) 1405 lck_mtx_free(unmount_threads_lock, triggers_lck_grp); 1406 if (resolved_triggers_rwlock != NULL) 1407 lck_rw_free(resolved_triggers_rwlock, triggers_lck_grp); 1408 if (triggers_lck_grp != NULL) 1409 lck_grp_free(triggers_lck_grp); 1410 return (KERN_FAILURE); 1411} 1412 1413__private_extern__ int 1414triggers_stop(__unused kmod_info_t *ki, __unused void *data) 1415{ 1416 /* 1417 * We cannot be unloaded if any kext that depends on us is 1418 * loaded; we rely on those kexts not to be unloaded if 1419 * they have any vnodes, so if we're being unloaded, they 1420 * have no trigger vnodes, so we know that no mounts will 1421 * be triggered, so there won't be any *new* triggered 1422 * mounts. 1423 * 1424 * However, there might still be resolved triggers, if the file 1425 * systems with the triggers in question were forcibly unmounted, 1426 * so we must check whether there are any resolved triggers left. 1427 * 1428 * XXX - should check for *any* triggers! 1429 */ 1430 lck_rw_lock_shared(resolved_triggers_rwlock); 1431 if (!TAILQ_EMPTY(&resolved_triggers)) { 1432 lck_rw_unlock_shared(resolved_triggers_rwlock); 1433 IOLog("triggers_stop: Can't remove, still some resolved triggers\n"); 1434 return (KERN_NO_ACCESS); 1435 } 1436 1437 /* 1438 * Cancel any queued unmount calls. 1439 */ 1440 thread_call_cancel(unmounter_thread_call); 1441 1442 /* 1443 * Wait until there are no unmount threads running. 1444 */ 1445 lck_mtx_lock(unmount_threads_lock); 1446 shutting_down = 1; 1447 while (unmount_threads != 0) { 1448 msleep(&unmount_threads, unmount_threads_lock, PWAIT, 1449 "unmount thread terminated", NULL); 1450 } 1451 lck_mtx_unlock(unmount_threads_lock); 1452 lck_mtx_free(unmount_threads_lock, triggers_lck_grp); 1453 1454 lck_rw_unlock_exclusive(resolved_triggers_rwlock); 1455 lck_rw_free(resolved_triggers_rwlock, triggers_lck_grp); 1456 lck_grp_free(triggers_lck_grp); 1457 1458 return (KERN_SUCCESS); 1459} 1460