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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/param.h> 29 #include <sys/kmem.h> 30 #include <sys/errno.h> 31 #include <sys/proc.h> 32 #include <sys/disp.h> 33 #include <sys/vfs.h> 34 #include <sys/vnode.h> 35 #include <sys/pathname.h> 36 #include <sys/cred.h> 37 #include <sys/mount.h> 38 #include <sys/cmn_err.h> 39 #include <sys/debug.h> 40 #include <sys/systm.h> 41 #include <sys/dirent.h> 42 #include <fs/fs_subr.h> 43 #include <sys/fs/autofs.h> 44 #include <sys/callb.h> 45 #include <sys/sysmacros.h> 46 #include <sys/zone.h> 47 #include <sys/door.h> 48 #include <sys/fs/mntdata.h> 49 #include <nfs/mount.h> 50 #include <rpc/clnt.h> 51 #include <rpcsvc/autofs_prot.h> 52 #include <nfs/rnode.h> 53 #include <sys/utsname.h> 54 55 /* 56 * Autofs and Zones: 57 * 58 * Zones are delegated the responsibility of managing their own autofs mounts 59 * and maps. Each zone runs its own copy of automountd, with its own timeouts, 60 * and other logically "global" parameters. kRPC and virtualization in the 61 * loopback transport (tl) will prevent a zone from communicating with another 62 * zone's automountd. 63 * 64 * Each zone has its own "rootfnnode" and associated tree of auto nodes. 65 * 66 * Each zone also has its own set of "unmounter" kernel threads; these are 67 * created and run within the zone's context (ie, they are created via 68 * zthread_create()). 69 * 70 * Cross-zone mount triggers are disallowed. There is a check in 71 * auto_trigger_mount() to this effect; EPERM is returned to indicate that the 72 * mount is not owned by the caller. 73 * 74 * autofssys() enables a caller in the global zone to clean up in-kernel (as 75 * well as regular) autofs mounts via the unmount_tree() mechanism. This is 76 * routinely done when all mounts are removed as part of zone shutdown. 77 */ 78 #define TYPICALMAXPATHLEN 64 79 80 static kmutex_t autofs_nodeid_lock; 81 82 static int auto_perform_link(fnnode_t *, struct linka *, cred_t *); 83 static int auto_perform_actions(fninfo_t *, fnnode_t *, 84 action_list *, cred_t *); 85 static int auto_getmntpnt(vnode_t *, char *, vnode_t **, cred_t *); 86 static int auto_lookup_request(fninfo_t *, char *, struct linka *, 87 bool_t, bool_t *); 88 static int auto_mount_request(fninfo_t *, char *, action_list **, 89 bool_t); 90 91 extern struct autofs_globals *autofs_zone_init(void); 92 93 /* 94 * Clears the MF_INPROG flag, and wakes up those threads sleeping on 95 * fn_cv_mount if MF_WAITING is set. 96 */ 97 void 98 auto_unblock_others( 99 fnnode_t *fnp, 100 uint_t operation) /* either MF_INPROG or MF_LOOKUP */ 101 { 102 ASSERT(operation & (MF_INPROG | MF_LOOKUP)); 103 fnp->fn_flags &= ~operation; 104 if (fnp->fn_flags & MF_WAITING) { 105 fnp->fn_flags &= ~MF_WAITING; 106 cv_broadcast(&fnp->fn_cv_mount); 107 } 108 } 109 110 int 111 auto_wait4mount(fnnode_t *fnp) 112 { 113 int error; 114 k_sigset_t smask; 115 116 AUTOFS_DPRINT((4, "auto_wait4mount: fnp=%p\n", (void *)fnp)); 117 118 mutex_enter(&fnp->fn_lock); 119 while (fnp->fn_flags & (MF_INPROG | MF_LOOKUP)) { 120 /* 121 * There is a mount or a lookup in progress. 122 */ 123 fnp->fn_flags |= MF_WAITING; 124 sigintr(&smask, 1); 125 if (!cv_wait_sig(&fnp->fn_cv_mount, &fnp->fn_lock)) { 126 /* 127 * Decided not to wait for operation to 128 * finish after all. 129 */ 130 sigunintr(&smask); 131 mutex_exit(&fnp->fn_lock); 132 return (EINTR); 133 } 134 sigunintr(&smask); 135 } 136 error = fnp->fn_error; 137 138 if (error == EINTR) { 139 /* 140 * The thread doing the mount got interrupted, we need to 141 * try again, by returning EAGAIN. 142 */ 143 error = EAGAIN; 144 } 145 mutex_exit(&fnp->fn_lock); 146 147 AUTOFS_DPRINT((5, "auto_wait4mount: fnp=%p error=%d\n", (void *)fnp, 148 error)); 149 return (error); 150 } 151 152 int 153 auto_lookup_aux(fnnode_t *fnp, char *name, cred_t *cred) 154 { 155 struct fninfo *fnip; 156 struct linka link; 157 bool_t mountreq = FALSE; 158 int error = 0; 159 160 fnip = vfstofni(fntovn(fnp)->v_vfsp); 161 bzero(&link, sizeof (link)); 162 error = auto_lookup_request(fnip, name, &link, TRUE, &mountreq); 163 if (!error) { 164 if (link.link != NULL || link.link != '\0') { 165 /* 166 * This node should be a symlink 167 */ 168 error = auto_perform_link(fnp, &link, cred); 169 } else if (mountreq) { 170 /* 171 * The automount daemon is requesting a mount, 172 * implying this entry must be a wildcard match and 173 * therefore in need of verification that the entry 174 * exists on the server. 175 */ 176 mutex_enter(&fnp->fn_lock); 177 AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG); 178 fnp->fn_error = 0; 179 180 /* 181 * Unblock other lookup requests on this node, 182 * this is needed to let the lookup generated by 183 * the mount call to complete. The caveat is 184 * other lookups on this node can also get by, 185 * i.e., another lookup on this node that occurs 186 * while this lookup is attempting the mount 187 * would return a positive result no matter what. 188 * Therefore two lookups on the this node could 189 * potentially get disparate results. 190 */ 191 AUTOFS_UNBLOCK_OTHERS(fnp, MF_LOOKUP); 192 mutex_exit(&fnp->fn_lock); 193 /* 194 * auto_new_mount_thread fires up a new thread which 195 * calls automountd finishing up the work 196 */ 197 auto_new_mount_thread(fnp, name, cred); 198 199 /* 200 * At this point, we are simply another thread 201 * waiting for the mount to complete 202 */ 203 error = auto_wait4mount(fnp); 204 if (error == AUTOFS_SHUTDOWN) 205 error = ENOENT; 206 } 207 } 208 209 if (link.link) 210 kmem_free(link.link, strlen(link.link) + 1); 211 if (link.dir) 212 kmem_free(link.dir, strlen(link.dir) + 1); 213 mutex_enter(&fnp->fn_lock); 214 fnp->fn_error = error; 215 216 /* 217 * Notify threads waiting for lookup/mount that 218 * it's done. 219 */ 220 if (mountreq) { 221 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 222 } else { 223 AUTOFS_UNBLOCK_OTHERS(fnp, MF_LOOKUP); 224 } 225 mutex_exit(&fnp->fn_lock); 226 return (error); 227 } 228 229 /* 230 * Starting point for thread to handle mount requests with automountd. 231 * XXX auto_mount_thread() is not suspend-safe within the scope of 232 * the present model defined for cpr to suspend the system. Calls 233 * made by the auto_mount_thread() that have been identified to be unsafe 234 * are (1) RPC client handle setup and client calls to automountd which 235 * can block deep down in the RPC library, (2) kmem_alloc() calls with the 236 * KM_SLEEP flag which can block if memory is low, and (3) VFS_*(), and 237 * lookuppnvp() calls which can result in over the wire calls to servers. 238 * The thread should be completely reevaluated to make it suspend-safe in 239 * case of future updates to the cpr model. 240 */ 241 static void 242 auto_mount_thread(struct autofs_callargs *argsp) 243 { 244 struct fninfo *fnip; 245 fnnode_t *fnp; 246 vnode_t *vp; 247 char *name; 248 size_t namelen; 249 cred_t *cred; 250 action_list *alp = NULL; 251 int error; 252 callb_cpr_t cprinfo; 253 kmutex_t auto_mount_thread_cpr_lock; 254 255 mutex_init(&auto_mount_thread_cpr_lock, NULL, MUTEX_DEFAULT, NULL); 256 CALLB_CPR_INIT(&cprinfo, &auto_mount_thread_cpr_lock, 257 callb_generic_cpr, "auto_mount_thread"); 258 259 fnp = argsp->fnc_fnp; 260 vp = fntovn(fnp); 261 fnip = vfstofni(vp->v_vfsp); 262 name = argsp->fnc_name; 263 cred = argsp->fnc_cred; 264 ASSERT(crgetzoneid(argsp->fnc_cred) == fnip->fi_zoneid); 265 266 error = auto_mount_request(fnip, name, &alp, TRUE); 267 if (!error) 268 error = auto_perform_actions(fnip, fnp, alp, cred); 269 mutex_enter(&fnp->fn_lock); 270 fnp->fn_error = error; 271 272 /* 273 * Notify threads waiting for mount that 274 * it's done. 275 */ 276 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 277 mutex_exit(&fnp->fn_lock); 278 279 VN_RELE(vp); 280 crfree(argsp->fnc_cred); 281 namelen = strlen(argsp->fnc_name) + 1; 282 kmem_free(argsp->fnc_name, namelen); 283 kmem_free(argsp, sizeof (*argsp)); 284 285 mutex_enter(&auto_mount_thread_cpr_lock); 286 CALLB_CPR_EXIT(&cprinfo); 287 mutex_destroy(&auto_mount_thread_cpr_lock); 288 zthread_exit(); 289 /* NOTREACHED */ 290 } 291 292 static int autofs_thr_success = 0; 293 294 /* 295 * Creates new thread which calls auto_mount_thread which does 296 * the bulk of the work calling automountd, via 'auto_perform_actions'. 297 */ 298 void 299 auto_new_mount_thread(fnnode_t *fnp, char *name, cred_t *cred) 300 { 301 struct autofs_callargs *argsp; 302 303 argsp = kmem_alloc(sizeof (*argsp), KM_SLEEP); 304 VN_HOLD(fntovn(fnp)); 305 argsp->fnc_fnp = fnp; 306 argsp->fnc_name = kmem_alloc(strlen(name) + 1, KM_SLEEP); 307 (void) strcpy(argsp->fnc_name, name); 308 argsp->fnc_origin = curthread; 309 crhold(cred); 310 argsp->fnc_cred = cred; 311 312 (void) zthread_create(NULL, 0, auto_mount_thread, argsp, 0, 313 minclsyspri); 314 autofs_thr_success++; 315 } 316 317 318 int 319 auto_calldaemon( 320 zoneid_t zoneid, 321 int which, 322 xdrproc_t xarg_func, 323 void *argsp, 324 xdrproc_t xresp_func, 325 void *resp, 326 int reslen, 327 bool_t hard) /* retry forever? */ 328 { 329 330 int retry, error = 0; 331 k_sigset_t smask; 332 door_arg_t door_args; 333 door_handle_t dh; 334 XDR xdrarg, xdrres; 335 struct autofs_globals *fngp = NULL; 336 void *orig_resp = NULL; 337 int orig_reslen = reslen; 338 autofs_door_args_t *xdr_argsp; 339 int xdr_len = 0; 340 341 /* 342 * We know that the current thread is doing work on 343 * behalf of its own zone, so it's ok to use 344 * curproc->p_zone. 345 */ 346 ASSERT(zoneid == getzoneid()); 347 if (zone_status_get(curproc->p_zone) >= 348 ZONE_IS_SHUTTING_DOWN) { 349 /* 350 * There's no point in trying to talk to 351 * automountd. Plus, zone_shutdown() is 352 * waiting for us. 353 */ 354 return (ECONNREFUSED); 355 } 356 357 if ((fngp = zone_getspecific(autofs_key, curproc->p_zone)) == 358 NULL) { 359 fngp = autofs_zone_init(); 360 (void) zone_setspecific(autofs_key, curproc->p_zone, fngp); 361 } 362 363 ASSERT(fngp != NULL); 364 365 if (argsp != NULL && (xdr_len = xdr_sizeof(xarg_func, argsp)) == 0) 366 return (EINVAL); 367 xdr_argsp = kmem_zalloc(xdr_len + sizeof (*xdr_argsp), KM_SLEEP); 368 xdr_argsp->xdr_len = xdr_len; 369 xdr_argsp->cmd = which; 370 371 if (argsp) { 372 xdrmem_create(&xdrarg, (char *)&xdr_argsp->xdr_arg, 373 xdr_argsp->xdr_len, XDR_ENCODE); 374 375 if (!(*xarg_func)(&xdrarg, argsp)) { 376 kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp)); 377 return (EINVAL); 378 } 379 } 380 381 /* 382 * We're saving off the original pointer and length due to the 383 * possibility that the results buffer returned by the door 384 * upcall can be different then what we passed in. This is because 385 * the door will allocate new memory if the results buffer passed 386 * in isn't large enough to hold what we need to send back. 387 * In this case we need to free the memory originally allocated 388 * for that buffer. 389 */ 390 if (orig_reslen) 391 orig_resp = kmem_zalloc(orig_reslen, KM_SLEEP); 392 393 do { 394 retry = 0; 395 mutex_enter(&fngp->fng_autofs_daemon_lock); 396 dh = fngp->fng_autofs_daemon_dh; 397 if (dh) 398 door_ki_hold(dh); 399 mutex_exit(&fngp->fng_autofs_daemon_lock); 400 401 if (dh == NULL) { 402 if (orig_resp) 403 kmem_free(orig_resp, orig_reslen); 404 kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp)); 405 return (ENOENT); 406 } 407 door_args.data_ptr = (char *)xdr_argsp; 408 door_args.data_size = sizeof (*xdr_argsp) + xdr_argsp->xdr_len; 409 door_args.desc_ptr = NULL; 410 door_args.desc_num = 0; 411 door_args.rbuf = orig_resp ? (char *)orig_resp : NULL; 412 door_args.rsize = reslen; 413 414 sigintr(&smask, 1); 415 error = door_ki_upcall(dh, &door_args); 416 sigunintr(&smask); 417 418 door_ki_rele(dh); 419 420 if (!error) { 421 autofs_door_res_t *adr = 422 (autofs_door_res_t *)door_args.rbuf; 423 if (door_args.rbuf != NULL && 424 (error = adr->res_status)) { 425 kmem_free(xdr_argsp, 426 xdr_len + sizeof (*xdr_argsp)); 427 if (orig_resp) 428 kmem_free(orig_resp, orig_reslen); 429 return (error); 430 } 431 continue; 432 } 433 switch (error) { 434 case EINTR: 435 /* 436 * interrupts should be handled properly by the 437 * door upcall. 438 * 439 * We may have gotten EINTR for other reasons 440 * like the door being revoked on us. Instead 441 * of trying to extract this out of the door 442 * handle, sleep and try again, if still 443 * revoked we will get EBADF next time 444 * through. 445 */ 446 case EAGAIN: /* process may be forking */ 447 /* 448 * Back off for a bit 449 */ 450 delay(hz); 451 retry = 1; 452 break; 453 case EBADF: /* Invalid door */ 454 case EINVAL: /* Not a door, wrong target */ 455 /* 456 * A fatal door error, if our failing door 457 * handle is the current door handle, clean 458 * up our state. 459 */ 460 mutex_enter(&fngp->fng_autofs_daemon_lock); 461 if (dh == fngp->fng_autofs_daemon_dh) { 462 door_ki_rele(fngp->fng_autofs_daemon_dh); 463 fngp->fng_autofs_daemon_dh = NULL; 464 } 465 mutex_exit(&fngp->fng_autofs_daemon_lock); 466 AUTOFS_DPRINT((5, 467 "auto_calldaemon error=%d\n", error)); 468 if (hard) { 469 if (!fngp->fng_printed_not_running_msg) { 470 fngp->fng_printed_not_running_msg = 1; 471 zprintf(zoneid, "automountd not "\ 472 "running, retrying\n"); 473 } 474 delay(hz); 475 retry = 1; 476 break; 477 } else { 478 error = ECONNREFUSED; 479 kmem_free(xdr_argsp, 480 xdr_len + sizeof (*xdr_argsp)); 481 if (orig_resp) 482 kmem_free(orig_resp, orig_reslen); 483 return (error); 484 } 485 default: /* Unknown must be fatal */ 486 error = ENOENT; 487 kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp)); 488 if (orig_resp) 489 kmem_free(orig_resp, orig_reslen); 490 return (error); 491 } 492 } while (retry); 493 494 if (fngp->fng_printed_not_running_msg == 1) { 495 fngp->fng_printed_not_running_msg = 0; 496 zprintf(zoneid, "automountd OK\n"); 497 } 498 499 if (orig_resp && orig_reslen) { 500 autofs_door_res_t *door_resp; 501 door_resp = 502 (autofs_door_res_t *)door_args.rbuf; 503 if ((void *)door_args.rbuf != orig_resp) 504 kmem_free(orig_resp, orig_reslen); 505 xdrmem_create(&xdrres, (char *)&door_resp->xdr_res, 506 door_resp->xdr_len, XDR_DECODE); 507 if (!((*xresp_func)(&xdrres, resp))) 508 error = EINVAL; 509 kmem_free(door_args.rbuf, door_args.rsize); 510 } 511 kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp)); 512 return (error); 513 } 514 515 static int 516 auto_null_request(fninfo_t *fnip, bool_t hard) 517 { 518 int error; 519 struct autofs_globals *fngp = vntofn(fnip->fi_rootvp)->fn_globals; 520 521 AUTOFS_DPRINT((4, "\tauto_null_request\n")); 522 523 error = auto_calldaemon(fngp->fng_zoneid, 524 NULLPROC, 525 xdr_void, 526 NULL, 527 xdr_void, 528 NULL, 529 0, 530 hard); 531 532 AUTOFS_DPRINT((5, "\tauto_null_request: error=%d\n", error)); 533 return (error); 534 } 535 536 static int 537 auto_lookup_request( 538 fninfo_t *fnip, 539 char *key, 540 struct linka *lnp, 541 bool_t hard, 542 bool_t *mountreq) 543 { 544 int error; 545 struct autofs_globals *fngp; 546 struct autofs_lookupargs reqst; 547 autofs_lookupres *resp; 548 struct linka *p; 549 550 551 AUTOFS_DPRINT((4, "auto_lookup_equest: path=%s name=%s\n", 552 fnip->fi_path, key)); 553 554 fngp = vntofn(fnip->fi_rootvp)->fn_globals; 555 556 reqst.map = fnip->fi_map; 557 reqst.path = fnip->fi_path; 558 559 if (fnip->fi_flags & MF_DIRECT) 560 reqst.name = fnip->fi_key; 561 else 562 reqst.name = key; 563 AUTOFS_DPRINT((4, "auto_lookup_request: using key=%s\n", reqst.name)); 564 565 reqst.subdir = fnip->fi_subdir; 566 reqst.opts = fnip->fi_opts; 567 reqst.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE; 568 569 resp = kmem_zalloc(sizeof (*resp), KM_SLEEP); 570 571 error = auto_calldaemon(fngp->fng_zoneid, 572 AUTOFS_LOOKUP, 573 xdr_autofs_lookupargs, 574 &reqst, 575 xdr_autofs_lookupres, 576 (void *)resp, 577 sizeof (autofs_lookupres), 578 hard); 579 580 581 if (error) { 582 xdr_free(xdr_autofs_lookupres, (char *)resp); 583 kmem_free(resp, sizeof (*resp)); 584 return (error); 585 } 586 587 if (!error) { 588 fngp->fng_verbose = resp->lu_verbose; 589 switch (resp->lu_res) { 590 case AUTOFS_OK: 591 switch (resp->lu_type.action) { 592 case AUTOFS_MOUNT_RQ: 593 lnp->link = NULL; 594 lnp->dir = NULL; 595 *mountreq = TRUE; 596 break; 597 case AUTOFS_LINK_RQ: 598 p = 599 &resp->lu_type.lookup_result_type_u.lt_linka; 600 lnp->dir = kmem_alloc(strlen(p->dir) + 1, 601 KM_SLEEP); 602 (void) strcpy(lnp->dir, p->dir); 603 lnp->link = kmem_alloc(strlen(p->link) + 1, 604 KM_SLEEP); 605 (void) strcpy(lnp->link, p->link); 606 break; 607 case AUTOFS_NONE: 608 lnp->link = NULL; 609 lnp->dir = NULL; 610 break; 611 default: 612 auto_log(fngp->fng_verbose, 613 fngp->fng_zoneid, CE_WARN, 614 "auto_lookup_request: bad action type %d", 615 resp->lu_res); 616 error = ENOENT; 617 } 618 break; 619 case AUTOFS_NOENT: 620 error = ENOENT; 621 break; 622 default: 623 error = ENOENT; 624 auto_log(fngp->fng_verbose, fngp->fng_zoneid, CE_WARN, 625 "auto_lookup_request: unknown result: %d", 626 resp->lu_res); 627 break; 628 } 629 } 630 done: 631 xdr_free(xdr_autofs_lookupres, (char *)resp); 632 kmem_free(resp, sizeof (*resp)); 633 AUTOFS_DPRINT((5, "auto_lookup_request: path=%s name=%s error=%d\n", 634 fnip->fi_path, key, error)); 635 return (error); 636 } 637 638 static int 639 auto_mount_request( 640 fninfo_t *fnip, 641 char *key, 642 action_list **alpp, 643 bool_t hard) 644 { 645 int error; 646 struct autofs_globals *fngp; 647 autofs_lookupargs reqst; 648 autofs_mountres *xdrres = NULL; 649 650 AUTOFS_DPRINT((4, "auto_mount_request: path=%s name=%s\n", 651 fnip->fi_path, key)); 652 653 fngp = vntofn(fnip->fi_rootvp)->fn_globals; 654 reqst.map = fnip->fi_map; 655 reqst.path = fnip->fi_path; 656 657 if (fnip->fi_flags & MF_DIRECT) 658 reqst.name = fnip->fi_key; 659 else 660 reqst.name = key; 661 662 AUTOFS_DPRINT((4, "auto_mount_request: using key=%s\n", reqst.name)); 663 664 reqst.subdir = fnip->fi_subdir; 665 reqst.opts = fnip->fi_opts; 666 reqst.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE; 667 668 xdrres = kmem_zalloc(sizeof (*xdrres), KM_SLEEP); 669 670 error = auto_calldaemon(fngp->fng_zoneid, 671 AUTOFS_MNTINFO, 672 xdr_autofs_lookupargs, 673 &reqst, 674 xdr_autofs_mountres, 675 (void *)xdrres, 676 sizeof (autofs_mountres), 677 hard); 678 679 680 if (!error) { 681 fngp->fng_verbose = xdrres->mr_verbose; 682 switch (xdrres->mr_type.status) { 683 case AUTOFS_ACTION: 684 error = 0; 685 /* 686 * Save the action list since it is used by 687 * the caller. We NULL the action list pointer 688 * in 'result' so that xdr_free() will not free 689 * the list. 690 */ 691 *alpp = xdrres->mr_type.mount_result_type_u.list; 692 xdrres->mr_type.mount_result_type_u.list = NULL; 693 break; 694 case AUTOFS_DONE: 695 error = xdrres->mr_type.mount_result_type_u.error; 696 break; 697 default: 698 error = ENOENT; 699 auto_log(fngp->fng_verbose, fngp->fng_zoneid, CE_WARN, 700 "auto_mount_request: unknown status %d", 701 xdrres->mr_type.status); 702 break; 703 } 704 } 705 706 xdr_free(xdr_autofs_mountres, (char *)xdrres); 707 kmem_free(xdrres, sizeof (*xdrres)); 708 709 710 AUTOFS_DPRINT((5, "auto_mount_request: path=%s name=%s error=%d\n", 711 fnip->fi_path, key, error)); 712 return (error); 713 } 714 715 716 static int 717 auto_send_unmount_request( 718 fninfo_t *fnip, 719 umntrequest *ul, 720 bool_t hard) 721 { 722 int error; 723 umntres xdrres; 724 725 struct autofs_globals *fngp = vntofn(fnip->fi_rootvp)->fn_globals; 726 727 AUTOFS_DPRINT((4, "\tauto_send_unmount_request: fstype=%s " 728 " mntpnt=%s\n", ul->fstype, ul->mntpnt)); 729 730 bzero(&xdrres, sizeof (umntres)); 731 error = auto_calldaemon(fngp->fng_zoneid, 732 AUTOFS_UNMOUNT, 733 xdr_umntrequest, 734 (void *)ul, 735 xdr_umntres, 736 (void *)&xdrres, 737 sizeof (umntres), 738 hard); 739 740 if (!error) 741 error = xdrres.status; 742 743 AUTOFS_DPRINT((5, "\tauto_send_unmount_request: error=%d\n", error)); 744 745 return (error); 746 } 747 748 static int 749 auto_perform_link(fnnode_t *fnp, struct linka *linkp, cred_t *cred) 750 { 751 vnode_t *vp; 752 size_t len; 753 char *tmp; 754 755 AUTOFS_DPRINT((3, "auto_perform_link: fnp=%p dir=%s link=%s\n", 756 (void *)fnp, linkp->dir, linkp->link)); 757 758 len = strlen(linkp->link) + 1; /* include '\0' */ 759 tmp = kmem_zalloc(len, KM_SLEEP); 760 (void) kcopy(linkp->link, tmp, len); 761 mutex_enter(&fnp->fn_lock); 762 fnp->fn_symlink = tmp; 763 fnp->fn_symlinklen = (uint_t)len; 764 fnp->fn_flags |= MF_THISUID_MATCH_RQD; 765 crhold(cred); 766 fnp->fn_cred = cred; 767 mutex_exit(&fnp->fn_lock); 768 769 vp = fntovn(fnp); 770 vp->v_type = VLNK; 771 772 return (0); 773 } 774 775 static void 776 auto_free_autofs_args(struct mounta *m) 777 { 778 autofs_args *aargs = (autofs_args *)m->dataptr; 779 780 if (aargs->addr.buf) 781 kmem_free(aargs->addr.buf, aargs->addr.len); 782 if (aargs->path) 783 kmem_free(aargs->path, strlen(aargs->path) + 1); 784 if (aargs->opts) 785 kmem_free(aargs->opts, strlen(aargs->opts) + 1); 786 if (aargs->map) 787 kmem_free(aargs->map, strlen(aargs->map) + 1); 788 if (aargs->subdir) 789 kmem_free(aargs->subdir, strlen(aargs->subdir) + 1); 790 if (aargs->key) 791 kmem_free(aargs->key, strlen(aargs->key) + 1); 792 kmem_free(aargs, sizeof (*aargs)); 793 } 794 795 static void 796 auto_free_action_list(action_list *alp) 797 { 798 struct mounta *m; 799 action_list *lastalp; 800 char *fstype; 801 802 m = &alp->action.action_list_entry_u.mounta; 803 while (alp != NULL) { 804 fstype = alp->action.action_list_entry_u.mounta.fstype; 805 m = &alp->action.action_list_entry_u.mounta; 806 if (m->dataptr) { 807 if (strcmp(fstype, "autofs") == 0) { 808 auto_free_autofs_args(m); 809 } 810 } 811 if (m->spec) 812 kmem_free(m->spec, strlen(m->spec) + 1); 813 if (m->dir) 814 kmem_free(m->dir, strlen(m->dir) + 1); 815 if (m->fstype) 816 kmem_free(m->fstype, strlen(m->fstype) + 1); 817 if (m->optptr) 818 kmem_free(m->optptr, m->optlen); 819 lastalp = alp; 820 alp = alp->next; 821 kmem_free(lastalp, sizeof (*lastalp)); 822 } 823 } 824 825 static boolean_t 826 auto_invalid_autofs(fninfo_t *dfnip, fnnode_t *dfnp, action_list *p) 827 { 828 struct mounta *m; 829 struct autofs_args *argsp; 830 vnode_t *dvp; 831 char buff[AUTOFS_MAXPATHLEN]; 832 size_t len; 833 struct autofs_globals *fngp; 834 835 fngp = dfnp->fn_globals; 836 dvp = fntovn(dfnp); 837 838 m = &p->action.action_list_entry_u.mounta; 839 /* 840 * Make sure we aren't geting passed NULL values or a "dir" that 841 * isn't "." and doesn't begin with "./". 842 * 843 * We also only want to perform autofs mounts, so make sure 844 * no-one is trying to trick us into doing anything else. 845 */ 846 if (m->spec == NULL || m->dir == NULL || m->dir[0] != '.' || 847 (m->dir[1] != '/' && m->dir[1] != '\0') || 848 m->fstype == NULL || strcmp(m->fstype, "autofs") != 0 || 849 m->dataptr == NULL || m->datalen != sizeof (struct autofs_args) || 850 m->optptr == NULL) 851 return (B_TRUE); 852 /* 853 * We also don't like ".."s in the pathname. Symlinks are 854 * handled by the fact that we'll use NOFOLLOW when we do 855 * lookup()s. 856 */ 857 if (strstr(m->dir, "/../") != NULL || 858 (len = strlen(m->dir)) > sizeof ("/..") - 1 && 859 m->dir[len] == '.' && m->dir[len - 1] == '.' && 860 m->dir[len - 2] == '/') 861 return (B_TRUE); 862 argsp = (struct autofs_args *)m->dataptr; 863 /* 864 * We don't want NULL values here either. 865 */ 866 if (argsp->addr.buf == NULL || argsp->path == NULL || 867 argsp->opts == NULL || argsp->map == NULL || argsp->subdir == NULL) 868 return (B_TRUE); 869 /* 870 * We know what the claimed pathname *should* look like: 871 * 872 * If the parent (dfnp) is a mount point (VROOT), then 873 * the path should be (dfnip->fi_path + m->dir). 874 * 875 * Else, we know we're only two levels deep, so we use 876 * (dfnip->fi_path + dfnp->fn_name + m->dir). 877 * 878 * Furthermore, "." only makes sense if dfnp is a 879 * trigger node. 880 * 881 * At this point it seems like the passed-in path is 882 * redundant. 883 */ 884 if (dvp->v_flag & VROOT) { 885 if (m->dir[1] == '\0' && !(dfnp->fn_flags & MF_TRIGGER)) 886 return (B_TRUE); 887 (void) snprintf(buff, sizeof (buff), "%s%s", 888 dfnip->fi_path, m->dir + 1); 889 } else { 890 (void) snprintf(buff, sizeof (buff), "%s/%s%s", 891 dfnip->fi_path, dfnp->fn_name, m->dir + 1); 892 } 893 if (strcmp(argsp->path, buff) != 0) { 894 auto_log(fngp->fng_verbose, fngp->fng_zoneid, 895 CE_WARN, "autofs: expected path of '%s', " 896 "got '%s' instead.", buff, argsp->path); 897 return (B_TRUE); 898 } 899 return (B_FALSE); /* looks OK */ 900 } 901 902 /* 903 * auto_invalid_action will validate the action_list received. If all is good 904 * this function returns FALSE, if there is a problem it returns TRUE. 905 */ 906 static boolean_t 907 auto_invalid_action(fninfo_t *dfnip, fnnode_t *dfnp, action_list *alistpp) 908 { 909 910 /* 911 * Before we go any further, this better be a mount request. 912 */ 913 if (alistpp->action.action != AUTOFS_MOUNT_RQ) 914 return (B_TRUE); 915 return (auto_invalid_autofs(dfnip, dfnp, alistpp)); 916 917 } 918 919 static int 920 auto_perform_actions( 921 fninfo_t *dfnip, 922 fnnode_t *dfnp, 923 action_list *alp, 924 cred_t *cred) /* Credentials of the caller */ 925 { 926 927 action_list *p; 928 struct mounta *m, margs; 929 struct autofs_args *argsp; 930 int error, success = 0; 931 vnode_t *mvp, *dvp, *newvp; 932 fnnode_t *newfnp, *mfnp; 933 int auto_mount = 0; 934 int save_triggers = 0; 935 int update_times = 0; 936 char *mntpnt; 937 char buff[AUTOFS_MAXPATHLEN]; 938 timestruc_t now; 939 struct autofs_globals *fngp; 940 cred_t *zcred; 941 942 AUTOFS_DPRINT((4, "auto_perform_actions: alp=%p\n", 943 (void *)alp)); 944 945 fngp = dfnp->fn_globals; 946 dvp = fntovn(dfnp); 947 948 /* 949 * As automountd running in a zone may be compromised, and this may be 950 * an attack, we can't trust everything passed in by automountd, and we 951 * need to do argument verification. We'll issue a warning and drop 952 * the request if it doesn't seem right. 953 */ 954 955 for (p = alp; p != NULL; p = p->next) { 956 if (auto_invalid_action(dfnip, dfnp, p)) { 957 /* 958 * This warning should be sent to the global zone, 959 * since presumably the zone administrator is the same 960 * as the attacker. 961 */ 962 cmn_err(CE_WARN, "autofs: invalid action list received " 963 "by automountd in zone %s.", 964 curproc->p_zone->zone_name); 965 /* 966 * This conversation is over. 967 */ 968 xdr_free(xdr_action_list, (char *)alp); 969 return (EINVAL); 970 } 971 } 972 973 zcred = zone_get_kcred(getzoneid()); 974 ASSERT(zcred != NULL); 975 976 if (vn_mountedvfs(dvp) != NULL) { 977 /* 978 * The daemon successfully mounted a filesystem 979 * on the AUTOFS root node. 980 */ 981 mutex_enter(&dfnp->fn_lock); 982 dfnp->fn_flags |= MF_MOUNTPOINT; 983 ASSERT(dfnp->fn_dirents == NULL); 984 mutex_exit(&dfnp->fn_lock); 985 success++; 986 } else { 987 /* 988 * Clear MF_MOUNTPOINT. 989 */ 990 mutex_enter(&dfnp->fn_lock); 991 if (dfnp->fn_flags & MF_MOUNTPOINT) { 992 AUTOFS_DPRINT((10, "autofs: clearing mountpoint " 993 "flag on %s.", dfnp->fn_name)); 994 ASSERT(dfnp->fn_dirents == NULL); 995 ASSERT(dfnp->fn_trigger == NULL); 996 } 997 dfnp->fn_flags &= ~MF_MOUNTPOINT; 998 mutex_exit(&dfnp->fn_lock); 999 } 1000 1001 for (p = alp; p != NULL; p = p->next) { 1002 1003 vfs_t *vfsp; /* dummy argument */ 1004 vfs_t *mvfsp; 1005 1006 auto_mount = 0; 1007 1008 m = &p->action.action_list_entry_u.mounta; 1009 argsp = (struct autofs_args *)m->dataptr; 1010 ASSERT(strcmp(m->fstype, "autofs") == 0); 1011 /* 1012 * use the parent directory's timeout since it's the 1013 * one specified/inherited by automount. 1014 */ 1015 argsp->mount_to = dfnip->fi_mount_to; 1016 /* 1017 * The mountpoint is relative, and it is guaranteed to 1018 * begin with "." 1019 * 1020 */ 1021 ASSERT(m->dir[0] == '.'); 1022 if (m->dir[0] == '.' && m->dir[1] == '\0') { 1023 /* 1024 * mounting on the trigger node 1025 */ 1026 mvp = dvp; 1027 VN_HOLD(mvp); 1028 goto mount; 1029 } 1030 /* 1031 * ignore "./" in front of mountpoint 1032 */ 1033 ASSERT(m->dir[1] == '/'); 1034 mntpnt = m->dir + 2; 1035 1036 AUTOFS_DPRINT((10, "\tdfnip->fi_path=%s\n", dfnip->fi_path)); 1037 AUTOFS_DPRINT((10, "\tdfnip->fi_flags=%x\n", dfnip->fi_flags)); 1038 AUTOFS_DPRINT((10, "\tmntpnt=%s\n", mntpnt)); 1039 1040 if (dfnip->fi_flags & MF_DIRECT) { 1041 AUTOFS_DPRINT((10, "\tDIRECT\n")); 1042 (void) sprintf(buff, "%s/%s", dfnip->fi_path, 1043 mntpnt); 1044 } else { 1045 AUTOFS_DPRINT((10, "\tINDIRECT\n")); 1046 (void) sprintf(buff, "%s/%s/%s", 1047 dfnip->fi_path, 1048 dfnp->fn_name, mntpnt); 1049 } 1050 1051 if (vn_mountedvfs(dvp) == NULL) { 1052 /* 1053 * Daemon didn't mount anything on the root 1054 * We have to create the mountpoint if it 1055 * doesn't exist already 1056 * 1057 * We use the caller's credentials in case a 1058 * UID-match is required 1059 * (MF_THISUID_MATCH_RQD). 1060 */ 1061 rw_enter(&dfnp->fn_rwlock, RW_WRITER); 1062 error = auto_search(dfnp, mntpnt, &mfnp, cred); 1063 if (error == 0) { 1064 /* 1065 * AUTOFS mountpoint exists 1066 */ 1067 if (vn_mountedvfs(fntovn(mfnp)) != NULL) { 1068 cmn_err(CE_PANIC, 1069 "auto_perform_actions:" 1070 " mfnp=%p covered", 1071 (void *)mfnp); 1072 } 1073 } else { 1074 /* 1075 * Create AUTOFS mountpoint 1076 */ 1077 ASSERT((dfnp->fn_flags & MF_MOUNTPOINT) == 0); 1078 error = auto_enter(dfnp, mntpnt, &mfnp, cred); 1079 ASSERT(mfnp->fn_linkcnt == 1); 1080 mfnp->fn_linkcnt++; 1081 } 1082 if (!error) 1083 update_times = 1; 1084 rw_exit(&dfnp->fn_rwlock); 1085 ASSERT(error != EEXIST); 1086 if (!error) { 1087 /* 1088 * mfnp is already held. 1089 */ 1090 mvp = fntovn(mfnp); 1091 } else { 1092 auto_log(fngp->fng_verbose, fngp->fng_zoneid, 1093 CE_WARN, "autofs: mount of %s " 1094 "failed - can't create" 1095 " mountpoint.", buff); 1096 continue; 1097 } 1098 } else { 1099 /* 1100 * Find mountpoint in VFS mounted here. If not 1101 * found, fail the submount, though the overall 1102 * mount has succeeded since the root is 1103 * mounted. 1104 */ 1105 if (error = auto_getmntpnt(dvp, mntpnt, &mvp, 1106 kcred)) { 1107 auto_log(fngp->fng_verbose, 1108 fngp->fng_zoneid, 1109 CE_WARN, "autofs: mount of %s " 1110 "failed - mountpoint doesn't" 1111 " exist.", buff); 1112 continue; 1113 } 1114 if (mvp->v_type == VLNK) { 1115 auto_log(fngp->fng_verbose, 1116 fngp->fng_zoneid, 1117 CE_WARN, "autofs: %s symbolic " 1118 "link: not a valid mountpoint " 1119 "- mount failed", buff); 1120 VN_RELE(mvp); 1121 error = ENOENT; 1122 continue; 1123 } 1124 } 1125 mount: 1126 m->flags |= MS_SYSSPACE | MS_OPTIONSTR; 1127 1128 /* 1129 * Copy mounta struct here so we can substitute a 1130 * buffer that is large enough to hold the returned 1131 * option string, if that string is longer than the 1132 * input option string. 1133 * This can happen if there are default options enabled 1134 * that were not in the input option string. 1135 */ 1136 bcopy(m, &margs, sizeof (*m)); 1137 margs.optptr = kmem_alloc(MAX_MNTOPT_STR, KM_SLEEP); 1138 margs.optlen = MAX_MNTOPT_STR; 1139 (void) strcpy(margs.optptr, m->optptr); 1140 margs.dir = argsp->path; 1141 1142 /* 1143 * We use the zone's kcred because we don't want the 1144 * zone to be able to thus do something it wouldn't 1145 * normally be able to. 1146 */ 1147 error = domount(NULL, &margs, mvp, zcred, &vfsp); 1148 kmem_free(margs.optptr, MAX_MNTOPT_STR); 1149 if (error != 0) { 1150 auto_log(fngp->fng_verbose, fngp->fng_zoneid, 1151 CE_WARN, "autofs: domount of %s failed " 1152 "error=%d", buff, error); 1153 VN_RELE(mvp); 1154 continue; 1155 } 1156 VFS_RELE(vfsp); 1157 1158 /* 1159 * If mountpoint is an AUTOFS node, then I'm going to 1160 * flag it that the Filesystem mounted on top was 1161 * mounted in the kernel so that the unmount can be 1162 * done inside the kernel as well. 1163 * I don't care to flag non-AUTOFS mountpoints when an 1164 * AUTOFS in-kernel mount was done on top, because the 1165 * unmount routine already knows that such case was 1166 * done in the kernel. 1167 */ 1168 if (vfs_matchops(dvp->v_vfsp, 1169 vfs_getops(mvp->v_vfsp))) { 1170 mfnp = vntofn(mvp); 1171 mutex_enter(&mfnp->fn_lock); 1172 mfnp->fn_flags |= MF_IK_MOUNT; 1173 mutex_exit(&mfnp->fn_lock); 1174 } 1175 1176 (void) vn_vfswlock_wait(mvp); 1177 mvfsp = vn_mountedvfs(mvp); 1178 if (mvfsp != NULL) { 1179 vfs_lock_wait(mvfsp); 1180 vn_vfsunlock(mvp); 1181 error = VFS_ROOT(mvfsp, &newvp); 1182 vfs_unlock(mvfsp); 1183 if (error) { 1184 /* 1185 * We've dropped the locks, so let's 1186 * get the mounted vfs again in case 1187 * it changed. 1188 */ 1189 (void) vn_vfswlock_wait(mvp); 1190 mvfsp = vn_mountedvfs(mvp); 1191 if (mvfsp != NULL) { 1192 error = dounmount(mvfsp, 0, CRED()); 1193 if (error) { 1194 cmn_err(CE_WARN, 1195 "autofs: could" 1196 " not unmount" 1197 " vfs=%p", 1198 (void *)mvfsp); 1199 } 1200 } else 1201 vn_vfsunlock(mvp); 1202 VN_RELE(mvp); 1203 continue; 1204 } 1205 } else { 1206 vn_vfsunlock(mvp); 1207 VN_RELE(mvp); 1208 continue; 1209 } 1210 1211 auto_mount = vfs_matchops(dvp->v_vfsp, 1212 vfs_getops(newvp->v_vfsp)); 1213 newfnp = vntofn(newvp); 1214 newfnp->fn_parent = dfnp; 1215 1216 /* 1217 * At this time we want to save the AUTOFS filesystem 1218 * as a trigger node. (We only do this if the mount 1219 * occurred on a node different from the root. 1220 * We look at the trigger nodes during 1221 * the automatic unmounting to make sure we remove them 1222 * as a unit and remount them as a unit if the 1223 * filesystem mounted at the root could not be 1224 * unmounted. 1225 */ 1226 if (auto_mount && (error == 0) && (mvp != dvp)) { 1227 save_triggers++; 1228 /* 1229 * Add AUTOFS mount to hierarchy 1230 */ 1231 newfnp->fn_flags |= MF_TRIGGER; 1232 rw_enter(&newfnp->fn_rwlock, RW_WRITER); 1233 newfnp->fn_next = dfnp->fn_trigger; 1234 rw_exit(&newfnp->fn_rwlock); 1235 rw_enter(&dfnp->fn_rwlock, RW_WRITER); 1236 dfnp->fn_trigger = newfnp; 1237 rw_exit(&dfnp->fn_rwlock); 1238 /* 1239 * Don't VN_RELE(newvp) here since dfnp now 1240 * holds reference to it as its trigger node. 1241 */ 1242 AUTOFS_DPRINT((10, "\tadding trigger %s to %s\n", 1243 newfnp->fn_name, dfnp->fn_name)); 1244 AUTOFS_DPRINT((10, "\tfirst trigger is %s\n", 1245 dfnp->fn_trigger->fn_name)); 1246 if (newfnp->fn_next != NULL) 1247 AUTOFS_DPRINT((10, 1248 "\tnext trigger is %s\n", 1249 newfnp->fn_next->fn_name)); 1250 else 1251 AUTOFS_DPRINT((10, 1252 "\tno next trigger\n")); 1253 } else 1254 VN_RELE(newvp); 1255 1256 if (!error) 1257 success++; 1258 1259 if (update_times) { 1260 gethrestime(&now); 1261 dfnp->fn_atime = dfnp->fn_mtime = now; 1262 } 1263 1264 VN_RELE(mvp); 1265 } 1266 1267 if (save_triggers) { 1268 /* 1269 * Make sure the parent can't be freed while it has triggers. 1270 */ 1271 VN_HOLD(dvp); 1272 } 1273 1274 crfree(zcred); 1275 1276 done: 1277 /* 1278 * Return failure if daemon didn't mount anything, and all 1279 * kernel mounts attempted failed. 1280 */ 1281 error = success ? 0 : ENOENT; 1282 1283 if (alp != NULL) { 1284 if ((error == 0) && save_triggers) { 1285 /* 1286 * Save action_list information, so that we can use it 1287 * when it comes time to remount the trigger nodes 1288 * The action list is freed when the directory node 1289 * containing the reference to it is unmounted in 1290 * unmount_tree(). 1291 */ 1292 mutex_enter(&dfnp->fn_lock); 1293 ASSERT(dfnp->fn_alp == NULL); 1294 dfnp->fn_alp = alp; 1295 mutex_exit(&dfnp->fn_lock); 1296 } else { 1297 /* 1298 * free the action list now, 1299 */ 1300 xdr_free(xdr_action_list, (char *)alp); 1301 } 1302 } 1303 AUTOFS_DPRINT((5, "auto_perform_actions: error=%d\n", error)); 1304 return (error); 1305 } 1306 1307 fnnode_t * 1308 auto_makefnnode( 1309 vtype_t type, 1310 vfs_t *vfsp, 1311 char *name, 1312 cred_t *cred, 1313 struct autofs_globals *fngp) 1314 { 1315 fnnode_t *fnp; 1316 vnode_t *vp; 1317 char *tmpname; 1318 timestruc_t now; 1319 /* 1320 * autofs uses odd inode numbers 1321 * automountd uses even inode numbers 1322 * 1323 * To preserve the age-old semantics that inum+devid is unique across 1324 * the system, this variable must be global across zones. 1325 */ 1326 static ino_t nodeid = 3; 1327 1328 fnp = kmem_zalloc(sizeof (*fnp), KM_SLEEP); 1329 fnp->fn_vnode = vn_alloc(KM_SLEEP); 1330 1331 vp = fntovn(fnp); 1332 tmpname = kmem_alloc(strlen(name) + 1, KM_SLEEP); 1333 (void) strcpy(tmpname, name); 1334 fnp->fn_name = &tmpname[0]; 1335 fnp->fn_namelen = (int)strlen(tmpname) + 1; /* include '\0' */ 1336 fnp->fn_uid = crgetuid(cred); 1337 fnp->fn_gid = crgetgid(cred); 1338 /* 1339 * ".." is added in auto_enter and auto_mount. 1340 * "." is added in auto_mkdir and auto_mount. 1341 */ 1342 /* 1343 * Note that fn_size and fn_linkcnt are already 0 since 1344 * we used kmem_zalloc to allocated fnp 1345 */ 1346 fnp->fn_mode = AUTOFS_MODE; 1347 gethrestime(&now); 1348 fnp->fn_atime = fnp->fn_mtime = fnp->fn_ctime = now; 1349 fnp->fn_ref_time = now.tv_sec; 1350 mutex_enter(&autofs_nodeid_lock); 1351 fnp->fn_nodeid = nodeid; 1352 nodeid += 2; 1353 fnp->fn_globals = fngp; 1354 fngp->fng_fnnode_count++; 1355 mutex_exit(&autofs_nodeid_lock); 1356 vn_setops(vp, auto_vnodeops); 1357 vp->v_type = type; 1358 vp->v_data = (void *)fnp; 1359 vp->v_vfsp = vfsp; 1360 mutex_init(&fnp->fn_lock, NULL, MUTEX_DEFAULT, NULL); 1361 rw_init(&fnp->fn_rwlock, NULL, RW_DEFAULT, NULL); 1362 cv_init(&fnp->fn_cv_mount, NULL, CV_DEFAULT, NULL); 1363 vn_exists(vp); 1364 return (fnp); 1365 } 1366 1367 1368 void 1369 auto_freefnnode(fnnode_t *fnp) 1370 { 1371 vnode_t *vp = fntovn(fnp); 1372 1373 AUTOFS_DPRINT((4, "auto_freefnnode: fnp=%p\n", (void *)fnp)); 1374 1375 ASSERT(fnp->fn_linkcnt == 0); 1376 ASSERT(vp->v_count == 0); 1377 ASSERT(fnp->fn_dirents == NULL); 1378 ASSERT(fnp->fn_parent == NULL); 1379 1380 vn_invalid(vp); 1381 kmem_free(fnp->fn_name, fnp->fn_namelen); 1382 if (fnp->fn_symlink) { 1383 ASSERT(fnp->fn_flags & MF_THISUID_MATCH_RQD); 1384 kmem_free(fnp->fn_symlink, fnp->fn_symlinklen); 1385 } 1386 if (fnp->fn_cred) 1387 crfree(fnp->fn_cred); 1388 mutex_destroy(&fnp->fn_lock); 1389 rw_destroy(&fnp->fn_rwlock); 1390 cv_destroy(&fnp->fn_cv_mount); 1391 vn_free(vp); 1392 1393 mutex_enter(&autofs_nodeid_lock); 1394 fnp->fn_globals->fng_fnnode_count--; 1395 mutex_exit(&autofs_nodeid_lock); 1396 kmem_free(fnp, sizeof (*fnp)); 1397 } 1398 1399 void 1400 auto_disconnect( 1401 fnnode_t *dfnp, 1402 fnnode_t *fnp) 1403 { 1404 fnnode_t *tmp, **fnpp; 1405 vnode_t *vp = fntovn(fnp); 1406 timestruc_t now; 1407 1408 AUTOFS_DPRINT((4, 1409 "auto_disconnect: dfnp=%p fnp=%p linkcnt=%d\n v_count=%d", 1410 (void *)dfnp, (void *)fnp, fnp->fn_linkcnt, vp->v_count)); 1411 1412 ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock)); 1413 ASSERT(fnp->fn_linkcnt == 1); 1414 1415 if (vn_mountedvfs(vp) != NULL) { 1416 cmn_err(CE_PANIC, "auto_disconnect: vp %p mounted on", 1417 (void *)vp); 1418 } 1419 1420 /* 1421 * Decrement by 1 because we're removing the entry in dfnp. 1422 */ 1423 fnp->fn_linkcnt--; 1424 fnp->fn_size--; 1425 1426 /* 1427 * only changed while holding parent's (dfnp) rw_lock 1428 */ 1429 fnp->fn_parent = NULL; 1430 1431 fnpp = &dfnp->fn_dirents; 1432 for (;;) { 1433 tmp = *fnpp; 1434 if (tmp == NULL) { 1435 cmn_err(CE_PANIC, 1436 "auto_disconnect: %p not in %p dirent list", 1437 (void *)fnp, (void *)dfnp); 1438 } 1439 if (tmp == fnp) { 1440 *fnpp = tmp->fn_next; /* remove it from the list */ 1441 ASSERT(vp->v_count == 0); 1442 /* child had a pointer to parent ".." */ 1443 dfnp->fn_linkcnt--; 1444 dfnp->fn_size--; 1445 break; 1446 } 1447 fnpp = &tmp->fn_next; 1448 } 1449 1450 mutex_enter(&fnp->fn_lock); 1451 gethrestime(&now); 1452 fnp->fn_atime = fnp->fn_mtime = now; 1453 mutex_exit(&fnp->fn_lock); 1454 1455 AUTOFS_DPRINT((5, "auto_disconnect: done\n")); 1456 } 1457 1458 int 1459 auto_enter(fnnode_t *dfnp, char *name, fnnode_t **fnpp, cred_t *cred) 1460 { 1461 struct fnnode *cfnp, **spp; 1462 vnode_t *dvp = fntovn(dfnp); 1463 ushort_t offset = 0; 1464 ushort_t diff; 1465 1466 AUTOFS_DPRINT((4, "auto_enter: dfnp=%p, name=%s ", (void *)dfnp, name)); 1467 1468 ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock)); 1469 1470 cfnp = dfnp->fn_dirents; 1471 if (cfnp == NULL) { 1472 /* 1473 * offset = 0 for '.' and offset = 1 for '..' 1474 */ 1475 spp = &dfnp->fn_dirents; 1476 offset = 2; 1477 } 1478 1479 for (; cfnp; cfnp = cfnp->fn_next) { 1480 if (strcmp(cfnp->fn_name, name) == 0) { 1481 mutex_enter(&cfnp->fn_lock); 1482 if (cfnp->fn_flags & MF_THISUID_MATCH_RQD) { 1483 /* 1484 * "thisuser" kind of node, need to 1485 * match CREDs as well 1486 */ 1487 mutex_exit(&cfnp->fn_lock); 1488 if (crcmp(cfnp->fn_cred, cred) == 0) 1489 return (EEXIST); 1490 } else { 1491 mutex_exit(&cfnp->fn_lock); 1492 return (EEXIST); 1493 } 1494 } 1495 1496 if (cfnp->fn_next != NULL) { 1497 diff = (ushort_t) 1498 (cfnp->fn_next->fn_offset - cfnp->fn_offset); 1499 ASSERT(diff != 0); 1500 if (diff > 1 && offset == 0) { 1501 offset = (ushort_t)cfnp->fn_offset + 1; 1502 spp = &cfnp->fn_next; 1503 } 1504 } else if (offset == 0) { 1505 offset = (ushort_t)cfnp->fn_offset + 1; 1506 spp = &cfnp->fn_next; 1507 } 1508 } 1509 1510 *fnpp = auto_makefnnode(VDIR, dvp->v_vfsp, name, cred, 1511 dfnp->fn_globals); 1512 if (*fnpp == NULL) 1513 return (ENOMEM); 1514 1515 /* 1516 * I don't hold the mutex on fnpp because I created it, and 1517 * I'm already holding the writers lock for it's parent 1518 * directory, therefore nobody can reference it without me first 1519 * releasing the writers lock. 1520 */ 1521 (*fnpp)->fn_offset = offset; 1522 (*fnpp)->fn_next = *spp; 1523 *spp = *fnpp; 1524 (*fnpp)->fn_parent = dfnp; 1525 (*fnpp)->fn_linkcnt++; /* parent now holds reference to entry */ 1526 (*fnpp)->fn_size++; 1527 1528 /* 1529 * dfnp->fn_linkcnt and dfnp->fn_size protected by dfnp->rw_lock 1530 */ 1531 dfnp->fn_linkcnt++; /* child now holds reference to parent '..' */ 1532 dfnp->fn_size++; 1533 1534 dfnp->fn_ref_time = gethrestime_sec(); 1535 1536 AUTOFS_DPRINT((5, "*fnpp=%p\n", (void *)*fnpp)); 1537 return (0); 1538 } 1539 1540 int 1541 auto_search(fnnode_t *dfnp, char *name, fnnode_t **fnpp, cred_t *cred) 1542 { 1543 vnode_t *dvp; 1544 fnnode_t *p; 1545 int error = ENOENT, match = 0; 1546 1547 AUTOFS_DPRINT((4, "auto_search: dfnp=%p, name=%s...\n", 1548 (void *)dfnp, name)); 1549 1550 dvp = fntovn(dfnp); 1551 if (dvp->v_type != VDIR) { 1552 cmn_err(CE_PANIC, "auto_search: dvp=%p not a directory", 1553 (void *)dvp); 1554 } 1555 1556 ASSERT(RW_LOCK_HELD(&dfnp->fn_rwlock)); 1557 for (p = dfnp->fn_dirents; p != NULL; p = p->fn_next) { 1558 if (strcmp(p->fn_name, name) == 0) { 1559 mutex_enter(&p->fn_lock); 1560 if (p->fn_flags & MF_THISUID_MATCH_RQD) { 1561 /* 1562 * "thisuser" kind of node 1563 * Need to match CREDs as well 1564 */ 1565 mutex_exit(&p->fn_lock); 1566 match = crcmp(p->fn_cred, cred) == 0; 1567 } else { 1568 /* 1569 * No need to check CRED 1570 */ 1571 mutex_exit(&p->fn_lock); 1572 match = 1; 1573 } 1574 } 1575 if (match) { 1576 error = 0; 1577 if (fnpp) { 1578 *fnpp = p; 1579 VN_HOLD(fntovn(*fnpp)); 1580 } 1581 break; 1582 } 1583 } 1584 1585 AUTOFS_DPRINT((5, "auto_search: error=%d\n", error)); 1586 return (error); 1587 } 1588 1589 /* 1590 * If dvp is mounted on, get path's vnode in the mounted on 1591 * filesystem. Path is relative to dvp, ie "./path". 1592 * If successful, *mvp points to a the held mountpoint vnode. 1593 */ 1594 /* ARGSUSED */ 1595 static int 1596 auto_getmntpnt( 1597 vnode_t *dvp, 1598 char *path, 1599 vnode_t **mvpp, /* vnode for mountpoint */ 1600 cred_t *cred) 1601 { 1602 int error = 0; 1603 vnode_t *newvp; 1604 char namebuf[TYPICALMAXPATHLEN]; 1605 struct pathname lookpn; 1606 vfs_t *vfsp; 1607 1608 AUTOFS_DPRINT((4, "auto_getmntpnt: path=%s\n", path)); 1609 1610 if (error = vn_vfsrlock_wait(dvp)) 1611 return (error); 1612 1613 /* 1614 * Now that we have the vfswlock, check to see if dvp 1615 * is still mounted on. If not, then just bail out as 1616 * there is no need to remount the triggers since the 1617 * higher level mount point has gotten unmounted. 1618 */ 1619 vfsp = vn_mountedvfs(dvp); 1620 if (vfsp == NULL) { 1621 vn_vfsunlock(dvp); 1622 error = EBUSY; 1623 goto done; 1624 } 1625 /* 1626 * Since mounted on, lookup "path" in the new filesystem, 1627 * it is important that we do the filesystem jump here to 1628 * avoid lookuppn() calling auto_lookup on dvp and deadlock. 1629 */ 1630 error = VFS_ROOT(vfsp, &newvp); 1631 vn_vfsunlock(dvp); 1632 if (error) 1633 goto done; 1634 1635 /* 1636 * We do a VN_HOLD on newvp just in case the first call to 1637 * lookuppnvp() fails with ENAMETOOLONG. We should still have a 1638 * reference to this vnode for the second call to lookuppnvp(). 1639 */ 1640 VN_HOLD(newvp); 1641 1642 /* 1643 * Now create the pathname struct so we can make use of lookuppnvp, 1644 * and pn_getcomponent. 1645 * This code is similar to lookupname() in fs/lookup.c. 1646 */ 1647 error = pn_get_buf(path, UIO_SYSSPACE, &lookpn, 1648 namebuf, sizeof (namebuf)); 1649 if (error == 0) { 1650 error = lookuppnvp(&lookpn, NULL, NO_FOLLOW, NULLVPP, 1651 mvpp, rootdir, newvp, cred); 1652 } else 1653 VN_RELE(newvp); 1654 if (error == ENAMETOOLONG) { 1655 /* 1656 * This thread used a pathname > TYPICALMAXPATHLEN bytes long. 1657 * newvp is VN_RELE'd by this call to lookuppnvp. 1658 * 1659 * Using 'rootdir' in a zone's context is OK here: we already 1660 * ascertained that there are no '..'s in the path, and we're 1661 * not following symlinks. 1662 */ 1663 if ((error = pn_get(path, UIO_SYSSPACE, &lookpn)) == 0) { 1664 error = lookuppnvp(&lookpn, NULL, NO_FOLLOW, NULLVPP, 1665 mvpp, rootdir, newvp, cred); 1666 pn_free(&lookpn); 1667 } else 1668 VN_RELE(newvp); 1669 } else { 1670 /* 1671 * Need to release newvp here since we held it. 1672 */ 1673 VN_RELE(newvp); 1674 } 1675 1676 done: 1677 AUTOFS_DPRINT((5, "auto_getmntpnt: path=%s *mvpp=%p error=%d\n", 1678 path, (void *)*mvpp, error)); 1679 return (error); 1680 } 1681 1682 #define DEEPER(x) (((x)->fn_dirents != NULL) || \ 1683 (vn_mountedvfs(fntovn((x)))) != NULL) 1684 1685 /* 1686 * The caller, should have already VN_RELE'd its reference to the 1687 * root vnode of this filesystem. 1688 */ 1689 static int 1690 auto_inkernel_unmount(vfs_t *vfsp) 1691 { 1692 vnode_t *cvp = vfsp->vfs_vnodecovered; 1693 int error; 1694 1695 AUTOFS_DPRINT((4, 1696 "auto_inkernel_unmount: devid=%lx mntpnt(%p) count %u\n", 1697 vfsp->vfs_dev, (void *)cvp, cvp->v_count)); 1698 1699 ASSERT(vn_vfswlock_held(cvp)); 1700 1701 /* 1702 * Perform the unmount 1703 * The mountpoint has already been locked by the caller. 1704 */ 1705 error = dounmount(vfsp, 0, kcred); 1706 1707 AUTOFS_DPRINT((5, "auto_inkernel_unmount: exit count %u\n", 1708 cvp->v_count)); 1709 return (error); 1710 } 1711 1712 /* 1713 * unmounts trigger nodes in the kernel. 1714 */ 1715 static void 1716 unmount_triggers(fnnode_t *fnp, action_list **alp) 1717 { 1718 fnnode_t *tp, *next; 1719 int error = 0; 1720 vfs_t *vfsp; 1721 vnode_t *tvp; 1722 1723 AUTOFS_DPRINT((4, "unmount_triggers: fnp=%p\n", (void *)fnp)); 1724 ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock)); 1725 1726 *alp = fnp->fn_alp; 1727 next = fnp->fn_trigger; 1728 while ((tp = next) != NULL) { 1729 tvp = fntovn(tp); 1730 ASSERT(tvp->v_count >= 2); 1731 next = tp->fn_next; 1732 /* 1733 * drop writer's lock since the unmount will end up 1734 * disconnecting this node from fnp and needs to acquire 1735 * the writer's lock again. 1736 * next has at least a reference count >= 2 since it's 1737 * a trigger node, therefore can not be accidentally freed 1738 * by a VN_RELE 1739 */ 1740 rw_exit(&fnp->fn_rwlock); 1741 1742 vfsp = tvp->v_vfsp; 1743 1744 /* 1745 * Its parent was holding a reference to it, since this 1746 * is a trigger vnode. 1747 */ 1748 VN_RELE(tvp); 1749 if (error = auto_inkernel_unmount(vfsp)) { 1750 cmn_err(CE_PANIC, "unmount_triggers: " 1751 "unmount of vp=%p failed error=%d", 1752 (void *)tvp, error); 1753 } 1754 /* 1755 * reacquire writer's lock 1756 */ 1757 rw_enter(&fnp->fn_rwlock, RW_WRITER); 1758 } 1759 1760 /* 1761 * We were holding a reference to our parent. Drop that. 1762 */ 1763 VN_RELE(fntovn(fnp)); 1764 fnp->fn_trigger = NULL; 1765 fnp->fn_alp = NULL; 1766 1767 AUTOFS_DPRINT((5, "unmount_triggers: finished\n")); 1768 } 1769 1770 /* 1771 * This routine locks the mountpoint of every trigger node if they're 1772 * not busy, or returns EBUSY if any node is busy. If a trigger node should 1773 * be unmounted first, then it sets nfnp to point to it, otherwise nfnp 1774 * points to NULL. 1775 */ 1776 static int 1777 triggers_busy(fnnode_t *fnp, fnnode_t **nfnp) 1778 { 1779 int error = 0, done; 1780 int lck_error = 0; 1781 fnnode_t *tp, *t1p; 1782 vfs_t *vfsp; 1783 1784 ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock)); 1785 1786 *nfnp = NULL; 1787 for (tp = fnp->fn_trigger; tp != NULL; tp = tp->fn_next) { 1788 AUTOFS_DPRINT((10, "\ttrigger: %s\n", tp->fn_name)); 1789 vfsp = fntovn(tp)->v_vfsp; 1790 error = 0; 1791 /* 1792 * The vn_vfsunlock will be done in auto_inkernel_unmount. 1793 */ 1794 lck_error = vn_vfswlock(vfsp->vfs_vnodecovered); 1795 if (lck_error == 0) { 1796 mutex_enter(&tp->fn_lock); 1797 ASSERT((tp->fn_flags & MF_LOOKUP) == 0); 1798 if (tp->fn_flags & MF_INPROG) { 1799 /* 1800 * a mount is in progress 1801 */ 1802 error = EBUSY; 1803 } 1804 mutex_exit(&tp->fn_lock); 1805 } 1806 if (lck_error || error || DEEPER(tp) || 1807 ((fntovn(tp))->v_count) > 2) { 1808 /* 1809 * couldn't lock it because it's busy, 1810 * It is mounted on or has dirents? 1811 * If reference count is greater than two, then 1812 * somebody else is holding a reference to this vnode. 1813 * One reference is for the mountpoint, and the second 1814 * is for the trigger node. 1815 */ 1816 AUTOFS_DPRINT((10, "\ttrigger busy\n")); 1817 if ((lck_error == 0) && (error == 0)) { 1818 *nfnp = tp; 1819 /* 1820 * The matching VN_RELE is done in 1821 * unmount_tree(). 1822 */ 1823 VN_HOLD(fntovn(*nfnp)); 1824 } 1825 /* 1826 * Unlock previously locked mountpoints 1827 */ 1828 for (done = 0, t1p = fnp->fn_trigger; !done; 1829 t1p = t1p->fn_next) { 1830 /* 1831 * Unlock all nodes previously 1832 * locked. All nodes up to 'tp' 1833 * were successfully locked. If 'lck_err' is 1834 * set, then 'tp' was not locked, and thus 1835 * should not be unlocked. If 1836 * 'lck_err' is not set, then 'tp' was 1837 * successfully locked, and it should 1838 * be unlocked. 1839 */ 1840 if (t1p != tp || !lck_error) { 1841 vfsp = fntovn(t1p)->v_vfsp; 1842 vn_vfsunlock(vfsp->vfs_vnodecovered); 1843 } 1844 done = (t1p == tp); 1845 } 1846 error = EBUSY; 1847 break; 1848 } 1849 } 1850 1851 AUTOFS_DPRINT((4, "triggers_busy: error=%d\n", error)); 1852 return (error); 1853 } 1854 1855 /* 1856 * Unlock previously locked trigger nodes. 1857 */ 1858 static int 1859 triggers_unlock(fnnode_t *fnp) 1860 { 1861 fnnode_t *tp; 1862 vfs_t *vfsp; 1863 1864 ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock)); 1865 1866 for (tp = fnp->fn_trigger; tp != NULL; tp = tp->fn_next) { 1867 AUTOFS_DPRINT((10, "\tunlock trigger: %s\n", tp->fn_name)); 1868 vfsp = fntovn(tp)->v_vfsp; 1869 vn_vfsunlock(vfsp->vfs_vnodecovered); 1870 } 1871 1872 return (0); 1873 } 1874 1875 /* 1876 * It is the caller's responsibility to grab the VVFSLOCK. 1877 * Releases the VVFSLOCK upon return. 1878 */ 1879 static int 1880 unmount_node(vnode_t *cvp, int force) 1881 { 1882 int error = 0; 1883 fnnode_t *cfnp; 1884 vfs_t *vfsp; 1885 umntrequest ul; 1886 fninfo_t *fnip; 1887 1888 AUTOFS_DPRINT((4, "\tunmount_node cvp=%p\n", (void *)cvp)); 1889 1890 ASSERT(vn_vfswlock_held(cvp)); 1891 cfnp = vntofn(cvp); 1892 vfsp = vn_mountedvfs(cvp); 1893 1894 if (force || cfnp->fn_flags & MF_IK_MOUNT) { 1895 /* 1896 * Mount was performed in the kernel, so 1897 * do an in-kernel unmount. auto_inkernel_unmount() 1898 * will vn_vfsunlock(cvp). 1899 */ 1900 error = auto_inkernel_unmount(vfsp); 1901 } else { 1902 zone_t *zone = NULL; 1903 refstr_t *mntpt, *resource; 1904 size_t mntoptslen; 1905 1906 /* 1907 * Get the mnttab information of the node 1908 * and ask the daemon to unmount it. 1909 */ 1910 bzero(&ul, sizeof (ul)); 1911 mntfs_getmntopts(vfsp, &ul.mntopts, &mntoptslen); 1912 if (ul.mntopts == NULL) { 1913 auto_log(cfnp->fn_globals->fng_verbose, 1914 cfnp->fn_globals->fng_zoneid, 1915 CE_WARN, "unmount_node: " 1916 "no memory"); 1917 vn_vfsunlock(cvp); 1918 error = ENOMEM; 1919 goto done; 1920 } 1921 if (mntoptslen > AUTOFS_MAXOPTSLEN) 1922 ul.mntopts[AUTOFS_MAXOPTSLEN - 1] = '\0'; 1923 1924 mntpt = vfs_getmntpoint(vfsp); 1925 ul.mntpnt = (char *)refstr_value(mntpt); 1926 resource = vfs_getresource(vfsp); 1927 ul.mntresource = (char *)refstr_value(resource); 1928 1929 fnip = vfstofni(cvp->v_vfsp); 1930 ul.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE; 1931 1932 /* 1933 * Since a zone'd automountd's view of the autofs mount points 1934 * differs from those in the kernel, we need to make sure we 1935 * give it consistent mount points. 1936 */ 1937 ASSERT(fnip->fi_zoneid == getzoneid()); 1938 zone = curproc->p_zone; 1939 1940 if (fnip->fi_zoneid != GLOBAL_ZONEID) { 1941 if (ZONE_PATH_VISIBLE(ul.mntpnt, zone)) { 1942 ul.mntpnt = 1943 ZONE_PATH_TRANSLATE(ul.mntpnt, zone); 1944 } 1945 if (ZONE_PATH_VISIBLE(ul.mntresource, zone)) { 1946 ul.mntresource = 1947 ZONE_PATH_TRANSLATE(ul.mntresource, zone); 1948 } 1949 } 1950 1951 ul.fstype = vfssw[vfsp->vfs_fstype].vsw_name; 1952 vn_vfsunlock(cvp); 1953 1954 error = auto_send_unmount_request(fnip, &ul, FALSE); 1955 kmem_free(ul.mntopts, mntoptslen); 1956 refstr_rele(mntpt); 1957 refstr_rele(resource); 1958 } 1959 1960 done: 1961 AUTOFS_DPRINT((5, "\tunmount_node cvp=%p error=%d\n", (void *)cvp, 1962 error)); 1963 return (error); 1964 } 1965 1966 /* 1967 * vp is the "root" of the AUTOFS filesystem. 1968 * return EBUSY if any thread is holding a reference to this vnode 1969 * other than us. 1970 */ 1971 static int 1972 check_auto_node(vnode_t *vp) 1973 { 1974 fnnode_t *fnp; 1975 int error = 0; 1976 /* 1977 * number of references to expect for 1978 * a non-busy vnode. 1979 */ 1980 uint_t count; 1981 1982 AUTOFS_DPRINT((4, "\tcheck_auto_node vp=%p ", (void *)vp)); 1983 fnp = vntofn(vp); 1984 ASSERT(fnp->fn_flags & MF_INPROG); 1985 ASSERT((fnp->fn_flags & MF_LOOKUP) == 0); 1986 1987 count = 1; /* we are holding a reference to vp */ 1988 if (fnp->fn_flags & MF_TRIGGER) { 1989 /* 1990 * parent holds a pointer to us (trigger) 1991 */ 1992 count++; 1993 } 1994 if (fnp->fn_trigger != NULL) { 1995 /* 1996 * The trigger nodes have a hold on us. 1997 */ 1998 count++; 1999 } 2000 mutex_enter(&vp->v_lock); 2001 if (vp->v_flag & VROOT) 2002 count++; 2003 ASSERT(vp->v_count > 0); 2004 AUTOFS_DPRINT((10, "\tcount=%u ", vp->v_count)); 2005 if (vp->v_count > count) 2006 error = EBUSY; 2007 mutex_exit(&vp->v_lock); 2008 2009 AUTOFS_DPRINT((5, "\tcheck_auto_node error=%d ", error)); 2010 return (error); 2011 } 2012 2013 /* 2014 * rootvp is the root of the AUTOFS filesystem. 2015 * If rootvp is busy (v_count > 1) returns EBUSY. 2016 * else removes every vnode under this tree. 2017 * ASSUMPTION: Assumes that the only node which can be busy is 2018 * the root vnode. This filesystem better be two levels deep only, 2019 * the root and its immediate subdirs. 2020 * The daemon will "AUTOFS direct-mount" only one level below the root. 2021 */ 2022 static int 2023 unmount_autofs(vnode_t *rootvp) 2024 { 2025 fnnode_t *fnp, *rootfnp, *nfnp; 2026 int error; 2027 2028 AUTOFS_DPRINT((4, "\tunmount_autofs rootvp=%p ", (void *)rootvp)); 2029 2030 error = check_auto_node(rootvp); 2031 if (error == 0) { 2032 /* 2033 * Remove all its immediate subdirectories. 2034 */ 2035 rootfnp = vntofn(rootvp); 2036 rw_enter(&rootfnp->fn_rwlock, RW_WRITER); 2037 nfnp = NULL; /* lint clean */ 2038 for (fnp = rootfnp->fn_dirents; fnp != NULL; fnp = nfnp) { 2039 ASSERT(fntovn(fnp)->v_count == 0); 2040 ASSERT(fnp->fn_dirents == NULL); 2041 ASSERT(fnp->fn_linkcnt == 2); 2042 fnp->fn_linkcnt--; 2043 auto_disconnect(rootfnp, fnp); 2044 nfnp = fnp->fn_next; 2045 auto_freefnnode(fnp); 2046 } 2047 rw_exit(&rootfnp->fn_rwlock); 2048 } 2049 AUTOFS_DPRINT((5, "\tunmount_autofs error=%d ", error)); 2050 return (error); 2051 } 2052 2053 /* 2054 * max number of unmount threads running 2055 */ 2056 static int autofs_unmount_threads = 5; 2057 2058 /* 2059 * XXX unmount_tree() is not suspend-safe within the scope of 2060 * the present model defined for cpr to suspend the system. Calls made 2061 * by the unmount_tree() that have been identified to be unsafe are 2062 * (1) RPC client handle setup and client calls to automountd which can 2063 * block deep down in the RPC library, (2) kmem_alloc() calls with the 2064 * KM_SLEEP flag which can block if memory is low, and (3) VFS_*() and 2065 * VOP_*() calls which can result in over the wire calls to servers. 2066 * The thread should be completely reevaluated to make it suspend-safe in 2067 * case of future updates to the cpr model. 2068 */ 2069 void 2070 unmount_tree(struct autofs_globals *fngp, int force) 2071 { 2072 vnode_t *vp, *newvp; 2073 vfs_t *vfsp; 2074 fnnode_t *fnp, *nfnp, *pfnp; 2075 action_list *alp; 2076 int error, ilocked_it = 0; 2077 fninfo_t *fnip; 2078 time_t ref_time; 2079 int autofs_busy_root, unmount_as_unit, unmount_done = 0; 2080 timestruc_t now; 2081 2082 callb_cpr_t cprinfo; 2083 kmutex_t unmount_tree_cpr_lock; 2084 2085 mutex_init(&unmount_tree_cpr_lock, NULL, MUTEX_DEFAULT, NULL); 2086 CALLB_CPR_INIT(&cprinfo, &unmount_tree_cpr_lock, callb_generic_cpr, 2087 "unmount_tree"); 2088 2089 /* 2090 * Got to release lock before attempting unmount in case 2091 * it hangs. 2092 */ 2093 rw_enter(&fngp->fng_rootfnnodep->fn_rwlock, RW_READER); 2094 if ((fnp = fngp->fng_rootfnnodep->fn_dirents) == NULL) { 2095 ASSERT(fngp->fng_fnnode_count == 1); 2096 /* 2097 * no autofs mounted, done. 2098 */ 2099 rw_exit(&fngp->fng_rootfnnodep->fn_rwlock); 2100 goto done; 2101 } 2102 VN_HOLD(fntovn(fnp)); 2103 rw_exit(&fngp->fng_rootfnnodep->fn_rwlock); 2104 2105 vp = fntovn(fnp); 2106 fnip = vfstofni(vp->v_vfsp); 2107 /* 2108 * autofssys() will be calling in from the global zone and doing 2109 * work on the behalf of the given zone, hence we can't always assert 2110 * that we have the right credentials, nor that the caller is always in 2111 * the correct zone. 2112 * 2113 * We do, however, know that if this is a "forced unmount" operation 2114 * (which autofssys() does), then we won't go down to the krpc layers, 2115 * so we don't need to fudge with the credentials. 2116 */ 2117 ASSERT(force || fnip->fi_zoneid == getzoneid()); 2118 if (!force && auto_null_request(fnip, FALSE) != 0) { 2119 /* 2120 * automountd not running in this zone, 2121 * don't attempt unmounting this round. 2122 */ 2123 VN_RELE(vp); 2124 goto done; 2125 } 2126 /* reference time for this unmount round */ 2127 ref_time = gethrestime_sec(); 2128 /* 2129 * If this an autofssys() call, we need to make sure we don't skip 2130 * nodes because we think we saw them recently. 2131 */ 2132 mutex_enter(&fnp->fn_lock); 2133 if (force && fnp->fn_unmount_ref_time >= ref_time) 2134 ref_time = fnp->fn_unmount_ref_time + 1; 2135 mutex_exit(&fnp->fn_lock); 2136 2137 AUTOFS_DPRINT((4, "unmount_tree (ID=%ld)\n", ref_time)); 2138 top: 2139 AUTOFS_DPRINT((10, "unmount_tree: %s\n", fnp->fn_name)); 2140 ASSERT(fnp); 2141 vp = fntovn(fnp); 2142 if (vp->v_type == VLNK) { 2143 /* 2144 * can't unmount symbolic links 2145 */ 2146 goto next; 2147 } 2148 fnip = vfstofni(vp->v_vfsp); 2149 ASSERT(vp->v_count > 0); 2150 error = 0; 2151 autofs_busy_root = unmount_as_unit = 0; 2152 alp = NULL; 2153 2154 ilocked_it = 0; 2155 mutex_enter(&fnp->fn_lock); 2156 if (fnp->fn_flags & (MF_INPROG | MF_LOOKUP)) { 2157 /* 2158 * Either a mount, lookup or another unmount of this 2159 * subtree is in progress, don't attempt to unmount at 2160 * this time. 2161 */ 2162 mutex_exit(&fnp->fn_lock); 2163 error = EBUSY; 2164 goto next; 2165 } 2166 if (fnp->fn_unmount_ref_time >= ref_time) { 2167 /* 2168 * Already been here, try next node. 2169 */ 2170 mutex_exit(&fnp->fn_lock); 2171 error = EBUSY; 2172 goto next; 2173 } 2174 fnp->fn_unmount_ref_time = ref_time; 2175 2176 /* 2177 * If forced operation ignore timeout values 2178 */ 2179 if (!force && fnp->fn_ref_time + fnip->fi_mount_to > 2180 gethrestime_sec()) { 2181 /* 2182 * Node has been referenced recently, try the 2183 * unmount of its children if any. 2184 */ 2185 mutex_exit(&fnp->fn_lock); 2186 AUTOFS_DPRINT((10, "fn_ref_time within range\n")); 2187 rw_enter(&fnp->fn_rwlock, RW_READER); 2188 if (fnp->fn_dirents) { 2189 /* 2190 * Has subdirectory, attempt their 2191 * unmount first 2192 */ 2193 nfnp = fnp->fn_dirents; 2194 VN_HOLD(fntovn(nfnp)); 2195 rw_exit(&fnp->fn_rwlock); 2196 2197 VN_RELE(vp); 2198 fnp = nfnp; 2199 goto top; 2200 } 2201 rw_exit(&fnp->fn_rwlock); 2202 /* 2203 * No children, try next node. 2204 */ 2205 error = EBUSY; 2206 goto next; 2207 } 2208 2209 AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG); 2210 fnp->fn_error = 0; 2211 mutex_exit(&fnp->fn_lock); 2212 ilocked_it = 1; 2213 2214 rw_enter(&fnp->fn_rwlock, RW_WRITER); 2215 if (fnp->fn_trigger != NULL) { 2216 unmount_as_unit = 1; 2217 if ((vn_mountedvfs(vp) == NULL) && (check_auto_node(vp))) { 2218 /* 2219 * AUTOFS mountpoint is busy, there's 2220 * no point trying to unmount. Fall through 2221 * to attempt to unmount subtrees rooted 2222 * at a possible trigger node, but remember 2223 * not to unmount this tree. 2224 */ 2225 autofs_busy_root = 1; 2226 } 2227 2228 if (triggers_busy(fnp, &nfnp)) { 2229 rw_exit(&fnp->fn_rwlock); 2230 if (nfnp == NULL) { 2231 error = EBUSY; 2232 goto next; 2233 } 2234 /* 2235 * nfnp is busy, try to unmount it first 2236 */ 2237 mutex_enter(&fnp->fn_lock); 2238 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 2239 mutex_exit(&fnp->fn_lock); 2240 VN_RELE(vp); 2241 ASSERT(fntovn(nfnp)->v_count > 1); 2242 fnp = nfnp; 2243 goto top; 2244 } 2245 2246 /* 2247 * At this point, we know all trigger nodes are locked, 2248 * and they're not busy or mounted on. 2249 */ 2250 2251 if (autofs_busy_root) { 2252 /* 2253 * Got to unlock the the trigger nodes since 2254 * I'm not really going to unmount the filesystem. 2255 */ 2256 (void) triggers_unlock(fnp); 2257 } else { 2258 /* 2259 * Attempt to unmount all the trigger nodes, 2260 * save the action_list in case we need to 2261 * remount them later. The action_list will be 2262 * freed later if there was no need to remount the 2263 * trigger nodes. 2264 */ 2265 unmount_triggers(fnp, &alp); 2266 } 2267 } 2268 rw_exit(&fnp->fn_rwlock); 2269 2270 if (autofs_busy_root) 2271 goto next; 2272 2273 (void) vn_vfswlock_wait(vp); 2274 2275 vfsp = vn_mountedvfs(vp); 2276 if (vfsp != NULL) { 2277 /* 2278 * Node is mounted on. 2279 */ 2280 AUTOFS_DPRINT((10, "\tNode is mounted on\n")); 2281 2282 /* 2283 * Deal with /xfn/host/jurassic alikes here... 2284 */ 2285 if (vfs_matchops(vfsp, vfs_getops(vp->v_vfsp))) { 2286 /* 2287 * If the filesystem mounted here is AUTOFS, and it 2288 * is busy, try to unmount the tree rooted on it 2289 * first. We know this call to VFS_ROOT is safe to 2290 * call while holding VVFSLOCK, since it resolves 2291 * to a call to auto_root(). 2292 */ 2293 AUTOFS_DPRINT((10, "\t\tAUTOFS mounted here\n")); 2294 if (VFS_ROOT(vfsp, &newvp)) { 2295 cmn_err(CE_PANIC, 2296 "unmount_tree: VFS_ROOT(vfs=%p) failed", 2297 (void *)vfsp); 2298 } 2299 nfnp = vntofn(newvp); 2300 if (DEEPER(nfnp)) { 2301 vn_vfsunlock(vp); 2302 mutex_enter(&fnp->fn_lock); 2303 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 2304 mutex_exit(&fnp->fn_lock); 2305 VN_RELE(vp); 2306 fnp = nfnp; 2307 goto top; 2308 } 2309 /* 2310 * Fall through to unmount this filesystem 2311 */ 2312 VN_RELE(newvp); 2313 } 2314 2315 /* 2316 * vn_vfsunlock(vp) is done inside unmount_node() 2317 */ 2318 error = unmount_node(vp, force); 2319 if (error == ECONNRESET) { 2320 AUTOFS_DPRINT((10, "\tConnection dropped\n")); 2321 if (vn_mountedvfs(vp) == NULL) { 2322 /* 2323 * The filesystem was unmounted before the 2324 * daemon died. Unfortunately we can not 2325 * determine whether all the cleanup work was 2326 * successfully finished (i.e. update mnttab, 2327 * or notify NFS server of the unmount). 2328 * We should not retry the operation since the 2329 * filesystem has already been unmounted, and 2330 * may have already been removed from mnttab, 2331 * in such case the devid/rdevid we send to 2332 * the daemon will not be matched. So we have 2333 * to be content with the partial unmount. 2334 * Since the mountpoint is no longer covered, we 2335 * clear the error condition. 2336 */ 2337 error = 0; 2338 auto_log(fngp->fng_verbose, fngp->fng_zoneid, 2339 CE_WARN, 2340 "unmount_tree: automountd connection " 2341 "dropped"); 2342 if (fnip->fi_flags & MF_DIRECT) { 2343 auto_log(fngp->fng_verbose, 2344 fngp->fng_zoneid, CE_WARN, 2345 "unmount_tree: " 2346 "%s successfully unmounted - " 2347 "do not remount triggers", 2348 fnip->fi_path); 2349 } else { 2350 auto_log(fngp->fng_verbose, 2351 fngp->fng_zoneid, CE_WARN, 2352 "unmount_tree: " 2353 "%s/%s successfully unmounted - " 2354 "do not remount triggers", 2355 fnip->fi_path, fnp->fn_name); 2356 } 2357 } 2358 } 2359 } else { 2360 vn_vfsunlock(vp); 2361 AUTOFS_DPRINT((10, "\tNode is AUTOFS\n")); 2362 if (unmount_as_unit) { 2363 AUTOFS_DPRINT((10, "\tunmount as unit\n")); 2364 error = unmount_autofs(vp); 2365 } else { 2366 AUTOFS_DPRINT((10, "\tunmount one at a time\n")); 2367 rw_enter(&fnp->fn_rwlock, RW_READER); 2368 if (fnp->fn_dirents != NULL) { 2369 /* 2370 * Has subdirectory, attempt their 2371 * unmount first 2372 */ 2373 nfnp = fnp->fn_dirents; 2374 VN_HOLD(fntovn(nfnp)); 2375 rw_exit(&fnp->fn_rwlock); 2376 2377 mutex_enter(&fnp->fn_lock); 2378 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 2379 mutex_exit(&fnp->fn_lock); 2380 VN_RELE(vp); 2381 fnp = nfnp; 2382 goto top; 2383 } 2384 rw_exit(&fnp->fn_rwlock); 2385 goto next; 2386 } 2387 } 2388 2389 if (error) { 2390 AUTOFS_DPRINT((10, "\tUnmount failed\n")); 2391 if (alp != NULL) { 2392 /* 2393 * Unmount failed, got to remount triggers. 2394 */ 2395 ASSERT((fnp->fn_flags & MF_THISUID_MATCH_RQD) == 0); 2396 error = auto_perform_actions(fnip, fnp, alp, 2397 CRED()); 2398 if (error) { 2399 auto_log(fngp->fng_verbose, 2400 fngp->fng_zoneid, CE_WARN, 2401 "autofs: can't remount " 2402 "triggers fnp=%p error=%d", (void *)fnp, 2403 error); 2404 error = 0; 2405 /* 2406 * The action list should have been 2407 * free'd by auto_perform_actions 2408 * since an error occured 2409 */ 2410 alp = NULL; 2411 2412 } 2413 } 2414 } else { 2415 /* 2416 * The unmount succeeded, which will cause this node to 2417 * be removed from its parent if its an indirect mount, 2418 * therefore update the parent's atime and mtime now. 2419 * I don't update them in auto_disconnect() because I 2420 * don't want atime and mtime changing every time a 2421 * lookup goes to the daemon and creates a new node. 2422 */ 2423 unmount_done = 1; 2424 if ((fnip->fi_flags & MF_DIRECT) == 0) { 2425 gethrestime(&now); 2426 if (fnp->fn_parent == fngp->fng_rootfnnodep) 2427 fnp->fn_atime = fnp->fn_mtime = now; 2428 else 2429 fnp->fn_parent->fn_atime = 2430 fnp->fn_parent->fn_mtime = now; 2431 } 2432 2433 /* 2434 * Free the action list here 2435 */ 2436 if (alp != NULL) { 2437 xdr_free(xdr_action_list, (char *)alp); 2438 alp = NULL; 2439 } 2440 } 2441 2442 fnp->fn_ref_time = gethrestime_sec(); 2443 2444 next: 2445 /* 2446 * Obtain parent's readers lock before grabbing 2447 * reference to next sibling. 2448 * XXX Note that nodes in the top level list (mounted 2449 * in user space not by the daemon in the kernel) parent is itself, 2450 * therefore grabbing the lock makes no sense, but doesn't 2451 * hurt either. 2452 */ 2453 pfnp = fnp->fn_parent; 2454 ASSERT(pfnp != NULL); 2455 rw_enter(&pfnp->fn_rwlock, RW_READER); 2456 if ((nfnp = fnp->fn_next) != NULL) 2457 VN_HOLD(fntovn(nfnp)); 2458 rw_exit(&pfnp->fn_rwlock); 2459 2460 if (ilocked_it) { 2461 mutex_enter(&fnp->fn_lock); 2462 if (unmount_done) { 2463 /* 2464 * Other threads may be waiting for this unmount to 2465 * finish. We must let it know that in order to 2466 * proceed, it must trigger the mount itself. 2467 */ 2468 fnp->fn_flags &= ~MF_IK_MOUNT; 2469 if (fnp->fn_flags & MF_WAITING) 2470 fnp->fn_error = EAGAIN; 2471 unmount_done = 0; 2472 } 2473 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 2474 mutex_exit(&fnp->fn_lock); 2475 ilocked_it = 0; 2476 } 2477 2478 if (nfnp != NULL) { 2479 VN_RELE(vp); 2480 fnp = nfnp; 2481 /* 2482 * Unmount next element 2483 */ 2484 goto top; 2485 } 2486 2487 /* 2488 * We don't want to unmount rootfnnodep, so the check is made here 2489 */ 2490 ASSERT(pfnp != fnp); 2491 if (pfnp != fngp->fng_rootfnnodep) { 2492 /* 2493 * Now attempt to unmount my parent 2494 */ 2495 VN_HOLD(fntovn(pfnp)); 2496 VN_RELE(vp); 2497 fnp = pfnp; 2498 2499 goto top; 2500 } 2501 2502 VN_RELE(vp); 2503 2504 /* 2505 * At this point we've walked the entire tree and attempted to unmount 2506 * as much as we can one level at a time. 2507 */ 2508 done: 2509 mutex_enter(&unmount_tree_cpr_lock); 2510 CALLB_CPR_EXIT(&cprinfo); 2511 mutex_destroy(&unmount_tree_cpr_lock); 2512 } 2513 2514 static void 2515 unmount_zone_tree(struct autofs_globals *fngp) 2516 { 2517 unmount_tree(fngp, 0); 2518 mutex_enter(&fngp->fng_unmount_threads_lock); 2519 fngp->fng_unmount_threads--; 2520 mutex_exit(&fngp->fng_unmount_threads_lock); 2521 2522 AUTOFS_DPRINT((5, "unmount_tree done. Thread exiting.\n")); 2523 2524 zthread_exit(); 2525 /* NOTREACHED */ 2526 } 2527 2528 static int autofs_unmount_thread_timer = 120; /* in seconds */ 2529 2530 void 2531 auto_do_unmount(struct autofs_globals *fngp) 2532 { 2533 callb_cpr_t cprinfo; 2534 clock_t timeleft; 2535 zone_t *zone = curproc->p_zone; 2536 2537 CALLB_CPR_INIT(&cprinfo, &fngp->fng_unmount_threads_lock, 2538 callb_generic_cpr, "auto_do_unmount"); 2539 2540 for (;;) { /* forever */ 2541 mutex_enter(&fngp->fng_unmount_threads_lock); 2542 CALLB_CPR_SAFE_BEGIN(&cprinfo); 2543 newthread: 2544 mutex_exit(&fngp->fng_unmount_threads_lock); 2545 timeleft = zone_status_timedwait(zone, lbolt + 2546 autofs_unmount_thread_timer * hz, ZONE_IS_SHUTTING_DOWN); 2547 mutex_enter(&fngp->fng_unmount_threads_lock); 2548 2549 if (timeleft != -1) { /* didn't time out */ 2550 ASSERT(zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN); 2551 /* 2552 * zone is exiting... don't create any new threads. 2553 * fng_unmount_threads_lock is released implicitly by 2554 * the below. 2555 */ 2556 CALLB_CPR_SAFE_END(&cprinfo, 2557 &fngp->fng_unmount_threads_lock); 2558 CALLB_CPR_EXIT(&cprinfo); 2559 zthread_exit(); 2560 /* NOTREACHED */ 2561 } 2562 if (fngp->fng_unmount_threads < autofs_unmount_threads) { 2563 fngp->fng_unmount_threads++; 2564 CALLB_CPR_SAFE_END(&cprinfo, 2565 &fngp->fng_unmount_threads_lock); 2566 mutex_exit(&fngp->fng_unmount_threads_lock); 2567 2568 (void) zthread_create(NULL, 0, unmount_zone_tree, fngp, 2569 0, minclsyspri); 2570 } else 2571 goto newthread; 2572 } 2573 /* NOTREACHED */ 2574 } 2575 2576 /* 2577 * Is nobrowse specified in option string? 2578 * opts should be a null ('\0') terminated string. 2579 * Returns non-zero if nobrowse has been specified. 2580 */ 2581 int 2582 auto_nobrowse_option(char *opts) 2583 { 2584 char *buf; 2585 char *p; 2586 char *t; 2587 int nobrowse = 0; 2588 int last_opt = 0; 2589 size_t len; 2590 2591 len = strlen(opts) + 1; 2592 p = buf = kmem_alloc(len, KM_SLEEP); 2593 (void) strcpy(buf, opts); 2594 do { 2595 if (t = strchr(p, ',')) 2596 *t++ = '\0'; 2597 else 2598 last_opt++; 2599 if (strcmp(p, MNTOPT_NOBROWSE) == 0) 2600 nobrowse = 1; 2601 else if (strcmp(p, MNTOPT_BROWSE) == 0) 2602 nobrowse = 0; 2603 p = t; 2604 } while (!last_opt); 2605 kmem_free(buf, len); 2606 2607 return (nobrowse); 2608 } 2609 2610 /* 2611 * used to log warnings only if automountd is running 2612 * with verbose mode set 2613 */ 2614 2615 void 2616 auto_log(int verbose, zoneid_t zoneid, int level, const char *fmt, ...) 2617 { 2618 va_list args; 2619 2620 if (verbose) { 2621 va_start(args, fmt); 2622 vzcmn_err(zoneid, level, fmt, args); 2623 va_end(args); 2624 } 2625 } 2626 2627 #ifdef DEBUG 2628 static int autofs_debug = 0; 2629 2630 /* 2631 * Utilities used by both client and server 2632 * Standard levels: 2633 * 0) no debugging 2634 * 1) hard failures 2635 * 2) soft failures 2636 * 3) current test software 2637 * 4) main procedure entry points 2638 * 5) main procedure exit points 2639 * 6) utility procedure entry points 2640 * 7) utility procedure exit points 2641 * 8) obscure procedure entry points 2642 * 9) obscure procedure exit points 2643 * 10) random stuff 2644 * 11) all <= 1 2645 * 12) all <= 2 2646 * 13) all <= 3 2647 * ... 2648 */ 2649 /* PRINTFLIKE2 */ 2650 void 2651 auto_dprint(int level, const char *fmt, ...) 2652 { 2653 va_list args; 2654 2655 if (autofs_debug == level || 2656 (autofs_debug > 10 && (autofs_debug - 10) >= level)) { 2657 va_start(args, fmt); 2658 (void) vprintf(fmt, args); 2659 va_end(args); 2660 } 2661 } 2662 #endif /* DEBUG */ 2663