xref: /titanic_50/usr/src/uts/common/io/devpool.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/open.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/policy.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/pool.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/pool_impl.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /*
44*7c478bd9Sstevel@tonic-gate  * The kernel pools subsystem is accessed and manipulated through the pool
45*7c478bd9Sstevel@tonic-gate  * device, which has two minor nodes /dev/pool, and /dev/poolctl.  User
46*7c478bd9Sstevel@tonic-gate  * processes can comminicate with pools through ioctls on these devices.
47*7c478bd9Sstevel@tonic-gate  *
48*7c478bd9Sstevel@tonic-gate  * The poolctl device (POOL_CTL_PARENT) can be used to modify and take
49*7c478bd9Sstevel@tonic-gate  * snapshot of the current configuration.  Only one process on the system
50*7c478bd9Sstevel@tonic-gate  * can have it open at any given time.  This device is also used to enable
51*7c478bd9Sstevel@tonic-gate  * or disable pools.  If pools are disabled, the pool driver can be unloaded
52*7c478bd9Sstevel@tonic-gate  * and completely removed from the system.
53*7c478bd9Sstevel@tonic-gate  *
54*7c478bd9Sstevel@tonic-gate  * The pool "info" device (POOL_INFO_PARENT) can only be used to obtain
55*7c478bd9Sstevel@tonic-gate  * snapshots of the current configuration and change/query pool bindings.
56*7c478bd9Sstevel@tonic-gate  * While some reconfiguration transaction via the poolctl device is in
57*7c478bd9Sstevel@tonic-gate  * progress, all processes using this "info" device will be provided with
58*7c478bd9Sstevel@tonic-gate  * the snapshot taken at the beginning of that transaction.
59*7c478bd9Sstevel@tonic-gate  */
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #define	POOL_CTL_PARENT		0
62*7c478bd9Sstevel@tonic-gate #define	POOL_INFO_PARENT	1
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate static dev_info_t *pool_devi;	/* pool device information */
65*7c478bd9Sstevel@tonic-gate static int pool_openctl;	/* poolctl device is already open */
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
68*7c478bd9Sstevel@tonic-gate static int
69*7c478bd9Sstevel@tonic-gate pool_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
70*7c478bd9Sstevel@tonic-gate {
71*7c478bd9Sstevel@tonic-gate 	int error = DDI_FAILURE;
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate 	switch (infocmd) {
74*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
75*7c478bd9Sstevel@tonic-gate 		*result = pool_devi;
76*7c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
77*7c478bd9Sstevel@tonic-gate 		break;
78*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
79*7c478bd9Sstevel@tonic-gate 		/*
80*7c478bd9Sstevel@tonic-gate 		 * All dev_t's map to the same, single instance.
81*7c478bd9Sstevel@tonic-gate 		 */
82*7c478bd9Sstevel@tonic-gate 		*result = NULL;
83*7c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
84*7c478bd9Sstevel@tonic-gate 		break;
85*7c478bd9Sstevel@tonic-gate 	default:
86*7c478bd9Sstevel@tonic-gate 		break;
87*7c478bd9Sstevel@tonic-gate 	}
88*7c478bd9Sstevel@tonic-gate 	return (error);
89*7c478bd9Sstevel@tonic-gate }
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate static int
92*7c478bd9Sstevel@tonic-gate pool_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
93*7c478bd9Sstevel@tonic-gate {
94*7c478bd9Sstevel@tonic-gate 	int ret = DDI_SUCCESS;
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
97*7c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
98*7c478bd9Sstevel@tonic-gate 		pool_lock();
99*7c478bd9Sstevel@tonic-gate 		if (pool_state == POOL_ENABLED) {
100*7c478bd9Sstevel@tonic-gate 			ret = DDI_FAILURE;
101*7c478bd9Sstevel@tonic-gate 			pool_unlock();
102*7c478bd9Sstevel@tonic-gate 			break;
103*7c478bd9Sstevel@tonic-gate 		}
104*7c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node(devi, NULL);
105*7c478bd9Sstevel@tonic-gate 		pool_devi = NULL;
106*7c478bd9Sstevel@tonic-gate 		pool_unlock();
107*7c478bd9Sstevel@tonic-gate 		break;
108*7c478bd9Sstevel@tonic-gate 	default:
109*7c478bd9Sstevel@tonic-gate 		ret = DDI_FAILURE;
110*7c478bd9Sstevel@tonic-gate 	}
111*7c478bd9Sstevel@tonic-gate 	return (ret);
112*7c478bd9Sstevel@tonic-gate }
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate static int
115*7c478bd9Sstevel@tonic-gate pool_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
116*7c478bd9Sstevel@tonic-gate {
117*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
118*7c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
119*7c478bd9Sstevel@tonic-gate 		if (pool_devi != NULL)
120*7c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
121*7c478bd9Sstevel@tonic-gate 		if (ddi_create_minor_node(devi, "poolctl", S_IFCHR,
122*7c478bd9Sstevel@tonic-gate 		    POOL_CTL_PARENT, DDI_PSEUDO, 0) == DDI_FAILURE ||
123*7c478bd9Sstevel@tonic-gate 		    ddi_create_minor_node(devi, "pool", S_IFCHR,
124*7c478bd9Sstevel@tonic-gate 		    POOL_INFO_PARENT, DDI_PSEUDO, 0) == DDI_FAILURE) {
125*7c478bd9Sstevel@tonic-gate 			ddi_remove_minor_node(devi, NULL);
126*7c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
127*7c478bd9Sstevel@tonic-gate 		}
128*7c478bd9Sstevel@tonic-gate 		pool_devi = devi;
129*7c478bd9Sstevel@tonic-gate 		ddi_report_dev(devi);
130*7c478bd9Sstevel@tonic-gate 		break;
131*7c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
132*7c478bd9Sstevel@tonic-gate 		break;
133*7c478bd9Sstevel@tonic-gate 	default:
134*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
135*7c478bd9Sstevel@tonic-gate 	}
136*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate }
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate /*
141*7c478bd9Sstevel@tonic-gate  * There is only one instance of the pool control device, poolctl,
142*7c478bd9Sstevel@tonic-gate  * and multiple instances of the pool info device, pool.
143*7c478bd9Sstevel@tonic-gate  */
144*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
145*7c478bd9Sstevel@tonic-gate static int
146*7c478bd9Sstevel@tonic-gate pool_open(dev_t *devp, int flag, int otype, cred_t *credp)
147*7c478bd9Sstevel@tonic-gate {
148*7c478bd9Sstevel@tonic-gate 	minor_t minor = getminor(*devp);
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	if (otype != OTYP_CHR)
151*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	switch (minor) {
154*7c478bd9Sstevel@tonic-gate 	case POOL_CTL_PARENT:
155*7c478bd9Sstevel@tonic-gate 		if (secpolicy_pool(CRED()) != 0)
156*7c478bd9Sstevel@tonic-gate 			return (EPERM);
157*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
158*7c478bd9Sstevel@tonic-gate 			return (EINTR);
159*7c478bd9Sstevel@tonic-gate 		if (pool_openctl == 1) {
160*7c478bd9Sstevel@tonic-gate 			pool_unlock();
161*7c478bd9Sstevel@tonic-gate 			return (EBUSY);
162*7c478bd9Sstevel@tonic-gate 		}
163*7c478bd9Sstevel@tonic-gate 		pool_openctl = 1;
164*7c478bd9Sstevel@tonic-gate 		pool_unlock();
165*7c478bd9Sstevel@tonic-gate 		break;
166*7c478bd9Sstevel@tonic-gate 	case POOL_INFO_PARENT:
167*7c478bd9Sstevel@tonic-gate 		break;
168*7c478bd9Sstevel@tonic-gate 	default:
169*7c478bd9Sstevel@tonic-gate 		return (ENXIO);
170*7c478bd9Sstevel@tonic-gate 	}
171*7c478bd9Sstevel@tonic-gate 	return (0);
172*7c478bd9Sstevel@tonic-gate }
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
175*7c478bd9Sstevel@tonic-gate static int
176*7c478bd9Sstevel@tonic-gate pool_close(dev_t dev, int flag, int otype, cred_t *credp)
177*7c478bd9Sstevel@tonic-gate {
178*7c478bd9Sstevel@tonic-gate 	if (otype != OTYP_CHR)
179*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
180*7c478bd9Sstevel@tonic-gate 	if (getminor(dev) == 0) {
181*7c478bd9Sstevel@tonic-gate 		/*
182*7c478bd9Sstevel@tonic-gate 		 * We could be closing the poolctl device without finishing
183*7c478bd9Sstevel@tonic-gate 		 * the commit transaction first, so do that now.
184*7c478bd9Sstevel@tonic-gate 		 */
185*7c478bd9Sstevel@tonic-gate 		pool_lock();
186*7c478bd9Sstevel@tonic-gate 		(void) pool_commit(0);	/* cannot fail since arg is 0 */
187*7c478bd9Sstevel@tonic-gate 		pool_openctl = 0;
188*7c478bd9Sstevel@tonic-gate 		pool_unlock();
189*7c478bd9Sstevel@tonic-gate 	}
190*7c478bd9Sstevel@tonic-gate 	return (0);
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate /*
194*7c478bd9Sstevel@tonic-gate  * Main pool interface.
195*7c478bd9Sstevel@tonic-gate  */
196*7c478bd9Sstevel@tonic-gate /* ARGSUSED4 */
197*7c478bd9Sstevel@tonic-gate static int
198*7c478bd9Sstevel@tonic-gate pool_ioctl(dev_t dev, int cmd, intptr_t arg, int  mode, cred_t *credp,
199*7c478bd9Sstevel@tonic-gate     int *rvalp)
200*7c478bd9Sstevel@tonic-gate {
201*7c478bd9Sstevel@tonic-gate 	pool_xtransfer_t xtransfer;
202*7c478bd9Sstevel@tonic-gate 	pool_transfer_t transfer;
203*7c478bd9Sstevel@tonic-gate 	pool_destroy_t destroy;
204*7c478bd9Sstevel@tonic-gate 	pool_propget_t propget;
205*7c478bd9Sstevel@tonic-gate 	pool_propput_t propput;
206*7c478bd9Sstevel@tonic-gate 	pool_proprm_t proprm;
207*7c478bd9Sstevel@tonic-gate 	pool_status_t status;
208*7c478bd9Sstevel@tonic-gate 	pool_dissoc_t dissoc;
209*7c478bd9Sstevel@tonic-gate 	pool_create_t create;
210*7c478bd9Sstevel@tonic-gate 	pool_assoc_t assoc;
211*7c478bd9Sstevel@tonic-gate 	pool_bindq_t bindq;
212*7c478bd9Sstevel@tonic-gate 	pool_query_t query;
213*7c478bd9Sstevel@tonic-gate 	pool_bind_t bind;
214*7c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
215*7c478bd9Sstevel@tonic-gate 	pool_xtransfer32_t xtransfer32;
216*7c478bd9Sstevel@tonic-gate 	pool_propput32_t propput32;
217*7c478bd9Sstevel@tonic-gate 	pool_propget32_t propget32;
218*7c478bd9Sstevel@tonic-gate 	pool_proprm32_t proprm32;
219*7c478bd9Sstevel@tonic-gate 	pool_query32_t query32;
220*7c478bd9Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
221*7c478bd9Sstevel@tonic-gate 	char *kbuf = NULL;
222*7c478bd9Sstevel@tonic-gate 	size_t kbufsz = 0;
223*7c478bd9Sstevel@tonic-gate 	int snapshot = 0;
224*7c478bd9Sstevel@tonic-gate 	char *prop_name;
225*7c478bd9Sstevel@tonic-gate 	size_t size = 0;
226*7c478bd9Sstevel@tonic-gate 	nvlist_t *list;
227*7c478bd9Sstevel@tonic-gate 	nvpair_t *pair;
228*7c478bd9Sstevel@tonic-gate 	char *listbuf;
229*7c478bd9Sstevel@tonic-gate 	minor_t minor;
230*7c478bd9Sstevel@tonic-gate 	uint_t model;
231*7c478bd9Sstevel@tonic-gate 	id_t *id_buf;
232*7c478bd9Sstevel@tonic-gate 	int ret = 0;
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	model = ddi_model_convert_from(mode & FMODELS);
235*7c478bd9Sstevel@tonic-gate 	minor = getminor(dev);
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	/*
238*7c478bd9Sstevel@tonic-gate 	 * Check basic permissions first.
239*7c478bd9Sstevel@tonic-gate 	 */
240*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
241*7c478bd9Sstevel@tonic-gate 	case POOL_STATUS:
242*7c478bd9Sstevel@tonic-gate 	case POOL_CREATE:
243*7c478bd9Sstevel@tonic-gate 	case POOL_ASSOC:
244*7c478bd9Sstevel@tonic-gate 	case POOL_DISSOC:
245*7c478bd9Sstevel@tonic-gate 	case POOL_DESTROY:
246*7c478bd9Sstevel@tonic-gate 	case POOL_TRANSFER:
247*7c478bd9Sstevel@tonic-gate 	case POOL_XTRANSFER:
248*7c478bd9Sstevel@tonic-gate 	case POOL_PROPPUT:
249*7c478bd9Sstevel@tonic-gate 	case POOL_PROPRM:
250*7c478bd9Sstevel@tonic-gate 	case POOL_COMMIT:
251*7c478bd9Sstevel@tonic-gate 		if (minor != POOL_CTL_PARENT)
252*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
253*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
254*7c478bd9Sstevel@tonic-gate 	case POOL_BIND:
255*7c478bd9Sstevel@tonic-gate 		if (secpolicy_pool(CRED()) != 0)
256*7c478bd9Sstevel@tonic-gate 			return (EPERM);
257*7c478bd9Sstevel@tonic-gate 		break;
258*7c478bd9Sstevel@tonic-gate 	}
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
261*7c478bd9Sstevel@tonic-gate 	case POOL_STATUS:
262*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &status,
263*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_status_t), mode) != 0)
264*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
265*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
266*7c478bd9Sstevel@tonic-gate 			return (EINTR);
267*7c478bd9Sstevel@tonic-gate 		ret = pool_status(status.ps_io_state);
268*7c478bd9Sstevel@tonic-gate 		pool_unlock();
269*7c478bd9Sstevel@tonic-gate 		break;
270*7c478bd9Sstevel@tonic-gate 	case POOL_STATUSQ:
271*7c478bd9Sstevel@tonic-gate 		/*
272*7c478bd9Sstevel@tonic-gate 		 * No need to grab pool_lock() to look at the current state.
273*7c478bd9Sstevel@tonic-gate 		 */
274*7c478bd9Sstevel@tonic-gate 		status.ps_io_state = pool_state;
275*7c478bd9Sstevel@tonic-gate 		if (ddi_copyout(&status, (void *)arg,
276*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_status_t), mode) != 0)
277*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
278*7c478bd9Sstevel@tonic-gate 		break;
279*7c478bd9Sstevel@tonic-gate 	case POOL_QUERY:
280*7c478bd9Sstevel@tonic-gate 		switch (model) {
281*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
282*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
283*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &query32,
284*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_query32_t), mode) != 0)
285*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
286*7c478bd9Sstevel@tonic-gate 			query.pq_io_bufsize = query32.pq_io_bufsize;
287*7c478bd9Sstevel@tonic-gate 			query.pq_io_buf = (char *)(uintptr_t)query32.pq_io_buf;
288*7c478bd9Sstevel@tonic-gate 			break;
289*7c478bd9Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
290*7c478bd9Sstevel@tonic-gate 		default:
291*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_NONE:
292*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &query,
293*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_query_t), mode) != 0)
294*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
295*7c478bd9Sstevel@tonic-gate 		}
296*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
297*7c478bd9Sstevel@tonic-gate 			return (EINTR);
298*7c478bd9Sstevel@tonic-gate 		if (pool_state == POOL_DISABLED) {
299*7c478bd9Sstevel@tonic-gate 			pool_unlock();
300*7c478bd9Sstevel@tonic-gate 			return (ENOTACTIVE);
301*7c478bd9Sstevel@tonic-gate 		}
302*7c478bd9Sstevel@tonic-gate 		if (minor != 0 && pool_buf != NULL) {
303*7c478bd9Sstevel@tonic-gate 			/*
304*7c478bd9Sstevel@tonic-gate 			 * Return last snapshot if some
305*7c478bd9Sstevel@tonic-gate 			 * transaction is still in progress
306*7c478bd9Sstevel@tonic-gate 			 */
307*7c478bd9Sstevel@tonic-gate 			if (kbufsz != 0 && pool_bufsz > kbufsz) {
308*7c478bd9Sstevel@tonic-gate 				pool_unlock();
309*7c478bd9Sstevel@tonic-gate 				return (ENOMEM);
310*7c478bd9Sstevel@tonic-gate 			}
311*7c478bd9Sstevel@tonic-gate 			kbuf = pool_buf;
312*7c478bd9Sstevel@tonic-gate 			kbufsz = size = pool_bufsz;
313*7c478bd9Sstevel@tonic-gate 			snapshot = 1;
314*7c478bd9Sstevel@tonic-gate 		} else if (query.pq_io_bufsize != 0) {
315*7c478bd9Sstevel@tonic-gate 			kbufsz = query.pq_io_bufsize;
316*7c478bd9Sstevel@tonic-gate 			kbuf = kmem_alloc(kbufsz, KM_NOSLEEP);
317*7c478bd9Sstevel@tonic-gate 			if (kbuf == NULL) {
318*7c478bd9Sstevel@tonic-gate 				pool_unlock();
319*7c478bd9Sstevel@tonic-gate 				return (ENOMEM);
320*7c478bd9Sstevel@tonic-gate 			}
321*7c478bd9Sstevel@tonic-gate 			ret = pool_pack_conf(kbuf, kbufsz, &size);
322*7c478bd9Sstevel@tonic-gate 		} else {
323*7c478bd9Sstevel@tonic-gate 			ret = pool_pack_conf(NULL, 0, &size);
324*7c478bd9Sstevel@tonic-gate 		}
325*7c478bd9Sstevel@tonic-gate 		if (ret == 0) {
326*7c478bd9Sstevel@tonic-gate 			switch (model) {
327*7c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
328*7c478bd9Sstevel@tonic-gate 			case DDI_MODEL_ILP32:
329*7c478bd9Sstevel@tonic-gate 				query32.pq_io_bufsize = size;
330*7c478bd9Sstevel@tonic-gate 				if (ddi_copyout((caddr_t)&query32, (void *)arg,
331*7c478bd9Sstevel@tonic-gate 				    sizeof (pool_query32_t), mode) != 0)
332*7c478bd9Sstevel@tonic-gate 					ret = EFAULT;
333*7c478bd9Sstevel@tonic-gate 				break;
334*7c478bd9Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
335*7c478bd9Sstevel@tonic-gate 			default:
336*7c478bd9Sstevel@tonic-gate 			case DDI_MODEL_NONE:
337*7c478bd9Sstevel@tonic-gate 				query.pq_io_bufsize = size;
338*7c478bd9Sstevel@tonic-gate 				if (ddi_copyout(&query, (void *)arg,
339*7c478bd9Sstevel@tonic-gate 				    sizeof (pool_query_t), mode) != 0)
340*7c478bd9Sstevel@tonic-gate 					ret = EFAULT;
341*7c478bd9Sstevel@tonic-gate 			}
342*7c478bd9Sstevel@tonic-gate 			if (ret == 0 && query.pq_io_buf != NULL &&
343*7c478bd9Sstevel@tonic-gate 			    ddi_copyout(kbuf, query.pq_io_buf, size, mode) != 0)
344*7c478bd9Sstevel@tonic-gate 				ret = EFAULT;
345*7c478bd9Sstevel@tonic-gate 		}
346*7c478bd9Sstevel@tonic-gate 		pool_unlock();
347*7c478bd9Sstevel@tonic-gate 		if (snapshot == 0)
348*7c478bd9Sstevel@tonic-gate 			kmem_free(kbuf, kbufsz);
349*7c478bd9Sstevel@tonic-gate 		break;
350*7c478bd9Sstevel@tonic-gate 	case POOL_CREATE:
351*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg,
352*7c478bd9Sstevel@tonic-gate 		    &create, sizeof (pool_create_t), mode) != 0)
353*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
354*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
355*7c478bd9Sstevel@tonic-gate 			return (EINTR);
356*7c478bd9Sstevel@tonic-gate 		ret = pool_create(create.pc_o_type,
357*7c478bd9Sstevel@tonic-gate 		    create.pc_o_sub_type, &create.pc_i_id);
358*7c478bd9Sstevel@tonic-gate 		pool_unlock();
359*7c478bd9Sstevel@tonic-gate 		if (ret == 0 && ddi_copyout(&create, (void *)arg,
360*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_create_t), mode) != 0)
361*7c478bd9Sstevel@tonic-gate 			ret = EFAULT;
362*7c478bd9Sstevel@tonic-gate 		break;
363*7c478bd9Sstevel@tonic-gate 	case POOL_ASSOC:
364*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &assoc,
365*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_assoc_t), mode) != 0)
366*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
367*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
368*7c478bd9Sstevel@tonic-gate 			return (EINTR);
369*7c478bd9Sstevel@tonic-gate 		ret = pool_assoc(assoc.pa_o_pool_id,
370*7c478bd9Sstevel@tonic-gate 		    assoc.pa_o_id_type, assoc.pa_o_res_id);
371*7c478bd9Sstevel@tonic-gate 		pool_unlock();
372*7c478bd9Sstevel@tonic-gate 		break;
373*7c478bd9Sstevel@tonic-gate 	case POOL_DISSOC:
374*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &dissoc,
375*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_dissoc_t), mode) != 0)
376*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
377*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
378*7c478bd9Sstevel@tonic-gate 			return (EINTR);
379*7c478bd9Sstevel@tonic-gate 		ret = pool_dissoc(dissoc.pd_o_pool_id, dissoc.pd_o_id_type);
380*7c478bd9Sstevel@tonic-gate 		pool_unlock();
381*7c478bd9Sstevel@tonic-gate 		break;
382*7c478bd9Sstevel@tonic-gate 	case POOL_DESTROY:
383*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &destroy,
384*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_destroy_t), mode) != 0)
385*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
386*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
387*7c478bd9Sstevel@tonic-gate 			return (EINTR);
388*7c478bd9Sstevel@tonic-gate 		ret = pool_destroy(destroy.pd_o_type, destroy.pd_o_sub_type,
389*7c478bd9Sstevel@tonic-gate 		    destroy.pd_o_id);
390*7c478bd9Sstevel@tonic-gate 		pool_unlock();
391*7c478bd9Sstevel@tonic-gate 		break;
392*7c478bd9Sstevel@tonic-gate 	case POOL_TRANSFER:
393*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &transfer,
394*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_transfer_t), mode) != 0)
395*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
396*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
397*7c478bd9Sstevel@tonic-gate 			return (EINTR);
398*7c478bd9Sstevel@tonic-gate 		ret = pool_transfer(transfer.pt_o_id_type, transfer.pt_o_src_id,
399*7c478bd9Sstevel@tonic-gate 		    transfer.pt_o_tgt_id, transfer.pt_o_qty);
400*7c478bd9Sstevel@tonic-gate 		pool_unlock();
401*7c478bd9Sstevel@tonic-gate 		break;
402*7c478bd9Sstevel@tonic-gate 	case POOL_XTRANSFER:
403*7c478bd9Sstevel@tonic-gate 		switch (model) {
404*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
405*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
406*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &xtransfer32,
407*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_xtransfer32_t), mode) != 0)
408*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
409*7c478bd9Sstevel@tonic-gate 			xtransfer.px_o_id_type = xtransfer32.px_o_id_type;
410*7c478bd9Sstevel@tonic-gate 			xtransfer.px_o_src_id = xtransfer32.px_o_src_id;
411*7c478bd9Sstevel@tonic-gate 			xtransfer.px_o_tgt_id = xtransfer32.px_o_tgt_id;
412*7c478bd9Sstevel@tonic-gate 			xtransfer.px_o_complist_size =
413*7c478bd9Sstevel@tonic-gate 				xtransfer32.px_o_complist_size;
414*7c478bd9Sstevel@tonic-gate 			xtransfer.px_o_comp_list =
415*7c478bd9Sstevel@tonic-gate 				(id_t *)(uintptr_t)xtransfer32.px_o_comp_list;
416*7c478bd9Sstevel@tonic-gate 			break;
417*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
418*7c478bd9Sstevel@tonic-gate 		default:
419*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_NONE:
420*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &xtransfer,
421*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_xtransfer_t), mode) != 0)
422*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
423*7c478bd9Sstevel@tonic-gate 		}
424*7c478bd9Sstevel@tonic-gate 		/*
425*7c478bd9Sstevel@tonic-gate 		 * Copy in IDs to transfer from the userland
426*7c478bd9Sstevel@tonic-gate 		 */
427*7c478bd9Sstevel@tonic-gate 		if (xtransfer.px_o_complist_size > POOL_IDLIST_SIZE)
428*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
429*7c478bd9Sstevel@tonic-gate 		id_buf = kmem_alloc(xtransfer.px_o_complist_size *
430*7c478bd9Sstevel@tonic-gate 		    sizeof (id_t), KM_SLEEP);
431*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)xtransfer.px_o_comp_list, id_buf,
432*7c478bd9Sstevel@tonic-gate 		    xtransfer.px_o_complist_size * sizeof (id_t), mode) != 0) {
433*7c478bd9Sstevel@tonic-gate 			kmem_free(id_buf, xtransfer.px_o_complist_size *
434*7c478bd9Sstevel@tonic-gate 			    sizeof (id_t));
435*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
436*7c478bd9Sstevel@tonic-gate 		}
437*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0) {
438*7c478bd9Sstevel@tonic-gate 			kmem_free(id_buf, xtransfer.px_o_complist_size *
439*7c478bd9Sstevel@tonic-gate 			    sizeof (id_t));
440*7c478bd9Sstevel@tonic-gate 			return (EINTR);
441*7c478bd9Sstevel@tonic-gate 		}
442*7c478bd9Sstevel@tonic-gate 		ret = pool_xtransfer(xtransfer.px_o_id_type,
443*7c478bd9Sstevel@tonic-gate 		    xtransfer.px_o_src_id, xtransfer.px_o_tgt_id,
444*7c478bd9Sstevel@tonic-gate 		    xtransfer.px_o_complist_size, id_buf);
445*7c478bd9Sstevel@tonic-gate 		pool_unlock();
446*7c478bd9Sstevel@tonic-gate 		kmem_free(id_buf, xtransfer.px_o_complist_size *
447*7c478bd9Sstevel@tonic-gate 		    sizeof (id_t));
448*7c478bd9Sstevel@tonic-gate 		break;
449*7c478bd9Sstevel@tonic-gate 	case POOL_BIND:
450*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &bind,
451*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_bind_t), mode) != 0)
452*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
453*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
454*7c478bd9Sstevel@tonic-gate 			return (EINTR);
455*7c478bd9Sstevel@tonic-gate 		ret = pool_bind(bind.pb_o_pool_id, bind.pb_o_id_type,
456*7c478bd9Sstevel@tonic-gate 		    bind.pb_o_id);
457*7c478bd9Sstevel@tonic-gate 		pool_unlock();
458*7c478bd9Sstevel@tonic-gate 		break;
459*7c478bd9Sstevel@tonic-gate 	case POOL_BINDQ:
460*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &bindq,
461*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_bindq_t), mode) != 0) {
462*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
463*7c478bd9Sstevel@tonic-gate 		}
464*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
465*7c478bd9Sstevel@tonic-gate 			return (EINTR);
466*7c478bd9Sstevel@tonic-gate 		if ((ret = pool_query_binding(bindq.pb_o_id_type,
467*7c478bd9Sstevel@tonic-gate 		    bindq.pb_o_id, &bindq.pb_i_id)) == 0 &&
468*7c478bd9Sstevel@tonic-gate 		    ddi_copyout(&bindq, (void *)arg,
469*7c478bd9Sstevel@tonic-gate 		    sizeof (pool_bindq_t), mode) != 0)
470*7c478bd9Sstevel@tonic-gate 			ret = EFAULT;
471*7c478bd9Sstevel@tonic-gate 		pool_unlock();
472*7c478bd9Sstevel@tonic-gate 		break;
473*7c478bd9Sstevel@tonic-gate 	case POOL_PROPGET:
474*7c478bd9Sstevel@tonic-gate 		switch (model) {
475*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
476*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
477*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &propget32,
478*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_propget32_t), mode) != 0)
479*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
480*7c478bd9Sstevel@tonic-gate 			propget.pp_o_id = propget32.pp_o_id;
481*7c478bd9Sstevel@tonic-gate 			propget.pp_o_id_type = propget32.pp_o_id_type;
482*7c478bd9Sstevel@tonic-gate 			propget.pp_o_id_subtype = propget32.pp_o_id_subtype;
483*7c478bd9Sstevel@tonic-gate 			propget.pp_o_prop_name =
484*7c478bd9Sstevel@tonic-gate 			    (char *)(uintptr_t)propget32.pp_o_prop_name;
485*7c478bd9Sstevel@tonic-gate 			propget.pp_o_prop_name_size =
486*7c478bd9Sstevel@tonic-gate 			    propget32.pp_o_prop_name_size;
487*7c478bd9Sstevel@tonic-gate 			propget.pp_i_buf =
488*7c478bd9Sstevel@tonic-gate 			    (char *)(uintptr_t)propget32.pp_i_buf;
489*7c478bd9Sstevel@tonic-gate 			propget.pp_i_bufsize = propget32.pp_i_bufsize;
490*7c478bd9Sstevel@tonic-gate 			break;
491*7c478bd9Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
492*7c478bd9Sstevel@tonic-gate 		default:
493*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_NONE:
494*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &propget,
495*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_propget_t), mode) != 0)
496*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
497*7c478bd9Sstevel@tonic-gate 		}
498*7c478bd9Sstevel@tonic-gate 		if (propget.pp_o_prop_name_size + 1 > POOL_PROPNAME_SIZE)
499*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
500*7c478bd9Sstevel@tonic-gate 		prop_name = kmem_alloc(propget.pp_o_prop_name_size + 1,
501*7c478bd9Sstevel@tonic-gate 		    KM_SLEEP);
502*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin(propget.pp_o_prop_name, prop_name,
503*7c478bd9Sstevel@tonic-gate 		    propget.pp_o_prop_name_size + 1, mode) != 0) {
504*7c478bd9Sstevel@tonic-gate 			kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
505*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
506*7c478bd9Sstevel@tonic-gate 		}
507*7c478bd9Sstevel@tonic-gate 		list = NULL;
508*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0) {
509*7c478bd9Sstevel@tonic-gate 			kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
510*7c478bd9Sstevel@tonic-gate 			return (EINTR);
511*7c478bd9Sstevel@tonic-gate 		}
512*7c478bd9Sstevel@tonic-gate 		ret = pool_propget(prop_name, propget.pp_o_id_type,
513*7c478bd9Sstevel@tonic-gate 		    propget.pp_o_id_subtype, propget.pp_o_id, &list);
514*7c478bd9Sstevel@tonic-gate 		pool_unlock();
515*7c478bd9Sstevel@tonic-gate 		kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
516*7c478bd9Sstevel@tonic-gate 		if (ret != 0)
517*7c478bd9Sstevel@tonic-gate 			return (ret);
518*7c478bd9Sstevel@tonic-gate 		ret = nvlist_pack(list, &kbuf, &kbufsz, NV_ENCODE_NATIVE, 0);
519*7c478bd9Sstevel@tonic-gate 		if (ret != 0) {
520*7c478bd9Sstevel@tonic-gate 			nvlist_free(list);
521*7c478bd9Sstevel@tonic-gate 			return (ret);
522*7c478bd9Sstevel@tonic-gate 		}
523*7c478bd9Sstevel@tonic-gate 		switch (model) {
524*7c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
525*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
526*7c478bd9Sstevel@tonic-gate 			propget32.pp_i_bufsize = kbufsz;
527*7c478bd9Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)&propget32, (void *)arg,
528*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_propget32_t), mode) != 0)
529*7c478bd9Sstevel@tonic-gate 				ret = EFAULT;
530*7c478bd9Sstevel@tonic-gate 			break;
531*7c478bd9Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
532*7c478bd9Sstevel@tonic-gate 		default:
533*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_NONE:
534*7c478bd9Sstevel@tonic-gate 			if (ddi_copyout(&propget, (void *)arg,
535*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_propget_t), mode) != 0)
536*7c478bd9Sstevel@tonic-gate 				ret = EFAULT;
537*7c478bd9Sstevel@tonic-gate 		}
538*7c478bd9Sstevel@tonic-gate 		if (ret == 0) {
539*7c478bd9Sstevel@tonic-gate 			if (propget.pp_i_buf == NULL) {
540*7c478bd9Sstevel@tonic-gate 				ret = 0;
541*7c478bd9Sstevel@tonic-gate 			} else if (propget.pp_i_bufsize >= kbufsz) {
542*7c478bd9Sstevel@tonic-gate 				if (ddi_copyout(kbuf, propget.pp_i_buf,
543*7c478bd9Sstevel@tonic-gate 				    kbufsz, mode) != 0)
544*7c478bd9Sstevel@tonic-gate 					ret = EFAULT;
545*7c478bd9Sstevel@tonic-gate 			} else {
546*7c478bd9Sstevel@tonic-gate 				ret = ENOMEM;
547*7c478bd9Sstevel@tonic-gate 			}
548*7c478bd9Sstevel@tonic-gate 		}
549*7c478bd9Sstevel@tonic-gate 		kmem_free(kbuf, kbufsz);
550*7c478bd9Sstevel@tonic-gate 		nvlist_free(list);
551*7c478bd9Sstevel@tonic-gate 		break;
552*7c478bd9Sstevel@tonic-gate 	case POOL_PROPPUT:
553*7c478bd9Sstevel@tonic-gate 		switch (model) {
554*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
555*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
556*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &propput32,
557*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_propput32_t), mode) != 0)
558*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
559*7c478bd9Sstevel@tonic-gate 			propput.pp_o_id_type = propput32.pp_o_id_type;
560*7c478bd9Sstevel@tonic-gate 			propput.pp_o_id_sub_type = propput32.pp_o_id_sub_type;
561*7c478bd9Sstevel@tonic-gate 			propput.pp_o_id = propput32.pp_o_id;
562*7c478bd9Sstevel@tonic-gate 			propput.pp_o_bufsize = propput32.pp_o_bufsize;
563*7c478bd9Sstevel@tonic-gate 			propput.pp_o_buf =
564*7c478bd9Sstevel@tonic-gate 			    (char *)(uintptr_t)propput32.pp_o_buf;
565*7c478bd9Sstevel@tonic-gate 			break;
566*7c478bd9Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
567*7c478bd9Sstevel@tonic-gate 		default:
568*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_NONE:
569*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &propput,
570*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_propput_t), mode) != 0)
571*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
572*7c478bd9Sstevel@tonic-gate 		}
573*7c478bd9Sstevel@tonic-gate 		if (propput.pp_o_bufsize > POOL_PROPBUF_SIZE)
574*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
575*7c478bd9Sstevel@tonic-gate 		listbuf = kmem_alloc(propput.pp_o_bufsize, KM_SLEEP);
576*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin(propput.pp_o_buf, listbuf,
577*7c478bd9Sstevel@tonic-gate 		    propput.pp_o_bufsize, mode) != 0) {
578*7c478bd9Sstevel@tonic-gate 			kmem_free(listbuf, propput.pp_o_bufsize);
579*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
580*7c478bd9Sstevel@tonic-gate 		}
581*7c478bd9Sstevel@tonic-gate 		if (nvlist_unpack(listbuf, propput.pp_o_bufsize,
582*7c478bd9Sstevel@tonic-gate 			&list, KM_SLEEP) != 0) {
583*7c478bd9Sstevel@tonic-gate 			kmem_free(listbuf, propput.pp_o_bufsize);
584*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
585*7c478bd9Sstevel@tonic-gate 		}
586*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0) {
587*7c478bd9Sstevel@tonic-gate 			nvlist_free(list);
588*7c478bd9Sstevel@tonic-gate 			kmem_free(listbuf, propput.pp_o_bufsize);
589*7c478bd9Sstevel@tonic-gate 			return (EINTR);
590*7c478bd9Sstevel@tonic-gate 		}
591*7c478bd9Sstevel@tonic-gate 		/*
592*7c478bd9Sstevel@tonic-gate 		 * Extract the nvpair from the list. The list may
593*7c478bd9Sstevel@tonic-gate 		 * contain multiple properties.
594*7c478bd9Sstevel@tonic-gate 		 */
595*7c478bd9Sstevel@tonic-gate 		for (pair = nvlist_next_nvpair(list, NULL); pair != NULL;
596*7c478bd9Sstevel@tonic-gate 		    pair = nvlist_next_nvpair(list, pair)) {
597*7c478bd9Sstevel@tonic-gate 			if ((ret = pool_propput(propput.pp_o_id_type,
598*7c478bd9Sstevel@tonic-gate 			    propput.pp_o_id_sub_type,
599*7c478bd9Sstevel@tonic-gate 			    propput.pp_o_id, pair)) != 0)
600*7c478bd9Sstevel@tonic-gate 				break;
601*7c478bd9Sstevel@tonic-gate 		}
602*7c478bd9Sstevel@tonic-gate 		pool_unlock();
603*7c478bd9Sstevel@tonic-gate 		nvlist_free(list);
604*7c478bd9Sstevel@tonic-gate 		kmem_free(listbuf, propput.pp_o_bufsize);
605*7c478bd9Sstevel@tonic-gate 		break;
606*7c478bd9Sstevel@tonic-gate 	case POOL_PROPRM:
607*7c478bd9Sstevel@tonic-gate 		switch (model) {
608*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
609*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
610*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &proprm32,
611*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_proprm32_t), mode) != 0)
612*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
613*7c478bd9Sstevel@tonic-gate 			proprm.pp_o_id_type = proprm32.pp_o_id_type;
614*7c478bd9Sstevel@tonic-gate 			proprm.pp_o_id_sub_type = proprm32.pp_o_id_sub_type;
615*7c478bd9Sstevel@tonic-gate 			proprm.pp_o_id = proprm32.pp_o_id;
616*7c478bd9Sstevel@tonic-gate 			proprm.pp_o_prop_name_size =
617*7c478bd9Sstevel@tonic-gate 			    proprm32.pp_o_prop_name_size;
618*7c478bd9Sstevel@tonic-gate 			proprm.pp_o_prop_name =
619*7c478bd9Sstevel@tonic-gate 			    (void *)(uintptr_t)proprm32.pp_o_prop_name;
620*7c478bd9Sstevel@tonic-gate 			break;
621*7c478bd9Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
622*7c478bd9Sstevel@tonic-gate 		default:
623*7c478bd9Sstevel@tonic-gate 		case DDI_MODEL_NONE:
624*7c478bd9Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &proprm,
625*7c478bd9Sstevel@tonic-gate 			    sizeof (pool_proprm_t), mode) != 0)
626*7c478bd9Sstevel@tonic-gate 				return (EFAULT);
627*7c478bd9Sstevel@tonic-gate 		}
628*7c478bd9Sstevel@tonic-gate 		if (proprm.pp_o_prop_name_size + 1 > POOL_PROPNAME_SIZE)
629*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
630*7c478bd9Sstevel@tonic-gate 		prop_name = kmem_alloc(proprm.pp_o_prop_name_size + 1,
631*7c478bd9Sstevel@tonic-gate 		    KM_SLEEP);
632*7c478bd9Sstevel@tonic-gate 		if (ddi_copyin(proprm.pp_o_prop_name, prop_name,
633*7c478bd9Sstevel@tonic-gate 		    proprm.pp_o_prop_name_size + 1, mode) != 0) {
634*7c478bd9Sstevel@tonic-gate 			kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
635*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
636*7c478bd9Sstevel@tonic-gate 		}
637*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0) {
638*7c478bd9Sstevel@tonic-gate 			kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
639*7c478bd9Sstevel@tonic-gate 			return (EINTR);
640*7c478bd9Sstevel@tonic-gate 		}
641*7c478bd9Sstevel@tonic-gate 		ret = pool_proprm(proprm.pp_o_id_type,
642*7c478bd9Sstevel@tonic-gate 		    proprm.pp_o_id_sub_type, proprm.pp_o_id, prop_name);
643*7c478bd9Sstevel@tonic-gate 		pool_unlock();
644*7c478bd9Sstevel@tonic-gate 		kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
645*7c478bd9Sstevel@tonic-gate 		break;
646*7c478bd9Sstevel@tonic-gate 	case POOL_COMMIT:
647*7c478bd9Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
648*7c478bd9Sstevel@tonic-gate 			return (EINTR);
649*7c478bd9Sstevel@tonic-gate 		ret = pool_commit((int)arg);
650*7c478bd9Sstevel@tonic-gate 		pool_unlock();
651*7c478bd9Sstevel@tonic-gate 		break;
652*7c478bd9Sstevel@tonic-gate 	default:
653*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
654*7c478bd9Sstevel@tonic-gate 	}
655*7c478bd9Sstevel@tonic-gate 	return (ret);
656*7c478bd9Sstevel@tonic-gate }
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate static struct cb_ops pool_cb_ops = {
659*7c478bd9Sstevel@tonic-gate 	pool_open,		/* open */
660*7c478bd9Sstevel@tonic-gate 	pool_close,		/* close */
661*7c478bd9Sstevel@tonic-gate 	nodev,			/* strategy */
662*7c478bd9Sstevel@tonic-gate 	nodev,			/* print */
663*7c478bd9Sstevel@tonic-gate 	nodev,			/* dump */
664*7c478bd9Sstevel@tonic-gate 	nodev,			/* read */
665*7c478bd9Sstevel@tonic-gate 	nodev,			/* write */
666*7c478bd9Sstevel@tonic-gate 	pool_ioctl,		/* ioctl */
667*7c478bd9Sstevel@tonic-gate 	nodev,			/* devmap */
668*7c478bd9Sstevel@tonic-gate 	nodev,			/* mmap */
669*7c478bd9Sstevel@tonic-gate 	nodev,			/* segmap */
670*7c478bd9Sstevel@tonic-gate 	nochpoll,		/* poll */
671*7c478bd9Sstevel@tonic-gate 	nodev,			/* cb_prop_op */
672*7c478bd9Sstevel@tonic-gate 	(struct streamtab *)0,	/* streamtab */
673*7c478bd9Sstevel@tonic-gate 	D_NEW | D_MP		/* driver compatibility flags */
674*7c478bd9Sstevel@tonic-gate };
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate static struct dev_ops pool_ops = {
677*7c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev */
678*7c478bd9Sstevel@tonic-gate 	0,			/* refcnt */
679*7c478bd9Sstevel@tonic-gate 	pool_info,		/* info */
680*7c478bd9Sstevel@tonic-gate 	nulldev,		/* identify */
681*7c478bd9Sstevel@tonic-gate 	nulldev,		/* probe */
682*7c478bd9Sstevel@tonic-gate 	pool_attach,		/* attach */
683*7c478bd9Sstevel@tonic-gate 	pool_detach,		/* detach */
684*7c478bd9Sstevel@tonic-gate 	nodev,			/* reset */
685*7c478bd9Sstevel@tonic-gate 	&pool_cb_ops,		/* cb_ops */
686*7c478bd9Sstevel@tonic-gate 	(struct bus_ops *)NULL,	/* bus_ops */
687*7c478bd9Sstevel@tonic-gate 	nulldev			/* power */
688*7c478bd9Sstevel@tonic-gate };
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate /*
691*7c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel
692*7c478bd9Sstevel@tonic-gate  */
693*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
694*7c478bd9Sstevel@tonic-gate 	&mod_driverops,		/* this one is a pseudo driver */
695*7c478bd9Sstevel@tonic-gate 	"pool driver %I%",
696*7c478bd9Sstevel@tonic-gate 	&pool_ops
697*7c478bd9Sstevel@tonic-gate };
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
700*7c478bd9Sstevel@tonic-gate 	MODREV_1,
701*7c478bd9Sstevel@tonic-gate 	&modldrv,
702*7c478bd9Sstevel@tonic-gate 	NULL
703*7c478bd9Sstevel@tonic-gate };
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate int
706*7c478bd9Sstevel@tonic-gate _init(void)
707*7c478bd9Sstevel@tonic-gate {
708*7c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
709*7c478bd9Sstevel@tonic-gate }
710*7c478bd9Sstevel@tonic-gate 
711*7c478bd9Sstevel@tonic-gate int
712*7c478bd9Sstevel@tonic-gate _fini(void)
713*7c478bd9Sstevel@tonic-gate {
714*7c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
715*7c478bd9Sstevel@tonic-gate }
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate int
718*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
719*7c478bd9Sstevel@tonic-gate {
720*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
721*7c478bd9Sstevel@tonic-gate }
722