xref: /onnv-gate/usr/src/uts/common/fs/zfs/zfs_ioctl.c (revision 5450:b25030891c44)
1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
51485Slling  * Common Development and Distribution License (the "License").
61485Slling  * You may not use this file except in compliance with the License.
7789Sahrens  *
8789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens  * or http://www.opensolaris.org/os/licensing.
10789Sahrens  * See the License for the specific language governing permissions
11789Sahrens  * and limitations under the License.
12789Sahrens  *
13789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens  *
19789Sahrens  * CDDL HEADER END
20789Sahrens  */
21789Sahrens /*
223444Sek110237  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23789Sahrens  * Use is subject to license terms.
24789Sahrens  */
25789Sahrens 
26789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
27789Sahrens 
28789Sahrens #include <sys/types.h>
29789Sahrens #include <sys/param.h>
30789Sahrens #include <sys/errno.h>
31789Sahrens #include <sys/uio.h>
32789Sahrens #include <sys/buf.h>
33789Sahrens #include <sys/modctl.h>
34789Sahrens #include <sys/open.h>
35789Sahrens #include <sys/file.h>
36789Sahrens #include <sys/kmem.h>
37789Sahrens #include <sys/conf.h>
38789Sahrens #include <sys/cmn_err.h>
39789Sahrens #include <sys/stat.h>
40789Sahrens #include <sys/zfs_ioctl.h>
415331Samw #include <sys/zfs_i18n.h>
425331Samw #include <sys/zfs_znode.h>
43789Sahrens #include <sys/zap.h>
44789Sahrens #include <sys/spa.h>
453912Slling #include <sys/spa_impl.h>
46789Sahrens #include <sys/vdev.h>
473912Slling #include <sys/vdev_impl.h>
48789Sahrens #include <sys/dmu.h>
49789Sahrens #include <sys/dsl_dir.h>
50789Sahrens #include <sys/dsl_dataset.h>
51789Sahrens #include <sys/dsl_prop.h>
524543Smarks #include <sys/dsl_deleg.h>
534543Smarks #include <sys/dmu_objset.h>
54789Sahrens #include <sys/ddi.h>
55789Sahrens #include <sys/sunddi.h>
56789Sahrens #include <sys/sunldi.h>
57789Sahrens #include <sys/policy.h>
58789Sahrens #include <sys/zone.h>
59789Sahrens #include <sys/nvpair.h>
60789Sahrens #include <sys/pathname.h>
61789Sahrens #include <sys/mount.h>
62789Sahrens #include <sys/sdt.h>
63789Sahrens #include <sys/fs/zfs.h>
64789Sahrens #include <sys/zfs_ctldir.h>
655331Samw #include <sys/zfs_dir.h>
662885Sahrens #include <sys/zvol.h>
674543Smarks #include <sharefs/share.h>
684577Sahrens #include <sys/zfs_znode.h>
695326Sek110237 #include <sys/zfs_vfsops.h>
705326Sek110237 #include <sys/dmu_objset.h>
71789Sahrens 
72789Sahrens #include "zfs_namecheck.h"
732676Seschrock #include "zfs_prop.h"
744543Smarks #include "zfs_deleg.h"
75789Sahrens 
76789Sahrens extern struct modlfs zfs_modlfs;
77789Sahrens 
78789Sahrens extern void zfs_init(void);
79789Sahrens extern void zfs_fini(void);
80789Sahrens 
81789Sahrens ldi_ident_t zfs_li = NULL;
82789Sahrens dev_info_t *zfs_dip;
83789Sahrens 
84789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *);
854543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *);
86789Sahrens 
87789Sahrens typedef struct zfs_ioc_vec {
88789Sahrens 	zfs_ioc_func_t		*zvec_func;
89789Sahrens 	zfs_secpolicy_func_t	*zvec_secpolicy;
90789Sahrens 	enum {
914577Sahrens 		NO_NAME,
924577Sahrens 		POOL_NAME,
934577Sahrens 		DATASET_NAME
944543Smarks 	} zvec_namecheck;
954543Smarks 	boolean_t		zvec_his_log;
96789Sahrens } zfs_ioc_vec_t;
97789Sahrens 
98789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */
99789Sahrens void
100789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
101789Sahrens {
102789Sahrens 	const char *newfile;
103789Sahrens 	char buf[256];
104789Sahrens 	va_list adx;
105789Sahrens 
106789Sahrens 	/*
107789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
108789Sahrens 	 */
109789Sahrens 	newfile = strrchr(file, '/');
110789Sahrens 	if (newfile != NULL) {
111789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
112789Sahrens 	} else {
113789Sahrens 		newfile = file;
114789Sahrens 	}
115789Sahrens 
116789Sahrens 	va_start(adx, fmt);
117789Sahrens 	(void) vsnprintf(buf, sizeof (buf), fmt, adx);
118789Sahrens 	va_end(adx);
119789Sahrens 
120789Sahrens 	/*
121789Sahrens 	 * To get this data, use the zfs-dprintf probe as so:
122789Sahrens 	 * dtrace -q -n 'zfs-dprintf \
123789Sahrens 	 *	/stringof(arg0) == "dbuf.c"/ \
124789Sahrens 	 *	{printf("%s: %s", stringof(arg1), stringof(arg3))}'
125789Sahrens 	 * arg0 = file name
126789Sahrens 	 * arg1 = function name
127789Sahrens 	 * arg2 = line number
128789Sahrens 	 * arg3 = message
129789Sahrens 	 */
130789Sahrens 	DTRACE_PROBE4(zfs__dprintf,
131789Sahrens 	    char *, newfile, char *, func, int, line, char *, buf);
132789Sahrens }
133789Sahrens 
1344543Smarks static void
1354715Sek110237 history_str_free(char *buf)
1364715Sek110237 {
1374715Sek110237 	kmem_free(buf, HIS_MAX_RECORD_LEN);
1384715Sek110237 }
1394715Sek110237 
1404715Sek110237 static char *
1414715Sek110237 history_str_get(zfs_cmd_t *zc)
1424715Sek110237 {
1434715Sek110237 	char *buf;
1444715Sek110237 
1454715Sek110237 	if (zc->zc_history == NULL)
1464715Sek110237 		return (NULL);
1474715Sek110237 
1484715Sek110237 	buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP);
1494715Sek110237 	if (copyinstr((void *)(uintptr_t)zc->zc_history,
1504715Sek110237 	    buf, HIS_MAX_RECORD_LEN, NULL) != 0) {
1514715Sek110237 		history_str_free(buf);
1524715Sek110237 		return (NULL);
1534715Sek110237 	}
1544715Sek110237 
1554715Sek110237 	buf[HIS_MAX_RECORD_LEN -1] = '\0';
1564715Sek110237 
1574715Sek110237 	return (buf);
1584715Sek110237 }
1594715Sek110237 
1605375Stimh /*
1615375Stimh  * zfs_check_version
1625375Stimh  *
1635375Stimh  *	Return non-zero if the spa version is less than requested version.
1645375Stimh  */
1655331Samw static int
1665331Samw zfs_check_version(const char *name, int version)
1675331Samw {
1685331Samw 
1695331Samw 	spa_t *spa;
1705331Samw 
1715331Samw 	if (spa_open(name, &spa, FTAG) == 0) {
1725331Samw 		if (spa_version(spa) < version) {
1735331Samw 			spa_close(spa, FTAG);
1745331Samw 			return (1);
1755331Samw 		}
1765331Samw 		spa_close(spa, FTAG);
1775331Samw 	}
1785331Samw 	return (0);
1795331Samw }
1805331Samw 
1814715Sek110237 static void
1824543Smarks zfs_log_history(zfs_cmd_t *zc)
1834543Smarks {
1844543Smarks 	spa_t *spa;
1854603Sahrens 	char *buf;
1864543Smarks 
1874715Sek110237 	if ((buf = history_str_get(zc)) == NULL)
1884577Sahrens 		return;
1894577Sahrens 
1904715Sek110237 	if (spa_open(zc->zc_name, &spa, FTAG) == 0) {
1914715Sek110237 		if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY)
1924715Sek110237 			(void) spa_history_log(spa, buf, LOG_CMD_NORMAL);
1934715Sek110237 		spa_close(spa, FTAG);
1944543Smarks 	}
1954715Sek110237 	history_str_free(buf);
1964543Smarks }
1974543Smarks 
198789Sahrens /*
199789Sahrens  * Policy for top-level read operations (list pools).  Requires no privileges,
200789Sahrens  * and can be used in the local zone, as there is no associated dataset.
201789Sahrens  */
202789Sahrens /* ARGSUSED */
203789Sahrens static int
2044543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr)
205789Sahrens {
206789Sahrens 	return (0);
207789Sahrens }
208789Sahrens 
209789Sahrens /*
210789Sahrens  * Policy for dataset read operations (list children, get statistics).  Requires
211789Sahrens  * no privileges, but must be visible in the local zone.
212789Sahrens  */
213789Sahrens /* ARGSUSED */
214789Sahrens static int
2154543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr)
216789Sahrens {
217789Sahrens 	if (INGLOBALZONE(curproc) ||
2184543Smarks 	    zone_dataset_visible(zc->zc_name, NULL))
219789Sahrens 		return (0);
220789Sahrens 
221789Sahrens 	return (ENOENT);
222789Sahrens }
223789Sahrens 
224789Sahrens static int
225789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr)
226789Sahrens {
227789Sahrens 	uint64_t zoned;
228789Sahrens 	int writable = 1;
229789Sahrens 
230789Sahrens 	/*
231789Sahrens 	 * The dataset must be visible by this zone -- check this first
232789Sahrens 	 * so they don't see EPERM on something they shouldn't know about.
233789Sahrens 	 */
234789Sahrens 	if (!INGLOBALZONE(curproc) &&
235789Sahrens 	    !zone_dataset_visible(dataset, &writable))
236789Sahrens 		return (ENOENT);
237789Sahrens 
238789Sahrens 	if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL))
239789Sahrens 		return (ENOENT);
240789Sahrens 
241789Sahrens 	if (INGLOBALZONE(curproc)) {
242789Sahrens 		/*
243789Sahrens 		 * If the fs is zoned, only root can access it from the
244789Sahrens 		 * global zone.
245789Sahrens 		 */
246789Sahrens 		if (secpolicy_zfs(cr) && zoned)
247789Sahrens 			return (EPERM);
248789Sahrens 	} else {
249789Sahrens 		/*
250789Sahrens 		 * If we are in a local zone, the 'zoned' property must be set.
251789Sahrens 		 */
252789Sahrens 		if (!zoned)
253789Sahrens 			return (EPERM);
254789Sahrens 
255789Sahrens 		/* must be writable by this zone */
256789Sahrens 		if (!writable)
257789Sahrens 			return (EPERM);
258789Sahrens 	}
259789Sahrens 	return (0);
260789Sahrens }
261789Sahrens 
262789Sahrens int
2634543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
264789Sahrens {
265789Sahrens 	int error;
266789Sahrens 
2674543Smarks 	error = zfs_dozonecheck(name, cr);
2684543Smarks 	if (error == 0) {
2694543Smarks 		error = secpolicy_zfs(cr);
2704670Sahrens 		if (error)
2714543Smarks 			error = dsl_deleg_access(name, perm, cr);
2724543Smarks 	}
2734543Smarks 	return (error);
2744543Smarks }
2754543Smarks 
2764543Smarks static int
2774543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr)
2784543Smarks {
2794543Smarks 	/*
2804543Smarks 	 * Check permissions for special properties.
2814543Smarks 	 */
2824543Smarks 	switch (prop) {
2834543Smarks 	case ZFS_PROP_ZONED:
2844543Smarks 		/*
2854543Smarks 		 * Disallow setting of 'zoned' from within a local zone.
2864543Smarks 		 */
2874543Smarks 		if (!INGLOBALZONE(curproc))
2884543Smarks 			return (EPERM);
2894543Smarks 		break;
290789Sahrens 
2914543Smarks 	case ZFS_PROP_QUOTA:
2924543Smarks 		if (!INGLOBALZONE(curproc)) {
2934543Smarks 			uint64_t zoned;
2944543Smarks 			char setpoint[MAXNAMELEN];
2954543Smarks 			/*
2964543Smarks 			 * Unprivileged users are allowed to modify the
2974543Smarks 			 * quota on things *under* (ie. contained by)
2984543Smarks 			 * the thing they own.
2994543Smarks 			 */
3004543Smarks 			if (dsl_prop_get_integer(name, "zoned", &zoned,
3014543Smarks 			    setpoint))
3024543Smarks 				return (EPERM);
3034670Sahrens 			if (!zoned || strlen(name) <= strlen(setpoint))
3044543Smarks 				return (EPERM);
3054543Smarks 		}
3064670Sahrens 		break;
3074543Smarks 	}
3084543Smarks 
3094787Sahrens 	return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr));
310789Sahrens }
311789Sahrens 
3124543Smarks int
3134543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr)
3144543Smarks {
3154543Smarks 	int error;
3164543Smarks 
3174543Smarks 	error = zfs_dozonecheck(zc->zc_name, cr);
3184543Smarks 	if (error)
3194543Smarks 		return (error);
3204543Smarks 
3214543Smarks 	/*
3224543Smarks 	 * permission to set permissions will be evaluated later in
3234543Smarks 	 * dsl_deleg_can_allow()
3244543Smarks 	 */
3254543Smarks 	return (0);
3264543Smarks }
3274543Smarks 
3284543Smarks int
3294543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr)
3304543Smarks {
3314543Smarks 	int error;
3324543Smarks 	error = zfs_secpolicy_write_perms(zc->zc_name,
3334543Smarks 	    ZFS_DELEG_PERM_ROLLBACK, cr);
3344543Smarks 	if (error == 0)
3354543Smarks 		error = zfs_secpolicy_write_perms(zc->zc_name,
3364543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr);
3374543Smarks 	return (error);
3384543Smarks }
3394543Smarks 
3404543Smarks int
3414543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr)
3424543Smarks {
3434543Smarks 	return (zfs_secpolicy_write_perms(zc->zc_name,
3444543Smarks 	    ZFS_DELEG_PERM_SEND, cr));
3454543Smarks }
3464543Smarks 
3474543Smarks int
3484543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr)
3494543Smarks {
3504543Smarks 	if (!INGLOBALZONE(curproc))
3514543Smarks 		return (EPERM);
3524543Smarks 
3535367Sahrens 	if (secpolicy_nfs(cr) == 0) {
3544543Smarks 		return (0);
3554543Smarks 	} else {
3564543Smarks 		vnode_t *vp;
3574543Smarks 		int error;
3584543Smarks 
3594543Smarks 		if ((error = lookupname(zc->zc_value, UIO_SYSSPACE,
3604543Smarks 		    NO_FOLLOW, NULL, &vp)) != 0)
3614543Smarks 			return (error);
3624543Smarks 
3634543Smarks 		/* Now make sure mntpnt and dataset are ZFS */
3644543Smarks 
3654543Smarks 		if (vp->v_vfsp->vfs_fstype != zfsfstype ||
3664543Smarks 		    (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource),
3674543Smarks 		    zc->zc_name) != 0)) {
3684543Smarks 			VN_RELE(vp);
3694543Smarks 			return (EPERM);
3704543Smarks 		}
3714543Smarks 
3724543Smarks 		VN_RELE(vp);
3734543Smarks 		return (dsl_deleg_access(zc->zc_name,
3744543Smarks 		    ZFS_DELEG_PERM_SHARE, cr));
3754543Smarks 	}
3764543Smarks }
3774543Smarks 
378789Sahrens static int
3794543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize)
380789Sahrens {
381789Sahrens 	char *cp;
382789Sahrens 
383789Sahrens 	/*
384789Sahrens 	 * Remove the @bla or /bla from the end of the name to get the parent.
385789Sahrens 	 */
3864543Smarks 	(void) strncpy(parent, datasetname, parentsize);
3874543Smarks 	cp = strrchr(parent, '@');
388789Sahrens 	if (cp != NULL) {
389789Sahrens 		cp[0] = '\0';
390789Sahrens 	} else {
3914543Smarks 		cp = strrchr(parent, '/');
392789Sahrens 		if (cp == NULL)
393789Sahrens 			return (ENOENT);
394789Sahrens 		cp[0] = '\0';
395789Sahrens 	}
396789Sahrens 
3974543Smarks 	return (0);
3984543Smarks }
3994543Smarks 
4004543Smarks int
4014543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
4024543Smarks {
4034543Smarks 	int error;
4044543Smarks 
4054543Smarks 	if ((error = zfs_secpolicy_write_perms(name,
4064543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
4074543Smarks 		return (error);
4084543Smarks 
4094543Smarks 	return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr));
4104543Smarks }
4114543Smarks 
4124543Smarks static int
4134543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr)
4144543Smarks {
4154543Smarks 	return (zfs_secpolicy_destroy_perms(zc->zc_name, cr));
4164543Smarks }
4174543Smarks 
4184543Smarks /*
4194543Smarks  * Must have sys_config privilege to check the iscsi permission
4204543Smarks  */
4214543Smarks /* ARGSUSED */
4224543Smarks static int
4234543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr)
4244543Smarks {
4254543Smarks 	return (secpolicy_zfs(cr));
4264543Smarks }
4274543Smarks 
4284543Smarks int
4294543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
4304543Smarks {
4314543Smarks 	char 	parentname[MAXNAMELEN];
4324543Smarks 	int	error;
4334543Smarks 
4344543Smarks 	if ((error = zfs_secpolicy_write_perms(from,
4354543Smarks 	    ZFS_DELEG_PERM_RENAME, cr)) != 0)
4364543Smarks 		return (error);
4374543Smarks 
4384543Smarks 	if ((error = zfs_secpolicy_write_perms(from,
4394543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
4404543Smarks 		return (error);
4414543Smarks 
4424543Smarks 	if ((error = zfs_get_parent(to, parentname,
4434543Smarks 	    sizeof (parentname))) != 0)
4444543Smarks 		return (error);
4454543Smarks 
4464543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
4474543Smarks 	    ZFS_DELEG_PERM_CREATE, cr)) != 0)
4484543Smarks 		return (error);
4494543Smarks 
4504543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
4514543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
4524543Smarks 		return (error);
4534543Smarks 
4544543Smarks 	return (error);
4554543Smarks }
4564543Smarks 
4574543Smarks static int
4584543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr)
4594543Smarks {
4604543Smarks 	return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr));
4614543Smarks }
4624543Smarks 
4634543Smarks static int
4644543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr)
4654543Smarks {
4664543Smarks 	char 	parentname[MAXNAMELEN];
4674543Smarks 	objset_t *clone;
4684543Smarks 	int error;
4694543Smarks 
4704543Smarks 	error = zfs_secpolicy_write_perms(zc->zc_name,
4714543Smarks 	    ZFS_DELEG_PERM_PROMOTE, cr);
4724543Smarks 	if (error)
4734543Smarks 		return (error);
4744543Smarks 
4754543Smarks 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
4764543Smarks 	    DS_MODE_STANDARD | DS_MODE_READONLY, &clone);
4774543Smarks 
4784543Smarks 	if (error == 0) {
4794543Smarks 		dsl_dataset_t *pclone = NULL;
4804543Smarks 		dsl_dir_t *dd;
4814543Smarks 		dd = clone->os->os_dsl_dataset->ds_dir;
4824543Smarks 
4834543Smarks 		rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER);
4844543Smarks 		error = dsl_dataset_open_obj(dd->dd_pool,
4855367Sahrens 		    dd->dd_phys->dd_origin_obj, NULL,
4864543Smarks 		    DS_MODE_NONE, FTAG, &pclone);
4874543Smarks 		rw_exit(&dd->dd_pool->dp_config_rwlock);
4884543Smarks 		if (error) {
4894543Smarks 			dmu_objset_close(clone);
4904543Smarks 			return (error);
4914543Smarks 		}
4924543Smarks 
4934543Smarks 		error = zfs_secpolicy_write_perms(zc->zc_name,
4944543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr);
4954543Smarks 
4964543Smarks 		dsl_dataset_name(pclone, parentname);
4974543Smarks 		dmu_objset_close(clone);
4984543Smarks 		dsl_dataset_close(pclone, DS_MODE_NONE, FTAG);
4994543Smarks 		if (error == 0)
5004543Smarks 			error = zfs_secpolicy_write_perms(parentname,
5014543Smarks 			    ZFS_DELEG_PERM_PROMOTE, cr);
5024543Smarks 	}
5034543Smarks 	return (error);
5044543Smarks }
5054543Smarks 
5064543Smarks static int
5074543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr)
5084543Smarks {
5094543Smarks 	int error;
5104543Smarks 
5114543Smarks 	if ((error = zfs_secpolicy_write_perms(zc->zc_name,
5124543Smarks 	    ZFS_DELEG_PERM_RECEIVE, cr)) != 0)
5134543Smarks 		return (error);
5144543Smarks 
5154543Smarks 	if ((error = zfs_secpolicy_write_perms(zc->zc_name,
5164543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
5174543Smarks 		return (error);
5184543Smarks 
5194543Smarks 	return (zfs_secpolicy_write_perms(zc->zc_name,
5204543Smarks 	    ZFS_DELEG_PERM_CREATE, cr));
5214543Smarks }
5224543Smarks 
5234543Smarks int
5244543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
5254543Smarks {
5264543Smarks 	int error;
5274543Smarks 
5284543Smarks 	if ((error = zfs_secpolicy_write_perms(name,
5294543Smarks 	    ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0)
5304543Smarks 		return (error);
5314543Smarks 
5324543Smarks 	error = zfs_secpolicy_write_perms(name,
5334543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr);
5344543Smarks 
5354543Smarks 	return (error);
5364543Smarks }
5374543Smarks 
5384543Smarks static int
5394543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr)
5404543Smarks {
5414543Smarks 
5424543Smarks 	return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr));
5434543Smarks }
5444543Smarks 
5454543Smarks static int
5464543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr)
5474543Smarks {
5484543Smarks 	char 	parentname[MAXNAMELEN];
5494543Smarks 	int 	error;
5504543Smarks 
5514543Smarks 	if ((error = zfs_get_parent(zc->zc_name, parentname,
5524543Smarks 	    sizeof (parentname))) != 0)
5534543Smarks 		return (error);
5544543Smarks 
5554543Smarks 	if (zc->zc_value[0] != '\0') {
5564543Smarks 		if ((error = zfs_secpolicy_write_perms(zc->zc_value,
5574543Smarks 		    ZFS_DELEG_PERM_CLONE, cr)) != 0)
5584543Smarks 			return (error);
5594543Smarks 	}
5604543Smarks 
5614543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
5624543Smarks 	    ZFS_DELEG_PERM_CREATE, cr)) != 0)
5634543Smarks 		return (error);
5644543Smarks 
5654543Smarks 	error = zfs_secpolicy_write_perms(parentname,
5664543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr);
5674543Smarks 
5684543Smarks 	return (error);
5694543Smarks }
5704543Smarks 
5714543Smarks static int
5724543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr)
5734543Smarks {
5744543Smarks 	int error;
5754543Smarks 
5764543Smarks 	error = secpolicy_fs_unmount(cr, NULL);
5774543Smarks 	if (error) {
5784543Smarks 		error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr);
5794543Smarks 	}
5804543Smarks 	return (error);
581789Sahrens }
582789Sahrens 
583789Sahrens /*
584789Sahrens  * Policy for pool operations - create/destroy pools, add vdevs, etc.  Requires
585789Sahrens  * SYS_CONFIG privilege, which is not available in a local zone.
586789Sahrens  */
587789Sahrens /* ARGSUSED */
588789Sahrens static int
5894543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr)
590789Sahrens {
591789Sahrens 	if (secpolicy_sys_config(cr, B_FALSE) != 0)
592789Sahrens 		return (EPERM);
593789Sahrens 
594789Sahrens 	return (0);
595789Sahrens }
596789Sahrens 
597789Sahrens /*
5984543Smarks  * Just like zfs_secpolicy_config, except that we will check for
5994543Smarks  * mount permission on the dataset for permission to create/remove
6004543Smarks  * the minor nodes.
6014543Smarks  */
6024543Smarks static int
6034543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr)
6044543Smarks {
6054543Smarks 	if (secpolicy_sys_config(cr, B_FALSE) != 0) {
6064543Smarks 		return (dsl_deleg_access(zc->zc_name,
6074543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr));
6084543Smarks 	}
6094543Smarks 
6104543Smarks 	return (0);
6114543Smarks }
6124543Smarks 
6134543Smarks /*
6141544Seschrock  * Policy for fault injection.  Requires all privileges.
6151544Seschrock  */
6161544Seschrock /* ARGSUSED */
6171544Seschrock static int
6184543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr)
6191544Seschrock {
6201544Seschrock 	return (secpolicy_zinject(cr));
6211544Seschrock }
6221544Seschrock 
6234849Sahrens static int
6244849Sahrens zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr)
6254849Sahrens {
6264849Sahrens 	zfs_prop_t prop = zfs_name_to_prop(zc->zc_value);
6274849Sahrens 
6285094Slling 	if (prop == ZPROP_INVAL) {
6294849Sahrens 		if (!zfs_prop_user(zc->zc_value))
6304849Sahrens 			return (EINVAL);
6314849Sahrens 		return (zfs_secpolicy_write_perms(zc->zc_name,
6324849Sahrens 		    ZFS_DELEG_PERM_USERPROP, cr));
6334849Sahrens 	} else {
6344849Sahrens 		if (!zfs_prop_inheritable(prop))
6354849Sahrens 			return (EINVAL);
6364849Sahrens 		return (zfs_secpolicy_setprop(zc->zc_name, prop, cr));
6374849Sahrens 	}
6384849Sahrens }
6394849Sahrens 
6401544Seschrock /*
641789Sahrens  * Returns the nvlist as specified by the user in the zfs_cmd_t.
642789Sahrens  */
643789Sahrens static int
6445094Slling get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp)
645789Sahrens {
646789Sahrens 	char *packed;
647789Sahrens 	int error;
6485094Slling 	nvlist_t *list = NULL;
649789Sahrens 
650789Sahrens 	/*
6512676Seschrock 	 * Read in and unpack the user-supplied nvlist.
652789Sahrens 	 */
6535094Slling 	if (size == 0)
654789Sahrens 		return (EINVAL);
655789Sahrens 
656789Sahrens 	packed = kmem_alloc(size, KM_SLEEP);
657789Sahrens 
6585094Slling 	if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) {
659789Sahrens 		kmem_free(packed, size);
660789Sahrens 		return (error);
661789Sahrens 	}
662789Sahrens 
6635094Slling 	if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) {
664789Sahrens 		kmem_free(packed, size);
665789Sahrens 		return (error);
666789Sahrens 	}
667789Sahrens 
668789Sahrens 	kmem_free(packed, size);
669789Sahrens 
6705094Slling 	*nvp = list;
671789Sahrens 	return (0);
672789Sahrens }
673789Sahrens 
674789Sahrens static int
6752676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
6762676Seschrock {
6772676Seschrock 	char *packed = NULL;
6782676Seschrock 	size_t size;
6792676Seschrock 	int error;
6802676Seschrock 
6812676Seschrock 	VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
6822676Seschrock 
6832676Seschrock 	if (size > zc->zc_nvlist_dst_size) {
6842676Seschrock 		error = ENOMEM;
6852676Seschrock 	} else {
6864611Smarks 		packed = kmem_alloc(size, KM_SLEEP);
6872676Seschrock 		VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
6882676Seschrock 		    KM_SLEEP) == 0);
6892676Seschrock 		error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst,
6902676Seschrock 		    size);
6912676Seschrock 		kmem_free(packed, size);
6922676Seschrock 	}
6932676Seschrock 
6942676Seschrock 	zc->zc_nvlist_dst_size = size;
6952676Seschrock 	return (error);
6962676Seschrock }
6972676Seschrock 
6982676Seschrock static int
699789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc)
700789Sahrens {
701789Sahrens 	int error;
7025094Slling 	nvlist_t *config, *props = NULL;
7034715Sek110237 	char *buf;
704789Sahrens 
7055094Slling 	if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
7065094Slling 	    &config))
7074988Sek110237 		return (error);
7084715Sek110237 
7095094Slling 	if (zc->zc_nvlist_src_size != 0 && (error =
7105094Slling 	    get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) {
7115094Slling 		nvlist_free(config);
7125094Slling 		return (error);
7135094Slling 	}
7145094Slling 
7154988Sek110237 	buf = history_str_get(zc);
716789Sahrens 
7175094Slling 	error = spa_create(zc->zc_name, config, props, buf);
718789Sahrens 
7194988Sek110237 	if (buf != NULL)
7204988Sek110237 		history_str_free(buf);
7215094Slling 
722789Sahrens 	nvlist_free(config);
723789Sahrens 
7245094Slling 	if (props)
7255094Slling 		nvlist_free(props);
7265094Slling 
727789Sahrens 	return (error);
728789Sahrens }
729789Sahrens 
730789Sahrens static int
731789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc)
732789Sahrens {
7334543Smarks 	int error;
7344543Smarks 	zfs_log_history(zc);
7354543Smarks 	error = spa_destroy(zc->zc_name);
7364543Smarks 	return (error);
737789Sahrens }
738789Sahrens 
739789Sahrens static int
740789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc)
741789Sahrens {
742789Sahrens 	int error;
7435094Slling 	nvlist_t *config, *props = NULL;
744789Sahrens 	uint64_t guid;
745789Sahrens 
7465094Slling 	if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
7475094Slling 	    &config)) != 0)
748789Sahrens 		return (error);
749789Sahrens 
7505094Slling 	if (zc->zc_nvlist_src_size != 0 && (error =
7515094Slling 	    get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) {
7525094Slling 		nvlist_free(config);
7535094Slling 		return (error);
7545094Slling 	}
7555094Slling 
756789Sahrens 	if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 ||
7571544Seschrock 	    guid != zc->zc_guid)
758789Sahrens 		error = EINVAL;
759789Sahrens 	else
7605094Slling 		error = spa_import(zc->zc_name, config, props);
761789Sahrens 
762789Sahrens 	nvlist_free(config);
763789Sahrens 
7645094Slling 	if (props)
7655094Slling 		nvlist_free(props);
7665094Slling 
767789Sahrens 	return (error);
768789Sahrens }
769789Sahrens 
770789Sahrens static int
771789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc)
772789Sahrens {
7734543Smarks 	int error;
7744543Smarks 	zfs_log_history(zc);
7754543Smarks 	error = spa_export(zc->zc_name, NULL);
7764543Smarks 	return (error);
777789Sahrens }
778789Sahrens 
779789Sahrens static int
780789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc)
781789Sahrens {
782789Sahrens 	nvlist_t *configs;
783789Sahrens 	int error;
784789Sahrens 
785789Sahrens 	if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL)
786789Sahrens 		return (EEXIST);
787789Sahrens 
7882676Seschrock 	error = put_nvlist(zc, configs);
789789Sahrens 
790789Sahrens 	nvlist_free(configs);
791789Sahrens 
792789Sahrens 	return (error);
793789Sahrens }
794789Sahrens 
795789Sahrens static int
796789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc)
797789Sahrens {
798789Sahrens 	nvlist_t *config;
799789Sahrens 	int error;
8001544Seschrock 	int ret = 0;
801789Sahrens 
8022676Seschrock 	error = spa_get_stats(zc->zc_name, &config, zc->zc_value,
8032676Seschrock 	    sizeof (zc->zc_value));
804789Sahrens 
805789Sahrens 	if (config != NULL) {
8062676Seschrock 		ret = put_nvlist(zc, config);
807789Sahrens 		nvlist_free(config);
8081544Seschrock 
8091544Seschrock 		/*
8101544Seschrock 		 * The config may be present even if 'error' is non-zero.
8111544Seschrock 		 * In this case we return success, and preserve the real errno
8121544Seschrock 		 * in 'zc_cookie'.
8131544Seschrock 		 */
8141544Seschrock 		zc->zc_cookie = error;
815789Sahrens 	} else {
8161544Seschrock 		ret = error;
817789Sahrens 	}
818789Sahrens 
8191544Seschrock 	return (ret);
820789Sahrens }
821789Sahrens 
822789Sahrens /*
823789Sahrens  * Try to import the given pool, returning pool stats as appropriate so that
824789Sahrens  * user land knows which devices are available and overall pool health.
825789Sahrens  */
826789Sahrens static int
827789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc)
828789Sahrens {
829789Sahrens 	nvlist_t *tryconfig, *config;
830789Sahrens 	int error;
831789Sahrens 
8325094Slling 	if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
8335094Slling 	    &tryconfig)) != 0)
834789Sahrens 		return (error);
835789Sahrens 
836789Sahrens 	config = spa_tryimport(tryconfig);
837789Sahrens 
838789Sahrens 	nvlist_free(tryconfig);
839789Sahrens 
840789Sahrens 	if (config == NULL)
841789Sahrens 		return (EINVAL);
842789Sahrens 
8432676Seschrock 	error = put_nvlist(zc, config);
844789Sahrens 	nvlist_free(config);
845789Sahrens 
846789Sahrens 	return (error);
847789Sahrens }
848789Sahrens 
849789Sahrens static int
850789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc)
851789Sahrens {
852789Sahrens 	spa_t *spa;
853789Sahrens 	int error;
854789Sahrens 
8552926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
8562926Sek110237 		return (error);
8572926Sek110237 
8584808Sek110237 	mutex_enter(&spa_namespace_lock);
8592926Sek110237 	error = spa_scrub(spa, zc->zc_cookie, B_FALSE);
8604808Sek110237 	mutex_exit(&spa_namespace_lock);
8612926Sek110237 
8622926Sek110237 	spa_close(spa, FTAG);
8632926Sek110237 
864789Sahrens 	return (error);
865789Sahrens }
866789Sahrens 
867789Sahrens static int
868789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc)
869789Sahrens {
870789Sahrens 	spa_t *spa;
871789Sahrens 	int error;
872789Sahrens 
873789Sahrens 	error = spa_open(zc->zc_name, &spa, FTAG);
874789Sahrens 	if (error == 0) {
875789Sahrens 		spa_freeze(spa);
876789Sahrens 		spa_close(spa, FTAG);
877789Sahrens 	}
878789Sahrens 	return (error);
879789Sahrens }
880789Sahrens 
881789Sahrens static int
8821760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc)
8831760Seschrock {
8841760Seschrock 	spa_t *spa;
8851760Seschrock 	int error;
8861760Seschrock 
8872926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
8882926Sek110237 		return (error);
8892926Sek110237 
8905118Slling 	if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) {
8915118Slling 		spa_close(spa, FTAG);
8925118Slling 		return (EINVAL);
8935118Slling 	}
8945118Slling 
8955094Slling 	spa_upgrade(spa, zc->zc_cookie);
8962926Sek110237 	spa_close(spa, FTAG);
8972926Sek110237 
8982926Sek110237 	return (error);
8992926Sek110237 }
9002926Sek110237 
9012926Sek110237 static int
9022926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc)
9032926Sek110237 {
9042926Sek110237 	spa_t *spa;
9052926Sek110237 	char *hist_buf;
9062926Sek110237 	uint64_t size;
9072926Sek110237 	int error;
9082926Sek110237 
9092926Sek110237 	if ((size = zc->zc_history_len) == 0)
9102926Sek110237 		return (EINVAL);
9112926Sek110237 
9122926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
9132926Sek110237 		return (error);
9142926Sek110237 
9154577Sahrens 	if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) {
9163863Sek110237 		spa_close(spa, FTAG);
9173863Sek110237 		return (ENOTSUP);
9183863Sek110237 	}
9193863Sek110237 
9202926Sek110237 	hist_buf = kmem_alloc(size, KM_SLEEP);
9212926Sek110237 	if ((error = spa_history_get(spa, &zc->zc_history_offset,
9222926Sek110237 	    &zc->zc_history_len, hist_buf)) == 0) {
9234543Smarks 		error = xcopyout(hist_buf,
9244543Smarks 		    (char *)(uintptr_t)zc->zc_history,
9252926Sek110237 		    zc->zc_history_len);
9262926Sek110237 	}
9272926Sek110237 
9282926Sek110237 	spa_close(spa, FTAG);
9292926Sek110237 	kmem_free(hist_buf, size);
9302926Sek110237 	return (error);
9312926Sek110237 }
9322926Sek110237 
9332926Sek110237 static int
9343444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc)
9353444Sek110237 {
9363444Sek110237 	int error;
9373444Sek110237 
9383912Slling 	if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value))
9393444Sek110237 		return (error);
9403444Sek110237 
9413444Sek110237 	return (0);
9423444Sek110237 }
9433444Sek110237 
9443444Sek110237 static int
9453444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc)
9463444Sek110237 {
9473444Sek110237 	objset_t *osp;
9483444Sek110237 	int error;
9493444Sek110237 
9503444Sek110237 	if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS,
9513444Sek110237 	    DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0)
9523444Sek110237 		return (error);
9533444Sek110237 
9543444Sek110237 	error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value,
9553444Sek110237 	    sizeof (zc->zc_value));
9563444Sek110237 	dmu_objset_close(osp);
9573444Sek110237 
9583444Sek110237 	return (error);
9593444Sek110237 }
9603444Sek110237 
9613444Sek110237 static int
962789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc)
963789Sahrens {
964789Sahrens 	spa_t *spa;
965789Sahrens 	int error;
966*5450Sbrendan 	nvlist_t *config, **l2cache;
967*5450Sbrendan 	uint_t nl2cache;
968789Sahrens 
969789Sahrens 	error = spa_open(zc->zc_name, &spa, FTAG);
970789Sahrens 	if (error != 0)
971789Sahrens 		return (error);
972789Sahrens 
973*5450Sbrendan 	error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
974*5450Sbrendan 	    &config);
975*5450Sbrendan 	(void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE,
976*5450Sbrendan 	    &l2cache, &nl2cache);
977*5450Sbrendan 
9783912Slling 	/*
9793912Slling 	 * A root pool with concatenated devices is not supported.
9803912Slling 	 * Thus, can not add a device to a root pool with one device.
981*5450Sbrendan 	 * Allow for l2cache devices to be added.
9823912Slling 	 */
983*5450Sbrendan 	if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0 &&
984*5450Sbrendan 	    nl2cache == 0) {
9853912Slling 		spa_close(spa, FTAG);
9863912Slling 		return (EDOM);
9873912Slling 	}
9883912Slling 
989*5450Sbrendan 	if (error == 0) {
990789Sahrens 		error = spa_vdev_add(spa, config);
991789Sahrens 		nvlist_free(config);
992789Sahrens 	}
993789Sahrens 	spa_close(spa, FTAG);
994789Sahrens 	return (error);
995789Sahrens }
996789Sahrens 
997789Sahrens static int
998789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc)
999789Sahrens {
10002082Seschrock 	spa_t *spa;
10012082Seschrock 	int error;
10022082Seschrock 
10032082Seschrock 	error = spa_open(zc->zc_name, &spa, FTAG);
10042082Seschrock 	if (error != 0)
10052082Seschrock 		return (error);
10062082Seschrock 	error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE);
10072082Seschrock 	spa_close(spa, FTAG);
10082082Seschrock 	return (error);
1009789Sahrens }
1010789Sahrens 
1011789Sahrens static int
10124451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc)
1013789Sahrens {
1014789Sahrens 	spa_t *spa;
1015789Sahrens 	int error;
10164451Seschrock 	vdev_state_t newstate = VDEV_STATE_UNKNOWN;
1017789Sahrens 
10182926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
1019789Sahrens 		return (error);
10204451Seschrock 	switch (zc->zc_cookie) {
10214451Seschrock 	case VDEV_STATE_ONLINE:
10224451Seschrock 		error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate);
10234451Seschrock 		break;
10244451Seschrock 
10254451Seschrock 	case VDEV_STATE_OFFLINE:
10264451Seschrock 		error = vdev_offline(spa, zc->zc_guid, zc->zc_obj);
10274451Seschrock 		break;
1028789Sahrens 
10294451Seschrock 	case VDEV_STATE_FAULTED:
10304451Seschrock 		error = vdev_fault(spa, zc->zc_guid);
10314451Seschrock 		break;
1032789Sahrens 
10334451Seschrock 	case VDEV_STATE_DEGRADED:
10344451Seschrock 		error = vdev_degrade(spa, zc->zc_guid);
10354451Seschrock 		break;
10364451Seschrock 
10374451Seschrock 	default:
10384451Seschrock 		error = EINVAL;
10394451Seschrock 	}
10404451Seschrock 	zc->zc_cookie = newstate;
1041789Sahrens 	spa_close(spa, FTAG);
1042789Sahrens 	return (error);
1043789Sahrens }
1044789Sahrens 
1045789Sahrens static int
1046789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc)
1047789Sahrens {
1048789Sahrens 	spa_t *spa;
1049789Sahrens 	int replacing = zc->zc_cookie;
1050789Sahrens 	nvlist_t *config;
1051789Sahrens 	int error;
1052789Sahrens 
10532926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
1054789Sahrens 		return (error);
1055789Sahrens 
10565094Slling 	if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size,
10575094Slling 	    &config)) == 0) {
10581544Seschrock 		error = spa_vdev_attach(spa, zc->zc_guid, config, replacing);
1059789Sahrens 		nvlist_free(config);
1060789Sahrens 	}
1061789Sahrens 
1062789Sahrens 	spa_close(spa, FTAG);
1063789Sahrens 	return (error);
1064789Sahrens }
1065789Sahrens 
1066789Sahrens static int
1067789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc)
1068789Sahrens {
1069789Sahrens 	spa_t *spa;
1070789Sahrens 	int error;
1071789Sahrens 
10722926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
1073789Sahrens 		return (error);
1074789Sahrens 
10751544Seschrock 	error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE);
1076789Sahrens 
1077789Sahrens 	spa_close(spa, FTAG);
1078789Sahrens 	return (error);
1079789Sahrens }
1080789Sahrens 
1081789Sahrens static int
10821354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc)
10831354Seschrock {
10841354Seschrock 	spa_t *spa;
10852676Seschrock 	char *path = zc->zc_value;
10861544Seschrock 	uint64_t guid = zc->zc_guid;
10871354Seschrock 	int error;
10881354Seschrock 
10891354Seschrock 	error = spa_open(zc->zc_name, &spa, FTAG);
10901354Seschrock 	if (error != 0)
10911354Seschrock 		return (error);
10921354Seschrock 
10931354Seschrock 	error = spa_vdev_setpath(spa, guid, path);
10941354Seschrock 	spa_close(spa, FTAG);
10951354Seschrock 	return (error);
10961354Seschrock }
10971354Seschrock 
10985367Sahrens /*
10995367Sahrens  * inputs:
11005367Sahrens  * zc_name		name of filesystem
11015367Sahrens  * zc_nvlist_dst_size	size of buffer for property nvlist
11025367Sahrens  *
11035367Sahrens  * outputs:
11045367Sahrens  * zc_objset_stats	stats
11055367Sahrens  * zc_nvlist_dst	property nvlist
11065367Sahrens  * zc_nvlist_dst_size	size of property nvlist
11075367Sahrens  * zc_value		alternate root
11085367Sahrens  */
11091354Seschrock static int
1110789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc)
1111789Sahrens {
1112789Sahrens 	objset_t *os = NULL;
1113789Sahrens 	int error;
11141356Seschrock 	nvlist_t *nv;
1115789Sahrens 
1116789Sahrens retry:
1117789Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1118789Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1119789Sahrens 	if (error != 0) {
1120789Sahrens 		/*
1121789Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1122789Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1123789Sahrens 		 * only for a short while, so we retry here.
1124789Sahrens 		 * This avoids user code having to handle EBUSY,
1125789Sahrens 		 * for example for a "zfs list".
1126789Sahrens 		 */
1127789Sahrens 		if (error == EBUSY) {
1128789Sahrens 			delay(1);
1129789Sahrens 			goto retry;
1130789Sahrens 		}
1131789Sahrens 		return (error);
1132789Sahrens 	}
1133789Sahrens 
11342885Sahrens 	dmu_objset_fast_stat(os, &zc->zc_objset_stats);
1135789Sahrens 
11362856Snd150628 	if (zc->zc_nvlist_dst != 0 &&
11371356Seschrock 	    (error = dsl_prop_get_all(os, &nv)) == 0) {
11382885Sahrens 		dmu_objset_stats(os, nv);
11393087Sahrens 		/*
11405147Srm160521 		 * NB: zvol_get_stats() will read the objset contents,
11413087Sahrens 		 * which we aren't supposed to do with a
11423087Sahrens 		 * DS_MODE_STANDARD open, because it could be
11433087Sahrens 		 * inconsistent.  So this is a bit of a workaround...
11443087Sahrens 		 */
11454577Sahrens 		if (!zc->zc_objset_stats.dds_inconsistent) {
11464577Sahrens 			if (dmu_objset_type(os) == DMU_OST_ZVOL)
11474577Sahrens 				VERIFY(zvol_get_stats(os, nv) == 0);
11484577Sahrens 		}
11492676Seschrock 		error = put_nvlist(zc, nv);
11501356Seschrock 		nvlist_free(nv);
11511356Seschrock 	}
1152789Sahrens 
11532676Seschrock 	spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value));
11541544Seschrock 
1155789Sahrens 	dmu_objset_close(os);
1156789Sahrens 	return (error);
1157789Sahrens }
1158789Sahrens 
11595367Sahrens /*
11605367Sahrens  * inputs:
11615367Sahrens  * zc_name		name of filesystem
11625367Sahrens  * zc_cookie		zap cursor
11635367Sahrens  * zc_nvlist_dst_size	size of buffer for property nvlist
11645367Sahrens  *
11655367Sahrens  * outputs:
11665367Sahrens  * zc_name		name of next filesystem
11675367Sahrens  * zc_objset_stats	stats
11685367Sahrens  * zc_nvlist_dst	property nvlist
11695367Sahrens  * zc_nvlist_dst_size	size of property nvlist
11705367Sahrens  * zc_value		alternate root
11715367Sahrens  */
1172789Sahrens static int
11735147Srm160521 zfs_ioc_objset_version(zfs_cmd_t *zc)
11745147Srm160521 {
11755147Srm160521 	objset_t *os = NULL;
11765147Srm160521 	int error;
11775147Srm160521 
11785147Srm160521 retry:
11795147Srm160521 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
11805147Srm160521 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
11815147Srm160521 	if (error != 0) {
11825147Srm160521 		/*
11835147Srm160521 		 * This is ugly: dmu_objset_open() can return EBUSY if
11845147Srm160521 		 * the objset is held exclusively. Fortunately this hold is
11855147Srm160521 		 * only for a short while, so we retry here.
11865147Srm160521 		 * This avoids user code having to handle EBUSY,
11875147Srm160521 		 * for example for a "zfs list".
11885147Srm160521 		 */
11895147Srm160521 		if (error == EBUSY) {
11905147Srm160521 			delay(1);
11915147Srm160521 			goto retry;
11925147Srm160521 		}
11935147Srm160521 		return (error);
11945147Srm160521 	}
11955147Srm160521 
11965147Srm160521 	dmu_objset_fast_stat(os, &zc->zc_objset_stats);
11975147Srm160521 
11985147Srm160521 	/*
11995147Srm160521 	 * NB: zfs_get_version() will read the objset contents,
12005147Srm160521 	 * which we aren't supposed to do with a
12015147Srm160521 	 * DS_MODE_STANDARD open, because it could be
12025147Srm160521 	 * inconsistent.  So this is a bit of a workaround...
12035147Srm160521 	 */
12045147Srm160521 	zc->zc_cookie = 0;
12055147Srm160521 	if (!zc->zc_objset_stats.dds_inconsistent)
12065147Srm160521 		if (dmu_objset_type(os) == DMU_OST_ZFS)
12075147Srm160521 			(void) zfs_get_version(os, &zc->zc_cookie);
12085147Srm160521 
12095147Srm160521 	dmu_objset_close(os);
12105147Srm160521 	return (0);
12115147Srm160521 }
12125147Srm160521 
12135147Srm160521 static int
1214789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc)
1215789Sahrens {
1216885Sahrens 	objset_t *os;
1217789Sahrens 	int error;
1218789Sahrens 	char *p;
1219789Sahrens 
1220885Sahrens retry:
1221885Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1222885Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1223885Sahrens 	if (error != 0) {
1224885Sahrens 		/*
1225885Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1226885Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1227885Sahrens 		 * only for a short while, so we retry here.
1228885Sahrens 		 * This avoids user code having to handle EBUSY,
1229885Sahrens 		 * for example for a "zfs list".
1230885Sahrens 		 */
1231885Sahrens 		if (error == EBUSY) {
1232885Sahrens 			delay(1);
1233885Sahrens 			goto retry;
1234885Sahrens 		}
1235885Sahrens 		if (error == ENOENT)
1236885Sahrens 			error = ESRCH;
1237885Sahrens 		return (error);
1238789Sahrens 	}
1239789Sahrens 
1240789Sahrens 	p = strrchr(zc->zc_name, '/');
1241789Sahrens 	if (p == NULL || p[1] != '\0')
1242789Sahrens 		(void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name));
1243789Sahrens 	p = zc->zc_name + strlen(zc->zc_name);
1244789Sahrens 
1245789Sahrens 	do {
1246885Sahrens 		error = dmu_dir_list_next(os,
1247885Sahrens 		    sizeof (zc->zc_name) - (p - zc->zc_name), p,
1248885Sahrens 		    NULL, &zc->zc_cookie);
1249789Sahrens 		if (error == ENOENT)
1250789Sahrens 			error = ESRCH;
1251885Sahrens 	} while (error == 0 && !INGLOBALZONE(curproc) &&
1252789Sahrens 	    !zone_dataset_visible(zc->zc_name, NULL));
1253789Sahrens 
1254885Sahrens 	/*
1255885Sahrens 	 * If it's a hidden dataset (ie. with a '$' in its name), don't
1256885Sahrens 	 * try to get stats for it.  Userland will skip over it.
1257885Sahrens 	 */
1258885Sahrens 	if (error == 0 && strchr(zc->zc_name, '$') == NULL)
1259885Sahrens 		error = zfs_ioc_objset_stats(zc); /* fill in the stats */
1260789Sahrens 
1261885Sahrens 	dmu_objset_close(os);
1262789Sahrens 	return (error);
1263789Sahrens }
1264789Sahrens 
12655367Sahrens /*
12665367Sahrens  * inputs:
12675367Sahrens  * zc_name		name of filesystem
12685367Sahrens  * zc_cookie		zap cursor
12695367Sahrens  * zc_nvlist_dst_size	size of buffer for property nvlist
12705367Sahrens  *
12715367Sahrens  * outputs:
12725367Sahrens  * zc_name		name of next snapshot
12735367Sahrens  * zc_objset_stats	stats
12745367Sahrens  * zc_nvlist_dst	property nvlist
12755367Sahrens  * zc_nvlist_dst_size	size of property nvlist
12765367Sahrens  * zc_value		alternate root
12775367Sahrens  */
1278789Sahrens static int
1279789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
1280789Sahrens {
1281885Sahrens 	objset_t *os;
1282789Sahrens 	int error;
1283789Sahrens 
1284789Sahrens retry:
1285885Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1286885Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1287885Sahrens 	if (error != 0) {
1288789Sahrens 		/*
1289885Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1290789Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1291789Sahrens 		 * only for a short while, so we retry here.
1292789Sahrens 		 * This avoids user code having to handle EBUSY,
1293885Sahrens 		 * for example for a "zfs list".
1294789Sahrens 		 */
1295789Sahrens 		if (error == EBUSY) {
1296789Sahrens 			delay(1);
1297789Sahrens 			goto retry;
1298789Sahrens 		}
1299789Sahrens 		if (error == ENOENT)
1300885Sahrens 			error = ESRCH;
1301789Sahrens 		return (error);
1302789Sahrens 	}
1303789Sahrens 
13041003Slling 	/*
13051003Slling 	 * A dataset name of maximum length cannot have any snapshots,
13061003Slling 	 * so exit immediately.
13071003Slling 	 */
13081003Slling 	if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) {
1309885Sahrens 		dmu_objset_close(os);
13101003Slling 		return (ESRCH);
1311789Sahrens 	}
1312789Sahrens 
1313885Sahrens 	error = dmu_snapshot_list_next(os,
1314885Sahrens 	    sizeof (zc->zc_name) - strlen(zc->zc_name),
1315885Sahrens 	    zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie);
1316789Sahrens 	if (error == ENOENT)
1317789Sahrens 		error = ESRCH;
1318789Sahrens 
1319885Sahrens 	if (error == 0)
1320885Sahrens 		error = zfs_ioc_objset_stats(zc); /* fill in the stats */
1321789Sahrens 
13225367Sahrens 	/* if we failed, undo the @ that we tacked on to zc_name */
13235367Sahrens 	if (error != 0)
13245367Sahrens 		*strchr(zc->zc_name, '@') = '\0';
13255367Sahrens 
1326885Sahrens 	dmu_objset_close(os);
1327789Sahrens 	return (error);
1328789Sahrens }
1329789Sahrens 
1330789Sahrens static int
13314787Sahrens zfs_set_prop_nvlist(const char *name, nvlist_t *nvl)
1332789Sahrens {
13332676Seschrock 	nvpair_t *elem;
13342676Seschrock 	int error;
13352676Seschrock 	uint64_t intval;
13362676Seschrock 	char *strval;
13372676Seschrock 
13384543Smarks 	/*
13394543Smarks 	 * First validate permission to set all of the properties
13404543Smarks 	 */
13412676Seschrock 	elem = NULL;
13422676Seschrock 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
13434670Sahrens 		const char *propname = nvpair_name(elem);
13444670Sahrens 		zfs_prop_t prop = zfs_name_to_prop(propname);
13452676Seschrock 
13465094Slling 		if (prop == ZPROP_INVAL) {
13472676Seschrock 			/*
13482676Seschrock 			 * If this is a user-defined property, it must be a
13492676Seschrock 			 * string, and there is no further validation to do.
13502676Seschrock 			 */
13512676Seschrock 			if (!zfs_prop_user(propname) ||
13522676Seschrock 			    nvpair_type(elem) != DATA_TYPE_STRING)
13532676Seschrock 				return (EINVAL);
13542676Seschrock 
13555331Samw 			if (error = zfs_secpolicy_write_perms(name,
13565331Samw 			    ZFS_DELEG_PERM_USERPROP, CRED()))
13574670Sahrens 				return (error);
13584543Smarks 			continue;
13592676Seschrock 		}
13602676Seschrock 
13614787Sahrens 		if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0)
13624670Sahrens 			return (error);
13632676Seschrock 
13644670Sahrens 		/*
13654670Sahrens 		 * Check that this value is valid for this pool version
13664670Sahrens 		 */
13674670Sahrens 		switch (prop) {
13683886Sahl 		case ZFS_PROP_COMPRESSION:
13693886Sahl 			/*
13703886Sahl 			 * If the user specified gzip compression, make sure
13713886Sahl 			 * the SPA supports it. We ignore any errors here since
13723886Sahl 			 * we'll catch them later.
13733886Sahl 			 */
13743886Sahl 			if (nvpair_type(elem) == DATA_TYPE_UINT64 &&
13753886Sahl 			    nvpair_value_uint64(elem, &intval) == 0 &&
13763886Sahl 			    intval >= ZIO_COMPRESS_GZIP_1 &&
13773886Sahl 			    intval <= ZIO_COMPRESS_GZIP_9) {
13785331Samw 				if (zfs_check_version(name,
13795331Samw 				    SPA_VERSION_GZIP_COMPRESSION))
13805331Samw 					return (ENOTSUP);
13813886Sahl 			}
13823886Sahl 			break;
13834603Sahrens 
13844603Sahrens 		case ZFS_PROP_COPIES:
13855331Samw 			if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS))
13865331Samw 				return (ENOTSUP);
13874603Sahrens 			break;
13885331Samw 		case ZFS_PROP_NORMALIZE:
13895331Samw 		case ZFS_PROP_UTF8ONLY:
13905331Samw 		case ZFS_PROP_CASE:
13915331Samw 			if (zfs_check_version(name, SPA_VERSION_NORMALIZATION))
13925331Samw 				return (ENOTSUP);
13935331Samw 
13944603Sahrens 		}
13955331Samw 		if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0)
13965331Samw 			return (error);
13974543Smarks 	}
13984543Smarks 
13994543Smarks 	elem = NULL;
14004543Smarks 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
14014670Sahrens 		const char *propname = nvpair_name(elem);
14024670Sahrens 		zfs_prop_t prop = zfs_name_to_prop(propname);
14034543Smarks 
14045094Slling 		if (prop == ZPROP_INVAL) {
14054543Smarks 			VERIFY(nvpair_value_string(elem, &strval) == 0);
14064543Smarks 			error = dsl_prop_set(name, propname, 1,
14074543Smarks 			    strlen(strval) + 1, strval);
14084543Smarks 			if (error == 0)
14094543Smarks 				continue;
14104543Smarks 			else
14114543Smarks 				return (error);
14124543Smarks 		}
14132676Seschrock 
14142676Seschrock 		switch (prop) {
14152676Seschrock 		case ZFS_PROP_QUOTA:
14162676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
14174577Sahrens 			    (error = dsl_dir_set_quota(name, intval)) != 0)
14182676Seschrock 				return (error);
14192676Seschrock 			break;
14202676Seschrock 
14215378Sck153898 		case ZFS_PROP_REFQUOTA:
14225378Sck153898 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
14235378Sck153898 			    (error = dsl_dataset_set_quota(name, intval)) != 0)
14245378Sck153898 				return (error);
14255378Sck153898 			break;
14265378Sck153898 
14272676Seschrock 		case ZFS_PROP_RESERVATION:
14282676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
14292676Seschrock 			    (error = dsl_dir_set_reservation(name,
14302676Seschrock 			    intval)) != 0)
14312676Seschrock 				return (error);
14322676Seschrock 			break;
1433789Sahrens 
14345378Sck153898 		case ZFS_PROP_REFRESERVATION:
14355378Sck153898 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
14365378Sck153898 			    (error = dsl_dataset_set_reservation(name,
14375378Sck153898 			    intval)) != 0)
14385378Sck153898 				return (error);
14395378Sck153898 			break;
14405378Sck153898 
14412676Seschrock 		case ZFS_PROP_VOLSIZE:
14422676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
14434787Sahrens 			    (error = zvol_set_volsize(name,
14444787Sahrens 			    ddi_driver_major(zfs_dip), intval)) != 0)
14452676Seschrock 				return (error);
14462676Seschrock 			break;
14472676Seschrock 
14482676Seschrock 		case ZFS_PROP_VOLBLOCKSIZE:
14492676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
14504577Sahrens 			    (error = zvol_set_volblocksize(name, intval)) != 0)
14514577Sahrens 				return (error);
14524577Sahrens 			break;
14534577Sahrens 
14544577Sahrens 		case ZFS_PROP_VERSION:
14554577Sahrens 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
14564577Sahrens 			    (error = zfs_set_version(name, intval)) != 0)
14572676Seschrock 				return (error);
14582676Seschrock 			break;
14592676Seschrock 
14602676Seschrock 		default:
14612676Seschrock 			if (nvpair_type(elem) == DATA_TYPE_STRING) {
14622676Seschrock 				if (zfs_prop_get_type(prop) !=
14634787Sahrens 				    PROP_TYPE_STRING)
14642676Seschrock 					return (EINVAL);
14652717Seschrock 				VERIFY(nvpair_value_string(elem, &strval) == 0);
14662717Seschrock 				if ((error = dsl_prop_set(name,
14672676Seschrock 				    nvpair_name(elem), 1, strlen(strval) + 1,
14682717Seschrock 				    strval)) != 0)
14692717Seschrock 					return (error);
14702676Seschrock 			} else if (nvpair_type(elem) == DATA_TYPE_UINT64) {
14712885Sahrens 				const char *unused;
14722885Sahrens 
14732717Seschrock 				VERIFY(nvpair_value_uint64(elem, &intval) == 0);
14742676Seschrock 
14752676Seschrock 				switch (zfs_prop_get_type(prop)) {
14764787Sahrens 				case PROP_TYPE_NUMBER:
14772676Seschrock 					break;
14784787Sahrens 				case PROP_TYPE_STRING:
14792717Seschrock 					return (EINVAL);
14804787Sahrens 				case PROP_TYPE_INDEX:
14812717Seschrock 					if (zfs_prop_index_to_string(prop,
14822717Seschrock 					    intval, &unused) != 0)
14832717Seschrock 						return (EINVAL);
14842676Seschrock 					break;
14852676Seschrock 				default:
14864577Sahrens 					cmn_err(CE_PANIC,
14874577Sahrens 					    "unknown property type");
14882676Seschrock 					break;
14892676Seschrock 				}
14902676Seschrock 
14912717Seschrock 				if ((error = dsl_prop_set(name, propname,
14922717Seschrock 				    8, 1, &intval)) != 0)
14932717Seschrock 					return (error);
14942676Seschrock 			} else {
14952676Seschrock 				return (EINVAL);
14962676Seschrock 			}
14972676Seschrock 			break;
14982676Seschrock 		}
14992676Seschrock 	}
15002676Seschrock 
15012676Seschrock 	return (0);
1502789Sahrens }
1503789Sahrens 
15045367Sahrens /*
15055367Sahrens  * inputs:
15065367Sahrens  * zc_name		name of filesystem
15075367Sahrens  * zc_value		name of property to inherit
15085367Sahrens  * zc_nvlist_src{_size}	nvlist of properties to apply
15095367Sahrens  *
15105367Sahrens  * outputs:		none
15115367Sahrens  */
1512789Sahrens static int
15132676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc)
1514789Sahrens {
15152676Seschrock 	nvlist_t *nvl;
15162676Seschrock 	int error;
1517789Sahrens 
15185094Slling 	if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
15195094Slling 	    &nvl)) != 0)
15202676Seschrock 		return (error);
15212676Seschrock 
15224787Sahrens 	error = zfs_set_prop_nvlist(zc->zc_name, nvl);
15234543Smarks 
15242676Seschrock 	nvlist_free(nvl);
15252676Seschrock 	return (error);
1526789Sahrens }
1527789Sahrens 
15285367Sahrens /*
15295367Sahrens  * inputs:
15305367Sahrens  * zc_name		name of filesystem
15315367Sahrens  * zc_value		name of property to inherit
15325367Sahrens  *
15335367Sahrens  * outputs:		none
15345367Sahrens  */
1535789Sahrens static int
15364849Sahrens zfs_ioc_inherit_prop(zfs_cmd_t *zc)
15374849Sahrens {
15384849Sahrens 	/* the property name has been validated by zfs_secpolicy_inherit() */
15394849Sahrens 	return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL));
15404849Sahrens }
15414849Sahrens 
15424849Sahrens static int
15434098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc)
15443912Slling {
15455094Slling 	nvlist_t *props;
15463912Slling 	spa_t *spa;
15475094Slling 	int error;
15483912Slling 
15495094Slling 	if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
15505094Slling 	    &props)))
15513912Slling 		return (error);
15523912Slling 
15533912Slling 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
15545094Slling 		nvlist_free(props);
15553912Slling 		return (error);
15563912Slling 	}
15573912Slling 
15585094Slling 	error = spa_prop_set(spa, props);
15593912Slling 
15605094Slling 	nvlist_free(props);
15613912Slling 	spa_close(spa, FTAG);
15623912Slling 
15633912Slling 	return (error);
15643912Slling }
15653912Slling 
15663912Slling static int
15674098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc)
15683912Slling {
15693912Slling 	spa_t *spa;
15703912Slling 	int error;
15713912Slling 	nvlist_t *nvp = NULL;
15723912Slling 
15733912Slling 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
15743912Slling 		return (error);
15753912Slling 
15765094Slling 	error = spa_prop_get(spa, &nvp);
15773912Slling 
15783912Slling 	if (error == 0 && zc->zc_nvlist_dst != NULL)
15793912Slling 		error = put_nvlist(zc, nvp);
15803912Slling 	else
15813912Slling 		error = EFAULT;
15823912Slling 
15833912Slling 	spa_close(spa, FTAG);
15843912Slling 
15853912Slling 	if (nvp)
15863912Slling 		nvlist_free(nvp);
15873912Slling 	return (error);
15883912Slling }
15893912Slling 
15903912Slling static int
15914543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc)
15924543Smarks {
15934543Smarks 	nvlist_t *nvp;
15944543Smarks 	int error;
15954543Smarks 	uint32_t uid;
15964543Smarks 	uint32_t gid;
15974543Smarks 	uint32_t *groups;
15984543Smarks 	uint_t group_cnt;
15994543Smarks 	cred_t	*usercred;
16004543Smarks 
16015094Slling 	if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
16025094Slling 	    &nvp)) != 0) {
16034543Smarks 		return (error);
16044543Smarks 	}
16054543Smarks 
16064543Smarks 	if ((error = nvlist_lookup_uint32(nvp,
16074543Smarks 	    ZFS_DELEG_PERM_UID, &uid)) != 0) {
16084543Smarks 		nvlist_free(nvp);
16094543Smarks 		return (EPERM);
16104543Smarks 	}
16114543Smarks 
16124543Smarks 	if ((error = nvlist_lookup_uint32(nvp,
16134543Smarks 	    ZFS_DELEG_PERM_GID, &gid)) != 0) {
16144543Smarks 		nvlist_free(nvp);
16154543Smarks 		return (EPERM);
16164543Smarks 	}
16174543Smarks 
16184543Smarks 	if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS,
16194543Smarks 	    &groups, &group_cnt)) != 0) {
16204543Smarks 		nvlist_free(nvp);
16214543Smarks 		return (EPERM);
16224543Smarks 	}
16234543Smarks 	usercred = cralloc();
16244543Smarks 	if ((crsetugid(usercred, uid, gid) != 0) ||
16254543Smarks 	    (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) {
16264543Smarks 		nvlist_free(nvp);
16274543Smarks 		crfree(usercred);
16284543Smarks 		return (EPERM);
16294543Smarks 	}
16304543Smarks 	nvlist_free(nvp);
16314543Smarks 	error = dsl_deleg_access(zc->zc_name,
16324787Sahrens 	    zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred);
16334543Smarks 	crfree(usercred);
16344543Smarks 	return (error);
16354543Smarks }
16364543Smarks 
16375367Sahrens /*
16385367Sahrens  * inputs:
16395367Sahrens  * zc_name		name of filesystem
16405367Sahrens  * zc_nvlist_src{_size}	nvlist of delegated permissions
16415367Sahrens  * zc_perm_action	allow/unallow flag
16425367Sahrens  *
16435367Sahrens  * outputs:		none
16445367Sahrens  */
16454543Smarks static int
16464543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc)
16474543Smarks {
16484543Smarks 	int error;
16494543Smarks 	nvlist_t *fsaclnv = NULL;
16504543Smarks 
16515094Slling 	if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
16525094Slling 	    &fsaclnv)) != 0)
16534543Smarks 		return (error);
16544543Smarks 
16554543Smarks 	/*
16564543Smarks 	 * Verify nvlist is constructed correctly
16574543Smarks 	 */
16584543Smarks 	if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) {
16594543Smarks 		nvlist_free(fsaclnv);
16604543Smarks 		return (EINVAL);
16614543Smarks 	}
16624543Smarks 
16634543Smarks 	/*
16644543Smarks 	 * If we don't have PRIV_SYS_MOUNT, then validate
16654543Smarks 	 * that user is allowed to hand out each permission in
16664543Smarks 	 * the nvlist(s)
16674543Smarks 	 */
16684543Smarks 
16694787Sahrens 	error = secpolicy_zfs(CRED());
16704543Smarks 	if (error) {
16714787Sahrens 		if (zc->zc_perm_action == B_FALSE) {
16724787Sahrens 			error = dsl_deleg_can_allow(zc->zc_name,
16734787Sahrens 			    fsaclnv, CRED());
16744787Sahrens 		} else {
16754787Sahrens 			error = dsl_deleg_can_unallow(zc->zc_name,
16764787Sahrens 			    fsaclnv, CRED());
16774787Sahrens 		}
16784543Smarks 	}
16794543Smarks 
16804543Smarks 	if (error == 0)
16814543Smarks 		error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action);
16824543Smarks 
16834543Smarks 	nvlist_free(fsaclnv);
16844543Smarks 	return (error);
16854543Smarks }
16864543Smarks 
16875367Sahrens /*
16885367Sahrens  * inputs:
16895367Sahrens  * zc_name		name of filesystem
16905367Sahrens  *
16915367Sahrens  * outputs:
16925367Sahrens  * zc_nvlist_src{_size}	nvlist of delegated permissions
16935367Sahrens  */
16944543Smarks static int
16954543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc)
16964543Smarks {
16974543Smarks 	nvlist_t *nvp;
16984543Smarks 	int error;
16994543Smarks 
17004543Smarks 	if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) {
17014543Smarks 		error = put_nvlist(zc, nvp);
17024543Smarks 		nvlist_free(nvp);
17034543Smarks 	}
17044543Smarks 
17054543Smarks 	return (error);
17064543Smarks }
17074543Smarks 
17085367Sahrens /*
17095367Sahrens  * inputs:
17105367Sahrens  * zc_name		name of volume
17115367Sahrens  *
17125367Sahrens  * outputs:		none
17135367Sahrens  */
17144543Smarks static int
1715789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc)
1716789Sahrens {
17174787Sahrens 	return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip)));
1718789Sahrens }
1719789Sahrens 
17205367Sahrens /*
17215367Sahrens  * inputs:
17225367Sahrens  * zc_name		name of volume
17235367Sahrens  *
17245367Sahrens  * outputs:		none
17255367Sahrens  */
1726789Sahrens static int
1727789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc)
1728789Sahrens {
17292676Seschrock 	return (zvol_remove_minor(zc->zc_name));
1730789Sahrens }
1731789Sahrens 
1732789Sahrens /*
1733789Sahrens  * Search the vfs list for a specified resource.  Returns a pointer to it
1734789Sahrens  * or NULL if no suitable entry is found. The caller of this routine
1735789Sahrens  * is responsible for releasing the returned vfs pointer.
1736789Sahrens  */
1737789Sahrens static vfs_t *
1738789Sahrens zfs_get_vfs(const char *resource)
1739789Sahrens {
1740789Sahrens 	struct vfs *vfsp;
1741789Sahrens 	struct vfs *vfs_found = NULL;
1742789Sahrens 
1743789Sahrens 	vfs_list_read_lock();
1744789Sahrens 	vfsp = rootvfs;
1745789Sahrens 	do {
1746789Sahrens 		if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) {
1747789Sahrens 			VFS_HOLD(vfsp);
1748789Sahrens 			vfs_found = vfsp;
1749789Sahrens 			break;
1750789Sahrens 		}
1751789Sahrens 		vfsp = vfsp->vfs_next;
1752789Sahrens 	} while (vfsp != rootvfs);
1753789Sahrens 	vfs_list_unlock();
1754789Sahrens 	return (vfs_found);
1755789Sahrens }
1756789Sahrens 
17574543Smarks /* ARGSUSED */
1758789Sahrens static void
17594543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
1760789Sahrens {
17615331Samw 	zfs_creat_t *zct = arg;
17625331Samw 	uint64_t version;
17635331Samw 
17645331Samw 	if (spa_version(dmu_objset_spa(os)) >= SPA_VERSION_FUID)
17655331Samw 		version = ZPL_VERSION;
17665331Samw 	else
17675331Samw 		version = ZPL_VERSION_FUID - 1;
17685331Samw 
17695331Samw 	(void) nvlist_lookup_uint64(zct->zct_props,
17704577Sahrens 	    zfs_prop_to_name(ZFS_PROP_VERSION), &version);
17714577Sahrens 
17725331Samw 	zfs_create_fs(os, cr, version, zct->zct_norm, tx);
17735331Samw }
17745331Samw 
17755331Samw /*
17765331Samw  * zfs_prop_lookup()
17775331Samw  *
17785331Samw  * Look for the property first in the existing property nvlist.  If
17795331Samw  * it's already present, you're done.  If it's not there, attempt to
17805331Samw  * find the property value from a parent dataset.  If that fails, fall
17815331Samw  * back to the property's default value.  In either of these two
17825331Samw  * cases, if update is TRUE, add a value for the property to the
17835331Samw  * property nvlist.
17845331Samw  *
17855331Samw  * If the rval pointer is non-NULL, copy the discovered value to rval.
17865331Samw  *
17875331Samw  * If we get any unexpected errors, bail and return the error number
17885331Samw  * to the caller.
17895331Samw  *
17905331Samw  * If we succeed, return 0.
17915331Samw  */
17925331Samw static int
17935331Samw zfs_prop_lookup(const char *parentname, zfs_prop_t propnum,
17945331Samw     nvlist_t *proplist, uint64_t *rval, boolean_t update)
17955331Samw {
17965331Samw 	const char *propname;
17975331Samw 	uint64_t value;
17985331Samw 	int error = ENOENT;
17995331Samw 
18005331Samw 	propname = zfs_prop_to_name(propnum);
18015331Samw 	if (proplist != NULL)
18025331Samw 		error = nvlist_lookup_uint64(proplist, propname, &value);
18035331Samw 	if (error == ENOENT) {
18045331Samw 		error = dsl_prop_get_integer(parentname, propname,
18055331Samw 		    &value, NULL);
18065331Samw 		if (error == ENOENT)
18075331Samw 			value = zfs_prop_default_numeric(propnum);
18085331Samw 		else if (error != 0)
18095331Samw 			return (error);
18105331Samw 		if (update) {
18115331Samw 			ASSERT(proplist != NULL);
18125331Samw 			error = nvlist_add_uint64(proplist, propname, value);
18135331Samw 		}
18145331Samw 	}
18155331Samw 	if (error == 0 && rval)
18165331Samw 		*rval = value;
18175331Samw 	return (error);
18185331Samw }
18195331Samw 
18205331Samw /*
18215331Samw  * zfs_normalization_get
18225331Samw  *
18235331Samw  * Get the normalization flag value.  If the properties have
18245331Samw  * non-default values, make sure the pool version is recent enough to
18255331Samw  * support these choices.
18265331Samw  */
18275331Samw static int
18285331Samw zfs_normalization_get(const char *dataset, nvlist_t *proplist, int *norm,
18295331Samw     boolean_t update)
18305331Samw {
18315331Samw 	char parentname[MAXNAMELEN];
18325331Samw 	char poolname[MAXNAMELEN];
18335331Samw 	char *cp;
18345331Samw 	uint64_t value;
18355331Samw 	int check = 0;
18365331Samw 	int error;
18375331Samw 
18385331Samw 	ASSERT(norm != NULL);
18395331Samw 	*norm = 0;
18405331Samw 
18415331Samw 	(void) strncpy(parentname, dataset, sizeof (parentname));
18425331Samw 	cp = strrchr(parentname, '@');
18435331Samw 	if (cp != NULL) {
18445331Samw 		cp[0] = '\0';
18455331Samw 	} else {
18465331Samw 		cp = strrchr(parentname, '/');
18475331Samw 		if (cp == NULL)
18485331Samw 			return (ENOENT);
18495331Samw 		cp[0] = '\0';
18505331Samw 	}
18515331Samw 
18525331Samw 	(void) strncpy(poolname, dataset, sizeof (poolname));
18535331Samw 	cp = strchr(poolname, '/');
18545331Samw 	if (cp != NULL)
18555331Samw 		cp[0] = '\0';
18565331Samw 
18575375Stimh 	/*
18585375Stimh 	 * Make sure pool is of new enough vintage to support normalization.
18595375Stimh 	 */
18605375Stimh 	if (zfs_check_version(poolname, SPA_VERSION_NORMALIZATION))
18615375Stimh 		return (0);
18625375Stimh 
18635331Samw 	error = zfs_prop_lookup(parentname, ZFS_PROP_UTF8ONLY,
18645331Samw 	    proplist, &value, update);
18655331Samw 	if (error != 0)
18665331Samw 		return (error);
18675331Samw 	if (value != zfs_prop_default_numeric(ZFS_PROP_UTF8ONLY))
18685331Samw 		check = 1;
18695331Samw 
18705331Samw 	error = zfs_prop_lookup(parentname, ZFS_PROP_NORMALIZE,
18715331Samw 	    proplist, &value, update);
18725331Samw 	if (error != 0)
18735331Samw 		return (error);
18745331Samw 	if (value != zfs_prop_default_numeric(ZFS_PROP_NORMALIZE)) {
18755331Samw 		check = 1;
18765331Samw 		switch ((int)value) {
18775331Samw 		case ZFS_NORMALIZE_NONE:
18785331Samw 			break;
18795331Samw 		case ZFS_NORMALIZE_C:
18805331Samw 			*norm |= U8_TEXTPREP_NFC;
18815331Samw 			break;
18825331Samw 		case ZFS_NORMALIZE_D:
18835331Samw 			*norm |= U8_TEXTPREP_NFD;
18845331Samw 			break;
18855331Samw 		case ZFS_NORMALIZE_KC:
18865331Samw 			*norm |= U8_TEXTPREP_NFKC;
18875331Samw 			break;
18885331Samw 		case ZFS_NORMALIZE_KD:
18895331Samw 			*norm |= U8_TEXTPREP_NFKD;
18905331Samw 			break;
18915331Samw 		default:
18925331Samw 			ASSERT((int)value >= ZFS_NORMALIZE_NONE);
18935331Samw 			ASSERT((int)value <= ZFS_NORMALIZE_KD);
18945331Samw 			break;
18955331Samw 		}
18965331Samw 	}
18975331Samw 
18985331Samw 	error = zfs_prop_lookup(parentname, ZFS_PROP_CASE,
18995331Samw 	    proplist, &value, update);
19005331Samw 	if (error != 0)
19015331Samw 		return (error);
19025331Samw 	if (value != zfs_prop_default_numeric(ZFS_PROP_CASE)) {
19035331Samw 		check = 1;
19045331Samw 		switch ((int)value) {
19055331Samw 		case ZFS_CASE_SENSITIVE:
19065331Samw 			break;
19075331Samw 		case ZFS_CASE_INSENSITIVE:
19085331Samw 			*norm |= U8_TEXTPREP_TOUPPER;
19095331Samw 			break;
19105331Samw 		case ZFS_CASE_MIXED:
19115331Samw 			*norm |= U8_TEXTPREP_TOUPPER;
19125331Samw 			break;
19135331Samw 		default:
19145331Samw 			ASSERT((int)value >= ZFS_CASE_SENSITIVE);
19155331Samw 			ASSERT((int)value <= ZFS_CASE_MIXED);
19165331Samw 			break;
19175331Samw 		}
19185331Samw 	}
19195331Samw 
19205375Stimh 	/*
19215375Stimh 	 * At the moment we are disabling non-default values for these
19225375Stimh 	 * properties because they cannot be preserved properly with a
19235375Stimh 	 * zfs send.
19245375Stimh 	 */
19255331Samw 	if (check == 1)
19265375Stimh 		return (ENOTSUP);
19275375Stimh 
19285331Samw 	return (0);
1929789Sahrens }
1930789Sahrens 
19315367Sahrens /*
19325367Sahrens  * inputs:
19335367Sahrens  * zc_objset_type	type of objset to create (fs vs zvol)
19345367Sahrens  * zc_name		name of new objset
19355367Sahrens  * zc_value		name of snapshot to clone from (may be empty)
19365367Sahrens  * zc_nvlist_src{_size}	nvlist of properties to apply
19375367Sahrens  *
19385367Sahrens  * outputs:		none
19395367Sahrens  */
1940789Sahrens static int
1941789Sahrens zfs_ioc_create(zfs_cmd_t *zc)
1942789Sahrens {
1943789Sahrens 	objset_t *clone;
1944789Sahrens 	int error = 0;
19455331Samw 	zfs_creat_t zct;
19464543Smarks 	nvlist_t *nvprops = NULL;
19474543Smarks 	void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
1948789Sahrens 	dmu_objset_type_t type = zc->zc_objset_type;
1949789Sahrens 
1950789Sahrens 	switch (type) {
1951789Sahrens 
1952789Sahrens 	case DMU_OST_ZFS:
1953789Sahrens 		cbfunc = zfs_create_cb;
1954789Sahrens 		break;
1955789Sahrens 
1956789Sahrens 	case DMU_OST_ZVOL:
1957789Sahrens 		cbfunc = zvol_create_cb;
1958789Sahrens 		break;
1959789Sahrens 
1960789Sahrens 	default:
19612199Sahrens 		cbfunc = NULL;
19622199Sahrens 	}
19635326Sek110237 	if (strchr(zc->zc_name, '@') ||
19645326Sek110237 	    strchr(zc->zc_name, '%'))
1965789Sahrens 		return (EINVAL);
1966789Sahrens 
19672676Seschrock 	if (zc->zc_nvlist_src != NULL &&
19685094Slling 	    (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
19695094Slling 	    &nvprops)) != 0)
19702676Seschrock 		return (error);
19712676Seschrock 
19725331Samw 	zct.zct_norm = 0;
19735331Samw 	zct.zct_props = nvprops;
19745331Samw 
19752676Seschrock 	if (zc->zc_value[0] != '\0') {
1976789Sahrens 		/*
1977789Sahrens 		 * We're creating a clone of an existing snapshot.
1978789Sahrens 		 */
19792676Seschrock 		zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
19802676Seschrock 		if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) {
19814543Smarks 			nvlist_free(nvprops);
1982789Sahrens 			return (EINVAL);
19832676Seschrock 		}
1984789Sahrens 
19852676Seschrock 		error = dmu_objset_open(zc->zc_value, type,
1986789Sahrens 		    DS_MODE_STANDARD | DS_MODE_READONLY, &clone);
19872676Seschrock 		if (error) {
19884543Smarks 			nvlist_free(nvprops);
1989789Sahrens 			return (error);
19902676Seschrock 		}
1991789Sahrens 		error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL);
19925331Samw 		if (error) {
19935331Samw 			dmu_objset_close(clone);
19945331Samw 			nvlist_free(nvprops);
19955331Samw 			return (error);
19965331Samw 		}
19975331Samw 		/*
19985331Samw 		 * If caller did not provide any properties, allocate
19995331Samw 		 * an nvlist for properties, as we will be adding our set-once
20005331Samw 		 * properties to it.  This carries the choices made on the
20015331Samw 		 * original file system into the clone.
20025331Samw 		 */
20035331Samw 		if (nvprops == NULL)
20045331Samw 			VERIFY(nvlist_alloc(&nvprops,
20055331Samw 			    NV_UNIQUE_NAME, KM_SLEEP) == 0);
20065331Samw 
20075331Samw 		/*
20085331Samw 		 * We have to have normalization and case-folding
20095331Samw 		 * flags correct when we do the file system creation,
20105331Samw 		 * so go figure them out now.  All we really care about
20115331Samw 		 * here is getting these values into the property list.
20125331Samw 		 */
20135331Samw 		error = zfs_normalization_get(zc->zc_value, nvprops,
20145331Samw 		    &zct.zct_norm, B_TRUE);
20155331Samw 		if (error != 0) {
20165331Samw 			dmu_objset_close(clone);
20175331Samw 			nvlist_free(nvprops);
20185331Samw 			return (error);
20195331Samw 		}
2020789Sahrens 		dmu_objset_close(clone);
2021789Sahrens 	} else {
20222676Seschrock 		if (cbfunc == NULL) {
20234543Smarks 			nvlist_free(nvprops);
20242199Sahrens 			return (EINVAL);
20252676Seschrock 		}
20262676Seschrock 
2027789Sahrens 		if (type == DMU_OST_ZVOL) {
20282676Seschrock 			uint64_t volsize, volblocksize;
20292676Seschrock 
20304543Smarks 			if (nvprops == NULL ||
20314543Smarks 			    nvlist_lookup_uint64(nvprops,
20322676Seschrock 			    zfs_prop_to_name(ZFS_PROP_VOLSIZE),
20332676Seschrock 			    &volsize) != 0) {
20344543Smarks 				nvlist_free(nvprops);
20352676Seschrock 				return (EINVAL);
20362676Seschrock 			}
20372676Seschrock 
20384543Smarks 			if ((error = nvlist_lookup_uint64(nvprops,
20392676Seschrock 			    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
20402676Seschrock 			    &volblocksize)) != 0 && error != ENOENT) {
20414543Smarks 				nvlist_free(nvprops);
20422676Seschrock 				return (EINVAL);
20432676Seschrock 			}
20441133Seschrock 
20452676Seschrock 			if (error != 0)
20462676Seschrock 				volblocksize = zfs_prop_default_numeric(
20472676Seschrock 				    ZFS_PROP_VOLBLOCKSIZE);
20482676Seschrock 
20492676Seschrock 			if ((error = zvol_check_volblocksize(
20502676Seschrock 			    volblocksize)) != 0 ||
20512676Seschrock 			    (error = zvol_check_volsize(volsize,
20522676Seschrock 			    volblocksize)) != 0) {
20534543Smarks 				nvlist_free(nvprops);
2054789Sahrens 				return (error);
20552676Seschrock 			}
20564577Sahrens 		} else if (type == DMU_OST_ZFS) {
20574577Sahrens 			uint64_t version;
20585331Samw 			int error;
20595331Samw 
20605331Samw 			error = nvlist_lookup_uint64(nvprops,
20615331Samw 			    zfs_prop_to_name(ZFS_PROP_VERSION), &version);
20625331Samw 
20635331Samw 			if (error == 0 && (version < ZPL_VERSION_INITIAL ||
20644577Sahrens 			    version > ZPL_VERSION)) {
20654577Sahrens 				nvlist_free(nvprops);
20665331Samw 				return (ENOTSUP);
20675331Samw 			} else if (error == 0 && version >= ZPL_VERSION_FUID &&
20685331Samw 			    zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) {
20695331Samw 				nvlist_free(nvprops);
20705331Samw 				return (ENOTSUP);
20715331Samw 			}
20725331Samw 
20735331Samw 			/*
20745331Samw 			 * We have to have normalization and
20755331Samw 			 * case-folding flags correct when we do the
20765331Samw 			 * file system creation, so go figure them out
20775331Samw 			 * now.  The final argument to zfs_normalization_get()
20785331Samw 			 * tells that routine not to update the nvprops
20795331Samw 			 * list.
20805331Samw 			 */
20815331Samw 			error = zfs_normalization_get(zc->zc_name, nvprops,
20825331Samw 			    &zct.zct_norm, B_FALSE);
20835331Samw 			if (error != 0) {
20845331Samw 				nvlist_free(nvprops);
20855331Samw 				return (error);
20864577Sahrens 			}
20872676Seschrock 		}
20882676Seschrock 		error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc,
20895331Samw 		    &zct);
2090789Sahrens 	}
20912676Seschrock 
20922676Seschrock 	/*
20932676Seschrock 	 * It would be nice to do this atomically.
20942676Seschrock 	 */
20952676Seschrock 	if (error == 0) {
20964787Sahrens 		if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0)
20972676Seschrock 			(void) dmu_objset_destroy(zc->zc_name);
20982676Seschrock 	}
20992676Seschrock 
21004543Smarks 	nvlist_free(nvprops);
2101789Sahrens 	return (error);
2102789Sahrens }
2103789Sahrens 
21045367Sahrens /*
21055367Sahrens  * inputs:
21065367Sahrens  * zc_name	name of filesystem
21075367Sahrens  * zc_value	short name of snapshot
21085367Sahrens  * zc_cookie	recursive flag
21095367Sahrens  *
21105367Sahrens  * outputs:	none
21115367Sahrens  */
2112789Sahrens static int
21132199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc)
21142199Sahrens {
21152676Seschrock 	if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
21162199Sahrens 		return (EINVAL);
21172199Sahrens 	return (dmu_objset_snapshot(zc->zc_name,
21182676Seschrock 	    zc->zc_value, zc->zc_cookie));
21192199Sahrens }
21202199Sahrens 
21214007Smmusante int
21222199Sahrens zfs_unmount_snap(char *name, void *arg)
2123789Sahrens {
21242199Sahrens 	char *snapname = arg;
21252199Sahrens 	char *cp;
21262417Sahrens 	vfs_t *vfsp = NULL;
21272199Sahrens 
21282199Sahrens 	/*
21292199Sahrens 	 * Snapshots (which are under .zfs control) must be unmounted
21302199Sahrens 	 * before they can be destroyed.
21312199Sahrens 	 */
21322199Sahrens 
21332199Sahrens 	if (snapname) {
21342199Sahrens 		(void) strcat(name, "@");
21352199Sahrens 		(void) strcat(name, snapname);
21362199Sahrens 		vfsp = zfs_get_vfs(name);
21372199Sahrens 		cp = strchr(name, '@');
21382199Sahrens 		*cp = '\0';
21392417Sahrens 	} else if (strchr(name, '@')) {
21402199Sahrens 		vfsp = zfs_get_vfs(name);
21412199Sahrens 	}
21422199Sahrens 
21432199Sahrens 	if (vfsp) {
21442199Sahrens 		/*
21452199Sahrens 		 * Always force the unmount for snapshots.
21462199Sahrens 		 */
21472199Sahrens 		int flag = MS_FORCE;
2148789Sahrens 		int err;
2149789Sahrens 
21502199Sahrens 		if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) {
21512199Sahrens 			VFS_RELE(vfsp);
21522199Sahrens 			return (err);
21532199Sahrens 		}
21542199Sahrens 		VFS_RELE(vfsp);
21552199Sahrens 		if ((err = dounmount(vfsp, flag, kcred)) != 0)
21562199Sahrens 			return (err);
21572199Sahrens 	}
21582199Sahrens 	return (0);
21592199Sahrens }
21602199Sahrens 
21615367Sahrens /*
21625367Sahrens  * inputs:
21635367Sahrens  * zc_name	name of filesystem
21645367Sahrens  * zc_value	short name of snapshot
21655367Sahrens  *
21665367Sahrens  * outputs:	none
21675367Sahrens  */
21682199Sahrens static int
21692199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc)
21702199Sahrens {
21712199Sahrens 	int err;
2172789Sahrens 
21732676Seschrock 	if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
21742199Sahrens 		return (EINVAL);
21752199Sahrens 	err = dmu_objset_find(zc->zc_name,
21762676Seschrock 	    zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN);
21772199Sahrens 	if (err)
21782199Sahrens 		return (err);
21792676Seschrock 	return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value));
21802199Sahrens }
21812199Sahrens 
21825367Sahrens /*
21835367Sahrens  * inputs:
21845367Sahrens  * zc_name		name of dataset to destroy
21855367Sahrens  * zc_objset_type	type of objset
21865367Sahrens  *
21875367Sahrens  * outputs:		none
21885367Sahrens  */
21892199Sahrens static int
21902199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc)
21912199Sahrens {
21922199Sahrens 	if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) {
21932199Sahrens 		int err = zfs_unmount_snap(zc->zc_name, NULL);
21942199Sahrens 		if (err)
21952199Sahrens 			return (err);
2196789Sahrens 	}
2197789Sahrens 
2198789Sahrens 	return (dmu_objset_destroy(zc->zc_name));
2199789Sahrens }
2200789Sahrens 
22015367Sahrens /*
22025367Sahrens  * inputs:
22035446Sahrens  * zc_name	name of dataset to rollback (to most recent snapshot)
22045367Sahrens  *
22055367Sahrens  * outputs:	none
22065367Sahrens  */
2207789Sahrens static int
2208789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc)
2209789Sahrens {
22105446Sahrens 	objset_t *os;
22115446Sahrens 	int error;
22125446Sahrens 	zfsvfs_t *zfsvfs = NULL;
22135446Sahrens 
22145446Sahrens 	/*
22155446Sahrens 	 * Get the zfsvfs for the receiving objset. There
22165446Sahrens 	 * won't be one if we're operating on a zvol, if the
22175446Sahrens 	 * objset doesn't exist yet, or is not mounted.
22185446Sahrens 	 */
22195446Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
22205446Sahrens 	    DS_MODE_STANDARD, &os);
22215446Sahrens 	if (error)
22225446Sahrens 		return (error);
22235446Sahrens 
22245446Sahrens 	if (dmu_objset_type(os) == DMU_OST_ZFS) {
22255446Sahrens 		mutex_enter(&os->os->os_user_ptr_lock);
22265446Sahrens 		zfsvfs = dmu_objset_get_user(os);
22275446Sahrens 		if (zfsvfs != NULL)
22285446Sahrens 			VFS_HOLD(zfsvfs->z_vfs);
22295446Sahrens 		mutex_exit(&os->os->os_user_ptr_lock);
22305446Sahrens 	}
22315446Sahrens 
22325446Sahrens 	if (zfsvfs != NULL) {
22335446Sahrens 		char osname[MAXNAMELEN];
22345446Sahrens 		int mode;
22355446Sahrens 
22365446Sahrens 		VERIFY3U(0, ==, zfs_suspend_fs(zfsvfs, osname, &mode));
22375446Sahrens 		ASSERT(strcmp(osname, zc->zc_name) == 0);
22385446Sahrens 		error = dmu_objset_rollback(os);
22395446Sahrens 		VERIFY3U(0, ==, zfs_resume_fs(zfsvfs, osname, mode));
22405446Sahrens 
22415446Sahrens 		VFS_RELE(zfsvfs->z_vfs);
22425446Sahrens 	} else {
22435446Sahrens 		error = dmu_objset_rollback(os);
22445446Sahrens 	}
22455446Sahrens 	/* Note, the dmu_objset_rollback() closes the objset for us. */
22465446Sahrens 
22475446Sahrens 	return (error);
2248789Sahrens }
2249789Sahrens 
22505367Sahrens /*
22515367Sahrens  * inputs:
22525367Sahrens  * zc_name	old name of dataset
22535367Sahrens  * zc_value	new name of dataset
22545367Sahrens  * zc_cookie	recursive flag (only valid for snapshots)
22555367Sahrens  *
22565367Sahrens  * outputs:	none
22575367Sahrens  */
2258789Sahrens static int
2259789Sahrens zfs_ioc_rename(zfs_cmd_t *zc)
2260789Sahrens {
22614490Svb160487 	boolean_t recursive = zc->zc_cookie & 1;
22624007Smmusante 
22632676Seschrock 	zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
22645326Sek110237 	if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
22655326Sek110237 	    strchr(zc->zc_value, '%'))
2266789Sahrens 		return (EINVAL);
2267789Sahrens 
22684007Smmusante 	/*
22694007Smmusante 	 * Unmount snapshot unless we're doing a recursive rename,
22704007Smmusante 	 * in which case the dataset code figures out which snapshots
22714007Smmusante 	 * to unmount.
22724007Smmusante 	 */
22734007Smmusante 	if (!recursive && strchr(zc->zc_name, '@') != NULL &&
2274789Sahrens 	    zc->zc_objset_type == DMU_OST_ZFS) {
22752199Sahrens 		int err = zfs_unmount_snap(zc->zc_name, NULL);
22762199Sahrens 		if (err)
22772199Sahrens 			return (err);
2278789Sahrens 	}
2279789Sahrens 
22804007Smmusante 	return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive));
2281789Sahrens }
2282789Sahrens 
22835367Sahrens /*
22845367Sahrens  * inputs:
22855367Sahrens  * zc_name		name of containing filesystem
22865367Sahrens  * zc_nvlist_src{_size}	nvlist of properties to apply
22875367Sahrens  * zc_value		name of snapshot to create
22885367Sahrens  * zc_string		name of clone origin (if DRR_FLAG_CLONE)
22895367Sahrens  * zc_cookie		file descriptor to recv from
22905367Sahrens  * zc_begin_record	the BEGIN record of the stream (not byteswapped)
22915367Sahrens  * zc_guid		force flag
22925367Sahrens  *
22935367Sahrens  * outputs:
22945367Sahrens  * zc_cookie		number of bytes read
22955367Sahrens  */
2296789Sahrens static int
22975367Sahrens zfs_ioc_recv(zfs_cmd_t *zc)
2298789Sahrens {
2299789Sahrens 	file_t *fp;
23005326Sek110237 	objset_t *os;
23015367Sahrens 	dmu_recv_cookie_t drc;
23025326Sek110237 	zfsvfs_t *zfsvfs = NULL;
23035326Sek110237 	boolean_t force = (boolean_t)zc->zc_guid;
2304789Sahrens 	int error, fd;
23055367Sahrens 	offset_t off;
23065367Sahrens 	nvlist_t *props = NULL;
23075367Sahrens 	objset_t *origin = NULL;
23085367Sahrens 	char *tosnap;
23095367Sahrens 	char tofs[ZFS_MAXNAMELEN];
2310789Sahrens 
23113265Sahrens 	if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
23125326Sek110237 	    strchr(zc->zc_value, '@') == NULL ||
23135326Sek110237 	    strchr(zc->zc_value, '%'))
23143265Sahrens 		return (EINVAL);
23153265Sahrens 
23165367Sahrens 	(void) strcpy(tofs, zc->zc_value);
23175367Sahrens 	tosnap = strchr(tofs, '@');
23185367Sahrens 	*tosnap = '\0';
23195367Sahrens 	tosnap++;
23205367Sahrens 
23215367Sahrens 	if (zc->zc_nvlist_src != NULL &&
23225367Sahrens 	    (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
23235367Sahrens 	    &props)) != 0)
23245367Sahrens 		return (error);
23255367Sahrens 
2326789Sahrens 	fd = zc->zc_cookie;
2327789Sahrens 	fp = getf(fd);
23285367Sahrens 	if (fp == NULL) {
23295367Sahrens 		nvlist_free(props);
2330789Sahrens 		return (EBADF);
23315367Sahrens 	}
23325326Sek110237 
23335326Sek110237 	/*
23345326Sek110237 	 * Get the zfsvfs for the receiving objset. There
23355326Sek110237 	 * won't be one if we're operating on a zvol, if the
23365326Sek110237 	 * objset doesn't exist yet, or is not mounted.
23375326Sek110237 	 */
23385367Sahrens 
23395446Sahrens 	error = dmu_objset_open(tofs, DMU_OST_ZFS,
23405326Sek110237 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
23415326Sek110237 	if (!error) {
23425446Sahrens 		mutex_enter(&os->os->os_user_ptr_lock);
23435446Sahrens 		zfsvfs = dmu_objset_get_user(os);
23445446Sahrens 		if (zfsvfs != NULL)
23455446Sahrens 			VFS_HOLD(zfsvfs->z_vfs);
23465446Sahrens 		mutex_exit(&os->os->os_user_ptr_lock);
23475326Sek110237 		dmu_objset_close(os);
23485326Sek110237 	}
23495326Sek110237 
23505367Sahrens 	if (zc->zc_string[0]) {
23515367Sahrens 		error = dmu_objset_open(zc->zc_string, DMU_OST_ANY,
23525367Sahrens 		    DS_MODE_STANDARD | DS_MODE_READONLY, &origin);
23535367Sahrens 		if (error) {
23545367Sahrens 			if (zfsvfs != NULL)
23555367Sahrens 				VFS_RELE(zfsvfs->z_vfs);
23565367Sahrens 			nvlist_free(props);
23575367Sahrens 			releasef(fd);
23585367Sahrens 			return (error);
23595367Sahrens 		}
23605367Sahrens 	}
23615367Sahrens 
23625367Sahrens 	error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record,
23635367Sahrens 	    force, origin, zfsvfs != NULL, &drc);
23645367Sahrens 	if (origin)
23655367Sahrens 		dmu_objset_close(origin);
23665367Sahrens 	if (error) {
23675367Sahrens 		if (zfsvfs != NULL)
23685367Sahrens 			VFS_RELE(zfsvfs->z_vfs);
23695367Sahrens 		nvlist_free(props);
23705367Sahrens 		releasef(fd);
23715367Sahrens 		return (error);
23725367Sahrens 	}
23735326Sek110237 
23745326Sek110237 	/*
23755367Sahrens 	 * If properties are supplied, they are to completely replace
23765367Sahrens 	 * the existing ones; "inherit" any existing properties.
23775326Sek110237 	 */
23785367Sahrens 	if (props) {
23795367Sahrens 		objset_t *os;
23805367Sahrens 		nvlist_t *nv = NULL;
23815367Sahrens 
23825367Sahrens 		error = dmu_objset_open(tofs, DMU_OST_ANY,
23835367Sahrens 		    DS_MODE_STANDARD | DS_MODE_READONLY | DS_MODE_INCONSISTENT,
23845367Sahrens 		    &os);
23855367Sahrens 		if (error == 0) {
23865367Sahrens 			error = dsl_prop_get_all(os, &nv);
23875367Sahrens 			dmu_objset_close(os);
23885367Sahrens 		}
23895367Sahrens 		if (error == 0) {
23905367Sahrens 			nvpair_t *elem;
23915446Sahrens 			zfs_cmd_t *zc2;
23925446Sahrens 			zc2 = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP);
23935446Sahrens 
23945446Sahrens 			(void) strcpy(zc2->zc_name, tofs);
23955367Sahrens 			for (elem = nvlist_next_nvpair(nv, NULL); elem;
23965367Sahrens 			    elem = nvlist_next_nvpair(nv, elem)) {
23975446Sahrens 				(void) strcpy(zc2->zc_value, nvpair_name(elem));
23985446Sahrens 				if (zfs_secpolicy_inherit(zc2, CRED()) == 0)
23995446Sahrens 					(void) zfs_ioc_inherit_prop(zc2);
24005326Sek110237 			}
24015446Sahrens 			kmem_free(zc2, sizeof (zfs_cmd_t));
24025326Sek110237 		}
24035367Sahrens 		if (nv)
24045367Sahrens 			nvlist_free(nv);
24055367Sahrens 	}
24065367Sahrens 
24075367Sahrens 	/*
24085367Sahrens 	 * Set properties.  Note, we ignore errors.  Would be better to
24095367Sahrens 	 * do best-effort in zfs_set_prop_nvlist, too.
24105367Sahrens 	 */
24115367Sahrens 	(void) zfs_set_prop_nvlist(tofs, props);
24125367Sahrens 	nvlist_free(props);
24135367Sahrens 
24145367Sahrens 	off = fp->f_offset;
24155367Sahrens 	error = dmu_recv_stream(&drc, fp->f_vnode, &off);
24165367Sahrens 
24175367Sahrens 	if (error == 0) {
24185367Sahrens 		if (zfsvfs != NULL) {
24195367Sahrens 			char osname[MAXNAMELEN];
24205367Sahrens 			int mode;
24215367Sahrens 
24225367Sahrens 			(void) zfs_suspend_fs(zfsvfs, osname, &mode);
24235367Sahrens 			error = dmu_recv_end(&drc);
24245367Sahrens 			error |= zfs_resume_fs(zfsvfs, osname, mode);
24255367Sahrens 		} else {
24265367Sahrens 			error = dmu_recv_end(&drc);
24275367Sahrens 		}
24285326Sek110237 	}
24295326Sek110237 	if (zfsvfs != NULL)
24305326Sek110237 		VFS_RELE(zfsvfs->z_vfs);
24315367Sahrens 
24325367Sahrens 	zc->zc_cookie = off - fp->f_offset;
24335367Sahrens 	if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
24345367Sahrens 		fp->f_offset = off;
24352885Sahrens 
2436789Sahrens 	releasef(fd);
2437789Sahrens 	return (error);
2438789Sahrens }
2439789Sahrens 
24405367Sahrens /*
24415367Sahrens  * inputs:
24425367Sahrens  * zc_name	name of snapshot to send
24435367Sahrens  * zc_value	short name of incremental fromsnap (may be empty)
24445367Sahrens  * zc_cookie	file descriptor to send stream to
24455367Sahrens  * zc_obj	fromorigin flag (mutually exclusive with zc_value)
24465367Sahrens  *
24475367Sahrens  * outputs: none
24485367Sahrens  */
2449789Sahrens static int
24505367Sahrens zfs_ioc_send(zfs_cmd_t *zc)
2451789Sahrens {
2452789Sahrens 	objset_t *fromsnap = NULL;
2453789Sahrens 	objset_t *tosnap;
2454789Sahrens 	file_t *fp;
2455789Sahrens 	int error;
24565367Sahrens 	offset_t off;
2457789Sahrens 
2458789Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
2459789Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap);
2460789Sahrens 	if (error)
2461789Sahrens 		return (error);
2462789Sahrens 
24632676Seschrock 	if (zc->zc_value[0] != '\0') {
24642885Sahrens 		char buf[MAXPATHLEN];
24652885Sahrens 		char *cp;
24662885Sahrens 
24672885Sahrens 		(void) strncpy(buf, zc->zc_name, sizeof (buf));
24682885Sahrens 		cp = strchr(buf, '@');
24692885Sahrens 		if (cp)
24702885Sahrens 			*(cp+1) = 0;
24712885Sahrens 		(void) strncat(buf, zc->zc_value, sizeof (buf));
24722885Sahrens 		error = dmu_objset_open(buf, DMU_OST_ANY,
2473789Sahrens 		    DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap);
2474789Sahrens 		if (error) {
2475789Sahrens 			dmu_objset_close(tosnap);
2476789Sahrens 			return (error);
2477789Sahrens 		}
2478789Sahrens 	}
2479789Sahrens 
2480789Sahrens 	fp = getf(zc->zc_cookie);
2481789Sahrens 	if (fp == NULL) {
2482789Sahrens 		dmu_objset_close(tosnap);
2483789Sahrens 		if (fromsnap)
2484789Sahrens 			dmu_objset_close(fromsnap);
2485789Sahrens 		return (EBADF);
2486789Sahrens 	}
2487789Sahrens 
24885367Sahrens 	off = fp->f_offset;
24895367Sahrens 	error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off);
24905367Sahrens 
24915367Sahrens 	if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
24925367Sahrens 		fp->f_offset = off;
2493789Sahrens 	releasef(zc->zc_cookie);
2494789Sahrens 	if (fromsnap)
2495789Sahrens 		dmu_objset_close(fromsnap);
2496789Sahrens 	dmu_objset_close(tosnap);
2497789Sahrens 	return (error);
2498789Sahrens }
2499789Sahrens 
25001544Seschrock static int
25011544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc)
25021544Seschrock {
25031544Seschrock 	int id, error;
25041544Seschrock 
25051544Seschrock 	error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id,
25061544Seschrock 	    &zc->zc_inject_record);
25071544Seschrock 
25081544Seschrock 	if (error == 0)
25091544Seschrock 		zc->zc_guid = (uint64_t)id;
25101544Seschrock 
25111544Seschrock 	return (error);
25121544Seschrock }
25131544Seschrock 
25141544Seschrock static int
25151544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc)
25161544Seschrock {
25171544Seschrock 	return (zio_clear_fault((int)zc->zc_guid));
25181544Seschrock }
25191544Seschrock 
25201544Seschrock static int
25211544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc)
25221544Seschrock {
25231544Seschrock 	int id = (int)zc->zc_guid;
25241544Seschrock 	int error;
25251544Seschrock 
25261544Seschrock 	error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name),
25271544Seschrock 	    &zc->zc_inject_record);
25281544Seschrock 
25291544Seschrock 	zc->zc_guid = id;
25301544Seschrock 
25311544Seschrock 	return (error);
25321544Seschrock }
25331544Seschrock 
25341544Seschrock static int
25351544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc)
25361544Seschrock {
25371544Seschrock 	spa_t *spa;
25381544Seschrock 	int error;
25392676Seschrock 	size_t count = (size_t)zc->zc_nvlist_dst_size;
25401544Seschrock 
25411544Seschrock 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
25421544Seschrock 		return (error);
25431544Seschrock 
25442676Seschrock 	error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst,
25451544Seschrock 	    &count);
25461544Seschrock 	if (error == 0)
25472676Seschrock 		zc->zc_nvlist_dst_size = count;
25481544Seschrock 	else
25492676Seschrock 		zc->zc_nvlist_dst_size = spa_get_errlog_size(spa);
25501544Seschrock 
25511544Seschrock 	spa_close(spa, FTAG);
25521544Seschrock 
25531544Seschrock 	return (error);
25541544Seschrock }
25551544Seschrock 
25561544Seschrock static int
25571544Seschrock zfs_ioc_clear(zfs_cmd_t *zc)
25581544Seschrock {
25591544Seschrock 	spa_t *spa;
25601544Seschrock 	vdev_t *vd;
25614808Sek110237 	uint64_t txg;
25621544Seschrock 	int error;
25631544Seschrock 
25641544Seschrock 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
25651544Seschrock 		return (error);
25661544Seschrock 
25675329Sgw25295 	/*
25685329Sgw25295 	 * Try to resume any I/Os which may have been suspended
25695329Sgw25295 	 * as a result of a complete pool failure.
25705329Sgw25295 	 */
25715329Sgw25295 	if (!list_is_empty(&spa->spa_zio_list)) {
25725329Sgw25295 		if (zio_vdev_resume_io(spa) != 0) {
25735329Sgw25295 			spa_close(spa, FTAG);
25745329Sgw25295 			return (EIO);
25755329Sgw25295 		}
25765329Sgw25295 	}
25775329Sgw25295 
25784451Seschrock 	txg = spa_vdev_enter(spa);
25791544Seschrock 
25802676Seschrock 	if (zc->zc_guid == 0) {
25811544Seschrock 		vd = NULL;
25822676Seschrock 	} else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) {
2583*5450Sbrendan 		spa_aux_vdev_t *sav;
2584*5450Sbrendan 		int i;
2585*5450Sbrendan 
2586*5450Sbrendan 		/*
2587*5450Sbrendan 		 * Check if this is an l2cache device.
2588*5450Sbrendan 		 */
2589*5450Sbrendan 		ASSERT(spa != NULL);
2590*5450Sbrendan 		sav = &spa->spa_l2cache;
2591*5450Sbrendan 		for (i = 0; i < sav->sav_count; i++) {
2592*5450Sbrendan 			if (sav->sav_vdevs[i]->vdev_guid == zc->zc_guid) {
2593*5450Sbrendan 				vd = sav->sav_vdevs[i];
2594*5450Sbrendan 				break;
2595*5450Sbrendan 			}
2596*5450Sbrendan 		}
2597*5450Sbrendan 
2598*5450Sbrendan 		if (vd == NULL) {
2599*5450Sbrendan 			(void) spa_vdev_exit(spa, NULL, txg, ENODEV);
2600*5450Sbrendan 			spa_close(spa, FTAG);
2601*5450Sbrendan 			return (ENODEV);
2602*5450Sbrendan 		}
26031544Seschrock 	}
26041544Seschrock 
26055329Sgw25295 	vdev_clear(spa, vd, B_TRUE);
26061544Seschrock 
26074451Seschrock 	(void) spa_vdev_exit(spa, NULL, txg, 0);
26081544Seschrock 
26091544Seschrock 	spa_close(spa, FTAG);
26101544Seschrock 
26111544Seschrock 	return (0);
26121544Seschrock }
26131544Seschrock 
26145367Sahrens /*
26155367Sahrens  * inputs:
26165367Sahrens  * zc_name	name of filesystem
26175367Sahrens  * zc_value	name of origin snapshot
26185367Sahrens  *
26195367Sahrens  * outputs:	none
26205367Sahrens  */
26211544Seschrock static int
26222082Seschrock zfs_ioc_promote(zfs_cmd_t *zc)
26232082Seschrock {
26242417Sahrens 	char *cp;
26252417Sahrens 
26262417Sahrens 	/*
26272417Sahrens 	 * We don't need to unmount *all* the origin fs's snapshots, but
26282417Sahrens 	 * it's easier.
26292417Sahrens 	 */
26302676Seschrock 	cp = strchr(zc->zc_value, '@');
26312417Sahrens 	if (cp)
26322417Sahrens 		*cp = '\0';
26332676Seschrock 	(void) dmu_objset_find(zc->zc_value,
26342417Sahrens 	    zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS);
26352082Seschrock 	return (dsl_dataset_promote(zc->zc_name));
26362082Seschrock }
26372082Seschrock 
26384543Smarks /*
26394543Smarks  * We don't want to have a hard dependency
26404543Smarks  * against some special symbols in sharefs
26415331Samw  * nfs, and smbsrv.  Determine them if needed when
26424543Smarks  * the first file system is shared.
26435331Samw  * Neither sharefs, nfs or smbsrv are unloadable modules.
26444543Smarks  */
26455331Samw int (*znfsexport_fs)(void *arg);
26464543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t);
26475331Samw int (*zsmbexport_fs)(void *arg, boolean_t add_share);
26485331Samw 
26495331Samw int zfs_nfsshare_inited;
26505331Samw int zfs_smbshare_inited;
26515331Samw 
26524543Smarks ddi_modhandle_t nfs_mod;
26534543Smarks ddi_modhandle_t sharefs_mod;
26545331Samw ddi_modhandle_t smbsrv_mod;
26554543Smarks kmutex_t zfs_share_lock;
26564543Smarks 
26574543Smarks static int
26585331Samw zfs_init_sharefs()
26595331Samw {
26605331Samw 	int error;
26615331Samw 
26625331Samw 	ASSERT(MUTEX_HELD(&zfs_share_lock));
26635331Samw 	/* Both NFS and SMB shares also require sharetab support. */
26645331Samw 	if (sharefs_mod == NULL && ((sharefs_mod =
26655331Samw 	    ddi_modopen("fs/sharefs",
26665331Samw 	    KRTLD_MODE_FIRST, &error)) == NULL)) {
26675331Samw 		return (ENOSYS);
26685331Samw 	}
26695331Samw 	if (zshare_fs == NULL && ((zshare_fs =
26705331Samw 	    (int (*)(enum sharefs_sys_op, share_t *, uint32_t))
26715331Samw 	    ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) {
26725331Samw 		return (ENOSYS);
26735331Samw 	}
26745331Samw 	return (0);
26755331Samw }
26765331Samw 
26775331Samw static int
26784543Smarks zfs_ioc_share(zfs_cmd_t *zc)
26794543Smarks {
26804543Smarks 	int error;
26814543Smarks 	int opcode;
26824543Smarks 
26835331Samw 	switch (zc->zc_share.z_sharetype) {
26845331Samw 	case ZFS_SHARE_NFS:
26855331Samw 	case ZFS_UNSHARE_NFS:
26865331Samw 		if (zfs_nfsshare_inited == 0) {
26875331Samw 			mutex_enter(&zfs_share_lock);
26885331Samw 			if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs",
26895331Samw 			    KRTLD_MODE_FIRST, &error)) == NULL)) {
26905331Samw 				mutex_exit(&zfs_share_lock);
26915331Samw 				return (ENOSYS);
26925331Samw 			}
26935331Samw 			if (znfsexport_fs == NULL &&
26945331Samw 			    ((znfsexport_fs = (int (*)(void *))
26955331Samw 			    ddi_modsym(nfs_mod,
26965331Samw 			    "nfs_export", &error)) == NULL)) {
26975331Samw 				mutex_exit(&zfs_share_lock);
26985331Samw 				return (ENOSYS);
26995331Samw 			}
27005331Samw 			error = zfs_init_sharefs();
27015331Samw 			if (error) {
27025331Samw 				mutex_exit(&zfs_share_lock);
27035331Samw 				return (ENOSYS);
27045331Samw 			}
27055331Samw 			zfs_nfsshare_inited = 1;
27064543Smarks 			mutex_exit(&zfs_share_lock);
27074543Smarks 		}
27085331Samw 		break;
27095331Samw 	case ZFS_SHARE_SMB:
27105331Samw 	case ZFS_UNSHARE_SMB:
27115331Samw 		if (zfs_smbshare_inited == 0) {
27125331Samw 			mutex_enter(&zfs_share_lock);
27135331Samw 			if (smbsrv_mod == NULL && ((smbsrv_mod =
27145331Samw 			    ddi_modopen("drv/smbsrv",
27155331Samw 			    KRTLD_MODE_FIRST, &error)) == NULL)) {
27165331Samw 				mutex_exit(&zfs_share_lock);
27175331Samw 				return (ENOSYS);
27185331Samw 			}
27195331Samw 			if (zsmbexport_fs == NULL && ((zsmbexport_fs =
27205331Samw 			    (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod,
27215331Samw 			    "lmshrd_share_upcall", &error)) == NULL)) {
27225331Samw 				mutex_exit(&zfs_share_lock);
27235331Samw 				return (ENOSYS);
27245331Samw 			}
27255331Samw 			error = zfs_init_sharefs();
27265331Samw 			if (error) {
27275331Samw 				mutex_exit(&zfs_share_lock);
27285331Samw 				return (ENOSYS);
27295331Samw 			}
27305331Samw 			zfs_smbshare_inited = 1;
27314543Smarks 			mutex_exit(&zfs_share_lock);
27324543Smarks 		}
27335331Samw 		break;
27345331Samw 	default:
27355331Samw 		return (EINVAL);
27364543Smarks 	}
27374543Smarks 
27385331Samw 	switch (zc->zc_share.z_sharetype) {
27395331Samw 	case ZFS_SHARE_NFS:
27405331Samw 	case ZFS_UNSHARE_NFS:
27415331Samw 		if (error =
27425331Samw 		    znfsexport_fs((void *)
27435331Samw 		    (uintptr_t)zc->zc_share.z_exportdata))
27445331Samw 			return (error);
27455331Samw 		break;
27465331Samw 	case ZFS_SHARE_SMB:
27475331Samw 	case ZFS_UNSHARE_SMB:
27485331Samw 		if (error = zsmbexport_fs((void *)
27495331Samw 		    (uintptr_t)zc->zc_share.z_exportdata,
27505331Samw 		    zc->zc_share.z_sharetype == ZFS_SHARE_SMB ?
27515331Samw 		    B_TRUE : B_FALSE)) {
27525331Samw 			return (error);
27535331Samw 		}
27545331Samw 		break;
27555331Samw 	}
27565331Samw 
27575331Samw 	opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS ||
27585331Samw 	    zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ?
27594543Smarks 	    SHAREFS_ADD : SHAREFS_REMOVE;
27604543Smarks 
27615331Samw 	/*
27625331Samw 	 * Add or remove share from sharetab
27635331Samw 	 */
27644543Smarks 	error = zshare_fs(opcode,
27654543Smarks 	    (void *)(uintptr_t)zc->zc_share.z_sharedata,
27664543Smarks 	    zc->zc_share.z_sharemax);
27674543Smarks 
27684543Smarks 	return (error);
27694543Smarks 
27704543Smarks }
27714543Smarks 
27724543Smarks /*
27734988Sek110237  * pool create, destroy, and export don't log the history as part of
27744988Sek110237  * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export
27754988Sek110237  * do the logging of those commands.
27764543Smarks  */
2777789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = {
27784715Sek110237 	{ zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE },
27794577Sahrens 	{ zfs_ioc_pool_destroy,	zfs_secpolicy_config, POOL_NAME, B_FALSE },
27804577Sahrens 	{ zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE },
27814577Sahrens 	{ zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE },
27824577Sahrens 	{ zfs_ioc_pool_configs,	zfs_secpolicy_none, NO_NAME, B_FALSE },
27834577Sahrens 	{ zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE },
27844577Sahrens 	{ zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE },
27854577Sahrens 	{ zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE },
27864577Sahrens 	{ zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE },
27874577Sahrens 	{ zfs_ioc_pool_upgrade,	zfs_secpolicy_config, POOL_NAME, B_TRUE },
27884577Sahrens 	{ zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE },
27894577Sahrens 	{ zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE },
27904577Sahrens 	{ zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE },
27914577Sahrens 	{ zfs_ioc_vdev_set_state, zfs_secpolicy_config,	POOL_NAME, B_TRUE },
27924577Sahrens 	{ zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE },
27934577Sahrens 	{ zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE },
27944577Sahrens 	{ zfs_ioc_vdev_setpath,	zfs_secpolicy_config, POOL_NAME, B_FALSE },
27954577Sahrens 	{ zfs_ioc_objset_stats,	zfs_secpolicy_read, DATASET_NAME, B_FALSE },
27965147Srm160521 	{ zfs_ioc_objset_version, zfs_secpolicy_read, DATASET_NAME, B_FALSE },
27974543Smarks 	{ zfs_ioc_dataset_list_next, zfs_secpolicy_read,
27984577Sahrens 	    DATASET_NAME, B_FALSE },
27994543Smarks 	{ zfs_ioc_snapshot_list_next, zfs_secpolicy_read,
28004577Sahrens 	    DATASET_NAME, B_FALSE },
28014577Sahrens 	{ zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE },
28024577Sahrens 	{ zfs_ioc_create_minor,	zfs_secpolicy_minor, DATASET_NAME, B_FALSE },
28034577Sahrens 	{ zfs_ioc_remove_minor,	zfs_secpolicy_minor, DATASET_NAME, B_FALSE },
28044577Sahrens 	{ zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE },
28054577Sahrens 	{ zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE },
28064577Sahrens 	{ zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE },
28074577Sahrens 	{ zfs_ioc_rename, zfs_secpolicy_rename,	DATASET_NAME, B_TRUE },
28085367Sahrens 	{ zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE },
28095367Sahrens 	{ zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE },
28104577Sahrens 	{ zfs_ioc_inject_fault,	zfs_secpolicy_inject, NO_NAME, B_FALSE },
28114577Sahrens 	{ zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE },
28124577Sahrens 	{ zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE },
28134577Sahrens 	{ zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE },
28144577Sahrens 	{ zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE },
28154577Sahrens 	{ zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE },
28164577Sahrens 	{ zfs_ioc_destroy_snaps, zfs_secpolicy_destroy,	DATASET_NAME, B_TRUE },
28174577Sahrens 	{ zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE },
28184577Sahrens 	{ zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE },
28194577Sahrens 	{ zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE },
28204577Sahrens 	{ zfs_ioc_pool_set_props, zfs_secpolicy_config,	POOL_NAME, B_TRUE },
28214577Sahrens 	{ zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE },
28224577Sahrens 	{ zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE },
28234577Sahrens 	{ zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE },
28244543Smarks 	{ zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi,
28254577Sahrens 	    DATASET_NAME, B_FALSE },
28264849Sahrens 	{ zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE },
28274849Sahrens 	{ zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE },
2828789Sahrens };
2829789Sahrens 
2830789Sahrens static int
2831789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
2832789Sahrens {
2833789Sahrens 	zfs_cmd_t *zc;
2834789Sahrens 	uint_t vec;
28352199Sahrens 	int error, rc;
2836789Sahrens 
2837789Sahrens 	if (getminor(dev) != 0)
2838789Sahrens 		return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp));
2839789Sahrens 
2840789Sahrens 	vec = cmd - ZFS_IOC;
28414787Sahrens 	ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip));
2842789Sahrens 
2843789Sahrens 	if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
2844789Sahrens 		return (EINVAL);
2845789Sahrens 
2846789Sahrens 	zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
2847789Sahrens 
2848789Sahrens 	error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t));
2849789Sahrens 
28504787Sahrens 	if (error == 0)
28514543Smarks 		error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr);
2852789Sahrens 
2853789Sahrens 	/*
2854789Sahrens 	 * Ensure that all pool/dataset names are valid before we pass down to
2855789Sahrens 	 * the lower layers.
2856789Sahrens 	 */
2857789Sahrens 	if (error == 0) {
2858789Sahrens 		zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
2859789Sahrens 		switch (zfs_ioc_vec[vec].zvec_namecheck) {
28604577Sahrens 		case POOL_NAME:
2861789Sahrens 			if (pool_namecheck(zc->zc_name, NULL, NULL) != 0)
2862789Sahrens 				error = EINVAL;
2863789Sahrens 			break;
2864789Sahrens 
28654577Sahrens 		case DATASET_NAME:
2866789Sahrens 			if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0)
2867789Sahrens 				error = EINVAL;
2868789Sahrens 			break;
28692856Snd150628 
28704577Sahrens 		case NO_NAME:
28712856Snd150628 			break;
2872789Sahrens 		}
2873789Sahrens 	}
2874789Sahrens 
2875789Sahrens 	if (error == 0)
2876789Sahrens 		error = zfs_ioc_vec[vec].zvec_func(zc);
2877789Sahrens 
28782199Sahrens 	rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t));
28794543Smarks 	if (error == 0) {
28802199Sahrens 		error = rc;
28814543Smarks 		if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE)
28824543Smarks 			zfs_log_history(zc);
28834543Smarks 	}
2884789Sahrens 
2885789Sahrens 	kmem_free(zc, sizeof (zfs_cmd_t));
2886789Sahrens 	return (error);
2887789Sahrens }
2888789Sahrens 
2889789Sahrens static int
2890789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2891789Sahrens {
2892789Sahrens 	if (cmd != DDI_ATTACH)
2893789Sahrens 		return (DDI_FAILURE);
2894789Sahrens 
2895789Sahrens 	if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0,
2896789Sahrens 	    DDI_PSEUDO, 0) == DDI_FAILURE)
2897789Sahrens 		return (DDI_FAILURE);
2898789Sahrens 
2899789Sahrens 	zfs_dip = dip;
2900789Sahrens 
2901789Sahrens 	ddi_report_dev(dip);
2902789Sahrens 
2903789Sahrens 	return (DDI_SUCCESS);
2904789Sahrens }
2905789Sahrens 
2906789Sahrens static int
2907789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2908789Sahrens {
2909789Sahrens 	if (spa_busy() || zfs_busy() || zvol_busy())
2910789Sahrens 		return (DDI_FAILURE);
2911789Sahrens 
2912789Sahrens 	if (cmd != DDI_DETACH)
2913789Sahrens 		return (DDI_FAILURE);
2914789Sahrens 
2915789Sahrens 	zfs_dip = NULL;
2916789Sahrens 
2917789Sahrens 	ddi_prop_remove_all(dip);
2918789Sahrens 	ddi_remove_minor_node(dip, NULL);
2919789Sahrens 
2920789Sahrens 	return (DDI_SUCCESS);
2921789Sahrens }
2922789Sahrens 
2923789Sahrens /*ARGSUSED*/
2924789Sahrens static int
2925789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
2926789Sahrens {
2927789Sahrens 	switch (infocmd) {
2928789Sahrens 	case DDI_INFO_DEVT2DEVINFO:
2929789Sahrens 		*result = zfs_dip;
2930789Sahrens 		return (DDI_SUCCESS);
2931789Sahrens 
2932789Sahrens 	case DDI_INFO_DEVT2INSTANCE:
2933849Sbonwick 		*result = (void *)0;
2934789Sahrens 		return (DDI_SUCCESS);
2935789Sahrens 	}
2936789Sahrens 
2937789Sahrens 	return (DDI_FAILURE);
2938789Sahrens }
2939789Sahrens 
2940789Sahrens /*
2941789Sahrens  * OK, so this is a little weird.
2942789Sahrens  *
2943789Sahrens  * /dev/zfs is the control node, i.e. minor 0.
2944789Sahrens  * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0.
2945789Sahrens  *
2946789Sahrens  * /dev/zfs has basically nothing to do except serve up ioctls,
2947789Sahrens  * so most of the standard driver entry points are in zvol.c.
2948789Sahrens  */
2949789Sahrens static struct cb_ops zfs_cb_ops = {
2950789Sahrens 	zvol_open,	/* open */
2951789Sahrens 	zvol_close,	/* close */
2952789Sahrens 	zvol_strategy,	/* strategy */
2953789Sahrens 	nodev,		/* print */
2954789Sahrens 	nodev,		/* dump */
2955789Sahrens 	zvol_read,	/* read */
2956789Sahrens 	zvol_write,	/* write */
2957789Sahrens 	zfsdev_ioctl,	/* ioctl */
2958789Sahrens 	nodev,		/* devmap */
2959789Sahrens 	nodev,		/* mmap */
2960789Sahrens 	nodev,		/* segmap */
2961789Sahrens 	nochpoll,	/* poll */
2962789Sahrens 	ddi_prop_op,	/* prop_op */
2963789Sahrens 	NULL,		/* streamtab */
2964789Sahrens 	D_NEW | D_MP | D_64BIT,		/* Driver compatibility flag */
2965789Sahrens 	CB_REV,		/* version */
29663638Sbillm 	nodev,		/* async read */
29673638Sbillm 	nodev,		/* async write */
2968789Sahrens };
2969789Sahrens 
2970789Sahrens static struct dev_ops zfs_dev_ops = {
2971789Sahrens 	DEVO_REV,	/* version */
2972789Sahrens 	0,		/* refcnt */
2973789Sahrens 	zfs_info,	/* info */
2974789Sahrens 	nulldev,	/* identify */
2975789Sahrens 	nulldev,	/* probe */
2976789Sahrens 	zfs_attach,	/* attach */
2977789Sahrens 	zfs_detach,	/* detach */
2978789Sahrens 	nodev,		/* reset */
2979789Sahrens 	&zfs_cb_ops,	/* driver operations */
2980789Sahrens 	NULL		/* no bus operations */
2981789Sahrens };
2982789Sahrens 
2983789Sahrens static struct modldrv zfs_modldrv = {
29844577Sahrens 	&mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING,
29852676Seschrock 	    &zfs_dev_ops
2986789Sahrens };
2987789Sahrens 
2988789Sahrens static struct modlinkage modlinkage = {
2989789Sahrens 	MODREV_1,
2990789Sahrens 	(void *)&zfs_modlfs,
2991789Sahrens 	(void *)&zfs_modldrv,
2992789Sahrens 	NULL
2993789Sahrens };
2994789Sahrens 
29954720Sfr157268 
29964720Sfr157268 uint_t zfs_fsyncer_key;
29975326Sek110237 extern uint_t rrw_tsd_key;
29984720Sfr157268 
2999789Sahrens int
3000789Sahrens _init(void)
3001789Sahrens {
3002789Sahrens 	int error;
3003789Sahrens 
3004849Sbonwick 	spa_init(FREAD | FWRITE);
3005849Sbonwick 	zfs_init();
3006849Sbonwick 	zvol_init();
3007849Sbonwick 
3008849Sbonwick 	if ((error = mod_install(&modlinkage)) != 0) {
3009849Sbonwick 		zvol_fini();
3010849Sbonwick 		zfs_fini();
3011849Sbonwick 		spa_fini();
3012789Sahrens 		return (error);
3013849Sbonwick 	}
3014789Sahrens 
30154720Sfr157268 	tsd_create(&zfs_fsyncer_key, NULL);
30165326Sek110237 	tsd_create(&rrw_tsd_key, NULL);
30174720Sfr157268 
3018789Sahrens 	error = ldi_ident_from_mod(&modlinkage, &zfs_li);
3019789Sahrens 	ASSERT(error == 0);
30204543Smarks 	mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
3021789Sahrens 
3022789Sahrens 	return (0);
3023789Sahrens }
3024789Sahrens 
3025789Sahrens int
3026789Sahrens _fini(void)
3027789Sahrens {
3028789Sahrens 	int error;
3029789Sahrens 
30301544Seschrock 	if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled)
3031789Sahrens 		return (EBUSY);
3032789Sahrens 
3033789Sahrens 	if ((error = mod_remove(&modlinkage)) != 0)
3034789Sahrens 		return (error);
3035789Sahrens 
3036789Sahrens 	zvol_fini();
3037789Sahrens 	zfs_fini();
3038789Sahrens 	spa_fini();
30395331Samw 	if (zfs_nfsshare_inited)
30404543Smarks 		(void) ddi_modclose(nfs_mod);
30415331Samw 	if (zfs_smbshare_inited)
30425331Samw 		(void) ddi_modclose(smbsrv_mod);
30435331Samw 	if (zfs_nfsshare_inited || zfs_smbshare_inited)
30444543Smarks 		(void) ddi_modclose(sharefs_mod);
3045789Sahrens 
30464720Sfr157268 	tsd_destroy(&zfs_fsyncer_key);
3047789Sahrens 	ldi_ident_release(zfs_li);
3048789Sahrens 	zfs_li = NULL;
30494543Smarks 	mutex_destroy(&zfs_share_lock);
3050789Sahrens 
3051789Sahrens 	return (error);
3052789Sahrens }
3053789Sahrens 
3054789Sahrens int
3055789Sahrens _info(struct modinfo *modinfop)
3056789Sahrens {
3057789Sahrens 	return (mod_info(&modlinkage, modinfop));
3058789Sahrens }
3059