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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/param.h> 26 #include <sys/systm.h> 27 #include <sys/errno.h> 28 #include <sys/proc.h> 29 #include <sys/vnode.h> 30 #include <sys/vfs.h> 31 #include <sys/vfs_opreg.h> 32 #include <sys/uio.h> 33 #include <sys/cred.h> 34 #include <sys/pathname.h> 35 #include <sys/dirent.h> 36 #include <sys/debug.h> 37 #include <sys/sysmacros.h> 38 #include <sys/tiuser.h> 39 #include <sys/cmn_err.h> 40 #include <sys/stat.h> 41 #include <sys/mode.h> 42 #include <sys/policy.h> 43 #include <rpc/types.h> 44 #include <rpc/auth.h> 45 #include <rpc/clnt.h> 46 #include <sys/fs/autofs.h> 47 #include <rpcsvc/autofs_prot.h> 48 #include <fs/fs_subr.h> 49 50 /* 51 * Vnode ops for autofs 52 */ 53 static int auto_open(vnode_t **, int, cred_t *, caller_context_t *); 54 static int auto_close(vnode_t *, int, int, offset_t, cred_t *, 55 caller_context_t *); 56 static int auto_getattr(vnode_t *, vattr_t *, int, cred_t *, 57 caller_context_t *); 58 static int auto_setattr(vnode_t *, vattr_t *, int, cred_t *, 59 caller_context_t *); 60 static int auto_access(vnode_t *, int, int, cred_t *, caller_context_t *); 61 static int auto_lookup(vnode_t *, char *, vnode_t **, 62 pathname_t *, int, vnode_t *, cred_t *, caller_context_t *, int *, 63 pathname_t *); 64 static int auto_create(vnode_t *, char *, vattr_t *, vcexcl_t, 65 int, vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *); 66 static int auto_remove(vnode_t *, char *, cred_t *, caller_context_t *, int); 67 static int auto_link(vnode_t *, vnode_t *, char *, cred_t *, 68 caller_context_t *, int); 69 static int auto_rename(vnode_t *, char *, vnode_t *, char *, cred_t *, 70 caller_context_t *, int); 71 static int auto_mkdir(vnode_t *, char *, vattr_t *, vnode_t **, cred_t *, 72 caller_context_t *, int, vsecattr_t *); 73 static int auto_rmdir(vnode_t *, char *, vnode_t *, cred_t *, 74 caller_context_t *, int); 75 static int auto_readdir(vnode_t *, uio_t *, cred_t *, int *, 76 caller_context_t *, int); 77 static int auto_symlink(vnode_t *, char *, vattr_t *, char *, cred_t *, 78 caller_context_t *, int); 79 static int auto_readlink(vnode_t *, struct uio *, cred_t *, 80 caller_context_t *); 81 static int auto_fsync(vnode_t *, int, cred_t *, caller_context_t *); 82 static void auto_inactive(vnode_t *, cred_t *, caller_context_t *); 83 static int auto_rwlock(vnode_t *, int, caller_context_t *); 84 static void auto_rwunlock(vnode_t *vp, int, caller_context_t *); 85 static int auto_seek(vnode_t *vp, offset_t, offset_t *, caller_context_t *); 86 87 static int auto_trigger_mount(vnode_t *, cred_t *, vnode_t **); 88 89 vnodeops_t *auto_vnodeops; 90 91 const fs_operation_def_t auto_vnodeops_template[] = { 92 { VOPNAME_OPEN, { .vop_open = auto_open } }, 93 { VOPNAME_CLOSE, { .vop_close = auto_close } }, 94 { VOPNAME_GETATTR, { .vop_getattr = auto_getattr } }, 95 { VOPNAME_SETATTR, { .vop_setattr = auto_setattr } }, 96 { VOPNAME_ACCESS, { .vop_access = auto_access } }, 97 { VOPNAME_LOOKUP, { .vop_lookup = auto_lookup } }, 98 { VOPNAME_CREATE, { .vop_create = auto_create } }, 99 { VOPNAME_REMOVE, { .vop_remove = auto_remove } }, 100 { VOPNAME_LINK, { .vop_link = auto_link } }, 101 { VOPNAME_RENAME, { .vop_rename = auto_rename } }, 102 { VOPNAME_MKDIR, { .vop_mkdir = auto_mkdir } }, 103 { VOPNAME_RMDIR, { .vop_rmdir = auto_rmdir } }, 104 { VOPNAME_READDIR, { .vop_readdir = auto_readdir } }, 105 { VOPNAME_SYMLINK, { .vop_symlink = auto_symlink } }, 106 { VOPNAME_READLINK, { .vop_readlink = auto_readlink } }, 107 { VOPNAME_FSYNC, { .vop_fsync = auto_fsync } }, 108 { VOPNAME_INACTIVE, { .vop_inactive = auto_inactive } }, 109 { VOPNAME_RWLOCK, { .vop_rwlock = auto_rwlock } }, 110 { VOPNAME_RWUNLOCK, { .vop_rwunlock = auto_rwunlock } }, 111 { VOPNAME_SEEK, { .vop_seek = auto_seek } }, 112 { VOPNAME_FRLOCK, { .error = fs_error } }, 113 { VOPNAME_DISPOSE, { .error = fs_error } }, 114 { VOPNAME_SHRLOCK, { .error = fs_error } }, 115 { VOPNAME_VNEVENT, { .vop_vnevent = fs_vnevent_support } }, 116 { NULL, { NULL } } 117 }; 118 119 120 121 /* ARGSUSED */ 122 static int 123 auto_open(vnode_t **vpp, int flag, cred_t *cred, caller_context_t *ct) 124 { 125 vnode_t *newvp; 126 int error; 127 128 AUTOFS_DPRINT((4, "auto_open: *vpp=%p\n", (void *)*vpp)); 129 130 error = auto_trigger_mount(*vpp, cred, &newvp); 131 if (error) 132 goto done; 133 134 if (newvp != NULL) { 135 /* 136 * Node is now mounted on. 137 */ 138 VN_RELE(*vpp); 139 *vpp = newvp; 140 error = VOP_ACCESS(*vpp, VREAD, 0, cred, ct); 141 if (!error) 142 error = VOP_OPEN(vpp, flag, cred, ct); 143 } 144 145 done: 146 AUTOFS_DPRINT((5, "auto_open: *vpp=%p error=%d\n", (void *)*vpp, 147 error)); 148 return (error); 149 } 150 151 /* ARGSUSED */ 152 static int 153 auto_close( 154 vnode_t *vp, 155 int flag, 156 int count, 157 offset_t offset, 158 cred_t *cred, 159 caller_context_t *ct) 160 { 161 return (0); 162 } 163 164 static int 165 auto_getattr( 166 vnode_t *vp, 167 vattr_t *vap, 168 int flags, 169 cred_t *cred, 170 caller_context_t *ct) 171 { 172 fnnode_t *fnp = vntofn(vp); 173 vnode_t *newvp; 174 vfs_t *vfsp; 175 int error; 176 177 AUTOFS_DPRINT((4, "auto_getattr vp %p\n", (void *)vp)); 178 179 if (flags & ATTR_TRIGGER) { 180 /* 181 * Pre-trigger the mount 182 */ 183 error = auto_trigger_mount(vp, cred, &newvp); 184 if (error) 185 return (error); 186 187 if (newvp == NULL) 188 goto defattr; 189 190 if (error = vn_vfsrlock_wait(vp)) { 191 VN_RELE(newvp); 192 return (error); 193 } 194 195 vfsp = newvp->v_vfsp; 196 VN_RELE(newvp); 197 } else { 198 /* 199 * Recursive auto_getattr/mount; go to the vfsp == NULL 200 * case. 201 */ 202 if (vn_vfswlock_held(vp)) 203 goto defattr; 204 205 if (error = vn_vfsrlock_wait(vp)) 206 return (error); 207 208 vfsp = vn_mountedvfs(vp); 209 } 210 211 if (vfsp != NULL) { 212 /* 213 * Node is mounted on. 214 */ 215 error = VFS_ROOT(vfsp, &newvp); 216 vn_vfsunlock(vp); 217 if (error) 218 return (error); 219 mutex_enter(&fnp->fn_lock); 220 if (fnp->fn_seen == newvp && fnp->fn_thread == curthread) { 221 /* 222 * Recursive auto_getattr(); just release newvp and drop 223 * into the vfsp == NULL case. 224 */ 225 mutex_exit(&fnp->fn_lock); 226 VN_RELE(newvp); 227 } else { 228 while (fnp->fn_thread && fnp->fn_thread != curthread) { 229 fnp->fn_flags |= MF_ATTR_WAIT; 230 cv_wait(&fnp->fn_cv_mount, &fnp->fn_lock); 231 } 232 fnp->fn_thread = curthread; 233 fnp->fn_seen = newvp; 234 mutex_exit(&fnp->fn_lock); 235 error = VOP_GETATTR(newvp, vap, flags, cred, ct); 236 VN_RELE(newvp); 237 mutex_enter(&fnp->fn_lock); 238 fnp->fn_seen = 0; 239 fnp->fn_thread = 0; 240 if (fnp->fn_flags & MF_ATTR_WAIT) { 241 fnp->fn_flags &= ~MF_ATTR_WAIT; 242 cv_broadcast(&fnp->fn_cv_mount); 243 } 244 mutex_exit(&fnp->fn_lock); 245 return (error); 246 } 247 } else { 248 vn_vfsunlock(vp); 249 } 250 251 defattr: 252 ASSERT(vp->v_type == VDIR || vp->v_type == VLNK); 253 vap->va_uid = 0; 254 vap->va_gid = 0; 255 vap->va_nlink = fnp->fn_linkcnt; 256 vap->va_nodeid = (u_longlong_t)fnp->fn_nodeid; 257 vap->va_size = fnp->fn_size; 258 vap->va_atime = fnp->fn_atime; 259 vap->va_mtime = fnp->fn_mtime; 260 vap->va_ctime = fnp->fn_ctime; 261 vap->va_type = vp->v_type; 262 vap->va_mode = fnp->fn_mode; 263 vap->va_fsid = vp->v_vfsp->vfs_dev; 264 vap->va_rdev = 0; 265 vap->va_blksize = MAXBSIZE; 266 vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size); 267 vap->va_seq = 0; 268 269 return (0); 270 } 271 272 /*ARGSUSED4*/ 273 static int 274 auto_setattr( 275 vnode_t *vp, 276 struct vattr *vap, 277 int flags, 278 cred_t *cred, 279 caller_context_t *ct) 280 { 281 vnode_t *newvp; 282 int error; 283 284 AUTOFS_DPRINT((4, "auto_setattr vp %p\n", (void *)vp)); 285 286 if (error = auto_trigger_mount(vp, cred, &newvp)) 287 goto done; 288 289 if (newvp != NULL) { 290 /* 291 * Node is mounted on. 292 */ 293 if (vn_is_readonly(newvp)) 294 error = EROFS; 295 else 296 error = VOP_SETATTR(newvp, vap, flags, cred, ct); 297 VN_RELE(newvp); 298 } else 299 error = ENOSYS; 300 301 done: 302 AUTOFS_DPRINT((5, "auto_setattr: error=%d\n", error)); 303 return (error); 304 } 305 306 /* ARGSUSED */ 307 static int 308 auto_access( 309 vnode_t *vp, 310 int mode, 311 int flags, 312 cred_t *cred, 313 caller_context_t *ct) 314 { 315 fnnode_t *fnp = vntofn(vp); 316 vnode_t *newvp; 317 int error; 318 319 AUTOFS_DPRINT((4, "auto_access: vp=%p\n", (void *)vp)); 320 321 if (error = auto_trigger_mount(vp, cred, &newvp)) 322 goto done; 323 324 if (newvp != NULL) { 325 /* 326 * Node is mounted on. 327 */ 328 error = VOP_ACCESS(newvp, mode, 0, cred, ct); 329 VN_RELE(newvp); 330 } else { 331 int shift = 0; 332 333 /* 334 * really interested in the autofs node, check the 335 * access on it 336 */ 337 ASSERT(error == 0); 338 if (crgetuid(cred) != fnp->fn_uid) { 339 shift += 3; 340 if (groupmember(fnp->fn_gid, cred) == 0) 341 shift += 3; 342 } 343 error = secpolicy_vnode_access2(cred, vp, fnp->fn_uid, 344 fnp->fn_mode << shift, mode); 345 } 346 347 done: 348 AUTOFS_DPRINT((5, "auto_access: error=%d\n", error)); 349 return (error); 350 } 351 352 static int 353 auto_lookup( 354 vnode_t *dvp, 355 char *nm, 356 vnode_t **vpp, 357 pathname_t *pnp, 358 int flags, 359 vnode_t *rdir, 360 cred_t *cred, 361 caller_context_t *ct, 362 int *direntflags, 363 pathname_t *realpnp) 364 { 365 int error = 0; 366 vnode_t *newvp = NULL; 367 vfs_t *vfsp; 368 fninfo_t *dfnip; 369 fnnode_t *dfnp = NULL; 370 fnnode_t *fnp = NULL; 371 char *searchnm; 372 int operation; /* either AUTOFS_LOOKUP or AUTOFS_MOUNT */ 373 374 dfnip = vfstofni(dvp->v_vfsp); 375 AUTOFS_DPRINT((3, "auto_lookup: dvp=%p (%s) name=%s\n", 376 (void *)dvp, dfnip->fi_map, nm)); 377 378 if (nm[0] == 0) { 379 VN_HOLD(dvp); 380 *vpp = dvp; 381 return (0); 382 } 383 384 if (error = VOP_ACCESS(dvp, VEXEC, 0, cred, ct)) 385 return (error); 386 387 if (nm[0] == '.' && nm[1] == 0) { 388 VN_HOLD(dvp); 389 *vpp = dvp; 390 return (0); 391 } 392 393 if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) { 394 fnnode_t *pdfnp; 395 396 pdfnp = (vntofn(dvp))->fn_parent; 397 ASSERT(pdfnp != NULL); 398 399 /* 400 * Since it is legitimate to have the VROOT flag set for the 401 * subdirectories of the indirect map in autofs filesystem, 402 * rootfnnodep is checked against fnnode of dvp instead of 403 * just checking whether VROOT flag is set in dvp 404 */ 405 406 if (pdfnp == pdfnp->fn_globals->fng_rootfnnodep) { 407 vnode_t *vp; 408 409 vfs_rlock_wait(dvp->v_vfsp); 410 if (dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) { 411 vfs_unlock(dvp->v_vfsp); 412 return (EIO); 413 } 414 vp = dvp->v_vfsp->vfs_vnodecovered; 415 VN_HOLD(vp); 416 vfs_unlock(dvp->v_vfsp); 417 error = VOP_LOOKUP(vp, nm, vpp, pnp, flags, rdir, cred, 418 ct, direntflags, realpnp); 419 VN_RELE(vp); 420 return (error); 421 } else { 422 *vpp = fntovn(pdfnp); 423 VN_HOLD(*vpp); 424 return (0); 425 } 426 } 427 428 top: 429 dfnp = vntofn(dvp); 430 searchnm = nm; 431 operation = 0; 432 433 ASSERT(vn_matchops(dvp, auto_vnodeops)); 434 435 AUTOFS_DPRINT((3, "auto_lookup: dvp=%p dfnp=%p\n", (void *)dvp, 436 (void *)dfnp)); 437 438 /* 439 * If a lookup or mount of this node is in progress, wait for it 440 * to finish, and return whatever result it got. 441 */ 442 mutex_enter(&dfnp->fn_lock); 443 if (dfnp->fn_flags & (MF_LOOKUP | MF_INPROG)) { 444 mutex_exit(&dfnp->fn_lock); 445 error = auto_wait4mount(dfnp); 446 if (error == AUTOFS_SHUTDOWN) 447 error = ENOENT; 448 if (error == EAGAIN) 449 goto top; 450 if (error) 451 return (error); 452 } else 453 mutex_exit(&dfnp->fn_lock); 454 455 456 error = vn_vfsrlock_wait(dvp); 457 if (error) 458 return (error); 459 vfsp = vn_mountedvfs(dvp); 460 if (vfsp != NULL) { 461 error = VFS_ROOT(vfsp, &newvp); 462 vn_vfsunlock(dvp); 463 if (!error) { 464 error = VOP_LOOKUP(newvp, nm, vpp, pnp, 465 flags, rdir, cred, ct, direntflags, realpnp); 466 VN_RELE(newvp); 467 } 468 return (error); 469 } 470 vn_vfsunlock(dvp); 471 472 rw_enter(&dfnp->fn_rwlock, RW_READER); 473 error = auto_search(dfnp, nm, &fnp, cred); 474 if (error) { 475 if (dfnip->fi_flags & MF_DIRECT) { 476 /* 477 * direct map. 478 */ 479 if (dfnp->fn_dirents) { 480 /* 481 * Mount previously triggered. 482 * 'nm' not found 483 */ 484 error = ENOENT; 485 } else { 486 /* 487 * I need to contact the daemon to trigger 488 * the mount. 'dfnp' will be the mountpoint. 489 */ 490 operation = AUTOFS_MOUNT; 491 VN_HOLD(fntovn(dfnp)); 492 fnp = dfnp; 493 error = 0; 494 } 495 } else if (dvp == dfnip->fi_rootvp) { 496 /* 497 * 'dfnp' is the root of the indirect AUTOFS. 498 */ 499 if (rw_tryupgrade(&dfnp->fn_rwlock) == 0) { 500 /* 501 * Could not acquire writer lock, release 502 * reader, and wait until available. We 503 * need to search for 'nm' again, since we 504 * had to release the lock before reacquiring 505 * it. 506 */ 507 rw_exit(&dfnp->fn_rwlock); 508 rw_enter(&dfnp->fn_rwlock, RW_WRITER); 509 error = auto_search(dfnp, nm, &fnp, cred); 510 } 511 512 ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock)); 513 if (error) { 514 /* 515 * create node being looked-up and request 516 * mount on it. 517 */ 518 error = auto_enter(dfnp, nm, &fnp, kcred); 519 if (!error) 520 operation = AUTOFS_LOOKUP; 521 } 522 } else if ((dfnp->fn_dirents == NULL) && 523 ((dvp->v_flag & VROOT) == 0) && 524 ((fntovn(dfnp->fn_parent))->v_flag & VROOT)) { 525 /* 526 * dfnp is the actual 'mountpoint' of indirect map, 527 * it is the equivalent of a direct mount, 528 * ie, /home/'user1' 529 */ 530 operation = AUTOFS_MOUNT; 531 VN_HOLD(fntovn(dfnp)); 532 fnp = dfnp; 533 error = 0; 534 searchnm = dfnp->fn_name; 535 } 536 } 537 538 if (error == EAGAIN) { 539 rw_exit(&dfnp->fn_rwlock); 540 goto top; 541 } 542 if (error) { 543 rw_exit(&dfnp->fn_rwlock); 544 return (error); 545 } 546 547 /* 548 * We now have the actual fnnode we're interested in. 549 * The 'MF_LOOKUP' indicates another thread is currently 550 * performing a daemon lookup of this node, therefore we 551 * wait for its completion. 552 * The 'MF_INPROG' indicates another thread is currently 553 * performing a daemon mount of this node, we wait for it 554 * to be done if we are performing a MOUNT. We don't 555 * wait for it if we are performing a LOOKUP. 556 * We can release the reader/writer lock as soon as we acquire 557 * the mutex, since the state of the lock can only change by 558 * first acquiring the mutex. 559 */ 560 mutex_enter(&fnp->fn_lock); 561 rw_exit(&dfnp->fn_rwlock); 562 if ((fnp->fn_flags & MF_LOOKUP) || 563 ((operation == AUTOFS_MOUNT) && (fnp->fn_flags & MF_INPROG))) { 564 mutex_exit(&fnp->fn_lock); 565 error = auto_wait4mount(fnp); 566 VN_RELE(fntovn(fnp)); 567 if (error == AUTOFS_SHUTDOWN) 568 error = ENOENT; 569 if (error && error != EAGAIN) 570 return (error); 571 goto top; 572 } 573 574 if (operation == 0) { 575 /* 576 * got the fnnode, check for any errors 577 * on the previous operation on that node. 578 */ 579 error = fnp->fn_error; 580 if ((error == EINTR) || (error == EAGAIN)) { 581 /* 582 * previous operation on this node was 583 * not completed, do a lookup now. 584 */ 585 operation = AUTOFS_LOOKUP; 586 } else { 587 /* 588 * previous operation completed. Return 589 * a pointer to the node only if there was 590 * no error. 591 */ 592 mutex_exit(&fnp->fn_lock); 593 if (!error) 594 *vpp = fntovn(fnp); 595 else 596 VN_RELE(fntovn(fnp)); 597 return (error); 598 } 599 } 600 601 /* 602 * Since I got to this point, it means I'm the one 603 * responsible for triggering the mount/look-up of this node. 604 */ 605 switch (operation) { 606 case AUTOFS_LOOKUP: 607 AUTOFS_BLOCK_OTHERS(fnp, MF_LOOKUP); 608 fnp->fn_error = 0; 609 mutex_exit(&fnp->fn_lock); 610 error = auto_lookup_aux(fnp, searchnm, cred); 611 if (!error) { 612 /* 613 * Return this vnode 614 */ 615 *vpp = fntovn(fnp); 616 } else { 617 /* 618 * release our reference to this vnode 619 * and return error 620 */ 621 VN_RELE(fntovn(fnp)); 622 } 623 break; 624 case AUTOFS_MOUNT: 625 AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG); 626 fnp->fn_error = 0; 627 mutex_exit(&fnp->fn_lock); 628 /* 629 * auto_new_mount_thread fires up a new thread which 630 * calls automountd finishing up the work 631 */ 632 auto_new_mount_thread(fnp, searchnm, cred); 633 634 /* 635 * At this point, we are simply another thread 636 * waiting for the mount to complete 637 */ 638 error = auto_wait4mount(fnp); 639 if (error == AUTOFS_SHUTDOWN) 640 error = ENOENT; 641 642 /* 643 * now release our reference to this vnode 644 */ 645 VN_RELE(fntovn(fnp)); 646 if (!error) 647 goto top; 648 break; 649 default: 650 auto_log(dfnp->fn_globals->fng_verbose, 651 dfnp->fn_globals->fng_zoneid, CE_WARN, 652 "auto_lookup: unknown operation %d", 653 operation); 654 } 655 656 AUTOFS_DPRINT((5, "auto_lookup: name=%s *vpp=%p return=%d\n", 657 nm, (void *)*vpp, error)); 658 659 return (error); 660 } 661 662 static int 663 auto_create( 664 vnode_t *dvp, 665 char *nm, 666 vattr_t *va, 667 vcexcl_t excl, 668 int mode, 669 vnode_t **vpp, 670 cred_t *cred, 671 int flag, 672 caller_context_t *ct, 673 vsecattr_t *vsecp) 674 { 675 vnode_t *newvp; 676 int error; 677 678 AUTOFS_DPRINT((4, "auto_create dvp %p nm %s\n", (void *)dvp, nm)); 679 680 if (error = auto_trigger_mount(dvp, cred, &newvp)) 681 goto done; 682 683 if (newvp != NULL) { 684 /* 685 * Node is now mounted on. 686 */ 687 if (vn_is_readonly(newvp)) 688 error = EROFS; 689 else 690 error = VOP_CREATE(newvp, nm, va, excl, 691 mode, vpp, cred, flag, ct, vsecp); 692 VN_RELE(newvp); 693 } else 694 error = ENOSYS; 695 696 done: 697 AUTOFS_DPRINT((5, "auto_create: error=%d\n", error)); 698 return (error); 699 } 700 701 static int 702 auto_remove( 703 vnode_t *dvp, 704 char *nm, 705 cred_t *cred, 706 caller_context_t *ct, 707 int flags) 708 { 709 vnode_t *newvp; 710 int error; 711 712 AUTOFS_DPRINT((4, "auto_remove dvp %p nm %s\n", (void *)dvp, nm)); 713 714 if (error = auto_trigger_mount(dvp, cred, &newvp)) 715 goto done; 716 717 if (newvp != NULL) { 718 /* 719 * Node is now mounted on. 720 */ 721 if (vn_is_readonly(newvp)) 722 error = EROFS; 723 else 724 error = VOP_REMOVE(newvp, nm, cred, ct, flags); 725 VN_RELE(newvp); 726 } else 727 error = ENOSYS; 728 729 done: 730 AUTOFS_DPRINT((5, "auto_remove: error=%d\n", error)); 731 return (error); 732 } 733 734 static int 735 auto_link( 736 vnode_t *tdvp, 737 vnode_t *svp, 738 char *nm, 739 cred_t *cred, 740 caller_context_t *ct, 741 int flags) 742 { 743 vnode_t *newvp; 744 int error; 745 746 AUTOFS_DPRINT((4, "auto_link tdvp %p svp %p nm %s\n", (void *)tdvp, 747 (void *)svp, nm)); 748 749 if (error = auto_trigger_mount(tdvp, cred, &newvp)) 750 goto done; 751 752 if (newvp == NULL) { 753 /* 754 * an autonode can not be a link to another node 755 */ 756 error = ENOSYS; 757 goto done; 758 } 759 760 if (vn_is_readonly(newvp)) { 761 error = EROFS; 762 VN_RELE(newvp); 763 goto done; 764 } 765 766 if (vn_matchops(svp, auto_vnodeops)) { 767 /* 768 * source vp can't be an autonode 769 */ 770 error = ENOSYS; 771 VN_RELE(newvp); 772 goto done; 773 } 774 775 error = VOP_LINK(newvp, svp, nm, cred, ct, flags); 776 VN_RELE(newvp); 777 778 done: 779 AUTOFS_DPRINT((5, "auto_link error=%d\n", error)); 780 return (error); 781 } 782 783 static int 784 auto_rename( 785 vnode_t *odvp, 786 char *onm, 787 vnode_t *ndvp, 788 char *nnm, 789 cred_t *cr, 790 caller_context_t *ct, 791 int flags) 792 { 793 vnode_t *o_newvp, *n_newvp; 794 int error; 795 796 AUTOFS_DPRINT((4, "auto_rename odvp %p onm %s to ndvp %p nnm %s\n", 797 (void *)odvp, onm, (void *)ndvp, nnm)); 798 799 /* 800 * we know odvp is an autonode, otherwise this function 801 * could not have ever been called. 802 */ 803 ASSERT(vn_matchops(odvp, auto_vnodeops)); 804 805 if (error = auto_trigger_mount(odvp, cr, &o_newvp)) 806 goto done; 807 808 if (o_newvp == NULL) { 809 /* 810 * can't rename an autonode 811 */ 812 error = ENOSYS; 813 goto done; 814 } 815 816 if (vn_matchops(ndvp, auto_vnodeops)) { 817 /* 818 * directory is AUTOFS, need to trigger the 819 * mount of the real filesystem. 820 */ 821 if (error = auto_trigger_mount(ndvp, cr, &n_newvp)) { 822 VN_RELE(o_newvp); 823 goto done; 824 } 825 826 if (n_newvp == NULL) { 827 /* 828 * target can't be an autonode 829 */ 830 error = ENOSYS; 831 VN_RELE(o_newvp); 832 goto done; 833 } 834 } else { 835 /* 836 * destination directory mount had been 837 * triggered prior to the call to this function. 838 */ 839 n_newvp = ndvp; 840 } 841 842 ASSERT(!vn_matchops(n_newvp, auto_vnodeops)); 843 844 if (vn_is_readonly(n_newvp)) { 845 error = EROFS; 846 VN_RELE(o_newvp); 847 if (n_newvp != ndvp) 848 VN_RELE(n_newvp); 849 goto done; 850 } 851 852 error = VOP_RENAME(o_newvp, onm, n_newvp, nnm, cr, ct, flags); 853 VN_RELE(o_newvp); 854 if (n_newvp != ndvp) 855 VN_RELE(n_newvp); 856 857 done: 858 AUTOFS_DPRINT((5, "auto_rename error=%d\n", error)); 859 return (error); 860 } 861 862 static int 863 auto_mkdir( 864 vnode_t *dvp, 865 char *nm, 866 vattr_t *va, 867 vnode_t **vpp, 868 cred_t *cred, 869 caller_context_t *ct, 870 int flags, 871 vsecattr_t *vsecp) 872 { 873 vnode_t *newvp; 874 int error; 875 876 AUTOFS_DPRINT((4, "auto_mkdir dvp %p nm %s\n", (void *)dvp, nm)); 877 878 if (error = auto_trigger_mount(dvp, cred, &newvp)) 879 goto done; 880 881 if (newvp != NULL) { 882 /* 883 * Node is now mounted on. 884 */ 885 if (vn_is_readonly(newvp)) 886 error = EROFS; 887 else 888 error = VOP_MKDIR(newvp, nm, va, vpp, cred, ct, 889 flags, vsecp); 890 VN_RELE(newvp); 891 } else 892 error = ENOSYS; 893 894 done: 895 AUTOFS_DPRINT((5, "auto_mkdir: error=%d\n", error)); 896 return (error); 897 } 898 899 static int 900 auto_rmdir( 901 vnode_t *dvp, 902 char *nm, 903 vnode_t *cdir, 904 cred_t *cred, 905 caller_context_t *ct, 906 int flags) 907 { 908 vnode_t *newvp; 909 int error; 910 911 AUTOFS_DPRINT((4, "auto_rmdir: vp=%p nm=%s\n", (void *)dvp, nm)); 912 913 if (error = auto_trigger_mount(dvp, cred, &newvp)) 914 goto done; 915 916 if (newvp != NULL) { 917 /* 918 * Node is now mounted on. 919 */ 920 if (vn_is_readonly(newvp)) 921 error = EROFS; 922 else 923 error = VOP_RMDIR(newvp, nm, cdir, cred, ct, flags); 924 VN_RELE(newvp); 925 } else 926 error = ENOSYS; 927 928 done: 929 AUTOFS_DPRINT((5, "auto_rmdir: error=%d\n", error)); 930 return (error); 931 } 932 933 static int autofs_nobrowse = 0; 934 935 #ifdef nextdp 936 #undef nextdp 937 #endif 938 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 939 940 /* ARGSUSED */ 941 static int 942 auto_readdir( 943 vnode_t *vp, 944 uio_t *uiop, 945 cred_t *cred, 946 int *eofp, 947 caller_context_t *ct, 948 int flags) 949 { 950 struct autofs_rddirargs rda; 951 autofs_rddirres rd; 952 fnnode_t *fnp = vntofn(vp); 953 fnnode_t *cfnp, *nfnp; 954 dirent64_t *dp; 955 ulong_t offset; 956 ulong_t outcount = 0, count = 0; 957 size_t namelen; 958 ulong_t alloc_count; 959 void *outbuf = NULL; 960 fninfo_t *fnip = vfstofni(vp->v_vfsp); 961 struct iovec *iovp; 962 int error = 0; 963 int reached_max = 0; 964 int myeof = 0; 965 int this_reclen; 966 struct autofs_globals *fngp = vntofn(fnip->fi_rootvp)->fn_globals; 967 968 AUTOFS_DPRINT((4, "auto_readdir vp=%p offset=%lld\n", 969 (void *)vp, uiop->uio_loffset)); 970 971 if (eofp != NULL) 972 *eofp = 0; 973 974 if (uiop->uio_iovcnt != 1) 975 return (EINVAL); 976 977 iovp = uiop->uio_iov; 978 alloc_count = iovp->iov_len; 979 980 gethrestime(&fnp->fn_atime); 981 fnp->fn_ref_time = fnp->fn_atime.tv_sec; 982 983 dp = outbuf = kmem_zalloc(alloc_count, KM_SLEEP); 984 985 /* 986 * Held when getdents calls VOP_RWLOCK.... 987 */ 988 ASSERT(RW_READ_HELD(&fnp->fn_rwlock)); 989 if (uiop->uio_offset >= AUTOFS_DAEMONCOOKIE) { 990 again: 991 /* 992 * Do readdir of daemon contents only 993 * Drop readers lock and reacquire after reply. 994 */ 995 rw_exit(&fnp->fn_rwlock); 996 bzero(&rd, sizeof (struct autofs_rddirres)); 997 count = 0; 998 rda.rda_map = fnip->fi_map; 999 rda.rda_offset = (uint_t)uiop->uio_offset; 1000 rd.rd_rddir.rddir_entries = dp; 1001 rda.rda_count = rd.rd_rddir.rddir_size = (uint_t)alloc_count; 1002 rda.uid = crgetuid(cred); 1003 1004 error = auto_calldaemon(fngp->fng_zoneid, 1005 AUTOFS_READDIR, 1006 xdr_autofs_rddirargs, 1007 &rda, 1008 xdr_autofs_rddirres, 1009 (void *)&rd, 1010 sizeof (autofs_rddirres), 1011 TRUE); 1012 1013 /* 1014 * reacquire previously dropped lock 1015 */ 1016 rw_enter(&fnp->fn_rwlock, RW_READER); 1017 1018 if (!error) { 1019 error = rd.rd_status; 1020 dp = rd.rd_rddir.rddir_entries; 1021 } 1022 1023 if (error) { 1024 if (error == AUTOFS_SHUTDOWN) { 1025 /* 1026 * treat as empty directory 1027 */ 1028 error = 0; 1029 myeof = 1; 1030 if (eofp) 1031 *eofp = 1; 1032 } 1033 goto done; 1034 } 1035 if (rd.rd_rddir.rddir_size) { 1036 dirent64_t *odp = dp; /* next in output buffer */ 1037 dirent64_t *cdp = dp; /* current examined entry */ 1038 1039 /* 1040 * Check for duplicates here 1041 */ 1042 do { 1043 this_reclen = cdp->d_reclen; 1044 if (auto_search(fnp, cdp->d_name, 1045 NULL, cred)) { 1046 /* 1047 * entry not found in kernel list, 1048 * include it in readdir output. 1049 * 1050 * If we are skipping entries. then 1051 * we need to copy this entry to the 1052 * correct position in the buffer 1053 * to be copied out. 1054 */ 1055 if (cdp != odp) 1056 bcopy(cdp, odp, 1057 (size_t)this_reclen); 1058 odp = nextdp(odp); 1059 outcount += this_reclen; 1060 } else { 1061 /* 1062 * Entry was found in the kernel 1063 * list. If it is the first entry 1064 * in this buffer, then just skip it 1065 */ 1066 if (odp == dp) { 1067 dp = nextdp(dp); 1068 odp = dp; 1069 } 1070 } 1071 count += this_reclen; 1072 cdp = (struct dirent64 *) 1073 ((char *)cdp + this_reclen); 1074 } while (count < rd.rd_rddir.rddir_size); 1075 1076 if (outcount) 1077 error = uiomove(dp, outcount, UIO_READ, uiop); 1078 uiop->uio_offset = rd.rd_rddir.rddir_offset; 1079 } else { 1080 if (rd.rd_rddir.rddir_eof == 0) { 1081 /* 1082 * alloc_count not large enough for one 1083 * directory entry 1084 */ 1085 error = EINVAL; 1086 } 1087 } 1088 if (rd.rd_rddir.rddir_eof && !error) { 1089 myeof = 1; 1090 if (eofp) 1091 *eofp = 1; 1092 } 1093 if (!error && !myeof && outcount == 0) { 1094 /* 1095 * call daemon with new cookie, all previous 1096 * elements happened to be duplicates 1097 */ 1098 dp = outbuf; 1099 goto again; 1100 } 1101 goto done; 1102 } 1103 1104 if (uiop->uio_offset == 0) { 1105 /* 1106 * first time: so fudge the . and .. 1107 */ 1108 this_reclen = DIRENT64_RECLEN(1); 1109 if (alloc_count < this_reclen) { 1110 error = EINVAL; 1111 goto done; 1112 } 1113 dp->d_ino = (ino64_t)fnp->fn_nodeid; 1114 dp->d_off = (off64_t)1; 1115 dp->d_reclen = (ushort_t)this_reclen; 1116 1117 /* use strncpy(9f) to zero out uninitialized bytes */ 1118 1119 (void) strncpy(dp->d_name, ".", 1120 DIRENT64_NAMELEN(this_reclen)); 1121 outcount += dp->d_reclen; 1122 dp = nextdp(dp); 1123 1124 this_reclen = DIRENT64_RECLEN(2); 1125 if (alloc_count < outcount + this_reclen) { 1126 error = EINVAL; 1127 goto done; 1128 } 1129 dp->d_reclen = (ushort_t)this_reclen; 1130 dp->d_ino = (ino64_t)fnp->fn_parent->fn_nodeid; 1131 dp->d_off = (off64_t)2; 1132 1133 /* use strncpy(9f) to zero out uninitialized bytes */ 1134 1135 (void) strncpy(dp->d_name, "..", 1136 DIRENT64_NAMELEN(this_reclen)); 1137 outcount += dp->d_reclen; 1138 dp = nextdp(dp); 1139 } 1140 1141 offset = 2; 1142 cfnp = fnp->fn_dirents; 1143 while (cfnp != NULL) { 1144 nfnp = cfnp->fn_next; 1145 offset = cfnp->fn_offset; 1146 if ((offset >= uiop->uio_offset) && 1147 (!(cfnp->fn_flags & MF_LOOKUP))) { 1148 int reclen; 1149 1150 /* 1151 * include node only if its offset is greater or 1152 * equal to the one required and it is not in 1153 * transient state (not being looked-up) 1154 */ 1155 namelen = strlen(cfnp->fn_name); 1156 reclen = (int)DIRENT64_RECLEN(namelen); 1157 if (outcount + reclen > alloc_count) { 1158 reached_max = 1; 1159 break; 1160 } 1161 dp->d_reclen = (ushort_t)reclen; 1162 dp->d_ino = (ino64_t)cfnp->fn_nodeid; 1163 if (nfnp != NULL) { 1164 /* 1165 * get the offset of the next element 1166 */ 1167 dp->d_off = (off64_t)nfnp->fn_offset; 1168 } else { 1169 /* 1170 * This is the last element, make 1171 * offset one plus the current 1172 */ 1173 dp->d_off = (off64_t)cfnp->fn_offset + 1; 1174 } 1175 1176 /* use strncpy(9f) to zero out uninitialized bytes */ 1177 1178 (void) strncpy(dp->d_name, cfnp->fn_name, 1179 DIRENT64_NAMELEN(reclen)); 1180 outcount += dp->d_reclen; 1181 dp = nextdp(dp); 1182 } 1183 cfnp = nfnp; 1184 } 1185 1186 if (outcount) 1187 error = uiomove(outbuf, outcount, UIO_READ, uiop); 1188 1189 if (!error) { 1190 if (reached_max) { 1191 /* 1192 * This entry did not get added to the buffer on this, 1193 * call. We need to add it on the next call therefore 1194 * set uio_offset to this entry's offset. If there 1195 * wasn't enough space for one dirent, return EINVAL. 1196 */ 1197 uiop->uio_offset = offset; 1198 if (outcount == 0) 1199 error = EINVAL; 1200 } else if (autofs_nobrowse || 1201 auto_nobrowse_option(fnip->fi_opts) || 1202 (fnip->fi_flags & MF_DIRECT) || 1203 (fnp->fn_trigger != NULL) || 1204 (((vp->v_flag & VROOT) == 0) && 1205 ((fntovn(fnp->fn_parent))->v_flag & VROOT) && 1206 (fnp->fn_dirents == NULL))) { 1207 /* 1208 * done reading directory entries 1209 */ 1210 uiop->uio_offset = offset + 1; 1211 if (eofp) 1212 *eofp = 1; 1213 } else { 1214 /* 1215 * Need to get the rest of the entries from the daemon. 1216 */ 1217 uiop->uio_offset = AUTOFS_DAEMONCOOKIE; 1218 } 1219 } 1220 1221 done: 1222 kmem_free(outbuf, alloc_count); 1223 AUTOFS_DPRINT((5, "auto_readdir vp=%p offset=%lld eof=%d\n", 1224 (void *)vp, uiop->uio_loffset, myeof)); 1225 return (error); 1226 } 1227 1228 static int 1229 auto_symlink( 1230 vnode_t *dvp, 1231 char *lnknm, /* new entry */ 1232 vattr_t *tva, 1233 char *tnm, /* existing entry */ 1234 cred_t *cred, 1235 caller_context_t *ct, 1236 int flags) 1237 { 1238 vnode_t *newvp; 1239 int error; 1240 1241 AUTOFS_DPRINT((4, "auto_symlink: dvp=%p lnknm=%s tnm=%s\n", 1242 (void *)dvp, lnknm, tnm)); 1243 1244 if (error = auto_trigger_mount(dvp, cred, &newvp)) 1245 goto done; 1246 1247 if (newvp != NULL) { 1248 /* 1249 * Node is mounted on. 1250 */ 1251 if (vn_is_readonly(newvp)) 1252 error = EROFS; 1253 else 1254 error = VOP_SYMLINK(newvp, lnknm, tva, tnm, cred, 1255 ct, flags); 1256 VN_RELE(newvp); 1257 } else 1258 error = ENOSYS; 1259 1260 done: 1261 AUTOFS_DPRINT((5, "auto_symlink: error=%d\n", error)); 1262 return (error); 1263 } 1264 1265 /* ARGSUSED */ 1266 static int 1267 auto_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr, caller_context_t *ct) 1268 { 1269 fnnode_t *fnp = vntofn(vp); 1270 int error; 1271 timestruc_t now; 1272 1273 AUTOFS_DPRINT((4, "auto_readlink: vp=%p\n", (void *)vp)); 1274 1275 gethrestime(&now); 1276 fnp->fn_ref_time = now.tv_sec; 1277 1278 if (vp->v_type != VLNK) 1279 error = EINVAL; 1280 else { 1281 ASSERT(!(fnp->fn_flags & (MF_INPROG | MF_LOOKUP))); 1282 fnp->fn_atime = now; 1283 error = uiomove(fnp->fn_symlink, MIN(fnp->fn_symlinklen, 1284 uiop->uio_resid), UIO_READ, uiop); 1285 } 1286 1287 AUTOFS_DPRINT((5, "auto_readlink: error=%d\n", error)); 1288 return (error); 1289 } 1290 1291 /* ARGSUSED */ 1292 static int 1293 auto_fsync(vnode_t *cp, int syncflag, cred_t *cred, caller_context_t *ct) 1294 { 1295 return (0); 1296 } 1297 1298 /* ARGSUSED */ 1299 static void 1300 auto_inactive(vnode_t *vp, cred_t *cred, caller_context_t *ct) 1301 { 1302 fnnode_t *fnp = vntofn(vp); 1303 fnnode_t *dfnp = fnp->fn_parent; 1304 int count; 1305 1306 AUTOFS_DPRINT((4, "auto_inactive: vp=%p v_count=%u fn_link=%d\n", 1307 (void *)vp, vp->v_count, fnp->fn_linkcnt)); 1308 1309 /* 1310 * The rwlock should not be already held by this thread. 1311 * The assert relies on the fact that the owner field is cleared 1312 * when the lock is released. 1313 */ 1314 ASSERT(dfnp != NULL); 1315 ASSERT(rw_owner(&dfnp->fn_rwlock) != curthread); 1316 rw_enter(&dfnp->fn_rwlock, RW_WRITER); 1317 mutex_enter(&vp->v_lock); 1318 ASSERT(vp->v_count > 0); 1319 count = --vp->v_count; 1320 mutex_exit(&vp->v_lock); 1321 if (count == 0) { 1322 /* 1323 * Free only if node has no subdirectories. 1324 */ 1325 if (fnp->fn_linkcnt == 1) { 1326 auto_disconnect(dfnp, fnp); 1327 rw_exit(&dfnp->fn_rwlock); 1328 auto_freefnnode(fnp); 1329 AUTOFS_DPRINT((5, "auto_inactive: (exit) vp=%p freed\n", 1330 (void *)vp)); 1331 return; 1332 } 1333 } 1334 rw_exit(&dfnp->fn_rwlock); 1335 1336 AUTOFS_DPRINT((5, "auto_inactive: (exit) vp=%p v_count=%u fn_link=%d\n", 1337 (void *)vp, vp->v_count, fnp->fn_linkcnt)); 1338 } 1339 1340 /* ARGSUSED2 */ 1341 static int 1342 auto_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct) 1343 { 1344 fnnode_t *fnp = vntofn(vp); 1345 if (write_lock) 1346 rw_enter(&fnp->fn_rwlock, RW_WRITER); 1347 else 1348 rw_enter(&fnp->fn_rwlock, RW_READER); 1349 return (write_lock); 1350 } 1351 1352 /* ARGSUSED */ 1353 static void 1354 auto_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct) 1355 { 1356 fnnode_t *fnp = vntofn(vp); 1357 rw_exit(&fnp->fn_rwlock); 1358 } 1359 1360 1361 /* ARGSUSED */ 1362 static int 1363 auto_seek( 1364 struct vnode *vp, 1365 offset_t ooff, 1366 offset_t *noffp, 1367 caller_context_t *ct) 1368 { 1369 /* 1370 * Return 0 unconditionally, since we expect 1371 * a VDIR all the time 1372 */ 1373 return (0); 1374 } 1375 1376 /* 1377 * Triggers the mount if needed. If the mount has been triggered by 1378 * another thread, it will wait for its return status, and return it. 1379 * Whether the mount is triggered by this thread, another thread, or 1380 * if the vnode was already covered, '*newvp' is a 1381 * VN_HELD vnode pointing to the root of the filesystem covering 'vp'. 1382 * If the node is not mounted on, and should not be mounted on, '*newvp' 1383 * will be NULL. 1384 * The calling routine may use '*newvp' to do the filesystem jump. 1385 */ 1386 static int 1387 auto_trigger_mount(vnode_t *vp, cred_t *cred, vnode_t **newvp) 1388 { 1389 fnnode_t *fnp = vntofn(vp); 1390 fninfo_t *fnip = vfstofni(vp->v_vfsp); 1391 vnode_t *dvp; 1392 vfs_t *vfsp; 1393 int delayed_ind; 1394 char name[AUTOFS_MAXPATHLEN]; 1395 int error; 1396 1397 AUTOFS_DPRINT((4, "auto_trigger_mount: vp=%p\n", (void *)vp)); 1398 1399 *newvp = NULL; 1400 1401 /* 1402 * Cross-zone mount triggering is disallowed. 1403 */ 1404 if (fnip->fi_zoneid != getzoneid()) 1405 return (EPERM); /* Not owner of mount */ 1406 1407 retry: 1408 error = 0; 1409 delayed_ind = 0; 1410 mutex_enter(&fnp->fn_lock); 1411 while (fnp->fn_flags & (MF_LOOKUP | MF_INPROG)) { 1412 /* 1413 * Mount or lookup in progress, 1414 * wait for it before proceeding. 1415 */ 1416 mutex_exit(&fnp->fn_lock); 1417 error = auto_wait4mount(fnp); 1418 if (error == AUTOFS_SHUTDOWN) { 1419 error = 0; 1420 goto done; 1421 } 1422 if (error && error != EAGAIN) 1423 goto done; 1424 error = 0; 1425 mutex_enter(&fnp->fn_lock); 1426 } 1427 1428 /* 1429 * If the vfslock can't be acquired for the first time. 1430 * drop the fn_lock and retry next time in blocking mode. 1431 */ 1432 if (vn_vfswlock(vp)) { 1433 /* 1434 * Lock held by another thread. 1435 * Perform blocking by dropping the 1436 * fn_lock. 1437 */ 1438 mutex_exit(&fnp->fn_lock); 1439 error = vn_vfswlock_wait(vp); 1440 if (error) 1441 goto done; 1442 /* 1443 * Because fn_lock wasn't held, the state 1444 * of the trigger node might have changed. 1445 * Need to run through the checks on trigger 1446 * node again. 1447 */ 1448 vn_vfsunlock(vp); 1449 goto retry; 1450 } 1451 1452 vfsp = vn_mountedvfs(vp); 1453 if (vfsp != NULL) { 1454 mutex_exit(&fnp->fn_lock); 1455 error = VFS_ROOT(vfsp, newvp); 1456 vn_vfsunlock(vp); 1457 goto done; 1458 } else { 1459 vn_vfsunlock(vp); 1460 if ((fnp->fn_flags & MF_MOUNTPOINT) && 1461 fnp->fn_trigger != NULL) { 1462 ASSERT(fnp->fn_dirents == NULL); 1463 mutex_exit(&fnp->fn_lock); 1464 /* 1465 * The filesystem that used to sit here has been 1466 * forcibly unmounted. Do our best to recover. 1467 * Try to unmount autofs subtree below this node 1468 * and retry the action. 1469 */ 1470 if (unmount_subtree(fnp, B_TRUE) != 0) { 1471 error = EIO; 1472 goto done; 1473 } 1474 goto retry; 1475 } 1476 } 1477 1478 ASSERT(vp->v_type == VDIR); 1479 dvp = fntovn(fnp->fn_parent); 1480 1481 if ((fnp->fn_dirents == NULL) && 1482 ((fnip->fi_flags & MF_DIRECT) == 0) && 1483 ((vp->v_flag & VROOT) == 0) && 1484 (dvp->v_flag & VROOT)) { 1485 /* 1486 * If the parent of this node is the root of an indirect 1487 * AUTOFS filesystem, this node is remountable. 1488 */ 1489 delayed_ind = 1; 1490 } 1491 1492 if (delayed_ind || 1493 ((fnip->fi_flags & MF_DIRECT) && (fnp->fn_dirents == NULL))) { 1494 /* 1495 * Trigger mount since: 1496 * direct mountpoint with no subdirs or 1497 * delayed indirect. 1498 */ 1499 AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG); 1500 fnp->fn_error = 0; 1501 mutex_exit(&fnp->fn_lock); 1502 if (delayed_ind) 1503 (void) strcpy(name, fnp->fn_name); 1504 else 1505 (void) strcpy(name, "."); 1506 fnp->fn_ref_time = gethrestime_sec(); 1507 auto_new_mount_thread(fnp, name, cred); 1508 /* 1509 * At this point we're simply another thread waiting 1510 * for the mount to finish. 1511 */ 1512 error = auto_wait4mount(fnp); 1513 if (error == EAGAIN) 1514 goto retry; 1515 if (error == AUTOFS_SHUTDOWN) { 1516 error = 0; 1517 goto done; 1518 } 1519 if (error == 0) { 1520 if (error = vn_vfsrlock_wait(vp)) 1521 goto done; 1522 /* Reacquire after dropping locks */ 1523 vfsp = vn_mountedvfs(vp); 1524 if (vfsp != NULL) { 1525 error = VFS_ROOT(vfsp, newvp); 1526 vn_vfsunlock(vp); 1527 } else { 1528 vn_vfsunlock(vp); 1529 goto retry; 1530 } 1531 } 1532 } else 1533 mutex_exit(&fnp->fn_lock); 1534 1535 done: 1536 AUTOFS_DPRINT((5, "auto_trigger_mount: error=%d\n", error)); 1537 return (error); 1538 }