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 1823 garypen * Common Development and Distribution License (the "License"). 6 1823 garypen * 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 1823 garypen 22 0 stevel /* 23 3864 raf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 28 0 stevel 29 0 stevel #include <assert.h> 30 0 stevel #include <stdio.h> 31 0 stevel #include <stdlib.h> 32 0 stevel #include <string.h> 33 0 stevel #include <thread.h> 34 3864 raf #include <pthread.h> 35 0 stevel #include <synch.h> 36 0 stevel #include <unistd.h> 37 0 stevel #include <stropts.h> 38 0 stevel #include <fcntl.h> 39 0 stevel #include <note.h> 40 0 stevel #include <errno.h> 41 0 stevel #include <ctype.h> 42 0 stevel #include <libintl.h> 43 3251 sl108498 #include <libscf.h> 44 0 stevel #include <pool.h> 45 0 stevel #include <signal.h> 46 0 stevel 47 0 stevel #include <sys/pool.h> 48 0 stevel #include <sys/priocntl.h> 49 0 stevel #include <sys/types.h> 50 0 stevel #include <sys/stat.h> 51 0 stevel #include <sys/wait.h> 52 0 stevel 53 0 stevel #include "pool_internal.h" 54 0 stevel #include "pool_impl.h" 55 0 stevel 56 0 stevel /* 57 0 stevel * libpool Interface Routines 58 0 stevel * 59 0 stevel * pool.c implements (most of) the external interface to libpool 60 0 stevel * users. Some of the interface is implemented in pool_internal.c for 61 0 stevel * reasons of internal code organisation. The core requirements for 62 0 stevel * pool.c are: 63 0 stevel * 64 0 stevel * Data Abstraction 65 0 stevel * 66 0 stevel * The abstraction of the actual datastore so that no details of the 67 0 stevel * underlying data representation mechanism are revealed to users of 68 0 stevel * the library. For instance, the fact that we use the kernel or files 69 0 stevel * to store our configurations is completely abstracted via the 70 0 stevel * various libpool APIs. 71 0 stevel * 72 0 stevel * External Interaction 73 0 stevel * 74 0 stevel * libpool users manipulate configuration components via the API 75 0 stevel * defined in pool.h. Most functions in this file act as interceptors, 76 0 stevel * validating parameters before redirecting the request into a 77 0 stevel * specific datastore implementation for the actual work to be done. 78 0 stevel * 79 0 stevel * These main sets of requirements have driven the design so that it 80 0 stevel * is possible to replace the entire datastore type without having to 81 0 stevel * modify the external (or internal provider) APIs. It is possible to 82 0 stevel * modify the storage technology used by libpool by implementing a new 83 0 stevel * set of datastore provider operations. Simply modify the 84 0 stevel * pool_conf_open() routine to establish a new datastore as the 85 0 stevel * provider for a configuration. 86 0 stevel * 87 0 stevel * The key components in a libpool configuration are : 88 0 stevel * pool_conf_t - This represents a complete configuration instance 89 0 stevel * pool_t - A pool inside a configuration 90 0 stevel * pool_resource_t - A resource inside a configuration 91 0 stevel * pool_component_t - A component of a resource 92 0 stevel * 93 0 stevel */ 94 0 stevel 95 0 stevel /* 96 0 stevel * Used to control transfer setup. 97 0 stevel */ 98 0 stevel #define XFER_FAIL PO_FAIL 99 0 stevel #define XFER_SUCCESS PO_SUCCESS 100 0 stevel #define XFER_CONTINUE 1 101 0 stevel 102 1042 garypen #define SMF_SVC_INSTANCE "svc:/system/pools:default" 103 0 stevel #define E_ERROR 1 /* Exit status for error */ 104 0 stevel 105 0 stevel #ifndef TEXT_DOMAIN 106 0 stevel #define TEXT_DOMAIN "SYS_TEST" 107 0 stevel #endif /* TEXT_DOMAIN */ 108 0 stevel 109 0 stevel const char pool_info_location[] = "/dev/pool"; 110 0 stevel 111 0 stevel /* 112 0 stevel * Static data 113 0 stevel */ 114 0 stevel static const char static_location[] = "/etc/pooladm.conf"; 115 0 stevel static const char dynamic_location[] = "/dev/poolctl"; 116 3864 raf static thread_key_t errkey = THR_ONCE_KEY; 117 0 stevel 118 0 stevel /* 119 0 stevel * libpool error code 120 0 stevel */ 121 0 stevel static int pool_errval = POE_OK; 122 0 stevel 123 0 stevel /* 124 0 stevel * libpool version 125 0 stevel */ 126 0 stevel static uint_t pool_workver = POOL_VER_CURRENT; 127 0 stevel 128 0 stevel static const char *data_type_tags[] = { 129 0 stevel "uint", 130 0 stevel "int", 131 0 stevel "float", 132 0 stevel "boolean", 133 0 stevel "string" 134 0 stevel }; 135 0 stevel 136 0 stevel /* 137 0 stevel * static functions 138 0 stevel */ 139 0 stevel static int pool_elem_remove(pool_elem_t *); 140 0 stevel static int is_valid_prop_name(const char *); 141 0 stevel static int prop_buf_build_cb(pool_conf_t *, pool_elem_t *, const char *, 142 0 stevel pool_value_t *, void *); 143 0 stevel static char *pool_base_info(const pool_elem_t *, char_buf_t *, int); 144 0 stevel static int choose_components(pool_resource_t *, pool_resource_t *, uint64_t); 145 0 stevel static int pool_conf_check(const pool_conf_t *); 146 0 stevel static void free_value_list(int, pool_value_t **); 147 0 stevel static int setup_transfer(pool_conf_t *, pool_resource_t *, pool_resource_t *, 148 0 stevel uint64_t, uint64_t *, uint64_t *); 149 0 stevel 150 0 stevel /* 151 0 stevel * Return the "static" location string for libpool. 152 0 stevel */ 153 0 stevel const char * 154 0 stevel pool_static_location(void) 155 0 stevel { 156 0 stevel return (static_location); 157 0 stevel } 158 0 stevel 159 0 stevel /* 160 0 stevel * Return the "dynamic" location string for libpool. 161 0 stevel */ 162 0 stevel const char * 163 0 stevel pool_dynamic_location(void) 164 0 stevel { 165 0 stevel return (dynamic_location); 166 0 stevel } 167 0 stevel 168 0 stevel /* 169 0 stevel * Return the status for a configuration. If the configuration has 170 0 stevel * been successfully opened, then the status will be POF_VALID or 171 0 stevel * POF_DESTROY. If the configuration failed to open properly or has 172 0 stevel * been closed or removed, then the status will be POF_INVALID. 173 0 stevel */ 174 0 stevel pool_conf_state_t 175 0 stevel pool_conf_status(const pool_conf_t *conf) 176 0 stevel { 177 0 stevel return (conf->pc_state); 178 0 stevel } 179 0 stevel 180 0 stevel /* 181 0 stevel * Bind idtype id to the pool name. 182 0 stevel */ 183 0 stevel int 184 0 stevel pool_set_binding(const char *pool_name, idtype_t idtype, id_t id) 185 0 stevel { 186 0 stevel pool_conf_t *conf; 187 0 stevel int result; 188 0 stevel 189 0 stevel if ((conf = pool_conf_alloc()) == NULL) 190 0 stevel return (PO_FAIL); 191 0 stevel 192 0 stevel if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) { 193 0 stevel pool_conf_free(conf); 194 0 stevel pool_seterror(POE_INVALID_CONF); 195 0 stevel return (PO_FAIL); 196 0 stevel } 197 0 stevel 198 0 stevel result = conf->pc_prov->pc_set_binding(conf, pool_name, idtype, id); 199 0 stevel 200 0 stevel (void) pool_conf_close(conf); 201 0 stevel pool_conf_free(conf); 202 0 stevel return (result); 203 0 stevel } 204 0 stevel 205 0 stevel /* 206 0 stevel * pool_get_resource_binding() returns the binding for a pid to the supplied 207 0 stevel * type of resource. If a binding cannot be determined, NULL is returned. 208 0 stevel */ 209 0 stevel char * 210 0 stevel pool_get_resource_binding(const char *sz_type, pid_t pid) 211 0 stevel { 212 0 stevel pool_conf_t *conf; 213 0 stevel char *result; 214 0 stevel pool_resource_elem_class_t type; 215 0 stevel 216 0 stevel if ((type = pool_resource_elem_class_from_string(sz_type)) == 217 0 stevel PREC_INVALID) { 218 0 stevel pool_seterror(POE_BADPARAM); 219 0 stevel return (NULL); 220 0 stevel } 221 0 stevel 222 0 stevel if ((conf = pool_conf_alloc()) == NULL) 223 0 stevel return (NULL); 224 0 stevel 225 0 stevel if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) 226 0 stevel != PO_SUCCESS) { 227 0 stevel pool_seterror(POE_INVALID_CONF); 228 0 stevel pool_conf_free(conf); 229 0 stevel return (NULL); 230 0 stevel } 231 0 stevel result = conf->pc_prov->pc_get_resource_binding(conf, type, pid); 232 0 stevel (void) pool_conf_close(conf); 233 0 stevel pool_conf_free(conf); 234 0 stevel return (result); 235 0 stevel } 236 0 stevel 237 0 stevel /* 238 0 stevel * pool_get_binding() returns the binding for a pid to a pool. If a 239 0 stevel * binding cannot be determined, NULL is returned. 240 0 stevel */ 241 0 stevel char * 242 0 stevel pool_get_binding(pid_t pid) 243 0 stevel { 244 0 stevel pool_conf_t *conf; 245 0 stevel char *result; 246 0 stevel 247 0 stevel if ((conf = pool_conf_alloc()) == NULL) 248 0 stevel return (NULL); 249 0 stevel 250 0 stevel if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) 251 0 stevel != PO_SUCCESS) { 252 0 stevel pool_seterror(POE_INVALID_CONF); 253 0 stevel pool_conf_free(conf); 254 0 stevel return (NULL); 255 0 stevel } 256 0 stevel result = conf->pc_prov->pc_get_binding(conf, pid); 257 0 stevel (void) pool_conf_close(conf); 258 0 stevel pool_conf_free(conf); 259 0 stevel return (result); 260 0 stevel } 261 0 stevel 262 0 stevel /*ARGSUSED*/ 263 0 stevel int 264 0 stevel prop_buf_build_cb(pool_conf_t *UNUSED, pool_elem_t *pe, const char *name, 265 0 stevel pool_value_t *pval, void *user) 266 0 stevel { 267 0 stevel uint64_t u; 268 0 stevel int64_t i; 269 0 stevel uchar_t bool; 270 0 stevel const char *str; 271 0 stevel double d; 272 0 stevel char_buf_t *cb = (char_buf_t *)user; 273 0 stevel int type = pool_value_get_type(pval); 274 0 stevel 275 0 stevel /* 276 0 stevel * Ignore "type" and "<type>.name" properties as these are not 277 0 stevel * to be displayed by this function 278 0 stevel */ 279 0 stevel if (strcmp(name, c_type) == 0 || 280 0 stevel strcmp(property_name_minus_ns(pe, name), c_name) == 0) 281 0 stevel return (PO_SUCCESS); 282 0 stevel if (append_char_buf(cb, "\n%s\t%s\t%s ", cb->cb_tab_buf, 283 0 stevel data_type_tags[type], name) == PO_FAIL) 284 0 stevel return (PO_FAIL); 285 0 stevel switch (type) { 286 0 stevel case POC_UINT: 287 0 stevel (void) pool_value_get_uint64(pval, &u); 288 0 stevel if (append_char_buf(cb, "%llu", (u_longlong_t)u) == PO_FAIL) 289 0 stevel return (PO_FAIL); 290 0 stevel break; 291 0 stevel case POC_INT: 292 0 stevel (void) pool_value_get_int64(pval, &i); 293 0 stevel if (append_char_buf(cb, "%lld", (longlong_t)i) == PO_FAIL) 294 0 stevel return (PO_FAIL); 295 0 stevel break; 296 0 stevel case POC_STRING: 297 0 stevel (void) pool_value_get_string(pval, &str); 298 0 stevel if (append_char_buf(cb, "%s", str) == PO_FAIL) 299 0 stevel return (PO_FAIL); 300 0 stevel break; 301 0 stevel case POC_BOOL: 302 0 stevel (void) pool_value_get_bool(pval, &bool); 303 0 stevel if (bool == 0) { 304 0 stevel if (append_char_buf(cb, "%s", "false") == PO_FAIL) 305 0 stevel return (PO_FAIL); 306 0 stevel } else { 307 0 stevel if (append_char_buf(cb, "%s", "true") == PO_FAIL) 308 0 stevel return (PO_FAIL); 309 0 stevel } 310 0 stevel break; 311 0 stevel case POC_DOUBLE: 312 0 stevel (void) pool_value_get_double(pval, &d); 313 0 stevel if (append_char_buf(cb, "%g", d) == PO_FAIL) 314 0 stevel return (PO_FAIL); 315 0 stevel break; 316 0 stevel case POC_INVAL: /* Do nothing */ 317 0 stevel break; 318 0 stevel default: 319 0 stevel return (PO_FAIL); 320 0 stevel } 321 0 stevel return (PO_SUCCESS); 322 0 stevel } 323 0 stevel 324 0 stevel /* 325 0 stevel * Return a buffer which describes the element 326 0 stevel * pe is a pointer to the element 327 0 stevel * deep is PO_TRUE/PO_FALSE to indicate whether children should be included 328 0 stevel */ 329 0 stevel char * 330 0 stevel pool_base_info(const pool_elem_t *pe, char_buf_t *cb, int deep) 331 0 stevel { 332 0 stevel const char *sres; 333 0 stevel uint_t i; 334 0 stevel uint_t nelem; 335 0 stevel 336 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 337 0 stevel pool_resource_t **rs; 338 0 stevel pool_elem_t *elem; 339 0 stevel pool_conf_t *conf = TO_CONF(pe); 340 0 stevel 341 0 stevel if (cb == NULL) { 342 0 stevel char *ret = NULL; 343 0 stevel 344 0 stevel if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) 345 0 stevel return (NULL); 346 0 stevel 347 0 stevel /* 348 0 stevel * Populate the buffer with element details 349 0 stevel */ 350 0 stevel (void) pool_base_info(pe, cb, deep); 351 0 stevel if (cb->cb_buf) 352 0 stevel ret = strdup(cb->cb_buf); 353 0 stevel free_char_buf(cb); 354 0 stevel return (ret); 355 0 stevel } 356 0 stevel 357 0 stevel if (append_char_buf(cb, "\n%s%s", cb->cb_tab_buf, 358 0 stevel pool_elem_class_string(pe)) == PO_FAIL) { 359 0 stevel return (NULL); 360 0 stevel } 361 0 stevel 362 0 stevel if (pool_get_ns_property(pe, c_name, &val) == POC_STRING) { 363 0 stevel (void) pool_value_get_string(&val, &sres); 364 0 stevel if (append_char_buf(cb, " %s", sres) == PO_FAIL) { 365 0 stevel return (NULL); 366 0 stevel } 367 0 stevel } 368 0 stevel 369 0 stevel /* 370 0 stevel * Add in some details about the element 371 0 stevel */ 372 0 stevel if (pool_walk_properties(conf, (pool_elem_t *)pe, cb, 373 0 stevel prop_buf_build_cb) == PO_FAIL) { 374 0 stevel (void) append_char_buf(cb, "\n%s%s\n", cb->cb_tab_buf, 375 0 stevel "Cannot access the properties of this element."); 376 0 stevel return (NULL); 377 0 stevel } 378 0 stevel if (append_char_buf(cb, "%s", "\n") == PO_FAIL) 379 0 stevel return (NULL); 380 0 stevel 381 0 stevel if (pe->pe_class == PEC_POOL) { 382 0 stevel /* 383 0 stevel * A shallow display of a pool only lists the resources by name 384 0 stevel */ 385 0 stevel 386 0 stevel if ((rs = pool_query_pool_resources(conf, pool_elem_pool(pe), 387 0 stevel &nelem, NULL)) == NULL) { 388 0 stevel return (NULL); 389 0 stevel } 390 0 stevel 391 0 stevel for (i = 0; i < nelem; i++) { 392 0 stevel const char *str; 393 0 stevel 394 0 stevel elem = TO_ELEM(rs[i]); 395 0 stevel 396 0 stevel if (append_char_buf(cb, "\t%s%s", cb->cb_tab_buf, 397 0 stevel pool_elem_class_string(elem)) == PO_FAIL) { 398 0 stevel free(rs); 399 0 stevel return (NULL); 400 0 stevel } 401 0 stevel 402 0 stevel if (pool_get_ns_property(elem, c_name, &val) != 403 0 stevel POC_STRING) { 404 0 stevel free(rs); 405 0 stevel pool_seterror(POE_INVALID_CONF); 406 0 stevel return (NULL); 407 0 stevel } 408 0 stevel (void) pool_value_get_string(&val, &str); 409 0 stevel if (append_char_buf(cb, "\t%s\n", str) == PO_FAIL) { 410 0 stevel free(rs); 411 0 stevel return (NULL); 412 0 stevel } 413 0 stevel } 414 0 stevel free(rs); 415 0 stevel } 416 0 stevel if (deep == PO_TRUE) { 417 0 stevel pool_t **ps; 418 0 stevel pool_component_t **cs; 419 0 stevel 420 0 stevel if (strlcat(cb->cb_tab_buf, "\t", CB_TAB_BUF_SIZE) 421 0 stevel >= CB_TAB_BUF_SIZE) { 422 0 stevel pool_seterror(POE_SYSTEM); 423 0 stevel return (NULL); 424 0 stevel } 425 0 stevel switch (pe->pe_class) { 426 0 stevel case PEC_SYSTEM: 427 0 stevel if ((ps = pool_query_pools(conf, &nelem, NULL)) != 428 0 stevel NULL) { /* process the pools */ 429 0 stevel for (i = 0; i < nelem; i++) { 430 0 stevel elem = TO_ELEM(ps[i]); 431 0 stevel if (pool_base_info(elem, cb, 432 0 stevel PO_FALSE) == NULL) { 433 0 stevel free(ps); 434 0 stevel return (NULL); 435 0 stevel } 436 0 stevel } 437 0 stevel free(ps); 438 0 stevel } 439 0 stevel if ((rs = pool_query_resources(conf, &nelem, NULL)) != 440 0 stevel NULL) { 441 0 stevel for (i = 0; i < nelem; i++) { 442 0 stevel elem = TO_ELEM(rs[i]); 443 0 stevel if (pool_base_info(elem, cb, 444 0 stevel PO_TRUE) == NULL) { 445 0 stevel free(rs); 446 0 stevel return (NULL); 447 0 stevel } 448 0 stevel } 449 0 stevel free(rs); 450 0 stevel } 451 0 stevel break; 452 0 stevel case PEC_POOL: 453 0 stevel if ((rs = pool_query_pool_resources(conf, 454 0 stevel pool_elem_pool(pe), &nelem, NULL)) == NULL) 455 0 stevel return (NULL); 456 0 stevel for (i = 0; i < nelem; i++) { 457 0 stevel elem = TO_ELEM(rs[i]); 458 0 stevel if (pool_base_info(elem, cb, PO_TRUE) == NULL) { 459 0 stevel free(rs); 460 0 stevel return (NULL); 461 0 stevel } 462 0 stevel } 463 0 stevel free(rs); 464 0 stevel break; 465 0 stevel case PEC_RES_COMP: 466 0 stevel if ((cs = pool_query_resource_components(conf, 467 0 stevel pool_elem_res(pe), &nelem, NULL)) != NULL) { 468 0 stevel for (i = 0; i < nelem; i++) { 469 0 stevel elem = TO_ELEM(cs[i]); 470 0 stevel if (pool_base_info(elem, cb, 471 0 stevel PO_FALSE) == NULL) { 472 0 stevel free(cs); 473 0 stevel return (NULL); 474 0 stevel } 475 0 stevel } 476 0 stevel free(cs); 477 0 stevel } 478 0 stevel break; 479 0 stevel case PEC_RES_AGG: 480 0 stevel case PEC_COMP: 481 0 stevel break; 482 0 stevel default: 483 0 stevel /*NOTREACHED*/ 484 0 stevel break; 485 0 stevel } 486 0 stevel if (cb->cb_tab_buf[0] != 0) 487 0 stevel cb->cb_tab_buf[strlen(cb->cb_tab_buf) - 1] = 0; 488 0 stevel } 489 0 stevel return (cb->cb_buf); 490 0 stevel } 491 0 stevel 492 0 stevel /* 493 0 stevel * Returns The information on the specified pool or NULL. 494 0 stevel * 495 0 stevel * Errors If the status of the conf is INVALID or the supplied 496 0 stevel * value of deep is illegal, POE_BADPARAM. 497 0 stevel * 498 0 stevel * The caller is responsible for free(3c)ing the string returned. 499 0 stevel */ 500 0 stevel char * 501 0 stevel pool_info(const pool_conf_t *conf, const pool_t *pool, int deep) 502 0 stevel { 503 0 stevel pool_elem_t *pe; 504 0 stevel 505 0 stevel pe = TO_ELEM(pool); 506 0 stevel 507 0 stevel if (TO_CONF(pe) != conf) { 508 0 stevel pool_seterror(POE_BADPARAM); 509 0 stevel return (NULL); 510 0 stevel } 511 0 stevel 512 0 stevel if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) { 513 0 stevel pool_seterror(POE_BADPARAM); 514 0 stevel return (NULL); 515 0 stevel } 516 0 stevel 517 0 stevel return (pool_base_info(pe, NULL, deep)); 518 0 stevel } 519 0 stevel 520 0 stevel /* 521 0 stevel * Returns The information on the specified resource or NULL. 522 0 stevel * 523 0 stevel * Errors If the status of the conf is INVALID or the supplied 524 0 stevel * value of deep is illegal, POE_BADPARAM. 525 0 stevel * 526 0 stevel * The caller is responsible for free(3c)ing the string returned. 527 0 stevel */ 528 0 stevel char * 529 0 stevel pool_resource_info(const pool_conf_t *conf, const pool_resource_t *res, 530 0 stevel int deep) 531 0 stevel { 532 0 stevel pool_elem_t *pe; 533 0 stevel 534 0 stevel pe = TO_ELEM(res); 535 0 stevel 536 0 stevel if (TO_CONF(pe) != conf) { 537 0 stevel pool_seterror(POE_BADPARAM); 538 0 stevel return (NULL); 539 0 stevel } 540 0 stevel 541 0 stevel if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) { 542 0 stevel pool_seterror(POE_BADPARAM); 543 0 stevel return (NULL); 544 0 stevel } 545 0 stevel 546 0 stevel return (pool_base_info(pe, NULL, deep)); 547 0 stevel } 548 0 stevel 549 0 stevel /* 550 0 stevel * Returns The information on the specified component or NULL. 551 0 stevel * 552 0 stevel * Errors If the status of the conf is INVALID or the supplied 553 0 stevel * value of deep is illegal, POE_BADPARAM. 554 0 stevel * 555 0 stevel * The caller is responsible for free(3c)ing the string returned. 556 0 stevel */ 557 0 stevel char * 558 0 stevel pool_component_info(const pool_conf_t *conf, const pool_component_t *comp, 559 0 stevel int deep) 560 0 stevel { 561 0 stevel pool_elem_t *pe; 562 0 stevel 563 0 stevel pe = TO_ELEM(comp); 564 0 stevel 565 0 stevel if (TO_CONF(pe) != conf) { 566 0 stevel pool_seterror(POE_BADPARAM); 567 0 stevel return (NULL); 568 0 stevel } 569 0 stevel 570 0 stevel if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) { 571 0 stevel pool_seterror(POE_BADPARAM); 572 0 stevel return (NULL); 573 0 stevel } 574 0 stevel 575 0 stevel return (pool_base_info(pe, NULL, deep)); 576 0 stevel } 577 0 stevel 578 0 stevel /* 579 0 stevel * Returns The information on the specified conf or NULL. 580 0 stevel * 581 0 stevel * Errors If the status of the conf is INVALID or the supplied 582 0 stevel * value of deep is illegal, POE_BADPARAM. 583 0 stevel * 584 0 stevel * The caller is responsible for free(3c)ing the string returned. 585 0 stevel */ 586 0 stevel char * 587 0 stevel pool_conf_info(const pool_conf_t *conf, int deep) 588 0 stevel { 589 0 stevel pool_elem_t *pe; 590 0 stevel 591 0 stevel if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) { 592 0 stevel pool_seterror(POE_BADPARAM); 593 0 stevel return (NULL); 594 0 stevel } 595 0 stevel if ((pe = pool_conf_to_elem(conf)) == NULL) { 596 0 stevel pool_seterror(POE_BADPARAM); 597 0 stevel return (NULL); 598 0 stevel } 599 0 stevel return (pool_base_info(pe, NULL, deep)); 600 0 stevel } 601 0 stevel 602 0 stevel 603 0 stevel /* 604 0 stevel * Set the thread specific error value. 605 0 stevel */ 606 0 stevel void 607 0 stevel pool_seterror(int errval) 608 0 stevel { 609 0 stevel if (thr_main()) { 610 0 stevel pool_errval = errval; 611 0 stevel return; 612 0 stevel } 613 3864 raf (void) thr_keycreate_once(&errkey, 0); 614 0 stevel (void) thr_setspecific(errkey, (void *)(intptr_t)errval); 615 0 stevel } 616 0 stevel 617 0 stevel /* 618 0 stevel * Return the current value of the error code. 619 0 stevel * Returns: int error code 620 0 stevel */ 621 0 stevel int 622 0 stevel pool_error(void) 623 0 stevel { 624 0 stevel if (thr_main()) 625 0 stevel return (pool_errval); 626 3864 raf if (errkey == THR_ONCE_KEY) 627 0 stevel return (POE_OK); 628 3864 raf return ((uintptr_t)pthread_getspecific(errkey)); 629 0 stevel } 630 0 stevel 631 0 stevel /* 632 0 stevel * Return the text represenation for the current value of the error code. 633 0 stevel * Returns: const char * error string 634 0 stevel */ 635 0 stevel const char * 636 0 stevel pool_strerror(int error) 637 0 stevel { 638 0 stevel char *str; 639 0 stevel 640 0 stevel switch (error) { 641 0 stevel case POE_OK: 642 0 stevel str = dgettext(TEXT_DOMAIN, "Operation successful"); 643 0 stevel break; 644 0 stevel case POE_BAD_PROP_TYPE: 645 0 stevel str = dgettext(TEXT_DOMAIN, 646 0 stevel "Attempted to retrieve the wrong property type"); 647 0 stevel break; 648 0 stevel case POE_INVALID_CONF: 649 0 stevel str = dgettext(TEXT_DOMAIN, "Invalid configuration"); 650 0 stevel break; 651 0 stevel case POE_NOTSUP: 652 0 stevel str = dgettext(TEXT_DOMAIN, "Operation is not supported"); 653 0 stevel break; 654 0 stevel case POE_INVALID_SEARCH: 655 0 stevel str = dgettext(TEXT_DOMAIN, "Invalid search"); 656 0 stevel break; 657 0 stevel case POE_BADPARAM: 658 0 stevel str = dgettext(TEXT_DOMAIN, "Bad parameter supplied"); 659 0 stevel break; 660 0 stevel case POE_PUTPROP: 661 0 stevel str = dgettext(TEXT_DOMAIN, "Error putting property"); 662 0 stevel break; 663 0 stevel case POE_DATASTORE: 664 0 stevel str = dgettext(TEXT_DOMAIN, "Pools repository error"); 665 0 stevel break; 666 0 stevel case POE_SYSTEM: 667 0 stevel str = dgettext(TEXT_DOMAIN, "System error"); 668 0 stevel break; 669 0 stevel case POE_ACCESS: 670 0 stevel str = dgettext(TEXT_DOMAIN, "Permission denied"); 671 0 stevel break; 672 0 stevel default: 673 0 stevel errno = ESRCH; 674 0 stevel str = NULL; 675 0 stevel } 676 0 stevel return (str); 677 0 stevel } 678 0 stevel 679 0 stevel int 680 0 stevel pool_get_status(int *state) 681 0 stevel { 682 0 stevel int fd; 683 0 stevel pool_status_t status; 684 0 stevel 685 0 stevel if ((fd = open(pool_info_location, O_RDONLY)) < 0) { 686 0 stevel pool_seterror(POE_SYSTEM); 687 0 stevel return (PO_FAIL); 688 0 stevel } 689 0 stevel if (ioctl(fd, POOL_STATUSQ, &status) < 0) { 690 0 stevel (void) close(fd); 691 0 stevel pool_seterror(POE_SYSTEM); 692 0 stevel return (PO_FAIL); 693 0 stevel } 694 0 stevel (void) close(fd); 695 0 stevel 696 0 stevel *state = status.ps_io_state; 697 0 stevel 698 0 stevel return (PO_SUCCESS); 699 0 stevel } 700 0 stevel 701 0 stevel int 702 0 stevel pool_set_status(int state) 703 0 stevel { 704 0 stevel int old_state; 705 0 stevel 706 0 stevel if (pool_get_status(&old_state) != PO_SUCCESS) { 707 0 stevel pool_seterror(POE_SYSTEM); 708 0 stevel return (PO_FAIL); 709 0 stevel } 710 0 stevel 711 0 stevel if (old_state != state) { 712 0 stevel int fd; 713 0 stevel pool_status_t status; 714 3251 sl108498 char *fmri; 715 0 stevel 716 1042 garypen /* 717 1042 garypen * Changing the status of pools is performed by enabling 718 1042 garypen * or disabling the pools service instance. If this 719 1042 garypen * function has not been invoked by startd then we simply 720 1042 garypen * enable/disable the service and return success. 721 1042 garypen * 722 1042 garypen * There is no way to specify that state changes must be 723 1042 garypen * synchronous using the library API as yet, so we use 724 1042 garypen * the -s option provided by svcadm. 725 1042 garypen */ 726 3251 sl108498 fmri = getenv("SMF_FMRI"); 727 3251 sl108498 if (fmri == NULL) { 728 1042 garypen FILE *p; 729 2706 garypen char *cmd; 730 2706 garypen 731 3251 sl108498 if (state != 0) { 732 2706 garypen cmd = "/usr/sbin/svcadm enable -s " \ 733 1042 garypen SMF_SVC_INSTANCE; 734 1042 garypen } else { 735 2706 garypen cmd = "/usr/sbin/svcadm disable -s " \ 736 1042 garypen SMF_SVC_INSTANCE; 737 2706 garypen } 738 2706 garypen if ((p = popen(cmd, "wF")) == NULL || pclose(p) != 0) { 739 2706 garypen pool_seterror(POE_SYSTEM); 740 2706 garypen return (PO_FAIL); 741 0 stevel } 742 1042 garypen return (PO_SUCCESS); 743 0 stevel } 744 0 stevel 745 0 stevel if ((fd = open(pool_dynamic_location(), O_RDWR | O_EXCL)) < 0) { 746 0 stevel pool_seterror(POE_SYSTEM); 747 0 stevel return (PO_FAIL); 748 0 stevel } 749 0 stevel 750 3251 sl108498 /* 751 3251 sl108498 * If pools are being enabled/disabled by another smf service, 752 3251 sl108498 * enable the smf service instance. This must be done 753 3251 sl108498 * asynchronously as one service cannot synchronously 754 3251 sl108498 * enable/disable another. 755 3251 sl108498 */ 756 3251 sl108498 if (strcmp(fmri, SMF_SVC_INSTANCE) != 0) { 757 3251 sl108498 int res; 758 3251 sl108498 759 3251 sl108498 if (state != 0) 760 3251 sl108498 res = smf_enable_instance(SMF_SVC_INSTANCE, 0); 761 3251 sl108498 else 762 3251 sl108498 res = smf_disable_instance(SMF_SVC_INSTANCE, 0); 763 3251 sl108498 764 3251 sl108498 if (res != 0) { 765 3251 sl108498 (void) close(fd); 766 3251 sl108498 pool_seterror(POE_SYSTEM); 767 3251 sl108498 return (PO_FAIL); 768 3251 sl108498 } 769 3251 sl108498 } 770 0 stevel status.ps_io_state = state; 771 0 stevel 772 0 stevel if (ioctl(fd, POOL_STATUS, &status) < 0) { 773 0 stevel (void) close(fd); 774 0 stevel pool_seterror(POE_SYSTEM); 775 0 stevel return (PO_FAIL); 776 0 stevel } 777 0 stevel 778 0 stevel (void) close(fd); 779 0 stevel 780 0 stevel } 781 0 stevel return (PO_SUCCESS); 782 0 stevel } 783 0 stevel 784 0 stevel /* 785 0 stevel * General Data Provider Independent Access Methods 786 0 stevel */ 787 0 stevel 788 0 stevel /* 789 0 stevel * Property manipulation code. 790 0 stevel * 791 0 stevel * The pool_(get|rm|set)_property() functions consult the plugins before 792 0 stevel * looking at the actual configuration. This allows plugins to provide 793 0 stevel * "virtual" properties that may not exist in the configuration file per se, 794 0 stevel * but behave like regular properties. This also allows plugins to reserve 795 0 stevel * certain properties as read-only, non-removable, etc. 796 0 stevel * 797 0 stevel * A negative value returned from the plugin denotes error, 0 means that the 798 0 stevel * property request should be forwarded to the backend, and 1 means the request 799 0 stevel * was satisfied by the plugin and should not be processed further. 800 0 stevel * 801 0 stevel * The (get|rm|set)_property() functions bypass the plugin layer completely, 802 0 stevel * and hence should not be generally used. 803 0 stevel */ 804 0 stevel 805 0 stevel /* 806 0 stevel * Return true if the string passed in matches the pattern 807 0 stevel * [A-Za-z][A-Za-z0-9,._-]* 808 0 stevel */ 809 0 stevel int 810 0 stevel is_valid_name(const char *name) 811 0 stevel { 812 0 stevel int i; 813 0 stevel char c; 814 0 stevel 815 0 stevel if (name == NULL) 816 0 stevel return (PO_FALSE); 817 0 stevel if (!isalpha(name[0])) 818 0 stevel return (PO_FALSE); 819 0 stevel for (i = 1; (c = name[i]) != '\0'; i++) { 820 0 stevel if (!isalnum(c) && c != ',' && c != '.' && c != '_' && c != '-') 821 0 stevel return (PO_FALSE); 822 0 stevel } 823 0 stevel return (PO_TRUE); 824 0 stevel } 825 0 stevel 826 0 stevel /* 827 0 stevel * Return true if the string passed in matches the pattern 828 0 stevel * [A-Za-z_][A-Za-z0-9,._-]* 829 0 stevel * A property name starting with a '_' is an "invisible" property that does not 830 0 stevel * show up in a property walk. 831 0 stevel */ 832 0 stevel int 833 0 stevel is_valid_prop_name(const char *prop_name) 834 0 stevel { 835 0 stevel int i; 836 0 stevel char c; 837 0 stevel 838 0 stevel if (prop_name == NULL) 839 0 stevel return (PO_FALSE); 840 0 stevel if (!isalpha(prop_name[0]) && prop_name[0] != '_') 841 0 stevel return (PO_FALSE); 842 0 stevel for (i = 1; (c = prop_name[i]) != '\0'; i++) { 843 0 stevel if (!isalnum(c) && c != ',' && c != '.' && c != '_' && c != '-') 844 0 stevel return (PO_FALSE); 845 0 stevel } 846 0 stevel return (PO_TRUE); 847 0 stevel } 848 0 stevel 849 0 stevel /* 850 0 stevel * Return the specified property value. 851 0 stevel * 852 0 stevel * POC_INVAL is returned if an error is detected and the error code is updated 853 0 stevel * to indicate the cause of the error. 854 0 stevel */ 855 0 stevel pool_value_class_t 856 0 stevel pool_get_property(const pool_conf_t *conf, const pool_elem_t *pe, 857 0 stevel const char *name, pool_value_t *val) 858 0 stevel { 859 0 stevel const pool_prop_t *prop_info; 860 0 stevel 861 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 862 0 stevel pool_seterror(POE_BADPARAM); 863 0 stevel return (POC_INVAL); 864 0 stevel } 865 0 stevel if (pool_value_set_name(val, name) != PO_SUCCESS) { 866 0 stevel return (POC_INVAL); 867 0 stevel } 868 0 stevel /* 869 0 stevel * Check to see if this is a property we are managing. If it 870 0 stevel * is and it has an interceptor installed for property 871 0 stevel * retrieval, use it. 872 0 stevel */ 873 0 stevel if ((prop_info = provider_get_prop(pe, name)) != NULL && 874 0 stevel prop_info->pp_op.ppo_get_value != NULL) { 875 0 stevel if (prop_info->pp_op.ppo_get_value(pe, val) == PO_FAIL) 876 0 stevel return (POC_INVAL); 877 0 stevel else 878 0 stevel return (pool_value_get_type(val)); 879 0 stevel } 880 0 stevel return (pe->pe_get_prop(pe, name, val)); 881 0 stevel } 882 0 stevel 883 0 stevel /* 884 0 stevel * Return the specified property value with the namespace prepended. 885 0 stevel * e.g. If this function is used to get the property "name" on a pool, it will 886 0 stevel * attempt to retrieve "pool.name". 887 0 stevel * 888 0 stevel * POC_INVAL is returned if an error is detected and the error code is updated 889 0 stevel * to indicate the cause of the error. 890 0 stevel */ 891 0 stevel pool_value_class_t 892 0 stevel pool_get_ns_property(const pool_elem_t *pe, const char *name, pool_value_t *val) 893 0 stevel { 894 0 stevel int ret; 895 0 stevel char_buf_t *cb; 896 0 stevel 897 0 stevel if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) 898 0 stevel return (POC_INVAL); 899 0 stevel if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) == 900 0 stevel PO_FAIL) { 901 0 stevel free_char_buf(cb); 902 0 stevel return (POC_INVAL); 903 0 stevel } 904 0 stevel ret = pool_get_property(TO_CONF(pe), pe, cb->cb_buf, val); 905 0 stevel free_char_buf(cb); 906 0 stevel return (ret); 907 0 stevel } 908 0 stevel 909 0 stevel /* 910 0 stevel * Update the specified property value. 911 0 stevel * 912 0 stevel * PO_FAIL is returned if an error is detected and the error code is updated 913 0 stevel * to indicate the cause of the error. 914 0 stevel */ 915 0 stevel int 916 0 stevel pool_put_property(pool_conf_t *conf, pool_elem_t *pe, const char *name, 917 0 stevel const pool_value_t *val) 918 0 stevel { 919 0 stevel const pool_prop_t *prop_info; 920 0 stevel 921 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 922 0 stevel return (PO_FAIL); 923 0 stevel 924 0 stevel if (TO_CONF(pe) != conf) { 925 0 stevel pool_seterror(POE_BADPARAM); 926 0 stevel return (NULL); 927 0 stevel } 928 0 stevel 929 3247 gjelinek /* Don't allow (re)setting of the "temporary" property */ 930 3247 gjelinek if (!is_valid_prop_name(name) || strstr(name, ".temporary") != NULL) { 931 0 stevel pool_seterror(POE_BADPARAM); 932 0 stevel return (PO_FAIL); 933 0 stevel } 934 3247 gjelinek 935 3247 gjelinek /* Don't allow rename of temporary pools/resources */ 936 3247 gjelinek if (strstr(name, ".name") != NULL && elem_is_tmp(pe)) { 937 3247 gjelinek boolean_t rename = B_TRUE; 938 3247 gjelinek pool_value_t *pv = pool_value_alloc(); 939 3247 gjelinek 940 3247 gjelinek if (pe->pe_get_prop(pe, name, pv) != POC_INVAL) { 941 3247 gjelinek const char *s1 = NULL; 942 3247 gjelinek const char *s2 = NULL; 943 3247 gjelinek 944 3247 gjelinek (void) pool_value_get_string(pv, &s1); 945 3247 gjelinek (void) pool_value_get_string(val, &s2); 946 3247 gjelinek if (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0) 947 3247 gjelinek rename = B_FALSE; 948 3247 gjelinek } 949 3247 gjelinek pool_value_free(pv); 950 3247 gjelinek 951 3247 gjelinek if (rename) { 952 3247 gjelinek pool_seterror(POE_BADPARAM); 953 3247 gjelinek return (PO_FAIL); 954 3247 gjelinek } 955 3247 gjelinek } 956 3247 gjelinek 957 0 stevel /* 958 0 stevel * Check to see if this is a property we are managing. If it is, 959 0 stevel * ensure that we are happy with what the user is doing. 960 0 stevel */ 961 0 stevel if ((prop_info = provider_get_prop(pe, name)) != NULL) { 962 0 stevel if (prop_is_readonly(prop_info) == PO_TRUE) { 963 0 stevel pool_seterror(POE_BADPARAM); 964 0 stevel return (PO_FAIL); 965 0 stevel } 966 0 stevel if (prop_info->pp_op.ppo_set_value && 967 0 stevel prop_info->pp_op.ppo_set_value(pe, val) == PO_FAIL) 968 0 stevel return (PO_FAIL); 969 0 stevel } 970 0 stevel 971 0 stevel return (pe->pe_put_prop(pe, name, val)); 972 3247 gjelinek } 973 3247 gjelinek 974 3247 gjelinek /* 975 3247 gjelinek * Set temporary property to flag as a temporary element. 976 3247 gjelinek * 977 3247 gjelinek * PO_FAIL is returned if an error is detected and the error code is updated 978 3247 gjelinek * to indicate the cause of the error. 979 3247 gjelinek */ 980 3247 gjelinek int 981 3247 gjelinek pool_set_temporary(pool_conf_t *conf, pool_elem_t *pe) 982 3247 gjelinek { 983 3247 gjelinek int res; 984 3247 gjelinek char name[128]; 985 3247 gjelinek pool_value_t *val; 986 3247 gjelinek 987 3247 gjelinek if (pool_conf_check(conf) != PO_SUCCESS) 988 3247 gjelinek return (PO_FAIL); 989 3247 gjelinek 990 3247 gjelinek if (TO_CONF(pe) != conf) { 991 3247 gjelinek pool_seterror(POE_BADPARAM); 992 3247 gjelinek return (PO_FAIL); 993 3247 gjelinek } 994 3247 gjelinek 995 3247 gjelinek /* create property name based on element type */ 996 3247 gjelinek if (snprintf(name, sizeof (name), "%s.temporary", 997 3247 gjelinek pool_elem_class_string(pe)) > sizeof (name)) { 998 3247 gjelinek pool_seterror(POE_SYSTEM); 999 3247 gjelinek return (PO_FAIL); 1000 3247 gjelinek } 1001 3247 gjelinek 1002 3247 gjelinek if ((val = pool_value_alloc()) == NULL) 1003 3247 gjelinek return (PO_FAIL); 1004 3247 gjelinek 1005 3247 gjelinek pool_value_set_bool(val, (uchar_t)1); 1006 3247 gjelinek 1007 3247 gjelinek res = pe->pe_put_prop(pe, name, val); 1008 3247 gjelinek 1009 3247 gjelinek pool_value_free(val); 1010 3247 gjelinek 1011 3247 gjelinek return (res); 1012 0 stevel } 1013 0 stevel 1014 0 stevel /* 1015 0 stevel * Update the specified property value with the namespace prepended. 1016 0 stevel * e.g. If this function is used to update the property "name" on a pool, it 1017 0 stevel * will attempt to update "pool.name". 1018 0 stevel * 1019 0 stevel * PO_FAIL is returned if an error is detected and the error code is updated 1020 0 stevel * to indicate the cause of the error. 1021 0 stevel */ 1022 0 stevel int 1023 0 stevel pool_put_ns_property(pool_elem_t *pe, const char *name, 1024 0 stevel const pool_value_t *val) 1025 0 stevel { 1026 0 stevel char_buf_t *cb; 1027 0 stevel int ret; 1028 0 stevel 1029 0 stevel if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) 1030 0 stevel return (PO_FAIL); 1031 0 stevel if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) == 1032 0 stevel PO_FAIL) { 1033 0 stevel free_char_buf(cb); 1034 0 stevel return (PO_FAIL); 1035 0 stevel } 1036 0 stevel ret = pool_put_property(TO_CONF(pe), pe, cb->cb_buf, val); 1037 0 stevel free_char_buf(cb); 1038 0 stevel return (ret); 1039 0 stevel } 1040 0 stevel 1041 0 stevel /* 1042 0 stevel * Update the specified property value. Do not use the property 1043 0 stevel * protection mechanism. This function should only be used for cases 1044 0 stevel * where the library must bypass the normal property protection 1045 0 stevel * mechanism. The only known use is to update properties in the static 1046 0 stevel * configuration when performing a commit. 1047 0 stevel * 1048 0 stevel * PO_FAIL is returned if an error is detected and the error code is 1049 0 stevel * updated to indicate the cause of the error. 1050 0 stevel */ 1051 0 stevel int 1052 0 stevel pool_put_any_property(pool_elem_t *pe, const char *name, 1053 0 stevel const pool_value_t *val) 1054 0 stevel { 1055 0 stevel if (!is_valid_prop_name(name)) { 1056 0 stevel pool_seterror(POE_BADPARAM); 1057 0 stevel return (PO_FAIL); 1058 0 stevel } 1059 0 stevel 1060 0 stevel return (pe->pe_put_prop(pe, name, val)); 1061 0 stevel } 1062 0 stevel 1063 0 stevel /* 1064 0 stevel * Update the specified property value with the namespace prepended. 1065 0 stevel * e.g. If this function is used to update the property "name" on a pool, it 1066 0 stevel * will attempt to update "pool.name". 1067 0 stevel * 1068 0 stevel * PO_FAIL is returned if an error is detected and the error code is updated 1069 0 stevel * to indicate the cause of the error. 1070 0 stevel */ 1071 0 stevel int 1072 0 stevel pool_put_any_ns_property(pool_elem_t *pe, const char *name, 1073 0 stevel const pool_value_t *val) 1074 0 stevel { 1075 0 stevel char_buf_t *cb; 1076 0 stevel int ret; 1077 0 stevel 1078 0 stevel if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) 1079 0 stevel return (PO_FAIL); 1080 0 stevel if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) == 1081 0 stevel PO_FAIL) { 1082 0 stevel free_char_buf(cb); 1083 0 stevel return (PO_FAIL); 1084 0 stevel } 1085 0 stevel ret = pool_put_any_property(pe, cb->cb_buf, val); 1086 0 stevel free_char_buf(cb); 1087 0 stevel return (ret); 1088 0 stevel } 1089 0 stevel 1090 0 stevel /* 1091 0 stevel * Remove the specified property value. Note that some properties are 1092 0 stevel * mandatory and thus failure to remove these properties is inevitable. 1093 0 stevel * PO_FAIL is returned if an error is detected and the error code is updated 1094 0 stevel * to indicate the cause of the error. 1095 0 stevel */ 1096 0 stevel int 1097 0 stevel pool_rm_property(pool_conf_t *conf, pool_elem_t *pe, const char *name) 1098 0 stevel { 1099 0 stevel const pool_prop_t *prop_info; 1100 0 stevel 1101 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 1102 0 stevel return (PO_FAIL); 1103 0 stevel 1104 0 stevel if (TO_CONF(pe) != conf) { 1105 0 stevel pool_seterror(POE_BADPARAM); 1106 0 stevel return (NULL); 1107 0 stevel } 1108 0 stevel 1109 3247 gjelinek /* Don't allow removal of the "temporary" property */ 1110 3247 gjelinek if (strstr(name, ".temporary") != NULL) { 1111 3247 gjelinek pool_seterror(POE_BADPARAM); 1112 3247 gjelinek return (PO_FAIL); 1113 3247 gjelinek } 1114 3247 gjelinek 1115 0 stevel /* 1116 0 stevel * Check to see if this is a property we are managing. If it is, 1117 0 stevel * ensure that we are happy with what the user is doing. 1118 0 stevel */ 1119 0 stevel if ((prop_info = provider_get_prop(pe, name)) != NULL) { 1120 0 stevel if (prop_is_optional(prop_info) == PO_FALSE) { 1121 0 stevel pool_seterror(POE_BADPARAM); 1122 0 stevel return (PO_FAIL); 1123 0 stevel } 1124 0 stevel } 1125 0 stevel return (pe->pe_rm_prop(pe, name)); 1126 0 stevel } 1127 0 stevel 1128 0 stevel /* 1129 0 stevel * Check if the supplied name is a namespace protected property for the supplied 1130 0 stevel * element, pe. If it is, return the prefix, otherwise just return NULL. 1131 0 stevel */ 1132 0 stevel const char * 1133 0 stevel is_ns_property(const pool_elem_t *pe, const char *name) 1134 0 stevel { 1135 0 stevel const char *prefix; 1136 0 stevel 1137 0 stevel if ((prefix = pool_elem_class_string(pe)) != NULL) { 1138 0 stevel if (strncmp(name, prefix, strlen(prefix)) == 0) 1139 0 stevel return (prefix); 1140 0 stevel } 1141 0 stevel return (NULL); 1142 0 stevel } 1143 0 stevel 1144 0 stevel /* 1145 0 stevel * Check if the supplied name is a namespace protected property for the supplied 1146 0 stevel * element, pe. If it is, return the property name with the namespace stripped, 1147 0 stevel * otherwise just return the name. 1148 0 stevel */ 1149 0 stevel const char * 1150 0 stevel property_name_minus_ns(const pool_elem_t *pe, const char *name) 1151 0 stevel { 1152 0 stevel const char *prefix; 1153 0 stevel if ((prefix = is_ns_property(pe, name)) != NULL) { 1154 0 stevel return (name + strlen(prefix) + 1); 1155 0 stevel } 1156 0 stevel return (name); 1157 0 stevel } 1158 0 stevel 1159 0 stevel /* 1160 0 stevel * Create an element to represent a pool and add it to the supplied 1161 0 stevel * configuration. 1162 0 stevel */ 1163 0 stevel pool_t * 1164 0 stevel pool_create(pool_conf_t *conf, const char *name) 1165 0 stevel { 1166 0 stevel pool_elem_t *pe; 1167 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1168 0 stevel const pool_prop_t *default_props; 1169 0 stevel 1170 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 1171 0 stevel return (NULL); 1172 0 stevel 1173 0 stevel if (!is_valid_name(name) || pool_get_pool(conf, name) != NULL) { 1174 0 stevel /* 1175 0 stevel * A pool with the same name exists. Reject. 1176 0 stevel */ 1177 0 stevel pool_seterror(POE_BADPARAM); 1178 0 stevel return (NULL); 1179 0 stevel } 1180 0 stevel if ((pe = conf->pc_prov->pc_elem_create(conf, PEC_POOL, PREC_INVALID, 1181 0 stevel PCEC_INVALID)) == NULL) { 1182 0 stevel pool_seterror(POE_INVALID_CONF); 1183 0 stevel return (NULL); 1184 0 stevel } 1185 0 stevel if ((default_props = provider_get_props(pe)) != NULL) { 1186 0 stevel int i; 1187 0 stevel for (i = 0; default_props[i].pp_pname != NULL; i++) { 1188 0 stevel if (prop_is_init(&default_props[i]) && 1189 0 stevel (pool_put_any_property(pe, 1190 0 stevel default_props[i].pp_pname, 1191 0 stevel &default_props[i].pp_value) == PO_FAIL)) { 1192 0 stevel (void) pool_destroy(conf, pool_elem_pool(pe)); 1193 0 stevel return (NULL); 1194 0 stevel } 1195 0 stevel } 1196 0 stevel } 1197 0 stevel if (pool_value_set_string(&val, name) != PO_SUCCESS) { 1198 0 stevel (void) pool_destroy(conf, pool_elem_pool(pe)); 1199 0 stevel pool_seterror(POE_SYSTEM); 1200 0 stevel return (NULL); 1201 0 stevel } 1202 0 stevel if (pool_put_property(conf, pe, "pool.name", &val) == PO_FAIL) { 1203 0 stevel (void) pool_destroy(conf, pool_elem_pool(pe)); 1204 0 stevel pool_seterror(POE_PUTPROP); 1205 0 stevel return (NULL); 1206 0 stevel } 1207 3247 gjelinek 1208 3247 gjelinek /* 1209 3247 gjelinek * If we are creating a temporary pool configuration, flag the pool. 1210 3247 gjelinek */ 1211 3247 gjelinek if (conf->pc_prov->pc_oflags & PO_TEMP) { 1212 3247 gjelinek if (pool_set_temporary(conf, pe) == PO_FAIL) { 1213 3247 gjelinek (void) pool_destroy(conf, pool_elem_pool(pe)); 1214 3247 gjelinek return (NULL); 1215 3247 gjelinek } 1216 3247 gjelinek } 1217 3247 gjelinek 1218 0 stevel return (pool_elem_pool(pe)); 1219 0 stevel } 1220 0 stevel 1221 0 stevel /* 1222 0 stevel * Create an element to represent a res. 1223 0 stevel */ 1224 0 stevel pool_resource_t * 1225 0 stevel pool_resource_create(pool_conf_t *conf, const char *sz_type, const char *name) 1226 0 stevel { 1227 0 stevel pool_elem_t *pe; 1228 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1229 0 stevel const pool_prop_t *default_props; 1230 0 stevel pool_resource_t **resources; 1231 0 stevel int is_default = 0; 1232 0 stevel uint_t nelem; 1233 0 stevel pool_elem_class_t elem_class; 1234 0 stevel pool_resource_elem_class_t type; 1235 0 stevel pool_value_t *props[] = { NULL, NULL }; 1236 0 stevel 1237 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 1238 0 stevel return (NULL); 1239 0 stevel 1240 0 stevel if ((type = pool_resource_elem_class_from_string(sz_type)) == 1241 0 stevel PREC_INVALID) { 1242 0 stevel pool_seterror(POE_BADPARAM); 1243 0 stevel return (NULL); 1244 0 stevel } 1245 0 stevel 1246 0 stevel if (strcmp(sz_type, "pset") != 0) { 1247 0 stevel pool_seterror(POE_BADPARAM); 1248 0 stevel return (NULL); 1249 0 stevel } 1250 0 stevel 1251 0 stevel if (!is_valid_name(name) || pool_get_resource(conf, sz_type, name) != 1252 0 stevel NULL) { 1253 0 stevel /* 1254 0 stevel * Resources must be unique by name+type. 1255 0 stevel */ 1256 0 stevel pool_seterror(POE_BADPARAM); 1257 0 stevel return (NULL); 1258 0 stevel } 1259 0 stevel 1260 0 stevel props[0] = &val; 1261 0 stevel 1262 0 stevel if (pool_value_set_string(props[0], sz_type) != PO_SUCCESS || 1263 0 stevel pool_value_set_name(props[0], c_type) != PO_SUCCESS) { 1264 0 stevel return (NULL); 1265 0 stevel } 1266 0 stevel 1267 0 stevel if ((resources = pool_query_resources(conf, &nelem, props)) == NULL) { 1268 0 stevel /* 1269 0 stevel * This is the first representative of this type; when it's 1270 0 stevel * created it should be created with 'default' = 'true'. 1271 0 stevel */ 1272 0 stevel is_default = 1; 1273 0 stevel } else { 1274 0 stevel free(resources); 1275 0 stevel } 1276 0 stevel /* 1277 0 stevel * TODO: If Additional PEC_RES_COMP types are added to 1278 0 stevel * pool_impl.h, this would need to be extended. 1279 0 stevel */ 1280 0 stevel switch (type) { 1281 0 stevel case PREC_PSET: 1282 0 stevel elem_class = PEC_RES_COMP; 1283 0 stevel break; 1284 0 stevel default: 1285 0 stevel elem_class = PEC_RES_AGG; 1286 0 stevel break; 1287 0 stevel } 1288 0 stevel if ((pe = conf->pc_prov->pc_elem_create(conf, elem_class, type, 1289 0 stevel PCEC_INVALID)) == NULL) { 1290 0 stevel pool_seterror(POE_INVALID_CONF); 1291 0 stevel return (NULL); 1292 0 stevel } 1293 0 stevel 1294 0 stevel /* 1295 0 stevel * The plugins contain a list of default properties and their values 1296 0 stevel * for resources. The resource returned, hence, is fully initialized. 1297 0 stevel */ 1298 0 stevel if ((default_props = provider_get_props(pe)) != NULL) { 1299 0 stevel int i; 1300 0 stevel for (i = 0; default_props[i].pp_pname != NULL; i++) { 1301 0 stevel if (prop_is_init(&default_props[i]) && 1302 0 stevel pool_put_any_property(pe, default_props[i].pp_pname, 1303 0 stevel &default_props[i].pp_value) == PO_FAIL) { 1304 0 stevel (void) pool_resource_destroy(conf, 1305 0 stevel pool_elem_res(pe)); 1306 0 stevel return (NULL); 1307 0 stevel } 1308 0 stevel } 1309 0 stevel } 1310 0 stevel if (pool_value_set_string(&val, name) != PO_SUCCESS || 1311 0 stevel pool_put_ns_property(pe, "name", &val) != PO_SUCCESS) { 1312 0 stevel (void) pool_resource_destroy(conf, pool_elem_res(pe)); 1313 0 stevel return (NULL); 1314 0 stevel } 1315 0 stevel if (is_default) { 1316 0 stevel pool_value_set_bool(&val, PO_TRUE); 1317 0 stevel if (pool_put_any_ns_property(pe, "default", &val) != 1318 0 stevel PO_SUCCESS) { 1319 0 stevel (void) pool_resource_destroy(conf, pool_elem_res(pe)); 1320 0 stevel return (NULL); 1321 0 stevel } 1322 0 stevel } 1323 3247 gjelinek 1324 3247 gjelinek /* 1325 3247 gjelinek * If we are creating a temporary pool configuration, flag the resource. 1326 3247 gjelinek */ 1327 3247 gjelinek if (conf->pc_prov->pc_oflags & PO_TEMP) { 1328 3247 gjelinek if (pool_set_temporary(conf, pe) != PO_SUCCESS) { 1329 3247 gjelinek (void) pool_resource_destroy(conf, pool_elem_res(pe)); 1330 3247 gjelinek return (NULL); 1331 3247 gjelinek } 1332 3247 gjelinek } 1333 3247 gjelinek 1334 0 stevel return (pool_elem_res(pe)); 1335 0 stevel } 1336 0 stevel 1337 0 stevel /* 1338 0 stevel * Create an element to represent a resource component. 1339 0 stevel */ 1340 0 stevel pool_component_t * 1341 0 stevel pool_component_create(pool_conf_t *conf, const pool_resource_t *res, 1342 0 stevel int64_t sys_id) 1343 0 stevel { 1344 0 stevel pool_elem_t *pe; 1345 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1346 0 stevel const pool_prop_t *default_props; 1347 0 stevel char refbuf[KEY_BUFFER_SIZE]; 1348 0 stevel 1349 0 stevel if ((pe = conf->pc_prov->pc_elem_create(conf, PEC_COMP, 1350 0 stevel PREC_INVALID, PCEC_CPU)) == NULL) { 1351 0 stevel pool_seterror(POE_INVALID_CONF); 1352 0 stevel return (NULL); 1353 0 stevel } 1354 0 stevel /* 1355 0 stevel * TODO: If additional PEC_COMP types are added in pool_impl.h, 1356 0 stevel * this would need to be extended. 1357 0 stevel */ 1358 0 stevel pe->pe_component_class = PCEC_CPU; 1359 0 stevel /* Now set the container for this comp */ 1360 0 stevel if (pool_set_container(TO_ELEM(res), pe) == PO_FAIL) { 1361 0 stevel (void) pool_component_destroy(pool_elem_comp(pe)); 1362 0 stevel return (NULL); 1363 0 stevel } 1364 0 stevel /* 1365 0 stevel * The plugins contain a list of default properties and their values 1366 0 stevel * for resources. The resource returned, hence, is fully initialized. 1367 0 stevel */ 1368 0 stevel if ((default_props = provider_get_props(pe)) != NULL) { 1369 0 stevel int i; 1370 0 stevel for (i = 0; default_props[i].pp_pname != NULL; i++) { 1371 0 stevel if (prop_is_init(&default_props[i]) && 1372 0 stevel pool_put_any_property(pe, 1373 0 stevel default_props[i].pp_pname, 1374 0 stevel &default_props[i].pp_value) == PO_FAIL) { 1375 0 stevel (void) pool_component_destroy( 1376 0 stevel pool_elem_comp(pe)); 1377 0 stevel return (NULL); 1378 0 stevel } 1379 0 stevel } 1380 0 stevel } 1381 0 stevel /* 1382 0 stevel * Set additional attributes/properties on component. 1383 0 stevel */ 1384 0 stevel pool_value_set_int64(&val, sys_id); 1385 0 stevel if (pool_put_any_ns_property(pe, c_sys_prop, &val) != PO_SUCCESS) { 1386 0 stevel (void) pool_component_destroy(pool_elem_comp(pe)); 1387 0 stevel return (NULL); 1388 0 stevel } 1389 0 stevel if (snprintf(refbuf, KEY_BUFFER_SIZE, "%s_%lld", 1390 0 stevel pool_elem_class_string(pe), sys_id) > KEY_BUFFER_SIZE) { 1391 0 stevel (void) pool_component_destroy(pool_elem_comp(pe)); 1392 0 stevel return (NULL); 1393 0 stevel } 1394 0 stevel if (pool_value_set_string(&val, refbuf) != PO_SUCCESS) { 1395 0 stevel (void) pool_component_destroy(pool_elem_comp(pe)); 1396 0 stevel return (NULL); 1397 0 stevel } 1398 0 stevel if (pool_put_any_ns_property(pe, c_ref_id, &val) != PO_SUCCESS) { 1399 0 stevel (void) pool_component_destroy(pool_elem_comp(pe)); 1400 0 stevel return (NULL); 1401 0 stevel } 1402 0 stevel return (pool_elem_comp(pe)); 1403 0 stevel } 1404 0 stevel 1405 0 stevel /* 1406 0 stevel * Return the location of a configuration. 1407 0 stevel */ 1408 0 stevel const char * 1409 0 stevel pool_conf_location(const pool_conf_t *conf) 1410 0 stevel { 1411 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1412 0 stevel pool_seterror(POE_BADPARAM); 1413 0 stevel return (NULL); 1414 0 stevel } 1415 0 stevel return (conf->pc_location); 1416 0 stevel } 1417 0 stevel /* 1418 0 stevel * Close a configuration, freeing all associated resources. Once a 1419 0 stevel * configuration is closed, it can no longer be used. 1420 0 stevel */ 1421 0 stevel int 1422 0 stevel pool_conf_close(pool_conf_t *conf) 1423 0 stevel { 1424 0 stevel int rv; 1425 0 stevel 1426 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1427 0 stevel pool_seterror(POE_BADPARAM); 1428 0 stevel return (PO_FAIL); 1429 0 stevel } 1430 0 stevel rv = conf->pc_prov->pc_close(conf); 1431 0 stevel conf->pc_prov = NULL; 1432 0 stevel free((void *)conf->pc_location); 1433 0 stevel conf->pc_location = NULL; 1434 0 stevel conf->pc_state = POF_INVALID; 1435 0 stevel return (rv); 1436 0 stevel } 1437 0 stevel 1438 0 stevel /* 1439 0 stevel * Remove a configuration, freeing all associated resources. Once a 1440 0 stevel * configuration is removed, it can no longer be accessed and is forever 1441 0 stevel * gone. 1442 0 stevel */ 1443 0 stevel int 1444 0 stevel pool_conf_remove(pool_conf_t *conf) 1445 0 stevel { 1446 0 stevel int rv; 1447 0 stevel 1448 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1449 0 stevel pool_seterror(POE_BADPARAM); 1450 0 stevel return (PO_FAIL); 1451 0 stevel } 1452 0 stevel rv = conf->pc_prov->pc_remove(conf); 1453 0 stevel conf->pc_state = POF_INVALID; 1454 0 stevel return (rv); 1455 0 stevel } 1456 0 stevel 1457 0 stevel /* 1458 0 stevel * pool_conf_alloc() allocate the resources to represent a configuration. 1459 0 stevel */ 1460 0 stevel pool_conf_t * 1461 0 stevel pool_conf_alloc(void) 1462 0 stevel { 1463 0 stevel pool_conf_t *conf; 1464 0 stevel 1465 0 stevel if ((conf = calloc(1, sizeof (pool_conf_t))) == NULL) { 1466 0 stevel pool_seterror(POE_SYSTEM); 1467 0 stevel return (NULL); 1468 0 stevel } 1469 0 stevel conf->pc_state = POF_INVALID; 1470 0 stevel return (conf); 1471 0 stevel } 1472 0 stevel 1473 0 stevel /* 1474 0 stevel * pool_conf_free() frees the resources associated with a configuration. 1475 0 stevel */ 1476 0 stevel void 1477 0 stevel pool_conf_free(pool_conf_t *conf) 1478 0 stevel { 1479 0 stevel free(conf); 1480 0 stevel } 1481 0 stevel 1482 0 stevel /* 1483 0 stevel * pool_conf_open() opens a configuration, establishing all required 1484 0 stevel * connections to the data source. 1485 0 stevel */ 1486 0 stevel int 1487 0 stevel pool_conf_open(pool_conf_t *conf, const char *location, int oflags) 1488 0 stevel { 1489 0 stevel /* 1490 0 stevel * Since you can't do anything to a pool configuration without opening 1491 0 stevel * it, this represents a good point to intialise structures that would 1492 0 stevel * otherwise need to be initialised in a .init section. 1493 0 stevel */ 1494 0 stevel internal_init(); 1495 0 stevel 1496 0 stevel if (pool_conf_status(conf) != POF_INVALID) { 1497 0 stevel /* 1498 0 stevel * Already opened configuration, return PO_FAIL 1499 0 stevel */ 1500 0 stevel pool_seterror(POE_BADPARAM); 1501 0 stevel return (PO_FAIL); 1502 0 stevel } 1503 3247 gjelinek if (oflags & ~(PO_RDONLY | PO_RDWR | PO_CREAT | PO_DISCO | PO_UPDATE | 1504 3247 gjelinek PO_TEMP)) { 1505 0 stevel pool_seterror(POE_BADPARAM); 1506 0 stevel return (PO_FAIL); 1507 0 stevel } 1508 0 stevel 1509 0 stevel /* 1510 0 stevel * Creating a configuration implies read-write access, so make 1511 0 stevel * sure that PO_RDWR is set in addition if PO_CREAT is set. 1512 0 stevel */ 1513 0 stevel if (oflags & PO_CREAT) 1514 0 stevel oflags |= PO_RDWR; 1515 0 stevel 1516 3247 gjelinek /* location is ignored when creating a temporary configuration */ 1517 3247 gjelinek if (oflags & PO_TEMP) 1518 3247 gjelinek location = ""; 1519 3247 gjelinek 1520 0 stevel if ((conf->pc_location = strdup(location)) == NULL) { 1521 0 stevel pool_seterror(POE_SYSTEM); 1522 0 stevel return (PO_FAIL); 1523 0 stevel } 1524 0 stevel /* 1525 0 stevel * This is the crossover point into the actual data provider 1526 0 stevel * implementation, allocate a data provider of the appropriate 1527 3247 gjelinek * type for your data storage medium. In this case it's either a kernel 1528 3247 gjelinek * or xml data provider. To use a different data provider, write some 1529 3247 gjelinek * code to implement all the required interfaces and then change the 1530 3247 gjelinek * following code to allocate a data provider which uses your new code. 1531 3247 gjelinek * All data provider routines can be static, apart from the allocation 1532 3247 gjelinek * routine. 1533 3247 gjelinek * 1534 3247 gjelinek * For temporary pools (PO_TEMP) we start with a copy of the current 1535 3247 gjelinek * dynamic configuration and do all of the updates in-memory. 1536 0 stevel */ 1537 3247 gjelinek if (oflags & PO_TEMP) { 1538 3247 gjelinek if (pool_knl_connection_alloc(conf, PO_TEMP) != PO_SUCCESS) { 1539 3247 gjelinek conf->pc_state = POF_INVALID; 1540 3247 gjelinek return (PO_FAIL); 1541 3247 gjelinek } 1542 3247 gjelinek /* set rdwr flag so we can updated the in-memory config. */ 1543 3247 gjelinek conf->pc_prov->pc_oflags |= PO_RDWR; 1544 3247 gjelinek 1545 3247 gjelinek } else if (strcmp(location, pool_dynamic_location()) == 0) { 1546 0 stevel if (pool_knl_connection_alloc(conf, oflags) != PO_SUCCESS) { 1547 0 stevel conf->pc_state = POF_INVALID; 1548 0 stevel return (PO_FAIL); 1549 0 stevel } 1550 0 stevel } else { 1551 0 stevel if (pool_xml_connection_alloc(conf, oflags) != PO_SUCCESS) { 1552 0 stevel conf->pc_state = POF_INVALID; 1553 0 stevel return (PO_FAIL); 1554 0 stevel } 1555 0 stevel } 1556 0 stevel return (PO_SUCCESS); 1557 0 stevel } 1558 0 stevel 1559 0 stevel /* 1560 0 stevel * Rollback a configuration. This will undo all changes to the configuration 1561 0 stevel * since the last time pool_conf_commit was called. 1562 0 stevel */ 1563 0 stevel int 1564 0 stevel pool_conf_rollback(pool_conf_t *conf) 1565 0 stevel { 1566 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1567 0 stevel pool_seterror(POE_BADPARAM); 1568 0 stevel return (PO_FAIL); 1569 0 stevel } 1570 0 stevel return (conf->pc_prov->pc_rollback(conf)); 1571 0 stevel } 1572 0 stevel 1573 0 stevel /* 1574 0 stevel * Commit a configuration. This will apply all changes to the 1575 0 stevel * configuration to the permanent data store. The active parameter 1576 0 stevel * indicates whether the configuration should be used to update the 1577 0 stevel * dynamic configuration from the supplied (static) configuration or 1578 0 stevel * whether it should be written back to persistent store. 1579 0 stevel */ 1580 0 stevel int 1581 0 stevel pool_conf_commit(pool_conf_t *conf, int active) 1582 0 stevel { 1583 0 stevel int retval; 1584 0 stevel 1585 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1586 0 stevel pool_seterror(POE_BADPARAM); 1587 0 stevel return (PO_FAIL); 1588 0 stevel } 1589 0 stevel if (active) { 1590 0 stevel int oflags; 1591 0 stevel 1592 0 stevel if (conf_is_dynamic(conf) == PO_TRUE) { 1593 0 stevel pool_seterror(POE_BADPARAM); 1594 0 stevel return (PO_FAIL); 1595 0 stevel } 1596 0 stevel /* 1597 0 stevel * Pretend that the configuration was opened PO_RDWR 1598 0 stevel * so that a configuration which was opened PO_RDONLY 1599 0 stevel * can be committed. The original flags are preserved 1600 0 stevel * in oflags and restored after pool_conf_commit_sys() 1601 0 stevel * returns. 1602 0 stevel */ 1603 0 stevel oflags = conf->pc_prov->pc_oflags; 1604 0 stevel conf->pc_prov->pc_oflags |= PO_RDWR; 1605 0 stevel retval = pool_conf_commit_sys(conf, active); 1606 0 stevel conf->pc_prov->pc_oflags = oflags; 1607 0 stevel } else { 1608 0 stevel /* 1609 0 stevel * Write the configuration back to the backing store. 1610 0 stevel */ 1611 0 stevel retval = conf->pc_prov->pc_commit(conf); 1612 0 stevel } 1613 0 stevel return (retval); 1614 0 stevel } 1615 0 stevel 1616 0 stevel /* 1617 0 stevel * Export a configuration. This will export a configuration in the specified 1618 0 stevel * format (fmt) to the specified location. 1619 0 stevel */ 1620 0 stevel int 1621 0 stevel pool_conf_export(const pool_conf_t *conf, const char *location, 1622 0 stevel pool_export_format_t fmt) 1623 0 stevel { 1624 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1625 0 stevel pool_seterror(POE_BADPARAM); 1626 0 stevel return (PO_FAIL); 1627 0 stevel } 1628 0 stevel return (conf->pc_prov->pc_export(conf, location, fmt)); 1629 0 stevel } 1630 0 stevel 1631 0 stevel /* 1632 0 stevel * Validate a configuration. This will validate a configuration at the 1633 0 stevel * specified level. 1634 0 stevel */ 1635 0 stevel int 1636 0 stevel pool_conf_validate(const pool_conf_t *conf, pool_valid_level_t level) 1637 0 stevel { 1638 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1639 0 stevel pool_seterror(POE_BADPARAM); 1640 0 stevel return (PO_FAIL); 1641 0 stevel } 1642 0 stevel return (conf->pc_prov->pc_validate(conf, level)); 1643 0 stevel } 1644 0 stevel 1645 0 stevel /* 1646 0 stevel * Update the snapshot of a configuration. This can only be used on a 1647 0 stevel * dynamic configuration. 1648 0 stevel */ 1649 0 stevel int 1650 0 stevel pool_conf_update(const pool_conf_t *conf, int *changed) 1651 0 stevel { 1652 0 stevel if (pool_conf_status(conf) == POF_INVALID || 1653 0 stevel conf_is_dynamic(conf) == PO_FALSE) { 1654 0 stevel pool_seterror(POE_BADPARAM); 1655 0 stevel return (PO_FAIL); 1656 0 stevel } 1657 0 stevel /* 1658 0 stevel * Since this function only makes sense for dynamic 1659 0 stevel * configurations, just call directly into the appropriate 1660 0 stevel * function. This could be added into the pool_connection_t 1661 0 stevel * interface if it was ever required. 1662 0 stevel */ 1663 0 stevel if (changed) 1664 0 stevel *changed = 0; 1665 0 stevel return (pool_knl_update((pool_conf_t *)conf, changed)); 1666 0 stevel } 1667 0 stevel 1668 0 stevel /* 1669 0 stevel * Walk the properties of the supplied elem, calling the user supplied 1670 0 stevel * function repeatedly as long as the user function returns 1671 0 stevel * PO_SUCCESS. 1672 0 stevel */ 1673 0 stevel int 1674 0 stevel pool_walk_properties(pool_conf_t *conf, pool_elem_t *elem, void *arg, 1675 0 stevel int (*prop_callback)(pool_conf_t *, pool_elem_t *, const char *, 1676 0 stevel pool_value_t *, void *)) 1677 0 stevel { 1678 0 stevel return (pool_walk_any_properties(conf, elem, arg, prop_callback, 0)); 1679 0 stevel } 1680 0 stevel 1681 0 stevel void 1682 0 stevel free_value_list(int npvals, pool_value_t **pvals) 1683 0 stevel { 1684 0 stevel int j; 1685 0 stevel 1686 0 stevel for (j = 0; j < npvals; j++) { 1687 0 stevel if (pvals[j]) 1688 0 stevel pool_value_free(pvals[j]); 1689 0 stevel } 1690 0 stevel free(pvals); 1691 0 stevel } 1692 0 stevel 1693 0 stevel /* 1694 0 stevel * Walk the properties of the supplied elem, calling the user supplied 1695 0 stevel * function repeatedly as long as the user function returns 1696 0 stevel * PO_SUCCESS. 1697 0 stevel * The list of properties to be walked is retrieved from the element 1698 0 stevel */ 1699 0 stevel int 1700 0 stevel pool_walk_any_properties(pool_conf_t *conf, pool_elem_t *elem, void *arg, 1701 0 stevel int (*prop_callback)(pool_conf_t *, pool_elem_t *, const char *, 1702 0 stevel pool_value_t *, void *), int any) 1703 0 stevel { 1704 0 stevel pool_value_t **pvals; 1705 0 stevel int i; 1706 0 stevel const pool_prop_t *props = provider_get_props(elem); 1707 0 stevel uint_t npvals; 1708 0 stevel 1709 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1710 0 stevel pool_seterror(POE_BADPARAM); 1711 0 stevel return (PO_FAIL); 1712 0 stevel } 1713 0 stevel 1714 0 stevel if (props == NULL) { 1715 0 stevel pool_seterror(POE_INVALID_CONF); 1716 0 stevel return (PO_FAIL); 1717 0 stevel } 1718 0 stevel 1719 0 stevel if ((pvals = elem->pe_get_props(elem, &npvals)) == NULL) 1720 0 stevel return (PO_FAIL); 1721 0 stevel 1722 0 stevel /* 1723 0 stevel * Now walk the managed properties. As we find managed 1724 0 stevel * properties removed them from the list of all properties to 1725 0 stevel * prevent duplication. 1726 0 stevel */ 1727 0 stevel for (i = 0; props[i].pp_pname != NULL; i++) { 1728 0 stevel int j; 1729 0 stevel 1730 0 stevel /* 1731 0 stevel * Special processing for type 1732 0 stevel */ 1733 0 stevel if (strcmp(props[i].pp_pname, c_type) == 0) { 1734 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1735 0 stevel 1736 0 stevel if (pool_value_set_name(&val, props[i].pp_pname) == 1737 0 stevel PO_FAIL) { 1738 0 stevel free_value_list(npvals, pvals); 1739 0 stevel return (PO_FAIL); 1740 0 stevel } 1741 0 stevel if (props[i].pp_op.ppo_get_value(elem, &val) == 1742 0 stevel PO_FAIL) { 1743 0 stevel free_value_list(npvals, pvals); 1744 0 stevel return (PO_FAIL); 1745 0 stevel } 1746 0 stevel if (any == 1 || prop_is_hidden(&props[i]) == PO_FALSE) { 1747 0 stevel if (prop_callback(conf, elem, props[i].pp_pname, 1748 0 stevel &val, arg) != PO_SUCCESS) { 1749 0 stevel free_value_list(npvals, pvals); 1750 0 stevel pool_seterror(POE_BADPARAM); 1751 0 stevel return (PO_FAIL); 1752 0 stevel } 1753 0 stevel } 1754 0 stevel continue; 1755 0 stevel } 1756 0 stevel 1757 0 stevel for (j = 0; j < npvals; j++) { 1758 0 stevel if (pvals[j] && strcmp(pool_value_get_name(pvals[j]), 1759 0 stevel props[i].pp_pname) == 0) 1760 0 stevel break; 1761 0 stevel } 1762 0 stevel /* 1763 0 stevel * If we have found the property, then j < npvals. Process it 1764 0 stevel * according to our property attributes. Otherwise, it's not 1765 0 stevel * a managed property, so just ignore it until later. 1766 0 stevel */ 1767 0 stevel if (j < npvals) { 1768 0 stevel if (any == 1 || prop_is_hidden(&props[i]) == PO_FALSE) { 1769 0 stevel if (props[i].pp_op.ppo_get_value) { 1770 0 stevel if (pool_value_set_name(pvals[j], 1771 0 stevel props[i].pp_pname) == PO_FAIL) { 1772 0 stevel free_value_list(npvals, pvals); 1773 0 stevel return (PO_FAIL); 1774 0 stevel } 1775 0 stevel if (props[i].pp_op.ppo_get_value(elem, 1776 0 stevel pvals[j]) == PO_FAIL) { 1777 0 stevel free_value_list(npvals, pvals); 1778 0 stevel return (PO_FAIL); 1779 0 stevel } 1780 0 stevel } 1781 0 stevel if (prop_callback(conf, elem, props[i].pp_pname, 1782 0 stevel pvals[j], arg) != PO_SUCCESS) { 1783 0 stevel free_value_list(npvals, pvals); 1784 0 stevel pool_seterror(POE_BADPARAM); 1785 0 stevel return (PO_FAIL); 1786 0 stevel } 1787 0 stevel } 1788 0 stevel pool_value_free(pvals[j]); 1789 0 stevel pvals[j] = NULL; 1790 0 stevel } 1791 0 stevel } 1792 0 stevel for (i = 0; i < npvals; i++) { 1793 0 stevel if (pvals[i]) { 1794 0 stevel const char *name = pool_value_get_name(pvals[i]); 1795 0 stevel char *qname = strrchr(name, '.'); 1796 0 stevel if ((qname && qname[1] != '_') || 1797 0 stevel (!qname && name[0] != '_')) { 1798 0 stevel if (prop_callback(conf, elem, name, pvals[i], 1799 0 stevel arg) != PO_SUCCESS) { 1800 0 stevel free_value_list(npvals, pvals); 1801 0 stevel pool_seterror(POE_BADPARAM); 1802 0 stevel return (PO_FAIL); 1803 0 stevel } 1804 0 stevel } 1805 0 stevel pool_value_free(pvals[i]); 1806 0 stevel pvals[i] = NULL; 1807 0 stevel } 1808 0 stevel } 1809 0 stevel free(pvals); 1810 0 stevel return (PO_SUCCESS); 1811 0 stevel } 1812 0 stevel 1813 0 stevel /* 1814 0 stevel * Return a pool, searching the supplied configuration for a pool with the 1815 0 stevel * supplied name. The search is case sensitive. 1816 0 stevel */ 1817 0 stevel pool_t * 1818 0 stevel pool_get_pool(const pool_conf_t *conf, const char *name) 1819 0 stevel { 1820 0 stevel pool_value_t *props[] = { NULL, NULL }; 1821 0 stevel pool_t **rs; 1822 0 stevel pool_t *ret; 1823 0 stevel uint_t size = 0; 1824 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1825 0 stevel 1826 0 stevel props[0] = &val; 1827 0 stevel 1828 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1829 0 stevel pool_seterror(POE_BADPARAM); 1830 0 stevel return (NULL); 1831 0 stevel } 1832 0 stevel 1833 0 stevel if (pool_value_set_name(props[0], "pool.name") != PO_SUCCESS || 1834 0 stevel pool_value_set_string(props[0], name) != PO_SUCCESS) { 1835 0 stevel return (NULL); 1836 0 stevel } 1837 0 stevel rs = pool_query_pools(conf, &size, props); 1838 0 stevel if (rs == NULL) { /* Can't find a pool to match the name */ 1839 0 stevel return (NULL); 1840 0 stevel } 1841 0 stevel if (size != 1) { 1842 0 stevel free(rs); 1843 0 stevel pool_seterror(POE_INVALID_CONF); 1844 0 stevel return (NULL); 1845 0 stevel } 1846 0 stevel ret = rs[0]; 1847 0 stevel free(rs); 1848 0 stevel return (ret); 1849 0 stevel } 1850 0 stevel 1851 0 stevel /* 1852 0 stevel * Return a result set of pools, searching the supplied configuration 1853 0 stevel * for pools which match the supplied property criteria. props is a null 1854 0 stevel * terminated list of properties which will be used to match qualifying 1855 0 stevel * pools. size is updated with the size of the pool 1856 0 stevel */ 1857 0 stevel pool_t ** 1858 0 stevel pool_query_pools(const pool_conf_t *conf, uint_t *size, pool_value_t **props) 1859 0 stevel { 1860 0 stevel pool_result_set_t *rs; 1861 0 stevel pool_elem_t *pe; 1862 0 stevel pool_t **result = NULL; 1863 0 stevel int i = 0; 1864 0 stevel 1865 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1866 0 stevel pool_seterror(POE_BADPARAM); 1867 0 stevel return (NULL); 1868 0 stevel } 1869 0 stevel rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_POOL, props); 1870 0 stevel if (rs == NULL) { 1871 0 stevel return (NULL); 1872 0 stevel } 1873 0 stevel if ((*size = pool_rs_count(rs)) == 0) { 1874 0 stevel (void) pool_rs_close(rs); 1875 0 stevel return (NULL); 1876 0 stevel } 1877 0 stevel if ((result = malloc(sizeof (pool_t *) * (*size + 1))) == NULL) { 1878 0 stevel pool_seterror(POE_SYSTEM); 1879 0 stevel (void) pool_rs_close(rs); 1880 0 stevel return (NULL); 1881 0 stevel } 1882 0 stevel (void) memset(result, 0, sizeof (pool_t *) * (*size + 1)); 1883 0 stevel for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) { 1884 0 stevel if (pool_elem_class(pe) != PEC_POOL) { 1885 0 stevel pool_seterror(POE_INVALID_CONF); 1886 0 stevel free(result); 1887 0 stevel (void) pool_rs_close(rs); 1888 0 stevel return (NULL); 1889 0 stevel } 1890 0 stevel result[i++] = pool_elem_pool(pe); 1891 0 stevel } 1892 0 stevel (void) pool_rs_close(rs); 1893 0 stevel return (result); 1894 0 stevel } 1895 0 stevel 1896 0 stevel /* 1897 0 stevel * Return an res, searching the supplied configuration for an res with the 1898 0 stevel * supplied name. The search is case sensitive. 1899 0 stevel */ 1900 0 stevel pool_resource_t * 1901 0 stevel pool_get_resource(const pool_conf_t *conf, const char *sz_type, 1902 0 stevel const char *name) 1903 0 stevel { 1904 0 stevel pool_value_t *props[] = { NULL, NULL, NULL }; 1905 0 stevel pool_resource_t **rs; 1906 0 stevel pool_resource_t *ret; 1907 0 stevel uint_t size = 0; 1908 0 stevel char_buf_t *cb = NULL; 1909 0 stevel pool_value_t val0 = POOL_VALUE_INITIALIZER; 1910 0 stevel pool_value_t val1 = POOL_VALUE_INITIALIZER; 1911 0 stevel 1912 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1913 0 stevel pool_seterror(POE_BADPARAM); 1914 0 stevel return (NULL); 1915 0 stevel } 1916 0 stevel 1917 0 stevel if (sz_type == NULL) { 1918 0 stevel pool_seterror(POE_BADPARAM); 1919 0 stevel return (NULL); 1920 0 stevel } 1921 0 stevel 1922 0 stevel props[0] = &val0; 1923 0 stevel props[1] = &val1; 1924 0 stevel 1925 0 stevel if (pool_value_set_string(props[0], sz_type) != PO_SUCCESS || 1926 0 stevel pool_value_set_name(props[0], c_type) != PO_SUCCESS) 1927 0 stevel return (NULL); 1928 0 stevel 1929 0 stevel if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) { 1930 0 stevel return (NULL); 1931 0 stevel } 1932 0 stevel if (set_char_buf(cb, "%s.name", sz_type) != PO_SUCCESS) { 1933 0 stevel free_char_buf(cb); 1934 0 stevel return (NULL); 1935 0 stevel } 1936 0 stevel if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) { 1937 0 stevel free_char_buf(cb); 1938 0 stevel return (NULL); 1939 0 stevel } 1940 0 stevel if (pool_value_set_string(props[1], name) != PO_SUCCESS) { 1941 0 stevel free_char_buf(cb); 1942 0 stevel return (NULL); 1943 0 stevel } 1944 0 stevel free_char_buf(cb); 1945 0 stevel rs = pool_query_resources(conf, &size, props); 1946 0 stevel if (rs == NULL) { 1947 0 stevel return (NULL); 1948 0 stevel } 1949 0 stevel if (size != 1) { 1950 0 stevel free(rs); 1951 0 stevel pool_seterror(POE_INVALID_CONF); 1952 0 stevel return (NULL); 1953 0 stevel } 1954 0 stevel ret = rs[0]; 1955 0 stevel free(rs); 1956 0 stevel return (ret); 1957 0 stevel } 1958 0 stevel 1959 0 stevel /* 1960 0 stevel * Return a result set of res (actually as pool_elem_ts), searching the 1961 0 stevel * supplied configuration for res which match the supplied property 1962 0 stevel * criteria. props is a null terminated list of properties which will be used 1963 0 stevel * to match qualifying res. 1964 0 stevel */ 1965 0 stevel pool_resource_t ** 1966 0 stevel pool_query_resources(const pool_conf_t *conf, uint_t *size, 1967 0 stevel pool_value_t **props) 1968 0 stevel { 1969 0 stevel pool_result_set_t *rs; 1970 0 stevel pool_elem_t *pe; 1971 0 stevel pool_resource_t **result = NULL; 1972 0 stevel int i = 0; 1973 0 stevel 1974 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 1975 0 stevel pool_seterror(POE_BADPARAM); 1976 0 stevel return (NULL); 1977 0 stevel } 1978 0 stevel 1979 0 stevel *size = 0; 1980 0 stevel 1981 0 stevel rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_RES, props); 1982 0 stevel if (rs == NULL) { 1983 0 stevel return (NULL); 1984 0 stevel } 1985 0 stevel if ((*size = pool_rs_count(rs)) == 0) { 1986 0 stevel (void) pool_rs_close(rs); 1987 0 stevel return (NULL); 1988 0 stevel } 1989 0 stevel if ((result = malloc(sizeof (pool_resource_t *) * (*size + 1))) 1990 0 stevel == NULL) { 1991 0 stevel pool_seterror(POE_SYSTEM); 1992 0 stevel (void) pool_rs_close(rs); 1993 0 stevel return (NULL); 1994 0 stevel } 1995 0 stevel (void) memset(result, 0, sizeof (pool_resource_t *) * (*size + 1)); 1996 0 stevel for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) { 1997 0 stevel if (pool_elem_class(pe) != PEC_RES_COMP && 1998 0 stevel pool_elem_class(pe) != PEC_RES_AGG) { 1999 0 stevel pool_seterror(POE_INVALID_CONF); 2000 0 stevel free(result); 2001 0 stevel (void) pool_rs_close(rs); 2002 0 stevel return (NULL); 2003 0 stevel } 2004 0 stevel result[i++] = pool_elem_res(pe); 2005 0 stevel } 2006 0 stevel (void) pool_rs_close(rs); 2007 0 stevel return (result); 2008 0 stevel } 2009 0 stevel 2010 0 stevel /* 2011 0 stevel * Return a result set of comp (actually as pool_elem_ts), searching the 2012 0 stevel * supplied configuration for comp which match the supplied property 2013 0 stevel * criteria. props is a null terminated list of properties which will be used 2014 0 stevel * to match qualifying comp. 2015 0 stevel */ 2016 0 stevel pool_component_t ** 2017 0 stevel pool_query_components(const pool_conf_t *conf, uint_t *size, 2018 0 stevel pool_value_t **props) 2019 0 stevel { 2020 0 stevel return (pool_query_resource_components(conf, NULL, size, props)); 2021 0 stevel } 2022 0 stevel 2023 0 stevel /* 2024 0 stevel * Destroy a pool. If the pool cannot be found or removed an error is 2025 0 stevel * returned. This is basically a wrapper around pool_elem_remove to ensure 2026 0 stevel * some type safety for the pool subtype. 2027 0 stevel */ 2028 0 stevel int 2029 0 stevel pool_destroy(pool_conf_t *conf, pool_t *pp) 2030 0 stevel { 2031 0 stevel pool_elem_t *pe; 2032 0 stevel 2033 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 2034 0 stevel return (PO_FAIL); 2035 0 stevel 2036 0 stevel pe = TO_ELEM(pp); 2037 0 stevel 2038 0 stevel /* 2039 0 stevel * Cannot destroy the default pool. 2040 0 stevel */ 2041 0 stevel if (elem_is_default(pe) == PO_TRUE) { 2042 0 stevel pool_seterror(POE_BADPARAM); 2043 0 stevel return (PO_FAIL); 2044 0 stevel } 2045 0 stevel if (pool_elem_remove(pe) != PO_SUCCESS) 2046 0 stevel return (PO_FAIL); 2047 0 stevel return (PO_SUCCESS); 2048 0 stevel } 2049 0 stevel 2050 0 stevel /* 2051 0 stevel * Destroy an res. If the res cannot be found or removed an error is 2052 0 stevel * returned. This is basically a wrapper around pool_elem_remove to ensure 2053 0 stevel * some type safety for the res subtype. 2054 0 stevel */ 2055 0 stevel int 2056 0 stevel pool_resource_destroy(pool_conf_t *conf, pool_resource_t *prs) 2057 0 stevel { 2058 0 stevel pool_elem_t *pe; 2059 0 stevel pool_component_t **rl; 2060 0 stevel uint_t res_size; 2061 0 stevel pool_t **pl; 2062 0 stevel uint_t npool; 2063 0 stevel int i; 2064 0 stevel 2065 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 2066 0 stevel return (PO_FAIL); 2067 0 stevel 2068 0 stevel pe = TO_ELEM(prs); 2069 0 stevel 2070 0 stevel if (resource_is_system(prs) == PO_TRUE) { 2071 0 stevel pool_seterror(POE_BADPARAM); 2072 0 stevel return (PO_FAIL); 2073 0 stevel } 2074 0 stevel /* 2075 0 stevel * Walk all the pools and dissociate any pools which are using 2076 0 stevel * this resource. 2077 0 stevel */ 2078 0 stevel if ((pl = pool_query_pools(conf, &npool, NULL)) != NULL) { 2079 0 stevel for (i = 0; i < npool; i++) { 2080 0 stevel pool_resource_t **rl; 2081 0 stevel uint_t nres; 2082 0 stevel int j; 2083 0 stevel 2084 0 stevel if ((rl = pool_query_pool_resources(conf, pl[i], &nres, 2085 0 stevel NULL)) != NULL) { 2086 0 stevel for (j = 0; j < nres; j++) { 2087 0 stevel if (rl[j] == prs) { 2088 0 stevel if (pool_dissociate(conf, pl[i], 2089 0 stevel rl[j]) != PO_SUCCESS) { 2090 0 stevel free(rl); 2091 0 stevel free(pl); 2092 0 stevel return (PO_FAIL); 2093 0 stevel } 2094 0 stevel break; 2095 0 stevel } 2096 0 stevel } 2097 0 stevel free(rl); 2098 0 stevel } 2099 0 stevel } 2100 0 stevel free(pl); 2101 0 stevel } 2102 0 stevel if (pe->pe_class == PEC_RES_COMP) { 2103 0 stevel pool_resource_t *default_set_res; 2104 0 stevel 2105 0 stevel /* 2106 0 stevel * Use the xtransfer option to move comp around 2107 0 stevel */ 2108 0 stevel default_set_res = (pool_resource_t *)get_default_resource(prs); 2109 0 stevel 2110 0 stevel if ((rl = pool_query_resource_components(conf, prs, &res_size, 2111 0 stevel NULL)) != NULL) { 2112 0 stevel int ostate = conf->pc_state; 2113 0 stevel conf->pc_state = POF_DESTROY; 2114 0 stevel if (pool_resource_xtransfer(conf, prs, default_set_res, 2115 0 stevel rl) == PO_FAIL) { 2116 0 stevel free(rl); 2117 0 stevel conf->pc_state = ostate; 2118 0 stevel return (PO_FAIL); 2119 0 stevel } 2120 0 stevel conf->pc_state = ostate; 2121 0 stevel free(rl); 2122 0 stevel } 2123 0 stevel } 2124 0 stevel if (pool_elem_remove(pe) != PO_SUCCESS) 2125 0 stevel return (PO_FAIL); 2126 0 stevel return (PO_SUCCESS); 2127 0 stevel } 2128 0 stevel 2129 0 stevel /* 2130 0 stevel * Destroy a comp. If the comp cannot be found or removed an error is 2131 0 stevel * returned. This is basically a wrapper around pool_elem_remove to ensure 2132 0 stevel * some type safety for the comp subtype. 2133 0 stevel */ 2134 0 stevel int 2135 0 stevel pool_component_destroy(pool_component_t *pr) 2136 0 stevel { 2137 0 stevel pool_elem_t *pe = TO_ELEM(pr); 2138 0 stevel 2139 0 stevel if (pool_elem_remove(pe) != PO_SUCCESS) 2140 0 stevel return (PO_FAIL); 2141 0 stevel return (PO_SUCCESS); 2142 0 stevel } 2143 0 stevel 2144 0 stevel /* 2145 0 stevel * Remove a pool_elem_t from a configuration. This has been "hidden" away as 2146 0 stevel * a static routine since the only elements which are currently being removed 2147 0 stevel * are pools, res & comp and the wrapper functions above provide type-safe 2148 0 stevel * access. However, if there is a need to remove other types of elements 2149 0 stevel * then this could be promoted to pool_impl.h or more wrappers could 2150 0 stevel * be added to pool_impl.h. 2151 0 stevel */ 2152 0 stevel int 2153 0 stevel pool_elem_remove(pool_elem_t *pe) 2154 0 stevel { 2155 0 stevel return (pe->pe_remove(pe)); 2156 0 stevel } 2157 0 stevel 2158 0 stevel /* 2159 0 stevel * Execute a query to search for a qualifying set of elements. 2160 0 stevel */ 2161 0 stevel pool_result_set_t * 2162 0 stevel pool_exec_query(const pool_conf_t *conf, const pool_elem_t *src, 2163 0 stevel const char *src_attr, pool_elem_class_t classes, pool_value_t **props) 2164 0 stevel { 2165 0 stevel return (conf->pc_prov->pc_exec_query(conf, src, src_attr, classes, 2166 0 stevel props)); 2167 0 stevel } 2168 0 stevel 2169 0 stevel /* 2170 0 stevel * Get the next result from a result set of elements. 2171 0 stevel */ 2172 0 stevel pool_elem_t * 2173 0 stevel pool_rs_next(pool_result_set_t *set) 2174 0 stevel { 2175 0 stevel return (set->prs_next(set)); 2176 0 stevel } 2177 0 stevel 2178 0 stevel /* 2179 0 stevel * Get the previous result from a result set of elements. 2180 0 stevel */ 2181 0 stevel pool_elem_t * 2182 0 stevel pool_rs_prev(pool_result_set_t *set) 2183 0 stevel { 2184 0 stevel return (set->prs_prev(set)); 2185 0 stevel } 2186 0 stevel 2187 0 stevel /* 2188 0 stevel * Get the first result from a result set of elements. 2189 0 stevel */ 2190 0 stevel pool_elem_t * 2191 0 stevel pool_rs_first(pool_result_set_t *set) 2192 0 stevel { 2193 0 stevel return (set->prs_first(set)); 2194 0 stevel } 2195 0 stevel 2196 0 stevel /* 2197 0 stevel * Get the last result from a result set of elements. 2198 0 stevel */ 2199 0 stevel pool_elem_t * 2200 0 stevel pool_rs_last(pool_result_set_t *set) 2201 0 stevel { 2202 0 stevel return (set->prs_last(set)); 2203 0 stevel } 2204 0 stevel 2205 0 stevel 2206 0 stevel /* 2207 0 stevel * Get the count for a result set of elements. 2208 0 stevel */ 2209 0 stevel int 2210 0 stevel pool_rs_count(pool_result_set_t *set) 2211 0 stevel { 2212 0 stevel return (set->prs_count(set)); 2213 0 stevel } 2214 0 stevel 2215 0 stevel /* 2216 0 stevel * Get the index for a result set of elements. 2217 0 stevel */ 2218 0 stevel int 2219 0 stevel pool_rs_get_index(pool_result_set_t *set) 2220 0 stevel { 2221 0 stevel return (set->prs_get_index(set)); 2222 0 stevel } 2223 0 stevel 2224 0 stevel /* 2225 0 stevel * Set the index for a result set of elements. 2226 0 stevel */ 2227 0 stevel int 2228 0 stevel pool_rs_set_index(pool_result_set_t *set, int index) 2229 0 stevel { 2230 0 stevel return (set->prs_set_index(set, index)); 2231 0 stevel } 2232 0 stevel 2233 0 stevel /* 2234 0 stevel * Close a result set of elements, freeing all associated resources. 2235 0 stevel */ 2236 0 stevel int 2237 0 stevel pool_rs_close(pool_result_set_t *set) 2238 0 stevel { 2239 0 stevel return (set->prs_close(set)); 2240 0 stevel } 2241 0 stevel 2242 0 stevel /* 2243 0 stevel * When transferring resource components using pool_resource_transfer, 2244 0 stevel * this function is invoked to choose which actual components will be 2245 0 stevel * transferred. 2246 0 stevel */ 2247 0 stevel int 2248 0 stevel choose_components(pool_resource_t *src, pool_resource_t *dst, uint64_t size) 2249 0 stevel { 2250 0 stevel pool_component_t **components = NULL, *moved[] = { NULL, NULL }; 2251 0 stevel int i; 2252 0 stevel uint_t ncomponent; 2253 0 stevel pool_conf_t *conf = TO_CONF(TO_ELEM(src)); 2254 0 stevel 2255 0 stevel if (size == 0) 2256 0 stevel return (PO_SUCCESS); 2257 0 stevel /* 2258 0 stevel * Get the component list from our src component. 2259 0 stevel */ 2260 0 stevel if ((components = pool_query_resource_components(conf, src, &ncomponent, 2261 0 stevel NULL)) == NULL) { 2262 0 stevel pool_seterror(POE_BADPARAM); 2263 0 stevel return (PO_FAIL); 2264 0 stevel } 2265 0 stevel qsort(components, ncomponent, sizeof (pool_elem_t *), 2266 0 stevel qsort_elem_compare); 2267 0 stevel /* 2268 0 stevel * Components that aren't specifically requested by the resource 2269 0 stevel * should be transferred out first. 2270 0 stevel */ 2271 0 stevel for (i = 0; size > 0 && components[i] != NULL; i++) { 2272 0 stevel if (!cpu_is_requested(components[i])) { 2273 0 stevel moved[0] = components[i]; 2274 0 stevel if (pool_resource_xtransfer(conf, src, dst, moved) == 2275 0 stevel PO_SUCCESS) { 2276 0 stevel size--; 2277 0 stevel } 2278 0 stevel } 2279 0 stevel } 2280 0 stevel 2281 0 stevel /* 2282 0 stevel * If we couldn't find enough "un-requested" components, select random 2283 0 stevel * requested components. 2284 0 stevel */ 2285 0 stevel for (i = 0; size > 0 && components[i] != NULL; i++) { 2286 0 stevel if (cpu_is_requested(components[i])) { 2287 0 stevel moved[0] = components[i]; 2288 0 stevel if (pool_resource_xtransfer(conf, src, dst, moved) == 2289 0 stevel PO_SUCCESS) { 2290 0 stevel size--; 2291 0 stevel } 2292 0 stevel } 2293 0 stevel } 2294 0 stevel 2295 0 stevel free(components); 2296 0 stevel /* 2297 0 stevel * If we couldn't transfer out all the resources we asked for, then 2298 0 stevel * return error. 2299 0 stevel */ 2300 0 stevel return (size == 0 ? PO_SUCCESS : PO_FAIL); 2301 0 stevel } 2302 0 stevel 2303 0 stevel /* 2304 0 stevel * Common processing for a resource transfer (xfer or xxfer). 2305 0 stevel * 2306 0 stevel * - Return XFER_CONTINUE if the transfer should proceeed 2307 0 stevel * - Return XFER_FAIL if the transfer should be stopped in failure 2308 0 stevel * - Return XFER_SUCCESS if the transfer should be stopped in success 2309 0 stevel */ 2310 0 stevel int 2311 0 stevel setup_transfer(pool_conf_t *conf, pool_resource_t *src, pool_resource_t *tgt, 2312 0 stevel uint64_t size, uint64_t *src_size, uint64_t *tgt_size) 2313 0 stevel { 2314 0 stevel uint64_t src_min; 2315 0 stevel uint64_t tgt_max; 2316 0 stevel 2317 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 2318 0 stevel return (XFER_FAIL); 2319 0 stevel 2320 0 stevel /* 2321 0 stevel * Makes sure the two resources are of the same type 2322 0 stevel */ 2323 0 stevel if (pool_resource_elem_class(TO_ELEM(src)) != 2324 0 stevel pool_resource_elem_class(TO_ELEM(tgt))) { 2325 0 stevel pool_seterror(POE_BADPARAM); 2326 0 stevel return (XFER_FAIL); 2327 0 stevel } 2328 0 stevel 2329 0 stevel /* 2330 0 stevel * Transferring to yourself is a no-op 2331 0 stevel */ 2332 0 stevel if (src == tgt) 2333 0 stevel return (XFER_SUCCESS); 2334 0 stevel 2335 0 stevel /* 2336 0 stevel * Transferring nothing is a no-op 2337 0 stevel */ 2338 0 stevel if (size == 0) 2339 0 stevel return (XFER_SUCCESS); 2340 0 stevel 2341 0 stevel if (resource_get_min(src, &src_min) != PO_SUCCESS || 2342 0 stevel resource_get_size(src, src_size) != PO_SUCCESS || 2343 0 stevel resource_get_max(tgt, &tgt_max) != PO_SUCCESS || 2344 0 stevel resource_get_size(tgt, tgt_size) != PO_SUCCESS) { 2345 0 stevel pool_seterror(POE_BADPARAM); 2346 0 stevel return (XFER_FAIL); 2347 0 stevel } 2348 0 stevel if (pool_conf_status(conf) != POF_DESTROY) { 2349 0 stevel /* 2350 0 stevel * src_size - donating >= src.min 2351 0 stevel * size + receiving <= tgt.max (except for default) 2352 0 stevel */ 2353 0 stevel #ifdef DEBUG 2354 0 stevel dprintf("conf is %s\n", pool_conf_location(conf)); 2355 0 stevel dprintf("setup_transfer: src_size %llu\n", *src_size); 2356 0 stevel pool_elem_dprintf(TO_ELEM(src)); 2357 0 stevel dprintf("setup_transfer: tgt_size %llu\n", *tgt_size); 2358 0 stevel pool_elem_dprintf(TO_ELEM(tgt)); 2359 0 stevel #endif /* DEBUG */ 2360 0 stevel if (*src_size - size < src_min || 2361 0 stevel (resource_is_default(tgt) == PO_FALSE && 2362 0 stevel *tgt_size + size > tgt_max)) { 2363 0 stevel pool_seterror(POE_INVALID_CONF); 2364 0 stevel return (XFER_FAIL); 2365 0 stevel } 2366 0 stevel } 2367 0 stevel return (XFER_CONTINUE); 2368 0 stevel } 2369 0 stevel 2370 0 stevel /* 2371 0 stevel * Transfer resource quantities from one resource set to another. 2372 0 stevel */ 2373 0 stevel int 2374 0 stevel pool_resource_transfer(pool_conf_t *conf, pool_resource_t *src, 2375 0 stevel pool_resource_t *tgt, uint64_t size) 2376 0 stevel { 2377 0 stevel uint64_t src_size; 2378 0 stevel uint64_t tgt_size; 2379 0 stevel int ret; 2380 0 stevel 2381 0 stevel if ((ret = setup_transfer(conf, src, tgt, size, &src_size, &tgt_size)) 2382 0 stevel != XFER_CONTINUE) 2383 0 stevel return (ret); 2384 0 stevel /* 2385 0 stevel * If this resource is a res_comp we must call move components 2386 0 stevel */ 2387 0 stevel if (pool_elem_class(TO_ELEM(src)) == PEC_RES_COMP) 2388 0 stevel return (choose_components(src, tgt, size)); 2389 0 stevel /* 2390 0 stevel * Now do the transfer. 2391 0 stevel */ 2392 0 stevel ret = conf->pc_prov->pc_res_xfer(src, tgt, size); 2393 0 stevel /* 2394 0 stevel * Modify the sizes of the resource sets if the process was 2395 0 stevel * successful 2396 0 stevel */ 2397 0 stevel if (ret == PO_SUCCESS) { 2398 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 2399 0 stevel 2400 0 stevel src_size -= size; 2401 0 stevel tgt_size += size; 2402 0 stevel pool_value_set_uint64(&val, src_size); 2403 0 stevel (void) pool_put_any_ns_property(TO_ELEM(src), c_size_prop, 2404 0 stevel &val); 2405 0 stevel pool_value_set_uint64(&val, tgt_size); 2406 0 stevel (void) pool_put_any_ns_property(TO_ELEM(tgt), c_size_prop, 2407 0 stevel &val); 2408 0 stevel } 2409 0 stevel return (ret); 2410 0 stevel } 2411 0 stevel 2412 0 stevel /* 2413 0 stevel * Transfer resource components from one resource set to another. 2414 0 stevel */ 2415 0 stevel int 2416 0 stevel pool_resource_xtransfer(pool_conf_t *conf, pool_resource_t *src, 2417 0 stevel pool_resource_t *tgt, 2418 0 stevel pool_component_t **rl) 2419 0 stevel { 2420 0 stevel int i; 2421 0 stevel uint64_t src_size; 2422 0 stevel uint64_t tgt_size; 2423 0 stevel uint64_t size; 2424 0 stevel int ret; 2425 0 stevel 2426 0 stevel /* 2427 0 stevel * Make sure the components are all contained in 'src'. This 2428 0 stevel * processing must be done before setup_transfer so that size 2429 0 stevel * is known. 2430 0 stevel */ 2431 0 stevel for (i = 0; rl[i] != NULL; i++) { 2432 0 stevel #ifdef DEBUG 2433 0 stevel dprintf("resource xtransfer\n"); 2434 0 stevel dprintf("in conf %s\n", pool_conf_location(conf)); 2435 0 stevel dprintf("transferring component\n"); 2436 0 stevel pool_elem_dprintf(TO_ELEM(rl[i])); 2437 0 stevel dprintf("from\n"); 2438 0 stevel pool_elem_dprintf(TO_ELEM(src)); 2439 0 stevel dprintf("to\n"); 2440 0 stevel pool_elem_dprintf(TO_ELEM(tgt)); 2441 0 stevel #endif /* DEBUG */ 2442 0 stevel 2443 0 stevel if (pool_get_owning_resource(conf, rl[i]) != src) { 2444 0 stevel pool_seterror(POE_BADPARAM); 2445 0 stevel return (PO_FAIL); 2446 0 stevel } 2447 0 stevel } 2448 0 stevel 2449 0 stevel size = (uint64_t)i; 2450 0 stevel 2451 0 stevel if ((ret = setup_transfer(conf, src, tgt, size, &src_size, &tgt_size)) 2452 0 stevel != XFER_CONTINUE) 2453 0 stevel return (ret); 2454 0 stevel 2455 0 stevel ret = conf->pc_prov->pc_res_xxfer(src, tgt, rl); 2456 0 stevel /* 2457 0 stevel * Modify the sizes of the resource sets if the process was 2458 0 stevel * successful 2459 0 stevel */ 2460 0 stevel if (ret == PO_SUCCESS) { 2461 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 2462 0 stevel 2463 0 stevel #ifdef DEBUG 2464 0 stevel dprintf("src_size %llu\n", src_size); 2465 0 stevel dprintf("tgt_size %llu\n", tgt_size); 2466 0 stevel dprintf("size %llu\n", size); 2467 0 stevel #endif /* DEBUG */ 2468 0 stevel src_size -= size; 2469 0 stevel tgt_size += size; 2470 0 stevel pool_value_set_uint64(&val, src_size); 2471 0 stevel (void) pool_put_any_ns_property(TO_ELEM(src), c_size_prop, 2472 0 stevel &val); 2473 0 stevel pool_value_set_uint64(&val, tgt_size); 2474 0 stevel (void) pool_put_any_ns_property(TO_ELEM(tgt), c_size_prop, 2475 0 stevel &val); 2476 0 stevel } 2477 0 stevel return (ret); 2478 0 stevel } 2479 0 stevel 2480 0 stevel /* 2481 0 stevel * Find the owning resource for a resource component. 2482 0 stevel */ 2483 0 stevel pool_resource_t * 2484 0 stevel pool_get_owning_resource(const pool_conf_t *conf, const pool_component_t *comp) 2485 0 stevel { 2486 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2487 0 stevel pool_seterror(POE_BADPARAM); 2488 0 stevel return (NULL); 2489 0 stevel } 2490 0 stevel return (pool_elem_res(pool_get_container(TO_ELEM(comp)))); 2491 0 stevel } 2492 0 stevel 2493 0 stevel /* 2494 0 stevel * pool_get_container() returns the container of pc. 2495 0 stevel */ 2496 0 stevel pool_elem_t * 2497 0 stevel pool_get_container(const pool_elem_t *pc) 2498 0 stevel { 2499 0 stevel return (pc->pe_get_container(pc)); 2500 0 stevel } 2501 0 stevel 2502 0 stevel /* 2503 0 stevel * pool_set_container() moves pc so that it is contained by pp. 2504 0 stevel * 2505 0 stevel * Returns PO_SUCCESS/PO_FAIL 2506 0 stevel */ 2507 0 stevel int 2508 0 stevel pool_set_container(pool_elem_t *pp, pool_elem_t *pc) 2509 0 stevel { 2510 0 stevel return (pc->pe_set_container(pp, pc)); 2511 0 stevel } 2512 0 stevel 2513 0 stevel /* 2514 0 stevel * Conversion routines for converting to and from elem and it's various 2515 0 stevel * subtypes of system, pool, res and comp. 2516 0 stevel */ 2517 0 stevel pool_elem_t * 2518 0 stevel pool_system_elem(const pool_system_t *ph) 2519 0 stevel { 2520 0 stevel return ((pool_elem_t *)ph); 2521 0 stevel } 2522 0 stevel 2523 0 stevel pool_elem_t * 2524 0 stevel pool_conf_to_elem(const pool_conf_t *conf) 2525 0 stevel { 2526 0 stevel pool_system_t *sys; 2527 0 stevel 2528 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2529 0 stevel pool_seterror(POE_BADPARAM); 2530 0 stevel return (NULL); 2531 0 stevel } 2532 0 stevel if ((sys = pool_conf_system(conf)) == NULL) { 2533 0 stevel pool_seterror(POE_BADPARAM); 2534 0 stevel return (NULL); 2535 0 stevel } 2536 0 stevel return (pool_system_elem(sys)); 2537 0 stevel } 2538 0 stevel 2539 0 stevel pool_elem_t * 2540 0 stevel pool_to_elem(const pool_conf_t *conf, const pool_t *pp) 2541 0 stevel { 2542 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2543 0 stevel pool_seterror(POE_BADPARAM); 2544 0 stevel return (NULL); 2545 0 stevel } 2546 0 stevel return ((pool_elem_t *)pp); 2547 0 stevel } 2548 0 stevel 2549 0 stevel pool_elem_t * 2550 0 stevel pool_resource_to_elem(const pool_conf_t *conf, const pool_resource_t *prs) 2551 0 stevel { 2552 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2553 0 stevel pool_seterror(POE_BADPARAM); 2554 0 stevel return (NULL); 2555 0 stevel } 2556 0 stevel return ((pool_elem_t *)prs); 2557 0 stevel } 2558 0 stevel 2559 0 stevel pool_elem_t * 2560 0 stevel pool_component_to_elem(const pool_conf_t *conf, const pool_component_t *pr) 2561 0 stevel { 2562 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2563 0 stevel pool_seterror(POE_BADPARAM); 2564 0 stevel return (NULL); 2565 0 stevel } 2566 0 stevel return ((pool_elem_t *)pr); 2567 0 stevel } 2568 0 stevel 2569 0 stevel /* 2570 0 stevel * Walk all the pools of the configuration calling the user supplied function 2571 0 stevel * as long as the user function continues to return PO_TRUE 2572 0 stevel */ 2573 0 stevel int 2574 0 stevel pool_walk_pools(pool_conf_t *conf, void *arg, 2575 0 stevel int (*callback)(pool_conf_t *conf, pool_t *pool, void *arg)) 2576 0 stevel { 2577 0 stevel pool_t **rs; 2578 0 stevel int i; 2579 0 stevel uint_t size; 2580 0 stevel int error = PO_SUCCESS; 2581 0 stevel 2582 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2583 0 stevel pool_seterror(POE_BADPARAM); 2584 0 stevel return (PO_FAIL); 2585 0 stevel } 2586 0 stevel 2587 0 stevel if ((rs = pool_query_pools(conf, &size, NULL)) == NULL) /* None */ 2588 0 stevel return (PO_SUCCESS); 2589 0 stevel for (i = 0; i < size; i++) 2590 0 stevel if (callback(conf, rs[i], arg) != PO_SUCCESS) { 2591 0 stevel error = PO_FAIL; 2592 0 stevel break; 2593 0 stevel } 2594 0 stevel free(rs); 2595 0 stevel return (error); 2596 0 stevel } 2597 0 stevel 2598 0 stevel /* 2599 0 stevel * Walk all the comp of the res calling the user supplied function 2600 0 stevel * as long as the user function continues to return PO_TRUE 2601 0 stevel */ 2602 0 stevel int 2603 0 stevel pool_walk_components(pool_conf_t *conf, pool_resource_t *prs, void *arg, 2604 0 stevel int (*callback)(pool_conf_t *conf, pool_component_t *pr, void *arg)) 2605 0 stevel { 2606 0 stevel pool_component_t **rs; 2607 0 stevel int i; 2608 0 stevel uint_t size; 2609 0 stevel int error = PO_SUCCESS; 2610 0 stevel 2611 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2612 0 stevel pool_seterror(POE_BADPARAM); 2613 0 stevel return (PO_FAIL); 2614 0 stevel } 2615 0 stevel 2616 0 stevel if ((rs = pool_query_resource_components(conf, prs, &size, NULL)) == 2617 0 stevel NULL) 2618 0 stevel return (PO_SUCCESS); /* None */ 2619 0 stevel for (i = 0; i < size; i++) 2620 0 stevel if (callback(conf, rs[i], arg) != PO_SUCCESS) { 2621 0 stevel error = PO_FAIL; 2622 0 stevel break; 2623 0 stevel } 2624 0 stevel free(rs); 2625 0 stevel return (error); 2626 0 stevel } 2627 0 stevel 2628 0 stevel /* 2629 0 stevel * Return an array of all matching res for the supplied pool. 2630 0 stevel */ 2631 0 stevel pool_resource_t ** 2632 0 stevel pool_query_pool_resources(const pool_conf_t *conf, const pool_t *pp, 2633 0 stevel uint_t *size, pool_value_t **props) 2634 0 stevel { 2635 0 stevel pool_result_set_t *rs; 2636 0 stevel pool_elem_t *pe; 2637 0 stevel pool_resource_t **result = NULL; 2638 0 stevel int i = 0; 2639 0 stevel 2640 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2641 0 stevel pool_seterror(POE_BADPARAM); 2642 0 stevel return (NULL); 2643 0 stevel } 2644 0 stevel 2645 0 stevel pe = TO_ELEM(pp); 2646 0 stevel 2647 0 stevel rs = pool_exec_query(conf, pe, "res", PEC_QRY_RES, props); 2648 0 stevel if (rs == NULL) { 2649 0 stevel return (NULL); 2650 0 stevel } 2651 0 stevel if ((*size = pool_rs_count(rs)) == 0) { 2652 0 stevel (void) pool_rs_close(rs); 2653 0 stevel return (NULL); 2654 0 stevel } 2655 0 stevel if ((result = malloc(sizeof (pool_resource_t *) * (*size + 1))) 2656 0 stevel == NULL) { 2657 0 stevel pool_seterror(POE_SYSTEM); 2658 0 stevel (void) pool_rs_close(rs); 2659 0 stevel return (NULL); 2660 0 stevel } 2661 0 stevel (void) memset(result, 0, sizeof (pool_resource_t *) * (*size + 1)); 2662 0 stevel for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) { 2663 0 stevel if (pool_elem_class(pe) != PEC_RES_COMP && 2664 0 stevel pool_elem_class(pe) != PEC_RES_AGG) { 2665 0 stevel pool_seterror(POE_INVALID_CONF); 2666 0 stevel free(result); 2667 0 stevel (void) pool_rs_close(rs); 2668 0 stevel return (NULL); 2669 0 stevel } 2670 0 stevel result[i++] = pool_elem_res(pe); 2671 0 stevel } 2672 0 stevel (void) pool_rs_close(rs); 2673 0 stevel return (result); 2674 0 stevel } 2675 0 stevel 2676 0 stevel /* 2677 0 stevel * Walk all the res of the pool calling the user supplied function 2678 0 stevel * as long as the user function continues to return PO_TRUE 2679 0 stevel */ 2680 0 stevel int 2681 0 stevel pool_walk_resources(pool_conf_t *conf, pool_t *pp, void *arg, 2682 0 stevel int (*callback)(pool_conf_t *, pool_resource_t *, void *)) 2683 0 stevel { 2684 0 stevel pool_resource_t **rs; 2685 0 stevel int i; 2686 0 stevel uint_t size; 2687 0 stevel int error = PO_SUCCESS; 2688 0 stevel 2689 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2690 0 stevel pool_seterror(POE_BADPARAM); 2691 0 stevel return (PO_FAIL); 2692 0 stevel } 2693 0 stevel if ((rs = pool_query_pool_resources(conf, pp, &size, NULL)) == NULL) 2694 0 stevel return (PO_SUCCESS); /* None */ 2695 0 stevel for (i = 0; i < size; i++) 2696 0 stevel if (callback(conf, rs[i], arg) != PO_SUCCESS) { 2697 0 stevel error = PO_FAIL; 2698 0 stevel break; 2699 0 stevel } 2700 0 stevel free(rs); 2701 0 stevel return (error); 2702 0 stevel } 2703 0 stevel 2704 0 stevel /* 2705 0 stevel * Return a result set of all comp for the supplied res. 2706 0 stevel */ 2707 0 stevel pool_component_t ** 2708 0 stevel pool_query_resource_components(const pool_conf_t *conf, 2709 0 stevel const pool_resource_t *prs, uint_t *size, pool_value_t **props) 2710 0 stevel { 2711 0 stevel pool_result_set_t *rs; 2712 0 stevel pool_elem_t *pe; 2713 0 stevel pool_component_t **result = NULL; 2714 0 stevel int i = 0; 2715 0 stevel 2716 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2717 0 stevel pool_seterror(POE_BADPARAM); 2718 0 stevel return (NULL); 2719 0 stevel } 2720 0 stevel pe = TO_ELEM(prs); 2721 0 stevel 2722 0 stevel rs = pool_exec_query(conf, pe, NULL, PEC_QRY_COMP, props); 2723 0 stevel if (rs == NULL) { 2724 0 stevel return (NULL); 2725 0 stevel } 2726 0 stevel if ((*size = pool_rs_count(rs)) == 0) { 2727 0 stevel (void) pool_rs_close(rs); 2728 0 stevel return (NULL); 2729 0 stevel } 2730 0 stevel if ((result = malloc(sizeof (pool_component_t *) * (*size + 1))) 2731 0 stevel == NULL) { 2732 0 stevel pool_seterror(POE_SYSTEM); 2733 0 stevel (void) pool_rs_close(rs); 2734 0 stevel return (NULL); 2735 0 stevel } 2736 0 stevel (void) memset(result, 0, sizeof (pool_component_t *) * (*size + 1)); 2737 0 stevel for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) { 2738 0 stevel if (pool_elem_class(pe) != PEC_COMP) { 2739 0 stevel pool_seterror(POE_INVALID_CONF); 2740 0 stevel free(result); 2741 0 stevel (void) pool_rs_close(rs); 2742 0 stevel return (NULL); 2743 0 stevel } 2744 0 stevel result[i++] = pool_elem_comp(pe); 2745 0 stevel } 2746 0 stevel (void) pool_rs_close(rs); 2747 0 stevel return (result); 2748 0 stevel } 2749 0 stevel 2750 0 stevel /* 2751 0 stevel * pool_version() returns the version of this library, depending on the supplied 2752 0 stevel * parameter. 2753 0 stevel * 2754 0 stevel * Returns: library version depening on the supplied ver parameter. 2755 0 stevel */ 2756 0 stevel uint_t 2757 0 stevel pool_version(uint_t ver) 2758 0 stevel { 2759 0 stevel switch (ver) { 2760 0 stevel case POOL_VER_NONE: 2761 0 stevel break; 2762 0 stevel case POOL_VER_CURRENT: 2763 0 stevel pool_workver = ver; 2764 0 stevel break; 2765 0 stevel default: 2766 0 stevel return (POOL_VER_NONE); 2767 0 stevel } 2768 0 stevel return (pool_workver); 2769 0 stevel } 2770 0 stevel 2771 0 stevel /* 2772 0 stevel * pool_associate() associates the supplied resource to the supplied pool. 2773 0 stevel * 2774 0 stevel * Returns: PO_SUCCESS/PO_FAIL 2775 0 stevel */ 2776 0 stevel int 2777 0 stevel pool_associate(pool_conf_t *conf, pool_t *pool, const pool_resource_t *res) 2778 0 stevel { 2779 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 2780 0 stevel return (PO_FAIL); 2781 0 stevel 2782 0 stevel return (pool->pp_associate(pool, res)); 2783 0 stevel } 2784 0 stevel 2785 0 stevel /* 2786 0 stevel * pool_dissociate() dissociates the supplied resource from the supplied pool. 2787 0 stevel * 2788 0 stevel * Returns: PO_SUCCESS/PO_FAIL 2789 0 stevel */ 2790 0 stevel int 2791 0 stevel pool_dissociate(pool_conf_t *conf, pool_t *pool, const pool_resource_t *res) 2792 0 stevel { 2793 0 stevel if (pool_conf_check(conf) != PO_SUCCESS) 2794 0 stevel return (PO_FAIL); 2795 0 stevel 2796 0 stevel if (elem_is_default(TO_ELEM(res))) 2797 0 stevel return (PO_SUCCESS); 2798 0 stevel return (pool->pp_dissociate(pool, res)); 2799 0 stevel } 2800 0 stevel 2801 0 stevel /* 2802 0 stevel * Compare two elements for purposes of ordering. 2803 0 stevel * Return: 2804 0 stevel * < 0 if e1 is "before" e2 2805 0 stevel * 0 if e1 "equals" e2 2806 0 stevel * > 0 if e1 comes after e2 2807 0 stevel */ 2808 0 stevel int 2809 0 stevel pool_elem_compare_name(const pool_elem_t *e1, const pool_elem_t *e2) 2810 0 stevel { 2811 0 stevel char *name1, *name2; 2812 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 2813 0 stevel int retval; 2814 0 stevel 2815 0 stevel /* 2816 0 stevel * We may be asked to compare two elements from different classes. 2817 0 stevel * They are different so return (1). 2818 0 stevel */ 2819 0 stevel if (pool_elem_same_class(e1, e2) != PO_TRUE) 2820 0 stevel return (1); 2821 0 stevel 2822 0 stevel /* 2823 0 stevel * If the class is PEC_SYSTEM, always match them 2824 0 stevel */ 2825 0 stevel if (pool_elem_class(e1) == PEC_SYSTEM) 2826 0 stevel return (0); 2827 0 stevel 2828 0 stevel /* 2829 0 stevel * If we are going to compare components, then use sys_id 2830 0 stevel */ 2831 0 stevel if (pool_elem_class(e1) == PEC_COMP) { 2832 0 stevel int64_t sys_id1, sys_id2; 2833 0 stevel 2834 0 stevel if (pool_get_ns_property(e1, c_sys_prop, &val) == POC_INVAL) { 2835 0 stevel return (-1); 2836 0 stevel } 2837 0 stevel (void) pool_value_get_int64(&val, &sys_id1); 2838 0 stevel if (pool_get_ns_property(e2, c_sys_prop, &val) == POC_INVAL) { 2839 0 stevel return (-1); 2840 0 stevel } 2841 0 stevel (void) pool_value_get_int64(&val, &sys_id2); 2842 0 stevel retval = (sys_id1 - sys_id2); 2843 0 stevel } else { 2844 0 stevel if (pool_get_ns_property(e1, "name", &val) == POC_INVAL) { 2845 0 stevel return (-1); 2846 0 stevel } 2847 0 stevel (void) pool_value_get_string(&val, (const char **)&name1); 2848 0 stevel if ((name1 = strdup(name1)) == NULL) { 2849 0 stevel return (-1); 2850 0 stevel } 2851 0 stevel 2852 0 stevel if (pool_get_ns_property(e2, "name", &val) == POC_INVAL) { 2853 0 stevel return (-1); 2854 0 stevel } 2855 0 stevel 2856 0 stevel (void) pool_value_get_string(&val, (const char **)&name2); 2857 0 stevel retval = strcmp(name1, name2); 2858 0 stevel free(name1); 2859 0 stevel } 2860 0 stevel return (retval); 2861 0 stevel } 2862 0 stevel 2863 0 stevel /* 2864 0 stevel * Compare two elements for purposes of ordering. 2865 0 stevel * Return: 2866 0 stevel * < 0 if e1 is "before" e2 2867 0 stevel * 0 if e1 "equals" e2 2868 0 stevel * > 0 if e1 comes after e2 2869 0 stevel */ 2870 0 stevel int 2871 0 stevel pool_elem_compare(const pool_elem_t *e1, const pool_elem_t *e2) 2872 0 stevel { 2873 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 2874 0 stevel int64_t sys_id1, sys_id2; 2875 0 stevel 2876 0 stevel /* 2877 0 stevel * We may be asked to compare two elements from different classes. 2878 0 stevel * They are different so return the difference in their classes 2879 0 stevel */ 2880 0 stevel if (pool_elem_same_class(e1, e2) != PO_TRUE) 2881 0 stevel return (1); 2882 0 stevel 2883 0 stevel /* 2884 0 stevel * If the class is PEC_SYSTEM, always match them 2885 0 stevel */ 2886 0 stevel if (pool_elem_class(e1) == PEC_SYSTEM) 2887 0 stevel return (0); 2888 0 stevel 2889 0 stevel /* 2890 0 stevel * Compare with sys_id 2891 0 stevel */ 2892 0 stevel if (pool_get_ns_property(e1, c_sys_prop, &val) == POC_INVAL) { 2893 0 stevel assert(!"no sys_id on e1\n"); 2894 0 stevel } 2895 0 stevel (void) pool_value_get_int64(&val, &sys_id1); 2896 0 stevel if (pool_get_ns_property(e2, c_sys_prop, &val) == POC_INVAL) { 2897 0 stevel assert(!"no sys_id on e2\n"); 2898 0 stevel } 2899 0 stevel (void) pool_value_get_int64(&val, &sys_id2); 2900 0 stevel return (sys_id1 - sys_id2); 2901 0 stevel } 2902 0 stevel 2903 0 stevel /* 2904 0 stevel * Return PO_TRUE if the supplied elems are of the same class. 2905 0 stevel */ 2906 0 stevel int 2907 0 stevel pool_elem_same_class(const pool_elem_t *e1, const pool_elem_t *e2) 2908 0 stevel { 2909 0 stevel if (pool_elem_class(e1) != pool_elem_class(e2)) 2910 0 stevel return (PO_FALSE); 2911 0 stevel 2912 0 stevel /* 2913 0 stevel * Check to make sure the fundamental class of the elements match 2914 0 stevel */ 2915 0 stevel if (pool_elem_class(e1) == PEC_RES_COMP || 2916 0 stevel pool_elem_class(e1) == PEC_RES_AGG) 2917 0 stevel if (pool_resource_elem_class(e1) != 2918 0 stevel pool_resource_elem_class(e2)) 2919 0 stevel return (PO_FALSE); 2920 0 stevel if (pool_elem_class(e1) == PEC_COMP) 2921 0 stevel if (pool_component_elem_class(e1) != 2922 0 stevel pool_component_elem_class(e2)) 2923 0 stevel return (PO_FALSE); 2924 0 stevel return (PO_TRUE); 2925 0 stevel } 2926 0 stevel 2927 0 stevel /* 2928 0 stevel * pool_conf_check() checks that the configuration state isn't invalid 2929 0 stevel * and that the configuration was opened for modification. 2930 0 stevel */ 2931 0 stevel int 2932 0 stevel pool_conf_check(const pool_conf_t *conf) 2933 0 stevel { 2934 0 stevel if (pool_conf_status(conf) == POF_INVALID) { 2935 0 stevel pool_seterror(POE_BADPARAM); 2936 0 stevel return (PO_FAIL); 2937 0 stevel } 2938 0 stevel 2939 0 stevel if ((conf->pc_prov->pc_oflags & PO_RDWR) == 0) { 2940 0 stevel pool_seterror(POE_BADPARAM); 2941 0 stevel return (PO_FAIL); 2942 0 stevel } 2943 0 stevel return (PO_SUCCESS); 2944 0 stevel } 2945