xref: /onnv-gate/usr/src/uts/common/fs/zfs/zfs_ioctl.c (revision 4543:12bb2876a62e)
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>
50*4543Smarks #include <sys/dsl_deleg.h>
51*4543Smarks #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>
64*4543Smarks #include <sharefs/share.h>
65789Sahrens 
66789Sahrens #include "zfs_namecheck.h"
672676Seschrock #include "zfs_prop.h"
68*4543Smarks #include "zfs_deleg.h"
69789Sahrens 
70789Sahrens extern struct modlfs zfs_modlfs;
71789Sahrens 
72789Sahrens extern void zfs_init(void);
73789Sahrens extern void zfs_fini(void);
74789Sahrens 
75789Sahrens ldi_ident_t zfs_li = NULL;
76789Sahrens dev_info_t *zfs_dip;
77789Sahrens 
78789Sahrens typedef int zfs_ioc_func_t(zfs_cmd_t *);
79*4543Smarks typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *);
80789Sahrens 
81789Sahrens typedef struct zfs_ioc_vec {
82789Sahrens 	zfs_ioc_func_t		*zvec_func;
83789Sahrens 	zfs_secpolicy_func_t	*zvec_secpolicy;
84789Sahrens 	enum {
85789Sahrens 		no_name,
86789Sahrens 		pool_name,
87789Sahrens 		dataset_name
88*4543Smarks 	} zvec_namecheck;
89*4543Smarks 	boolean_t		zvec_his_log;
90789Sahrens } zfs_ioc_vec_t;
91789Sahrens 
92789Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */
93789Sahrens void
94789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
95789Sahrens {
96789Sahrens 	const char *newfile;
97789Sahrens 	char buf[256];
98789Sahrens 	va_list adx;
99789Sahrens 
100789Sahrens 	/*
101789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
102789Sahrens 	 */
103789Sahrens 	newfile = strrchr(file, '/');
104789Sahrens 	if (newfile != NULL) {
105789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
106789Sahrens 	} else {
107789Sahrens 		newfile = file;
108789Sahrens 	}
109789Sahrens 
110789Sahrens 	va_start(adx, fmt);
111789Sahrens 	(void) vsnprintf(buf, sizeof (buf), fmt, adx);
112789Sahrens 	va_end(adx);
113789Sahrens 
114789Sahrens 	/*
115789Sahrens 	 * To get this data, use the zfs-dprintf probe as so:
116789Sahrens 	 * dtrace -q -n 'zfs-dprintf \
117789Sahrens 	 *	/stringof(arg0) == "dbuf.c"/ \
118789Sahrens 	 *	{printf("%s: %s", stringof(arg1), stringof(arg3))}'
119789Sahrens 	 * arg0 = file name
120789Sahrens 	 * arg1 = function name
121789Sahrens 	 * arg2 = line number
122789Sahrens 	 * arg3 = message
123789Sahrens 	 */
124789Sahrens 	DTRACE_PROBE4(zfs__dprintf,
125789Sahrens 	    char *, newfile, char *, func, int, line, char *, buf);
126789Sahrens }
127789Sahrens 
128*4543Smarks static void
129*4543Smarks zfs_log_history(zfs_cmd_t *zc)
130*4543Smarks {
131*4543Smarks 	spa_t *spa;
132*4543Smarks 	char poolname[MAXNAMELEN];
133*4543Smarks 	char *buf, *cp;
134*4543Smarks 
135*4543Smarks 	if (zc->zc_history == NULL)
136*4543Smarks 		return;
137*4543Smarks 
138*4543Smarks 	buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP);
139*4543Smarks 	if (copyinstr((void *)(uintptr_t)zc->zc_history,
140*4543Smarks 	    buf, HIS_MAX_RECORD_LEN, NULL) != 0) {
141*4543Smarks 		kmem_free(buf, HIS_MAX_RECORD_LEN);
142*4543Smarks 		return;
143*4543Smarks 	}
144*4543Smarks 
145*4543Smarks 	buf[HIS_MAX_RECORD_LEN -1] = '\0';
146*4543Smarks 
147*4543Smarks 	(void) strlcpy(poolname, zc->zc_name, sizeof (poolname));
148*4543Smarks 	cp = strpbrk(poolname, "/@");
149*4543Smarks 	if (cp != NULL)
150*4543Smarks 		*cp = '\0';
151*4543Smarks 
152*4543Smarks 	if (spa_open(poolname, &spa, FTAG) != 0) {
153*4543Smarks 		kmem_free(buf, HIS_MAX_RECORD_LEN);
154*4543Smarks 		return;
155*4543Smarks 	}
156*4543Smarks 
157*4543Smarks 	if (spa_version(spa) >= ZFS_VERSION_ZPOOL_HISTORY)
158*4543Smarks 		(void) spa_history_log(spa, buf, zc->zc_history_offset);
159*4543Smarks 
160*4543Smarks 	spa_close(spa, FTAG);
161*4543Smarks 	kmem_free(buf, HIS_MAX_RECORD_LEN);
162*4543Smarks }
163*4543Smarks 
164789Sahrens /*
165789Sahrens  * Policy for top-level read operations (list pools).  Requires no privileges,
166789Sahrens  * and can be used in the local zone, as there is no associated dataset.
167789Sahrens  */
168789Sahrens /* ARGSUSED */
169789Sahrens static int
170*4543Smarks zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr)
171789Sahrens {
172789Sahrens 	return (0);
173789Sahrens }
174789Sahrens 
175789Sahrens /*
176789Sahrens  * Policy for dataset read operations (list children, get statistics).  Requires
177789Sahrens  * no privileges, but must be visible in the local zone.
178789Sahrens  */
179789Sahrens /* ARGSUSED */
180789Sahrens static int
181*4543Smarks zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr)
182789Sahrens {
183789Sahrens 	if (INGLOBALZONE(curproc) ||
184*4543Smarks 	    zone_dataset_visible(zc->zc_name, NULL))
185789Sahrens 		return (0);
186789Sahrens 
187789Sahrens 	return (ENOENT);
188789Sahrens }
189789Sahrens 
190789Sahrens static int
191789Sahrens zfs_dozonecheck(const char *dataset, cred_t *cr)
192789Sahrens {
193789Sahrens 	uint64_t zoned;
194789Sahrens 	int writable = 1;
195789Sahrens 
196789Sahrens 	/*
197789Sahrens 	 * The dataset must be visible by this zone -- check this first
198789Sahrens 	 * so they don't see EPERM on something they shouldn't know about.
199789Sahrens 	 */
200789Sahrens 	if (!INGLOBALZONE(curproc) &&
201789Sahrens 	    !zone_dataset_visible(dataset, &writable))
202789Sahrens 		return (ENOENT);
203789Sahrens 
204789Sahrens 	if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL))
205789Sahrens 		return (ENOENT);
206789Sahrens 
207789Sahrens 	if (INGLOBALZONE(curproc)) {
208789Sahrens 		/*
209789Sahrens 		 * If the fs is zoned, only root can access it from the
210789Sahrens 		 * global zone.
211789Sahrens 		 */
212789Sahrens 		if (secpolicy_zfs(cr) && zoned)
213789Sahrens 			return (EPERM);
214789Sahrens 	} else {
215789Sahrens 		/*
216789Sahrens 		 * If we are in a local zone, the 'zoned' property must be set.
217789Sahrens 		 */
218789Sahrens 		if (!zoned)
219789Sahrens 			return (EPERM);
220789Sahrens 
221789Sahrens 		/* must be writable by this zone */
222789Sahrens 		if (!writable)
223789Sahrens 			return (EPERM);
224789Sahrens 	}
225789Sahrens 	return (0);
226789Sahrens }
227789Sahrens 
228789Sahrens int
229*4543Smarks zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
230789Sahrens {
231789Sahrens 	int error;
232789Sahrens 
233*4543Smarks 	error = zfs_dozonecheck(name, cr);
234*4543Smarks 	if (error == 0) {
235*4543Smarks 		error = secpolicy_zfs(cr);
236*4543Smarks 		if (error) {
237*4543Smarks 			error = dsl_deleg_access(name, perm, cr);
238*4543Smarks 		}
239*4543Smarks 	}
240*4543Smarks 	return (error);
241*4543Smarks }
242*4543Smarks 
243*4543Smarks static int
244*4543Smarks zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr)
245*4543Smarks {
246*4543Smarks 	int error = 0;
247*4543Smarks 
248*4543Smarks 	/*
249*4543Smarks 	 * Check permissions for special properties.
250*4543Smarks 	 */
251*4543Smarks 	switch (prop) {
252*4543Smarks 	case ZFS_PROP_ZONED:
253*4543Smarks 		/*
254*4543Smarks 		 * Disallow setting of 'zoned' from within a local zone.
255*4543Smarks 		 */
256*4543Smarks 		if (!INGLOBALZONE(curproc))
257*4543Smarks 			return (EPERM);
258*4543Smarks 		break;
259789Sahrens 
260*4543Smarks 	case ZFS_PROP_QUOTA:
261*4543Smarks 		if (error =
262*4543Smarks 		    zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_QUOTA, cr))
263*4543Smarks 			return (error);
264*4543Smarks 
265*4543Smarks 		if (!INGLOBALZONE(curproc)) {
266*4543Smarks 			uint64_t zoned;
267*4543Smarks 			char setpoint[MAXNAMELEN];
268*4543Smarks 			int dslen;
269*4543Smarks 			/*
270*4543Smarks 			 * Unprivileged users are allowed to modify the
271*4543Smarks 			 * quota on things *under* (ie. contained by)
272*4543Smarks 			 * the thing they own.
273*4543Smarks 			 */
274*4543Smarks 			if (dsl_prop_get_integer(name, "zoned", &zoned,
275*4543Smarks 			    setpoint))
276*4543Smarks 				return (EPERM);
277*4543Smarks 			if (!zoned) /* this shouldn't happen */
278*4543Smarks 				return (EPERM);
279*4543Smarks 			dslen = strlen(name);
280*4543Smarks 			if (dslen <= strlen(setpoint))
281*4543Smarks 				return (EPERM);
282*4543Smarks 		}
283*4543Smarks 	default:
284*4543Smarks 		error = zfs_secpolicy_write_perms(name,
285*4543Smarks 		    zfs_prop_perm(prop), cr);
286*4543Smarks 	}
287*4543Smarks 
288*4543Smarks 	return (error);
289789Sahrens }
290789Sahrens 
291*4543Smarks int
292*4543Smarks zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr)
293*4543Smarks {
294*4543Smarks 	int error;
295*4543Smarks 
296*4543Smarks 	error = zfs_dozonecheck(zc->zc_name, cr);
297*4543Smarks 	if (error)
298*4543Smarks 		return (error);
299*4543Smarks 
300*4543Smarks 	/*
301*4543Smarks 	 * permission to set permissions will be evaluated later in
302*4543Smarks 	 * dsl_deleg_can_allow()
303*4543Smarks 	 */
304*4543Smarks 	return (0);
305*4543Smarks }
306*4543Smarks 
307*4543Smarks int
308*4543Smarks zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr)
309*4543Smarks {
310*4543Smarks 	int error;
311*4543Smarks 	error = zfs_secpolicy_write_perms(zc->zc_name,
312*4543Smarks 	    ZFS_DELEG_PERM_ROLLBACK, cr);
313*4543Smarks 	if (error == 0)
314*4543Smarks 		error = zfs_secpolicy_write_perms(zc->zc_name,
315*4543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr);
316*4543Smarks 	return (error);
317*4543Smarks }
318*4543Smarks 
319*4543Smarks int
320*4543Smarks zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr)
321*4543Smarks {
322*4543Smarks 	return (zfs_secpolicy_write_perms(zc->zc_name,
323*4543Smarks 	    ZFS_DELEG_PERM_SEND, cr));
324*4543Smarks }
325*4543Smarks 
326*4543Smarks int
327*4543Smarks zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr)
328*4543Smarks {
329*4543Smarks 	if (!INGLOBALZONE(curproc))
330*4543Smarks 		return (EPERM);
331*4543Smarks 
332*4543Smarks 	if (secpolicy_nfs(CRED()) == 0) {
333*4543Smarks 		return (0);
334*4543Smarks 	} else {
335*4543Smarks 		vnode_t *vp;
336*4543Smarks 		int error;
337*4543Smarks 
338*4543Smarks 		if ((error = lookupname(zc->zc_value, UIO_SYSSPACE,
339*4543Smarks 		    NO_FOLLOW, NULL, &vp)) != 0)
340*4543Smarks 			return (error);
341*4543Smarks 
342*4543Smarks 		/* Now make sure mntpnt and dataset are ZFS */
343*4543Smarks 
344*4543Smarks 		if (vp->v_vfsp->vfs_fstype != zfsfstype ||
345*4543Smarks 		    (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource),
346*4543Smarks 		    zc->zc_name) != 0)) {
347*4543Smarks 			VN_RELE(vp);
348*4543Smarks 			return (EPERM);
349*4543Smarks 		}
350*4543Smarks 
351*4543Smarks 		VN_RELE(vp);
352*4543Smarks 		return (dsl_deleg_access(zc->zc_name,
353*4543Smarks 		    ZFS_DELEG_PERM_SHARE, cr));
354*4543Smarks 	}
355*4543Smarks }
356*4543Smarks 
357789Sahrens static int
358*4543Smarks zfs_get_parent(const char *datasetname, char *parent, int parentsize)
359789Sahrens {
360789Sahrens 	char *cp;
361789Sahrens 
362789Sahrens 	/*
363789Sahrens 	 * Remove the @bla or /bla from the end of the name to get the parent.
364789Sahrens 	 */
365*4543Smarks 	(void) strncpy(parent, datasetname, parentsize);
366*4543Smarks 	cp = strrchr(parent, '@');
367789Sahrens 	if (cp != NULL) {
368789Sahrens 		cp[0] = '\0';
369789Sahrens 	} else {
370*4543Smarks 		cp = strrchr(parent, '/');
371789Sahrens 		if (cp == NULL)
372789Sahrens 			return (ENOENT);
373789Sahrens 		cp[0] = '\0';
374789Sahrens 	}
375789Sahrens 
376*4543Smarks 	return (0);
377*4543Smarks }
378*4543Smarks 
379*4543Smarks int
380*4543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
381*4543Smarks {
382*4543Smarks 	int error;
383*4543Smarks 
384*4543Smarks 	if ((error = zfs_secpolicy_write_perms(name,
385*4543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
386*4543Smarks 		return (error);
387*4543Smarks 
388*4543Smarks 	return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr));
389*4543Smarks }
390*4543Smarks 
391*4543Smarks static int
392*4543Smarks zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr)
393*4543Smarks {
394*4543Smarks 	return (zfs_secpolicy_destroy_perms(zc->zc_name, cr));
395*4543Smarks }
396*4543Smarks 
397*4543Smarks /*
398*4543Smarks  * Must have sys_config privilege to check the iscsi permission
399*4543Smarks  */
400*4543Smarks /* ARGSUSED */
401*4543Smarks static int
402*4543Smarks zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr)
403*4543Smarks {
404*4543Smarks 	return (secpolicy_zfs(cr));
405*4543Smarks }
406*4543Smarks 
407*4543Smarks int
408*4543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
409*4543Smarks {
410*4543Smarks 	char 	parentname[MAXNAMELEN];
411*4543Smarks 	int	error;
412*4543Smarks 
413*4543Smarks 	if ((error = zfs_secpolicy_write_perms(from,
414*4543Smarks 	    ZFS_DELEG_PERM_RENAME, cr)) != 0)
415*4543Smarks 		return (error);
416*4543Smarks 
417*4543Smarks 	if ((error = zfs_secpolicy_write_perms(from,
418*4543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
419*4543Smarks 		return (error);
420*4543Smarks 
421*4543Smarks 	if ((error = zfs_get_parent(to, parentname,
422*4543Smarks 	    sizeof (parentname))) != 0)
423*4543Smarks 		return (error);
424*4543Smarks 
425*4543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
426*4543Smarks 	    ZFS_DELEG_PERM_CREATE, cr)) != 0)
427*4543Smarks 		return (error);
428*4543Smarks 
429*4543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
430*4543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
431*4543Smarks 		return (error);
432*4543Smarks 
433*4543Smarks 	return (error);
434*4543Smarks }
435*4543Smarks 
436*4543Smarks static int
437*4543Smarks zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr)
438*4543Smarks {
439*4543Smarks 	return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr));
440*4543Smarks }
441*4543Smarks 
442*4543Smarks static int
443*4543Smarks zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr)
444*4543Smarks {
445*4543Smarks 	char 	parentname[MAXNAMELEN];
446*4543Smarks 	objset_t *clone;
447*4543Smarks 	int error;
448*4543Smarks 
449*4543Smarks 	error = zfs_secpolicy_write_perms(zc->zc_name,
450*4543Smarks 	    ZFS_DELEG_PERM_PROMOTE, cr);
451*4543Smarks 	if (error)
452*4543Smarks 		return (error);
453*4543Smarks 
454*4543Smarks 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
455*4543Smarks 	    DS_MODE_STANDARD | DS_MODE_READONLY, &clone);
456*4543Smarks 
457*4543Smarks 	if (error == 0) {
458*4543Smarks 		dsl_dataset_t *pclone = NULL;
459*4543Smarks 		dsl_dir_t *dd;
460*4543Smarks 		dd = clone->os->os_dsl_dataset->ds_dir;
461*4543Smarks 
462*4543Smarks 		rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER);
463*4543Smarks 		error = dsl_dataset_open_obj(dd->dd_pool,
464*4543Smarks 		    dd->dd_phys->dd_clone_parent_obj, NULL,
465*4543Smarks 		    DS_MODE_NONE, FTAG, &pclone);
466*4543Smarks 		rw_exit(&dd->dd_pool->dp_config_rwlock);
467*4543Smarks 		if (error) {
468*4543Smarks 			dmu_objset_close(clone);
469*4543Smarks 			return (error);
470*4543Smarks 		}
471*4543Smarks 
472*4543Smarks 		error = zfs_secpolicy_write_perms(zc->zc_name,
473*4543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr);
474*4543Smarks 
475*4543Smarks 		dsl_dataset_name(pclone, parentname);
476*4543Smarks 		dmu_objset_close(clone);
477*4543Smarks 		dsl_dataset_close(pclone, DS_MODE_NONE, FTAG);
478*4543Smarks 		if (error == 0)
479*4543Smarks 			error = zfs_secpolicy_write_perms(parentname,
480*4543Smarks 			    ZFS_DELEG_PERM_PROMOTE, cr);
481*4543Smarks 	}
482*4543Smarks 	return (error);
483*4543Smarks }
484*4543Smarks 
485*4543Smarks static int
486*4543Smarks zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr)
487*4543Smarks {
488*4543Smarks 	int error;
489*4543Smarks 
490*4543Smarks 	if ((error = zfs_secpolicy_write_perms(zc->zc_name,
491*4543Smarks 	    ZFS_DELEG_PERM_RECEIVE, cr)) != 0)
492*4543Smarks 		return (error);
493*4543Smarks 
494*4543Smarks 	if ((error = zfs_secpolicy_write_perms(zc->zc_name,
495*4543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr)) != 0)
496*4543Smarks 		return (error);
497*4543Smarks 
498*4543Smarks 	return (zfs_secpolicy_write_perms(zc->zc_name,
499*4543Smarks 	    ZFS_DELEG_PERM_CREATE, cr));
500*4543Smarks }
501*4543Smarks 
502*4543Smarks int
503*4543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
504*4543Smarks {
505*4543Smarks 	int error;
506*4543Smarks 
507*4543Smarks 	if ((error = zfs_secpolicy_write_perms(name,
508*4543Smarks 	    ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0)
509*4543Smarks 		return (error);
510*4543Smarks 
511*4543Smarks 	error = zfs_secpolicy_write_perms(name,
512*4543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr);
513*4543Smarks 
514*4543Smarks 	return (error);
515*4543Smarks }
516*4543Smarks 
517*4543Smarks static int
518*4543Smarks zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr)
519*4543Smarks {
520*4543Smarks 
521*4543Smarks 	return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr));
522*4543Smarks }
523*4543Smarks 
524*4543Smarks 
525*4543Smarks 
526*4543Smarks static int
527*4543Smarks zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr)
528*4543Smarks {
529*4543Smarks 	char 	parentname[MAXNAMELEN];
530*4543Smarks 	int 	error;
531*4543Smarks 
532*4543Smarks 	if ((error = zfs_get_parent(zc->zc_name, parentname,
533*4543Smarks 	    sizeof (parentname))) != 0)
534*4543Smarks 		return (error);
535*4543Smarks 
536*4543Smarks 	if (zc->zc_value[0] != '\0') {
537*4543Smarks 		if ((error = zfs_secpolicy_write_perms(zc->zc_value,
538*4543Smarks 		    ZFS_DELEG_PERM_CLONE, cr)) != 0)
539*4543Smarks 			return (error);
540*4543Smarks 	}
541*4543Smarks 
542*4543Smarks 	if ((error = zfs_secpolicy_write_perms(parentname,
543*4543Smarks 	    ZFS_DELEG_PERM_CREATE, cr)) != 0)
544*4543Smarks 		return (error);
545*4543Smarks 
546*4543Smarks 	error = zfs_secpolicy_write_perms(parentname,
547*4543Smarks 	    ZFS_DELEG_PERM_MOUNT, cr);
548*4543Smarks 
549*4543Smarks 	return (error);
550*4543Smarks }
551*4543Smarks 
552*4543Smarks static int
553*4543Smarks zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr)
554*4543Smarks {
555*4543Smarks 	int error;
556*4543Smarks 
557*4543Smarks 	error = secpolicy_fs_unmount(cr, NULL);
558*4543Smarks 	if (error) {
559*4543Smarks 		error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr);
560*4543Smarks 	}
561*4543Smarks 	return (error);
562789Sahrens }
563789Sahrens 
564789Sahrens /*
565789Sahrens  * Policy for pool operations - create/destroy pools, add vdevs, etc.  Requires
566789Sahrens  * SYS_CONFIG privilege, which is not available in a local zone.
567789Sahrens  */
568789Sahrens /* ARGSUSED */
569789Sahrens static int
570*4543Smarks zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr)
571789Sahrens {
572789Sahrens 	if (secpolicy_sys_config(cr, B_FALSE) != 0)
573789Sahrens 		return (EPERM);
574789Sahrens 
575789Sahrens 	return (0);
576789Sahrens }
577789Sahrens 
578789Sahrens /*
579*4543Smarks  * Just like zfs_secpolicy_config, except that we will check for
580*4543Smarks  * mount permission on the dataset for permission to create/remove
581*4543Smarks  * the minor nodes.
582*4543Smarks  */
583*4543Smarks static int
584*4543Smarks zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr)
585*4543Smarks {
586*4543Smarks 	if (secpolicy_sys_config(cr, B_FALSE) != 0) {
587*4543Smarks 		return (dsl_deleg_access(zc->zc_name,
588*4543Smarks 		    ZFS_DELEG_PERM_MOUNT, cr));
589*4543Smarks 	}
590*4543Smarks 
591*4543Smarks 	return (0);
592*4543Smarks }
593*4543Smarks 
594*4543Smarks /*
5951544Seschrock  * Policy for fault injection.  Requires all privileges.
5961544Seschrock  */
5971544Seschrock /* ARGSUSED */
5981544Seschrock static int
599*4543Smarks zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr)
6001544Seschrock {
6011544Seschrock 	return (secpolicy_zinject(cr));
6021544Seschrock }
6031544Seschrock 
6041544Seschrock /*
605789Sahrens  * Returns the nvlist as specified by the user in the zfs_cmd_t.
606789Sahrens  */
607789Sahrens static int
6082676Seschrock get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp)
609789Sahrens {
610789Sahrens 	char *packed;
611789Sahrens 	size_t size;
612789Sahrens 	int error;
613789Sahrens 	nvlist_t *config = NULL;
614789Sahrens 
615789Sahrens 	/*
6162676Seschrock 	 * Read in and unpack the user-supplied nvlist.
617789Sahrens 	 */
6182676Seschrock 	if ((size = zc->zc_nvlist_src_size) == 0)
619789Sahrens 		return (EINVAL);
620789Sahrens 
621789Sahrens 	packed = kmem_alloc(size, KM_SLEEP);
622789Sahrens 
6232676Seschrock 	if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed,
624789Sahrens 	    size)) != 0) {
625789Sahrens 		kmem_free(packed, size);
626789Sahrens 		return (error);
627789Sahrens 	}
628789Sahrens 
629789Sahrens 	if ((error = nvlist_unpack(packed, size, &config, 0)) != 0) {
630789Sahrens 		kmem_free(packed, size);
631789Sahrens 		return (error);
632789Sahrens 	}
633789Sahrens 
634789Sahrens 	kmem_free(packed, size);
635789Sahrens 
636789Sahrens 	*nvp = config;
637789Sahrens 	return (0);
638789Sahrens }
639789Sahrens 
640789Sahrens static int
6412676Seschrock put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
6422676Seschrock {
6432676Seschrock 	char *packed = NULL;
6442676Seschrock 	size_t size;
6452676Seschrock 	int error;
6462676Seschrock 
6472676Seschrock 	VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
6482676Seschrock 
6492676Seschrock 	if (size > zc->zc_nvlist_dst_size) {
6502676Seschrock 		error = ENOMEM;
6512676Seschrock 	} else {
6522676Seschrock 		VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
6532676Seschrock 		    KM_SLEEP) == 0);
6542676Seschrock 		error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst,
6552676Seschrock 		    size);
6562676Seschrock 		kmem_free(packed, size);
6572676Seschrock 	}
6582676Seschrock 
6592676Seschrock 	zc->zc_nvlist_dst_size = size;
6602676Seschrock 	return (error);
6612676Seschrock }
6622676Seschrock 
6632676Seschrock static int
664789Sahrens zfs_ioc_pool_create(zfs_cmd_t *zc)
665789Sahrens {
666789Sahrens 	int error;
667789Sahrens 	nvlist_t *config;
668789Sahrens 
6692676Seschrock 	if ((error = get_nvlist(zc, &config)) != 0)
670789Sahrens 		return (error);
671789Sahrens 
6722676Seschrock 	error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ?
6732676Seschrock 	    NULL : zc->zc_value);
674789Sahrens 
675789Sahrens 	nvlist_free(config);
676789Sahrens 
677789Sahrens 	return (error);
678789Sahrens }
679789Sahrens 
680789Sahrens static int
681789Sahrens zfs_ioc_pool_destroy(zfs_cmd_t *zc)
682789Sahrens {
683*4543Smarks 	int error;
684*4543Smarks 	zfs_log_history(zc);
685*4543Smarks 	error = spa_destroy(zc->zc_name);
686*4543Smarks 	return (error);
687789Sahrens }
688789Sahrens 
689789Sahrens static int
690789Sahrens zfs_ioc_pool_import(zfs_cmd_t *zc)
691789Sahrens {
692789Sahrens 	int error;
693789Sahrens 	nvlist_t *config;
694789Sahrens 	uint64_t guid;
695789Sahrens 
6962676Seschrock 	if ((error = get_nvlist(zc, &config)) != 0)
697789Sahrens 		return (error);
698789Sahrens 
699789Sahrens 	if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 ||
7001544Seschrock 	    guid != zc->zc_guid)
701789Sahrens 		error = EINVAL;
702789Sahrens 	else
703789Sahrens 		error = spa_import(zc->zc_name, config,
7042676Seschrock 		    zc->zc_value[0] == '\0' ? NULL : zc->zc_value);
705789Sahrens 
706789Sahrens 	nvlist_free(config);
707789Sahrens 
708789Sahrens 	return (error);
709789Sahrens }
710789Sahrens 
711789Sahrens static int
712789Sahrens zfs_ioc_pool_export(zfs_cmd_t *zc)
713789Sahrens {
714*4543Smarks 	int error;
715*4543Smarks 	zfs_log_history(zc);
716*4543Smarks 	error = spa_export(zc->zc_name, NULL);
717*4543Smarks 	return (error);
718789Sahrens }
719789Sahrens 
720789Sahrens static int
721789Sahrens zfs_ioc_pool_configs(zfs_cmd_t *zc)
722789Sahrens {
723789Sahrens 	nvlist_t *configs;
724789Sahrens 	int error;
725789Sahrens 
726789Sahrens 	if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL)
727789Sahrens 		return (EEXIST);
728789Sahrens 
7292676Seschrock 	error = put_nvlist(zc, configs);
730789Sahrens 
731789Sahrens 	nvlist_free(configs);
732789Sahrens 
733789Sahrens 	return (error);
734789Sahrens }
735789Sahrens 
736789Sahrens static int
737789Sahrens zfs_ioc_pool_stats(zfs_cmd_t *zc)
738789Sahrens {
739789Sahrens 	nvlist_t *config;
740789Sahrens 	int error;
7411544Seschrock 	int ret = 0;
742789Sahrens 
7432676Seschrock 	error = spa_get_stats(zc->zc_name, &config, zc->zc_value,
7442676Seschrock 	    sizeof (zc->zc_value));
745789Sahrens 
746789Sahrens 	if (config != NULL) {
7472676Seschrock 		ret = put_nvlist(zc, config);
748789Sahrens 		nvlist_free(config);
7491544Seschrock 
7501544Seschrock 		/*
7511544Seschrock 		 * The config may be present even if 'error' is non-zero.
7521544Seschrock 		 * In this case we return success, and preserve the real errno
7531544Seschrock 		 * in 'zc_cookie'.
7541544Seschrock 		 */
7551544Seschrock 		zc->zc_cookie = error;
756789Sahrens 	} else {
7571544Seschrock 		ret = error;
758789Sahrens 	}
759789Sahrens 
7601544Seschrock 	return (ret);
761789Sahrens }
762789Sahrens 
763789Sahrens /*
764789Sahrens  * Try to import the given pool, returning pool stats as appropriate so that
765789Sahrens  * user land knows which devices are available and overall pool health.
766789Sahrens  */
767789Sahrens static int
768789Sahrens zfs_ioc_pool_tryimport(zfs_cmd_t *zc)
769789Sahrens {
770789Sahrens 	nvlist_t *tryconfig, *config;
771789Sahrens 	int error;
772789Sahrens 
7732676Seschrock 	if ((error = get_nvlist(zc, &tryconfig)) != 0)
774789Sahrens 		return (error);
775789Sahrens 
776789Sahrens 	config = spa_tryimport(tryconfig);
777789Sahrens 
778789Sahrens 	nvlist_free(tryconfig);
779789Sahrens 
780789Sahrens 	if (config == NULL)
781789Sahrens 		return (EINVAL);
782789Sahrens 
7832676Seschrock 	error = put_nvlist(zc, config);
784789Sahrens 	nvlist_free(config);
785789Sahrens 
786789Sahrens 	return (error);
787789Sahrens }
788789Sahrens 
789789Sahrens static int
790789Sahrens zfs_ioc_pool_scrub(zfs_cmd_t *zc)
791789Sahrens {
792789Sahrens 	spa_t *spa;
793789Sahrens 	int error;
794789Sahrens 
7952926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
7962926Sek110237 		return (error);
7972926Sek110237 
7984451Seschrock 	spa_config_enter(spa, RW_READER, FTAG);
7992926Sek110237 	error = spa_scrub(spa, zc->zc_cookie, B_FALSE);
8004451Seschrock 	spa_config_exit(spa, FTAG);
8012926Sek110237 
8022926Sek110237 	spa_close(spa, FTAG);
8032926Sek110237 
804789Sahrens 	return (error);
805789Sahrens }
806789Sahrens 
807789Sahrens static int
808789Sahrens zfs_ioc_pool_freeze(zfs_cmd_t *zc)
809789Sahrens {
810789Sahrens 	spa_t *spa;
811789Sahrens 	int error;
812789Sahrens 
813789Sahrens 	error = spa_open(zc->zc_name, &spa, FTAG);
814789Sahrens 	if (error == 0) {
815789Sahrens 		spa_freeze(spa);
816789Sahrens 		spa_close(spa, FTAG);
817789Sahrens 	}
818789Sahrens 	return (error);
819789Sahrens }
820789Sahrens 
821789Sahrens static int
8221760Seschrock zfs_ioc_pool_upgrade(zfs_cmd_t *zc)
8231760Seschrock {
8241760Seschrock 	spa_t *spa;
8251760Seschrock 	int error;
8261760Seschrock 
8272926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
8282926Sek110237 		return (error);
8292926Sek110237 
8302926Sek110237 	spa_upgrade(spa);
8312926Sek110237 	spa_close(spa, FTAG);
8322926Sek110237 
8332926Sek110237 	return (error);
8342926Sek110237 }
8352926Sek110237 
8362926Sek110237 static int
8372926Sek110237 zfs_ioc_pool_get_history(zfs_cmd_t *zc)
8382926Sek110237 {
8392926Sek110237 	spa_t *spa;
8402926Sek110237 	char *hist_buf;
8412926Sek110237 	uint64_t size;
8422926Sek110237 	int error;
8432926Sek110237 
8442926Sek110237 	if ((size = zc->zc_history_len) == 0)
8452926Sek110237 		return (EINVAL);
8462926Sek110237 
8472926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
8482926Sek110237 		return (error);
8492926Sek110237 
8503863Sek110237 	if (spa_version(spa) < ZFS_VERSION_ZPOOL_HISTORY) {
8513863Sek110237 		spa_close(spa, FTAG);
8523863Sek110237 		return (ENOTSUP);
8533863Sek110237 	}
8543863Sek110237 
8552926Sek110237 	hist_buf = kmem_alloc(size, KM_SLEEP);
8562926Sek110237 	if ((error = spa_history_get(spa, &zc->zc_history_offset,
8572926Sek110237 	    &zc->zc_history_len, hist_buf)) == 0) {
858*4543Smarks 		error = xcopyout(hist_buf,
859*4543Smarks 		    (char *)(uintptr_t)zc->zc_history,
8602926Sek110237 		    zc->zc_history_len);
8612926Sek110237 	}
8622926Sek110237 
8632926Sek110237 	spa_close(spa, FTAG);
8642926Sek110237 	kmem_free(hist_buf, size);
8652926Sek110237 	return (error);
8662926Sek110237 }
8672926Sek110237 
8682926Sek110237 static int
8693444Sek110237 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc)
8703444Sek110237 {
8713444Sek110237 	int error;
8723444Sek110237 
8733912Slling 	if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value))
8743444Sek110237 		return (error);
8753444Sek110237 
8763444Sek110237 	return (0);
8773444Sek110237 }
8783444Sek110237 
8793444Sek110237 static int
8803444Sek110237 zfs_ioc_obj_to_path(zfs_cmd_t *zc)
8813444Sek110237 {
8823444Sek110237 	objset_t *osp;
8833444Sek110237 	int error;
8843444Sek110237 
8853444Sek110237 	if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS,
8863444Sek110237 	    DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0)
8873444Sek110237 		return (error);
8883444Sek110237 
8893444Sek110237 	error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value,
8903444Sek110237 	    sizeof (zc->zc_value));
8913444Sek110237 	dmu_objset_close(osp);
8923444Sek110237 
8933444Sek110237 	return (error);
8943444Sek110237 }
8953444Sek110237 
8963444Sek110237 static int
897789Sahrens zfs_ioc_vdev_add(zfs_cmd_t *zc)
898789Sahrens {
899789Sahrens 	spa_t *spa;
900789Sahrens 	int error;
901789Sahrens 	nvlist_t *config;
902789Sahrens 
903789Sahrens 	error = spa_open(zc->zc_name, &spa, FTAG);
904789Sahrens 	if (error != 0)
905789Sahrens 		return (error);
906789Sahrens 
9073912Slling 	/*
9083912Slling 	 * A root pool with concatenated devices is not supported.
9093912Slling 	 * Thus, can not add a device to a root pool with one device.
9103912Slling 	 */
9113912Slling 	if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) {
9123912Slling 		spa_close(spa, FTAG);
9133912Slling 		return (EDOM);
9143912Slling 	}
9153912Slling 
9162676Seschrock 	if ((error = get_nvlist(zc, &config)) == 0) {
917789Sahrens 		error = spa_vdev_add(spa, config);
918789Sahrens 		nvlist_free(config);
919789Sahrens 	}
920789Sahrens 	spa_close(spa, FTAG);
921789Sahrens 	return (error);
922789Sahrens }
923789Sahrens 
924789Sahrens static int
925789Sahrens zfs_ioc_vdev_remove(zfs_cmd_t *zc)
926789Sahrens {
9272082Seschrock 	spa_t *spa;
9282082Seschrock 	int error;
9292082Seschrock 
9302082Seschrock 	error = spa_open(zc->zc_name, &spa, FTAG);
9312082Seschrock 	if (error != 0)
9322082Seschrock 		return (error);
9332082Seschrock 	error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE);
9342082Seschrock 	spa_close(spa, FTAG);
9352082Seschrock 	return (error);
936789Sahrens }
937789Sahrens 
938789Sahrens static int
9394451Seschrock zfs_ioc_vdev_set_state(zfs_cmd_t *zc)
940789Sahrens {
941789Sahrens 	spa_t *spa;
942789Sahrens 	int error;
9434451Seschrock 	vdev_state_t newstate = VDEV_STATE_UNKNOWN;
944789Sahrens 
9452926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
946789Sahrens 		return (error);
9474451Seschrock 	switch (zc->zc_cookie) {
9484451Seschrock 	case VDEV_STATE_ONLINE:
9494451Seschrock 		error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate);
9504451Seschrock 		break;
9514451Seschrock 
9524451Seschrock 	case VDEV_STATE_OFFLINE:
9534451Seschrock 		error = vdev_offline(spa, zc->zc_guid, zc->zc_obj);
9544451Seschrock 		break;
955789Sahrens 
9564451Seschrock 	case VDEV_STATE_FAULTED:
9574451Seschrock 		error = vdev_fault(spa, zc->zc_guid);
9584451Seschrock 		break;
959789Sahrens 
9604451Seschrock 	case VDEV_STATE_DEGRADED:
9614451Seschrock 		error = vdev_degrade(spa, zc->zc_guid);
9624451Seschrock 		break;
9634451Seschrock 
9644451Seschrock 	default:
9654451Seschrock 		error = EINVAL;
9664451Seschrock 	}
9674451Seschrock 	zc->zc_cookie = newstate;
968789Sahrens 	spa_close(spa, FTAG);
969789Sahrens 	return (error);
970789Sahrens }
971789Sahrens 
972789Sahrens static int
973789Sahrens zfs_ioc_vdev_attach(zfs_cmd_t *zc)
974789Sahrens {
975789Sahrens 	spa_t *spa;
976789Sahrens 	int replacing = zc->zc_cookie;
977789Sahrens 	nvlist_t *config;
978789Sahrens 	int error;
979789Sahrens 
9802926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
981789Sahrens 		return (error);
982789Sahrens 
9832676Seschrock 	if ((error = get_nvlist(zc, &config)) == 0) {
9841544Seschrock 		error = spa_vdev_attach(spa, zc->zc_guid, config, replacing);
985789Sahrens 		nvlist_free(config);
986789Sahrens 	}
987789Sahrens 
988789Sahrens 	spa_close(spa, FTAG);
989789Sahrens 	return (error);
990789Sahrens }
991789Sahrens 
992789Sahrens static int
993789Sahrens zfs_ioc_vdev_detach(zfs_cmd_t *zc)
994789Sahrens {
995789Sahrens 	spa_t *spa;
996789Sahrens 	int error;
997789Sahrens 
9982926Sek110237 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
999789Sahrens 		return (error);
1000789Sahrens 
10011544Seschrock 	error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE);
1002789Sahrens 
1003789Sahrens 	spa_close(spa, FTAG);
1004789Sahrens 	return (error);
1005789Sahrens }
1006789Sahrens 
1007789Sahrens static int
10081354Seschrock zfs_ioc_vdev_setpath(zfs_cmd_t *zc)
10091354Seschrock {
10101354Seschrock 	spa_t *spa;
10112676Seschrock 	char *path = zc->zc_value;
10121544Seschrock 	uint64_t guid = zc->zc_guid;
10131354Seschrock 	int error;
10141354Seschrock 
10151354Seschrock 	error = spa_open(zc->zc_name, &spa, FTAG);
10161354Seschrock 	if (error != 0)
10171354Seschrock 		return (error);
10181354Seschrock 
10191354Seschrock 	error = spa_vdev_setpath(spa, guid, path);
10201354Seschrock 	spa_close(spa, FTAG);
10211354Seschrock 	return (error);
10221354Seschrock }
10231354Seschrock 
10241354Seschrock static int
1025789Sahrens zfs_ioc_objset_stats(zfs_cmd_t *zc)
1026789Sahrens {
1027789Sahrens 	objset_t *os = NULL;
1028789Sahrens 	int error;
10291356Seschrock 	nvlist_t *nv;
1030789Sahrens 
1031789Sahrens retry:
1032789Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1033789Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1034789Sahrens 	if (error != 0) {
1035789Sahrens 		/*
1036789Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1037789Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1038789Sahrens 		 * only for a short while, so we retry here.
1039789Sahrens 		 * This avoids user code having to handle EBUSY,
1040789Sahrens 		 * for example for a "zfs list".
1041789Sahrens 		 */
1042789Sahrens 		if (error == EBUSY) {
1043789Sahrens 			delay(1);
1044789Sahrens 			goto retry;
1045789Sahrens 		}
1046789Sahrens 		return (error);
1047789Sahrens 	}
1048789Sahrens 
10492885Sahrens 	dmu_objset_fast_stat(os, &zc->zc_objset_stats);
1050789Sahrens 
10512856Snd150628 	if (zc->zc_nvlist_dst != 0 &&
10521356Seschrock 	    (error = dsl_prop_get_all(os, &nv)) == 0) {
10532885Sahrens 		dmu_objset_stats(os, nv);
10543087Sahrens 		/*
10553087Sahrens 		 * NB: zvol_get_stats() will read the objset contents,
10563087Sahrens 		 * which we aren't supposed to do with a
10573087Sahrens 		 * DS_MODE_STANDARD open, because it could be
10583087Sahrens 		 * inconsistent.  So this is a bit of a workaround...
10593087Sahrens 		 */
10603087Sahrens 		if (!zc->zc_objset_stats.dds_inconsistent &&
10613087Sahrens 		    dmu_objset_type(os) == DMU_OST_ZVOL)
10622885Sahrens 			VERIFY(zvol_get_stats(os, nv) == 0);
10632676Seschrock 		error = put_nvlist(zc, nv);
10641356Seschrock 		nvlist_free(nv);
10651356Seschrock 	}
1066789Sahrens 
10672676Seschrock 	spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value));
10681544Seschrock 
1069789Sahrens 	dmu_objset_close(os);
1070789Sahrens 	return (error);
1071789Sahrens }
1072789Sahrens 
1073789Sahrens static int
1074789Sahrens zfs_ioc_dataset_list_next(zfs_cmd_t *zc)
1075789Sahrens {
1076885Sahrens 	objset_t *os;
1077789Sahrens 	int error;
1078789Sahrens 	char *p;
1079789Sahrens 
1080885Sahrens retry:
1081885Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1082885Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1083885Sahrens 	if (error != 0) {
1084885Sahrens 		/*
1085885Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1086885Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1087885Sahrens 		 * only for a short while, so we retry here.
1088885Sahrens 		 * This avoids user code having to handle EBUSY,
1089885Sahrens 		 * for example for a "zfs list".
1090885Sahrens 		 */
1091885Sahrens 		if (error == EBUSY) {
1092885Sahrens 			delay(1);
1093885Sahrens 			goto retry;
1094885Sahrens 		}
1095885Sahrens 		if (error == ENOENT)
1096885Sahrens 			error = ESRCH;
1097885Sahrens 		return (error);
1098789Sahrens 	}
1099789Sahrens 
1100789Sahrens 	p = strrchr(zc->zc_name, '/');
1101789Sahrens 	if (p == NULL || p[1] != '\0')
1102789Sahrens 		(void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name));
1103789Sahrens 	p = zc->zc_name + strlen(zc->zc_name);
1104789Sahrens 
1105789Sahrens 	do {
1106885Sahrens 		error = dmu_dir_list_next(os,
1107885Sahrens 		    sizeof (zc->zc_name) - (p - zc->zc_name), p,
1108885Sahrens 		    NULL, &zc->zc_cookie);
1109789Sahrens 		if (error == ENOENT)
1110789Sahrens 			error = ESRCH;
1111885Sahrens 	} while (error == 0 && !INGLOBALZONE(curproc) &&
1112789Sahrens 	    !zone_dataset_visible(zc->zc_name, NULL));
1113789Sahrens 
1114885Sahrens 	/*
1115885Sahrens 	 * If it's a hidden dataset (ie. with a '$' in its name), don't
1116885Sahrens 	 * try to get stats for it.  Userland will skip over it.
1117885Sahrens 	 */
1118885Sahrens 	if (error == 0 && strchr(zc->zc_name, '$') == NULL)
1119885Sahrens 		error = zfs_ioc_objset_stats(zc); /* fill in the stats */
1120789Sahrens 
1121885Sahrens 	dmu_objset_close(os);
1122789Sahrens 	return (error);
1123789Sahrens }
1124789Sahrens 
1125789Sahrens static int
1126789Sahrens zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
1127789Sahrens {
1128885Sahrens 	objset_t *os;
1129789Sahrens 	int error;
1130789Sahrens 
1131789Sahrens retry:
1132885Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1133885Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &os);
1134885Sahrens 	if (error != 0) {
1135789Sahrens 		/*
1136885Sahrens 		 * This is ugly: dmu_objset_open() can return EBUSY if
1137789Sahrens 		 * the objset is held exclusively. Fortunately this hold is
1138789Sahrens 		 * only for a short while, so we retry here.
1139789Sahrens 		 * This avoids user code having to handle EBUSY,
1140885Sahrens 		 * for example for a "zfs list".
1141789Sahrens 		 */
1142789Sahrens 		if (error == EBUSY) {
1143789Sahrens 			delay(1);
1144789Sahrens 			goto retry;
1145789Sahrens 		}
1146789Sahrens 		if (error == ENOENT)
1147885Sahrens 			error = ESRCH;
1148789Sahrens 		return (error);
1149789Sahrens 	}
1150789Sahrens 
11511003Slling 	/*
11521003Slling 	 * A dataset name of maximum length cannot have any snapshots,
11531003Slling 	 * so exit immediately.
11541003Slling 	 */
11551003Slling 	if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) {
1156885Sahrens 		dmu_objset_close(os);
11571003Slling 		return (ESRCH);
1158789Sahrens 	}
1159789Sahrens 
1160885Sahrens 	error = dmu_snapshot_list_next(os,
1161885Sahrens 	    sizeof (zc->zc_name) - strlen(zc->zc_name),
1162885Sahrens 	    zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie);
1163789Sahrens 	if (error == ENOENT)
1164789Sahrens 		error = ESRCH;
1165789Sahrens 
1166885Sahrens 	if (error == 0)
1167885Sahrens 		error = zfs_ioc_objset_stats(zc); /* fill in the stats */
1168789Sahrens 
1169885Sahrens 	dmu_objset_close(os);
1170789Sahrens 	return (error);
1171789Sahrens }
1172789Sahrens 
1173789Sahrens static int
11742676Seschrock zfs_set_prop_nvlist(const char *name, dev_t dev, cred_t *cr, nvlist_t *nvl)
1175789Sahrens {
11762676Seschrock 	nvpair_t *elem;
11772676Seschrock 	int error;
11782676Seschrock 	const char *propname;
11792676Seschrock 	zfs_prop_t prop;
11802676Seschrock 	uint64_t intval;
11812676Seschrock 	char *strval;
11822676Seschrock 
1183*4543Smarks 	/*
1184*4543Smarks 	 * First validate permission to set all of the properties
1185*4543Smarks 	 */
11862676Seschrock 	elem = NULL;
11872676Seschrock 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
11882676Seschrock 		propname = nvpair_name(elem);
11892676Seschrock 
11902676Seschrock 		if ((prop = zfs_name_to_prop(propname)) ==
11912676Seschrock 		    ZFS_PROP_INVAL) {
11922676Seschrock 			/*
11932676Seschrock 			 * If this is a user-defined property, it must be a
11942676Seschrock 			 * string, and there is no further validation to do.
11952676Seschrock 			 */
11962676Seschrock 			if (!zfs_prop_user(propname) ||
11972676Seschrock 			    nvpair_type(elem) != DATA_TYPE_STRING)
11982676Seschrock 				return (EINVAL);
11992676Seschrock 
1200*4543Smarks 			error = zfs_secpolicy_write_perms(name,
1201*4543Smarks 			    ZFS_DELEG_PERM_USERPROP, cr);
1202*4543Smarks 			if (error) {
1203*4543Smarks 				return (EPERM);
1204*4543Smarks 			}
1205*4543Smarks 			continue;
12062676Seschrock 		}
12072676Seschrock 
12082676Seschrock 		/*
1209*4543Smarks 		 * Check permissions for special properties
12102676Seschrock 		 */
1211*4543Smarks 
12122676Seschrock 		switch (prop) {
12132676Seschrock 		case ZFS_PROP_ZONED:
12142676Seschrock 			/*
12152676Seschrock 			 * Disallow setting of 'zoned' from within a local zone.
12162676Seschrock 			 */
12172676Seschrock 			if (!INGLOBALZONE(curproc))
12182676Seschrock 				return (EPERM);
12192676Seschrock 			break;
12202676Seschrock 
12212676Seschrock 		case ZFS_PROP_QUOTA:
12222676Seschrock 			if (error = zfs_dozonecheck(name, cr))
12232676Seschrock 				return (error);
12242676Seschrock 
12252676Seschrock 			if (!INGLOBALZONE(curproc)) {
12262676Seschrock 				uint64_t zoned;
12272676Seschrock 				char setpoint[MAXNAMELEN];
12282676Seschrock 				int dslen;
12292676Seschrock 				/*
12302676Seschrock 				 * Unprivileged users are allowed to modify the
12312676Seschrock 				 * quota on things *under* (ie. contained by)
12322676Seschrock 				 * the thing they own.
12332676Seschrock 				 */
12342676Seschrock 				if (dsl_prop_get_integer(name, "zoned", &zoned,
12352676Seschrock 				    setpoint))
12362676Seschrock 					return (EPERM);
12372676Seschrock 				if (!zoned) /* this shouldn't happen */
12382676Seschrock 					return (EPERM);
12392676Seschrock 				dslen = strlen(name);
12402676Seschrock 				if (dslen <= strlen(setpoint))
12412676Seschrock 					return (EPERM);
12422676Seschrock 			}
12433886Sahl 			break;
12443886Sahl 
12453886Sahl 		case ZFS_PROP_COMPRESSION:
12463886Sahl 			/*
12473886Sahl 			 * If the user specified gzip compression, make sure
12483886Sahl 			 * the SPA supports it. We ignore any errors here since
12493886Sahl 			 * we'll catch them later.
12503886Sahl 			 */
12513886Sahl 			if (nvpair_type(elem) == DATA_TYPE_UINT64 &&
12523886Sahl 			    nvpair_value_uint64(elem, &intval) == 0 &&
12533886Sahl 			    intval >= ZIO_COMPRESS_GZIP_1 &&
12543886Sahl 			    intval <= ZIO_COMPRESS_GZIP_9) {
1255*4543Smarks 				char buf[MAXNAMELEN];
1256*4543Smarks 				spa_t *spa;
1257*4543Smarks 				const char *p;
1258*4543Smarks 
12593886Sahl 				if ((p = strchr(name, '/')) == NULL) {
12603886Sahl 					p = name;
12613886Sahl 				} else {
12623886Sahl 					bcopy(name, buf, p - name);
12633886Sahl 					buf[p - name] = '\0';
12643886Sahl 					p = buf;
12653886Sahl 				}
12663886Sahl 
12673886Sahl 				if (spa_open(p, &spa, FTAG) == 0) {
12683886Sahl 					if (spa_version(spa) <
12693886Sahl 					    ZFS_VERSION_GZIP_COMPRESSION) {
12703886Sahl 						spa_close(spa, FTAG);
12713886Sahl 						return (ENOTSUP);
12723886Sahl 					}
12733886Sahl 
12743886Sahl 					spa_close(spa, FTAG);
12753886Sahl 				}
12763886Sahl 			}
12773886Sahl 			break;
12782676Seschrock 		}
1279*4543Smarks 		if ((error = zfs_secpolicy_setprop(name, prop, cr)) != 0)
1280*4543Smarks 			return (error);
1281*4543Smarks 	}
1282*4543Smarks 
1283*4543Smarks 	elem = NULL;
1284*4543Smarks 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
1285*4543Smarks 		propname = nvpair_name(elem);
1286*4543Smarks 
1287*4543Smarks 		if ((prop = zfs_name_to_prop(propname)) ==
1288*4543Smarks 		    ZFS_PROP_INVAL) {
1289*4543Smarks 
1290*4543Smarks 			VERIFY(nvpair_value_string(elem, &strval) == 0);
1291*4543Smarks 			error = dsl_prop_set(name, propname, 1,
1292*4543Smarks 			    strlen(strval) + 1, strval);
1293*4543Smarks 			if (error == 0)
1294*4543Smarks 				continue;
1295*4543Smarks 			else
1296*4543Smarks 				return (error);
1297*4543Smarks 		}
12982676Seschrock 
12992676Seschrock 		switch (prop) {
13002676Seschrock 		case ZFS_PROP_QUOTA:
13012676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
13022676Seschrock 			    (error = dsl_dir_set_quota(name,
13032676Seschrock 			    intval)) != 0)
13042676Seschrock 				return (error);
13052676Seschrock 			break;
13062676Seschrock 
13072676Seschrock 		case ZFS_PROP_RESERVATION:
13082676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
13092676Seschrock 			    (error = dsl_dir_set_reservation(name,
13102676Seschrock 			    intval)) != 0)
13112676Seschrock 				return (error);
13122676Seschrock 			break;
1313789Sahrens 
13142676Seschrock 		case ZFS_PROP_VOLSIZE:
13152676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
13162676Seschrock 			    (error = zvol_set_volsize(name, dev,
13172676Seschrock 			    intval)) != 0)
13182676Seschrock 				return (error);
13192676Seschrock 			break;
13202676Seschrock 
13212676Seschrock 		case ZFS_PROP_VOLBLOCKSIZE:
13222676Seschrock 			if ((error = nvpair_value_uint64(elem, &intval)) != 0 ||
13232676Seschrock 			    (error = zvol_set_volblocksize(name,
13242676Seschrock 			    intval)) != 0)
13252676Seschrock 				return (error);
13262676Seschrock 			break;
13272676Seschrock 
13282676Seschrock 		default:
13292676Seschrock 			if (nvpair_type(elem) == DATA_TYPE_STRING) {
13302676Seschrock 				if (zfs_prop_get_type(prop) !=
13312676Seschrock 				    prop_type_string)
13322676Seschrock 					return (EINVAL);
13332717Seschrock 				VERIFY(nvpair_value_string(elem, &strval) == 0);
13342717Seschrock 				if ((error = dsl_prop_set(name,
13352676Seschrock 				    nvpair_name(elem), 1, strlen(strval) + 1,
13362717Seschrock 				    strval)) != 0)
13372717Seschrock 					return (error);
13382676Seschrock 			} else if (nvpair_type(elem) == DATA_TYPE_UINT64) {
13392885Sahrens 				const char *unused;
13402885Sahrens 
13412717Seschrock 				VERIFY(nvpair_value_uint64(elem, &intval) == 0);
13422676Seschrock 
13432676Seschrock 				switch (zfs_prop_get_type(prop)) {
13442676Seschrock 				case prop_type_number:
13452676Seschrock 					break;
13462676Seschrock 				case prop_type_boolean:
13472676Seschrock 					if (intval > 1)
13482717Seschrock 						return (EINVAL);
13492676Seschrock 					break;
13502676Seschrock 				case prop_type_string:
13512717Seschrock 					return (EINVAL);
13522676Seschrock 				case prop_type_index:
13532717Seschrock 					if (zfs_prop_index_to_string(prop,
13542717Seschrock 					    intval, &unused) != 0)
13552717Seschrock 						return (EINVAL);
13562676Seschrock 					break;
13572676Seschrock 				default:
13582676Seschrock 					cmn_err(CE_PANIC, "unknown property "
13592676Seschrock 					    "type");
13602676Seschrock 					break;
13612676Seschrock 				}
13622676Seschrock 
13632717Seschrock 				if ((error = dsl_prop_set(name, propname,
13642717Seschrock 				    8, 1, &intval)) != 0)
13652717Seschrock 					return (error);
13662676Seschrock 			} else {
13672676Seschrock 				return (EINVAL);
13682676Seschrock 			}
13692676Seschrock 			break;
13702676Seschrock 		}
13712676Seschrock 	}
13722676Seschrock 
13732676Seschrock 	return (0);
1374789Sahrens }
1375789Sahrens 
1376789Sahrens static int
13772676Seschrock zfs_ioc_set_prop(zfs_cmd_t *zc)
1378789Sahrens {
13792676Seschrock 	nvlist_t *nvl;
13802676Seschrock 	int error;
13812676Seschrock 	zfs_prop_t prop;
1382789Sahrens 
13832676Seschrock 	/*
13842676Seschrock 	 * If zc_value is set, then this is an attempt to inherit a value.
13852676Seschrock 	 * Otherwise, zc_nvlist refers to a list of properties to set.
13862676Seschrock 	 */
13872676Seschrock 	if (zc->zc_value[0] != '\0') {
13882676Seschrock 		if (!zfs_prop_user(zc->zc_value) &&
13892676Seschrock 		    ((prop = zfs_name_to_prop(zc->zc_value)) ==
13902676Seschrock 		    ZFS_PROP_INVAL ||
13912676Seschrock 		    !zfs_prop_inheritable(prop)))
13922676Seschrock 			return (EINVAL);
13932676Seschrock 
13942676Seschrock 		return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL));
13952676Seschrock 	}
13962676Seschrock 
13972676Seschrock 	if ((error = get_nvlist(zc, &nvl)) != 0)
13982676Seschrock 		return (error);
13992676Seschrock 
14002676Seschrock 	error = zfs_set_prop_nvlist(zc->zc_name, zc->zc_dev,
14012676Seschrock 	    (cred_t *)(uintptr_t)zc->zc_cred, nvl);
1402*4543Smarks 
14032676Seschrock 	nvlist_free(nvl);
14042676Seschrock 	return (error);
1405789Sahrens }
1406789Sahrens 
1407789Sahrens static int
14084098Slling zfs_ioc_pool_set_props(zfs_cmd_t *zc)
14093912Slling {
14103912Slling 	nvlist_t *nvl;
14113912Slling 	int error, reset_bootfs = 0;
14123912Slling 	uint64_t objnum;
1413*4543Smarks 	uint64_t intval;
14143912Slling 	zpool_prop_t prop;
14153912Slling 	nvpair_t *elem;
14163912Slling 	char *propname, *strval;
14173912Slling 	spa_t *spa;
14183912Slling 	vdev_t *rvdev;
14193912Slling 	char *vdev_type;
14203912Slling 	objset_t *os;
14213912Slling 
14223912Slling 	if ((error = get_nvlist(zc, &nvl)) != 0)
14233912Slling 		return (error);
14243912Slling 
14253912Slling 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
14263912Slling 		nvlist_free(nvl);
14273912Slling 		return (error);
14283912Slling 	}
14293912Slling 
14303912Slling 	if (spa_version(spa) < ZFS_VERSION_BOOTFS) {
14313912Slling 		nvlist_free(nvl);
14323912Slling 		spa_close(spa, FTAG);
14333912Slling 		return (ENOTSUP);
14343912Slling 	}
14353912Slling 
14363912Slling 	elem = NULL;
14373912Slling 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
14383912Slling 
14393912Slling 		propname = nvpair_name(elem);
14403912Slling 
14413912Slling 		if ((prop = zpool_name_to_prop(propname)) ==
14423912Slling 		    ZFS_PROP_INVAL) {
14433912Slling 			nvlist_free(nvl);
14443912Slling 			spa_close(spa, FTAG);
14453912Slling 			return (EINVAL);
14463912Slling 		}
14473912Slling 
14483912Slling 		switch (prop) {
1449*4543Smarks 		case ZPOOL_PROP_DELEGATION:
1450*4543Smarks 			VERIFY(nvpair_value_uint64(elem, &intval) == 0);
1451*4543Smarks 			if (intval > 1)
1452*4543Smarks 				error = EINVAL;
1453*4543Smarks 			break;
14544451Seschrock 		case ZPOOL_PROP_BOOTFS:
14553912Slling 			/*
14563912Slling 			 * A bootable filesystem can not be on a RAIDZ pool
14573912Slling 			 * nor a striped pool with more than 1 device.
14583912Slling 			 */
14593912Slling 			rvdev = spa->spa_root_vdev;
14603912Slling 			vdev_type =
14613912Slling 			    rvdev->vdev_child[0]->vdev_ops->vdev_op_type;
14623912Slling 			if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 ||
14633912Slling 			    (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 &&
14643912Slling 			    rvdev->vdev_children > 1)) {
14653912Slling 				error = ENOTSUP;
14663912Slling 				break;
14673912Slling 			}
14683912Slling 
14693912Slling 			reset_bootfs = 1;
14703912Slling 
14713912Slling 			VERIFY(nvpair_value_string(elem, &strval) == 0);
14723912Slling 			if (strval == NULL || strval[0] == '\0') {
14734451Seschrock 				objnum = zpool_prop_default_numeric(
14744451Seschrock 				    ZPOOL_PROP_BOOTFS);
14753912Slling 				break;
14763912Slling 			}
14773912Slling 
14783912Slling 			if (error = dmu_objset_open(strval, DMU_OST_ZFS,
14793912Slling 			    DS_MODE_STANDARD | DS_MODE_READONLY, &os))
14803912Slling 				break;
14813912Slling 			objnum = dmu_objset_id(os);
14823912Slling 			dmu_objset_close(os);
14833912Slling 			break;
14843912Slling 		}
14853912Slling 
14863912Slling 		if (error)
14873912Slling 			break;
14883912Slling 	}
14893912Slling 	if (error == 0) {
14903912Slling 		if (reset_bootfs) {
14913912Slling 			VERIFY(nvlist_remove(nvl,
14924451Seschrock 			    zpool_prop_to_name(ZPOOL_PROP_BOOTFS),
14933912Slling 			    DATA_TYPE_STRING) == 0);
14943912Slling 			VERIFY(nvlist_add_uint64(nvl,
14954451Seschrock 			    zpool_prop_to_name(ZPOOL_PROP_BOOTFS),
14964451Seschrock 			    objnum) == 0);
14973912Slling 		}
14983912Slling 		error = spa_set_props(spa, nvl);
14993912Slling 	}
15003912Slling 
15013912Slling 	nvlist_free(nvl);
15023912Slling 	spa_close(spa, FTAG);
15033912Slling 
15043912Slling 	return (error);
15053912Slling }
15063912Slling 
15073912Slling static int
15084098Slling zfs_ioc_pool_get_props(zfs_cmd_t *zc)
15093912Slling {
15103912Slling 	spa_t *spa;
15113912Slling 	int error;
15123912Slling 	nvlist_t *nvp = NULL;
15133912Slling 
15143912Slling 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
15153912Slling 		return (error);
15163912Slling 
15173912Slling 	error = spa_get_props(spa, &nvp);
15183912Slling 
15193912Slling 	if (error == 0 && zc->zc_nvlist_dst != NULL)
15203912Slling 		error = put_nvlist(zc, nvp);
15213912Slling 	else
15223912Slling 		error = EFAULT;
15233912Slling 
15243912Slling 	spa_close(spa, FTAG);
15253912Slling 
15263912Slling 	if (nvp)
15273912Slling 		nvlist_free(nvp);
15283912Slling 	return (error);
15293912Slling }
15303912Slling 
15313912Slling static int
1532*4543Smarks zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc)
1533*4543Smarks {
1534*4543Smarks 	nvlist_t *nvp;
1535*4543Smarks 	int error;
1536*4543Smarks 	uint32_t uid;
1537*4543Smarks 	uint32_t gid;
1538*4543Smarks 	uint32_t *groups;
1539*4543Smarks 	uint_t group_cnt;
1540*4543Smarks 	cred_t	*usercred;
1541*4543Smarks 
1542*4543Smarks 	if ((error = get_nvlist(zc, &nvp)) != 0) {
1543*4543Smarks 		return (error);
1544*4543Smarks 	}
1545*4543Smarks 
1546*4543Smarks 	if ((error = nvlist_lookup_uint32(nvp,
1547*4543Smarks 	    ZFS_DELEG_PERM_UID, &uid)) != 0) {
1548*4543Smarks 		nvlist_free(nvp);
1549*4543Smarks 		return (EPERM);
1550*4543Smarks 	}
1551*4543Smarks 
1552*4543Smarks 	if ((error = nvlist_lookup_uint32(nvp,
1553*4543Smarks 	    ZFS_DELEG_PERM_GID, &gid)) != 0) {
1554*4543Smarks 		nvlist_free(nvp);
1555*4543Smarks 		return (EPERM);
1556*4543Smarks 	}
1557*4543Smarks 
1558*4543Smarks 	if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS,
1559*4543Smarks 	    &groups, &group_cnt)) != 0) {
1560*4543Smarks 		nvlist_free(nvp);
1561*4543Smarks 		return (EPERM);
1562*4543Smarks 	}
1563*4543Smarks 	usercred = cralloc();
1564*4543Smarks 	if ((crsetugid(usercred, uid, gid) != 0) ||
1565*4543Smarks 	    (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) {
1566*4543Smarks 		nvlist_free(nvp);
1567*4543Smarks 		crfree(usercred);
1568*4543Smarks 		return (EPERM);
1569*4543Smarks 	}
1570*4543Smarks 	nvlist_free(nvp);
1571*4543Smarks 	error = dsl_deleg_access(zc->zc_name,
1572*4543Smarks 	    ZFS_DELEG_PERM_SHAREISCSI, usercred);
1573*4543Smarks 	crfree(usercred);
1574*4543Smarks 	return (error);
1575*4543Smarks }
1576*4543Smarks 
1577*4543Smarks static int
1578*4543Smarks zfs_ioc_set_fsacl(zfs_cmd_t *zc)
1579*4543Smarks {
1580*4543Smarks 	int error;
1581*4543Smarks 	nvlist_t *fsaclnv = NULL;
1582*4543Smarks 	cred_t *cr;
1583*4543Smarks 
1584*4543Smarks 	if ((error = get_nvlist(zc, &fsaclnv)) != 0)
1585*4543Smarks 		return (error);
1586*4543Smarks 
1587*4543Smarks 	/*
1588*4543Smarks 	 * Verify nvlist is constructed correctly
1589*4543Smarks 	 */
1590*4543Smarks 	if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) {
1591*4543Smarks 		nvlist_free(fsaclnv);
1592*4543Smarks 		return (EINVAL);
1593*4543Smarks 	}
1594*4543Smarks 
1595*4543Smarks 	/*
1596*4543Smarks 	 * If we don't have PRIV_SYS_MOUNT, then validate
1597*4543Smarks 	 * that user is allowed to hand out each permission in
1598*4543Smarks 	 * the nvlist(s)
1599*4543Smarks 	 */
1600*4543Smarks 
1601*4543Smarks 	cr = (cred_t *)(uintptr_t)zc->zc_cred;
1602*4543Smarks 	error = secpolicy_zfs(cr);
1603*4543Smarks 	if (error) {
1604*4543Smarks 		if (zc->zc_perm_action == B_FALSE)
1605*4543Smarks 			error = dsl_deleg_can_allow(zc->zc_name, fsaclnv, cr);
1606*4543Smarks 		else
1607*4543Smarks 			error = dsl_deleg_can_unallow(zc->zc_name, fsaclnv, cr);
1608*4543Smarks 	}
1609*4543Smarks 
1610*4543Smarks 	if (error == 0)
1611*4543Smarks 		error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action);
1612*4543Smarks 
1613*4543Smarks 	nvlist_free(fsaclnv);
1614*4543Smarks 	return (error);
1615*4543Smarks }
1616*4543Smarks 
1617*4543Smarks static int
1618*4543Smarks zfs_ioc_get_fsacl(zfs_cmd_t *zc)
1619*4543Smarks {
1620*4543Smarks 	nvlist_t *nvp;
1621*4543Smarks 	int error;
1622*4543Smarks 
1623*4543Smarks 	if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) {
1624*4543Smarks 		error = put_nvlist(zc, nvp);
1625*4543Smarks 		nvlist_free(nvp);
1626*4543Smarks 	}
1627*4543Smarks 
1628*4543Smarks 	return (error);
1629*4543Smarks }
1630*4543Smarks 
1631*4543Smarks static int
1632789Sahrens zfs_ioc_create_minor(zfs_cmd_t *zc)
1633789Sahrens {
16342676Seschrock 	return (zvol_create_minor(zc->zc_name, zc->zc_dev));
1635789Sahrens }
1636789Sahrens 
1637789Sahrens static int
1638789Sahrens zfs_ioc_remove_minor(zfs_cmd_t *zc)
1639789Sahrens {
16402676Seschrock 	return (zvol_remove_minor(zc->zc_name));
1641789Sahrens }
1642789Sahrens 
1643789Sahrens /*
1644789Sahrens  * Search the vfs list for a specified resource.  Returns a pointer to it
1645789Sahrens  * or NULL if no suitable entry is found. The caller of this routine
1646789Sahrens  * is responsible for releasing the returned vfs pointer.
1647789Sahrens  */
1648789Sahrens static vfs_t *
1649789Sahrens zfs_get_vfs(const char *resource)
1650789Sahrens {
1651789Sahrens 	struct vfs *vfsp;
1652789Sahrens 	struct vfs *vfs_found = NULL;
1653789Sahrens 
1654789Sahrens 	vfs_list_read_lock();
1655789Sahrens 	vfsp = rootvfs;
1656789Sahrens 	do {
1657789Sahrens 		if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) {
1658789Sahrens 			VFS_HOLD(vfsp);
1659789Sahrens 			vfs_found = vfsp;
1660789Sahrens 			break;
1661789Sahrens 		}
1662789Sahrens 		vfsp = vfsp->vfs_next;
1663789Sahrens 	} while (vfsp != rootvfs);
1664789Sahrens 	vfs_list_unlock();
1665789Sahrens 	return (vfs_found);
1666789Sahrens }
1667789Sahrens 
1668*4543Smarks /* ARGSUSED */
1669789Sahrens static void
1670*4543Smarks zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
1671789Sahrens {
1672*4543Smarks 	zfs_create_fs(os, cr, tx);
1673789Sahrens }
1674789Sahrens 
1675789Sahrens static int
1676789Sahrens zfs_ioc_create(zfs_cmd_t *zc)
1677789Sahrens {
1678789Sahrens 	objset_t *clone;
1679789Sahrens 	int error = 0;
1680*4543Smarks 	nvlist_t *nvprops = NULL;
1681*4543Smarks 	void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
1682789Sahrens 	dmu_objset_type_t type = zc->zc_objset_type;
1683789Sahrens 
1684789Sahrens 	switch (type) {
1685789Sahrens 
1686789Sahrens 	case DMU_OST_ZFS:
1687789Sahrens 		cbfunc = zfs_create_cb;
1688789Sahrens 		break;
1689789Sahrens 
1690789Sahrens 	case DMU_OST_ZVOL:
1691789Sahrens 		cbfunc = zvol_create_cb;
1692789Sahrens 		break;
1693789Sahrens 
1694789Sahrens 	default:
16952199Sahrens 		cbfunc = NULL;
16962199Sahrens 	}
16972199Sahrens 	if (strchr(zc->zc_name, '@'))
1698789Sahrens 		return (EINVAL);
1699789Sahrens 
17002676Seschrock 	if (zc->zc_nvlist_src != NULL &&
1701*4543Smarks 	    (error = get_nvlist(zc, &nvprops)) != 0)
17022676Seschrock 		return (error);
17032676Seschrock 
17042676Seschrock 	if (zc->zc_value[0] != '\0') {
1705789Sahrens 		/*
1706789Sahrens 		 * We're creating a clone of an existing snapshot.
1707789Sahrens 		 */
17082676Seschrock 		zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
17092676Seschrock 		if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) {
1710*4543Smarks 			nvlist_free(nvprops);
1711789Sahrens 			return (EINVAL);
17122676Seschrock 		}
1713789Sahrens 
17142676Seschrock 		error = dmu_objset_open(zc->zc_value, type,
1715789Sahrens 		    DS_MODE_STANDARD | DS_MODE_READONLY, &clone);
17162676Seschrock 		if (error) {
1717*4543Smarks 			nvlist_free(nvprops);
1718789Sahrens 			return (error);
17192676Seschrock 		}
1720789Sahrens 		error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL);
1721789Sahrens 		dmu_objset_close(clone);
1722789Sahrens 	} else {
17232676Seschrock 		if (cbfunc == NULL) {
1724*4543Smarks 			nvlist_free(nvprops);
17252199Sahrens 			return (EINVAL);
17262676Seschrock 		}
17272676Seschrock 
1728789Sahrens 		if (type == DMU_OST_ZVOL) {
17292676Seschrock 			uint64_t volsize, volblocksize;
17302676Seschrock 
1731*4543Smarks 			if (nvprops == NULL ||
1732*4543Smarks 			    nvlist_lookup_uint64(nvprops,
17332676Seschrock 			    zfs_prop_to_name(ZFS_PROP_VOLSIZE),
17342676Seschrock 			    &volsize) != 0) {
1735*4543Smarks 				nvlist_free(nvprops);
17362676Seschrock 				return (EINVAL);
17372676Seschrock 			}
17382676Seschrock 
1739*4543Smarks 			if ((error = nvlist_lookup_uint64(nvprops,
17402676Seschrock 			    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
17412676Seschrock 			    &volblocksize)) != 0 && error != ENOENT) {
1742*4543Smarks 				nvlist_free(nvprops);
17432676Seschrock 				return (EINVAL);
17442676Seschrock 			}
17451133Seschrock 
17462676Seschrock 			if (error != 0)
17472676Seschrock 				volblocksize = zfs_prop_default_numeric(
17482676Seschrock 				    ZFS_PROP_VOLBLOCKSIZE);
17492676Seschrock 
17502676Seschrock 			if ((error = zvol_check_volblocksize(
17512676Seschrock 			    volblocksize)) != 0 ||
17522676Seschrock 			    (error = zvol_check_volsize(volsize,
17532676Seschrock 			    volblocksize)) != 0) {
1754*4543Smarks 				nvlist_free(nvprops);
1755789Sahrens 				return (error);
17562676Seschrock 			}
17572676Seschrock 		}
17581133Seschrock 
17592676Seschrock 		error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc,
1760*4543Smarks 		    nvprops);
1761789Sahrens 	}
17622676Seschrock 
17632676Seschrock 	/*
17642676Seschrock 	 * It would be nice to do this atomically.
17652676Seschrock 	 */
17662676Seschrock 	if (error == 0) {
17672676Seschrock 		if ((error = zfs_set_prop_nvlist(zc->zc_name,
17682676Seschrock 		    zc->zc_dev, (cred_t *)(uintptr_t)zc->zc_cred,
1769*4543Smarks 		    nvprops)) != 0)
17702676Seschrock 			(void) dmu_objset_destroy(zc->zc_name);
17712676Seschrock 	}
17722676Seschrock 
1773*4543Smarks 	nvlist_free(nvprops);
1774789Sahrens 	return (error);
1775789Sahrens }
1776789Sahrens 
1777789Sahrens static int
17782199Sahrens zfs_ioc_snapshot(zfs_cmd_t *zc)
17792199Sahrens {
17802676Seschrock 	if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
17812199Sahrens 		return (EINVAL);
17822199Sahrens 	return (dmu_objset_snapshot(zc->zc_name,
17832676Seschrock 	    zc->zc_value, zc->zc_cookie));
17842199Sahrens }
17852199Sahrens 
17864007Smmusante int
17872199Sahrens zfs_unmount_snap(char *name, void *arg)
1788789Sahrens {
17892199Sahrens 	char *snapname = arg;
17902199Sahrens 	char *cp;
17912417Sahrens 	vfs_t *vfsp = NULL;
17922199Sahrens 
17932199Sahrens 	/*
17942199Sahrens 	 * Snapshots (which are under .zfs control) must be unmounted
17952199Sahrens 	 * before they can be destroyed.
17962199Sahrens 	 */
17972199Sahrens 
17982199Sahrens 	if (snapname) {
17992199Sahrens 		(void) strcat(name, "@");
18002199Sahrens 		(void) strcat(name, snapname);
18012199Sahrens 		vfsp = zfs_get_vfs(name);
18022199Sahrens 		cp = strchr(name, '@');
18032199Sahrens 		*cp = '\0';
18042417Sahrens 	} else if (strchr(name, '@')) {
18052199Sahrens 		vfsp = zfs_get_vfs(name);
18062199Sahrens 	}
18072199Sahrens 
18082199Sahrens 	if (vfsp) {
18092199Sahrens 		/*
18102199Sahrens 		 * Always force the unmount for snapshots.
18112199Sahrens 		 */
18122199Sahrens 		int flag = MS_FORCE;
1813789Sahrens 		int err;
1814789Sahrens 
18152199Sahrens 		if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) {
18162199Sahrens 			VFS_RELE(vfsp);
18172199Sahrens 			return (err);
18182199Sahrens 		}
18192199Sahrens 		VFS_RELE(vfsp);
18202199Sahrens 		if ((err = dounmount(vfsp, flag, kcred)) != 0)
18212199Sahrens 			return (err);
18222199Sahrens 	}
18232199Sahrens 	return (0);
18242199Sahrens }
18252199Sahrens 
18262199Sahrens static int
18272199Sahrens zfs_ioc_destroy_snaps(zfs_cmd_t *zc)
18282199Sahrens {
18292199Sahrens 	int err;
1830789Sahrens 
18312676Seschrock 	if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
18322199Sahrens 		return (EINVAL);
18332199Sahrens 	err = dmu_objset_find(zc->zc_name,
18342676Seschrock 	    zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN);
18352199Sahrens 	if (err)
18362199Sahrens 		return (err);
18372676Seschrock 	return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value));
18382199Sahrens }
18392199Sahrens 
18402199Sahrens static int
18412199Sahrens zfs_ioc_destroy(zfs_cmd_t *zc)
18422199Sahrens {
18432199Sahrens 	if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) {
18442199Sahrens 		int err = zfs_unmount_snap(zc->zc_name, NULL);
18452199Sahrens 		if (err)
18462199Sahrens 			return (err);
1847789Sahrens 	}
1848789Sahrens 
1849789Sahrens 	return (dmu_objset_destroy(zc->zc_name));
1850789Sahrens }
1851789Sahrens 
1852789Sahrens static int
1853789Sahrens zfs_ioc_rollback(zfs_cmd_t *zc)
1854789Sahrens {
1855789Sahrens 	return (dmu_objset_rollback(zc->zc_name));
1856789Sahrens }
1857789Sahrens 
1858789Sahrens static int
1859789Sahrens zfs_ioc_rename(zfs_cmd_t *zc)
1860789Sahrens {
18614490Svb160487 	boolean_t recursive = zc->zc_cookie & 1;
18624007Smmusante 
18632676Seschrock 	zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
18642676Seschrock 	if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0)
1865789Sahrens 		return (EINVAL);
1866789Sahrens 
18674007Smmusante 	/*
18684007Smmusante 	 * Unmount snapshot unless we're doing a recursive rename,
18694007Smmusante 	 * in which case the dataset code figures out which snapshots
18704007Smmusante 	 * to unmount.
18714007Smmusante 	 */
18724007Smmusante 	if (!recursive && strchr(zc->zc_name, '@') != NULL &&
1873789Sahrens 	    zc->zc_objset_type == DMU_OST_ZFS) {
18742199Sahrens 		int err = zfs_unmount_snap(zc->zc_name, NULL);
18752199Sahrens 		if (err)
18762199Sahrens 			return (err);
1877789Sahrens 	}
1878789Sahrens 
18794007Smmusante 	return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive));
1880789Sahrens }
1881789Sahrens 
1882789Sahrens static int
1883789Sahrens zfs_ioc_recvbackup(zfs_cmd_t *zc)
1884789Sahrens {
1885789Sahrens 	file_t *fp;
1886789Sahrens 	int error, fd;
18872885Sahrens 	offset_t new_off;
1888789Sahrens 
18893265Sahrens 	if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
18903265Sahrens 	    strchr(zc->zc_value, '@') == NULL)
18913265Sahrens 		return (EINVAL);
18923265Sahrens 
1893789Sahrens 	fd = zc->zc_cookie;
1894789Sahrens 	fp = getf(fd);
1895789Sahrens 	if (fp == NULL)
1896789Sahrens 		return (EBADF);
18972676Seschrock 	error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record,
18982676Seschrock 	    &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode,
18992665Snd150628 	    fp->f_offset);
19002885Sahrens 
19012885Sahrens 	new_off = fp->f_offset + zc->zc_cookie;
19022885Sahrens 	if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0)
19032885Sahrens 		fp->f_offset = new_off;
19042885Sahrens 
1905789Sahrens 	releasef(fd);
1906789Sahrens 	return (error);
1907789Sahrens }
1908789Sahrens 
1909789Sahrens static int
1910789Sahrens zfs_ioc_sendbackup(zfs_cmd_t *zc)
1911789Sahrens {
1912789Sahrens 	objset_t *fromsnap = NULL;
1913789Sahrens 	objset_t *tosnap;
1914789Sahrens 	file_t *fp;
1915789Sahrens 	int error;
1916789Sahrens 
1917789Sahrens 	error = dmu_objset_open(zc->zc_name, DMU_OST_ANY,
1918789Sahrens 	    DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap);
1919789Sahrens 	if (error)
1920789Sahrens 		return (error);
1921789Sahrens 
19222676Seschrock 	if (zc->zc_value[0] != '\0') {
19232885Sahrens 		char buf[MAXPATHLEN];
19242885Sahrens 		char *cp;
19252885Sahrens 
19262885Sahrens 		(void) strncpy(buf, zc->zc_name, sizeof (buf));
19272885Sahrens 		cp = strchr(buf, '@');
19282885Sahrens 		if (cp)
19292885Sahrens 			*(cp+1) = 0;
19302885Sahrens 		(void) strncat(buf, zc->zc_value, sizeof (buf));
19312885Sahrens 		error = dmu_objset_open(buf, DMU_OST_ANY,
1932789Sahrens 		    DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap);
1933789Sahrens 		if (error) {
1934789Sahrens 			dmu_objset_close(tosnap);
1935789Sahrens 			return (error);
1936789Sahrens 		}
1937789Sahrens 	}
1938789Sahrens 
1939789Sahrens 	fp = getf(zc->zc_cookie);
1940789Sahrens 	if (fp == NULL) {
1941789Sahrens 		dmu_objset_close(tosnap);
1942789Sahrens 		if (fromsnap)
1943789Sahrens 			dmu_objset_close(fromsnap);
1944789Sahrens 		return (EBADF);
1945789Sahrens 	}
1946789Sahrens 
1947789Sahrens 	error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode);
1948789Sahrens 
1949789Sahrens 	releasef(zc->zc_cookie);
1950789Sahrens 	if (fromsnap)
1951789Sahrens 		dmu_objset_close(fromsnap);
1952789Sahrens 	dmu_objset_close(tosnap);
1953789Sahrens 	return (error);
1954789Sahrens }
1955789Sahrens 
19561544Seschrock static int
19571544Seschrock zfs_ioc_inject_fault(zfs_cmd_t *zc)
19581544Seschrock {
19591544Seschrock 	int id, error;
19601544Seschrock 
19611544Seschrock 	error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id,
19621544Seschrock 	    &zc->zc_inject_record);
19631544Seschrock 
19641544Seschrock 	if (error == 0)
19651544Seschrock 		zc->zc_guid = (uint64_t)id;
19661544Seschrock 
19671544Seschrock 	return (error);
19681544Seschrock }
19691544Seschrock 
19701544Seschrock static int
19711544Seschrock zfs_ioc_clear_fault(zfs_cmd_t *zc)
19721544Seschrock {
19731544Seschrock 	return (zio_clear_fault((int)zc->zc_guid));
19741544Seschrock }
19751544Seschrock 
19761544Seschrock static int
19771544Seschrock zfs_ioc_inject_list_next(zfs_cmd_t *zc)
19781544Seschrock {
19791544Seschrock 	int id = (int)zc->zc_guid;
19801544Seschrock 	int error;
19811544Seschrock 
19821544Seschrock 	error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name),
19831544Seschrock 	    &zc->zc_inject_record);
19841544Seschrock 
19851544Seschrock 	zc->zc_guid = id;
19861544Seschrock 
19871544Seschrock 	return (error);
19881544Seschrock }
19891544Seschrock 
19901544Seschrock static int
19911544Seschrock zfs_ioc_error_log(zfs_cmd_t *zc)
19921544Seschrock {
19931544Seschrock 	spa_t *spa;
19941544Seschrock 	int error;
19952676Seschrock 	size_t count = (size_t)zc->zc_nvlist_dst_size;
19961544Seschrock 
19971544Seschrock 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
19981544Seschrock 		return (error);
19991544Seschrock 
20002676Seschrock 	error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst,
20011544Seschrock 	    &count);
20021544Seschrock 	if (error == 0)
20032676Seschrock 		zc->zc_nvlist_dst_size = count;
20041544Seschrock 	else
20052676Seschrock 		zc->zc_nvlist_dst_size = spa_get_errlog_size(spa);
20061544Seschrock 
20071544Seschrock 	spa_close(spa, FTAG);
20081544Seschrock 
20091544Seschrock 	return (error);
20101544Seschrock }
20111544Seschrock 
20121544Seschrock static int
20131544Seschrock zfs_ioc_clear(zfs_cmd_t *zc)
20141544Seschrock {
20151544Seschrock 	spa_t *spa;
20161544Seschrock 	vdev_t *vd;
20171544Seschrock 	int error;
20184451Seschrock 	uint64_t txg;
20191544Seschrock 
20201544Seschrock 	if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
20211544Seschrock 		return (error);
20221544Seschrock 
20234451Seschrock 	txg = spa_vdev_enter(spa);
20241544Seschrock 
20252676Seschrock 	if (zc->zc_guid == 0) {
20261544Seschrock 		vd = NULL;
20272676Seschrock 	} else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) {
20284451Seschrock 		(void) spa_vdev_exit(spa, NULL, txg, ENODEV);
20291544Seschrock 		spa_close(spa, FTAG);
20301544Seschrock 		return (ENODEV);
20311544Seschrock 	}
20321544Seschrock 
20331544Seschrock 	vdev_clear(spa, vd);
20341544Seschrock 
20354451Seschrock 	(void) spa_vdev_exit(spa, NULL, txg, 0);
20361544Seschrock 
20371544Seschrock 	spa_close(spa, FTAG);
20381544Seschrock 
20391544Seschrock 	return (0);
20401544Seschrock }
20411544Seschrock 
20421544Seschrock static int
20432082Seschrock zfs_ioc_promote(zfs_cmd_t *zc)
20442082Seschrock {
20452417Sahrens 	char *cp;
20462417Sahrens 
20472417Sahrens 	/*
20482417Sahrens 	 * We don't need to unmount *all* the origin fs's snapshots, but
20492417Sahrens 	 * it's easier.
20502417Sahrens 	 */
20512676Seschrock 	cp = strchr(zc->zc_value, '@');
20522417Sahrens 	if (cp)
20532417Sahrens 		*cp = '\0';
20542676Seschrock 	(void) dmu_objset_find(zc->zc_value,
20552417Sahrens 	    zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS);
20562082Seschrock 	return (dsl_dataset_promote(zc->zc_name));
20572082Seschrock }
20582082Seschrock 
2059*4543Smarks /*
2060*4543Smarks  * We don't want to have a hard dependency
2061*4543Smarks  * against some special symbols in sharefs
2062*4543Smarks  * and nfs.  Determine them if needed when
2063*4543Smarks  * the first file system is shared.
2064*4543Smarks  * Neither sharefs or nfs are unloadable modules.
2065*4543Smarks  */
2066*4543Smarks int (*zexport_fs)(void *arg);
2067*4543Smarks int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t);
2068*4543Smarks 
2069*4543Smarks int zfs_share_inited;
2070*4543Smarks ddi_modhandle_t nfs_mod;
2071*4543Smarks ddi_modhandle_t sharefs_mod;
2072*4543Smarks kmutex_t zfs_share_lock;
2073*4543Smarks 
2074*4543Smarks static int
2075*4543Smarks zfs_ioc_share(zfs_cmd_t *zc)
2076*4543Smarks {
2077*4543Smarks 	int error;
2078*4543Smarks 	int opcode;
2079*4543Smarks 
2080*4543Smarks 	if (zfs_share_inited == 0) {
2081*4543Smarks 		mutex_enter(&zfs_share_lock);
2082*4543Smarks 		nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error);
2083*4543Smarks 		sharefs_mod = ddi_modopen("fs/sharefs",
2084*4543Smarks 		    KRTLD_MODE_FIRST, &error);
2085*4543Smarks 		if (nfs_mod == NULL || sharefs_mod == NULL) {
2086*4543Smarks 			mutex_exit(&zfs_share_lock);
2087*4543Smarks 			return (ENOSYS);
2088*4543Smarks 		}
2089*4543Smarks 		if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *))
2090*4543Smarks 		    ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) {
2091*4543Smarks 			mutex_exit(&zfs_share_lock);
2092*4543Smarks 			return (ENOSYS);
2093*4543Smarks 		}
2094*4543Smarks 
2095*4543Smarks 		if (zshare_fs == NULL && ((zshare_fs =
2096*4543Smarks 		    (int (*)(enum sharefs_sys_op, share_t *, uint32_t))
2097*4543Smarks 		    ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) {
2098*4543Smarks 			mutex_exit(&zfs_share_lock);
2099*4543Smarks 			return (ENOSYS);
2100*4543Smarks 		}
2101*4543Smarks 		zfs_share_inited = 1;
2102*4543Smarks 		mutex_exit(&zfs_share_lock);
2103*4543Smarks 	}
2104*4543Smarks 
2105*4543Smarks 	if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata))
2106*4543Smarks 		return (error);
2107*4543Smarks 
2108*4543Smarks 	opcode = (zc->zc_share.z_sharetype == B_TRUE) ?
2109*4543Smarks 	    SHAREFS_ADD : SHAREFS_REMOVE;
2110*4543Smarks 
2111*4543Smarks 	error = zshare_fs(opcode,
2112*4543Smarks 	    (void *)(uintptr_t)zc->zc_share.z_sharedata,
2113*4543Smarks 	    zc->zc_share.z_sharemax);
2114*4543Smarks 
2115*4543Smarks 	return (error);
2116*4543Smarks 
2117*4543Smarks }
2118*4543Smarks 
2119*4543Smarks /*
2120*4543Smarks  * pool destroy and pool export don't log the history as part of zfsdev_ioctl,
2121*4543Smarks  * but rather zfs_ioc_pool_create, and zfs_ioc_pool_export do the loggin
2122*4543Smarks  * of those commands.
2123*4543Smarks  */
2124789Sahrens static zfs_ioc_vec_t zfs_ioc_vec[] = {
2125*4543Smarks 	{ zfs_ioc_pool_create, zfs_secpolicy_config, pool_name, B_TRUE },
2126*4543Smarks 	{ zfs_ioc_pool_destroy,	zfs_secpolicy_config, pool_name, B_FALSE },
2127*4543Smarks 	{ zfs_ioc_pool_import, zfs_secpolicy_config, pool_name, B_TRUE },
2128*4543Smarks 	{ zfs_ioc_pool_export, zfs_secpolicy_config, pool_name, B_FALSE },
2129*4543Smarks 	{ zfs_ioc_pool_configs,	zfs_secpolicy_none, no_name, B_FALSE },
2130*4543Smarks 	{ zfs_ioc_pool_stats, zfs_secpolicy_read, pool_name, B_FALSE },
2131*4543Smarks 	{ zfs_ioc_pool_tryimport, zfs_secpolicy_config, no_name, B_FALSE },
2132*4543Smarks 	{ zfs_ioc_pool_scrub, zfs_secpolicy_config, pool_name, B_TRUE },
2133*4543Smarks 	{ zfs_ioc_pool_freeze, zfs_secpolicy_config, no_name, B_FALSE },
2134*4543Smarks 	{ zfs_ioc_pool_upgrade,	zfs_secpolicy_config, pool_name, B_TRUE },
2135*4543Smarks 	{ zfs_ioc_pool_get_history, zfs_secpolicy_config, pool_name, B_FALSE },
2136*4543Smarks 	{ zfs_ioc_vdev_add, zfs_secpolicy_config, pool_name, B_TRUE },
2137*4543Smarks 	{ zfs_ioc_vdev_remove, zfs_secpolicy_config, pool_name, B_TRUE },
2138*4543Smarks 	{ zfs_ioc_vdev_set_state, zfs_secpolicy_config,	pool_name, B_TRUE },
2139*4543Smarks 	{ zfs_ioc_vdev_attach, zfs_secpolicy_config, pool_name, B_TRUE },
2140*4543Smarks 	{ zfs_ioc_vdev_detach, zfs_secpolicy_config, pool_name, B_TRUE },
2141*4543Smarks 	{ zfs_ioc_vdev_setpath,	zfs_secpolicy_config, pool_name, B_FALSE },
2142*4543Smarks 	{ zfs_ioc_objset_stats,	zfs_secpolicy_read, dataset_name, B_FALSE },
2143*4543Smarks 	{ zfs_ioc_dataset_list_next, zfs_secpolicy_read,
2144*4543Smarks 	    dataset_name, B_FALSE },
2145*4543Smarks 	{ zfs_ioc_snapshot_list_next, zfs_secpolicy_read,
2146*4543Smarks 	    dataset_name, B_FALSE },
2147*4543Smarks 	{ zfs_ioc_set_prop, zfs_secpolicy_none, dataset_name, B_TRUE },
2148*4543Smarks 	{ zfs_ioc_create_minor,	zfs_secpolicy_minor, dataset_name, B_FALSE },
2149*4543Smarks 	{ zfs_ioc_remove_minor,	zfs_secpolicy_minor, dataset_name, B_FALSE },
2150*4543Smarks 	{ zfs_ioc_create, zfs_secpolicy_create, dataset_name, B_TRUE },
2151*4543Smarks 	{ zfs_ioc_destroy, zfs_secpolicy_destroy, dataset_name, B_TRUE },
2152*4543Smarks 	{ zfs_ioc_rollback, zfs_secpolicy_rollback, dataset_name, B_TRUE },
2153*4543Smarks 	{ zfs_ioc_rename, zfs_secpolicy_rename,	dataset_name, B_TRUE },
2154*4543Smarks 	{ zfs_ioc_recvbackup, zfs_secpolicy_receive, dataset_name, B_TRUE },
2155*4543Smarks 	{ zfs_ioc_sendbackup, zfs_secpolicy_send, dataset_name, B_TRUE },
2156*4543Smarks 	{ zfs_ioc_inject_fault,	zfs_secpolicy_inject, no_name, B_FALSE },
2157*4543Smarks 	{ zfs_ioc_clear_fault, zfs_secpolicy_inject, no_name, B_FALSE },
2158*4543Smarks 	{ zfs_ioc_inject_list_next, zfs_secpolicy_inject, no_name, B_FALSE },
2159*4543Smarks 	{ zfs_ioc_error_log, zfs_secpolicy_inject, pool_name, B_FALSE },
2160*4543Smarks 	{ zfs_ioc_clear, zfs_secpolicy_config, pool_name, B_TRUE },
2161*4543Smarks 	{ zfs_ioc_promote, zfs_secpolicy_promote, dataset_name, B_TRUE },
2162*4543Smarks 	{ zfs_ioc_destroy_snaps, zfs_secpolicy_destroy,	dataset_name, B_TRUE },
2163*4543Smarks 	{ zfs_ioc_snapshot, zfs_secpolicy_snapshot, dataset_name, B_TRUE },
2164*4543Smarks 	{ zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, pool_name, B_FALSE },
2165*4543Smarks 	{ zfs_ioc_obj_to_path, zfs_secpolicy_config, no_name, B_FALSE },
2166*4543Smarks 	{ zfs_ioc_pool_set_props, zfs_secpolicy_config,	pool_name, B_TRUE },
2167*4543Smarks 	{ zfs_ioc_pool_get_props, zfs_secpolicy_read, pool_name, B_FALSE },
2168*4543Smarks 	{ zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, dataset_name, B_TRUE },
2169*4543Smarks 	{ zfs_ioc_get_fsacl, zfs_secpolicy_read, dataset_name, B_FALSE },
2170*4543Smarks 	{ zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi,
2171*4543Smarks 	    dataset_name, B_FALSE },
2172*4543Smarks 	{ zfs_ioc_share, zfs_secpolicy_share, dataset_name, B_FALSE }
2173789Sahrens };
2174789Sahrens 
2175789Sahrens static int
2176789Sahrens zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
2177789Sahrens {
2178789Sahrens 	zfs_cmd_t *zc;
2179789Sahrens 	uint_t vec;
21802199Sahrens 	int error, rc;
2181789Sahrens 
2182789Sahrens 	if (getminor(dev) != 0)
2183789Sahrens 		return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp));
2184789Sahrens 
2185789Sahrens 	vec = cmd - ZFS_IOC;
2186789Sahrens 
2187789Sahrens 	if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
2188789Sahrens 		return (EINVAL);
2189789Sahrens 
2190789Sahrens 	zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
2191789Sahrens 
2192789Sahrens 	error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t));
2193789Sahrens 
2194789Sahrens 	if (error == 0) {
2195789Sahrens 		zc->zc_cred = (uintptr_t)cr;
2196789Sahrens 		zc->zc_dev = dev;
2197*4543Smarks 		error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr);
2198789Sahrens 	}
2199789Sahrens 
2200789Sahrens 	/*
2201789Sahrens 	 * Ensure that all pool/dataset names are valid before we pass down to
2202789Sahrens 	 * the lower layers.
2203789Sahrens 	 */
2204789Sahrens 	if (error == 0) {
2205789Sahrens 		zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
2206789Sahrens 		switch (zfs_ioc_vec[vec].zvec_namecheck) {
2207789Sahrens 		case pool_name:
2208789Sahrens 			if (pool_namecheck(zc->zc_name, NULL, NULL) != 0)
2209789Sahrens 				error = EINVAL;
2210789Sahrens 			break;
2211789Sahrens 
2212789Sahrens 		case dataset_name:
2213789Sahrens 			if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0)
2214789Sahrens 				error = EINVAL;
2215789Sahrens 			break;
22162856Snd150628 
22172856Snd150628 		case no_name:
22182856Snd150628 			break;
2219789Sahrens 		}
2220789Sahrens 	}
2221789Sahrens 
2222789Sahrens 	if (error == 0)
2223789Sahrens 		error = zfs_ioc_vec[vec].zvec_func(zc);
2224789Sahrens 
22252199Sahrens 	rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t));
2226*4543Smarks 	if (error == 0) {
22272199Sahrens 		error = rc;
2228*4543Smarks 		if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE)
2229*4543Smarks 			zfs_log_history(zc);
2230*4543Smarks 	}
2231789Sahrens 
2232789Sahrens 	kmem_free(zc, sizeof (zfs_cmd_t));
2233789Sahrens 	return (error);
2234789Sahrens }
2235789Sahrens 
2236789Sahrens static int
2237789Sahrens zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2238789Sahrens {
2239789Sahrens 	if (cmd != DDI_ATTACH)
2240789Sahrens 		return (DDI_FAILURE);
2241789Sahrens 
2242789Sahrens 	if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0,
2243789Sahrens 	    DDI_PSEUDO, 0) == DDI_FAILURE)
2244789Sahrens 		return (DDI_FAILURE);
2245789Sahrens 
2246789Sahrens 	zfs_dip = dip;
2247789Sahrens 
2248789Sahrens 	ddi_report_dev(dip);
2249789Sahrens 
2250789Sahrens 	return (DDI_SUCCESS);
2251789Sahrens }
2252789Sahrens 
2253789Sahrens static int
2254789Sahrens zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2255789Sahrens {
2256789Sahrens 	if (spa_busy() || zfs_busy() || zvol_busy())
2257789Sahrens 		return (DDI_FAILURE);
2258789Sahrens 
2259789Sahrens 	if (cmd != DDI_DETACH)
2260789Sahrens 		return (DDI_FAILURE);
2261789Sahrens 
2262789Sahrens 	zfs_dip = NULL;
2263789Sahrens 
2264789Sahrens 	ddi_prop_remove_all(dip);
2265789Sahrens 	ddi_remove_minor_node(dip, NULL);
2266789Sahrens 
2267789Sahrens 	return (DDI_SUCCESS);
2268789Sahrens }
2269789Sahrens 
2270789Sahrens /*ARGSUSED*/
2271789Sahrens static int
2272789Sahrens zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
2273789Sahrens {
2274789Sahrens 	switch (infocmd) {
2275789Sahrens 	case DDI_INFO_DEVT2DEVINFO:
2276789Sahrens 		*result = zfs_dip;
2277789Sahrens 		return (DDI_SUCCESS);
2278789Sahrens 
2279789Sahrens 	case DDI_INFO_DEVT2INSTANCE:
2280849Sbonwick 		*result = (void *)0;
2281789Sahrens 		return (DDI_SUCCESS);
2282789Sahrens 	}
2283789Sahrens 
2284789Sahrens 	return (DDI_FAILURE);
2285789Sahrens }
2286789Sahrens 
2287789Sahrens /*
2288789Sahrens  * OK, so this is a little weird.
2289789Sahrens  *
2290789Sahrens  * /dev/zfs is the control node, i.e. minor 0.
2291789Sahrens  * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0.
2292789Sahrens  *
2293789Sahrens  * /dev/zfs has basically nothing to do except serve up ioctls,
2294789Sahrens  * so most of the standard driver entry points are in zvol.c.
2295789Sahrens  */
2296789Sahrens static struct cb_ops zfs_cb_ops = {
2297789Sahrens 	zvol_open,	/* open */
2298789Sahrens 	zvol_close,	/* close */
2299789Sahrens 	zvol_strategy,	/* strategy */
2300789Sahrens 	nodev,		/* print */
2301789Sahrens 	nodev,		/* dump */
2302789Sahrens 	zvol_read,	/* read */
2303789Sahrens 	zvol_write,	/* write */
2304789Sahrens 	zfsdev_ioctl,	/* ioctl */
2305789Sahrens 	nodev,		/* devmap */
2306789Sahrens 	nodev,		/* mmap */
2307789Sahrens 	nodev,		/* segmap */
2308789Sahrens 	nochpoll,	/* poll */
2309789Sahrens 	ddi_prop_op,	/* prop_op */
2310789Sahrens 	NULL,		/* streamtab */
2311789Sahrens 	D_NEW | D_MP | D_64BIT,		/* Driver compatibility flag */
2312789Sahrens 	CB_REV,		/* version */
23133638Sbillm 	nodev,		/* async read */
23143638Sbillm 	nodev,		/* async write */
2315789Sahrens };
2316789Sahrens 
2317789Sahrens static struct dev_ops zfs_dev_ops = {
2318789Sahrens 	DEVO_REV,	/* version */
2319789Sahrens 	0,		/* refcnt */
2320789Sahrens 	zfs_info,	/* info */
2321789Sahrens 	nulldev,	/* identify */
2322789Sahrens 	nulldev,	/* probe */
2323789Sahrens 	zfs_attach,	/* attach */
2324789Sahrens 	zfs_detach,	/* detach */
2325789Sahrens 	nodev,		/* reset */
2326789Sahrens 	&zfs_cb_ops,	/* driver operations */
2327789Sahrens 	NULL		/* no bus operations */
2328789Sahrens };
2329789Sahrens 
2330789Sahrens static struct modldrv zfs_modldrv = {
23312676Seschrock 	&mod_driverops, "ZFS storage pool version " ZFS_VERSION_STRING,
23322676Seschrock 	    &zfs_dev_ops
2333789Sahrens };
2334789Sahrens 
2335789Sahrens static struct modlinkage modlinkage = {
2336789Sahrens 	MODREV_1,
2337789Sahrens 	(void *)&zfs_modlfs,
2338789Sahrens 	(void *)&zfs_modldrv,
2339789Sahrens 	NULL
2340789Sahrens };
2341789Sahrens 
2342789Sahrens int
2343789Sahrens _init(void)
2344789Sahrens {
2345789Sahrens 	int error;
2346789Sahrens 
2347849Sbonwick 	spa_init(FREAD | FWRITE);
2348849Sbonwick 	zfs_init();
2349849Sbonwick 	zvol_init();
2350849Sbonwick 
2351849Sbonwick 	if ((error = mod_install(&modlinkage)) != 0) {
2352849Sbonwick 		zvol_fini();
2353849Sbonwick 		zfs_fini();
2354849Sbonwick 		spa_fini();
2355789Sahrens 		return (error);
2356849Sbonwick 	}
2357789Sahrens 
2358789Sahrens 	error = ldi_ident_from_mod(&modlinkage, &zfs_li);
2359789Sahrens 	ASSERT(error == 0);
2360*4543Smarks 	mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
2361789Sahrens 
2362789Sahrens 	return (0);
2363789Sahrens }
2364789Sahrens 
2365789Sahrens int
2366789Sahrens _fini(void)
2367789Sahrens {
2368789Sahrens 	int error;
2369789Sahrens 
23701544Seschrock 	if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled)
2371789Sahrens 		return (EBUSY);
2372789Sahrens 
2373789Sahrens 	if ((error = mod_remove(&modlinkage)) != 0)
2374789Sahrens 		return (error);
2375789Sahrens 
2376789Sahrens 	zvol_fini();
2377789Sahrens 	zfs_fini();
2378789Sahrens 	spa_fini();
2379*4543Smarks 	if (zfs_share_inited) {
2380*4543Smarks 		(void) ddi_modclose(nfs_mod);
2381*4543Smarks 		(void) ddi_modclose(sharefs_mod);
2382*4543Smarks 	}
2383789Sahrens 
2384789Sahrens 	ldi_ident_release(zfs_li);
2385789Sahrens 	zfs_li = NULL;
2386*4543Smarks 	mutex_destroy(&zfs_share_lock);
2387789Sahrens 
2388789Sahrens 	return (error);
2389789Sahrens }
2390789Sahrens 
2391789Sahrens int
2392789Sahrens _info(struct modinfo *modinfop)
2393789Sahrens {
2394789Sahrens 	return (mod_info(&modlinkage, modinfop));
2395789Sahrens }
2396