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