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/errno.h> 30 #include <sys/proc.h> 31 #include <sys/disp.h> 32 #include <sys/vfs.h> 33 #include <sys/vfs_opreg.h> 34 #include <sys/vnode.h> 35 #include <sys/uio.h> 36 #include <sys/kmem.h> 37 #include <sys/cred.h> 38 #include <sys/statvfs.h> 39 #include <sys/mount.h> 40 #include <sys/tiuser.h> 41 #include <sys/cmn_err.h> 42 #include <sys/debug.h> 43 #include <sys/systm.h> 44 #include <sys/sysmacros.h> 45 #include <sys/pathname.h> 46 #include <rpc/types.h> 47 #include <rpc/auth.h> 48 #include <rpc/clnt.h> 49 #include <fs/fs_subr.h> 50 #include <sys/fs/autofs.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 61 kmutex_t autofs_minor_lock; 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 &modlfs, 107 &modlsys, 108 #ifdef _SYSCALL32_IMPL 109 &modlsys32, 110 #endif 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 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 mutex_init(&fngp->fng_autofs_daemon_lock, NULL, MUTEX_DEFAULT, NULL); 242 243 /* 244 * Start the unmounter thread for this zone. 245 */ 246 (void) zthread_create(NULL, 0, auto_do_unmount, fngp, 0, minclsyspri); 247 return (fngp); 248 } 249 250 int 251 autofs_init(int fstype, char *name) 252 { 253 static const fs_operation_def_t auto_vfsops_template[] = { 254 VFSNAME_MOUNT, { .vfs_mount = auto_mount }, 255 VFSNAME_UNMOUNT, { .vfs_unmount = auto_unmount }, 256 VFSNAME_ROOT, { .vfs_root = auto_root }, 257 VFSNAME_STATVFS, { .vfs_statvfs = auto_statvfs }, 258 NULL, NULL 259 }; 260 int error; 261 262 autofs_fstype = fstype; 263 ASSERT(autofs_fstype != 0); 264 /* 265 * Associate VFS ops vector with this fstype 266 */ 267 error = vfs_setfsops(fstype, auto_vfsops_template, NULL); 268 if (error != 0) { 269 cmn_err(CE_WARN, "autofs_init: bad vfs ops template"); 270 return (error); 271 } 272 273 error = vn_make_ops(name, auto_vnodeops_template, &auto_vnodeops); 274 if (error != 0) { 275 (void) vfs_freevfsops_by_type(fstype); 276 cmn_err(CE_WARN, "autofs_init: bad vnode ops template"); 277 return (error); 278 } 279 280 mutex_init(&autofs_minor_lock, NULL, MUTEX_DEFAULT, NULL); 281 /* 282 * Assign unique major number for all autofs mounts 283 */ 284 if ((autofs_major = getudev()) == (major_t)-1) { 285 cmn_err(CE_WARN, 286 "autofs: autofs_init: can't get unique device number"); 287 mutex_destroy(&autofs_minor_lock); 288 return (1); 289 } 290 291 /* 292 * We'd like to be able to provide a constructor here, but we can't 293 * since it wants to zthread_create(), something it can't do in a ZSD 294 * constructor. 295 */ 296 zone_key_create(&autofs_key, NULL, NULL, autofs_zone_destructor); 297 298 return (0); 299 } 300 301 static char *restropts[] = { 302 RESTRICTED_MNTOPTS 303 }; 304 305 /* 306 * This routine adds those options to the option string `buf' which are 307 * forced by secpolicy_fs_mount. If the automatic "security" options 308 * are set, the option string gets them added if they aren't already 309 * there. We search the string with "strstr" and make sure that 310 * the string we find is bracketed with <start|",">MNTOPT<","|"\0"> 311 * 312 * This is one half of the option inheritence algorithm which 313 * implements the "restrict" option. The other half is implemented 314 * in automountd; it takes its cue from the options we add here. 315 */ 316 static int 317 autofs_restrict_opts(struct vfs *vfsp, char *buf, size_t maxlen, size_t *curlen) 318 { 319 int i; 320 char *p; 321 size_t len = *curlen - 1; 322 323 /* Unrestricted */ 324 if (!vfs_optionisset(vfsp, restropts[0], NULL)) 325 return (0); 326 327 for (i = 0; i < sizeof (restropts)/sizeof (restropts[0]); i++) { 328 size_t olen = strlen(restropts[i]); 329 330 /* Add "restrict" always and the others insofar set */ 331 if ((i == 0 || vfs_optionisset(vfsp, restropts[i], NULL)) && 332 ((p = strstr(buf, restropts[i])) == NULL || 333 !((p == buf || p[-1] == ',') && 334 (p[olen] == '\0' || p[olen] == ',')))) { 335 336 if (len + olen + 1 > maxlen) 337 return (-1); 338 339 if (*buf != '\0') 340 buf[len++] = ','; 341 (void) strcpy(&buf[len], restropts[i]); 342 len += olen; 343 } 344 } 345 *curlen = len + 1; 346 return (0); 347 } 348 349 /* ARGSUSED */ 350 static int 351 auto_mount(vfs_t *vfsp, vnode_t *vp, struct mounta *uap, cred_t *cr) 352 { 353 int error; 354 size_t len = 0; 355 autofs_args args; 356 fninfo_t *fnip = NULL; 357 vnode_t *rootvp = NULL; 358 fnnode_t *rootfnp = NULL; 359 char *data = uap->dataptr; 360 char datalen = uap->datalen; 361 dev_t autofs_dev; 362 char strbuff[MAXPATHLEN + 1]; 363 vnode_t *kvp; 364 struct autofs_globals *fngp; 365 zone_t *zone = curproc->p_zone; 366 367 AUTOFS_DPRINT((4, "auto_mount: vfs %p vp %p\n", (void *)vfsp, 368 (void *)vp)); 369 370 if ((error = secpolicy_fs_mount(cr, vp, vfsp)) != 0) 371 return (EPERM); 372 373 if (zone == global_zone) { 374 zone_t *mntzone; 375 376 mntzone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt)); 377 ASSERT(mntzone != NULL); 378 zone_rele(mntzone); 379 if (mntzone != zone) { 380 return (EBUSY); 381 } 382 } 383 384 /* 385 * Stop the mount from going any further if the zone is going away. 386 */ 387 if (zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN) 388 return (EBUSY); 389 390 /* 391 * We need a lock to serialize this; minor_lock is as good as any. 392 */ 393 mutex_enter(&autofs_minor_lock); 394 if ((fngp = zone_getspecific(autofs_key, zone)) == NULL) { 395 fngp = autofs_zone_init(); 396 (void) zone_setspecific(autofs_key, zone, fngp); 397 } 398 mutex_exit(&autofs_minor_lock); 399 ASSERT(fngp != NULL); 400 401 /* 402 * Get arguments 403 */ 404 if (uap->flags & MS_SYSSPACE) { 405 if (datalen != sizeof (args)) 406 return (EINVAL); 407 error = kcopy(data, &args, sizeof (args)); 408 } else { 409 if (get_udatamodel() == DATAMODEL_NATIVE) { 410 if (datalen != sizeof (args)) 411 return (EINVAL); 412 error = copyin(data, &args, sizeof (args)); 413 } else { 414 struct autofs_args32 args32; 415 416 if (datalen != sizeof (args32)) 417 return (EINVAL); 418 error = copyin(data, &args32, sizeof (args32)); 419 420 args.addr.maxlen = args32.addr.maxlen; 421 args.addr.len = args32.addr.len; 422 args.addr.buf = (char *)(uintptr_t)args32.addr.buf; 423 args.path = (char *)(uintptr_t)args32.path; 424 args.opts = (char *)(uintptr_t)args32.opts; 425 args.map = (char *)(uintptr_t)args32.map; 426 args.subdir = (char *)(uintptr_t)args32.subdir; 427 args.key = (char *)(uintptr_t)args32.key; 428 args.mount_to = args32.mount_to; 429 args.rpc_to = args32.rpc_to; 430 args.direct = args32.direct; 431 } 432 } 433 if (error) 434 return (EFAULT); 435 436 /* 437 * For a remount, only update mount information 438 * i.e. default mount options, map name, etc. 439 */ 440 if (uap->flags & MS_REMOUNT) { 441 fnip = vfstofni(vfsp); 442 if (fnip == NULL) 443 return (EINVAL); 444 445 if (args.direct == 1) 446 fnip->fi_flags |= MF_DIRECT; 447 else 448 fnip->fi_flags &= ~MF_DIRECT; 449 fnip->fi_mount_to = args.mount_to; 450 fnip->fi_rpc_to = args.rpc_to; 451 452 /* 453 * Get default options 454 */ 455 if (uap->flags & MS_SYSSPACE) 456 error = copystr(args.opts, strbuff, sizeof (strbuff), 457 &len); 458 else 459 error = copyinstr(args.opts, strbuff, sizeof (strbuff), 460 &len); 461 if (error) 462 return (EFAULT); 463 464 if (autofs_restrict_opts(vfsp, strbuff, sizeof (strbuff), &len) 465 != 0) { 466 return (EFAULT); 467 } 468 469 kmem_free(fnip->fi_opts, fnip->fi_optslen); 470 fnip->fi_opts = kmem_alloc(len, KM_SLEEP); 471 fnip->fi_optslen = (int)len; 472 bcopy(strbuff, fnip->fi_opts, len); 473 474 /* 475 * Get context/map name 476 */ 477 if (uap->flags & MS_SYSSPACE) 478 error = copystr(args.map, strbuff, sizeof (strbuff), 479 &len); 480 else 481 error = copyinstr(args.map, strbuff, sizeof (strbuff), 482 &len); 483 if (error) 484 return (EFAULT); 485 486 kmem_free(fnip->fi_map, fnip->fi_maplen); 487 fnip->fi_map = kmem_alloc(len, KM_SLEEP); 488 fnip->fi_maplen = (int)len; 489 bcopy(strbuff, fnip->fi_map, len); 490 491 return (0); 492 } 493 494 /* 495 * Allocate fninfo struct and attach it to vfs 496 */ 497 fnip = kmem_zalloc(sizeof (*fnip), KM_SLEEP); 498 fnip->fi_mountvfs = vfsp; 499 500 fnip->fi_mount_to = args.mount_to; 501 fnip->fi_rpc_to = args.rpc_to; 502 fnip->fi_refcnt = 0; 503 vfsp->vfs_bsize = AUTOFS_BLOCKSIZE; 504 vfsp->vfs_fstype = autofs_fstype; 505 506 /* 507 * Assign a unique device id to the mount 508 */ 509 mutex_enter(&autofs_minor_lock); 510 do { 511 autofs_minor = (autofs_minor + 1) & L_MAXMIN32; 512 autofs_dev = makedevice(autofs_major, autofs_minor); 513 } while (vfs_devismounted(autofs_dev)); 514 mutex_exit(&autofs_minor_lock); 515 vfsp->vfs_dev = autofs_dev; 516 vfs_make_fsid(&vfsp->vfs_fsid, autofs_dev, autofs_fstype); 517 vfsp->vfs_data = (void *)fnip; 518 vfsp->vfs_bcount = 0; 519 520 /* 521 * Get daemon address 522 */ 523 fnip->fi_addr.len = args.addr.len; 524 fnip->fi_addr.maxlen = fnip->fi_addr.len; 525 fnip->fi_addr.buf = kmem_alloc(args.addr.len, KM_SLEEP); 526 if (uap->flags & MS_SYSSPACE) 527 error = kcopy(args.addr.buf, fnip->fi_addr.buf, args.addr.len); 528 else 529 error = copyin(args.addr.buf, fnip->fi_addr.buf, args.addr.len); 530 if (error) { 531 error = EFAULT; 532 goto errout; 533 } 534 535 fnip->fi_zoneid = getzoneid(); 536 /* 537 * Get path for mountpoint 538 */ 539 if (uap->flags & MS_SYSSPACE) 540 error = copystr(args.path, strbuff, sizeof (strbuff), &len); 541 else 542 error = copyinstr(args.path, strbuff, sizeof (strbuff), &len); 543 if (error) { 544 error = EFAULT; 545 goto errout; 546 } 547 fnip->fi_path = kmem_alloc(len, KM_SLEEP); 548 fnip->fi_pathlen = (int)len; 549 bcopy(strbuff, fnip->fi_path, len); 550 551 /* 552 * Get default options 553 */ 554 if (uap->flags & MS_SYSSPACE) 555 error = copystr(args.opts, strbuff, sizeof (strbuff), &len); 556 else 557 error = copyinstr(args.opts, strbuff, sizeof (strbuff), &len); 558 559 if (error != 0 || 560 autofs_restrict_opts(vfsp, strbuff, sizeof (strbuff), &len) != 0) { 561 error = EFAULT; 562 goto errout; 563 } 564 fnip->fi_opts = kmem_alloc(len, KM_SLEEP); 565 fnip->fi_optslen = (int)len; 566 bcopy(strbuff, fnip->fi_opts, len); 567 568 /* 569 * Get context/map name 570 */ 571 if (uap->flags & MS_SYSSPACE) 572 error = copystr(args.map, strbuff, sizeof (strbuff), &len); 573 else 574 error = copyinstr(args.map, strbuff, sizeof (strbuff), &len); 575 if (error) { 576 error = EFAULT; 577 goto errout; 578 } 579 fnip->fi_map = kmem_alloc(len, KM_SLEEP); 580 fnip->fi_maplen = (int)len; 581 bcopy(strbuff, fnip->fi_map, len); 582 583 /* 584 * Get subdirectory within map 585 */ 586 if (uap->flags & MS_SYSSPACE) 587 error = copystr(args.subdir, strbuff, sizeof (strbuff), &len); 588 else 589 error = copyinstr(args.subdir, strbuff, sizeof (strbuff), &len); 590 if (error) { 591 error = EFAULT; 592 goto errout; 593 } 594 fnip->fi_subdir = kmem_alloc(len, KM_SLEEP); 595 fnip->fi_subdirlen = (int)len; 596 bcopy(strbuff, fnip->fi_subdir, len); 597 598 /* 599 * Get the key 600 */ 601 if (uap->flags & MS_SYSSPACE) 602 error = copystr(args.key, strbuff, sizeof (strbuff), &len); 603 else 604 error = copyinstr(args.key, strbuff, sizeof (strbuff), &len); 605 if (error) { 606 error = EFAULT; 607 goto errout; 608 } 609 fnip->fi_key = kmem_alloc(len, KM_SLEEP); 610 fnip->fi_keylen = (int)len; 611 bcopy(strbuff, fnip->fi_key, len); 612 613 /* 614 * Is this a direct mount? 615 */ 616 if (args.direct == 1) 617 fnip->fi_flags |= MF_DIRECT; 618 619 /* 620 * Setup netconfig. 621 * Can I pass in knconf as mount argument? what 622 * happens when the daemon gets restarted? 623 */ 624 if ((error = lookupname("/dev/ticotsord", UIO_SYSSPACE, FOLLOW, 625 NULLVPP, &kvp)) != 0) { 626 cmn_err(CE_WARN, "autofs: lookupname: %d", error); 627 goto errout; 628 } 629 630 fnip->fi_knconf.knc_rdev = kvp->v_rdev; 631 fnip->fi_knconf.knc_protofmly = NC_LOOPBACK; 632 fnip->fi_knconf.knc_semantics = NC_TPI_COTS_ORD; 633 VN_RELE(kvp); 634 635 /* 636 * Make the root vnode 637 */ 638 rootfnp = auto_makefnnode(VDIR, vfsp, fnip->fi_path, cr, fngp); 639 if (rootfnp == NULL) { 640 error = ENOMEM; 641 goto errout; 642 } 643 rootvp = fntovn(rootfnp); 644 645 rootvp->v_flag |= VROOT; 646 rootfnp->fn_mode = AUTOFS_MODE; 647 rootfnp->fn_parent = rootfnp; 648 /* account for ".." entry */ 649 rootfnp->fn_linkcnt = rootfnp->fn_size = 1; 650 fnip->fi_rootvp = rootvp; 651 652 /* 653 * Add to list of top level AUTOFS' if it is being mounted by 654 * a user level process. 655 */ 656 if (!(uap->flags & MS_SYSSPACE)) { 657 rw_enter(&fngp->fng_rootfnnodep->fn_rwlock, RW_WRITER); 658 rootfnp->fn_parent = fngp->fng_rootfnnodep; 659 rootfnp->fn_next = fngp->fng_rootfnnodep->fn_dirents; 660 fngp->fng_rootfnnodep->fn_dirents = rootfnp; 661 rw_exit(&fngp->fng_rootfnnodep->fn_rwlock); 662 } 663 664 AUTOFS_DPRINT((5, "auto_mount: vfs %p root %p fnip %p return %d\n", 665 (void *)vfsp, (void *)rootvp, (void *)fnip, error)); 666 667 return (0); 668 669 errout: 670 ASSERT(fnip != NULL); 671 ASSERT((uap->flags & MS_REMOUNT) == 0); 672 673 if (fnip->fi_addr.buf != NULL) 674 kmem_free(fnip->fi_addr.buf, fnip->fi_addr.len); 675 if (fnip->fi_path != NULL) 676 kmem_free(fnip->fi_path, fnip->fi_pathlen); 677 if (fnip->fi_opts != NULL) 678 kmem_free(fnip->fi_opts, fnip->fi_optslen); 679 if (fnip->fi_map != NULL) 680 kmem_free(fnip->fi_map, fnip->fi_maplen); 681 if (fnip->fi_subdir != NULL) 682 kmem_free(fnip->fi_subdir, fnip->fi_subdirlen); 683 if (fnip->fi_key != NULL) 684 kmem_free(fnip->fi_key, fnip->fi_keylen); 685 kmem_free(fnip, sizeof (*fnip)); 686 687 AUTOFS_DPRINT((5, "auto_mount: vfs %p root %p fnip %p return %d\n", 688 (void *)vfsp, (void *)rootvp, (void *)fnip, error)); 689 690 return (error); 691 } 692 693 /* ARGSUSED */ 694 static int 695 auto_unmount(vfs_t *vfsp, int flag, cred_t *cr) 696 { 697 fninfo_t *fnip; 698 vnode_t *rvp; 699 fnnode_t *rfnp, *fnp, *pfnp; 700 fnnode_t *myrootfnnodep; 701 702 fnip = vfstofni(vfsp); 703 AUTOFS_DPRINT((4, "auto_unmount vfsp %p fnip %p\n", (void *)vfsp, 704 (void *)fnip)); 705 706 if (secpolicy_fs_unmount(cr, vfsp) != 0) 707 return (EPERM); 708 /* 709 * forced unmount is not supported by this file system 710 * and thus, ENOTSUP, is being returned. 711 */ 712 if (flag & MS_FORCE) 713 return (ENOTSUP); 714 715 ASSERT(vn_vfswlock_held(vfsp->vfs_vnodecovered)); 716 rvp = fnip->fi_rootvp; 717 rfnp = vntofn(rvp); 718 719 if (rvp->v_count > 1 || rfnp->fn_dirents != NULL) 720 return (EBUSY); 721 722 /* 723 * The root vnode is on the linked list of root fnnodes only if 724 * this was not a trigger node. Since we have no way of knowing, 725 * if we don't find it, then we assume it was a trigger node. 726 */ 727 myrootfnnodep = rfnp->fn_globals->fng_rootfnnodep; 728 pfnp = NULL; 729 rw_enter(&myrootfnnodep->fn_rwlock, RW_WRITER); 730 fnp = myrootfnnodep->fn_dirents; 731 while (fnp != NULL) { 732 if (fnp == rfnp) { 733 /* 734 * A check here is made to see if rvp is busy. If 735 * so, return EBUSY. Otherwise proceed with 736 * disconnecting it from the list. 737 */ 738 if (rvp->v_count > 1 || rfnp->fn_dirents != NULL) { 739 rw_exit(&myrootfnnodep->fn_rwlock); 740 return (EBUSY); 741 } 742 if (pfnp) 743 pfnp->fn_next = fnp->fn_next; 744 else 745 myrootfnnodep->fn_dirents = fnp->fn_next; 746 fnp->fn_next = NULL; 747 break; 748 } 749 pfnp = fnp; 750 fnp = fnp->fn_next; 751 } 752 rw_exit(&myrootfnnodep->fn_rwlock); 753 754 ASSERT(rvp->v_count == 1); 755 ASSERT(rfnp->fn_size == 1); 756 ASSERT(rfnp->fn_linkcnt == 1); 757 /* 758 * The following drops linkcnt to 0, therefore the disconnect is 759 * not attempted when auto_inactive() is called by 760 * vn_rele(). This is necessary because we have nothing to get 761 * disconnected from since we're the root of the filesystem. As a 762 * side effect the node is not freed, therefore I should free the 763 * node here. 764 * 765 * XXX - I really need to think of a better way of doing this. 766 */ 767 rfnp->fn_size--; 768 rfnp->fn_linkcnt--; 769 770 /* 771 * release of last reference causes node 772 * to be freed 773 */ 774 VN_RELE(rvp); 775 rfnp->fn_parent = NULL; 776 777 auto_freefnnode(rfnp); 778 779 kmem_free(fnip->fi_addr.buf, fnip->fi_addr.len); 780 kmem_free(fnip->fi_path, fnip->fi_pathlen); 781 kmem_free(fnip->fi_map, fnip->fi_maplen); 782 kmem_free(fnip->fi_subdir, fnip->fi_subdirlen); 783 kmem_free(fnip->fi_key, fnip->fi_keylen); 784 kmem_free(fnip->fi_opts, fnip->fi_optslen); 785 kmem_free(fnip, sizeof (*fnip)); 786 AUTOFS_DPRINT((5, "auto_unmount: return=0\n")); 787 788 return (0); 789 } 790 791 792 /* 793 * find root of autofs 794 */ 795 static int 796 auto_root(vfs_t *vfsp, vnode_t **vpp) 797 { 798 *vpp = (vnode_t *)vfstofni(vfsp)->fi_rootvp; 799 VN_HOLD(*vpp); 800 801 AUTOFS_DPRINT((5, "auto_root: vfs %p, *vpp %p\n", (void *)vfsp, 802 (void *)*vpp)); 803 return (0); 804 } 805 806 /* 807 * Get file system statistics. 808 */ 809 static int 810 auto_statvfs(vfs_t *vfsp, struct statvfs64 *sbp) 811 { 812 dev32_t d32; 813 814 AUTOFS_DPRINT((4, "auto_statvfs %p\n", (void *)vfsp)); 815 816 bzero(sbp, sizeof (*sbp)); 817 sbp->f_bsize = vfsp->vfs_bsize; 818 sbp->f_frsize = sbp->f_bsize; 819 sbp->f_blocks = (fsblkcnt64_t)0; 820 sbp->f_bfree = (fsblkcnt64_t)0; 821 sbp->f_bavail = (fsblkcnt64_t)0; 822 sbp->f_files = (fsfilcnt64_t)0; 823 sbp->f_ffree = (fsfilcnt64_t)0; 824 sbp->f_favail = (fsfilcnt64_t)0; 825 (void) cmpldev(&d32, vfsp->vfs_dev); 826 sbp->f_fsid = d32; 827 (void) strcpy(sbp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 828 sbp->f_flag = vf_to_stf(vfsp->vfs_flag); 829 sbp->f_namemax = MAXNAMELEN; 830 (void) strcpy(sbp->f_fstr, MNTTYPE_AUTOFS); 831 832 return (0); 833 } 834