1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 3247 gjelinek * Common Development and Distribution License (the "License"). 6 3247 gjelinek * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 3247 gjelinek * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 27 0 stevel 28 0 stevel #include <limits.h> 29 0 stevel #include <pool.h> 30 0 stevel #include <stdlib.h> 31 0 stevel #include <stdio.h> 32 0 stevel #include <string.h> 33 0 stevel #include <synch.h> 34 0 stevel #include <thread.h> 35 0 stevel 36 0 stevel #include <sys/loadavg.h> 37 0 stevel #include <sys/types.h> 38 0 stevel #include <sys/utsname.h> 39 0 stevel 40 0 stevel #include "dict.h" 41 0 stevel #include "pool_internal.h" 42 0 stevel #include "pool_impl.h" 43 0 stevel 44 0 stevel /* 45 0 stevel * Atom structure, used to reference count string atoms. 46 0 stevel */ 47 0 stevel typedef struct { 48 0 stevel char *a_string; /* String atom */ 49 0 stevel uint_t a_count; /* String reference count */ 50 0 stevel } atom_t; 51 0 stevel 52 0 stevel /* 53 0 stevel * The _internal_lock is used to lock the state of libpool during 54 0 stevel * internal initialisation operations. 55 0 stevel */ 56 0 stevel mutex_t _internal_lock; 57 0 stevel 58 0 stevel static int _libpool_debug = 0; /* debugging messages */ 59 0 stevel static dict_hdl_t *_pv_atoms; /* pool_value_t atoms */ 60 0 stevel static mutex_t _atom_lock; /* atom table lock */ 61 0 stevel static int _libpool_internal_initialised = PO_FALSE; 62 0 stevel 63 0 stevel /* 64 0 stevel * Various useful constant strings which are often encountered 65 0 stevel */ 66 0 stevel const char *c_a_dtype = "a-dtype"; 67 0 stevel const char *c_name = "name"; 68 0 stevel const char *c_type = "type"; 69 0 stevel const char *c_ref_id = "ref_id"; 70 0 stevel const char *c_max_prop = "max"; 71 0 stevel const char *c_min_prop = "min"; 72 0 stevel const char *c_size_prop = "size"; 73 0 stevel const char *c_sys_prop = "sys_id"; 74 0 stevel 75 0 stevel /* 76 0 stevel * prop_is_type() checks the supplied property and returns PO_TRUE if the 77 0 stevel * property value is set for the property else PO_FALSE 78 0 stevel */ 79 0 stevel static int prop_is_type(int, const pool_prop_t *); 80 0 stevel static int resource_get_common(const pool_resource_t *, const char *, 81 0 stevel uint64_t *); 82 0 stevel static int64_t elem_get_expected_int64(const pool_elem_t *, const char *); 83 0 stevel 84 0 stevel /* 85 0 stevel * The following returns a malloc'ed string which must be free'd by the 86 0 stevel * caller. 87 0 stevel */ 88 0 stevel static char *elem_get_expected_string(const pool_elem_t *, const char *); 89 0 stevel static int element_props_init(pool_prop_t *); 90 0 stevel 91 0 stevel /* 92 0 stevel * Each element class/sub-class has a set of properties and behaviours 93 0 stevel * which are used to create the element with appropriate property 94 0 stevel * values and to ensure correct property manipulations. The details 95 0 stevel * are all stored in the following arrays. 96 0 stevel */ 97 0 stevel 98 0 stevel static int elem_name_init(pool_prop_t *); 99 0 stevel static int elem_comment_init(pool_prop_t *); 100 0 stevel 101 0 stevel static int pool_importance_init(pool_prop_t *); 102 0 stevel static int pool_active_init(pool_prop_t *); 103 0 stevel 104 0 stevel static int res_max_init(pool_prop_t *); 105 0 stevel static int res_min_init(pool_prop_t *); 106 0 stevel static int res_size_init(pool_prop_t *); 107 0 stevel static int res_load_init(pool_prop_t *); 108 0 stevel 109 0 stevel static int pset_units_init(pool_prop_t *); 110 0 stevel 111 0 stevel static int cpu_status_init(pool_prop_t *); 112 0 stevel 113 0 stevel static int elem_no_set(pool_elem_t *, const pool_value_t *); 114 0 stevel static int elem_set_name(pool_elem_t *, const pool_value_t *); 115 0 stevel static int elem_get_type(const pool_elem_t *, pool_value_t *); 116 0 stevel static int elem_set_string(pool_elem_t *, const pool_value_t *); 117 0 stevel static int elem_set_bool(pool_elem_t *, const pool_value_t *); 118 0 stevel static int elem_set_uint(pool_elem_t *, const pool_value_t *); 119 0 stevel 120 0 stevel static int system_set_allocate(pool_elem_t *, const pool_value_t *); 121 0 stevel 122 0 stevel static int pool_set_scheduler(pool_elem_t *, const pool_value_t *); 123 0 stevel static int pool_set_active(pool_elem_t *, const pool_value_t *); 124 0 stevel 125 0 stevel static int res_set_max(pool_elem_t *, const pool_value_t *); 126 0 stevel static int res_set_min(pool_elem_t *, const pool_value_t *); 127 0 stevel 128 0 stevel static int cpu_set_status(pool_elem_t *, const pool_value_t *); 129 0 stevel 130 0 stevel static const char *pool_elem_class_name[] = { 131 0 stevel "invalid", 132 0 stevel "system", 133 0 stevel "pool", 134 0 stevel "component resource", 135 0 stevel "aggregate resource", 136 0 stevel "component" 137 0 stevel }; 138 0 stevel 139 0 stevel /* 140 0 stevel * This must be kept in sync with the pool_resource_elem_ctl array and 141 0 stevel * the "enum pool_resource_elem_class" type. 142 0 stevel */ 143 0 stevel static const char *pool_resource_elem_class_name[] = { 144 0 stevel "invalid", 145 0 stevel "pset" 146 0 stevel }; 147 0 stevel 148 0 stevel static const char *pool_component_elem_class_name[] = { 149 0 stevel "invalid", 150 0 stevel "cpu" 151 0 stevel }; 152 0 stevel 153 0 stevel static pool_prop_t system_props[] = { 154 0 stevel { "system.name", POOL_VALUE_INITIALIZER, PP_STORED, NULL, 155 0 stevel { NULL, elem_set_name } }, 156 0 stevel { "system.ref_id", POOL_VALUE_INITIALIZER, 157 0 stevel PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } }, 158 0 stevel { "system.comment", POOL_VALUE_INITIALIZER, PP_STORED, NULL, NULL }, 159 0 stevel { "system.version", POOL_VALUE_INITIALIZER, 160 0 stevel PP_STORED | PP_READ, NULL, NULL }, 161 0 stevel { "system.bind-default", POOL_VALUE_INITIALIZER, 162 0 stevel PP_STORED, NULL, NULL }, 163 0 stevel { "system.allocate-method", POOL_VALUE_INITIALIZER, 164 0 stevel PP_STORED | PP_OPTIONAL, NULL, { NULL, system_set_allocate } }, 165 0 stevel { "system.poold.log-level", POOL_VALUE_INITIALIZER, 166 0 stevel PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } }, 167 0 stevel { "system.poold.log-location", POOL_VALUE_INITIALIZER, 168 0 stevel PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } }, 169 0 stevel { "system.poold.monitor-interval", POOL_VALUE_INITIALIZER, 170 0 stevel PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_uint } }, 171 0 stevel { "system.poold.history-file", POOL_VALUE_INITIALIZER, 172 0 stevel PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } }, 173 0 stevel { "system.poold.objectives", POOL_VALUE_INITIALIZER, 174 0 stevel PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } }, 175 0 stevel NULL 176 0 stevel }; 177 0 stevel 178 0 stevel static pool_prop_t pool_props[] = { 179 0 stevel { "pool.sys_id", POOL_VALUE_INITIALIZER, 180 0 stevel PP_STORED | PP_READ, NULL, NULL }, 181 0 stevel { "pool.name", POOL_VALUE_INITIALIZER, 182 0 stevel PP_STORED | PP_INIT, elem_name_init, { NULL, elem_set_name } }, 183 0 stevel { "pool.res", POOL_VALUE_INITIALIZER, 184 0 stevel PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } }, 185 0 stevel { "pool.ref_id", POOL_VALUE_INITIALIZER, 186 0 stevel PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } }, 187 0 stevel { "pool.active", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, 188 0 stevel pool_active_init, { NULL, pool_set_active } }, 189 0 stevel { "pool.default", POOL_VALUE_INITIALIZER, 190 0 stevel PP_STORED | PP_READ, NULL, NULL }, 191 0 stevel { "pool.scheduler", POOL_VALUE_INITIALIZER, 192 0 stevel PP_STORED | PP_OPTIONAL, NULL, 193 0 stevel { NULL, pool_set_scheduler } }, 194 0 stevel { "pool.importance", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, 195 0 stevel pool_importance_init, NULL }, 196 0 stevel { "pool.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, 197 0 stevel elem_comment_init, NULL }, 198 0 stevel NULL 199 0 stevel }; 200 0 stevel 201 0 stevel static pool_prop_t pset_props[] = { 202 0 stevel { "type", POOL_VALUE_INITIALIZER, PP_HIDDEN | PP_STORED | PP_READ, NULL, 203 0 stevel { elem_get_type, NULL } }, 204 0 stevel { "pset.sys_id", POOL_VALUE_INITIALIZER, 205 0 stevel PP_STORED | PP_READ, NULL, NULL }, 206 0 stevel { "pset.name", POOL_VALUE_INITIALIZER, 207 0 stevel PP_STORED | PP_INIT, elem_name_init, { NULL, elem_set_name } }, 208 0 stevel { "pset.ref_id", POOL_VALUE_INITIALIZER, 209 0 stevel PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } }, 210 0 stevel { "pset.default", POOL_VALUE_INITIALIZER, 211 0 stevel PP_STORED | PP_READ, NULL, NULL }, 212 0 stevel { "pset.min", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, res_min_init, 213 0 stevel { NULL, res_set_min } }, 214 0 stevel { "pset.max", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, res_max_init, 215 0 stevel { NULL, res_set_max } }, 216 0 stevel { "pset.units", POOL_VALUE_INITIALIZER, 217 0 stevel PP_STORED | PP_INIT, pset_units_init, NULL }, 218 0 stevel { "pset.load", POOL_VALUE_INITIALIZER, PP_READ | PP_INIT, 219 0 stevel res_load_init, NULL }, 220 0 stevel { "pset.size", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT | PP_READ, 221 0 stevel res_size_init, NULL }, 222 0 stevel { "pset.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, 223 0 stevel elem_comment_init, NULL }, 224 0 stevel { "pset.poold.objectives", POOL_VALUE_INITIALIZER, 225 0 stevel PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } }, 226 0 stevel NULL 227 0 stevel }; 228 0 stevel 229 0 stevel static pool_prop_t cpu_props[] = { 230 0 stevel { "type", POOL_VALUE_INITIALIZER, PP_HIDDEN | PP_STORED | PP_READ, NULL, 231 0 stevel { elem_get_type, NULL } }, 232 0 stevel { "cpu.sys_id", POOL_VALUE_INITIALIZER, PP_STORED | PP_READ, NULL, 233 0 stevel NULL }, 234 0 stevel { "cpu.ref_id", POOL_VALUE_INITIALIZER, 235 0 stevel PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } }, 236 0 stevel { "cpu.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, 237 0 stevel elem_comment_init, NULL }, 238 0 stevel { "cpu.status", POOL_VALUE_INITIALIZER, PP_INIT, cpu_status_init, 239 0 stevel { NULL, cpu_set_status } }, 240 0 stevel { "cpu.pinned", POOL_VALUE_INITIALIZER, PP_STORED | PP_OPTIONAL, NULL, 241 0 stevel { NULL, elem_set_bool } }, 242 0 stevel NULL 243 0 stevel }; 244 0 stevel 245 0 stevel static pool_prop_t *pool_elem_ctl[] = { 246 0 stevel NULL, 247 0 stevel system_props, 248 0 stevel pool_props, 249 0 stevel NULL, 250 0 stevel NULL, 251 0 stevel NULL 252 0 stevel }; 253 0 stevel 254 0 stevel /* 255 0 stevel * This must be kept in sync with the pool_resource_elem_class_name array and 256 0 stevel * the "enum pool_resource_elem_class" type. 257 0 stevel */ 258 0 stevel static pool_prop_t *pool_resource_elem_ctl[] = { 259 0 stevel NULL, 260 0 stevel pset_props 261 0 stevel }; 262 0 stevel 263 0 stevel static pool_prop_t *pool_component_elem_ctl[] = { 264 0 stevel NULL, 265 0 stevel cpu_props 266 0 stevel }; 267 0 stevel 268 0 stevel static void 269 0 stevel atom_init(void) 270 0 stevel { 271 0 stevel (void) mutex_lock(&_atom_lock); 272 0 stevel /* 273 0 stevel * Initialize pool_value_t atom dictionary 274 0 stevel */ 275 0 stevel if (_pv_atoms == NULL) 276 0 stevel if ((_pv_atoms = dict_new((int (*)(const void *, const void *)) 277 0 stevel strcmp, (uint64_t (*)(const void *))hash_str)) == NULL) 278 0 stevel abort(); 279 0 stevel (void) mutex_unlock(&_atom_lock); 280 0 stevel } 281 0 stevel 282 0 stevel /* 283 0 stevel * Initializer, called when the library is initialized. 284 0 stevel */ 285 0 stevel void 286 0 stevel internal_init(void) 287 0 stevel { 288 0 stevel (void) mutex_lock(&_internal_lock); 289 0 stevel if (_libpool_internal_initialised == PO_TRUE) { 290 0 stevel (void) mutex_unlock(&_internal_lock); 291 0 stevel return; 292 0 stevel } 293 0 stevel atom_init(); 294 0 stevel /* 295 0 stevel * Initialize all available property arrays. 296 0 stevel */ 297 0 stevel if (element_props_init(system_props) == PO_FAIL) 298 0 stevel abort(); 299 0 stevel if (element_props_init(pool_props) == PO_FAIL) 300 0 stevel abort(); 301 0 stevel if (element_props_init(pset_props) == PO_FAIL) 302 0 stevel abort(); 303 0 stevel if (element_props_init(cpu_props) == PO_FAIL) 304 0 stevel abort(); 305 0 stevel _libpool_internal_initialised = PO_TRUE; 306 0 stevel (void) mutex_unlock(&_internal_lock); 307 0 stevel 308 0 stevel } 309 0 stevel 310 0 stevel static int 311 0 stevel element_props_init(pool_prop_t *props) 312 0 stevel { 313 0 stevel int i; 314 0 stevel 315 0 stevel for (i = 0; props[i].pp_pname != NULL; i++) { 316 0 stevel /* 317 0 stevel * Initialise each of the properties 318 0 stevel */ 319 0 stevel if (pool_value_set_name(&props[i].pp_value, 320 0 stevel props[i].pp_pname) != PO_SUCCESS) { 321 0 stevel return (PO_FAIL); 322 0 stevel } 323 0 stevel if (props[i].pp_init && 324 0 stevel props[i].pp_init(&props[i]) != PO_SUCCESS) { 325 0 stevel return (PO_FAIL); 326 0 stevel } 327 0 stevel } 328 0 stevel return (PO_SUCCESS); 329 0 stevel } 330 0 stevel 331 0 stevel 332 0 stevel /* 333 0 stevel * These functions intialise the properties of this plugin. The only reason 334 0 stevel * they exist is because the ability to perform the static initialisation of 335 0 stevel * union members properly was only introduced in the C99 standard. i.e. if you 336 0 stevel * could do {.f = 1.0} like in the proposed C99 standard then that would 337 0 stevel * be the preferred way to do this as it keeps the data in the array and 338 0 stevel * minimises the scope for errors. However, until that time these functions 339 0 stevel * are the best way to minimise the scope for errors and to maximise 340 0 stevel * maintainability. 341 0 stevel * 342 0 stevel * There is one function for each property, and the initial value for each 343 0 stevel * property is hard-coded into each function. 344 0 stevel */ 345 0 stevel 346 0 stevel static int 347 0 stevel elem_name_init(pool_prop_t *prop) 348 0 stevel { 349 0 stevel return (string_init(prop, "default")); 350 0 stevel } 351 0 stevel 352 0 stevel static int 353 0 stevel elem_comment_init(pool_prop_t *prop) 354 0 stevel { 355 0 stevel return (string_init(prop, "")); 356 0 stevel } 357 0 stevel 358 0 stevel static int 359 0 stevel pool_importance_init(pool_prop_t *prop) 360 0 stevel { 361 0 stevel return (int_init(prop, 1)); 362 0 stevel } 363 0 stevel 364 0 stevel static int 365 0 stevel pool_active_init(pool_prop_t *prop) 366 0 stevel { 367 0 stevel return (bool_init(prop, PO_TRUE)); 368 0 stevel } 369 0 stevel 370 0 stevel static int 371 0 stevel res_max_init(pool_prop_t *prop) 372 0 stevel { 373 0 stevel return (uint_init(prop, 0)); 374 0 stevel } 375 0 stevel 376 0 stevel static int 377 0 stevel res_min_init(pool_prop_t *prop) 378 0 stevel { 379 0 stevel return (uint_init(prop, 0)); 380 0 stevel } 381 0 stevel 382 0 stevel static int 383 0 stevel res_size_init(pool_prop_t *prop) 384 0 stevel { 385 0 stevel return (uint_init(prop, 0)); 386 0 stevel } 387 0 stevel 388 0 stevel static int 389 0 stevel res_load_init(pool_prop_t *prop) 390 0 stevel { 391 0 stevel return (uint_init(prop, 0)); 392 0 stevel } 393 0 stevel 394 0 stevel static int 395 0 stevel pset_units_init(pool_prop_t *prop) 396 0 stevel { 397 0 stevel return (string_init(prop, "population")); 398 0 stevel } 399 0 stevel 400 0 stevel static int 401 0 stevel cpu_status_init(pool_prop_t *prop) 402 0 stevel { 403 0 stevel return (string_init(prop, PS_ONLINE)); 404 0 stevel } 405 0 stevel 406 0 stevel /* 407 0 stevel * Individual property manipulation routines for use by the generic 408 0 stevel * get/put property routines 409 0 stevel */ 410 0 stevel 411 0 stevel /* 412 0 stevel * Many properties cannot be modified. This function prevents property 413 0 stevel * modification. 414 0 stevel */ 415 0 stevel /* ARGSUSED */ 416 0 stevel static int 417 0 stevel elem_no_set(pool_elem_t *elem, const pool_value_t *pval) 418 0 stevel { 419 0 stevel return (PO_FAIL); 420 0 stevel } 421 0 stevel 422 0 stevel /* 423 0 stevel * Duplicate names for a pool or resource type are illegal. 424 0 stevel */ 425 0 stevel static int 426 0 stevel elem_set_name(pool_elem_t *elem, const pool_value_t *pval) 427 0 stevel { 428 0 stevel const char *nm; 429 0 stevel pool_t *pool; 430 0 stevel pool_resource_t *res; 431 0 stevel 432 0 stevel if (pool_value_get_string(pval, &nm) != PO_SUCCESS) { 433 0 stevel return (PO_FAIL); 434 0 stevel } 435 0 stevel if (!is_valid_name(nm)) { 436 0 stevel pool_seterror(POE_PUTPROP); 437 0 stevel return (PO_FAIL); 438 0 stevel } 439 0 stevel switch (pool_elem_class(elem)) { 440 0 stevel case PEC_SYSTEM: 441 0 stevel break; 442 0 stevel case PEC_POOL: 443 0 stevel pool = pool_get_pool(TO_CONF(elem), nm); 444 0 stevel if (pool != NULL && pool != pool_elem_pool(elem)) { 445 0 stevel pool_seterror(POE_PUTPROP); 446 0 stevel return (PO_FAIL); 447 0 stevel } 448 0 stevel break; 449 0 stevel case PEC_RES_COMP: 450 0 stevel case PEC_RES_AGG: 451 0 stevel res = pool_get_resource(TO_CONF(elem), 452 0 stevel pool_elem_class_string(elem), nm); 453 0 stevel if (res != NULL && res != pool_elem_res(elem)) { 454 0 stevel pool_seterror(POE_PUTPROP); 455 0 stevel return (PO_FAIL); 456 0 stevel } 457 0 stevel break; 458 0 stevel default: 459 0 stevel return (PO_FAIL); 460 0 stevel } 461 0 stevel return (PO_SUCCESS); 462 0 stevel } 463 0 stevel 464 0 stevel /* 465 0 stevel * Ensure the type is a string. 466 0 stevel */ 467 0 stevel /* ARGSUSED */ 468 0 stevel static int 469 0 stevel elem_set_string(pool_elem_t *elem, const pool_value_t *pval) 470 0 stevel { 471 0 stevel if (pool_value_get_type(pval) == POC_STRING) 472 0 stevel return (PO_SUCCESS); 473 0 stevel else { 474 0 stevel pool_seterror(POE_BADPARAM); 475 0 stevel return (PO_FAIL); 476 0 stevel } 477 0 stevel } 478 0 stevel 479 0 stevel /* 480 0 stevel * Ensure the type is a boolean. 481 0 stevel */ 482 0 stevel /* ARGSUSED */ 483 0 stevel static int 484 0 stevel elem_set_bool(pool_elem_t *elem, const pool_value_t *pval) 485 0 stevel { 486 0 stevel if (pool_value_get_type(pval) == POC_BOOL) 487 0 stevel return (PO_SUCCESS); 488 0 stevel else { 489 0 stevel pool_seterror(POE_BADPARAM); 490 0 stevel return (PO_FAIL); 491 0 stevel } 492 0 stevel } 493 0 stevel 494 0 stevel /* 495 0 stevel * Ensure the type is an unsigned int. 496 0 stevel */ 497 0 stevel /* ARGSUSED */ 498 0 stevel static int 499 0 stevel elem_set_uint(pool_elem_t *elem, const pool_value_t *pval) 500 0 stevel { 501 0 stevel if (pool_value_get_type(pval) == POC_UINT) 502 0 stevel return (PO_SUCCESS); 503 0 stevel else { 504 0 stevel pool_seterror(POE_BADPARAM); 505 0 stevel return (PO_FAIL); 506 0 stevel } 507 0 stevel } 508 0 stevel 509 0 stevel /* ARGSUSED */ 510 0 stevel int 511 0 stevel system_set_allocate(pool_elem_t *elem, const pool_value_t *pval) 512 0 stevel { 513 0 stevel const char *sval; 514 0 stevel 515 0 stevel if (pool_value_get_string(pval, &sval) != PO_SUCCESS) { 516 0 stevel pool_seterror(POE_PUTPROP); 517 0 stevel return (PO_FAIL); 518 0 stevel } 519 0 stevel if (strcmp(POA_IMPORTANCE, sval) != 0 && 520 0 stevel strcmp(POA_SURPLUS_TO_DEFAULT, sval) != 0) { 521 0 stevel pool_seterror(POE_PUTPROP); 522 0 stevel return (PO_FAIL); 523 0 stevel } 524 0 stevel return (PO_SUCCESS); 525 0 stevel } 526 0 stevel 527 0 stevel /* ARGSUSED */ 528 0 stevel int 529 0 stevel pool_set_active(pool_elem_t *elem, const pool_value_t *pval) 530 0 stevel { 531 0 stevel uchar_t bval; 532 0 stevel 533 0 stevel if (pool_value_get_type(pval) != POC_BOOL) { 534 0 stevel pool_seterror(POE_BADPARAM); 535 0 stevel return (PO_FAIL); 536 0 stevel } 537 0 stevel (void) pool_value_get_bool(pval, &bval); 538 0 stevel if (bval != 1) { 539 0 stevel /* 540 0 stevel * "active" must be true on pools for 541 0 stevel * now. 542 0 stevel */ 543 0 stevel pool_seterror(POE_BADPARAM); 544 0 stevel return (PO_FAIL); 545 0 stevel } 546 0 stevel return (PO_SUCCESS); 547 0 stevel } 548 0 stevel 549 0 stevel /* ARGSUSED */ 550 0 stevel int 551 0 stevel pool_set_scheduler(pool_elem_t *elem, const pool_value_t *pval) 552 0 stevel { 553 0 stevel pcinfo_t pcinfo; 554 0 stevel const char *sched; 555 0 stevel 556 0 stevel if (pool_value_get_string(pval, &sched) != 0) { 557 0 stevel pool_seterror(POE_PUTPROP); 558 0 stevel return (PO_FAIL); 559 0 stevel } 560 0 stevel (void) strncpy(pcinfo.pc_clname, sched, PC_CLNMSZ); 561 0 stevel if (priocntl(0, 0, PC_GETCID, &pcinfo) == -1) { 562 0 stevel pool_seterror(POE_PUTPROP); 563 0 stevel return (PO_FAIL); 564 0 stevel } 565 0 stevel return (PO_SUCCESS); 566 0 stevel } 567 0 stevel 568 0 stevel static int 569 0 stevel res_set_max(pool_elem_t *elem, const pool_value_t *pval) 570 0 stevel { 571 0 stevel uint64_t min, max; 572 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 573 0 stevel 574 0 stevel /* 575 0 stevel * max must be a uint 576 0 stevel */ 577 0 stevel if (pool_value_get_uint64(pval, &max) != PO_SUCCESS) { 578 0 stevel pool_seterror(POE_PUTPROP); 579 0 stevel return (PO_FAIL); 580 0 stevel } 581 0 stevel /* 582 0 stevel * max can't be less than min (if it exists) 583 0 stevel */ 584 0 stevel if (pool_get_ns_property(elem, c_min_prop, &val) == POC_INVAL) 585 0 stevel return (PO_SUCCESS); 586 0 stevel if (pool_value_get_uint64(&val, &min) != PO_SUCCESS) { 587 0 stevel pool_seterror(POE_PUTPROP); 588 0 stevel return (PO_FAIL); 589 0 stevel } 590 0 stevel if (max < min) { 591 0 stevel pool_seterror(POE_PUTPROP); 592 0 stevel return (PO_FAIL); 593 0 stevel } 594 0 stevel /* 595 0 stevel * Ensure that changes to the max in a dynamic configuration 596 0 stevel * are still valid. 597 0 stevel */ 598 0 stevel if (conf_is_dynamic(TO_CONF(elem)) == PO_TRUE) { 599 0 stevel uint64_t oldmax; 600 0 stevel 601 0 stevel if (pool_get_ns_property(elem, c_max_prop, &val) == POC_INVAL) { 602 0 stevel pool_seterror(POE_PUTPROP); 603 0 stevel return (PO_FAIL); 604 0 stevel } 605 0 stevel if (pool_value_get_uint64(&val, &oldmax) != PO_SUCCESS) { 606 0 stevel pool_seterror(POE_PUTPROP); 607 0 stevel return (PO_FAIL); 608 0 stevel } 609 0 stevel if (max < oldmax) { 610 0 stevel /* 611 0 stevel * Ensure that the modified total max is >= size 612 0 stevel * of all resources of this type 613 0 stevel */ 614 0 stevel return (pool_validate_resource(TO_CONF(elem), 615 0 stevel pool_elem_class_string(elem), c_max_prop, 616 0 stevel max - oldmax)); 617 0 stevel } 618 0 stevel } 619 0 stevel return (PO_SUCCESS); 620 0 stevel } 621 0 stevel 622 0 stevel static int 623 0 stevel res_set_min(pool_elem_t *elem, const pool_value_t *pval) 624 0 stevel { 625 0 stevel uint64_t min, max; 626 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 627 0 stevel 628 0 stevel /* 629 0 stevel * min must be a uint 630 0 stevel */ 631 0 stevel if (pool_value_get_uint64(pval, &min) != PO_SUCCESS) { 632 0 stevel pool_seterror(POE_PUTPROP); 633 0 stevel return (PO_FAIL); 634 0 stevel } 635 0 stevel /* 636 0 stevel * min can't be more than max (if it exists) 637 0 stevel */ 638 0 stevel if (pool_get_ns_property(elem, c_max_prop, &val) == POC_INVAL) 639 0 stevel return (PO_SUCCESS); 640 0 stevel if (pool_value_get_uint64(&val, &max) != PO_SUCCESS) { 641 0 stevel pool_seterror(POE_PUTPROP); 642 0 stevel return (PO_FAIL); 643 0 stevel } 644 0 stevel if (min > max) { 645 0 stevel pool_seterror(POE_PUTPROP); 646 0 stevel return (PO_FAIL); 647 0 stevel } 648 0 stevel 649 0 stevel switch (pool_resource_elem_class(elem)) { 650 0 stevel case PREC_PSET: 651 0 stevel if (resource_is_default(pool_elem_res(elem))) { 652 0 stevel if (min < 1) { 653 0 stevel pool_seterror(POE_PUTPROP); 654 0 stevel return (PO_FAIL); 655 0 stevel } 656 0 stevel } 657 0 stevel break; 658 0 stevel default: 659 0 stevel break; 660 0 stevel } 661 0 stevel 662 0 stevel /* 663 0 stevel * Ensure that changes to the min in a dynamic configuration 664 0 stevel * are still valid. 665 0 stevel */ 666 0 stevel if (conf_is_dynamic(TO_CONF(elem)) == PO_TRUE) { 667 0 stevel uint64_t oldmin; 668 0 stevel 669 0 stevel if (pool_get_ns_property(elem, c_min_prop, &val) == POC_INVAL) { 670 0 stevel pool_seterror(POE_PUTPROP); 671 0 stevel return (PO_FAIL); 672 0 stevel } 673 0 stevel if (pool_value_get_uint64(&val, &oldmin) != PO_SUCCESS) { 674 0 stevel pool_seterror(POE_PUTPROP); 675 0 stevel return (PO_FAIL); 676 0 stevel } 677 0 stevel if (min > oldmin) { 678 0 stevel /* 679 0 stevel * Ensure that the modified total min is <= size 680 0 stevel * of all resources of this type 681 0 stevel */ 682 0 stevel return (pool_validate_resource(TO_CONF(elem), 683 0 stevel pool_elem_class_string(elem), c_min_prop, 684 0 stevel min - oldmin)); 685 0 stevel } 686 0 stevel } 687 0 stevel return (PO_SUCCESS); 688 0 stevel } 689 0 stevel 690 0 stevel /* ARGSUSED */ 691 0 stevel int 692 0 stevel cpu_set_status(pool_elem_t *elem, const pool_value_t *pval) 693 0 stevel { 694 0 stevel const char *status; 695 0 stevel 696 0 stevel if (pool_value_get_string(pval, &status) != 0) { 697 0 stevel pool_seterror(POE_PUTPROP); 698 0 stevel return (PO_FAIL); 699 0 stevel } 700 0 stevel 701 0 stevel if (strcmp(PS_ONLINE, status) != 0 && 702 0 stevel strcmp(PS_OFFLINE, status) != 0 && 703 0 stevel strcmp(PS_NOINTR, status) != 0 && 704 0 stevel strcmp(PS_SPARE, status) != 0 && 705 0 stevel strcmp(PS_FAULTED, status) != 0) { 706 0 stevel pool_seterror(POE_PUTPROP); 707 0 stevel return (PO_FAIL); 708 0 stevel } 709 0 stevel return (PO_SUCCESS); 710 0 stevel } 711 0 stevel 712 0 stevel static int 713 0 stevel elem_get_type(const pool_elem_t *elem, pool_value_t *pval) 714 0 stevel { 715 0 stevel if (pool_value_set_string(pval, pool_elem_class_string(elem)) == 716 0 stevel PO_FAIL) 717 0 stevel return (PO_FAIL); 718 0 stevel return (PO_SUCCESS); 719 0 stevel } 720 0 stevel 721 0 stevel /* 722 0 stevel * More general utilities 723 0 stevel */ 724 0 stevel /* 725 0 stevel * Is the supplied configuration the dynamic configuration 726 0 stevel * Return: PO_TRUE/PO_FALSE 727 0 stevel */ 728 0 stevel int 729 0 stevel conf_is_dynamic(const pool_conf_t *conf) 730 0 stevel { 731 0 stevel if (strcmp(pool_conf_location(conf), pool_dynamic_location()) == 0) 732 0 stevel return (PO_TRUE); 733 0 stevel return (PO_FALSE); 734 0 stevel } 735 0 stevel 736 0 stevel /* 737 0 stevel * uint_init() initialises the value of the supplied property with the 738 0 stevel * supplied value. 739 0 stevel * Returns PO_SUCCESS 740 0 stevel */ 741 0 stevel int 742 0 stevel uint_init(pool_prop_t *prop, uint64_t val) 743 0 stevel { 744 0 stevel pool_value_set_uint64(&prop->pp_value, val); 745 0 stevel return (PO_SUCCESS); 746 0 stevel } 747 0 stevel 748 0 stevel /* 749 0 stevel * int_init() initialises the value of the supplied property with the 750 0 stevel * supplied value. 751 0 stevel * Returns PO_SUCCESS 752 0 stevel */ 753 0 stevel int 754 0 stevel int_init(pool_prop_t *prop, int64_t val) 755 0 stevel { 756 0 stevel pool_value_set_int64(&prop->pp_value, val); 757 0 stevel return (PO_SUCCESS); 758 0 stevel } 759 0 stevel 760 0 stevel /* 761 0 stevel * double_init() initialises the value of the supplied property with the 762 0 stevel * supplied value. 763 0 stevel * Returns PO_SUCCESS 764 0 stevel */ 765 0 stevel int 766 0 stevel double_init(pool_prop_t *prop, double val) 767 0 stevel { 768 0 stevel pool_value_set_double(&prop->pp_value, val); 769 0 stevel return (PO_SUCCESS); 770 0 stevel } 771 0 stevel 772 0 stevel /* 773 0 stevel * bool_init() initialises the value of the supplied property with the 774 0 stevel * supplied value. 775 0 stevel * Returns PO_SUCCESS 776 0 stevel */ 777 0 stevel int 778 0 stevel bool_init(pool_prop_t *prop, uchar_t val) 779 0 stevel { 780 0 stevel pool_value_set_bool(&prop->pp_value, val); 781 0 stevel return (PO_SUCCESS); 782 0 stevel } 783 0 stevel 784 0 stevel /* 785 0 stevel * string_init() initialises the value of the supplied property with the 786 0 stevel * supplied value. 787 0 stevel * Returns PO_SUCCESS/PO_FAIL 788 0 stevel */ 789 0 stevel int 790 0 stevel string_init(pool_prop_t *prop, const char *val) 791 0 stevel { 792 0 stevel return (pool_value_set_string(&prop->pp_value, val)); 793 0 stevel } 794 0 stevel 795 0 stevel /* 796 0 stevel * pool_get_provider_count() returns the count of registered providers. 797 0 stevel * 798 0 stevel * Returns count of registered providers 799 0 stevel */ 800 0 stevel uint_t 801 0 stevel pool_get_provider_count(void) 802 0 stevel { 803 0 stevel uint_t count = 0; 804 0 stevel int i; 805 0 stevel 806 0 stevel for (i = 0; i < sizeof (pool_resource_elem_ctl) / 807 0 stevel sizeof (pool_resource_elem_ctl[0]); i++) { 808 0 stevel if (pool_resource_elem_ctl[i] != NULL) 809 0 stevel count++; 810 0 stevel } 811 0 stevel return (count); 812 0 stevel } 813 0 stevel 814 0 stevel /* 815 0 stevel * Return all the props for a specified provider 816 0 stevel */ 817 0 stevel const pool_prop_t * 818 0 stevel provider_get_props(const pool_elem_t *elem) 819 0 stevel { 820 0 stevel const pool_prop_t *prop_list = NULL; 821 0 stevel pool_elem_class_t elem_class = pool_elem_class(elem); 822 0 stevel 823 0 stevel switch (elem_class) { 824 0 stevel case PEC_SYSTEM: 825 0 stevel case PEC_POOL: 826 0 stevel prop_list = pool_elem_ctl[elem_class]; 827 0 stevel break; 828 0 stevel case PEC_RES_AGG: 829 0 stevel case PEC_RES_COMP: 830 0 stevel prop_list = pool_resource_elem_ctl 831 0 stevel [pool_resource_elem_class(elem)]; 832 0 stevel break; 833 0 stevel case PEC_COMP: 834 0 stevel prop_list = pool_component_elem_ctl 835 0 stevel [pool_component_elem_class(elem)]; 836 0 stevel break; 837 0 stevel } 838 0 stevel return (prop_list); 839 0 stevel } 840 0 stevel 841 0 stevel /* 842 0 stevel * provider_get_prop() return the pool_prop_t structure which 843 0 stevel * describes the supplied property name for the supplied provider. 844 0 stevel * 845 0 stevel * Returns the property description or NULL if it doesn't exist. 846 0 stevel */ 847 0 stevel const pool_prop_t * 848 0 stevel provider_get_prop(const pool_elem_t *elem, const char *name) 849 0 stevel { 850 0 stevel int i; 851 0 stevel const pool_prop_t *prop_list; 852 0 stevel 853 0 stevel if ((prop_list = provider_get_props(elem)) == NULL) 854 0 stevel return (NULL); 855 0 stevel 856 0 stevel for (i = 0; prop_list[i].pp_pname != NULL; i++) { 857 0 stevel if (strcmp(name, prop_list[i].pp_pname) == 0) { 858 0 stevel return (&prop_list[i]); 859 0 stevel } 860 0 stevel } 861 0 stevel return (NULL); 862 0 stevel } 863 0 stevel 864 0 stevel /* 865 0 stevel * prop_is_type() checks the supplied property and returns PO_TRUE if the 866 0 stevel * property value is 1 else PO_FALSE 867 0 stevel */ 868 0 stevel static int 869 0 stevel prop_is_type(int prop_type, const pool_prop_t *prop) 870 0 stevel { 871 0 stevel return ((prop->pp_perms & prop_type) ? PO_TRUE : PO_FALSE); 872 0 stevel } 873 0 stevel 874 0 stevel /* 875 0 stevel * prop_is_stored() returns PO_TRUE if the property is stored in the backing 876 0 stevel * configuration and PO_FALSE else. 877 0 stevel */ 878 0 stevel int 879 0 stevel prop_is_stored(const pool_prop_t *prop) 880 0 stevel { 881 0 stevel return (prop_is_type(PP_STORED, prop)); 882 0 stevel } 883 0 stevel 884 0 stevel /* 885 0 stevel * prop_is_readonly() returns PO_TRUE if the property is a read-only property 886 0 stevel * and PO_FALSE else. 887 0 stevel */ 888 0 stevel int 889 0 stevel prop_is_readonly(const pool_prop_t *prop) 890 0 stevel { 891 0 stevel return (prop_is_type(PP_READ, prop)); 892 0 stevel } 893 0 stevel 894 0 stevel /* 895 0 stevel * prop_is_init() returns PO_TRUE if the property should be 896 0 stevel * initialised when an element of this type is created and PO_FALSE 897 0 stevel * else. 898 0 stevel */ 899 0 stevel int 900 0 stevel prop_is_init(const pool_prop_t *prop) 901 0 stevel { 902 0 stevel return (prop_is_type(PP_INIT, prop)); 903 0 stevel } 904 0 stevel 905 0 stevel /* 906 0 stevel * prop_is_hidden() returns PO_TRUE if the property should be hidden 907 0 stevel * from access by the external property access mechanisms. 908 0 stevel */ 909 0 stevel int 910 0 stevel prop_is_hidden(const pool_prop_t *prop) 911 0 stevel { 912 0 stevel return (prop_is_type(PP_HIDDEN, prop)); 913 0 stevel } 914 0 stevel 915 0 stevel /* 916 0 stevel * prop_is_optional() returns PO_TRUE if the property is optional and 917 0 stevel * can be removed by external property access mechanisms. 918 0 stevel */ 919 0 stevel int 920 0 stevel prop_is_optional(const pool_prop_t *prop) 921 0 stevel { 922 0 stevel return (prop_is_type(PP_OPTIONAL, prop)); 923 0 stevel } 924 0 stevel 925 0 stevel int 926 0 stevel cpu_is_requested(pool_component_t *component) 927 0 stevel { 928 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 929 0 stevel uchar_t requested; 930 0 stevel 931 0 stevel if (pool_get_property(TO_CONF(TO_ELEM(component)), TO_ELEM(component), 932 0 stevel "cpu.requested", &val) != POC_BOOL) { 933 0 stevel return (PO_FALSE); 934 0 stevel } 935 0 stevel if (pool_value_get_bool(&val, &requested) != PO_SUCCESS) { 936 0 stevel return (PO_FALSE); 937 0 stevel } 938 0 stevel return ((int)requested); 939 0 stevel } 940 0 stevel 941 0 stevel /* 942 0 stevel * Common code for various resource get functions 943 0 stevel */ 944 0 stevel static int 945 0 stevel resource_get_common(const pool_resource_t *res, const char *name, 946 0 stevel uint64_t *uval) 947 0 stevel { 948 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 949 0 stevel pool_value_class_t pvc; 950 0 stevel int retval = PO_SUCCESS; 951 0 stevel 952 0 stevel pvc = pool_get_ns_property(TO_ELEM(res), name, &val); 953 0 stevel if (pvc == POC_INVAL) { 954 0 stevel *uval = 0; 955 0 stevel #ifdef DEBUG 956 0 stevel dprintf("can't retrieve %s\n"); 957 0 stevel pool_elem_dprintf(TO_ELEM(res)); 958 0 stevel #endif /* DEBUG */ 959 0 stevel } else if (pvc == POC_UINT) { 960 0 stevel retval = pool_value_get_uint64(&val, uval); 961 0 stevel } 962 0 stevel return (retval); 963 0 stevel } 964 0 stevel 965 0 stevel /* 966 0 stevel * resource_get_size() updates size with the size of the supplied resource. 967 0 stevel * 968 0 stevel * Returns PO_SUCCESS/PO_FAIL 969 0 stevel */ 970 0 stevel int 971 0 stevel resource_get_size(const pool_resource_t *res, uint64_t *size) 972 0 stevel { 973 0 stevel return (resource_get_common(res, c_size_prop, size)); 974 0 stevel } 975 0 stevel 976 0 stevel /* 977 0 stevel * resource_get_pinned() updates pinned with the size of the 978 0 stevel * pinned part of a supplied resource. Resource is not available for 979 0 stevel * allocation if it is marked as "pinned". 980 0 stevel * 981 0 stevel * Returns PO_SUCCESS/PO_FAIL 982 0 stevel */ 983 0 stevel int 984 0 stevel resource_get_pinned(const pool_resource_t *res, uint64_t *pinned) 985 0 stevel { 986 0 stevel pool_value_t *props[] = { NULL, NULL }; 987 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 988 0 stevel pool_component_t **cs = NULL; 989 0 stevel uint_t ncompelem; 990 0 stevel 991 0 stevel props[0] = &val; 992 0 stevel 993 0 stevel pool_value_set_bool(props[0], PO_TRUE); 994 0 stevel if (pool_value_set_name(props[0], "cpu.pinned") != PO_SUCCESS) 995 0 stevel return (PO_FAIL); 996 0 stevel 997 0 stevel if ((cs = pool_query_resource_components(TO_CONF(TO_ELEM(res)), res, 998 0 stevel &ncompelem, props)) != NULL) { 999 0 stevel *pinned = ncompelem; 1000 0 stevel free(cs); 1001 0 stevel } else 1002 0 stevel *pinned = 0; 1003 0 stevel return (PO_SUCCESS); 1004 0 stevel } 1005 0 stevel 1006 0 stevel /* 1007 0 stevel * resource_get_min() updates min with the minimum size of the supplied 1008 0 stevel * resource. 1009 0 stevel * 1010 0 stevel * Returns PO_SUCCESS/PO_FAIL 1011 0 stevel */ 1012 0 stevel int 1013 0 stevel resource_get_min(const pool_resource_t *res, uint64_t *min) 1014 0 stevel { 1015 0 stevel return (resource_get_common(res, c_min_prop, min)); 1016 0 stevel } 1017 0 stevel 1018 0 stevel /* 1019 0 stevel * resource_get_max() updates max with the maximum size of the supplied 1020 0 stevel * resource. 1021 0 stevel * 1022 0 stevel * Returns PO_SUCCESS/PO_FAIL 1023 0 stevel */ 1024 0 stevel int 1025 0 stevel resource_get_max(const pool_resource_t *res, uint64_t *max) 1026 0 stevel { 1027 0 stevel return (resource_get_common(res, c_max_prop, max)); 1028 0 stevel } 1029 0 stevel 1030 0 stevel /* 1031 0 stevel * TODO: This is pset specific 1032 0 stevel * 1033 0 stevel * get_default_resource() returns the default resource for type of the supplied 1034 0 stevel * resource. 1035 0 stevel * 1036 0 stevel * Returns A pointer to the default resource of the same type as the supplied 1037 0 stevel * resource. 1038 0 stevel */ 1039 0 stevel const pool_resource_t * 1040 0 stevel get_default_resource(const pool_resource_t *res) 1041 0 stevel { 1042 0 stevel return (resource_by_sysid(TO_CONF(TO_ELEM(res)), PS_NONE, 1043 0 stevel pool_elem_class_string(TO_ELEM(res)))); 1044 0 stevel } 1045 0 stevel 1046 0 stevel /* 1047 0 stevel * resource_is_default() returns 1 if the supplied resource is the default 1048 0 stevel * resource for it's type. 1049 0 stevel */ 1050 0 stevel int 1051 0 stevel resource_is_default(const pool_resource_t *res) 1052 0 stevel { 1053 0 stevel 1054 0 stevel return (get_default_resource(res) == res); 1055 0 stevel } 1056 0 stevel 1057 0 stevel /* 1058 0 stevel * resource_is_system() determines if the resource is a system resource. 1059 0 stevel */ 1060 0 stevel int 1061 0 stevel resource_is_system(const pool_resource_t *res) 1062 0 stevel { 1063 0 stevel return (res->pr_is_system(res)); 1064 0 stevel 1065 0 stevel } 1066 0 stevel 1067 0 stevel /* 1068 0 stevel * resource_can_associate() determines if it is possible to associate 1069 0 stevel * with the supplied resource. 1070 0 stevel */ 1071 0 stevel int 1072 0 stevel resource_can_associate(const pool_resource_t *res) 1073 0 stevel { 1074 0 stevel return (res->pr_can_associate(res)); 1075 0 stevel } 1076 0 stevel 1077 0 stevel /* 1078 0 stevel * Common code to get an int64 property. 1079 0 stevel * Unfortunately (-1) is a valid psetid, so we'll return (-2) in case of 1080 0 stevel * error. 1081 0 stevel */ 1082 0 stevel static int64_t 1083 0 stevel elem_get_expected_int64(const pool_elem_t *elem, const char *name) 1084 0 stevel { 1085 0 stevel int64_t val64; 1086 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1087 0 stevel 1088 0 stevel if (pool_get_ns_property(elem, name, &val) != POC_INT) { 1089 0 stevel return (POOL_SYSID_BAD); 1090 0 stevel } 1091 0 stevel (void) pool_value_get_int64(&val, &val64); 1092 0 stevel 1093 0 stevel return (val64); 1094 0 stevel } 1095 0 stevel 1096 0 stevel /* 1097 0 stevel * The following returns a malloc'ed string which must be free'd by the 1098 0 stevel * caller. 1099 0 stevel */ 1100 0 stevel static char * 1101 0 stevel elem_get_expected_string(const pool_elem_t *elem, const char *name) 1102 0 stevel { 1103 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1104 0 stevel char *retval; 1105 0 stevel 1106 0 stevel if (pool_get_ns_property(elem, name, &val) != POC_STRING) { 1107 0 stevel return (NULL); 1108 0 stevel } 1109 0 stevel (void) pool_value_get_string(&val, (const char **)&retval); 1110 0 stevel retval = strdup(retval); 1111 0 stevel return (retval); 1112 0 stevel } 1113 0 stevel 1114 0 stevel /* 1115 0 stevel * elem_get_sysid() returns the sys_id for the supplied elem. 1116 0 stevel */ 1117 0 stevel id_t 1118 0 stevel elem_get_sysid(const pool_elem_t *elem) 1119 0 stevel { 1120 0 stevel return ((id_t)elem_get_expected_int64(elem, c_sys_prop)); 1121 0 stevel } 1122 0 stevel 1123 0 stevel /* 1124 0 stevel * elem_get_name() returns the name for the supplied elem. Note that 1125 0 stevel * it is the caller's responsibility to free this memory. 1126 0 stevel */ 1127 0 stevel char * 1128 0 stevel elem_get_name(const pool_elem_t *elem) 1129 0 stevel { 1130 0 stevel return (elem_get_expected_string(elem, c_name)); 1131 0 stevel } 1132 0 stevel 1133 0 stevel /* 1134 0 stevel * elem_is_default() returns 1 if the supplied elem is the default 1135 0 stevel * elem for it's type. 1136 0 stevel */ 1137 0 stevel int 1138 0 stevel elem_is_default(const pool_elem_t *res) 1139 0 stevel { 1140 0 stevel 1141 0 stevel return (get_default_elem(res) == res); 1142 0 stevel } 1143 0 stevel 1144 0 stevel /* 1145 3247 gjelinek * Return B_TRUE if the element has the 'temporary' property set. 1146 3247 gjelinek */ 1147 3247 gjelinek boolean_t 1148 3247 gjelinek elem_is_tmp(const pool_elem_t *elem) 1149 3247 gjelinek { 1150 3247 gjelinek pool_value_t val = POOL_VALUE_INITIALIZER; 1151 3247 gjelinek uchar_t bval; 1152 3247 gjelinek 1153 3247 gjelinek if (pool_get_ns_property(elem, "temporary", &val) != POC_BOOL) 1154 3247 gjelinek return (B_FALSE); 1155 3247 gjelinek 1156 3247 gjelinek (void) pool_value_get_bool(&val, &bval); 1157 3247 gjelinek 1158 3247 gjelinek return (bval != 0); 1159 3247 gjelinek } 1160 3247 gjelinek 1161 3247 gjelinek /* 1162 0 stevel * get_default_elem() returns the default elem for type of the supplied 1163 0 stevel * elem. 1164 0 stevel * 1165 0 stevel * Returns A pointer to the default elem of the same type as the 1166 0 stevel * supplied elem or NULL on error. Trying to access the default elem 1167 0 stevel * for a type of element which doesn't support the notion of default 1168 0 stevel * is an error. 1169 0 stevel */ 1170 0 stevel const pool_elem_t * 1171 0 stevel get_default_elem(const pool_elem_t *pe) 1172 0 stevel { 1173 0 stevel pool_result_set_t *rs; 1174 0 stevel pool_value_t *props[] = { NULL, NULL }; 1175 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1176 0 stevel char_buf_t *cb; 1177 0 stevel const pool_elem_t *pe_default; 1178 0 stevel 1179 0 stevel props[0] = &val; 1180 0 stevel if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) { 1181 0 stevel return (NULL); 1182 0 stevel } 1183 0 stevel if (set_char_buf(cb, "%s.default", pool_elem_class_string(pe)) != 1184 0 stevel PO_SUCCESS) { 1185 0 stevel free_char_buf(cb); 1186 0 stevel return (NULL); 1187 0 stevel } 1188 0 stevel if (pool_value_set_name(props[0], cb->cb_buf) != PO_SUCCESS) { 1189 0 stevel free_char_buf(cb); 1190 0 stevel return (NULL); 1191 0 stevel } 1192 0 stevel free_char_buf(cb); 1193 0 stevel pool_value_set_bool(props[0], PO_TRUE); 1194 0 stevel 1195 0 stevel if ((rs = pool_exec_query(TO_CONF(pe), NULL, NULL, 1196 0 stevel PEC_QRY_ELEM(pe), props)) == NULL) { 1197 0 stevel pool_seterror(POE_INVALID_CONF); 1198 0 stevel return (NULL); 1199 0 stevel } 1200 0 stevel if (pool_rs_count(rs) != 1) { 1201 0 stevel (void) pool_rs_close(rs); 1202 0 stevel pool_seterror(POE_INVALID_CONF); 1203 0 stevel return (NULL); 1204 0 stevel } 1205 0 stevel 1206 0 stevel pe_default = rs->prs_next(rs); 1207 0 stevel (void) pool_rs_close(rs); 1208 0 stevel return (pe_default); 1209 0 stevel } 1210 0 stevel 1211 0 stevel /* 1212 0 stevel * is_a_known_prefix() determines if the supplied prop_name is a known 1213 0 stevel * name for the supplied class. 1214 0 stevel * 1215 0 stevel * Returns a pointer to the prefix if it is found or NULL 1216 0 stevel */ 1217 0 stevel const char * 1218 0 stevel is_a_known_prefix(pool_elem_class_t class, const char *prop_name) 1219 0 stevel { 1220 0 stevel int i; 1221 0 stevel int len; 1222 0 stevel 1223 0 stevel switch (class) { 1224 0 stevel case PEC_SYSTEM: 1225 0 stevel case PEC_POOL: 1226 0 stevel len = strlen(pool_elem_class_name[class]); 1227 0 stevel if (strncmp(prop_name, pool_elem_class_name[class], len) == 0 && 1228 0 stevel prop_name[len] == '.' || strcmp(prop_name, c_type) == 0) 1229 0 stevel return (pool_elem_class_name[class]); 1230 0 stevel break; 1231 0 stevel case PEC_RES_COMP: 1232 0 stevel case PEC_RES_AGG: 1233 0 stevel for (i = 0; i < sizeof (pool_resource_elem_class_name) / 1234 0 stevel sizeof (pool_resource_elem_class_name[0]); i++) { 1235 0 stevel len = strlen(pool_resource_elem_class_name[i]); 1236 0 stevel if (strncmp(prop_name, 1237 0 stevel pool_resource_elem_class_name[i], len) == 0 && 1238 0 stevel prop_name[len] == '.' || 1239 0 stevel strcmp(prop_name, c_type) == 0) 1240 0 stevel return (pool_resource_elem_class_name[i]); 1241 0 stevel } 1242 0 stevel break; 1243 0 stevel case PEC_COMP: 1244 0 stevel for (i = 0; i < sizeof (pool_component_elem_class_name) / 1245 0 stevel sizeof (pool_component_elem_class_name[0]); i++) { 1246 0 stevel len = strlen(pool_component_elem_class_name[i]); 1247 0 stevel if (strncmp(prop_name, 1248 0 stevel pool_component_elem_class_name[i], len) == 0 && 1249 0 stevel prop_name[len] == '.' || 1250 0 stevel strcmp(prop_name, c_type) == 0) 1251 0 stevel return (pool_component_elem_class_name[i]); 1252 0 stevel } 1253 0 stevel break; 1254 0 stevel default: 1255 0 stevel break; 1256 0 stevel } 1257 0 stevel return (NULL); 1258 0 stevel } 1259 0 stevel 1260 0 stevel 1261 0 stevel const char * 1262 0 stevel pool_elem_class_string(const pool_elem_t *pe) 1263 0 stevel { 1264 0 stevel switch (pool_elem_class(pe)) { 1265 0 stevel case PEC_SYSTEM: 1266 0 stevel case PEC_POOL: 1267 0 stevel return (pool_elem_class_name[pool_elem_class(pe)]); 1268 0 stevel case PEC_RES_COMP: 1269 0 stevel case PEC_RES_AGG: 1270 0 stevel return (pool_resource_elem_class_name 1271 0 stevel [pool_resource_elem_class(pe)]); 1272 0 stevel case PEC_COMP: 1273 0 stevel return (pool_component_elem_class_name 1274 0 stevel [pool_component_elem_class(pe)]); 1275 0 stevel default: 1276 0 stevel return (pool_elem_class_name[PEC_INVALID]); 1277 0 stevel } 1278 0 stevel } 1279 0 stevel 1280 0 stevel const char * 1281 0 stevel pool_resource_type_string(pool_resource_elem_class_t type) 1282 0 stevel { 1283 0 stevel return (pool_resource_elem_class_name[type]); 1284 0 stevel } 1285 0 stevel 1286 0 stevel const char * 1287 0 stevel pool_component_type_string(pool_component_elem_class_t type) 1288 0 stevel { 1289 0 stevel return (pool_component_elem_class_name[type]); 1290 0 stevel } 1291 0 stevel 1292 0 stevel /* 1293 0 stevel * resource_by_sysid() finds a resource from it's supplied sysid and type. 1294 0 stevel * 1295 0 stevel * Returns a pointer to the resource or NULL if it doesn't exist. 1296 0 stevel */ 1297 0 stevel pool_resource_t * 1298 0 stevel resource_by_sysid(const pool_conf_t *conf, id_t sysid, const char *type) 1299 0 stevel { 1300 0 stevel pool_value_t *props[] = { NULL, NULL, NULL }; 1301 0 stevel pool_resource_t **resources = NULL; 1302 0 stevel pool_resource_t *retval = NULL; 1303 0 stevel uint_t nelem; 1304 0 stevel char_buf_t *cb; 1305 0 stevel pool_value_t val0 = POOL_VALUE_INITIALIZER; 1306 0 stevel pool_value_t val1 = POOL_VALUE_INITIALIZER; 1307 0 stevel 1308 0 stevel props[0] = &val0; 1309 0 stevel props[1] = &val1; 1310 0 stevel 1311 0 stevel if (pool_value_set_string(props[0], type) != PO_SUCCESS || 1312 0 stevel pool_value_set_name(props[0], c_type) != PO_SUCCESS) 1313 0 stevel return (NULL); 1314 0 stevel 1315 0 stevel if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) { 1316 0 stevel return (NULL); 1317 0 stevel } 1318 0 stevel if (set_char_buf(cb, "%s.sys_id", type) != PO_SUCCESS) { 1319 0 stevel free_char_buf(cb); 1320 0 stevel return (NULL); 1321 0 stevel } 1322 0 stevel if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) { 1323 0 stevel free_char_buf(cb); 1324 0 stevel return (NULL); 1325 0 stevel } 1326 0 stevel free_char_buf(cb); 1327 0 stevel pool_value_set_int64(props[1], sysid); 1328 0 stevel 1329 0 stevel resources = pool_query_resources(conf, &nelem, props); 1330 0 stevel 1331 0 stevel if (resources != NULL) { 1332 0 stevel retval = resources[0]; 1333 0 stevel free(resources); 1334 0 stevel } 1335 0 stevel return (retval); 1336 0 stevel } 1337 0 stevel 1338 0 stevel pool_elem_class_t 1339 0 stevel pool_elem_class_from_string(const char *type) 1340 0 stevel { 1341 0 stevel int i; 1342 0 stevel 1343 0 stevel for (i = 0; i < sizeof (pool_elem_class_name) / 1344 0 stevel sizeof (pool_elem_class_name[0]); i++) { 1345 0 stevel if (strcmp(pool_elem_class_name[i], type) == 0) 1346 0 stevel break; 1347 0 stevel } 1348 0 stevel if (i == sizeof (pool_elem_class_name) / 1349 0 stevel sizeof (pool_elem_class_name[0])) 1350 0 stevel return (PEC_INVALID); 1351 0 stevel return ((pool_elem_class_t)i); 1352 0 stevel } 1353 0 stevel 1354 0 stevel pool_resource_elem_class_t 1355 0 stevel pool_resource_elem_class_from_string(const char *type) 1356 0 stevel { 1357 0 stevel int i; 1358 0 stevel 1359 0 stevel for (i = 0; i < sizeof (pool_resource_elem_class_name) / 1360 0 stevel sizeof (pool_resource_elem_class_name[0]); i++) { 1361 0 stevel if (strcmp(pool_resource_elem_class_name[i], type) == 0) 1362 0 stevel break; 1363 0 stevel } 1364 0 stevel if (i == sizeof (pool_resource_elem_class_name) / 1365 0 stevel sizeof (pool_resource_elem_class_name[0])) 1366 0 stevel return (PREC_INVALID); 1367 0 stevel return ((pool_resource_elem_class_t)i); 1368 0 stevel } 1369 0 stevel 1370 0 stevel pool_component_elem_class_t 1371 0 stevel pool_component_elem_class_from_string(const char *type) 1372 0 stevel { 1373 0 stevel int i; 1374 0 stevel 1375 0 stevel for (i = 0; i < sizeof (pool_component_elem_class_name) / 1376 0 stevel sizeof (pool_component_elem_class_name[0]); i++) { 1377 0 stevel if (strcmp(pool_component_elem_class_name[i], type) == 0) 1378 0 stevel break; 1379 0 stevel } 1380 0 stevel if (i == sizeof (pool_component_elem_class_name) / 1381 0 stevel sizeof (pool_component_elem_class_name[0])) 1382 0 stevel return (PCEC_INVALID); 1383 0 stevel return ((pool_component_elem_class_t)i); 1384 0 stevel } 1385 0 stevel 1386 0 stevel /* 1387 0 stevel * pool_resource_type_list() populates the supplied array of pointers 1388 0 stevel * with the names of the available resource types on this system. 1389 0 stevel */ 1390 0 stevel int 1391 0 stevel pool_resource_type_list(const char **types, uint_t *numtypes) 1392 0 stevel { 1393 0 stevel int i, j; 1394 0 stevel uint_t maxnum = *numtypes; 1395 0 stevel 1396 0 stevel *numtypes = pool_get_provider_count(); 1397 0 stevel 1398 0 stevel if (types) { 1399 0 stevel for (i = 0, j = 0; i < sizeof (pool_resource_elem_ctl) / 1400 0 stevel sizeof (pool_resource_elem_ctl[0]) && j < maxnum; i++) { 1401 0 stevel if (pool_resource_elem_ctl[i] != NULL) 1402 0 stevel types[j++] = pool_resource_elem_class_name[i]; 1403 0 stevel } 1404 0 stevel } 1405 0 stevel return (PO_SUCCESS); 1406 0 stevel } 1407 0 stevel 1408 0 stevel /* 1409 0 stevel * Return the system element for the supplied conf. 1410 0 stevel * NULL is returned if an error is detected and the error code is updated 1411 0 stevel * to indicate the cause of the error. 1412 0 stevel */ 1413 0 stevel pool_system_t * 1414 0 stevel pool_conf_system(const pool_conf_t *conf) 1415 0 stevel { 1416 0 stevel pool_elem_t *system; 1417 0 stevel pool_result_set_t *rs; 1418 0 stevel 1419 0 stevel if ((rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_SYSTEM, NULL)) == 1420 0 stevel NULL) { 1421 0 stevel pool_seterror(POE_INVALID_CONF); 1422 0 stevel return (NULL); 1423 0 stevel } 1424 0 stevel /* There should only be one system record */ 1425 0 stevel if (pool_rs_count(rs) != 1) { 1426 0 stevel pool_seterror(POE_INVALID_CONF); 1427 0 stevel (void) pool_rs_close(rs); 1428 0 stevel return (NULL); 1429 0 stevel } 1430 0 stevel system = rs->prs_next(rs); 1431 0 stevel (void) pool_rs_close(rs); 1432 0 stevel return (pool_elem_system(system)); 1433 0 stevel } 1434 0 stevel 1435 0 stevel pool_system_t * 1436 0 stevel pool_elem_system(const pool_elem_t *pe) 1437 0 stevel { 1438 0 stevel if (pe->pe_class != PEC_SYSTEM) { 1439 0 stevel pool_seterror(POE_BADPARAM); 1440 0 stevel return (NULL); 1441 0 stevel } 1442 0 stevel return ((pool_system_t *)pe); 1443 0 stevel } 1444 0 stevel 1445 0 stevel pool_t * 1446 0 stevel pool_elem_pool(const pool_elem_t *pe) 1447 0 stevel { 1448 0 stevel if (pe->pe_class != PEC_POOL) { 1449 0 stevel pool_seterror(POE_BADPARAM); 1450 0 stevel return (NULL); 1451 0 stevel } 1452 0 stevel return ((pool_t *)pe); 1453 0 stevel } 1454 0 stevel 1455 0 stevel pool_resource_t * 1456 0 stevel pool_elem_res(const pool_elem_t *pe) 1457 0 stevel { 1458 0 stevel if (pe->pe_class != PEC_RES_COMP && 1459 0 stevel pool_elem_class(pe) != PEC_RES_AGG) { 1460 0 stevel pool_seterror(POE_BADPARAM); 1461 0 stevel return (NULL); 1462 0 stevel } 1463 0 stevel return ((pool_resource_t *)pe); 1464 0 stevel } 1465 0 stevel 1466 0 stevel pool_component_t * 1467 0 stevel pool_elem_comp(const pool_elem_t *pe) 1468 0 stevel { 1469 0 stevel if (pe->pe_class != PEC_COMP) { 1470 0 stevel pool_seterror(POE_BADPARAM); 1471 0 stevel return (NULL); 1472 0 stevel } 1473 0 stevel return ((pool_component_t *)pe); 1474 0 stevel } 1475 0 stevel 1476 0 stevel /* 1477 0 stevel * qsort_elem_compare() is used for qsort elemement comparison. 1478 0 stevel * 1479 0 stevel * Returns see qsort(3c) 1480 0 stevel */ 1481 0 stevel int 1482 0 stevel qsort_elem_compare(const void *a, const void *b) 1483 0 stevel { 1484 0 stevel const pool_elem_t *e1 = *(const pool_elem_t **)a; 1485 0 stevel const pool_elem_t *e2 = *(const pool_elem_t **)b; 1486 0 stevel 1487 0 stevel /* 1488 0 stevel * Special case for handling name changes on default elements 1489 0 stevel * If both elements are default elements then always return 0 1490 0 stevel */ 1491 0 stevel if (pool_elem_same_class(e1, e2) == PO_TRUE && 1492 0 stevel (elem_is_default(e1) && elem_is_default(e2))) 1493 0 stevel return (0); 1494 0 stevel else 1495 0 stevel return (pool_elem_compare_name(e1, e2)); 1496 0 stevel } 1497 0 stevel 1498 0 stevel /* 1499 0 stevel * Dynamic character buffers. 1500 0 stevel */ 1501 0 stevel 1502 0 stevel /* 1503 0 stevel * Resize the supplied character buffer to the new size. 1504 0 stevel */ 1505 0 stevel static int 1506 0 stevel resize_char_buf(char_buf_t *cb, size_t size) 1507 0 stevel { 1508 0 stevel char *re_cb = NULL; 1509 0 stevel 1510 0 stevel if ((re_cb = realloc(cb->cb_buf, size)) == NULL) { 1511 0 stevel pool_seterror(POE_SYSTEM); 1512 0 stevel return (PO_FAIL); 1513 0 stevel } 1514 0 stevel /* If inital allocation, make sure buffer is zeroed */ 1515 0 stevel if (cb->cb_buf == NULL) 1516 0 stevel (void) memset(re_cb, 0, sizeof (re_cb)); 1517 0 stevel /* If resized smaller, make sure buffer NULL terminated */ 1518 0 stevel if (size < cb->cb_size) 1519 0 stevel re_cb[size] = 0; 1520 0 stevel cb->cb_buf = re_cb; 1521 0 stevel cb->cb_size = size; 1522 0 stevel return (PO_SUCCESS); 1523 0 stevel } 1524 0 stevel 1525 0 stevel /* 1526 0 stevel * Allocate a new char_buf_t structure. If there isn't enough memory, return 1527 0 stevel * NULL. Initialise the new char_buf_t to 0 and then call resize_char_buf 1528 0 stevel * to initialise the character buffer. Return a pointer to the new 1529 0 stevel * char_buf_t if the operation succeeds. 1530 0 stevel */ 1531 0 stevel char_buf_t * 1532 0 stevel alloc_char_buf(size_t size) 1533 0 stevel { 1534 0 stevel char_buf_t *cb; 1535 0 stevel 1536 0 stevel if ((cb = malloc(sizeof (char_buf_t))) == NULL) { 1537 0 stevel pool_seterror(POE_SYSTEM); 1538 0 stevel return (NULL); 1539 0 stevel } 1540 0 stevel (void) memset(cb, 0, sizeof (char_buf_t)); 1541 0 stevel 1542 0 stevel if (resize_char_buf(cb, size + 1) == PO_FAIL) { 1543 0 stevel free(cb); 1544 0 stevel return (NULL); 1545 0 stevel } 1546 0 stevel return (cb); 1547 0 stevel } 1548 0 stevel 1549 0 stevel /* 1550 0 stevel * Free the character buffer and then free the char_buf_t. 1551 0 stevel */ 1552 0 stevel void 1553 0 stevel free_char_buf(char_buf_t *cb) 1554 0 stevel { 1555 0 stevel free((void *)cb->cb_buf); 1556 0 stevel free(cb); 1557 0 stevel } 1558 0 stevel 1559 0 stevel /* 1560 0 stevel * Set the character buffer to the supplied data. The user supplies a printf 1561 0 stevel * like format string and then an appropriate number of parameters for the 1562 0 stevel * specified format. The character buffer is automatically resized to fit 1563 0 stevel * the data as determined by resize_char_buf. 1564 0 stevel */ 1565 0 stevel /*PRINTFLIKE2*/ 1566 0 stevel int 1567 0 stevel set_char_buf(char_buf_t *cb, const char *fmt, ...) 1568 0 stevel { 1569 0 stevel va_list ap; 1570 0 stevel int new_size; 1571 0 stevel 1572 0 stevel va_start(ap, fmt); 1573 0 stevel if ((new_size = vsnprintf(cb->cb_buf, cb->cb_size, fmt, ap)) >= 1574 0 stevel cb->cb_size) { 1575 0 stevel if (resize_char_buf(cb, new_size + 1) != PO_SUCCESS) { 1576 0 stevel pool_seterror(POE_SYSTEM); 1577 0 stevel return (PO_FAIL); 1578 0 stevel } 1579 0 stevel (void) vsnprintf(cb->cb_buf, cb->cb_size, fmt, ap); 1580 0 stevel } 1581 0 stevel va_end(ap); 1582 0 stevel return (PO_SUCCESS); 1583 0 stevel } 1584 0 stevel 1585 0 stevel /* 1586 0 stevel * Append the supplied data to the character buffer. The user supplies a printf 1587 0 stevel * like format string and then an appropriate number of parameters for the 1588 0 stevel * specified format. The character buffer is automatically resized to fit 1589 0 stevel * the data as determined by resize_char_buf. 1590 0 stevel */ 1591 0 stevel /*PRINTFLIKE2*/ 1592 0 stevel int 1593 0 stevel append_char_buf(char_buf_t *cb, const char *fmt, ...) 1594 0 stevel { 1595 0 stevel va_list ap; 1596 0 stevel int new_len; 1597 0 stevel char size_buf[1]; 1598 0 stevel int old_len = 0; 1599 0 stevel 1600 0 stevel if (cb->cb_buf != NULL) 1601 0 stevel old_len = strlen(cb->cb_buf); 1602 0 stevel va_start(ap, fmt); 1603 0 stevel new_len = vsnprintf(size_buf, sizeof (size_buf), fmt, ap); 1604 0 stevel if (new_len + old_len >= cb->cb_size) { 1605 0 stevel if (resize_char_buf(cb, old_len + new_len + 1) != 1606 0 stevel PO_SUCCESS) { 1607 0 stevel pool_seterror(POE_SYSTEM); 1608 0 stevel return (PO_FAIL); 1609 0 stevel } 1610 0 stevel } 1611 0 stevel /* 1612 0 stevel * Resized the buffer to the right size, now append the new data 1613 0 stevel */ 1614 0 stevel (void) vsnprintf(&cb->cb_buf[old_len], cb->cb_size - old_len, fmt, ap); 1615 0 stevel va_end(ap); 1616 0 stevel return (PO_SUCCESS); 1617 0 stevel } 1618 0 stevel 1619 0 stevel /* 1620 0 stevel * Return the class for the supplied elem. 1621 0 stevel * If the return is PEC_INVALID, the error code will be set to reflect cause. 1622 0 stevel */ 1623 0 stevel pool_elem_class_t 1624 0 stevel pool_elem_class(const pool_elem_t *elem) 1625 0 stevel { 1626 0 stevel return (elem->pe_class); 1627 0 stevel } 1628 0 stevel 1629 0 stevel 1630 0 stevel /* 1631 0 stevel * Return the resource class for the supplied elem. 1632 0 stevel */ 1633 0 stevel pool_resource_elem_class_t 1634 0 stevel pool_resource_elem_class(const pool_elem_t *elem) 1635 0 stevel { 1636 0 stevel return (elem->pe_resource_class); 1637 0 stevel } 1638 0 stevel 1639 0 stevel /* 1640 0 stevel * Return the component class for the supplied elem. 1641 0 stevel */ 1642 0 stevel pool_component_elem_class_t 1643 0 stevel pool_component_elem_class(const pool_elem_t *elem) 1644 0 stevel { 1645 0 stevel return (elem->pe_component_class); 1646 0 stevel } 1647 0 stevel 1648 0 stevel pool_elem_t * 1649 0 stevel pool_get_pair(const pool_elem_t *pe) 1650 0 stevel { 1651 0 stevel return (pe->pe_pair); 1652 0 stevel } 1653 0 stevel 1654 0 stevel void 1655 0 stevel pool_set_pair(pool_elem_t *pe1, pool_elem_t *pe2) 1656 0 stevel { 1657 0 stevel pe1->pe_pair = pe2; 1658 0 stevel } 1659 0 stevel 1660 0 stevel int 1661 0 stevel pool_validate_resource(const pool_conf_t *conf, const char *type, 1662 0 stevel const char *prop, int64_t delta) 1663 0 stevel { 1664 0 stevel pool_conf_t *dyn; 1665 0 stevel uint_t nelem; 1666 0 stevel uint64_t available, required, uval; 1667 0 stevel int i; 1668 0 stevel pool_resource_t **rl; 1669 0 stevel pool_value_t val = POOL_VALUE_INITIALIZER; 1670 0 stevel pool_value_t val1 = POOL_VALUE_INITIALIZER; 1671 0 stevel pool_value_t *pvals[] = { NULL, NULL }; 1672 0 stevel 1673 0 stevel if (strcmp(prop, c_min_prop) && strcmp(prop, c_max_prop)) { 1674 0 stevel pool_seterror(POE_BADPARAM); 1675 0 stevel return (PO_FAIL); 1676 0 stevel } 1677 0 stevel 1678 0 stevel pvals[0] = &val; 1679 0 stevel (void) pool_value_set_string(&val, type); 1680 0 stevel (void) pool_value_set_name(&val, c_type); 1681 0 stevel 1682 0 stevel /* 1683 0 stevel * Check that there are available resources on this 1684 0 stevel * system for this configuration to be applied. Find 1685 0 stevel * each resource type and then find all resources of 1686 0 stevel * each type and total ".min". Find all available 1687 0 stevel * resources and ensure >= total min. 1688 0 stevel */ 1689 0 stevel 1690 0 stevel available = 0; 1691 0 stevel required = delta; 1692 0 stevel 1693 0 stevel if ((rl = (pool_query_resources(conf, &nelem, pvals))) == NULL) 1694 0 stevel return (PO_FAIL); 1695 0 stevel 1696 0 stevel for (i = 0; i < nelem; i++) { 1697 0 stevel if (pool_get_ns_property(TO_ELEM(rl[i]), prop, 1698 0 stevel &val1) == POC_INVAL || 1699 0 stevel pool_value_get_uint64(&val1, &uval) != PO_SUCCESS) { 1700 0 stevel free(rl); 1701 0 stevel return (PO_FAIL); 1702 0 stevel } 1703 0 stevel /* 1704 0 stevel * Watch out for overflow 1705 0 stevel */ 1706 0 stevel if (required + uval < required) { 1707 0 stevel required = UINT64_MAX; 1708 0 stevel break; 1709 0 stevel } else 1710 0 stevel required += uval; 1711 0 stevel } 1712 0 stevel 1713 0 stevel if (conf_is_dynamic(conf) == PO_TRUE) { 1714 0 stevel dyn = (pool_conf_t *)conf; 1715 0 stevel } else { 1716 0 stevel free(rl); 1717 0 stevel if ((dyn = pool_conf_alloc()) == NULL) 1718 0 stevel return (PO_FAIL); 1719 0 stevel if (pool_conf_open(dyn, pool_dynamic_location(), PO_RDONLY) != 1720 0 stevel PO_SUCCESS) { 1721 0 stevel pool_conf_free(dyn); 1722 0 stevel return (PO_FAIL); 1723 0 stevel } 1724 0 stevel if ((rl = (pool_query_resources(dyn, &nelem, pvals))) == 1725 0 stevel NULL) { 1726 0 stevel (void) pool_conf_close(dyn); 1727 0 stevel pool_conf_free(dyn); 1728 0 stevel return (PO_FAIL); 1729 0 stevel } 1730 0 stevel } 1731 0 stevel for (i = 0; i < nelem; i++) { 1732 0 stevel if (pool_get_ns_property(TO_ELEM(rl[i]), c_size_prop, 1733 0 stevel &val1) == POC_INVAL || 1734 0 stevel pool_value_get_uint64(&val1, &uval) != PO_SUCCESS) { 1735 0 stevel free(rl); 1736 0 stevel if (conf != dyn) { 1737 0 stevel (void) pool_conf_close(dyn); 1738 0 stevel pool_conf_free(dyn); 1739 0 stevel } 1740 0 stevel return (PO_FAIL); 1741 0 stevel } 1742 0 stevel available += uval; 1743 0 stevel } 1744 0 stevel free(rl); 1745 0 stevel if (conf != dyn) { 1746 0 stevel (void) pool_conf_close(dyn); 1747 0 stevel pool_conf_free(dyn); 1748 0 stevel } 1749 0 stevel if (strcmp(prop, c_min_prop) == 0) { 1750 0 stevel if (available < required) { 1751 0 stevel pool_seterror(POE_INVALID_CONF); 1752 0 stevel return (PO_FAIL); 1753 0 stevel } 1754 0 stevel } else { 1755 0 stevel if (available > required) { 1756 0 stevel pool_seterror(POE_INVALID_CONF); 1757 0 stevel return (PO_FAIL); 1758 0 stevel } 1759 0 stevel } 1760 0 stevel return (PO_SUCCESS); 1761 0 stevel } 1762 0 stevel 1763 0 stevel /* 1764 0 stevel * If _libpool_debug is set, printf the debug message to stderr with an 1765 0 stevel * appropriate prefix in front of it. 1766 0 stevel */ 1767 0 stevel void 1768 0 stevel do_dprintf(const char *format, va_list ap) 1769 0 stevel { 1770 0 stevel if (_libpool_debug) { 1771 0 stevel (void) fputs("libpool DEBUG: ", stderr); 1772 0 stevel (void) vfprintf(stderr, format, ap); 1773 0 stevel } 1774 0 stevel } 1775 0 stevel 1776 0 stevel /*PRINTFLIKE1*/ 1777 0 stevel void 1778 0 stevel dprintf(const char *format, ...) 1779 0 stevel { 1780 0 stevel if (_libpool_debug) { 1781 0 stevel va_list alist; 1782 0 stevel va_start(alist, format); 1783 0 stevel do_dprintf(format, alist); 1784 0 stevel va_end(alist); 1785 0 stevel } 1786 0 stevel } 1787 0 stevel 1788 0 stevel /* 1789 0 stevel * log_alloc() allocates a new, empty transaction log. 1790 0 stevel * 1791 0 stevel * Returns a pointer to the new log or NULL on failure. 1792 0 stevel */ 1793 0 stevel log_t * 1794 0 stevel log_alloc(pool_conf_t *conf) 1795 0 stevel { 1796 0 stevel log_t *l; 1797 0 stevel 1798 0 stevel if ((l = calloc(1, sizeof (log_t))) == NULL) { 1799 0 stevel pool_seterror(POE_SYSTEM); 1800 0 stevel return (NULL); 1801 0 stevel } 1802 0 stevel l->l_state = LS_DO; 1803 0 stevel l->l_conf = conf; 1804 0 stevel if ((l->l_sentinel = log_item_alloc(l, 0, NULL)) 1805 0 stevel == NULL) { 1806 0 stevel free(l); 1807 0 stevel pool_seterror(POE_SYSTEM); 1808 0 stevel return (NULL); 1809 0 stevel } 1810 0 stevel l->l_sentinel->li_next = l->l_sentinel; 1811 0 stevel l->l_sentinel->li_prev = l->l_sentinel; 1812 0 stevel 1813 0 stevel return (l); 1814 0 stevel } 1815 0 stevel 1816 0 stevel /* 1817 0 stevel * log_free() reclaims the resources associated with a transaction log. 1818 0 stevel */ 1819 0 stevel void 1820 0 stevel log_free(log_t *l) 1821 0 stevel { 1822 0 stevel (void) log_walk(l, log_item_free); 1823 0 stevel (void) log_item_free(l->l_sentinel); 1824 0 stevel free(l); 1825 0 stevel } 1826 0 stevel /* 1827 0 stevel * log_empty() removes all items from a transaction log. It is the 1828 0 stevel * users responsibility to ensure that any resources associated with 1829 0 stevel * an item are reclaimed before this function is invoked. 1830 0 stevel */ 1831 0 stevel void 1832 0 stevel log_empty(log_t *l) 1833 0 stevel { 1834 0 stevel (void) log_walk(l, log_item_free); 1835 0 stevel } 1836 0 stevel 1837 0 stevel /* 1838 0 stevel * log_walk() visits each log item in turn and executes the supplied action 1839 0 stevel * using the item as a parameter. If no action is supplied, then the item 1840 0 stevel * uses it's own stored action. 1841 0 stevel * 1842 0 stevel * Returns PO_SUCCESS/PO_FAIL 1843 0 stevel */ 1844 0 stevel int 1845 0 stevel log_walk(log_t *l, log_item_action_t action) 1846 0 stevel { 1847 0 stevel log_item_t *li, *li_next; 1848 0 stevel 1849 0 stevel li = l->l_sentinel->li_next; 1850 0 stevel while (li != l->l_sentinel) { 1851 0 stevel li_next = li->li_next; 1852 0 stevel if ((action(li)) != PO_SUCCESS) 1853 0 stevel return (PO_FAIL); 1854 0 stevel li = li_next; 1855 0 stevel } 1856 0 stevel return (PO_SUCCESS); 1857 0 stevel } 1858 0 stevel 1859 0 stevel /* 1860 0 stevel * log_reverse_walk() visits each log item in turn (in reverse order) 1861 0 stevel * and executes the supplied action using the item as a parameter. 1862 0 stevel * 1863 0 stevel * Returns PO_SUCCESS/PO_FAIL 1864 0 stevel */ 1865 0 stevel int 1866 0 stevel log_reverse_walk(log_t *l, log_item_action_t action) 1867 0 stevel { 1868 0 stevel log_item_t *li, *li_prev; 1869 0 stevel 1870 0 stevel li = l->l_sentinel->li_prev; 1871 0 stevel while (li != l->l_sentinel) { 1872 0 stevel li_prev = li->li_prev; 1873 0 stevel if ((action(li)) != PO_SUCCESS) 1874 0 stevel return (PO_FAIL); 1875 0 stevel li = li_prev; 1876 0 stevel } 1877 0 stevel return (PO_SUCCESS); 1878 0 stevel } 1879 0 stevel 1880 0 stevel /* 1881 0 stevel * log_size() returns the size of the log, i.e. the number of items pending in 1882 0 stevel * the log. 1883 0 stevel */ 1884 0 stevel uint_t 1885 0 stevel log_size(log_t *l) 1886 0 stevel { 1887 0 stevel log_item_t *li; 1888 0 stevel uint_t size = 0; 1889 0 stevel 1890 0 stevel for (li = l->l_sentinel->li_next; li != l->l_sentinel; li = li->li_next) 1891 0 stevel size++; 1892 0 stevel return (size); 1893 0 stevel } 1894 0 stevel 1895 0 stevel /* 1896 0 stevel * log_append() allocates a new log item to hold the supplied details and 1897 0 stevel * appends the newly created item to the supplied log. 1898 0 stevel * 1899 0 stevel * Returns PO_SUCCESS/PO_FAIL 1900 0 stevel */ 1901 0 stevel int 1902 0 stevel log_append(log_t *l, int op, void *details) 1903 0 stevel { 1904 0 stevel log_item_t *li; 1905 0 stevel 1906 0 stevel if ((li = log_item_alloc(l, op, details)) == NULL) { 1907 0 stevel l->l_state = LS_UNDO; 1908 0 stevel return (PO_FAIL); 1909 0 stevel } 1910 0 stevel /* 1911 0 stevel * Link it in 1912 0 stevel */ 1913 0 stevel li->li_prev = l->l_sentinel->li_prev; 1914 0 stevel li->li_next = l->l_sentinel; 1915 0 stevel l->l_sentinel->li_prev->li_next = li; 1916 0 stevel l->l_sentinel->li_prev = li; 1917 0 stevel return (PO_SUCCESS); 1918 0 stevel } 1919 0 stevel 1920 0 stevel /* 1921 0 stevel * log_item_alloc() allocates a new transaction log item. The item should be 1922 0 stevel * used to store details about a transaction which may need to be undone if 1923 0 stevel * commit processing fails. 1924 0 stevel * 1925 0 stevel * Returns a pointer to a new transaction log item or NULL. 1926 0 stevel */ 1927 0 stevel log_item_t * 1928 0 stevel log_item_alloc(log_t *l, int op, void *details) 1929 0 stevel { 1930 0 stevel log_item_t *li; 1931 0 stevel 1932 0 stevel if ((li = malloc(sizeof (log_item_t))) == NULL) { 1933 0 stevel pool_seterror(POE_SYSTEM); 1934 0 stevel return (NULL); 1935 0 stevel } 1936 0 stevel 1937 0 stevel (void) memset(li, 0, sizeof (log_item_t)); 1938 0 stevel li->li_log = l; 1939 0 stevel li->li_op = op; 1940 0 stevel li->li_details = details; 1941 0 stevel li->li_state = LS_DO; 1942 0 stevel 1943 0 stevel return (li); 1944 0 stevel } 1945 0 stevel 1946 0 stevel /* 1947 0 stevel * log_item_free() reclaims the resources associated with a log_item_t. 1948 0 stevel */ 1949 0 stevel int 1950 0 stevel log_item_free(log_item_t *li) 1951 0 stevel { 1952 0 stevel li->li_prev->li_next = li->li_next; 1953 0 stevel li->li_next->li_prev = li->li_prev; 1954 0 stevel free(li); 1955 0 stevel return (PO_SUCCESS); 1956 0 stevel } 1957 0 stevel 1958 0 stevel /* 1959 0 stevel * atom_string() checks the string table to see if a string is already 1960 0 stevel * stored. If it is, return a pointer to it. If not, duplicate the 1961 0 stevel * string and return a pointer to the duplicate. 1962 0 stevel */ 1963 0 stevel const char * 1964 0 stevel atom_string(const char *s) 1965 0 stevel { 1966 0 stevel atom_t *atom; 1967 0 stevel 1968 0 stevel /* 1969 0 stevel * atom_init() must have completed successfully 1970 0 stevel */ 1971 0 stevel atom_init(); 1972 0 stevel (void) mutex_lock(&_atom_lock); 1973 0 stevel if ((atom = dict_get(_pv_atoms, s)) == NULL) { 1974 0 stevel if ((atom = calloc(1, sizeof (atom_t))) == NULL) { 1975 0 stevel pool_seterror(POE_SYSTEM); 1976 0 stevel (void) mutex_unlock(&_atom_lock); 1977 0 stevel return (NULL); 1978 0 stevel } 1979 0 stevel if ((atom->a_string = strdup(s)) == NULL) { 1980 0 stevel (void) mutex_unlock(&_atom_lock); 1981 0 stevel free(atom); 1982 0 stevel pool_seterror(POE_SYSTEM); 1983 0 stevel return (NULL); 1984 0 stevel } 1985 0 stevel (void) dict_put(_pv_atoms, atom->a_string, atom); 1986 0 stevel } 1987 0 stevel atom->a_count++; 1988 0 stevel (void) mutex_unlock(&_atom_lock); 1989 0 stevel return (atom->a_string); 1990 0 stevel } 1991 0 stevel 1992 0 stevel /* 1993 0 stevel * atom_free() decrements the reference count for the supplied 1994 0 stevel * string. If the reference count reaches zero, then the atom is 1995 0 stevel * destroyed. 1996 0 stevel */ 1997 0 stevel void 1998 0 stevel atom_free(const char *s) 1999 0 stevel { 2000 0 stevel atom_t *atom; 2001 0 stevel 2002 0 stevel (void) mutex_lock(&_atom_lock); 2003 0 stevel if ((atom = dict_get(_pv_atoms, s)) != NULL) { 2004 0 stevel if (--atom->a_count == 0) { 2005 0 stevel (void) dict_remove(_pv_atoms, s); 2006 0 stevel free(atom->a_string); 2007 0 stevel free(atom); 2008 0 stevel } 2009 0 stevel } 2010 0 stevel (void) mutex_unlock(&_atom_lock); 2011 0 stevel } 2012 0 stevel 2013 0 stevel #ifdef DEBUG 2014 0 stevel /* 2015 0 stevel * log_item_dprintf() prints the contents of the supplied log item using the 2016 0 stevel * pools dprintf() trace mechanism. 2017 0 stevel * 2018 0 stevel * Returns PO_SUCCESS 2019 0 stevel */ 2020 0 stevel void 2021 0 stevel log_item_dprintf(log_item_t *li) 2022 0 stevel { 2023 0 stevel dprintf("LOGDUMP: %d operation, %p\n", li->li_op, li->li_details); 2024 0 stevel } 2025 0 stevel 2026 0 stevel /* 2027 0 stevel * log_item_dprintf() prints the contents of the supplied log item using the 2028 0 stevel * pools dprintf() trace mechanism. 2029 0 stevel * 2030 0 stevel * Returns PO_SUCCESS 2031 0 stevel */ 2032 0 stevel void 2033 0 stevel pool_elem_dprintf(const pool_elem_t *pe) 2034 0 stevel { 2035 0 stevel if (pool_elem_class(pe) != PEC_COMP) { 2036 0 stevel const char *name = elem_get_name(pe); 2037 0 stevel dprintf("element type: %s name: %s\n", 2038 0 stevel pool_elem_class_string(pe), name); 2039 0 stevel free((void *)name); 2040 0 stevel } else { 2041 0 stevel id_t sys_id = elem_get_sysid(pe); 2042 0 stevel dprintf("element type: %s sys_id: %d\n", 2043 0 stevel pool_elem_class_string(pe), sys_id); 2044 0 stevel } 2045 0 stevel } 2046 0 stevel #endif /* DEBUG */ 2047