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 AUTOFS_DPRINT((5, "\tauto_send_unmount_request: error=%d\n", error)); 741 742 return (error); 743 } 744 745 static int 746 auto_perform_link(fnnode_t *fnp, struct linka *linkp, cred_t *cred) 747 { 748 vnode_t *vp; 749 size_t len; 750 char *tmp; 751 752 AUTOFS_DPRINT((3, "auto_perform_link: fnp=%p dir=%s link=%s\n", 753 (void *)fnp, linkp->dir, linkp->link)); 754 755 len = strlen(linkp->link) + 1; /* include '\0' */ 756 tmp = kmem_zalloc(len, KM_SLEEP); 757 (void) kcopy(linkp->link, tmp, len); 758 mutex_enter(&fnp->fn_lock); 759 fnp->fn_symlink = tmp; 760 fnp->fn_symlinklen = (uint_t)len; 761 fnp->fn_flags |= MF_THISUID_MATCH_RQD; 762 crhold(cred); 763 fnp->fn_cred = cred; 764 mutex_exit(&fnp->fn_lock); 765 766 vp = fntovn(fnp); 767 vp->v_type = VLNK; 768 769 return (0); 770 } 771 772 static void 773 auto_free_autofs_args(struct mounta *m) 774 { 775 autofs_args *aargs = (autofs_args *)m->dataptr; 776 777 if (aargs->addr.buf) 778 kmem_free(aargs->addr.buf, aargs->addr.len); 779 if (aargs->path) 780 kmem_free(aargs->path, strlen(aargs->path) + 1); 781 if (aargs->opts) 782 kmem_free(aargs->opts, strlen(aargs->opts) + 1); 783 if (aargs->map) 784 kmem_free(aargs->map, strlen(aargs->map) + 1); 785 if (aargs->subdir) 786 kmem_free(aargs->subdir, strlen(aargs->subdir) + 1); 787 if (aargs->key) 788 kmem_free(aargs->key, strlen(aargs->key) + 1); 789 kmem_free(aargs, sizeof (*aargs)); 790 } 791 792 static void 793 auto_free_action_list(action_list *alp) 794 { 795 struct mounta *m; 796 action_list *lastalp; 797 char *fstype; 798 799 m = &alp->action.action_list_entry_u.mounta; 800 while (alp != NULL) { 801 fstype = alp->action.action_list_entry_u.mounta.fstype; 802 m = &alp->action.action_list_entry_u.mounta; 803 if (m->dataptr) { 804 if (strcmp(fstype, "autofs") == 0) { 805 auto_free_autofs_args(m); 806 } 807 } 808 if (m->spec) 809 kmem_free(m->spec, strlen(m->spec) + 1); 810 if (m->dir) 811 kmem_free(m->dir, strlen(m->dir) + 1); 812 if (m->fstype) 813 kmem_free(m->fstype, strlen(m->fstype) + 1); 814 if (m->optptr) 815 kmem_free(m->optptr, m->optlen); 816 lastalp = alp; 817 alp = alp->next; 818 kmem_free(lastalp, sizeof (*lastalp)); 819 } 820 } 821 822 static boolean_t 823 auto_invalid_autofs(fninfo_t *dfnip, fnnode_t *dfnp, action_list *p) 824 { 825 struct mounta *m; 826 struct autofs_args *argsp; 827 vnode_t *dvp; 828 char buff[AUTOFS_MAXPATHLEN]; 829 size_t len; 830 struct autofs_globals *fngp; 831 832 fngp = dfnp->fn_globals; 833 dvp = fntovn(dfnp); 834 835 m = &p->action.action_list_entry_u.mounta; 836 /* 837 * Make sure we aren't geting passed NULL values or a "dir" that 838 * isn't "." and doesn't begin with "./". 839 * 840 * We also only want to perform autofs mounts, so make sure 841 * no-one is trying to trick us into doing anything else. 842 */ 843 if (m->spec == NULL || m->dir == NULL || m->dir[0] != '.' || 844 (m->dir[1] != '/' && m->dir[1] != '\0') || 845 m->fstype == NULL || strcmp(m->fstype, "autofs") != 0 || 846 m->dataptr == NULL || m->datalen != sizeof (struct autofs_args) || 847 m->optptr == NULL) 848 return (B_TRUE); 849 /* 850 * We also don't like ".."s in the pathname. Symlinks are 851 * handled by the fact that we'll use NOFOLLOW when we do 852 * lookup()s. 853 */ 854 if (strstr(m->dir, "/../") != NULL || 855 (len = strlen(m->dir)) > sizeof ("/..") - 1 && 856 m->dir[len] == '.' && m->dir[len - 1] == '.' && 857 m->dir[len - 2] == '/') 858 return (B_TRUE); 859 argsp = (struct autofs_args *)m->dataptr; 860 /* 861 * We don't want NULL values here either. 862 */ 863 if (argsp->addr.buf == NULL || argsp->path == NULL || 864 argsp->opts == NULL || argsp->map == NULL || argsp->subdir == NULL) 865 return (B_TRUE); 866 /* 867 * We know what the claimed pathname *should* look like: 868 * 869 * If the parent (dfnp) is a mount point (VROOT), then 870 * the path should be (dfnip->fi_path + m->dir). 871 * 872 * Else, we know we're only two levels deep, so we use 873 * (dfnip->fi_path + dfnp->fn_name + m->dir). 874 * 875 * Furthermore, "." only makes sense if dfnp is a 876 * trigger node. 877 * 878 * At this point it seems like the passed-in path is 879 * redundant. 880 */ 881 if (dvp->v_flag & VROOT) { 882 if (m->dir[1] == '\0' && !(dfnp->fn_flags & MF_TRIGGER)) 883 return (B_TRUE); 884 (void) snprintf(buff, sizeof (buff), "%s%s", 885 dfnip->fi_path, m->dir + 1); 886 } else { 887 (void) snprintf(buff, sizeof (buff), "%s/%s%s", 888 dfnip->fi_path, dfnp->fn_name, m->dir + 1); 889 } 890 if (strcmp(argsp->path, buff) != 0) { 891 auto_log(fngp->fng_verbose, fngp->fng_zoneid, 892 CE_WARN, "autofs: expected path of '%s', " 893 "got '%s' instead.", buff, argsp->path); 894 return (B_TRUE); 895 } 896 return (B_FALSE); /* looks OK */ 897 } 898 899 /* 900 * auto_invalid_action will validate the action_list received. If all is good 901 * this function returns FALSE, if there is a problem it returns TRUE. 902 */ 903 static boolean_t 904 auto_invalid_action(fninfo_t *dfnip, fnnode_t *dfnp, action_list *alistpp) 905 { 906 907 /* 908 * Before we go any further, this better be a mount request. 909 */ 910 if (alistpp->action.action != AUTOFS_MOUNT_RQ) 911 return (B_TRUE); 912 return (auto_invalid_autofs(dfnip, dfnp, alistpp)); 913 914 } 915 916 static int 917 auto_perform_actions( 918 fninfo_t *dfnip, 919 fnnode_t *dfnp, 920 action_list *alp, 921 cred_t *cred) /* Credentials of the caller */ 922 { 923 924 action_list *p; 925 struct mounta *m, margs; 926 struct autofs_args *argsp; 927 int error, success = 0; 928 vnode_t *mvp, *dvp, *newvp; 929 fnnode_t *newfnp, *mfnp; 930 int auto_mount = 0; 931 int save_triggers = 0; 932 int update_times = 0; 933 char *mntpnt; 934 char buff[AUTOFS_MAXPATHLEN]; 935 timestruc_t now; 936 struct autofs_globals *fngp; 937 cred_t *zcred; 938 939 AUTOFS_DPRINT((4, "auto_perform_actions: alp=%p\n", 940 (void *)alp)); 941 942 fngp = dfnp->fn_globals; 943 dvp = fntovn(dfnp); 944 945 /* 946 * As automountd running in a zone may be compromised, and this may be 947 * an attack, we can't trust everything passed in by automountd, and we 948 * need to do argument verification. We'll issue a warning and drop 949 * the request if it doesn't seem right. 950 */ 951 952 for (p = alp; p != NULL; p = p->next) { 953 if (auto_invalid_action(dfnip, dfnp, p)) { 954 /* 955 * This warning should be sent to the global zone, 956 * since presumably the zone administrator is the same 957 * as the attacker. 958 */ 959 cmn_err(CE_WARN, "autofs: invalid action list received " 960 "by automountd in zone %s.", 961 curproc->p_zone->zone_name); 962 /* 963 * This conversation is over. 964 */ 965 xdr_free(xdr_action_list, (char *)alp); 966 return (EINVAL); 967 } 968 } 969 970 zcred = zone_get_kcred(getzoneid()); 971 ASSERT(zcred != NULL); 972 973 if (vn_mountedvfs(dvp) != NULL) { 974 /* 975 * The daemon successfully mounted a filesystem 976 * on the AUTOFS root node. 977 */ 978 mutex_enter(&dfnp->fn_lock); 979 dfnp->fn_flags |= MF_MOUNTPOINT; 980 ASSERT(dfnp->fn_dirents == NULL); 981 mutex_exit(&dfnp->fn_lock); 982 success++; 983 } else { 984 /* 985 * Clear MF_MOUNTPOINT. 986 */ 987 mutex_enter(&dfnp->fn_lock); 988 if (dfnp->fn_flags & MF_MOUNTPOINT) { 989 AUTOFS_DPRINT((10, "autofs: clearing mountpoint " 990 "flag on %s.", dfnp->fn_name)); 991 ASSERT(dfnp->fn_dirents == NULL); 992 ASSERT(dfnp->fn_trigger == NULL); 993 } 994 dfnp->fn_flags &= ~MF_MOUNTPOINT; 995 mutex_exit(&dfnp->fn_lock); 996 } 997 998 for (p = alp; p != NULL; p = p->next) { 999 1000 vfs_t *vfsp; /* dummy argument */ 1001 vfs_t *mvfsp; 1002 1003 auto_mount = 0; 1004 1005 m = &p->action.action_list_entry_u.mounta; 1006 argsp = (struct autofs_args *)m->dataptr; 1007 ASSERT(strcmp(m->fstype, "autofs") == 0); 1008 /* 1009 * use the parent directory's timeout since it's the 1010 * one specified/inherited by automount. 1011 */ 1012 argsp->mount_to = dfnip->fi_mount_to; 1013 /* 1014 * The mountpoint is relative, and it is guaranteed to 1015 * begin with "." 1016 * 1017 */ 1018 ASSERT(m->dir[0] == '.'); 1019 if (m->dir[0] == '.' && m->dir[1] == '\0') { 1020 /* 1021 * mounting on the trigger node 1022 */ 1023 mvp = dvp; 1024 VN_HOLD(mvp); 1025 goto mount; 1026 } 1027 /* 1028 * ignore "./" in front of mountpoint 1029 */ 1030 ASSERT(m->dir[1] == '/'); 1031 mntpnt = m->dir + 2; 1032 1033 AUTOFS_DPRINT((10, "\tdfnip->fi_path=%s\n", dfnip->fi_path)); 1034 AUTOFS_DPRINT((10, "\tdfnip->fi_flags=%x\n", dfnip->fi_flags)); 1035 AUTOFS_DPRINT((10, "\tmntpnt=%s\n", mntpnt)); 1036 1037 if (dfnip->fi_flags & MF_DIRECT) { 1038 AUTOFS_DPRINT((10, "\tDIRECT\n")); 1039 (void) sprintf(buff, "%s/%s", dfnip->fi_path, 1040 mntpnt); 1041 } else { 1042 AUTOFS_DPRINT((10, "\tINDIRECT\n")); 1043 (void) sprintf(buff, "%s/%s/%s", 1044 dfnip->fi_path, 1045 dfnp->fn_name, mntpnt); 1046 } 1047 1048 if (vn_mountedvfs(dvp) == NULL) { 1049 /* 1050 * Daemon didn't mount anything on the root 1051 * We have to create the mountpoint if it 1052 * doesn't exist already 1053 * 1054 * We use the caller's credentials in case a 1055 * UID-match is required 1056 * (MF_THISUID_MATCH_RQD). 1057 */ 1058 rw_enter(&dfnp->fn_rwlock, RW_WRITER); 1059 error = auto_search(dfnp, mntpnt, &mfnp, cred); 1060 if (error == 0) { 1061 /* 1062 * AUTOFS mountpoint exists 1063 */ 1064 if (vn_mountedvfs(fntovn(mfnp)) != NULL) { 1065 cmn_err(CE_PANIC, 1066 "auto_perform_actions:" 1067 " mfnp=%p covered", 1068 (void *)mfnp); 1069 } 1070 } else { 1071 /* 1072 * Create AUTOFS mountpoint 1073 */ 1074 ASSERT((dfnp->fn_flags & MF_MOUNTPOINT) == 0); 1075 error = auto_enter(dfnp, mntpnt, &mfnp, cred); 1076 ASSERT(mfnp->fn_linkcnt == 1); 1077 mfnp->fn_linkcnt++; 1078 } 1079 if (!error) 1080 update_times = 1; 1081 rw_exit(&dfnp->fn_rwlock); 1082 ASSERT(error != EEXIST); 1083 if (!error) { 1084 /* 1085 * mfnp is already held. 1086 */ 1087 mvp = fntovn(mfnp); 1088 } else { 1089 auto_log(fngp->fng_verbose, fngp->fng_zoneid, 1090 CE_WARN, "autofs: mount of %s " 1091 "failed - can't create" 1092 " mountpoint.", buff); 1093 continue; 1094 } 1095 } else { 1096 /* 1097 * Find mountpoint in VFS mounted here. If not 1098 * found, fail the submount, though the overall 1099 * mount has succeeded since the root is 1100 * mounted. 1101 */ 1102 if (error = auto_getmntpnt(dvp, mntpnt, &mvp, 1103 kcred)) { 1104 auto_log(fngp->fng_verbose, 1105 fngp->fng_zoneid, 1106 CE_WARN, "autofs: mount of %s " 1107 "failed - mountpoint doesn't" 1108 " exist.", buff); 1109 continue; 1110 } 1111 if (mvp->v_type == VLNK) { 1112 auto_log(fngp->fng_verbose, 1113 fngp->fng_zoneid, 1114 CE_WARN, "autofs: %s symbolic " 1115 "link: not a valid mountpoint " 1116 "- mount failed", buff); 1117 VN_RELE(mvp); 1118 error = ENOENT; 1119 continue; 1120 } 1121 } 1122 mount: 1123 m->flags |= MS_SYSSPACE | MS_OPTIONSTR; 1124 1125 /* 1126 * Copy mounta struct here so we can substitute a 1127 * buffer that is large enough to hold the returned 1128 * option string, if that string is longer than the 1129 * input option string. 1130 * This can happen if there are default options enabled 1131 * that were not in the input option string. 1132 */ 1133 bcopy(m, &margs, sizeof (*m)); 1134 margs.optptr = kmem_alloc(MAX_MNTOPT_STR, KM_SLEEP); 1135 margs.optlen = MAX_MNTOPT_STR; 1136 (void) strcpy(margs.optptr, m->optptr); 1137 margs.dir = argsp->path; 1138 1139 /* 1140 * We use the zone's kcred because we don't want the 1141 * zone to be able to thus do something it wouldn't 1142 * normally be able to. 1143 */ 1144 error = domount(NULL, &margs, mvp, zcred, &vfsp); 1145 kmem_free(margs.optptr, MAX_MNTOPT_STR); 1146 if (error != 0) { 1147 auto_log(fngp->fng_verbose, fngp->fng_zoneid, 1148 CE_WARN, "autofs: domount of %s failed " 1149 "error=%d", buff, error); 1150 VN_RELE(mvp); 1151 continue; 1152 } 1153 VFS_RELE(vfsp); 1154 1155 /* 1156 * If mountpoint is an AUTOFS node, then I'm going to 1157 * flag it that the Filesystem mounted on top was 1158 * mounted in the kernel so that the unmount can be 1159 * done inside the kernel as well. 1160 * I don't care to flag non-AUTOFS mountpoints when an 1161 * AUTOFS in-kernel mount was done on top, because the 1162 * unmount routine already knows that such case was 1163 * done in the kernel. 1164 */ 1165 if (vfs_matchops(dvp->v_vfsp, 1166 vfs_getops(mvp->v_vfsp))) { 1167 mfnp = vntofn(mvp); 1168 mutex_enter(&mfnp->fn_lock); 1169 mfnp->fn_flags |= MF_IK_MOUNT; 1170 mutex_exit(&mfnp->fn_lock); 1171 } 1172 1173 (void) vn_vfswlock_wait(mvp); 1174 mvfsp = vn_mountedvfs(mvp); 1175 if (mvfsp != NULL) { 1176 vfs_lock_wait(mvfsp); 1177 vn_vfsunlock(mvp); 1178 error = VFS_ROOT(mvfsp, &newvp); 1179 vfs_unlock(mvfsp); 1180 if (error) { 1181 /* 1182 * We've dropped the locks, so let's 1183 * get the mounted vfs again in case 1184 * it changed. 1185 */ 1186 (void) vn_vfswlock_wait(mvp); 1187 mvfsp = vn_mountedvfs(mvp); 1188 if (mvfsp != NULL) { 1189 error = dounmount(mvfsp, 0, CRED()); 1190 if (error) { 1191 cmn_err(CE_WARN, 1192 "autofs: could" 1193 " not unmount" 1194 " vfs=%p", 1195 (void *)mvfsp); 1196 } 1197 } else 1198 vn_vfsunlock(mvp); 1199 VN_RELE(mvp); 1200 continue; 1201 } 1202 } else { 1203 vn_vfsunlock(mvp); 1204 VN_RELE(mvp); 1205 continue; 1206 } 1207 1208 auto_mount = vfs_matchops(dvp->v_vfsp, 1209 vfs_getops(newvp->v_vfsp)); 1210 newfnp = vntofn(newvp); 1211 newfnp->fn_parent = dfnp; 1212 1213 /* 1214 * At this time we want to save the AUTOFS filesystem 1215 * as a trigger node. (We only do this if the mount 1216 * occurred on a node different from the root. 1217 * We look at the trigger nodes during 1218 * the automatic unmounting to make sure we remove them 1219 * as a unit and remount them as a unit if the 1220 * filesystem mounted at the root could not be 1221 * unmounted. 1222 */ 1223 if (auto_mount && (error == 0) && (mvp != dvp)) { 1224 save_triggers++; 1225 /* 1226 * Add AUTOFS mount to hierarchy 1227 */ 1228 newfnp->fn_flags |= MF_TRIGGER; 1229 rw_enter(&newfnp->fn_rwlock, RW_WRITER); 1230 newfnp->fn_next = dfnp->fn_trigger; 1231 rw_exit(&newfnp->fn_rwlock); 1232 rw_enter(&dfnp->fn_rwlock, RW_WRITER); 1233 dfnp->fn_trigger = newfnp; 1234 rw_exit(&dfnp->fn_rwlock); 1235 /* 1236 * Don't VN_RELE(newvp) here since dfnp now 1237 * holds reference to it as its trigger node. 1238 */ 1239 AUTOFS_DPRINT((10, "\tadding trigger %s to %s\n", 1240 newfnp->fn_name, dfnp->fn_name)); 1241 AUTOFS_DPRINT((10, "\tfirst trigger is %s\n", 1242 dfnp->fn_trigger->fn_name)); 1243 if (newfnp->fn_next != NULL) 1244 AUTOFS_DPRINT((10, 1245 "\tnext trigger is %s\n", 1246 newfnp->fn_next->fn_name)); 1247 else 1248 AUTOFS_DPRINT((10, 1249 "\tno next trigger\n")); 1250 } else 1251 VN_RELE(newvp); 1252 1253 if (!error) 1254 success++; 1255 1256 if (update_times) { 1257 gethrestime(&now); 1258 dfnp->fn_atime = dfnp->fn_mtime = now; 1259 } 1260 1261 VN_RELE(mvp); 1262 } 1263 1264 if (save_triggers) { 1265 /* 1266 * Make sure the parent can't be freed while it has triggers. 1267 */ 1268 VN_HOLD(dvp); 1269 } 1270 1271 crfree(zcred); 1272 1273 done: 1274 /* 1275 * Return failure if daemon didn't mount anything, and all 1276 * kernel mounts attempted failed. 1277 */ 1278 error = success ? 0 : ENOENT; 1279 1280 if (alp != NULL) { 1281 if ((error == 0) && save_triggers) { 1282 /* 1283 * Save action_list information, so that we can use it 1284 * when it comes time to remount the trigger nodes 1285 * The action list is freed when the directory node 1286 * containing the reference to it is unmounted in 1287 * unmount_tree(). 1288 */ 1289 mutex_enter(&dfnp->fn_lock); 1290 ASSERT(dfnp->fn_alp == NULL); 1291 dfnp->fn_alp = alp; 1292 mutex_exit(&dfnp->fn_lock); 1293 } else { 1294 /* 1295 * free the action list now, 1296 */ 1297 xdr_free(xdr_action_list, (char *)alp); 1298 } 1299 } 1300 AUTOFS_DPRINT((5, "auto_perform_actions: error=%d\n", error)); 1301 return (error); 1302 } 1303 1304 fnnode_t * 1305 auto_makefnnode( 1306 vtype_t type, 1307 vfs_t *vfsp, 1308 char *name, 1309 cred_t *cred, 1310 struct autofs_globals *fngp) 1311 { 1312 fnnode_t *fnp; 1313 vnode_t *vp; 1314 char *tmpname; 1315 timestruc_t now; 1316 /* 1317 * autofs uses odd inode numbers 1318 * automountd uses even inode numbers 1319 * 1320 * To preserve the age-old semantics that inum+devid is unique across 1321 * the system, this variable must be global across zones. 1322 */ 1323 static ino_t nodeid = 3; 1324 1325 fnp = kmem_zalloc(sizeof (*fnp), KM_SLEEP); 1326 fnp->fn_vnode = vn_alloc(KM_SLEEP); 1327 1328 vp = fntovn(fnp); 1329 tmpname = kmem_alloc(strlen(name) + 1, KM_SLEEP); 1330 (void) strcpy(tmpname, name); 1331 fnp->fn_name = &tmpname[0]; 1332 fnp->fn_namelen = (int)strlen(tmpname) + 1; /* include '\0' */ 1333 fnp->fn_uid = crgetuid(cred); 1334 fnp->fn_gid = crgetgid(cred); 1335 /* 1336 * ".." is added in auto_enter and auto_mount. 1337 * "." is added in auto_mkdir and auto_mount. 1338 */ 1339 /* 1340 * Note that fn_size and fn_linkcnt are already 0 since 1341 * we used kmem_zalloc to allocated fnp 1342 */ 1343 fnp->fn_mode = AUTOFS_MODE; 1344 gethrestime(&now); 1345 fnp->fn_atime = fnp->fn_mtime = fnp->fn_ctime = now; 1346 fnp->fn_ref_time = now.tv_sec; 1347 mutex_enter(&autofs_nodeid_lock); 1348 fnp->fn_nodeid = nodeid; 1349 nodeid += 2; 1350 fnp->fn_globals = fngp; 1351 fngp->fng_fnnode_count++; 1352 mutex_exit(&autofs_nodeid_lock); 1353 vn_setops(vp, auto_vnodeops); 1354 vp->v_type = type; 1355 vp->v_data = (void *)fnp; 1356 vp->v_vfsp = vfsp; 1357 mutex_init(&fnp->fn_lock, NULL, MUTEX_DEFAULT, NULL); 1358 rw_init(&fnp->fn_rwlock, NULL, RW_DEFAULT, NULL); 1359 cv_init(&fnp->fn_cv_mount, NULL, CV_DEFAULT, NULL); 1360 vn_exists(vp); 1361 return (fnp); 1362 } 1363 1364 1365 void 1366 auto_freefnnode(fnnode_t *fnp) 1367 { 1368 vnode_t *vp = fntovn(fnp); 1369 1370 AUTOFS_DPRINT((4, "auto_freefnnode: fnp=%p\n", (void *)fnp)); 1371 1372 ASSERT(fnp->fn_linkcnt == 0); 1373 ASSERT(vp->v_count == 0); 1374 ASSERT(fnp->fn_dirents == NULL); 1375 ASSERT(fnp->fn_parent == NULL); 1376 1377 vn_invalid(vp); 1378 kmem_free(fnp->fn_name, fnp->fn_namelen); 1379 if (fnp->fn_symlink) { 1380 ASSERT(fnp->fn_flags & MF_THISUID_MATCH_RQD); 1381 kmem_free(fnp->fn_symlink, fnp->fn_symlinklen); 1382 } 1383 if (fnp->fn_cred) 1384 crfree(fnp->fn_cred); 1385 mutex_destroy(&fnp->fn_lock); 1386 rw_destroy(&fnp->fn_rwlock); 1387 cv_destroy(&fnp->fn_cv_mount); 1388 vn_free(vp); 1389 1390 mutex_enter(&autofs_nodeid_lock); 1391 fnp->fn_globals->fng_fnnode_count--; 1392 mutex_exit(&autofs_nodeid_lock); 1393 kmem_free(fnp, sizeof (*fnp)); 1394 } 1395 1396 void 1397 auto_disconnect( 1398 fnnode_t *dfnp, 1399 fnnode_t *fnp) 1400 { 1401 fnnode_t *tmp, **fnpp; 1402 vnode_t *vp = fntovn(fnp); 1403 timestruc_t now; 1404 1405 AUTOFS_DPRINT((4, 1406 "auto_disconnect: dfnp=%p fnp=%p linkcnt=%d\n v_count=%d", 1407 (void *)dfnp, (void *)fnp, fnp->fn_linkcnt, vp->v_count)); 1408 1409 ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock)); 1410 ASSERT(fnp->fn_linkcnt == 1); 1411 1412 if (vn_mountedvfs(vp) != NULL) { 1413 cmn_err(CE_PANIC, "auto_disconnect: vp %p mounted on", 1414 (void *)vp); 1415 } 1416 1417 /* 1418 * Decrement by 1 because we're removing the entry in dfnp. 1419 */ 1420 fnp->fn_linkcnt--; 1421 fnp->fn_size--; 1422 1423 /* 1424 * only changed while holding parent's (dfnp) rw_lock 1425 */ 1426 fnp->fn_parent = NULL; 1427 1428 fnpp = &dfnp->fn_dirents; 1429 for (;;) { 1430 tmp = *fnpp; 1431 if (tmp == NULL) { 1432 cmn_err(CE_PANIC, 1433 "auto_disconnect: %p not in %p dirent list", 1434 (void *)fnp, (void *)dfnp); 1435 } 1436 if (tmp == fnp) { 1437 *fnpp = tmp->fn_next; /* remove it from the list */ 1438 ASSERT(vp->v_count == 0); 1439 /* child had a pointer to parent ".." */ 1440 dfnp->fn_linkcnt--; 1441 dfnp->fn_size--; 1442 break; 1443 } 1444 fnpp = &tmp->fn_next; 1445 } 1446 1447 mutex_enter(&fnp->fn_lock); 1448 gethrestime(&now); 1449 fnp->fn_atime = fnp->fn_mtime = now; 1450 mutex_exit(&fnp->fn_lock); 1451 1452 AUTOFS_DPRINT((5, "auto_disconnect: done\n")); 1453 } 1454 1455 int 1456 auto_enter(fnnode_t *dfnp, char *name, fnnode_t **fnpp, cred_t *cred) 1457 { 1458 struct fnnode *cfnp, **spp; 1459 vnode_t *dvp = fntovn(dfnp); 1460 ushort_t offset = 0; 1461 ushort_t diff; 1462 1463 AUTOFS_DPRINT((4, "auto_enter: dfnp=%p, name=%s ", (void *)dfnp, name)); 1464 1465 ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock)); 1466 1467 cfnp = dfnp->fn_dirents; 1468 if (cfnp == NULL) { 1469 /* 1470 * offset = 0 for '.' and offset = 1 for '..' 1471 */ 1472 spp = &dfnp->fn_dirents; 1473 offset = 2; 1474 } 1475 1476 for (; cfnp; cfnp = cfnp->fn_next) { 1477 if (strcmp(cfnp->fn_name, name) == 0) { 1478 mutex_enter(&cfnp->fn_lock); 1479 if (cfnp->fn_flags & MF_THISUID_MATCH_RQD) { 1480 /* 1481 * "thisuser" kind of node, need to 1482 * match CREDs as well 1483 */ 1484 mutex_exit(&cfnp->fn_lock); 1485 if (crcmp(cfnp->fn_cred, cred) == 0) 1486 return (EEXIST); 1487 } else { 1488 mutex_exit(&cfnp->fn_lock); 1489 return (EEXIST); 1490 } 1491 } 1492 1493 if (cfnp->fn_next != NULL) { 1494 diff = (ushort_t) 1495 (cfnp->fn_next->fn_offset - cfnp->fn_offset); 1496 ASSERT(diff != 0); 1497 if (diff > 1 && offset == 0) { 1498 offset = (ushort_t)cfnp->fn_offset + 1; 1499 spp = &cfnp->fn_next; 1500 } 1501 } else if (offset == 0) { 1502 offset = (ushort_t)cfnp->fn_offset + 1; 1503 spp = &cfnp->fn_next; 1504 } 1505 } 1506 1507 *fnpp = auto_makefnnode(VDIR, dvp->v_vfsp, name, cred, 1508 dfnp->fn_globals); 1509 if (*fnpp == NULL) 1510 return (ENOMEM); 1511 1512 /* 1513 * I don't hold the mutex on fnpp because I created it, and 1514 * I'm already holding the writers lock for it's parent 1515 * directory, therefore nobody can reference it without me first 1516 * releasing the writers lock. 1517 */ 1518 (*fnpp)->fn_offset = offset; 1519 (*fnpp)->fn_next = *spp; 1520 *spp = *fnpp; 1521 (*fnpp)->fn_parent = dfnp; 1522 (*fnpp)->fn_linkcnt++; /* parent now holds reference to entry */ 1523 (*fnpp)->fn_size++; 1524 1525 /* 1526 * dfnp->fn_linkcnt and dfnp->fn_size protected by dfnp->rw_lock 1527 */ 1528 dfnp->fn_linkcnt++; /* child now holds reference to parent '..' */ 1529 dfnp->fn_size++; 1530 1531 dfnp->fn_ref_time = gethrestime_sec(); 1532 1533 AUTOFS_DPRINT((5, "*fnpp=%p\n", (void *)*fnpp)); 1534 return (0); 1535 } 1536 1537 int 1538 auto_search(fnnode_t *dfnp, char *name, fnnode_t **fnpp, cred_t *cred) 1539 { 1540 vnode_t *dvp; 1541 fnnode_t *p; 1542 int error = ENOENT, match = 0; 1543 1544 AUTOFS_DPRINT((4, "auto_search: dfnp=%p, name=%s...\n", 1545 (void *)dfnp, name)); 1546 1547 dvp = fntovn(dfnp); 1548 if (dvp->v_type != VDIR) { 1549 cmn_err(CE_PANIC, "auto_search: dvp=%p not a directory", 1550 (void *)dvp); 1551 } 1552 1553 ASSERT(RW_LOCK_HELD(&dfnp->fn_rwlock)); 1554 for (p = dfnp->fn_dirents; p != NULL; p = p->fn_next) { 1555 if (strcmp(p->fn_name, name) == 0) { 1556 mutex_enter(&p->fn_lock); 1557 if (p->fn_flags & MF_THISUID_MATCH_RQD) { 1558 /* 1559 * "thisuser" kind of node 1560 * Need to match CREDs as well 1561 */ 1562 mutex_exit(&p->fn_lock); 1563 match = crcmp(p->fn_cred, cred) == 0; 1564 } else { 1565 /* 1566 * No need to check CRED 1567 */ 1568 mutex_exit(&p->fn_lock); 1569 match = 1; 1570 } 1571 } 1572 if (match) { 1573 error = 0; 1574 if (fnpp) { 1575 *fnpp = p; 1576 VN_HOLD(fntovn(*fnpp)); 1577 } 1578 break; 1579 } 1580 } 1581 1582 AUTOFS_DPRINT((5, "auto_search: error=%d\n", error)); 1583 return (error); 1584 } 1585 1586 /* 1587 * If dvp is mounted on, get path's vnode in the mounted on 1588 * filesystem. Path is relative to dvp, ie "./path". 1589 * If successful, *mvp points to a the held mountpoint vnode. 1590 */ 1591 /* ARGSUSED */ 1592 static int 1593 auto_getmntpnt( 1594 vnode_t *dvp, 1595 char *path, 1596 vnode_t **mvpp, /* vnode for mountpoint */ 1597 cred_t *cred) 1598 { 1599 int error = 0; 1600 vnode_t *newvp; 1601 char namebuf[TYPICALMAXPATHLEN]; 1602 struct pathname lookpn; 1603 vfs_t *vfsp; 1604 1605 AUTOFS_DPRINT((4, "auto_getmntpnt: path=%s\n", path)); 1606 1607 if (error = vn_vfsrlock_wait(dvp)) 1608 return (error); 1609 1610 /* 1611 * Now that we have the vfswlock, check to see if dvp 1612 * is still mounted on. If not, then just bail out as 1613 * there is no need to remount the triggers since the 1614 * higher level mount point has gotten unmounted. 1615 */ 1616 vfsp = vn_mountedvfs(dvp); 1617 if (vfsp == NULL) { 1618 vn_vfsunlock(dvp); 1619 error = EBUSY; 1620 goto done; 1621 } 1622 /* 1623 * Since mounted on, lookup "path" in the new filesystem, 1624 * it is important that we do the filesystem jump here to 1625 * avoid lookuppn() calling auto_lookup on dvp and deadlock. 1626 */ 1627 error = VFS_ROOT(vfsp, &newvp); 1628 vn_vfsunlock(dvp); 1629 if (error) 1630 goto done; 1631 1632 /* 1633 * We do a VN_HOLD on newvp just in case the first call to 1634 * lookuppnvp() fails with ENAMETOOLONG. We should still have a 1635 * reference to this vnode for the second call to lookuppnvp(). 1636 */ 1637 VN_HOLD(newvp); 1638 1639 /* 1640 * Now create the pathname struct so we can make use of lookuppnvp, 1641 * and pn_getcomponent. 1642 * This code is similar to lookupname() in fs/lookup.c. 1643 */ 1644 error = pn_get_buf(path, UIO_SYSSPACE, &lookpn, 1645 namebuf, sizeof (namebuf)); 1646 if (error == 0) { 1647 error = lookuppnvp(&lookpn, NULL, NO_FOLLOW, NULLVPP, 1648 mvpp, rootdir, newvp, cred); 1649 } else 1650 VN_RELE(newvp); 1651 if (error == ENAMETOOLONG) { 1652 /* 1653 * This thread used a pathname > TYPICALMAXPATHLEN bytes long. 1654 * newvp is VN_RELE'd by this call to lookuppnvp. 1655 * 1656 * Using 'rootdir' in a zone's context is OK here: we already 1657 * ascertained that there are no '..'s in the path, and we're 1658 * not following symlinks. 1659 */ 1660 if ((error = pn_get(path, UIO_SYSSPACE, &lookpn)) == 0) { 1661 error = lookuppnvp(&lookpn, NULL, NO_FOLLOW, NULLVPP, 1662 mvpp, rootdir, newvp, cred); 1663 pn_free(&lookpn); 1664 } else 1665 VN_RELE(newvp); 1666 } else { 1667 /* 1668 * Need to release newvp here since we held it. 1669 */ 1670 VN_RELE(newvp); 1671 } 1672 1673 done: 1674 AUTOFS_DPRINT((5, "auto_getmntpnt: path=%s *mvpp=%p error=%d\n", 1675 path, (void *)*mvpp, error)); 1676 return (error); 1677 } 1678 1679 #define DEEPER(x) (((x)->fn_dirents != NULL) || \ 1680 (vn_mountedvfs(fntovn((x)))) != NULL) 1681 1682 /* 1683 * The caller, should have already VN_RELE'd its reference to the 1684 * root vnode of this filesystem. 1685 */ 1686 static int 1687 auto_inkernel_unmount(vfs_t *vfsp) 1688 { 1689 vnode_t *cvp = vfsp->vfs_vnodecovered; 1690 int error; 1691 1692 AUTOFS_DPRINT((4, 1693 "auto_inkernel_unmount: devid=%lx mntpnt(%p) count %u\n", 1694 vfsp->vfs_dev, (void *)cvp, cvp->v_count)); 1695 1696 ASSERT(vn_vfswlock_held(cvp)); 1697 1698 /* 1699 * Perform the unmount 1700 * The mountpoint has already been locked by the caller. 1701 */ 1702 error = dounmount(vfsp, 0, kcred); 1703 1704 AUTOFS_DPRINT((5, "auto_inkernel_unmount: exit count %u\n", 1705 cvp->v_count)); 1706 return (error); 1707 } 1708 1709 /* 1710 * unmounts trigger nodes in the kernel. 1711 */ 1712 static void 1713 unmount_triggers(fnnode_t *fnp, action_list **alp) 1714 { 1715 fnnode_t *tp, *next; 1716 int error = 0; 1717 vfs_t *vfsp; 1718 vnode_t *tvp; 1719 1720 AUTOFS_DPRINT((4, "unmount_triggers: fnp=%p\n", (void *)fnp)); 1721 ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock)); 1722 1723 *alp = fnp->fn_alp; 1724 next = fnp->fn_trigger; 1725 while ((tp = next) != NULL) { 1726 tvp = fntovn(tp); 1727 ASSERT(tvp->v_count >= 2); 1728 next = tp->fn_next; 1729 /* 1730 * drop writer's lock since the unmount will end up 1731 * disconnecting this node from fnp and needs to acquire 1732 * the writer's lock again. 1733 * next has at least a reference count >= 2 since it's 1734 * a trigger node, therefore can not be accidentally freed 1735 * by a VN_RELE 1736 */ 1737 rw_exit(&fnp->fn_rwlock); 1738 1739 vfsp = tvp->v_vfsp; 1740 1741 /* 1742 * Its parent was holding a reference to it, since this 1743 * is a trigger vnode. 1744 */ 1745 VN_RELE(tvp); 1746 if (error = auto_inkernel_unmount(vfsp)) { 1747 cmn_err(CE_PANIC, "unmount_triggers: " 1748 "unmount of vp=%p failed error=%d", 1749 (void *)tvp, error); 1750 } 1751 /* 1752 * reacquire writer's lock 1753 */ 1754 rw_enter(&fnp->fn_rwlock, RW_WRITER); 1755 } 1756 1757 /* 1758 * We were holding a reference to our parent. Drop that. 1759 */ 1760 VN_RELE(fntovn(fnp)); 1761 fnp->fn_trigger = NULL; 1762 fnp->fn_alp = NULL; 1763 1764 AUTOFS_DPRINT((5, "unmount_triggers: finished\n")); 1765 } 1766 1767 /* 1768 * This routine locks the mountpoint of every trigger node if they're 1769 * not busy, or returns EBUSY if any node is busy. If a trigger node should 1770 * be unmounted first, then it sets nfnp to point to it, otherwise nfnp 1771 * points to NULL. 1772 */ 1773 static int 1774 triggers_busy(fnnode_t *fnp, fnnode_t **nfnp) 1775 { 1776 int error = 0, done; 1777 int lck_error = 0; 1778 fnnode_t *tp, *t1p; 1779 vfs_t *vfsp; 1780 1781 ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock)); 1782 1783 *nfnp = NULL; 1784 for (tp = fnp->fn_trigger; tp != NULL; tp = tp->fn_next) { 1785 AUTOFS_DPRINT((10, "\ttrigger: %s\n", tp->fn_name)); 1786 vfsp = fntovn(tp)->v_vfsp; 1787 error = 0; 1788 /* 1789 * The vn_vfsunlock will be done in auto_inkernel_unmount. 1790 */ 1791 lck_error = vn_vfswlock(vfsp->vfs_vnodecovered); 1792 if (lck_error == 0) { 1793 mutex_enter(&tp->fn_lock); 1794 ASSERT((tp->fn_flags & MF_LOOKUP) == 0); 1795 if (tp->fn_flags & MF_INPROG) { 1796 /* 1797 * a mount is in progress 1798 */ 1799 error = EBUSY; 1800 } 1801 mutex_exit(&tp->fn_lock); 1802 } 1803 if (lck_error || error || DEEPER(tp) || 1804 ((fntovn(tp))->v_count) > 2) { 1805 /* 1806 * couldn't lock it because it's busy, 1807 * It is mounted on or has dirents? 1808 * If reference count is greater than two, then 1809 * somebody else is holding a reference to this vnode. 1810 * One reference is for the mountpoint, and the second 1811 * is for the trigger node. 1812 */ 1813 AUTOFS_DPRINT((10, "\ttrigger busy\n")); 1814 if ((lck_error == 0) && (error == 0)) { 1815 *nfnp = tp; 1816 /* 1817 * The matching VN_RELE is done in 1818 * unmount_tree(). 1819 */ 1820 VN_HOLD(fntovn(*nfnp)); 1821 } 1822 /* 1823 * Unlock previously locked mountpoints 1824 */ 1825 for (done = 0, t1p = fnp->fn_trigger; !done; 1826 t1p = t1p->fn_next) { 1827 /* 1828 * Unlock all nodes previously 1829 * locked. All nodes up to 'tp' 1830 * were successfully locked. If 'lck_err' is 1831 * set, then 'tp' was not locked, and thus 1832 * should not be unlocked. If 1833 * 'lck_err' is not set, then 'tp' was 1834 * successfully locked, and it should 1835 * be unlocked. 1836 */ 1837 if (t1p != tp || !lck_error) { 1838 vfsp = fntovn(t1p)->v_vfsp; 1839 vn_vfsunlock(vfsp->vfs_vnodecovered); 1840 } 1841 done = (t1p == tp); 1842 } 1843 error = EBUSY; 1844 break; 1845 } 1846 } 1847 1848 AUTOFS_DPRINT((4, "triggers_busy: error=%d\n", error)); 1849 return (error); 1850 } 1851 1852 /* 1853 * Unlock previously locked trigger nodes. 1854 */ 1855 static int 1856 triggers_unlock(fnnode_t *fnp) 1857 { 1858 fnnode_t *tp; 1859 vfs_t *vfsp; 1860 1861 ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock)); 1862 1863 for (tp = fnp->fn_trigger; tp != NULL; tp = tp->fn_next) { 1864 AUTOFS_DPRINT((10, "\tunlock trigger: %s\n", tp->fn_name)); 1865 vfsp = fntovn(tp)->v_vfsp; 1866 vn_vfsunlock(vfsp->vfs_vnodecovered); 1867 } 1868 1869 return (0); 1870 } 1871 1872 /* 1873 * It is the caller's responsibility to grab the VVFSLOCK. 1874 * Releases the VVFSLOCK upon return. 1875 */ 1876 static int 1877 unmount_node(vnode_t *cvp, int force) 1878 { 1879 int error = 0; 1880 fnnode_t *cfnp; 1881 vfs_t *vfsp; 1882 umntrequest ul; 1883 fninfo_t *fnip; 1884 1885 AUTOFS_DPRINT((4, "\tunmount_node cvp=%p\n", (void *)cvp)); 1886 1887 ASSERT(vn_vfswlock_held(cvp)); 1888 cfnp = vntofn(cvp); 1889 vfsp = vn_mountedvfs(cvp); 1890 1891 if (force || cfnp->fn_flags & MF_IK_MOUNT) { 1892 /* 1893 * Mount was performed in the kernel, so 1894 * do an in-kernel unmount. auto_inkernel_unmount() 1895 * will vn_vfsunlock(cvp). 1896 */ 1897 error = auto_inkernel_unmount(vfsp); 1898 } else { 1899 zone_t *zone = NULL; 1900 refstr_t *mntpt, *resource; 1901 size_t mntoptslen; 1902 1903 /* 1904 * Get the mnttab information of the node 1905 * and ask the daemon to unmount it. 1906 */ 1907 bzero(&ul, sizeof (ul)); 1908 mntfs_getmntopts(vfsp, &ul.mntopts, &mntoptslen); 1909 if (ul.mntopts == NULL) { 1910 auto_log(cfnp->fn_globals->fng_verbose, 1911 cfnp->fn_globals->fng_zoneid, 1912 CE_WARN, "unmount_node: " 1913 "no memory"); 1914 vn_vfsunlock(cvp); 1915 error = ENOMEM; 1916 goto done; 1917 } 1918 if (mntoptslen > AUTOFS_MAXOPTSLEN) 1919 ul.mntopts[AUTOFS_MAXOPTSLEN - 1] = '\0'; 1920 1921 mntpt = vfs_getmntpoint(vfsp); 1922 ul.mntpnt = (char *)refstr_value(mntpt); 1923 resource = vfs_getresource(vfsp); 1924 ul.mntresource = (char *)refstr_value(resource); 1925 1926 fnip = vfstofni(cvp->v_vfsp); 1927 ul.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE; 1928 1929 /* 1930 * Since a zone'd automountd's view of the autofs mount points 1931 * differs from those in the kernel, we need to make sure we 1932 * give it consistent mount points. 1933 */ 1934 ASSERT(fnip->fi_zoneid == getzoneid()); 1935 zone = curproc->p_zone; 1936 1937 if (fnip->fi_zoneid != GLOBAL_ZONEID) { 1938 if (ZONE_PATH_VISIBLE(ul.mntpnt, zone)) { 1939 ul.mntpnt = 1940 ZONE_PATH_TRANSLATE(ul.mntpnt, zone); 1941 } 1942 if (ZONE_PATH_VISIBLE(ul.mntresource, zone)) { 1943 ul.mntresource = 1944 ZONE_PATH_TRANSLATE(ul.mntresource, zone); 1945 } 1946 } 1947 1948 ul.fstype = vfssw[vfsp->vfs_fstype].vsw_name; 1949 vn_vfsunlock(cvp); 1950 1951 error = auto_send_unmount_request(fnip, &ul, FALSE); 1952 kmem_free(ul.mntopts, mntoptslen); 1953 refstr_rele(mntpt); 1954 refstr_rele(resource); 1955 } 1956 1957 done: 1958 AUTOFS_DPRINT((5, "\tunmount_node cvp=%p error=%d\n", (void *)cvp, 1959 error)); 1960 return (error); 1961 } 1962 1963 /* 1964 * vp is the "root" of the AUTOFS filesystem. 1965 * return EBUSY if any thread is holding a reference to this vnode 1966 * other than us. 1967 */ 1968 static int 1969 check_auto_node(vnode_t *vp) 1970 { 1971 fnnode_t *fnp; 1972 int error = 0; 1973 /* 1974 * number of references to expect for 1975 * a non-busy vnode. 1976 */ 1977 uint_t count; 1978 1979 AUTOFS_DPRINT((4, "\tcheck_auto_node vp=%p ", (void *)vp)); 1980 fnp = vntofn(vp); 1981 ASSERT(fnp->fn_flags & MF_INPROG); 1982 ASSERT((fnp->fn_flags & MF_LOOKUP) == 0); 1983 1984 count = 1; /* we are holding a reference to vp */ 1985 if (fnp->fn_flags & MF_TRIGGER) { 1986 /* 1987 * parent holds a pointer to us (trigger) 1988 */ 1989 count++; 1990 } 1991 if (fnp->fn_trigger != NULL) { 1992 /* 1993 * The trigger nodes have a hold on us. 1994 */ 1995 count++; 1996 } 1997 mutex_enter(&vp->v_lock); 1998 if (vp->v_flag & VROOT) 1999 count++; 2000 ASSERT(vp->v_count > 0); 2001 AUTOFS_DPRINT((10, "\tcount=%u ", vp->v_count)); 2002 if (vp->v_count > count) 2003 error = EBUSY; 2004 mutex_exit(&vp->v_lock); 2005 2006 AUTOFS_DPRINT((5, "\tcheck_auto_node error=%d ", error)); 2007 return (error); 2008 } 2009 2010 /* 2011 * rootvp is the root of the AUTOFS filesystem. 2012 * If rootvp is busy (v_count > 1) returns EBUSY. 2013 * else removes every vnode under this tree. 2014 * ASSUMPTION: Assumes that the only node which can be busy is 2015 * the root vnode. This filesystem better be two levels deep only, 2016 * the root and its immediate subdirs. 2017 * The daemon will "AUTOFS direct-mount" only one level below the root. 2018 */ 2019 static int 2020 unmount_autofs(vnode_t *rootvp) 2021 { 2022 fnnode_t *fnp, *rootfnp, *nfnp; 2023 int error; 2024 2025 AUTOFS_DPRINT((4, "\tunmount_autofs rootvp=%p ", (void *)rootvp)); 2026 2027 error = check_auto_node(rootvp); 2028 if (error == 0) { 2029 /* 2030 * Remove all its immediate subdirectories. 2031 */ 2032 rootfnp = vntofn(rootvp); 2033 rw_enter(&rootfnp->fn_rwlock, RW_WRITER); 2034 nfnp = NULL; /* lint clean */ 2035 for (fnp = rootfnp->fn_dirents; fnp != NULL; fnp = nfnp) { 2036 ASSERT(fntovn(fnp)->v_count == 0); 2037 ASSERT(fnp->fn_dirents == NULL); 2038 ASSERT(fnp->fn_linkcnt == 2); 2039 fnp->fn_linkcnt--; 2040 auto_disconnect(rootfnp, fnp); 2041 nfnp = fnp->fn_next; 2042 auto_freefnnode(fnp); 2043 } 2044 rw_exit(&rootfnp->fn_rwlock); 2045 } 2046 AUTOFS_DPRINT((5, "\tunmount_autofs error=%d ", error)); 2047 return (error); 2048 } 2049 2050 /* 2051 * max number of unmount threads running 2052 */ 2053 static int autofs_unmount_threads = 5; 2054 2055 /* 2056 * XXX unmount_tree() is not suspend-safe within the scope of 2057 * the present model defined for cpr to suspend the system. Calls made 2058 * by the unmount_tree() that have been identified to be unsafe are 2059 * (1) RPC client handle setup and client calls to automountd which can 2060 * block deep down in the RPC library, (2) kmem_alloc() calls with the 2061 * KM_SLEEP flag which can block if memory is low, and (3) VFS_*() and 2062 * VOP_*() calls which can result in over the wire calls to servers. 2063 * The thread should be completely reevaluated to make it suspend-safe in 2064 * case of future updates to the cpr model. 2065 */ 2066 void 2067 unmount_tree(struct autofs_globals *fngp, int force) 2068 { 2069 vnode_t *vp, *newvp; 2070 vfs_t *vfsp; 2071 fnnode_t *fnp, *nfnp, *pfnp; 2072 action_list *alp; 2073 int error, ilocked_it = 0; 2074 fninfo_t *fnip; 2075 time_t ref_time; 2076 int autofs_busy_root, unmount_as_unit, unmount_done = 0; 2077 timestruc_t now; 2078 2079 callb_cpr_t cprinfo; 2080 kmutex_t unmount_tree_cpr_lock; 2081 2082 mutex_init(&unmount_tree_cpr_lock, NULL, MUTEX_DEFAULT, NULL); 2083 CALLB_CPR_INIT(&cprinfo, &unmount_tree_cpr_lock, callb_generic_cpr, 2084 "unmount_tree"); 2085 2086 /* 2087 * Got to release lock before attempting unmount in case 2088 * it hangs. 2089 */ 2090 rw_enter(&fngp->fng_rootfnnodep->fn_rwlock, RW_READER); 2091 if ((fnp = fngp->fng_rootfnnodep->fn_dirents) == NULL) { 2092 ASSERT(fngp->fng_fnnode_count == 1); 2093 /* 2094 * no autofs mounted, done. 2095 */ 2096 rw_exit(&fngp->fng_rootfnnodep->fn_rwlock); 2097 goto done; 2098 } 2099 VN_HOLD(fntovn(fnp)); 2100 rw_exit(&fngp->fng_rootfnnodep->fn_rwlock); 2101 2102 vp = fntovn(fnp); 2103 fnip = vfstofni(vp->v_vfsp); 2104 /* 2105 * autofssys() will be calling in from the global zone and doing 2106 * work on the behalf of the given zone, hence we can't always assert 2107 * that we have the right credentials, nor that the caller is always in 2108 * the correct zone. 2109 * 2110 * We do, however, know that if this is a "forced unmount" operation 2111 * (which autofssys() does), then we won't go down to the krpc layers, 2112 * so we don't need to fudge with the credentials. 2113 */ 2114 ASSERT(force || fnip->fi_zoneid == getzoneid()); 2115 if (!force && auto_null_request(fnip, FALSE) != 0) { 2116 /* 2117 * automountd not running in this zone, 2118 * don't attempt unmounting this round. 2119 */ 2120 VN_RELE(vp); 2121 goto done; 2122 } 2123 /* reference time for this unmount round */ 2124 ref_time = gethrestime_sec(); 2125 /* 2126 * If this an autofssys() call, we need to make sure we don't skip 2127 * nodes because we think we saw them recently. 2128 */ 2129 mutex_enter(&fnp->fn_lock); 2130 if (force && fnp->fn_unmount_ref_time >= ref_time) 2131 ref_time = fnp->fn_unmount_ref_time + 1; 2132 mutex_exit(&fnp->fn_lock); 2133 2134 AUTOFS_DPRINT((4, "unmount_tree (ID=%ld)\n", ref_time)); 2135 top: 2136 AUTOFS_DPRINT((10, "unmount_tree: %s\n", fnp->fn_name)); 2137 ASSERT(fnp); 2138 vp = fntovn(fnp); 2139 if (vp->v_type == VLNK) { 2140 /* 2141 * can't unmount symbolic links 2142 */ 2143 goto next; 2144 } 2145 fnip = vfstofni(vp->v_vfsp); 2146 ASSERT(vp->v_count > 0); 2147 error = 0; 2148 autofs_busy_root = unmount_as_unit = 0; 2149 alp = NULL; 2150 2151 ilocked_it = 0; 2152 mutex_enter(&fnp->fn_lock); 2153 if (fnp->fn_flags & (MF_INPROG | MF_LOOKUP)) { 2154 /* 2155 * Either a mount, lookup or another unmount of this 2156 * subtree is in progress, don't attempt to unmount at 2157 * this time. 2158 */ 2159 mutex_exit(&fnp->fn_lock); 2160 error = EBUSY; 2161 goto next; 2162 } 2163 if (fnp->fn_unmount_ref_time >= ref_time) { 2164 /* 2165 * Already been here, try next node. 2166 */ 2167 mutex_exit(&fnp->fn_lock); 2168 error = EBUSY; 2169 goto next; 2170 } 2171 fnp->fn_unmount_ref_time = ref_time; 2172 2173 /* 2174 * If forced operation ignore timeout values 2175 */ 2176 if (!force && fnp->fn_ref_time + fnip->fi_mount_to > 2177 gethrestime_sec()) { 2178 /* 2179 * Node has been referenced recently, try the 2180 * unmount of its children if any. 2181 */ 2182 mutex_exit(&fnp->fn_lock); 2183 AUTOFS_DPRINT((10, "fn_ref_time within range\n")); 2184 rw_enter(&fnp->fn_rwlock, RW_READER); 2185 if (fnp->fn_dirents) { 2186 /* 2187 * Has subdirectory, attempt their 2188 * unmount first 2189 */ 2190 nfnp = fnp->fn_dirents; 2191 VN_HOLD(fntovn(nfnp)); 2192 rw_exit(&fnp->fn_rwlock); 2193 2194 VN_RELE(vp); 2195 fnp = nfnp; 2196 goto top; 2197 } 2198 rw_exit(&fnp->fn_rwlock); 2199 /* 2200 * No children, try next node. 2201 */ 2202 error = EBUSY; 2203 goto next; 2204 } 2205 2206 AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG); 2207 fnp->fn_error = 0; 2208 mutex_exit(&fnp->fn_lock); 2209 ilocked_it = 1; 2210 2211 rw_enter(&fnp->fn_rwlock, RW_WRITER); 2212 if (fnp->fn_trigger != NULL) { 2213 unmount_as_unit = 1; 2214 if ((vn_mountedvfs(vp) == NULL) && (check_auto_node(vp))) { 2215 /* 2216 * AUTOFS mountpoint is busy, there's 2217 * no point trying to unmount. Fall through 2218 * to attempt to unmount subtrees rooted 2219 * at a possible trigger node, but remember 2220 * not to unmount this tree. 2221 */ 2222 autofs_busy_root = 1; 2223 } 2224 2225 if (triggers_busy(fnp, &nfnp)) { 2226 rw_exit(&fnp->fn_rwlock); 2227 if (nfnp == NULL) { 2228 error = EBUSY; 2229 goto next; 2230 } 2231 /* 2232 * nfnp is busy, try to unmount it first 2233 */ 2234 mutex_enter(&fnp->fn_lock); 2235 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 2236 mutex_exit(&fnp->fn_lock); 2237 VN_RELE(vp); 2238 ASSERT(fntovn(nfnp)->v_count > 1); 2239 fnp = nfnp; 2240 goto top; 2241 } 2242 2243 /* 2244 * At this point, we know all trigger nodes are locked, 2245 * and they're not busy or mounted on. 2246 */ 2247 2248 if (autofs_busy_root) { 2249 /* 2250 * Got to unlock the the trigger nodes since 2251 * I'm not really going to unmount the filesystem. 2252 */ 2253 (void) triggers_unlock(fnp); 2254 } else { 2255 /* 2256 * Attempt to unmount all the trigger nodes, 2257 * save the action_list in case we need to 2258 * remount them later. The action_list will be 2259 * freed later if there was no need to remount the 2260 * trigger nodes. 2261 */ 2262 unmount_triggers(fnp, &alp); 2263 } 2264 } 2265 rw_exit(&fnp->fn_rwlock); 2266 2267 if (autofs_busy_root) 2268 goto next; 2269 2270 (void) vn_vfswlock_wait(vp); 2271 2272 vfsp = vn_mountedvfs(vp); 2273 if (vfsp != NULL) { 2274 /* 2275 * Node is mounted on. 2276 */ 2277 AUTOFS_DPRINT((10, "\tNode is mounted on\n")); 2278 2279 /* 2280 * Deal with /xfn/host/jurassic alikes here... 2281 */ 2282 if (vfs_matchops(vfsp, vfs_getops(vp->v_vfsp))) { 2283 /* 2284 * If the filesystem mounted here is AUTOFS, and it 2285 * is busy, try to unmount the tree rooted on it 2286 * first. We know this call to VFS_ROOT is safe to 2287 * call while holding VVFSLOCK, since it resolves 2288 * to a call to auto_root(). 2289 */ 2290 AUTOFS_DPRINT((10, "\t\tAUTOFS mounted here\n")); 2291 if (VFS_ROOT(vfsp, &newvp)) { 2292 cmn_err(CE_PANIC, 2293 "unmount_tree: VFS_ROOT(vfs=%p) failed", 2294 (void *)vfsp); 2295 } 2296 nfnp = vntofn(newvp); 2297 if (DEEPER(nfnp)) { 2298 vn_vfsunlock(vp); 2299 mutex_enter(&fnp->fn_lock); 2300 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 2301 mutex_exit(&fnp->fn_lock); 2302 VN_RELE(vp); 2303 fnp = nfnp; 2304 goto top; 2305 } 2306 /* 2307 * Fall through to unmount this filesystem 2308 */ 2309 VN_RELE(newvp); 2310 } 2311 2312 /* 2313 * vn_vfsunlock(vp) is done inside unmount_node() 2314 */ 2315 error = unmount_node(vp, force); 2316 if (error == ECONNRESET) { 2317 AUTOFS_DPRINT((10, "\tConnection dropped\n")); 2318 if (vn_mountedvfs(vp) == NULL) { 2319 /* 2320 * The filesystem was unmounted before the 2321 * daemon died. Unfortunately we can not 2322 * determine whether all the cleanup work was 2323 * successfully finished (i.e. update mnttab, 2324 * or notify NFS server of the unmount). 2325 * We should not retry the operation since the 2326 * filesystem has already been unmounted, and 2327 * may have already been removed from mnttab, 2328 * in such case the devid/rdevid we send to 2329 * the daemon will not be matched. So we have 2330 * to be content with the partial unmount. 2331 * Since the mountpoint is no longer covered, we 2332 * clear the error condition. 2333 */ 2334 error = 0; 2335 auto_log(fngp->fng_verbose, fngp->fng_zoneid, 2336 CE_WARN, 2337 "unmount_tree: automountd connection " 2338 "dropped"); 2339 if (fnip->fi_flags & MF_DIRECT) { 2340 auto_log(fngp->fng_verbose, 2341 fngp->fng_zoneid, CE_WARN, 2342 "unmount_tree: " 2343 "%s successfully unmounted - " 2344 "do not remount triggers", 2345 fnip->fi_path); 2346 } else { 2347 auto_log(fngp->fng_verbose, 2348 fngp->fng_zoneid, CE_WARN, 2349 "unmount_tree: " 2350 "%s/%s successfully unmounted - " 2351 "do not remount triggers", 2352 fnip->fi_path, fnp->fn_name); 2353 } 2354 } 2355 } 2356 } else { 2357 vn_vfsunlock(vp); 2358 AUTOFS_DPRINT((10, "\tNode is AUTOFS\n")); 2359 if (unmount_as_unit) { 2360 AUTOFS_DPRINT((10, "\tunmount as unit\n")); 2361 error = unmount_autofs(vp); 2362 } else { 2363 AUTOFS_DPRINT((10, "\tunmount one at a time\n")); 2364 rw_enter(&fnp->fn_rwlock, RW_READER); 2365 if (fnp->fn_dirents != NULL) { 2366 /* 2367 * Has subdirectory, attempt their 2368 * unmount first 2369 */ 2370 nfnp = fnp->fn_dirents; 2371 VN_HOLD(fntovn(nfnp)); 2372 rw_exit(&fnp->fn_rwlock); 2373 2374 mutex_enter(&fnp->fn_lock); 2375 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 2376 mutex_exit(&fnp->fn_lock); 2377 VN_RELE(vp); 2378 fnp = nfnp; 2379 goto top; 2380 } 2381 rw_exit(&fnp->fn_rwlock); 2382 goto next; 2383 } 2384 } 2385 2386 if (error) { 2387 AUTOFS_DPRINT((10, "\tUnmount failed\n")); 2388 if (alp != NULL) { 2389 /* 2390 * Unmount failed, got to remount triggers. 2391 */ 2392 ASSERT((fnp->fn_flags & MF_THISUID_MATCH_RQD) == 0); 2393 error = auto_perform_actions(fnip, fnp, alp, 2394 CRED()); 2395 if (error) { 2396 auto_log(fngp->fng_verbose, 2397 fngp->fng_zoneid, CE_WARN, 2398 "autofs: can't remount " 2399 "triggers fnp=%p error=%d", (void *)fnp, 2400 error); 2401 error = 0; 2402 /* 2403 * The action list should have been 2404 * free'd by auto_perform_actions 2405 * since an error occured 2406 */ 2407 alp = NULL; 2408 2409 } 2410 } 2411 } else { 2412 /* 2413 * The unmount succeeded, which will cause this node to 2414 * be removed from its parent if its an indirect mount, 2415 * therefore update the parent's atime and mtime now. 2416 * I don't update them in auto_disconnect() because I 2417 * don't want atime and mtime changing every time a 2418 * lookup goes to the daemon and creates a new node. 2419 */ 2420 unmount_done = 1; 2421 if ((fnip->fi_flags & MF_DIRECT) == 0) { 2422 gethrestime(&now); 2423 if (fnp->fn_parent == fngp->fng_rootfnnodep) 2424 fnp->fn_atime = fnp->fn_mtime = now; 2425 else 2426 fnp->fn_parent->fn_atime = 2427 fnp->fn_parent->fn_mtime = now; 2428 } 2429 2430 /* 2431 * Free the action list here 2432 */ 2433 if (alp != NULL) { 2434 xdr_free(xdr_action_list, (char *)alp); 2435 alp = NULL; 2436 } 2437 } 2438 2439 fnp->fn_ref_time = gethrestime_sec(); 2440 2441 next: 2442 /* 2443 * Obtain parent's readers lock before grabbing 2444 * reference to next sibling. 2445 * XXX Note that nodes in the top level list (mounted 2446 * in user space not by the daemon in the kernel) parent is itself, 2447 * therefore grabbing the lock makes no sense, but doesn't 2448 * hurt either. 2449 */ 2450 pfnp = fnp->fn_parent; 2451 ASSERT(pfnp != NULL); 2452 rw_enter(&pfnp->fn_rwlock, RW_READER); 2453 if ((nfnp = fnp->fn_next) != NULL) 2454 VN_HOLD(fntovn(nfnp)); 2455 rw_exit(&pfnp->fn_rwlock); 2456 2457 if (ilocked_it) { 2458 mutex_enter(&fnp->fn_lock); 2459 if (unmount_done) { 2460 /* 2461 * Other threads may be waiting for this unmount to 2462 * finish. We must let it know that in order to 2463 * proceed, it must trigger the mount itself. 2464 */ 2465 fnp->fn_flags &= ~MF_IK_MOUNT; 2466 if (fnp->fn_flags & MF_WAITING) 2467 fnp->fn_error = EAGAIN; 2468 unmount_done = 0; 2469 } 2470 AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG); 2471 mutex_exit(&fnp->fn_lock); 2472 ilocked_it = 0; 2473 } 2474 2475 if (nfnp != NULL) { 2476 VN_RELE(vp); 2477 fnp = nfnp; 2478 /* 2479 * Unmount next element 2480 */ 2481 goto top; 2482 } 2483 2484 /* 2485 * We don't want to unmount rootfnnodep, so the check is made here 2486 */ 2487 ASSERT(pfnp != fnp); 2488 if (pfnp != fngp->fng_rootfnnodep) { 2489 /* 2490 * Now attempt to unmount my parent 2491 */ 2492 VN_HOLD(fntovn(pfnp)); 2493 VN_RELE(vp); 2494 fnp = pfnp; 2495 2496 goto top; 2497 } 2498 2499 VN_RELE(vp); 2500 2501 /* 2502 * At this point we've walked the entire tree and attempted to unmount 2503 * as much as we can one level at a time. 2504 */ 2505 done: 2506 mutex_enter(&unmount_tree_cpr_lock); 2507 CALLB_CPR_EXIT(&cprinfo); 2508 mutex_destroy(&unmount_tree_cpr_lock); 2509 } 2510 2511 static void 2512 unmount_zone_tree(struct autofs_globals *fngp) 2513 { 2514 unmount_tree(fngp, 0); 2515 mutex_enter(&fngp->fng_unmount_threads_lock); 2516 fngp->fng_unmount_threads--; 2517 mutex_exit(&fngp->fng_unmount_threads_lock); 2518 2519 AUTOFS_DPRINT((5, "unmount_tree done. Thread exiting.\n")); 2520 2521 zthread_exit(); 2522 /* NOTREACHED */ 2523 } 2524 2525 static int autofs_unmount_thread_timer = 120; /* in seconds */ 2526 2527 void 2528 auto_do_unmount(struct autofs_globals *fngp) 2529 { 2530 callb_cpr_t cprinfo; 2531 clock_t timeleft; 2532 zone_t *zone = curproc->p_zone; 2533 2534 CALLB_CPR_INIT(&cprinfo, &fngp->fng_unmount_threads_lock, 2535 callb_generic_cpr, "auto_do_unmount"); 2536 2537 for (;;) { /* forever */ 2538 mutex_enter(&fngp->fng_unmount_threads_lock); 2539 CALLB_CPR_SAFE_BEGIN(&cprinfo); 2540 newthread: 2541 mutex_exit(&fngp->fng_unmount_threads_lock); 2542 timeleft = zone_status_timedwait(zone, lbolt + 2543 autofs_unmount_thread_timer * hz, ZONE_IS_SHUTTING_DOWN); 2544 mutex_enter(&fngp->fng_unmount_threads_lock); 2545 2546 if (timeleft != -1) { /* didn't time out */ 2547 ASSERT(zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN); 2548 /* 2549 * zone is exiting... don't create any new threads. 2550 * fng_unmount_threads_lock is released implicitly by 2551 * the below. 2552 */ 2553 CALLB_CPR_SAFE_END(&cprinfo, 2554 &fngp->fng_unmount_threads_lock); 2555 CALLB_CPR_EXIT(&cprinfo); 2556 zthread_exit(); 2557 /* NOTREACHED */ 2558 } 2559 if (fngp->fng_unmount_threads < autofs_unmount_threads) { 2560 fngp->fng_unmount_threads++; 2561 CALLB_CPR_SAFE_END(&cprinfo, 2562 &fngp->fng_unmount_threads_lock); 2563 mutex_exit(&fngp->fng_unmount_threads_lock); 2564 2565 (void) zthread_create(NULL, 0, unmount_zone_tree, fngp, 2566 0, minclsyspri); 2567 } else 2568 goto newthread; 2569 } 2570 /* NOTREACHED */ 2571 } 2572 2573 /* 2574 * Is nobrowse specified in option string? 2575 * opts should be a null ('\0') terminated string. 2576 * Returns non-zero if nobrowse has been specified. 2577 */ 2578 int 2579 auto_nobrowse_option(char *opts) 2580 { 2581 char *buf; 2582 char *p; 2583 char *t; 2584 int nobrowse = 0; 2585 int last_opt = 0; 2586 size_t len; 2587 2588 len = strlen(opts) + 1; 2589 p = buf = kmem_alloc(len, KM_SLEEP); 2590 (void) strcpy(buf, opts); 2591 do { 2592 if (t = strchr(p, ',')) 2593 *t++ = '\0'; 2594 else 2595 last_opt++; 2596 if (strcmp(p, MNTOPT_NOBROWSE) == 0) 2597 nobrowse = 1; 2598 else if (strcmp(p, MNTOPT_BROWSE) == 0) 2599 nobrowse = 0; 2600 p = t; 2601 } while (!last_opt); 2602 kmem_free(buf, len); 2603 2604 return (nobrowse); 2605 } 2606 2607 /* 2608 * used to log warnings only if automountd is running 2609 * with verbose mode set 2610 */ 2611 2612 void 2613 auto_log(int verbose, zoneid_t zoneid, int level, const char *fmt, ...) 2614 { 2615 va_list args; 2616 2617 if (verbose) { 2618 va_start(args, fmt); 2619 vzcmn_err(zoneid, level, fmt, args); 2620 va_end(args); 2621 } 2622 } 2623 2624 #ifdef DEBUG 2625 static int autofs_debug = 0; 2626 2627 /* 2628 * Utilities used by both client and server 2629 * Standard levels: 2630 * 0) no debugging 2631 * 1) hard failures 2632 * 2) soft failures 2633 * 3) current test software 2634 * 4) main procedure entry points 2635 * 5) main procedure exit points 2636 * 6) utility procedure entry points 2637 * 7) utility procedure exit points 2638 * 8) obscure procedure entry points 2639 * 9) obscure procedure exit points 2640 * 10) random stuff 2641 * 11) all <= 1 2642 * 12) all <= 2 2643 * 13) all <= 3 2644 * ... 2645 */ 2646 /* PRINTFLIKE2 */ 2647 void 2648 auto_dprint(int level, const char *fmt, ...) 2649 { 2650 va_list args; 2651 2652 if (autofs_debug == level || 2653 (autofs_debug > 10 && (autofs_debug - 10) >= level)) { 2654 va_start(args, fmt); 2655 (void) vprintf(fmt, args); 2656 va_end(args); 2657 } 2658 } 2659 #endif /* DEBUG */ 2660