summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/devpool.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/uts/common/io/devpool.c
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/uts/common/io/devpool.c')
-rw-r--r--usr/src/uts/common/io/devpool.c721
1 files changed, 721 insertions, 0 deletions
diff --git a/usr/src/uts/common/io/devpool.c b/usr/src/uts/common/io/devpool.c
new file mode 100644
index 0000000000..246aef1bfc
--- /dev/null
+++ b/usr/src/uts/common/io/devpool.c
@@ -0,0 +1,721 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/errno.h>
+#include <sys/open.h>
+#include <sys/cred.h>
+#include <sys/conf.h>
+#include <sys/modctl.h>
+#include <sys/stat.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/policy.h>
+#include <sys/pool.h>
+#include <sys/pool_impl.h>
+
+/*
+ * The kernel pools subsystem is accessed and manipulated through the pool
+ * device, which has two minor nodes /dev/pool, and /dev/poolctl. User
+ * 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
+ * snapshots of the current configuration and change/query pool bindings.
+ * 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
+#define POOL_INFO_PARENT 1
+
+static dev_info_t *pool_devi; /* pool device information */
+static int pool_openctl; /* poolctl device is already open */
+
+/*ARGSUSED*/
+static int
+pool_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
+{
+ int error = DDI_FAILURE;
+
+ switch (infocmd) {
+ case DDI_INFO_DEVT2DEVINFO:
+ *result = pool_devi;
+ error = DDI_SUCCESS;
+ break;
+ case DDI_INFO_DEVT2INSTANCE:
+ /*
+ * All dev_t's map to the same, single instance.
+ */
+ *result = NULL;
+ error = DDI_SUCCESS;
+ break;
+ default:
+ break;
+ }
+ return (error);
+}
+
+static int
+pool_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
+{
+ int ret = DDI_SUCCESS;
+
+ switch (cmd) {
+ case DDI_DETACH:
+ pool_lock();
+ if (pool_state == POOL_ENABLED) {
+ ret = DDI_FAILURE;
+ pool_unlock();
+ break;
+ }
+ ddi_remove_minor_node(devi, NULL);
+ pool_devi = NULL;
+ pool_unlock();
+ break;
+ default:
+ ret = DDI_FAILURE;
+ }
+ return (ret);
+}
+
+static int
+pool_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
+{
+ switch (cmd) {
+ case DDI_ATTACH:
+ if (pool_devi != NULL)
+ return (DDI_FAILURE);
+ if (ddi_create_minor_node(devi, "poolctl", S_IFCHR,
+ POOL_CTL_PARENT, DDI_PSEUDO, 0) == DDI_FAILURE ||
+ ddi_create_minor_node(devi, "pool", S_IFCHR,
+ POOL_INFO_PARENT, DDI_PSEUDO, 0) == DDI_FAILURE) {
+ ddi_remove_minor_node(devi, NULL);
+ return (DDI_FAILURE);
+ }
+ pool_devi = devi;
+ ddi_report_dev(devi);
+ 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
+pool_open(dev_t *devp, int flag, int otype, cred_t *credp)
+{
+ minor_t minor = getminor(*devp);
+
+ if (otype != OTYP_CHR)
+ 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
+pool_close(dev_t dev, int flag, int otype, cred_t *credp)
+{
+ if (otype != OTYP_CHR)
+ return (EINVAL);
+ if (getminor(dev) == 0) {
+ /*
+ * 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
+pool_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
+ int *rvalp)
+{
+ pool_xtransfer_t xtransfer;
+ pool_transfer_t transfer;
+ pool_destroy_t destroy;
+ pool_propget_t propget;
+ pool_propput_t propput;
+ pool_proprm_t proprm;
+ pool_status_t status;
+ pool_dissoc_t dissoc;
+ pool_create_t create;
+ pool_assoc_t assoc;
+ pool_bindq_t bindq;
+ pool_query_t query;
+ pool_bind_t bind;
+#ifdef _MULTI_DATAMODEL
+ pool_xtransfer32_t xtransfer32;
+ pool_propput32_t propput32;
+ pool_propget32_t propget32;
+ pool_proprm32_t proprm32;
+ pool_query32_t query32;
+#endif /* _MULTI_DATAMODEL */
+ char *kbuf = NULL;
+ size_t kbufsz = 0;
+ int snapshot = 0;
+ char *prop_name;
+ size_t size = 0;
+ nvlist_t *list;
+ nvpair_t *pair;
+ char *listbuf;
+ minor_t minor;
+ uint_t model;
+ id_t *id_buf;
+ int ret = 0;
+
+ model = ddi_model_convert_from(mode & FMODELS);
+ minor = getminor(dev);
+
+ /*
+ * 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:
+ if (ddi_copyin((void *)arg, &status,
+ sizeof (pool_status_t), mode) != 0)
+ return (EFAULT);
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ ret = pool_status(status.ps_io_state);
+ pool_unlock();
+ break;
+ case POOL_STATUSQ:
+ /*
+ * No need to grab pool_lock() to look at the current state.
+ */
+ status.ps_io_state = pool_state;
+ if (ddi_copyout(&status, (void *)arg,
+ sizeof (pool_status_t), mode) != 0)
+ return (EFAULT);
+ break;
+ case POOL_QUERY:
+ switch (model) {
+#ifdef _MULTI_DATAMODEL
+ case DDI_MODEL_ILP32:
+ if (ddi_copyin((void *)arg, &query32,
+ sizeof (pool_query32_t), mode) != 0)
+ return (EFAULT);
+ query.pq_io_bufsize = query32.pq_io_bufsize;
+ query.pq_io_buf = (char *)(uintptr_t)query32.pq_io_buf;
+ break;
+#endif /* _MULTI_DATAMODEL */
+ default:
+ case DDI_MODEL_NONE:
+ if (ddi_copyin((void *)arg, &query,
+ sizeof (pool_query_t), mode) != 0)
+ return (EFAULT);
+ }
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ if (pool_state == POOL_DISABLED) {
+ pool_unlock();
+ return (ENOTACTIVE);
+ }
+ if (minor != 0 && pool_buf != NULL) {
+ /*
+ * Return last snapshot if some
+ * transaction is still in progress
+ */
+ if (kbufsz != 0 && pool_bufsz > kbufsz) {
+ pool_unlock();
+ return (ENOMEM);
+ }
+ kbuf = pool_buf;
+ kbufsz = size = pool_bufsz;
+ snapshot = 1;
+ } else if (query.pq_io_bufsize != 0) {
+ kbufsz = query.pq_io_bufsize;
+ kbuf = kmem_alloc(kbufsz, KM_NOSLEEP);
+ if (kbuf == NULL) {
+ pool_unlock();
+ return (ENOMEM);
+ }
+ ret = pool_pack_conf(kbuf, kbufsz, &size);
+ } else {
+ ret = pool_pack_conf(NULL, 0, &size);
+ }
+ if (ret == 0) {
+ switch (model) {
+#ifdef _MULTI_DATAMODEL
+ case DDI_MODEL_ILP32:
+ query32.pq_io_bufsize = size;
+ if (ddi_copyout((caddr_t)&query32, (void *)arg,
+ sizeof (pool_query32_t), mode) != 0)
+ ret = EFAULT;
+ break;
+#endif /* _MULTI_DATAMODEL */
+ default:
+ case DDI_MODEL_NONE:
+ query.pq_io_bufsize = size;
+ if (ddi_copyout(&query, (void *)arg,
+ sizeof (pool_query_t), mode) != 0)
+ ret = EFAULT;
+ }
+ if (ret == 0 && query.pq_io_buf != NULL &&
+ ddi_copyout(kbuf, query.pq_io_buf, size, mode) != 0)
+ ret = EFAULT;
+ }
+ pool_unlock();
+ if (snapshot == 0)
+ kmem_free(kbuf, kbufsz);
+ break;
+ case POOL_CREATE:
+ if (ddi_copyin((void *)arg,
+ &create, sizeof (pool_create_t), mode) != 0)
+ return (EFAULT);
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ ret = pool_create(create.pc_o_type,
+ create.pc_o_sub_type, &create.pc_i_id);
+ pool_unlock();
+ if (ret == 0 && ddi_copyout(&create, (void *)arg,
+ sizeof (pool_create_t), mode) != 0)
+ ret = EFAULT;
+ break;
+ case POOL_ASSOC:
+ if (ddi_copyin((void *)arg, &assoc,
+ sizeof (pool_assoc_t), mode) != 0)
+ return (EFAULT);
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ ret = pool_assoc(assoc.pa_o_pool_id,
+ assoc.pa_o_id_type, assoc.pa_o_res_id);
+ pool_unlock();
+ break;
+ case POOL_DISSOC:
+ if (ddi_copyin((void *)arg, &dissoc,
+ sizeof (pool_dissoc_t), mode) != 0)
+ return (EFAULT);
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ ret = pool_dissoc(dissoc.pd_o_pool_id, dissoc.pd_o_id_type);
+ pool_unlock();
+ break;
+ case POOL_DESTROY:
+ if (ddi_copyin((void *)arg, &destroy,
+ sizeof (pool_destroy_t), mode) != 0)
+ return (EFAULT);
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ ret = pool_destroy(destroy.pd_o_type, destroy.pd_o_sub_type,
+ destroy.pd_o_id);
+ pool_unlock();
+ break;
+ case POOL_TRANSFER:
+ if (ddi_copyin((void *)arg, &transfer,
+ sizeof (pool_transfer_t), mode) != 0)
+ return (EFAULT);
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ ret = pool_transfer(transfer.pt_o_id_type, transfer.pt_o_src_id,
+ transfer.pt_o_tgt_id, transfer.pt_o_qty);
+ pool_unlock();
+ break;
+ case POOL_XTRANSFER:
+ switch (model) {
+#ifdef _MULTI_DATAMODEL
+ case DDI_MODEL_ILP32:
+ if (ddi_copyin((void *)arg, &xtransfer32,
+ sizeof (pool_xtransfer32_t), mode) != 0)
+ return (EFAULT);
+ xtransfer.px_o_id_type = xtransfer32.px_o_id_type;
+ xtransfer.px_o_src_id = xtransfer32.px_o_src_id;
+ xtransfer.px_o_tgt_id = xtransfer32.px_o_tgt_id;
+ xtransfer.px_o_complist_size =
+ xtransfer32.px_o_complist_size;
+ xtransfer.px_o_comp_list =
+ (id_t *)(uintptr_t)xtransfer32.px_o_comp_list;
+ break;
+#endif /* _MULTI_DATAMODEL */
+ default:
+ case DDI_MODEL_NONE:
+ if (ddi_copyin((void *)arg, &xtransfer,
+ sizeof (pool_xtransfer_t), mode) != 0)
+ return (EFAULT);
+ }
+ /*
+ * Copy in IDs to transfer from the userland
+ */
+ if (xtransfer.px_o_complist_size > POOL_IDLIST_SIZE)
+ return (EINVAL);
+ id_buf = kmem_alloc(xtransfer.px_o_complist_size *
+ sizeof (id_t), KM_SLEEP);
+ if (ddi_copyin((void *)xtransfer.px_o_comp_list, id_buf,
+ xtransfer.px_o_complist_size * sizeof (id_t), mode) != 0) {
+ kmem_free(id_buf, xtransfer.px_o_complist_size *
+ sizeof (id_t));
+ return (EFAULT);
+ }
+ if (pool_lock_intr() != 0) {
+ kmem_free(id_buf, xtransfer.px_o_complist_size *
+ sizeof (id_t));
+ return (EINTR);
+ }
+ ret = pool_xtransfer(xtransfer.px_o_id_type,
+ xtransfer.px_o_src_id, xtransfer.px_o_tgt_id,
+ xtransfer.px_o_complist_size, id_buf);
+ pool_unlock();
+ kmem_free(id_buf, xtransfer.px_o_complist_size *
+ sizeof (id_t));
+ break;
+ case POOL_BIND:
+ if (ddi_copyin((void *)arg, &bind,
+ sizeof (pool_bind_t), mode) != 0)
+ return (EFAULT);
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ ret = pool_bind(bind.pb_o_pool_id, bind.pb_o_id_type,
+ bind.pb_o_id);
+ pool_unlock();
+ break;
+ case POOL_BINDQ:
+ if (ddi_copyin((void *)arg, &bindq,
+ sizeof (pool_bindq_t), mode) != 0) {
+ return (EFAULT);
+ }
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ if ((ret = pool_query_binding(bindq.pb_o_id_type,
+ bindq.pb_o_id, &bindq.pb_i_id)) == 0 &&
+ ddi_copyout(&bindq, (void *)arg,
+ sizeof (pool_bindq_t), mode) != 0)
+ ret = EFAULT;
+ pool_unlock();
+ break;
+ case POOL_PROPGET:
+ switch (model) {
+#ifdef _MULTI_DATAMODEL
+ case DDI_MODEL_ILP32:
+ if (ddi_copyin((void *)arg, &propget32,
+ sizeof (pool_propget32_t), mode) != 0)
+ return (EFAULT);
+ propget.pp_o_id = propget32.pp_o_id;
+ propget.pp_o_id_type = propget32.pp_o_id_type;
+ propget.pp_o_id_subtype = propget32.pp_o_id_subtype;
+ propget.pp_o_prop_name =
+ (char *)(uintptr_t)propget32.pp_o_prop_name;
+ propget.pp_o_prop_name_size =
+ propget32.pp_o_prop_name_size;
+ propget.pp_i_buf =
+ (char *)(uintptr_t)propget32.pp_i_buf;
+ propget.pp_i_bufsize = propget32.pp_i_bufsize;
+ break;
+#endif /* _MULTI_DATAMODEL */
+ default:
+ case DDI_MODEL_NONE:
+ if (ddi_copyin((void *)arg, &propget,
+ sizeof (pool_propget_t), mode) != 0)
+ return (EFAULT);
+ }
+ if (propget.pp_o_prop_name_size + 1 > POOL_PROPNAME_SIZE)
+ return (EINVAL);
+ prop_name = kmem_alloc(propget.pp_o_prop_name_size + 1,
+ KM_SLEEP);
+ if (ddi_copyin(propget.pp_o_prop_name, prop_name,
+ propget.pp_o_prop_name_size + 1, mode) != 0) {
+ kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
+ return (EFAULT);
+ }
+ list = NULL;
+ if (pool_lock_intr() != 0) {
+ kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
+ return (EINTR);
+ }
+ ret = pool_propget(prop_name, propget.pp_o_id_type,
+ propget.pp_o_id_subtype, propget.pp_o_id, &list);
+ pool_unlock();
+ kmem_free(prop_name, propget.pp_o_prop_name_size + 1);
+ if (ret != 0)
+ return (ret);
+ ret = nvlist_pack(list, &kbuf, &kbufsz, NV_ENCODE_NATIVE, 0);
+ if (ret != 0) {
+ nvlist_free(list);
+ return (ret);
+ }
+ switch (model) {
+#ifdef _MULTI_DATAMODEL
+ case DDI_MODEL_ILP32:
+ propget32.pp_i_bufsize = kbufsz;
+ if (ddi_copyout((caddr_t)&propget32, (void *)arg,
+ sizeof (pool_propget32_t), mode) != 0)
+ ret = EFAULT;
+ break;
+#endif /* _MULTI_DATAMODEL */
+ default:
+ case DDI_MODEL_NONE:
+ if (ddi_copyout(&propget, (void *)arg,
+ sizeof (pool_propget_t), mode) != 0)
+ ret = EFAULT;
+ }
+ if (ret == 0) {
+ if (propget.pp_i_buf == NULL) {
+ ret = 0;
+ } else if (propget.pp_i_bufsize >= kbufsz) {
+ if (ddi_copyout(kbuf, propget.pp_i_buf,
+ kbufsz, mode) != 0)
+ ret = EFAULT;
+ } else {
+ ret = ENOMEM;
+ }
+ }
+ kmem_free(kbuf, kbufsz);
+ nvlist_free(list);
+ break;
+ case POOL_PROPPUT:
+ switch (model) {
+#ifdef _MULTI_DATAMODEL
+ case DDI_MODEL_ILP32:
+ if (ddi_copyin((void *)arg, &propput32,
+ sizeof (pool_propput32_t), mode) != 0)
+ return (EFAULT);
+ propput.pp_o_id_type = propput32.pp_o_id_type;
+ propput.pp_o_id_sub_type = propput32.pp_o_id_sub_type;
+ propput.pp_o_id = propput32.pp_o_id;
+ propput.pp_o_bufsize = propput32.pp_o_bufsize;
+ propput.pp_o_buf =
+ (char *)(uintptr_t)propput32.pp_o_buf;
+ break;
+#endif /* _MULTI_DATAMODEL */
+ default:
+ case DDI_MODEL_NONE:
+ if (ddi_copyin((void *)arg, &propput,
+ sizeof (pool_propput_t), mode) != 0)
+ return (EFAULT);
+ }
+ if (propput.pp_o_bufsize > POOL_PROPBUF_SIZE)
+ return (EINVAL);
+ listbuf = kmem_alloc(propput.pp_o_bufsize, KM_SLEEP);
+ if (ddi_copyin(propput.pp_o_buf, listbuf,
+ propput.pp_o_bufsize, mode) != 0) {
+ kmem_free(listbuf, propput.pp_o_bufsize);
+ return (EFAULT);
+ }
+ if (nvlist_unpack(listbuf, propput.pp_o_bufsize,
+ &list, KM_SLEEP) != 0) {
+ kmem_free(listbuf, propput.pp_o_bufsize);
+ return (EFAULT);
+ }
+ if (pool_lock_intr() != 0) {
+ nvlist_free(list);
+ kmem_free(listbuf, propput.pp_o_bufsize);
+ return (EINTR);
+ }
+ /*
+ * Extract the nvpair from the list. The list may
+ * contain multiple properties.
+ */
+ for (pair = nvlist_next_nvpair(list, NULL); pair != NULL;
+ pair = nvlist_next_nvpair(list, pair)) {
+ if ((ret = pool_propput(propput.pp_o_id_type,
+ propput.pp_o_id_sub_type,
+ propput.pp_o_id, pair)) != 0)
+ break;
+ }
+ pool_unlock();
+ nvlist_free(list);
+ kmem_free(listbuf, propput.pp_o_bufsize);
+ break;
+ case POOL_PROPRM:
+ switch (model) {
+#ifdef _MULTI_DATAMODEL
+ case DDI_MODEL_ILP32:
+ if (ddi_copyin((void *)arg, &proprm32,
+ sizeof (pool_proprm32_t), mode) != 0)
+ return (EFAULT);
+ proprm.pp_o_id_type = proprm32.pp_o_id_type;
+ proprm.pp_o_id_sub_type = proprm32.pp_o_id_sub_type;
+ proprm.pp_o_id = proprm32.pp_o_id;
+ proprm.pp_o_prop_name_size =
+ proprm32.pp_o_prop_name_size;
+ proprm.pp_o_prop_name =
+ (void *)(uintptr_t)proprm32.pp_o_prop_name;
+ break;
+#endif /* _MULTI_DATAMODEL */
+ default:
+ case DDI_MODEL_NONE:
+ if (ddi_copyin((void *)arg, &proprm,
+ sizeof (pool_proprm_t), mode) != 0)
+ return (EFAULT);
+ }
+ if (proprm.pp_o_prop_name_size + 1 > POOL_PROPNAME_SIZE)
+ return (EINVAL);
+ prop_name = kmem_alloc(proprm.pp_o_prop_name_size + 1,
+ KM_SLEEP);
+ if (ddi_copyin(proprm.pp_o_prop_name, prop_name,
+ proprm.pp_o_prop_name_size + 1, mode) != 0) {
+ kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
+ return (EFAULT);
+ }
+ if (pool_lock_intr() != 0) {
+ kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
+ return (EINTR);
+ }
+ ret = pool_proprm(proprm.pp_o_id_type,
+ proprm.pp_o_id_sub_type, proprm.pp_o_id, prop_name);
+ pool_unlock();
+ kmem_free(prop_name, proprm.pp_o_prop_name_size + 1);
+ break;
+ case POOL_COMMIT:
+ if (pool_lock_intr() != 0)
+ return (EINTR);
+ ret = pool_commit((int)arg);
+ pool_unlock();
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (ret);
+}
+
+static struct cb_ops pool_cb_ops = {
+ 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 */
+ D_NEW | D_MP /* driver compatibility flags */
+};
+
+static struct dev_ops pool_ops = {
+ 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 */
+ (struct bus_ops *)NULL, /* bus_ops */
+ nulldev /* power */
+};
+
+/*
+ * Module linkage information for the kernel
+ */
+static struct modldrv modldrv = {
+ &mod_driverops, /* this one is a pseudo driver */
+ "pool driver %I%",
+ &pool_ops
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1,
+ &modldrv,
+ NULL
+};
+
+int
+_init(void)
+{
+ return (mod_install(&modlinkage));
+}
+
+int
+_fini(void)
+{
+ return (mod_remove(&modlinkage));
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
+}