xref: /onnv-gate/usr/src/lib/libpool/common/pool_internal.c (revision 3247:e05001c14ea2)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*3247Sgjelinek  * Common Development and Distribution License (the "License").
6*3247Sgjelinek  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*3247Sgjelinek  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <limits.h>
290Sstevel@tonic-gate #include <pool.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <synch.h>
340Sstevel@tonic-gate #include <thread.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <sys/loadavg.h>
370Sstevel@tonic-gate #include <sys/types.h>
380Sstevel@tonic-gate #include <sys/utsname.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include "dict.h"
410Sstevel@tonic-gate #include "pool_internal.h"
420Sstevel@tonic-gate #include "pool_impl.h"
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
450Sstevel@tonic-gate  * Atom structure, used to reference count string atoms.
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate typedef struct {
480Sstevel@tonic-gate 	char *a_string;				/* String atom */
490Sstevel@tonic-gate 	uint_t a_count;				/* String reference count */
500Sstevel@tonic-gate } atom_t;
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate  * The _internal_lock is used to lock the state of libpool during
540Sstevel@tonic-gate  * internal initialisation operations.
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate mutex_t		_internal_lock;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate static int _libpool_debug = 0;			/* debugging messages */
590Sstevel@tonic-gate static dict_hdl_t *_pv_atoms;			/* pool_value_t atoms */
600Sstevel@tonic-gate static mutex_t _atom_lock;			/* atom table lock */
610Sstevel@tonic-gate static int _libpool_internal_initialised = PO_FALSE;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate  * Various useful constant strings which are often encountered
650Sstevel@tonic-gate  */
660Sstevel@tonic-gate const char *c_a_dtype = "a-dtype";
670Sstevel@tonic-gate const char *c_name = "name";
680Sstevel@tonic-gate const char *c_type = "type";
690Sstevel@tonic-gate const char *c_ref_id = "ref_id";
700Sstevel@tonic-gate const char *c_max_prop = "max";
710Sstevel@tonic-gate const char *c_min_prop = "min";
720Sstevel@tonic-gate const char *c_size_prop = "size";
730Sstevel@tonic-gate const char *c_sys_prop = "sys_id";
740Sstevel@tonic-gate 
750Sstevel@tonic-gate /*
760Sstevel@tonic-gate  * prop_is_type() checks the supplied property and returns PO_TRUE if the
770Sstevel@tonic-gate  * property value is set for the property else PO_FALSE
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate static int prop_is_type(int, const pool_prop_t *);
800Sstevel@tonic-gate static int resource_get_common(const pool_resource_t *, const char *,
810Sstevel@tonic-gate     uint64_t *);
820Sstevel@tonic-gate static int64_t elem_get_expected_int64(const pool_elem_t *, const char *);
830Sstevel@tonic-gate 
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate  * The following returns a malloc'ed string which must be free'd by the
860Sstevel@tonic-gate  * caller.
870Sstevel@tonic-gate  */
880Sstevel@tonic-gate static char *elem_get_expected_string(const pool_elem_t *, const char *);
890Sstevel@tonic-gate static int element_props_init(pool_prop_t *);
900Sstevel@tonic-gate 
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate  * Each element class/sub-class has a set of properties and behaviours
930Sstevel@tonic-gate  * which are used to create the element with appropriate property
940Sstevel@tonic-gate  * values and to ensure correct property manipulations. The details
950Sstevel@tonic-gate  * are all stored in the following arrays.
960Sstevel@tonic-gate  */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate static int elem_name_init(pool_prop_t *);
990Sstevel@tonic-gate static int elem_comment_init(pool_prop_t *);
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate static int pool_importance_init(pool_prop_t *);
1020Sstevel@tonic-gate static int pool_active_init(pool_prop_t *);
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate static int res_max_init(pool_prop_t *);
1050Sstevel@tonic-gate static int res_min_init(pool_prop_t *);
1060Sstevel@tonic-gate static int res_size_init(pool_prop_t *);
1070Sstevel@tonic-gate static int res_load_init(pool_prop_t *);
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate static int pset_units_init(pool_prop_t *);
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate static int cpu_status_init(pool_prop_t *);
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate static int elem_no_set(pool_elem_t *, const pool_value_t *);
1140Sstevel@tonic-gate static int elem_set_name(pool_elem_t *, const pool_value_t *);
1150Sstevel@tonic-gate static int elem_get_type(const pool_elem_t *, pool_value_t *);
1160Sstevel@tonic-gate static int elem_set_string(pool_elem_t *, const pool_value_t *);
1170Sstevel@tonic-gate static int elem_set_bool(pool_elem_t *, const pool_value_t *);
1180Sstevel@tonic-gate static int elem_set_uint(pool_elem_t *, const pool_value_t *);
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate static int system_set_allocate(pool_elem_t *, const pool_value_t *);
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate static int pool_set_scheduler(pool_elem_t *, const pool_value_t *);
1230Sstevel@tonic-gate static int pool_set_active(pool_elem_t *, const pool_value_t *);
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate static int res_set_max(pool_elem_t *, const pool_value_t *);
1260Sstevel@tonic-gate static int res_set_min(pool_elem_t *, const pool_value_t *);
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate static int cpu_set_status(pool_elem_t *, const pool_value_t *);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate static const char *pool_elem_class_name[] = {
1310Sstevel@tonic-gate 	"invalid",
1320Sstevel@tonic-gate 	"system",
1330Sstevel@tonic-gate 	"pool",
1340Sstevel@tonic-gate 	"component resource",
1350Sstevel@tonic-gate 	"aggregate resource",
1360Sstevel@tonic-gate 	"component"
1370Sstevel@tonic-gate };
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate /*
1400Sstevel@tonic-gate  * This must be kept in sync with the pool_resource_elem_ctl array and
1410Sstevel@tonic-gate  * the "enum pool_resource_elem_class" type.
1420Sstevel@tonic-gate  */
1430Sstevel@tonic-gate static const char *pool_resource_elem_class_name[] = {
1440Sstevel@tonic-gate 	"invalid",
1450Sstevel@tonic-gate 	"pset"
1460Sstevel@tonic-gate };
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate static const char *pool_component_elem_class_name[] = {
1490Sstevel@tonic-gate 	"invalid",
1500Sstevel@tonic-gate 	"cpu"
1510Sstevel@tonic-gate };
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate static pool_prop_t system_props[] = {
1540Sstevel@tonic-gate 	{ "system.name", POOL_VALUE_INITIALIZER, PP_STORED, NULL,
1550Sstevel@tonic-gate 	    { NULL, elem_set_name } },
1560Sstevel@tonic-gate 	{ "system.ref_id", POOL_VALUE_INITIALIZER,
1570Sstevel@tonic-gate 	    PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
1580Sstevel@tonic-gate 	{ "system.comment", POOL_VALUE_INITIALIZER, PP_STORED, NULL, NULL },
1590Sstevel@tonic-gate 	{ "system.version", POOL_VALUE_INITIALIZER,
1600Sstevel@tonic-gate 	    PP_STORED | PP_READ, NULL, NULL },
1610Sstevel@tonic-gate 	{ "system.bind-default", POOL_VALUE_INITIALIZER,
1620Sstevel@tonic-gate 	    PP_STORED, NULL, NULL },
1630Sstevel@tonic-gate 	{ "system.allocate-method", POOL_VALUE_INITIALIZER,
1640Sstevel@tonic-gate 	    PP_STORED | PP_OPTIONAL, NULL, { NULL, system_set_allocate } },
1650Sstevel@tonic-gate 	{ "system.poold.log-level", POOL_VALUE_INITIALIZER,
1660Sstevel@tonic-gate 	    PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
1670Sstevel@tonic-gate 	{ "system.poold.log-location", POOL_VALUE_INITIALIZER,
1680Sstevel@tonic-gate 	    PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
1690Sstevel@tonic-gate 	{ "system.poold.monitor-interval", POOL_VALUE_INITIALIZER,
1700Sstevel@tonic-gate 	    PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_uint } },
1710Sstevel@tonic-gate 	{ "system.poold.history-file", POOL_VALUE_INITIALIZER,
1720Sstevel@tonic-gate 	    PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
1730Sstevel@tonic-gate 	{ "system.poold.objectives", POOL_VALUE_INITIALIZER,
1740Sstevel@tonic-gate 	    PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
1750Sstevel@tonic-gate 	NULL
1760Sstevel@tonic-gate };
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate static pool_prop_t pool_props[] = {
1790Sstevel@tonic-gate 	{ "pool.sys_id", POOL_VALUE_INITIALIZER,
1800Sstevel@tonic-gate 	    PP_STORED | PP_READ, NULL, NULL },
1810Sstevel@tonic-gate 	{ "pool.name", POOL_VALUE_INITIALIZER,
1820Sstevel@tonic-gate 	    PP_STORED | PP_INIT, elem_name_init, { NULL, elem_set_name } },
1830Sstevel@tonic-gate 	{ "pool.res", POOL_VALUE_INITIALIZER,
1840Sstevel@tonic-gate 	    PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
1850Sstevel@tonic-gate 	{ "pool.ref_id", POOL_VALUE_INITIALIZER,
1860Sstevel@tonic-gate 	    PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
1870Sstevel@tonic-gate 	{ "pool.active", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
1880Sstevel@tonic-gate 	    pool_active_init, { NULL, pool_set_active } },
1890Sstevel@tonic-gate 	{ "pool.default", POOL_VALUE_INITIALIZER,
1900Sstevel@tonic-gate 	    PP_STORED | PP_READ, NULL, NULL },
1910Sstevel@tonic-gate 	{ "pool.scheduler", POOL_VALUE_INITIALIZER,
1920Sstevel@tonic-gate 	    PP_STORED | PP_OPTIONAL, NULL,
1930Sstevel@tonic-gate 	    { NULL, pool_set_scheduler } },
1940Sstevel@tonic-gate 	{ "pool.importance", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
1950Sstevel@tonic-gate 	    pool_importance_init, NULL },
1960Sstevel@tonic-gate 	{ "pool.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
1970Sstevel@tonic-gate 	    elem_comment_init, NULL },
1980Sstevel@tonic-gate 	NULL
1990Sstevel@tonic-gate };
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate static pool_prop_t pset_props[] = {
2020Sstevel@tonic-gate 	{ "type", POOL_VALUE_INITIALIZER, PP_HIDDEN | PP_STORED | PP_READ, NULL,
2030Sstevel@tonic-gate 	    { elem_get_type, NULL }  },
2040Sstevel@tonic-gate 	{ "pset.sys_id", POOL_VALUE_INITIALIZER,
2050Sstevel@tonic-gate 	    PP_STORED | PP_READ, NULL, NULL },
2060Sstevel@tonic-gate 	{ "pset.name", POOL_VALUE_INITIALIZER,
2070Sstevel@tonic-gate 	    PP_STORED | PP_INIT, elem_name_init, { NULL, elem_set_name } },
2080Sstevel@tonic-gate 	{ "pset.ref_id", POOL_VALUE_INITIALIZER,
2090Sstevel@tonic-gate 	    PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
2100Sstevel@tonic-gate 	{ "pset.default", POOL_VALUE_INITIALIZER,
2110Sstevel@tonic-gate 	    PP_STORED | PP_READ, NULL, NULL },
2120Sstevel@tonic-gate 	{ "pset.min", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, res_min_init,
2130Sstevel@tonic-gate 	    { NULL, res_set_min } },
2140Sstevel@tonic-gate 	{ "pset.max", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, res_max_init,
2150Sstevel@tonic-gate 	    { NULL, res_set_max } },
2160Sstevel@tonic-gate 	{ "pset.units", POOL_VALUE_INITIALIZER,
2170Sstevel@tonic-gate 	    PP_STORED | PP_INIT, pset_units_init, NULL },
2180Sstevel@tonic-gate 	{ "pset.load", POOL_VALUE_INITIALIZER, PP_READ | PP_INIT,
2190Sstevel@tonic-gate 	    res_load_init, NULL },
2200Sstevel@tonic-gate 	{ "pset.size", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT | PP_READ,
2210Sstevel@tonic-gate 	    res_size_init, NULL },
2220Sstevel@tonic-gate 	{ "pset.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
2230Sstevel@tonic-gate 	    elem_comment_init, NULL },
2240Sstevel@tonic-gate 	{ "pset.poold.objectives", POOL_VALUE_INITIALIZER,
2250Sstevel@tonic-gate 	    PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
2260Sstevel@tonic-gate 	NULL
2270Sstevel@tonic-gate };
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate static pool_prop_t cpu_props[] = {
2300Sstevel@tonic-gate 	{ "type", POOL_VALUE_INITIALIZER, PP_HIDDEN | PP_STORED | PP_READ, NULL,
2310Sstevel@tonic-gate 	    { elem_get_type, NULL }  },
2320Sstevel@tonic-gate 	{ "cpu.sys_id", POOL_VALUE_INITIALIZER, PP_STORED | PP_READ, NULL,
2330Sstevel@tonic-gate 	    NULL },
2340Sstevel@tonic-gate 	{ "cpu.ref_id", POOL_VALUE_INITIALIZER,
2350Sstevel@tonic-gate 	    PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
2360Sstevel@tonic-gate 	{ "cpu.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
2370Sstevel@tonic-gate 	    elem_comment_init, NULL },
2380Sstevel@tonic-gate 	{ "cpu.status", POOL_VALUE_INITIALIZER, PP_INIT, cpu_status_init,
2390Sstevel@tonic-gate 	    { NULL, cpu_set_status } },
2400Sstevel@tonic-gate 	{ "cpu.pinned", POOL_VALUE_INITIALIZER, PP_STORED | PP_OPTIONAL, NULL,
2410Sstevel@tonic-gate 	    { NULL, elem_set_bool } },
2420Sstevel@tonic-gate 	NULL
2430Sstevel@tonic-gate };
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate static pool_prop_t *pool_elem_ctl[] = {
2460Sstevel@tonic-gate 	NULL,
2470Sstevel@tonic-gate 	system_props,
2480Sstevel@tonic-gate 	pool_props,
2490Sstevel@tonic-gate 	NULL,
2500Sstevel@tonic-gate 	NULL,
2510Sstevel@tonic-gate 	NULL
2520Sstevel@tonic-gate };
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate /*
2550Sstevel@tonic-gate  * This must be kept in sync with the pool_resource_elem_class_name array and
2560Sstevel@tonic-gate  * the "enum pool_resource_elem_class" type.
2570Sstevel@tonic-gate  */
2580Sstevel@tonic-gate static pool_prop_t *pool_resource_elem_ctl[] = {
2590Sstevel@tonic-gate 	NULL,
2600Sstevel@tonic-gate 	pset_props
2610Sstevel@tonic-gate };
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate static pool_prop_t *pool_component_elem_ctl[] = {
2640Sstevel@tonic-gate 	NULL,
2650Sstevel@tonic-gate 	cpu_props
2660Sstevel@tonic-gate };
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate static void
atom_init(void)2690Sstevel@tonic-gate atom_init(void)
2700Sstevel@tonic-gate {
2710Sstevel@tonic-gate 	(void) mutex_lock(&_atom_lock);
2720Sstevel@tonic-gate 	/*
2730Sstevel@tonic-gate 	 * Initialize pool_value_t atom dictionary
2740Sstevel@tonic-gate 	 */
2750Sstevel@tonic-gate 	if (_pv_atoms == NULL)
2760Sstevel@tonic-gate 		if ((_pv_atoms = dict_new((int (*)(const void *, const void *))
2770Sstevel@tonic-gate 		    strcmp, (uint64_t (*)(const void *))hash_str)) == NULL)
2780Sstevel@tonic-gate 			abort();
2790Sstevel@tonic-gate 	(void) mutex_unlock(&_atom_lock);
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate /*
2830Sstevel@tonic-gate  * Initializer, called when the library is initialized.
2840Sstevel@tonic-gate  */
2850Sstevel@tonic-gate void
internal_init(void)2860Sstevel@tonic-gate internal_init(void)
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate 	(void) mutex_lock(&_internal_lock);
2890Sstevel@tonic-gate 	if (_libpool_internal_initialised == PO_TRUE) {
2900Sstevel@tonic-gate 		(void) mutex_unlock(&_internal_lock);
2910Sstevel@tonic-gate 		return;
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 	atom_init();
2940Sstevel@tonic-gate 	/*
2950Sstevel@tonic-gate 	 * Initialize all available property arrays.
2960Sstevel@tonic-gate 	 */
2970Sstevel@tonic-gate 	if (element_props_init(system_props) == PO_FAIL)
2980Sstevel@tonic-gate 		abort();
2990Sstevel@tonic-gate 	if (element_props_init(pool_props) == PO_FAIL)
3000Sstevel@tonic-gate 		abort();
3010Sstevel@tonic-gate 	if (element_props_init(pset_props) == PO_FAIL)
3020Sstevel@tonic-gate 		abort();
3030Sstevel@tonic-gate 	if (element_props_init(cpu_props) == PO_FAIL)
3040Sstevel@tonic-gate 		abort();
3050Sstevel@tonic-gate 	_libpool_internal_initialised = PO_TRUE;
3060Sstevel@tonic-gate 	(void) mutex_unlock(&_internal_lock);
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate static int
element_props_init(pool_prop_t * props)3110Sstevel@tonic-gate element_props_init(pool_prop_t *props)
3120Sstevel@tonic-gate {
3130Sstevel@tonic-gate 	int i;
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	for (i = 0; props[i].pp_pname != NULL; i++) {
3160Sstevel@tonic-gate 		/*
3170Sstevel@tonic-gate 		 * Initialise each of the properties
3180Sstevel@tonic-gate 		 */
3190Sstevel@tonic-gate 		if (pool_value_set_name(&props[i].pp_value,
3200Sstevel@tonic-gate 		    props[i].pp_pname) != PO_SUCCESS) {
3210Sstevel@tonic-gate 			return (PO_FAIL);
3220Sstevel@tonic-gate 		}
3230Sstevel@tonic-gate 		if (props[i].pp_init &&
3240Sstevel@tonic-gate 		    props[i].pp_init(&props[i]) != PO_SUCCESS) {
3250Sstevel@tonic-gate 			return (PO_FAIL);
3260Sstevel@tonic-gate 		}
3270Sstevel@tonic-gate 	}
3280Sstevel@tonic-gate 	return (PO_SUCCESS);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate /*
3330Sstevel@tonic-gate  * These functions intialise the properties of this plugin. The only reason
3340Sstevel@tonic-gate  * they exist is because the ability to perform the static initialisation of
3350Sstevel@tonic-gate  * union members properly was only introduced in the C99 standard. i.e. if you
3360Sstevel@tonic-gate  * could do {.f = 1.0} like in the proposed C99 standard then that would
3370Sstevel@tonic-gate  * be the preferred way to do this as it keeps the data in the array and
3380Sstevel@tonic-gate  * minimises the scope for errors. However, until that time these functions
3390Sstevel@tonic-gate  * are the best way to minimise the scope for errors and to maximise
3400Sstevel@tonic-gate  * maintainability.
3410Sstevel@tonic-gate  *
3420Sstevel@tonic-gate  * There is one function for each property, and the initial value for each
3430Sstevel@tonic-gate  * property is hard-coded into each function.
3440Sstevel@tonic-gate  */
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate static int
elem_name_init(pool_prop_t * prop)3470Sstevel@tonic-gate elem_name_init(pool_prop_t *prop)
3480Sstevel@tonic-gate {
3490Sstevel@tonic-gate 	return (string_init(prop, "default"));
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate static int
elem_comment_init(pool_prop_t * prop)3530Sstevel@tonic-gate elem_comment_init(pool_prop_t *prop)
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate 	return (string_init(prop, ""));
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate static int
pool_importance_init(pool_prop_t * prop)3590Sstevel@tonic-gate pool_importance_init(pool_prop_t *prop)
3600Sstevel@tonic-gate {
3610Sstevel@tonic-gate 	return (int_init(prop, 1));
3620Sstevel@tonic-gate }
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate static int
pool_active_init(pool_prop_t * prop)3650Sstevel@tonic-gate pool_active_init(pool_prop_t *prop)
3660Sstevel@tonic-gate {
3670Sstevel@tonic-gate 	return (bool_init(prop, PO_TRUE));
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate static int
res_max_init(pool_prop_t * prop)3710Sstevel@tonic-gate res_max_init(pool_prop_t *prop)
3720Sstevel@tonic-gate {
3730Sstevel@tonic-gate 	return (uint_init(prop, 0));
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate static int
res_min_init(pool_prop_t * prop)3770Sstevel@tonic-gate res_min_init(pool_prop_t *prop)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate 	return (uint_init(prop, 0));
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate static int
res_size_init(pool_prop_t * prop)3830Sstevel@tonic-gate res_size_init(pool_prop_t *prop)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	return (uint_init(prop, 0));
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate static int
res_load_init(pool_prop_t * prop)3890Sstevel@tonic-gate res_load_init(pool_prop_t *prop)
3900Sstevel@tonic-gate {
3910Sstevel@tonic-gate 	return (uint_init(prop, 0));
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate static int
pset_units_init(pool_prop_t * prop)3950Sstevel@tonic-gate pset_units_init(pool_prop_t *prop)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate 	return (string_init(prop, "population"));
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate static int
cpu_status_init(pool_prop_t * prop)4010Sstevel@tonic-gate cpu_status_init(pool_prop_t *prop)
4020Sstevel@tonic-gate {
4030Sstevel@tonic-gate 	return (string_init(prop, PS_ONLINE));
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate /*
4070Sstevel@tonic-gate  * Individual property manipulation routines for use by the generic
4080Sstevel@tonic-gate  * get/put property routines
4090Sstevel@tonic-gate  */
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate /*
4120Sstevel@tonic-gate  * Many properties cannot be modified. This function prevents property
4130Sstevel@tonic-gate  * modification.
4140Sstevel@tonic-gate  */
4150Sstevel@tonic-gate /* ARGSUSED */
4160Sstevel@tonic-gate static int
elem_no_set(pool_elem_t * elem,const pool_value_t * pval)4170Sstevel@tonic-gate elem_no_set(pool_elem_t *elem, const pool_value_t *pval)
4180Sstevel@tonic-gate {
4190Sstevel@tonic-gate 	return (PO_FAIL);
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate /*
4230Sstevel@tonic-gate  * Duplicate names for a pool or resource type are illegal.
4240Sstevel@tonic-gate  */
4250Sstevel@tonic-gate static int
elem_set_name(pool_elem_t * elem,const pool_value_t * pval)4260Sstevel@tonic-gate elem_set_name(pool_elem_t *elem, const pool_value_t *pval)
4270Sstevel@tonic-gate {
4280Sstevel@tonic-gate 	const char *nm;
4290Sstevel@tonic-gate 	pool_t *pool;
4300Sstevel@tonic-gate 	pool_resource_t *res;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	if (pool_value_get_string(pval, &nm) != PO_SUCCESS) {
4330Sstevel@tonic-gate 		return (PO_FAIL);
4340Sstevel@tonic-gate 	}
4350Sstevel@tonic-gate 	if (!is_valid_name(nm)) {
4360Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
4370Sstevel@tonic-gate 		return (PO_FAIL);
4380Sstevel@tonic-gate 	}
4390Sstevel@tonic-gate 	switch (pool_elem_class(elem)) {
4400Sstevel@tonic-gate 	case PEC_SYSTEM:
4410Sstevel@tonic-gate 		break;
4420Sstevel@tonic-gate 	case PEC_POOL:
4430Sstevel@tonic-gate 		pool = pool_get_pool(TO_CONF(elem), nm);
4440Sstevel@tonic-gate 		if (pool != NULL && pool != pool_elem_pool(elem)) {
4450Sstevel@tonic-gate 			pool_seterror(POE_PUTPROP);
4460Sstevel@tonic-gate 			return (PO_FAIL);
4470Sstevel@tonic-gate 		}
4480Sstevel@tonic-gate 		break;
4490Sstevel@tonic-gate 	case PEC_RES_COMP:
4500Sstevel@tonic-gate 	case PEC_RES_AGG:
4510Sstevel@tonic-gate 		res = pool_get_resource(TO_CONF(elem),
4520Sstevel@tonic-gate 		    pool_elem_class_string(elem), nm);
4530Sstevel@tonic-gate 		if (res != NULL && res != pool_elem_res(elem)) {
4540Sstevel@tonic-gate 			pool_seterror(POE_PUTPROP);
4550Sstevel@tonic-gate 			return (PO_FAIL);
4560Sstevel@tonic-gate 		}
4570Sstevel@tonic-gate 		break;
4580Sstevel@tonic-gate 	default:
4590Sstevel@tonic-gate 		return (PO_FAIL);
4600Sstevel@tonic-gate 	}
4610Sstevel@tonic-gate 	return (PO_SUCCESS);
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate /*
4650Sstevel@tonic-gate  * Ensure the type is a string.
4660Sstevel@tonic-gate  */
4670Sstevel@tonic-gate /* ARGSUSED */
4680Sstevel@tonic-gate static int
elem_set_string(pool_elem_t * elem,const pool_value_t * pval)4690Sstevel@tonic-gate elem_set_string(pool_elem_t *elem, const pool_value_t *pval)
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate 	if (pool_value_get_type(pval) == POC_STRING)
4720Sstevel@tonic-gate 		return (PO_SUCCESS);
4730Sstevel@tonic-gate 	else {
4740Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
4750Sstevel@tonic-gate 		return (PO_FAIL);
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate /*
4800Sstevel@tonic-gate  * Ensure the type is a boolean.
4810Sstevel@tonic-gate  */
4820Sstevel@tonic-gate /* ARGSUSED */
4830Sstevel@tonic-gate static int
elem_set_bool(pool_elem_t * elem,const pool_value_t * pval)4840Sstevel@tonic-gate elem_set_bool(pool_elem_t *elem, const pool_value_t *pval)
4850Sstevel@tonic-gate {
4860Sstevel@tonic-gate 	if (pool_value_get_type(pval) == POC_BOOL)
4870Sstevel@tonic-gate 		return (PO_SUCCESS);
4880Sstevel@tonic-gate 	else {
4890Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
4900Sstevel@tonic-gate 		return (PO_FAIL);
4910Sstevel@tonic-gate 	}
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate /*
4950Sstevel@tonic-gate  * Ensure the type is an unsigned int.
4960Sstevel@tonic-gate  */
4970Sstevel@tonic-gate /* ARGSUSED */
4980Sstevel@tonic-gate static int
elem_set_uint(pool_elem_t * elem,const pool_value_t * pval)4990Sstevel@tonic-gate elem_set_uint(pool_elem_t *elem, const pool_value_t *pval)
5000Sstevel@tonic-gate {
5010Sstevel@tonic-gate 	if (pool_value_get_type(pval) == POC_UINT)
5020Sstevel@tonic-gate 		return (PO_SUCCESS);
5030Sstevel@tonic-gate 	else {
5040Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5050Sstevel@tonic-gate 		return (PO_FAIL);
5060Sstevel@tonic-gate 	}
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate /* ARGSUSED */
5100Sstevel@tonic-gate int
system_set_allocate(pool_elem_t * elem,const pool_value_t * pval)5110Sstevel@tonic-gate system_set_allocate(pool_elem_t *elem, const pool_value_t *pval)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate 	const char *sval;
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	if (pool_value_get_string(pval, &sval) != PO_SUCCESS) {
5160Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
5170Sstevel@tonic-gate 		return (PO_FAIL);
5180Sstevel@tonic-gate 	}
5190Sstevel@tonic-gate 	if (strcmp(POA_IMPORTANCE, sval) != 0 &&
5200Sstevel@tonic-gate 	    strcmp(POA_SURPLUS_TO_DEFAULT, sval) != 0) {
5210Sstevel@tonic-gate 			pool_seterror(POE_PUTPROP);
5220Sstevel@tonic-gate 			return (PO_FAIL);
5230Sstevel@tonic-gate 	}
5240Sstevel@tonic-gate 	return (PO_SUCCESS);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate /* ARGSUSED */
5280Sstevel@tonic-gate int
pool_set_active(pool_elem_t * elem,const pool_value_t * pval)5290Sstevel@tonic-gate pool_set_active(pool_elem_t *elem, const pool_value_t *pval)
5300Sstevel@tonic-gate {
5310Sstevel@tonic-gate 	uchar_t bval;
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	if (pool_value_get_type(pval) != POC_BOOL) {
5340Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5350Sstevel@tonic-gate 		return (PO_FAIL);
5360Sstevel@tonic-gate 	}
5370Sstevel@tonic-gate 	(void) pool_value_get_bool(pval, &bval);
5380Sstevel@tonic-gate 	if (bval != 1) {
5390Sstevel@tonic-gate 		/*
5400Sstevel@tonic-gate 		 * "active" must be true on pools for
5410Sstevel@tonic-gate 		 * now.
5420Sstevel@tonic-gate 		 */
5430Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5440Sstevel@tonic-gate 		return (PO_FAIL);
5450Sstevel@tonic-gate 	}
5460Sstevel@tonic-gate 	return (PO_SUCCESS);
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate /* ARGSUSED */
5500Sstevel@tonic-gate int
pool_set_scheduler(pool_elem_t * elem,const pool_value_t * pval)5510Sstevel@tonic-gate pool_set_scheduler(pool_elem_t *elem, const pool_value_t *pval)
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate 	pcinfo_t pcinfo;
5540Sstevel@tonic-gate 	const char *sched;
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	if (pool_value_get_string(pval, &sched) != 0) {
5570Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
5580Sstevel@tonic-gate 		return (PO_FAIL);
5590Sstevel@tonic-gate 	}
5600Sstevel@tonic-gate 	(void) strncpy(pcinfo.pc_clname, sched, PC_CLNMSZ);
5610Sstevel@tonic-gate 	if (priocntl(0, 0, PC_GETCID, &pcinfo) == -1) {
5620Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
5630Sstevel@tonic-gate 		return (PO_FAIL);
5640Sstevel@tonic-gate 	}
5650Sstevel@tonic-gate 	return (PO_SUCCESS);
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate static int
res_set_max(pool_elem_t * elem,const pool_value_t * pval)5690Sstevel@tonic-gate res_set_max(pool_elem_t *elem, const pool_value_t *pval)
5700Sstevel@tonic-gate {
5710Sstevel@tonic-gate 	uint64_t min, max;
5720Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 	/*
5750Sstevel@tonic-gate 	 * max must be a uint
5760Sstevel@tonic-gate 	 */
5770Sstevel@tonic-gate 	if (pool_value_get_uint64(pval, &max) != PO_SUCCESS) {
5780Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
5790Sstevel@tonic-gate 		return (PO_FAIL);
5800Sstevel@tonic-gate 	}
5810Sstevel@tonic-gate 	/*
5820Sstevel@tonic-gate 	 * max can't be less than min (if it exists)
5830Sstevel@tonic-gate 	 */
5840Sstevel@tonic-gate 	if (pool_get_ns_property(elem, c_min_prop, &val) == POC_INVAL)
5850Sstevel@tonic-gate 		return (PO_SUCCESS);
5860Sstevel@tonic-gate 	if (pool_value_get_uint64(&val, &min) != PO_SUCCESS) {
5870Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
5880Sstevel@tonic-gate 		return (PO_FAIL);
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 	if (max < min) {
5910Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
5920Sstevel@tonic-gate 		return (PO_FAIL);
5930Sstevel@tonic-gate 	}
5940Sstevel@tonic-gate 	/*
5950Sstevel@tonic-gate 	 * Ensure that changes to the max in a dynamic configuration
5960Sstevel@tonic-gate 	 * are still valid.
5970Sstevel@tonic-gate 	 */
5980Sstevel@tonic-gate 	if (conf_is_dynamic(TO_CONF(elem)) == PO_TRUE) {
5990Sstevel@tonic-gate 		uint64_t oldmax;
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 		if (pool_get_ns_property(elem, c_max_prop, &val) == POC_INVAL) {
6020Sstevel@tonic-gate 			pool_seterror(POE_PUTPROP);
6030Sstevel@tonic-gate 			return (PO_FAIL);
6040Sstevel@tonic-gate 		}
6050Sstevel@tonic-gate 		if (pool_value_get_uint64(&val, &oldmax) != PO_SUCCESS) {
6060Sstevel@tonic-gate 			pool_seterror(POE_PUTPROP);
6070Sstevel@tonic-gate 			return (PO_FAIL);
6080Sstevel@tonic-gate 		}
6090Sstevel@tonic-gate 		if (max < oldmax) {
6100Sstevel@tonic-gate 			/*
6110Sstevel@tonic-gate 			 * Ensure that the modified total max is >= size
6120Sstevel@tonic-gate 			 * of all resources of this type
6130Sstevel@tonic-gate 			 */
6140Sstevel@tonic-gate 			return (pool_validate_resource(TO_CONF(elem),
6150Sstevel@tonic-gate 				pool_elem_class_string(elem), c_max_prop,
6160Sstevel@tonic-gate 				max - oldmax));
6170Sstevel@tonic-gate 		}
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 	return (PO_SUCCESS);
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate static int
res_set_min(pool_elem_t * elem,const pool_value_t * pval)6230Sstevel@tonic-gate res_set_min(pool_elem_t *elem, const pool_value_t *pval)
6240Sstevel@tonic-gate {
6250Sstevel@tonic-gate 	uint64_t min, max;
6260Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	/*
6290Sstevel@tonic-gate 	 * min must be a uint
6300Sstevel@tonic-gate 	 */
6310Sstevel@tonic-gate 	if (pool_value_get_uint64(pval, &min) != PO_SUCCESS) {
6320Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
6330Sstevel@tonic-gate 		return (PO_FAIL);
6340Sstevel@tonic-gate 	}
6350Sstevel@tonic-gate 	/*
6360Sstevel@tonic-gate 	 * min can't be more than max (if it exists)
6370Sstevel@tonic-gate 	 */
6380Sstevel@tonic-gate 	if (pool_get_ns_property(elem, c_max_prop, &val) == POC_INVAL)
6390Sstevel@tonic-gate 		return (PO_SUCCESS);
6400Sstevel@tonic-gate 	if (pool_value_get_uint64(&val, &max) != PO_SUCCESS) {
6410Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
6420Sstevel@tonic-gate 		return (PO_FAIL);
6430Sstevel@tonic-gate 	}
6440Sstevel@tonic-gate 	if (min > max) {
6450Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
6460Sstevel@tonic-gate 		return (PO_FAIL);
6470Sstevel@tonic-gate 	}
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 	switch (pool_resource_elem_class(elem)) {
6500Sstevel@tonic-gate 	case PREC_PSET:
6510Sstevel@tonic-gate 		if (resource_is_default(pool_elem_res(elem))) {
6520Sstevel@tonic-gate 			if (min < 1) {
6530Sstevel@tonic-gate 				pool_seterror(POE_PUTPROP);
6540Sstevel@tonic-gate 				return (PO_FAIL);
6550Sstevel@tonic-gate 			}
6560Sstevel@tonic-gate 		}
6570Sstevel@tonic-gate 		break;
6580Sstevel@tonic-gate 	default:
6590Sstevel@tonic-gate 		break;
6600Sstevel@tonic-gate 	}
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 	/*
6630Sstevel@tonic-gate 	 * Ensure that changes to the min in a dynamic configuration
6640Sstevel@tonic-gate 	 * are still valid.
6650Sstevel@tonic-gate 	 */
6660Sstevel@tonic-gate 	if (conf_is_dynamic(TO_CONF(elem)) == PO_TRUE) {
6670Sstevel@tonic-gate 		uint64_t oldmin;
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 		if (pool_get_ns_property(elem, c_min_prop, &val) == POC_INVAL) {
6700Sstevel@tonic-gate 			pool_seterror(POE_PUTPROP);
6710Sstevel@tonic-gate 			return (PO_FAIL);
6720Sstevel@tonic-gate 		}
6730Sstevel@tonic-gate 		if (pool_value_get_uint64(&val, &oldmin) != PO_SUCCESS) {
6740Sstevel@tonic-gate 			pool_seterror(POE_PUTPROP);
6750Sstevel@tonic-gate 			return (PO_FAIL);
6760Sstevel@tonic-gate 		}
6770Sstevel@tonic-gate 		if (min > oldmin) {
6780Sstevel@tonic-gate 			/*
6790Sstevel@tonic-gate 			 * Ensure that the modified total min is <= size
6800Sstevel@tonic-gate 			 * of all resources of this type
6810Sstevel@tonic-gate 			 */
6820Sstevel@tonic-gate 			return (pool_validate_resource(TO_CONF(elem),
6830Sstevel@tonic-gate 				pool_elem_class_string(elem), c_min_prop,
6840Sstevel@tonic-gate 				min - oldmin));
6850Sstevel@tonic-gate 		}
6860Sstevel@tonic-gate 	}
6870Sstevel@tonic-gate 	return (PO_SUCCESS);
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate /* ARGSUSED */
6910Sstevel@tonic-gate int
cpu_set_status(pool_elem_t * elem,const pool_value_t * pval)6920Sstevel@tonic-gate cpu_set_status(pool_elem_t *elem, const pool_value_t *pval)
6930Sstevel@tonic-gate {
6940Sstevel@tonic-gate 	const char *status;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	if (pool_value_get_string(pval, &status) != 0) {
6970Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
6980Sstevel@tonic-gate 		return (PO_FAIL);
6990Sstevel@tonic-gate 	}
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	if (strcmp(PS_ONLINE, status) != 0 &&
7020Sstevel@tonic-gate 	    strcmp(PS_OFFLINE, status) != 0 &&
7030Sstevel@tonic-gate 	    strcmp(PS_NOINTR, status) != 0 &&
7040Sstevel@tonic-gate 	    strcmp(PS_SPARE, status) != 0 &&
7050Sstevel@tonic-gate 	    strcmp(PS_FAULTED, status) != 0) {
7060Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
7070Sstevel@tonic-gate 		return (PO_FAIL);
7080Sstevel@tonic-gate 	}
7090Sstevel@tonic-gate 	return (PO_SUCCESS);
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate static int
elem_get_type(const pool_elem_t * elem,pool_value_t * pval)7130Sstevel@tonic-gate elem_get_type(const pool_elem_t *elem, pool_value_t *pval)
7140Sstevel@tonic-gate {
7150Sstevel@tonic-gate 	if (pool_value_set_string(pval, pool_elem_class_string(elem)) ==
7160Sstevel@tonic-gate 	    PO_FAIL)
7170Sstevel@tonic-gate 		return (PO_FAIL);
7180Sstevel@tonic-gate 	return (PO_SUCCESS);
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate /*
7220Sstevel@tonic-gate  * More general utilities
7230Sstevel@tonic-gate  */
7240Sstevel@tonic-gate /*
7250Sstevel@tonic-gate  * Is the supplied configuration the dynamic configuration
7260Sstevel@tonic-gate  * Return: PO_TRUE/PO_FALSE
7270Sstevel@tonic-gate  */
7280Sstevel@tonic-gate int
conf_is_dynamic(const pool_conf_t * conf)7290Sstevel@tonic-gate conf_is_dynamic(const pool_conf_t *conf)
7300Sstevel@tonic-gate {
7310Sstevel@tonic-gate 	if (strcmp(pool_conf_location(conf), pool_dynamic_location()) == 0)
7320Sstevel@tonic-gate 		return (PO_TRUE);
7330Sstevel@tonic-gate 	return (PO_FALSE);
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate /*
7370Sstevel@tonic-gate  * uint_init() initialises the value of the supplied property with the
7380Sstevel@tonic-gate  * supplied value.
7390Sstevel@tonic-gate  * Returns PO_SUCCESS
7400Sstevel@tonic-gate  */
7410Sstevel@tonic-gate int
uint_init(pool_prop_t * prop,uint64_t val)7420Sstevel@tonic-gate uint_init(pool_prop_t *prop, uint64_t val)
7430Sstevel@tonic-gate {
7440Sstevel@tonic-gate 	pool_value_set_uint64(&prop->pp_value, val);
7450Sstevel@tonic-gate 	return (PO_SUCCESS);
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate /*
7490Sstevel@tonic-gate  * int_init() initialises the value of the supplied property with the
7500Sstevel@tonic-gate  * supplied value.
7510Sstevel@tonic-gate  * Returns PO_SUCCESS
7520Sstevel@tonic-gate  */
7530Sstevel@tonic-gate int
int_init(pool_prop_t * prop,int64_t val)7540Sstevel@tonic-gate int_init(pool_prop_t *prop, int64_t val)
7550Sstevel@tonic-gate {
7560Sstevel@tonic-gate 	pool_value_set_int64(&prop->pp_value, val);
7570Sstevel@tonic-gate 	return (PO_SUCCESS);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate /*
7610Sstevel@tonic-gate  * double_init() initialises the value of the supplied property with the
7620Sstevel@tonic-gate  * supplied value.
7630Sstevel@tonic-gate  * Returns PO_SUCCESS
7640Sstevel@tonic-gate  */
7650Sstevel@tonic-gate int
double_init(pool_prop_t * prop,double val)7660Sstevel@tonic-gate double_init(pool_prop_t *prop, double val)
7670Sstevel@tonic-gate {
7680Sstevel@tonic-gate 	pool_value_set_double(&prop->pp_value, val);
7690Sstevel@tonic-gate 	return (PO_SUCCESS);
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate /*
7730Sstevel@tonic-gate  * bool_init() initialises the value of the supplied property with the
7740Sstevel@tonic-gate  * supplied value.
7750Sstevel@tonic-gate  * Returns PO_SUCCESS
7760Sstevel@tonic-gate  */
7770Sstevel@tonic-gate int
bool_init(pool_prop_t * prop,uchar_t val)7780Sstevel@tonic-gate bool_init(pool_prop_t *prop, uchar_t val)
7790Sstevel@tonic-gate {
7800Sstevel@tonic-gate 	pool_value_set_bool(&prop->pp_value, val);
7810Sstevel@tonic-gate 	return (PO_SUCCESS);
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate /*
7850Sstevel@tonic-gate  * string_init() initialises the value of the supplied property with the
7860Sstevel@tonic-gate  * supplied value.
7870Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
7880Sstevel@tonic-gate  */
7890Sstevel@tonic-gate int
string_init(pool_prop_t * prop,const char * val)7900Sstevel@tonic-gate string_init(pool_prop_t *prop, const char *val)
7910Sstevel@tonic-gate {
7920Sstevel@tonic-gate 	return (pool_value_set_string(&prop->pp_value, val));
7930Sstevel@tonic-gate }
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate /*
7960Sstevel@tonic-gate  * pool_get_provider_count() returns the count of registered providers.
7970Sstevel@tonic-gate  *
7980Sstevel@tonic-gate  * Returns count of registered providers
7990Sstevel@tonic-gate  */
8000Sstevel@tonic-gate uint_t
pool_get_provider_count(void)8010Sstevel@tonic-gate pool_get_provider_count(void)
8020Sstevel@tonic-gate {
8030Sstevel@tonic-gate 	uint_t count = 0;
8040Sstevel@tonic-gate 	int i;
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 	for (i = 0; i < sizeof (pool_resource_elem_ctl) /
8070Sstevel@tonic-gate 	    sizeof (pool_resource_elem_ctl[0]); i++) {
8080Sstevel@tonic-gate 		if (pool_resource_elem_ctl[i] != NULL)
8090Sstevel@tonic-gate 			count++;
8100Sstevel@tonic-gate 	}
8110Sstevel@tonic-gate 	return (count);
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate  * Return all the props for a specified provider
8160Sstevel@tonic-gate  */
8170Sstevel@tonic-gate const pool_prop_t *
provider_get_props(const pool_elem_t * elem)8180Sstevel@tonic-gate provider_get_props(const pool_elem_t *elem)
8190Sstevel@tonic-gate {
8200Sstevel@tonic-gate 	const pool_prop_t *prop_list = NULL;
8210Sstevel@tonic-gate 	pool_elem_class_t elem_class = pool_elem_class(elem);
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	switch (elem_class) {
8240Sstevel@tonic-gate 	case PEC_SYSTEM:
8250Sstevel@tonic-gate 	case PEC_POOL:
8260Sstevel@tonic-gate 		prop_list = pool_elem_ctl[elem_class];
8270Sstevel@tonic-gate 		break;
8280Sstevel@tonic-gate 	case PEC_RES_AGG:
8290Sstevel@tonic-gate 	case PEC_RES_COMP:
8300Sstevel@tonic-gate 		prop_list = pool_resource_elem_ctl
8310Sstevel@tonic-gate 		    [pool_resource_elem_class(elem)];
8320Sstevel@tonic-gate 		break;
8330Sstevel@tonic-gate 	case PEC_COMP:
8340Sstevel@tonic-gate 		prop_list = pool_component_elem_ctl
8350Sstevel@tonic-gate 		    [pool_component_elem_class(elem)];
8360Sstevel@tonic-gate 		break;
8370Sstevel@tonic-gate 	}
8380Sstevel@tonic-gate 	return (prop_list);
8390Sstevel@tonic-gate }
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate /*
8420Sstevel@tonic-gate  * provider_get_prop() return the pool_prop_t structure which
8430Sstevel@tonic-gate  * describes the supplied property name for the supplied provider.
8440Sstevel@tonic-gate  *
8450Sstevel@tonic-gate  * Returns the property description or NULL if it doesn't exist.
8460Sstevel@tonic-gate  */
8470Sstevel@tonic-gate const pool_prop_t *
provider_get_prop(const pool_elem_t * elem,const char * name)8480Sstevel@tonic-gate provider_get_prop(const pool_elem_t *elem, const char *name)
8490Sstevel@tonic-gate {
8500Sstevel@tonic-gate 	int i;
8510Sstevel@tonic-gate 	const pool_prop_t *prop_list;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 	if ((prop_list = provider_get_props(elem)) == NULL)
8540Sstevel@tonic-gate 		return (NULL);
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 	for (i = 0; prop_list[i].pp_pname != NULL; i++) {
8570Sstevel@tonic-gate 		if (strcmp(name, prop_list[i].pp_pname) == 0) {
8580Sstevel@tonic-gate 			return (&prop_list[i]);
8590Sstevel@tonic-gate 		}
8600Sstevel@tonic-gate 	}
8610Sstevel@tonic-gate 	return (NULL);
8620Sstevel@tonic-gate }
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate /*
8650Sstevel@tonic-gate  * prop_is_type() checks the supplied property and returns PO_TRUE if the
8660Sstevel@tonic-gate  * property value is 1 else PO_FALSE
8670Sstevel@tonic-gate  */
8680Sstevel@tonic-gate static int
prop_is_type(int prop_type,const pool_prop_t * prop)8690Sstevel@tonic-gate prop_is_type(int prop_type, const pool_prop_t *prop)
8700Sstevel@tonic-gate {
8710Sstevel@tonic-gate 	return ((prop->pp_perms & prop_type) ? PO_TRUE : PO_FALSE);
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate /*
8750Sstevel@tonic-gate  * prop_is_stored() returns PO_TRUE if the property is stored in the backing
8760Sstevel@tonic-gate  * configuration and PO_FALSE else.
8770Sstevel@tonic-gate  */
8780Sstevel@tonic-gate int
prop_is_stored(const pool_prop_t * prop)8790Sstevel@tonic-gate prop_is_stored(const pool_prop_t *prop)
8800Sstevel@tonic-gate {
8810Sstevel@tonic-gate 	return (prop_is_type(PP_STORED, prop));
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate /*
8850Sstevel@tonic-gate  * prop_is_readonly() returns PO_TRUE if the property is a read-only property
8860Sstevel@tonic-gate  * and PO_FALSE else.
8870Sstevel@tonic-gate  */
8880Sstevel@tonic-gate int
prop_is_readonly(const pool_prop_t * prop)8890Sstevel@tonic-gate prop_is_readonly(const pool_prop_t *prop)
8900Sstevel@tonic-gate {
8910Sstevel@tonic-gate 	return (prop_is_type(PP_READ, prop));
8920Sstevel@tonic-gate }
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate /*
8950Sstevel@tonic-gate  * prop_is_init() returns PO_TRUE if the property should be
8960Sstevel@tonic-gate  * initialised when an element of this type is created and PO_FALSE
8970Sstevel@tonic-gate  * else.
8980Sstevel@tonic-gate  */
8990Sstevel@tonic-gate int
prop_is_init(const pool_prop_t * prop)9000Sstevel@tonic-gate prop_is_init(const pool_prop_t *prop)
9010Sstevel@tonic-gate {
9020Sstevel@tonic-gate 	return (prop_is_type(PP_INIT, prop));
9030Sstevel@tonic-gate }
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate /*
9060Sstevel@tonic-gate  * prop_is_hidden() returns PO_TRUE if the property should be hidden
9070Sstevel@tonic-gate  * from access by the external property access mechanisms.
9080Sstevel@tonic-gate  */
9090Sstevel@tonic-gate int
prop_is_hidden(const pool_prop_t * prop)9100Sstevel@tonic-gate prop_is_hidden(const pool_prop_t *prop)
9110Sstevel@tonic-gate {
9120Sstevel@tonic-gate 	return (prop_is_type(PP_HIDDEN, prop));
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate /*
9160Sstevel@tonic-gate  * prop_is_optional() returns PO_TRUE if the property is optional and
9170Sstevel@tonic-gate  * can be removed by external property access mechanisms.
9180Sstevel@tonic-gate  */
9190Sstevel@tonic-gate int
prop_is_optional(const pool_prop_t * prop)9200Sstevel@tonic-gate prop_is_optional(const pool_prop_t *prop)
9210Sstevel@tonic-gate {
9220Sstevel@tonic-gate 	return (prop_is_type(PP_OPTIONAL, prop));
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate int
cpu_is_requested(pool_component_t * component)9260Sstevel@tonic-gate cpu_is_requested(pool_component_t *component)
9270Sstevel@tonic-gate {
9280Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
9290Sstevel@tonic-gate 	uchar_t requested;
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 	if (pool_get_property(TO_CONF(TO_ELEM(component)), TO_ELEM(component),
9320Sstevel@tonic-gate 	    "cpu.requested", &val) != POC_BOOL) {
9330Sstevel@tonic-gate 		return (PO_FALSE);
9340Sstevel@tonic-gate 	}
9350Sstevel@tonic-gate 	if (pool_value_get_bool(&val, &requested) != PO_SUCCESS) {
9360Sstevel@tonic-gate 		return (PO_FALSE);
9370Sstevel@tonic-gate 	}
9380Sstevel@tonic-gate 	return ((int)requested);
9390Sstevel@tonic-gate }
9400Sstevel@tonic-gate 
9410Sstevel@tonic-gate /*
9420Sstevel@tonic-gate  * Common code for various resource get functions
9430Sstevel@tonic-gate  */
9440Sstevel@tonic-gate static int
resource_get_common(const pool_resource_t * res,const char * name,uint64_t * uval)9450Sstevel@tonic-gate resource_get_common(const pool_resource_t *res, const char *name,
9460Sstevel@tonic-gate     uint64_t *uval)
9470Sstevel@tonic-gate {
9480Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
9490Sstevel@tonic-gate 	pool_value_class_t pvc;
9500Sstevel@tonic-gate 	int retval = PO_SUCCESS;
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	pvc = pool_get_ns_property(TO_ELEM(res), name, &val);
9530Sstevel@tonic-gate 	if (pvc == POC_INVAL) {
9540Sstevel@tonic-gate 		*uval = 0;
9550Sstevel@tonic-gate #ifdef DEBUG
9560Sstevel@tonic-gate 		dprintf("can't retrieve %s\n");
9570Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(res));
9580Sstevel@tonic-gate #endif	/* DEBUG */
9590Sstevel@tonic-gate 	} else if (pvc == POC_UINT) {
9600Sstevel@tonic-gate 		retval = pool_value_get_uint64(&val, uval);
9610Sstevel@tonic-gate 	}
9620Sstevel@tonic-gate 	return (retval);
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate /*
9660Sstevel@tonic-gate  * resource_get_size() updates size with the size of the supplied resource.
9670Sstevel@tonic-gate  *
9680Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
9690Sstevel@tonic-gate  */
9700Sstevel@tonic-gate int
resource_get_size(const pool_resource_t * res,uint64_t * size)9710Sstevel@tonic-gate resource_get_size(const pool_resource_t *res, uint64_t *size)
9720Sstevel@tonic-gate {
9730Sstevel@tonic-gate 	return (resource_get_common(res, c_size_prop, size));
9740Sstevel@tonic-gate }
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate /*
9770Sstevel@tonic-gate  * resource_get_pinned() updates pinned with the size of the
9780Sstevel@tonic-gate  * pinned part of a supplied resource. Resource is not available for
9790Sstevel@tonic-gate  * allocation if it is marked as "pinned".
9800Sstevel@tonic-gate  *
9810Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
9820Sstevel@tonic-gate  */
9830Sstevel@tonic-gate int
resource_get_pinned(const pool_resource_t * res,uint64_t * pinned)9840Sstevel@tonic-gate resource_get_pinned(const pool_resource_t *res, uint64_t *pinned)
9850Sstevel@tonic-gate {
9860Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
9870Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
9880Sstevel@tonic-gate 	pool_component_t **cs = NULL;
9890Sstevel@tonic-gate 	uint_t ncompelem;
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 	props[0] = &val;
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	pool_value_set_bool(props[0], PO_TRUE);
9940Sstevel@tonic-gate 	if (pool_value_set_name(props[0], "cpu.pinned") != PO_SUCCESS)
9950Sstevel@tonic-gate 		return (PO_FAIL);
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 	if ((cs = pool_query_resource_components(TO_CONF(TO_ELEM(res)), res,
9980Sstevel@tonic-gate 	    &ncompelem, props)) != NULL) {
9990Sstevel@tonic-gate 		*pinned = ncompelem;
10000Sstevel@tonic-gate 		free(cs);
10010Sstevel@tonic-gate 	} else
10020Sstevel@tonic-gate 		*pinned = 0;
10030Sstevel@tonic-gate 	return (PO_SUCCESS);
10040Sstevel@tonic-gate }
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate /*
10070Sstevel@tonic-gate  * resource_get_min() updates min with the minimum size of the supplied
10080Sstevel@tonic-gate  * resource.
10090Sstevel@tonic-gate  *
10100Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
10110Sstevel@tonic-gate  */
10120Sstevel@tonic-gate int
resource_get_min(const pool_resource_t * res,uint64_t * min)10130Sstevel@tonic-gate resource_get_min(const pool_resource_t *res, uint64_t *min)
10140Sstevel@tonic-gate {
10150Sstevel@tonic-gate 	return (resource_get_common(res, c_min_prop, min));
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate /*
10190Sstevel@tonic-gate  * resource_get_max() updates max with the maximum size of the supplied
10200Sstevel@tonic-gate  * resource.
10210Sstevel@tonic-gate  *
10220Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
10230Sstevel@tonic-gate  */
10240Sstevel@tonic-gate int
resource_get_max(const pool_resource_t * res,uint64_t * max)10250Sstevel@tonic-gate resource_get_max(const pool_resource_t *res, uint64_t *max)
10260Sstevel@tonic-gate {
10270Sstevel@tonic-gate 	return (resource_get_common(res, c_max_prop, max));
10280Sstevel@tonic-gate }
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate /*
10310Sstevel@tonic-gate  * TODO: This is pset specific
10320Sstevel@tonic-gate  *
10330Sstevel@tonic-gate  * get_default_resource() returns the default resource for type of the supplied
10340Sstevel@tonic-gate  * resource.
10350Sstevel@tonic-gate  *
10360Sstevel@tonic-gate  * Returns A pointer to the default resource of the same type as the supplied
10370Sstevel@tonic-gate  * resource.
10380Sstevel@tonic-gate  */
10390Sstevel@tonic-gate const pool_resource_t *
get_default_resource(const pool_resource_t * res)10400Sstevel@tonic-gate get_default_resource(const pool_resource_t *res)
10410Sstevel@tonic-gate {
10420Sstevel@tonic-gate 	return (resource_by_sysid(TO_CONF(TO_ELEM(res)), PS_NONE,
10430Sstevel@tonic-gate 	    pool_elem_class_string(TO_ELEM(res))));
10440Sstevel@tonic-gate }
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate /*
10470Sstevel@tonic-gate  * resource_is_default() returns 1 if the supplied resource is the default
10480Sstevel@tonic-gate  * resource for it's type.
10490Sstevel@tonic-gate  */
10500Sstevel@tonic-gate int
resource_is_default(const pool_resource_t * res)10510Sstevel@tonic-gate resource_is_default(const pool_resource_t *res)
10520Sstevel@tonic-gate {
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 	return (get_default_resource(res) == res);
10550Sstevel@tonic-gate }
10560Sstevel@tonic-gate 
10570Sstevel@tonic-gate /*
10580Sstevel@tonic-gate  * resource_is_system() determines if the resource is a system resource.
10590Sstevel@tonic-gate  */
10600Sstevel@tonic-gate int
resource_is_system(const pool_resource_t * res)10610Sstevel@tonic-gate resource_is_system(const pool_resource_t *res)
10620Sstevel@tonic-gate {
10630Sstevel@tonic-gate 	return (res->pr_is_system(res));
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate /*
10680Sstevel@tonic-gate  * resource_can_associate() determines if it is possible to associate
10690Sstevel@tonic-gate  * with the supplied resource.
10700Sstevel@tonic-gate  */
10710Sstevel@tonic-gate int
resource_can_associate(const pool_resource_t * res)10720Sstevel@tonic-gate resource_can_associate(const pool_resource_t *res)
10730Sstevel@tonic-gate {
10740Sstevel@tonic-gate 	return (res->pr_can_associate(res));
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate /*
10780Sstevel@tonic-gate  * Common code to get an int64 property.
10790Sstevel@tonic-gate  * Unfortunately (-1) is a valid psetid, so we'll return (-2) in case of
10800Sstevel@tonic-gate  * error.
10810Sstevel@tonic-gate  */
10820Sstevel@tonic-gate static int64_t
elem_get_expected_int64(const pool_elem_t * elem,const char * name)10830Sstevel@tonic-gate elem_get_expected_int64(const pool_elem_t *elem, const char *name)
10840Sstevel@tonic-gate {
10850Sstevel@tonic-gate 	int64_t val64;
10860Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 	if (pool_get_ns_property(elem, name, &val) != POC_INT) {
10890Sstevel@tonic-gate 		return (POOL_SYSID_BAD);
10900Sstevel@tonic-gate 	}
10910Sstevel@tonic-gate 	(void) pool_value_get_int64(&val, &val64);
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	return (val64);
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate /*
10970Sstevel@tonic-gate  * The following returns a malloc'ed string which must be free'd by the
10980Sstevel@tonic-gate  * caller.
10990Sstevel@tonic-gate  */
11000Sstevel@tonic-gate static char *
elem_get_expected_string(const pool_elem_t * elem,const char * name)11010Sstevel@tonic-gate elem_get_expected_string(const pool_elem_t *elem, const char *name)
11020Sstevel@tonic-gate {
11030Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
11040Sstevel@tonic-gate 	char *retval;
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate 	if (pool_get_ns_property(elem, name, &val) != POC_STRING) {
11070Sstevel@tonic-gate 		return (NULL);
11080Sstevel@tonic-gate 	}
11090Sstevel@tonic-gate 	(void) pool_value_get_string(&val, (const char **)&retval);
11100Sstevel@tonic-gate 	retval = strdup(retval);
11110Sstevel@tonic-gate 	return (retval);
11120Sstevel@tonic-gate }
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate /*
11150Sstevel@tonic-gate  * elem_get_sysid() returns the sys_id for the supplied elem.
11160Sstevel@tonic-gate  */
11170Sstevel@tonic-gate id_t
elem_get_sysid(const pool_elem_t * elem)11180Sstevel@tonic-gate elem_get_sysid(const pool_elem_t *elem)
11190Sstevel@tonic-gate {
11200Sstevel@tonic-gate 	return ((id_t)elem_get_expected_int64(elem, c_sys_prop));
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate 
11230Sstevel@tonic-gate /*
11240Sstevel@tonic-gate  * elem_get_name() returns the name for the supplied elem. Note that
11250Sstevel@tonic-gate  * it is the caller's responsibility to free this memory.
11260Sstevel@tonic-gate  */
11270Sstevel@tonic-gate char *
elem_get_name(const pool_elem_t * elem)11280Sstevel@tonic-gate elem_get_name(const pool_elem_t *elem)
11290Sstevel@tonic-gate {
11300Sstevel@tonic-gate 	return (elem_get_expected_string(elem, c_name));
11310Sstevel@tonic-gate }
11320Sstevel@tonic-gate 
11330Sstevel@tonic-gate /*
11340Sstevel@tonic-gate  * elem_is_default() returns 1 if the supplied elem is the default
11350Sstevel@tonic-gate  * elem for it's type.
11360Sstevel@tonic-gate  */
11370Sstevel@tonic-gate int
elem_is_default(const pool_elem_t * res)11380Sstevel@tonic-gate elem_is_default(const pool_elem_t *res)
11390Sstevel@tonic-gate {
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	return (get_default_elem(res) == res);
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate /*
1145*3247Sgjelinek  * Return B_TRUE if the element has the 'temporary' property set.
1146*3247Sgjelinek  */
1147*3247Sgjelinek boolean_t
elem_is_tmp(const pool_elem_t * elem)1148*3247Sgjelinek elem_is_tmp(const pool_elem_t *elem)
1149*3247Sgjelinek {
1150*3247Sgjelinek 	pool_value_t val = POOL_VALUE_INITIALIZER;
1151*3247Sgjelinek 	uchar_t bval;
1152*3247Sgjelinek 
1153*3247Sgjelinek 	if (pool_get_ns_property(elem, "temporary", &val) != POC_BOOL)
1154*3247Sgjelinek 		return (B_FALSE);
1155*3247Sgjelinek 
1156*3247Sgjelinek 	(void) pool_value_get_bool(&val, &bval);
1157*3247Sgjelinek 
1158*3247Sgjelinek 	return (bval != 0);
1159*3247Sgjelinek }
1160*3247Sgjelinek 
1161*3247Sgjelinek /*
11620Sstevel@tonic-gate  * get_default_elem() returns the default elem for type of the supplied
11630Sstevel@tonic-gate  * elem.
11640Sstevel@tonic-gate  *
11650Sstevel@tonic-gate  * Returns A pointer to the default elem of the same type as the
11660Sstevel@tonic-gate  * supplied elem or NULL on error. Trying to access the default elem
11670Sstevel@tonic-gate  * for a type of element which doesn't support the notion of default
11680Sstevel@tonic-gate  * is an error.
11690Sstevel@tonic-gate  */
11700Sstevel@tonic-gate const pool_elem_t *
get_default_elem(const pool_elem_t * pe)11710Sstevel@tonic-gate get_default_elem(const pool_elem_t *pe)
11720Sstevel@tonic-gate {
11730Sstevel@tonic-gate 	pool_result_set_t *rs;
11740Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
11750Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
11760Sstevel@tonic-gate 	char_buf_t *cb;
11770Sstevel@tonic-gate 	const pool_elem_t *pe_default;
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 	props[0] = &val;
11800Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
11810Sstevel@tonic-gate 		return (NULL);
11820Sstevel@tonic-gate 	}
11830Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.default", pool_elem_class_string(pe)) !=
11840Sstevel@tonic-gate 	    PO_SUCCESS) {
11850Sstevel@tonic-gate 		free_char_buf(cb);
11860Sstevel@tonic-gate 		return (NULL);
11870Sstevel@tonic-gate 	}
11880Sstevel@tonic-gate 	if (pool_value_set_name(props[0], cb->cb_buf) != PO_SUCCESS) {
11890Sstevel@tonic-gate 		free_char_buf(cb);
11900Sstevel@tonic-gate 		return (NULL);
11910Sstevel@tonic-gate 	}
11920Sstevel@tonic-gate 	free_char_buf(cb);
11930Sstevel@tonic-gate 	pool_value_set_bool(props[0], PO_TRUE);
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate 	if ((rs = pool_exec_query(TO_CONF(pe), NULL, NULL,
11960Sstevel@tonic-gate 	    PEC_QRY_ELEM(pe), props)) == NULL) {
11970Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
11980Sstevel@tonic-gate 		return (NULL);
11990Sstevel@tonic-gate 	}
12000Sstevel@tonic-gate 	if (pool_rs_count(rs) != 1) {
12010Sstevel@tonic-gate 		(void) pool_rs_close(rs);
12020Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
12030Sstevel@tonic-gate 		return (NULL);
12040Sstevel@tonic-gate 	}
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate 	pe_default = rs->prs_next(rs);
12070Sstevel@tonic-gate 	(void) pool_rs_close(rs);
12080Sstevel@tonic-gate 	return (pe_default);
12090Sstevel@tonic-gate }
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate /*
12120Sstevel@tonic-gate  * is_a_known_prefix() determines if the supplied prop_name is a known
12130Sstevel@tonic-gate  * name for the supplied class.
12140Sstevel@tonic-gate  *
12150Sstevel@tonic-gate  * Returns a pointer to the prefix if it is found or NULL
12160Sstevel@tonic-gate  */
12170Sstevel@tonic-gate const char *
is_a_known_prefix(pool_elem_class_t class,const char * prop_name)12180Sstevel@tonic-gate is_a_known_prefix(pool_elem_class_t class, const char *prop_name)
12190Sstevel@tonic-gate {
12200Sstevel@tonic-gate 	int i;
12210Sstevel@tonic-gate 	int len;
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 	switch (class) {
12240Sstevel@tonic-gate 	case PEC_SYSTEM:
12250Sstevel@tonic-gate 	case PEC_POOL:
12260Sstevel@tonic-gate 		len = strlen(pool_elem_class_name[class]);
12270Sstevel@tonic-gate 		if (strncmp(prop_name, pool_elem_class_name[class], len) == 0 &&
12280Sstevel@tonic-gate 		    prop_name[len] == '.' || strcmp(prop_name, c_type) == 0)
12290Sstevel@tonic-gate 			return (pool_elem_class_name[class]);
12300Sstevel@tonic-gate 		break;
12310Sstevel@tonic-gate 	case PEC_RES_COMP:
12320Sstevel@tonic-gate 	case PEC_RES_AGG:
12330Sstevel@tonic-gate 		for (i = 0; i < sizeof (pool_resource_elem_class_name) /
12340Sstevel@tonic-gate 		    sizeof (pool_resource_elem_class_name[0]); i++) {
12350Sstevel@tonic-gate 			len = strlen(pool_resource_elem_class_name[i]);
12360Sstevel@tonic-gate 			if (strncmp(prop_name,
12370Sstevel@tonic-gate 			    pool_resource_elem_class_name[i], len) == 0 &&
12380Sstevel@tonic-gate 			    prop_name[len] == '.' ||
12390Sstevel@tonic-gate 			    strcmp(prop_name, c_type) == 0)
12400Sstevel@tonic-gate 				return (pool_resource_elem_class_name[i]);
12410Sstevel@tonic-gate 		}
12420Sstevel@tonic-gate 		break;
12430Sstevel@tonic-gate 	case PEC_COMP:
12440Sstevel@tonic-gate 		for (i = 0; i < sizeof (pool_component_elem_class_name) /
12450Sstevel@tonic-gate 		    sizeof (pool_component_elem_class_name[0]); i++) {
12460Sstevel@tonic-gate 			len = strlen(pool_component_elem_class_name[i]);
12470Sstevel@tonic-gate 			if (strncmp(prop_name,
12480Sstevel@tonic-gate 			    pool_component_elem_class_name[i], len) == 0 &&
12490Sstevel@tonic-gate 			    prop_name[len] == '.' ||
12500Sstevel@tonic-gate 			    strcmp(prop_name, c_type) == 0)
12510Sstevel@tonic-gate 				return (pool_component_elem_class_name[i]);
12520Sstevel@tonic-gate 		}
12530Sstevel@tonic-gate 		break;
12540Sstevel@tonic-gate 	default:
12550Sstevel@tonic-gate 		break;
12560Sstevel@tonic-gate 	}
12570Sstevel@tonic-gate 	return (NULL);
12580Sstevel@tonic-gate }
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate const char *
pool_elem_class_string(const pool_elem_t * pe)12620Sstevel@tonic-gate pool_elem_class_string(const pool_elem_t *pe)
12630Sstevel@tonic-gate {
12640Sstevel@tonic-gate 	switch (pool_elem_class(pe)) {
12650Sstevel@tonic-gate 	case PEC_SYSTEM:
12660Sstevel@tonic-gate 	case PEC_POOL:
12670Sstevel@tonic-gate 		return (pool_elem_class_name[pool_elem_class(pe)]);
12680Sstevel@tonic-gate 	case PEC_RES_COMP:
12690Sstevel@tonic-gate 	case PEC_RES_AGG:
12700Sstevel@tonic-gate 		return (pool_resource_elem_class_name
12710Sstevel@tonic-gate 		    [pool_resource_elem_class(pe)]);
12720Sstevel@tonic-gate 	case PEC_COMP:
12730Sstevel@tonic-gate 		return (pool_component_elem_class_name
12740Sstevel@tonic-gate 		    [pool_component_elem_class(pe)]);
12750Sstevel@tonic-gate 	default:
12760Sstevel@tonic-gate 		return (pool_elem_class_name[PEC_INVALID]);
12770Sstevel@tonic-gate 	}
12780Sstevel@tonic-gate }
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate const char *
pool_resource_type_string(pool_resource_elem_class_t type)12810Sstevel@tonic-gate pool_resource_type_string(pool_resource_elem_class_t type)
12820Sstevel@tonic-gate {
12830Sstevel@tonic-gate 	return (pool_resource_elem_class_name[type]);
12840Sstevel@tonic-gate }
12850Sstevel@tonic-gate 
12860Sstevel@tonic-gate const char *
pool_component_type_string(pool_component_elem_class_t type)12870Sstevel@tonic-gate pool_component_type_string(pool_component_elem_class_t type)
12880Sstevel@tonic-gate {
12890Sstevel@tonic-gate 	return (pool_component_elem_class_name[type]);
12900Sstevel@tonic-gate }
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate /*
12930Sstevel@tonic-gate  * resource_by_sysid() finds a resource from it's supplied sysid and type.
12940Sstevel@tonic-gate  *
12950Sstevel@tonic-gate  * Returns a pointer to the resource or NULL if it doesn't exist.
12960Sstevel@tonic-gate  */
12970Sstevel@tonic-gate pool_resource_t *
resource_by_sysid(const pool_conf_t * conf,id_t sysid,const char * type)12980Sstevel@tonic-gate resource_by_sysid(const pool_conf_t *conf, id_t sysid, const char *type)
12990Sstevel@tonic-gate {
13000Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL, NULL };
13010Sstevel@tonic-gate 	pool_resource_t **resources = NULL;
13020Sstevel@tonic-gate 	pool_resource_t *retval = NULL;
13030Sstevel@tonic-gate 	uint_t nelem;
13040Sstevel@tonic-gate 	char_buf_t *cb;
13050Sstevel@tonic-gate 	pool_value_t val0 = POOL_VALUE_INITIALIZER;
13060Sstevel@tonic-gate 	pool_value_t val1 = POOL_VALUE_INITIALIZER;
13070Sstevel@tonic-gate 
13080Sstevel@tonic-gate 	props[0] = &val0;
13090Sstevel@tonic-gate 	props[1] = &val1;
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 	if (pool_value_set_string(props[0], type) != PO_SUCCESS ||
13120Sstevel@tonic-gate 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS)
13130Sstevel@tonic-gate 		return (NULL);
13140Sstevel@tonic-gate 
13150Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
13160Sstevel@tonic-gate 		return (NULL);
13170Sstevel@tonic-gate 	}
13180Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.sys_id", type) != PO_SUCCESS) {
13190Sstevel@tonic-gate 		free_char_buf(cb);
13200Sstevel@tonic-gate 		return (NULL);
13210Sstevel@tonic-gate 	}
13220Sstevel@tonic-gate 	if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) {
13230Sstevel@tonic-gate 		free_char_buf(cb);
13240Sstevel@tonic-gate 		return (NULL);
13250Sstevel@tonic-gate 	}
13260Sstevel@tonic-gate 	free_char_buf(cb);
13270Sstevel@tonic-gate 	pool_value_set_int64(props[1], sysid);
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate 	resources = pool_query_resources(conf, &nelem, props);
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate 	if (resources != NULL) {
13320Sstevel@tonic-gate 		retval = resources[0];
13330Sstevel@tonic-gate 		free(resources);
13340Sstevel@tonic-gate 	}
13350Sstevel@tonic-gate 	return (retval);
13360Sstevel@tonic-gate }
13370Sstevel@tonic-gate 
13380Sstevel@tonic-gate pool_elem_class_t
pool_elem_class_from_string(const char * type)13390Sstevel@tonic-gate pool_elem_class_from_string(const char *type)
13400Sstevel@tonic-gate {
13410Sstevel@tonic-gate 	int i;
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 	for (i = 0; i < sizeof (pool_elem_class_name) /
13440Sstevel@tonic-gate 	    sizeof (pool_elem_class_name[0]); i++) {
13450Sstevel@tonic-gate 		if (strcmp(pool_elem_class_name[i], type) == 0)
13460Sstevel@tonic-gate 			break;
13470Sstevel@tonic-gate 	}
13480Sstevel@tonic-gate 	if (i == sizeof (pool_elem_class_name) /
13490Sstevel@tonic-gate 	    sizeof (pool_elem_class_name[0]))
13500Sstevel@tonic-gate 		return (PEC_INVALID);
13510Sstevel@tonic-gate 	return ((pool_elem_class_t)i);
13520Sstevel@tonic-gate }
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate pool_resource_elem_class_t
pool_resource_elem_class_from_string(const char * type)13550Sstevel@tonic-gate pool_resource_elem_class_from_string(const char *type)
13560Sstevel@tonic-gate {
13570Sstevel@tonic-gate 	int i;
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 	for (i = 0; i < sizeof (pool_resource_elem_class_name) /
13600Sstevel@tonic-gate 	    sizeof (pool_resource_elem_class_name[0]); i++) {
13610Sstevel@tonic-gate 		if (strcmp(pool_resource_elem_class_name[i], type) == 0)
13620Sstevel@tonic-gate 			break;
13630Sstevel@tonic-gate 	}
13640Sstevel@tonic-gate 	if (i == sizeof (pool_resource_elem_class_name) /
13650Sstevel@tonic-gate 	    sizeof (pool_resource_elem_class_name[0]))
13660Sstevel@tonic-gate 		return (PREC_INVALID);
13670Sstevel@tonic-gate 	return ((pool_resource_elem_class_t)i);
13680Sstevel@tonic-gate }
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate pool_component_elem_class_t
pool_component_elem_class_from_string(const char * type)13710Sstevel@tonic-gate pool_component_elem_class_from_string(const char *type)
13720Sstevel@tonic-gate {
13730Sstevel@tonic-gate 	int i;
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 	for (i = 0; i < sizeof (pool_component_elem_class_name) /
13760Sstevel@tonic-gate 	    sizeof (pool_component_elem_class_name[0]); i++) {
13770Sstevel@tonic-gate 		if (strcmp(pool_component_elem_class_name[i], type) == 0)
13780Sstevel@tonic-gate 			break;
13790Sstevel@tonic-gate 	}
13800Sstevel@tonic-gate 	if (i == sizeof (pool_component_elem_class_name) /
13810Sstevel@tonic-gate 	    sizeof (pool_component_elem_class_name[0]))
13820Sstevel@tonic-gate 		return (PCEC_INVALID);
13830Sstevel@tonic-gate 	return ((pool_component_elem_class_t)i);
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate 
13860Sstevel@tonic-gate /*
13870Sstevel@tonic-gate  * pool_resource_type_list() populates the supplied array of pointers
13880Sstevel@tonic-gate  * with the names of the available resource types on this system.
13890Sstevel@tonic-gate  */
13900Sstevel@tonic-gate int
pool_resource_type_list(const char ** types,uint_t * numtypes)13910Sstevel@tonic-gate pool_resource_type_list(const char **types, uint_t *numtypes)
13920Sstevel@tonic-gate {
13930Sstevel@tonic-gate 	int i, j;
13940Sstevel@tonic-gate 	uint_t maxnum = *numtypes;
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	*numtypes = pool_get_provider_count();
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 	if (types) {
13990Sstevel@tonic-gate 		for (i = 0, j = 0; i < sizeof (pool_resource_elem_ctl) /
14000Sstevel@tonic-gate 		    sizeof (pool_resource_elem_ctl[0]) && j < maxnum; i++) {
14010Sstevel@tonic-gate 			if (pool_resource_elem_ctl[i] != NULL)
14020Sstevel@tonic-gate 				types[j++] = pool_resource_elem_class_name[i];
14030Sstevel@tonic-gate 		}
14040Sstevel@tonic-gate 	}
14050Sstevel@tonic-gate 	return (PO_SUCCESS);
14060Sstevel@tonic-gate }
14070Sstevel@tonic-gate 
14080Sstevel@tonic-gate /*
14090Sstevel@tonic-gate  * Return the system element for the supplied conf.
14100Sstevel@tonic-gate  * NULL is returned if an error is detected and the error code is updated
14110Sstevel@tonic-gate  * to indicate the cause of the error.
14120Sstevel@tonic-gate  */
14130Sstevel@tonic-gate pool_system_t *
pool_conf_system(const pool_conf_t * conf)14140Sstevel@tonic-gate pool_conf_system(const pool_conf_t *conf)
14150Sstevel@tonic-gate {
14160Sstevel@tonic-gate 	pool_elem_t *system;
14170Sstevel@tonic-gate 	pool_result_set_t *rs;
14180Sstevel@tonic-gate 
14190Sstevel@tonic-gate 	if ((rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_SYSTEM, NULL)) ==
14200Sstevel@tonic-gate 	    NULL) {
14210Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
14220Sstevel@tonic-gate 		return (NULL);
14230Sstevel@tonic-gate 	}
14240Sstevel@tonic-gate 	/* There should only be one system record */
14250Sstevel@tonic-gate 	if (pool_rs_count(rs) != 1) {
14260Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
14270Sstevel@tonic-gate 		(void) pool_rs_close(rs);
14280Sstevel@tonic-gate 		return (NULL);
14290Sstevel@tonic-gate 	}
14300Sstevel@tonic-gate 	system = rs->prs_next(rs);
14310Sstevel@tonic-gate 	(void) pool_rs_close(rs);
14320Sstevel@tonic-gate 	return (pool_elem_system(system));
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate pool_system_t *
pool_elem_system(const pool_elem_t * pe)14360Sstevel@tonic-gate pool_elem_system(const pool_elem_t *pe)
14370Sstevel@tonic-gate {
14380Sstevel@tonic-gate 	if (pe->pe_class != PEC_SYSTEM) {
14390Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14400Sstevel@tonic-gate 		return (NULL);
14410Sstevel@tonic-gate 	}
14420Sstevel@tonic-gate 	return ((pool_system_t *)pe);
14430Sstevel@tonic-gate }
14440Sstevel@tonic-gate 
14450Sstevel@tonic-gate pool_t *
pool_elem_pool(const pool_elem_t * pe)14460Sstevel@tonic-gate pool_elem_pool(const pool_elem_t *pe)
14470Sstevel@tonic-gate {
14480Sstevel@tonic-gate 	if (pe->pe_class != PEC_POOL) {
14490Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14500Sstevel@tonic-gate 		return (NULL);
14510Sstevel@tonic-gate 	}
14520Sstevel@tonic-gate 	return ((pool_t *)pe);
14530Sstevel@tonic-gate }
14540Sstevel@tonic-gate 
14550Sstevel@tonic-gate pool_resource_t *
pool_elem_res(const pool_elem_t * pe)14560Sstevel@tonic-gate pool_elem_res(const pool_elem_t *pe)
14570Sstevel@tonic-gate {
14580Sstevel@tonic-gate 	if (pe->pe_class != PEC_RES_COMP &&
14590Sstevel@tonic-gate 	    pool_elem_class(pe) != PEC_RES_AGG) {
14600Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14610Sstevel@tonic-gate 		return (NULL);
14620Sstevel@tonic-gate 	}
14630Sstevel@tonic-gate 	return ((pool_resource_t *)pe);
14640Sstevel@tonic-gate }
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate pool_component_t *
pool_elem_comp(const pool_elem_t * pe)14670Sstevel@tonic-gate pool_elem_comp(const pool_elem_t *pe)
14680Sstevel@tonic-gate {
14690Sstevel@tonic-gate 	if (pe->pe_class != PEC_COMP) {
14700Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14710Sstevel@tonic-gate 		return (NULL);
14720Sstevel@tonic-gate 	}
14730Sstevel@tonic-gate 	return ((pool_component_t *)pe);
14740Sstevel@tonic-gate }
14750Sstevel@tonic-gate 
14760Sstevel@tonic-gate /*
14770Sstevel@tonic-gate  * qsort_elem_compare() is used for qsort elemement comparison.
14780Sstevel@tonic-gate  *
14790Sstevel@tonic-gate  * Returns see qsort(3c)
14800Sstevel@tonic-gate  */
14810Sstevel@tonic-gate int
qsort_elem_compare(const void * a,const void * b)14820Sstevel@tonic-gate qsort_elem_compare(const void *a, const void *b)
14830Sstevel@tonic-gate {
14840Sstevel@tonic-gate 	const pool_elem_t *e1 = *(const pool_elem_t **)a;
14850Sstevel@tonic-gate 	const pool_elem_t *e2 = *(const pool_elem_t **)b;
14860Sstevel@tonic-gate 
14870Sstevel@tonic-gate 	/*
14880Sstevel@tonic-gate 	 * Special case for handling name changes on default elements
14890Sstevel@tonic-gate 	 * If both elements are default elements then always return 0
14900Sstevel@tonic-gate 	 */
14910Sstevel@tonic-gate 	if (pool_elem_same_class(e1, e2) == PO_TRUE &&
14920Sstevel@tonic-gate 	    (elem_is_default(e1) && elem_is_default(e2)))
14930Sstevel@tonic-gate 			return (0);
14940Sstevel@tonic-gate 	else
14950Sstevel@tonic-gate 		return (pool_elem_compare_name(e1, e2));
14960Sstevel@tonic-gate }
14970Sstevel@tonic-gate 
14980Sstevel@tonic-gate /*
14990Sstevel@tonic-gate  * Dynamic character buffers.
15000Sstevel@tonic-gate  */
15010Sstevel@tonic-gate 
15020Sstevel@tonic-gate /*
15030Sstevel@tonic-gate  * Resize the supplied character buffer to the new size.
15040Sstevel@tonic-gate  */
15050Sstevel@tonic-gate static int
resize_char_buf(char_buf_t * cb,size_t size)15060Sstevel@tonic-gate resize_char_buf(char_buf_t *cb, size_t size)
15070Sstevel@tonic-gate {
15080Sstevel@tonic-gate 	char *re_cb = NULL;
15090Sstevel@tonic-gate 
15100Sstevel@tonic-gate 	if ((re_cb = realloc(cb->cb_buf, size)) == NULL) {
15110Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
15120Sstevel@tonic-gate 		return (PO_FAIL);
15130Sstevel@tonic-gate 	}
15140Sstevel@tonic-gate 	/* If inital allocation, make sure buffer is zeroed */
15150Sstevel@tonic-gate 	if (cb->cb_buf == NULL)
15160Sstevel@tonic-gate 		(void) memset(re_cb, 0, sizeof (re_cb));
15170Sstevel@tonic-gate 	/* If resized smaller, make sure buffer NULL terminated */
15180Sstevel@tonic-gate 	if (size < cb->cb_size)
15190Sstevel@tonic-gate 		re_cb[size] = 0;
15200Sstevel@tonic-gate 	cb->cb_buf = re_cb;
15210Sstevel@tonic-gate 	cb->cb_size = size;
15220Sstevel@tonic-gate 	return (PO_SUCCESS);
15230Sstevel@tonic-gate }
15240Sstevel@tonic-gate 
15250Sstevel@tonic-gate /*
15260Sstevel@tonic-gate  * Allocate a new char_buf_t structure. If there isn't enough memory, return
15270Sstevel@tonic-gate  * NULL. Initialise the new char_buf_t to 0 and then call resize_char_buf
15280Sstevel@tonic-gate  * to initialise the character buffer. Return a pointer to the new
15290Sstevel@tonic-gate  * char_buf_t if the operation succeeds.
15300Sstevel@tonic-gate  */
15310Sstevel@tonic-gate char_buf_t *
alloc_char_buf(size_t size)15320Sstevel@tonic-gate alloc_char_buf(size_t size)
15330Sstevel@tonic-gate {
15340Sstevel@tonic-gate 	char_buf_t *cb;
15350Sstevel@tonic-gate 
15360Sstevel@tonic-gate 	if ((cb = malloc(sizeof (char_buf_t))) == NULL) {
15370Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
15380Sstevel@tonic-gate 		return (NULL);
15390Sstevel@tonic-gate 	}
15400Sstevel@tonic-gate 	(void) memset(cb, 0, sizeof (char_buf_t));
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 	if (resize_char_buf(cb, size + 1) == PO_FAIL) {
15430Sstevel@tonic-gate 		free(cb);
15440Sstevel@tonic-gate 		return (NULL);
15450Sstevel@tonic-gate 	}
15460Sstevel@tonic-gate 	return (cb);
15470Sstevel@tonic-gate }
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate /*
15500Sstevel@tonic-gate  * Free the character buffer and then free the char_buf_t.
15510Sstevel@tonic-gate  */
15520Sstevel@tonic-gate void
free_char_buf(char_buf_t * cb)15530Sstevel@tonic-gate free_char_buf(char_buf_t *cb)
15540Sstevel@tonic-gate {
15550Sstevel@tonic-gate 	free((void *)cb->cb_buf);
15560Sstevel@tonic-gate 	free(cb);
15570Sstevel@tonic-gate }
15580Sstevel@tonic-gate 
15590Sstevel@tonic-gate /*
15600Sstevel@tonic-gate  * Set the character buffer to the supplied data. The user supplies a printf
15610Sstevel@tonic-gate  * like format string and then an appropriate number of parameters for the
15620Sstevel@tonic-gate  * specified format. The character buffer is automatically resized to fit
15630Sstevel@tonic-gate  * the data as determined by resize_char_buf.
15640Sstevel@tonic-gate  */
15650Sstevel@tonic-gate /*PRINTFLIKE2*/
15660Sstevel@tonic-gate int
set_char_buf(char_buf_t * cb,const char * fmt,...)15670Sstevel@tonic-gate set_char_buf(char_buf_t *cb, const char *fmt, ...)
15680Sstevel@tonic-gate {
15690Sstevel@tonic-gate 	va_list ap;
15700Sstevel@tonic-gate 	int new_size;
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate 	va_start(ap, fmt);
15730Sstevel@tonic-gate 	if ((new_size = vsnprintf(cb->cb_buf, cb->cb_size, fmt, ap)) >=
15740Sstevel@tonic-gate 	    cb->cb_size) {
15750Sstevel@tonic-gate 		if (resize_char_buf(cb, new_size + 1) != PO_SUCCESS) {
15760Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
15770Sstevel@tonic-gate 			return (PO_FAIL);
15780Sstevel@tonic-gate 		}
15790Sstevel@tonic-gate 		(void) vsnprintf(cb->cb_buf, cb->cb_size, fmt, ap);
15800Sstevel@tonic-gate 	}
15810Sstevel@tonic-gate 	va_end(ap);
15820Sstevel@tonic-gate 	return (PO_SUCCESS);
15830Sstevel@tonic-gate }
15840Sstevel@tonic-gate 
15850Sstevel@tonic-gate /*
15860Sstevel@tonic-gate  * Append the supplied data to the character buffer. The user supplies a printf
15870Sstevel@tonic-gate  * like format string and then an appropriate number of parameters for the
15880Sstevel@tonic-gate  * specified format. The character buffer is automatically resized to fit
15890Sstevel@tonic-gate  * the data as determined by resize_char_buf.
15900Sstevel@tonic-gate  */
15910Sstevel@tonic-gate /*PRINTFLIKE2*/
15920Sstevel@tonic-gate int
append_char_buf(char_buf_t * cb,const char * fmt,...)15930Sstevel@tonic-gate append_char_buf(char_buf_t *cb, const char *fmt, ...)
15940Sstevel@tonic-gate {
15950Sstevel@tonic-gate 	va_list ap;
15960Sstevel@tonic-gate 	int new_len;
15970Sstevel@tonic-gate 	char size_buf[1];
15980Sstevel@tonic-gate 	int old_len = 0;
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate 	if (cb->cb_buf != NULL)
16010Sstevel@tonic-gate 		old_len = strlen(cb->cb_buf);
16020Sstevel@tonic-gate 	va_start(ap, fmt);
16030Sstevel@tonic-gate 	new_len = vsnprintf(size_buf, sizeof (size_buf), fmt, ap);
16040Sstevel@tonic-gate 	if (new_len + old_len >= cb->cb_size) {
16050Sstevel@tonic-gate 		if (resize_char_buf(cb, old_len + new_len + 1) !=
16060Sstevel@tonic-gate 		    PO_SUCCESS) {
16070Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
16080Sstevel@tonic-gate 			return (PO_FAIL);
16090Sstevel@tonic-gate 		}
16100Sstevel@tonic-gate 	}
16110Sstevel@tonic-gate 	/*
16120Sstevel@tonic-gate 	 * Resized the buffer to the right size, now append the new data
16130Sstevel@tonic-gate 	 */
16140Sstevel@tonic-gate 	(void) vsnprintf(&cb->cb_buf[old_len], cb->cb_size - old_len, fmt, ap);
16150Sstevel@tonic-gate 	va_end(ap);
16160Sstevel@tonic-gate 	return (PO_SUCCESS);
16170Sstevel@tonic-gate }
16180Sstevel@tonic-gate 
16190Sstevel@tonic-gate /*
16200Sstevel@tonic-gate  * Return the class for the supplied elem.
16210Sstevel@tonic-gate  * If the return is PEC_INVALID, the error code will be set to reflect cause.
16220Sstevel@tonic-gate  */
16230Sstevel@tonic-gate pool_elem_class_t
pool_elem_class(const pool_elem_t * elem)16240Sstevel@tonic-gate pool_elem_class(const pool_elem_t *elem)
16250Sstevel@tonic-gate {
16260Sstevel@tonic-gate 	return (elem->pe_class);
16270Sstevel@tonic-gate }
16280Sstevel@tonic-gate 
16290Sstevel@tonic-gate 
16300Sstevel@tonic-gate /*
16310Sstevel@tonic-gate  * Return the resource class for the supplied elem.
16320Sstevel@tonic-gate  */
16330Sstevel@tonic-gate pool_resource_elem_class_t
pool_resource_elem_class(const pool_elem_t * elem)16340Sstevel@tonic-gate pool_resource_elem_class(const pool_elem_t *elem)
16350Sstevel@tonic-gate {
16360Sstevel@tonic-gate 	return (elem->pe_resource_class);
16370Sstevel@tonic-gate }
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate /*
16400Sstevel@tonic-gate  * Return the component class for the supplied elem.
16410Sstevel@tonic-gate  */
16420Sstevel@tonic-gate pool_component_elem_class_t
pool_component_elem_class(const pool_elem_t * elem)16430Sstevel@tonic-gate pool_component_elem_class(const pool_elem_t *elem)
16440Sstevel@tonic-gate {
16450Sstevel@tonic-gate 	return (elem->pe_component_class);
16460Sstevel@tonic-gate }
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate pool_elem_t *
pool_get_pair(const pool_elem_t * pe)16490Sstevel@tonic-gate pool_get_pair(const pool_elem_t *pe)
16500Sstevel@tonic-gate {
16510Sstevel@tonic-gate 	return (pe->pe_pair);
16520Sstevel@tonic-gate }
16530Sstevel@tonic-gate 
16540Sstevel@tonic-gate void
pool_set_pair(pool_elem_t * pe1,pool_elem_t * pe2)16550Sstevel@tonic-gate pool_set_pair(pool_elem_t *pe1, pool_elem_t *pe2)
16560Sstevel@tonic-gate {
16570Sstevel@tonic-gate 	pe1->pe_pair = pe2;
16580Sstevel@tonic-gate }
16590Sstevel@tonic-gate 
16600Sstevel@tonic-gate int
pool_validate_resource(const pool_conf_t * conf,const char * type,const char * prop,int64_t delta)16610Sstevel@tonic-gate pool_validate_resource(const pool_conf_t *conf, const char *type,
16620Sstevel@tonic-gate     const char *prop, int64_t delta)
16630Sstevel@tonic-gate {
16640Sstevel@tonic-gate 	pool_conf_t *dyn;
16650Sstevel@tonic-gate 	uint_t nelem;
16660Sstevel@tonic-gate 	uint64_t available, required, uval;
16670Sstevel@tonic-gate 	int i;
16680Sstevel@tonic-gate 	pool_resource_t **rl;
16690Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
16700Sstevel@tonic-gate 	pool_value_t val1 = POOL_VALUE_INITIALIZER;
16710Sstevel@tonic-gate 	pool_value_t *pvals[] = { NULL, NULL };
16720Sstevel@tonic-gate 
16730Sstevel@tonic-gate 	if (strcmp(prop, c_min_prop) && strcmp(prop, c_max_prop)) {
16740Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16750Sstevel@tonic-gate 		return (PO_FAIL);
16760Sstevel@tonic-gate 	}
16770Sstevel@tonic-gate 
16780Sstevel@tonic-gate 	pvals[0] = &val;
16790Sstevel@tonic-gate 	(void) pool_value_set_string(&val, type);
16800Sstevel@tonic-gate 	(void) pool_value_set_name(&val, c_type);
16810Sstevel@tonic-gate 
16820Sstevel@tonic-gate 	/*
16830Sstevel@tonic-gate 	 * Check that there are available resources on this
16840Sstevel@tonic-gate 	 * system for this configuration to be applied. Find
16850Sstevel@tonic-gate 	 * each resource type and then find all resources of
16860Sstevel@tonic-gate 	 * each type and total ".min". Find all available
16870Sstevel@tonic-gate 	 * resources and ensure >= total min.
16880Sstevel@tonic-gate 	 */
16890Sstevel@tonic-gate 
16900Sstevel@tonic-gate 	available = 0;
16910Sstevel@tonic-gate 	required = delta;
16920Sstevel@tonic-gate 
16930Sstevel@tonic-gate 	if ((rl = (pool_query_resources(conf, &nelem, pvals))) == NULL)
16940Sstevel@tonic-gate 		return (PO_FAIL);
16950Sstevel@tonic-gate 
16960Sstevel@tonic-gate 	for (i = 0; i < nelem; i++) {
16970Sstevel@tonic-gate 		if (pool_get_ns_property(TO_ELEM(rl[i]), prop,
16980Sstevel@tonic-gate 		    &val1) == POC_INVAL ||
16990Sstevel@tonic-gate 		    pool_value_get_uint64(&val1, &uval) != PO_SUCCESS) {
17000Sstevel@tonic-gate 			free(rl);
17010Sstevel@tonic-gate 			return (PO_FAIL);
17020Sstevel@tonic-gate 		}
17030Sstevel@tonic-gate 		/*
17040Sstevel@tonic-gate 		 * Watch out for overflow
17050Sstevel@tonic-gate 		 */
17060Sstevel@tonic-gate 		if (required + uval < required) {
17070Sstevel@tonic-gate 			required = UINT64_MAX;
17080Sstevel@tonic-gate 			break;
17090Sstevel@tonic-gate 		} else
17100Sstevel@tonic-gate 			required += uval;
17110Sstevel@tonic-gate 	}
17120Sstevel@tonic-gate 
17130Sstevel@tonic-gate 	if (conf_is_dynamic(conf) == PO_TRUE) {
17140Sstevel@tonic-gate 		dyn = (pool_conf_t *)conf;
17150Sstevel@tonic-gate 	} else {
17160Sstevel@tonic-gate 		free(rl);
17170Sstevel@tonic-gate 		if ((dyn = pool_conf_alloc()) == NULL)
17180Sstevel@tonic-gate 			return (PO_FAIL);
17190Sstevel@tonic-gate 		if (pool_conf_open(dyn, pool_dynamic_location(), PO_RDONLY) !=
17200Sstevel@tonic-gate 		PO_SUCCESS) {
17210Sstevel@tonic-gate 			pool_conf_free(dyn);
17220Sstevel@tonic-gate 			return (PO_FAIL);
17230Sstevel@tonic-gate 		}
17240Sstevel@tonic-gate 		if ((rl = (pool_query_resources(dyn, &nelem, pvals))) ==
17250Sstevel@tonic-gate 		    NULL) {
17260Sstevel@tonic-gate 			(void) pool_conf_close(dyn);
17270Sstevel@tonic-gate 			pool_conf_free(dyn);
17280Sstevel@tonic-gate 			return (PO_FAIL);
17290Sstevel@tonic-gate 		}
17300Sstevel@tonic-gate 	}
17310Sstevel@tonic-gate 	for (i = 0; i < nelem; i++) {
17320Sstevel@tonic-gate 		if (pool_get_ns_property(TO_ELEM(rl[i]), c_size_prop,
17330Sstevel@tonic-gate 		    &val1) == POC_INVAL ||
17340Sstevel@tonic-gate 		    pool_value_get_uint64(&val1, &uval) != PO_SUCCESS) {
17350Sstevel@tonic-gate 			free(rl);
17360Sstevel@tonic-gate 			if (conf != dyn) {
17370Sstevel@tonic-gate 				(void) pool_conf_close(dyn);
17380Sstevel@tonic-gate 				pool_conf_free(dyn);
17390Sstevel@tonic-gate 			}
17400Sstevel@tonic-gate 			return (PO_FAIL);
17410Sstevel@tonic-gate 		}
17420Sstevel@tonic-gate 		available += uval;
17430Sstevel@tonic-gate 	}
17440Sstevel@tonic-gate 	free(rl);
17450Sstevel@tonic-gate 	if (conf != dyn) {
17460Sstevel@tonic-gate 		(void) pool_conf_close(dyn);
17470Sstevel@tonic-gate 		pool_conf_free(dyn);
17480Sstevel@tonic-gate 	}
17490Sstevel@tonic-gate 	if (strcmp(prop, c_min_prop) == 0) {
17500Sstevel@tonic-gate 		if (available < required) {
17510Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
17520Sstevel@tonic-gate 			return (PO_FAIL);
17530Sstevel@tonic-gate 		}
17540Sstevel@tonic-gate 	} else {
17550Sstevel@tonic-gate 		if (available > required) {
17560Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
17570Sstevel@tonic-gate 			return (PO_FAIL);
17580Sstevel@tonic-gate 		}
17590Sstevel@tonic-gate 	}
17600Sstevel@tonic-gate 	return (PO_SUCCESS);
17610Sstevel@tonic-gate }
17620Sstevel@tonic-gate 
17630Sstevel@tonic-gate /*
17640Sstevel@tonic-gate  * If _libpool_debug is set, printf the debug message to stderr with an
17650Sstevel@tonic-gate  * appropriate prefix in front of it.
17660Sstevel@tonic-gate  */
17670Sstevel@tonic-gate void
do_dprintf(const char * format,va_list ap)17680Sstevel@tonic-gate do_dprintf(const char *format, va_list ap)
17690Sstevel@tonic-gate {
17700Sstevel@tonic-gate 	if (_libpool_debug) {
17710Sstevel@tonic-gate 		(void) fputs("libpool DEBUG: ", stderr);
17720Sstevel@tonic-gate 		(void) vfprintf(stderr, format, ap);
17730Sstevel@tonic-gate 	}
17740Sstevel@tonic-gate }
17750Sstevel@tonic-gate 
17760Sstevel@tonic-gate /*PRINTFLIKE1*/
17770Sstevel@tonic-gate void
dprintf(const char * format,...)17780Sstevel@tonic-gate dprintf(const char *format, ...)
17790Sstevel@tonic-gate {
17800Sstevel@tonic-gate 	if (_libpool_debug) {
17810Sstevel@tonic-gate 		va_list alist;
17820Sstevel@tonic-gate 		va_start(alist, format);
17830Sstevel@tonic-gate 		do_dprintf(format, alist);
17840Sstevel@tonic-gate 		va_end(alist);
17850Sstevel@tonic-gate 	}
17860Sstevel@tonic-gate }
17870Sstevel@tonic-gate 
17880Sstevel@tonic-gate /*
17890Sstevel@tonic-gate  * log_alloc() allocates a new, empty transaction log.
17900Sstevel@tonic-gate  *
17910Sstevel@tonic-gate  * Returns a pointer to the new log or NULL on failure.
17920Sstevel@tonic-gate  */
17930Sstevel@tonic-gate log_t *
log_alloc(pool_conf_t * conf)17940Sstevel@tonic-gate log_alloc(pool_conf_t *conf)
17950Sstevel@tonic-gate {
17960Sstevel@tonic-gate 	log_t *l;
17970Sstevel@tonic-gate 
17980Sstevel@tonic-gate 	if ((l = calloc(1, sizeof (log_t))) == NULL) {
17990Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
18000Sstevel@tonic-gate 		return (NULL);
18010Sstevel@tonic-gate 	}
18020Sstevel@tonic-gate 	l->l_state = LS_DO;
18030Sstevel@tonic-gate 	l->l_conf = conf;
18040Sstevel@tonic-gate 	if ((l->l_sentinel = log_item_alloc(l, 0, NULL))
18050Sstevel@tonic-gate 	    == NULL) {
18060Sstevel@tonic-gate 		free(l);
18070Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
18080Sstevel@tonic-gate 		return (NULL);
18090Sstevel@tonic-gate 	}
18100Sstevel@tonic-gate 	l->l_sentinel->li_next = l->l_sentinel;
18110Sstevel@tonic-gate 	l->l_sentinel->li_prev = l->l_sentinel;
18120Sstevel@tonic-gate 
18130Sstevel@tonic-gate 	return (l);
18140Sstevel@tonic-gate }
18150Sstevel@tonic-gate 
18160Sstevel@tonic-gate /*
18170Sstevel@tonic-gate  * log_free() reclaims the resources associated with a transaction log.
18180Sstevel@tonic-gate  */
18190Sstevel@tonic-gate void
log_free(log_t * l)18200Sstevel@tonic-gate log_free(log_t *l)
18210Sstevel@tonic-gate {
18220Sstevel@tonic-gate 	(void) log_walk(l, log_item_free);
18230Sstevel@tonic-gate 	(void) log_item_free(l->l_sentinel);
18240Sstevel@tonic-gate 	free(l);
18250Sstevel@tonic-gate }
18260Sstevel@tonic-gate /*
18270Sstevel@tonic-gate  * log_empty() removes all items from a transaction log. It is the
18280Sstevel@tonic-gate  * users responsibility to ensure that any resources associated with
18290Sstevel@tonic-gate  * an item are reclaimed before this function is invoked.
18300Sstevel@tonic-gate  */
18310Sstevel@tonic-gate void
log_empty(log_t * l)18320Sstevel@tonic-gate log_empty(log_t *l)
18330Sstevel@tonic-gate {
18340Sstevel@tonic-gate 	(void) log_walk(l, log_item_free);
18350Sstevel@tonic-gate }
18360Sstevel@tonic-gate 
18370Sstevel@tonic-gate /*
18380Sstevel@tonic-gate  * log_walk() visits each log item in turn and executes the supplied action
18390Sstevel@tonic-gate  * using the item as a parameter. If no action is supplied, then the item
18400Sstevel@tonic-gate  * uses it's own stored action.
18410Sstevel@tonic-gate  *
18420Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
18430Sstevel@tonic-gate  */
18440Sstevel@tonic-gate int
log_walk(log_t * l,log_item_action_t action)18450Sstevel@tonic-gate log_walk(log_t *l, log_item_action_t action)
18460Sstevel@tonic-gate {
18470Sstevel@tonic-gate 	log_item_t *li, *li_next;
18480Sstevel@tonic-gate 
18490Sstevel@tonic-gate 	li = l->l_sentinel->li_next;
18500Sstevel@tonic-gate 	while (li != l->l_sentinel) {
18510Sstevel@tonic-gate 		li_next = li->li_next;
18520Sstevel@tonic-gate 		if ((action(li)) != PO_SUCCESS)
18530Sstevel@tonic-gate 			return (PO_FAIL);
18540Sstevel@tonic-gate 		li = li_next;
18550Sstevel@tonic-gate 	}
18560Sstevel@tonic-gate 	return (PO_SUCCESS);
18570Sstevel@tonic-gate }
18580Sstevel@tonic-gate 
18590Sstevel@tonic-gate /*
18600Sstevel@tonic-gate  * log_reverse_walk() visits each log item in turn (in reverse order)
18610Sstevel@tonic-gate  * and executes the supplied action using the item as a parameter.
18620Sstevel@tonic-gate  *
18630Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
18640Sstevel@tonic-gate  */
18650Sstevel@tonic-gate int
log_reverse_walk(log_t * l,log_item_action_t action)18660Sstevel@tonic-gate log_reverse_walk(log_t *l, log_item_action_t action)
18670Sstevel@tonic-gate {
18680Sstevel@tonic-gate 	log_item_t *li, *li_prev;
18690Sstevel@tonic-gate 
18700Sstevel@tonic-gate 	li = l->l_sentinel->li_prev;
18710Sstevel@tonic-gate 	while (li != l->l_sentinel) {
18720Sstevel@tonic-gate 		li_prev = li->li_prev;
18730Sstevel@tonic-gate 		if ((action(li)) != PO_SUCCESS)
18740Sstevel@tonic-gate 			return (PO_FAIL);
18750Sstevel@tonic-gate 		li = li_prev;
18760Sstevel@tonic-gate 	}
18770Sstevel@tonic-gate 	return (PO_SUCCESS);
18780Sstevel@tonic-gate }
18790Sstevel@tonic-gate 
18800Sstevel@tonic-gate /*
18810Sstevel@tonic-gate  * log_size() returns the size of the log, i.e. the number of items pending in
18820Sstevel@tonic-gate  * the log.
18830Sstevel@tonic-gate  */
18840Sstevel@tonic-gate uint_t
log_size(log_t * l)18850Sstevel@tonic-gate log_size(log_t *l)
18860Sstevel@tonic-gate {
18870Sstevel@tonic-gate 	log_item_t *li;
18880Sstevel@tonic-gate 	uint_t size = 0;
18890Sstevel@tonic-gate 
18900Sstevel@tonic-gate 	for (li = l->l_sentinel->li_next; li != l->l_sentinel; li = li->li_next)
18910Sstevel@tonic-gate 		size++;
18920Sstevel@tonic-gate 	return (size);
18930Sstevel@tonic-gate }
18940Sstevel@tonic-gate 
18950Sstevel@tonic-gate /*
18960Sstevel@tonic-gate  * log_append() allocates a new log item to hold the supplied details and
18970Sstevel@tonic-gate  * appends the newly created item to the supplied log.
18980Sstevel@tonic-gate  *
18990Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
19000Sstevel@tonic-gate  */
19010Sstevel@tonic-gate int
log_append(log_t * l,int op,void * details)19020Sstevel@tonic-gate log_append(log_t *l, int op, void *details)
19030Sstevel@tonic-gate {
19040Sstevel@tonic-gate 	log_item_t *li;
19050Sstevel@tonic-gate 
19060Sstevel@tonic-gate 	if ((li = log_item_alloc(l, op, details)) == NULL) {
19070Sstevel@tonic-gate 		l->l_state = LS_UNDO;
19080Sstevel@tonic-gate 		return (PO_FAIL);
19090Sstevel@tonic-gate 	}
19100Sstevel@tonic-gate 	/*
19110Sstevel@tonic-gate 	 * Link it in
19120Sstevel@tonic-gate 	 */
19130Sstevel@tonic-gate 	li->li_prev = l->l_sentinel->li_prev;
19140Sstevel@tonic-gate 	li->li_next = l->l_sentinel;
19150Sstevel@tonic-gate 	l->l_sentinel->li_prev->li_next = li;
19160Sstevel@tonic-gate 	l->l_sentinel->li_prev = li;
19170Sstevel@tonic-gate 	return (PO_SUCCESS);
19180Sstevel@tonic-gate }
19190Sstevel@tonic-gate 
19200Sstevel@tonic-gate /*
19210Sstevel@tonic-gate  * log_item_alloc() allocates a new transaction log item. The item should be
19220Sstevel@tonic-gate  * used to store details about a transaction which may need to be undone if
19230Sstevel@tonic-gate  * commit processing fails.
19240Sstevel@tonic-gate  *
19250Sstevel@tonic-gate  * Returns a pointer to a new transaction log item or NULL.
19260Sstevel@tonic-gate  */
19270Sstevel@tonic-gate log_item_t *
log_item_alloc(log_t * l,int op,void * details)19280Sstevel@tonic-gate log_item_alloc(log_t *l, int op, void *details)
19290Sstevel@tonic-gate {
19300Sstevel@tonic-gate 	log_item_t *li;
19310Sstevel@tonic-gate 
19320Sstevel@tonic-gate 	if ((li = malloc(sizeof (log_item_t))) == NULL) {
19330Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
19340Sstevel@tonic-gate 		return (NULL);
19350Sstevel@tonic-gate 	}
19360Sstevel@tonic-gate 
19370Sstevel@tonic-gate 	(void) memset(li, 0, sizeof (log_item_t));
19380Sstevel@tonic-gate 	li->li_log = l;
19390Sstevel@tonic-gate 	li->li_op = op;
19400Sstevel@tonic-gate 	li->li_details = details;
19410Sstevel@tonic-gate 	li->li_state = LS_DO;
19420Sstevel@tonic-gate 
19430Sstevel@tonic-gate 	return (li);
19440Sstevel@tonic-gate }
19450Sstevel@tonic-gate 
19460Sstevel@tonic-gate /*
19470Sstevel@tonic-gate  * log_item_free() reclaims the resources associated with a log_item_t.
19480Sstevel@tonic-gate  */
19490Sstevel@tonic-gate int
log_item_free(log_item_t * li)19500Sstevel@tonic-gate log_item_free(log_item_t *li)
19510Sstevel@tonic-gate {
19520Sstevel@tonic-gate 	li->li_prev->li_next = li->li_next;
19530Sstevel@tonic-gate 	li->li_next->li_prev = li->li_prev;
19540Sstevel@tonic-gate 	free(li);
19550Sstevel@tonic-gate 	return (PO_SUCCESS);
19560Sstevel@tonic-gate }
19570Sstevel@tonic-gate 
19580Sstevel@tonic-gate /*
19590Sstevel@tonic-gate  * atom_string() checks the string table to see if a string is already
19600Sstevel@tonic-gate  * stored. If it is, return a pointer to it. If not, duplicate the
19610Sstevel@tonic-gate  * string and return a pointer to the duplicate.
19620Sstevel@tonic-gate  */
19630Sstevel@tonic-gate const char *
atom_string(const char * s)19640Sstevel@tonic-gate atom_string(const char *s)
19650Sstevel@tonic-gate {
19660Sstevel@tonic-gate 	atom_t *atom;
19670Sstevel@tonic-gate 
19680Sstevel@tonic-gate 	/*
19690Sstevel@tonic-gate 	 * atom_init() must have completed successfully
19700Sstevel@tonic-gate 	 */
19710Sstevel@tonic-gate 	atom_init();
19720Sstevel@tonic-gate 	(void) mutex_lock(&_atom_lock);
19730Sstevel@tonic-gate 	if ((atom = dict_get(_pv_atoms, s)) == NULL) {
19740Sstevel@tonic-gate 		if ((atom = calloc(1, sizeof (atom_t))) == NULL) {
19750Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
19760Sstevel@tonic-gate 			(void) mutex_unlock(&_atom_lock);
19770Sstevel@tonic-gate 			return (NULL);
19780Sstevel@tonic-gate 		}
19790Sstevel@tonic-gate 		if ((atom->a_string = strdup(s)) == NULL) {
19800Sstevel@tonic-gate 			(void) mutex_unlock(&_atom_lock);
19810Sstevel@tonic-gate 			free(atom);
19820Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
19830Sstevel@tonic-gate 			return (NULL);
19840Sstevel@tonic-gate 		}
19850Sstevel@tonic-gate 		(void) dict_put(_pv_atoms, atom->a_string, atom);
19860Sstevel@tonic-gate 	}
19870Sstevel@tonic-gate 	atom->a_count++;
19880Sstevel@tonic-gate 	(void) mutex_unlock(&_atom_lock);
19890Sstevel@tonic-gate 	return (atom->a_string);
19900Sstevel@tonic-gate }
19910Sstevel@tonic-gate 
19920Sstevel@tonic-gate /*
19930Sstevel@tonic-gate  * atom_free() decrements the reference count for the supplied
19940Sstevel@tonic-gate  * string. If the reference count reaches zero, then the atom is
19950Sstevel@tonic-gate  * destroyed.
19960Sstevel@tonic-gate  */
19970Sstevel@tonic-gate void
atom_free(const char * s)19980Sstevel@tonic-gate atom_free(const char *s)
19990Sstevel@tonic-gate {
20000Sstevel@tonic-gate 	atom_t *atom;
20010Sstevel@tonic-gate 
20020Sstevel@tonic-gate 	(void) mutex_lock(&_atom_lock);
20030Sstevel@tonic-gate 	if ((atom = dict_get(_pv_atoms, s)) != NULL) {
20040Sstevel@tonic-gate 		if (--atom->a_count == 0) {
20050Sstevel@tonic-gate 			(void) dict_remove(_pv_atoms, s);
20060Sstevel@tonic-gate 			free(atom->a_string);
20070Sstevel@tonic-gate 			free(atom);
20080Sstevel@tonic-gate 		}
20090Sstevel@tonic-gate 	}
20100Sstevel@tonic-gate 	(void) mutex_unlock(&_atom_lock);
20110Sstevel@tonic-gate }
20120Sstevel@tonic-gate 
20130Sstevel@tonic-gate #ifdef DEBUG
20140Sstevel@tonic-gate /*
20150Sstevel@tonic-gate  * log_item_dprintf() prints the contents of the supplied log item using the
20160Sstevel@tonic-gate  * pools dprintf() trace mechanism.
20170Sstevel@tonic-gate  *
20180Sstevel@tonic-gate  * Returns PO_SUCCESS
20190Sstevel@tonic-gate  */
20200Sstevel@tonic-gate void
log_item_dprintf(log_item_t * li)20210Sstevel@tonic-gate log_item_dprintf(log_item_t *li)
20220Sstevel@tonic-gate {
20230Sstevel@tonic-gate 	dprintf("LOGDUMP: %d operation, %p\n", li->li_op, li->li_details);
20240Sstevel@tonic-gate }
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate /*
20270Sstevel@tonic-gate  * log_item_dprintf() prints the contents of the supplied log item using the
20280Sstevel@tonic-gate  * pools dprintf() trace mechanism.
20290Sstevel@tonic-gate  *
20300Sstevel@tonic-gate  * Returns PO_SUCCESS
20310Sstevel@tonic-gate  */
20320Sstevel@tonic-gate void
pool_elem_dprintf(const pool_elem_t * pe)20330Sstevel@tonic-gate pool_elem_dprintf(const pool_elem_t *pe)
20340Sstevel@tonic-gate {
20350Sstevel@tonic-gate 	if (pool_elem_class(pe) != PEC_COMP) {
20360Sstevel@tonic-gate 		const char *name = elem_get_name(pe);
20370Sstevel@tonic-gate 		dprintf("element type: %s name: %s\n",
20380Sstevel@tonic-gate 		    pool_elem_class_string(pe), name);
20390Sstevel@tonic-gate 		free((void *)name);
20400Sstevel@tonic-gate 	} else {
20410Sstevel@tonic-gate 		id_t sys_id = elem_get_sysid(pe);
20420Sstevel@tonic-gate 		dprintf("element type: %s sys_id: %d\n",
20430Sstevel@tonic-gate 		    pool_elem_class_string(pe), sys_id);
20440Sstevel@tonic-gate 	}
20450Sstevel@tonic-gate }
20460Sstevel@tonic-gate #endif	/* DEBUG */
2047