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