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