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