xref: /illumos-gate/usr/src/uts/common/fs/vfs.c (revision c6f039c7)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55a59a8b3Srsb  * Common Development and Distribution License (the "License").
65a59a8b3Srsb  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
215f10ef69SYuri Pankov 
227c478bd9Sstevel@tonic-gate /*
230fbb751dSJohn Levon  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24d6294894SJohn Levon  * Copyright (c) 2019, Joyent, Inc.
25406fc510SToomas Soome  * Copyright 2016 Toomas Soome <tsoome@me.com>
26d9a54dd1SSebastien Roy  * Copyright (c) 2016, 2017 by Delphix. All rights reserved.
275f10ef69SYuri Pankov  * Copyright 2016 Nexenta Systems, Inc.
282fc78efeSAndrew Stormont  * Copyright 2017 RackTop Systems.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
32b6d49c84SToomas Soome /*	  All Rights Reserved	*/
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
367c478bd9Sstevel@tonic-gate  * The Regents of the University of California
377c478bd9Sstevel@tonic-gate  * All Rights Reserved
387c478bd9Sstevel@tonic-gate  *
397c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
407c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
417c478bd9Sstevel@tonic-gate  * contributors.
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include <sys/types.h>
457c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
467c478bd9Sstevel@tonic-gate #include <sys/param.h>
477c478bd9Sstevel@tonic-gate #include <sys/errno.h>
487c478bd9Sstevel@tonic-gate #include <sys/user.h>
497c478bd9Sstevel@tonic-gate #include <sys/fstyp.h>
507c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
517c478bd9Sstevel@tonic-gate #include <sys/systm.h>
527c478bd9Sstevel@tonic-gate #include <sys/proc.h>
537c478bd9Sstevel@tonic-gate #include <sys/mount.h>
547c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
55aa59c4cbSrsb #include <sys/vfs_opreg.h>
567c478bd9Sstevel@tonic-gate #include <sys/fem.h>
577c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
587c478bd9Sstevel@tonic-gate #include <sys/stat.h>
597c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
607c478bd9Sstevel@tonic-gate #include <sys/statfs.h>
617c478bd9Sstevel@tonic-gate #include <sys/cred.h>
627c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
637c478bd9Sstevel@tonic-gate #include <sys/rwstlock.h>
647c478bd9Sstevel@tonic-gate #include <sys/dnlc.h>
657c478bd9Sstevel@tonic-gate #include <sys/file.h>
667c478bd9Sstevel@tonic-gate #include <sys/time.h>
677c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
687c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
697c478bd9Sstevel@tonic-gate #include <sys/buf.h>
707c478bd9Sstevel@tonic-gate #include <sys/swap.h>
717c478bd9Sstevel@tonic-gate #include <sys/debug.h>
727c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
737c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
747c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
757c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
767c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
777c478bd9Sstevel@tonic-gate #include <sys/dumphdr.h>
787c478bd9Sstevel@tonic-gate #include <sys/dc_ki.h>
797c478bd9Sstevel@tonic-gate #include <sys/poll.h>
807c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
817c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
827c478bd9Sstevel@tonic-gate #include <sys/zone.h>
837c478bd9Sstevel@tonic-gate #include <sys/policy.h>
847c478bd9Sstevel@tonic-gate #include <sys/ctfs.h>
857c478bd9Sstevel@tonic-gate #include <sys/objfs.h>
867c478bd9Sstevel@tonic-gate #include <sys/console.h>
877c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
88da6c28aaSamw #include <sys/attr.h>
89b24ab676SJeff Bonwick #include <sys/zio.h>
90e7cbe64fSgw #include <sys/spa.h>
9193239addSjohnlev #include <sys/lofi.h>
926cefaae1SJack Meng #include <sys/bootprops.h>
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate #include <vm/page.h>
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
9782c7f3c4Srsb /* Private interfaces to create vopstats-related data structures */
9882c7f3c4Srsb extern void		initialize_vopstats(vopstats_t *);
9982c7f3c4Srsb extern vopstats_t	*get_fstype_vopstats(struct vfs *, struct vfssw *);
10082c7f3c4Srsb extern vsk_anchor_t	*get_vskstat_anchor(struct vfs *);
10182c7f3c4Srsb 
1027c478bd9Sstevel@tonic-gate static void vfs_clearmntopt_nolock(mntopts_t *, const char *, int);
1037c478bd9Sstevel@tonic-gate static void vfs_setmntopt_nolock(mntopts_t *, const char *,
1047c478bd9Sstevel@tonic-gate     const char *, int, int);
1057c478bd9Sstevel@tonic-gate static int  vfs_optionisset_nolock(const mntopts_t *, const char *, char **);
1067c478bd9Sstevel@tonic-gate static void vfs_freemnttab(struct vfs *);
1077c478bd9Sstevel@tonic-gate static void vfs_freeopt(mntopt_t *);
1087c478bd9Sstevel@tonic-gate static void vfs_swapopttbl_nolock(mntopts_t *, mntopts_t *);
1097c478bd9Sstevel@tonic-gate static void vfs_swapopttbl(mntopts_t *, mntopts_t *);
1107c478bd9Sstevel@tonic-gate static void vfs_copyopttbl_extend(const mntopts_t *, mntopts_t *, int);
1117c478bd9Sstevel@tonic-gate static void vfs_createopttbl_extend(mntopts_t *, const char *,
1127c478bd9Sstevel@tonic-gate     const mntopts_t *);
1137c478bd9Sstevel@tonic-gate static char **vfs_copycancelopt_extend(char **const, int);
1147c478bd9Sstevel@tonic-gate static void vfs_freecancelopt(char **);
115843e1988Sjohnlev static void getrootfs(char **, char **);
1167c478bd9Sstevel@tonic-gate static int getmacpath(dev_info_t *, void *);
117df2381bfSpraks static void vfs_mnttabvp_setup(void);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate struct ipmnt {
1207c478bd9Sstevel@tonic-gate 	struct ipmnt	*mip_next;
1217c478bd9Sstevel@tonic-gate 	dev_t		mip_dev;
1227c478bd9Sstevel@tonic-gate 	struct vfs	*mip_vfsp;
1237c478bd9Sstevel@tonic-gate };
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate static kmutex_t		vfs_miplist_mutex;
1267c478bd9Sstevel@tonic-gate static struct ipmnt	*vfs_miplist = NULL;
1277c478bd9Sstevel@tonic-gate static struct ipmnt	*vfs_miplist_end = NULL;
1287c478bd9Sstevel@tonic-gate 
129da6c28aaSamw static kmem_cache_t *vfs_cache;	/* Pointer to VFS kmem cache */
130da6c28aaSamw 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  * VFS global data.
1337c478bd9Sstevel@tonic-gate  */
1347c478bd9Sstevel@tonic-gate vnode_t *rootdir;		/* pointer to root inode vnode. */
1357c478bd9Sstevel@tonic-gate vnode_t *devicesdir;		/* pointer to inode of devices root */
136facf4a8dSllai vnode_t	*devdir;		/* pointer to inode of dev root */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate char *server_rootpath;		/* root path for diskless clients */
1397c478bd9Sstevel@tonic-gate char *server_hostname;		/* hostname of diskless server */
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate static struct vfs root;
1427c478bd9Sstevel@tonic-gate static struct vfs devices;
143facf4a8dSllai static struct vfs dev;
1447c478bd9Sstevel@tonic-gate struct vfs *rootvfs = &root;	/* pointer to root vfs; head of VFS list. */
1457c478bd9Sstevel@tonic-gate rvfs_t *rvfs_list;		/* array of vfs ptrs for vfs hash list */
1467c478bd9Sstevel@tonic-gate int vfshsz = 512;		/* # of heads/locks in vfs hash arrays */
1477c478bd9Sstevel@tonic-gate 				/* must be power of 2!	*/
1487c478bd9Sstevel@tonic-gate timespec_t vfs_mnttab_ctime;	/* mnttab created time */
1497c478bd9Sstevel@tonic-gate timespec_t vfs_mnttab_mtime;	/* mnttab last modified time */
150ffc349abSdm char *vfs_dummyfstype = "\0";
1517c478bd9Sstevel@tonic-gate struct pollhead vfs_pollhd;	/* for mnttab pollers */
152df2381bfSpraks struct vnode *vfs_mntdummyvp;	/* to fake mnttab read/write for file events */
153df2381bfSpraks int	mntfstype;		/* will be set once mnt fs is mounted */
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate /*
1567c478bd9Sstevel@tonic-gate  * Table for generic options recognized in the VFS layer and acted
1577c478bd9Sstevel@tonic-gate  * on at this level before parsing file system specific options.
1587c478bd9Sstevel@tonic-gate  * The nosuid option is stronger than any of the devices and setuid
1597c478bd9Sstevel@tonic-gate  * options, so those are canceled when nosuid is seen.
1607c478bd9Sstevel@tonic-gate  *
1617c478bd9Sstevel@tonic-gate  * All options which are added here need to be added to the
1627c478bd9Sstevel@tonic-gate  * list of standard options in usr/src/cmd/fs.d/fslib.c as well.
1637c478bd9Sstevel@tonic-gate  */
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate  * VFS Mount options table
1667c478bd9Sstevel@tonic-gate  */
1677c478bd9Sstevel@tonic-gate static char *ro_cancel[] = { MNTOPT_RW, NULL };
1687c478bd9Sstevel@tonic-gate static char *rw_cancel[] = { MNTOPT_RO, NULL };
1697c478bd9Sstevel@tonic-gate static char *suid_cancel[] = { MNTOPT_NOSUID, NULL };
1707c478bd9Sstevel@tonic-gate static char *nosuid_cancel[] = { MNTOPT_SUID, MNTOPT_DEVICES, MNTOPT_NODEVICES,
1717c478bd9Sstevel@tonic-gate     MNTOPT_NOSETUID, MNTOPT_SETUID, NULL };
1727c478bd9Sstevel@tonic-gate static char *devices_cancel[] = { MNTOPT_NODEVICES, NULL };
1737c478bd9Sstevel@tonic-gate static char *nodevices_cancel[] = { MNTOPT_DEVICES, NULL };
1747c478bd9Sstevel@tonic-gate static char *setuid_cancel[] = { MNTOPT_NOSETUID, NULL };
1757c478bd9Sstevel@tonic-gate static char *nosetuid_cancel[] = { MNTOPT_SETUID, NULL };
1767c478bd9Sstevel@tonic-gate static char *nbmand_cancel[] = { MNTOPT_NONBMAND, NULL };
1777c478bd9Sstevel@tonic-gate static char *nonbmand_cancel[] = { MNTOPT_NBMAND, NULL };
1787c478bd9Sstevel@tonic-gate static char *exec_cancel[] = { MNTOPT_NOEXEC, NULL };
1797c478bd9Sstevel@tonic-gate static char *noexec_cancel[] = { MNTOPT_EXEC, NULL };
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate static const mntopt_t mntopts[] = {
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate  *	option name		cancel options		default arg	flags
1847c478bd9Sstevel@tonic-gate  */
1857c478bd9Sstevel@tonic-gate 	{ MNTOPT_REMOUNT,	NULL,			NULL,
1867c478bd9Sstevel@tonic-gate 		MO_NODISPLAY, (void *)0 },
1877c478bd9Sstevel@tonic-gate 	{ MNTOPT_RO,		ro_cancel,		NULL,		0,
1887c478bd9Sstevel@tonic-gate 		(void *)0 },
1897c478bd9Sstevel@tonic-gate 	{ MNTOPT_RW,		rw_cancel,		NULL,		0,
1907c478bd9Sstevel@tonic-gate 		(void *)0 },
1917c478bd9Sstevel@tonic-gate 	{ MNTOPT_SUID,		suid_cancel,		NULL,		0,
1927c478bd9Sstevel@tonic-gate 		(void *)0 },
1937c478bd9Sstevel@tonic-gate 	{ MNTOPT_NOSUID,	nosuid_cancel,		NULL,		0,
1947c478bd9Sstevel@tonic-gate 		(void *)0 },
1957c478bd9Sstevel@tonic-gate 	{ MNTOPT_DEVICES,	devices_cancel,		NULL,		0,
1967c478bd9Sstevel@tonic-gate 		(void *)0 },
1977c478bd9Sstevel@tonic-gate 	{ MNTOPT_NODEVICES,	nodevices_cancel,	NULL,		0,
1987c478bd9Sstevel@tonic-gate 		(void *)0 },
1997c478bd9Sstevel@tonic-gate 	{ MNTOPT_SETUID,	setuid_cancel,		NULL,		0,
2007c478bd9Sstevel@tonic-gate 		(void *)0 },
2017c478bd9Sstevel@tonic-gate 	{ MNTOPT_NOSETUID,	nosetuid_cancel,	NULL,		0,
2027c478bd9Sstevel@tonic-gate 		(void *)0 },
2037c478bd9Sstevel@tonic-gate 	{ MNTOPT_NBMAND,	nbmand_cancel,		NULL,		0,
2047c478bd9Sstevel@tonic-gate 		(void *)0 },
2057c478bd9Sstevel@tonic-gate 	{ MNTOPT_NONBMAND,	nonbmand_cancel,	NULL,		0,
2067c478bd9Sstevel@tonic-gate 		(void *)0 },
2077c478bd9Sstevel@tonic-gate 	{ MNTOPT_EXEC,		exec_cancel,		NULL,		0,
2087c478bd9Sstevel@tonic-gate 		(void *)0 },
2097c478bd9Sstevel@tonic-gate 	{ MNTOPT_NOEXEC,	noexec_cancel,		NULL,		0,
2107c478bd9Sstevel@tonic-gate 		(void *)0 },
2117c478bd9Sstevel@tonic-gate };
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate const mntopts_t vfs_mntopts = {
2147c478bd9Sstevel@tonic-gate 	sizeof (mntopts) / sizeof (mntopt_t),
2157c478bd9Sstevel@tonic-gate 	(mntopt_t *)&mntopts[0]
2167c478bd9Sstevel@tonic-gate };
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate  * File system operation dispatch functions.
2207c478bd9Sstevel@tonic-gate  */
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate int
fsop_mount(vfs_t * vfsp,vnode_t * mvp,struct mounta * uap,cred_t * cr)2237c478bd9Sstevel@tonic-gate fsop_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
2247c478bd9Sstevel@tonic-gate {
2257c478bd9Sstevel@tonic-gate 	return (*(vfsp)->vfs_op->vfs_mount)(vfsp, mvp, uap, cr);
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate int
fsop_unmount(vfs_t * vfsp,int flag,cred_t * cr)2297c478bd9Sstevel@tonic-gate fsop_unmount(vfs_t *vfsp, int flag, cred_t *cr)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	return (*(vfsp)->vfs_op->vfs_unmount)(vfsp, flag, cr);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate int
fsop_root(vfs_t * vfsp,vnode_t ** vpp)2357c478bd9Sstevel@tonic-gate fsop_root(vfs_t *vfsp, vnode_t **vpp)
2367c478bd9Sstevel@tonic-gate {
2377c478bd9Sstevel@tonic-gate 	refstr_t *mntpt;
2387c478bd9Sstevel@tonic-gate 	int ret = (*(vfsp)->vfs_op->vfs_root)(vfsp, vpp);
2397c478bd9Sstevel@tonic-gate 	/*
2407c478bd9Sstevel@tonic-gate 	 * Make sure this root has a path.  With lofs, it is possible to have
2417c478bd9Sstevel@tonic-gate 	 * a NULL mountpoint.
2427c478bd9Sstevel@tonic-gate 	 */
243e2fc3408SPatrick Mooney 	if (ret == 0 && vfsp->vfs_mntpt != NULL &&
244e2fc3408SPatrick Mooney 	    (*vpp)->v_path == vn_vpath_empty) {
245e2fc3408SPatrick Mooney 		const char *path;
246e2fc3408SPatrick Mooney 
2477c478bd9Sstevel@tonic-gate 		mntpt = vfs_getmntpoint(vfsp);
248e2fc3408SPatrick Mooney 		path = refstr_value(mntpt);
249e2fc3408SPatrick Mooney 		vn_setpath_str(*vpp, path, strlen(path));
2507c478bd9Sstevel@tonic-gate 		refstr_rele(mntpt);
2517c478bd9Sstevel@tonic-gate 	}
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	return (ret);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate int
fsop_statfs(vfs_t * vfsp,statvfs64_t * sp)2577c478bd9Sstevel@tonic-gate fsop_statfs(vfs_t *vfsp, statvfs64_t *sp)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate 	return (*(vfsp)->vfs_op->vfs_statvfs)(vfsp, sp);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate int
fsop_sync(vfs_t * vfsp,short flag,cred_t * cr)2637c478bd9Sstevel@tonic-gate fsop_sync(vfs_t *vfsp, short flag, cred_t *cr)
2647c478bd9Sstevel@tonic-gate {
2657c478bd9Sstevel@tonic-gate 	return (*(vfsp)->vfs_op->vfs_sync)(vfsp, flag, cr);
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate int
fsop_vget(vfs_t * vfsp,vnode_t ** vpp,fid_t * fidp)2697c478bd9Sstevel@tonic-gate fsop_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
2707c478bd9Sstevel@tonic-gate {
271da6c28aaSamw 	/*
272da6c28aaSamw 	 * In order to handle system attribute fids in a manner
273da6c28aaSamw 	 * transparent to the underlying fs, we embed the fid for
274da6c28aaSamw 	 * the sysattr parent object in the sysattr fid and tack on
275da6c28aaSamw 	 * some extra bytes that only the sysattr layer knows about.
276da6c28aaSamw 	 *
277da6c28aaSamw 	 * This guarantees that sysattr fids are larger than other fids
2789660e5cbSJanice Chang 	 * for this vfs. If the vfs supports the sysattr view interface
2799660e5cbSJanice Chang 	 * (as indicated by VFSFT_SYSATTR_VIEWS), we cannot have a size
2809660e5cbSJanice Chang 	 * collision with XATTR_FIDSZ.
281da6c28aaSamw 	 */
2829660e5cbSJanice Chang 	if (vfs_has_feature(vfsp, VFSFT_SYSATTR_VIEWS) &&
283da6c28aaSamw 	    fidp->fid_len == XATTR_FIDSZ)
284da6c28aaSamw 		return (xattr_dir_vget(vfsp, vpp, fidp));
285da6c28aaSamw 
2867c478bd9Sstevel@tonic-gate 	return (*(vfsp)->vfs_op->vfs_vget)(vfsp, vpp, fidp);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate int
fsop_mountroot(vfs_t * vfsp,enum whymountroot reason)2907c478bd9Sstevel@tonic-gate fsop_mountroot(vfs_t *vfsp, enum whymountroot reason)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 	return (*(vfsp)->vfs_op->vfs_mountroot)(vfsp, reason);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate void
fsop_freefs(vfs_t * vfsp)2967c478bd9Sstevel@tonic-gate fsop_freefs(vfs_t *vfsp)
2977c478bd9Sstevel@tonic-gate {
2987c478bd9Sstevel@tonic-gate 	(*(vfsp)->vfs_op->vfs_freevfs)(vfsp);
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate int
fsop_vnstate(vfs_t * vfsp,vnode_t * vp,vntrans_t nstate)3027c478bd9Sstevel@tonic-gate fsop_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate)
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate 	return ((*(vfsp)->vfs_op->vfs_vnstate)(vfsp, vp, nstate));
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate int
fsop_sync_by_kind(int fstype,short flag,cred_t * cr)3087c478bd9Sstevel@tonic-gate fsop_sync_by_kind(int fstype, short flag, cred_t *cr)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate 	ASSERT((fstype >= 0) && (fstype < nfstype));
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	if (ALLOCATED_VFSSW(&vfssw[fstype]) && VFS_INSTALLED(&vfssw[fstype]))
3137c478bd9Sstevel@tonic-gate 		return (*vfssw[fstype].vsw_vfsops.vfs_sync) (NULL, flag, cr);
3147c478bd9Sstevel@tonic-gate 	else
3157c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate /*
3197c478bd9Sstevel@tonic-gate  * File system initialization.  vfs_setfsops() must be called from a file
3207c478bd9Sstevel@tonic-gate  * system's init routine.
3217c478bd9Sstevel@tonic-gate  */
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate static int
fs_copyfsops(const fs_operation_def_t * template,vfsops_t * actual,int * unused_ops)3247c478bd9Sstevel@tonic-gate fs_copyfsops(const fs_operation_def_t *template, vfsops_t *actual,
3257c478bd9Sstevel@tonic-gate     int *unused_ops)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate 	static const fs_operation_trans_def_t vfs_ops_table[] = {
3287c478bd9Sstevel@tonic-gate 		VFSNAME_MOUNT, offsetof(vfsops_t, vfs_mount),
3297c478bd9Sstevel@tonic-gate 			fs_nosys, fs_nosys,
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 		VFSNAME_UNMOUNT, offsetof(vfsops_t, vfs_unmount),
3327c478bd9Sstevel@tonic-gate 			fs_nosys, fs_nosys,
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 		VFSNAME_ROOT, offsetof(vfsops_t, vfs_root),
3357c478bd9Sstevel@tonic-gate 			fs_nosys, fs_nosys,
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 		VFSNAME_STATVFS, offsetof(vfsops_t, vfs_statvfs),
3387c478bd9Sstevel@tonic-gate 			fs_nosys, fs_nosys,
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 		VFSNAME_SYNC, offsetof(vfsops_t, vfs_sync),
3417c478bd9Sstevel@tonic-gate 			(fs_generic_func_p) fs_sync,
3427c478bd9Sstevel@tonic-gate 			(fs_generic_func_p) fs_sync,	/* No errors allowed */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 		VFSNAME_VGET, offsetof(vfsops_t, vfs_vget),
3457c478bd9Sstevel@tonic-gate 			fs_nosys, fs_nosys,
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 		VFSNAME_MOUNTROOT, offsetof(vfsops_t, vfs_mountroot),
3487c478bd9Sstevel@tonic-gate 			fs_nosys, fs_nosys,
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 		VFSNAME_FREEVFS, offsetof(vfsops_t, vfs_freevfs),
351b6d49c84SToomas Soome 			(fs_generic_func_p)(uintptr_t)fs_freevfs,
352b6d49c84SToomas Soome 			/* Shouldn't fail */
353b6d49c84SToomas Soome 			(fs_generic_func_p)(uintptr_t)fs_freevfs,
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		VFSNAME_VNSTATE, offsetof(vfsops_t, vfs_vnstate),
3567c478bd9Sstevel@tonic-gate 			(fs_generic_func_p)fs_nosys,
3577c478bd9Sstevel@tonic-gate 			(fs_generic_func_p)fs_nosys,
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 		NULL, 0, NULL, NULL
3607c478bd9Sstevel@tonic-gate 	};
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	return (fs_build_vector(actual, unused_ops, vfs_ops_table, template));
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
365e7cbe64fSgw void
zfs_boot_init(void)366406fc510SToomas Soome zfs_boot_init(void)
367406fc510SToomas Soome {
368e7cbe64fSgw 	if (strcmp(rootfs.bo_fstype, MNTTYPE_ZFS) == 0)
369e7cbe64fSgw 		spa_boot_init();
370e7cbe64fSgw }
371e7cbe64fSgw 
3727c478bd9Sstevel@tonic-gate int
vfs_setfsops(int fstype,const fs_operation_def_t * template,vfsops_t ** actual)3737c478bd9Sstevel@tonic-gate vfs_setfsops(int fstype, const fs_operation_def_t *template, vfsops_t **actual)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	int error;
3767c478bd9Sstevel@tonic-gate 	int unused_ops;
3777c478bd9Sstevel@tonic-gate 
378d320ee2dSrsb 	/*
379d320ee2dSrsb 	 * Verify that fstype refers to a valid fs.  Note that
380d320ee2dSrsb 	 * 0 is valid since it's used to set "stray" ops.
381d320ee2dSrsb 	 */
382d320ee2dSrsb 	if ((fstype < 0) || (fstype >= nfstype))
3837c478bd9Sstevel@tonic-gate 		return (EINVAL);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	if (!ALLOCATED_VFSSW(&vfssw[fstype]))
3867c478bd9Sstevel@tonic-gate 		return (EINVAL);
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	/* Set up the operations vector. */
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	error = fs_copyfsops(template, &vfssw[fstype].vsw_vfsops, &unused_ops);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (error != 0)
3937c478bd9Sstevel@tonic-gate 		return (error);
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	vfssw[fstype].vsw_flag |= VSW_INSTALLED;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if (actual != NULL)
3987c478bd9Sstevel@tonic-gate 		*actual = &vfssw[fstype].vsw_vfsops;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate #if DEBUG
4017c478bd9Sstevel@tonic-gate 	if (unused_ops != 0)
4027c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "vfs_setfsops: %s: %d operations supplied "
4037c478bd9Sstevel@tonic-gate 		    "but not used", vfssw[fstype].vsw_name, unused_ops);
4047c478bd9Sstevel@tonic-gate #endif
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	return (0);
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate int
vfs_makefsops(const fs_operation_def_t * template,vfsops_t ** actual)4107c478bd9Sstevel@tonic-gate vfs_makefsops(const fs_operation_def_t *template, vfsops_t **actual)
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate 	int error;
4137c478bd9Sstevel@tonic-gate 	int unused_ops;
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	*actual = (vfsops_t *)kmem_alloc(sizeof (vfsops_t), KM_SLEEP);
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	error = fs_copyfsops(template, *actual, &unused_ops);
4187c478bd9Sstevel@tonic-gate 	if (error != 0) {
4197c478bd9Sstevel@tonic-gate 		kmem_free(*actual, sizeof (vfsops_t));
4207c478bd9Sstevel@tonic-gate 		*actual = NULL;
4217c478bd9Sstevel@tonic-gate 		return (error);
4227c478bd9Sstevel@tonic-gate 	}
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	return (0);
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate /*
4287c478bd9Sstevel@tonic-gate  * Free a vfsops structure created as a result of vfs_makefsops().
4297c478bd9Sstevel@tonic-gate  * NOTE: For a vfsops structure initialized by vfs_setfsops(), use
4307c478bd9Sstevel@tonic-gate  * vfs_freevfsops_by_type().
4317c478bd9Sstevel@tonic-gate  */
4327c478bd9Sstevel@tonic-gate void
vfs_freevfsops(vfsops_t * vfsops)4337c478bd9Sstevel@tonic-gate vfs_freevfsops(vfsops_t *vfsops)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	kmem_free(vfsops, sizeof (vfsops_t));
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate /*
4397c478bd9Sstevel@tonic-gate  * Since the vfsops structure is part of the vfssw table and wasn't
4407c478bd9Sstevel@tonic-gate  * really allocated, we're not really freeing anything.  We keep
4417c478bd9Sstevel@tonic-gate  * the name for consistency with vfs_freevfsops().  We do, however,
4427c478bd9Sstevel@tonic-gate  * need to take care of a little bookkeeping.
4437c478bd9Sstevel@tonic-gate  * NOTE: For a vfsops structure created by vfs_setfsops(), use
4447c478bd9Sstevel@tonic-gate  * vfs_freevfsops_by_type().
4457c478bd9Sstevel@tonic-gate  */
4467c478bd9Sstevel@tonic-gate int
vfs_freevfsops_by_type(int fstype)4477c478bd9Sstevel@tonic-gate vfs_freevfsops_by_type(int fstype)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	/* Verify that fstype refers to a loaded fs (and not fsid 0). */
4517c478bd9Sstevel@tonic-gate 	if ((fstype <= 0) || (fstype >= nfstype))
4527c478bd9Sstevel@tonic-gate 		return (EINVAL);
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	WLOCK_VFSSW();
4557c478bd9Sstevel@tonic-gate 	if ((vfssw[fstype].vsw_flag & VSW_INSTALLED) == 0) {
4567c478bd9Sstevel@tonic-gate 		WUNLOCK_VFSSW();
4577c478bd9Sstevel@tonic-gate 		return (EINVAL);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	vfssw[fstype].vsw_flag &= ~VSW_INSTALLED;
4617c478bd9Sstevel@tonic-gate 	WUNLOCK_VFSSW();
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	return (0);
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate /* Support routines used to reference vfs_op */
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate /* Set the operations vector for a vfs */
4697c478bd9Sstevel@tonic-gate void
vfs_setops(vfs_t * vfsp,vfsops_t * vfsops)4707c478bd9Sstevel@tonic-gate vfs_setops(vfs_t *vfsp, vfsops_t *vfsops)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate 	vfsops_t	*op;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	ASSERT(vfsp != NULL);
4757c478bd9Sstevel@tonic-gate 	ASSERT(vfsops != NULL);
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	op = vfsp->vfs_op;
4787c478bd9Sstevel@tonic-gate 	membar_consumer();
479da6c28aaSamw 	if (vfsp->vfs_femhead == NULL &&
48075d94465SJosef 'Jeff' Sipek 	    atomic_cas_ptr(&vfsp->vfs_op, op, vfsops) == op) {
4817c478bd9Sstevel@tonic-gate 		return;
4827c478bd9Sstevel@tonic-gate 	}
4837c478bd9Sstevel@tonic-gate 	fsem_setvfsops(vfsp, vfsops);
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate /* Retrieve the operations vector for a vfs */
4877c478bd9Sstevel@tonic-gate vfsops_t *
vfs_getops(vfs_t * vfsp)4887c478bd9Sstevel@tonic-gate vfs_getops(vfs_t *vfsp)
4897c478bd9Sstevel@tonic-gate {
4907c478bd9Sstevel@tonic-gate 	vfsops_t	*op;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	ASSERT(vfsp != NULL);
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	op = vfsp->vfs_op;
4957c478bd9Sstevel@tonic-gate 	membar_consumer();
496da6c28aaSamw 	if (vfsp->vfs_femhead == NULL && op == vfsp->vfs_op) {
4977c478bd9Sstevel@tonic-gate 		return (op);
4987c478bd9Sstevel@tonic-gate 	} else {
4997c478bd9Sstevel@tonic-gate 		return (fsem_getvfsops(vfsp));
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate /*
5047c478bd9Sstevel@tonic-gate  * Returns non-zero (1) if the vfsops matches that of the vfs.
5057c478bd9Sstevel@tonic-gate  * Returns zero (0) if not.
5067c478bd9Sstevel@tonic-gate  */
5077c478bd9Sstevel@tonic-gate int
vfs_matchops(vfs_t * vfsp,vfsops_t * vfsops)5087c478bd9Sstevel@tonic-gate vfs_matchops(vfs_t *vfsp, vfsops_t *vfsops)
5097c478bd9Sstevel@tonic-gate {
5107c478bd9Sstevel@tonic-gate 	return (vfs_getops(vfsp) == vfsops);
5117c478bd9Sstevel@tonic-gate }
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate /*
5147c478bd9Sstevel@tonic-gate  * Returns non-zero (1) if the file system has installed a non-default,
5157c478bd9Sstevel@tonic-gate  * non-error vfs_sync routine.  Returns zero (0) otherwise.
5167c478bd9Sstevel@tonic-gate  */
5177c478bd9Sstevel@tonic-gate int
vfs_can_sync(vfs_t * vfsp)5187c478bd9Sstevel@tonic-gate vfs_can_sync(vfs_t *vfsp)
5197c478bd9Sstevel@tonic-gate {
5207c478bd9Sstevel@tonic-gate 	/* vfs_sync() routine is not the default/error function */
5217c478bd9Sstevel@tonic-gate 	return (vfs_getops(vfsp)->vfs_sync != fs_sync);
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate /*
5257c478bd9Sstevel@tonic-gate  * Initialize a vfs structure.
5267c478bd9Sstevel@tonic-gate  */
5277c478bd9Sstevel@tonic-gate void
vfs_init(vfs_t * vfsp,vfsops_t * op,void * data)5287c478bd9Sstevel@tonic-gate vfs_init(vfs_t *vfsp, vfsops_t *op, void *data)
5297c478bd9Sstevel@tonic-gate {
530da6c28aaSamw 	/* Other initialization has been moved to vfs_alloc() */
5317c478bd9Sstevel@tonic-gate 	vfsp->vfs_count = 0;
5327c478bd9Sstevel@tonic-gate 	vfsp->vfs_next = vfsp;
5337c478bd9Sstevel@tonic-gate 	vfsp->vfs_prev = vfsp;
5347c478bd9Sstevel@tonic-gate 	vfsp->vfs_zone_next = vfsp;
5357c478bd9Sstevel@tonic-gate 	vfsp->vfs_zone_prev = vfsp;
536406fc510SToomas Soome 	vfsp->vfs_lofi_id = 0;
537da6c28aaSamw 	sema_init(&vfsp->vfs_reflock, 1, NULL, SEMA_DEFAULT, NULL);
538da6c28aaSamw 	vfsimpl_setup(vfsp);
5397c478bd9Sstevel@tonic-gate 	vfsp->vfs_data = (data);
5407c478bd9Sstevel@tonic-gate 	vfs_setops((vfsp), (op));
5417c478bd9Sstevel@tonic-gate }
5427c478bd9Sstevel@tonic-gate 
543ddfcde86Srsb /*
544ddfcde86Srsb  * Allocate and initialize the vfs implementation private data
545ddfcde86Srsb  * structure, vfs_impl_t.
546ddfcde86Srsb  */
547ddfcde86Srsb void
vfsimpl_setup(vfs_t * vfsp)548ddfcde86Srsb vfsimpl_setup(vfs_t *vfsp)
549ddfcde86Srsb {
550da6c28aaSamw 	int i;
551da6c28aaSamw 
552da6c28aaSamw 	if (vfsp->vfs_implp != NULL) {
553da6c28aaSamw 		return;
554da6c28aaSamw 	}
555da6c28aaSamw 
556ddfcde86Srsb 	vfsp->vfs_implp = kmem_alloc(sizeof (vfs_impl_t), KM_SLEEP);
557da6c28aaSamw 	/* Note that these are #define'd in vfs.h */
558ddfcde86Srsb 	vfsp->vfs_vskap = NULL;
559ddfcde86Srsb 	vfsp->vfs_fstypevsp = NULL;
560da6c28aaSamw 
561da6c28aaSamw 	/* Set size of counted array, then zero the array */
562da6c28aaSamw 	vfsp->vfs_featureset[0] = VFS_FEATURE_MAXSZ - 1;
563da6c28aaSamw 	for (i = 1; i <  VFS_FEATURE_MAXSZ; i++) {
564da6c28aaSamw 		vfsp->vfs_featureset[i] = 0;
565da6c28aaSamw 	}
566ddfcde86Srsb }
567ddfcde86Srsb 
568ddfcde86Srsb /*
569ddfcde86Srsb  * Release the vfs_impl_t structure, if it exists. Some unbundled
570ddfcde86Srsb  * filesystems may not use the newer version of vfs and thus
571ddfcde86Srsb  * would not contain this implementation private data structure.
572ddfcde86Srsb  */
573ddfcde86Srsb void
vfsimpl_teardown(vfs_t * vfsp)574ddfcde86Srsb vfsimpl_teardown(vfs_t *vfsp)
575ddfcde86Srsb {
576ddfcde86Srsb 	vfs_impl_t	*vip = vfsp->vfs_implp;
577ddfcde86Srsb 
578ddfcde86Srsb 	if (vip == NULL)
579ddfcde86Srsb 		return;
580ddfcde86Srsb 
581ddfcde86Srsb 	kmem_free(vfsp->vfs_implp, sizeof (vfs_impl_t));
582ddfcde86Srsb 	vfsp->vfs_implp = NULL;
583ddfcde86Srsb }
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate /*
5867c478bd9Sstevel@tonic-gate  * VFS system calls: mount, umount, syssync, statfs, fstatfs, statvfs,
5877c478bd9Sstevel@tonic-gate  * fstatvfs, and sysfs moved to common/syscall.
5887c478bd9Sstevel@tonic-gate  */
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate /*
5917c478bd9Sstevel@tonic-gate  * Update every mounted file system.  We call the vfs_sync operation of
5927c478bd9Sstevel@tonic-gate  * each file system type, passing it a NULL vfsp to indicate that all
5937c478bd9Sstevel@tonic-gate  * mounted file systems of that type should be updated.
5947c478bd9Sstevel@tonic-gate  */
5957c478bd9Sstevel@tonic-gate void
vfs_sync(int flag)5967c478bd9Sstevel@tonic-gate vfs_sync(int flag)
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate 	struct vfssw *vswp;
5997c478bd9Sstevel@tonic-gate 	RLOCK_VFSSW();
6007c478bd9Sstevel@tonic-gate 	for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) {
6017c478bd9Sstevel@tonic-gate 		if (ALLOCATED_VFSSW(vswp) && VFS_INSTALLED(vswp)) {
6027c478bd9Sstevel@tonic-gate 			vfs_refvfssw(vswp);
6037c478bd9Sstevel@tonic-gate 			RUNLOCK_VFSSW();
6047c478bd9Sstevel@tonic-gate 			(void) (*vswp->vsw_vfsops.vfs_sync)(NULL, flag,
6057c478bd9Sstevel@tonic-gate 			    CRED());
6067c478bd9Sstevel@tonic-gate 			vfs_unrefvfssw(vswp);
6077c478bd9Sstevel@tonic-gate 			RLOCK_VFSSW();
6087c478bd9Sstevel@tonic-gate 		}
6097c478bd9Sstevel@tonic-gate 	}
6107c478bd9Sstevel@tonic-gate 	RUNLOCK_VFSSW();
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate void
sync(void)6147c478bd9Sstevel@tonic-gate sync(void)
6157c478bd9Sstevel@tonic-gate {
6167c478bd9Sstevel@tonic-gate 	vfs_sync(0);
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate  * External routines.
6217c478bd9Sstevel@tonic-gate  */
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate krwlock_t vfssw_lock;	/* lock accesses to vfssw */
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate /*
6267c478bd9Sstevel@tonic-gate  * Lock for accessing the vfs linked list.  Initialized in vfs_mountroot(),
6277c478bd9Sstevel@tonic-gate  * but otherwise should be accessed only via vfs_list_lock() and
6287c478bd9Sstevel@tonic-gate  * vfs_list_unlock().  Also used to protect the timestamp for mods to the list.
6297c478bd9Sstevel@tonic-gate  */
6307c478bd9Sstevel@tonic-gate static krwlock_t vfslist;
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate  * Mount devfs on /devices. This is done right after root is mounted
6347c478bd9Sstevel@tonic-gate  * to provide device access support for the system
6357c478bd9Sstevel@tonic-gate  */
6367c478bd9Sstevel@tonic-gate static void
vfs_mountdevices(void)6377c478bd9Sstevel@tonic-gate vfs_mountdevices(void)
6387c478bd9Sstevel@tonic-gate {
6397c478bd9Sstevel@tonic-gate 	struct vfssw *vsw;
6407c478bd9Sstevel@tonic-gate 	struct vnode *mvp;
6417c478bd9Sstevel@tonic-gate 	struct mounta mounta = {	/* fake mounta for devfs_mount() */
6427c478bd9Sstevel@tonic-gate 		NULL,
6437c478bd9Sstevel@tonic-gate 		NULL,
6447c478bd9Sstevel@tonic-gate 		MS_SYSSPACE,
6457c478bd9Sstevel@tonic-gate 		NULL,
6467c478bd9Sstevel@tonic-gate 		NULL,
6477c478bd9Sstevel@tonic-gate 		0,
6487c478bd9Sstevel@tonic-gate 		NULL,
6497c478bd9Sstevel@tonic-gate 		0
6507c478bd9Sstevel@tonic-gate 	};
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	/*
6537c478bd9Sstevel@tonic-gate 	 * _init devfs module to fill in the vfssw
6547c478bd9Sstevel@tonic-gate 	 */
6557c478bd9Sstevel@tonic-gate 	if (modload("fs", "devfs") == -1)
656ae115bc7Smrj 		panic("Cannot _init devfs module");
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	/*
6597c478bd9Sstevel@tonic-gate 	 * Hold vfs
6607c478bd9Sstevel@tonic-gate 	 */
6617c478bd9Sstevel@tonic-gate 	RLOCK_VFSSW();
6627c478bd9Sstevel@tonic-gate 	vsw = vfs_getvfsswbyname("devfs");
6637c478bd9Sstevel@tonic-gate 	VFS_INIT(&devices, &vsw->vsw_vfsops, NULL);
6647c478bd9Sstevel@tonic-gate 	VFS_HOLD(&devices);
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	/*
6677c478bd9Sstevel@tonic-gate 	 * Locate mount point
6687c478bd9Sstevel@tonic-gate 	 */
6697c478bd9Sstevel@tonic-gate 	if (lookupname("/devices", UIO_SYSSPACE, FOLLOW, NULLVPP, &mvp))
670ae115bc7Smrj 		panic("Cannot find /devices");
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	/*
6737c478bd9Sstevel@tonic-gate 	 * Perform the mount of /devices
6747c478bd9Sstevel@tonic-gate 	 */
6757c478bd9Sstevel@tonic-gate 	if (VFS_MOUNT(&devices, mvp, &mounta, CRED()))
676ae115bc7Smrj 		panic("Cannot mount /devices");
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	RUNLOCK_VFSSW();
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 	/*
6817c478bd9Sstevel@tonic-gate 	 * Set appropriate members and add to vfs list for mnttab display
6827c478bd9Sstevel@tonic-gate 	 */
683d7de0ceaSRobert Harris 	vfs_setresource(&devices, "/devices", 0);
684d7de0ceaSRobert Harris 	vfs_setmntpoint(&devices, "/devices", 0);
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	/*
6877c478bd9Sstevel@tonic-gate 	 * Hold the root of /devices so it won't go away
6887c478bd9Sstevel@tonic-gate 	 */
6897c478bd9Sstevel@tonic-gate 	if (VFS_ROOT(&devices, &devicesdir))
690