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 2006 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/errno.h> 30 #include <sys/proc.h> 31 #include <sys/disp.h> 32 #include <sys/vfs.h> 33 #include <sys/vnode.h> 34 #include <sys/uio.h> 35 #include <sys/kmem.h> 36 #include <sys/cred.h> 37 #include <sys/statvfs.h> 38 #include <sys/mount.h> 39 #include <sys/tiuser.h> 40 #include <sys/cmn_err.h> 41 #include <sys/debug.h> 42 #include <sys/systm.h> 43 #include <sys/sysmacros.h> 44 #include <sys/pathname.h> 45 #include <rpc/types.h> 46 #include <rpc/auth.h> 47 #include <rpc/clnt.h> 48 #include <fs/fs_subr.h> 49 #include <sys/fs/autofs.h> 50 #include <rpcsvc/autofs_prot.h> 51 #include <sys/modctl.h> 52 #include <sys/mntent.h> 53 #include <sys/policy.h> 54 #include <sys/zone.h> 55 56 static int autofs_init(int, char *); 57 58 static major_t autofs_major; 59 static minor_t autofs_minor; 60 static kmutex_t autofs_minor_lock; 61 62 zone_key_t autofs_key; 63 64 static mntopts_t auto_mntopts; 65 66 /* 67 * The AUTOFS system call. 68 */ 69 static struct sysent autofssysent = { 70 2, 71 SE_32RVAL1 | SE_ARGC | SE_NOUNLOAD, 72 autofssys 73 }; 74 75 static struct modlsys modlsys = { 76 &mod_syscallops, 77 "AUTOFS syscall", 78 &autofssysent 79 }; 80 81 #ifdef _SYSCALL32_IMPL 82 static struct modlsys modlsys32 = { 83 &mod_syscallops32, 84 "AUTOFS syscall (32-bit)", 85 &autofssysent 86 }; 87 #endif /* _SYSCALL32_IMPL */ 88 89 static vfsdef_t vfw = { 90 VFSDEF_VERSION, 91 "autofs", 92 autofs_init, 93 VSW_HASPROTO|VSW_CANRWRO|VSW_CANREMOUNT|VSW_STATS, 94 &auto_mntopts 95 }; 96 97 /* 98 * Module linkage information for the kernel. 99 */ 100 static struct modlfs modlfs = { 101 &mod_fsops, "filesystem for autofs", &vfw 102 }; 103 104 static struct modlinkage modlinkage = { 105 MODREV_1, 106 &modlsys, 107 #ifdef _SYSCALL32_IMPL 108 &modlsys32, 109 #endif 110 &modlfs, 111 NULL 112 }; 113 114 /* 115 * There are not enough stubs for rpcmod so we must force load it 116 */ 117 char _depends_on[] = "strmod/rpcmod misc/rpcsec fs/mntfs"; 118 119 /* 120 * This is the module initialization routine. 121 */ 122 int 123 _init(void) 124 { 125 return (mod_install(&modlinkage)); 126 } 127 128 int 129 _fini(void) 130 { 131 /* 132 * Don't allow the autofs module to be unloaded for now. 133 */ 134 return (EBUSY); 135 } 136 137 int 138 _info(struct modinfo *modinfop) 139 { 140 return (mod_info(&modlinkage, modinfop)); 141 } 142 143 static int autofs_fstype; 144 145 /* 146 * autofs VFS operations 147 */ 148 static int auto_mount(vfs_t *, vnode_t *, struct mounta *, cred_t *); 149 static int auto_unmount(vfs_t *, int, cred_t *); 150 static int auto_root(vfs_t *, vnode_t **); 151 static int auto_statvfs(vfs_t *, struct statvfs64 *); 152 153 /* 154 * Auto Mount options table 155 */ 156 157 static char *direct_cancel[] = { MNTOPT_INDIRECT, NULL }; 158 static char *indirect_cancel[] = { MNTOPT_DIRECT, NULL }; 159 static char *browse_cancel[] = { MNTOPT_NOBROWSE, NULL }; 160 static char *nobrowse_cancel[] = { MNTOPT_BROWSE, NULL }; 161 162 static mntopt_t mntopts[] = { 163 /* 164 * option name cancel options default arg flags 165 */ 166 { MNTOPT_DIRECT, direct_cancel, NULL, 0, 167 NULL }, 168 { MNTOPT_INDIRECT, indirect_cancel, NULL, 0, 169 NULL }, 170 { MNTOPT_IGNORE, NULL, NULL, 171 MO_DEFAULT|MO_TAG, NULL }, 172 { "nest", NULL, NULL, MO_TAG, 173 NULL }, 174 { MNTOPT_BROWSE, browse_cancel, NULL, MO_TAG, 175 NULL }, 176 { MNTOPT_NOBROWSE, nobrowse_cancel, NULL, MO_TAG, 177 NULL }, 178 { MNTOPT_RESTRICT, NULL, NULL, MO_TAG, 179 NULL }, 180 }; 181 182 static mntopts_t auto_mntopts = { 183 sizeof (mntopts) / sizeof (mntopt_t), 184 mntopts 185 }; 186 187 /*ARGSUSED*/ 188 static void 189 autofs_zone_destructor(zoneid_t zoneid, void *arg) 190 { 191 struct autofs_globals *fngp = arg; 192 vnode_t *vp; 193 194 if (fngp == NULL) 195 return; 196 ASSERT(fngp->fng_fnnode_count == 1); 197 ASSERT(fngp->fng_unmount_threads == 0); 198 /* 199 * vn_alloc() initialized the rootnode with a count of 1; we need to 200 * make this 0 to placate auto_freefnnode(). 201 */ 202 vp = fntovn(fngp->fng_rootfnnodep); 203 ASSERT(vp->v_count == 1); 204 vp->v_count--; 205 auto_freefnnode(fngp->fng_rootfnnodep); 206 mutex_destroy(&fngp->fng_unmount_threads_lock); 207 kmem_free(fngp, sizeof (*fngp)); 208 } 209 210 /* 211 * rootfnnodep is allocated here. Its sole purpose is to provide 212 * read/write locking for top level fnnodes. This object is 213 * persistent and will not be deallocated until the zone is destroyed. 214 * 215 * The current zone is implied as the zone of interest, since we will be 216 * calling zthread_create() which must be called from the correct zone. 217 */ 218 static struct autofs_globals * 219 autofs_zone_init(void) 220 { 221 char rootname[sizeof ("root_fnnode_zone_") + ZONEID_WIDTH]; 222 struct autofs_globals *fngp; 223 zoneid_t zoneid = getzoneid(); 224 225 fngp = kmem_zalloc(sizeof (*fngp), KM_SLEEP); 226 (void) snprintf(rootname, sizeof (rootname), "root_fnnode_zone_%d", 227 zoneid); 228 fngp->fng_rootfnnodep = auto_makefnnode(VNON, NULL, rootname, CRED(), 229 fngp); 230 /* 231 * Don't need to hold fng_rootfnnodep as it's never really used for 232 * anything. 233 */ 234 fngp->fng_fnnode_count = 1; 235 fngp->fng_printed_not_running_msg = 0; 236 fngp->fng_zoneid = zoneid; 237 mutex_init(&fngp->fng_unmount_threads_lock, NULL, MUTEX_DEFAULT, 238 NULL); 239 fngp->fng_unmount_threads = 0; 240 241 /* 242 * Start the unmounter thread for this zone. 243 */ 244 (void) zthread_create(NULL, 0, auto_do_unmount, fngp, 0, minclsyspri); 245 return (fngp); 246 } 247 248 int 249 autofs_init(int fstype, char *name) 250 { 251 static const fs_operation_def_t auto_vfsops_template[] = { 252 VFSNAME_MOUNT, auto_mount, 253 VFSNAME_UNMOUNT, auto_unmount, 254 VFSNAME_ROOT, auto_root, 255 VFSNAME_STATVFS, auto_statvfs, 256 NULL, NULL 257 }; 258 int error; 259 260 autofs_fstype = fstype; 261 ASSERT(autofs_fstype != 0); 262 /* 263 * Associate VFS ops vector with this fstype 264 */ 265 error = vfs_setfsops(fstype, auto_vfsops_template, NULL); 266 if (error != 0) { 267 cmn_err(CE_WARN, "autofs_init: bad vfs ops template"); 268 return (error); 269 } 270 271 error = vn_make_ops(name, auto_vnodeops_template, &auto_vnodeops); 272 if (error != 0) { 273 (void) vfs_freevfsops_by_type(fstype); 274 cmn_err(CE_WARN, "autofs_init: bad vnode ops template"); 275 return (error); 276 } 277 278 mutex_init(&autofs_minor_lock, NULL, MUTEX_DEFAULT, NULL); 279 /* 280 * Assign unique major number for all autofs mounts 281 */ 282 if ((autofs_major = getudev()) == (major_t)-1) { 283 cmn_err(CE_WARN, 284 "autofs: autofs_init: can't get unique device number"); 285 mutex_destroy(&autofs_minor_lock); 286 return (1); 287 } 288 289 /* 290 * We'd like to be able to provide a constructor here, but we can't 291 * since it wants to zthread_create(), something it can't do in a ZSD 292 * constructor. 293 */ 294 zone_key_create(&autofs_key, NULL, NULL, autofs_zone_destructor); 295 296 return (0); 297 } 298 299 static char *restropts[] = { 300 RESTRICTED_MNTOPTS 301 }; 302 303 /* 304 * This routine adds those options to the option string `buf' which are 305 * forced by secpolicy_fs_mount. If the automatic "security" options 306 * are set, the option string gets them added if they aren't already 307 * there. We search the string with "strstr" and make sure that 308 * the string we find is bracketed with <start|",">MNTOPT<","|"\0"> 309 * 310 * This is one half of the option inheritence algorithm which 311 * implements the "restrict" option. The other half is implemented 312 * in automountd; it takes its cue from the options we add here. 313 */ 314 static int 315 autofs_restrict_opts(struct vfs *vfsp, char *buf, size_t maxlen, size_t *curlen) 316 { 317 int i; 318 char *p; 319 size_t len = *curlen - 1; 320 321 /* Unrestricted */ 322 if (!vfs_optionisset(vfsp, restropts[0], NULL)) 323 return (0); 324 325 for (i = 0; i < sizeof (restropts)/sizeof (restropts[0]); i++) { 326 size_t olen = strlen(restropts[i]); 327 328 /* Add "restrict" always and the others insofar set */ 329 if ((i == 0 || vfs_optionisset(vfsp, restropts[i], NULL)) && 330 ((p = strstr(buf, restropts[i])) == NULL || 331 !((p == buf || p[-1] == ',') && 332 (p[olen] == '\0' || p[olen] == ',')))) { 333 334 if (len + olen + 1 > maxlen) 335 return (-1); 336 337 if (*buf != '\0') 338 buf[len++] = ','; 339 (void) strcpy(&buf[len], restropts[i]); 340 len += olen; 341 } 342 } 343 *curlen = len + 1; 344 return (0); 345 } 346 347 /* ARGSUSED */ 348 static int 349 auto_mount(vfs_t *vfsp, vnode_t *vp, struct mounta *uap, cred_t *cr) 350 { 351 int error; 352 size_t len = 0; 353 struct autofs_args args; 354 fninfo_t *fnip = NULL; 355 vnode_t *rootvp = NULL; 356 fnnode_t *rootfnp = NULL; 357 char *data = uap->dataptr; 358 char datalen = uap->datalen; 359 dev_t autofs_dev; 360 char strbuff[MAXPATHLEN+1]; 361 vnode_t *kvp; 362 struct autofs_globals *fngp; 363 zone_t *zone = curproc->p_zone; 364 365 AUTOFS_DPRINT((4, "auto_mount: vfs %p vp %p\n", (void *)vfsp, 366 (void *)vp)); 367 368 if ((error = secpolicy_fs_mount(cr, vp, vfsp)) != 0) 369 return (EPERM); 370 371 if (zone == global_zone) { 372 zone_t *mntzone; 373 374 mntzone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt)); 375 ASSERT(mntzone != NULL); 376 zone_rele(mntzone); 377 if (mntzone != zone) { 378 return (EBUSY); 379 } 380 } 381 382 /* 383 * Stop the mount from going any further if the zone is going away. 384 */ 385 if (zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN) 386 return (EBUSY); 387 388 /* 389 * We need a lock to serialize this; minor_lock is as good as any. 390 */ 391 mutex_enter(&autofs_minor_lock); 392 if ((fngp = zone_getspecific(autofs_key, zone)) == NULL) { 393 fngp = autofs_zone_init(); 394 (void) zone_setspecific(autofs_key, zone, fngp); 395 } 396 mutex_exit(&autofs_minor_lock); 397 ASSERT(fngp != NULL); 398 399 /* 400 * Get arguments 401 */ 402 if (uap->flags & MS_SYSSPACE) { 403 if (datalen != sizeof (args)) 404 return (EINVAL); 405 error = kcopy(data, &args, sizeof (args)); 406 } else { 407 if (get_udatamodel() == DATAMODEL_NATIVE) { 408 if (datalen != sizeof (args)) 409 return (EINVAL); 410 error = copyin(data, &args, sizeof (args)); 411 } else { 412 struct autofs_args32 args32; 413 414 if (datalen != sizeof (args32)) 415 return (EINVAL); 416 error = copyin(data, &args32, sizeof (args32)); 417 418 args.addr.maxlen = args32.addr.maxlen; 419 args.addr.len = args32.addr.len; 420 args.addr.buf = (char *)(uintptr_t)args32.addr.buf; 421 args.path = (char *)(uintptr_t)args32.path; 422 args.opts = (char *)(uintptr_t)args32.opts; 423 args.map = (char *)(uintptr_t)args32.map; 424 args.subdir = (char *)(uintptr_t)args32.subdir; 425 args.key = (char *)(uintptr_t)args32.key; 426 args.mount_to = args32.mount_to; 427 args.rpc_to = args32.rpc_to; 428 args.direct = args32.direct; 429 } 430 } 431 if (error) 432 return (EFAULT); 433 434 /* 435 * For a remount, only update mount information 436 * i.e. default mount options, map name, etc. 437 */ 438 if (uap->flags & MS_REMOUNT) { 439 fnip = vfstofni(vfsp); 440 if (fnip == NULL) 441 return (EINVAL); 442 443 if (args.direct == 1) 444 fnip->fi_flags |= MF_DIRECT; 445 else 446 fnip->fi_flags &= ~MF_DIRECT; 447 fnip->fi_mount_to = args.mount_to; 448 fnip->fi_rpc_to = args.rpc_to; 449 450 /* 451 * Get default options 452 */ 453 if (uap->flags & MS_SYSSPACE) 454 error = copystr(args.opts, strbuff, sizeof (strbuff), 455 &len); 456 else 457 error = copyinstr(args.opts, strbuff, sizeof (strbuff), 458 &len); 459 if (error) 460 return (EFAULT); 461 462 if (autofs_restrict_opts(vfsp, strbuff, sizeof (strbuff), &len) 463 != 0) { 464 return (EFAULT); 465 } 466 467 kmem_free(fnip->fi_opts, fnip->fi_optslen); 468 fnip->fi_opts = kmem_alloc(len, KM_SLEEP); 469 fnip->fi_optslen = (int)len; 470 bcopy(strbuff, fnip->fi_opts, len); 471 472 /* 473 * Get context/map name 474 */ 475 if (uap->flags & MS_SYSSPACE) 476 error = copystr(args.map, strbuff, sizeof (strbuff), 477 &len); 478 else 479 error = copyinstr(args.map, strbuff, sizeof (strbuff), 480 &len); 481 if (error) 482 return (EFAULT); 483 484 kmem_free(fnip->fi_map, fnip->fi_maplen); 485 fnip->fi_map = kmem_alloc(len, KM_SLEEP); 486 fnip->fi_maplen = (int)len; 487 bcopy(strbuff, fnip->fi_map, len); 488 489 return (0); 490 } 491 492 /* 493 * Allocate fninfo struct and attach it to vfs 494 */ 495 fnip = kmem_zalloc(sizeof (*fnip), KM_SLEEP); 496 fnip->fi_mountvfs = vfsp; 497 498 fnip->fi_mount_to = args.mount_to; 499 fnip->fi_rpc_to = args.rpc_to; 500 fnip->fi_refcnt = 0; 501 vfsp->vfs_bsize = AUTOFS_BLOCKSIZE; 502 vfsp->vfs_fstype = autofs_fstype; 503 504 /* 505 * Assign a unique device id to the mount 506 */ 507 mutex_enter(&autofs_minor_lock); 508 do { 509 autofs_minor = (autofs_minor + 1) & L_MAXMIN32; 510 autofs_dev = makedevice(autofs_major, autofs_minor); 511 } while (vfs_devismounted(autofs_dev)); 512 mutex_exit(&autofs_minor_lock); 513 vfsp->vfs_dev = autofs_dev; 514 vfs_make_fsid(&vfsp->vfs_fsid, autofs_dev, autofs_fstype); 515 vfsp->vfs_data = (void *)fnip; 516 vfsp->vfs_bcount = 0; 517 518 /* 519 * Get daemon address 520 */ 521 fnip->fi_addr.len = args.addr.len; 522 fnip->fi_addr.maxlen = fnip->fi_addr.len; 523 fnip->fi_addr.buf = kmem_alloc(args.addr.len, KM_SLEEP); 524 if (uap->flags & MS_SYSSPACE) 525 error = kcopy(args.addr.buf, fnip->fi_addr.buf, args.addr.len); 526 else 527 error = copyin(args.addr.buf, fnip->fi_addr.buf, args.addr.len); 528 if (error) { 529 error = EFAULT; 530 goto errout; 531 } 532 533 fnip->fi_zoneid = getzoneid(); 534 /* 535 * Get path for mountpoint 536 */ 537 if (uap->flags & MS_SYSSPACE) 538 error = copystr(args.path, strbuff, sizeof (strbuff), &len); 539 else 540 error = copyinstr(args.path, strbuff, sizeof (strbuff), &len); 541 if (error) { 542 error = EFAULT; 543 goto errout; 544 } 545 fnip->fi_path = kmem_alloc(len, KM_SLEEP); 546 fnip->fi_pathlen = (int)len; 547 bcopy(strbuff, fnip->fi_path, len); 548 549 /* 550 * Get default options 551 */ 552 if (uap->flags & MS_SYSSPACE) 553 error = copystr(args.opts, strbuff, sizeof (strbuff), &len); 554 else 555 error = copyinstr(args.opts, strbuff, sizeof (strbuff), &len); 556 557 if (error != 0 || 558 autofs_restrict_opts(vfsp, strbuff, sizeof (strbuff), &len) != 0) { 559 error = EFAULT; 560 goto errout; 561 } 562 fnip->fi_opts = kmem_alloc(len, KM_SLEEP); 563 fnip->fi_optslen = (int)len; 564 bcopy(strbuff, fnip->fi_opts, len); 565 566 /* 567 * Get context/map name 568 */ 569 if (uap->flags & MS_SYSSPACE) 570 error = copystr(args.map, strbuff, sizeof (strbuff), &len); 571 else 572 error = copyinstr(args.map, strbuff, sizeof (strbuff), &len); 573 if (error) { 574 error = EFAULT; 575 goto errout; 576 } 577 fnip->fi_map = kmem_alloc(len, KM_SLEEP); 578 fnip->fi_maplen = (int)len; 579 bcopy(strbuff, fnip->fi_map, len); 580 581 /* 582 * Get subdirectory within map 583 */ 584 if (uap->flags & MS_SYSSPACE) 585 error = copystr(args.subdir, strbuff, sizeof (strbuff), &len); 586 else 587 error = copyinstr(args.subdir, strbuff, sizeof (strbuff), &len); 588 if (error) { 589 error = EFAULT; 590 goto errout; 591 } 592 fnip->fi_subdir = kmem_alloc(len, KM_SLEEP); 593 fnip->fi_subdirlen = (int)len; 594 bcopy(strbuff, fnip->fi_subdir, len); 595 596 /* 597 * Get the key 598 */ 599 if (uap->flags & MS_SYSSPACE) 600 error = copystr(args.key, strbuff, sizeof (strbuff), &len); 601 else 602 error = copyinstr(args.key, strbuff, sizeof (strbuff), &len); 603 if (error) { 604 error = EFAULT; 605 goto errout; 606 } 607 fnip->fi_key = kmem_alloc(len, KM_SLEEP); 608 fnip->fi_keylen = (int)len; 609 bcopy(strbuff, fnip->fi_key, len); 610 611 /* 612 * Is this a direct mount? 613 */ 614 if (args.direct == 1) 615 fnip->fi_flags |= MF_DIRECT; 616 617 /* 618 * Setup netconfig. 619 * Can I pass in knconf as mount argument? what 620 * happens when the daemon gets restarted? 621 */ 622 if ((error = lookupname("/dev/ticotsord", UIO_SYSSPACE, FOLLOW, 623 NULLVPP, &kvp)) != 0) { 624 cmn_err(CE_WARN, "autofs: lookupname: %d", error); 625 goto errout; 626 } 627 628 fnip->fi_knconf.knc_rdev = kvp->v_rdev; 629 fnip->fi_knconf.knc_protofmly = NC_LOOPBACK; 630 fnip->fi_knconf.knc_semantics = NC_TPI_COTS_ORD; 631 VN_RELE(kvp); 632 633 /* 634 * Make the root vnode 635 */ 636 rootfnp = auto_makefnnode(VDIR, vfsp, fnip->fi_path, cr, fngp); 637 if (rootfnp == NULL) { 638 error = ENOMEM; 639 goto errout; 640 } 641 rootvp = fntovn(rootfnp); 642 643 rootvp->v_flag |= VROOT; 644 rootfnp->fn_mode = AUTOFS_MODE; 645 rootfnp->fn_parent = rootfnp; 646 /* account for ".." entry */ 647 rootfnp->fn_linkcnt = rootfnp->fn_size = 1; 648 fnip->fi_rootvp = rootvp; 649 650 /* 651 * Add to list of top level AUTOFS' if it is being mounted by 652 * a user level process. 653 */ 654 if (!(uap->flags & MS_SYSSPACE)) { 655 rw_enter(&fngp->fng_rootfnnodep->fn_rwlock, RW_WRITER); 656 rootfnp->fn_parent = fngp->fng_rootfnnodep; 657 rootfnp->fn_next = fngp->fng_rootfnnodep->fn_dirents; 658 fngp->fng_rootfnnodep->fn_dirents = rootfnp; 659 rw_exit(&fngp->fng_rootfnnodep->fn_rwlock); 660 } 661 662 AUTOFS_DPRINT((5, "auto_mount: vfs %p root %p fnip %p return %d\n", 663 (void *)vfsp, (void *)rootvp, (void *)fnip, error)); 664 665 return (0); 666 667 errout: 668 ASSERT(fnip != NULL); 669 ASSERT((uap->flags & MS_REMOUNT) == 0); 670 671 if (fnip->fi_addr.buf != NULL) 672 kmem_free(fnip->fi_addr.buf, fnip->fi_addr.len); 673 if (fnip->fi_path != NULL) 674 kmem_free(fnip->fi_path, fnip->fi_pathlen); 675 if (fnip->fi_opts != NULL) 676 kmem_free(fnip->fi_opts, fnip->fi_optslen); 677 if (fnip->fi_map != NULL) 678 kmem_free(fnip->fi_map, fnip->fi_maplen); 679 if (fnip->fi_subdir != NULL) 680 kmem_free(fnip->fi_subdir, fnip->fi_subdirlen); 681 if (fnip->fi_key != NULL) 682 kmem_free(fnip->fi_key, fnip->fi_keylen); 683 kmem_free(fnip, sizeof (*fnip)); 684 685 AUTOFS_DPRINT((5, "auto_mount: vfs %p root %p fnip %p return %d\n", 686 (void *)vfsp, (void *)rootvp, (void *)fnip, error)); 687 688 return (error); 689 } 690 691 /* ARGSUSED */ 692 static int 693 auto_unmount(vfs_t *vfsp, int flag, cred_t *cr) 694 { 695 fninfo_t *fnip; 696 vnode_t *rvp; 697 fnnode_t *rfnp, *fnp, *pfnp; 698 fnnode_t *myrootfnnodep; 699 700 fnip = vfstofni(vfsp); 701 AUTOFS_DPRINT((4, "auto_unmount vfsp %p fnip %p\n", (void *)vfsp, 702 (void *)fnip)); 703 704 if (secpolicy_fs_unmount(cr, vfsp) != 0) 705 return (EPERM); 706 /* 707 * forced unmount is not supported by this file system 708 * and thus, ENOTSUP, is being returned. 709 */ 710 if (flag & MS_FORCE) 711 return (ENOTSUP); 712 713 ASSERT(vn_vfswlock_held(vfsp->vfs_vnodecovered)); 714 rvp = fnip->fi_rootvp; 715 rfnp = vntofn(rvp); 716 717 if (rvp->v_count > 1 || rfnp->fn_dirents != NULL) 718 return (EBUSY); 719 720 /* 721 * The root vnode is on the linked list of root fnnodes only if 722 * this was not a trigger node. Since we have no way of knowing, 723 * if we don't find it, then we assume it was a trigger node. 724 */ 725 myrootfnnodep = rfnp->fn_globals->fng_rootfnnodep; 726 pfnp = NULL; 727 rw_enter(&myrootfnnodep->fn_rwlock, RW_WRITER); 728 fnp = myrootfnnodep->fn_dirents; 729 while (fnp != NULL) { 730 if (fnp == rfnp) { 731 /* 732 * A check here is made to see if rvp is busy. If 733 * so, return EBUSY. Otherwise proceed with 734 * disconnecting it from the list. 735 */ 736 if (rvp->v_count > 1 || rfnp->fn_dirents != NULL) { 737 rw_exit(&myrootfnnodep->fn_rwlock); 738 return (EBUSY); 739 } 740 if (pfnp) 741 pfnp->fn_next = fnp->fn_next; 742 else 743 myrootfnnodep->fn_dirents = fnp->fn_next; 744 fnp->fn_next = NULL; 745 break; 746 } 747 pfnp = fnp; 748 fnp = fnp->fn_next; 749 } 750 rw_exit(&myrootfnnodep->fn_rwlock); 751 752 ASSERT(rvp->v_count == 1); 753 ASSERT(rfnp->fn_size == 1); 754 ASSERT(rfnp->fn_linkcnt == 1); 755 /* 756 * The following drops linkcnt to 0, therefore the disconnect is 757 * not attempted when auto_inactive() is called by 758 * vn_rele(). This is necessary because we have nothing to get 759 * disconnected from since we're the root of the filesystem. As a 760 * side effect the node is not freed, therefore I should free the 761 * node here. 762 * 763 * XXX - I really need to think of a better way of doing this. 764 */ 765 rfnp->fn_size--; 766 rfnp->fn_linkcnt--; 767 768 /* 769 * release of last reference causes node 770 * to be freed 771 */ 772 VN_RELE(rvp); 773 rfnp->fn_parent = NULL; 774 775 auto_freefnnode(rfnp); 776 777 kmem_free(fnip->fi_addr.buf, fnip->fi_addr.len); 778 kmem_free(fnip->fi_path, fnip->fi_pathlen); 779 kmem_free(fnip->fi_map, fnip->fi_maplen); 780 kmem_free(fnip->fi_subdir, fnip->fi_subdirlen); 781 kmem_free(fnip->fi_key, fnip->fi_keylen); 782 kmem_free(fnip->fi_opts, fnip->fi_optslen); 783 kmem_free(fnip, sizeof (*fnip)); 784 AUTOFS_DPRINT((5, "auto_unmount: return=0\n")); 785 786 return (0); 787 } 788 789 790 /* 791 * find root of autofs 792 */ 793 static int 794 auto_root(vfs_t *vfsp, vnode_t **vpp) 795 { 796 *vpp = (vnode_t *)vfstofni(vfsp)->fi_rootvp; 797 VN_HOLD(*vpp); 798 799 AUTOFS_DPRINT((5, "auto_root: vfs %p, *vpp %p\n", (void *)vfsp, 800 (void *)*vpp)); 801 return (0); 802 } 803 804 /* 805 * Get file system statistics. 806 */ 807 static int 808 auto_statvfs(vfs_t *vfsp, struct statvfs64 *sbp) 809 { 810 dev32_t d32; 811 812 AUTOFS_DPRINT((4, "auto_statvfs %p\n", (void *)vfsp)); 813 814 bzero(sbp, sizeof (*sbp)); 815 sbp->f_bsize = vfsp->vfs_bsize; 816 sbp->f_frsize = sbp->f_bsize; 817 sbp->f_blocks = (fsblkcnt64_t)0; 818 sbp->f_bfree = (fsblkcnt64_t)0; 819 sbp->f_bavail = (fsblkcnt64_t)0; 820 sbp->f_files = (fsfilcnt64_t)0; 821 sbp->f_ffree = (fsfilcnt64_t)0; 822 sbp->f_favail = (fsfilcnt64_t)0; 823 (void) cmpldev(&d32, vfsp->vfs_dev); 824 sbp->f_fsid = d32; 825 (void) strcpy(sbp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 826 sbp->f_flag = vf_to_stf(vfsp->vfs_flag); 827 sbp->f_namemax = MAXNAMELEN; 828 (void) strcpy(sbp->f_fstr, MNTTYPE_AUTOFS); 829 830 return (0); 831 } 832