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