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