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