Home | History | Annotate | Download | only in common
      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