xref: /onnv-gate/usr/src/uts/common/io/devpool.c (revision 7656:2621e50fdf4a)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7656SSherry.Moore@Sun.COM  * Common Development and Distribution License (the "License").
6*7656SSherry.Moore@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*7656SSherry.Moore@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <sys/file.h>
290Sstevel@tonic-gate #include <sys/errno.h>
300Sstevel@tonic-gate #include <sys/open.h>
310Sstevel@tonic-gate #include <sys/cred.h>
320Sstevel@tonic-gate #include <sys/conf.h>
330Sstevel@tonic-gate #include <sys/modctl.h>
340Sstevel@tonic-gate #include <sys/stat.h>
350Sstevel@tonic-gate #include <sys/ddi.h>
360Sstevel@tonic-gate #include <sys/sunddi.h>
370Sstevel@tonic-gate #include <sys/policy.h>
380Sstevel@tonic-gate #include <sys/pool.h>
390Sstevel@tonic-gate #include <sys/pool_impl.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate  * The kernel pools subsystem is accessed and manipulated through the pool
430Sstevel@tonic-gate  * device, which has two minor nodes /dev/pool, and /dev/poolctl.  User
440Sstevel@tonic-gate  * processes can comminicate with pools through ioctls on these devices.
450Sstevel@tonic-gate  *
460Sstevel@tonic-gate  * The poolctl device (POOL_CTL_PARENT) can be used to modify and take
470Sstevel@tonic-gate  * snapshot of the current configuration.  Only one process on the system
480Sstevel@tonic-gate  * can have it open at any given time.  This device is also used to enable
490Sstevel@tonic-gate  * or disable pools.  If pools are disabled, the pool driver can be unloaded
500Sstevel@tonic-gate  * and completely removed from the system.
510Sstevel@tonic-gate  *
520Sstevel@tonic-gate  * The pool "info" device (POOL_INFO_PARENT) can only be used to obtain
530Sstevel@tonic-gate  * snapshots of the current configuration and change/query pool bindings.
540Sstevel@tonic-gate  * While some reconfiguration transaction via the poolctl device is in
550Sstevel@tonic-gate  * progress, all processes using this "info" device will be provided with
560Sstevel@tonic-gate  * the snapshot taken at the beginning of that transaction.
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #define	POOL_CTL_PARENT		0
600Sstevel@tonic-gate #define	POOL_INFO_PARENT	1
610Sstevel@tonic-gate 
620Sstevel@tonic-gate static dev_info_t *pool_devi;	/* pool device information */
630Sstevel@tonic-gate static int pool_openctl;	/* poolctl device is already open */
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*ARGSUSED*/
660Sstevel@tonic-gate static int
pool_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)670Sstevel@tonic-gate pool_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	int error = DDI_FAILURE;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	switch (infocmd) {
720Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
730Sstevel@tonic-gate 		*result = pool_devi;
740Sstevel@tonic-gate 		error = DDI_SUCCESS;
750Sstevel@tonic-gate 		break;
760Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
770Sstevel@tonic-gate 		/*
780Sstevel@tonic-gate 		 * All dev_t's map to the same, single instance.
790Sstevel@tonic-gate 		 */
800Sstevel@tonic-gate 		*result = NULL;
810Sstevel@tonic-gate 		error = DDI_SUCCESS;
820Sstevel@tonic-gate 		break;
830Sstevel@tonic-gate 	default:
840Sstevel@tonic-gate 		break;
850Sstevel@tonic-gate 	}
860Sstevel@tonic-gate 	return (error);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
890Sstevel@tonic-gate static int
pool_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)900Sstevel@tonic-gate pool_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate 	int ret = DDI_SUCCESS;
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	switch (cmd) {
950Sstevel@tonic-gate 	case DDI_DETACH:
960Sstevel@tonic-gate 		pool_lock();
970Sstevel@tonic-gate 		if (pool_state == POOL_ENABLED) {
980Sstevel@tonic-gate 			ret = DDI_FAILURE;
990Sstevel@tonic-gate 			pool_unlock();
1000Sstevel@tonic-gate 			break;
1010Sstevel@tonic-gate 		}
1020Sstevel@tonic-gate 		ddi_remove_minor_node(devi, NULL);
1030Sstevel@tonic-gate 		pool_devi = NULL;
1040Sstevel@tonic-gate 		pool_unlock();
1050Sstevel@tonic-gate 		break;
1060Sstevel@tonic-gate 	default:
1070Sstevel@tonic-gate 		ret = DDI_FAILURE;
1080Sstevel@tonic-gate 	}
1090Sstevel@tonic-gate 	return (ret);
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate static int
pool_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)1130Sstevel@tonic-gate pool_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	switch (cmd) {
1160Sstevel@tonic-gate 	case DDI_ATTACH:
1170Sstevel@tonic-gate 		if (pool_devi != NULL)
1180Sstevel@tonic-gate 			return (DDI_FAILURE);
1190Sstevel@tonic-gate 		if (ddi_create_minor_node(devi, "poolctl", S_IFCHR,
1200Sstevel@tonic-gate 		    POOL_CTL_PARENT, DDI_PSEUDO, 0) == DDI_FAILURE ||
1210Sstevel@tonic-gate 		    ddi_create_minor_node(devi, "pool", S_IFCHR,
1220Sstevel@tonic-gate 		    POOL_INFO_PARENT, DDI_PSEUDO, 0) == DDI_FAILURE) {
1230Sstevel@tonic-gate 			ddi_remove_minor_node(devi, NULL);
1240Sstevel@tonic-gate 			return (DDI_FAILURE);
1250Sstevel@tonic-gate 		}
1260Sstevel@tonic-gate 		pool_devi = devi;
1270Sstevel@tonic-gate 		ddi_report_dev(devi);
1280Sstevel@tonic-gate 		break;
1290Sstevel@tonic-gate 	case DDI_RESUME:
1300Sstevel@tonic-gate 		break;
1310Sstevel@tonic-gate 	default:
1320Sstevel@tonic-gate 		return (DDI_FAILURE);
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 	return (DDI_SUCCESS);
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate /*
1390Sstevel@tonic-gate  * There is only one instance of the pool control device, poolctl,
1400Sstevel@tonic-gate  * and multiple instances of the pool info device, pool.
1410Sstevel@tonic-gate  */
1420Sstevel@tonic-gate /*ARGSUSED*/
1430Sstevel@tonic-gate static int
pool_open(dev_t * devp,int flag,int otype,cred_t * credp)1440Sstevel@tonic-gate pool_open(dev_t *devp, int flag, int otype, cred_t *credp)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate 	minor_t minor = getminor(*devp);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	if (otype != OTYP_CHR)
1490Sstevel@tonic-gate 		return (EINVAL);
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	switch (minor) {
1520Sstevel@tonic-gate 	case POOL_CTL_PARENT:
1530Sstevel@tonic-gate 		if (secpolicy_pool(CRED()) != 0)
1540Sstevel@tonic-gate 			return (EPERM);
1550Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
1560Sstevel@tonic-gate 			return (EINTR);
1570Sstevel@tonic-gate 		if (pool_openctl == 1) {
1580Sstevel@tonic-gate 			pool_unlock();
1590Sstevel@tonic-gate 			return (EBUSY);
1600Sstevel@tonic-gate 		}
1610Sstevel@tonic-gate 		pool_openctl = 1;
1620Sstevel@tonic-gate 		pool_unlock();
1630Sstevel@tonic-gate 		break;
1640Sstevel@tonic-gate 	case POOL_INFO_PARENT:
1650Sstevel@tonic-gate 		break;
1660Sstevel@tonic-gate 	default:
1670Sstevel@tonic-gate 		return (ENXIO);
1680Sstevel@tonic-gate 	}
1690Sstevel@tonic-gate 	return (0);
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*ARGSUSED*/
1730Sstevel@tonic-gate static int
pool_close(dev_t dev,int flag,int otype,cred_t * credp)1740Sstevel@tonic-gate pool_close(dev_t dev, int flag, int otype, cred_t *credp)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate 	if (otype != OTYP_CHR)
1770Sstevel@tonic-gate 		return (EINVAL);
1780Sstevel@tonic-gate 	if (getminor(dev) == 0) {
1790Sstevel@tonic-gate 		/*
1800Sstevel@tonic-gate 		 * We could be closing the poolctl device without finishing
1810Sstevel@tonic-gate 		 * the commit transaction first, so do that now.
1820Sstevel@tonic-gate 		 */
1830Sstevel@tonic-gate 		pool_lock();
1840Sstevel@tonic-gate 		(void) pool_commit(0);	/* cannot fail since arg is 0 */
1850Sstevel@tonic-gate 		pool_openctl = 0;
1860Sstevel@tonic-gate 		pool_unlock();
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 	return (0);
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate /*
1920Sstevel@tonic-gate  * Main pool interface.
1930Sstevel@tonic-gate  */
1940Sstevel@tonic-gate /* ARGSUSED4 */
1950Sstevel@tonic-gate static int
pool_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)1960Sstevel@tonic-gate pool_ioctl(dev_t dev, int cmd, intptr_t arg, int  mode, cred_t *credp,
1970Sstevel@tonic-gate     int *rvalp)
1980Sstevel@tonic-gate {
1990Sstevel@tonic-gate 	pool_xtransfer_t xtransfer;
2000Sstevel@tonic-gate 	pool_transfer_t transfer;
2010Sstevel@tonic-gate 	pool_destroy_t destroy;
2020Sstevel@tonic-gate 	pool_propget_t propget;
2030Sstevel@tonic-gate 	pool_propput_t propput;
2040Sstevel@tonic-gate 	pool_proprm_t proprm;
2050Sstevel@tonic-gate 	pool_status_t status;
2060Sstevel@tonic-gate 	pool_dissoc_t dissoc;
2070Sstevel@tonic-gate 	pool_create_t create;
2080Sstevel@tonic-gate 	pool_assoc_t assoc;
2090Sstevel@tonic-gate 	pool_bindq_t bindq;
2100Sstevel@tonic-gate 	pool_query_t query;
2110Sstevel@tonic-gate 	pool_bind_t bind;
2120Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
2130Sstevel@tonic-gate 	pool_xtransfer32_t xtransfer32;
2140Sstevel@tonic-gate 	pool_propput32_t propput32;
2150Sstevel@tonic-gate 	pool_propget32_t propget32;
2160Sstevel@tonic-gate 	pool_proprm32_t proprm32;
2170Sstevel@tonic-gate 	pool_query32_t query32;
2180Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
2190Sstevel@tonic-gate 	char *kbuf = NULL;
2200Sstevel@tonic-gate 	size_t kbufsz = 0;
2210Sstevel@tonic-gate 	int snapshot = 0;
2220Sstevel@tonic-gate 	char *prop_name;
2230Sstevel@tonic-gate 	size_t size = 0;
2240Sstevel@tonic-gate 	nvlist_t *list;
2250Sstevel@tonic-gate 	nvpair_t *pair;
2260Sstevel@tonic-gate 	char *listbuf;
2270Sstevel@tonic-gate 	minor_t minor;
2280Sstevel@tonic-gate 	uint_t model;
2290Sstevel@tonic-gate 	id_t *id_buf;
2300Sstevel@tonic-gate 	int ret = 0;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	model = ddi_model_convert_from(mode & FMODELS);
2330Sstevel@tonic-gate 	minor = getminor(dev);
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	/*
2360Sstevel@tonic-gate 	 * Check basic permissions first.
2370Sstevel@tonic-gate 	 */
2380Sstevel@tonic-gate 	switch (cmd) {
2390Sstevel@tonic-gate 	case POOL_STATUS:
2400Sstevel@tonic-gate 	case POOL_CREATE:
2410Sstevel@tonic-gate 	case POOL_ASSOC:
2420Sstevel@tonic-gate 	case POOL_DISSOC:
2430Sstevel@tonic-gate 	case POOL_DESTROY:
2440Sstevel@tonic-gate 	case POOL_TRANSFER:
2450Sstevel@tonic-gate 	case POOL_XTRANSFER:
2460Sstevel@tonic-gate 	case POOL_PROPPUT:
2470Sstevel@tonic-gate 	case POOL_PROPRM:
2480Sstevel@tonic-gate 	case POOL_COMMIT:
2490Sstevel@tonic-gate 		if (minor != POOL_CTL_PARENT)
2500Sstevel@tonic-gate 			return (EINVAL);
2510Sstevel@tonic-gate 		/*FALLTHROUGH*/
2520Sstevel@tonic-gate 	case POOL_BIND:
2530Sstevel@tonic-gate 		if (secpolicy_pool(CRED()) != 0)
2540Sstevel@tonic-gate 			return (EPERM);
2550Sstevel@tonic-gate 		break;
2560Sstevel@tonic-gate 	}
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	switch (cmd) {
2590Sstevel@tonic-gate 	case POOL_STATUS:
2600Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &status,
2610Sstevel@tonic-gate 		    sizeof (pool_status_t), mode) != 0)
2620Sstevel@tonic-gate 			return (EFAULT);
2630Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
2640Sstevel@tonic-gate 			return (EINTR);
2650Sstevel@tonic-gate 		ret = pool_status(status.ps_io_state);
2660Sstevel@tonic-gate 		pool_unlock();
2670Sstevel@tonic-gate 		break;
2680Sstevel@tonic-gate 	case POOL_STATUSQ:
2690Sstevel@tonic-gate 		/*
2700Sstevel@tonic-gate 		 * No need to grab pool_lock() to look at the current state.
2710Sstevel@tonic-gate 		 */
2720Sstevel@tonic-gate 		status.ps_io_state = pool_state;
2730Sstevel@tonic-gate 		if (ddi_copyout(&status, (void *)arg,
2740Sstevel@tonic-gate 		    sizeof (pool_status_t), mode) != 0)
2750Sstevel@tonic-gate 			return (EFAULT);
2760Sstevel@tonic-gate 		break;
2770Sstevel@tonic-gate 	case POOL_QUERY:
2780Sstevel@tonic-gate 		switch (model) {
2790Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
2800Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
2810Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &query32,
2820Sstevel@tonic-gate 			    sizeof (pool_query32_t), mode) != 0)
2830Sstevel@tonic-gate 				return (EFAULT);
2840Sstevel@tonic-gate 			query.pq_io_bufsize = query32.pq_io_bufsize;
2850Sstevel@tonic-gate 			query.pq_io_buf = (char *)(uintptr_t)query32.pq_io_buf;
2860Sstevel@tonic-gate 			break;
2870Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
2880Sstevel@tonic-gate 		default:
2890Sstevel@tonic-gate 		case DDI_MODEL_NONE:
2900Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &query,
2910Sstevel@tonic-gate 			    sizeof (pool_query_t), mode) != 0)
2920Sstevel@tonic-gate 				return (EFAULT);
2930Sstevel@tonic-gate 		}
2940Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
2950Sstevel@tonic-gate 			return (EINTR);
2960Sstevel@tonic-gate 		if (pool_state == POOL_DISABLED) {
2970Sstevel@tonic-gate 			pool_unlock();
2980Sstevel@tonic-gate 			return (ENOTACTIVE);
2990Sstevel@tonic-gate 		}
3000Sstevel@tonic-gate 		if (minor != 0 && pool_buf != NULL) {
3010Sstevel@tonic-gate 			/*
3020Sstevel@tonic-gate 			 * Return last snapshot if some
3030Sstevel@tonic-gate 			 * transaction is still in progress
3040Sstevel@tonic-gate 			 */
3050Sstevel@tonic-gate 			if (kbufsz != 0 && pool_bufsz > kbufsz) {
3060Sstevel@tonic-gate 				pool_unlock();
3070Sstevel@tonic-gate 				return (ENOMEM);
3080Sstevel@tonic-gate 			}
3090Sstevel@tonic-gate 			kbuf = pool_buf;
3100Sstevel@tonic-gate 			kbufsz = size = pool_bufsz;
3110Sstevel@tonic-gate 			snapshot = 1;
3120Sstevel@tonic-gate 		} else if (query.pq_io_bufsize != 0) {
3130Sstevel@tonic-gate 			kbufsz = query.pq_io_bufsize;
3140Sstevel@tonic-gate 			kbuf = kmem_alloc(kbufsz, KM_NOSLEEP);
3150Sstevel@tonic-gate 			if (kbuf == NULL) {
3160Sstevel@tonic-gate 				pool_unlock();
3170Sstevel@tonic-gate 				return (ENOMEM);
3180Sstevel@tonic-gate 			}
3190Sstevel@tonic-gate 			ret = pool_pack_conf(kbuf, kbufsz, &size);
3200Sstevel@tonic-gate 		} else {
3210Sstevel@tonic-gate 			ret = pool_pack_conf(NULL, 0, &size);
3220Sstevel@tonic-gate 		}
3230Sstevel@tonic-gate 		if (ret == 0) {
3240Sstevel@tonic-gate 			switch (model) {
3250Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
3260Sstevel@tonic-gate 			case DDI_MODEL_ILP32:
3270Sstevel@tonic-gate 				query32.pq_io_bufsize = size;
3280Sstevel@tonic-gate 				if (ddi_copyout((caddr_t)&query32, (void *)arg,
3290Sstevel@tonic-gate 				    sizeof (pool_query32_t), mode) != 0)
3300Sstevel@tonic-gate 					ret = EFAULT;
3310Sstevel@tonic-gate 				break;
3320Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
3330Sstevel@tonic-gate 			default:
3340Sstevel@tonic-gate 			case DDI_MODEL_NONE:
3350Sstevel@tonic-gate 				query.pq_io_bufsize = size;
3360Sstevel@tonic-gate 				if (ddi_copyout(&query, (void *)arg,
3370Sstevel@tonic-gate 				    sizeof (pool_query_t), mode) != 0)
3380Sstevel@tonic-gate 					ret = EFAULT;
3390Sstevel@tonic-gate 			}
3400Sstevel@tonic-gate 			if (ret == 0 && query.pq_io_buf != NULL &&
3410Sstevel@tonic-gate 			    ddi_copyout(kbuf, query.pq_io_buf, size, mode) != 0)
3420Sstevel@tonic-gate 				ret = EFAULT;
3430Sstevel@tonic-gate 		}
3440Sstevel@tonic-gate 		pool_unlock();
3450Sstevel@tonic-gate 		if (snapshot == 0)
3460Sstevel@tonic-gate 			kmem_free(kbuf, kbufsz);
3470Sstevel@tonic-gate 		break;
3480Sstevel@tonic-gate 	case POOL_CREATE:
3490Sstevel@tonic-gate 		if (ddi_copyin((void *)arg,
3500Sstevel@tonic-gate 		    &create, sizeof (pool_create_t), mode) != 0)
3510Sstevel@tonic-gate 			return (EFAULT);
3520Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
3530Sstevel@tonic-gate 			return (EINTR);
3540Sstevel@tonic-gate 		ret = pool_create(create.pc_o_type,
3550Sstevel@tonic-gate 		    create.pc_o_sub_type, &create.pc_i_id);
3560Sstevel@tonic-gate 		pool_unlock();
3570Sstevel@tonic-gate 		if (ret == 0 && ddi_copyout(&create, (void *)arg,
3580Sstevel@tonic-gate 		    sizeof (pool_create_t), mode) != 0)
3590Sstevel@tonic-gate 			ret = EFAULT;
3600Sstevel@tonic-gate 		break;
3610Sstevel@tonic-gate 	case POOL_ASSOC:
3620Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &assoc,
3630Sstevel@tonic-gate 		    sizeof (pool_assoc_t), mode) != 0)
3640Sstevel@tonic-gate 			return (EFAULT);
3650Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
3660Sstevel@tonic-gate 			return (EINTR);
3670Sstevel@tonic-gate 		ret = pool_assoc(assoc.pa_o_pool_id,
3680Sstevel@tonic-gate 		    assoc.pa_o_id_type, assoc.pa_o_res_id);
3690Sstevel@tonic-gate 		pool_unlock();
3700Sstevel@tonic-gate 		break;
3710Sstevel@tonic-gate 	case POOL_DISSOC:
3720Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &dissoc,
3730Sstevel@tonic-gate 		    sizeof (pool_dissoc_t), mode) != 0)
3740Sstevel@tonic-gate 			return (EFAULT);
3750Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
3760Sstevel@tonic-gate 			return (EINTR);
3770Sstevel@tonic-gate 		ret = pool_dissoc(dissoc.pd_o_pool_id, dissoc.pd_o_id_type);
3780Sstevel@tonic-gate 		pool_unlock();
3790Sstevel@tonic-gate 		break;
3800Sstevel@tonic-gate 	case POOL_DESTROY:
3810Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &destroy,
3820Sstevel@tonic-gate 		    sizeof (pool_destroy_t), mode) != 0)
3830Sstevel@tonic-gate 			return (EFAULT);
3840Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
3850Sstevel@tonic-gate 			return (EINTR);
3860Sstevel@tonic-gate 		ret = pool_destroy(destroy.pd_o_type, destroy.pd_o_sub_type,
3870Sstevel@tonic-gate 		    destroy.pd_o_id);
3880Sstevel@tonic-gate 		pool_unlock();
3890Sstevel@tonic-gate 		break;
3900Sstevel@tonic-gate 	case POOL_TRANSFER:
3910Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &transfer,
3920Sstevel@tonic-gate 		    sizeof (pool_transfer_t), mode) != 0)
3930Sstevel@tonic-gate 			return (EFAULT);
3940Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
3950Sstevel@tonic-gate 			return (EINTR);
3960Sstevel@tonic-gate 		ret = pool_transfer(transfer.pt_o_id_type, transfer.pt_o_src_id,
3970Sstevel@tonic-gate 		    transfer.pt_o_tgt_id, transfer.pt_o_qty);
3980Sstevel@tonic-gate 		pool_unlock();
3990Sstevel@tonic-gate 		break;
4000Sstevel@tonic-gate 	case POOL_XTRANSFER:
4010Sstevel@tonic-gate 		switch (model) {
4020Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
4030Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
4040Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &xtransfer32,
4050Sstevel@tonic-gate 			    sizeof (pool_xtransfer32_t), mode) != 0)
4060Sstevel@tonic-gate 				return (EFAULT);
4070Sstevel@tonic-gate 			xtransfer.px_o_id_type = xtransfer32.px_o_id_type;
4080Sstevel@tonic-gate 			xtransfer.px_o_src_id = xtransfer32.px_o_src_id;
4090Sstevel@tonic-gate 			xtransfer.px_o_tgt_id = xtransfer32.px_o_tgt_id;
4100Sstevel@tonic-gate 			xtransfer.px_o_complist_size =
411*7656SSherry.Moore@Sun.COM 			    xtransfer32.px_o_complist_size;
4120Sstevel@tonic-gate 			xtransfer.px_o_comp_list =
413*7656SSherry.Moore@Sun.COM 			    (id_t *)(uintptr_t)xtransfer32.px_o_comp_list;
4140Sstevel@tonic-gate 			break;
4150Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
4160Sstevel@tonic-gate 		default:
4170Sstevel@tonic-gate 		case DDI_MODEL_NONE:
4180Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &xtransfer,
4190Sstevel@tonic-gate 			    sizeof (pool_xtransfer_t), mode) != 0)
4200Sstevel@tonic-gate 				return (EFAULT);
4210Sstevel@tonic-gate 		}
4220Sstevel@tonic-gate 		/*
4230Sstevel@tonic-gate 		 * Copy in IDs to transfer from the userland
4240Sstevel@tonic-gate 		 */
4250Sstevel@tonic-gate 		if (xtransfer.px_o_complist_size > POOL_IDLIST_SIZE)
4260Sstevel@tonic-gate 			return (EINVAL);
4270Sstevel@tonic-gate 		id_buf = kmem_alloc(xtransfer.px_o_complist_size *
4280Sstevel@tonic-gate 		    sizeof (id_t), KM_SLEEP);
4290Sstevel@tonic-gate 		if (ddi_copyin((void *)xtransfer.px_o_comp_list, id_buf,
4300Sstevel@tonic-gate 		    xtransfer.px_o_complist_size * sizeof (id_t), mode) != 0) {
4310Sstevel@tonic-gate 			kmem_free(id_buf, xtransfer.px_o_complist_size *
4320Sstevel@tonic-gate 			    sizeof (id_t));
4330Sstevel@tonic-gate 			return (EFAULT);
4340Sstevel@tonic-gate 		}
4350Sstevel@tonic-gate 		if (pool_lock_intr() != 0) {
4360Sstevel@tonic-gate 			kmem_free(id_buf, xtransfer.px_o_complist_size *
4370Sstevel@tonic-gate 			    sizeof (id_t));
4380Sstevel@tonic-gate 			return (EINTR);
4390Sstevel@tonic-gate 		}
4400Sstevel@tonic-gate 		ret = pool_xtransfer(xtransfer.px_o_id_type,
4410Sstevel@tonic-gate 		    xtransfer.px_o_src_id, xtransfer.px_o_tgt_id,
4420Sstevel@tonic-gate 		    xtransfer.px_o_complist_size, id_buf);
4430Sstevel@tonic-gate 		pool_unlock();
4440Sstevel@tonic-gate 		kmem_free(id_buf, xtransfer.px_o_complist_size *
4450Sstevel@tonic-gate 		    sizeof (id_t));
4460Sstevel@tonic-gate 		break;
4470Sstevel@tonic-gate 	case POOL_BIND:
4480Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &bind,
4490Sstevel@tonic-gate 		    sizeof (pool_bind_t), mode) != 0)
4500Sstevel@tonic-gate 			return (EFAULT);
4510Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
4520Sstevel@tonic-gate 			return (EINTR);
4530Sstevel@tonic-gate 		ret = pool_bind(bind.pb_o_pool_id, bind.pb_o_id_type,
4540Sstevel@tonic-gate 		    bind.pb_o_id);
4550Sstevel@tonic-gate 		pool_unlock();
4560Sstevel@tonic-gate 		break;
4570Sstevel@tonic-gate 	case POOL_BINDQ:
4580Sstevel@tonic-gate 		if (ddi_copyin((void *)arg, &bindq,
4590Sstevel@tonic-gate 		    sizeof (pool_bindq_t), mode) != 0) {
4600Sstevel@tonic-gate 			return (EFAULT);
4610Sstevel@tonic-gate 		}
4620Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
4630Sstevel@tonic-gate 			return (EINTR);
4640Sstevel@tonic-gate 		if ((ret = pool_query_binding(bindq.pb_o_id_type,
4650Sstevel@tonic-gate 		    bindq.pb_o_id, &bindq.pb_i_id)) == 0 &&
4660Sstevel@tonic-gate 		    ddi_copyout(&bindq, (void *)arg,
4670Sstevel@tonic-gate 		    sizeof (pool_bindq_t), mode) != 0)
4680Sstevel@tonic-gate 			ret = EFAULT;
4690Sstevel@tonic-gate 		pool_unlock();
4700Sstevel@tonic-gate 		break;
4710Sstevel@tonic-gate 	case POOL_PROPGET:
4720Sstevel@tonic-gate 		switch (model) {
4730Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
4740Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
4750Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &propget32,
4760Sstevel@tonic-gate 			    sizeof (pool_propget32_t), mode) != 0)
4770Sstevel@tonic-gate 				return (EFAULT);
4780Sstevel@tonic-gate 			propget.pp_o_id = propget32.pp_o_id;
4790Sstevel@tonic-gate 			propget.pp_o_id_type = propget32.pp_o_id_type;
4800Sstevel@tonic-gate 			propget.pp_o_id_subtype = propget32.pp_o_id_subtype;
4810Sstevel@tonic-gate 			propget.pp_o_prop_name =
4820Sstevel@tonic-gate 			    (char *)(uintptr_t)propget32.pp_o_prop_name;
4830Sstevel@tonic-gate 			propget.pp_o_prop_name_size =
4840Sstevel@tonic-gate 			    propget32.pp_o_prop_name_size;
4850Sstevel@tonic-gate 			propget.pp_i_buf =
4860Sstevel@tonic-gate 			    (char *)(uintptr_t)propget32.pp_i_buf;
4870Sstevel@tonic-gate 			propget.pp_i_bufsize = propget32.pp_i_bufsize;
4880Sstevel@tonic-gate 			break;
4890Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
4900Sstevel@tonic-gate 		default:
4910Sstevel@tonic-gate 		case DDI_MODEL_NONE:
4920Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &propget,
4930Sstevel@tonic-gate 			    sizeof (pool_propget_t), mode) != 0)
4940Sstevel@tonic-gate 				return (EFAULT);
4950Sstevel@tonic-gate 		}
4960Sstevel@tonic-gate 		if (propget.pp_o_prop_name_size + 1 > POOL_PROPNAME_SIZE)
4970Sstevel@tonic-gate 			return (EINVAL);
4980Sstevel@tonic-gate 		prop_name = kmem_alloc(propget.pp_o_prop_name_size + 1,
4990Sstevel@tonic-gate 		    KM_SLEEP);
5000Sstevel@tonic-gate 		if (ddi_copyin(propget.pp_o_prop_name, prop_name,
5010Sstevel@tonic-gate 		    propget.pp_o_prop_name_size + 1, mode) != 0) {
5020Sstevel@tonic-gate 			kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
5030Sstevel@tonic-gate 			return (EFAULT);
5040Sstevel@tonic-gate 		}
5050Sstevel@tonic-gate 		list = NULL;
5060Sstevel@tonic-gate 		if (pool_lock_intr() != 0) {
5070Sstevel@tonic-gate 			kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
5080Sstevel@tonic-gate 			return (EINTR);
5090Sstevel@tonic-gate 		}
5100Sstevel@tonic-gate 		ret = pool_propget(prop_name, propget.pp_o_id_type,
5110Sstevel@tonic-gate 		    propget.pp_o_id_subtype, propget.pp_o_id, &list);
5120Sstevel@tonic-gate 		pool_unlock();
5130Sstevel@tonic-gate 		kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
5140Sstevel@tonic-gate 		if (ret != 0)
5150Sstevel@tonic-gate 			return (ret);
5160Sstevel@tonic-gate 		ret = nvlist_pack(list, &kbuf, &kbufsz, NV_ENCODE_NATIVE, 0);
5170Sstevel@tonic-gate 		if (ret != 0) {
5180Sstevel@tonic-gate 			nvlist_free(list);
5190Sstevel@tonic-gate 			return (ret);
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate 		switch (model) {
5220Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
5230Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
5240Sstevel@tonic-gate 			propget32.pp_i_bufsize = kbufsz;
5250Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)&propget32, (void *)arg,
5260Sstevel@tonic-gate 			    sizeof (pool_propget32_t), mode) != 0)
5270Sstevel@tonic-gate 				ret = EFAULT;
5280Sstevel@tonic-gate 			break;
5290Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
5300Sstevel@tonic-gate 		default:
5310Sstevel@tonic-gate 		case DDI_MODEL_NONE:
5320Sstevel@tonic-gate 			if (ddi_copyout(&propget, (void *)arg,
5330Sstevel@tonic-gate 			    sizeof (pool_propget_t), mode) != 0)
5340Sstevel@tonic-gate 				ret = EFAULT;
5350Sstevel@tonic-gate 		}
5360Sstevel@tonic-gate 		if (ret == 0) {
5370Sstevel@tonic-gate 			if (propget.pp_i_buf == NULL) {
5380Sstevel@tonic-gate 				ret = 0;
5390Sstevel@tonic-gate 			} else if (propget.pp_i_bufsize >= kbufsz) {
5400Sstevel@tonic-gate 				if (ddi_copyout(kbuf, propget.pp_i_buf,
5410Sstevel@tonic-gate 				    kbufsz, mode) != 0)
5420Sstevel@tonic-gate 					ret = EFAULT;
5430Sstevel@tonic-gate 			} else {
5440Sstevel@tonic-gate 				ret = ENOMEM;
5450Sstevel@tonic-gate 			}
5460Sstevel@tonic-gate 		}
5470Sstevel@tonic-gate 		kmem_free(kbuf, kbufsz);
5480Sstevel@tonic-gate 		nvlist_free(list);
5490Sstevel@tonic-gate 		break;
5500Sstevel@tonic-gate 	case POOL_PROPPUT:
5510Sstevel@tonic-gate 		switch (model) {
5520Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
5530Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
5540Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &propput32,
5550Sstevel@tonic-gate 			    sizeof (pool_propput32_t), mode) != 0)
5560Sstevel@tonic-gate 				return (EFAULT);
5570Sstevel@tonic-gate 			propput.pp_o_id_type = propput32.pp_o_id_type;
5580Sstevel@tonic-gate 			propput.pp_o_id_sub_type = propput32.pp_o_id_sub_type;
5590Sstevel@tonic-gate 			propput.pp_o_id = propput32.pp_o_id;
5600Sstevel@tonic-gate 			propput.pp_o_bufsize = propput32.pp_o_bufsize;
5610Sstevel@tonic-gate 			propput.pp_o_buf =
5620Sstevel@tonic-gate 			    (char *)(uintptr_t)propput32.pp_o_buf;
5630Sstevel@tonic-gate 			break;
5640Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
5650Sstevel@tonic-gate 		default:
5660Sstevel@tonic-gate 		case DDI_MODEL_NONE:
5670Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &propput,
5680Sstevel@tonic-gate 			    sizeof (pool_propput_t), mode) != 0)
5690Sstevel@tonic-gate 				return (EFAULT);
5700Sstevel@tonic-gate 		}
5710Sstevel@tonic-gate 		if (propput.pp_o_bufsize > POOL_PROPBUF_SIZE)
5720Sstevel@tonic-gate 			return (EINVAL);
5730Sstevel@tonic-gate 		listbuf = kmem_alloc(propput.pp_o_bufsize, KM_SLEEP);
5740Sstevel@tonic-gate 		if (ddi_copyin(propput.pp_o_buf, listbuf,
5750Sstevel@tonic-gate 		    propput.pp_o_bufsize, mode) != 0) {
5760Sstevel@tonic-gate 			kmem_free(listbuf, propput.pp_o_bufsize);
5770Sstevel@tonic-gate 			return (EFAULT);
5780Sstevel@tonic-gate 		}
5790Sstevel@tonic-gate 		if (nvlist_unpack(listbuf, propput.pp_o_bufsize,
580*7656SSherry.Moore@Sun.COM 		    &list, KM_SLEEP) != 0) {
5810Sstevel@tonic-gate 			kmem_free(listbuf, propput.pp_o_bufsize);
5820Sstevel@tonic-gate 			return (EFAULT);
5830Sstevel@tonic-gate 		}
5840Sstevel@tonic-gate 		if (pool_lock_intr() != 0) {
5850Sstevel@tonic-gate 			nvlist_free(list);
5860Sstevel@tonic-gate 			kmem_free(listbuf, propput.pp_o_bufsize);
5870Sstevel@tonic-gate 			return (EINTR);
5880Sstevel@tonic-gate 		}
5890Sstevel@tonic-gate 		/*
5900Sstevel@tonic-gate 		 * Extract the nvpair from the list. The list may
5910Sstevel@tonic-gate 		 * contain multiple properties.
5920Sstevel@tonic-gate 		 */
5930Sstevel@tonic-gate 		for (pair = nvlist_next_nvpair(list, NULL); pair != NULL;
5940Sstevel@tonic-gate 		    pair = nvlist_next_nvpair(list, pair)) {
5950Sstevel@tonic-gate 			if ((ret = pool_propput(propput.pp_o_id_type,
5960Sstevel@tonic-gate 			    propput.pp_o_id_sub_type,
5970Sstevel@tonic-gate 			    propput.pp_o_id, pair)) != 0)
5980Sstevel@tonic-gate 				break;
5990Sstevel@tonic-gate 		}
6000Sstevel@tonic-gate 		pool_unlock();
6010Sstevel@tonic-gate 		nvlist_free(list);
6020Sstevel@tonic-gate 		kmem_free(listbuf, propput.pp_o_bufsize);
6030Sstevel@tonic-gate 		break;
6040Sstevel@tonic-gate 	case POOL_PROPRM:
6050Sstevel@tonic-gate 		switch (model) {
6060Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
6070Sstevel@tonic-gate 		case DDI_MODEL_ILP32:
6080Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &proprm32,
6090Sstevel@tonic-gate 			    sizeof (pool_proprm32_t), mode) != 0)
6100Sstevel@tonic-gate 				return (EFAULT);
6110Sstevel@tonic-gate 			proprm.pp_o_id_type = proprm32.pp_o_id_type;
6120Sstevel@tonic-gate 			proprm.pp_o_id_sub_type = proprm32.pp_o_id_sub_type;
6130Sstevel@tonic-gate 			proprm.pp_o_id = proprm32.pp_o_id;
6140Sstevel@tonic-gate 			proprm.pp_o_prop_name_size =
6150Sstevel@tonic-gate 			    proprm32.pp_o_prop_name_size;
6160Sstevel@tonic-gate 			proprm.pp_o_prop_name =
6170Sstevel@tonic-gate 			    (void *)(uintptr_t)proprm32.pp_o_prop_name;
6180Sstevel@tonic-gate 			break;
6190Sstevel@tonic-gate #endif	/* _MULTI_DATAMODEL */
6200Sstevel@tonic-gate 		default:
6210Sstevel@tonic-gate 		case DDI_MODEL_NONE:
6220Sstevel@tonic-gate 			if (ddi_copyin((void *)arg, &proprm,
6230Sstevel@tonic-gate 			    sizeof (pool_proprm_t), mode) != 0)
6240Sstevel@tonic-gate 				return (EFAULT);
6250Sstevel@tonic-gate 		}
6260Sstevel@tonic-gate 		if (proprm.pp_o_prop_name_size + 1 > POOL_PROPNAME_SIZE)
6270Sstevel@tonic-gate 			return (EINVAL);
6280Sstevel@tonic-gate 		prop_name = kmem_alloc(proprm.pp_o_prop_name_size + 1,
6290Sstevel@tonic-gate 		    KM_SLEEP);
6300Sstevel@tonic-gate 		if (ddi_copyin(proprm.pp_o_prop_name, prop_name,
6310Sstevel@tonic-gate 		    proprm.pp_o_prop_name_size + 1, mode) != 0) {
6320Sstevel@tonic-gate 			kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
6330Sstevel@tonic-gate 			return (EFAULT);
6340Sstevel@tonic-gate 		}
6350Sstevel@tonic-gate 		if (pool_lock_intr() != 0) {
6360Sstevel@tonic-gate 			kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
6370Sstevel@tonic-gate 			return (EINTR);
6380Sstevel@tonic-gate 		}
6390Sstevel@tonic-gate 		ret = pool_proprm(proprm.pp_o_id_type,
6400Sstevel@tonic-gate 		    proprm.pp_o_id_sub_type, proprm.pp_o_id, prop_name);
6410Sstevel@tonic-gate 		pool_unlock();
6420Sstevel@tonic-gate 		kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
6430Sstevel@tonic-gate 		break;
6440Sstevel@tonic-gate 	case POOL_COMMIT:
6450Sstevel@tonic-gate 		if (pool_lock_intr() != 0)
6460Sstevel@tonic-gate 			return (EINTR);
6470Sstevel@tonic-gate 		ret = pool_commit((int)arg);
6480Sstevel@tonic-gate 		pool_unlock();
6490Sstevel@tonic-gate 		break;
6500Sstevel@tonic-gate 	default:
6510Sstevel@tonic-gate 		return (EINVAL);
6520Sstevel@tonic-gate 	}
6530Sstevel@tonic-gate 	return (ret);
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate static struct cb_ops pool_cb_ops = {
6570Sstevel@tonic-gate 	pool_open,		/* open */
6580Sstevel@tonic-gate 	pool_close,		/* close */
6590Sstevel@tonic-gate 	nodev,			/* strategy */
6600Sstevel@tonic-gate 	nodev,			/* print */
6610Sstevel@tonic-gate 	nodev,			/* dump */
6620Sstevel@tonic-gate 	nodev,			/* read */
6630Sstevel@tonic-gate 	nodev,			/* write */
6640Sstevel@tonic-gate 	pool_ioctl,		/* ioctl */
6650Sstevel@tonic-gate 	nodev,			/* devmap */
6660Sstevel@tonic-gate 	nodev,			/* mmap */
6670Sstevel@tonic-gate 	nodev,			/* segmap */
6680Sstevel@tonic-gate 	nochpoll,		/* poll */
6690Sstevel@tonic-gate 	nodev,			/* cb_prop_op */
6700Sstevel@tonic-gate 	(struct streamtab *)0,	/* streamtab */
6710Sstevel@tonic-gate 	D_NEW | D_MP		/* driver compatibility flags */
6720Sstevel@tonic-gate };
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate static struct dev_ops pool_ops = {
6750Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev */
6760Sstevel@tonic-gate 	0,			/* refcnt */
6770Sstevel@tonic-gate 	pool_info,		/* info */
6780Sstevel@tonic-gate 	nulldev,		/* identify */
6790Sstevel@tonic-gate 	nulldev,		/* probe */
6800Sstevel@tonic-gate 	pool_attach,		/* attach */
6810Sstevel@tonic-gate 	pool_detach,		/* detach */
6820Sstevel@tonic-gate 	nodev,			/* reset */
6830Sstevel@tonic-gate 	&pool_cb_ops,		/* cb_ops */
6840Sstevel@tonic-gate 	(struct bus_ops *)NULL,	/* bus_ops */
685*7656SSherry.Moore@Sun.COM 	nulldev,		/* power */
686*7656SSherry.Moore@Sun.COM 	ddi_quiesce_not_needed,		/* quiesce */
6870Sstevel@tonic-gate };
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate /*
6900Sstevel@tonic-gate  * Module linkage information for the kernel
6910Sstevel@tonic-gate  */
6920Sstevel@tonic-gate static struct modldrv modldrv = {
6930Sstevel@tonic-gate 	&mod_driverops,		/* this one is a pseudo driver */
694*7656SSherry.Moore@Sun.COM 	"pool driver",
6950Sstevel@tonic-gate 	&pool_ops
6960Sstevel@tonic-gate };
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate static struct modlinkage modlinkage = {
6990Sstevel@tonic-gate 	MODREV_1,
7000Sstevel@tonic-gate 	&modldrv,
7010Sstevel@tonic-gate 	NULL
7020Sstevel@tonic-gate };
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate int
_init(void)7050Sstevel@tonic-gate _init(void)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate 	return (mod_install(&modlinkage));
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate int
_fini(void)7110Sstevel@tonic-gate _fini(void)
7120Sstevel@tonic-gate {
7130Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
7140Sstevel@tonic-gate }
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate int
_info(struct modinfo * modinfop)7170Sstevel@tonic-gate _info(struct modinfo *modinfop)
7180Sstevel@tonic-gate {
7190Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
7200Sstevel@tonic-gate }
721