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 <assert.h> 30*0Sstevel@tonic-gate #include <errno.h> 31*0Sstevel@tonic-gate #include <exacct.h> 32*0Sstevel@tonic-gate #include <fcntl.h> 33*0Sstevel@tonic-gate #include <libnvpair.h> 34*0Sstevel@tonic-gate #include <limits.h> 35*0Sstevel@tonic-gate #include <poll.h> 36*0Sstevel@tonic-gate #include <pool.h> 37*0Sstevel@tonic-gate #include <stdlib.h> 38*0Sstevel@tonic-gate #include <stdio.h> 39*0Sstevel@tonic-gate #include <string.h> 40*0Sstevel@tonic-gate #include <strings.h> 41*0Sstevel@tonic-gate #include <stropts.h> 42*0Sstevel@tonic-gate #include <thread.h> 43*0Sstevel@tonic-gate #include <time.h> 44*0Sstevel@tonic-gate #include <unistd.h> 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #include <libxml/tree.h> 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include <sys/mman.h> 49*0Sstevel@tonic-gate #include <sys/pool.h> 50*0Sstevel@tonic-gate #include <sys/pool_impl.h> 51*0Sstevel@tonic-gate #include <sys/priocntl.h> 52*0Sstevel@tonic-gate #include <sys/stat.h> 53*0Sstevel@tonic-gate #include <sys/time.h> 54*0Sstevel@tonic-gate #include <sys/types.h> 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate #include "dict.h" 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate #include "pool_internal.h" 59*0Sstevel@tonic-gate #include "pool_impl.h" 60*0Sstevel@tonic-gate #include "pool_kernel_impl.h" 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate /* 63*0Sstevel@tonic-gate * libpool kernel Manipulation Routines 64*0Sstevel@tonic-gate * 65*0Sstevel@tonic-gate * pool_kernel.c implements the kernel manipulation routines used by the 66*0Sstevel@tonic-gate * libpool kernel datastore. The functions are grouped into the following 67*0Sstevel@tonic-gate * logical areas 68*0Sstevel@tonic-gate * 69*0Sstevel@tonic-gate */ 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate /* 72*0Sstevel@tonic-gate * Device snapshot transfer buffer size 73*0Sstevel@tonic-gate */ 74*0Sstevel@tonic-gate #define KERNEL_SNAPSHOT_BUF_SZ 65535 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate /* 77*0Sstevel@tonic-gate * Kernel result set's initial size. 8 is probably large enough for 78*0Sstevel@tonic-gate * most queries. Queries requiring more space are accomodated using 79*0Sstevel@tonic-gate * realloc on a per result set basis. 80*0Sstevel@tonic-gate */ 81*0Sstevel@tonic-gate #define KERNEL_RS_INITIAL_SZ 8 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * Property manipulation macros 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate #define KERNEL_PROP_RDONLY 0x1 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate /* 89*0Sstevel@tonic-gate * Information required to evaluate qualifying elements for a query 90*0Sstevel@tonic-gate */ 91*0Sstevel@tonic-gate struct query_obj { 92*0Sstevel@tonic-gate const pool_conf_t *conf; 93*0Sstevel@tonic-gate const pool_elem_t *src; 94*0Sstevel@tonic-gate const char *src_attr; 95*0Sstevel@tonic-gate pool_elem_class_t classes; 96*0Sstevel@tonic-gate pool_value_t **props; 97*0Sstevel@tonic-gate pool_knl_result_set_t *rs; 98*0Sstevel@tonic-gate }; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate /* 101*0Sstevel@tonic-gate * Identifies a pool element with a processor set id 102*0Sstevel@tonic-gate */ 103*0Sstevel@tonic-gate typedef struct pool_set_xref { 104*0Sstevel@tonic-gate pool_knl_pool_t *psx_pool; 105*0Sstevel@tonic-gate uint_t psx_pset_id; 106*0Sstevel@tonic-gate struct pool_set_xref *psx_next; 107*0Sstevel@tonic-gate } pool_set_xref_t; 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* 110*0Sstevel@tonic-gate * Controls exacct snapshot load into libpool data structure 111*0Sstevel@tonic-gate */ 112*0Sstevel@tonic-gate typedef struct pool_snap_load { 113*0Sstevel@tonic-gate int *psl_changed; 114*0Sstevel@tonic-gate pool_set_xref_t *psl_xref; 115*0Sstevel@tonic-gate pool_elem_t *psl_system; 116*0Sstevel@tonic-gate pool_knl_resource_t *psl_pset; 117*0Sstevel@tonic-gate } pool_snap_load_t; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * Information about an XML document which is being constructed 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate struct knl_to_xml { 123*0Sstevel@tonic-gate xmlDocPtr ktx_doc; 124*0Sstevel@tonic-gate xmlNodePtr ktx_node; 125*0Sstevel@tonic-gate }; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* 128*0Sstevel@tonic-gate * Undo structure processing. The following structures are all used to 129*0Sstevel@tonic-gate * allow changes to the libpool snapshot and kernel following an 130*0Sstevel@tonic-gate * unsuccessful commit. 131*0Sstevel@tonic-gate */ 132*0Sstevel@tonic-gate typedef struct pool_create_undo { 133*0Sstevel@tonic-gate pool_create_t pcu_ioctl; 134*0Sstevel@tonic-gate pool_elem_t *pcu_elem; 135*0Sstevel@tonic-gate } pool_create_undo_t; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate typedef struct pool_destroy_undo { 138*0Sstevel@tonic-gate pool_destroy_t pdu_ioctl; 139*0Sstevel@tonic-gate pool_elem_t *pdu_elem; 140*0Sstevel@tonic-gate } pool_destroy_undo_t; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate typedef struct pool_assoc_undo { 143*0Sstevel@tonic-gate pool_assoc_t pau_ioctl; 144*0Sstevel@tonic-gate pool_elem_t *pau_assoc; 145*0Sstevel@tonic-gate pool_elem_t *pau_oldres; 146*0Sstevel@tonic-gate pool_elem_t *pau_newres; 147*0Sstevel@tonic-gate } pool_assoc_undo_t; 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate typedef struct pool_dissoc_undo { 150*0Sstevel@tonic-gate pool_dissoc_t pdu_ioctl; 151*0Sstevel@tonic-gate pool_elem_t *pdu_dissoc; 152*0Sstevel@tonic-gate pool_elem_t *pdu_oldres; 153*0Sstevel@tonic-gate pool_elem_t *pdu_newres; 154*0Sstevel@tonic-gate } pool_dissoc_undo_t; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate typedef struct pool_xtransfer_undo { 157*0Sstevel@tonic-gate pool_xtransfer_t pxu_ioctl; 158*0Sstevel@tonic-gate pool_elem_t *pxu_src; 159*0Sstevel@tonic-gate pool_elem_t *pxu_tgt; 160*0Sstevel@tonic-gate pool_component_t **pxu_rl; 161*0Sstevel@tonic-gate } pool_xtransfer_undo_t; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate typedef struct pool_propput_undo { 164*0Sstevel@tonic-gate pool_propput_t ppu_ioctl; 165*0Sstevel@tonic-gate pool_elem_t *ppu_elem; 166*0Sstevel@tonic-gate nvlist_t *ppu_alist; 167*0Sstevel@tonic-gate nvlist_t *ppu_blist; 168*0Sstevel@tonic-gate uchar_t ppu_doioctl; 169*0Sstevel@tonic-gate } pool_propput_undo_t; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate typedef struct pool_proprm_undo { 172*0Sstevel@tonic-gate pool_proprm_t pru_ioctl; 173*0Sstevel@tonic-gate pool_elem_t *pru_elem; 174*0Sstevel@tonic-gate pool_value_t pru_oldval; 175*0Sstevel@tonic-gate } pool_proprm_undo_t; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate extern const char *dtd_location; 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate extern const char *element_class_tags[]; 180*0Sstevel@tonic-gate extern const char pool_info_location[]; 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* 183*0Sstevel@tonic-gate * These functions are defined in pool_xml.c and represent the minimum 184*0Sstevel@tonic-gate * XML support required to allow a pool kernel configuration to be 185*0Sstevel@tonic-gate * exported as an XML document. 186*0Sstevel@tonic-gate */ 187*0Sstevel@tonic-gate extern int pool_xml_set_attr(xmlNodePtr, xmlChar *, const pool_value_t *); 188*0Sstevel@tonic-gate extern int pool_xml_set_prop(xmlNodePtr, xmlChar *, const pool_value_t *); 189*0Sstevel@tonic-gate extern void xml_init(void); 190*0Sstevel@tonic-gate extern xmlNodePtr node_create(xmlNodePtr, const xmlChar *); 191*0Sstevel@tonic-gate extern void pool_error_func(void *, const char *, ...); 192*0Sstevel@tonic-gate /* 193*0Sstevel@tonic-gate * Utilities 194*0Sstevel@tonic-gate */ 195*0Sstevel@tonic-gate static int load_group(pool_conf_t *, pool_knl_elem_t *, ea_object_t *, 196*0Sstevel@tonic-gate pool_snap_load_t *); 197*0Sstevel@tonic-gate static void pool_knl_elem_free(pool_knl_elem_t *, int); 198*0Sstevel@tonic-gate static int pool_knl_put_xml_property(pool_elem_t *, xmlNodePtr, const char *, 199*0Sstevel@tonic-gate const pool_value_t *); 200*0Sstevel@tonic-gate static int pool_knl_snap_load_push(pool_snap_load_t *, pool_knl_pool_t *); 201*0Sstevel@tonic-gate static int pool_knl_snap_load_update(pool_snap_load_t *, int, uint_t); 202*0Sstevel@tonic-gate static int pool_knl_snap_load_remove(pool_snap_load_t *, int, uint_t); 203*0Sstevel@tonic-gate static nvpair_t *pool_knl_find_nvpair(nvlist_t *, const char *); 204*0Sstevel@tonic-gate static int pool_knl_nvlist_add_value(nvlist_t *, const char *, 205*0Sstevel@tonic-gate const pool_value_t *); 206*0Sstevel@tonic-gate static int pool_knl_recover(pool_conf_t *); 207*0Sstevel@tonic-gate static uint64_t hash_id(const pool_elem_t *); 208*0Sstevel@tonic-gate static int blocking_open(const char *, int); 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate /* 211*0Sstevel@tonic-gate * Connections 212*0Sstevel@tonic-gate */ 213*0Sstevel@tonic-gate static void pool_knl_connection_free(pool_knl_connection_t *); 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate /* 216*0Sstevel@tonic-gate * Configuration 217*0Sstevel@tonic-gate */ 218*0Sstevel@tonic-gate static int pool_knl_close(pool_conf_t *); 219*0Sstevel@tonic-gate static int pool_knl_validate(const pool_conf_t *, pool_valid_level_t); 220*0Sstevel@tonic-gate static int pool_knl_commit(pool_conf_t *); 221*0Sstevel@tonic-gate static int pool_knl_export(const pool_conf_t *, const char *, 222*0Sstevel@tonic-gate pool_export_format_t); 223*0Sstevel@tonic-gate static int pool_knl_rollback(pool_conf_t *); 224*0Sstevel@tonic-gate static pool_result_set_t *pool_knl_exec_query(const pool_conf_t *, 225*0Sstevel@tonic-gate const pool_elem_t *, const char *, pool_elem_class_t, pool_value_t **); 226*0Sstevel@tonic-gate static int pool_knl_remove(pool_conf_t *); 227*0Sstevel@tonic-gate static char *pool_knl_get_binding(pool_conf_t *, pid_t); 228*0Sstevel@tonic-gate static int pool_knl_set_binding(pool_conf_t *, const char *, idtype_t, id_t); 229*0Sstevel@tonic-gate static char *pool_knl_get_resource_binding(pool_conf_t *, 230*0Sstevel@tonic-gate pool_resource_elem_class_t, pid_t); 231*0Sstevel@tonic-gate static int pool_knl_res_transfer(pool_resource_t *, pool_resource_t *, 232*0Sstevel@tonic-gate uint64_t); 233*0Sstevel@tonic-gate static int pool_knl_res_xtransfer(pool_resource_t *, pool_resource_t *, 234*0Sstevel@tonic-gate pool_component_t **); 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate /* 237*0Sstevel@tonic-gate * Result Sets 238*0Sstevel@tonic-gate */ 239*0Sstevel@tonic-gate static pool_knl_result_set_t *pool_knl_result_set_alloc(const pool_conf_t *); 240*0Sstevel@tonic-gate static int pool_knl_result_set_append(pool_knl_result_set_t *, 241*0Sstevel@tonic-gate pool_knl_elem_t *); 242*0Sstevel@tonic-gate static int pool_knl_result_set_realloc(pool_knl_result_set_t *); 243*0Sstevel@tonic-gate static void pool_knl_result_set_free(pool_knl_result_set_t *); 244*0Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_next(pool_result_set_t *); 245*0Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_prev(pool_result_set_t *); 246*0Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_first(pool_result_set_t *); 247*0Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_last(pool_result_set_t *); 248*0Sstevel@tonic-gate static int pool_knl_rs_set_index(pool_result_set_t *, int); 249*0Sstevel@tonic-gate static int pool_knl_rs_get_index(pool_result_set_t *); 250*0Sstevel@tonic-gate static int pool_knl_rs_count(pool_result_set_t *); 251*0Sstevel@tonic-gate static int pool_knl_rs_close(pool_result_set_t *); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * Element (and sub-type) 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate static pool_knl_elem_t *pool_knl_elem_wrap(pool_conf_t *, pool_elem_class_t, 257*0Sstevel@tonic-gate pool_resource_elem_class_t, pool_component_elem_class_t); 258*0Sstevel@tonic-gate static pool_elem_t *pool_knl_elem_create(pool_conf_t *, pool_elem_class_t, 259*0Sstevel@tonic-gate pool_resource_elem_class_t, pool_component_elem_class_t); 260*0Sstevel@tonic-gate static int pool_knl_elem_remove(pool_elem_t *); 261*0Sstevel@tonic-gate static int pool_knl_set_container(pool_elem_t *, pool_elem_t *); 262*0Sstevel@tonic-gate static pool_elem_t *pool_knl_get_container(const pool_elem_t *); 263*0Sstevel@tonic-gate /* 264*0Sstevel@tonic-gate * Pool element specific 265*0Sstevel@tonic-gate */ 266*0Sstevel@tonic-gate static int pool_knl_pool_associate(pool_t *, const pool_resource_t *); 267*0Sstevel@tonic-gate static int pool_knl_pool_dissociate(pool_t *, const pool_resource_t *); 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate /* 270*0Sstevel@tonic-gate * Resource elements specific 271*0Sstevel@tonic-gate */ 272*0Sstevel@tonic-gate static int pool_knl_resource_is_system(const pool_resource_t *); 273*0Sstevel@tonic-gate static int pool_knl_resource_can_associate(const pool_resource_t *); 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* Properties */ 276*0Sstevel@tonic-gate static pool_value_class_t pool_knl_get_property(const pool_elem_t *, 277*0Sstevel@tonic-gate const char *, pool_value_t *); 278*0Sstevel@tonic-gate static pool_value_class_t pool_knl_get_dynamic_property(const pool_elem_t *, 279*0Sstevel@tonic-gate const char *, pool_value_t *); 280*0Sstevel@tonic-gate static int pool_knl_put_property(pool_elem_t *, const char *, 281*0Sstevel@tonic-gate const pool_value_t *); 282*0Sstevel@tonic-gate static int pool_knl_rm_property(pool_elem_t *, const char *); 283*0Sstevel@tonic-gate static pool_value_t **pool_knl_get_properties(const pool_elem_t *, uint_t *); 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate /* 286*0Sstevel@tonic-gate * Logging 287*0Sstevel@tonic-gate */ 288*0Sstevel@tonic-gate static int log_item_commit(log_item_t *); 289*0Sstevel@tonic-gate static int log_item_undo(log_item_t *); 290*0Sstevel@tonic-gate static int log_item_release(log_item_t *); 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate /* 293*0Sstevel@tonic-gate * Utilities 294*0Sstevel@tonic-gate */ 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate /* 297*0Sstevel@tonic-gate * load_group() updates the library configuration with the kernel 298*0Sstevel@tonic-gate * snapshot supplied in ep. The function is designed to be called 299*0Sstevel@tonic-gate * recursively. This function depends implicitly on the ordering of 300*0Sstevel@tonic-gate * the data provided in ep. Changes to the ordering of data in ep must 301*0Sstevel@tonic-gate * be matched by changes to this function. 302*0Sstevel@tonic-gate */ 303*0Sstevel@tonic-gate int 304*0Sstevel@tonic-gate load_group(pool_conf_t *conf, pool_knl_elem_t *elem, ea_object_t *ep, 305*0Sstevel@tonic-gate pool_snap_load_t *psl) 306*0Sstevel@tonic-gate { 307*0Sstevel@tonic-gate ea_object_t *eo; 308*0Sstevel@tonic-gate pool_knl_elem_t *old_elem; 309*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 310*0Sstevel@tonic-gate int ret = PO_SUCCESS; 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate if ((ep->eo_catalog & EXD_DATA_MASK) == EXD_GROUP_SYSTEM) { 313*0Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, PEC_SYSTEM, PREC_INVALID, 314*0Sstevel@tonic-gate PCEC_INVALID)) == NULL) 315*0Sstevel@tonic-gate return (PO_FAIL); 316*0Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties, NV_UNIQUE_NAME_TYPE, 317*0Sstevel@tonic-gate 0) != 0) { 318*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE); 319*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 320*0Sstevel@tonic-gate return (PO_FAIL); 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate /* 323*0Sstevel@tonic-gate * Check to see if we already have an element 324*0Sstevel@tonic-gate * for this data. If we have, free the newly 325*0Sstevel@tonic-gate * created elem and continue with the old one 326*0Sstevel@tonic-gate */ 327*0Sstevel@tonic-gate if ((old_elem = dict_get(prov->pkc_elements, elem)) != NULL) { 328*0Sstevel@tonic-gate nvlist_free(old_elem->pke_properties); 329*0Sstevel@tonic-gate old_elem->pke_properties = elem->pke_properties; 330*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE); 331*0Sstevel@tonic-gate elem = old_elem; 332*0Sstevel@tonic-gate } else { 333*0Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) != NULL) { 334*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 335*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 336*0Sstevel@tonic-gate return (PO_FAIL); 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate psl->psl_system = (pool_elem_t *)elem; 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate for (eo = ep->eo_group.eg_objs; eo != NULL; eo = eo->eo_next) { 343*0Sstevel@tonic-gate int data; 344*0Sstevel@tonic-gate pool_knl_elem_t *prop_elem = NULL; 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate data = (eo->eo_catalog & EXD_DATA_MASK); 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate switch (data) { 349*0Sstevel@tonic-gate case EXD_SYSTEM_TSTAMP: 350*0Sstevel@tonic-gate case EXD_POOL_TSTAMP: 351*0Sstevel@tonic-gate case EXD_PSET_TSTAMP: 352*0Sstevel@tonic-gate case EXD_CPU_TSTAMP: 353*0Sstevel@tonic-gate if (eo->eo_item.ei_uint64 > prov->pkc_lotime) { 354*0Sstevel@tonic-gate if (eo->eo_item.ei_uint64 > prov->pkc_ltime) 355*0Sstevel@tonic-gate prov->pkc_ltime = eo->eo_item.ei_uint64; 356*0Sstevel@tonic-gate if (psl->psl_changed) { 357*0Sstevel@tonic-gate switch (data) { 358*0Sstevel@tonic-gate case EXD_SYSTEM_TSTAMP: 359*0Sstevel@tonic-gate *psl->psl_changed |= POU_SYSTEM; 360*0Sstevel@tonic-gate break; 361*0Sstevel@tonic-gate case EXD_POOL_TSTAMP: 362*0Sstevel@tonic-gate *psl->psl_changed |= POU_POOL; 363*0Sstevel@tonic-gate break; 364*0Sstevel@tonic-gate case EXD_PSET_TSTAMP: 365*0Sstevel@tonic-gate *psl->psl_changed |= POU_PSET; 366*0Sstevel@tonic-gate break; 367*0Sstevel@tonic-gate case EXD_CPU_TSTAMP: 368*0Sstevel@tonic-gate *psl->psl_changed |= POU_CPU; 369*0Sstevel@tonic-gate break; 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate } 373*0Sstevel@tonic-gate break; 374*0Sstevel@tonic-gate case EXD_SYSTEM_PROP: 375*0Sstevel@tonic-gate case EXD_POOL_PROP: 376*0Sstevel@tonic-gate case EXD_PSET_PROP: 377*0Sstevel@tonic-gate case EXD_CPU_PROP: 378*0Sstevel@tonic-gate if (data == EXD_PSET_PROP) { 379*0Sstevel@tonic-gate prop_elem = elem; 380*0Sstevel@tonic-gate elem = (pool_knl_elem_t *)psl->psl_pset; 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate nvlist_free(elem->pke_properties); 383*0Sstevel@tonic-gate if (nvlist_unpack(eo->eo_item.ei_raw, 384*0Sstevel@tonic-gate eo->eo_item.ei_size, &elem->pke_properties, 0) != 385*0Sstevel@tonic-gate 0) { 386*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 387*0Sstevel@tonic-gate return (PO_FAIL); 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate elem->pke_ltime = prov->pkc_ltime; 390*0Sstevel@tonic-gate if (data == EXD_PSET_PROP) { 391*0Sstevel@tonic-gate elem = prop_elem; 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate break; 394*0Sstevel@tonic-gate case EXD_POOL_POOLID: 395*0Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties, 396*0Sstevel@tonic-gate NV_UNIQUE_NAME_TYPE, 0) != 0) { 397*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 398*0Sstevel@tonic-gate return (PO_FAIL); 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate if (nvlist_add_int64(elem->pke_properties, 401*0Sstevel@tonic-gate "pool.sys_id", 402*0Sstevel@tonic-gate (int64_t)eo->eo_item.ei_uint32) != 0) { 403*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 404*0Sstevel@tonic-gate return (PO_FAIL); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate if ((old_elem = dict_get(prov->pkc_elements, elem)) != 407*0Sstevel@tonic-gate NULL) { 408*0Sstevel@tonic-gate nvlist_free(old_elem->pke_properties); 409*0Sstevel@tonic-gate old_elem->pke_properties = elem->pke_properties; 410*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE); 411*0Sstevel@tonic-gate elem = old_elem; 412*0Sstevel@tonic-gate } else { 413*0Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) != 414*0Sstevel@tonic-gate NULL) { 415*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 416*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 417*0Sstevel@tonic-gate return (PO_FAIL); 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate if (pool_knl_snap_load_push(psl, 421*0Sstevel@tonic-gate (pool_knl_pool_t *)elem) != PO_SUCCESS) { 422*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 423*0Sstevel@tonic-gate return (PO_FAIL); 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate ((pool_knl_pool_t *)elem)->pkp_assoc[PREC_PSET] = NULL; 426*0Sstevel@tonic-gate break; 427*0Sstevel@tonic-gate case EXD_POOL_PSETID: 428*0Sstevel@tonic-gate if (pool_knl_snap_load_update(psl, EXD_POOL_PSETID, 429*0Sstevel@tonic-gate eo->eo_item.ei_uint32) != PO_SUCCESS) { 430*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 431*0Sstevel@tonic-gate return (PO_FAIL); 432*0Sstevel@tonic-gate } 433*0Sstevel@tonic-gate break; 434*0Sstevel@tonic-gate case EXD_PSET_PSETID: 435*0Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties, 436*0Sstevel@tonic-gate NV_UNIQUE_NAME_TYPE, 0) != 0) { 437*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 438*0Sstevel@tonic-gate return (PO_FAIL); 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate if (nvlist_add_int64(elem->pke_properties, 441*0Sstevel@tonic-gate "pset.sys_id", 442*0Sstevel@tonic-gate (int64_t)eo->eo_item.ei_uint32) != 0) { 443*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 444*0Sstevel@tonic-gate return (PO_FAIL); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate if ((old_elem = dict_get(prov->pkc_elements, elem)) != 447*0Sstevel@tonic-gate NULL) { 448*0Sstevel@tonic-gate nvlist_free(old_elem->pke_properties); 449*0Sstevel@tonic-gate old_elem->pke_properties = elem->pke_properties; 450*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE); 451*0Sstevel@tonic-gate elem = old_elem; 452*0Sstevel@tonic-gate } else { 453*0Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) != 454*0Sstevel@tonic-gate NULL) { 455*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 456*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 457*0Sstevel@tonic-gate return (PO_FAIL); 458*0Sstevel@tonic-gate } 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate psl->psl_pset = (pool_knl_resource_t *)elem; 461*0Sstevel@tonic-gate if (pool_knl_snap_load_remove(psl, data, 462*0Sstevel@tonic-gate eo->eo_item.ei_uint32) != PO_SUCCESS) { 463*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 464*0Sstevel@tonic-gate return (PO_FAIL); 465*0Sstevel@tonic-gate } 466*0Sstevel@tonic-gate break; 467*0Sstevel@tonic-gate case EXD_CPU_CPUID: 468*0Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties, 469*0Sstevel@tonic-gate NV_UNIQUE_NAME_TYPE, 0) != 0) { 470*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 471*0Sstevel@tonic-gate return (PO_FAIL); 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate if (nvlist_add_int64(elem->pke_properties, 474*0Sstevel@tonic-gate "cpu.sys_id", 475*0Sstevel@tonic-gate (int64_t)eo->eo_item.ei_uint32) != 0) { 476*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 477*0Sstevel@tonic-gate return (PO_FAIL); 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate if ((old_elem = dict_get(prov->pkc_elements, elem)) != 480*0Sstevel@tonic-gate NULL) { 481*0Sstevel@tonic-gate nvlist_free(old_elem->pke_properties); 482*0Sstevel@tonic-gate old_elem->pke_properties = elem->pke_properties; 483*0Sstevel@tonic-gate old_elem->pke_parent = elem->pke_parent; 484*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE); 485*0Sstevel@tonic-gate elem = old_elem; 486*0Sstevel@tonic-gate } else { 487*0Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) != 488*0Sstevel@tonic-gate NULL) { 489*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 490*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 491*0Sstevel@tonic-gate return (PO_FAIL); 492*0Sstevel@tonic-gate } 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate break; 495*0Sstevel@tonic-gate case EXD_GROUP_POOL: 496*0Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, PEC_POOL, 497*0Sstevel@tonic-gate PREC_INVALID, PCEC_INVALID)) == NULL) 498*0Sstevel@tonic-gate return (PO_FAIL); 499*0Sstevel@tonic-gate if (pool_set_container(psl->psl_system, 500*0Sstevel@tonic-gate (pool_elem_t *)elem) != PO_SUCCESS) { 501*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 502*0Sstevel@tonic-gate return (PO_FAIL); 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate break; 505*0Sstevel@tonic-gate case EXD_GROUP_PSET: 506*0Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, PEC_RES_COMP, 507*0Sstevel@tonic-gate PREC_PSET, PCEC_INVALID)) == NULL) 508*0Sstevel@tonic-gate return (PO_FAIL); 509*0Sstevel@tonic-gate if (pool_set_container(psl->psl_system, 510*0Sstevel@tonic-gate (pool_elem_t *)elem) != PO_SUCCESS) { 511*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 512*0Sstevel@tonic-gate return (PO_FAIL); 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate break; 515*0Sstevel@tonic-gate case EXD_GROUP_CPU: 516*0Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, PEC_COMP, 517*0Sstevel@tonic-gate PREC_INVALID, PCEC_CPU)) == NULL) 518*0Sstevel@tonic-gate return (PO_FAIL); 519*0Sstevel@tonic-gate if (pool_set_container((pool_elem_t *)psl->psl_pset, 520*0Sstevel@tonic-gate (pool_elem_t *)elem) != PO_SUCCESS) { 521*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 522*0Sstevel@tonic-gate return (PO_FAIL); 523*0Sstevel@tonic-gate } 524*0Sstevel@tonic-gate break; 525*0Sstevel@tonic-gate default: 526*0Sstevel@tonic-gate break; 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate if (eo->eo_type == EO_GROUP) { 531*0Sstevel@tonic-gate if ((ret = load_group(conf, elem, eo, psl)) == PO_FAIL) 532*0Sstevel@tonic-gate break; 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate return (ret); 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate /* 539*0Sstevel@tonic-gate * Push a snapshot entry onto the list of pools in the snapshot. 540*0Sstevel@tonic-gate */ 541*0Sstevel@tonic-gate int 542*0Sstevel@tonic-gate pool_knl_snap_load_push(pool_snap_load_t *psl, pool_knl_pool_t *pkp) 543*0Sstevel@tonic-gate { 544*0Sstevel@tonic-gate pool_set_xref_t *psx; 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate if ((psx = malloc(sizeof (pool_set_xref_t))) == NULL) { 547*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 548*0Sstevel@tonic-gate return (PO_FAIL); 549*0Sstevel@tonic-gate } 550*0Sstevel@tonic-gate (void) memset(psx, 0, sizeof (pool_set_xref_t)); 551*0Sstevel@tonic-gate psx->psx_pool = pkp; 552*0Sstevel@tonic-gate /* 553*0Sstevel@tonic-gate * Push onto the list of pools 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate psx->psx_next = psl->psl_xref; 556*0Sstevel@tonic-gate psl->psl_xref = psx; 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate return (PO_SUCCESS); 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate /* 562*0Sstevel@tonic-gate * Update the current cross-reference for the supplied type of 563*0Sstevel@tonic-gate * resource. 564*0Sstevel@tonic-gate */ 565*0Sstevel@tonic-gate int 566*0Sstevel@tonic-gate pool_knl_snap_load_update(pool_snap_load_t *psl, int type, uint_t id) 567*0Sstevel@tonic-gate { 568*0Sstevel@tonic-gate switch (type) { 569*0Sstevel@tonic-gate case EXD_POOL_PSETID: 570*0Sstevel@tonic-gate psl->psl_xref->psx_pset_id = id; 571*0Sstevel@tonic-gate break; 572*0Sstevel@tonic-gate default: 573*0Sstevel@tonic-gate return (PO_FAIL); 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate return (PO_SUCCESS); 577*0Sstevel@tonic-gate } 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate /* 580*0Sstevel@tonic-gate * Remove a resource entry with the supplied type and id from the 581*0Sstevel@tonic-gate * snapshot list when it is no longer required. 582*0Sstevel@tonic-gate */ 583*0Sstevel@tonic-gate int 584*0Sstevel@tonic-gate pool_knl_snap_load_remove(pool_snap_load_t *psl, int type, uint_t id) 585*0Sstevel@tonic-gate { 586*0Sstevel@tonic-gate pool_set_xref_t *current, *prev, *next; 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate for (prev = NULL, current = psl->psl_xref; current != NULL; 589*0Sstevel@tonic-gate current = next) { 590*0Sstevel@tonic-gate switch (type) { 591*0Sstevel@tonic-gate case EXD_PSET_PSETID: 592*0Sstevel@tonic-gate if (current->psx_pset_id == id) 593*0Sstevel@tonic-gate current->psx_pool->pkp_assoc[PREC_PSET] = 594*0Sstevel@tonic-gate psl->psl_pset; 595*0Sstevel@tonic-gate break; 596*0Sstevel@tonic-gate default: 597*0Sstevel@tonic-gate return (PO_FAIL); 598*0Sstevel@tonic-gate } 599*0Sstevel@tonic-gate next = current->psx_next; 600*0Sstevel@tonic-gate if (current->psx_pool->pkp_assoc[PREC_PSET] != NULL) { 601*0Sstevel@tonic-gate if (prev != NULL) { 602*0Sstevel@tonic-gate prev->psx_next = current->psx_next; 603*0Sstevel@tonic-gate } else { 604*0Sstevel@tonic-gate psl->psl_xref = current->psx_next; 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate free(current); 607*0Sstevel@tonic-gate } else 608*0Sstevel@tonic-gate prev = current; 609*0Sstevel@tonic-gate } 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate return (PO_SUCCESS); 612*0Sstevel@tonic-gate } 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate /* 615*0Sstevel@tonic-gate * Return the nvpair with the supplied name from the supplied list. 616*0Sstevel@tonic-gate * 617*0Sstevel@tonic-gate * NULL is returned if the name cannot be found in the list. 618*0Sstevel@tonic-gate */ 619*0Sstevel@tonic-gate nvpair_t * 620*0Sstevel@tonic-gate pool_knl_find_nvpair(nvlist_t *l, const char *name) 621*0Sstevel@tonic-gate { 622*0Sstevel@tonic-gate nvpair_t *pair; 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate for (pair = nvlist_next_nvpair(l, NULL); pair != NULL; 625*0Sstevel@tonic-gate pair = nvlist_next_nvpair(l, pair)) { 626*0Sstevel@tonic-gate if (strcmp(nvpair_name(pair), name) == 0) 627*0Sstevel@tonic-gate break; 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate return (pair); 630*0Sstevel@tonic-gate } 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate /* 633*0Sstevel@tonic-gate * Close the configuration. There are a few steps to closing a configuration: 634*0Sstevel@tonic-gate * - Close the pseudo device 635*0Sstevel@tonic-gate * - Free the data provider 636*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 637*0Sstevel@tonic-gate */ 638*0Sstevel@tonic-gate int 639*0Sstevel@tonic-gate pool_knl_close(pool_conf_t *conf) 640*0Sstevel@tonic-gate { 641*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate if (close(prov->pkc_fd) < 0) { 644*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 645*0Sstevel@tonic-gate return (PO_FAIL); 646*0Sstevel@tonic-gate } 647*0Sstevel@tonic-gate /* 648*0Sstevel@tonic-gate * Rollback any pending changes before freeing the prov. This 649*0Sstevel@tonic-gate * ensures there are no memory leaks from pending 650*0Sstevel@tonic-gate * transactions. 651*0Sstevel@tonic-gate */ 652*0Sstevel@tonic-gate (void) pool_knl_rollback(conf); 653*0Sstevel@tonic-gate pool_knl_connection_free(prov); 654*0Sstevel@tonic-gate return (PO_SUCCESS); 655*0Sstevel@tonic-gate } 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate /* 658*0Sstevel@tonic-gate * Remove elements in this map (previously identified as "dead") from 659*0Sstevel@tonic-gate * the configuration map (prov->pkc_elements). 660*0Sstevel@tonic-gate */ 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate /* ARGSUSED1 */ 663*0Sstevel@tonic-gate static void 664*0Sstevel@tonic-gate remove_dead_elems(const void *key, void **value, void *cl) 665*0Sstevel@tonic-gate { 666*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key; 667*0Sstevel@tonic-gate pool_conf_t *conf = TO_CONF(TO_ELEM(pke)); 668*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate assert(dict_remove(prov->pkc_elements, pke) != NULL); 671*0Sstevel@tonic-gate #ifdef DEBUG 672*0Sstevel@tonic-gate dprintf("remove_dead_elems:\n"); 673*0Sstevel@tonic-gate pool_elem_dprintf(TO_ELEM(pke)); 674*0Sstevel@tonic-gate #endif /* DEBUG */ 675*0Sstevel@tonic-gate pool_knl_elem_free(pke, PO_TRUE); 676*0Sstevel@tonic-gate } 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate /* 679*0Sstevel@tonic-gate * Find elements which were not updated the last time that 680*0Sstevel@tonic-gate * load_group() was called. Add those elements into a separate map 681*0Sstevel@tonic-gate * (passed in cl) which will be later used to remove these elements 682*0Sstevel@tonic-gate * from the configuration map. 683*0Sstevel@tonic-gate */ 684*0Sstevel@tonic-gate /* ARGSUSED1 */ 685*0Sstevel@tonic-gate static void 686*0Sstevel@tonic-gate find_dead_elems(const void *key, void **value, void *cl) 687*0Sstevel@tonic-gate { 688*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key; 689*0Sstevel@tonic-gate pool_conf_t *conf = TO_CONF(TO_ELEM(pke)); 690*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 691*0Sstevel@tonic-gate dict_hdl_t *dead_map = (dict_hdl_t *)cl; 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate if (pke->pke_ltime < prov->pkc_ltime) 694*0Sstevel@tonic-gate (void) dict_put(dead_map, pke, pke); 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate /* 698*0Sstevel@tonic-gate * Update the snapshot held by the library. This function acts as the 699*0Sstevel@tonic-gate * controller for the snapshot update procedure. Then snapshot is 700*0Sstevel@tonic-gate * actually updated in multiple phases by the load_group() function 701*0Sstevel@tonic-gate * (which updates existing elements and creates new elements as 702*0Sstevel@tonic-gate * required) and then by find_dead_elems and remove_dead_elems 703*0Sstevel@tonic-gate * (respectively responsible for identifying elements which are to be 704*0Sstevel@tonic-gate * removed and then removing them). 705*0Sstevel@tonic-gate * 706*0Sstevel@tonic-gate * Returns PO_SUCCESS 707*0Sstevel@tonic-gate */ 708*0Sstevel@tonic-gate int 709*0Sstevel@tonic-gate pool_knl_update(pool_conf_t *conf, int *changed) 710*0Sstevel@tonic-gate { 711*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 712*0Sstevel@tonic-gate pool_query_t query = {0}; 713*0Sstevel@tonic-gate ea_object_t *ep; 714*0Sstevel@tonic-gate dict_hdl_t *dead_map; 715*0Sstevel@tonic-gate pool_snap_load_t psl = { NULL }; 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate /* 718*0Sstevel@tonic-gate * Ensure the library snapshot is consistent, if there are any 719*0Sstevel@tonic-gate * outstanding transactions return failure. 720*0Sstevel@tonic-gate */ 721*0Sstevel@tonic-gate if (log_size(prov->pkc_log) != 0) { 722*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 723*0Sstevel@tonic-gate return (PO_FAIL); 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate /* 726*0Sstevel@tonic-gate * Query the kernel for a snapshot of the configuration state. Use 727*0Sstevel@tonic-gate * load_group to allocate the user-land representation of the 728*0Sstevel@tonic-gate * data returned in the snapshot. 729*0Sstevel@tonic-gate */ 730*0Sstevel@tonic-gate /* LINTED E_CONSTANT_CONDITION */ 731*0Sstevel@tonic-gate while (1) { 732*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_QUERY, &query) < 0) { 733*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 734*0Sstevel@tonic-gate return (PO_FAIL); 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate if ((query.pq_io_buf = calloc(1, 737*0Sstevel@tonic-gate (query.pq_io_bufsize < KERNEL_SNAPSHOT_BUF_SZ) ? 738*0Sstevel@tonic-gate query.pq_io_bufsize * 2 : query.pq_io_bufsize)) == NULL) { 739*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 740*0Sstevel@tonic-gate return (PO_FAIL); 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_QUERY, &query) < 0) { 743*0Sstevel@tonic-gate free(query.pq_io_buf); 744*0Sstevel@tonic-gate if (errno != ENOMEM) { 745*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 746*0Sstevel@tonic-gate return (PO_FAIL); 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate query.pq_io_bufsize = 0; 749*0Sstevel@tonic-gate query.pq_io_buf = NULL; 750*0Sstevel@tonic-gate } else 751*0Sstevel@tonic-gate break; 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate if (ea_unpack_object(&ep, EUP_NOALLOC, query.pq_io_buf, 754*0Sstevel@tonic-gate query.pq_io_bufsize) != EO_GROUP) { 755*0Sstevel@tonic-gate free(query.pq_io_buf); 756*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 757*0Sstevel@tonic-gate return (PO_FAIL); 758*0Sstevel@tonic-gate } 759*0Sstevel@tonic-gate /* 760*0Sstevel@tonic-gate * Update the library snapshot 761*0Sstevel@tonic-gate */ 762*0Sstevel@tonic-gate psl.psl_changed = changed; 763*0Sstevel@tonic-gate prov->pkc_lotime = prov->pkc_ltime; 764*0Sstevel@tonic-gate if (load_group(conf, NULL, ep, &psl) != PO_SUCCESS) { 765*0Sstevel@tonic-gate free(query.pq_io_buf); 766*0Sstevel@tonic-gate ea_free_object(ep, EUP_NOALLOC); 767*0Sstevel@tonic-gate return (PO_FAIL); 768*0Sstevel@tonic-gate } 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate free(query.pq_io_buf); 771*0Sstevel@tonic-gate ea_free_object(ep, EUP_NOALLOC); 772*0Sstevel@tonic-gate /* 773*0Sstevel@tonic-gate * Now search the dictionary for items that must be removed because 774*0Sstevel@tonic-gate * they were neither created nor updated. 775*0Sstevel@tonic-gate */ 776*0Sstevel@tonic-gate if ((dead_map = dict_new((int (*)(const void *, const void *)) 777*0Sstevel@tonic-gate pool_elem_compare, (uint64_t (*)(const void *))hash_id)) == NULL) { 778*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 779*0Sstevel@tonic-gate return (PO_FAIL); 780*0Sstevel@tonic-gate } 781*0Sstevel@tonic-gate dict_map(prov->pkc_elements, find_dead_elems, dead_map); 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate if (dict_length(dead_map) > 0) { 784*0Sstevel@tonic-gate dict_map(dead_map, remove_dead_elems, NULL); 785*0Sstevel@tonic-gate } 786*0Sstevel@tonic-gate dict_free(&dead_map); 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate return (PO_SUCCESS); 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate /* 792*0Sstevel@tonic-gate * Rely on the kernel to always keep a kernel configuration valid. 793*0Sstevel@tonic-gate * Returns PO_SUCCESS 794*0Sstevel@tonic-gate */ 795*0Sstevel@tonic-gate /* ARGSUSED */ 796*0Sstevel@tonic-gate int 797*0Sstevel@tonic-gate pool_knl_validate(const pool_conf_t *conf, pool_valid_level_t level) 798*0Sstevel@tonic-gate { 799*0Sstevel@tonic-gate return ((conf->pc_state == POF_INVALID) ? PO_FAIL : PO_SUCCESS); 800*0Sstevel@tonic-gate } 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate /* 803*0Sstevel@tonic-gate * Process all the outstanding transactions in the log. If the processing 804*0Sstevel@tonic-gate * fails, then attempt to rollback and "undo" the changes. 805*0Sstevel@tonic-gate */ 806*0Sstevel@tonic-gate int 807*0Sstevel@tonic-gate pool_knl_commit(pool_conf_t *conf) 808*0Sstevel@tonic-gate { 809*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 810*0Sstevel@tonic-gate int lock = 1; 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate /* 813*0Sstevel@tonic-gate * Lock the kernel state for the commit 814*0Sstevel@tonic-gate */ 815*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_COMMIT, lock) < 0) { 816*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 817*0Sstevel@tonic-gate return (PO_FAIL); 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate lock = 0; 820*0Sstevel@tonic-gate /* 821*0Sstevel@tonic-gate * If the state is LS_FAIL, then try to recover before 822*0Sstevel@tonic-gate * performing the commit. 823*0Sstevel@tonic-gate */ 824*0Sstevel@tonic-gate if (prov->pkc_log->l_state == LS_FAIL) { 825*0Sstevel@tonic-gate if (pool_knl_recover(conf) == PO_FAIL) { 826*0Sstevel@tonic-gate /* 827*0Sstevel@tonic-gate * Unlock the kernel state for the 828*0Sstevel@tonic-gate * commit. Assert that this * can't fail, 829*0Sstevel@tonic-gate * since if it ever does fail the library is 830*0Sstevel@tonic-gate * unusable. 831*0Sstevel@tonic-gate */ 832*0Sstevel@tonic-gate assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0); 833*0Sstevel@tonic-gate } 834*0Sstevel@tonic-gate } 835*0Sstevel@tonic-gate /* 836*0Sstevel@tonic-gate * Commit the log 837*0Sstevel@tonic-gate */ 838*0Sstevel@tonic-gate if (log_walk(prov->pkc_log, log_item_commit) != PO_SUCCESS) { 839*0Sstevel@tonic-gate (void) pool_knl_recover(conf); 840*0Sstevel@tonic-gate /* 841*0Sstevel@tonic-gate * Unlock the kernel state for the commit. Assert that 842*0Sstevel@tonic-gate * this can't fail, since if it ever does fail the 843*0Sstevel@tonic-gate * library is unusable. 844*0Sstevel@tonic-gate */ 845*0Sstevel@tonic-gate assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0); 846*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 847*0Sstevel@tonic-gate return (PO_FAIL); 848*0Sstevel@tonic-gate } 849*0Sstevel@tonic-gate /* 850*0Sstevel@tonic-gate * Unlock the kernel state for the commit. Assert that this 851*0Sstevel@tonic-gate * can't fail, since if it ever does fail the library is 852*0Sstevel@tonic-gate * unusable. 853*0Sstevel@tonic-gate */ 854*0Sstevel@tonic-gate assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0); 855*0Sstevel@tonic-gate /* 856*0Sstevel@tonic-gate * Release the log resources 857*0Sstevel@tonic-gate */ 858*0Sstevel@tonic-gate (void) log_walk(prov->pkc_log, log_item_release); 859*0Sstevel@tonic-gate log_empty(prov->pkc_log); 860*0Sstevel@tonic-gate return (PO_SUCCESS); 861*0Sstevel@tonic-gate } 862*0Sstevel@tonic-gate 863*0Sstevel@tonic-gate /* 864*0Sstevel@tonic-gate * prop_build_cb() is designed to be called from 865*0Sstevel@tonic-gate * pool_walk_properties(). The property value is used to put an XML 866*0Sstevel@tonic-gate * property on the supplied ktx_node. This is an essential part of the 867*0Sstevel@tonic-gate * mechanism used to export a kernel configuration in libpool XML 868*0Sstevel@tonic-gate * form. 869*0Sstevel@tonic-gate */ 870*0Sstevel@tonic-gate /* ARGSUSED */ 871*0Sstevel@tonic-gate static int 872*0Sstevel@tonic-gate prop_build_cb(pool_conf_t *UNUSED, pool_elem_t *pe, const char *name, 873*0Sstevel@tonic-gate pool_value_t *pval, void *user) 874*0Sstevel@tonic-gate { 875*0Sstevel@tonic-gate struct knl_to_xml *info = (struct knl_to_xml *)user; 876*0Sstevel@tonic-gate 877*0Sstevel@tonic-gate return (pool_knl_put_xml_property((pool_elem_t *)pe, info->ktx_node, 878*0Sstevel@tonic-gate name, pval)); 879*0Sstevel@tonic-gate } 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate /* 882*0Sstevel@tonic-gate * Duplicate some of the functionality from pool_xml_put_property() 883*0Sstevel@tonic-gate * (see pool_xml.c) to allow a kernel configuration to add XML nodes 884*0Sstevel@tonic-gate * to an XML tree which represents the kernel configuration. This is 885*0Sstevel@tonic-gate * an essential part of the mechanism used to export a kernel 886*0Sstevel@tonic-gate * configuration in libpool XML form. 887*0Sstevel@tonic-gate */ 888*0Sstevel@tonic-gate int 889*0Sstevel@tonic-gate pool_knl_put_xml_property(pool_elem_t *pe, xmlNodePtr node, const char *name, 890*0Sstevel@tonic-gate const pool_value_t *val) 891*0Sstevel@tonic-gate { 892*0Sstevel@tonic-gate 893*0Sstevel@tonic-gate /* 894*0Sstevel@tonic-gate * "type" is a special attribute which is not visible ever outside of 895*0Sstevel@tonic-gate * libpool. Use the specific type accessor function. 896*0Sstevel@tonic-gate */ 897*0Sstevel@tonic-gate if (strcmp(name, c_type) == 0) { 898*0Sstevel@tonic-gate return (pool_xml_set_attr(node, BAD_CAST name, 899*0Sstevel@tonic-gate val)); 900*0Sstevel@tonic-gate } 901*0Sstevel@tonic-gate if (is_ns_property(pe, name) != NULL) { /* in ns */ 902*0Sstevel@tonic-gate if (pool_xml_set_attr(node, 903*0Sstevel@tonic-gate BAD_CAST property_name_minus_ns(pe, name), val) == PO_FAIL) 904*0Sstevel@tonic-gate return (pool_xml_set_prop(node, BAD_CAST name, 905*0Sstevel@tonic-gate val)); 906*0Sstevel@tonic-gate } else 907*0Sstevel@tonic-gate return (pool_xml_set_prop(node, BAD_CAST name, val)); 908*0Sstevel@tonic-gate return (PO_SUCCESS); 909*0Sstevel@tonic-gate } 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate /* 912*0Sstevel@tonic-gate * Export the kernel configuration as an XML file. The configuration 913*0Sstevel@tonic-gate * is used to build an XML document in memory. This document is then 914*0Sstevel@tonic-gate * saved to the supplied location. 915*0Sstevel@tonic-gate */ 916*0Sstevel@tonic-gate int 917*0Sstevel@tonic-gate pool_knl_export(const pool_conf_t *conf, const char *location, 918*0Sstevel@tonic-gate pool_export_format_t fmt) 919*0Sstevel@tonic-gate { 920*0Sstevel@tonic-gate xmlNodePtr node_comment; 921*0Sstevel@tonic-gate xmlNodePtr system; 922*0Sstevel@tonic-gate int ret; 923*0Sstevel@tonic-gate pool_t **ps; 924*0Sstevel@tonic-gate pool_resource_t **rs; 925*0Sstevel@tonic-gate uint_t nelem; 926*0Sstevel@tonic-gate int i; 927*0Sstevel@tonic-gate struct knl_to_xml info; 928*0Sstevel@tonic-gate char_buf_t *cb = NULL; 929*0Sstevel@tonic-gate xmlValidCtxtPtr cvp; 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate xml_init(); 932*0Sstevel@tonic-gate 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate switch (fmt) { 935*0Sstevel@tonic-gate case POX_NATIVE: 936*0Sstevel@tonic-gate info.ktx_doc = xmlNewDoc(BAD_CAST "1.0"); 937*0Sstevel@tonic-gate xmlCreateIntSubset(info.ktx_doc, BAD_CAST "system", 938*0Sstevel@tonic-gate BAD_CAST "-//Sun Microsystems Inc//DTD Resource " 939*0Sstevel@tonic-gate "Management All//EN", 940*0Sstevel@tonic-gate BAD_CAST dtd_location); 941*0Sstevel@tonic-gate 942*0Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) { 943*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 944*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 945*0Sstevel@tonic-gate return (PO_FAIL); 946*0Sstevel@tonic-gate } 947*0Sstevel@tonic-gate /* 948*0Sstevel@tonic-gate * Call xmlValidateDocument() to force the parsing of 949*0Sstevel@tonic-gate * the DTD. Ignore errors and warning messages as we 950*0Sstevel@tonic-gate * know the document isn't valid. 951*0Sstevel@tonic-gate */ 952*0Sstevel@tonic-gate (void) xmlValidateDocument(cvp, info.ktx_doc); 953*0Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 954*0Sstevel@tonic-gate if ((info.ktx_node = node_create(NULL, BAD_CAST "system")) == 955*0Sstevel@tonic-gate NULL) { 956*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 957*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 958*0Sstevel@tonic-gate return (PO_FAIL); 959*0Sstevel@tonic-gate } 960*0Sstevel@tonic-gate 961*0Sstevel@tonic-gate system = info.ktx_node; 962*0Sstevel@tonic-gate info.ktx_doc->_private = (void *)conf; 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate xmlDocSetRootElement(info.ktx_doc, info.ktx_node); 965*0Sstevel@tonic-gate xmlSetProp(info.ktx_node, BAD_CAST c_ref_id, BAD_CAST "dummy"); 966*0Sstevel@tonic-gate if ((node_comment = xmlNewDocComment(info.ktx_doc, 967*0Sstevel@tonic-gate BAD_CAST "\nConfiguration for pools facility. Do NOT" 968*0Sstevel@tonic-gate " edit this file by hand - use poolcfg(1)" 969*0Sstevel@tonic-gate " or libpool(3POOL) instead.\n")) == NULL) { 970*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 971*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 972*0Sstevel@tonic-gate return (PO_FAIL); 973*0Sstevel@tonic-gate } 974*0Sstevel@tonic-gate if (xmlAddPrevSibling(info.ktx_node, node_comment) == NULL) { 975*0Sstevel@tonic-gate xmlFree(node_comment); 976*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 977*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 978*0Sstevel@tonic-gate return (PO_FAIL); 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate if (pool_walk_any_properties((pool_conf_t *)conf, 981*0Sstevel@tonic-gate pool_conf_to_elem(conf), &info, prop_build_cb, 1) == 982*0Sstevel@tonic-gate PO_FAIL) { 983*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 984*0Sstevel@tonic-gate return (PO_FAIL); 985*0Sstevel@tonic-gate } 986*0Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) { 987*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 988*0Sstevel@tonic-gate return (PO_FAIL); 989*0Sstevel@tonic-gate } 990*0Sstevel@tonic-gate /* 991*0Sstevel@tonic-gate * Now add pool details 992*0Sstevel@tonic-gate */ 993*0Sstevel@tonic-gate if ((ps = pool_query_pools(conf, &nelem, NULL)) != NULL) { 994*0Sstevel@tonic-gate for (i = 0; i < nelem; i++) { 995*0Sstevel@tonic-gate pool_elem_t *elem = TO_ELEM(ps[i]); 996*0Sstevel@tonic-gate uint_t nreselem; 997*0Sstevel@tonic-gate const char *sep = ""; 998*0Sstevel@tonic-gate int j; 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate if ((info.ktx_node = node_create(system, 1001*0Sstevel@tonic-gate BAD_CAST element_class_tags 1002*0Sstevel@tonic-gate [pool_elem_class(elem)])) == NULL) { 1003*0Sstevel@tonic-gate free(ps); 1004*0Sstevel@tonic-gate free_char_buf(cb); 1005*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1006*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1007*0Sstevel@tonic-gate return (PO_FAIL); 1008*0Sstevel@tonic-gate } 1009*0Sstevel@tonic-gate if (pool_walk_any_properties( 1010*0Sstevel@tonic-gate (pool_conf_t *)conf, 1011*0Sstevel@tonic-gate elem, &info, prop_build_cb, 1) == PO_FAIL) { 1012*0Sstevel@tonic-gate free(ps); 1013*0Sstevel@tonic-gate free_char_buf(cb); 1014*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1015*0Sstevel@tonic-gate return (PO_FAIL); 1016*0Sstevel@tonic-gate } 1017*0Sstevel@tonic-gate /* 1018*0Sstevel@tonic-gate * TODO: pset specific res manipulation 1019*0Sstevel@tonic-gate */ 1020*0Sstevel@tonic-gate if ((rs = pool_query_pool_resources(conf, ps[i], 1021*0Sstevel@tonic-gate &nreselem, NULL)) == NULL) { 1022*0Sstevel@tonic-gate free(ps); 1023*0Sstevel@tonic-gate free_char_buf(cb); 1024*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1025*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1026*0Sstevel@tonic-gate return (PO_FAIL); 1027*0Sstevel@tonic-gate } 1028*0Sstevel@tonic-gate if (set_char_buf(cb, "") == PO_FAIL) { 1029*0Sstevel@tonic-gate free(rs); 1030*0Sstevel@tonic-gate free(ps); 1031*0Sstevel@tonic-gate free_char_buf(cb); 1032*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1033*0Sstevel@tonic-gate return (PO_FAIL); 1034*0Sstevel@tonic-gate } 1035*0Sstevel@tonic-gate for (j = 0; j < nreselem; j++) { 1036*0Sstevel@tonic-gate pool_elem_t *reselem = TO_ELEM(rs[j]); 1037*0Sstevel@tonic-gate if (append_char_buf(cb, "%s%s_%d", sep, 1038*0Sstevel@tonic-gate pool_elem_class_string(reselem), 1039*0Sstevel@tonic-gate (int)elem_get_sysid(reselem)) == 1040*0Sstevel@tonic-gate PO_FAIL) { 1041*0Sstevel@tonic-gate free(rs); 1042*0Sstevel@tonic-gate free(ps); 1043*0Sstevel@tonic-gate free_char_buf(cb); 1044*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1045*0Sstevel@tonic-gate return (PO_FAIL); 1046*0Sstevel@tonic-gate } 1047*0Sstevel@tonic-gate sep = " "; 1048*0Sstevel@tonic-gate } 1049*0Sstevel@tonic-gate free(rs); 1050*0Sstevel@tonic-gate xmlSetProp(info.ktx_node, BAD_CAST "res", 1051*0Sstevel@tonic-gate BAD_CAST cb->cb_buf); 1052*0Sstevel@tonic-gate if (set_char_buf(cb, "%s_%d", 1053*0Sstevel@tonic-gate pool_elem_class_string(elem), 1054*0Sstevel@tonic-gate (int)elem_get_sysid(elem)) == PO_FAIL) { 1055*0Sstevel@tonic-gate free(ps); 1056*0Sstevel@tonic-gate free_char_buf(cb); 1057*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1058*0Sstevel@tonic-gate return (PO_FAIL); 1059*0Sstevel@tonic-gate } 1060*0Sstevel@tonic-gate xmlSetProp(info.ktx_node, BAD_CAST c_ref_id, 1061*0Sstevel@tonic-gate BAD_CAST cb->cb_buf); 1062*0Sstevel@tonic-gate } 1063*0Sstevel@tonic-gate free(ps); 1064*0Sstevel@tonic-gate } 1065*0Sstevel@tonic-gate /* 1066*0Sstevel@tonic-gate * Now add resource details (including components) 1067*0Sstevel@tonic-gate */ 1068*0Sstevel@tonic-gate if ((rs = pool_query_resources(conf, &nelem, NULL)) != NULL) { 1069*0Sstevel@tonic-gate for (i = 0; i < nelem; i++) { 1070*0Sstevel@tonic-gate pool_elem_t *elem = TO_ELEM(rs[i]); 1071*0Sstevel@tonic-gate pool_component_t **cs = NULL; 1072*0Sstevel@tonic-gate uint_t ncompelem; 1073*0Sstevel@tonic-gate int j; 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate if ((info.ktx_node = node_create(system, 1076*0Sstevel@tonic-gate BAD_CAST element_class_tags 1077*0Sstevel@tonic-gate [pool_elem_class(elem)])) == NULL) { 1078*0Sstevel@tonic-gate free(rs); 1079*0Sstevel@tonic-gate free_char_buf(cb); 1080*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1081*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1082*0Sstevel@tonic-gate return (PO_FAIL); 1083*0Sstevel@tonic-gate } 1084*0Sstevel@tonic-gate if (pool_walk_any_properties( 1085*0Sstevel@tonic-gate (pool_conf_t *)conf, 1086*0Sstevel@tonic-gate elem, &info, prop_build_cb, 1) == PO_FAIL) { 1087*0Sstevel@tonic-gate free(rs); 1088*0Sstevel@tonic-gate free_char_buf(cb); 1089*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1090*0Sstevel@tonic-gate return (PO_FAIL); 1091*0Sstevel@tonic-gate } 1092*0Sstevel@tonic-gate if (set_char_buf(cb, "%s_%d", 1093*0Sstevel@tonic-gate pool_elem_class_string(elem), 1094*0Sstevel@tonic-gate (int)elem_get_sysid(elem)) == PO_FAIL) { 1095*0Sstevel@tonic-gate free(rs); 1096*0Sstevel@tonic-gate free_char_buf(cb); 1097*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1098*0Sstevel@tonic-gate return (PO_FAIL); 1099*0Sstevel@tonic-gate } 1100*0Sstevel@tonic-gate xmlSetProp(info.ktx_node, BAD_CAST c_ref_id, 1101*0Sstevel@tonic-gate BAD_CAST cb->cb_buf); 1102*0Sstevel@tonic-gate if ((cs = pool_query_resource_components(conf, 1103*0Sstevel@tonic-gate rs[i], &ncompelem, NULL)) != NULL) { 1104*0Sstevel@tonic-gate xmlNodePtr resource = info.ktx_node; 1105*0Sstevel@tonic-gate 1106*0Sstevel@tonic-gate for (j = 0; j < ncompelem; j++) { 1107*0Sstevel@tonic-gate pool_elem_t *compelem = 1108*0Sstevel@tonic-gate TO_ELEM(cs[j]); 1109*0Sstevel@tonic-gate if ((info.ktx_node = 1110*0Sstevel@tonic-gate node_create(resource, 1111*0Sstevel@tonic-gate BAD_CAST element_class_tags 1112*0Sstevel@tonic-gate [pool_elem_class( 1113*0Sstevel@tonic-gate compelem)])) == NULL) { 1114*0Sstevel@tonic-gate pool_seterror( 1115*0Sstevel@tonic-gate POE_DATASTORE); 1116*0Sstevel@tonic-gate free(rs); 1117*0Sstevel@tonic-gate free(cs); 1118*0Sstevel@tonic-gate free_char_buf(cb); 1119*0Sstevel@tonic-gate xmlFreeDoc(info. 1120*0Sstevel@tonic-gate ktx_doc); 1121*0Sstevel@tonic-gate return (PO_FAIL); 1122*0Sstevel@tonic-gate } 1123*0Sstevel@tonic-gate if (pool_walk_any_properties( 1124*0Sstevel@tonic-gate (pool_conf_t *)conf, 1125*0Sstevel@tonic-gate compelem, &info, 1126*0Sstevel@tonic-gate prop_build_cb, 1) == 1127*0Sstevel@tonic-gate PO_FAIL) { 1128*0Sstevel@tonic-gate free(rs); 1129*0Sstevel@tonic-gate free(cs); 1130*0Sstevel@tonic-gate free_char_buf(cb); 1131*0Sstevel@tonic-gate xmlFreeDoc(info. 1132*0Sstevel@tonic-gate ktx_doc); 1133*0Sstevel@tonic-gate return (PO_FAIL); 1134*0Sstevel@tonic-gate } 1135*0Sstevel@tonic-gate if (set_char_buf(cb, "%s_%d", 1136*0Sstevel@tonic-gate pool_elem_class_string( 1137*0Sstevel@tonic-gate compelem), 1138*0Sstevel@tonic-gate (int)elem_get_sysid( 1139*0Sstevel@tonic-gate compelem)) == PO_FAIL) { 1140*0Sstevel@tonic-gate free(rs); 1141*0Sstevel@tonic-gate free(cs); 1142*0Sstevel@tonic-gate free_char_buf(cb); 1143*0Sstevel@tonic-gate xmlFreeDoc(info. 1144*0Sstevel@tonic-gate ktx_doc); 1145*0Sstevel@tonic-gate return (PO_FAIL); 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate xmlSetProp(info.ktx_node, 1148*0Sstevel@tonic-gate BAD_CAST c_ref_id, 1149*0Sstevel@tonic-gate BAD_CAST cb->cb_buf); 1150*0Sstevel@tonic-gate } 1151*0Sstevel@tonic-gate free(cs); 1152*0Sstevel@tonic-gate } 1153*0Sstevel@tonic-gate } 1154*0Sstevel@tonic-gate free(rs); 1155*0Sstevel@tonic-gate } 1156*0Sstevel@tonic-gate free_char_buf(cb); 1157*0Sstevel@tonic-gate /* 1158*0Sstevel@tonic-gate * Set up the message handlers prior to calling 1159*0Sstevel@tonic-gate * xmlValidateDocument() 1160*0Sstevel@tonic-gate */ 1161*0Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) { 1162*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1163*0Sstevel@tonic-gate pool_seterror(POE_DATASTORE); 1164*0Sstevel@tonic-gate return (PO_FAIL); 1165*0Sstevel@tonic-gate } 1166*0Sstevel@tonic-gate cvp->error = pool_error_func; 1167*0Sstevel@tonic-gate cvp->warning = pool_error_func; 1168*0Sstevel@tonic-gate if (xmlValidateDocument(cvp, info.ktx_doc) == 0) { 1169*0Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 1170*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1171*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1172*0Sstevel@tonic-gate return (PO_FAIL); 1173*0Sstevel@tonic-gate } 1174*0Sstevel@tonic-gate xmlFreeValidCtxt(cvp); 1175*0Sstevel@tonic-gate ret = xmlSaveFormatFile(location, info.ktx_doc, 1); 1176*0Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc); 1177*0Sstevel@tonic-gate if (ret == -1) { 1178*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1179*0Sstevel@tonic-gate return (PO_FAIL); 1180*0Sstevel@tonic-gate } 1181*0Sstevel@tonic-gate return (PO_SUCCESS); 1182*0Sstevel@tonic-gate default: 1183*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1184*0Sstevel@tonic-gate return (PO_FAIL); 1185*0Sstevel@tonic-gate } 1186*0Sstevel@tonic-gate } 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate /* 1189*0Sstevel@tonic-gate * Rollback the changes to the kernel 1190*0Sstevel@tonic-gate */ 1191*0Sstevel@tonic-gate int 1192*0Sstevel@tonic-gate pool_knl_recover(pool_conf_t *conf) 1193*0Sstevel@tonic-gate { 1194*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 1195*0Sstevel@tonic-gate 1196*0Sstevel@tonic-gate prov->pkc_log->l_state = LS_RECOVER; 1197*0Sstevel@tonic-gate if (log_reverse_walk(prov->pkc_log, log_item_undo) != PO_SUCCESS) { 1198*0Sstevel@tonic-gate dprintf("Library configuration consistency error\n"); 1199*0Sstevel@tonic-gate prov->pkc_log->l_state = LS_FAIL; 1200*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1201*0Sstevel@tonic-gate return (PO_FAIL); 1202*0Sstevel@tonic-gate } 1203*0Sstevel@tonic-gate prov->pkc_log->l_state = LS_DO; 1204*0Sstevel@tonic-gate return (PO_SUCCESS); 1205*0Sstevel@tonic-gate } 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gate /* 1208*0Sstevel@tonic-gate * Rollback the changes to the configuration 1209*0Sstevel@tonic-gate */ 1210*0Sstevel@tonic-gate int 1211*0Sstevel@tonic-gate pool_knl_rollback(pool_conf_t *conf) 1212*0Sstevel@tonic-gate { 1213*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 1214*0Sstevel@tonic-gate 1215*0Sstevel@tonic-gate prov->pkc_log->l_state = LS_UNDO; 1216*0Sstevel@tonic-gate if (log_reverse_walk(prov->pkc_log, log_item_undo) != PO_SUCCESS) { 1217*0Sstevel@tonic-gate dprintf("Kernel configuration consistency error\n"); 1218*0Sstevel@tonic-gate (void) log_walk(prov->pkc_log, log_item_release); 1219*0Sstevel@tonic-gate log_empty(prov->pkc_log); 1220*0Sstevel@tonic-gate prov->pkc_log->l_state = LS_FAIL; 1221*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1222*0Sstevel@tonic-gate return (PO_FAIL); 1223*0Sstevel@tonic-gate } 1224*0Sstevel@tonic-gate (void) log_walk(prov->pkc_log, log_item_release); 1225*0Sstevel@tonic-gate log_empty(prov->pkc_log); 1226*0Sstevel@tonic-gate prov->pkc_log->l_state = LS_DO; 1227*0Sstevel@tonic-gate return (PO_SUCCESS); 1228*0Sstevel@tonic-gate } 1229*0Sstevel@tonic-gate 1230*0Sstevel@tonic-gate /* 1231*0Sstevel@tonic-gate * Callback used to build the result set for a query. Each invocation will 1232*0Sstevel@tonic-gate * supply a candidate element for inclusion. The element is filtered by: 1233*0Sstevel@tonic-gate * - class 1234*0Sstevel@tonic-gate * - properties 1235*0Sstevel@tonic-gate * If the element "matches" the target, then it is added to the result 1236*0Sstevel@tonic-gate * set, otherwise it is ignored. 1237*0Sstevel@tonic-gate */ 1238*0Sstevel@tonic-gate /* ARGSUSED1 */ 1239*0Sstevel@tonic-gate static void 1240*0Sstevel@tonic-gate build_result_set(const void *key, void **value, void *cl) 1241*0Sstevel@tonic-gate { 1242*0Sstevel@tonic-gate struct query_obj *qo = (struct query_obj *)cl; 1243*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key; 1244*0Sstevel@tonic-gate 1245*0Sstevel@tonic-gate /* 1246*0Sstevel@tonic-gate * Check to see if it's the right class of element 1247*0Sstevel@tonic-gate */ 1248*0Sstevel@tonic-gate if (qo->classes & (1 << pool_elem_class((pool_elem_t *)key))) { 1249*0Sstevel@tonic-gate int i; 1250*0Sstevel@tonic-gate /* 1251*0Sstevel@tonic-gate * Now check to see if the src element is correct. If no src 1252*0Sstevel@tonic-gate * element is supplied, ignore this check 1253*0Sstevel@tonic-gate */ 1254*0Sstevel@tonic-gate if (qo->src) { 1255*0Sstevel@tonic-gate pool_knl_elem_t *parent; 1256*0Sstevel@tonic-gate 1257*0Sstevel@tonic-gate for (parent = pke; parent != NULL; 1258*0Sstevel@tonic-gate parent = parent->pke_parent) { 1259*0Sstevel@tonic-gate if (parent == (pool_knl_elem_t *)qo->src) 1260*0Sstevel@tonic-gate break; 1261*0Sstevel@tonic-gate } 1262*0Sstevel@tonic-gate if (parent == NULL) 1263*0Sstevel@tonic-gate return; 1264*0Sstevel@tonic-gate } 1265*0Sstevel@tonic-gate /* 1266*0Sstevel@tonic-gate * Now check for property matches (if there are any specified) 1267*0Sstevel@tonic-gate */ 1268*0Sstevel@tonic-gate if (qo->props) { 1269*0Sstevel@tonic-gate int matched = PO_TRUE; 1270*0Sstevel@tonic-gate for (i = 0; qo->props[i] != NULL; i++) { 1271*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 1272*0Sstevel@tonic-gate 1273*0Sstevel@tonic-gate if (pool_get_property(TO_CONF(TO_ELEM(pke)), 1274*0Sstevel@tonic-gate (pool_elem_t *)pke, 1275*0Sstevel@tonic-gate pool_value_get_name(qo->props[i]), &val) == 1276*0Sstevel@tonic-gate POC_INVAL) { 1277*0Sstevel@tonic-gate matched = PO_FALSE; 1278*0Sstevel@tonic-gate break; 1279*0Sstevel@tonic-gate } else { 1280*0Sstevel@tonic-gate if (pool_value_equal(qo->props[i], 1281*0Sstevel@tonic-gate &val) != PO_TRUE) { 1282*0Sstevel@tonic-gate matched = PO_FALSE; 1283*0Sstevel@tonic-gate break; 1284*0Sstevel@tonic-gate } 1285*0Sstevel@tonic-gate } 1286*0Sstevel@tonic-gate } 1287*0Sstevel@tonic-gate if (matched == PO_TRUE) 1288*0Sstevel@tonic-gate (void) pool_knl_result_set_append(qo->rs, 1289*0Sstevel@tonic-gate (pool_knl_elem_t *)key); 1290*0Sstevel@tonic-gate } else { 1291*0Sstevel@tonic-gate (void) pool_knl_result_set_append(qo->rs, 1292*0Sstevel@tonic-gate (pool_knl_elem_t *)key); 1293*0Sstevel@tonic-gate } 1294*0Sstevel@tonic-gate } 1295*0Sstevel@tonic-gate } 1296*0Sstevel@tonic-gate 1297*0Sstevel@tonic-gate /* 1298*0Sstevel@tonic-gate * Execute the supplied query and return a result set which contains 1299*0Sstevel@tonic-gate * all qualifying elements. 1300*0Sstevel@tonic-gate */ 1301*0Sstevel@tonic-gate pool_result_set_t * 1302*0Sstevel@tonic-gate pool_knl_exec_query(const pool_conf_t *conf, const pool_elem_t *src, 1303*0Sstevel@tonic-gate const char *src_attr, pool_elem_class_t classes, pool_value_t **props) 1304*0Sstevel@tonic-gate { 1305*0Sstevel@tonic-gate pool_knl_result_set_t *rs; 1306*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 1307*0Sstevel@tonic-gate struct query_obj qo; 1308*0Sstevel@tonic-gate int matched = PO_TRUE; 1309*0Sstevel@tonic-gate 1310*0Sstevel@tonic-gate /* 1311*0Sstevel@tonic-gate * Have a buffer at this point, that we can use 1312*0Sstevel@tonic-gate */ 1313*0Sstevel@tonic-gate if ((rs = pool_knl_result_set_alloc(conf)) == NULL) { 1314*0Sstevel@tonic-gate return (NULL); 1315*0Sstevel@tonic-gate } 1316*0Sstevel@tonic-gate qo.conf = conf; 1317*0Sstevel@tonic-gate qo.src = src; 1318*0Sstevel@tonic-gate qo.src_attr = src_attr; 1319*0Sstevel@tonic-gate qo.classes = classes; 1320*0Sstevel@tonic-gate qo.props = props; 1321*0Sstevel@tonic-gate qo.rs = rs; 1322*0Sstevel@tonic-gate if (src_attr != NULL) { 1323*0Sstevel@tonic-gate pool_knl_pool_t *pkp = (pool_knl_pool_t *)src; 1324*0Sstevel@tonic-gate 1325*0Sstevel@tonic-gate /* 1326*0Sstevel@tonic-gate * Note: This logic is resource specific and must be 1327*0Sstevel@tonic-gate * extended for additional resource types. 1328*0Sstevel@tonic-gate */ 1329*0Sstevel@tonic-gate /* 1330*0Sstevel@tonic-gate * Check for property matches (if there are any specified) 1331*0Sstevel@tonic-gate */ 1332*0Sstevel@tonic-gate if (props) { 1333*0Sstevel@tonic-gate int i; 1334*0Sstevel@tonic-gate 1335*0Sstevel@tonic-gate for (i = 0; props[i] != NULL; i++) { 1336*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 1337*0Sstevel@tonic-gate 1338*0Sstevel@tonic-gate if (pool_get_property(conf, 1339*0Sstevel@tonic-gate (pool_elem_t *)pkp->pkp_assoc[PREC_PSET], 1340*0Sstevel@tonic-gate pool_value_get_name(props[i]), &val) == 1341*0Sstevel@tonic-gate POC_INVAL) { 1342*0Sstevel@tonic-gate matched = PO_FALSE; 1343*0Sstevel@tonic-gate break; 1344*0Sstevel@tonic-gate } else { 1345*0Sstevel@tonic-gate if (pool_value_equal(props[i], 1346*0Sstevel@tonic-gate &val) != PO_TRUE) { 1347*0Sstevel@tonic-gate matched = PO_FALSE; 1348*0Sstevel@tonic-gate break; 1349*0Sstevel@tonic-gate } 1350*0Sstevel@tonic-gate } 1351*0Sstevel@tonic-gate } 1352*0Sstevel@tonic-gate } 1353*0Sstevel@tonic-gate 1354*0Sstevel@tonic-gate if (matched == PO_TRUE) 1355*0Sstevel@tonic-gate (void) pool_knl_result_set_append(rs, 1356*0Sstevel@tonic-gate (pool_knl_elem_t *)pkp->pkp_assoc[PREC_PSET]); 1357*0Sstevel@tonic-gate } else 1358*0Sstevel@tonic-gate dict_map(prov->pkc_elements, build_result_set, &qo); 1359*0Sstevel@tonic-gate 1360*0Sstevel@tonic-gate return ((pool_result_set_t *)rs); 1361*0Sstevel@tonic-gate } 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gate /* 1364*0Sstevel@tonic-gate * Callback function intended to be used from pool_walk_pools(). If 1365*0Sstevel@tonic-gate * the supplied pool is not the default pool attempt to destroy it. 1366*0Sstevel@tonic-gate */ 1367*0Sstevel@tonic-gate /*ARGSUSED*/ 1368*0Sstevel@tonic-gate static int 1369*0Sstevel@tonic-gate destroy_pool_cb(pool_conf_t *conf, pool_t *pool, void *unused) 1370*0Sstevel@tonic-gate { 1371*0Sstevel@tonic-gate if (elem_is_default(TO_ELEM(pool)) != PO_TRUE) 1372*0Sstevel@tonic-gate return (pool_destroy(conf, pool)); 1373*0Sstevel@tonic-gate /* 1374*0Sstevel@tonic-gate * Return PO_SUCCESS even though we don't delete the default 1375*0Sstevel@tonic-gate * pool so that the walk continues 1376*0Sstevel@tonic-gate */ 1377*0Sstevel@tonic-gate return (PO_SUCCESS); 1378*0Sstevel@tonic-gate } 1379*0Sstevel@tonic-gate 1380*0Sstevel@tonic-gate /* 1381*0Sstevel@tonic-gate * Remove the configuration details. This means remove all elements 1382*0Sstevel@tonic-gate * apart from the system elements. 1383*0Sstevel@tonic-gate */ 1384*0Sstevel@tonic-gate int 1385*0Sstevel@tonic-gate pool_knl_remove(pool_conf_t *conf) 1386*0Sstevel@tonic-gate { 1387*0Sstevel@tonic-gate uint_t i, nelem; 1388*0Sstevel@tonic-gate pool_resource_t **resources; 1389*0Sstevel@tonic-gate 1390*0Sstevel@tonic-gate conf->pc_state = POF_DESTROY; 1391*0Sstevel@tonic-gate if ((resources = pool_query_resources(conf, &nelem, NULL)) != NULL) { 1392*0Sstevel@tonic-gate for (i = 0; i < nelem; i++) { 1393*0Sstevel@tonic-gate if (resource_is_system(resources[i]) == PO_FALSE) 1394*0Sstevel@tonic-gate if (pool_resource_destroy(conf, resources[i]) != 1395*0Sstevel@tonic-gate PO_SUCCESS) { 1396*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1397*0Sstevel@tonic-gate return (PO_FAIL); 1398*0Sstevel@tonic-gate } 1399*0Sstevel@tonic-gate } 1400*0Sstevel@tonic-gate free(resources); 1401*0Sstevel@tonic-gate } 1402*0Sstevel@tonic-gate (void) pool_walk_pools(conf, conf, destroy_pool_cb); 1403*0Sstevel@tonic-gate if (pool_conf_commit(conf, PO_FALSE) != PO_SUCCESS) 1404*0Sstevel@tonic-gate return (PO_FAIL); 1405*0Sstevel@tonic-gate 1406*0Sstevel@tonic-gate if (pool_conf_close(conf) != PO_SUCCESS) 1407*0Sstevel@tonic-gate return (PO_FAIL); 1408*0Sstevel@tonic-gate 1409*0Sstevel@tonic-gate return (PO_SUCCESS); 1410*0Sstevel@tonic-gate } 1411*0Sstevel@tonic-gate 1412*0Sstevel@tonic-gate /* 1413*0Sstevel@tonic-gate * Determine the name of the pool to which the supplied pid is 1414*0Sstevel@tonic-gate * bound. If it cannot be determined return NULL. 1415*0Sstevel@tonic-gate */ 1416*0Sstevel@tonic-gate char * 1417*0Sstevel@tonic-gate pool_knl_get_binding(pool_conf_t *conf, pid_t pid) 1418*0Sstevel@tonic-gate { 1419*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 1420*0Sstevel@tonic-gate const char *sval; 1421*0Sstevel@tonic-gate char *name = NULL; 1422*0Sstevel@tonic-gate pool_bindq_t bindq; 1423*0Sstevel@tonic-gate pool_value_t *props[] = { NULL, NULL }; 1424*0Sstevel@tonic-gate uint_t nelem = 0; 1425*0Sstevel@tonic-gate pool_t **pools; 1426*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 1427*0Sstevel@tonic-gate 1428*0Sstevel@tonic-gate props[0] = &val; 1429*0Sstevel@tonic-gate 1430*0Sstevel@tonic-gate bindq.pb_o_id_type = P_PID; 1431*0Sstevel@tonic-gate bindq.pb_o_id = pid; 1432*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_BINDQ, &bindq) < 0) { 1433*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1434*0Sstevel@tonic-gate return (NULL); 1435*0Sstevel@tonic-gate } 1436*0Sstevel@tonic-gate 1437*0Sstevel@tonic-gate if (pool_value_set_name(props[0], "pool.sys_id") != PO_SUCCESS) { 1438*0Sstevel@tonic-gate return (NULL); 1439*0Sstevel@tonic-gate } 1440*0Sstevel@tonic-gate pool_value_set_int64(props[0], bindq.pb_i_id); 1441*0Sstevel@tonic-gate if ((pools = pool_query_pools(conf, &nelem, props)) == NULL) { 1442*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1443*0Sstevel@tonic-gate return (NULL); 1444*0Sstevel@tonic-gate } 1445*0Sstevel@tonic-gate 1446*0Sstevel@tonic-gate if (nelem != 1) { 1447*0Sstevel@tonic-gate free(pools); 1448*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1449*0Sstevel@tonic-gate return (NULL); 1450*0Sstevel@tonic-gate } 1451*0Sstevel@tonic-gate if (pool_get_ns_property(TO_ELEM(pools[0]), c_name, props[0]) 1452*0Sstevel@tonic-gate == POC_INVAL) { 1453*0Sstevel@tonic-gate free(pools); 1454*0Sstevel@tonic-gate return (NULL); 1455*0Sstevel@tonic-gate } 1456*0Sstevel@tonic-gate if (pool_value_get_string(props[0], &sval) != PO_SUCCESS) { 1457*0Sstevel@tonic-gate free(pools); 1458*0Sstevel@tonic-gate return (NULL); 1459*0Sstevel@tonic-gate } 1460*0Sstevel@tonic-gate if ((name = strdup(sval)) == NULL) { 1461*0Sstevel@tonic-gate free(pools); 1462*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1463*0Sstevel@tonic-gate return (NULL); 1464*0Sstevel@tonic-gate } 1465*0Sstevel@tonic-gate return (name); 1466*0Sstevel@tonic-gate } 1467*0Sstevel@tonic-gate 1468*0Sstevel@tonic-gate /* 1469*0Sstevel@tonic-gate * Bind idtype id to the pool name. 1470*0Sstevel@tonic-gate */ 1471*0Sstevel@tonic-gate int 1472*0Sstevel@tonic-gate pool_knl_set_binding(pool_conf_t *conf, const char *pool_name, idtype_t idtype, 1473*0Sstevel@tonic-gate id_t id) 1474*0Sstevel@tonic-gate { 1475*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 1476*0Sstevel@tonic-gate pool_bind_t bind; 1477*0Sstevel@tonic-gate pool_t *pool; 1478*0Sstevel@tonic-gate int ret; 1479*0Sstevel@tonic-gate 1480*0Sstevel@tonic-gate if ((pool = pool_get_pool(conf, pool_name)) == NULL) 1481*0Sstevel@tonic-gate return (PO_FAIL); 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate bind.pb_o_id_type = idtype; 1484*0Sstevel@tonic-gate bind.pb_o_id = id; 1485*0Sstevel@tonic-gate bind.pb_o_pool_id = elem_get_sysid(TO_ELEM(pool)); 1486*0Sstevel@tonic-gate 1487*0Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_BIND, &bind)) < 0 && 1488*0Sstevel@tonic-gate errno == EAGAIN); 1489*0Sstevel@tonic-gate if (ret < 0) { 1490*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1491*0Sstevel@tonic-gate return (PO_FAIL); 1492*0Sstevel@tonic-gate } 1493*0Sstevel@tonic-gate return (PO_SUCCESS); 1494*0Sstevel@tonic-gate } 1495*0Sstevel@tonic-gate 1496*0Sstevel@tonic-gate /* 1497*0Sstevel@tonic-gate * pool_knl_get_resource_binding() returns the binding for a pid to 1498*0Sstevel@tonic-gate * the supplied type of resource. If a binding cannot be determined, 1499*0Sstevel@tonic-gate * NULL is returned. 1500*0Sstevel@tonic-gate */ 1501*0Sstevel@tonic-gate char * 1502*0Sstevel@tonic-gate pool_knl_get_resource_binding(pool_conf_t *conf, 1503*0Sstevel@tonic-gate pool_resource_elem_class_t type, pid_t pid) 1504*0Sstevel@tonic-gate { 1505*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 1506*0Sstevel@tonic-gate const char *sval; 1507*0Sstevel@tonic-gate char *name = NULL; 1508*0Sstevel@tonic-gate pool_bindq_t bindq; 1509*0Sstevel@tonic-gate pool_value_t *props[] = { NULL, NULL }; 1510*0Sstevel@tonic-gate uint_t nelem = 0; 1511*0Sstevel@tonic-gate pool_t **pools; 1512*0Sstevel@tonic-gate pool_resource_t **resources; 1513*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 1514*0Sstevel@tonic-gate 1515*0Sstevel@tonic-gate props[0] = &val; 1516*0Sstevel@tonic-gate bindq.pb_o_id_type = P_PID; 1517*0Sstevel@tonic-gate bindq.pb_o_id = pid; 1518*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_BINDQ, &bindq) < 0) { 1519*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1520*0Sstevel@tonic-gate return (NULL); 1521*0Sstevel@tonic-gate } 1522*0Sstevel@tonic-gate 1523*0Sstevel@tonic-gate if (pool_value_set_name(props[0], "pool.sys_id") != PO_SUCCESS) { 1524*0Sstevel@tonic-gate return (NULL); 1525*0Sstevel@tonic-gate } 1526*0Sstevel@tonic-gate pool_value_set_int64(props[0], bindq.pb_i_id); 1527*0Sstevel@tonic-gate if ((pools = pool_query_pools(conf, &nelem, props)) == NULL) { 1528*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1529*0Sstevel@tonic-gate return (NULL); 1530*0Sstevel@tonic-gate } 1531*0Sstevel@tonic-gate 1532*0Sstevel@tonic-gate if (nelem != 1) { 1533*0Sstevel@tonic-gate free(pools); 1534*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1535*0Sstevel@tonic-gate return (NULL); 1536*0Sstevel@tonic-gate } 1537*0Sstevel@tonic-gate 1538*0Sstevel@tonic-gate if (pool_value_set_string(props[0], pool_resource_type_string(type)) != 1539*0Sstevel@tonic-gate PO_SUCCESS || 1540*0Sstevel@tonic-gate pool_value_set_name(props[0], c_type) != PO_SUCCESS) { 1541*0Sstevel@tonic-gate free(pools); 1542*0Sstevel@tonic-gate return (NULL); 1543*0Sstevel@tonic-gate } 1544*0Sstevel@tonic-gate 1545*0Sstevel@tonic-gate if ((resources = pool_query_pool_resources(conf, pools[0], &nelem, 1546*0Sstevel@tonic-gate NULL)) == NULL) { 1547*0Sstevel@tonic-gate free(pools); 1548*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1549*0Sstevel@tonic-gate return (NULL); 1550*0Sstevel@tonic-gate } 1551*0Sstevel@tonic-gate free(pools); 1552*0Sstevel@tonic-gate if (nelem != 1) { 1553*0Sstevel@tonic-gate free(resources); 1554*0Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF); 1555*0Sstevel@tonic-gate return (NULL); 1556*0Sstevel@tonic-gate } 1557*0Sstevel@tonic-gate if (pool_get_ns_property(TO_ELEM(resources[0]), c_name, props[0]) == 1558*0Sstevel@tonic-gate POC_INVAL) { 1559*0Sstevel@tonic-gate free(resources); 1560*0Sstevel@tonic-gate return (NULL); 1561*0Sstevel@tonic-gate } 1562*0Sstevel@tonic-gate free(resources); 1563*0Sstevel@tonic-gate if (pool_value_get_string(props[0], &sval) != PO_SUCCESS) { 1564*0Sstevel@tonic-gate return (NULL); 1565*0Sstevel@tonic-gate } 1566*0Sstevel@tonic-gate if ((name = strdup(sval)) == NULL) { 1567*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1568*0Sstevel@tonic-gate return (NULL); 1569*0Sstevel@tonic-gate } 1570*0Sstevel@tonic-gate return (name); 1571*0Sstevel@tonic-gate } 1572*0Sstevel@tonic-gate 1573*0Sstevel@tonic-gate /* 1574*0Sstevel@tonic-gate * Allocate the required library data structure and initialise it. 1575*0Sstevel@tonic-gate */ 1576*0Sstevel@tonic-gate pool_knl_elem_t * 1577*0Sstevel@tonic-gate pool_knl_elem_wrap(pool_conf_t *conf, pool_elem_class_t class, 1578*0Sstevel@tonic-gate pool_resource_elem_class_t res_class, 1579*0Sstevel@tonic-gate pool_component_elem_class_t comp_class) 1580*0Sstevel@tonic-gate { 1581*0Sstevel@tonic-gate pool_knl_elem_t *elem; 1582*0Sstevel@tonic-gate pool_elem_t *pe; 1583*0Sstevel@tonic-gate 1584*0Sstevel@tonic-gate switch (class) { 1585*0Sstevel@tonic-gate case PEC_SYSTEM: 1586*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_knl_system_t))) == NULL) { 1587*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1588*0Sstevel@tonic-gate return (NULL); 1589*0Sstevel@tonic-gate } 1590*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_knl_system_t)); 1591*0Sstevel@tonic-gate break; 1592*0Sstevel@tonic-gate case PEC_POOL: 1593*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_knl_pool_t))) == NULL) { 1594*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1595*0Sstevel@tonic-gate return (NULL); 1596*0Sstevel@tonic-gate } 1597*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_knl_pool_t)); 1598*0Sstevel@tonic-gate break; 1599*0Sstevel@tonic-gate case PEC_RES_COMP: 1600*0Sstevel@tonic-gate case PEC_RES_AGG: 1601*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_knl_resource_t))) == NULL) { 1602*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1603*0Sstevel@tonic-gate return (NULL); 1604*0Sstevel@tonic-gate } 1605*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_knl_resource_t)); 1606*0Sstevel@tonic-gate break; 1607*0Sstevel@tonic-gate case PEC_COMP: 1608*0Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_knl_component_t))) == NULL) { 1609*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1610*0Sstevel@tonic-gate return (NULL); 1611*0Sstevel@tonic-gate } 1612*0Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_knl_component_t)); 1613*0Sstevel@tonic-gate break; 1614*0Sstevel@tonic-gate default: 1615*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1616*0Sstevel@tonic-gate return (NULL); 1617*0Sstevel@tonic-gate } 1618*0Sstevel@tonic-gate pe = TO_ELEM(elem); 1619*0Sstevel@tonic-gate pe->pe_conf = conf; 1620*0Sstevel@tonic-gate pe->pe_class = class; 1621*0Sstevel@tonic-gate pe->pe_resource_class = res_class; 1622*0Sstevel@tonic-gate pe->pe_component_class = comp_class; 1623*0Sstevel@tonic-gate /* Set up the function pointers for element manipulation */ 1624*0Sstevel@tonic-gate pe->pe_get_prop = pool_knl_get_property; 1625*0Sstevel@tonic-gate pe->pe_put_prop = pool_knl_put_property; 1626*0Sstevel@tonic-gate pe->pe_rm_prop = pool_knl_rm_property; 1627*0Sstevel@tonic-gate pe->pe_get_props = pool_knl_get_properties; 1628*0Sstevel@tonic-gate pe->pe_remove = pool_knl_elem_remove; 1629*0Sstevel@tonic-gate pe->pe_get_container = pool_knl_get_container; 1630*0Sstevel@tonic-gate pe->pe_set_container = pool_knl_set_container; 1631*0Sstevel@tonic-gate /* 1632*0Sstevel@tonic-gate * Specific initialisation for different types of element 1633*0Sstevel@tonic-gate */ 1634*0Sstevel@tonic-gate if (class == PEC_POOL) { 1635*0Sstevel@tonic-gate pool_knl_pool_t *pp = (pool_knl_pool_t *)elem; 1636*0Sstevel@tonic-gate pp->pp_associate = pool_knl_pool_associate; 1637*0Sstevel@tonic-gate pp->pp_dissociate = pool_knl_pool_dissociate; 1638*0Sstevel@tonic-gate pp->pkp_assoc[PREC_PSET] = (pool_knl_resource_t *) 1639*0Sstevel@tonic-gate resource_by_sysid(conf, PS_NONE, "pset"); 1640*0Sstevel@tonic-gate } 1641*0Sstevel@tonic-gate if (class == PEC_RES_COMP || class == PEC_RES_AGG) { 1642*0Sstevel@tonic-gate pool_knl_resource_t *pr = (pool_knl_resource_t *)elem; 1643*0Sstevel@tonic-gate pr->pr_is_system = pool_knl_resource_is_system; 1644*0Sstevel@tonic-gate pr->pr_can_associate = pool_knl_resource_can_associate; 1645*0Sstevel@tonic-gate } 1646*0Sstevel@tonic-gate #if DEBUG 1647*0Sstevel@tonic-gate if (dict_put(((pool_knl_connection_t *)conf->pc_prov)->pkc_leaks, 1648*0Sstevel@tonic-gate elem, elem) != NULL) 1649*0Sstevel@tonic-gate assert(!"leak map put failed"); 1650*0Sstevel@tonic-gate dprintf("allocated %p\n", elem); 1651*0Sstevel@tonic-gate #endif /* DEBUG */ 1652*0Sstevel@tonic-gate return (elem); 1653*0Sstevel@tonic-gate } 1654*0Sstevel@tonic-gate 1655*0Sstevel@tonic-gate /* 1656*0Sstevel@tonic-gate * Allocate a new pool_knl_elem_t in the supplied configuration of the 1657*0Sstevel@tonic-gate * specified class. 1658*0Sstevel@tonic-gate * Returns element pointer/NULL 1659*0Sstevel@tonic-gate */ 1660*0Sstevel@tonic-gate pool_elem_t * 1661*0Sstevel@tonic-gate pool_knl_elem_create(pool_conf_t *conf, pool_elem_class_t class, 1662*0Sstevel@tonic-gate pool_resource_elem_class_t res_class, 1663*0Sstevel@tonic-gate pool_component_elem_class_t comp_class) 1664*0Sstevel@tonic-gate { 1665*0Sstevel@tonic-gate pool_knl_elem_t *elem; 1666*0Sstevel@tonic-gate pool_create_undo_t *create; 1667*0Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov; 1668*0Sstevel@tonic-gate static int id = -3; 1669*0Sstevel@tonic-gate char_buf_t *cb; 1670*0Sstevel@tonic-gate 1671*0Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, class, res_class, comp_class)) == 1672*0Sstevel@tonic-gate NULL) 1673*0Sstevel@tonic-gate return (NULL); 1674*0Sstevel@tonic-gate 1675*0Sstevel@tonic-gate /* 1676*0Sstevel@tonic-gate * Allocate an nvlist to hold properties 1677*0Sstevel@tonic-gate */ 1678*0Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties, NV_UNIQUE_NAME_TYPE, 0) != 0) { 1679*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE); 1680*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1681*0Sstevel@tonic-gate return (NULL); 1682*0Sstevel@tonic-gate } 1683*0Sstevel@tonic-gate /* 1684*0Sstevel@tonic-gate * Allocate a temporary ID and name until the element is 1685*0Sstevel@tonic-gate * created for real 1686*0Sstevel@tonic-gate */ 1687*0Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) { 1688*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 1689*0Sstevel@tonic-gate return (NULL); 1690*0Sstevel@tonic-gate } 1691*0Sstevel@tonic-gate if (set_char_buf(cb, "%s.sys_id", 1692*0Sstevel@tonic-gate pool_elem_class_string((pool_elem_t *)elem)) != PO_SUCCESS) { 1693*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 1694*0Sstevel@tonic-gate free_char_buf(cb); 1695*0Sstevel@tonic-gate return (NULL); 1696*0Sstevel@tonic-gate } 1697*0Sstevel@tonic-gate (void) nvlist_add_int64(elem->pke_properties, cb->cb_buf, id--); 1698*0Sstevel@tonic-gate if (set_char_buf(cb, "%s.name", 1699*0Sstevel@tonic-gate pool_elem_class_string((pool_elem_t *)elem)) != PO_SUCCESS) { 1700*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 1701*0Sstevel@tonic-gate free_char_buf(cb); 1702*0Sstevel@tonic-gate return (NULL); 1703*0Sstevel@tonic-gate } 1704*0Sstevel@tonic-gate (void) nvlist_add_string(elem->pke_properties, cb->cb_buf, ""); 1705*0Sstevel@tonic-gate /* 1706*0Sstevel@tonic-gate * If it's a resource class, it will need an initial size 1707*0Sstevel@tonic-gate */ 1708*0Sstevel@tonic-gate if (class == PEC_RES_COMP || class == PEC_RES_AGG) { 1709*0Sstevel@tonic-gate if (set_char_buf(cb, "%s.size", 1710*0Sstevel@tonic-gate pool_elem_class_string((pool_elem_t *)elem)) != 1711*0Sstevel@tonic-gate PO_SUCCESS) { 1712*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 1713*0Sstevel@tonic-gate free_char_buf(cb); 1714*0Sstevel@tonic-gate return (NULL); 1715*0Sstevel@tonic-gate } 1716*0Sstevel@tonic-gate (void) nvlist_add_uint64(elem->pke_properties, cb->cb_buf, 0); 1717*0Sstevel@tonic-gate } 1718*0Sstevel@tonic-gate free_char_buf(cb); 1719*0Sstevel@tonic-gate 1720*0Sstevel@tonic-gate /* 1721*0Sstevel@tonic-gate * Register the newly created element 1722*0Sstevel@tonic-gate */ 1723*0Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) != NULL) { 1724*0Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE); 1725*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1726*0Sstevel@tonic-gate return (NULL); 1727*0Sstevel@tonic-gate } 1728*0Sstevel@tonic-gate 1729*0Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) 1730*0Sstevel@tonic-gate return ((pool_elem_t *)elem); 1731*0Sstevel@tonic-gate 1732*0Sstevel@tonic-gate /* 1733*0Sstevel@tonic-gate * The remaining logic is setting up the arguments for the 1734*0Sstevel@tonic-gate * POOL_CREATE ioctl and appending the details into the log. 1735*0Sstevel@tonic-gate */ 1736*0Sstevel@tonic-gate if ((create = malloc(sizeof (pool_create_undo_t))) == NULL) { 1737*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1738*0Sstevel@tonic-gate return (NULL); 1739*0Sstevel@tonic-gate } 1740*0Sstevel@tonic-gate create->pcu_ioctl.pc_o_type = class; 1741*0Sstevel@tonic-gate switch (class) { 1742*0Sstevel@tonic-gate case PEC_SYSTEM: 1743*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1744*0Sstevel@tonic-gate free(create); 1745*0Sstevel@tonic-gate return (NULL); 1746*0Sstevel@tonic-gate case PEC_POOL: /* NO-OP */ 1747*0Sstevel@tonic-gate break; 1748*0Sstevel@tonic-gate case PEC_RES_COMP: 1749*0Sstevel@tonic-gate case PEC_RES_AGG: 1750*0Sstevel@tonic-gate create->pcu_ioctl.pc_o_sub_type = res_class; 1751*0Sstevel@tonic-gate break; 1752*0Sstevel@tonic-gate case PEC_COMP: 1753*0Sstevel@tonic-gate create->pcu_ioctl.pc_o_sub_type = comp_class; 1754*0Sstevel@tonic-gate break; 1755*0Sstevel@tonic-gate default: 1756*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1757*0Sstevel@tonic-gate free(create); 1758*0Sstevel@tonic-gate return (NULL); 1759*0Sstevel@tonic-gate } 1760*0Sstevel@tonic-gate 1761*0Sstevel@tonic-gate create->pcu_elem = (pool_elem_t *)elem; 1762*0Sstevel@tonic-gate 1763*0Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_CREATE, (void *)create) != 1764*0Sstevel@tonic-gate PO_SUCCESS) { 1765*0Sstevel@tonic-gate free(create); 1766*0Sstevel@tonic-gate return (NULL); 1767*0Sstevel@tonic-gate } 1768*0Sstevel@tonic-gate return ((pool_elem_t *)elem); 1769*0Sstevel@tonic-gate } 1770*0Sstevel@tonic-gate 1771*0Sstevel@tonic-gate /* 1772*0Sstevel@tonic-gate * Remove the details of the element from our userland copy and destroy 1773*0Sstevel@tonic-gate * the element (if appropriate) in the kernel. 1774*0Sstevel@tonic-gate */ 1775*0Sstevel@tonic-gate int 1776*0Sstevel@tonic-gate pool_knl_elem_remove(pool_elem_t *pe) 1777*0Sstevel@tonic-gate { 1778*0Sstevel@tonic-gate pool_knl_connection_t *prov; 1779*0Sstevel@tonic-gate pool_destroy_undo_t *destroy; 1780*0Sstevel@tonic-gate 1781*0Sstevel@tonic-gate prov = (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov; 1782*0Sstevel@tonic-gate 1783*0Sstevel@tonic-gate if (dict_remove(prov->pkc_elements, pe) == NULL) { 1784*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1785*0Sstevel@tonic-gate return (PO_FAIL); 1786*0Sstevel@tonic-gate } 1787*0Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) { 1788*0Sstevel@tonic-gate return (PO_SUCCESS); 1789*0Sstevel@tonic-gate } 1790*0Sstevel@tonic-gate 1791*0Sstevel@tonic-gate /* 1792*0Sstevel@tonic-gate * The remaining logic is setting up the arguments for the 1793*0Sstevel@tonic-gate * POOL_DESTROY ioctl and appending the details into the log. 1794*0Sstevel@tonic-gate */ 1795*0Sstevel@tonic-gate if ((destroy = malloc(sizeof (pool_destroy_undo_t))) == NULL) { 1796*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1797*0Sstevel@tonic-gate return (PO_FAIL); 1798*0Sstevel@tonic-gate } 1799*0Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_type = pool_elem_class(pe); 1800*0Sstevel@tonic-gate 1801*0Sstevel@tonic-gate if (destroy->pdu_ioctl.pd_o_type == PEC_RES_COMP || 1802*0Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_type == PEC_RES_AGG) 1803*0Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_sub_type = pool_resource_elem_class(pe); 1804*0Sstevel@tonic-gate 1805*0Sstevel@tonic-gate if (destroy->pdu_ioctl.pd_o_type == PEC_COMP) 1806*0Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_sub_type = 1807*0Sstevel@tonic-gate pool_component_elem_class(pe); 1808*0Sstevel@tonic-gate 1809*0Sstevel@tonic-gate destroy->pdu_elem = pe; 1810*0Sstevel@tonic-gate 1811*0Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_DESTROY, (void *)destroy) != 1812*0Sstevel@tonic-gate PO_SUCCESS) { 1813*0Sstevel@tonic-gate free(destroy); 1814*0Sstevel@tonic-gate return (PO_FAIL); 1815*0Sstevel@tonic-gate } 1816*0Sstevel@tonic-gate return (PO_SUCCESS); 1817*0Sstevel@tonic-gate } 1818*0Sstevel@tonic-gate 1819*0Sstevel@tonic-gate /* 1820*0Sstevel@tonic-gate * Set the parent of the supplied child to the supplied parent 1821*0Sstevel@tonic-gate */ 1822*0Sstevel@tonic-gate int 1823*0Sstevel@tonic-gate pool_knl_set_container(pool_elem_t *pp, pool_elem_t *pc) 1824*0Sstevel@tonic-gate { 1825*0Sstevel@tonic-gate pool_knl_elem_t *pkp = (pool_knl_elem_t *)pp; 1826*0Sstevel@tonic-gate pool_knl_elem_t *pkc = (pool_knl_elem_t *)pc; 1827*0Sstevel@tonic-gate 1828*0Sstevel@tonic-gate pkc->pke_parent = pkp; 1829*0Sstevel@tonic-gate return (PO_SUCCESS); 1830*0Sstevel@tonic-gate } 1831*0Sstevel@tonic-gate 1832*0Sstevel@tonic-gate /* 1833*0Sstevel@tonic-gate * TODO: Needed for msets and ssets. 1834*0Sstevel@tonic-gate */ 1835*0Sstevel@tonic-gate /* ARGSUSED */ 1836*0Sstevel@tonic-gate int 1837*0Sstevel@tonic-gate pool_knl_res_transfer(pool_resource_t *src, pool_resource_t *tgt, 1838*0Sstevel@tonic-gate uint64_t size) { 1839*0Sstevel@tonic-gate return (PO_FAIL); 1840*0Sstevel@tonic-gate } 1841*0Sstevel@tonic-gate 1842*0Sstevel@tonic-gate /* 1843*0Sstevel@tonic-gate * Transfer resource components from one resource set to another. 1844*0Sstevel@tonic-gate */ 1845*0Sstevel@tonic-gate int 1846*0Sstevel@tonic-gate pool_knl_res_xtransfer(pool_resource_t *src, pool_resource_t *tgt, 1847*0Sstevel@tonic-gate pool_component_t **rl) { 1848*0Sstevel@tonic-gate pool_elem_t *src_e = TO_ELEM(src); 1849*0Sstevel@tonic-gate pool_elem_t *tgt_e = TO_ELEM(tgt); 1850*0Sstevel@tonic-gate pool_xtransfer_undo_t *xtransfer; 1851*0Sstevel@tonic-gate size_t size; 1852*0Sstevel@tonic-gate pool_knl_connection_t *prov = 1853*0Sstevel@tonic-gate (pool_knl_connection_t *)TO_CONF(src_e)->pc_prov; 1854*0Sstevel@tonic-gate 1855*0Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) { 1856*0Sstevel@tonic-gate /* 1857*0Sstevel@tonic-gate * Walk the Result Set and move the resource components 1858*0Sstevel@tonic-gate */ 1859*0Sstevel@tonic-gate for (size = 0; rl[size] != NULL; size++) { 1860*0Sstevel@tonic-gate if (pool_set_container(TO_ELEM(tgt), 1861*0Sstevel@tonic-gate TO_ELEM(rl[size])) == PO_FAIL) { 1862*0Sstevel@tonic-gate return (PO_FAIL); 1863*0Sstevel@tonic-gate } 1864*0Sstevel@tonic-gate } 1865*0Sstevel@tonic-gate return (PO_SUCCESS); 1866*0Sstevel@tonic-gate } 1867*0Sstevel@tonic-gate 1868*0Sstevel@tonic-gate /* 1869*0Sstevel@tonic-gate * The remaining logic is setting up the arguments for the 1870*0Sstevel@tonic-gate * POOL_XTRANSFER ioctl and appending the details into the log. 1871*0Sstevel@tonic-gate */ 1872*0Sstevel@tonic-gate if ((xtransfer = malloc(sizeof (pool_xtransfer_undo_t))) == NULL) { 1873*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1874*0Sstevel@tonic-gate return (PO_FAIL); 1875*0Sstevel@tonic-gate } 1876*0Sstevel@tonic-gate 1877*0Sstevel@tonic-gate if (pool_elem_class(src_e) == PEC_RES_COMP) { 1878*0Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_id_type = 1879*0Sstevel@tonic-gate pool_resource_elem_class(src_e); 1880*0Sstevel@tonic-gate } else { 1881*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1882*0Sstevel@tonic-gate return (PO_FAIL); 1883*0Sstevel@tonic-gate } 1884*0Sstevel@tonic-gate 1885*0Sstevel@tonic-gate 1886*0Sstevel@tonic-gate for (xtransfer->pxu_ioctl.px_o_complist_size = 0; 1887*0Sstevel@tonic-gate rl[xtransfer->pxu_ioctl.px_o_complist_size] != NULL; 1888*0Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_complist_size++) 1889*0Sstevel@tonic-gate /* calculate the size using the terminating NULL */; 1890*0Sstevel@tonic-gate if ((xtransfer->pxu_ioctl.px_o_comp_list = 1891*0Sstevel@tonic-gate calloc(xtransfer->pxu_ioctl.px_o_complist_size, 1892*0Sstevel@tonic-gate sizeof (id_t))) == NULL) { 1893*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1894*0Sstevel@tonic-gate return (PO_FAIL); 1895*0Sstevel@tonic-gate } 1896*0Sstevel@tonic-gate if ((xtransfer->pxu_rl = calloc( 1897*0Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_complist_size + 1, 1898*0Sstevel@tonic-gate sizeof (pool_component_t *))) == NULL) { 1899*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 1900*0Sstevel@tonic-gate return (PO_FAIL); 1901*0Sstevel@tonic-gate } 1902*0Sstevel@tonic-gate (void) memcpy(xtransfer->pxu_rl, rl, 1903*0Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_complist_size * 1904*0Sstevel@tonic-gate sizeof (pool_component_t *)); 1905*0Sstevel@tonic-gate xtransfer->pxu_src = src_e; 1906*0Sstevel@tonic-gate xtransfer->pxu_tgt = tgt_e; 1907*0Sstevel@tonic-gate 1908*0Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_XTRANSFER, (void *)xtransfer) != 1909*0Sstevel@tonic-gate PO_SUCCESS) { 1910*0Sstevel@tonic-gate free(xtransfer); 1911*0Sstevel@tonic-gate return (PO_FAIL); 1912*0Sstevel@tonic-gate } 1913*0Sstevel@tonic-gate for (size = 0; rl[size] != NULL; size++) { 1914*0Sstevel@tonic-gate if (pool_set_container(TO_ELEM(tgt), TO_ELEM(rl[size])) == 1915*0Sstevel@tonic-gate PO_FAIL) { 1916*0Sstevel@tonic-gate return (PO_FAIL); 1917*0Sstevel@tonic-gate } 1918*0Sstevel@tonic-gate } 1919*0Sstevel@tonic-gate return (PO_SUCCESS); 1920*0Sstevel@tonic-gate } 1921*0Sstevel@tonic-gate 1922*0Sstevel@tonic-gate /* 1923*0Sstevel@tonic-gate * Return the parent of an element. 1924*0Sstevel@tonic-gate */ 1925*0Sstevel@tonic-gate pool_elem_t * 1926*0Sstevel@tonic-gate pool_knl_get_container(const pool_elem_t *pe) 1927*0Sstevel@tonic-gate { 1928*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe; 1929*0Sstevel@tonic-gate 1930*0Sstevel@tonic-gate return ((pool_elem_t *)pke->pke_parent); 1931*0Sstevel@tonic-gate } 1932*0Sstevel@tonic-gate 1933*0Sstevel@tonic-gate /* 1934*0Sstevel@tonic-gate * Note: This function is resource specific, needs extending for other 1935*0Sstevel@tonic-gate * resource types 1936*0Sstevel@tonic-gate */ 1937*0Sstevel@tonic-gate int 1938*0Sstevel@tonic-gate pool_knl_resource_is_system(const pool_resource_t *pr) 1939*0Sstevel@tonic-gate { 1940*0Sstevel@tonic-gate switch (pool_resource_elem_class(TO_ELEM(pr))) { 1941*0Sstevel@tonic-gate case PREC_PSET: 1942*0Sstevel@tonic-gate return (PSID_IS_SYSSET( 1943*0Sstevel@tonic-gate elem_get_sysid(TO_ELEM(pr)))); 1944*0Sstevel@tonic-gate default: 1945*0Sstevel@tonic-gate return (PO_FALSE); 1946*0Sstevel@tonic-gate } 1947*0Sstevel@tonic-gate } 1948*0Sstevel@tonic-gate 1949*0Sstevel@tonic-gate /* 1950*0Sstevel@tonic-gate * Note: This function is resource specific, needs extending for other 1951*0Sstevel@tonic-gate * resource types 1952*0Sstevel@tonic-gate */ 1953*0Sstevel@tonic-gate int 1954*0Sstevel@tonic-gate pool_knl_resource_can_associate(const pool_resource_t *pr) 1955*0Sstevel@tonic-gate { 1956*0Sstevel@tonic-gate switch (pool_resource_elem_class(TO_ELEM(pr))) { 1957*0Sstevel@tonic-gate case PREC_PSET: 1958*0Sstevel@tonic-gate return (PO_TRUE); 1959*0Sstevel@tonic-gate default: 1960*0Sstevel@tonic-gate return (PO_FALSE); 1961*0Sstevel@tonic-gate } 1962*0Sstevel@tonic-gate } 1963*0Sstevel@tonic-gate 1964*0Sstevel@tonic-gate /* 1965*0Sstevel@tonic-gate * pool_knl_pool_associate() associates the supplied resource to the 1966*0Sstevel@tonic-gate * supplied pool. 1967*0Sstevel@tonic-gate * 1968*0Sstevel@tonic-gate * Returns: PO_SUCCESS/PO_FAIL 1969*0Sstevel@tonic-gate */ 1970*0Sstevel@tonic-gate int 1971*0Sstevel@tonic-gate pool_knl_pool_associate(pool_t *pool, const pool_resource_t *resource) 1972*0Sstevel@tonic-gate { 1973*0Sstevel@tonic-gate pool_knl_connection_t *prov; 1974*0Sstevel@tonic-gate pool_knl_pool_t *pkp = (pool_knl_pool_t *)pool; 1975*0Sstevel@tonic-gate pool_resource_elem_class_t res_class = 1976*0Sstevel@tonic-gate pool_resource_elem_class(TO_ELEM(resource)); 1977*0Sstevel@tonic-gate pool_assoc_undo_t *assoc; 1978*0Sstevel@tonic-gate pool_knl_resource_t *orig_res = pkp->pkp_assoc[res_class]; 1979*0Sstevel@tonic-gate 1980*0Sstevel@tonic-gate /* 1981*0Sstevel@tonic-gate * Are we allowed to associate with this target? 1982*0Sstevel@tonic-gate */ 1983*0Sstevel@tonic-gate if (pool_knl_resource_can_associate(resource) == PO_FALSE) { 1984*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 1985*0Sstevel@tonic-gate return (PO_FAIL); 1986*0Sstevel@tonic-gate } 1987*0Sstevel@tonic-gate prov = (pool_knl_connection_t *)(TO_CONF(TO_ELEM(pool)))->pc_prov; 1988*0Sstevel@tonic-gate 1989*0Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) { 1990*0Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource; 1991*0Sstevel@tonic-gate return (PO_SUCCESS); 1992*0Sstevel@tonic-gate } 1993*0Sstevel@tonic-gate 1994*0Sstevel@tonic-gate /* 1995*0Sstevel@tonic-gate * The remaining logic is setting up the arguments for the 1996*0Sstevel@tonic-gate * POOL_ASSOC ioctl and appending the details into the log. 1997*0Sstevel@tonic-gate */ 1998*0Sstevel@tonic-gate if ((assoc = malloc(sizeof (pool_assoc_undo_t))) == NULL) { 1999*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2000*0Sstevel@tonic-gate return (PO_FAIL); 2001*0Sstevel@tonic-gate } 2002*0Sstevel@tonic-gate assoc->pau_assoc = TO_ELEM(pool); 2003*0Sstevel@tonic-gate assoc->pau_oldres = (pool_elem_t *)orig_res; 2004*0Sstevel@tonic-gate assoc->pau_newres = TO_ELEM(resource); 2005*0Sstevel@tonic-gate 2006*0Sstevel@tonic-gate assoc->pau_ioctl.pa_o_id_type = res_class; 2007*0Sstevel@tonic-gate 2008*0Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_ASSOC, (void *)assoc) != 2009*0Sstevel@tonic-gate PO_SUCCESS) { 2010*0Sstevel@tonic-gate free(assoc); 2011*0Sstevel@tonic-gate pkp->pkp_assoc[res_class] = orig_res; 2012*0Sstevel@tonic-gate return (PO_FAIL); 2013*0Sstevel@tonic-gate } 2014*0Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource; 2015*0Sstevel@tonic-gate return (PO_SUCCESS); 2016*0Sstevel@tonic-gate } 2017*0Sstevel@tonic-gate 2018*0Sstevel@tonic-gate /* 2019*0Sstevel@tonic-gate * pool_knl_pool_dissociate() dissociates the supplied resource from 2020*0Sstevel@tonic-gate * the supplied pool. 2021*0Sstevel@tonic-gate * 2022*0Sstevel@tonic-gate * Returns: PO_SUCCESS/PO_FAIL 2023*0Sstevel@tonic-gate */ 2024*0Sstevel@tonic-gate int 2025*0Sstevel@tonic-gate pool_knl_pool_dissociate(pool_t *pool, const pool_resource_t *resource) 2026*0Sstevel@tonic-gate { 2027*0Sstevel@tonic-gate pool_knl_connection_t *prov; 2028*0Sstevel@tonic-gate pool_dissoc_undo_t *dissoc; 2029*0Sstevel@tonic-gate pool_knl_pool_t *pkp = (pool_knl_pool_t *)pool; 2030*0Sstevel@tonic-gate pool_resource_t *default_res = (pool_resource_t *)get_default_resource( 2031*0Sstevel@tonic-gate resource); 2032*0Sstevel@tonic-gate pool_resource_elem_class_t res_class = 2033*0Sstevel@tonic-gate pool_resource_elem_class(TO_ELEM(resource)); 2034*0Sstevel@tonic-gate 2035*0Sstevel@tonic-gate prov = (pool_knl_connection_t *)(TO_CONF(TO_ELEM(pool)))->pc_prov; 2036*0Sstevel@tonic-gate 2037*0Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) { 2038*0Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)default_res; 2039*0Sstevel@tonic-gate return (PO_SUCCESS); 2040*0Sstevel@tonic-gate } 2041*0Sstevel@tonic-gate /* 2042*0Sstevel@tonic-gate * The remaining logic is setting up the arguments for the 2043*0Sstevel@tonic-gate * POOL_DISSOC ioctl and appending the details into the log. 2044*0Sstevel@tonic-gate */ 2045*0Sstevel@tonic-gate if ((dissoc = malloc(sizeof (pool_dissoc_undo_t))) == NULL) { 2046*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2047*0Sstevel@tonic-gate return (PO_FAIL); 2048*0Sstevel@tonic-gate } 2049*0Sstevel@tonic-gate dissoc->pdu_dissoc = TO_ELEM(pool); 2050*0Sstevel@tonic-gate dissoc->pdu_oldres = TO_ELEM(resource); 2051*0Sstevel@tonic-gate dissoc->pdu_newres = TO_ELEM(default_res); 2052*0Sstevel@tonic-gate 2053*0Sstevel@tonic-gate dissoc->pdu_ioctl.pd_o_id_type = res_class; 2054*0Sstevel@tonic-gate 2055*0Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_DISSOC, (void *)dissoc) != 2056*0Sstevel@tonic-gate PO_SUCCESS) { 2057*0Sstevel@tonic-gate free(dissoc); 2058*0Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource; 2059*0Sstevel@tonic-gate return (PO_FAIL); 2060*0Sstevel@tonic-gate } 2061*0Sstevel@tonic-gate 2062*0Sstevel@tonic-gate /* 2063*0Sstevel@tonic-gate * Update our local copy 2064*0Sstevel@tonic-gate */ 2065*0Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)default_res; 2066*0Sstevel@tonic-gate return (PO_SUCCESS); 2067*0Sstevel@tonic-gate } 2068*0Sstevel@tonic-gate 2069*0Sstevel@tonic-gate /* 2070*0Sstevel@tonic-gate * Allocate a data provider for the supplied configuration and optionally 2071*0Sstevel@tonic-gate * discover resources. 2072*0Sstevel@tonic-gate * The data provider is the cross over point from the "abstract" configuration 2073*0Sstevel@tonic-gate * functions into the data representation specific manipulation routines. 2074*0Sstevel@tonic-gate * This function sets up all the required pointers to create a kernel aware 2075*0Sstevel@tonic-gate * data provider. 2076*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 2077*0Sstevel@tonic-gate */ 2078*0Sstevel@tonic-gate int 2079*0Sstevel@tonic-gate pool_knl_connection_alloc(pool_conf_t *conf, int oflags) 2080*0Sstevel@tonic-gate { 2081*0Sstevel@tonic-gate pool_knl_connection_t *prov; 2082*0Sstevel@tonic-gate 2083*0Sstevel@tonic-gate if ((prov = malloc(sizeof (pool_knl_connection_t))) == NULL) { 2084*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2085*0Sstevel@tonic-gate return (PO_FAIL); 2086*0Sstevel@tonic-gate } 2087*0Sstevel@tonic-gate (void) memset(prov, 0, sizeof (pool_knl_connection_t)); 2088*0Sstevel@tonic-gate /* 2089*0Sstevel@tonic-gate * Initialise data members 2090*0Sstevel@tonic-gate */ 2091*0Sstevel@tonic-gate prov->pc_name = strdup("kernel"); 2092*0Sstevel@tonic-gate prov->pc_store_type = KERNEL_DATA_STORE; 2093*0Sstevel@tonic-gate prov->pc_oflags = oflags; 2094*0Sstevel@tonic-gate /* 2095*0Sstevel@tonic-gate * Initialise function pointers 2096*0Sstevel@tonic-gate */ 2097*0Sstevel@tonic-gate prov->pc_close = pool_knl_close; 2098*0Sstevel@tonic-gate prov->pc_validate = pool_knl_validate; 2099*0Sstevel@tonic-gate prov->pc_commit = pool_knl_commit; 2100*0Sstevel@tonic-gate prov->pc_export = pool_knl_export; 2101*0Sstevel@tonic-gate prov->pc_rollback = pool_knl_rollback; 2102*0Sstevel@tonic-gate prov->pc_exec_query = pool_knl_exec_query; 2103*0Sstevel@tonic-gate prov->pc_elem_create = pool_knl_elem_create; 2104*0Sstevel@tonic-gate prov->pc_remove = pool_knl_remove; 2105*0Sstevel@tonic-gate prov->pc_res_xfer = pool_knl_res_transfer; 2106*0Sstevel@tonic-gate prov->pc_res_xxfer = pool_knl_res_xtransfer; 2107*0Sstevel@tonic-gate prov->pc_get_binding = pool_knl_get_binding; 2108*0Sstevel@tonic-gate prov->pc_set_binding = pool_knl_set_binding; 2109*0Sstevel@tonic-gate prov->pc_get_resource_binding = pool_knl_get_resource_binding; 2110*0Sstevel@tonic-gate /* 2111*0Sstevel@tonic-gate * Associate the provider to it's configuration 2112*0Sstevel@tonic-gate */ 2113*0Sstevel@tonic-gate conf->pc_prov = (pool_connection_t *)prov; 2114*0Sstevel@tonic-gate /* 2115*0Sstevel@tonic-gate * End of common initialisation 2116*0Sstevel@tonic-gate */ 2117*0Sstevel@tonic-gate /* 2118*0Sstevel@tonic-gate * Attempt to open the pseudo device, if the configuration is opened 2119*0Sstevel@tonic-gate * readonly then try to open an info device, otherwise try to open 2120*0Sstevel@tonic-gate * the writeable device. 2121*0Sstevel@tonic-gate */ 2122*0Sstevel@tonic-gate if (oflags & PO_RDWR) { 2123*0Sstevel@tonic-gate if ((prov->pkc_fd = blocking_open(pool_dynamic_location(), 2124*0Sstevel@tonic-gate O_RDWR)) < 0) { 2125*0Sstevel@tonic-gate free(prov); 2126*0Sstevel@tonic-gate conf->pc_prov = NULL; 2127*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2128*0Sstevel@tonic-gate return (PO_FAIL); 2129*0Sstevel@tonic-gate } 2130*0Sstevel@tonic-gate } else { 2131*0Sstevel@tonic-gate if ((prov->pkc_fd = open(pool_info_location, O_RDWR)) < 0) { 2132*0Sstevel@tonic-gate free(prov); 2133*0Sstevel@tonic-gate conf->pc_prov = NULL; 2134*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2135*0Sstevel@tonic-gate return (PO_FAIL); 2136*0Sstevel@tonic-gate } 2137*0Sstevel@tonic-gate } 2138*0Sstevel@tonic-gate /* 2139*0Sstevel@tonic-gate * Allocate the element dictionary 2140*0Sstevel@tonic-gate */ 2141*0Sstevel@tonic-gate if ((prov->pkc_elements = dict_new((int (*)(const void *, const void *)) 2142*0Sstevel@tonic-gate pool_elem_compare, (uint64_t (*)(const void *))hash_id)) == NULL) { 2143*0Sstevel@tonic-gate (void) close(prov->pkc_fd); 2144*0Sstevel@tonic-gate free(prov); 2145*0Sstevel@tonic-gate conf->pc_prov = NULL; 2146*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2147*0Sstevel@tonic-gate return (PO_FAIL); 2148*0Sstevel@tonic-gate } 2149*0Sstevel@tonic-gate #if DEBUG 2150*0Sstevel@tonic-gate if ((prov->pkc_leaks = dict_new(NULL, NULL)) == NULL) { 2151*0Sstevel@tonic-gate dict_free(&prov->pkc_elements); 2152*0Sstevel@tonic-gate (void) close(prov->pkc_fd); 2153*0Sstevel@tonic-gate free(prov); 2154*0Sstevel@tonic-gate conf->pc_prov = NULL; 2155*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2156*0Sstevel@tonic-gate return (PO_FAIL); 2157*0Sstevel@tonic-gate } 2158*0Sstevel@tonic-gate #endif /* DEBUG */ 2159*0Sstevel@tonic-gate /* 2160*0Sstevel@tonic-gate * Allocate the transaction log 2161*0Sstevel@tonic-gate */ 2162*0Sstevel@tonic-gate if ((prov->pkc_log = log_alloc(conf)) == NULL) { 2163*0Sstevel@tonic-gate #if DEBUG 2164*0Sstevel@tonic-gate dict_free(&prov->pkc_leaks); 2165*0Sstevel@tonic-gate #endif /* DEBUG */ 2166*0Sstevel@tonic-gate dict_free(&prov->pkc_elements); 2167*0Sstevel@tonic-gate (void) close(prov->pkc_fd); 2168*0Sstevel@tonic-gate free(prov); 2169*0Sstevel@tonic-gate conf->pc_prov = NULL; 2170*0Sstevel@tonic-gate return (PO_FAIL); 2171*0Sstevel@tonic-gate } 2172*0Sstevel@tonic-gate /* 2173*0Sstevel@tonic-gate * At this point the configuration provider has been initialized, 2174*0Sstevel@tonic-gate * mark the configuration as valid so that the various routines 2175*0Sstevel@tonic-gate * which rely on a valid configuration will work correctly. 2176*0Sstevel@tonic-gate */ 2177*0Sstevel@tonic-gate conf->pc_state = POF_VALID; 2178*0Sstevel@tonic-gate /* 2179*0Sstevel@tonic-gate * Update the library snapshot from the kernel 2180*0Sstevel@tonic-gate */ 2181*0Sstevel@tonic-gate if (pool_knl_update(conf, NULL) != PO_SUCCESS) { 2182*0Sstevel@tonic-gate #if DEBUG 2183*0Sstevel@tonic-gate dict_free(&prov->pkc_leaks); 2184*0Sstevel@tonic-gate #endif /* DEBUG */ 2185*0Sstevel@tonic-gate dict_free(&prov->pkc_elements); 2186*0Sstevel@tonic-gate (void) close(prov->pkc_fd); 2187*0Sstevel@tonic-gate free(prov); 2188*0Sstevel@tonic-gate conf->pc_prov = NULL; 2189*0Sstevel@tonic-gate conf->pc_state = POF_INVALID; 2190*0Sstevel@tonic-gate return (PO_FAIL); 2191*0Sstevel@tonic-gate } 2192*0Sstevel@tonic-gate return (PO_SUCCESS); 2193*0Sstevel@tonic-gate } 2194*0Sstevel@tonic-gate 2195*0Sstevel@tonic-gate #if DEBUG 2196*0Sstevel@tonic-gate static void 2197*0Sstevel@tonic-gate pool_knl_elem_printf_cb(const void *key, void **value, void *cl) 2198*0Sstevel@tonic-gate { 2199*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key; 2200*0Sstevel@tonic-gate dict_hdl_t *map = (dict_hdl_t *)cl; 2201*0Sstevel@tonic-gate 2202*0Sstevel@tonic-gate dprintf("leak elem:%p\n", pke); 2203*0Sstevel@tonic-gate if (pke->pke_properties != NULL) { 2204*0Sstevel@tonic-gate nvlist_print(stdout, pke->pke_properties); 2205*0Sstevel@tonic-gate } else 2206*0Sstevel@tonic-gate dprintf("no properties\n"); 2207*0Sstevel@tonic-gate assert(dict_get(map, pke) == NULL); 2208*0Sstevel@tonic-gate } 2209*0Sstevel@tonic-gate #endif /* DEBUG */ 2210*0Sstevel@tonic-gate /* 2211*0Sstevel@tonic-gate * pool_knl_elem_free() releases the resources associated with the 2212*0Sstevel@tonic-gate * supplied element. 2213*0Sstevel@tonic-gate */ 2214*0Sstevel@tonic-gate static void 2215*0Sstevel@tonic-gate pool_knl_elem_free(pool_knl_elem_t *pke, int freeprop) 2216*0Sstevel@tonic-gate { 2217*0Sstevel@tonic-gate #if DEBUG 2218*0Sstevel@tonic-gate pool_conf_t *conf = TO_CONF(TO_ELEM(pke)); 2219*0Sstevel@tonic-gate if (dict_remove(((pool_knl_connection_t *)conf->pc_prov)->pkc_leaks, 2220*0Sstevel@tonic-gate pke) == NULL) 2221*0Sstevel@tonic-gate dprintf("%p, wasn't in the leak map\n", pke); 2222*0Sstevel@tonic-gate if (freeprop == PO_TRUE) { 2223*0Sstevel@tonic-gate pool_elem_dprintf(TO_ELEM(pke)); 2224*0Sstevel@tonic-gate } 2225*0Sstevel@tonic-gate dprintf("released %p\n", pke); 2226*0Sstevel@tonic-gate #endif /* DEBUG */ 2227*0Sstevel@tonic-gate if (freeprop == PO_TRUE) { 2228*0Sstevel@tonic-gate nvlist_free(pke->pke_properties); 2229*0Sstevel@tonic-gate } 2230*0Sstevel@tonic-gate free(pke); 2231*0Sstevel@tonic-gate } 2232*0Sstevel@tonic-gate 2233*0Sstevel@tonic-gate /* 2234*0Sstevel@tonic-gate * pool_knl_elem_free_cb() is designed to be used with 2235*0Sstevel@tonic-gate * dict_map(). When a connection is freed, this function is used to 2236*0Sstevel@tonic-gate * free all element resources. 2237*0Sstevel@tonic-gate */ 2238*0Sstevel@tonic-gate /* ARGSUSED1 */ 2239*0Sstevel@tonic-gate static void 2240*0Sstevel@tonic-gate pool_knl_elem_free_cb(const void *key, void **value, void *cl) 2241*0Sstevel@tonic-gate { 2242*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key; 2243*0Sstevel@tonic-gate 2244*0Sstevel@tonic-gate #ifdef DEBUG 2245*0Sstevel@tonic-gate dprintf("pool_knl_elem_free_cb:\n"); 2246*0Sstevel@tonic-gate dprintf("about to release %p ", pke); 2247*0Sstevel@tonic-gate pool_elem_dprintf(TO_ELEM(pke)); 2248*0Sstevel@tonic-gate #endif /* DEBUG */ 2249*0Sstevel@tonic-gate pool_knl_elem_free(pke, PO_TRUE); 2250*0Sstevel@tonic-gate } 2251*0Sstevel@tonic-gate 2252*0Sstevel@tonic-gate /* 2253*0Sstevel@tonic-gate * Free the resources for a kernel data provider. 2254*0Sstevel@tonic-gate */ 2255*0Sstevel@tonic-gate void 2256*0Sstevel@tonic-gate pool_knl_connection_free(pool_knl_connection_t *prov) 2257*0Sstevel@tonic-gate { 2258*0Sstevel@tonic-gate if (prov->pkc_log != NULL) { 2259*0Sstevel@tonic-gate (void) log_walk(prov->pkc_log, log_item_release); 2260*0Sstevel@tonic-gate log_free(prov->pkc_log); 2261*0Sstevel@tonic-gate } 2262*0Sstevel@tonic-gate if (prov->pkc_elements != NULL) { 2263*0Sstevel@tonic-gate dict_map(prov->pkc_elements, pool_knl_elem_free_cb, NULL); 2264*0Sstevel@tonic-gate #if DEBUG 2265*0Sstevel@tonic-gate dprintf("dict length is %llu\n", dict_length(prov->pkc_leaks)); 2266*0Sstevel@tonic-gate dict_map(prov->pkc_leaks, pool_knl_elem_printf_cb, 2267*0Sstevel@tonic-gate prov->pkc_elements); 2268*0Sstevel@tonic-gate assert(dict_length(prov->pkc_leaks) == 0); 2269*0Sstevel@tonic-gate dict_free(&prov->pkc_leaks); 2270*0Sstevel@tonic-gate #endif /* DEBUG */ 2271*0Sstevel@tonic-gate dict_free(&prov->pkc_elements); 2272*0Sstevel@tonic-gate } 2273*0Sstevel@tonic-gate free((void *)prov->pc_name); 2274*0Sstevel@tonic-gate free(prov); 2275*0Sstevel@tonic-gate } 2276*0Sstevel@tonic-gate 2277*0Sstevel@tonic-gate /* 2278*0Sstevel@tonic-gate * Return the specified property value. 2279*0Sstevel@tonic-gate * 2280*0Sstevel@tonic-gate * POC_INVAL is returned if an error is detected and the error code is updated 2281*0Sstevel@tonic-gate * to indicate the cause of the error. 2282*0Sstevel@tonic-gate */ 2283*0Sstevel@tonic-gate pool_value_class_t 2284*0Sstevel@tonic-gate pool_knl_get_property(const pool_elem_t *pe, const char *name, 2285*0Sstevel@tonic-gate pool_value_t *val) 2286*0Sstevel@tonic-gate { 2287*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe; 2288*0Sstevel@tonic-gate nvpair_t *pair; 2289*0Sstevel@tonic-gate const pool_prop_t *prop; 2290*0Sstevel@tonic-gate 2291*0Sstevel@tonic-gate if ((prop = provider_get_prop(pe, name)) != NULL) 2292*0Sstevel@tonic-gate if (prop_is_stored(prop) == PO_FALSE) 2293*0Sstevel@tonic-gate return (pool_knl_get_dynamic_property(pe, name, val)); 2294*0Sstevel@tonic-gate 2295*0Sstevel@tonic-gate if ((pair = pool_knl_find_nvpair(pke->pke_properties, name)) == NULL) { 2296*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 2297*0Sstevel@tonic-gate return (POC_INVAL); 2298*0Sstevel@tonic-gate } 2299*0Sstevel@tonic-gate 2300*0Sstevel@tonic-gate if (pool_value_from_nvpair(val, pair) == PO_FAIL) { 2301*0Sstevel@tonic-gate return (POC_INVAL); 2302*0Sstevel@tonic-gate } 2303*0Sstevel@tonic-gate 2304*0Sstevel@tonic-gate return (pool_value_get_type(val)); 2305*0Sstevel@tonic-gate } 2306*0Sstevel@tonic-gate 2307*0Sstevel@tonic-gate /* 2308*0Sstevel@tonic-gate * Return the specified property value. 2309*0Sstevel@tonic-gate * 2310*0Sstevel@tonic-gate * If a property is designated as dynamic, then this function will 2311*0Sstevel@tonic-gate * always try to return the latest value of the property from the 2312*0Sstevel@tonic-gate * kernel. 2313*0Sstevel@tonic-gate * 2314*0Sstevel@tonic-gate * POC_INVAL is returned if an error is detected and the error code is updated 2315*0Sstevel@tonic-gate * to indicate the cause of the error. 2316*0Sstevel@tonic-gate */ 2317*0Sstevel@tonic-gate pool_value_class_t 2318*0Sstevel@tonic-gate pool_knl_get_dynamic_property(const pool_elem_t *pe, const char *name, 2319*0Sstevel@tonic-gate pool_value_t *val) 2320*0Sstevel@tonic-gate { 2321*0Sstevel@tonic-gate pool_knl_connection_t *prov; 2322*0Sstevel@tonic-gate pool_propget_t propget = { 0 }; 2323*0Sstevel@tonic-gate nvlist_t *proplist; 2324*0Sstevel@tonic-gate nvpair_t *pair; 2325*0Sstevel@tonic-gate 2326*0Sstevel@tonic-gate propget.pp_o_id_type = pool_elem_class(pe); 2327*0Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_RES_COMP || 2328*0Sstevel@tonic-gate pool_elem_class(pe) == PEC_RES_AGG) 2329*0Sstevel@tonic-gate propget.pp_o_id_subtype = pool_resource_elem_class(pe); 2330*0Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_COMP) 2331*0Sstevel@tonic-gate propget.pp_o_id_subtype = 2332*0Sstevel@tonic-gate (pool_resource_elem_class_t)pool_component_elem_class(pe); 2333*0Sstevel@tonic-gate 2334*0Sstevel@tonic-gate propget.pp_o_id = elem_get_sysid(pe); 2335*0Sstevel@tonic-gate propget.pp_o_prop_name_size = strlen(name); 2336*0Sstevel@tonic-gate propget.pp_o_prop_name = (char *)name; 2337*0Sstevel@tonic-gate propget.pp_i_bufsize = KERNEL_SNAPSHOT_BUF_SZ; 2338*0Sstevel@tonic-gate propget.pp_i_buf = malloc(KERNEL_SNAPSHOT_BUF_SZ); 2339*0Sstevel@tonic-gate bzero(propget.pp_i_buf, KERNEL_SNAPSHOT_BUF_SZ); 2340*0Sstevel@tonic-gate 2341*0Sstevel@tonic-gate prov = (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov; 2342*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPGET, &propget) < 0) { 2343*0Sstevel@tonic-gate free(propget.pp_i_buf); 2344*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2345*0Sstevel@tonic-gate return (POC_INVAL); 2346*0Sstevel@tonic-gate } 2347*0Sstevel@tonic-gate if (nvlist_unpack(propget.pp_i_buf, propget.pp_i_bufsize, 2348*0Sstevel@tonic-gate &proplist, 0) != 0) { 2349*0Sstevel@tonic-gate free(propget.pp_i_buf); 2350*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2351*0Sstevel@tonic-gate return (POC_INVAL); 2352*0Sstevel@tonic-gate } 2353*0Sstevel@tonic-gate free(propget.pp_i_buf); 2354*0Sstevel@tonic-gate 2355*0Sstevel@tonic-gate if ((pair = nvlist_next_nvpair(proplist, NULL)) == NULL) { 2356*0Sstevel@tonic-gate nvlist_free(proplist); 2357*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2358*0Sstevel@tonic-gate return (POC_INVAL); 2359*0Sstevel@tonic-gate } 2360*0Sstevel@tonic-gate 2361*0Sstevel@tonic-gate if (pool_value_from_nvpair(val, pair) == PO_FAIL) { 2362*0Sstevel@tonic-gate nvlist_free(proplist); 2363*0Sstevel@tonic-gate return (POC_INVAL); 2364*0Sstevel@tonic-gate } 2365*0Sstevel@tonic-gate nvlist_free(proplist); 2366*0Sstevel@tonic-gate return (pool_value_get_type(val)); 2367*0Sstevel@tonic-gate } 2368*0Sstevel@tonic-gate 2369*0Sstevel@tonic-gate /* 2370*0Sstevel@tonic-gate * Update the specified property value. 2371*0Sstevel@tonic-gate * 2372*0Sstevel@tonic-gate * PO_FAIL is returned if an error is detected and the error code is updated 2373*0Sstevel@tonic-gate * to indicate the cause of the error. 2374*0Sstevel@tonic-gate */ 2375*0Sstevel@tonic-gate int 2376*0Sstevel@tonic-gate pool_knl_put_property(pool_elem_t *pe, const char *name, 2377*0Sstevel@tonic-gate const pool_value_t *val) 2378*0Sstevel@tonic-gate { 2379*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe; 2380*0Sstevel@tonic-gate pool_knl_connection_t *prov = 2381*0Sstevel@tonic-gate (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov; 2382*0Sstevel@tonic-gate nvpair_t *bp, *ap; 2383*0Sstevel@tonic-gate pool_propput_undo_t *propput; 2384*0Sstevel@tonic-gate nvlist_t *bl = NULL; 2385*0Sstevel@tonic-gate const pool_prop_t *prop; 2386*0Sstevel@tonic-gate 2387*0Sstevel@tonic-gate if ((bp = pool_knl_find_nvpair(pke->pke_properties, name)) != NULL) { 2388*0Sstevel@tonic-gate if (nvlist_alloc(&bl, NV_UNIQUE_NAME_TYPE, 0) != 0) { 2389*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2390*0Sstevel@tonic-gate return (PO_FAIL); 2391*0Sstevel@tonic-gate } 2392*0Sstevel@tonic-gate if (nvlist_add_nvpair(bl, bp) != 0) { 2393*0Sstevel@tonic-gate nvlist_free(bl); 2394*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2395*0Sstevel@tonic-gate return (PO_FAIL); 2396*0Sstevel@tonic-gate } 2397*0Sstevel@tonic-gate } 2398*0Sstevel@tonic-gate if (pool_knl_nvlist_add_value(pke->pke_properties, name, val) != 2399*0Sstevel@tonic-gate PO_SUCCESS) 2400*0Sstevel@tonic-gate return (PO_FAIL); 2401*0Sstevel@tonic-gate 2402*0Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) { 2403*0Sstevel@tonic-gate if (bl) 2404*0Sstevel@tonic-gate nvlist_free(bl); 2405*0Sstevel@tonic-gate return (PO_SUCCESS); 2406*0Sstevel@tonic-gate } 2407*0Sstevel@tonic-gate /* 2408*0Sstevel@tonic-gate * The remaining logic is setting up the arguments for the 2409*0Sstevel@tonic-gate * POOL_PROPPUT ioctl and appending the details into the log. 2410*0Sstevel@tonic-gate */ 2411*0Sstevel@tonic-gate if ((propput = malloc(sizeof (pool_propput_undo_t))) == NULL) { 2412*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2413*0Sstevel@tonic-gate return (PO_FAIL); 2414*0Sstevel@tonic-gate } 2415*0Sstevel@tonic-gate (void) memset(propput, 0, sizeof (pool_propput_undo_t)); 2416*0Sstevel@tonic-gate propput->ppu_blist = bl; 2417*0Sstevel@tonic-gate 2418*0Sstevel@tonic-gate ap = pool_knl_find_nvpair(pke->pke_properties, name); 2419*0Sstevel@tonic-gate 2420*0Sstevel@tonic-gate if (nvlist_alloc(&propput->ppu_alist, NV_UNIQUE_NAME_TYPE, 0) != 0) { 2421*0Sstevel@tonic-gate nvlist_free(propput->ppu_blist); 2422*0Sstevel@tonic-gate free(propput); 2423*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2424*0Sstevel@tonic-gate return (PO_FAIL); 2425*0Sstevel@tonic-gate } 2426*0Sstevel@tonic-gate if (nvlist_add_nvpair(propput->ppu_alist, ap) != 0) { 2427*0Sstevel@tonic-gate nvlist_free(propput->ppu_blist); 2428*0Sstevel@tonic-gate nvlist_free(propput->ppu_alist); 2429*0Sstevel@tonic-gate free(propput); 2430*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2431*0Sstevel@tonic-gate return (PO_FAIL); 2432*0Sstevel@tonic-gate } 2433*0Sstevel@tonic-gate 2434*0Sstevel@tonic-gate if (nvlist_pack(propput->ppu_alist, 2435*0Sstevel@tonic-gate (char **)&propput->ppu_ioctl.pp_o_buf, 2436*0Sstevel@tonic-gate &propput->ppu_ioctl.pp_o_bufsize, NV_ENCODE_NATIVE, 0) != 0) { 2437*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2438*0Sstevel@tonic-gate return (PO_FAIL); 2439*0Sstevel@tonic-gate } 2440*0Sstevel@tonic-gate nvlist_free(propput->ppu_alist); 2441*0Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_type = pool_elem_class(pe); 2442*0Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_RES_COMP || 2443*0Sstevel@tonic-gate pool_elem_class(pe) == PEC_RES_AGG) 2444*0Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_sub_type = 2445*0Sstevel@tonic-gate pool_resource_elem_class(pe); 2446*0Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_COMP) 2447*0Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_sub_type = 2448*0Sstevel@tonic-gate (pool_resource_elem_class_t)pool_component_elem_class(pe); 2449*0Sstevel@tonic-gate 2450*0Sstevel@tonic-gate propput->ppu_elem = pe; 2451*0Sstevel@tonic-gate if ((prop = provider_get_prop(propput->ppu_elem, name)) != NULL) { 2452*0Sstevel@tonic-gate if (prop_is_readonly(prop) == PO_TRUE) 2453*0Sstevel@tonic-gate propput->ppu_doioctl |= KERNEL_PROP_RDONLY; 2454*0Sstevel@tonic-gate } 2455*0Sstevel@tonic-gate 2456*0Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_PROPPUT, (void *)propput) != 2457*0Sstevel@tonic-gate PO_SUCCESS) { 2458*0Sstevel@tonic-gate nvlist_free(propput->ppu_blist); 2459*0Sstevel@tonic-gate free(propput); 2460*0Sstevel@tonic-gate return (PO_FAIL); 2461*0Sstevel@tonic-gate } 2462*0Sstevel@tonic-gate return (PO_SUCCESS); 2463*0Sstevel@tonic-gate } 2464*0Sstevel@tonic-gate 2465*0Sstevel@tonic-gate /* 2466*0Sstevel@tonic-gate * Remove the specified property value. 2467*0Sstevel@tonic-gate * 2468*0Sstevel@tonic-gate * PO_FAIL is returned if an error is detected and the error code is 2469*0Sstevel@tonic-gate * updated to indicate the cause of the error. 2470*0Sstevel@tonic-gate */ 2471*0Sstevel@tonic-gate int 2472*0Sstevel@tonic-gate pool_knl_rm_property(pool_elem_t *pe, const char *name) 2473*0Sstevel@tonic-gate { 2474*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe; 2475*0Sstevel@tonic-gate pool_knl_connection_t *prov = 2476*0Sstevel@tonic-gate (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov; 2477*0Sstevel@tonic-gate pool_proprm_undo_t *proprm; 2478*0Sstevel@tonic-gate 2479*0Sstevel@tonic-gate if (pool_knl_find_nvpair(pke->pke_properties, name) == NULL) { 2480*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 2481*0Sstevel@tonic-gate return (PO_FAIL); 2482*0Sstevel@tonic-gate } 2483*0Sstevel@tonic-gate 2484*0Sstevel@tonic-gate if ((proprm = malloc(sizeof (pool_proprm_undo_t))) == NULL) { 2485*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2486*0Sstevel@tonic-gate return (PO_FAIL); 2487*0Sstevel@tonic-gate } 2488*0Sstevel@tonic-gate (void) memset(proprm, 0, sizeof (pool_proprm_undo_t)); 2489*0Sstevel@tonic-gate proprm->pru_oldval.pv_class = POC_INVAL; 2490*0Sstevel@tonic-gate (void) pool_get_property(TO_CONF(pe), pe, name, &proprm->pru_oldval); 2491*0Sstevel@tonic-gate 2492*0Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) { 2493*0Sstevel@tonic-gate free(proprm); 2494*0Sstevel@tonic-gate (void) nvlist_remove_all(pke->pke_properties, (char *)name); 2495*0Sstevel@tonic-gate return (PO_SUCCESS); 2496*0Sstevel@tonic-gate } 2497*0Sstevel@tonic-gate /* 2498*0Sstevel@tonic-gate * The remaining logic is setting up the arguments for the 2499*0Sstevel@tonic-gate * POOL_PROPRM ioctl and appending the details into the log. 2500*0Sstevel@tonic-gate */ 2501*0Sstevel@tonic-gate 2502*0Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id_type = pool_elem_class(pe); 2503*0Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_RES_COMP || 2504*0Sstevel@tonic-gate pool_elem_class(pe) == PEC_RES_AGG) 2505*0Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id_sub_type = 2506*0Sstevel@tonic-gate pool_resource_elem_class(pe); 2507*0Sstevel@tonic-gate 2508*0Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_COMP) 2509*0Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id_sub_type = 2510*0Sstevel@tonic-gate (pool_resource_elem_class_t)pool_component_elem_class(pe); 2511*0Sstevel@tonic-gate 2512*0Sstevel@tonic-gate proprm->pru_ioctl.pp_o_prop_name_size = strlen(name); 2513*0Sstevel@tonic-gate proprm->pru_ioctl.pp_o_prop_name = 2514*0Sstevel@tonic-gate (char *)pool_value_get_name(&proprm->pru_oldval); 2515*0Sstevel@tonic-gate proprm->pru_elem = pe; 2516*0Sstevel@tonic-gate 2517*0Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_PROPRM, (void *)proprm) != 2518*0Sstevel@tonic-gate PO_SUCCESS) { 2519*0Sstevel@tonic-gate free(proprm); 2520*0Sstevel@tonic-gate return (PO_FAIL); 2521*0Sstevel@tonic-gate } 2522*0Sstevel@tonic-gate 2523*0Sstevel@tonic-gate (void) nvlist_remove_all(pke->pke_properties, (char *)name); 2524*0Sstevel@tonic-gate return (PO_SUCCESS); 2525*0Sstevel@tonic-gate } 2526*0Sstevel@tonic-gate 2527*0Sstevel@tonic-gate /* 2528*0Sstevel@tonic-gate * Return a NULL terminated array of pool_value_t which represents all 2529*0Sstevel@tonic-gate * of the properties stored for an element 2530*0Sstevel@tonic-gate * 2531*0Sstevel@tonic-gate * Return NULL on failure. It is the caller's responsibility to free 2532*0Sstevel@tonic-gate * the returned array of values. 2533*0Sstevel@tonic-gate */ 2534*0Sstevel@tonic-gate pool_value_t ** 2535*0Sstevel@tonic-gate pool_knl_get_properties(const pool_elem_t *pe, uint_t *nprops) 2536*0Sstevel@tonic-gate { 2537*0Sstevel@tonic-gate nvpair_t *pair; 2538*0Sstevel@tonic-gate pool_value_t **result; 2539*0Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe; 2540*0Sstevel@tonic-gate int i = 0; 2541*0Sstevel@tonic-gate 2542*0Sstevel@tonic-gate *nprops = 0; 2543*0Sstevel@tonic-gate 2544*0Sstevel@tonic-gate for (pair = nvlist_next_nvpair(pke->pke_properties, NULL); pair != NULL; 2545*0Sstevel@tonic-gate pair = nvlist_next_nvpair(pke->pke_properties, pair)) 2546*0Sstevel@tonic-gate (*nprops)++; 2547*0Sstevel@tonic-gate if ((result = calloc(*nprops + 1, sizeof (pool_value_t *))) == NULL) { 2548*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2549*0Sstevel@tonic-gate return (NULL); 2550*0Sstevel@tonic-gate } 2551*0Sstevel@tonic-gate for (pair = nvlist_next_nvpair(pke->pke_properties, NULL); pair != NULL; 2552*0Sstevel@tonic-gate pair = nvlist_next_nvpair(pke->pke_properties, pair), i++) { 2553*0Sstevel@tonic-gate result[i] = pool_value_alloc(); 2554*0Sstevel@tonic-gate if (pool_value_from_nvpair(result[i], pair) == PO_FAIL) { 2555*0Sstevel@tonic-gate while (i-- >= 0) 2556*0Sstevel@tonic-gate pool_value_free(result[i]); 2557*0Sstevel@tonic-gate free(result); 2558*0Sstevel@tonic-gate return (NULL); 2559*0Sstevel@tonic-gate } 2560*0Sstevel@tonic-gate } 2561*0Sstevel@tonic-gate return (result); 2562*0Sstevel@tonic-gate } 2563*0Sstevel@tonic-gate 2564*0Sstevel@tonic-gate /* 2565*0Sstevel@tonic-gate * Append an entry to a result set. Reallocate the array used to store 2566*0Sstevel@tonic-gate * results if it's full. 2567*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 2568*0Sstevel@tonic-gate */ 2569*0Sstevel@tonic-gate int 2570*0Sstevel@tonic-gate pool_knl_result_set_append(pool_knl_result_set_t *rs, pool_knl_elem_t *pke) 2571*0Sstevel@tonic-gate { 2572*0Sstevel@tonic-gate if (rs->pkr_count == rs->pkr_size) 2573*0Sstevel@tonic-gate if (pool_knl_result_set_realloc(rs) != PO_SUCCESS) 2574*0Sstevel@tonic-gate return (PO_FAIL); 2575*0Sstevel@tonic-gate 2576*0Sstevel@tonic-gate rs->pkr_list[rs->pkr_count++] = pke; 2577*0Sstevel@tonic-gate 2578*0Sstevel@tonic-gate return (PO_SUCCESS); 2579*0Sstevel@tonic-gate } 2580*0Sstevel@tonic-gate 2581*0Sstevel@tonic-gate /* 2582*0Sstevel@tonic-gate * Resize the array used to store results. A simple doubling strategy 2583*0Sstevel@tonic-gate * is used. 2584*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 2585*0Sstevel@tonic-gate */ 2586*0Sstevel@tonic-gate int 2587*0Sstevel@tonic-gate pool_knl_result_set_realloc(pool_knl_result_set_t *rs) 2588*0Sstevel@tonic-gate { 2589*0Sstevel@tonic-gate pool_knl_elem_t **old_list = rs->pkr_list; 2590*0Sstevel@tonic-gate int new_size = rs->pkr_size * 2; 2591*0Sstevel@tonic-gate 2592*0Sstevel@tonic-gate if ((rs->pkr_list = realloc(rs->pkr_list, 2593*0Sstevel@tonic-gate new_size * sizeof (pool_knl_elem_t *))) == NULL) { 2594*0Sstevel@tonic-gate rs->pkr_list = old_list; 2595*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2596*0Sstevel@tonic-gate return (PO_FAIL); 2597*0Sstevel@tonic-gate } 2598*0Sstevel@tonic-gate rs->pkr_size = new_size; 2599*0Sstevel@tonic-gate 2600*0Sstevel@tonic-gate return (PO_SUCCESS); 2601*0Sstevel@tonic-gate } 2602*0Sstevel@tonic-gate 2603*0Sstevel@tonic-gate /* 2604*0Sstevel@tonic-gate * Allocate a result set. The Result Set stores the result of a query. 2605*0Sstevel@tonic-gate * Returns pool_knl_result_set_t pointer/NULL 2606*0Sstevel@tonic-gate */ 2607*0Sstevel@tonic-gate pool_knl_result_set_t * 2608*0Sstevel@tonic-gate pool_knl_result_set_alloc(const pool_conf_t *conf) 2609*0Sstevel@tonic-gate { 2610*0Sstevel@tonic-gate pool_knl_result_set_t *rs; 2611*0Sstevel@tonic-gate 2612*0Sstevel@tonic-gate if ((rs = malloc(sizeof (pool_knl_result_set_t))) == NULL) { 2613*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2614*0Sstevel@tonic-gate return (NULL); 2615*0Sstevel@tonic-gate } 2616*0Sstevel@tonic-gate (void) memset(rs, 0, sizeof (pool_knl_result_set_t)); 2617*0Sstevel@tonic-gate rs->pkr_size = KERNEL_RS_INITIAL_SZ; 2618*0Sstevel@tonic-gate if (pool_knl_result_set_realloc(rs) == PO_FAIL) { 2619*0Sstevel@tonic-gate free(rs); 2620*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2621*0Sstevel@tonic-gate return (NULL); 2622*0Sstevel@tonic-gate } 2623*0Sstevel@tonic-gate rs->prs_conf = conf; 2624*0Sstevel@tonic-gate rs->prs_index = -1; 2625*0Sstevel@tonic-gate rs->prs_active = PO_TRUE; 2626*0Sstevel@tonic-gate /* Fix up the result set accessor functions to the knl specfic ones */ 2627*0Sstevel@tonic-gate rs->prs_next = pool_knl_rs_next; 2628*0Sstevel@tonic-gate rs->prs_prev = pool_knl_rs_prev; 2629*0Sstevel@tonic-gate rs->prs_first = pool_knl_rs_first; 2630*0Sstevel@tonic-gate rs->prs_last = pool_knl_rs_last; 2631*0Sstevel@tonic-gate rs->prs_get_index = pool_knl_rs_get_index; 2632*0Sstevel@tonic-gate rs->prs_set_index = pool_knl_rs_set_index; 2633*0Sstevel@tonic-gate rs->prs_close = pool_knl_rs_close; 2634*0Sstevel@tonic-gate rs->prs_count = pool_knl_rs_count; 2635*0Sstevel@tonic-gate return (rs); 2636*0Sstevel@tonic-gate } 2637*0Sstevel@tonic-gate 2638*0Sstevel@tonic-gate /* 2639*0Sstevel@tonic-gate * Free a result set. Ensure that the resources are all released at 2640*0Sstevel@tonic-gate * this point. 2641*0Sstevel@tonic-gate */ 2642*0Sstevel@tonic-gate void 2643*0Sstevel@tonic-gate pool_knl_result_set_free(pool_knl_result_set_t *rs) 2644*0Sstevel@tonic-gate { 2645*0Sstevel@tonic-gate free(rs->pkr_list); 2646*0Sstevel@tonic-gate free(rs); 2647*0Sstevel@tonic-gate } 2648*0Sstevel@tonic-gate /* 2649*0Sstevel@tonic-gate * Return the next element in a result set. 2650*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 2651*0Sstevel@tonic-gate */ 2652*0Sstevel@tonic-gate pool_elem_t * 2653*0Sstevel@tonic-gate pool_knl_rs_next(pool_result_set_t *set) 2654*0Sstevel@tonic-gate { 2655*0Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set; 2656*0Sstevel@tonic-gate 2657*0Sstevel@tonic-gate if (kset->prs_index == kset->pkr_count - 1) 2658*0Sstevel@tonic-gate return (NULL); 2659*0Sstevel@tonic-gate return ((pool_elem_t *)kset->pkr_list[++kset->prs_index]); 2660*0Sstevel@tonic-gate } 2661*0Sstevel@tonic-gate 2662*0Sstevel@tonic-gate /* 2663*0Sstevel@tonic-gate * Return the previous element in a result set. 2664*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 2665*0Sstevel@tonic-gate */ 2666*0Sstevel@tonic-gate pool_elem_t * 2667*0Sstevel@tonic-gate pool_knl_rs_prev(pool_result_set_t *set) 2668*0Sstevel@tonic-gate { 2669*0Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set; 2670*0Sstevel@tonic-gate 2671*0Sstevel@tonic-gate if (kset->prs_index < 0) 2672*0Sstevel@tonic-gate return (NULL); 2673*0Sstevel@tonic-gate return ((pool_elem_t *)kset->pkr_list[kset->prs_index--]); 2674*0Sstevel@tonic-gate } 2675*0Sstevel@tonic-gate 2676*0Sstevel@tonic-gate /* 2677*0Sstevel@tonic-gate * Sets the current index in a result set. 2678*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 2679*0Sstevel@tonic-gate */ 2680*0Sstevel@tonic-gate int 2681*0Sstevel@tonic-gate pool_knl_rs_set_index(pool_result_set_t *set, int index) 2682*0Sstevel@tonic-gate { 2683*0Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set; 2684*0Sstevel@tonic-gate 2685*0Sstevel@tonic-gate if (index < 0 || index >= kset->pkr_count) { 2686*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 2687*0Sstevel@tonic-gate return (PO_FAIL); 2688*0Sstevel@tonic-gate } 2689*0Sstevel@tonic-gate kset->prs_index = index; 2690*0Sstevel@tonic-gate return (PO_SUCCESS); 2691*0Sstevel@tonic-gate } 2692*0Sstevel@tonic-gate 2693*0Sstevel@tonic-gate /* 2694*0Sstevel@tonic-gate * Return the current index in a result set. 2695*0Sstevel@tonic-gate * Returns current index 2696*0Sstevel@tonic-gate */ 2697*0Sstevel@tonic-gate int 2698*0Sstevel@tonic-gate pool_knl_rs_get_index(pool_result_set_t *set) 2699*0Sstevel@tonic-gate { 2700*0Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set; 2701*0Sstevel@tonic-gate 2702*0Sstevel@tonic-gate return (kset->prs_index); 2703*0Sstevel@tonic-gate } 2704*0Sstevel@tonic-gate 2705*0Sstevel@tonic-gate /* 2706*0Sstevel@tonic-gate * Return the first element in a result set. 2707*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 2708*0Sstevel@tonic-gate */ 2709*0Sstevel@tonic-gate pool_elem_t * 2710*0Sstevel@tonic-gate pool_knl_rs_first(pool_result_set_t *set) 2711*0Sstevel@tonic-gate { 2712*0Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set; 2713*0Sstevel@tonic-gate 2714*0Sstevel@tonic-gate return ((pool_elem_t *)kset->pkr_list[0]); 2715*0Sstevel@tonic-gate } 2716*0Sstevel@tonic-gate 2717*0Sstevel@tonic-gate /* 2718*0Sstevel@tonic-gate * Return the last element in a result set. 2719*0Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL 2720*0Sstevel@tonic-gate */ 2721*0Sstevel@tonic-gate pool_elem_t * 2722*0Sstevel@tonic-gate pool_knl_rs_last(pool_result_set_t *set) 2723*0Sstevel@tonic-gate { 2724*0Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set; 2725*0Sstevel@tonic-gate 2726*0Sstevel@tonic-gate return ((pool_elem_t *)kset->pkr_list[kset->pkr_count - 1]); 2727*0Sstevel@tonic-gate } 2728*0Sstevel@tonic-gate 2729*0Sstevel@tonic-gate /* 2730*0Sstevel@tonic-gate * Return the number of results in a result set. 2731*0Sstevel@tonic-gate * Returns result count 2732*0Sstevel@tonic-gate */ 2733*0Sstevel@tonic-gate int 2734*0Sstevel@tonic-gate pool_knl_rs_count(pool_result_set_t *set) 2735*0Sstevel@tonic-gate { 2736*0Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set; 2737*0Sstevel@tonic-gate 2738*0Sstevel@tonic-gate return (kset->pkr_count); 2739*0Sstevel@tonic-gate } 2740*0Sstevel@tonic-gate 2741*0Sstevel@tonic-gate 2742*0Sstevel@tonic-gate /* 2743*0Sstevel@tonic-gate * Close a result set. Free the resources 2744*0Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL 2745*0Sstevel@tonic-gate */ 2746*0Sstevel@tonic-gate int 2747*0Sstevel@tonic-gate pool_knl_rs_close(pool_result_set_t *set) 2748*0Sstevel@tonic-gate { 2749*0Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set; 2750*0Sstevel@tonic-gate 2751*0Sstevel@tonic-gate pool_knl_result_set_free(kset); 2752*0Sstevel@tonic-gate return (PO_SUCCESS); 2753*0Sstevel@tonic-gate } 2754*0Sstevel@tonic-gate 2755*0Sstevel@tonic-gate /* 2756*0Sstevel@tonic-gate * Commit an individual transaction log item(). This processing is 2757*0Sstevel@tonic-gate * essential to the pool_conf_commit() logic. When pool_conf_commit() 2758*0Sstevel@tonic-gate * is invoked, the pending transaction log for the configuration is 2759*0Sstevel@tonic-gate * walked and all pending changes to the kernel are invoked. If a 2760*0Sstevel@tonic-gate * change succeeds it is marked in the log as successful and 2761*0Sstevel@tonic-gate * processing continues, if it fails then failure is returned and the 2762*0Sstevel@tonic-gate * log will be "rolled back" to undo changes to the library snapshot 2763*0Sstevel@tonic-gate * and the kernel. 2764*0Sstevel@tonic-gate */ 2765*0Sstevel@tonic-gate int 2766*0Sstevel@tonic-gate log_item_commit(log_item_t *li) 2767*0Sstevel@tonic-gate { 2768*0Sstevel@tonic-gate pool_knl_connection_t *prov = 2769*0Sstevel@tonic-gate (pool_knl_connection_t *)li->li_log->l_conf->pc_prov; 2770*0Sstevel@tonic-gate pool_create_undo_t *create; 2771*0Sstevel@tonic-gate pool_destroy_undo_t *destroy; 2772*0Sstevel@tonic-gate pool_assoc_undo_t *assoc; 2773*0Sstevel@tonic-gate pool_dissoc_undo_t *dissoc; 2774*0Sstevel@tonic-gate pool_propput_undo_t *propput; 2775*0Sstevel@tonic-gate pool_proprm_undo_t *proprm; 2776*0Sstevel@tonic-gate pool_xtransfer_undo_t *xtransfer; 2777*0Sstevel@tonic-gate char_buf_t *cb; 2778*0Sstevel@tonic-gate size_t size; 2779*0Sstevel@tonic-gate pool_elem_t *pair; 2780*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 2781*0Sstevel@tonic-gate int ret; 2782*0Sstevel@tonic-gate 2783*0Sstevel@tonic-gate switch (li->li_op) { 2784*0Sstevel@tonic-gate case POOL_CREATE: 2785*0Sstevel@tonic-gate create = (pool_create_undo_t *)li->li_details; 2786*0Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) 2787*0Sstevel@tonic-gate return (PO_FAIL); 2788*0Sstevel@tonic-gate if (set_char_buf(cb, "%s.sys_id", 2789*0Sstevel@tonic-gate pool_elem_class_string(create->pcu_elem)) != PO_SUCCESS) { 2790*0Sstevel@tonic-gate free_char_buf(cb); 2791*0Sstevel@tonic-gate return (PO_FAIL); 2792*0Sstevel@tonic-gate } 2793*0Sstevel@tonic-gate #ifdef DEBUG 2794*0Sstevel@tonic-gate dprintf("log_item_commit: POOL_CREATE, remove from dict\n"); 2795*0Sstevel@tonic-gate pool_elem_dprintf(create->pcu_elem); 2796*0Sstevel@tonic-gate #endif /* DEBUG */ 2797*0Sstevel@tonic-gate /* 2798*0Sstevel@tonic-gate * May not need to remove the element if it was 2799*0Sstevel@tonic-gate * already destroyed before commit. Just cast the 2800*0Sstevel@tonic-gate * return to void. 2801*0Sstevel@tonic-gate */ 2802*0Sstevel@tonic-gate (void) dict_remove(prov->pkc_elements, 2803*0Sstevel@tonic-gate (pool_knl_elem_t *)create->pcu_elem); 2804*0Sstevel@tonic-gate 2805*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_CREATE, &create->pcu_ioctl) < 0) { 2806*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2807*0Sstevel@tonic-gate return (PO_FAIL); 2808*0Sstevel@tonic-gate } 2809*0Sstevel@tonic-gate /* 2810*0Sstevel@tonic-gate * Now that we have created our element in the kernel, 2811*0Sstevel@tonic-gate * it has a valid allocated system id. Remove the 2812*0Sstevel@tonic-gate * element from the element dictionary, using the 2813*0Sstevel@tonic-gate * current key, and then re-insert under the new key. 2814*0Sstevel@tonic-gate */ 2815*0Sstevel@tonic-gate #ifdef DEBUG 2816*0Sstevel@tonic-gate pool_elem_dprintf(create->pcu_elem); 2817*0Sstevel@tonic-gate #endif /* DEBUG */ 2818*0Sstevel@tonic-gate assert(nvlist_add_int64( 2819*0Sstevel@tonic-gate ((pool_knl_elem_t *)create->pcu_elem)->pke_properties, 2820*0Sstevel@tonic-gate cb->cb_buf, create->pcu_ioctl.pc_i_id) == 0); 2821*0Sstevel@tonic-gate free_char_buf(cb); 2822*0Sstevel@tonic-gate assert(dict_put(prov->pkc_elements, create->pcu_elem, 2823*0Sstevel@tonic-gate create->pcu_elem) == NULL); 2824*0Sstevel@tonic-gate /* 2825*0Sstevel@tonic-gate * If the element has a pair in the static 2826*0Sstevel@tonic-gate * configuration, update it with the sys_id 2827*0Sstevel@tonic-gate */ 2828*0Sstevel@tonic-gate if ((pair = pool_get_pair(create->pcu_elem)) != NULL) { 2829*0Sstevel@tonic-gate pool_value_set_int64(&val, create->pcu_ioctl.pc_i_id); 2830*0Sstevel@tonic-gate assert(pool_put_any_ns_property(pair, c_sys_prop, &val) 2831*0Sstevel@tonic-gate == PO_SUCCESS); 2832*0Sstevel@tonic-gate } 2833*0Sstevel@tonic-gate li->li_state = LS_UNDO; 2834*0Sstevel@tonic-gate break; 2835*0Sstevel@tonic-gate case POOL_DESTROY: 2836*0Sstevel@tonic-gate destroy = (pool_destroy_undo_t *)li->li_details; 2837*0Sstevel@tonic-gate 2838*0Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_id = elem_get_sysid(destroy->pdu_elem); 2839*0Sstevel@tonic-gate 2840*0Sstevel@tonic-gate /* 2841*0Sstevel@tonic-gate * It may be that this element was created in the last 2842*0Sstevel@tonic-gate * transaction. In which case POOL_CREATE, above, will 2843*0Sstevel@tonic-gate * have re-inserted the element in the dictionary. Try 2844*0Sstevel@tonic-gate * to remove it just in case this has occurred. 2845*0Sstevel@tonic-gate */ 2846*0Sstevel@tonic-gate (void) dict_remove(prov->pkc_elements, 2847*0Sstevel@tonic-gate (pool_knl_elem_t *)destroy->pdu_elem); 2848*0Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_DESTROY, 2849*0Sstevel@tonic-gate &destroy->pdu_ioctl)) < 0 && errno == EAGAIN); 2850*0Sstevel@tonic-gate if (ret < 0) { 2851*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2852*0Sstevel@tonic-gate return (PO_FAIL); 2853*0Sstevel@tonic-gate } 2854*0Sstevel@tonic-gate #ifdef DEBUG 2855*0Sstevel@tonic-gate dprintf("log_item_commit: POOL_DESTROY\n"); 2856*0Sstevel@tonic-gate pool_elem_dprintf(destroy->pdu_elem); 2857*0Sstevel@tonic-gate #endif /* DEBUG */ 2858*0Sstevel@tonic-gate li->li_state = LS_UNDO; 2859*0Sstevel@tonic-gate break; 2860*0Sstevel@tonic-gate case POOL_ASSOC: 2861*0Sstevel@tonic-gate assoc = (pool_assoc_undo_t *)li->li_details; 2862*0Sstevel@tonic-gate 2863*0Sstevel@tonic-gate assoc->pau_ioctl.pa_o_pool_id = 2864*0Sstevel@tonic-gate elem_get_sysid(assoc->pau_assoc); 2865*0Sstevel@tonic-gate assoc->pau_ioctl.pa_o_res_id = 2866*0Sstevel@tonic-gate elem_get_sysid(assoc->pau_newres); 2867*0Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC, 2868*0Sstevel@tonic-gate &assoc->pau_ioctl)) < 0 && errno == EAGAIN); 2869*0Sstevel@tonic-gate if (ret < 0) { 2870*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2871*0Sstevel@tonic-gate return (PO_FAIL); 2872*0Sstevel@tonic-gate } 2873*0Sstevel@tonic-gate li->li_state = LS_UNDO; 2874*0Sstevel@tonic-gate break; 2875*0Sstevel@tonic-gate case POOL_DISSOC: 2876*0Sstevel@tonic-gate dissoc = (pool_dissoc_undo_t *)li->li_details; 2877*0Sstevel@tonic-gate 2878*0Sstevel@tonic-gate dissoc->pdu_ioctl.pd_o_pool_id = 2879*0Sstevel@tonic-gate elem_get_sysid(dissoc->pdu_dissoc); 2880*0Sstevel@tonic-gate 2881*0Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_DISSOC, 2882*0Sstevel@tonic-gate &dissoc->pdu_ioctl)) < 0 && errno == EAGAIN); 2883*0Sstevel@tonic-gate if (ret < 0) { 2884*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2885*0Sstevel@tonic-gate return (PO_FAIL); 2886*0Sstevel@tonic-gate } 2887*0Sstevel@tonic-gate li->li_state = LS_UNDO; 2888*0Sstevel@tonic-gate break; 2889*0Sstevel@tonic-gate case POOL_TRANSFER: 2890*0Sstevel@tonic-gate li->li_state = LS_UNDO; 2891*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 2892*0Sstevel@tonic-gate return (PO_FAIL); 2893*0Sstevel@tonic-gate break; 2894*0Sstevel@tonic-gate case POOL_XTRANSFER: 2895*0Sstevel@tonic-gate xtransfer = (pool_xtransfer_undo_t *)li->li_details; 2896*0Sstevel@tonic-gate 2897*0Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_src_id = 2898*0Sstevel@tonic-gate elem_get_sysid(xtransfer->pxu_src); 2899*0Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_tgt_id = 2900*0Sstevel@tonic-gate elem_get_sysid(xtransfer->pxu_tgt); 2901*0Sstevel@tonic-gate for (size = 0; xtransfer->pxu_rl[size] != NULL; size ++) { 2902*0Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_comp_list[size] = 2903*0Sstevel@tonic-gate elem_get_sysid(TO_ELEM(xtransfer->pxu_rl[size])); 2904*0Sstevel@tonic-gate #ifdef DEBUG 2905*0Sstevel@tonic-gate dprintf("log_item_commit: POOL_XTRANSFER\n"); 2906*0Sstevel@tonic-gate pool_elem_dprintf(TO_ELEM(xtransfer->pxu_rl[size])); 2907*0Sstevel@tonic-gate #endif /* DEBUG */ 2908*0Sstevel@tonic-gate } 2909*0Sstevel@tonic-gate 2910*0Sstevel@tonic-gate /* 2911*0Sstevel@tonic-gate * Don't actually transfer resources if the configuration 2912*0Sstevel@tonic-gate * is in POF_DESTROY state. This is to prevent problems 2913*0Sstevel@tonic-gate * relating to transferring off-line CPUs. Instead rely 2914*0Sstevel@tonic-gate * on the POOL_DESTROY ioctl to transfer the CPUS. 2915*0Sstevel@tonic-gate */ 2916*0Sstevel@tonic-gate if (li->li_log->l_conf->pc_state != POF_DESTROY && 2917*0Sstevel@tonic-gate ioctl(prov->pkc_fd, POOL_XTRANSFER, 2918*0Sstevel@tonic-gate &xtransfer->pxu_ioctl) < 0) { 2919*0Sstevel@tonic-gate #ifdef DEBUG 2920*0Sstevel@tonic-gate dprintf("log_item_commit: POOL_XTRANSFER, ioctl " 2921*0Sstevel@tonic-gate "failed\n"); 2922*0Sstevel@tonic-gate #endif /* DEBUG */ 2923*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2924*0Sstevel@tonic-gate return (PO_FAIL); 2925*0Sstevel@tonic-gate } 2926*0Sstevel@tonic-gate li->li_state = LS_UNDO; 2927*0Sstevel@tonic-gate break; 2928*0Sstevel@tonic-gate case POOL_PROPPUT: 2929*0Sstevel@tonic-gate propput = (pool_propput_undo_t *)li->li_details; 2930*0Sstevel@tonic-gate 2931*0Sstevel@tonic-gate if (pool_elem_class(propput->ppu_elem) != PEC_SYSTEM) { 2932*0Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id = 2933*0Sstevel@tonic-gate elem_get_sysid(propput->ppu_elem); 2934*0Sstevel@tonic-gate } 2935*0Sstevel@tonic-gate /* 2936*0Sstevel@tonic-gate * Some properties, e.g. pset.size, are read-only in the 2937*0Sstevel@tonic-gate * kernel and attempting to change them will fail and cause 2938*0Sstevel@tonic-gate * problems. Although this property is read-only through the 2939*0Sstevel@tonic-gate * public interface, the library needs to modify it's value. 2940*0Sstevel@tonic-gate */ 2941*0Sstevel@tonic-gate if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) { 2942*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPPUT, 2943*0Sstevel@tonic-gate &propput->ppu_ioctl) < 0) { 2944*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2945*0Sstevel@tonic-gate return (PO_FAIL); 2946*0Sstevel@tonic-gate } 2947*0Sstevel@tonic-gate } 2948*0Sstevel@tonic-gate li->li_state = LS_UNDO; 2949*0Sstevel@tonic-gate break; 2950*0Sstevel@tonic-gate case POOL_PROPRM: 2951*0Sstevel@tonic-gate proprm = (pool_proprm_undo_t *)li->li_details; 2952*0Sstevel@tonic-gate 2953*0Sstevel@tonic-gate if (pool_elem_class(proprm->pru_elem) != PEC_SYSTEM) { 2954*0Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id = 2955*0Sstevel@tonic-gate elem_get_sysid(proprm->pru_elem); 2956*0Sstevel@tonic-gate } 2957*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPRM, &proprm->pru_ioctl) < 0) { 2958*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 2959*0Sstevel@tonic-gate return (PO_FAIL); 2960*0Sstevel@tonic-gate } 2961*0Sstevel@tonic-gate li->li_state = LS_UNDO; 2962*0Sstevel@tonic-gate break; 2963*0Sstevel@tonic-gate default: 2964*0Sstevel@tonic-gate return (PO_FAIL); 2965*0Sstevel@tonic-gate } 2966*0Sstevel@tonic-gate return (PO_SUCCESS); 2967*0Sstevel@tonic-gate } 2968*0Sstevel@tonic-gate 2969*0Sstevel@tonic-gate /* 2970*0Sstevel@tonic-gate * Undo an individual transaction log item(). This processing is 2971*0Sstevel@tonic-gate * essential to the pool_conf_commit() and pool_conf_rollback() 2972*0Sstevel@tonic-gate * logic. Changes to the libpool snapshot and the kernel are carried 2973*0Sstevel@tonic-gate * out separately. The library snapshot is updated synchronously, 2974*0Sstevel@tonic-gate * however the kernel update is delayed until the user calls 2975*0Sstevel@tonic-gate * pool_conf_commit(). 2976*0Sstevel@tonic-gate * 2977*0Sstevel@tonic-gate * When undoing transactions, library changes will be undone unless 2978*0Sstevel@tonic-gate * this invocation is as a result of a commit failure, in which case 2979*0Sstevel@tonic-gate * the log state will be LS_RECOVER. Kernel changes will only be 2980*0Sstevel@tonic-gate * undone if they are marked as having been done, in which case the 2981*0Sstevel@tonic-gate * log item state will be LS_UNDO. 2982*0Sstevel@tonic-gate */ 2983*0Sstevel@tonic-gate int 2984*0Sstevel@tonic-gate log_item_undo(log_item_t *li) 2985*0Sstevel@tonic-gate { 2986*0Sstevel@tonic-gate pool_knl_connection_t *prov = 2987*0Sstevel@tonic-gate (pool_knl_connection_t *)li->li_log->l_conf->pc_prov; 2988*0Sstevel@tonic-gate pool_create_undo_t *create; 2989*0Sstevel@tonic-gate pool_destroy_undo_t *destroy; 2990*0Sstevel@tonic-gate pool_assoc_undo_t *assoc; 2991*0Sstevel@tonic-gate pool_dissoc_undo_t *dissoc; 2992*0Sstevel@tonic-gate pool_propput_undo_t *propput; 2993*0Sstevel@tonic-gate pool_proprm_undo_t *proprm; 2994*0Sstevel@tonic-gate pool_xtransfer_undo_t *xtransfer; 2995*0Sstevel@tonic-gate char_buf_t *cb; 2996*0Sstevel@tonic-gate size_t size; 2997*0Sstevel@tonic-gate pool_destroy_t u_destroy; 2998*0Sstevel@tonic-gate pool_create_t u_create; 2999*0Sstevel@tonic-gate pool_assoc_t u_assoc; 3000*0Sstevel@tonic-gate pool_xtransfer_t u_xtransfer; 3001*0Sstevel@tonic-gate pool_propput_t u_propput; 3002*0Sstevel@tonic-gate pool_proprm_t u_proprm; 3003*0Sstevel@tonic-gate pool_conf_t *conf = li->li_log->l_conf; 3004*0Sstevel@tonic-gate nvpair_t *pair; 3005*0Sstevel@tonic-gate nvlist_t *tmplist; 3006*0Sstevel@tonic-gate int ret; 3007*0Sstevel@tonic-gate 3008*0Sstevel@tonic-gate if (li->li_log->l_state != LS_RECOVER) { 3009*0Sstevel@tonic-gate switch (li->li_op) { 3010*0Sstevel@tonic-gate case POOL_CREATE: 3011*0Sstevel@tonic-gate create = (pool_create_undo_t *)li->li_details; 3012*0Sstevel@tonic-gate 3013*0Sstevel@tonic-gate (void) dict_remove(prov->pkc_elements, create->pcu_elem); 3014*0Sstevel@tonic-gate #ifdef DEBUG 3015*0Sstevel@tonic-gate dprintf("log_item_undo: POOL_CREATE\n"); 3016*0Sstevel@tonic-gate assert(create->pcu_elem != NULL); 3017*0Sstevel@tonic-gate dprintf("log_item_undo: POOL_CREATE %p\n", create->pcu_elem); 3018*0Sstevel@tonic-gate pool_elem_dprintf(create->pcu_elem); 3019*0Sstevel@tonic-gate #endif /* DEBUG */ 3020*0Sstevel@tonic-gate pool_knl_elem_free((pool_knl_elem_t *)create->pcu_elem, 3021*0Sstevel@tonic-gate PO_TRUE); 3022*0Sstevel@tonic-gate break; 3023*0Sstevel@tonic-gate case POOL_DESTROY: 3024*0Sstevel@tonic-gate destroy = (pool_destroy_undo_t *)li->li_details; 3025*0Sstevel@tonic-gate 3026*0Sstevel@tonic-gate assert(dict_put(prov->pkc_elements, destroy->pdu_elem, 3027*0Sstevel@tonic-gate destroy->pdu_elem) == NULL); 3028*0Sstevel@tonic-gate break; 3029*0Sstevel@tonic-gate case POOL_ASSOC: 3030*0Sstevel@tonic-gate assoc = (pool_assoc_undo_t *)li->li_details; 3031*0Sstevel@tonic-gate 3032*0Sstevel@tonic-gate if (assoc->pau_oldres != NULL) 3033*0Sstevel@tonic-gate ((pool_knl_pool_t *)assoc->pau_assoc)->pkp_assoc 3034*0Sstevel@tonic-gate [pool_resource_elem_class(assoc->pau_oldres)] = 3035*0Sstevel@tonic-gate (pool_knl_resource_t *)assoc->pau_oldres; 3036*0Sstevel@tonic-gate break; 3037*0Sstevel@tonic-gate case POOL_DISSOC: 3038*0Sstevel@tonic-gate dissoc = (pool_dissoc_undo_t *)li->li_details; 3039*0Sstevel@tonic-gate 3040*0Sstevel@tonic-gate if (dissoc->pdu_oldres != NULL) 3041*0Sstevel@tonic-gate ((pool_knl_pool_t *)dissoc->pdu_dissoc)->pkp_assoc 3042*0Sstevel@tonic-gate [pool_resource_elem_class(dissoc->pdu_oldres)] = 3043*0Sstevel@tonic-gate (pool_knl_resource_t *)dissoc->pdu_oldres; 3044*0Sstevel@tonic-gate break; 3045*0Sstevel@tonic-gate case POOL_TRANSFER: 3046*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 3047*0Sstevel@tonic-gate return (PO_FAIL); 3048*0Sstevel@tonic-gate break; 3049*0Sstevel@tonic-gate case POOL_XTRANSFER: 3050*0Sstevel@tonic-gate xtransfer = (pool_xtransfer_undo_t *)li->li_details; 3051*0Sstevel@tonic-gate 3052*0Sstevel@tonic-gate for (size = 0; xtransfer->pxu_rl[size] != NULL; size++) { 3053*0Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER; 3054*0Sstevel@tonic-gate uint64_t src_size; 3055*0Sstevel@tonic-gate uint64_t tgt_size; 3056*0Sstevel@tonic-gate 3057*0Sstevel@tonic-gate if (pool_set_container(xtransfer->pxu_src, 3058*0Sstevel@tonic-gate TO_ELEM(xtransfer->pxu_rl[size])) == PO_FAIL) { 3059*0Sstevel@tonic-gate return (PO_FAIL); 3060*0Sstevel@tonic-gate } 3061*0Sstevel@tonic-gate /* 3062*0Sstevel@tonic-gate * Maintain the library view of the size 3063*0Sstevel@tonic-gate */ 3064*0Sstevel@tonic-gate if (resource_get_size(pool_elem_res(xtransfer->pxu_src), 3065*0Sstevel@tonic-gate &src_size) != PO_SUCCESS || 3066*0Sstevel@tonic-gate resource_get_size(pool_elem_res(xtransfer->pxu_tgt), 3067*0Sstevel@tonic-gate &tgt_size) != PO_SUCCESS) { 3068*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 3069*0Sstevel@tonic-gate return (PO_FAIL); 3070*0Sstevel@tonic-gate } 3071*0Sstevel@tonic-gate src_size++; 3072*0Sstevel@tonic-gate tgt_size--; 3073*0Sstevel@tonic-gate pool_value_set_uint64(&val, src_size); 3074*0Sstevel@tonic-gate (void) pool_put_any_ns_property(xtransfer->pxu_src, 3075*0Sstevel@tonic-gate c_size_prop, &val); 3076*0Sstevel@tonic-gate pool_value_set_uint64(&val, tgt_size); 3077*0Sstevel@tonic-gate (void) pool_put_any_ns_property(xtransfer->pxu_tgt, 3078*0Sstevel@tonic-gate c_size_prop, &val); 3079*0Sstevel@tonic-gate } 3080*0Sstevel@tonic-gate break; 3081*0Sstevel@tonic-gate case POOL_PROPPUT: 3082*0Sstevel@tonic-gate propput = (pool_propput_undo_t *)li->li_details; 3083*0Sstevel@tonic-gate 3084*0Sstevel@tonic-gate if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) { 3085*0Sstevel@tonic-gate if (propput->ppu_blist != NULL) { 3086*0Sstevel@tonic-gate if (nvlist_merge( 3087*0Sstevel@tonic-gate ((pool_knl_elem_t *)propput->ppu_elem)-> 3088*0Sstevel@tonic-gate pke_properties, propput->ppu_blist, 0) 3089*0Sstevel@tonic-gate != 0) { 3090*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3091*0Sstevel@tonic-gate return (PO_FAIL); 3092*0Sstevel@tonic-gate } 3093*0Sstevel@tonic-gate } else { 3094*0Sstevel@tonic-gate if (nvlist_unpack(propput->ppu_ioctl.pp_o_buf, 3095*0Sstevel@tonic-gate propput->ppu_ioctl.pp_o_bufsize, 3096*0Sstevel@tonic-gate &propput->ppu_alist, 0) != 0) { 3097*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3098*0Sstevel@tonic-gate return (PO_FAIL); 3099*0Sstevel@tonic-gate } 3100*0Sstevel@tonic-gate pair = nvlist_next_nvpair(propput->ppu_alist, 3101*0Sstevel@tonic-gate NULL); 3102*0Sstevel@tonic-gate (void) nvlist_remove_all(((pool_knl_elem_t *) 3103*0Sstevel@tonic-gate propput->ppu_elem)->pke_properties, 3104*0Sstevel@tonic-gate nvpair_name(pair)); 3105*0Sstevel@tonic-gate nvlist_free(propput->ppu_alist); 3106*0Sstevel@tonic-gate } 3107*0Sstevel@tonic-gate } 3108*0Sstevel@tonic-gate break; 3109*0Sstevel@tonic-gate case POOL_PROPRM: 3110*0Sstevel@tonic-gate proprm = (pool_proprm_undo_t *)li->li_details; 3111*0Sstevel@tonic-gate 3112*0Sstevel@tonic-gate if (pool_value_get_type(&proprm->pru_oldval) != POC_INVAL) { 3113*0Sstevel@tonic-gate if (pool_put_property(conf, proprm->pru_elem, 3114*0Sstevel@tonic-gate proprm->pru_ioctl.pp_o_prop_name, 3115*0Sstevel@tonic-gate &proprm->pru_oldval) != PO_SUCCESS) { 3116*0Sstevel@tonic-gate return (PO_FAIL); 3117*0Sstevel@tonic-gate } 3118*0Sstevel@tonic-gate } 3119*0Sstevel@tonic-gate break; 3120*0Sstevel@tonic-gate default: 3121*0Sstevel@tonic-gate return (PO_FAIL); 3122*0Sstevel@tonic-gate } 3123*0Sstevel@tonic-gate } 3124*0Sstevel@tonic-gate /* 3125*0Sstevel@tonic-gate * Only try to undo the state of the kernel if we modified it. 3126*0Sstevel@tonic-gate */ 3127*0Sstevel@tonic-gate if (li->li_state == LS_DO) { 3128*0Sstevel@tonic-gate return (PO_SUCCESS); 3129*0Sstevel@tonic-gate } 3130*0Sstevel@tonic-gate 3131*0Sstevel@tonic-gate switch (li->li_op) { 3132*0Sstevel@tonic-gate case POOL_CREATE: 3133*0Sstevel@tonic-gate create = (pool_create_undo_t *)li->li_details; 3134*0Sstevel@tonic-gate 3135*0Sstevel@tonic-gate u_destroy.pd_o_type = create->pcu_ioctl.pc_o_type; 3136*0Sstevel@tonic-gate u_destroy.pd_o_sub_type = create->pcu_ioctl.pc_o_sub_type; 3137*0Sstevel@tonic-gate u_destroy.pd_o_id = create->pcu_ioctl.pc_i_id; 3138*0Sstevel@tonic-gate 3139*0Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_DESTROY, 3140*0Sstevel@tonic-gate &u_destroy)) < 0 && errno == EAGAIN); 3141*0Sstevel@tonic-gate if (ret < 0) { 3142*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3143*0Sstevel@tonic-gate return (PO_FAIL); 3144*0Sstevel@tonic-gate } 3145*0Sstevel@tonic-gate li->li_state = LS_DO; 3146*0Sstevel@tonic-gate break; 3147*0Sstevel@tonic-gate case POOL_DESTROY: 3148*0Sstevel@tonic-gate destroy = (pool_destroy_undo_t *)li->li_details; 3149*0Sstevel@tonic-gate 3150*0Sstevel@tonic-gate u_create.pc_o_type = destroy->pdu_ioctl.pd_o_type; 3151*0Sstevel@tonic-gate u_create.pc_o_sub_type = destroy->pdu_ioctl.pd_o_sub_type; 3152*0Sstevel@tonic-gate 3153*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_CREATE, &u_create) < 0) { 3154*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3155*0Sstevel@tonic-gate return (PO_FAIL); 3156*0Sstevel@tonic-gate } 3157*0Sstevel@tonic-gate 3158*0Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) { 3159*0Sstevel@tonic-gate return (PO_FAIL); 3160*0Sstevel@tonic-gate } 3161*0Sstevel@tonic-gate if (set_char_buf(cb, "%s.sys_id", 3162*0Sstevel@tonic-gate pool_elem_class_string(destroy->pdu_elem)) != PO_SUCCESS) { 3163*0Sstevel@tonic-gate free_char_buf(cb); 3164*0Sstevel@tonic-gate return (PO_FAIL); 3165*0Sstevel@tonic-gate } 3166*0Sstevel@tonic-gate (void) nvlist_add_int64( 3167*0Sstevel@tonic-gate ((pool_knl_elem_t *)destroy->pdu_elem)->pke_properties, 3168*0Sstevel@tonic-gate cb->cb_buf, u_create.pc_i_id); 3169*0Sstevel@tonic-gate free_char_buf(cb); 3170*0Sstevel@tonic-gate if (dict_put(prov->pkc_elements, destroy->pdu_elem, 3171*0Sstevel@tonic-gate destroy->pdu_elem) != NULL) { 3172*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3173*0Sstevel@tonic-gate return (PO_FAIL); 3174*0Sstevel@tonic-gate } 3175*0Sstevel@tonic-gate /* 3176*0Sstevel@tonic-gate * Now we need to reset all the properties and 3177*0Sstevel@tonic-gate * associations in the kernel for this newly created 3178*0Sstevel@tonic-gate * replacement. 3179*0Sstevel@tonic-gate */ 3180*0Sstevel@tonic-gate u_propput.pp_o_id_type = destroy->pdu_ioctl.pd_o_type; 3181*0Sstevel@tonic-gate u_propput.pp_o_id_sub_type = destroy->pdu_ioctl.pd_o_sub_type; 3182*0Sstevel@tonic-gate u_propput.pp_o_id = u_create.pc_i_id; 3183*0Sstevel@tonic-gate u_propput.pp_o_buf = NULL; 3184*0Sstevel@tonic-gate /* 3185*0Sstevel@tonic-gate * Remove the read-only properties before attempting 3186*0Sstevel@tonic-gate * to restore the state of the newly created property 3187*0Sstevel@tonic-gate */ 3188*0Sstevel@tonic-gate (void) nvlist_dup(((pool_knl_elem_t *)destroy->pdu_elem)-> 3189*0Sstevel@tonic-gate pke_properties, &tmplist, 0); 3190*0Sstevel@tonic-gate for (pair = nvlist_next_nvpair(tmplist, NULL); pair != NULL; 3191*0Sstevel@tonic-gate pair = nvlist_next_nvpair(tmplist, pair)) { 3192*0Sstevel@tonic-gate const pool_prop_t *prop; 3193*0Sstevel@tonic-gate char *name = nvpair_name(pair); 3194*0Sstevel@tonic-gate if ((prop = provider_get_prop(destroy->pdu_elem, 3195*0Sstevel@tonic-gate name)) != NULL) 3196*0Sstevel@tonic-gate if (prop_is_readonly(prop) == PO_TRUE) 3197*0Sstevel@tonic-gate (void) nvlist_remove_all(tmplist, name); 3198*0Sstevel@tonic-gate } 3199*0Sstevel@tonic-gate if (nvlist_pack(tmplist, (char **)&u_propput.pp_o_buf, 3200*0Sstevel@tonic-gate &u_propput.pp_o_bufsize, NV_ENCODE_NATIVE, 0) != 0) { 3201*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3202*0Sstevel@tonic-gate return (PO_FAIL); 3203*0Sstevel@tonic-gate } 3204*0Sstevel@tonic-gate nvlist_free(tmplist); 3205*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPPUT, &u_propput) < 0) { 3206*0Sstevel@tonic-gate free(u_propput.pp_o_buf); 3207*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3208*0Sstevel@tonic-gate return (PO_FAIL); 3209*0Sstevel@tonic-gate } 3210*0Sstevel@tonic-gate free(u_propput.pp_o_buf); 3211*0Sstevel@tonic-gate /* 3212*0Sstevel@tonic-gate * Now reset the associations for all the resource 3213*0Sstevel@tonic-gate * types if the thing which we are recreating is a 3214*0Sstevel@tonic-gate * pool 3215*0Sstevel@tonic-gate * 3216*0Sstevel@tonic-gate * TODO: This is resource specific and must be 3217*0Sstevel@tonic-gate * extended for additional resource types. 3218*0Sstevel@tonic-gate */ 3219*0Sstevel@tonic-gate if (destroy->pdu_ioctl.pd_o_type == PEC_POOL) { 3220*0Sstevel@tonic-gate u_assoc.pa_o_pool_id = u_create.pc_i_id; 3221*0Sstevel@tonic-gate u_assoc.pa_o_res_id = 3222*0Sstevel@tonic-gate elem_get_sysid( 3223*0Sstevel@tonic-gate TO_ELEM(((pool_knl_pool_t *)destroy->pdu_elem)-> 3224*0Sstevel@tonic-gate pkp_assoc[PREC_PSET])); 3225*0Sstevel@tonic-gate u_assoc.pa_o_id_type = PREC_PSET; 3226*0Sstevel@tonic-gate 3227*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc) < 0) { 3228*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3229*0Sstevel@tonic-gate return (PO_FAIL); 3230*0Sstevel@tonic-gate } 3231*0Sstevel@tonic-gate } 3232*0Sstevel@tonic-gate li->li_state = LS_DO; 3233*0Sstevel@tonic-gate break; 3234*0Sstevel@tonic-gate case POOL_ASSOC: 3235*0Sstevel@tonic-gate assoc = (pool_assoc_undo_t *)li->li_details; 3236*0Sstevel@tonic-gate 3237*0Sstevel@tonic-gate u_assoc.pa_o_pool_id = elem_get_sysid(assoc->pau_assoc); 3238*0Sstevel@tonic-gate u_assoc.pa_o_res_id = elem_get_sysid(assoc->pau_oldres); 3239*0Sstevel@tonic-gate u_assoc.pa_o_id_type = assoc->pau_ioctl.pa_o_id_type; 3240*0Sstevel@tonic-gate 3241*0Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc)) < 0 && 3242*0Sstevel@tonic-gate errno == EAGAIN); 3243*0Sstevel@tonic-gate if (ret < 0) { 3244*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3245*0Sstevel@tonic-gate return (PO_FAIL); 3246*0Sstevel@tonic-gate } 3247*0Sstevel@tonic-gate li->li_state = LS_DO; 3248*0Sstevel@tonic-gate break; 3249*0Sstevel@tonic-gate case POOL_DISSOC: 3250*0Sstevel@tonic-gate dissoc = (pool_dissoc_undo_t *)li->li_details; 3251*0Sstevel@tonic-gate 3252*0Sstevel@tonic-gate u_assoc.pa_o_pool_id = elem_get_sysid(dissoc->pdu_dissoc); 3253*0Sstevel@tonic-gate u_assoc.pa_o_res_id = elem_get_sysid(dissoc->pdu_oldres); 3254*0Sstevel@tonic-gate u_assoc.pa_o_id_type = dissoc->pdu_ioctl.pd_o_id_type; 3255*0Sstevel@tonic-gate 3256*0Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc)) < 0 && 3257*0Sstevel@tonic-gate errno == EAGAIN); 3258*0Sstevel@tonic-gate if (ret < 0) { 3259*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3260*0Sstevel@tonic-gate return (PO_FAIL); 3261*0Sstevel@tonic-gate } 3262*0Sstevel@tonic-gate li->li_state = LS_DO; 3263*0Sstevel@tonic-gate break; 3264*0Sstevel@tonic-gate case POOL_TRANSFER: 3265*0Sstevel@tonic-gate li->li_state = LS_DO; 3266*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 3267*0Sstevel@tonic-gate return (PO_FAIL); 3268*0Sstevel@tonic-gate break; 3269*0Sstevel@tonic-gate case POOL_XTRANSFER: 3270*0Sstevel@tonic-gate xtransfer = (pool_xtransfer_undo_t *)li->li_details; 3271*0Sstevel@tonic-gate 3272*0Sstevel@tonic-gate (void) memcpy(&u_xtransfer, &xtransfer->pxu_ioctl, 3273*0Sstevel@tonic-gate sizeof (pool_xtransfer_t)); 3274*0Sstevel@tonic-gate u_xtransfer.px_o_src_id = elem_get_sysid(xtransfer->pxu_tgt); 3275*0Sstevel@tonic-gate u_xtransfer.px_o_tgt_id = elem_get_sysid(xtransfer->pxu_src); 3276*0Sstevel@tonic-gate 3277*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_XTRANSFER, &u_xtransfer) < 0) { 3278*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3279*0Sstevel@tonic-gate return (PO_FAIL); 3280*0Sstevel@tonic-gate } 3281*0Sstevel@tonic-gate li->li_state = LS_DO; 3282*0Sstevel@tonic-gate break; 3283*0Sstevel@tonic-gate case POOL_PROPPUT: 3284*0Sstevel@tonic-gate propput = (pool_propput_undo_t *)li->li_details; 3285*0Sstevel@tonic-gate 3286*0Sstevel@tonic-gate if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) { 3287*0Sstevel@tonic-gate if (propput->ppu_blist) { 3288*0Sstevel@tonic-gate (void) memcpy(&u_propput, &propput->ppu_ioctl, 3289*0Sstevel@tonic-gate sizeof (pool_propput_t)); 3290*0Sstevel@tonic-gate u_propput.pp_o_id = 3291*0Sstevel@tonic-gate elem_get_sysid(propput->ppu_elem); 3292*0Sstevel@tonic-gate u_propput.pp_o_buf = NULL; 3293*0Sstevel@tonic-gate if (nvlist_pack(propput->ppu_blist, 3294*0Sstevel@tonic-gate (char **)&u_propput.pp_o_buf, 3295*0Sstevel@tonic-gate &u_propput.pp_o_bufsize, 3296*0Sstevel@tonic-gate NV_ENCODE_NATIVE, 0) != 0) { 3297*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3298*0Sstevel@tonic-gate return (PO_FAIL); 3299*0Sstevel@tonic-gate } 3300*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPPUT, 3301*0Sstevel@tonic-gate &u_propput) < 0) { 3302*0Sstevel@tonic-gate free(u_propput.pp_o_buf); 3303*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3304*0Sstevel@tonic-gate return (PO_FAIL); 3305*0Sstevel@tonic-gate } 3306*0Sstevel@tonic-gate free(u_propput.pp_o_buf); 3307*0Sstevel@tonic-gate } else { 3308*0Sstevel@tonic-gate if (nvlist_unpack(propput-> 3309*0Sstevel@tonic-gate ppu_ioctl.pp_o_buf, 3310*0Sstevel@tonic-gate propput->ppu_ioctl.pp_o_bufsize, 3311*0Sstevel@tonic-gate &propput->ppu_alist, 0) != 0) { 3312*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3313*0Sstevel@tonic-gate return (PO_FAIL); 3314*0Sstevel@tonic-gate } 3315*0Sstevel@tonic-gate u_proprm.pp_o_id_type = 3316*0Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_type; 3317*0Sstevel@tonic-gate u_proprm.pp_o_id_sub_type = 3318*0Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_sub_type; 3319*0Sstevel@tonic-gate u_proprm.pp_o_id = 3320*0Sstevel@tonic-gate elem_get_sysid(propput->ppu_elem); 3321*0Sstevel@tonic-gate pair = nvlist_next_nvpair(propput->ppu_alist, 3322*0Sstevel@tonic-gate NULL); 3323*0Sstevel@tonic-gate u_proprm.pp_o_prop_name = nvpair_name(pair); 3324*0Sstevel@tonic-gate u_proprm.pp_o_prop_name_size = 3325*0Sstevel@tonic-gate strlen(u_proprm.pp_o_prop_name); 3326*0Sstevel@tonic-gate 3327*0Sstevel@tonic-gate if (provider_get_prop(propput->ppu_elem, 3328*0Sstevel@tonic-gate u_proprm.pp_o_prop_name) == NULL) { 3329*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPRM, 3330*0Sstevel@tonic-gate &u_proprm) < 0) { 3331*0Sstevel@tonic-gate nvlist_free(propput->ppu_alist); 3332*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3333*0Sstevel@tonic-gate return (PO_FAIL); 3334*0Sstevel@tonic-gate } 3335*0Sstevel@tonic-gate } 3336*0Sstevel@tonic-gate nvlist_free(propput->ppu_alist); 3337*0Sstevel@tonic-gate } 3338*0Sstevel@tonic-gate } 3339*0Sstevel@tonic-gate li->li_state = LS_DO; 3340*0Sstevel@tonic-gate break; 3341*0Sstevel@tonic-gate case POOL_PROPRM: 3342*0Sstevel@tonic-gate proprm = (pool_proprm_undo_t *)li->li_details; 3343*0Sstevel@tonic-gate 3344*0Sstevel@tonic-gate u_propput.pp_o_id_type = proprm->pru_ioctl.pp_o_id_type; 3345*0Sstevel@tonic-gate u_propput.pp_o_id_sub_type = 3346*0Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id_sub_type; 3347*0Sstevel@tonic-gate u_propput.pp_o_id = elem_get_sysid(proprm->pru_elem); 3348*0Sstevel@tonic-gate u_propput.pp_o_buf = NULL; 3349*0Sstevel@tonic-gate /* 3350*0Sstevel@tonic-gate * Only try to remove the appropriate property 3351*0Sstevel@tonic-gate */ 3352*0Sstevel@tonic-gate if (nvlist_alloc(&tmplist, NV_UNIQUE_NAME_TYPE, 0) != 3353*0Sstevel@tonic-gate 0) { 3354*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3355*0Sstevel@tonic-gate return (PO_FAIL); 3356*0Sstevel@tonic-gate } 3357*0Sstevel@tonic-gate if (pool_knl_nvlist_add_value(tmplist, 3358*0Sstevel@tonic-gate pool_value_get_name(&proprm->pru_oldval), 3359*0Sstevel@tonic-gate &proprm->pru_oldval) != PO_SUCCESS) 3360*0Sstevel@tonic-gate return (PO_FAIL); 3361*0Sstevel@tonic-gate 3362*0Sstevel@tonic-gate if (nvlist_pack(tmplist, 3363*0Sstevel@tonic-gate (char **)&u_propput.pp_o_buf, &u_propput.pp_o_bufsize, 3364*0Sstevel@tonic-gate NV_ENCODE_NATIVE, 0) != 0) { 3365*0Sstevel@tonic-gate nvlist_free(tmplist); 3366*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3367*0Sstevel@tonic-gate return (PO_FAIL); 3368*0Sstevel@tonic-gate } 3369*0Sstevel@tonic-gate nvlist_free(tmplist); 3370*0Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPPUT, &u_propput) < 0) { 3371*0Sstevel@tonic-gate free(u_propput.pp_o_buf); 3372*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3373*0Sstevel@tonic-gate return (PO_FAIL); 3374*0Sstevel@tonic-gate } 3375*0Sstevel@tonic-gate free(u_propput.pp_o_buf); 3376*0Sstevel@tonic-gate li->li_state = LS_DO; 3377*0Sstevel@tonic-gate break; 3378*0Sstevel@tonic-gate default: 3379*0Sstevel@tonic-gate return (PO_FAIL); 3380*0Sstevel@tonic-gate } 3381*0Sstevel@tonic-gate return (PO_SUCCESS); 3382*0Sstevel@tonic-gate } 3383*0Sstevel@tonic-gate 3384*0Sstevel@tonic-gate /* 3385*0Sstevel@tonic-gate * A log item stores state about the transaction it represents. This 3386*0Sstevel@tonic-gate * function releases the resources associated with the transaction and 3387*0Sstevel@tonic-gate * used to store the transaction state. 3388*0Sstevel@tonic-gate */ 3389*0Sstevel@tonic-gate int 3390*0Sstevel@tonic-gate log_item_release(log_item_t *li) 3391*0Sstevel@tonic-gate { 3392*0Sstevel@tonic-gate pool_create_undo_t *create; 3393*0Sstevel@tonic-gate pool_destroy_undo_t *destroy; 3394*0Sstevel@tonic-gate pool_assoc_undo_t *assoc; 3395*0Sstevel@tonic-gate pool_dissoc_undo_t *dissoc; 3396*0Sstevel@tonic-gate pool_propput_undo_t *propput; 3397*0Sstevel@tonic-gate pool_proprm_undo_t *proprm; 3398*0Sstevel@tonic-gate pool_xtransfer_undo_t *xtransfer; 3399*0Sstevel@tonic-gate 3400*0Sstevel@tonic-gate switch (li->li_op) { 3401*0Sstevel@tonic-gate case POOL_CREATE: 3402*0Sstevel@tonic-gate create = (pool_create_undo_t *)li->li_details; 3403*0Sstevel@tonic-gate 3404*0Sstevel@tonic-gate free(create); 3405*0Sstevel@tonic-gate break; 3406*0Sstevel@tonic-gate case POOL_DESTROY: 3407*0Sstevel@tonic-gate destroy = (pool_destroy_undo_t *)li->li_details; 3408*0Sstevel@tonic-gate 3409*0Sstevel@tonic-gate #ifdef DEBUG 3410*0Sstevel@tonic-gate dprintf("log_item_release: POOL_DESTROY\n"); 3411*0Sstevel@tonic-gate #endif /* DEBUG */ 3412*0Sstevel@tonic-gate 3413*0Sstevel@tonic-gate if (li->li_state == LS_UNDO) { 3414*0Sstevel@tonic-gate #ifdef DEBUG 3415*0Sstevel@tonic-gate pool_elem_dprintf(destroy->pdu_elem); 3416*0Sstevel@tonic-gate #endif /* DEBUG */ 3417*0Sstevel@tonic-gate pool_knl_elem_free((pool_knl_elem_t *)destroy-> 3418*0Sstevel@tonic-gate pdu_elem, PO_TRUE); 3419*0Sstevel@tonic-gate } 3420*0Sstevel@tonic-gate free(destroy); 3421*0Sstevel@tonic-gate break; 3422*0Sstevel@tonic-gate case POOL_ASSOC: 3423*0Sstevel@tonic-gate assoc = (pool_assoc_undo_t *)li->li_details; 3424*0Sstevel@tonic-gate 3425*0Sstevel@tonic-gate free(assoc); 3426*0Sstevel@tonic-gate break; 3427*0Sstevel@tonic-gate case POOL_DISSOC: 3428*0Sstevel@tonic-gate dissoc = (pool_dissoc_undo_t *)li->li_details; 3429*0Sstevel@tonic-gate 3430*0Sstevel@tonic-gate free(dissoc); 3431*0Sstevel@tonic-gate break; 3432*0Sstevel@tonic-gate case POOL_TRANSFER: 3433*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 3434*0Sstevel@tonic-gate return (PO_FAIL); 3435*0Sstevel@tonic-gate break; 3436*0Sstevel@tonic-gate case POOL_XTRANSFER: 3437*0Sstevel@tonic-gate xtransfer = (pool_xtransfer_undo_t *)li->li_details; 3438*0Sstevel@tonic-gate 3439*0Sstevel@tonic-gate free(xtransfer->pxu_rl); 3440*0Sstevel@tonic-gate free(xtransfer->pxu_ioctl.px_o_comp_list); 3441*0Sstevel@tonic-gate free(xtransfer); 3442*0Sstevel@tonic-gate break; 3443*0Sstevel@tonic-gate case POOL_PROPPUT: 3444*0Sstevel@tonic-gate propput = (pool_propput_undo_t *)li->li_details; 3445*0Sstevel@tonic-gate 3446*0Sstevel@tonic-gate if (propput->ppu_blist) 3447*0Sstevel@tonic-gate nvlist_free(propput->ppu_blist); 3448*0Sstevel@tonic-gate free(propput->ppu_ioctl.pp_o_buf); 3449*0Sstevel@tonic-gate free(propput); 3450*0Sstevel@tonic-gate break; 3451*0Sstevel@tonic-gate case POOL_PROPRM: 3452*0Sstevel@tonic-gate proprm = (pool_proprm_undo_t *)li->li_details; 3453*0Sstevel@tonic-gate 3454*0Sstevel@tonic-gate free(proprm); 3455*0Sstevel@tonic-gate break; 3456*0Sstevel@tonic-gate default: 3457*0Sstevel@tonic-gate return (PO_FAIL); 3458*0Sstevel@tonic-gate } 3459*0Sstevel@tonic-gate return (PO_SUCCESS); 3460*0Sstevel@tonic-gate } 3461*0Sstevel@tonic-gate 3462*0Sstevel@tonic-gate /* 3463*0Sstevel@tonic-gate * pool_knl_nvlist_add_value() adds a pool_value_t to an nvlist. 3464*0Sstevel@tonic-gate */ 3465*0Sstevel@tonic-gate int 3466*0Sstevel@tonic-gate pool_knl_nvlist_add_value(nvlist_t *list, const char *name, 3467*0Sstevel@tonic-gate const pool_value_t *pv) 3468*0Sstevel@tonic-gate { 3469*0Sstevel@tonic-gate uint64_t uval; 3470*0Sstevel@tonic-gate int64_t ival; 3471*0Sstevel@tonic-gate double dval; 3472*0Sstevel@tonic-gate uchar_t dval_b[sizeof (double)]; 3473*0Sstevel@tonic-gate uchar_t bval; 3474*0Sstevel@tonic-gate const char *sval; 3475*0Sstevel@tonic-gate pool_value_class_t type; 3476*0Sstevel@tonic-gate char *nv_name; 3477*0Sstevel@tonic-gate 3478*0Sstevel@tonic-gate if ((type = pool_value_get_type(pv)) == POC_INVAL) { 3479*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 3480*0Sstevel@tonic-gate return (PO_FAIL); 3481*0Sstevel@tonic-gate } 3482*0Sstevel@tonic-gate nv_name = (char *)name; 3483*0Sstevel@tonic-gate 3484*0Sstevel@tonic-gate switch (type) { 3485*0Sstevel@tonic-gate case POC_UINT: 3486*0Sstevel@tonic-gate if (pool_value_get_uint64(pv, &uval) == POC_INVAL) { 3487*0Sstevel@tonic-gate return (PO_FAIL); 3488*0Sstevel@tonic-gate } 3489*0Sstevel@tonic-gate if (nvlist_add_uint64(list, nv_name, uval) != 0) { 3490*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3491*0Sstevel@tonic-gate return (PO_FAIL); 3492*0Sstevel@tonic-gate } 3493*0Sstevel@tonic-gate break; 3494*0Sstevel@tonic-gate case POC_INT: 3495*0Sstevel@tonic-gate if (pool_value_get_int64(pv, &ival) == POC_INVAL) { 3496*0Sstevel@tonic-gate return (PO_FAIL); 3497*0Sstevel@tonic-gate } 3498*0Sstevel@tonic-gate if (nvlist_add_int64(list, nv_name, ival) != 0) { 3499*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3500*0Sstevel@tonic-gate return (PO_FAIL); 3501*0Sstevel@tonic-gate } 3502*0Sstevel@tonic-gate break; 3503*0Sstevel@tonic-gate case POC_DOUBLE: 3504*0Sstevel@tonic-gate if (pool_value_get_double(pv, &dval) == POC_INVAL) { 3505*0Sstevel@tonic-gate return (PO_FAIL); 3506*0Sstevel@tonic-gate } 3507*0Sstevel@tonic-gate /* 3508*0Sstevel@tonic-gate * Since there is no support for doubles in the 3509*0Sstevel@tonic-gate * kernel, store the double value in a byte array. 3510*0Sstevel@tonic-gate */ 3511*0Sstevel@tonic-gate (void) memcpy(dval_b, &dval, sizeof (double)); 3512*0Sstevel@tonic-gate if (nvlist_add_byte_array(list, nv_name, dval_b, 3513*0Sstevel@tonic-gate sizeof (double)) != 0) { 3514*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3515*0Sstevel@tonic-gate return (PO_FAIL); 3516*0Sstevel@tonic-gate } 3517*0Sstevel@tonic-gate break; 3518*0Sstevel@tonic-gate case POC_BOOL: 3519*0Sstevel@tonic-gate if (pool_value_get_bool(pv, &bval) == POC_INVAL) { 3520*0Sstevel@tonic-gate return (PO_FAIL); 3521*0Sstevel@tonic-gate } 3522*0Sstevel@tonic-gate if (nvlist_add_byte(list, nv_name, bval) != 0) { 3523*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3524*0Sstevel@tonic-gate return (PO_FAIL); 3525*0Sstevel@tonic-gate } 3526*0Sstevel@tonic-gate break; 3527*0Sstevel@tonic-gate case POC_STRING: 3528*0Sstevel@tonic-gate if (pool_value_get_string(pv, &sval) == POC_INVAL) { 3529*0Sstevel@tonic-gate return (PO_FAIL); 3530*0Sstevel@tonic-gate } 3531*0Sstevel@tonic-gate if (nvlist_add_string(list, nv_name, (char *)sval) != 0) { 3532*0Sstevel@tonic-gate pool_seterror(POE_SYSTEM); 3533*0Sstevel@tonic-gate return (PO_FAIL); 3534*0Sstevel@tonic-gate } 3535*0Sstevel@tonic-gate break; 3536*0Sstevel@tonic-gate default: 3537*0Sstevel@tonic-gate pool_seterror(POE_BADPARAM); 3538*0Sstevel@tonic-gate return (PO_FAIL); 3539*0Sstevel@tonic-gate } 3540*0Sstevel@tonic-gate return (PO_SUCCESS); 3541*0Sstevel@tonic-gate } 3542*0Sstevel@tonic-gate 3543*0Sstevel@tonic-gate /* 3544*0Sstevel@tonic-gate * hash_id() hashes all elements in a pool configuration using the 3545*0Sstevel@tonic-gate * "sys_id" property. Not all elements have a "sys_id" property, 3546*0Sstevel@tonic-gate * however elem_get_sysid() caters for this by always returning a 3547*0Sstevel@tonic-gate * constant value for those elements. This isn't anticipated to lead 3548*0Sstevel@tonic-gate * to a performance degradation in the hash, since those elements 3549*0Sstevel@tonic-gate * which are likely to be most prevalent in a configuration do have 3550*0Sstevel@tonic-gate * "sys_id" as a property. 3551*0Sstevel@tonic-gate */ 3552*0Sstevel@tonic-gate uint64_t 3553*0Sstevel@tonic-gate hash_id(const pool_elem_t *pe) 3554*0Sstevel@tonic-gate { 3555*0Sstevel@tonic-gate id_t id; 3556*0Sstevel@tonic-gate 3557*0Sstevel@tonic-gate id = elem_get_sysid(pe); 3558*0Sstevel@tonic-gate return (hash_buf(&id, sizeof (id))); 3559*0Sstevel@tonic-gate } 3560*0Sstevel@tonic-gate 3561*0Sstevel@tonic-gate /* 3562*0Sstevel@tonic-gate * blocking_open() guarantees access to the pool device, if open() 3563*0Sstevel@tonic-gate * is failing with EBUSY. 3564*0Sstevel@tonic-gate */ 3565*0Sstevel@tonic-gate int 3566*0Sstevel@tonic-gate blocking_open(const char *path, int oflag) 3567*0Sstevel@tonic-gate { 3568*0Sstevel@tonic-gate int fd; 3569*0Sstevel@tonic-gate 3570*0Sstevel@tonic-gate while ((fd = open(path, oflag)) == -1 && errno == EBUSY) 3571*0Sstevel@tonic-gate (void) poll(NULL, 0, 1 * MILLISEC); 3572*0Sstevel@tonic-gate 3573*0Sstevel@tonic-gate return (fd); 3574*0Sstevel@tonic-gate } 3575