xref: /onnv-gate/usr/src/uts/common/fs/zfs/zfs_ioctl.c (revision 4670:002728040e28)
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>
41789Sahrens #include <sys/zap.h>
42789Sahrens #include <sys/spa.h>
433912Slling #include <sys/spa_impl.h>
44789Sahrens #include <sys/vdev.h>
453912Slling #include <sys/vdev_impl.h>
46789Sahrens #include <sys/dmu.h>
47789Sahrens #include <sys/dsl_dir.h>
48789Sahrens #include <sys/dsl_dataset.h>
49789Sahrens #include <sys/dsl_prop.h>
504543Smarks #include <sys/dsl_deleg.h>
514543Smarks #include <sys/dmu_objset.h>
52789Sahrens #include <sys/ddi.h>
53789Sahrens #include <sys/sunddi.h>
54789Sahrens #include <sys/sunldi.h>
55789Sahrens #include <sys/policy.h>
56789Sahrens #include <sys/zone.h>
57789Sahrens #include <sys/nvpair.h>
58789Sahrens #include <sys/pathname.h>
59789Sahrens #include <sys/mount.h>
60789Sahrens #include <sys/sdt.h>
61789Sahrens #include <sys/fs/zfs.h>
62789Sahrens #include <sys/zfs_ctldir.h>
632885Sahrens #include <sys/zvol.h>
644543Smarks #include <sharefs/share.h>
654577Sahrens #include <sys/zfs_znode.h>
66789Sahrens 
67789Sahrens #include "zfs_namecheck.h"
682676Seschrock #include "zfs_prop.h"
694543Smarks #include "zfs_deleg.h"
70789Sahrens 
71789Sahrens extern struct modlfs zfs_modlfs;
72789Sahrens 
73789Sahrens extern void zfs_init(void);
74789Sahrens extern void zfs_fini(void);
75789Sahrens 
76789Sahrens ldi_ident_t zfs_li = NULL;
77789Sahrens dev_info_t *zfs_dip;
78789Sahrens 
79789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *);
804543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *);
81789Sahrens 
82789Sahrens typedef struct zfs_ioc_vec {
83789Sahrens 	zfs_ioc_func_t		*zvec_func;
84789Sahrens 	zfs_secpolicy_func_t	*zvec_secpolicy;
85789Sahrens 	enum {
864577Sahrens 		NO_NAME,
874577Sahrens 		POOL_NAME,
884577Sahrens 		DATASET_NAME
894543Smarks 	} zvec_namecheck;
904543Smarks 	boolean_t		zvec_his_log;
91789Sahrens } zfs_ioc_vec_t;
92789Sahrens 
93789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */
94789Sahrens void
95789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
96789Sahrens {
97789Sahrens 	const char *newfile;
98789Sahrens 	char buf[256];
99789Sahrens 	va_list adx;
100789Sahrens 
101789Sahrens 	/*
102789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
103789Sahrens 	 */
104789Sahrens 	newfile = strrchr(file, '/');
105789Sahrens 	if (newfile != NULL) {
106789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
107789Sahrens 	} else {
108789Sahrens 		newfile = file;
109789Sahrens 	}
110789Sahrens 
111789Sahrens 	va_start(adx, fmt);
112789Sahrens 	(void) vsnprintf(buf, sizeof (buf), fmt, adx);
113789Sahrens 	va_end(adx);
114789Sahrens 
115789Sahrens 	/*
116789Sahrens 	 * To get this data, use the zfs-dprintf probe as so:
117789Sahrens 	 * dtrace -q -n 'zfs-dprintf \
118789Sahrens 	 *	/stringof(arg0) == "dbuf.c"/ \
119789Sahrens 	 *	{printf("%s: %s", stringof(arg1), stringof(arg3))}'
120789Sahrens 	 * arg0 = file name
121789Sahrens 	 * arg1 = function name
122789Sahrens 	 * arg2 = line number
123789Sahrens 	 * arg3 = message
124789Sahrens 	 */
125789Sahrens 	DTRACE_PROBE4(zfs__dprintf,
126789Sahrens 	    char *, newfile, char *, func, int, line, char *, buf);
127789Sahrens }
128789Sahrens 
1294543Smarks static void
1304543Smarks zfs_log_history(zfs_cmd_t *zc)
1314543Smarks {
1324543Smarks 	spa_t *spa;
1334603Sahrens 	char *buf;
1344543Smarks 
1354543Smarks 	if (zc->zc_history == NULL)
1364543Smarks 		return;
1374543Smarks 
1384577Sahrens 	if (zc->zc_history_offset != LOG_CMD_POOL_CREATE &&
1394577Sahrens 	    zc->zc_history_offset != LOG_CMD_NORMAL)
1404577Sahrens 		return;
1414577Sahrens 
1424543Smarks 	buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP);
1434543Smarks 	if (copyinstr((void *)(uintptr_t)zc->zc_history,
1444543Smarks 	    buf, HIS_MAX_RECORD_LEN, NULL) != 0) {
1454543Smarks 		kmem_free(buf, HIS_MAX_RECORD_LEN);
1464543Smarks 		return;
1474543Smarks 	}
1484543Smarks 
1494543Smarks 	buf[HIS_MAX_RECORD_LEN -1] = '\0';
1504543Smarks 
1514603Sahrens 	if (spa_open(zc->zc_name, &spa, FTAG) != 0) {
1524543Smarks 		kmem_free(buf, HIS_MAX_RECORD_LEN);
1534543Smarks 		return;
1544543Smarks 	}
1554543Smarks 
1564577Sahrens 	if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY)
1574543Smarks 		(void) spa_history_log(spa, buf, zc->zc_history_offset);
1584543Smarks 
1594543Smarks 	spa_close(spa, FTAG);
1604543Smarks 	kmem_free(buf, HIS_MAX_RECORD_LEN);
1614543Smarks }
1624543Smarks 
163789Sahrens /*
164789Sahrens  * Policy for top-level read operations (list pools).  Requires no privileges,
165789Sahrens  * and can be used in the local zone, as there is no associated dataset.
166789Sahrens  */
167789Sahrens /* ARGSUSED */
168789Sahrens static int
1694543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr)
170789Sahrens {
171789Sahrens 	return (0);
172789Sahrens }
173789Sahrens 
174789Sahrens /*
175789Sahrens  * Policy for dataset read operations (list children, get statistics).  Requires
176789Sahrens  * no privileges, but must be visible in the local zone.
177789Sahrens  */
178789Sahrens /* ARGSUSED */
179789Sahrens static int
1804543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr)
181789Sahrens {
182789Sahrens 	if (INGLOBALZONE(curproc) ||
1834543Smarks 	    zone_dataset_visible(zc->zc_name, NULL))
184789Sahrens 		return (0);
185789Sahrens 
186789Sahrens 	return (ENOENT);
187789Sahrens }
188789Sahrens 
189789Sahrens static int
190789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr)
191789Sahrens {
192789Sahrens 	uint64_t zoned;
193789Sahrens 	int writable = 1;
194789Sahrens 
195789Sahrens 	/*
196789Sahrens 	 * The dataset must be visible by this zone -- check this first
197789Sahrens 	 * so they don't see EPERM on something they shouldn't know about.
198789Sahrens 	 */
199789Sahrens 	if (!INGLOBALZONE(curproc) &&
200789Sahrens 	    !zone_dataset_visible(dataset, &writable))
201789Sahrens 		return (ENOENT);
202789Sahrens 
203789Sahrens 	if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL))
204789Sahrens 		return (ENOENT);
205789Sahrens 
206789Sahrens 	if (INGLOBALZONE(curproc)) {
207789Sahrens 		/*
208789Sahrens 		 * If the fs is zoned, only root can access it from the
209789Sahrens 		 * global zone.
210789Sahrens 		 */
211789Sahrens 		if (secpolicy_zfs(cr) && zoned)
212789Sahrens 			return (EPERM);
213789Sahrens 	} else {
214789Sahrens 		/*
215789Sahrens 		 * If we are in a local zone, the 'zoned' property must be set.
216789Sahrens 		 */
217789Sahrens 		if (!zoned)
218789Sahrens 			return (EPERM);
219789Sahrens 
220789Sahrens 		/* must be writable by this zone */
221789Sahrens 		if (!writable)
222789Sahrens 			return (EPERM);
223789Sahrens 	}
224789Sahrens 	return (0);
225789Sahrens }
226789Sahrens 
227789Sahrens int
2284543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
229789Sahrens {
230789Sahrens 	int error;
231789Sahrens 
2324543Smarks 	error = zfs_dozonecheck(name, cr);
2334543Smarks 	if (error == 0) {
2344543Smarks 		error = secpolicy_zfs(cr);
235*4670Sahrens 		if (error)
2364543Smarks 			error = dsl_deleg_access(name, perm, cr);
2374543Smarks 	}
2384543Smarks 	return (error);
2394543Smarks }
2404543Smarks 
2414543Smarks static int
2424543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr)
2434543Smarks {
2444543Smarks 	/*
2454543Smarks 	 * Check permissions for special properties.
2464543Smarks 	 */
2474543Smarks 	switch (prop) {
2484543Smarks 	case ZFS_PROP_ZONED:
2494543Smarks 		/*
2504543Smarks 		 * Disallow setting of 'zoned' from within a local zone.
2514543Smarks 		 */
2524543Smarks 		if (!INGLOBALZONE(curproc))
2534543Smarks 			return (EPERM);
2544543Smarks 		break;
255789Sahrens 
2564543Smarks 	case ZFS_PROP_QUOTA:
2574543Smarks 		if (!INGLOBALZONE(curproc)) {
2584543Smarks 			uint64_t zoned;
2594543Smarks 			char setpoint[MAXNAMELEN];
2604543Smarks 			/*
2614543Smarks 			 * Unprivileged users are allowed to modify the
2624543Smarks 			 * quota on things *under* (ie. contained by)
2634543Smarks 			 * the thing they own.
2644543Smarks 			 */
2654543Smarks 			if (dsl_prop_get_integer(name, "zoned", &zoned,
2664543Smarks 			    setpoint))
2674543Smarks 				return (EPERM);
268*4670Sahrens 			if (!zoned || strlen(name) <= strlen(setpoint))
2694543Smarks 				return (EPERM);
2704543Smarks 		}
271*4670Sahrens 		break;
2724543Smarks 	}
2734543Smarks 
274*4670Sahrens 	return (zfs_secpolicy_write_perms(name, zfs_prop_perm(prop), cr));
275789Sahrens }
276789Sahrens 
2774543Smarks int
2784543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr)
2794543Smarks {
2804543Smarks 	int error;
2814543Smarks 
2824543Smarks 	error = zfs_dozonecheck(zc->zc_name, cr);
2834543Smarks 	if (error)
2844543Smarks 		return (error);
2854543Smarks 
2864543Smarks 	/*
2874543Smarks 	 * permission to set permissions will be evaluated later in
2884543Smarks 	 * dsl_deleg_can_allow()
2894543Smarks 	 */
2904543Smarks 	return (0);
2914543Smarks }
2924543Smarks 
2934543Smarks int
2944543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr)
2954543Smarks {
2964543Smarks 	int error;
2974543Smarks 	error = zfs_secpolicy_write_perms(zc->zc_name,
2984543Smarks 	    ZFS_DELEG_PERM_ROLLBACK, cr);
2994543Smarks 	if (error == 0)
3004543Smarks 		error = zfs_secpolicy_write_perms(zc->zc_name,
3014543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr);
3024543Smarks 	return (error);
3034543Smarks }
3044543Smarks 
3054543Smarks int
3064543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr)
3074543Smarks {
3084543Smarks 	return (zfs_secpolicy_write_perms(zc->zc_name,
3094543Smarks 	    ZFS_DELEG_PERM_SEND, cr));
3104543Smarks }
3114543Smarks 
3124543Smarks int
3134543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr)
3144543Smarks {
3154543Smarks 	if (!INGLOBALZONE(curproc))
3164543Smarks 		return (EPERM);
3174543Smarks 
3184543Smarks 	if (secpolicy_nfs(CRED()) == 0) {
3194543Smarks 		return (0);
3204543Smarks 	} else {
3214543Smarks 		vnode_t *vp;
3224543Smarks 		int error;
3234543Smarks 
3244543Smarks 		if ((error = lookupname(zc->zc_value, UIO_SYSSPACE,
3254543Smarks 		    NO_FOLLOW, NULL, &vp)) != 0)
3264543Smarks 			return (error);
3274543Smarks 
3284543Smarks 		/* Now make sure mntpnt and dataset are ZFS */
3294543Smarks 
3304543Smarks 		if (vp->v_vfsp->vfs_fstype != zfsfstype ||
3314543Smarks 		    (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource),
3324543Smarks 		    zc->zc_name) != 0)) {
3334543Smarks 			VN_RELE(vp);
3344543Smarks 			return (EPERM);
3354543Smarks 		}
3364543Smarks 
3374543Smarks 		VN_RELE(vp);
3384543Smarks 		return (dsl_deleg_access(zc->zc_name,
3394543Smarks 		    ZFS_DELEG_PERM_SHARE, cr));
3404543Smarks 	}
3414543Smarks }
3424543Smarks 
343789Sahrens static int
3444543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize)
345789Sahrens {
346789Sahrens 	char *cp;
347789Sahrens 
348789Sahrens 	/*
349789Sahrens 	 * Remove the @bla or /bla from the end of the name to get the parent.
350789Sahrens 	 */
3514543Smarks 	(void) strncpy(parent, datasetname, parentsize);
3524543Smarks 	cp = strrchr(parent, '@');
353789Sahrens 	if (cp != NULL) {
354789Sahrens 		cp[0] = '\0';
355789Sahrens 	} else {
3564543Smarks 		cp = strrchr(parent, '/');
357789Sahrens 		if (cp == NULL)
358789Sahrens 			return (ENOENT);
359789Sahrens 		cp[0] = '\0';
360789Sahrens 	}
361789Sahrens 
3624543Smarks 	return (0);
3634543Smarks }
3644543Smarks 
3654543Smarks int
3664543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
3674543Smarks {
3684543Smarks 	int error;
3694543Smarks 
3704543Smarks 	if ((error = zfs_secpolicy_write_perms(name,
3714543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
3724543Smarks 		return (error);
3734543Smarks 
3744543Smarks 	return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr));
3754543Smarks }
3764543Smarks 
3774543Smarks static int
3784543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr)
3794543Smarks {
3804543Smarks 	return (zfs_secpolicy_destroy_perms(zc->zc_name, cr));
3814543Smarks }
3824543Smarks 
3834543Smarks /*
3844543Smarks  * Must have sys_config privilege to check the iscsi permission
3854543Smarks  */
3864543Smarks /* ARGSUSED */
3874543Smarks static int
3884543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr)
3894543Smarks {
3904543Smarks 	return (secpolicy_zfs(cr));
3914543Smarks }
3924543Smarks 
3934543Smarks int
3944543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
3954543Smarks {
3964543Smarks 	char 	parentname[MAXNAMELEN];
3974543Smarks 	int	error;
3984543Smarks 
3994543Smarks 	if ((error = zfs_secpolicy_write_perms(from,
4004543Smarks 	    ZFS_DELEG_PERM_RENAME, cr)) != 0)
4014543Smarks 		return (error);
4024543Smarks 
4034543Smarks 	if ((error = zfs_secpolicy_write_perms(from,
4044543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
4054543Smarks 		return (error);
4064543Smarks 
4074543Smarks 	if ((error = zfs_get_parent(to, parentname,
4084543Smarks 	    sizeof (parentname))) != 0)
4094543Smarks 		return (error);
4104543Smarks 
4114543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
4124543Smarks 	    ZFS_DELEG_PERM_CREATE, cr)) != 0)
4134543Smarks 		return (error);
4144543Smarks 
4154543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
4164543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
4174543Smarks 		return (error);
4184543Smarks 
4194543Smarks 	return (error);
4204543Smarks }
4214543Smarks 
4224543Smarks static int
4234543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr)
4244543Smarks {
4254543Smarks 	return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr));
4264543Smarks }
4274543Smarks 
4284543Smarks static int
4294543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr)
4304543Smarks {
4314543Smarks 	char 	parentname[MAXNAMELEN];
4324543Smarks 	objset_t *clone;
4334543Smarks 	int error;
4344543Smarks 
4354543Smarks 	error = zfs_secpolicy_write_perms(zc->zc_name,
4364543Smarks 	    ZFS_DELEG_PERM_PROMOTE, cr);
4374543Smarks 	if (error)
4384543Smarks 		return (error);
4394543Smarks 
4404543Smarks 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
4414543Smarks 	    DS_MODE_STANDARD | DS_MODE_READONLY, &clone);
4424543Smarks 
4434543Smarks 	if (error == 0) {
4444543Smarks 		dsl_dataset_t *pclone = NULL;
4454543Smarks 		dsl_dir_t *dd;
4464543Smarks 		dd = clone->os->os_dsl_dataset->ds_dir;
4474543Smarks 
4484543Smarks 		rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER);
4494543Smarks 		error = dsl_dataset_open_obj(dd->dd_pool,
4504543Smarks 		    dd->dd_phys->dd_clone_parent_obj, NULL,
4514543Smarks 		    DS_MODE_NONE, FTAG, &pclone);
4524543Smarks 		rw_exit(&dd->dd_pool->dp_config_rwlock);
4534543Smarks 		if (error) {
4544543Smarks 			dmu_objset_close(clone);
4554543Smarks 			return (error);
4564543Smarks 		}
4574543Smarks 
4584543Smarks 		error = zfs_secpolicy_write_perms(zc->zc_name,
4594543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr);
4604543Smarks 
4614543Smarks 		dsl_dataset_name(pclone, parentname);
4624543Smarks 		dmu_objset_close(clone);
4634543Smarks 		dsl_dataset_close(pclone, DS_MODE_NONE, FTAG);
4644543Smarks 		if (error == 0)
4654543Smarks 			error = zfs_secpolicy_write_perms(parentname,
4664543Smarks 			    ZFS_DELEG_PERM_PROMOTE, cr);
4674543Smarks 	}
4684543Smarks 	return (error);
4694543Smarks }
4704543Smarks 
4714543Smarks static int
4724543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr)
4734543Smarks {
4744543Smarks 	int error;
4754543Smarks 
4764543Smarks 	if ((error = zfs_secpolicy_write_perms(zc->zc_name,
4774543Smarks 	    ZFS_DELEG_PERM_RECEIVE, cr)) != 0)
4784543Smarks 		return (error);
4794543Smarks 
4804543Smarks 	if ((error = zfs_secpolicy_write_perms(zc->zc_name,
4814543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
4824543Smarks 		return (error);
4834543Smarks 
4844543Smarks 	return (zfs_secpolicy_write_perms(zc->zc_name,
4854543Smarks 	    ZFS_DELEG_PERM_CREATE, cr));
4864543Smarks }
4874543Smarks 
4884543Smarks int
4894543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
4904543Smarks {
4914543Smarks 	int error;
4924543Smarks 
4934543Smarks 	if ((error = zfs_secpolicy_write_perms(name,
4944543Smarks 	    ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0)
4954543Smarks 		return (error);
4964543Smarks 
4974543Smarks 	error = zfs_secpolicy_write_perms(name,
4984543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr);
4994543Smarks 
5004543Smarks 	return (error);
5014543Smarks }
5024543Smarks 
5034543Smarks static int
5044543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr)
5054543Smarks {
5064543Smarks 
5074543Smarks 	return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr));
5084543Smarks }
5094543Smarks 
5104543Smarks static int
5114543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr)
5124543Smarks {
5134543Smarks 	char 	parentname[MAXNAMELEN];
5144543Smarks 	int 	error;
5154543Smarks 
5164543Smarks 	if ((error = zfs_get_parent(zc->zc_name, parentname,
5174543Smarks 	    sizeof (parentname))) != 0)
5184543Smarks 		return (error);
5194543Smarks 
5204543Smarks 	if (zc->zc_value[0] != '\0') {
5214543Smarks 		if ((error = zfs_secpolicy_write_perms(zc->zc_value,
5224543Smarks 		    ZFS_DELEG_PERM_CLONE, cr)) != 0)
5234543Smarks 			return (error);
5244543Smarks 	}
5254543Smarks 
5264543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
5274543Smarks 	    ZFS_DELEG_PERM_CREATE, cr)) != 0)
5284543Smarks 		return (error);
5294543Smarks 
5304543Smarks 	error = zfs_secpolicy_write_perms(parentname,
5314543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr);
5324543Smarks 
5334543Smarks 	return (error);
5344543Smarks }
5354543Smarks 
5364543Smarks static int
5374543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr)
5384543Smarks {
5394543Smarks 	int error;
5404543Smarks 
5414543Smarks 	error = secpolicy_fs_unmount(cr, NULL);
5424543Smarks 	if (error) {
5434543Smarks 		error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr);
5444543Smarks 	}
5454543Smarks 	return (error);
546789Sahrens }
547789Sahrens 
548789Sahrens /*
549789Sahrens  * Policy for pool operations - create/destroy pools, add vdevs, etc.  Requires
550789Sahrens  * SYS_CONFIG privilege, which is not available in a local zone.
551789Sahrens  */
552789Sahrens /* ARGSUSED */
553789Sahrens static int
5544543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr)
555789Sahrens {
556789Sahrens 	if (secpolicy_sys_config(cr, B_FALSE) != 0)
557789Sahrens 		return (EPERM);
558789Sahrens 
559789Sahrens 	return (0);
560789Sahrens }
561789Sahrens 
562789Sahrens /*
5634543Smarks  * Just like zfs_secpolicy_config, except that we will check for
5644543Smarks  * mount permission on the dataset for permission to create/remove
5654543Smarks  * the minor nodes.
5664543Smarks  */
5674543Smarks static int
5684543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr)
5694543Smarks {
5704543Smarks 	if (secpolicy_sys_config(cr, B_FALSE) != 0) {
5714543Smarks 		return (dsl_deleg_access(zc->zc_name,
5724543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr));
5734543Smarks 	}
5744543Smarks 
5754543Smarks 	return (0);
5764543Smarks }
5774543Smarks 
5784543Smarks /*
5791544Seschrock  * Policy for fault injection.  Requires all privileges.
5801544Seschrock  */
5811544Seschrock /* ARGSUSED */
5821544Seschrock static int
5834543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr)
5841544Seschrock {
5851544Seschrock 	return (secpolicy_zinject(cr));
5861544Seschrock }
5871544Seschrock 
5881544Seschrock /*
589789Sahrens  * Returns the nvlist as specified by the user in the zfs_cmd_t.
590789Sahrens  */
591789Sahrens static int
5922676Seschrock get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp)
593789Sahrens {
594789Sahrens 	char *packed;
595789Sahrens 	size_t size;
596789Sahrens 	int error;
597789Sahrens 	nvlist_t *config = NULL;
598789Sahrens 
599789Sahrens 	/*
6002676Seschrock 	 * Read in and unpack the user-supplied nvlist.
601789Sahrens 	 */
6022676Seschrock 	if ((size = zc->zc_nvlist_src_size) == 0)
603789Sahrens 		return (EINVAL);
604789Sahrens 
605789Sahrens 	packed = kmem_alloc(size, KM_SLEEP);
606789Sahrens 
6072676Seschrock 	if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed,
608789Sahrens 	    size)) != 0) {
609789Sahrens 		kmem_free(packed, size);
610789Sahrens 		return (error);
611789Sahrens 	}
612789Sahrens 
613789Sahrens 	if ((error = nvlist_unpack(packed, size, &config, 0)) != 0) {
614789Sahrens 		kmem_free(packed, size);
615789Sahrens 		return (error);
616789Sahrens 	}
617789Sahrens 
618789Sahrens 	kmem_free(packed, size);
619789Sahrens 
620789Sahrens 	*nvp = config;
621789Sahrens 	return (0);
622789Sahrens }
623789Sahrens 
624789Sahrens static int
6252676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
6262676Seschrock {
6272676Seschrock 	char *packed = NULL;
6282676Seschrock 	size_t size;
6292676Seschrock 	int error;
6302676Seschrock 
6312676Seschrock 	VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
6322676Seschrock 
6332676Seschrock 	if (size > zc->zc_nvlist_dst_size) {
6342676Seschrock 		error = ENOMEM;
6352676Seschrock 	} else {
6364611Smarks 		packed = kmem_alloc(size, KM_SLEEP);
6372676Seschrock 		VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
6382676Seschrock 		    KM_SLEEP) == 0);
6392676Seschrock 		error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst,
6402676Seschrock 		    size);
6412676Seschrock 		kmem_free(packed, size);
6422676Seschrock 	}
6432676Seschrock 
6442676Seschrock 	zc->zc_nvlist_dst_size = size;
6452676Seschrock 	return (error);
6462676Seschrock }
6472676Seschrock 
6482676Seschrock static int
649789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc)
650789Sahrens {
651789Sahrens 	int error;
652789Sahrens 	nvlist_t *config;
653789Sahrens 
6542676Seschrock 	if ((error = get_nvlist(zc, &config)) != 0)
655789Sahrens 		return (error);
656789Sahrens 
6572676Seschrock 	error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ?
6582676Seschrock 	    NULL : zc->zc_value);
659789Sahrens 
660789Sahrens 	nvlist_free(config);
661789Sahrens 
662789Sahrens 	return (error);
663789Sahrens }
664789Sahrens 
665789Sahrens static int
666789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc)
667789Sahrens {
6684543Smarks 	int error;
6694543Smarks 	zfs_log_history(zc);
6704543Smarks 	error = spa_destroy(zc->zc_name);
6714543Smarks 	return (error);
672789Sahrens }
673789Sahrens 
674789Sahrens static int
675789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc)
676789Sahrens {
677789Sahrens 	int error;
678789Sahrens 	nvlist_t *config;
679789Sahrens 	uint64_t guid;
680789Sahrens 
6812676Seschrock 	if ((error = get_nvlist(zc, &config)) != 0)
682789Sahrens 		return (error);
683789Sahrens 
684789Sahrens 	if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 ||
6851544Seschrock 	    guid != zc->zc_guid)
686789Sahrens 		error = EINVAL;
687789Sahrens 	else
688789Sahrens 		error = spa_import(zc->zc_name, config,
6892676Seschrock 		    zc->zc_value[0] == '\0' ? NULL : zc->zc_value);
690789Sahrens 
691789Sahrens 	nvlist_free(config);
692789Sahrens 
693789Sahrens 	return (error);
694789Sahrens }
695789Sahrens 
696789Sahrens static int
697789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc)
698789Sahrens {
6994543Smarks 	int error;
7004543Smarks 	zfs_log_history(zc);
7014543Smarks 	error = spa_export(zc->zc_name, NULL);
7024543Smarks 	return (error);
703789Sahrens }
704789Sahrens 
705789Sahrens static int
706789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc)
707789Sahrens {
708789Sahrens 	nvlist_t *configs;
709789Sahrens 	int error;
710789Sahrens 
711789Sahrens 	if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL)
712789Sahrens 		return (EEXIST);
713789Sahrens 
7142676Seschrock 	error = put_nvlist(zc, configs);
715789Sahrens 
716789Sahrens 	nvlist_free(configs);
717789Sahrens 
718789Sahrens 	return (error);
719789Sahrens }
720789Sahrens 
721789Sahrens static int
722789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc)
723789Sahrens {
724789Sahrens 	nvlist_t *config;
725789Sahrens 	int error;
7261544Seschrock 	int ret = 0;
727789Sahrens 
7282676Seschrock 	error = spa_get_stats(zc->zc_name, &config, zc->zc_value,
7292676Seschrock 	    sizeof (zc->zc_value));
730789Sahrens 
731789Sahrens 	if (config != NULL) {
7322676Seschrock 		ret = put_nvlist(zc, config);
733789Sahrens 		nvlist_free(config);
7341544Seschrock 
7351544Seschrock 		/*
7361544Seschrock 		 * The config may be present even if 'error' is non-zero.
7371544Seschrock 		 * In this case we return success, and preserve the real errno
7381544Seschrock 		 * in 'zc_cookie'.
7391544Seschrock 		 */
7401544Seschrock 		zc->zc_cookie = error;
741789Sahrens 	} else {
7421544Seschrock 		ret = error;
743789Sahrens 	}
744789Sahrens 
7451544Seschrock 	return (ret);
746789Sahrens }
747789Sahrens 
748789Sahrens /*
749789Sahrens  * Try to import the given pool, returning pool stats as appropriate so that
750789Sahrens  * user land knows which devices are available and overall pool health.
751789Sahrens  */
752789Sahrens static int
753789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc)
754789Sahrens {
755789Sahrens 	nvlist_t *tryconfig, *config;
756789Sahrens 	int error;
757789Sahrens 
7582676Seschrock 	if ((error = get_nvlist(zc, &tryconfig)) != 0)
759789Sahrens 		return (error);
760789Sahrens 
761789Sahrens 	config = spa_tryimport(tryconfig);
762789Sahrens 
763789Sahrens 	nvlist_free(tryconfig);
764789Sahrens 
765789Sahrens 	if (config == NULL)
766789Sahrens 		return (EINVAL);
767789Sahrens 
7682676Seschrock 	error = put_nvlist(zc, config);
769789Sahrens 	nvlist_free(config);
770789Sahrens 
771789Sahrens 	return (error);
772789Sahrens }
773789Sahrens 
774789Sahrens static int
775789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc)
776789Sahrens {
777789Sahrens 	spa_t *spa;
778789Sahrens 	int error;
779789Sahrens 
7802926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
7812926Sek110237 		return (error);
7822926Sek110237 
7834451Seschrock 	spa_config_enter(spa, RW_READER, FTAG);
7842926Sek110237 	error = spa_scrub(spa, zc->zc_cookie, B_FALSE);
7854451Seschrock 	spa_config_exit(spa, FTAG);
7862926Sek110237 
7872926Sek110237 	spa_close(spa, FTAG);
7882926Sek110237 
789789Sahrens 	return (error);
790789Sahrens }
791789Sahrens 
792789Sahrens static int
793789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc)
794789Sahrens {
795789Sahrens 	spa_t *spa;
796789Sahrens 	int error;
797789Sahrens 
798789Sahrens 	error = spa_open(zc->zc_name, &spa, FTAG);
799789Sahrens 	if (error == 0) {
800789Sahrens 		spa_freeze(spa);
801789Sahrens 		spa_close(spa, FTAG);
802789Sahrens 	}
803789Sahrens 	return (error);
804789Sahrens }
805789Sahrens 
806789Sahrens static int
8071760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc)
8081760Seschrock {
8091760Seschrock 	spa_t *spa;
8101760Seschrock 	int error;
8111760Seschrock 
8122926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
8132926Sek110237 		return (error);
8142926Sek110237 
8152926Sek110237 	spa_upgrade(spa);
8162926Sek110237 	spa_close(spa, FTAG);
8172926Sek110237 
8182926Sek110237 	return (error);
8192926Sek110237 }
8202926Sek110237 
8212926Sek110237 static int
8222926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc)
8232926Sek110237 {
8242926Sek110237 	spa_t *spa;
8252926Sek110237 	char *hist_buf;
8262926Sek110237 	uint64_t size;
8272926Sek110237 	int error;
8282926Sek110237 
8292926Sek110237 	if ((size = zc->zc_history_len) == 0)
8302926Sek110237 		return (EINVAL);
8312926Sek110237 
8322926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
8332926Sek110237 		return (error);
8342926Sek110237 
8354577Sahrens 	if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) {
8363863Sek110237 		spa_close(spa, FTAG);
8373863Sek110237 		return (ENOTSUP);
8383863Sek110237 	}
8393863Sek110237 
8402926Sek110237 	hist_buf = kmem_alloc(size, KM_SLEEP);
8412926Sek110237 	if ((error = spa_history_get(spa, &zc->zc_history_offset,
8422926Sek110237 	    &zc->zc_history_len, hist_buf)) == 0) {
8434543Smarks 		error = xcopyout(hist_buf,
8444543Smarks 		    (char *)(uintptr_t)zc->zc_history,
8452926Sek110237 		    zc->zc_history_len);
8462926Sek110237 	}
8472926Sek110237 
8482926Sek110237 	spa_close(spa, FTAG);
8492926Sek110237 	kmem_free(hist_buf, size);
8502926Sek110237 	return (error);
8512926Sek110237 }
8522926Sek110237 
8532926Sek110237 static int
8543444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc)
8553444Sek110237 {
8563444Sek110237 	int error;
8573444Sek110237 
8583912Slling 	if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value))
8593444Sek110237 		return (error);
8603444Sek110237 
8613444Sek110237 	return (0);
8623444Sek110237 }
8633444Sek110237 
8643444Sek110237 static int
8653444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc)
8663444Sek110237 {
8673444Sek110237 	objset_t *osp;
8683444Sek110237 	int error;
8693444Sek110237 
8703444Sek110237 	if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS,
8713444Sek110237 	    DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0)
8723444Sek110237 		return (error);
8733444Sek110237 
8743444Sek110237 	error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value,
8753444Sek110237 	    sizeof (zc->zc_value));
8763444Sek110237 	dmu_objset_close(osp);
8773444Sek110237 
8783444Sek110237 	return (error);
8793444Sek110237 }
8803444Sek110237 
8813444Sek110237 static int
882789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc)
883789Sahrens {
884789Sahrens 	spa_t *spa;
885789Sahrens 	int error;
886789Sahrens 	nvlist_t *config;
887789Sahrens 
888789Sahrens 	error = spa_open(zc->zc_name, &spa, FTAG);
889789Sahrens 	if (error != 0)
890789Sahrens 		return (error);
891789Sahrens 
8923912Slling 	/*
8933912Slling 	 * A root pool with concatenated devices is not supported.
8943912Slling 	 * Thus, can not add a device to a root pool with one device.
8953912Slling 	 */
8963912Slling 	if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) {
8973912Slling 		spa_close(spa, FTAG);
8983912Slling 		return (EDOM);
8993912Slling 	}
9003912Slling 
9012676Seschrock 	if ((error = get_nvlist(zc, &config)) == 0) {
902789Sahrens 		error = spa_vdev_add(spa, config);
903789Sahrens 		nvlist_free(config);
904789Sahrens 	}
905789Sahrens 	spa_close(spa, FTAG);
906789Sahrens 	return (error);
907789Sahrens }
908789Sahrens 
909789Sahrens static int
910789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc)
911789Sahrens {
9122082Seschrock 	spa_t *spa;
9132082Seschrock 	int error;
9142082Seschrock 
9152082Seschrock 	error = spa_open(zc->zc_name, &spa, FTAG);
9162082Seschrock 	if (error != 0)
9172082Seschrock 		return (error);
9182082Seschrock 	error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE);
9192082Seschrock 	spa_close(spa, FTAG);
9202082Seschrock 	return (error);
921789Sahrens }
922789Sahrens 
923789Sahrens static int
9244451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc)
925789Sahrens {
926789Sahrens 	spa_t *spa;
927789Sahrens 	int error;
9284451Seschrock 	vdev_state_t newstate = VDEV_STATE_UNKNOWN;
929789Sahrens 
9302926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
931789Sahrens 		return (error);
9324451Seschrock 	switch (zc->zc_cookie) {
9334451Seschrock 	case VDEV_STATE_ONLINE:
9344451Seschrock 		error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate);
9354451Seschrock 		break;
9364451Seschrock 
9374451Seschrock 	case VDEV_STATE_OFFLINE:
9384451Seschrock 		error = vdev_offline(spa, zc->zc_guid, zc->zc_obj);
9394451Seschrock 		break;
940789Sahrens 
9414451Seschrock 	case VDEV_STATE_FAULTED:
9424451Seschrock 		error = vdev_fault(spa, zc->zc_guid);
9434451Seschrock 		break;
944789Sahrens 
9454451Seschrock 	case VDEV_STATE_DEGRADED:
9464451Seschrock 		error = vdev_degrade(spa, zc->zc_guid);
9474451Seschrock 		break;
9484451Seschrock 
9494451Seschrock 	default:
9504451Seschrock 		error = EINVAL;
9514451Seschrock 	}
9524451Seschrock 	zc->zc_cookie = newstate;
953789Sahrens 	spa_close(spa, FTAG);
954789Sahrens 	return (error);
955789Sahrens }
956789Sahrens 
957789Sahrens static int
958789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc)
959789Sahrens {
960789Sahrens 	spa_t *spa;
961789Sahrens 	int replacing = zc->zc_cookie;
962789Sahrens 	nvlist_t *config;
963789Sahrens 	int error;
964789Sahrens 
9652926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
966789Sahrens 		return (error);
967789Sahrens 
9682676Seschrock 	if ((error = get_nvlist(zc, &config)) == 0) {
9691544Seschrock 		error = spa_vdev_attach(spa, zc->zc_guid, config, replacing);
970789Sahrens 		nvlist_free(config);
971789Sahrens 	}
972789Sahrens 
973789Sahrens 	spa_close(spa, FTAG);
974789Sahrens 	return (error);
975789Sahrens }
976789Sahrens 
977789Sahrens static int
978789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc)
979789Sahrens {
980789Sahrens 	spa_t *spa;
981789Sahrens 	int error;
982789Sahrens 
9832926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
984789Sahrens 		return (error);
985789Sahrens 
9861544Seschrock 	error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE);
987789Sahrens 
988789Sahrens 	spa_close(spa, FTAG);
989789Sahrens 	return (error);
990789Sahrens }
991789Sahrens 
992789Sahrens static int
9931354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc)
9941354Seschrock {
9951354Seschrock 	spa_t *spa;
9962676Seschrock 	char *path = zc->zc_value;
9971544Seschrock 	uint64_t guid = zc->zc_guid;
9981354Seschrock 	int error;
9991354Seschrock 
10001354Seschrock 	error = spa_open(zc->zc_name, &spa, FTAG);
10011354Seschrock 	if (error != 0)
10021354Seschrock 		return (error);
10031354Seschrock 
10041354Seschrock 	error = spa_vdev_setpath(spa, guid, path);
10051354Seschrock 	spa_close(spa, FTAG);
10061354Seschrock 	return (error);
10071354Seschrock }
10081354Seschrock 
10091354Seschrock static int
1010789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc)
1011789Sahrens {
1012789Sahrens 	objset_t *os = NULL;
1013789Sahrens 	int error;
10141356Seschrock 	nvlist_t *nv;
1015789Sahrens 
1016789Sahrens retry:
1017789Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1018789Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1019789Sahrens 	if (error != 0) {
1020789Sahrens 		/*
1021789Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1022789Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1023789Sahrens 		 * only for a short while, so we retry here.
1024789Sahrens 		 * This avoids user code having to handle EBUSY,
1025789Sahrens 		 * for example for a "zfs list".
1026789Sahrens 		 */
1027789Sahrens 		if (error == EBUSY) {
1028789Sahrens 			delay(1);
1029789Sahrens 			goto retry;
1030789Sahrens 		}
1031789Sahrens 		return (error);
1032789Sahrens 	}
1033789Sahrens 
10342885Sahrens 	dmu_objset_fast_stat(os, &zc->zc_objset_stats);
1035789Sahrens 
10362856Snd150628 	if (zc->zc_nvlist_dst != 0 &&
10371356Seschrock 	    (error = dsl_prop_get_all(os, &nv)) == 0) {
10382885Sahrens 		dmu_objset_stats(os, nv);
10393087Sahrens 		/*
10404577Sahrens 		 * NB: {zpl,zvol}_get_stats() will read the objset contents,
10413087Sahrens 		 * which we aren't supposed to do with a
10423087Sahrens 		 * DS_MODE_STANDARD open, because it could be
10433087Sahrens 		 * inconsistent.  So this is a bit of a workaround...
10443087Sahrens 		 */
10454577Sahrens 		if (!zc->zc_objset_stats.dds_inconsistent) {
10464577Sahrens 			if (dmu_objset_type(os) == DMU_OST_ZVOL)
10474577Sahrens 				VERIFY(zvol_get_stats(os, nv) == 0);
10484577Sahrens 			else if (dmu_objset_type(os) == DMU_OST_ZFS)
10494577Sahrens 				(void) zfs_get_stats(os, nv);
10504577Sahrens 		}
10512676Seschrock 		error = put_nvlist(zc, nv);
10521356Seschrock 		nvlist_free(nv);
10531356Seschrock 	}
1054789Sahrens 
10552676Seschrock 	spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value));
10561544Seschrock 
1057789Sahrens 	dmu_objset_close(os);
1058789Sahrens 	return (error);
1059789Sahrens }
1060789Sahrens 
1061789Sahrens static int
1062789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc)
1063789Sahrens {
1064885Sahrens 	objset_t *os;
1065789Sahrens 	int error;
1066789Sahrens 	char *p;
1067789Sahrens 
1068885Sahrens retry:
1069885Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1070885Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1071885Sahrens 	if (error != 0) {
1072885Sahrens 		/*
1073885Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1074885Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1075885Sahrens 		 * only for a short while, so we retry here.
1076885Sahrens 		 * This avoids user code having to handle EBUSY,
1077885Sahrens 		 * for example for a "zfs list".
1078885Sahrens 		 */
1079885Sahrens 		if (error == EBUSY) {
1080885Sahrens 			delay(1);
1081885Sahrens 			goto retry;
1082885Sahrens 		}
1083885Sahrens 		if (error == ENOENT)
1084885Sahrens 			error = ESRCH;
1085885Sahrens 		return (error);
1086789Sahrens 	}
1087789Sahrens 
1088789Sahrens 	p = strrchr(zc->zc_name, '/');
1089789Sahrens 	if (p == NULL || p[1] != '\0')
1090789Sahrens 		(void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name));
1091789Sahrens 	p = zc->zc_name + strlen(zc->zc_name);
1092789Sahrens 
1093789Sahrens 	do {
1094885Sahrens 		error = dmu_dir_list_next(os,
1095885Sahrens 		    sizeof (zc->zc_name) - (p - zc->zc_name), p,
1096885Sahrens 		    NULL, &zc->zc_cookie);
1097789Sahrens 		if (error == ENOENT)
1098789Sahrens 			error = ESRCH;
1099885Sahrens 	} while (error == 0 && !INGLOBALZONE(curproc) &&
1100789Sahrens 	    !zone_dataset_visible(zc->zc_name, NULL));
1101789Sahrens 
1102885Sahrens 	/*
1103885Sahrens 	 * If it's a hidden dataset (ie. with a '$' in its name), don't
1104885Sahrens 	 * try to get stats for it.  Userland will skip over it.
1105885Sahrens 	 */
1106885Sahrens 	if (error == 0 && strchr(zc->zc_name, '$') == NULL)
1107885Sahrens 		error = zfs_ioc_objset_stats(zc); /* fill in the stats */
1108789Sahrens 
1109885Sahrens 	dmu_objset_close(os);
1110789Sahrens 	return (error);
1111789Sahrens }
1112789Sahrens 
1113789Sahrens static int
1114789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
1115789Sahrens {
1116885Sahrens 	objset_t *os;
1117789Sahrens 	int error;
1118789Sahrens 
1119789Sahrens retry:
1120885Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1121885Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1122885Sahrens 	if (error != 0) {
1123789Sahrens 		/*
1124885Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1125789Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1126789Sahrens 		 * only for a short while, so we retry here.
1127789Sahrens 		 * This avoids user code having to handle EBUSY,
1128885Sahrens 		 * for example for a "zfs list".
1129789Sahrens 		 */
1130789Sahrens 		if (error == EBUSY) {
1131789Sahrens 			delay(1);
1132789Sahrens 			goto retry;
1133789Sahrens 		}
1134789Sahrens 		if (error == ENOENT)
1135885Sahrens 			error = ESRCH;
1136789Sahrens 		return (error);
1137789Sahrens 	}
1138789Sahrens 
11391003Slling 	/*
11401003Slling 	 * A dataset name of maximum length cannot have any snapshots,
11411003Slling 	 * so exit immediately.
11421003Slling 	 */
11431003Slling 	if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) {
1144885Sahrens 		dmu_objset_close(os);
11451003Slling 		return (ESRCH);
1146789Sahrens 	}
1147789Sahrens 
1148885Sahrens 	error = dmu_snapshot_list_next(os,
1149885Sahrens 	    sizeof (zc->zc_name) - strlen(zc->zc_name),
1150885Sahrens 	    zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie);
1151789Sahrens 	if (error == ENOENT)
1152789Sahrens 		error = ESRCH;
1153789Sahrens 
1154885Sahrens 	if (error == 0)
1155885Sahrens 		error = zfs_ioc_objset_stats(zc); /* fill in the stats */
1156789Sahrens 
1157885Sahrens 	dmu_objset_close(os);
1158789Sahrens 	return (error);
1159789Sahrens }
1160789Sahrens 
1161789Sahrens static int
11622676Seschrock zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl)
1163789Sahrens {
11642676Seschrock 	nvpair_t *elem;
11652676Seschrock 	int error;
11662676Seschrock 	uint64_t intval;
11672676Seschrock 	char *strval;
11682676Seschrock 
11694543Smarks 	/*
11704543Smarks 	 * First validate permission to set all of the properties
11714543Smarks 	 */
11722676Seschrock 	elem = NULL;
11732676Seschrock 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
1174*4670Sahrens 		const char *propname = nvpair_name(elem);
1175*4670Sahrens 		zfs_prop_t prop = zfs_name_to_prop(propname);
11762676Seschrock 
1177*4670Sahrens 		if (prop == ZFS_PROP_INVAL) {
11782676Seschrock 			/*
11792676Seschrock 			 * If this is a user-defined property, it must be a
11802676Seschrock 			 * string, and there is no further validation to do.
11812676Seschrock 			 */
11822676Seschrock 			if (!zfs_prop_user(propname) ||
11832676Seschrock 			    nvpair_type(elem) != DATA_TYPE_STRING)
11842676Seschrock 				return (EINVAL);
11852676Seschrock 
11864543Smarks 			error = zfs_secpolicy_write_perms(name,
11874543Smarks 			    ZFS_DELEG_PERM_USERPROP, cr);
1188*4670Sahrens 			if (error)
1189*4670Sahrens 				return (error);
11904543Smarks 			continue;
11912676Seschrock 		}
11922676Seschrock 
1193*4670Sahrens 		if ((error = zfs_secpolicy_setprop(name, prop, cr)) != 0)
1194*4670Sahrens 			return (error);
11952676Seschrock 
1196*4670Sahrens 		/*
1197*4670Sahrens 		 * Check that this value is valid for this pool version
1198*4670Sahrens 		 */
1199*4670Sahrens 		switch (prop) {
12003886Sahl 		case ZFS_PROP_COMPRESSION:
12013886Sahl 			/*
12023886Sahl 			 * If the user specified gzip compression, make sure
12033886Sahl 			 * the SPA supports it. We ignore any errors here since
12043886Sahl 			 * we'll catch them later.
12053886Sahl 			 */
12063886Sahl 			if (nvpair_type(elem) == DATA_TYPE_UINT64 &&
12073886Sahl 			    nvpair_value_uint64(elem, &intval) == 0 &&
12083886Sahl 			    intval >= ZIO_COMPRESS_GZIP_1 &&
12093886Sahl 			    intval <= ZIO_COMPRESS_GZIP_9) {
12104543Smarks 				spa_t *spa;
12114543Smarks 
12124603Sahrens 				if (spa_open(name, &spa, FTAG) == 0) {
12133886Sahl 					if (spa_version(spa) <
12144577Sahrens 					    SPA_VERSION_GZIP_COMPRESSION) {
12153886Sahl 						spa_close(spa, FTAG);
12163886Sahl 						return (ENOTSUP);
12173886Sahl 					}
12183886Sahl 
12193886Sahl 					spa_close(spa, FTAG);
12203886Sahl 				}
12213886Sahl 			}
12223886Sahl 			break;
12234603Sahrens 
12244603Sahrens 		case ZFS_PROP_COPIES:
12254603Sahrens 		{
12264603Sahrens 			spa_t *spa;
12274603Sahrens 
12284603Sahrens 			if (spa_open(name, &spa, FTAG) == 0) {
12294603Sahrens 				if (spa_version(spa) <
12304603Sahrens 				    SPA_VERSION_DITTO_BLOCKS) {
12314603Sahrens 					spa_close(spa, FTAG);
12324603Sahrens 					return (ENOTSUP);
12334603Sahrens 				}
12344603Sahrens 				spa_close(spa, FTAG);
12354603Sahrens 			}
12364603Sahrens 			break;
12374603Sahrens 		}
12382676Seschrock 		}
12394543Smarks 	}
12404543Smarks 
12414543Smarks 	elem = NULL;
12424543Smarks 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
1243*4670Sahrens 		const char *propname = nvpair_name(elem);
1244*4670Sahrens 		zfs_prop_t prop = zfs_name_to_prop(propname);
12454543Smarks 
1246*4670Sahrens 		if (prop == ZFS_PROP_INVAL) {
12474543Smarks 			VERIFY(nvpair_value_string(elem, &strval) == 0);
12484543Smarks 			error = dsl_prop_set(name, propname, 1,
12494543Smarks 			    strlen(strval) + 1, strval);
12504543Smarks 			if (error == 0)
12514543Smarks 				continue;
12524543Smarks 			else
12534543Smarks 				return (error);
12544543Smarks 		}
12552676Seschrock 
12562676Seschrock 		switch (prop) {
12572676Seschrock 		case ZFS_PROP_QUOTA:
12582676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
12594577Sahrens 			    (error = dsl_dir_set_quota(name, intval)) != 0)
12602676Seschrock 				return (error);
12612676Seschrock 			break;
12622676Seschrock 
12632676Seschrock 		case ZFS_PROP_RESERVATION:
12642676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
12652676Seschrock 			    (error = dsl_dir_set_reservation(name,
12662676Seschrock 			    intval)) != 0)
12672676Seschrock 				return (error);
12682676Seschrock 			break;
1269789Sahrens 
12702676Seschrock 		case ZFS_PROP_VOLSIZE:
12712676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
12724577Sahrens 			    (error = zvol_set_volsize(name, dev, intval)) != 0)
12732676Seschrock 				return (error);
12742676Seschrock 			break;
12752676Seschrock 
12762676Seschrock 		case ZFS_PROP_VOLBLOCKSIZE:
12772676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
12784577Sahrens 			    (error = zvol_set_volblocksize(name, intval)) != 0)
12794577Sahrens 				return (error);
12804577Sahrens 			break;
12814577Sahrens 
12824577Sahrens 		case ZFS_PROP_VERSION:
12834577Sahrens 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
12844577Sahrens 			    (error = zfs_set_version(name, intval)) != 0)
12852676Seschrock 				return (error);
12862676Seschrock 			break;
12872676Seschrock 
12882676Seschrock 		default:
12892676Seschrock 			if (nvpair_type(elem) == DATA_TYPE_STRING) {
12902676Seschrock 				if (zfs_prop_get_type(prop) !=
12912676Seschrock 				    prop_type_string)
12922676Seschrock 					return (EINVAL);
12932717Seschrock 				VERIFY(nvpair_value_string(elem, &strval) == 0);
12942717Seschrock 				if ((error = dsl_prop_set(name,
12952676Seschrock 				    nvpair_name(elem), 1, strlen(strval) + 1,
12962717Seschrock 				    strval)) != 0)
12972717Seschrock 					return (error);
12982676Seschrock 			} else if (nvpair_type(elem) == DATA_TYPE_UINT64) {
12992885Sahrens 				const char *unused;
13002885Sahrens 
13012717Seschrock 				VERIFY(nvpair_value_uint64(elem, &intval) == 0);
13022676Seschrock 
13032676Seschrock 				switch (zfs_prop_get_type(prop)) {
13042676Seschrock 				case prop_type_number:
13052676Seschrock 					break;
13062676Seschrock 				case prop_type_boolean:
13072676Seschrock 					if (intval > 1)
13082717Seschrock 						return (EINVAL);
13092676Seschrock 					break;
13102676Seschrock 				case prop_type_string:
13112717Seschrock 					return (EINVAL);
13122676Seschrock 				case prop_type_index:
13132717Seschrock 					if (zfs_prop_index_to_string(prop,
13142717Seschrock 					    intval, &unused) != 0)
13152717Seschrock 						return (EINVAL);
13162676Seschrock 					break;
13172676Seschrock 				default:
13184577Sahrens 					cmn_err(CE_PANIC,
13194577Sahrens 					    "unknown property type");
13202676Seschrock 					break;
13212676Seschrock 				}
13222676Seschrock 
13232717Seschrock 				if ((error = dsl_prop_set(name, propname,
13242717Seschrock 				    8, 1, &intval)) != 0)
13252717Seschrock 					return (error);
13262676Seschrock 			} else {
13272676Seschrock 				return (EINVAL);
13282676Seschrock 			}
13292676Seschrock 			break;
13302676Seschrock 		}
13312676Seschrock 	}
13322676Seschrock 
13332676Seschrock 	return (0);
1334789Sahrens }
1335789Sahrens 
1336789Sahrens static int
13372676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc)
1338789Sahrens {
13392676Seschrock 	nvlist_t *nvl;
13402676Seschrock 	int error;
1341789Sahrens 
13422676Seschrock 	/*
13432676Seschrock 	 * If zc_value is set, then this is an attempt to inherit a value.
13442676Seschrock 	 * Otherwise, zc_nvlist refers to a list of properties to set.
13452676Seschrock 	 */
13462676Seschrock 	if (zc->zc_value[0] != '\0') {
1347*4670Sahrens 		zfs_prop_t prop = zfs_name_to_prop(zc->zc_value);
1348*4670Sahrens 
1349*4670Sahrens 		if (prop == ZFS_PROP_INVAL) {
1350*4670Sahrens 			if (!zfs_prop_user(zc->zc_value))
1351*4670Sahrens 				return (EINVAL);
1352*4670Sahrens 			error = zfs_secpolicy_write_perms(zc->zc_name,
1353*4670Sahrens 			    ZFS_DELEG_PERM_USERPROP,
1354*4670Sahrens 			    (cred_t *)(uintptr_t)zc->zc_cred);
1355*4670Sahrens 		} else {
1356*4670Sahrens 			if (!zfs_prop_inheritable(prop))
1357*4670Sahrens 				return (EINVAL);
1358*4670Sahrens 			error = zfs_secpolicy_setprop(zc->zc_name,
1359*4670Sahrens 			    prop, (cred_t *)(uintptr_t)zc->zc_cred);
1360*4670Sahrens 		}
1361*4670Sahrens 		if (error)
1362*4670Sahrens 			return (error);
13632676Seschrock 
13642676Seschrock 		return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL));
13652676Seschrock 	}
13662676Seschrock 
13672676Seschrock 	if ((error = get_nvlist(zc, &nvl)) != 0)
13682676Seschrock 		return (error);
13692676Seschrock 
13702676Seschrock 	error = zfs_set_prop_nvlist(zc->zc_name, zc->zc_dev,
13712676Seschrock 	    (cred_t *)(uintptr_t)zc->zc_cred, nvl);
13724543Smarks 
13732676Seschrock 	nvlist_free(nvl);
13742676Seschrock 	return (error);
1375789Sahrens }
1376789Sahrens 
1377789Sahrens static int
13784098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc)
13793912Slling {
13803912Slling 	nvlist_t *nvl;
13813912Slling 	int error, reset_bootfs = 0;
13823912Slling 	uint64_t objnum;
13834543Smarks 	uint64_t intval;
13843912Slling 	zpool_prop_t prop;
13853912Slling 	nvpair_t *elem;
13863912Slling 	char *propname, *strval;
13873912Slling 	spa_t *spa;
13883912Slling 	vdev_t *rvdev;
13893912Slling 	char *vdev_type;
13903912Slling 	objset_t *os;
13913912Slling 
13923912Slling 	if ((error = get_nvlist(zc, &nvl)) != 0)
13933912Slling 		return (error);
13943912Slling 
13953912Slling 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
13963912Slling 		nvlist_free(nvl);
13973912Slling 		return (error);
13983912Slling 	}
13993912Slling 
14004577Sahrens 	if (spa_version(spa) < SPA_VERSION_BOOTFS) {
14013912Slling 		nvlist_free(nvl);
14023912Slling 		spa_close(spa, FTAG);
14033912Slling 		return (ENOTSUP);
14043912Slling 	}
14053912Slling 
14063912Slling 	elem = NULL;
14073912Slling 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
14083912Slling 
14093912Slling 		propname = nvpair_name(elem);
14103912Slling 
14113912Slling 		if ((prop = zpool_name_to_prop(propname)) ==
14123912Slling 		    ZFS_PROP_INVAL) {
14133912Slling 			nvlist_free(nvl);
14143912Slling 			spa_close(spa, FTAG);
14153912Slling 			return (EINVAL);
14163912Slling 		}
14173912Slling 
14183912Slling 		switch (prop) {
14194543Smarks 		case ZPOOL_PROP_DELEGATION:
14204543Smarks 			VERIFY(nvpair_value_uint64(elem, &intval) == 0);
14214543Smarks 			if (intval > 1)
14224543Smarks 				error = EINVAL;
14234543Smarks 			break;
14244451Seschrock 		case ZPOOL_PROP_BOOTFS:
14253912Slling 			/*
14263912Slling 			 * A bootable filesystem can not be on a RAIDZ pool
14273912Slling 			 * nor a striped pool with more than 1 device.
14283912Slling 			 */
14293912Slling 			rvdev = spa->spa_root_vdev;
14303912Slling 			vdev_type =
14313912Slling 			    rvdev->vdev_child[0]->vdev_ops->vdev_op_type;
14323912Slling 			if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 ||
14333912Slling 			    (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 &&
14343912Slling 			    rvdev->vdev_children > 1)) {
14353912Slling 				error = ENOTSUP;
14363912Slling 				break;
14373912Slling 			}
14383912Slling 
14393912Slling 			reset_bootfs = 1;
14403912Slling 
14413912Slling 			VERIFY(nvpair_value_string(elem, &strval) == 0);
14423912Slling 			if (strval == NULL || strval[0] == '\0') {
14434451Seschrock 				objnum = zpool_prop_default_numeric(
14444451Seschrock 				    ZPOOL_PROP_BOOTFS);
14453912Slling 				break;
14463912Slling 			}
14473912Slling 
14483912Slling 			if (error = dmu_objset_open(strval, DMU_OST_ZFS,
14493912Slling 			    DS_MODE_STANDARD | DS_MODE_READONLY, &os))
14503912Slling 				break;
14513912Slling 			objnum = dmu_objset_id(os);
14523912Slling 			dmu_objset_close(os);
14533912Slling 			break;
14543912Slling 		}
14553912Slling 
14563912Slling 		if (error)
14573912Slling 			break;
14583912Slling 	}
14593912Slling 	if (error == 0) {
14603912Slling 		if (reset_bootfs) {
14613912Slling 			VERIFY(nvlist_remove(nvl,
14624451Seschrock 			    zpool_prop_to_name(ZPOOL_PROP_BOOTFS),
14633912Slling 			    DATA_TYPE_STRING) == 0);
14643912Slling 			VERIFY(nvlist_add_uint64(nvl,
14654451Seschrock 			    zpool_prop_to_name(ZPOOL_PROP_BOOTFS),
14664451Seschrock 			    objnum) == 0);
14673912Slling 		}
14683912Slling 		error = spa_set_props(spa, nvl);
14693912Slling 	}
14703912Slling 
14713912Slling 	nvlist_free(nvl);
14723912Slling 	spa_close(spa, FTAG);
14733912Slling 
14743912Slling 	return (error);
14753912Slling }
14763912Slling 
14773912Slling static int
14784098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc)
14793912Slling {
14803912Slling 	spa_t *spa;
14813912Slling 	int error;
14823912Slling 	nvlist_t *nvp = NULL;
14833912Slling 
14843912Slling 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
14853912Slling 		return (error);
14863912Slling 
14873912Slling 	error = spa_get_props(spa, &nvp);
14883912Slling 
14893912Slling 	if (error == 0 && zc->zc_nvlist_dst != NULL)
14903912Slling 		error = put_nvlist(zc, nvp);
14913912Slling 	else
14923912Slling 		error = EFAULT;
14933912Slling 
14943912Slling 	spa_close(spa, FTAG);
14953912Slling 
14963912Slling 	if (nvp)
14973912Slling 		nvlist_free(nvp);
14983912Slling 	return (error);
14993912Slling }
15003912Slling 
15013912Slling static int
15024543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc)
15034543Smarks {
15044543Smarks 	nvlist_t *nvp;
15054543Smarks 	int error;
15064543Smarks 	uint32_t uid;
15074543Smarks 	uint32_t gid;
15084543Smarks 	uint32_t *groups;
15094543Smarks 	uint_t group_cnt;
15104543Smarks 	cred_t	*usercred;
15114543Smarks 
15124543Smarks 	if ((error = get_nvlist(zc, &nvp)) != 0) {
15134543Smarks 		return (error);
15144543Smarks 	}
15154543Smarks 
15164543Smarks 	if ((error = nvlist_lookup_uint32(nvp,
15174543Smarks 	    ZFS_DELEG_PERM_UID, &uid)) != 0) {
15184543Smarks 		nvlist_free(nvp);
15194543Smarks 		return (EPERM);
15204543Smarks 	}
15214543Smarks 
15224543Smarks 	if ((error = nvlist_lookup_uint32(nvp,
15234543Smarks 	    ZFS_DELEG_PERM_GID, &gid)) != 0) {
15244543Smarks 		nvlist_free(nvp);
15254543Smarks 		return (EPERM);
15264543Smarks 	}
15274543Smarks 
15284543Smarks 	if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS,
15294543Smarks 	    &groups, &group_cnt)) != 0) {
15304543Smarks 		nvlist_free(nvp);
15314543Smarks 		return (EPERM);
15324543Smarks 	}
15334543Smarks 	usercred = cralloc();
15344543Smarks 	if ((crsetugid(usercred, uid, gid) != 0) ||
15354543Smarks 	    (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) {
15364543Smarks 		nvlist_free(nvp);
15374543Smarks 		crfree(usercred);
15384543Smarks 		return (EPERM);
15394543Smarks 	}
15404543Smarks 	nvlist_free(nvp);
15414543Smarks 	error = dsl_deleg_access(zc->zc_name,
15424543Smarks 	    ZFS_DELEG_PERM_SHAREISCSI, usercred);
15434543Smarks 	crfree(usercred);
15444543Smarks 	return (error);
15454543Smarks }
15464543Smarks 
15474543Smarks static int
15484543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc)
15494543Smarks {
15504543Smarks 	int error;
15514543Smarks 	nvlist_t *fsaclnv = NULL;
15524543Smarks 	cred_t *cr;
15534543Smarks 
15544543Smarks 	if ((error = get_nvlist(zc, &fsaclnv)) != 0)
15554543Smarks 		return (error);
15564543Smarks 
15574543Smarks 	/*
15584543Smarks 	 * Verify nvlist is constructed correctly
15594543Smarks 	 */
15604543Smarks 	if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) {
15614543Smarks 		nvlist_free(fsaclnv);
15624543Smarks 		return (EINVAL);
15634543Smarks 	}
15644543Smarks 
15654543Smarks 	/*
15664543Smarks 	 * If we don't have PRIV_SYS_MOUNT, then validate
15674543Smarks 	 * that user is allowed to hand out each permission in
15684543Smarks 	 * the nvlist(s)
15694543Smarks 	 */
15704543Smarks 
15714543Smarks 	cr = (cred_t *)(uintptr_t)zc->zc_cred;
15724543Smarks 	error = secpolicy_zfs(cr);
15734543Smarks 	if (error) {
15744543Smarks 		if (zc->zc_perm_action == B_FALSE)
15754543Smarks 			error = dsl_deleg_can_allow(zc->zc_name, fsaclnv, cr);
15764543Smarks 		else
15774543Smarks 			error = dsl_deleg_can_unallow(zc->zc_name, fsaclnv, cr);
15784543Smarks 	}
15794543Smarks 
15804543Smarks 	if (error == 0)
15814543Smarks 		error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action);
15824543Smarks 
15834543Smarks 	nvlist_free(fsaclnv);
15844543Smarks 	return (error);
15854543Smarks }
15864543Smarks 
15874543Smarks static int
15884543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc)
15894543Smarks {
15904543Smarks 	nvlist_t *nvp;
15914543Smarks 	int error;
15924543Smarks 
15934543Smarks 	if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) {
15944543Smarks 		error = put_nvlist(zc, nvp);
15954543Smarks 		nvlist_free(nvp);
15964543Smarks 	}
15974543Smarks 
15984543Smarks 	return (error);
15994543Smarks }
16004543Smarks 
16014543Smarks static int
1602789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc)
1603789Sahrens {
16042676Seschrock 	return (zvol_create_minor(zc->zc_name, zc->zc_dev));
1605789Sahrens }
1606789Sahrens 
1607789Sahrens static int
1608789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc)
1609789Sahrens {
16102676Seschrock 	return (zvol_remove_minor(zc->zc_name));
1611789Sahrens }
1612789Sahrens 
1613789Sahrens /*
1614789Sahrens  * Search the vfs list for a specified resource.  Returns a pointer to it
1615789Sahrens  * or NULL if no suitable entry is found. The caller of this routine
1616789Sahrens  * is responsible for releasing the returned vfs pointer.
1617789Sahrens  */
1618789Sahrens static vfs_t *
1619789Sahrens zfs_get_vfs(const char *resource)
1620789Sahrens {
1621789Sahrens 	struct vfs *vfsp;
1622789Sahrens 	struct vfs *vfs_found = NULL;
1623789Sahrens 
1624789Sahrens 	vfs_list_read_lock();
1625789Sahrens 	vfsp = rootvfs;
1626789Sahrens 	do {
1627789Sahrens 		if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) {
1628789Sahrens 			VFS_HOLD(vfsp);
1629789Sahrens 			vfs_found = vfsp;
1630789Sahrens 			break;
1631789Sahrens 		}
1632789Sahrens 		vfsp = vfsp->vfs_next;
1633789Sahrens 	} while (vfsp != rootvfs);
1634789Sahrens 	vfs_list_unlock();
1635789Sahrens 	return (vfs_found);
1636789Sahrens }
1637789Sahrens 
16384543Smarks /* ARGSUSED */
1639789Sahrens static void
16404543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
1641789Sahrens {
16424577Sahrens 	nvlist_t *nvprops = arg;
16434577Sahrens 	uint64_t version = ZPL_VERSION;
16444577Sahrens 
16454577Sahrens 	(void) nvlist_lookup_uint64(nvprops,
16464577Sahrens 	    zfs_prop_to_name(ZFS_PROP_VERSION), &version);
16474577Sahrens 
16484577Sahrens 	zfs_create_fs(os, cr, version, tx);
1649789Sahrens }
1650789Sahrens 
1651789Sahrens static int
1652789Sahrens zfs_ioc_create(zfs_cmd_t *zc)
1653789Sahrens {
1654789Sahrens 	objset_t *clone;
1655789Sahrens 	int error = 0;
16564543Smarks 	nvlist_t *nvprops = NULL;
16574543Smarks 	void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
1658789Sahrens 	dmu_objset_type_t type = zc->zc_objset_type;
1659789Sahrens 
1660789Sahrens 	switch (type) {
1661789Sahrens 
1662789Sahrens 	case DMU_OST_ZFS:
1663789Sahrens 		cbfunc = zfs_create_cb;
1664789Sahrens 		break;
1665789Sahrens 
1666789Sahrens 	case DMU_OST_ZVOL:
1667789Sahrens 		cbfunc = zvol_create_cb;
1668789Sahrens 		break;
1669789Sahrens 
1670789Sahrens 	default:
16712199Sahrens 		cbfunc = NULL;
16722199Sahrens 	}
16732199Sahrens 	if (strchr(zc->zc_name, '@'))
1674789Sahrens 		return (EINVAL);
1675789Sahrens 
16762676Seschrock 	if (zc->zc_nvlist_src != NULL &&
16774543Smarks 	    (error = get_nvlist(zc, &nvprops)) != 0)
16782676Seschrock 		return (error);
16792676Seschrock 
16802676Seschrock 	if (zc->zc_value[0] != '\0') {
1681789Sahrens 		/*
1682789Sahrens 		 * We're creating a clone of an existing snapshot.
1683789Sahrens 		 */
16842676Seschrock 		zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
16852676Seschrock 		if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) {
16864543Smarks 			nvlist_free(nvprops);
1687789Sahrens 			return (EINVAL);
16882676Seschrock 		}
1689789Sahrens 
16902676Seschrock 		error = dmu_objset_open(zc->zc_value, type,
1691789Sahrens 		    DS_MODE_STANDARD | DS_MODE_READONLY, &clone);
16922676Seschrock 		if (error) {
16934543Smarks 			nvlist_free(nvprops);
1694789Sahrens 			return (error);
16952676Seschrock 		}
1696789Sahrens 		error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL);
1697789Sahrens 		dmu_objset_close(clone);
1698789Sahrens 	} else {
16992676Seschrock 		if (cbfunc == NULL) {
17004543Smarks 			nvlist_free(nvprops);
17012199Sahrens 			return (EINVAL);
17022676Seschrock 		}
17032676Seschrock 
1704789Sahrens 		if (type == DMU_OST_ZVOL) {
17052676Seschrock 			uint64_t volsize, volblocksize;
17062676Seschrock 
17074543Smarks 			if (nvprops == NULL ||
17084543Smarks 			    nvlist_lookup_uint64(nvprops,
17092676Seschrock 			    zfs_prop_to_name(ZFS_PROP_VOLSIZE),
17102676Seschrock 			    &volsize) != 0) {
17114543Smarks 				nvlist_free(nvprops);
17122676Seschrock 				return (EINVAL);
17132676Seschrock 			}
17142676Seschrock 
17154543Smarks 			if ((error = nvlist_lookup_uint64(nvprops,
17162676Seschrock 			    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
17172676Seschrock 			    &volblocksize)) != 0 && error != ENOENT) {
17184543Smarks 				nvlist_free(nvprops);
17192676Seschrock 				return (EINVAL);
17202676Seschrock 			}
17211133Seschrock 
17222676Seschrock 			if (error != 0)
17232676Seschrock 				volblocksize = zfs_prop_default_numeric(
17242676Seschrock 				    ZFS_PROP_VOLBLOCKSIZE);
17252676Seschrock 
17262676Seschrock 			if ((error = zvol_check_volblocksize(
17272676Seschrock 			    volblocksize)) != 0 ||
17282676Seschrock 			    (error = zvol_check_volsize(volsize,
17292676Seschrock 			    volblocksize)) != 0) {
17304543Smarks 				nvlist_free(nvprops);
1731789Sahrens 				return (error);
17322676Seschrock 			}
17334577Sahrens 		} else if (type == DMU_OST_ZFS) {
17344577Sahrens 			uint64_t version;
17354577Sahrens 
17364577Sahrens 			if (0 == nvlist_lookup_uint64(nvprops,
17374577Sahrens 			    zfs_prop_to_name(ZFS_PROP_VERSION), &version) &&
17384577Sahrens 			    (version < ZPL_VERSION_INITIAL ||
17394577Sahrens 			    version > ZPL_VERSION)) {
17404577Sahrens 				nvlist_free(nvprops);
17414577Sahrens 				return (EINVAL);
17424577Sahrens 			}
17432676Seschrock 		}
17441133Seschrock 
17452676Seschrock 		error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc,
17464543Smarks 		    nvprops);
1747789Sahrens 	}
17482676Seschrock 
17492676Seschrock 	/*
17502676Seschrock 	 * It would be nice to do this atomically.
17512676Seschrock 	 */
17522676Seschrock 	if (error == 0) {
17532676Seschrock 		if ((error = zfs_set_prop_nvlist(zc->zc_name,
17542676Seschrock 		    zc->zc_dev, (cred_t *)(uintptr_t)zc->zc_cred,
17554543Smarks 		    nvprops)) != 0)
17562676Seschrock 			(void) dmu_objset_destroy(zc->zc_name);
17572676Seschrock 	}
17582676Seschrock 
17594543Smarks 	nvlist_free(nvprops);
1760789Sahrens 	return (error);
1761789Sahrens }
1762789Sahrens 
1763789Sahrens static int
17642199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc)
17652199Sahrens {
17662676Seschrock 	if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
17672199Sahrens 		return (EINVAL);
17682199Sahrens 	return (dmu_objset_snapshot(zc->zc_name,
17692676Seschrock 	    zc->zc_value, zc->zc_cookie));
17702199Sahrens }
17712199Sahrens 
17724007Smmusante int
17732199Sahrens zfs_unmount_snap(char *name, void *arg)
1774789Sahrens {
17752199Sahrens 	char *snapname = arg;
17762199Sahrens 	char *cp;
17772417Sahrens 	vfs_t *vfsp = NULL;
17782199Sahrens 
17792199Sahrens 	/*
17802199Sahrens 	 * Snapshots (which are under .zfs control) must be unmounted
17812199Sahrens 	 * before they can be destroyed.
17822199Sahrens 	 */
17832199Sahrens 
17842199Sahrens 	if (snapname) {
17852199Sahrens 		(void) strcat(name, "@");
17862199Sahrens 		(void) strcat(name, snapname);
17872199Sahrens 		vfsp = zfs_get_vfs(name);
17882199Sahrens 		cp = strchr(name, '@');
17892199Sahrens 		*cp = '\0';
17902417Sahrens 	} else if (strchr(name, '@')) {
17912199Sahrens 		vfsp = zfs_get_vfs(name);
17922199Sahrens 	}
17932199Sahrens 
17942199Sahrens 	if (vfsp) {
17952199Sahrens 		/*
17962199Sahrens 		 * Always force the unmount for snapshots.
17972199Sahrens 		 */
17982199Sahrens 		int flag = MS_FORCE;
1799789Sahrens 		int err;
1800789Sahrens 
18012199Sahrens 		if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) {
18022199Sahrens 			VFS_RELE(vfsp);
18032199Sahrens 			return (err);
18042199Sahrens 		}
18052199Sahrens 		VFS_RELE(vfsp);
18062199Sahrens 		if ((err = dounmount(vfsp, flag, kcred)) != 0)
18072199Sahrens 			return (err);
18082199Sahrens 	}
18092199Sahrens 	return (0);
18102199Sahrens }
18112199Sahrens 
18122199Sahrens static int
18132199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc)
18142199Sahrens {
18152199Sahrens 	int err;
1816789Sahrens 
18172676Seschrock 	if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
18182199Sahrens 		return (EINVAL);
18192199Sahrens 	err = dmu_objset_find(zc->zc_name,
18202676Seschrock 	    zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN);
18212199Sahrens 	if (err)
18222199Sahrens 		return (err);
18232676Seschrock 	return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value));
18242199Sahrens }
18252199Sahrens 
18262199Sahrens static int
18272199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc)
18282199Sahrens {
18292199Sahrens 	if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) {
18302199Sahrens 		int err = zfs_unmount_snap(zc->zc_name, NULL);
18312199Sahrens 		if (err)
18322199Sahrens 			return (err);
1833789Sahrens 	}
1834789Sahrens 
1835789Sahrens 	return (dmu_objset_destroy(zc->zc_name));
1836789Sahrens }
1837789Sahrens 
1838789Sahrens static int
1839789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc)
1840789Sahrens {
1841789Sahrens 	return (dmu_objset_rollback(zc->zc_name));
1842789Sahrens }
1843789Sahrens 
1844789Sahrens static int
1845789Sahrens zfs_ioc_rename(zfs_cmd_t *zc)
1846789Sahrens {
18474490Svb160487 	boolean_t recursive = zc->zc_cookie & 1;
18484007Smmusante 
18492676Seschrock 	zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
18502676Seschrock 	if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0)
1851789Sahrens 		return (EINVAL);
1852789Sahrens 
18534007Smmusante 	/*
18544007Smmusante 	 * Unmount snapshot unless we're doing a recursive rename,
18554007Smmusante 	 * in which case the dataset code figures out which snapshots
18564007Smmusante 	 * to unmount.
18574007Smmusante 	 */
18584007Smmusante 	if (!recursive && strchr(zc->zc_name, '@') != NULL &&
1859789Sahrens 	    zc->zc_objset_type == DMU_OST_ZFS) {
18602199Sahrens 		int err = zfs_unmount_snap(zc->zc_name, NULL);
18612199Sahrens 		if (err)
18622199Sahrens 			return (err);
1863789Sahrens 	}
1864789Sahrens 
18654007Smmusante 	return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive));
1866789Sahrens }
1867789Sahrens 
1868789Sahrens static int
1869789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc)
1870789Sahrens {
1871789Sahrens 	file_t *fp;
1872789Sahrens 	int error, fd;
18732885Sahrens 	offset_t new_off;
1874789Sahrens 
18753265Sahrens 	if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
18763265Sahrens 	    strchr(zc->zc_value, '@') == NULL)
18773265Sahrens 		return (EINVAL);
18783265Sahrens 
1879789Sahrens 	fd = zc->zc_cookie;
1880789Sahrens 	fp = getf(fd);
1881789Sahrens 	if (fp == NULL)
1882789Sahrens 		return (EBADF);
18832676Seschrock 	error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record,
18842676Seschrock 	    &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode,
18852665Snd150628 	    fp->f_offset);
18862885Sahrens 
18872885Sahrens 	new_off = fp->f_offset + zc->zc_cookie;
18882885Sahrens 	if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0)
18892885Sahrens 		fp->f_offset = new_off;
18902885Sahrens 
1891789Sahrens 	releasef(fd);
1892789Sahrens 	return (error);
1893789Sahrens }
1894789Sahrens 
1895789Sahrens static int
1896789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc)
1897789Sahrens {
1898789Sahrens 	objset_t *fromsnap = NULL;
1899789Sahrens 	objset_t *tosnap;
1900789Sahrens 	file_t *fp;
1901789Sahrens 	int error;
1902789Sahrens 
1903789Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1904789Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap);
1905789Sahrens 	if (error)
1906789Sahrens 		return (error);
1907789Sahrens 
19082676Seschrock 	if (zc->zc_value[0] != '\0') {
19092885Sahrens 		char buf[MAXPATHLEN];
19102885Sahrens 		char *cp;
19112885Sahrens 
19122885Sahrens 		(void) strncpy(buf, zc->zc_name, sizeof (buf));
19132885Sahrens 		cp = strchr(buf, '@');
19142885Sahrens 		if (cp)
19152885Sahrens 			*(cp+1) = 0;
19162885Sahrens 		(void) strncat(buf, zc->zc_value, sizeof (buf));
19172885Sahrens 		error = dmu_objset_open(buf, DMU_OST_ANY,
1918789Sahrens 		    DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap);
1919789Sahrens 		if (error) {
1920789Sahrens 			dmu_objset_close(tosnap);
1921789Sahrens 			return (error);
1922789Sahrens 		}
1923789Sahrens 	}
1924789Sahrens 
1925789Sahrens 	fp = getf(zc->zc_cookie);
1926789Sahrens 	if (fp == NULL) {
1927789Sahrens 		dmu_objset_close(tosnap);
1928789Sahrens 		if (fromsnap)
1929789Sahrens 			dmu_objset_close(fromsnap);
1930789Sahrens 		return (EBADF);
1931789Sahrens 	}
1932789Sahrens 
1933789Sahrens 	error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode);
1934789Sahrens 
1935789Sahrens 	releasef(zc->zc_cookie);
1936789Sahrens 	if (fromsnap)
1937789Sahrens 		dmu_objset_close(fromsnap);
1938789Sahrens 	dmu_objset_close(tosnap);
1939789Sahrens 	return (error);
1940789Sahrens }
1941789Sahrens 
19421544Seschrock static int
19431544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc)
19441544Seschrock {
19451544Seschrock 	int id, error;
19461544Seschrock 
19471544Seschrock 	error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id,
19481544Seschrock 	    &zc->zc_inject_record);
19491544Seschrock 
19501544Seschrock 	if (error == 0)
19511544Seschrock 		zc->zc_guid = (uint64_t)id;
19521544Seschrock 
19531544Seschrock 	return (error);
19541544Seschrock }
19551544Seschrock 
19561544Seschrock static int
19571544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc)
19581544Seschrock {
19591544Seschrock 	return (zio_clear_fault((int)zc->zc_guid));
19601544Seschrock }
19611544Seschrock 
19621544Seschrock static int
19631544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc)
19641544Seschrock {
19651544Seschrock 	int id = (int)zc->zc_guid;
19661544Seschrock 	int error;
19671544Seschrock 
19681544Seschrock 	error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name),
19691544Seschrock 	    &zc->zc_inject_record);
19701544Seschrock 
19711544Seschrock 	zc->zc_guid = id;
19721544Seschrock 
19731544Seschrock 	return (error);
19741544Seschrock }
19751544Seschrock 
19761544Seschrock static int
19771544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc)
19781544Seschrock {
19791544Seschrock 	spa_t *spa;
19801544Seschrock 	int error;
19812676Seschrock 	size_t count = (size_t)zc->zc_nvlist_dst_size;
19821544Seschrock 
19831544Seschrock 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
19841544Seschrock 		return (error);
19851544Seschrock 
19862676Seschrock 	error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst,
19871544Seschrock 	    &count);
19881544Seschrock 	if (error == 0)
19892676Seschrock 		zc->zc_nvlist_dst_size = count;
19901544Seschrock 	else
19912676Seschrock 		zc->zc_nvlist_dst_size = spa_get_errlog_size(spa);
19921544Seschrock 
19931544Seschrock 	spa_close(spa, FTAG);
19941544Seschrock 
19951544Seschrock 	return (error);
19961544Seschrock }
19971544Seschrock 
19981544Seschrock static int
19991544Seschrock zfs_ioc_clear(zfs_cmd_t *zc)
20001544Seschrock {
20011544Seschrock 	spa_t *spa;
20021544Seschrock 	vdev_t *vd;
20031544Seschrock 	int error;
20044451Seschrock 	uint64_t txg;
20051544Seschrock 
20061544Seschrock 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
20071544Seschrock 		return (error);
20081544Seschrock 
20094451Seschrock 	txg = spa_vdev_enter(spa);
20101544Seschrock 
20112676Seschrock 	if (zc->zc_guid == 0) {
20121544Seschrock 		vd = NULL;
20132676Seschrock 	} else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) {
20144451Seschrock 		(void) spa_vdev_exit(spa, NULL, txg, ENODEV);
20151544Seschrock 		spa_close(spa, FTAG);
20161544Seschrock 		return (ENODEV);
20171544Seschrock 	}
20181544Seschrock 
20191544Seschrock 	vdev_clear(spa, vd);
20201544Seschrock 
20214451Seschrock 	(void) spa_vdev_exit(spa, NULL, txg, 0);
20221544Seschrock 
20231544Seschrock 	spa_close(spa, FTAG);
20241544Seschrock 
20251544Seschrock 	return (0);
20261544Seschrock }
20271544Seschrock 
20281544Seschrock static int
20292082Seschrock zfs_ioc_promote(zfs_cmd_t *zc)
20302082Seschrock {
20312417Sahrens 	char *cp;
20322417Sahrens 
20332417Sahrens 	/*
20342417Sahrens 	 * We don't need to unmount *all* the origin fs's snapshots, but
20352417Sahrens 	 * it's easier.
20362417Sahrens 	 */
20372676Seschrock 	cp = strchr(zc->zc_value, '@');
20382417Sahrens 	if (cp)
20392417Sahrens 		*cp = '\0';
20402676Seschrock 	(void) dmu_objset_find(zc->zc_value,
20412417Sahrens 	    zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS);
20422082Seschrock 	return (dsl_dataset_promote(zc->zc_name));
20432082Seschrock }
20442082Seschrock 
20454543Smarks /*
20464543Smarks  * We don't want to have a hard dependency
20474543Smarks  * against some special symbols in sharefs
20484543Smarks  * and nfs.  Determine them if needed when
20494543Smarks  * the first file system is shared.
20504543Smarks  * Neither sharefs or nfs are unloadable modules.
20514543Smarks  */
20524543Smarks int (*zexport_fs)(void *arg);
20534543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t);
20544543Smarks 
20554543Smarks int zfs_share_inited;
20564543Smarks ddi_modhandle_t nfs_mod;
20574543Smarks ddi_modhandle_t sharefs_mod;
20584543Smarks kmutex_t zfs_share_lock;
20594543Smarks 
20604543Smarks static int
20614543Smarks zfs_ioc_share(zfs_cmd_t *zc)
20624543Smarks {
20634543Smarks 	int error;
20644543Smarks 	int opcode;
20654543Smarks 
20664543Smarks 	if (zfs_share_inited == 0) {
20674543Smarks 		mutex_enter(&zfs_share_lock);
20684543Smarks 		nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error);
20694543Smarks 		sharefs_mod = ddi_modopen("fs/sharefs",
20704543Smarks 		    KRTLD_MODE_FIRST, &error);
20714543Smarks 		if (nfs_mod == NULL || sharefs_mod == NULL) {
20724543Smarks 			mutex_exit(&zfs_share_lock);
20734543Smarks 			return (ENOSYS);
20744543Smarks 		}
20754543Smarks 		if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *))
20764543Smarks 		    ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) {
20774543Smarks 			mutex_exit(&zfs_share_lock);
20784543Smarks 			return (ENOSYS);
20794543Smarks 		}
20804543Smarks 
20814543Smarks 		if (zshare_fs == NULL && ((zshare_fs =
20824543Smarks 		    (int (*)(enum sharefs_sys_op, share_t *, uint32_t))
20834543Smarks 		    ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) {
20844543Smarks 			mutex_exit(&zfs_share_lock);
20854543Smarks 			return (ENOSYS);
20864543Smarks 		}
20874543Smarks 		zfs_share_inited = 1;
20884543Smarks 		mutex_exit(&zfs_share_lock);
20894543Smarks 	}
20904543Smarks 
20914543Smarks 	if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata))
20924543Smarks 		return (error);
20934543Smarks 
20944543Smarks 	opcode = (zc->zc_share.z_sharetype == B_TRUE) ?
20954543Smarks 	    SHAREFS_ADD : SHAREFS_REMOVE;
20964543Smarks 
20974543Smarks 	error = zshare_fs(opcode,
20984543Smarks 	    (void *)(uintptr_t)zc->zc_share.z_sharedata,
20994543Smarks 	    zc->zc_share.z_sharemax);
21004543Smarks 
21014543Smarks 	return (error);
21024543Smarks 
21034543Smarks }
21044543Smarks 
21054543Smarks /*
21064543Smarks  * pool destroy and pool export don't log the history as part of zfsdev_ioctl,
21074543Smarks  * but rather zfs_ioc_pool_create, and zfs_ioc_pool_export do the loggin
21084543Smarks  * of those commands.
21094543Smarks  */
2110789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = {
21114577Sahrens 	{ zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_TRUE },
21124577Sahrens 	{ zfs_ioc_pool_destroy,	zfs_secpolicy_config, POOL_NAME, B_FALSE },
21134577Sahrens 	{ zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE },
21144577Sahrens 	{ zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE },
21154577Sahrens 	{ zfs_ioc_pool_configs,	zfs_secpolicy_none, NO_NAME, B_FALSE },
21164577Sahrens 	{ zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE },
21174577Sahrens 	{ zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE },
21184577Sahrens 	{ zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE },
21194577Sahrens 	{ zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE },
21204577Sahrens 	{ zfs_ioc_pool_upgrade,	zfs_secpolicy_config, POOL_NAME, B_TRUE },
21214577Sahrens 	{ zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE },
21224577Sahrens 	{ zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE },
21234577Sahrens 	{ zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE },
21244577Sahrens 	{ zfs_ioc_vdev_set_state, zfs_secpolicy_config,	POOL_NAME, B_TRUE },
21254577Sahrens 	{ zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE },
21264577Sahrens 	{ zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE },
21274577Sahrens 	{ zfs_ioc_vdev_setpath,	zfs_secpolicy_config, POOL_NAME, B_FALSE },
21284577Sahrens 	{ zfs_ioc_objset_stats,	zfs_secpolicy_read, DATASET_NAME, B_FALSE },
21294543Smarks 	{ zfs_ioc_dataset_list_next, zfs_secpolicy_read,
21304577Sahrens 	    DATASET_NAME, B_FALSE },
21314543Smarks 	{ zfs_ioc_snapshot_list_next, zfs_secpolicy_read,
21324577Sahrens 	    DATASET_NAME, B_FALSE },
21334577Sahrens 	{ zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE },
21344577Sahrens 	{ zfs_ioc_create_minor,	zfs_secpolicy_minor, DATASET_NAME, B_FALSE },
21354577Sahrens 	{ zfs_ioc_remove_minor,	zfs_secpolicy_minor, DATASET_NAME, B_FALSE },
21364577Sahrens 	{ zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE },
21374577Sahrens 	{ zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE },
21384577Sahrens 	{ zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE },
21394577Sahrens 	{ zfs_ioc_rename, zfs_secpolicy_rename,	DATASET_NAME, B_TRUE },
21404577Sahrens 	{ zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE },
21414577Sahrens 	{ zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE },
21424577Sahrens 	{ zfs_ioc_inject_fault,	zfs_secpolicy_inject, NO_NAME, B_FALSE },
21434577Sahrens 	{ zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE },
21444577Sahrens 	{ zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE },
21454577Sahrens 	{ zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE },
21464577Sahrens 	{ zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE },
21474577Sahrens 	{ zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE },
21484577Sahrens 	{ zfs_ioc_destroy_snaps, zfs_secpolicy_destroy,	DATASET_NAME, B_TRUE },
21494577Sahrens 	{ zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE },
21504577Sahrens 	{ zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE },
21514577Sahrens 	{ zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE },
21524577Sahrens 	{ zfs_ioc_pool_set_props, zfs_secpolicy_config,	POOL_NAME, B_TRUE },
21534577Sahrens 	{ zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE },
21544577Sahrens 	{ zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE },
21554577Sahrens 	{ zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE },
21564543Smarks 	{ zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi,
21574577Sahrens 	    DATASET_NAME, B_FALSE },
21584577Sahrens 	{ zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }
2159789Sahrens };
2160789Sahrens 
2161789Sahrens static int
2162789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
2163789Sahrens {
2164789Sahrens 	zfs_cmd_t *zc;
2165789Sahrens 	uint_t vec;
21662199Sahrens 	int error, rc;
2167789Sahrens 
2168789Sahrens 	if (getminor(dev) != 0)
2169789Sahrens 		return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp));
2170789Sahrens 
2171789Sahrens 	vec = cmd - ZFS_IOC;
2172789Sahrens 
2173789Sahrens 	if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
2174789Sahrens 		return (EINVAL);
2175789Sahrens 
2176789Sahrens 	zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
2177789Sahrens 
2178789Sahrens 	error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t));
2179789Sahrens 
2180789Sahrens 	if (error == 0) {
2181789Sahrens 		zc->zc_cred = (uintptr_t)cr;
2182789Sahrens 		zc->zc_dev = dev;
21834543Smarks 		error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr);
2184789Sahrens 	}
2185789Sahrens 
2186789Sahrens 	/*
2187789Sahrens 	 * Ensure that all pool/dataset names are valid before we pass down to
2188789Sahrens 	 * the lower layers.
2189789Sahrens 	 */
2190789Sahrens 	if (error == 0) {
2191789Sahrens 		zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
2192789Sahrens 		switch (zfs_ioc_vec[vec].zvec_namecheck) {
21934577Sahrens 		case POOL_NAME:
2194789Sahrens 			if (pool_namecheck(zc->zc_name, NULL, NULL) != 0)
2195789Sahrens 				error = EINVAL;
2196789Sahrens 			break;
2197789Sahrens 
21984577Sahrens 		case DATASET_NAME:
2199789Sahrens 			if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0)
2200789Sahrens 				error = EINVAL;
2201789Sahrens 			break;
22022856Snd150628 
22034577Sahrens 		case NO_NAME:
22042856Snd150628 			break;
2205789Sahrens 		}
2206789Sahrens 	}
2207789Sahrens 
2208789Sahrens 	if (error == 0)
2209789Sahrens 		error = zfs_ioc_vec[vec].zvec_func(zc);
2210789Sahrens 
22112199Sahrens 	rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t));
22124543Smarks 	if (error == 0) {
22132199Sahrens 		error = rc;
22144543Smarks 		if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE)
22154543Smarks 			zfs_log_history(zc);
22164543Smarks 	}
2217789Sahrens 
2218789Sahrens 	kmem_free(zc, sizeof (zfs_cmd_t));
2219789Sahrens 	return (error);
2220789Sahrens }
2221789Sahrens 
2222789Sahrens static int
2223789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2224789Sahrens {
2225789Sahrens 	if (cmd != DDI_ATTACH)
2226789Sahrens 		return (DDI_FAILURE);
2227789Sahrens 
2228789Sahrens 	if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0,
2229789Sahrens 	    DDI_PSEUDO, 0) == DDI_FAILURE)
2230789Sahrens 		return (DDI_FAILURE);
2231789Sahrens 
2232789Sahrens 	zfs_dip = dip;
2233789Sahrens 
2234789Sahrens 	ddi_report_dev(dip);
2235789Sahrens 
2236789Sahrens 	return (DDI_SUCCESS);
2237789Sahrens }
2238789Sahrens 
2239789Sahrens static int
2240789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2241789Sahrens {
2242789Sahrens 	if (spa_busy() || zfs_busy() || zvol_busy())
2243789Sahrens 		return (DDI_FAILURE);
2244789Sahrens 
2245789Sahrens 	if (cmd != DDI_DETACH)
2246789Sahrens 		return (DDI_FAILURE);
2247789Sahrens 
2248789Sahrens 	zfs_dip = NULL;
2249789Sahrens 
2250789Sahrens 	ddi_prop_remove_all(dip);
2251789Sahrens 	ddi_remove_minor_node(dip, NULL);
2252789Sahrens 
2253789Sahrens 	return (DDI_SUCCESS);
2254789Sahrens }
2255789Sahrens 
2256789Sahrens /*ARGSUSED*/
2257789Sahrens static int
2258789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
2259789Sahrens {
2260789Sahrens 	switch (infocmd) {
2261789Sahrens 	case DDI_INFO_DEVT2DEVINFO:
2262789Sahrens 		*result = zfs_dip;
2263789Sahrens 		return (DDI_SUCCESS);
2264789Sahrens 
2265789Sahrens 	case DDI_INFO_DEVT2INSTANCE:
2266849Sbonwick 		*result = (void *)0;
2267789Sahrens 		return (DDI_SUCCESS);
2268789Sahrens 	}
2269789Sahrens 
2270789Sahrens 	return (DDI_FAILURE);
2271789Sahrens }
2272789Sahrens 
2273789Sahrens /*
2274789Sahrens  * OK, so this is a little weird.
2275789Sahrens  *
2276789Sahrens  * /dev/zfs is the control node, i.e. minor 0.
2277789Sahrens  * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0.
2278789Sahrens  *
2279789Sahrens  * /dev/zfs has basically nothing to do except serve up ioctls,
2280789Sahrens  * so most of the standard driver entry points are in zvol.c.
2281789Sahrens  */
2282789Sahrens static struct cb_ops zfs_cb_ops = {
2283789Sahrens 	zvol_open,	/* open */
2284789Sahrens 	zvol_close,	/* close */
2285789Sahrens 	zvol_strategy,	/* strategy */
2286789Sahrens 	nodev,		/* print */
2287789Sahrens 	nodev,		/* dump */
2288789Sahrens 	zvol_read,	/* read */
2289789Sahrens 	zvol_write,	/* write */
2290789Sahrens 	zfsdev_ioctl,	/* ioctl */
2291789Sahrens 	nodev,		/* devmap */
2292789Sahrens 	nodev,		/* mmap */
2293789Sahrens 	nodev,		/* segmap */
2294789Sahrens 	nochpoll,	/* poll */
2295789Sahrens 	ddi_prop_op,	/* prop_op */
2296789Sahrens 	NULL,		/* streamtab */
2297789Sahrens 	D_NEW | D_MP | D_64BIT,		/* Driver compatibility flag */
2298789Sahrens 	CB_REV,		/* version */
22993638Sbillm 	nodev,		/* async read */
23003638Sbillm 	nodev,		/* async write */
2301789Sahrens };
2302789Sahrens 
2303789Sahrens static struct dev_ops zfs_dev_ops = {
2304789Sahrens 	DEVO_REV,	/* version */
2305789Sahrens 	0,		/* refcnt */
2306789Sahrens 	zfs_info,	/* info */
2307789Sahrens 	nulldev,	/* identify */
2308789Sahrens 	nulldev,	/* probe */
2309789Sahrens 	zfs_attach,	/* attach */
2310789Sahrens 	zfs_detach,	/* detach */
2311789Sahrens 	nodev,		/* reset */
2312789Sahrens 	&zfs_cb_ops,	/* driver operations */
2313789Sahrens 	NULL		/* no bus operations */
2314789Sahrens };
2315789Sahrens 
2316789Sahrens static struct modldrv zfs_modldrv = {
23174577Sahrens 	&mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING,
23182676Seschrock 	    &zfs_dev_ops
2319789Sahrens };
2320789Sahrens 
2321789Sahrens static struct modlinkage modlinkage = {
2322789Sahrens 	MODREV_1,
2323789Sahrens 	(void *)&zfs_modlfs,
2324789Sahrens 	(void *)&zfs_modldrv,
2325789Sahrens 	NULL
2326789Sahrens };
2327789Sahrens 
2328789Sahrens int
2329789Sahrens _init(void)
2330789Sahrens {
2331789Sahrens 	int error;
2332789Sahrens 
2333849Sbonwick 	spa_init(FREAD | FWRITE);
2334849Sbonwick 	zfs_init();
2335849Sbonwick 	zvol_init();
2336849Sbonwick 
2337849Sbonwick 	if ((error = mod_install(&modlinkage)) != 0) {
2338849Sbonwick 		zvol_fini();
2339849Sbonwick 		zfs_fini();
2340849Sbonwick 		spa_fini();
2341789Sahrens 		return (error);
2342849Sbonwick 	}
2343789Sahrens 
2344789Sahrens 	error = ldi_ident_from_mod(&modlinkage, &zfs_li);
2345789Sahrens 	ASSERT(error == 0);
23464543Smarks 	mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
2347789Sahrens 
2348789Sahrens 	return (0);
2349789Sahrens }
2350789Sahrens 
2351789Sahrens int
2352789Sahrens _fini(void)
2353789Sahrens {
2354789Sahrens 	int error;
2355789Sahrens 
23561544Seschrock 	if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled)
2357789Sahrens 		return (EBUSY);
2358789Sahrens 
2359789Sahrens 	if ((error = mod_remove(&modlinkage)) != 0)
2360789Sahrens 		return (error);
2361789Sahrens 
2362789Sahrens 	zvol_fini();
2363789Sahrens 	zfs_fini();
2364789Sahrens 	spa_fini();
23654543Smarks 	if (zfs_share_inited) {
23664543Smarks 		(void) ddi_modclose(nfs_mod);
23674543Smarks 		(void) ddi_modclose(sharefs_mod);
23684543Smarks 	}
2369789Sahrens 
2370789Sahrens 	ldi_ident_release(zfs_li);
2371789Sahrens 	zfs_li = NULL;
23724543Smarks 	mutex_destroy(&zfs_share_lock);
2373789Sahrens 
2374789Sahrens 	return (error);
2375789Sahrens }
2376789Sahrens 
2377789Sahrens int
2378789Sahrens _info(struct modinfo *modinfop)
2379789Sahrens {
2380789Sahrens 	return (mod_info(&modlinkage, modinfop));
2381789Sahrens }
2382