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