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