/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/pool_impl.h>
/*
* The kernel pools subsystem is accessed and manipulated through the pool
* processes can comminicate with pools through ioctls on these devices.
*
* The poolctl device (POOL_CTL_PARENT) can be used to modify and take
* snapshot of the current configuration. Only one process on the system
* can have it open at any given time. This device is also used to enable
* or disable pools. If pools are disabled, the pool driver can be unloaded
* and completely removed from the system.
*
* The pool "info" device (POOL_INFO_PARENT) can only be used to obtain
* While some reconfiguration transaction via the poolctl device is in
* progress, all processes using this "info" device will be provided with
* the snapshot taken at the beginning of that transaction.
*/
#define POOL_CTL_PARENT 0
/*ARGSUSED*/
static int
{
switch (infocmd) {
case DDI_INFO_DEVT2DEVINFO:
error = DDI_SUCCESS;
break;
case DDI_INFO_DEVT2INSTANCE:
/*
* All dev_t's map to the same, single instance.
*/
error = DDI_SUCCESS;
break;
default:
break;
}
return (error);
}
static int
{
switch (cmd) {
case DDI_DETACH:
pool_lock();
if (pool_state == POOL_ENABLED) {
ret = DDI_FAILURE;
pool_unlock();
break;
}
pool_unlock();
break;
default:
ret = DDI_FAILURE;
}
return (ret);
}
static int
{
switch (cmd) {
case DDI_ATTACH:
return (DDI_FAILURE);
return (DDI_FAILURE);
}
break;
case DDI_RESUME:
break;
default:
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* There is only one instance of the pool control device, poolctl,
* and multiple instances of the pool info device, pool.
*/
/*ARGSUSED*/
static int
{
return (EINVAL);
switch (minor) {
case POOL_CTL_PARENT:
if (secpolicy_pool(CRED()) != 0)
return (EPERM);
if (pool_lock_intr() != 0)
return (EINTR);
if (pool_openctl == 1) {
pool_unlock();
return (EBUSY);
}
pool_openctl = 1;
pool_unlock();
break;
case POOL_INFO_PARENT:
break;
default:
return (ENXIO);
}
return (0);
}
/*ARGSUSED*/
static int
{
return (EINVAL);
/*
* We could be closing the poolctl device without finishing
* the commit transaction first, so do that now.
*/
pool_lock();
(void) pool_commit(0); /* cannot fail since arg is 0 */
pool_openctl = 0;
pool_unlock();
}
return (0);
}
/*
* Main pool interface.
*/
/* ARGSUSED4 */
static int
int *rvalp)
{
#ifdef _MULTI_DATAMODEL
#endif /* _MULTI_DATAMODEL */
int snapshot = 0;
char *prop_name;
char *listbuf;
int ret = 0;
/*
* Check basic permissions first.
*/
switch (cmd) {
case POOL_STATUS:
case POOL_CREATE:
case POOL_ASSOC:
case POOL_DISSOC:
case POOL_DESTROY:
case POOL_TRANSFER:
case POOL_XTRANSFER:
case POOL_PROPPUT:
case POOL_PROPRM:
case POOL_COMMIT:
if (minor != POOL_CTL_PARENT)
return (EINVAL);
/*FALLTHROUGH*/
case POOL_BIND:
if (secpolicy_pool(CRED()) != 0)
return (EPERM);
break;
}
switch (cmd) {
case POOL_STATUS:
sizeof (pool_status_t), mode) != 0)
return (EFAULT);
if (pool_lock_intr() != 0)
return (EINTR);
pool_unlock();
break;
case POOL_STATUSQ:
/*
* No need to grab pool_lock() to look at the current state.
*/
sizeof (pool_status_t), mode) != 0)
return (EFAULT);
break;
case POOL_QUERY:
switch (model) {
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
sizeof (pool_query32_t), mode) != 0)
return (EFAULT);
break;
#endif /* _MULTI_DATAMODEL */
default:
case DDI_MODEL_NONE:
sizeof (pool_query_t), mode) != 0)
return (EFAULT);
}
if (pool_lock_intr() != 0)
return (EINTR);
if (pool_state == POOL_DISABLED) {
pool_unlock();
return (ENOTACTIVE);
}
/*
* Return last snapshot if some
* transaction is still in progress
*/
pool_unlock();
return (ENOMEM);
}
snapshot = 1;
} else if (query.pq_io_bufsize != 0) {
pool_unlock();
return (ENOMEM);
}
} else {
}
if (ret == 0) {
switch (model) {
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
sizeof (pool_query32_t), mode) != 0)
break;
#endif /* _MULTI_DATAMODEL */
default:
case DDI_MODEL_NONE:
sizeof (pool_query_t), mode) != 0)
}
}
pool_unlock();
if (snapshot == 0)
break;
case POOL_CREATE:
if (ddi_copyin((void *)arg,
return (EFAULT);
if (pool_lock_intr() != 0)
return (EINTR);
pool_unlock();
sizeof (pool_create_t), mode) != 0)
break;
case POOL_ASSOC:
sizeof (pool_assoc_t), mode) != 0)
return (EFAULT);
if (pool_lock_intr() != 0)
return (EINTR);
pool_unlock();
break;
case POOL_DISSOC:
sizeof (pool_dissoc_t), mode) != 0)
return (EFAULT);
if (pool_lock_intr() != 0)
return (EINTR);
pool_unlock();
break;
case POOL_DESTROY:
sizeof (pool_destroy_t), mode) != 0)
return (EFAULT);
if (pool_lock_intr() != 0)
return (EINTR);
pool_unlock();
break;
case POOL_TRANSFER:
sizeof (pool_transfer_t), mode) != 0)
return (EFAULT);
if (pool_lock_intr() != 0)
return (EINTR);
pool_unlock();
break;
case POOL_XTRANSFER:
switch (model) {
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
sizeof (pool_xtransfer32_t), mode) != 0)
return (EFAULT);
break;
#endif /* _MULTI_DATAMODEL */
default:
case DDI_MODEL_NONE:
sizeof (pool_xtransfer_t), mode) != 0)
return (EFAULT);
}
/*
* Copy in IDs to transfer from the userland
*/
return (EINVAL);
sizeof (id_t));
return (EFAULT);
}
if (pool_lock_intr() != 0) {
sizeof (id_t));
return (EINTR);
}
pool_unlock();
sizeof (id_t));
break;
case POOL_BIND:
sizeof (pool_bind_t), mode) != 0)
return (EFAULT);
if (pool_lock_intr() != 0)
return (EINTR);
pool_unlock();
break;
case POOL_BINDQ:
sizeof (pool_bindq_t), mode) != 0) {
return (EFAULT);
}
if (pool_lock_intr() != 0)
return (EINTR);
sizeof (pool_bindq_t), mode) != 0)
pool_unlock();
break;
case POOL_PROPGET:
switch (model) {
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
sizeof (pool_propget32_t), mode) != 0)
return (EFAULT);
break;
#endif /* _MULTI_DATAMODEL */
default:
case DDI_MODEL_NONE:
sizeof (pool_propget_t), mode) != 0)
return (EFAULT);
}
return (EINVAL);
KM_SLEEP);
return (EFAULT);
}
if (pool_lock_intr() != 0) {
return (EINTR);
}
pool_unlock();
if (ret != 0)
return (ret);
if (ret != 0) {
return (ret);
}
switch (model) {
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
sizeof (pool_propget32_t), mode) != 0)
break;
#endif /* _MULTI_DATAMODEL */
default:
case DDI_MODEL_NONE:
sizeof (pool_propget_t), mode) != 0)
}
if (ret == 0) {
ret = 0;
} else {
}
}
break;
case POOL_PROPPUT:
switch (model) {
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
sizeof (pool_propput32_t), mode) != 0)
return (EFAULT);
break;
#endif /* _MULTI_DATAMODEL */
default:
case DDI_MODEL_NONE:
sizeof (pool_propput_t), mode) != 0)
return (EFAULT);
}
return (EINVAL);
return (EFAULT);
}
return (EFAULT);
}
if (pool_lock_intr() != 0) {
return (EINTR);
}
/*
* Extract the nvpair from the list. The list may
* contain multiple properties.
*/
break;
}
pool_unlock();
break;
case POOL_PROPRM:
switch (model) {
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
sizeof (pool_proprm32_t), mode) != 0)
return (EFAULT);
break;
#endif /* _MULTI_DATAMODEL */
default:
case DDI_MODEL_NONE:
sizeof (pool_proprm_t), mode) != 0)
return (EFAULT);
}
return (EINVAL);
KM_SLEEP);
return (EFAULT);
}
if (pool_lock_intr() != 0) {
return (EINTR);
}
pool_unlock();
break;
case POOL_COMMIT:
if (pool_lock_intr() != 0)
return (EINTR);
pool_unlock();
break;
default:
return (EINVAL);
}
return (ret);
}
pool_open, /* open */
pool_close, /* close */
nodev, /* strategy */
nodev, /* print */
nodev, /* dump */
nodev, /* read */
nodev, /* write */
pool_ioctl, /* ioctl */
nodev, /* devmap */
nodev, /* mmap */
nodev, /* segmap */
nochpoll, /* poll */
nodev, /* cb_prop_op */
(struct streamtab *)0, /* streamtab */
};
DEVO_REV, /* devo_rev */
0, /* refcnt */
pool_info, /* info */
nulldev, /* identify */
nulldev, /* probe */
pool_attach, /* attach */
pool_detach, /* detach */
nodev, /* reset */
&pool_cb_ops, /* cb_ops */
nulldev, /* power */
ddi_quiesce_not_needed, /* quiesce */
};
/*
* Module linkage information for the kernel
*/
&mod_driverops, /* this one is a pseudo driver */
"pool driver",
};
&modldrv,
};
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
{
}