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