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.
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.
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]
22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
24 * Copyright (c) 2017 by Delphix. All rights reserved.
27 #include <sys/param.h>
28 #include <sys/errno.h>
32 #include <sys/vnode.h>
36 #include <sys/statvfs.h>
37 #include <sys/mount.h>
38 #include <sys/tiuser.h>
39 #include <sys/cmn_err.h>
40 #include <sys/debug.h>
41 #include <sys/systm.h>
42 #include <sys/sysmacros.h>
43 #include <sys/pathname.h>
44 #include <rpc/types.h>
47 #include <sys/fs_subr.h>
48 #include <sys/fs/autofs.h>
49 #include <sys/modctl.h>
50 #include <sys/mntent.h>
51 #include <sys/policy.h>
54 static int autofs_init(int, char *);
56 static major_t autofs_major
;
57 static minor_t autofs_minor
;
59 kmutex_t autofs_minor_lock
;
60 zone_key_t autofs_key
;
62 static mntopts_t auto_mntopts
;
65 * The AUTOFS system call.
67 static struct sysent autofssysent
= {
69 SE_32RVAL1
| SE_ARGC
| SE_NOUNLOAD
,
73 static struct modlsys modlsys
= {
79 #ifdef _SYSCALL32_IMPL
80 static struct modlsys modlsys32
= {
82 "AUTOFS syscall (32-bit)",
85 #endif /* _SYSCALL32_IMPL */
87 static vfsdef_t vfw
= {
91 VSW_HASPROTO
|VSW_CANRWRO
|VSW_CANREMOUNT
|VSW_STATS
|VSW_ZMOUNT
,
96 * Module linkage information for the kernel.
98 static struct modlfs modlfs
= {
99 &mod_fsops
, "filesystem for autofs", &vfw
102 static struct modlinkage modlinkage
= {
106 #ifdef _SYSCALL32_IMPL
113 * This is the module initialization routine.
118 return (mod_install(&modlinkage
));
125 * Don't allow the autofs module to be unloaded for now.
131 _info(struct modinfo
*modinfop
)
133 return (mod_info(&modlinkage
, modinfop
));
136 static int autofs_fstype
;
139 * autofs VFS operations
141 static int auto_mount(vfs_t
*, vnode_t
*, struct mounta
*, cred_t
*);
142 static int auto_unmount(vfs_t
*, int, cred_t
*);
143 static int auto_root(vfs_t
*, vnode_t
**);
144 static int auto_statvfs(vfs_t
*, struct statvfs64
*);
147 * Auto Mount options table
150 static char *direct_cancel
[] = { MNTOPT_INDIRECT
, NULL
};
151 static char *indirect_cancel
[] = { MNTOPT_DIRECT
, NULL
};
152 static char *browse_cancel
[] = { MNTOPT_NOBROWSE
, NULL
};
153 static char *nobrowse_cancel
[] = { MNTOPT_BROWSE
, NULL
};
155 static mntopt_t mntopts
[] = {
157 * option name cancel options default arg flags
159 { MNTOPT_DIRECT
, direct_cancel
, NULL
, 0,
161 { MNTOPT_INDIRECT
, indirect_cancel
, NULL
, 0,
163 { MNTOPT_IGNORE
, NULL
, NULL
,
164 MO_DEFAULT
|MO_TAG
, NULL
},
165 { "nest", NULL
, NULL
, MO_TAG
,
167 { MNTOPT_BROWSE
, browse_cancel
, NULL
, MO_TAG
,
169 { MNTOPT_NOBROWSE
, nobrowse_cancel
, NULL
, MO_TAG
,
171 { MNTOPT_RESTRICT
, NULL
, NULL
, MO_TAG
,
175 static mntopts_t auto_mntopts
= {
176 sizeof (mntopts
) / sizeof (mntopt_t
),
182 autofs_zone_destructor(zoneid_t zoneid
, void *arg
)
184 struct autofs_globals
*fngp
= arg
;
189 ASSERT(fngp
->fng_fnnode_count
== 1);
190 ASSERT(fngp
->fng_unmount_threads
== 0);
192 if (fngp
->fng_autofs_daemon_dh
!= NULL
)
193 door_ki_rele(fngp
->fng_autofs_daemon_dh
);
195 * vn_alloc() initialized the rootnode with a count of 1; we need to
196 * make this 0 to placate auto_freefnnode().
198 vp
= fntovn(fngp
->fng_rootfnnodep
);
199 mutex_enter(&vp
->v_lock
);
200 ASSERT(vp
->v_count
== 1);
202 mutex_exit(&vp
->v_lock
);
203 auto_freefnnode(fngp
->fng_rootfnnodep
);
204 mutex_destroy(&fngp
->fng_unmount_threads_lock
);
205 kmem_free(fngp
, sizeof (*fngp
));
209 * rootfnnodep is allocated here. Its sole purpose is to provide
210 * read/write locking for top level fnnodes. This object is
211 * persistent and will not be deallocated until the zone is destroyed.
213 * The current zone is implied as the zone of interest, since we will be
214 * calling zthread_create() which must be called from the correct zone.
216 struct autofs_globals
*
217 autofs_zone_init(void)
219 char rootname
[sizeof ("root_fnnode_zone_") + ZONEID_WIDTH
];
220 struct autofs_globals
*fngp
;
221 zoneid_t zoneid
= getzoneid();
223 fngp
= kmem_zalloc(sizeof (*fngp
), KM_SLEEP
);
224 (void) snprintf(rootname
, sizeof (rootname
), "root_fnnode_zone_%d",
226 fngp
->fng_rootfnnodep
= auto_makefnnode(VNON
, NULL
, rootname
, CRED(),
229 * Don't need to hold fng_rootfnnodep as it's never really used for
232 fngp
->fng_fnnode_count
= 1;
233 fngp
->fng_printed_not_running_msg
= 0;
234 fngp
->fng_zoneid
= zoneid
;
235 mutex_init(&fngp
->fng_unmount_threads_lock
, NULL
, MUTEX_DEFAULT
,
237 fngp
->fng_unmount_threads
= 0;
239 mutex_init(&fngp
->fng_autofs_daemon_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
242 * Start the unmounter thread for this zone.
244 (void) zthread_create(NULL
, 0, auto_do_unmount
, fngp
, 0, minclsyspri
);
248 static const struct vfsops auto_vfsops
= {
249 .vfs_mount
= auto_mount
,
250 .vfs_unmount
= auto_unmount
,
251 .vfs_root
= auto_root
,
252 .vfs_statvfs
= auto_statvfs
,
256 autofs_init(int fstype
, char *name
)
260 autofs_fstype
= fstype
;
261 ASSERT(autofs_fstype
!= 0);
263 * Associate VFS ops vector with this fstype
265 error
= vfs_setfsops(fstype
, &auto_vfsops
);
267 cmn_err(CE_WARN
, "autofs_init: bad fstype");
271 mutex_init(&autofs_minor_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
273 * Assign unique major number for all autofs mounts
275 if ((autofs_major
= getudev()) == (major_t
)-1) {
277 "autofs: autofs_init: can't get unique device number");
278 mutex_destroy(&autofs_minor_lock
);
283 * We'd like to be able to provide a constructor here, but we can't
284 * since it wants to zthread_create(), something it can't do in a ZSD
287 zone_key_create(&autofs_key
, NULL
, NULL
, autofs_zone_destructor
);
292 static char *restropts
[] = {
297 * This routine adds those options to the option string `buf' which are
298 * forced by secpolicy_fs_mount. If the automatic "security" options
299 * are set, the option string gets them added if they aren't already
300 * there. We search the string with "strstr" and make sure that
301 * the string we find is bracketed with <start|",">MNTOPT<","|"\0">
303 * This is one half of the option inheritence algorithm which
304 * implements the "restrict" option. The other half is implemented
305 * in automountd; it takes its cue from the options we add here.
308 autofs_restrict_opts(struct vfs
*vfsp
, char *buf
, size_t maxlen
, size_t *curlen
)
312 size_t len
= *curlen
- 1;
315 if (!vfs_optionisset(vfsp
, restropts
[0], NULL
))
318 for (i
= 0; i
< sizeof (restropts
)/sizeof (restropts
[0]); i
++) {
319 size_t olen
= strlen(restropts
[i
]);
321 /* Add "restrict" always and the others insofar set */
322 if ((i
== 0 || vfs_optionisset(vfsp
, restropts
[i
], NULL
)) &&
323 ((p
= strstr(buf
, restropts
[i
])) == NULL
||
324 !((p
== buf
|| p
[-1] == ',') &&
325 (p
[olen
] == '\0' || p
[olen
] == ',')))) {
327 if (len
+ olen
+ 1 > maxlen
)
332 (void) strcpy(&buf
[len
], restropts
[i
]);
342 auto_mount(vfs_t
*vfsp
, vnode_t
*vp
, struct mounta
*uap
, cred_t
*cr
)
347 fninfo_t
*fnip
= NULL
;
348 vnode_t
*rootvp
= NULL
;
349 fnnode_t
*rootfnp
= NULL
;
350 char *data
= uap
->dataptr
;
351 char datalen
= uap
->datalen
;
353 char strbuff
[MAXPATHLEN
+ 1];
355 struct autofs_globals
*fngp
;
356 zone_t
*zone
= curproc
->p_zone
;
358 AUTOFS_DPRINT((4, "auto_mount: vfs %p vp %p\n", (void *)vfsp
,
361 if ((error
= secpolicy_fs_mount(cr
, vp
, vfsp
)) != 0)
364 if (zone
== global_zone
) {
367 mntzone
= zone_find_by_path(refstr_value(vfsp
->vfs_mntpt
));
368 ASSERT(mntzone
!= NULL
);
370 if (mntzone
!= zone
) {
376 * Stop the mount from going any further if the zone is going away.
378 if (zone_status_get(zone
) >= ZONE_IS_SHUTTING_DOWN
)
382 * We need a lock to serialize this; minor_lock is as good as any.
384 mutex_enter(&autofs_minor_lock
);
385 if ((fngp
= zone_getspecific(autofs_key
, zone
)) == NULL
) {
386 fngp
= autofs_zone_init();
387 (void) zone_setspecific(autofs_key
, zone
, fngp
);
389 mutex_exit(&autofs_minor_lock
);
390 ASSERT(fngp
!= NULL
);
395 if (uap
->flags
& MS_SYSSPACE
) {
396 if (datalen
!= sizeof (args
))
398 error
= kcopy(data
, &args
, sizeof (args
));
400 if (get_udatamodel() == DATAMODEL_NATIVE
) {
401 if (datalen
!= sizeof (args
))
403 error
= copyin(data
, &args
, sizeof (args
));
405 struct autofs_args32 args32
;
407 if (datalen
!= sizeof (args32
))
409 error
= copyin(data
, &args32
, sizeof (args32
));
411 args
.addr
.maxlen
= args32
.addr
.maxlen
;
412 args
.addr
.len
= args32
.addr
.len
;
413 args
.addr
.buf
= (char *)(uintptr_t)args32
.addr
.buf
;
414 args
.path
= (char *)(uintptr_t)args32
.path
;
415 args
.opts
= (char *)(uintptr_t)args32
.opts
;
416 args
.map
= (char *)(uintptr_t)args32
.map
;
417 args
.subdir
= (char *)(uintptr_t)args32
.subdir
;
418 args
.key
= (char *)(uintptr_t)args32
.key
;
419 args
.mount_to
= args32
.mount_to
;
420 args
.rpc_to
= args32
.rpc_to
;
421 args
.direct
= args32
.direct
;
428 * For a remount, only update mount information
429 * i.e. default mount options, map name, etc.
431 if (uap
->flags
& MS_REMOUNT
) {
432 fnip
= vfstofni(vfsp
);
436 if (args
.direct
== 1)
437 fnip
->fi_flags
|= MF_DIRECT
;
439 fnip
->fi_flags
&= ~MF_DIRECT
;
440 fnip
->fi_mount_to
= args
.mount_to
;
441 fnip
->fi_rpc_to
= args
.rpc_to
;
444 * Get default options
446 if (uap
->flags
& MS_SYSSPACE
)
447 error
= copystr(args
.opts
, strbuff
, sizeof (strbuff
),
450 error
= copyinstr(args
.opts
, strbuff
, sizeof (strbuff
),
455 if (autofs_restrict_opts(vfsp
, strbuff
, sizeof (strbuff
), &len
)
460 kmem_free(fnip
->fi_opts
, fnip
->fi_optslen
);
461 fnip
->fi_opts
= kmem_alloc(len
, KM_SLEEP
);
462 fnip
->fi_optslen
= (int)len
;
463 bcopy(strbuff
, fnip
->fi_opts
, len
);
466 * Get context/map name
468 if (uap
->flags
& MS_SYSSPACE
)
469 error
= copystr(args
.map
, strbuff
, sizeof (strbuff
),
472 error
= copyinstr(args
.map
, strbuff
, sizeof (strbuff
),
477 kmem_free(fnip
->fi_map
, fnip
->fi_maplen
);
478 fnip
->fi_map
= kmem_alloc(len
, KM_SLEEP
);
479 fnip
->fi_maplen
= (int)len
;
480 bcopy(strbuff
, fnip
->fi_map
, len
);
486 * Allocate fninfo struct and attach it to vfs
488 fnip
= kmem_zalloc(sizeof (*fnip
), KM_SLEEP
);
489 fnip
->fi_mountvfs
= vfsp
;
491 fnip
->fi_mount_to
= args
.mount_to
;
492 fnip
->fi_rpc_to
= args
.rpc_to
;
494 vfsp
->vfs_bsize
= AUTOFS_BLOCKSIZE
;
495 vfsp
->vfs_fstype
= autofs_fstype
;
498 * Assign a unique device id to the mount
500 mutex_enter(&autofs_minor_lock
);
502 autofs_minor
= (autofs_minor
+ 1) & L_MAXMIN32
;
503 autofs_dev
= makedevice(autofs_major
, autofs_minor
);
504 } while (vfs_devismounted(autofs_dev
));
505 mutex_exit(&autofs_minor_lock
);
506 vfsp
->vfs_dev
= autofs_dev
;
507 vfs_make_fsid(&vfsp
->vfs_fsid
, autofs_dev
, autofs_fstype
);
508 vfsp
->vfs_data
= (void *)fnip
;
509 vfsp
->vfs_bcount
= 0;
514 fnip
->fi_addr
.len
= args
.addr
.len
;
515 fnip
->fi_addr
.maxlen
= fnip
->fi_addr
.len
;
516 fnip
->fi_addr
.buf
= kmem_alloc(args
.addr
.len
, KM_SLEEP
);
517 if (uap
->flags
& MS_SYSSPACE
)
518 error
= kcopy(args
.addr
.buf
, fnip
->fi_addr
.buf
, args
.addr
.len
);
520 error
= copyin(args
.addr
.buf
, fnip
->fi_addr
.buf
, args
.addr
.len
);
526 fnip
->fi_zoneid
= getzoneid();
528 * Get path for mountpoint
530 if (uap
->flags
& MS_SYSSPACE
)
531 error
= copystr(args
.path
, strbuff
, sizeof (strbuff
), &len
);
533 error
= copyinstr(args
.path
, strbuff
, sizeof (strbuff
), &len
);
538 fnip
->fi_path
= kmem_alloc(len
, KM_SLEEP
);
539 fnip
->fi_pathlen
= (int)len
;
540 bcopy(strbuff
, fnip
->fi_path
, len
);
543 * Get default options
545 if (uap
->flags
& MS_SYSSPACE
)
546 error
= copystr(args
.opts
, strbuff
, sizeof (strbuff
), &len
);
548 error
= copyinstr(args
.opts
, strbuff
, sizeof (strbuff
), &len
);
551 autofs_restrict_opts(vfsp
, strbuff
, sizeof (strbuff
), &len
) != 0) {
555 fnip
->fi_opts
= kmem_alloc(len
, KM_SLEEP
);
556 fnip
->fi_optslen
= (int)len
;
557 bcopy(strbuff
, fnip
->fi_opts
, len
);
560 * Get context/map name
562 if (uap
->flags
& MS_SYSSPACE
)
563 error
= copystr(args
.map
, strbuff
, sizeof (strbuff
), &len
);
565 error
= copyinstr(args
.map
, strbuff
, sizeof (strbuff
), &len
);
570 fnip
->fi_map
= kmem_alloc(len
, KM_SLEEP
);
571 fnip
->fi_maplen
= (int)len
;
572 bcopy(strbuff
, fnip
->fi_map
, len
);
575 * Get subdirectory within map
577 if (uap
->flags
& MS_SYSSPACE
)
578 error
= copystr(args
.subdir
, strbuff
, sizeof (strbuff
), &len
);
580 error
= copyinstr(args
.subdir
, strbuff
, sizeof (strbuff
), &len
);
585 fnip
->fi_subdir
= kmem_alloc(len
, KM_SLEEP
);
586 fnip
->fi_subdirlen
= (int)len
;
587 bcopy(strbuff
, fnip
->fi_subdir
, len
);
592 if (uap
->flags
& MS_SYSSPACE
)
593 error
= copystr(args
.key
, strbuff
, sizeof (strbuff
), &len
);
595 error
= copyinstr(args
.key
, strbuff
, sizeof (strbuff
), &len
);
600 fnip
->fi_key
= kmem_alloc(len
, KM_SLEEP
);
601 fnip
->fi_keylen
= (int)len
;
602 bcopy(strbuff
, fnip
->fi_key
, len
);
605 * Is this a direct mount?
607 if (args
.direct
== 1)
608 fnip
->fi_flags
|= MF_DIRECT
;
612 * Can I pass in knconf as mount argument? what
613 * happens when the daemon gets restarted?
615 if ((error
= lookupname("/dev/ticotsord", UIO_SYSSPACE
, FOLLOW
,
616 NULLVPP
, &kkvp
)) != 0) {
617 cmn_err(CE_WARN
, "autofs: lookupname: %d", error
);
621 fnip
->fi_knconf
.knc_rdev
= kkvp
->v_rdev
;
622 fnip
->fi_knconf
.knc_protofmly
= NC_LOOPBACK
;
623 fnip
->fi_knconf
.knc_semantics
= NC_TPI_COTS_ORD
;
627 * Make the root vnode
629 rootfnp
= auto_makefnnode(VDIR
, vfsp
, fnip
->fi_path
, cr
, fngp
);
630 if (rootfnp
== NULL
) {
634 rootvp
= fntovn(rootfnp
);
636 rootvp
->v_flag
|= VROOT
;
637 rootfnp
->fn_mode
= AUTOFS_MODE
;
638 rootfnp
->fn_parent
= rootfnp
;
639 /* account for ".." entry */
640 rootfnp
->fn_linkcnt
= rootfnp
->fn_size
= 1;
641 fnip
->fi_rootvp
= rootvp
;
644 * Add to list of top level AUTOFS' if it is being mounted by
645 * a user level process.
647 if (!(uap
->flags
& MS_SYSSPACE
)) {
648 rw_enter(&fngp
->fng_rootfnnodep
->fn_rwlock
, RW_WRITER
);
649 rootfnp
->fn_parent
= fngp
->fng_rootfnnodep
;
650 rootfnp
->fn_next
= fngp
->fng_rootfnnodep
->fn_dirents
;
651 fngp
->fng_rootfnnodep
->fn_dirents
= rootfnp
;
652 rw_exit(&fngp
->fng_rootfnnodep
->fn_rwlock
);
655 AUTOFS_DPRINT((5, "auto_mount: vfs %p root %p fnip %p return %d\n",
656 (void *)vfsp
, (void *)rootvp
, (void *)fnip
, error
));
661 ASSERT(fnip
!= NULL
);
662 ASSERT((uap
->flags
& MS_REMOUNT
) == 0);
664 if (fnip
->fi_addr
.buf
!= NULL
)
665 kmem_free(fnip
->fi_addr
.buf
, fnip
->fi_addr
.len
);
666 if (fnip
->fi_path
!= NULL
)
667 kmem_free(fnip
->fi_path
, fnip
->fi_pathlen
);
668 if (fnip
->fi_opts
!= NULL
)
669 kmem_free(fnip
->fi_opts
, fnip
->fi_optslen
);
670 if (fnip
->fi_map
!= NULL
)
671 kmem_free(fnip
->fi_map
, fnip
->fi_maplen
);
672 if (fnip
->fi_subdir
!= NULL
)
673 kmem_free(fnip
->fi_subdir
, fnip
->fi_subdirlen
);
674 if (fnip
->fi_key
!= NULL
)
675 kmem_free(fnip
->fi_key
, fnip
->fi_keylen
);
676 kmem_free(fnip
, sizeof (*fnip
));
678 AUTOFS_DPRINT((5, "auto_mount: vfs %p root %p fnip %p return %d\n",
679 (void *)vfsp
, (void *)rootvp
, (void *)fnip
, error
));
686 auto_unmount(vfs_t
*vfsp
, int flag
, cred_t
*cr
)
690 fnnode_t
*rfnp
, *fnp
, *pfnp
;
691 fnnode_t
*myrootfnnodep
;
693 fnip
= vfstofni(vfsp
);
694 AUTOFS_DPRINT((4, "auto_unmount vfsp %p fnip %p\n", (void *)vfsp
,
697 if (secpolicy_fs_unmount(cr
, vfsp
) != 0)
700 * forced unmount is not supported by this file system
701 * and thus, ENOTSUP, is being returned.
706 ASSERT(vn_vfswlock_held(vfsp
->vfs_vnodecovered
));
707 rvp
= fnip
->fi_rootvp
;
710 if (rvp
->v_count
> 1 || rfnp
->fn_dirents
!= NULL
)
714 * The root vnode is on the linked list of root fnnodes only if
715 * this was not a trigger node. Since we have no way of knowing,
716 * if we don't find it, then we assume it was a trigger node.
718 myrootfnnodep
= rfnp
->fn_globals
->fng_rootfnnodep
;
720 rw_enter(&myrootfnnodep
->fn_rwlock
, RW_WRITER
);
721 fnp
= myrootfnnodep
->fn_dirents
;
722 while (fnp
!= NULL
) {
725 * A check here is made to see if rvp is busy. If
726 * so, return EBUSY. Otherwise proceed with
727 * disconnecting it from the list.
729 if (rvp
->v_count
> 1 || rfnp
->fn_dirents
!= NULL
) {
730 rw_exit(&myrootfnnodep
->fn_rwlock
);
734 pfnp
->fn_next
= fnp
->fn_next
;
736 myrootfnnodep
->fn_dirents
= fnp
->fn_next
;
743 rw_exit(&myrootfnnodep
->fn_rwlock
);
745 ASSERT(rvp
->v_count
== 1);
746 ASSERT(rfnp
->fn_size
== 1);
747 ASSERT(rfnp
->fn_linkcnt
== 1);
749 * The following drops linkcnt to 0, therefore the disconnect is
750 * not attempted when auto_inactive() is called by
751 * vn_rele(). This is necessary because we have nothing to get
752 * disconnected from since we're the root of the filesystem. As a
753 * side effect the node is not freed, therefore I should free the
756 * XXX - I really need to think of a better way of doing this.
762 * release of last reference causes node
766 rfnp
->fn_parent
= NULL
;
768 auto_freefnnode(rfnp
);
770 kmem_free(fnip
->fi_addr
.buf
, fnip
->fi_addr
.len
);
771 kmem_free(fnip
->fi_path
, fnip
->fi_pathlen
);
772 kmem_free(fnip
->fi_map
, fnip
->fi_maplen
);
773 kmem_free(fnip
->fi_subdir
, fnip
->fi_subdirlen
);
774 kmem_free(fnip
->fi_key
, fnip
->fi_keylen
);
775 kmem_free(fnip
->fi_opts
, fnip
->fi_optslen
);
776 kmem_free(fnip
, sizeof (*fnip
));
777 AUTOFS_DPRINT((5, "auto_unmount: return=0\n"));
784 * find root of autofs
787 auto_root(vfs_t
*vfsp
, vnode_t
**vpp
)
789 *vpp
= (vnode_t
*)vfstofni(vfsp
)->fi_rootvp
;
792 AUTOFS_DPRINT((5, "auto_root: vfs %p, *vpp %p\n", (void *)vfsp
,
798 * Get file system statistics.
801 auto_statvfs(vfs_t
*vfsp
, struct statvfs64
*sbp
)
805 AUTOFS_DPRINT((4, "auto_statvfs %p\n", (void *)vfsp
));
807 bzero(sbp
, sizeof (*sbp
));
808 sbp
->f_bsize
= vfsp
->vfs_bsize
;
809 sbp
->f_frsize
= sbp
->f_bsize
;
810 sbp
->f_blocks
= (fsblkcnt64_t
)0;
811 sbp
->f_bfree
= (fsblkcnt64_t
)0;
812 sbp
->f_bavail
= (fsblkcnt64_t
)0;
813 sbp
->f_files
= (fsfilcnt64_t
)0;
814 sbp
->f_ffree
= (fsfilcnt64_t
)0;
815 sbp
->f_favail
= (fsfilcnt64_t
)0;
816 (void) cmpldev(&d32
, vfsp
->vfs_dev
);
818 (void) strcpy(sbp
->f_basetype
, vfssw
[vfsp
->vfs_fstype
].vsw_name
);
819 sbp
->f_flag
= vf_to_stf(vfsp
->vfs_flag
);
820 sbp
->f_namemax
= MAXNAMELEN
;
821 (void) strcpy(sbp
->f_fstr
, MNTTYPE_AUTOFS
);