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