xref: /onnv-gate/usr/src/lib/libpool/common/pool.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
51823Sgarypen  * Common Development and Distribution License (the "License").
61823Sgarypen  * 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  */
211823Sgarypen 
220Sstevel@tonic-gate /*
231823Sgarypen  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <assert.h>
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <stdlib.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <thread.h>
340Sstevel@tonic-gate #include <synch.h>
350Sstevel@tonic-gate #include <unistd.h>
360Sstevel@tonic-gate #include <stropts.h>
370Sstevel@tonic-gate #include <fcntl.h>
380Sstevel@tonic-gate #include <note.h>
390Sstevel@tonic-gate #include <errno.h>
400Sstevel@tonic-gate #include <ctype.h>
410Sstevel@tonic-gate #include <libintl.h>
420Sstevel@tonic-gate #include <pool.h>
430Sstevel@tonic-gate #include <signal.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #include <sys/pool.h>
460Sstevel@tonic-gate #include <sys/priocntl.h>
470Sstevel@tonic-gate #include <sys/types.h>
480Sstevel@tonic-gate #include <sys/stat.h>
490Sstevel@tonic-gate #include <sys/wait.h>
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #include "pool_internal.h"
520Sstevel@tonic-gate #include "pool_impl.h"
530Sstevel@tonic-gate 
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate  * libpool Interface Routines
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  * pool.c implements (most of) the external interface to libpool
580Sstevel@tonic-gate  * users. Some of the interface is implemented in pool_internal.c for
590Sstevel@tonic-gate  * reasons of internal code organisation.  The core requirements for
600Sstevel@tonic-gate  * pool.c are:
610Sstevel@tonic-gate  *
620Sstevel@tonic-gate  * Data Abstraction
630Sstevel@tonic-gate  *
640Sstevel@tonic-gate  * The abstraction of the actual datastore so that no details of the
650Sstevel@tonic-gate  * underlying data representation mechanism are revealed to users of
660Sstevel@tonic-gate  * the library. For instance, the fact that we use the kernel or files
670Sstevel@tonic-gate  * to store our configurations is completely abstracted via the
680Sstevel@tonic-gate  * various libpool APIs.
690Sstevel@tonic-gate  *
700Sstevel@tonic-gate  * External Interaction
710Sstevel@tonic-gate  *
720Sstevel@tonic-gate  * libpool users manipulate configuration components via the API
730Sstevel@tonic-gate  * defined in pool.h. Most functions in this file act as interceptors,
740Sstevel@tonic-gate  * validating parameters before redirecting the request into a
750Sstevel@tonic-gate  * specific datastore implementation for the actual work to be done.
760Sstevel@tonic-gate  *
770Sstevel@tonic-gate  * These main sets of requirements have driven the design so that it
780Sstevel@tonic-gate  * is possible to replace the entire datastore type without having to
790Sstevel@tonic-gate  * modify the external (or internal provider) APIs. It is possible to
800Sstevel@tonic-gate  * modify the storage technology used by libpool by implementing a new
810Sstevel@tonic-gate  * set of datastore provider operations. Simply modify the
820Sstevel@tonic-gate  * pool_conf_open() routine to establish a new datastore as the
830Sstevel@tonic-gate  * provider for a configuration.
840Sstevel@tonic-gate  *
850Sstevel@tonic-gate  * The key components in a libpool configuration are :
860Sstevel@tonic-gate  * pool_conf_t - This represents a complete configuration instance
870Sstevel@tonic-gate  * pool_t - A pool inside a configuration
880Sstevel@tonic-gate  * pool_resource_t - A resource inside a configuration
890Sstevel@tonic-gate  * pool_component_t - A component of a resource
900Sstevel@tonic-gate  *
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate 
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate  * Used to control transfer setup.
950Sstevel@tonic-gate  */
960Sstevel@tonic-gate #define	XFER_FAIL	PO_FAIL
970Sstevel@tonic-gate #define	XFER_SUCCESS	PO_SUCCESS
980Sstevel@tonic-gate #define	XFER_CONTINUE	1
990Sstevel@tonic-gate 
1001042Sgarypen #define	SMF_SVC_INSTANCE	"svc:/system/pools:default"
1010Sstevel@tonic-gate #define	E_ERROR		1		/* Exit status for error */
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate #ifndef	TEXT_DOMAIN
1040Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
1050Sstevel@tonic-gate #endif	/* TEXT_DOMAIN */
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate const char pool_info_location[] =  "/dev/pool";
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate /*
1100Sstevel@tonic-gate  * Static data
1110Sstevel@tonic-gate  */
1120Sstevel@tonic-gate static const char static_location[] = "/etc/pooladm.conf";
1130Sstevel@tonic-gate static const char dynamic_location[] =  "/dev/poolctl";
1140Sstevel@tonic-gate static mutex_t		keylock;
1150Sstevel@tonic-gate static thread_key_t	errkey;
1160Sstevel@tonic-gate static int		keyonce = 0;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate /*
1190Sstevel@tonic-gate  * libpool error code
1200Sstevel@tonic-gate  */
1210Sstevel@tonic-gate static int pool_errval = POE_OK;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate /*
1240Sstevel@tonic-gate  * libpool version
1250Sstevel@tonic-gate  */
1260Sstevel@tonic-gate static uint_t pool_workver = POOL_VER_CURRENT;
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate static const char *data_type_tags[] = {
1290Sstevel@tonic-gate 	"uint",
1300Sstevel@tonic-gate 	"int",
1310Sstevel@tonic-gate 	"float",
1320Sstevel@tonic-gate 	"boolean",
1330Sstevel@tonic-gate 	"string"
1340Sstevel@tonic-gate };
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate /*
1370Sstevel@tonic-gate  * static functions
1380Sstevel@tonic-gate  */
1390Sstevel@tonic-gate static int pool_elem_remove(pool_elem_t *);
1400Sstevel@tonic-gate static int is_valid_prop_name(const char *);
1410Sstevel@tonic-gate static int prop_buf_build_cb(pool_conf_t *, pool_elem_t *, const char *,
1420Sstevel@tonic-gate     pool_value_t *, void *);
1430Sstevel@tonic-gate static char *pool_base_info(const pool_elem_t *, char_buf_t *, int);
1440Sstevel@tonic-gate static int choose_components(pool_resource_t *, pool_resource_t *, uint64_t);
1450Sstevel@tonic-gate static int pool_conf_check(const pool_conf_t *);
1460Sstevel@tonic-gate static void free_value_list(int, pool_value_t **);
1470Sstevel@tonic-gate static int setup_transfer(pool_conf_t *, pool_resource_t *, pool_resource_t *,
1480Sstevel@tonic-gate     uint64_t, uint64_t *, uint64_t *);
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate /*
1510Sstevel@tonic-gate  * Return the "static" location string for libpool.
1520Sstevel@tonic-gate  */
1530Sstevel@tonic-gate const char *
1540Sstevel@tonic-gate pool_static_location(void)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate 	return (static_location);
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate  * Return the "dynamic" location string for libpool.
1610Sstevel@tonic-gate  */
1620Sstevel@tonic-gate const char *
1630Sstevel@tonic-gate pool_dynamic_location(void)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate 	return (dynamic_location);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate  * Return the status for a configuration. If the configuration has
1700Sstevel@tonic-gate  * been successfully opened, then the status will be POF_VALID or
1710Sstevel@tonic-gate  * POF_DESTROY.  If the configuration failed to open properly or has
1720Sstevel@tonic-gate  * been closed or removed, then the status will be POF_INVALID.
1730Sstevel@tonic-gate  */
1740Sstevel@tonic-gate pool_conf_state_t
1750Sstevel@tonic-gate pool_conf_status(const pool_conf_t *conf)
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate 	return (conf->pc_state);
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate /*
1810Sstevel@tonic-gate  * Bind idtype id to the pool name.
1820Sstevel@tonic-gate  */
1830Sstevel@tonic-gate int
1840Sstevel@tonic-gate pool_set_binding(const char *pool_name, idtype_t idtype, id_t id)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate 	pool_conf_t *conf;
1870Sstevel@tonic-gate 	int result;
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	if ((conf = pool_conf_alloc()) == NULL)
1900Sstevel@tonic-gate 		return (PO_FAIL);
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
1930Sstevel@tonic-gate 		pool_conf_free(conf);
1940Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
1950Sstevel@tonic-gate 		return (PO_FAIL);
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	result = conf->pc_prov->pc_set_binding(conf, pool_name, idtype, id);
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	(void) pool_conf_close(conf);
2010Sstevel@tonic-gate 	pool_conf_free(conf);
2020Sstevel@tonic-gate 	return (result);
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate /*
2060Sstevel@tonic-gate  * pool_get_resource_binding() returns the binding for a pid to the supplied
2070Sstevel@tonic-gate  * type of resource. If a binding cannot be determined, NULL is returned.
2080Sstevel@tonic-gate  */
2090Sstevel@tonic-gate char *
2100Sstevel@tonic-gate pool_get_resource_binding(const char *sz_type, pid_t pid)
2110Sstevel@tonic-gate {
2120Sstevel@tonic-gate 	pool_conf_t *conf;
2130Sstevel@tonic-gate 	char *result;
2140Sstevel@tonic-gate 	pool_resource_elem_class_t type;
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	if ((type = pool_resource_elem_class_from_string(sz_type)) ==
2170Sstevel@tonic-gate 	    PREC_INVALID) {
2180Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
2190Sstevel@tonic-gate 		return (NULL);
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	if ((conf = pool_conf_alloc()) == NULL)
2230Sstevel@tonic-gate 		return (NULL);
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY)
2260Sstevel@tonic-gate 	    != PO_SUCCESS) {
2270Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
2280Sstevel@tonic-gate 		pool_conf_free(conf);
2290Sstevel@tonic-gate 		return (NULL);
2300Sstevel@tonic-gate 	}
2310Sstevel@tonic-gate 	result = conf->pc_prov->pc_get_resource_binding(conf, type, pid);
2320Sstevel@tonic-gate 	(void) pool_conf_close(conf);
2330Sstevel@tonic-gate 	pool_conf_free(conf);
2340Sstevel@tonic-gate 	return (result);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate  * pool_get_binding() returns the binding for a pid to a pool. If a
2390Sstevel@tonic-gate  * binding cannot be determined, NULL is returned.
2400Sstevel@tonic-gate  */
2410Sstevel@tonic-gate char *
2420Sstevel@tonic-gate pool_get_binding(pid_t pid)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate 	pool_conf_t *conf;
2450Sstevel@tonic-gate 	char *result;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	if ((conf = pool_conf_alloc()) == NULL)
2480Sstevel@tonic-gate 		return (NULL);
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY)
2510Sstevel@tonic-gate 	    != PO_SUCCESS) {
2520Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
2530Sstevel@tonic-gate 		pool_conf_free(conf);
2540Sstevel@tonic-gate 		return (NULL);
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 	result = conf->pc_prov->pc_get_binding(conf, pid);
2570Sstevel@tonic-gate 	(void) pool_conf_close(conf);
2580Sstevel@tonic-gate 	pool_conf_free(conf);
2590Sstevel@tonic-gate 	return (result);
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate /*ARGSUSED*/
2630Sstevel@tonic-gate int
2640Sstevel@tonic-gate prop_buf_build_cb(pool_conf_t *UNUSED, pool_elem_t *pe, const char *name,
2650Sstevel@tonic-gate     pool_value_t *pval, void *user)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate 	uint64_t u;
2680Sstevel@tonic-gate 	int64_t i;
2690Sstevel@tonic-gate 	uchar_t bool;
2700Sstevel@tonic-gate 	const char *str;
2710Sstevel@tonic-gate 	double d;
2720Sstevel@tonic-gate 	char_buf_t *cb = (char_buf_t *)user;
2730Sstevel@tonic-gate 	int type = pool_value_get_type(pval);
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	/*
2760Sstevel@tonic-gate 	 * Ignore "type" and "<type>.name" properties as these are not
2770Sstevel@tonic-gate 	 * to be displayed by this function
2780Sstevel@tonic-gate 	 */
2790Sstevel@tonic-gate 	if (strcmp(name, c_type) == 0 ||
2800Sstevel@tonic-gate 	    strcmp(property_name_minus_ns(pe, name), c_name) == 0)
2810Sstevel@tonic-gate 		return (PO_SUCCESS);
2820Sstevel@tonic-gate 	if (append_char_buf(cb, "\n%s\t%s\t%s ", cb->cb_tab_buf,
2830Sstevel@tonic-gate 	    data_type_tags[type], name) == PO_FAIL)
2840Sstevel@tonic-gate 		return (PO_FAIL);
2850Sstevel@tonic-gate 	switch (type) {
2860Sstevel@tonic-gate 	case POC_UINT:
2870Sstevel@tonic-gate 		(void) pool_value_get_uint64(pval, &u);
2880Sstevel@tonic-gate 		if (append_char_buf(cb, "%llu", (u_longlong_t)u) == PO_FAIL)
2890Sstevel@tonic-gate 			return (PO_FAIL);
2900Sstevel@tonic-gate 		break;
2910Sstevel@tonic-gate 	case POC_INT:
2920Sstevel@tonic-gate 		(void) pool_value_get_int64(pval, &i);
2930Sstevel@tonic-gate 		if (append_char_buf(cb, "%lld", (longlong_t)i) == PO_FAIL)
2940Sstevel@tonic-gate 			return (PO_FAIL);
2950Sstevel@tonic-gate 		break;
2960Sstevel@tonic-gate 	case POC_STRING:
2970Sstevel@tonic-gate 		(void) pool_value_get_string(pval, &str);
2980Sstevel@tonic-gate 		if (append_char_buf(cb, "%s", str) == PO_FAIL)
2990Sstevel@tonic-gate 			return (PO_FAIL);
3000Sstevel@tonic-gate 		break;
3010Sstevel@tonic-gate 	case POC_BOOL:
3020Sstevel@tonic-gate 		(void) pool_value_get_bool(pval, &bool);
3030Sstevel@tonic-gate 		if (bool == 0) {
3040Sstevel@tonic-gate 			if (append_char_buf(cb, "%s", "false") == PO_FAIL)
3050Sstevel@tonic-gate 				return (PO_FAIL);
3060Sstevel@tonic-gate 		} else {
3070Sstevel@tonic-gate 			if (append_char_buf(cb, "%s", "true") == PO_FAIL)
3080Sstevel@tonic-gate 				return (PO_FAIL);
3090Sstevel@tonic-gate 		}
3100Sstevel@tonic-gate 		break;
3110Sstevel@tonic-gate 	case POC_DOUBLE:
3120Sstevel@tonic-gate 		(void) pool_value_get_double(pval, &d);
3130Sstevel@tonic-gate 		if (append_char_buf(cb, "%g", d) == PO_FAIL)
3140Sstevel@tonic-gate 			return (PO_FAIL);
3150Sstevel@tonic-gate 		break;
3160Sstevel@tonic-gate 	case POC_INVAL: /* Do nothing */
3170Sstevel@tonic-gate 		break;
3180Sstevel@tonic-gate 	default:
3190Sstevel@tonic-gate 		return (PO_FAIL);
3200Sstevel@tonic-gate 	}
3210Sstevel@tonic-gate 	return (PO_SUCCESS);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate  * Return a buffer which describes the element
3260Sstevel@tonic-gate  * pe is a pointer to the element
3270Sstevel@tonic-gate  * deep is PO_TRUE/PO_FALSE to indicate whether children should be included
3280Sstevel@tonic-gate  */
3290Sstevel@tonic-gate char *
3300Sstevel@tonic-gate pool_base_info(const pool_elem_t *pe, char_buf_t *cb, int deep)
3310Sstevel@tonic-gate {
3320Sstevel@tonic-gate 	const char *sres;
3330Sstevel@tonic-gate 	uint_t i;
3340Sstevel@tonic-gate 	uint_t nelem;
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
3370Sstevel@tonic-gate 	pool_resource_t **rs;
3380Sstevel@tonic-gate 	pool_elem_t *elem;
3390Sstevel@tonic-gate 	pool_conf_t *conf = TO_CONF(pe);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	if (cb == NULL) {
3420Sstevel@tonic-gate 		char *ret = NULL;
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 		if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
3450Sstevel@tonic-gate 			return (NULL);
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 		/*
3480Sstevel@tonic-gate 		 * Populate the buffer with element details
3490Sstevel@tonic-gate 		 */
3500Sstevel@tonic-gate 		(void) pool_base_info(pe, cb, deep);
3510Sstevel@tonic-gate 		if (cb->cb_buf)
3520Sstevel@tonic-gate 			ret = strdup(cb->cb_buf);
3530Sstevel@tonic-gate 		free_char_buf(cb);
3540Sstevel@tonic-gate 		return (ret);
3550Sstevel@tonic-gate 	}
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	if (append_char_buf(cb, "\n%s%s", cb->cb_tab_buf,
3580Sstevel@tonic-gate 		pool_elem_class_string(pe)) == PO_FAIL) {
3590Sstevel@tonic-gate 		return (NULL);
3600Sstevel@tonic-gate 	}
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	if (pool_get_ns_property(pe, c_name, &val) == POC_STRING) {
3630Sstevel@tonic-gate 		(void) pool_value_get_string(&val, &sres);
3640Sstevel@tonic-gate 		if (append_char_buf(cb, " %s", sres) == PO_FAIL) {
3650Sstevel@tonic-gate 			return (NULL);
3660Sstevel@tonic-gate 		}
3670Sstevel@tonic-gate 	}
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	/*
3700Sstevel@tonic-gate 	 * Add in some details about the element
3710Sstevel@tonic-gate 	 */
3720Sstevel@tonic-gate 	if (pool_walk_properties(conf, (pool_elem_t *)pe, cb,
3730Sstevel@tonic-gate 	    prop_buf_build_cb) == PO_FAIL) {
3740Sstevel@tonic-gate 		(void) append_char_buf(cb, "\n%s%s\n", cb->cb_tab_buf,
3750Sstevel@tonic-gate 		    "Cannot access the properties of this element.");
3760Sstevel@tonic-gate 		return (NULL);
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate 	if (append_char_buf(cb, "%s", "\n") == PO_FAIL)
3790Sstevel@tonic-gate 		return (NULL);
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	if (pe->pe_class == PEC_POOL) {
3820Sstevel@tonic-gate 		/*
3830Sstevel@tonic-gate 		 * A shallow display of a pool only lists the resources by name
3840Sstevel@tonic-gate 		 */
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 		if ((rs = pool_query_pool_resources(conf, pool_elem_pool(pe),
3870Sstevel@tonic-gate 		    &nelem, NULL)) == NULL) {
3880Sstevel@tonic-gate 			return (NULL);
3890Sstevel@tonic-gate 		}
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 		for (i = 0; i < nelem; i++) {
3920Sstevel@tonic-gate 			const char *str;
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 			elem = TO_ELEM(rs[i]);
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 			if (append_char_buf(cb, "\t%s%s", cb->cb_tab_buf,
3970Sstevel@tonic-gate 			    pool_elem_class_string(elem)) == PO_FAIL) {
3980Sstevel@tonic-gate 				free(rs);
3990Sstevel@tonic-gate 				return (NULL);
4000Sstevel@tonic-gate 			}
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 			if (pool_get_ns_property(elem, c_name, &val) !=
4030Sstevel@tonic-gate 			    POC_STRING) {
4040Sstevel@tonic-gate 				free(rs);
4050Sstevel@tonic-gate 				pool_seterror(POE_INVALID_CONF);
4060Sstevel@tonic-gate 				return (NULL);
4070Sstevel@tonic-gate 			}
4080Sstevel@tonic-gate 			(void) pool_value_get_string(&val, &str);
4090Sstevel@tonic-gate 			if (append_char_buf(cb, "\t%s\n", str) == PO_FAIL) {
4100Sstevel@tonic-gate 				free(rs);
4110Sstevel@tonic-gate 				return (NULL);
4120Sstevel@tonic-gate 			}
4130Sstevel@tonic-gate 		}
4140Sstevel@tonic-gate 		free(rs);
4150Sstevel@tonic-gate 	}
4160Sstevel@tonic-gate 	if (deep == PO_TRUE) {
4170Sstevel@tonic-gate 		pool_t **ps;
4180Sstevel@tonic-gate 		pool_component_t **cs;
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 		if (strlcat(cb->cb_tab_buf, "\t", CB_TAB_BUF_SIZE)
4210Sstevel@tonic-gate 		    >= CB_TAB_BUF_SIZE) {
4220Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
4230Sstevel@tonic-gate 			return (NULL);
4240Sstevel@tonic-gate 		}
4250Sstevel@tonic-gate 		switch (pe->pe_class) {
4260Sstevel@tonic-gate 		case PEC_SYSTEM:
4270Sstevel@tonic-gate 			if ((ps = pool_query_pools(conf, &nelem, NULL)) !=
4280Sstevel@tonic-gate 			    NULL) { /* process the pools */
4290Sstevel@tonic-gate 				for (i = 0; i < nelem; i++) {
4300Sstevel@tonic-gate 					elem = TO_ELEM(ps[i]);
4310Sstevel@tonic-gate 					if (pool_base_info(elem, cb,
4320Sstevel@tonic-gate 					    PO_FALSE) == NULL) {
4330Sstevel@tonic-gate 						free(ps);
4340Sstevel@tonic-gate 						return (NULL);
4350Sstevel@tonic-gate 					}
4360Sstevel@tonic-gate 				}
4370Sstevel@tonic-gate 				free(ps);
4380Sstevel@tonic-gate 			}
4390Sstevel@tonic-gate 			if ((rs = pool_query_resources(conf, &nelem, NULL)) !=
4400Sstevel@tonic-gate 			    NULL) {
4410Sstevel@tonic-gate 				for (i = 0; i < nelem; i++) {
4420Sstevel@tonic-gate 					elem = TO_ELEM(rs[i]);
4430Sstevel@tonic-gate 					if (pool_base_info(elem, cb,
4440Sstevel@tonic-gate 					    PO_TRUE) == NULL) {
4450Sstevel@tonic-gate 						free(rs);
4460Sstevel@tonic-gate 						return (NULL);
4470Sstevel@tonic-gate 					}
4480Sstevel@tonic-gate 				}
4490Sstevel@tonic-gate 				free(rs);
4500Sstevel@tonic-gate 			}
4510Sstevel@tonic-gate 			break;
4520Sstevel@tonic-gate 		case PEC_POOL:
4530Sstevel@tonic-gate 			if ((rs = pool_query_pool_resources(conf,
4540Sstevel@tonic-gate 			    pool_elem_pool(pe), &nelem, NULL)) == NULL)
4550Sstevel@tonic-gate 				return (NULL);
4560Sstevel@tonic-gate 			for (i = 0; i < nelem; i++) {
4570Sstevel@tonic-gate 				elem = TO_ELEM(rs[i]);
4580Sstevel@tonic-gate 				if (pool_base_info(elem, cb, PO_TRUE) == NULL) {
4590Sstevel@tonic-gate 					free(rs);
4600Sstevel@tonic-gate 					return (NULL);
4610Sstevel@tonic-gate 				}
4620Sstevel@tonic-gate 			}
4630Sstevel@tonic-gate 			free(rs);
4640Sstevel@tonic-gate 			break;
4650Sstevel@tonic-gate 		case PEC_RES_COMP:
4660Sstevel@tonic-gate 			if ((cs = pool_query_resource_components(conf,
4670Sstevel@tonic-gate 			    pool_elem_res(pe), &nelem, NULL)) != NULL) {
4680Sstevel@tonic-gate 				for (i = 0; i < nelem; i++) {
4690Sstevel@tonic-gate 					elem = TO_ELEM(cs[i]);
4700Sstevel@tonic-gate 					if (pool_base_info(elem, cb,
4710Sstevel@tonic-gate 					    PO_FALSE) == NULL) {
4720Sstevel@tonic-gate 						free(cs);
4730Sstevel@tonic-gate 						return (NULL);
4740Sstevel@tonic-gate 					}
4750Sstevel@tonic-gate 				}
4760Sstevel@tonic-gate 				free(cs);
4770Sstevel@tonic-gate 			}
4780Sstevel@tonic-gate 			break;
4790Sstevel@tonic-gate 		case PEC_RES_AGG:
4800Sstevel@tonic-gate 		case PEC_COMP:
4810Sstevel@tonic-gate 			break;
4820Sstevel@tonic-gate 		default:
4830Sstevel@tonic-gate 			/*NOTREACHED*/
4840Sstevel@tonic-gate 			break;
4850Sstevel@tonic-gate 		}
4860Sstevel@tonic-gate 		if (cb->cb_tab_buf[0] != 0)
4870Sstevel@tonic-gate 			cb->cb_tab_buf[strlen(cb->cb_tab_buf) - 1] = 0;
4880Sstevel@tonic-gate 	}
4890Sstevel@tonic-gate 	return (cb->cb_buf);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate /*
4930Sstevel@tonic-gate  * Returns	The information on the specified pool or NULL.
4940Sstevel@tonic-gate  *
4950Sstevel@tonic-gate  * Errors	If the status of the conf is INVALID or the supplied
4960Sstevel@tonic-gate  *		value of deep is illegal, POE_BADPARAM.
4970Sstevel@tonic-gate  *
4980Sstevel@tonic-gate  * The caller is responsible for free(3c)ing the string returned.
4990Sstevel@tonic-gate  */
5000Sstevel@tonic-gate char *
5010Sstevel@tonic-gate pool_info(const pool_conf_t *conf, const pool_t *pool, int deep)
5020Sstevel@tonic-gate {
5030Sstevel@tonic-gate 	pool_elem_t *pe;
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	pe = TO_ELEM(pool);
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	if (TO_CONF(pe) != conf) {
5080Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5090Sstevel@tonic-gate 		return (NULL);
5100Sstevel@tonic-gate 	}
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) {
5130Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5140Sstevel@tonic-gate 		return (NULL);
5150Sstevel@tonic-gate 	}
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	return (pool_base_info(pe, NULL, deep));
5180Sstevel@tonic-gate }
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate /*
5210Sstevel@tonic-gate  * Returns	The information on the specified resource or NULL.
5220Sstevel@tonic-gate  *
5230Sstevel@tonic-gate  * Errors	If the status of the conf is INVALID or the supplied
5240Sstevel@tonic-gate  *		value of deep is illegal, POE_BADPARAM.
5250Sstevel@tonic-gate  *
5260Sstevel@tonic-gate  * The caller is responsible for free(3c)ing the string returned.
5270Sstevel@tonic-gate  */
5280Sstevel@tonic-gate char *
5290Sstevel@tonic-gate pool_resource_info(const pool_conf_t *conf, const pool_resource_t *res,
5300Sstevel@tonic-gate     int deep)
5310Sstevel@tonic-gate {
5320Sstevel@tonic-gate 	pool_elem_t *pe;
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	pe = TO_ELEM(res);
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	if (TO_CONF(pe) != conf) {
5370Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5380Sstevel@tonic-gate 		return (NULL);
5390Sstevel@tonic-gate 	}
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) {
5420Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5430Sstevel@tonic-gate 		return (NULL);
5440Sstevel@tonic-gate 	}
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	return (pool_base_info(pe, NULL, deep));
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate /*
5500Sstevel@tonic-gate  * Returns	The information on the specified component or NULL.
5510Sstevel@tonic-gate  *
5520Sstevel@tonic-gate  * Errors	If the status of the conf is INVALID or the supplied
5530Sstevel@tonic-gate  *		value of deep is illegal, POE_BADPARAM.
5540Sstevel@tonic-gate  *
5550Sstevel@tonic-gate  * The caller is responsible for free(3c)ing the string returned.
5560Sstevel@tonic-gate  */
5570Sstevel@tonic-gate char *
5580Sstevel@tonic-gate pool_component_info(const pool_conf_t *conf, const pool_component_t *comp,
5590Sstevel@tonic-gate     int deep)
5600Sstevel@tonic-gate {
5610Sstevel@tonic-gate 	pool_elem_t *pe;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	pe = TO_ELEM(comp);
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	if (TO_CONF(pe) != conf) {
5660Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5670Sstevel@tonic-gate 		return (NULL);
5680Sstevel@tonic-gate 	}
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) {
5710Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5720Sstevel@tonic-gate 		return (NULL);
5730Sstevel@tonic-gate 	}
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	return (pool_base_info(pe, NULL, deep));
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate /*
5790Sstevel@tonic-gate  * Returns	The information on the specified conf or NULL.
5800Sstevel@tonic-gate  *
5810Sstevel@tonic-gate  * Errors	If the status of the conf is INVALID or the supplied
5820Sstevel@tonic-gate  *		value of deep is illegal, POE_BADPARAM.
5830Sstevel@tonic-gate  *
5840Sstevel@tonic-gate  * The caller is responsible for free(3c)ing the string returned.
5850Sstevel@tonic-gate  */
5860Sstevel@tonic-gate char *
5870Sstevel@tonic-gate pool_conf_info(const pool_conf_t *conf, int deep)
5880Sstevel@tonic-gate {
5890Sstevel@tonic-gate 	pool_elem_t *pe;
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) {
5920Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5930Sstevel@tonic-gate 		return (NULL);
5940Sstevel@tonic-gate 	}
5950Sstevel@tonic-gate 	if ((pe = pool_conf_to_elem(conf)) == NULL) {
5960Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
5970Sstevel@tonic-gate 		return (NULL);
5980Sstevel@tonic-gate 	}
5990Sstevel@tonic-gate 	return (pool_base_info(pe, NULL, deep));
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate /*
6040Sstevel@tonic-gate  * Set the thread specific error value.
6050Sstevel@tonic-gate  */
6060Sstevel@tonic-gate void
6070Sstevel@tonic-gate pool_seterror(int errval)
6080Sstevel@tonic-gate {
6090Sstevel@tonic-gate 	if (thr_main()) {
6100Sstevel@tonic-gate 		pool_errval = errval;
6110Sstevel@tonic-gate 		return;
6120Sstevel@tonic-gate 	}
6130Sstevel@tonic-gate 	if (keyonce == 0) {
6140Sstevel@tonic-gate 		(void) mutex_lock(&keylock);
6150Sstevel@tonic-gate 		if (keyonce == 0) {
6160Sstevel@tonic-gate 			(void) thr_keycreate(&errkey, 0);
6170Sstevel@tonic-gate 			keyonce++;
6180Sstevel@tonic-gate 		}
6190Sstevel@tonic-gate 		(void) mutex_unlock(&keylock);
6200Sstevel@tonic-gate 	}
6210Sstevel@tonic-gate 	(void) thr_setspecific(errkey, (void *)(intptr_t)errval);
6220Sstevel@tonic-gate }
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate /*
6250Sstevel@tonic-gate  * Return the current value of the error code.
6260Sstevel@tonic-gate  * Returns: int error code
6270Sstevel@tonic-gate  */
6280Sstevel@tonic-gate int
6290Sstevel@tonic-gate pool_error(void)
6300Sstevel@tonic-gate {
6310Sstevel@tonic-gate 	void *errval;
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	if (thr_main())
6340Sstevel@tonic-gate 		return (pool_errval);
6350Sstevel@tonic-gate 	if (keyonce == 0)
6360Sstevel@tonic-gate 		return (POE_OK);
6370Sstevel@tonic-gate 	(void) thr_getspecific(errkey, &errval);
6380Sstevel@tonic-gate 	return ((intptr_t)errval);
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate /*
6420Sstevel@tonic-gate  * Return the text represenation for the current value of the error code.
6430Sstevel@tonic-gate  * Returns: const char * error string
6440Sstevel@tonic-gate  */
6450Sstevel@tonic-gate const char *
6460Sstevel@tonic-gate pool_strerror(int error)
6470Sstevel@tonic-gate {
6480Sstevel@tonic-gate 	char *str;
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	switch (error) {
6510Sstevel@tonic-gate 	case POE_OK:
6520Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Operation successful");
6530Sstevel@tonic-gate 		break;
6540Sstevel@tonic-gate 	case POE_BAD_PROP_TYPE:
6550Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN,
6560Sstevel@tonic-gate 		    "Attempted to retrieve the wrong property type");
6570Sstevel@tonic-gate 		break;
6580Sstevel@tonic-gate 	case POE_INVALID_CONF:
6590Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Invalid configuration");
6600Sstevel@tonic-gate 		break;
6610Sstevel@tonic-gate 	case POE_NOTSUP:
6620Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Operation is not supported");
6630Sstevel@tonic-gate 		break;
6640Sstevel@tonic-gate 	case POE_INVALID_SEARCH:
6650Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Invalid search");
6660Sstevel@tonic-gate 		break;
6670Sstevel@tonic-gate 	case POE_BADPARAM:
6680Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Bad parameter supplied");
6690Sstevel@tonic-gate 		break;
6700Sstevel@tonic-gate 	case POE_PUTPROP:
6710Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Error putting property");
6720Sstevel@tonic-gate 		break;
6730Sstevel@tonic-gate 	case POE_DATASTORE:
6740Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Pools repository error");
6750Sstevel@tonic-gate 		break;
6760Sstevel@tonic-gate 	case POE_SYSTEM:
6770Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "System error");
6780Sstevel@tonic-gate 		break;
6790Sstevel@tonic-gate 	case POE_ACCESS:
6800Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Permission denied");
6810Sstevel@tonic-gate 		break;
6820Sstevel@tonic-gate 	default:
6830Sstevel@tonic-gate 		errno = ESRCH;
6840Sstevel@tonic-gate 		str = NULL;
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 	return (str);
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate int
6900Sstevel@tonic-gate pool_get_status(int *state)
6910Sstevel@tonic-gate {
6920Sstevel@tonic-gate 	int fd;
6930Sstevel@tonic-gate 	pool_status_t status;
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	if ((fd = open(pool_info_location, O_RDONLY)) < 0) {
6960Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
6970Sstevel@tonic-gate 		return (PO_FAIL);
6980Sstevel@tonic-gate 	}
6990Sstevel@tonic-gate 	if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
7000Sstevel@tonic-gate 		(void) close(fd);
7010Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
7020Sstevel@tonic-gate 		return (PO_FAIL);
7030Sstevel@tonic-gate 	}
7040Sstevel@tonic-gate 	(void) close(fd);
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 	*state = status.ps_io_state;
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	return (PO_SUCCESS);
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate int
7120Sstevel@tonic-gate pool_set_status(int state)
7130Sstevel@tonic-gate {
7140Sstevel@tonic-gate 	int old_state;
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 	if (pool_get_status(&old_state) != PO_SUCCESS) {
7170Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
7180Sstevel@tonic-gate 		return (PO_FAIL);
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	if (old_state != state) {
7220Sstevel@tonic-gate 		int fd;
7230Sstevel@tonic-gate 		pool_status_t status;
7240Sstevel@tonic-gate 
7251042Sgarypen 		/*
7261042Sgarypen 		 * Changing the status of pools is performed by enabling
7271042Sgarypen 		 * or disabling the pools service instance. If this
7281042Sgarypen 		 * function has not been invoked by startd then we simply
7291042Sgarypen 		 * enable/disable the service and return success.
7301042Sgarypen 		 *
7311042Sgarypen 		 * There is no way to specify that state changes must be
7321042Sgarypen 		 * synchronous using the library API as yet, so we use
7331042Sgarypen 		 * the -s option provided by svcadm.
7341042Sgarypen 		 */
7351042Sgarypen 		if (getenv("SMF_FMRI") == NULL) {
7361042Sgarypen 			FILE *p;
7372706Sgarypen 			char *cmd;
7382706Sgarypen 
7391042Sgarypen 			if (state) {
7402706Sgarypen 				cmd = "/usr/sbin/svcadm enable -s " \
7411042Sgarypen 				    SMF_SVC_INSTANCE;
7421042Sgarypen 			} else {
7432706Sgarypen 				cmd = "/usr/sbin/svcadm disable -s " \
7441042Sgarypen 				    SMF_SVC_INSTANCE;
7452706Sgarypen 			}
7462706Sgarypen 			if ((p = popen(cmd, "wF")) == NULL || pclose(p) != 0) {
7472706Sgarypen 				pool_seterror(POE_SYSTEM);
7482706Sgarypen 				return (PO_FAIL);
7490Sstevel@tonic-gate 			}
7501042Sgarypen 			return (PO_SUCCESS);
7510Sstevel@tonic-gate 		}
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 		if ((fd = open(pool_dynamic_location(), O_RDWR | O_EXCL)) < 0) {
7540Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
7550Sstevel@tonic-gate 			return (PO_FAIL);
7560Sstevel@tonic-gate 		}
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 		status.ps_io_state = state;
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 		if (ioctl(fd, POOL_STATUS, &status) < 0) {
7610Sstevel@tonic-gate 			(void) close(fd);
7620Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
7630Sstevel@tonic-gate 			return (PO_FAIL);
7640Sstevel@tonic-gate 		}
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 		(void) close(fd);
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	}
7690Sstevel@tonic-gate 	return (PO_SUCCESS);
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate /*
7730Sstevel@tonic-gate  * General Data Provider Independent Access Methods
7740Sstevel@tonic-gate  */
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate /*
7770Sstevel@tonic-gate  * Property manipulation code.
7780Sstevel@tonic-gate  *
7790Sstevel@tonic-gate  * The pool_(get|rm|set)_property() functions consult the plugins before
7800Sstevel@tonic-gate  * looking at the actual configuration. This allows plugins to provide
7810Sstevel@tonic-gate  * "virtual" properties that may not exist in the configuration file per se,
7820Sstevel@tonic-gate  * but behave like regular properties. This also allows plugins to reserve
7830Sstevel@tonic-gate  * certain properties as read-only, non-removable, etc.
7840Sstevel@tonic-gate  *
7850Sstevel@tonic-gate  * A negative value returned from the plugin denotes error, 0 means that the
7860Sstevel@tonic-gate  * property request should be forwarded to the backend, and 1 means the request
7870Sstevel@tonic-gate  * was satisfied by the plugin and should not be processed further.
7880Sstevel@tonic-gate  *
7890Sstevel@tonic-gate  * The (get|rm|set)_property() functions bypass the plugin layer completely,
7900Sstevel@tonic-gate  * and hence should not be generally used.
7910Sstevel@tonic-gate  */
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate /*
7940Sstevel@tonic-gate  * Return true if the string passed in matches the pattern
7950Sstevel@tonic-gate  * [A-Za-z][A-Za-z0-9,._-]*
7960Sstevel@tonic-gate  */
7970Sstevel@tonic-gate int
7980Sstevel@tonic-gate is_valid_name(const char *name)
7990Sstevel@tonic-gate {
8000Sstevel@tonic-gate 	int i;
8010Sstevel@tonic-gate 	char c;
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	if (name == NULL)
8040Sstevel@tonic-gate 		return (PO_FALSE);
8050Sstevel@tonic-gate 	if (!isalpha(name[0]))
8060Sstevel@tonic-gate 		return (PO_FALSE);
8070Sstevel@tonic-gate 	for (i = 1; (c = name[i]) != '\0'; i++) {
8080Sstevel@tonic-gate 		if (!isalnum(c) && c != ',' && c != '.' && c != '_' && c != '-')
8090Sstevel@tonic-gate 			return (PO_FALSE);
8100Sstevel@tonic-gate 	}
8110Sstevel@tonic-gate 	return (PO_TRUE);
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate  * Return true if the string passed in matches the pattern
8160Sstevel@tonic-gate  * [A-Za-z_][A-Za-z0-9,._-]*
8170Sstevel@tonic-gate  * A property name starting with a '_' is an "invisible" property that does not
8180Sstevel@tonic-gate  * show up in a property walk.
8190Sstevel@tonic-gate  */
8200Sstevel@tonic-gate int
8210Sstevel@tonic-gate is_valid_prop_name(const char *prop_name)
8220Sstevel@tonic-gate {
8230Sstevel@tonic-gate 	int i;
8240Sstevel@tonic-gate 	char c;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	if (prop_name == NULL)
8270Sstevel@tonic-gate 		return (PO_FALSE);
8280Sstevel@tonic-gate 	if (!isalpha(prop_name[0]) && prop_name[0] != '_')
8290Sstevel@tonic-gate 		return (PO_FALSE);
8300Sstevel@tonic-gate 	for (i = 1; (c = prop_name[i]) != '\0'; i++) {
8310Sstevel@tonic-gate 		if (!isalnum(c) && c != ',' && c != '.' && c != '_' && c != '-')
8320Sstevel@tonic-gate 			return (PO_FALSE);
8330Sstevel@tonic-gate 	}
8340Sstevel@tonic-gate 	return (PO_TRUE);
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate /*
8380Sstevel@tonic-gate  * Return the specified property value.
8390Sstevel@tonic-gate  *
8400Sstevel@tonic-gate  * POC_INVAL is returned if an error is detected and the error code is updated
8410Sstevel@tonic-gate  * to indicate the cause of the error.
8420Sstevel@tonic-gate  */
8430Sstevel@tonic-gate pool_value_class_t
8440Sstevel@tonic-gate pool_get_property(const pool_conf_t *conf, const pool_elem_t *pe,
8450Sstevel@tonic-gate     const char *name, pool_value_t *val)
8460Sstevel@tonic-gate {
8470Sstevel@tonic-gate 	const pool_prop_t *prop_info;
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
8500Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
8510Sstevel@tonic-gate 		return (POC_INVAL);
8520Sstevel@tonic-gate 	}
8530Sstevel@tonic-gate 	if (pool_value_set_name(val, name) != PO_SUCCESS) {
8540Sstevel@tonic-gate 		return (POC_INVAL);
8550Sstevel@tonic-gate 	}
8560Sstevel@tonic-gate 	/*
8570Sstevel@tonic-gate 	 * Check to see if this is a property we are managing. If it
8580Sstevel@tonic-gate 	 * is and it has an interceptor installed for property
8590Sstevel@tonic-gate 	 * retrieval, use it.
8600Sstevel@tonic-gate 	 */
8610Sstevel@tonic-gate 	if ((prop_info = provider_get_prop(pe, name)) != NULL &&
8620Sstevel@tonic-gate 	    prop_info->pp_op.ppo_get_value != NULL) {
8630Sstevel@tonic-gate 		if (prop_info->pp_op.ppo_get_value(pe, val) == PO_FAIL)
8640Sstevel@tonic-gate 			return (POC_INVAL);
8650Sstevel@tonic-gate 		else
8660Sstevel@tonic-gate 			return (pool_value_get_type(val));
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 	return (pe->pe_get_prop(pe, name, val));
8690Sstevel@tonic-gate }
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate /*
8720Sstevel@tonic-gate  * Return the specified property value with the namespace prepended.
8730Sstevel@tonic-gate  * e.g. If this function is used to get the property "name" on a pool, it will
8740Sstevel@tonic-gate  * attempt to retrieve "pool.name".
8750Sstevel@tonic-gate  *
8760Sstevel@tonic-gate  * POC_INVAL is returned if an error is detected and the error code is updated
8770Sstevel@tonic-gate  * to indicate the cause of the error.
8780Sstevel@tonic-gate  */
8790Sstevel@tonic-gate pool_value_class_t
8800Sstevel@tonic-gate pool_get_ns_property(const pool_elem_t *pe, const char *name, pool_value_t *val)
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate 	int ret;
8830Sstevel@tonic-gate 	char_buf_t *cb;
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
8860Sstevel@tonic-gate 		return (POC_INVAL);
8870Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
8880Sstevel@tonic-gate 	    PO_FAIL) {
8890Sstevel@tonic-gate 		free_char_buf(cb);
8900Sstevel@tonic-gate 		return (POC_INVAL);
8910Sstevel@tonic-gate 	}
8920Sstevel@tonic-gate 	ret = pool_get_property(TO_CONF(pe), pe, cb->cb_buf, val);
8930Sstevel@tonic-gate 	free_char_buf(cb);
8940Sstevel@tonic-gate 	return (ret);
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate /*
8980Sstevel@tonic-gate  * Update the specified property value.
8990Sstevel@tonic-gate  *
9000Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
9010Sstevel@tonic-gate  * to indicate the cause of the error.
9020Sstevel@tonic-gate  */
9030Sstevel@tonic-gate int
9040Sstevel@tonic-gate pool_put_property(pool_conf_t *conf, pool_elem_t *pe, const char *name,
9050Sstevel@tonic-gate     const pool_value_t *val)
9060Sstevel@tonic-gate {
9070Sstevel@tonic-gate 	const pool_prop_t *prop_info;
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
9100Sstevel@tonic-gate 		return (PO_FAIL);
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	if (TO_CONF(pe) != conf) {
9130Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
9140Sstevel@tonic-gate 		return (NULL);
9150Sstevel@tonic-gate 	}
9160Sstevel@tonic-gate 
917*3247Sgjelinek 	/* Don't allow (re)setting of the "temporary" property */
918*3247Sgjelinek 	if (!is_valid_prop_name(name) || strstr(name, ".temporary") != NULL) {
9190Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
9200Sstevel@tonic-gate 		return (PO_FAIL);
9210Sstevel@tonic-gate 	}
922*3247Sgjelinek 
923*3247Sgjelinek 	/* Don't allow rename of temporary pools/resources */
924*3247Sgjelinek 	if (strstr(name, ".name") != NULL && elem_is_tmp(pe)) {
925*3247Sgjelinek 		boolean_t rename = B_TRUE;
926*3247Sgjelinek 		pool_value_t *pv = pool_value_alloc();
927*3247Sgjelinek 
928*3247Sgjelinek 		if (pe->pe_get_prop(pe, name, pv) != POC_INVAL) {
929*3247Sgjelinek 			const char *s1 = NULL;
930*3247Sgjelinek 			const char *s2 = NULL;
931*3247Sgjelinek 
932*3247Sgjelinek 			(void) pool_value_get_string(pv, &s1);
933*3247Sgjelinek 			(void) pool_value_get_string(val, &s2);
934*3247Sgjelinek 			if (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0)
935*3247Sgjelinek 				rename = B_FALSE;
936*3247Sgjelinek 		}
937*3247Sgjelinek 		pool_value_free(pv);
938*3247Sgjelinek 
939*3247Sgjelinek 		if (rename) {
940*3247Sgjelinek 			pool_seterror(POE_BADPARAM);
941*3247Sgjelinek 			return (PO_FAIL);
942*3247Sgjelinek 		}
943*3247Sgjelinek 	}
944*3247Sgjelinek 
9450Sstevel@tonic-gate 	/*
9460Sstevel@tonic-gate 	 * Check to see if this is a property we are managing. If it is,
9470Sstevel@tonic-gate 	 * ensure that we are happy with what the user is doing.
9480Sstevel@tonic-gate 	 */
9490Sstevel@tonic-gate 	if ((prop_info = provider_get_prop(pe, name)) != NULL) {
9500Sstevel@tonic-gate 		if (prop_is_readonly(prop_info) == PO_TRUE) {
9510Sstevel@tonic-gate 			pool_seterror(POE_BADPARAM);
9520Sstevel@tonic-gate 			return (PO_FAIL);
9530Sstevel@tonic-gate 		}
9540Sstevel@tonic-gate 		if (prop_info->pp_op.ppo_set_value &&
9550Sstevel@tonic-gate 		    prop_info->pp_op.ppo_set_value(pe, val) == PO_FAIL)
9560Sstevel@tonic-gate 			return (PO_FAIL);
9570Sstevel@tonic-gate 	}
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	return (pe->pe_put_prop(pe, name, val));
9600Sstevel@tonic-gate }
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate /*
963*3247Sgjelinek  * Set temporary property to flag as a temporary element.
964*3247Sgjelinek  *
965*3247Sgjelinek  * PO_FAIL is returned if an error is detected and the error code is updated
966*3247Sgjelinek  * to indicate the cause of the error.
967*3247Sgjelinek  */
968*3247Sgjelinek int
969*3247Sgjelinek pool_set_temporary(pool_conf_t *conf, pool_elem_t *pe)
970*3247Sgjelinek {
971*3247Sgjelinek 	int res;
972*3247Sgjelinek 	char name[128];
973*3247Sgjelinek 	pool_value_t *val;
974*3247Sgjelinek 
975*3247Sgjelinek 	if (pool_conf_check(conf) != PO_SUCCESS)
976*3247Sgjelinek 		return (PO_FAIL);
977*3247Sgjelinek 
978*3247Sgjelinek 	if (TO_CONF(pe) != conf) {
979*3247Sgjelinek 		pool_seterror(POE_BADPARAM);
980*3247Sgjelinek 		return (PO_FAIL);
981*3247Sgjelinek 	}
982*3247Sgjelinek 
983*3247Sgjelinek 	/* create property name based on element type */
984*3247Sgjelinek 	if (snprintf(name, sizeof (name), "%s.temporary",
985*3247Sgjelinek 	    pool_elem_class_string(pe)) > sizeof (name)) {
986*3247Sgjelinek 		pool_seterror(POE_SYSTEM);
987*3247Sgjelinek 		return (PO_FAIL);
988*3247Sgjelinek 	}
989*3247Sgjelinek 
990*3247Sgjelinek 	if ((val = pool_value_alloc()) == NULL)
991*3247Sgjelinek 		return (PO_FAIL);
992*3247Sgjelinek 
993*3247Sgjelinek 	pool_value_set_bool(val, (uchar_t)1);
994*3247Sgjelinek 
995*3247Sgjelinek 	res = pe->pe_put_prop(pe, name, val);
996*3247Sgjelinek 
997*3247Sgjelinek 	pool_value_free(val);
998*3247Sgjelinek 
999*3247Sgjelinek 	return (res);
1000*3247Sgjelinek }
1001*3247Sgjelinek 
1002*3247Sgjelinek /*
10030Sstevel@tonic-gate  * Update the specified property value with the namespace prepended.
10040Sstevel@tonic-gate  * e.g. If this function is used to update the property "name" on a pool, it
10050Sstevel@tonic-gate  * will attempt to update "pool.name".
10060Sstevel@tonic-gate  *
10070Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
10080Sstevel@tonic-gate  * to indicate the cause of the error.
10090Sstevel@tonic-gate  */
10100Sstevel@tonic-gate int
10110Sstevel@tonic-gate pool_put_ns_property(pool_elem_t *pe, const char *name,
10120Sstevel@tonic-gate     const pool_value_t *val)
10130Sstevel@tonic-gate {
10140Sstevel@tonic-gate 	char_buf_t *cb;
10150Sstevel@tonic-gate 	int ret;
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
10180Sstevel@tonic-gate 		return (PO_FAIL);
10190Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
10200Sstevel@tonic-gate 	    PO_FAIL) {
10210Sstevel@tonic-gate 		free_char_buf(cb);
10220Sstevel@tonic-gate 		return (PO_FAIL);
10230Sstevel@tonic-gate 	}
10240Sstevel@tonic-gate 	ret = pool_put_property(TO_CONF(pe), pe, cb->cb_buf, val);
10250Sstevel@tonic-gate 	free_char_buf(cb);
10260Sstevel@tonic-gate 	return (ret);
10270Sstevel@tonic-gate }
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate /*
10300Sstevel@tonic-gate  * Update the specified property value. Do not use the property
10310Sstevel@tonic-gate  * protection mechanism. This function should only be used for cases
10320Sstevel@tonic-gate  * where the library must bypass the normal property protection
10330Sstevel@tonic-gate  * mechanism. The only known use is to update properties in the static
10340Sstevel@tonic-gate  * configuration when performing a commit.
10350Sstevel@tonic-gate  *
10360Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is
10370Sstevel@tonic-gate  * updated to indicate the cause of the error.
10380Sstevel@tonic-gate  */
10390Sstevel@tonic-gate int
10400Sstevel@tonic-gate pool_put_any_property(pool_elem_t *pe, const char *name,
10410Sstevel@tonic-gate     const pool_value_t *val)
10420Sstevel@tonic-gate {
10430Sstevel@tonic-gate 	if (!is_valid_prop_name(name)) {
10440Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
10450Sstevel@tonic-gate 		return (PO_FAIL);
10460Sstevel@tonic-gate 	}
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 	return (pe->pe_put_prop(pe, name, val));
10490Sstevel@tonic-gate }
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate /*
10520Sstevel@tonic-gate  * Update the specified property value with the namespace prepended.
10530Sstevel@tonic-gate  * e.g. If this function is used to update the property "name" on a pool, it
10540Sstevel@tonic-gate  * will attempt to update "pool.name".
10550Sstevel@tonic-gate  *
10560Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
10570Sstevel@tonic-gate  * to indicate the cause of the error.
10580Sstevel@tonic-gate  */
10590Sstevel@tonic-gate int
10600Sstevel@tonic-gate pool_put_any_ns_property(pool_elem_t *pe, const char *name,
10610Sstevel@tonic-gate     const pool_value_t *val)
10620Sstevel@tonic-gate {
10630Sstevel@tonic-gate 	char_buf_t *cb;
10640Sstevel@tonic-gate 	int ret;
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
10670Sstevel@tonic-gate 		return (PO_FAIL);
10680Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
10690Sstevel@tonic-gate 	    PO_FAIL) {
10700Sstevel@tonic-gate 		free_char_buf(cb);
10710Sstevel@tonic-gate 		return (PO_FAIL);
10720Sstevel@tonic-gate 	}
10730Sstevel@tonic-gate 	ret = pool_put_any_property(pe, cb->cb_buf, val);
10740Sstevel@tonic-gate 	free_char_buf(cb);
10750Sstevel@tonic-gate 	return (ret);
10760Sstevel@tonic-gate }
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate /*
10790Sstevel@tonic-gate  * Remove the specified property value. Note that some properties are
10800Sstevel@tonic-gate  * mandatory and thus failure to remove these properties is inevitable.
10810Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
10820Sstevel@tonic-gate  * to indicate the cause of the error.
10830Sstevel@tonic-gate  */
10840Sstevel@tonic-gate int
10850Sstevel@tonic-gate pool_rm_property(pool_conf_t *conf, pool_elem_t *pe, const char *name)
10860Sstevel@tonic-gate {
10870Sstevel@tonic-gate 	const pool_prop_t *prop_info;
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
10900Sstevel@tonic-gate 		return (PO_FAIL);
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 	if (TO_CONF(pe) != conf) {
10930Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
10940Sstevel@tonic-gate 		return (NULL);
10950Sstevel@tonic-gate 	}
10960Sstevel@tonic-gate 
1097*3247Sgjelinek 	/* Don't allow removal of the "temporary" property */
1098*3247Sgjelinek 	if (strstr(name, ".temporary") != NULL) {
1099*3247Sgjelinek 		pool_seterror(POE_BADPARAM);
1100*3247Sgjelinek 		return (PO_FAIL);
1101*3247Sgjelinek 	}
1102*3247Sgjelinek 
11030Sstevel@tonic-gate 	/*
11040Sstevel@tonic-gate 	 * Check to see if this is a property we are managing. If it is,
11050Sstevel@tonic-gate 	 * ensure that we are happy with what the user is doing.
11060Sstevel@tonic-gate 	 */
11070Sstevel@tonic-gate 	if ((prop_info = provider_get_prop(pe, name)) != NULL) {
11080Sstevel@tonic-gate 		if (prop_is_optional(prop_info) == PO_FALSE) {
11090Sstevel@tonic-gate 			pool_seterror(POE_BADPARAM);
11100Sstevel@tonic-gate 			return (PO_FAIL);
11110Sstevel@tonic-gate 		}
11120Sstevel@tonic-gate 	}
11130Sstevel@tonic-gate 	return (pe->pe_rm_prop(pe, name));
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate /*
11170Sstevel@tonic-gate  * Check if the supplied name is a namespace protected property for the supplied
11180Sstevel@tonic-gate  * element, pe. If it is, return the prefix, otherwise just return NULL.
11190Sstevel@tonic-gate  */
11200Sstevel@tonic-gate const char *
11210Sstevel@tonic-gate is_ns_property(const pool_elem_t *pe, const char *name)
11220Sstevel@tonic-gate {
11230Sstevel@tonic-gate 	const char *prefix;
11240Sstevel@tonic-gate 
11250Sstevel@tonic-gate 	if ((prefix = pool_elem_class_string(pe)) != NULL) {
11260Sstevel@tonic-gate 		if (strncmp(name, prefix, strlen(prefix)) == 0)
11270Sstevel@tonic-gate 			return (prefix);
11280Sstevel@tonic-gate 	}
11290Sstevel@tonic-gate 	return (NULL);
11300Sstevel@tonic-gate }
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate /*
11330Sstevel@tonic-gate  * Check if the supplied name is a namespace protected property for the supplied
11340Sstevel@tonic-gate  * element, pe. If it is, return the property name with the namespace stripped,
11350Sstevel@tonic-gate  * otherwise just return the name.
11360Sstevel@tonic-gate  */
11370Sstevel@tonic-gate const char *
11380Sstevel@tonic-gate property_name_minus_ns(const pool_elem_t *pe, const char *name)
11390Sstevel@tonic-gate {
11400Sstevel@tonic-gate 	const char *prefix;
11410Sstevel@tonic-gate 	if ((prefix = is_ns_property(pe, name)) != NULL) {
11420Sstevel@tonic-gate 		return (name + strlen(prefix) + 1);
11430Sstevel@tonic-gate 	}
11440Sstevel@tonic-gate 	return (name);
11450Sstevel@tonic-gate }
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate /*
11480Sstevel@tonic-gate  * Create an element to represent a pool and add it to the supplied
11490Sstevel@tonic-gate  * configuration.
11500Sstevel@tonic-gate  */
11510Sstevel@tonic-gate pool_t *
11520Sstevel@tonic-gate pool_create(pool_conf_t *conf, const char *name)
11530Sstevel@tonic-gate {
11540Sstevel@tonic-gate 	pool_elem_t *pe;
11550Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
11560Sstevel@tonic-gate 	const pool_prop_t *default_props;
11570Sstevel@tonic-gate 
11580Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
11590Sstevel@tonic-gate 		return (NULL);
11600Sstevel@tonic-gate 
11610Sstevel@tonic-gate 	if (!is_valid_name(name) || pool_get_pool(conf, name) != NULL) {
11620Sstevel@tonic-gate 		/*
11630Sstevel@tonic-gate 		 * A pool with the same name exists. Reject.
11640Sstevel@tonic-gate 		 */
11650Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
11660Sstevel@tonic-gate 		return (NULL);
11670Sstevel@tonic-gate 	}
11680Sstevel@tonic-gate 	if ((pe = conf->pc_prov->pc_elem_create(conf, PEC_POOL, PREC_INVALID,
11690Sstevel@tonic-gate 	    PCEC_INVALID)) == NULL) {
11700Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
11710Sstevel@tonic-gate 		return (NULL);
11720Sstevel@tonic-gate 	}
11730Sstevel@tonic-gate 	if ((default_props = provider_get_props(pe)) != NULL) {
11740Sstevel@tonic-gate 		int i;
11750Sstevel@tonic-gate 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
11760Sstevel@tonic-gate 			if (prop_is_init(&default_props[i]) &&
11770Sstevel@tonic-gate 			    (pool_put_any_property(pe,
11780Sstevel@tonic-gate 			    default_props[i].pp_pname,
11790Sstevel@tonic-gate 			    &default_props[i].pp_value) == PO_FAIL)) {
11800Sstevel@tonic-gate 				(void) pool_destroy(conf, pool_elem_pool(pe));
11810Sstevel@tonic-gate 				return (NULL);
11820Sstevel@tonic-gate 			}
11830Sstevel@tonic-gate 		}
11840Sstevel@tonic-gate 	}
11850Sstevel@tonic-gate 	if (pool_value_set_string(&val, name) != PO_SUCCESS) {
11860Sstevel@tonic-gate 		(void) pool_destroy(conf, pool_elem_pool(pe));
11870Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
11880Sstevel@tonic-gate 		return (NULL);
11890Sstevel@tonic-gate 	}
11900Sstevel@tonic-gate 	if (pool_put_property(conf, pe, "pool.name", &val) == PO_FAIL) {
11910Sstevel@tonic-gate 		(void) pool_destroy(conf, pool_elem_pool(pe));
11920Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
11930Sstevel@tonic-gate 		return (NULL);
11940Sstevel@tonic-gate 	}
1195*3247Sgjelinek 
1196*3247Sgjelinek 	/*
1197*3247Sgjelinek 	 * If we are creating a temporary pool configuration, flag the pool.
1198*3247Sgjelinek 	 */
1199*3247Sgjelinek 	if (conf->pc_prov->pc_oflags & PO_TEMP) {
1200*3247Sgjelinek 		if (pool_set_temporary(conf, pe) == PO_FAIL) {
1201*3247Sgjelinek 			(void) pool_destroy(conf, pool_elem_pool(pe));
1202*3247Sgjelinek 			return (NULL);
1203*3247Sgjelinek 		}
1204*3247Sgjelinek 	}
1205*3247Sgjelinek 
12060Sstevel@tonic-gate 	return (pool_elem_pool(pe));
12070Sstevel@tonic-gate }
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate /*
12100Sstevel@tonic-gate  * Create an element to represent a res.
12110Sstevel@tonic-gate  */
12120Sstevel@tonic-gate pool_resource_t *
12130Sstevel@tonic-gate pool_resource_create(pool_conf_t *conf, const char *sz_type, const char *name)
12140Sstevel@tonic-gate {
12150Sstevel@tonic-gate 	pool_elem_t *pe;
12160Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
12170Sstevel@tonic-gate 	const pool_prop_t *default_props;
12180Sstevel@tonic-gate 	pool_resource_t **resources;
12190Sstevel@tonic-gate 	int is_default = 0;
12200Sstevel@tonic-gate 	uint_t nelem;
12210Sstevel@tonic-gate 	pool_elem_class_t elem_class;
12220Sstevel@tonic-gate 	pool_resource_elem_class_t type;
12230Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
12260Sstevel@tonic-gate 		return (NULL);
12270Sstevel@tonic-gate 
12280Sstevel@tonic-gate 	if ((type = pool_resource_elem_class_from_string(sz_type)) ==
12290Sstevel@tonic-gate 	    PREC_INVALID) {
12300Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
12310Sstevel@tonic-gate 		return (NULL);
12320Sstevel@tonic-gate 	}
12330Sstevel@tonic-gate 
12340Sstevel@tonic-gate 	if (strcmp(sz_type, "pset") != 0) {
12350Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
12360Sstevel@tonic-gate 		return (NULL);
12370Sstevel@tonic-gate 	}
12380Sstevel@tonic-gate 
12390Sstevel@tonic-gate 	if (!is_valid_name(name) || pool_get_resource(conf, sz_type, name) !=
12400Sstevel@tonic-gate 	    NULL) {
12410Sstevel@tonic-gate 		/*
12420Sstevel@tonic-gate 		 * Resources must be unique by name+type.
12430Sstevel@tonic-gate 		 */
12440Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
12450Sstevel@tonic-gate 		return (NULL);
12460Sstevel@tonic-gate 	}
12470Sstevel@tonic-gate 
12480Sstevel@tonic-gate 	props[0] = &val;
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 	if (pool_value_set_string(props[0], sz_type) != PO_SUCCESS ||
12510Sstevel@tonic-gate 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS) {
12520Sstevel@tonic-gate 		return (NULL);
12530Sstevel@tonic-gate 	}
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate 	if ((resources = pool_query_resources(conf, &nelem, props)) == NULL) {
12560Sstevel@tonic-gate 		/*
12570Sstevel@tonic-gate 		 * This is the first representative of this type; when it's
12580Sstevel@tonic-gate 		 * created it should be created with 'default' = 'true'.
12590Sstevel@tonic-gate 		 */
12600Sstevel@tonic-gate 		is_default = 1;
12610Sstevel@tonic-gate 	} else {
12620Sstevel@tonic-gate 		free(resources);
12630Sstevel@tonic-gate 	}
12640Sstevel@tonic-gate 	/*
12650Sstevel@tonic-gate 	 * TODO: If Additional PEC_RES_COMP types are added to
12660Sstevel@tonic-gate 	 * pool_impl.h, this would need to be extended.
12670Sstevel@tonic-gate 	 */
12680Sstevel@tonic-gate 	switch (type) {
12690Sstevel@tonic-gate 	case PREC_PSET:
12700Sstevel@tonic-gate 		elem_class = PEC_RES_COMP;
12710Sstevel@tonic-gate 		break;
12720Sstevel@tonic-gate 	default:
12730Sstevel@tonic-gate 		elem_class = PEC_RES_AGG;
12740Sstevel@tonic-gate 		break;
12750Sstevel@tonic-gate 	}
12760Sstevel@tonic-gate 	if ((pe = conf->pc_prov->pc_elem_create(conf, elem_class, type,
12770Sstevel@tonic-gate 	    PCEC_INVALID)) == NULL) {
12780Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
12790Sstevel@tonic-gate 		return (NULL);
12800Sstevel@tonic-gate 	}
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 	/*
12830Sstevel@tonic-gate 	 * The plugins contain a list of default properties and their values
12840Sstevel@tonic-gate 	 * for resources. The resource returned, hence, is fully initialized.
12850Sstevel@tonic-gate 	 */
12860Sstevel@tonic-gate 	if ((default_props = provider_get_props(pe)) != NULL) {
12870Sstevel@tonic-gate 		int i;
12880Sstevel@tonic-gate 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
12890Sstevel@tonic-gate 			if (prop_is_init(&default_props[i]) &&
12900Sstevel@tonic-gate 			    pool_put_any_property(pe, default_props[i].pp_pname,
12910Sstevel@tonic-gate 			    &default_props[i].pp_value) == PO_FAIL) {
12920Sstevel@tonic-gate 				(void) pool_resource_destroy(conf,
12930Sstevel@tonic-gate 				    pool_elem_res(pe));
12940Sstevel@tonic-gate 				return (NULL);
12950Sstevel@tonic-gate 			}
12960Sstevel@tonic-gate 		}
12970Sstevel@tonic-gate 	}
12980Sstevel@tonic-gate 	if (pool_value_set_string(&val, name) != PO_SUCCESS ||
12990Sstevel@tonic-gate 	    pool_put_ns_property(pe, "name", &val) != PO_SUCCESS) {
13000Sstevel@tonic-gate 		(void) pool_resource_destroy(conf, pool_elem_res(pe));
13010Sstevel@tonic-gate 		return (NULL);
13020Sstevel@tonic-gate 	}
13030Sstevel@tonic-gate 	if (is_default) {
13040Sstevel@tonic-gate 		pool_value_set_bool(&val, PO_TRUE);
13050Sstevel@tonic-gate 		if (pool_put_any_ns_property(pe, "default", &val) !=
13060Sstevel@tonic-gate 		    PO_SUCCESS) {
13070Sstevel@tonic-gate 			(void) pool_resource_destroy(conf, pool_elem_res(pe));
13080Sstevel@tonic-gate 			return (NULL);
13090Sstevel@tonic-gate 		}
13100Sstevel@tonic-gate 	}
1311*3247Sgjelinek 
1312*3247Sgjelinek 	/*
1313*3247Sgjelinek 	 * If we are creating a temporary pool configuration, flag the resource.
1314*3247Sgjelinek 	 */
1315*3247Sgjelinek 	if (conf->pc_prov->pc_oflags & PO_TEMP) {
1316*3247Sgjelinek 		if (pool_set_temporary(conf, pe) != PO_SUCCESS) {
1317*3247Sgjelinek 			(void) pool_resource_destroy(conf, pool_elem_res(pe));
1318*3247Sgjelinek 			return (NULL);
1319*3247Sgjelinek 		}
1320*3247Sgjelinek 	}
1321*3247Sgjelinek 
13220Sstevel@tonic-gate 	return (pool_elem_res(pe));
13230Sstevel@tonic-gate }
13240Sstevel@tonic-gate 
13250Sstevel@tonic-gate /*
13260Sstevel@tonic-gate  * Create an element to represent a resource component.
13270Sstevel@tonic-gate  */
13280Sstevel@tonic-gate pool_component_t *
13290Sstevel@tonic-gate pool_component_create(pool_conf_t *conf, const pool_resource_t *res,
13300Sstevel@tonic-gate     int64_t sys_id)
13310Sstevel@tonic-gate {
13320Sstevel@tonic-gate 	pool_elem_t *pe;
13330Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
13340Sstevel@tonic-gate 	const pool_prop_t *default_props;
13350Sstevel@tonic-gate 	char refbuf[KEY_BUFFER_SIZE];
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate 	if ((pe = conf->pc_prov->pc_elem_create(conf, PEC_COMP,
13380Sstevel@tonic-gate 	    PREC_INVALID, PCEC_CPU)) == NULL) {
13390Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
13400Sstevel@tonic-gate 		return (NULL);
13410Sstevel@tonic-gate 	}
13420Sstevel@tonic-gate 	/*
13430Sstevel@tonic-gate 	 * TODO: If additional PEC_COMP types are added in pool_impl.h,
13440Sstevel@tonic-gate 	 * this would need to be extended.
13450Sstevel@tonic-gate 	 */
13460Sstevel@tonic-gate 	pe->pe_component_class = PCEC_CPU;
13470Sstevel@tonic-gate 	/* Now set the container for this comp */
13480Sstevel@tonic-gate 	if (pool_set_container(TO_ELEM(res), pe) == PO_FAIL) {
13490Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13500Sstevel@tonic-gate 		return (NULL);
13510Sstevel@tonic-gate 	}
13520Sstevel@tonic-gate 	/*
13530Sstevel@tonic-gate 	 * The plugins contain a list of default properties and their values
13540Sstevel@tonic-gate 	 * for resources. The resource returned, hence, is fully initialized.
13550Sstevel@tonic-gate 	 */
13560Sstevel@tonic-gate 	if ((default_props = provider_get_props(pe)) != NULL) {
13570Sstevel@tonic-gate 		int i;
13580Sstevel@tonic-gate 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
13590Sstevel@tonic-gate 			if (prop_is_init(&default_props[i]) &&
13600Sstevel@tonic-gate 			    pool_put_any_property(pe,
13610Sstevel@tonic-gate 			    default_props[i].pp_pname,
13620Sstevel@tonic-gate 			    &default_props[i].pp_value) == PO_FAIL) {
13630Sstevel@tonic-gate 				(void) pool_component_destroy(
13640Sstevel@tonic-gate 				    pool_elem_comp(pe));
13650Sstevel@tonic-gate 				return (NULL);
13660Sstevel@tonic-gate 			}
13670Sstevel@tonic-gate 		}
13680Sstevel@tonic-gate 	}
13690Sstevel@tonic-gate 	/*
13700Sstevel@tonic-gate 	 * Set additional attributes/properties on component.
13710Sstevel@tonic-gate 	 */
13720Sstevel@tonic-gate 	pool_value_set_int64(&val, sys_id);
13730Sstevel@tonic-gate 	if (pool_put_any_ns_property(pe, c_sys_prop, &val) != PO_SUCCESS) {
13740Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13750Sstevel@tonic-gate 		return (NULL);
13760Sstevel@tonic-gate 	}
13770Sstevel@tonic-gate 	if (snprintf(refbuf, KEY_BUFFER_SIZE, "%s_%lld",
13780Sstevel@tonic-gate 	    pool_elem_class_string(pe), sys_id) > KEY_BUFFER_SIZE) {
13790Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13800Sstevel@tonic-gate 		return (NULL);
13810Sstevel@tonic-gate 	}
13820Sstevel@tonic-gate 	if (pool_value_set_string(&val, refbuf) != PO_SUCCESS) {
13830Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13840Sstevel@tonic-gate 		return (NULL);
13850Sstevel@tonic-gate 	}
13860Sstevel@tonic-gate 	if (pool_put_any_ns_property(pe, c_ref_id, &val) != PO_SUCCESS) {
13870Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13880Sstevel@tonic-gate 		return (NULL);
13890Sstevel@tonic-gate 	}
13900Sstevel@tonic-gate 	return (pool_elem_comp(pe));
13910Sstevel@tonic-gate }
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate /*
13940Sstevel@tonic-gate  * Return the location of a configuration.
13950Sstevel@tonic-gate  */
13960Sstevel@tonic-gate const char *
13970Sstevel@tonic-gate pool_conf_location(const pool_conf_t *conf)
13980Sstevel@tonic-gate {
13990Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
14000Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14010Sstevel@tonic-gate 		return (NULL);
14020Sstevel@tonic-gate 	}
14030Sstevel@tonic-gate 	return (conf->pc_location);
14040Sstevel@tonic-gate }
14050Sstevel@tonic-gate /*
14060Sstevel@tonic-gate  * Close a configuration, freeing all associated resources. Once a
14070Sstevel@tonic-gate  * configuration is closed, it can no longer be used.
14080Sstevel@tonic-gate  */
14090Sstevel@tonic-gate int
14100Sstevel@tonic-gate pool_conf_close(pool_conf_t *conf)
14110Sstevel@tonic-gate {
14120Sstevel@tonic-gate 	int rv;
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
14150Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14160Sstevel@tonic-gate 		return (PO_FAIL);
14170Sstevel@tonic-gate 	}
14180Sstevel@tonic-gate 	rv = conf->pc_prov->pc_close(conf);
14190Sstevel@tonic-gate 	conf->pc_prov = NULL;
14200Sstevel@tonic-gate 	free((void *)conf->pc_location);
14210Sstevel@tonic-gate 	conf->pc_location = NULL;
14220Sstevel@tonic-gate 	conf->pc_state = POF_INVALID;
14230Sstevel@tonic-gate 	return (rv);
14240Sstevel@tonic-gate }
14250Sstevel@tonic-gate 
14260Sstevel@tonic-gate /*
14270Sstevel@tonic-gate  * Remove a configuration, freeing all associated resources. Once a
14280Sstevel@tonic-gate  * configuration is removed, it can no longer be accessed and is forever
14290Sstevel@tonic-gate  * gone.
14300Sstevel@tonic-gate  */
14310Sstevel@tonic-gate int
14320Sstevel@tonic-gate pool_conf_remove(pool_conf_t *conf)
14330Sstevel@tonic-gate {
14340Sstevel@tonic-gate 	int rv;
14350Sstevel@tonic-gate 
14360Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
14370Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14380Sstevel@tonic-gate 		return (PO_FAIL);
14390Sstevel@tonic-gate 	}
14400Sstevel@tonic-gate 	rv = conf->pc_prov->pc_remove(conf);
14410Sstevel@tonic-gate 	conf->pc_state = POF_INVALID;
14420Sstevel@tonic-gate 	return (rv);
14430Sstevel@tonic-gate }
14440Sstevel@tonic-gate 
14450Sstevel@tonic-gate /*
14460Sstevel@tonic-gate  * pool_conf_alloc() allocate the resources to represent a configuration.
14470Sstevel@tonic-gate  */
14480Sstevel@tonic-gate pool_conf_t *
14490Sstevel@tonic-gate pool_conf_alloc(void)
14500Sstevel@tonic-gate {
14510Sstevel@tonic-gate 	pool_conf_t *conf;
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate 	if ((conf = calloc(1, sizeof (pool_conf_t))) == NULL) {
14540Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
14550Sstevel@tonic-gate 		return (NULL);
14560Sstevel@tonic-gate 	}
14570Sstevel@tonic-gate 	conf->pc_state = POF_INVALID;
14580Sstevel@tonic-gate 	return (conf);
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate 
14610Sstevel@tonic-gate /*
14620Sstevel@tonic-gate  * pool_conf_free() frees the resources associated with a configuration.
14630Sstevel@tonic-gate  */
14640Sstevel@tonic-gate void
14650Sstevel@tonic-gate pool_conf_free(pool_conf_t *conf)
14660Sstevel@tonic-gate {
14670Sstevel@tonic-gate 	free(conf);
14680Sstevel@tonic-gate }
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate /*
14710Sstevel@tonic-gate  * pool_conf_open() opens a configuration, establishing all required
14720Sstevel@tonic-gate  * connections to the data source.
14730Sstevel@tonic-gate  */
14740Sstevel@tonic-gate int
14750Sstevel@tonic-gate pool_conf_open(pool_conf_t *conf, const char *location, int oflags)
14760Sstevel@tonic-gate {
14770Sstevel@tonic-gate 	/*
14780Sstevel@tonic-gate 	 * Since you can't do anything to a pool configuration without opening
14790Sstevel@tonic-gate 	 * it, this represents a good point to intialise structures that would
14800Sstevel@tonic-gate 	 * otherwise need to be initialised in a .init section.
14810Sstevel@tonic-gate 	 */
14820Sstevel@tonic-gate 	internal_init();
14830Sstevel@tonic-gate 
14840Sstevel@tonic-gate 	if (pool_conf_status(conf) != POF_INVALID) {
14850Sstevel@tonic-gate 		/*
14860Sstevel@tonic-gate 		 * Already opened configuration, return PO_FAIL
14870Sstevel@tonic-gate 		 */
14880Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14890Sstevel@tonic-gate 		return (PO_FAIL);
14900Sstevel@tonic-gate 	}
1491*3247Sgjelinek 	if (oflags & ~(PO_RDONLY | PO_RDWR | PO_CREAT | PO_DISCO | PO_UPDATE |
1492*3247Sgjelinek 	    PO_TEMP)) {
14930Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14940Sstevel@tonic-gate 		return (PO_FAIL);
14950Sstevel@tonic-gate 	}
14960Sstevel@tonic-gate 
14970Sstevel@tonic-gate 	/*
14980Sstevel@tonic-gate 	 * Creating a configuration implies read-write access, so make
14990Sstevel@tonic-gate 	 * sure that PO_RDWR is set in addition if PO_CREAT is set.
15000Sstevel@tonic-gate 	 */
15010Sstevel@tonic-gate 	if (oflags & PO_CREAT)
15020Sstevel@tonic-gate 		oflags |= PO_RDWR;
15030Sstevel@tonic-gate 
1504*3247Sgjelinek 	/* location is ignored when creating a temporary configuration */
1505*3247Sgjelinek 	if (oflags & PO_TEMP)
1506*3247Sgjelinek 		location = "";
1507*3247Sgjelinek 
15080Sstevel@tonic-gate 	if ((conf->pc_location = strdup(location)) == NULL) {
15090Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
15100Sstevel@tonic-gate 		return (PO_FAIL);
15110Sstevel@tonic-gate 	}
15120Sstevel@tonic-gate 	/*
15130Sstevel@tonic-gate 	 * This is the crossover point into the actual data provider
15140Sstevel@tonic-gate 	 * implementation, allocate a data provider of the appropriate
1515*3247Sgjelinek 	 * type for your data storage medium. In this case it's either a kernel
1516*3247Sgjelinek 	 * or xml data provider. To use a different data provider, write some
1517*3247Sgjelinek 	 * code to implement all the required interfaces and then change the
1518*3247Sgjelinek 	 * following code to allocate a data provider which uses your new code.
1519*3247Sgjelinek 	 * All data provider routines can be static, apart from the allocation
1520*3247Sgjelinek 	 * routine.
1521*3247Sgjelinek 	 *
1522*3247Sgjelinek 	 * For temporary pools (PO_TEMP) we start with a copy of the current
1523*3247Sgjelinek 	 * dynamic configuration and do all of the updates in-memory.
15240Sstevel@tonic-gate 	 */
1525*3247Sgjelinek 	if (oflags & PO_TEMP) {
1526*3247Sgjelinek 		if (pool_knl_connection_alloc(conf, PO_TEMP) != PO_SUCCESS) {
1527*3247Sgjelinek 			conf->pc_state = POF_INVALID;
1528*3247Sgjelinek 			return (PO_FAIL);
1529*3247Sgjelinek 		}
1530*3247Sgjelinek 		/* set rdwr flag so we can updated the in-memory config. */
1531*3247Sgjelinek 		conf->pc_prov->pc_oflags |= PO_RDWR;
1532*3247Sgjelinek 
1533*3247Sgjelinek 	} else if (strcmp(location, pool_dynamic_location()) == 0) {
15340Sstevel@tonic-gate 		if (pool_knl_connection_alloc(conf, oflags) != PO_SUCCESS) {
15350Sstevel@tonic-gate 			conf->pc_state = POF_INVALID;
15360Sstevel@tonic-gate 			return (PO_FAIL);
15370Sstevel@tonic-gate 		}
15380Sstevel@tonic-gate 	} else {
15390Sstevel@tonic-gate 		if (pool_xml_connection_alloc(conf, oflags) != PO_SUCCESS) {
15400Sstevel@tonic-gate 			conf->pc_state = POF_INVALID;
15410Sstevel@tonic-gate 			return (PO_FAIL);
15420Sstevel@tonic-gate 		}
15430Sstevel@tonic-gate 	}
15440Sstevel@tonic-gate 	return (PO_SUCCESS);
15450Sstevel@tonic-gate }
15460Sstevel@tonic-gate 
15470Sstevel@tonic-gate /*
15480Sstevel@tonic-gate  * Rollback a configuration. This will undo all changes to the configuration
15490Sstevel@tonic-gate  * since the last time pool_conf_commit was called.
15500Sstevel@tonic-gate  */
15510Sstevel@tonic-gate int
15520Sstevel@tonic-gate pool_conf_rollback(pool_conf_t *conf)
15530Sstevel@tonic-gate {
15540Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
15550Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
15560Sstevel@tonic-gate 		return (PO_FAIL);
15570Sstevel@tonic-gate 	}
15580Sstevel@tonic-gate 	return (conf->pc_prov->pc_rollback(conf));
15590Sstevel@tonic-gate }
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate /*
15620Sstevel@tonic-gate  * Commit a configuration. This will apply all changes to the
15630Sstevel@tonic-gate  * configuration to the permanent data store. The active parameter
15640Sstevel@tonic-gate  * indicates whether the configuration should be used to update the
15650Sstevel@tonic-gate  * dynamic configuration from the supplied (static) configuration or
15660Sstevel@tonic-gate  * whether it should be written back to persistent store.
15670Sstevel@tonic-gate  */
15680Sstevel@tonic-gate int
15690Sstevel@tonic-gate pool_conf_commit(pool_conf_t *conf, int active)
15700Sstevel@tonic-gate {
15710Sstevel@tonic-gate 	int retval;
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
15740Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
15750Sstevel@tonic-gate 		return (PO_FAIL);
15760Sstevel@tonic-gate 	}
15770Sstevel@tonic-gate 	if (active) {
15780Sstevel@tonic-gate 		int oflags;
15790Sstevel@tonic-gate 
15800Sstevel@tonic-gate 		if (conf_is_dynamic(conf) == PO_TRUE) {
15810Sstevel@tonic-gate 			pool_seterror(POE_BADPARAM);
15820Sstevel@tonic-gate 			return (PO_FAIL);
15830Sstevel@tonic-gate 		}
15840Sstevel@tonic-gate 		/*
15850Sstevel@tonic-gate 		 * Pretend that the configuration was opened PO_RDWR
15860Sstevel@tonic-gate 		 * so that a configuration which was opened PO_RDONLY
15870Sstevel@tonic-gate 		 * can be committed. The original flags are preserved
15880Sstevel@tonic-gate 		 * in oflags and restored after pool_conf_commit_sys()
15890Sstevel@tonic-gate 		 * returns.
15900Sstevel@tonic-gate 		 */
15910Sstevel@tonic-gate 		oflags = conf->pc_prov->pc_oflags;
15920Sstevel@tonic-gate 		conf->pc_prov->pc_oflags |= PO_RDWR;
15930Sstevel@tonic-gate 		retval = pool_conf_commit_sys(conf, active);
15940Sstevel@tonic-gate 		conf->pc_prov->pc_oflags = oflags;
15950Sstevel@tonic-gate 	} else {
15960Sstevel@tonic-gate 		/*
15970Sstevel@tonic-gate 		 * Write the configuration back to the backing store.
15980Sstevel@tonic-gate 		 */
15990Sstevel@tonic-gate 		retval =  conf->pc_prov->pc_commit(conf);
16000Sstevel@tonic-gate 	}
16010Sstevel@tonic-gate 	return (retval);
16020Sstevel@tonic-gate }
16030Sstevel@tonic-gate 
16040Sstevel@tonic-gate /*
16050Sstevel@tonic-gate  * Export a configuration. This will export a configuration in the specified
16060Sstevel@tonic-gate  * format (fmt) to the specified location.
16070Sstevel@tonic-gate  */
16080Sstevel@tonic-gate int
16090Sstevel@tonic-gate pool_conf_export(const pool_conf_t *conf, const char *location,
16100Sstevel@tonic-gate     pool_export_format_t fmt)
16110Sstevel@tonic-gate {
16120Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
16130Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16140Sstevel@tonic-gate 		return (PO_FAIL);
16150Sstevel@tonic-gate 	}
16160Sstevel@tonic-gate 	return (conf->pc_prov->pc_export(conf, location, fmt));
16170Sstevel@tonic-gate }
16180Sstevel@tonic-gate 
16190Sstevel@tonic-gate /*
16200Sstevel@tonic-gate  * Validate a configuration. This will validate a configuration at the
16210Sstevel@tonic-gate  * specified level.
16220Sstevel@tonic-gate  */
16230Sstevel@tonic-gate int
16240Sstevel@tonic-gate pool_conf_validate(const pool_conf_t *conf, pool_valid_level_t level)
16250Sstevel@tonic-gate {
16260Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
16270Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16280Sstevel@tonic-gate 		return (PO_FAIL);
16290Sstevel@tonic-gate 	}
16300Sstevel@tonic-gate 	return (conf->pc_prov->pc_validate(conf, level));
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate 
16330Sstevel@tonic-gate /*
16340Sstevel@tonic-gate  * Update the snapshot of a configuration. This can only be used on a
16350Sstevel@tonic-gate  * dynamic configuration.
16360Sstevel@tonic-gate  */
16370Sstevel@tonic-gate int
16380Sstevel@tonic-gate pool_conf_update(const pool_conf_t *conf, int *changed)
16390Sstevel@tonic-gate {
16400Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID ||
16410Sstevel@tonic-gate 	    conf_is_dynamic(conf) == PO_FALSE) {
16420Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16430Sstevel@tonic-gate 		return (PO_FAIL);
16440Sstevel@tonic-gate 	}
16450Sstevel@tonic-gate 	/*
16460Sstevel@tonic-gate 	 * Since this function only makes sense for dynamic
16470Sstevel@tonic-gate 	 * configurations, just call directly into the appropriate
16480Sstevel@tonic-gate 	 * function. This could be added into the pool_connection_t
16490Sstevel@tonic-gate 	 * interface if it was ever required.
16500Sstevel@tonic-gate 	 */
16510Sstevel@tonic-gate 	if (changed)
16520Sstevel@tonic-gate 		*changed = 0;
16530Sstevel@tonic-gate 	return (pool_knl_update((pool_conf_t *)conf, changed));
16540Sstevel@tonic-gate }
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate /*
16570Sstevel@tonic-gate  * Walk the properties of the supplied elem, calling the user supplied
16580Sstevel@tonic-gate  * function repeatedly as long as the user function returns
16590Sstevel@tonic-gate  * PO_SUCCESS.
16600Sstevel@tonic-gate  */
16610Sstevel@tonic-gate int
16620Sstevel@tonic-gate pool_walk_properties(pool_conf_t *conf, pool_elem_t *elem, void *arg,
16630Sstevel@tonic-gate     int (*prop_callback)(pool_conf_t *, pool_elem_t *, const char *,
16640Sstevel@tonic-gate 	pool_value_t *, void *))
16650Sstevel@tonic-gate {
16660Sstevel@tonic-gate 	return (pool_walk_any_properties(conf, elem, arg, prop_callback, 0));
16670Sstevel@tonic-gate }
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate void
16700Sstevel@tonic-gate free_value_list(int npvals, pool_value_t **pvals)
16710Sstevel@tonic-gate {
16720Sstevel@tonic-gate 	int j;
16730Sstevel@tonic-gate 
16740Sstevel@tonic-gate 	for (j = 0; j < npvals; j++) {
16750Sstevel@tonic-gate 		if (pvals[j])
16760Sstevel@tonic-gate 			pool_value_free(pvals[j]);
16770Sstevel@tonic-gate 	}
16780Sstevel@tonic-gate 	free(pvals);
16790Sstevel@tonic-gate }
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate /*
16820Sstevel@tonic-gate  * Walk the properties of the supplied elem, calling the user supplied
16830Sstevel@tonic-gate  * function repeatedly as long as the user function returns
16840Sstevel@tonic-gate  * PO_SUCCESS.
16850Sstevel@tonic-gate  * The list of properties to be walked is retrieved from the element
16860Sstevel@tonic-gate  */
16870Sstevel@tonic-gate int
16880Sstevel@tonic-gate pool_walk_any_properties(pool_conf_t *conf, pool_elem_t *elem, void *arg,
16890Sstevel@tonic-gate     int (*prop_callback)(pool_conf_t *, pool_elem_t *, const char *,
16900Sstevel@tonic-gate 	pool_value_t *, void *), int any)
16910Sstevel@tonic-gate {
16920Sstevel@tonic-gate 	pool_value_t **pvals;
16930Sstevel@tonic-gate 	int i;
16940Sstevel@tonic-gate 	const pool_prop_t *props = provider_get_props(elem);
16950Sstevel@tonic-gate 	uint_t npvals;
16960Sstevel@tonic-gate 
16970Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
16980Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16990Sstevel@tonic-gate 		return (PO_FAIL);
17000Sstevel@tonic-gate 	}
17010Sstevel@tonic-gate 
17020Sstevel@tonic-gate 	if (props == NULL) {
17030Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
17040Sstevel@tonic-gate 		return (PO_FAIL);
17050Sstevel@tonic-gate 	}
17060Sstevel@tonic-gate 
17070Sstevel@tonic-gate 	if ((pvals = elem->pe_get_props(elem, &npvals)) == NULL)
17080Sstevel@tonic-gate 		return (PO_FAIL);
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 	/*
17110Sstevel@tonic-gate 	 * Now walk the managed properties. As we find managed
17120Sstevel@tonic-gate 	 * properties removed them from the list of all properties to
17130Sstevel@tonic-gate 	 * prevent duplication.
17140Sstevel@tonic-gate 	 */
17150Sstevel@tonic-gate 	for (i = 0;  props[i].pp_pname != NULL; i++) {
17160Sstevel@tonic-gate 		int j;
17170Sstevel@tonic-gate 
17180Sstevel@tonic-gate 		/*
17190Sstevel@tonic-gate 		 * Special processing for type
17200Sstevel@tonic-gate 		 */
17210Sstevel@tonic-gate 		if (strcmp(props[i].pp_pname, c_type) == 0) {
17220Sstevel@tonic-gate 			pool_value_t val = POOL_VALUE_INITIALIZER;
17230Sstevel@tonic-gate 
17240Sstevel@tonic-gate 			if (pool_value_set_name(&val, props[i].pp_pname) ==
17250Sstevel@tonic-gate 			    PO_FAIL) {
17260Sstevel@tonic-gate 				free_value_list(npvals, pvals);
17270Sstevel@tonic-gate 				return (PO_FAIL);
17280Sstevel@tonic-gate 			}
17290Sstevel@tonic-gate 			if (props[i].pp_op.ppo_get_value(elem, &val) ==
17300Sstevel@tonic-gate 			    PO_FAIL) {
17310Sstevel@tonic-gate 				free_value_list(npvals, pvals);
17320Sstevel@tonic-gate 				return (PO_FAIL);
17330Sstevel@tonic-gate 			}
17340Sstevel@tonic-gate 			if (any == 1 || prop_is_hidden(&props[i]) == PO_FALSE) {
17350Sstevel@tonic-gate 				if (prop_callback(conf, elem, props[i].pp_pname,
17360Sstevel@tonic-gate 				    &val, arg) != PO_SUCCESS) {
17370Sstevel@tonic-gate 					free_value_list(npvals, pvals);
17380Sstevel@tonic-gate 					pool_seterror(POE_BADPARAM);
17390Sstevel@tonic-gate 					return (PO_FAIL);
17400Sstevel@tonic-gate 				}
17410Sstevel@tonic-gate 			}
17420Sstevel@tonic-gate 			continue;
17430Sstevel@tonic-gate 		}
17440Sstevel@tonic-gate 
17450Sstevel@tonic-gate 		for (j = 0; j < npvals; j++) {
17460Sstevel@tonic-gate 			if (pvals[j] && strcmp(pool_value_get_name(pvals[j]),
17470Sstevel@tonic-gate 			    props[i].pp_pname) == 0)
17480Sstevel@tonic-gate 				break;
17490Sstevel@tonic-gate 		}
17500Sstevel@tonic-gate 		/*
17510Sstevel@tonic-gate 		 * If we have found the property, then j < npvals. Process it
17520Sstevel@tonic-gate 		 * according to our property attributes. Otherwise, it's not
17530Sstevel@tonic-gate 		 * a managed property, so just ignore it until later.
17540Sstevel@tonic-gate 		 */
17550Sstevel@tonic-gate 		if (j < npvals) {
17560Sstevel@tonic-gate 			if (any == 1 || prop_is_hidden(&props[i]) == PO_FALSE) {
17570Sstevel@tonic-gate 				if (props[i].pp_op.ppo_get_value) {
17580Sstevel@tonic-gate 					if (pool_value_set_name(pvals[j],
17590Sstevel@tonic-gate 					props[i].pp_pname) == PO_FAIL) {
17600Sstevel@tonic-gate 						free_value_list(npvals, pvals);
17610Sstevel@tonic-gate 						return (PO_FAIL);
17620Sstevel@tonic-gate 					}
17630Sstevel@tonic-gate 					if (props[i].pp_op.ppo_get_value(elem,
17640Sstevel@tonic-gate 					    pvals[j]) == PO_FAIL) {
17650Sstevel@tonic-gate 						free_value_list(npvals, pvals);
17660Sstevel@tonic-gate 						return (PO_FAIL);
17670Sstevel@tonic-gate 					}
17680Sstevel@tonic-gate 				}
17690Sstevel@tonic-gate 				if (prop_callback(conf, elem, props[i].pp_pname,
17700Sstevel@tonic-gate 				    pvals[j], arg) != PO_SUCCESS) {
17710Sstevel@tonic-gate 					free_value_list(npvals, pvals);
17720Sstevel@tonic-gate 					pool_seterror(POE_BADPARAM);
17730Sstevel@tonic-gate 					return (PO_FAIL);
17740Sstevel@tonic-gate 				}
17750Sstevel@tonic-gate 			}
17760Sstevel@tonic-gate 			pool_value_free(pvals[j]);
17770Sstevel@tonic-gate 			pvals[j] = NULL;
17780Sstevel@tonic-gate 		}
17790Sstevel@tonic-gate 	}
17800Sstevel@tonic-gate 	for (i = 0;  i < npvals; i++) {
17810Sstevel@tonic-gate 		if (pvals[i]) {
17820Sstevel@tonic-gate 			const char *name = pool_value_get_name(pvals[i]);
17830Sstevel@tonic-gate 			char *qname = strrchr(name, '.');
17840Sstevel@tonic-gate 			if ((qname && qname[1] != '_') ||
17850Sstevel@tonic-gate 			    (!qname && name[0] != '_')) {
17860Sstevel@tonic-gate 				if (prop_callback(conf, elem, name, pvals[i],
17870Sstevel@tonic-gate 				    arg) != PO_SUCCESS) {
17880Sstevel@tonic-gate 					free_value_list(npvals, pvals);
17890Sstevel@tonic-gate 					pool_seterror(POE_BADPARAM);
17900Sstevel@tonic-gate 					return (PO_FAIL);
17910Sstevel@tonic-gate 				}
17920Sstevel@tonic-gate 			}
17930Sstevel@tonic-gate 			pool_value_free(pvals[i]);
17940Sstevel@tonic-gate 			pvals[i] = NULL;
17950Sstevel@tonic-gate 		}
17960Sstevel@tonic-gate 	}
17970Sstevel@tonic-gate 	free(pvals);
17980Sstevel@tonic-gate 	return (PO_SUCCESS);
17990Sstevel@tonic-gate }
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate /*
18020Sstevel@tonic-gate  * Return a pool, searching the supplied configuration for a pool with the
18030Sstevel@tonic-gate  * supplied name. The search is case sensitive.
18040Sstevel@tonic-gate  */
18050Sstevel@tonic-gate pool_t *
18060Sstevel@tonic-gate pool_get_pool(const pool_conf_t *conf, const char *name)
18070Sstevel@tonic-gate {
18080Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
18090Sstevel@tonic-gate 	pool_t **rs;
18100Sstevel@tonic-gate 	pool_t *ret;
18110Sstevel@tonic-gate 	uint_t size = 0;
18120Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
18130Sstevel@tonic-gate 
18140Sstevel@tonic-gate 	props[0] = &val;
18150Sstevel@tonic-gate 
18160Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
18170Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
18180Sstevel@tonic-gate 		return (NULL);
18190Sstevel@tonic-gate 	}
18200Sstevel@tonic-gate 
18210Sstevel@tonic-gate 	if (pool_value_set_name(props[0], "pool.name") != PO_SUCCESS ||
18220Sstevel@tonic-gate 	    pool_value_set_string(props[0], name) != PO_SUCCESS) {
18230Sstevel@tonic-gate 		return (NULL);
18240Sstevel@tonic-gate 	}
18250Sstevel@tonic-gate 	rs = pool_query_pools(conf, &size, props);
18260Sstevel@tonic-gate 	if (rs == NULL) { /* Can't find a pool to match the name */
18270Sstevel@tonic-gate 		return (NULL);
18280Sstevel@tonic-gate 	}
18290Sstevel@tonic-gate 	if (size != 1) {
18300Sstevel@tonic-gate 		free(rs);
18310Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
18320Sstevel@tonic-gate 		return (NULL);
18330Sstevel@tonic-gate 	}
18340Sstevel@tonic-gate 	ret = rs[0];
18350Sstevel@tonic-gate 	free(rs);
18360Sstevel@tonic-gate 	return (ret);
18370Sstevel@tonic-gate }
18380Sstevel@tonic-gate 
18390Sstevel@tonic-gate /*
18400Sstevel@tonic-gate  * Return a result set of pools, searching the supplied configuration
18410Sstevel@tonic-gate  * for pools which match the supplied property criteria. props is a null
18420Sstevel@tonic-gate  * terminated list of properties which will be used to match qualifying
18430Sstevel@tonic-gate  * pools. size is updated with the size of the pool
18440Sstevel@tonic-gate  */
18450Sstevel@tonic-gate pool_t **
18460Sstevel@tonic-gate pool_query_pools(const pool_conf_t *conf, uint_t *size, pool_value_t **props)
18470Sstevel@tonic-gate {
18480Sstevel@tonic-gate 	pool_result_set_t *rs;
18490Sstevel@tonic-gate 	pool_elem_t *pe;
18500Sstevel@tonic-gate 	pool_t **result = NULL;
18510Sstevel@tonic-gate 	int i = 0;
18520Sstevel@tonic-gate 
18530Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
18540Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
18550Sstevel@tonic-gate 		return (NULL);
18560Sstevel@tonic-gate 	}
18570Sstevel@tonic-gate 	rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_POOL, props);
18580Sstevel@tonic-gate 	if (rs == NULL) {
18590Sstevel@tonic-gate 		return (NULL);
18600Sstevel@tonic-gate 	}
18610Sstevel@tonic-gate 	if ((*size = pool_rs_count(rs)) == 0) {
18620Sstevel@tonic-gate 		(void) pool_rs_close(rs);
18630Sstevel@tonic-gate 		return (NULL);
18640Sstevel@tonic-gate 	}
18650Sstevel@tonic-gate 	if ((result = malloc(sizeof (pool_t *) * (*size + 1))) == NULL) {
18660Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
18670Sstevel@tonic-gate 		(void) pool_rs_close(rs);
18680Sstevel@tonic-gate 		return (NULL);
18690Sstevel@tonic-gate 	}
18700Sstevel@tonic-gate 	(void) memset(result, 0, sizeof (pool_t *) * (*size + 1));
18710Sstevel@tonic-gate 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
18720Sstevel@tonic-gate 		if (pool_elem_class(pe) != PEC_POOL) {
18730Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
18740Sstevel@tonic-gate 			free(result);
18750Sstevel@tonic-gate 			(void) pool_rs_close(rs);
18760Sstevel@tonic-gate 			return (NULL);
18770Sstevel@tonic-gate 		}
18780Sstevel@tonic-gate 		result[i++] = pool_elem_pool(pe);
18790Sstevel@tonic-gate 	}
18800Sstevel@tonic-gate 	(void) pool_rs_close(rs);
18810Sstevel@tonic-gate 	return (result);
18820Sstevel@tonic-gate }
18830Sstevel@tonic-gate 
18840Sstevel@tonic-gate /*
18850Sstevel@tonic-gate  * Return an res, searching the supplied configuration for an res with the
18860Sstevel@tonic-gate  * supplied name. The search is case sensitive.
18870Sstevel@tonic-gate  */
18880Sstevel@tonic-gate pool_resource_t *
18890Sstevel@tonic-gate pool_get_resource(const pool_conf_t *conf, const char *sz_type,
18900Sstevel@tonic-gate     const char *name)
18910Sstevel@tonic-gate {
18920Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL, NULL };
18930Sstevel@tonic-gate 	pool_resource_t **rs;
18940Sstevel@tonic-gate 	pool_resource_t *ret;
18950Sstevel@tonic-gate 	uint_t size = 0;
18960Sstevel@tonic-gate 	char_buf_t *cb = NULL;
18970Sstevel@tonic-gate 	pool_value_t val0 = POOL_VALUE_INITIALIZER;
18980Sstevel@tonic-gate 	pool_value_t val1 = POOL_VALUE_INITIALIZER;
18990Sstevel@tonic-gate 
19000Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
19010Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
19020Sstevel@tonic-gate 		return (NULL);
19030Sstevel@tonic-gate 	}
19040Sstevel@tonic-gate 
19050Sstevel@tonic-gate 	if (sz_type == NULL) {
19060Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
19070Sstevel@tonic-gate 		return (NULL);
19080Sstevel@tonic-gate 	}
19090Sstevel@tonic-gate 
19100Sstevel@tonic-gate 	props[0] = &val0;
19110Sstevel@tonic-gate 	props[1] = &val1;
19120Sstevel@tonic-gate 
19130Sstevel@tonic-gate 	if (pool_value_set_string(props[0], sz_type) != PO_SUCCESS ||
19140Sstevel@tonic-gate 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS)
19150Sstevel@tonic-gate 		return (NULL);
19160Sstevel@tonic-gate 
19170Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
19180Sstevel@tonic-gate 		return (NULL);
19190Sstevel@tonic-gate 	}
19200Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.name", sz_type) != PO_SUCCESS) {
19210Sstevel@tonic-gate 		free_char_buf(cb);
19220Sstevel@tonic-gate 		return (NULL);
19230Sstevel@tonic-gate 	}
19240Sstevel@tonic-gate 	if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) {
19250Sstevel@tonic-gate 		free_char_buf(cb);
19260Sstevel@tonic-gate 		return (NULL);
19270Sstevel@tonic-gate 	}
19280Sstevel@tonic-gate 	if (pool_value_set_string(props[1], name) != PO_SUCCESS) {
19290Sstevel@tonic-gate 		free_char_buf(cb);
19300Sstevel@tonic-gate 		return (NULL);
19310Sstevel@tonic-gate 	}
19320Sstevel@tonic-gate 	free_char_buf(cb);
19330Sstevel@tonic-gate 	rs = pool_query_resources(conf, &size, props);
19340Sstevel@tonic-gate 	if (rs == NULL) {
19350Sstevel@tonic-gate 		return (NULL);
19360Sstevel@tonic-gate 	}
19370Sstevel@tonic-gate 	if (size != 1) {
19380Sstevel@tonic-gate 		free(rs);
19390Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
19400Sstevel@tonic-gate 		return (NULL);
19410Sstevel@tonic-gate 	}
19420Sstevel@tonic-gate 	ret = rs[0];
19430Sstevel@tonic-gate 	free(rs);
19440Sstevel@tonic-gate 	return (ret);
19450Sstevel@tonic-gate }
19460Sstevel@tonic-gate 
19470Sstevel@tonic-gate /*
19480Sstevel@tonic-gate  * Return a result set of res (actually as pool_elem_ts), searching the
19490Sstevel@tonic-gate  * supplied configuration for res which match the supplied property
19500Sstevel@tonic-gate  * criteria. props is a null terminated list of properties which will be used
19510Sstevel@tonic-gate  * to match qualifying res.
19520Sstevel@tonic-gate  */
19530Sstevel@tonic-gate pool_resource_t **
19540Sstevel@tonic-gate pool_query_resources(const pool_conf_t *conf, uint_t *size,
19550Sstevel@tonic-gate     pool_value_t **props)
19560Sstevel@tonic-gate {
19570Sstevel@tonic-gate 	pool_result_set_t *rs;
19580Sstevel@tonic-gate 	pool_elem_t *pe;
19590Sstevel@tonic-gate 	pool_resource_t **result = NULL;
19600Sstevel@tonic-gate 	int i = 0;
19610Sstevel@tonic-gate 
19620Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
19630Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
19640Sstevel@tonic-gate 		return (NULL);
19650Sstevel@tonic-gate 	}
19660Sstevel@tonic-gate 
19670Sstevel@tonic-gate 	*size = 0;
19680Sstevel@tonic-gate 
19690Sstevel@tonic-gate 	rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_RES, props);
19700Sstevel@tonic-gate 	if (rs == NULL) {
19710Sstevel@tonic-gate 		return (NULL);
19720Sstevel@tonic-gate 	}
19730Sstevel@tonic-gate 	if ((*size = pool_rs_count(rs)) == 0) {
19740Sstevel@tonic-gate 		(void) pool_rs_close(rs);
19750Sstevel@tonic-gate 		return (NULL);
19760Sstevel@tonic-gate 	}
19770Sstevel@tonic-gate 	if ((result = malloc(sizeof (pool_resource_t *) * (*size + 1)))
19780Sstevel@tonic-gate 	    == NULL) {
19790Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
19800Sstevel@tonic-gate 		(void) pool_rs_close(rs);
19810Sstevel@tonic-gate 		return (NULL);
19820Sstevel@tonic-gate 	}
19830Sstevel@tonic-gate 	(void) memset(result, 0, sizeof (pool_resource_t *) * (*size + 1));
19840Sstevel@tonic-gate 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
19850Sstevel@tonic-gate 		if (pool_elem_class(pe) != PEC_RES_COMP &&
19860Sstevel@tonic-gate 		    pool_elem_class(pe) != PEC_RES_AGG) {
19870Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
19880Sstevel@tonic-gate 			free(result);
19890Sstevel@tonic-gate 			(void) pool_rs_close(rs);
19900Sstevel@tonic-gate 			return (NULL);
19910Sstevel@tonic-gate 		}
19920Sstevel@tonic-gate 		result[i++] = pool_elem_res(pe);
19930Sstevel@tonic-gate 	}
19940Sstevel@tonic-gate 	(void) pool_rs_close(rs);
19950Sstevel@tonic-gate 	return (result);
19960Sstevel@tonic-gate }
19970Sstevel@tonic-gate 
19980Sstevel@tonic-gate /*
19990Sstevel@tonic-gate  * Return a result set of comp (actually as pool_elem_ts), searching the
20000Sstevel@tonic-gate  * supplied configuration for comp which match the supplied property
20010Sstevel@tonic-gate  * criteria. props is a null terminated list of properties which will be used
20020Sstevel@tonic-gate  * to match qualifying comp.
20030Sstevel@tonic-gate  */
20040Sstevel@tonic-gate pool_component_t **
20050Sstevel@tonic-gate pool_query_components(const pool_conf_t *conf, uint_t *size,
20060Sstevel@tonic-gate     pool_value_t **props)
20070Sstevel@tonic-gate {
20080Sstevel@tonic-gate 	return (pool_query_resource_components(conf, NULL, size, props));
20090Sstevel@tonic-gate }
20100Sstevel@tonic-gate 
20110Sstevel@tonic-gate /*
20120Sstevel@tonic-gate  * Destroy a pool. If the pool cannot be found or removed an error is
20130Sstevel@tonic-gate  * returned. This is basically a wrapper around pool_elem_remove to ensure
20140Sstevel@tonic-gate  * some type safety for the pool subtype.
20150Sstevel@tonic-gate  */
20160Sstevel@tonic-gate int
20170Sstevel@tonic-gate pool_destroy(pool_conf_t *conf, pool_t *pp)
20180Sstevel@tonic-gate {
20190Sstevel@tonic-gate 	pool_elem_t *pe;
20200Sstevel@tonic-gate 
20210Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
20220Sstevel@tonic-gate 		return (PO_FAIL);
20230Sstevel@tonic-gate 
20240Sstevel@tonic-gate 	pe = TO_ELEM(pp);
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate 	/*
20270Sstevel@tonic-gate 	 * Cannot destroy the default pool.
20280Sstevel@tonic-gate 	 */
20290Sstevel@tonic-gate 	if (elem_is_default(pe) == PO_TRUE) {
20300Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
20310Sstevel@tonic-gate 		return (PO_FAIL);
20320Sstevel@tonic-gate 	}
20330Sstevel@tonic-gate 	if (pool_elem_remove(pe) != PO_SUCCESS)
20340Sstevel@tonic-gate 		return (PO_FAIL);
20350Sstevel@tonic-gate 	return (PO_SUCCESS);
20360Sstevel@tonic-gate }
20370Sstevel@tonic-gate 
20380Sstevel@tonic-gate /*
20390Sstevel@tonic-gate  * Destroy an res. If the res cannot be found or removed an error is
20400Sstevel@tonic-gate  * returned. This is basically a wrapper around pool_elem_remove to ensure
20410Sstevel@tonic-gate  * some type safety for the res subtype.
20420Sstevel@tonic-gate  */
20430Sstevel@tonic-gate int
20440Sstevel@tonic-gate pool_resource_destroy(pool_conf_t *conf, pool_resource_t *prs)
20450Sstevel@tonic-gate {
20460Sstevel@tonic-gate 	pool_elem_t *pe;
20470Sstevel@tonic-gate 	pool_component_t **rl;
20480Sstevel@tonic-gate 	uint_t res_size;
20490Sstevel@tonic-gate 	pool_t **pl;
20500Sstevel@tonic-gate 	uint_t npool;
20510Sstevel@tonic-gate 	int i;
20520Sstevel@tonic-gate 
20530Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
20540Sstevel@tonic-gate 		return (PO_FAIL);
20550Sstevel@tonic-gate 
20560Sstevel@tonic-gate 	pe = TO_ELEM(prs);
20570Sstevel@tonic-gate 
20580Sstevel@tonic-gate 	if (resource_is_system(prs) == PO_TRUE) {
20590Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
20600Sstevel@tonic-gate 		return (PO_FAIL);
20610Sstevel@tonic-gate 	}
20620Sstevel@tonic-gate 	/*
20630Sstevel@tonic-gate 	 * Walk all the pools and dissociate any pools which are using
20640Sstevel@tonic-gate 	 * this resource.
20650Sstevel@tonic-gate 	 */
20660Sstevel@tonic-gate 	if ((pl = pool_query_pools(conf, &npool, NULL)) != NULL) {
20670Sstevel@tonic-gate 		for (i = 0; i < npool; i++) {
20680Sstevel@tonic-gate 			pool_resource_t **rl;
20690Sstevel@tonic-gate 			uint_t nres;
20700Sstevel@tonic-gate 			int j;
20710Sstevel@tonic-gate 
20720Sstevel@tonic-gate 			if ((rl = pool_query_pool_resources(conf, pl[i], &nres,
20730Sstevel@tonic-gate 			    NULL)) != NULL) {
20740Sstevel@tonic-gate 				for (j = 0; j < nres; j++) {
20750Sstevel@tonic-gate 					if (rl[j] == prs) {
20760Sstevel@tonic-gate 						if (pool_dissociate(conf, pl[i],
20770Sstevel@tonic-gate 						    rl[j]) != PO_SUCCESS) {
20780Sstevel@tonic-gate 							free(rl);
20790Sstevel@tonic-gate 							free(pl);
20800Sstevel@tonic-gate 							return (PO_FAIL);
20810Sstevel@tonic-gate 						}
20820Sstevel@tonic-gate 						break;
20830Sstevel@tonic-gate 					}
20840Sstevel@tonic-gate 				}
20850Sstevel@tonic-gate 			free(rl);
20860Sstevel@tonic-gate 			}
20870Sstevel@tonic-gate 		}
20880Sstevel@tonic-gate 		free(pl);
20890Sstevel@tonic-gate 	}
20900Sstevel@tonic-gate 	if (pe->pe_class == PEC_RES_COMP) {
20910Sstevel@tonic-gate 		pool_resource_t *default_set_res;
20920Sstevel@tonic-gate 
20930Sstevel@tonic-gate 		/*
20940Sstevel@tonic-gate 		 * Use the xtransfer option to move comp around
20950Sstevel@tonic-gate 		 */
20960Sstevel@tonic-gate 		default_set_res = (pool_resource_t *)get_default_resource(prs);
20970Sstevel@tonic-gate 
20980Sstevel@tonic-gate 		if ((rl = pool_query_resource_components(conf, prs, &res_size,
20990Sstevel@tonic-gate 		    NULL)) != NULL) {
21000Sstevel@tonic-gate 			int ostate = conf->pc_state;
21010Sstevel@tonic-gate 			conf->pc_state = POF_DESTROY;
21020Sstevel@tonic-gate 			if (pool_resource_xtransfer(conf, prs, default_set_res,
21030Sstevel@tonic-gate 			    rl) == PO_FAIL) {
21040Sstevel@tonic-gate 				free(rl);
21050Sstevel@tonic-gate 				conf->pc_state = ostate;
21060Sstevel@tonic-gate 				return (PO_FAIL);
21070Sstevel@tonic-gate 			}
21080Sstevel@tonic-gate 			conf->pc_state = ostate;
21090Sstevel@tonic-gate 			free(rl);
21100Sstevel@tonic-gate 		}
21110Sstevel@tonic-gate 	}
21120Sstevel@tonic-gate 	if (pool_elem_remove(pe) != PO_SUCCESS)
21130Sstevel@tonic-gate 		return (PO_FAIL);
21140Sstevel@tonic-gate 	return (PO_SUCCESS);
21150Sstevel@tonic-gate }
21160Sstevel@tonic-gate 
21170Sstevel@tonic-gate /*
21180Sstevel@tonic-gate  * Destroy a comp. If the comp cannot be found or removed an error is
21190Sstevel@tonic-gate  * returned. This is basically a wrapper around pool_elem_remove to ensure
21200Sstevel@tonic-gate  * some type safety for the comp subtype.
21210Sstevel@tonic-gate  */
21220Sstevel@tonic-gate int
21230Sstevel@tonic-gate pool_component_destroy(pool_component_t *pr)
21240Sstevel@tonic-gate {
21250Sstevel@tonic-gate 	pool_elem_t *pe = TO_ELEM(pr);
21260Sstevel@tonic-gate 
21270Sstevel@tonic-gate 	if (pool_elem_remove(pe) != PO_SUCCESS)
21280Sstevel@tonic-gate 		return (PO_FAIL);
21290Sstevel@tonic-gate 	return (PO_SUCCESS);
21300Sstevel@tonic-gate }
21310Sstevel@tonic-gate 
21320Sstevel@tonic-gate /*
21330Sstevel@tonic-gate  * Remove a pool_elem_t from a configuration. This has been "hidden" away as
21340Sstevel@tonic-gate  * a static routine since the only elements which are currently being removed
21350Sstevel@tonic-gate  * are pools, res & comp and the wrapper functions above provide type-safe
21360Sstevel@tonic-gate  * access. However, if there is a need to remove other types of elements
21370Sstevel@tonic-gate  * then this could be promoted to pool_impl.h or more wrappers could
21380Sstevel@tonic-gate  * be added to pool_impl.h.
21390Sstevel@tonic-gate  */
21400Sstevel@tonic-gate int
21410Sstevel@tonic-gate pool_elem_remove(pool_elem_t *pe)
21420Sstevel@tonic-gate {
21430Sstevel@tonic-gate 	return (pe->pe_remove(pe));
21440Sstevel@tonic-gate }
21450Sstevel@tonic-gate 
21460Sstevel@tonic-gate /*
21470Sstevel@tonic-gate  * Execute a query to search for a qualifying set of elements.
21480Sstevel@tonic-gate  */
21490Sstevel@tonic-gate pool_result_set_t *
21500Sstevel@tonic-gate pool_exec_query(const pool_conf_t *conf, const pool_elem_t *src,
21510Sstevel@tonic-gate     const char *src_attr, pool_elem_class_t classes, pool_value_t **props)
21520Sstevel@tonic-gate {
21530Sstevel@tonic-gate 	return (conf->pc_prov->pc_exec_query(conf, src, src_attr, classes,
21540Sstevel@tonic-gate 	    props));
21550Sstevel@tonic-gate }
21560Sstevel@tonic-gate 
21570Sstevel@tonic-gate /*
21580Sstevel@tonic-gate  * Get the next result from a result set of elements.
21590Sstevel@tonic-gate  */
21600Sstevel@tonic-gate pool_elem_t *
21610Sstevel@tonic-gate pool_rs_next(pool_result_set_t *set)
21620Sstevel@tonic-gate {
21630Sstevel@tonic-gate 	return (set->prs_next(set));
21640Sstevel@tonic-gate }
21650Sstevel@tonic-gate 
21660Sstevel@tonic-gate /*
21670Sstevel@tonic-gate  * Get the previous result from a result set of elements.
21680Sstevel@tonic-gate  */
21690Sstevel@tonic-gate pool_elem_t *
21700Sstevel@tonic-gate pool_rs_prev(pool_result_set_t *set)
21710Sstevel@tonic-gate {
21720Sstevel@tonic-gate 	return (set->prs_prev(set));
21730Sstevel@tonic-gate }
21740Sstevel@tonic-gate 
21750Sstevel@tonic-gate /*
21760Sstevel@tonic-gate  * Get the first result from a result set of elements.
21770Sstevel@tonic-gate  */
21780Sstevel@tonic-gate pool_elem_t *
21790Sstevel@tonic-gate pool_rs_first(pool_result_set_t *set)
21800Sstevel@tonic-gate {
21810Sstevel@tonic-gate 	return (set->prs_first(set));
21820Sstevel@tonic-gate }
21830Sstevel@tonic-gate 
21840Sstevel@tonic-gate /*
21850Sstevel@tonic-gate  * Get the last result from a result set of elements.
21860Sstevel@tonic-gate  */
21870Sstevel@tonic-gate pool_elem_t *
21880Sstevel@tonic-gate pool_rs_last(pool_result_set_t *set)
21890Sstevel@tonic-gate {
21900Sstevel@tonic-gate 	return (set->prs_last(set));
21910Sstevel@tonic-gate }
21920Sstevel@tonic-gate 
21930Sstevel@tonic-gate 
21940Sstevel@tonic-gate /*
21950Sstevel@tonic-gate  * Get the count for a result set of elements.
21960Sstevel@tonic-gate  */
21970Sstevel@tonic-gate int
21980Sstevel@tonic-gate pool_rs_count(pool_result_set_t *set)
21990Sstevel@tonic-gate {
22000Sstevel@tonic-gate 	return (set->prs_count(set));
22010Sstevel@tonic-gate }
22020Sstevel@tonic-gate 
22030Sstevel@tonic-gate /*
22040Sstevel@tonic-gate  * Get the index for a result set of elements.
22050Sstevel@tonic-gate  */
22060Sstevel@tonic-gate int
22070Sstevel@tonic-gate pool_rs_get_index(pool_result_set_t *set)
22080Sstevel@tonic-gate {
22090Sstevel@tonic-gate 	return (set->prs_get_index(set));
22100Sstevel@tonic-gate }
22110Sstevel@tonic-gate 
22120Sstevel@tonic-gate /*
22130Sstevel@tonic-gate  * Set the index for a result set of elements.
22140Sstevel@tonic-gate  */
22150Sstevel@tonic-gate int
22160Sstevel@tonic-gate pool_rs_set_index(pool_result_set_t *set, int index)
22170Sstevel@tonic-gate {
22180Sstevel@tonic-gate 	return (set->prs_set_index(set, index));
22190Sstevel@tonic-gate }
22200Sstevel@tonic-gate 
22210Sstevel@tonic-gate /*
22220Sstevel@tonic-gate  * Close a result set of elements, freeing all associated resources.
22230Sstevel@tonic-gate  */
22240Sstevel@tonic-gate int
22250Sstevel@tonic-gate pool_rs_close(pool_result_set_t *set)
22260Sstevel@tonic-gate {
22270Sstevel@tonic-gate 	return (set->prs_close(set));
22280Sstevel@tonic-gate }
22290Sstevel@tonic-gate 
22300Sstevel@tonic-gate /*
22310Sstevel@tonic-gate  * When transferring resource components using pool_resource_transfer,
22320Sstevel@tonic-gate  * this function is invoked to choose which actual components will be
22330Sstevel@tonic-gate  * transferred.
22340Sstevel@tonic-gate  */
22350Sstevel@tonic-gate int
22360Sstevel@tonic-gate choose_components(pool_resource_t *src, pool_resource_t *dst, uint64_t size)
22370Sstevel@tonic-gate {
22380Sstevel@tonic-gate 	pool_component_t **components = NULL, *moved[] = { NULL, NULL };
22390Sstevel@tonic-gate 	int i;
22400Sstevel@tonic-gate 	uint_t ncomponent;
22410Sstevel@tonic-gate 	pool_conf_t *conf = TO_CONF(TO_ELEM(src));
22420Sstevel@tonic-gate 
22430Sstevel@tonic-gate 	if (size == 0)
22440Sstevel@tonic-gate 		return (PO_SUCCESS);
22450Sstevel@tonic-gate 	/*
22460Sstevel@tonic-gate 	 * Get the component list from our src component.
22470Sstevel@tonic-gate 	 */
22480Sstevel@tonic-gate 	if ((components = pool_query_resource_components(conf, src, &ncomponent,
22490Sstevel@tonic-gate 	    NULL)) == NULL) {
22500Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
22510Sstevel@tonic-gate 		return (PO_FAIL);
22520Sstevel@tonic-gate 	}
22530Sstevel@tonic-gate 	qsort(components, ncomponent, sizeof (pool_elem_t *),
22540Sstevel@tonic-gate 	    qsort_elem_compare);
22550Sstevel@tonic-gate 	/*
22560Sstevel@tonic-gate 	 * Components that aren't specifically requested by the resource
22570Sstevel@tonic-gate 	 * should be transferred out first.
22580Sstevel@tonic-gate 	 */
22590Sstevel@tonic-gate 	for (i = 0; size > 0 && components[i] != NULL; i++) {
22600Sstevel@tonic-gate 		if (!cpu_is_requested(components[i])) {
22610Sstevel@tonic-gate 			moved[0] = components[i];
22620Sstevel@tonic-gate 			if (pool_resource_xtransfer(conf, src, dst, moved) ==
22630Sstevel@tonic-gate 			    PO_SUCCESS) {
22640Sstevel@tonic-gate 				size--;
22650Sstevel@tonic-gate 			}
22660Sstevel@tonic-gate 		}
22670Sstevel@tonic-gate 	}
22680Sstevel@tonic-gate 
22690Sstevel@tonic-gate 	/*
22700Sstevel@tonic-gate 	 * If we couldn't find enough "un-requested" components, select random
22710Sstevel@tonic-gate 	 * requested components.
22720Sstevel@tonic-gate 	 */
22730Sstevel@tonic-gate 	for (i = 0; size > 0 && components[i] != NULL; i++) {
22740Sstevel@tonic-gate 		if (cpu_is_requested(components[i])) {
22750Sstevel@tonic-gate 			moved[0] = components[i];
22760Sstevel@tonic-gate 			if (pool_resource_xtransfer(conf, src, dst, moved) ==
22770Sstevel@tonic-gate 			    PO_SUCCESS) {
22780Sstevel@tonic-gate 				size--;
22790Sstevel@tonic-gate 			}
22800Sstevel@tonic-gate 		}
22810Sstevel@tonic-gate 	}
22820Sstevel@tonic-gate 
22830Sstevel@tonic-gate 	free(components);
22840Sstevel@tonic-gate 	/*
22850Sstevel@tonic-gate 	 * If we couldn't transfer out all the resources we asked for, then
22860Sstevel@tonic-gate 	 * return error.
22870Sstevel@tonic-gate 	 */
22880Sstevel@tonic-gate 	return (size == 0 ? PO_SUCCESS : PO_FAIL);
22890Sstevel@tonic-gate }
22900Sstevel@tonic-gate 
22910Sstevel@tonic-gate /*
22920Sstevel@tonic-gate  * Common processing for a resource transfer (xfer or xxfer).
22930Sstevel@tonic-gate  *
22940Sstevel@tonic-gate  * - Return XFER_CONTINUE if the transfer should proceeed
22950Sstevel@tonic-gate  * - Return XFER_FAIL if the transfer should be stopped in failure
22960Sstevel@tonic-gate  * - Return XFER_SUCCESS if the transfer should be stopped in success
22970Sstevel@tonic-gate  */
22980Sstevel@tonic-gate int
22990Sstevel@tonic-gate setup_transfer(pool_conf_t *conf, pool_resource_t *src, pool_resource_t *tgt,
23000Sstevel@tonic-gate     uint64_t size, uint64_t *src_size, uint64_t *tgt_size)
23010Sstevel@tonic-gate {
23020Sstevel@tonic-gate 	uint64_t src_min;
23030Sstevel@tonic-gate 	uint64_t tgt_max;
23040Sstevel@tonic-gate 
23050Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
23060Sstevel@tonic-gate 		return (XFER_FAIL);
23070Sstevel@tonic-gate 
23080Sstevel@tonic-gate 	/*
23090Sstevel@tonic-gate 	 * Makes sure the two resources are of the same type
23100Sstevel@tonic-gate 	 */
23110Sstevel@tonic-gate 	if (pool_resource_elem_class(TO_ELEM(src)) !=
23120Sstevel@tonic-gate 	    pool_resource_elem_class(TO_ELEM(tgt))) {
23130Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
23140Sstevel@tonic-gate 		return (XFER_FAIL);
23150Sstevel@tonic-gate 	}
23160Sstevel@tonic-gate 
23170Sstevel@tonic-gate 	/*
23180Sstevel@tonic-gate 	 * Transferring to yourself is a no-op
23190Sstevel@tonic-gate 	 */
23200Sstevel@tonic-gate 	if (src == tgt)
23210Sstevel@tonic-gate 		return (XFER_SUCCESS);
23220Sstevel@tonic-gate 
23230Sstevel@tonic-gate 	/*
23240Sstevel@tonic-gate 	 * Transferring nothing is a no-op
23250Sstevel@tonic-gate 	 */
23260Sstevel@tonic-gate 	if (size == 0)
23270Sstevel@tonic-gate 		return (XFER_SUCCESS);
23280Sstevel@tonic-gate 
23290Sstevel@tonic-gate 	if (resource_get_min(src, &src_min) != PO_SUCCESS ||
23300Sstevel@tonic-gate 	    resource_get_size(src, src_size) != PO_SUCCESS ||
23310Sstevel@tonic-gate 	    resource_get_max(tgt, &tgt_max) != PO_SUCCESS ||
23320Sstevel@tonic-gate 	    resource_get_size(tgt, tgt_size) != PO_SUCCESS) {
23330Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
23340Sstevel@tonic-gate 		return (XFER_FAIL);
23350Sstevel@tonic-gate 	}
23360Sstevel@tonic-gate 	if (pool_conf_status(conf) != POF_DESTROY) {
23370Sstevel@tonic-gate 		/*
23380Sstevel@tonic-gate 		 * src_size - donating >= src.min
23390Sstevel@tonic-gate 		 * size + receiving <= tgt.max (except for default)
23400Sstevel@tonic-gate 		 */
23410Sstevel@tonic-gate #ifdef DEBUG
23420Sstevel@tonic-gate 		dprintf("conf is %s\n", pool_conf_location(conf));
23430Sstevel@tonic-gate 		dprintf("setup_transfer: src_size %llu\n", *src_size);
23440Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(src));
23450Sstevel@tonic-gate 		dprintf("setup_transfer: tgt_size %llu\n", *tgt_size);
23460Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(tgt));
23470Sstevel@tonic-gate #endif	/* DEBUG */
23480Sstevel@tonic-gate 		if (*src_size - size < src_min ||
23490Sstevel@tonic-gate 		    (resource_is_default(tgt) == PO_FALSE &&
23500Sstevel@tonic-gate 			*tgt_size + size > tgt_max)) {
23510Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
23520Sstevel@tonic-gate 			return (XFER_FAIL);
23530Sstevel@tonic-gate 		}
23540Sstevel@tonic-gate 	}
23550Sstevel@tonic-gate 	return (XFER_CONTINUE);
23560Sstevel@tonic-gate }
23570Sstevel@tonic-gate 
23580Sstevel@tonic-gate /*
23590Sstevel@tonic-gate  * Transfer resource quantities from one resource set to another.
23600Sstevel@tonic-gate  */
23610Sstevel@tonic-gate int
23620Sstevel@tonic-gate pool_resource_transfer(pool_conf_t *conf, pool_resource_t *src,
23630Sstevel@tonic-gate     pool_resource_t *tgt, uint64_t size)
23640Sstevel@tonic-gate {
23650Sstevel@tonic-gate 	uint64_t src_size;
23660Sstevel@tonic-gate 	uint64_t tgt_size;
23670Sstevel@tonic-gate 	int ret;
23680Sstevel@tonic-gate 
23690Sstevel@tonic-gate 	if ((ret = setup_transfer(conf, src, tgt, size, &src_size, &tgt_size))
23700Sstevel@tonic-gate 	    != XFER_CONTINUE)
23710Sstevel@tonic-gate 		return (ret);
23720Sstevel@tonic-gate 	/*
23730Sstevel@tonic-gate 	 * If this resource is a res_comp we must call move components
23740Sstevel@tonic-gate 	 */
23750Sstevel@tonic-gate 	if (pool_elem_class(TO_ELEM(src)) == PEC_RES_COMP)
23760Sstevel@tonic-gate 		return (choose_components(src, tgt, size));
23770Sstevel@tonic-gate 	/*
23780Sstevel@tonic-gate 	 * Now do the transfer.
23790Sstevel@tonic-gate 	 */
23800Sstevel@tonic-gate 	ret = conf->pc_prov->pc_res_xfer(src, tgt, size);
23810Sstevel@tonic-gate 	/*
23820Sstevel@tonic-gate 	 * Modify the sizes of the resource sets if the process was
23830Sstevel@tonic-gate 	 * successful
23840Sstevel@tonic-gate 	 */
23850Sstevel@tonic-gate 	if (ret == PO_SUCCESS) {
23860Sstevel@tonic-gate 		pool_value_t val = POOL_VALUE_INITIALIZER;
23870Sstevel@tonic-gate 
23880Sstevel@tonic-gate 		src_size -= size;
23890Sstevel@tonic-gate 		tgt_size += size;
23900Sstevel@tonic-gate 		pool_value_set_uint64(&val, src_size);
23910Sstevel@tonic-gate 		(void) pool_put_any_ns_property(TO_ELEM(src), c_size_prop,
23920Sstevel@tonic-gate 		    &val);
23930Sstevel@tonic-gate 		pool_value_set_uint64(&val, tgt_size);
23940Sstevel@tonic-gate 		(void) pool_put_any_ns_property(TO_ELEM(tgt), c_size_prop,
23950Sstevel@tonic-gate 		    &val);
23960Sstevel@tonic-gate 	}
23970Sstevel@tonic-gate 	return (ret);
23980Sstevel@tonic-gate }
23990Sstevel@tonic-gate 
24000Sstevel@tonic-gate /*
24010Sstevel@tonic-gate  * Transfer resource components from one resource set to another.
24020Sstevel@tonic-gate  */
24030Sstevel@tonic-gate int
24040Sstevel@tonic-gate pool_resource_xtransfer(pool_conf_t *conf, pool_resource_t *src,
24050Sstevel@tonic-gate     pool_resource_t *tgt,
24060Sstevel@tonic-gate     pool_component_t **rl)
24070Sstevel@tonic-gate {
24080Sstevel@tonic-gate 	int i;
24090Sstevel@tonic-gate 	uint64_t src_size;
24100Sstevel@tonic-gate 	uint64_t tgt_size;
24110Sstevel@tonic-gate 	uint64_t size;
24120Sstevel@tonic-gate 	int ret;
24130Sstevel@tonic-gate 
24140Sstevel@tonic-gate 	/*
24150Sstevel@tonic-gate 	 * Make sure the components are all contained in 'src'. This
24160Sstevel@tonic-gate 	 * processing must be done before setup_transfer so that size
24170Sstevel@tonic-gate 	 * is known.
24180Sstevel@tonic-gate 	 */
24190Sstevel@tonic-gate 	for (i = 0; rl[i] != NULL; i++) {
24200Sstevel@tonic-gate #ifdef DEBUG
24210Sstevel@tonic-gate 		dprintf("resource xtransfer\n");
24220Sstevel@tonic-gate 		dprintf("in conf %s\n", pool_conf_location(conf));
24230Sstevel@tonic-gate 		dprintf("transferring component\n");
24240Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(rl[i]));
24250Sstevel@tonic-gate 		dprintf("from\n");
24260Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(src));
24270Sstevel@tonic-gate 		dprintf("to\n");
24280Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(tgt));
24290Sstevel@tonic-gate #endif	/* DEBUG */
24300Sstevel@tonic-gate 
24310Sstevel@tonic-gate 		if (pool_get_owning_resource(conf, rl[i]) != src) {
24320Sstevel@tonic-gate 			pool_seterror(POE_BADPARAM);
24330Sstevel@tonic-gate 			return (PO_FAIL);
24340Sstevel@tonic-gate 		}
24350Sstevel@tonic-gate 	}
24360Sstevel@tonic-gate 
24370Sstevel@tonic-gate 	size = (uint64_t)i;
24380Sstevel@tonic-gate 
24390Sstevel@tonic-gate 	if ((ret = setup_transfer(conf, src, tgt, size, &src_size, &tgt_size))
24400Sstevel@tonic-gate 	    != XFER_CONTINUE)
24410Sstevel@tonic-gate 		return (ret);
24420Sstevel@tonic-gate 
24430Sstevel@tonic-gate 	ret = conf->pc_prov->pc_res_xxfer(src, tgt, rl);
24440Sstevel@tonic-gate 	/*
24450Sstevel@tonic-gate 	 * Modify the sizes of the resource sets if the process was
24460Sstevel@tonic-gate 	 * successful
24470Sstevel@tonic-gate 	 */
24480Sstevel@tonic-gate 	if (ret == PO_SUCCESS) {
24490Sstevel@tonic-gate 		pool_value_t val = POOL_VALUE_INITIALIZER;
24500Sstevel@tonic-gate 
24510Sstevel@tonic-gate #ifdef DEBUG
24520Sstevel@tonic-gate 		dprintf("src_size %llu\n", src_size);
24530Sstevel@tonic-gate 		dprintf("tgt_size %llu\n", tgt_size);
24540Sstevel@tonic-gate 		dprintf("size %llu\n", size);
24550Sstevel@tonic-gate #endif	/* DEBUG */
24560Sstevel@tonic-gate 		src_size -= size;
24570Sstevel@tonic-gate 		tgt_size += size;
24580Sstevel@tonic-gate 		pool_value_set_uint64(&val, src_size);
24590Sstevel@tonic-gate 		(void) pool_put_any_ns_property(TO_ELEM(src), c_size_prop,
24600Sstevel@tonic-gate 		    &val);
24610Sstevel@tonic-gate 		pool_value_set_uint64(&val, tgt_size);
24620Sstevel@tonic-gate 		(void) pool_put_any_ns_property(TO_ELEM(tgt), c_size_prop,
24630Sstevel@tonic-gate 		    &val);
24640Sstevel@tonic-gate 	}
24650Sstevel@tonic-gate 	return (ret);
24660Sstevel@tonic-gate }
24670Sstevel@tonic-gate 
24680Sstevel@tonic-gate /*
24690Sstevel@tonic-gate  * Find the owning resource for a resource component.
24700Sstevel@tonic-gate  */
24710Sstevel@tonic-gate pool_resource_t *
24720Sstevel@tonic-gate pool_get_owning_resource(const pool_conf_t *conf, const pool_component_t *comp)
24730Sstevel@tonic-gate {
24740Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
24750Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
24760Sstevel@tonic-gate 		return (NULL);
24770Sstevel@tonic-gate 	}
24780Sstevel@tonic-gate 	return (pool_elem_res(pool_get_container(TO_ELEM(comp))));
24790Sstevel@tonic-gate }
24800Sstevel@tonic-gate 
24810Sstevel@tonic-gate /*
24820Sstevel@tonic-gate  * pool_get_container() returns the container of pc.
24830Sstevel@tonic-gate  */
24840Sstevel@tonic-gate pool_elem_t *
24850Sstevel@tonic-gate pool_get_container(const pool_elem_t *pc)
24860Sstevel@tonic-gate {
24870Sstevel@tonic-gate 	return (pc->pe_get_container(pc));
24880Sstevel@tonic-gate }
24890Sstevel@tonic-gate 
24900Sstevel@tonic-gate /*
24910Sstevel@tonic-gate  * pool_set_container() moves pc so that it is contained by pp.
24920Sstevel@tonic-gate  *
24930Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
24940Sstevel@tonic-gate  */
24950Sstevel@tonic-gate int
24960Sstevel@tonic-gate pool_set_container(pool_elem_t *pp, pool_elem_t *pc)
24970Sstevel@tonic-gate {
24980Sstevel@tonic-gate 	return (pc->pe_set_container(pp, pc));
24990Sstevel@tonic-gate }
25000Sstevel@tonic-gate 
25010Sstevel@tonic-gate /*
25020Sstevel@tonic-gate  * Conversion routines for converting to and from elem and it's various
25030Sstevel@tonic-gate  * subtypes of system, pool, res and comp.
25040Sstevel@tonic-gate  */
25050Sstevel@tonic-gate pool_elem_t *
25060Sstevel@tonic-gate pool_system_elem(const pool_system_t *ph)
25070Sstevel@tonic-gate {
25080Sstevel@tonic-gate 	return ((pool_elem_t *)ph);
25090Sstevel@tonic-gate }
25100Sstevel@tonic-gate 
25110Sstevel@tonic-gate pool_elem_t *
25120Sstevel@tonic-gate pool_conf_to_elem(const pool_conf_t *conf)
25130Sstevel@tonic-gate {
25140Sstevel@tonic-gate 	pool_system_t *sys;
25150Sstevel@tonic-gate 
25160Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25170Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25180Sstevel@tonic-gate 		return (NULL);
25190Sstevel@tonic-gate 	}
25200Sstevel@tonic-gate 	if ((sys = pool_conf_system(conf)) == NULL) {
25210Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25220Sstevel@tonic-gate 		return (NULL);
25230Sstevel@tonic-gate 	}
25240Sstevel@tonic-gate 	return (pool_system_elem(sys));
25250Sstevel@tonic-gate }
25260Sstevel@tonic-gate 
25270Sstevel@tonic-gate pool_elem_t *
25280Sstevel@tonic-gate pool_to_elem(const pool_conf_t *conf, const pool_t *pp)
25290Sstevel@tonic-gate {
25300Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25310Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25320Sstevel@tonic-gate 		return (NULL);
25330Sstevel@tonic-gate 	}
25340Sstevel@tonic-gate 	return ((pool_elem_t *)pp);
25350Sstevel@tonic-gate }
25360Sstevel@tonic-gate 
25370Sstevel@tonic-gate pool_elem_t *
25380Sstevel@tonic-gate pool_resource_to_elem(const pool_conf_t *conf, const pool_resource_t *prs)
25390Sstevel@tonic-gate {
25400Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25410Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25420Sstevel@tonic-gate 		return (NULL);
25430Sstevel@tonic-gate 	}
25440Sstevel@tonic-gate 	return ((pool_elem_t *)prs);
25450Sstevel@tonic-gate }
25460Sstevel@tonic-gate 
25470Sstevel@tonic-gate pool_elem_t *
25480Sstevel@tonic-gate pool_component_to_elem(const pool_conf_t *conf, const pool_component_t *pr)
25490Sstevel@tonic-gate {
25500Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25510Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25520Sstevel@tonic-gate 		return (NULL);
25530Sstevel@tonic-gate 	}
25540Sstevel@tonic-gate 	return ((pool_elem_t *)pr);
25550Sstevel@tonic-gate }
25560Sstevel@tonic-gate 
25570Sstevel@tonic-gate /*
25580Sstevel@tonic-gate  * Walk all the pools of the configuration calling the user supplied function
25590Sstevel@tonic-gate  * as long as the user function continues to return PO_TRUE
25600Sstevel@tonic-gate  */
25610Sstevel@tonic-gate int
25620Sstevel@tonic-gate pool_walk_pools(pool_conf_t *conf, void *arg,
25630Sstevel@tonic-gate     int (*callback)(pool_conf_t *conf, pool_t *pool, void *arg))
25640Sstevel@tonic-gate {
25650Sstevel@tonic-gate 	pool_t **rs;
25660Sstevel@tonic-gate 	int i;
25670Sstevel@tonic-gate 	uint_t size;
25680Sstevel@tonic-gate 	int error = PO_SUCCESS;
25690Sstevel@tonic-gate 
25700Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25710Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25720Sstevel@tonic-gate 		return (PO_FAIL);
25730Sstevel@tonic-gate 	}
25740Sstevel@tonic-gate 
25750Sstevel@tonic-gate 	if ((rs = pool_query_pools(conf, &size, NULL)) == NULL) /* None */
25760Sstevel@tonic-gate 		return (PO_SUCCESS);
25770Sstevel@tonic-gate 	for (i = 0; i < size; i++)
25780Sstevel@tonic-gate 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
25790Sstevel@tonic-gate 			error = PO_FAIL;
25800Sstevel@tonic-gate 			break;
25810Sstevel@tonic-gate 		}
25820Sstevel@tonic-gate 	free(rs);
25830Sstevel@tonic-gate 	return (error);
25840Sstevel@tonic-gate }
25850Sstevel@tonic-gate 
25860Sstevel@tonic-gate /*
25870Sstevel@tonic-gate  * Walk all the comp of the res calling the user supplied function
25880Sstevel@tonic-gate  * as long as the user function continues to return PO_TRUE
25890Sstevel@tonic-gate  */
25900Sstevel@tonic-gate int
25910Sstevel@tonic-gate pool_walk_components(pool_conf_t *conf, pool_resource_t *prs, void *arg,
25920Sstevel@tonic-gate     int (*callback)(pool_conf_t *conf, pool_component_t *pr, void *arg))
25930Sstevel@tonic-gate {
25940Sstevel@tonic-gate 	pool_component_t **rs;
25950Sstevel@tonic-gate 	int i;
25960Sstevel@tonic-gate 	uint_t size;
25970Sstevel@tonic-gate 	int error = PO_SUCCESS;
25980Sstevel@tonic-gate 
25990Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
26000Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
26010Sstevel@tonic-gate 		return (PO_FAIL);
26020Sstevel@tonic-gate 	}
26030Sstevel@tonic-gate 
26040Sstevel@tonic-gate 	if ((rs = pool_query_resource_components(conf, prs, &size, NULL)) ==
26050Sstevel@tonic-gate 	    NULL)
26060Sstevel@tonic-gate 		return (PO_SUCCESS); /* None */
26070Sstevel@tonic-gate 	for (i = 0; i < size; i++)
26080Sstevel@tonic-gate 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
26090Sstevel@tonic-gate 			error = PO_FAIL;
26100Sstevel@tonic-gate 			break;
26110Sstevel@tonic-gate 		}
26120Sstevel@tonic-gate 	free(rs);
26130Sstevel@tonic-gate 	return (error);
26140Sstevel@tonic-gate }
26150Sstevel@tonic-gate 
26160Sstevel@tonic-gate /*
26170Sstevel@tonic-gate  * Return an array of all matching res for the supplied pool.
26180Sstevel@tonic-gate  */
26190Sstevel@tonic-gate pool_resource_t **
26200Sstevel@tonic-gate pool_query_pool_resources(const pool_conf_t *conf, const pool_t *pp,
26210Sstevel@tonic-gate     uint_t *size, pool_value_t **props)
26220Sstevel@tonic-gate {
26230Sstevel@tonic-gate 	pool_result_set_t *rs;
26240Sstevel@tonic-gate 	pool_elem_t *pe;
26250Sstevel@tonic-gate 	pool_resource_t **result = NULL;
26260Sstevel@tonic-gate 	int i = 0;
26270Sstevel@tonic-gate 
26280Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
26290Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
26300Sstevel@tonic-gate 		return (NULL);
26310Sstevel@tonic-gate 	}
26320Sstevel@tonic-gate 
26330Sstevel@tonic-gate 	pe = TO_ELEM(pp);
26340Sstevel@tonic-gate 
26350Sstevel@tonic-gate 	rs = pool_exec_query(conf, pe, "res", PEC_QRY_RES, props);
26360Sstevel@tonic-gate 	if (rs == NULL) {
26370Sstevel@tonic-gate 		return (NULL);
26380Sstevel@tonic-gate 	}
26390Sstevel@tonic-gate 	if ((*size = pool_rs_count(rs)) == 0) {
26400Sstevel@tonic-gate 		(void) pool_rs_close(rs);
26410Sstevel@tonic-gate 		return (NULL);
26420Sstevel@tonic-gate 	}
26430Sstevel@tonic-gate 	if ((result = malloc(sizeof (pool_resource_t *) * (*size + 1)))
26440Sstevel@tonic-gate 	    == NULL) {
26450Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
26460Sstevel@tonic-gate 		(void) pool_rs_close(rs);
26470Sstevel@tonic-gate 		return (NULL);
26480Sstevel@tonic-gate 	}
26490Sstevel@tonic-gate 	(void) memset(result, 0, sizeof (pool_resource_t *) * (*size + 1));
26500Sstevel@tonic-gate 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
26510Sstevel@tonic-gate 		if (pool_elem_class(pe) != PEC_RES_COMP &&
26520Sstevel@tonic-gate 		    pool_elem_class(pe) != PEC_RES_AGG) {
26530Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
26540Sstevel@tonic-gate 			free(result);
26550Sstevel@tonic-gate 			(void) pool_rs_close(rs);
26560Sstevel@tonic-gate 			return (NULL);
26570Sstevel@tonic-gate 		}
26580Sstevel@tonic-gate 		result[i++] = pool_elem_res(pe);
26590Sstevel@tonic-gate 	}
26600Sstevel@tonic-gate 	(void) pool_rs_close(rs);
26610Sstevel@tonic-gate 	return (result);
26620Sstevel@tonic-gate }
26630Sstevel@tonic-gate 
26640Sstevel@tonic-gate /*
26650Sstevel@tonic-gate  * Walk all the res of the pool calling the user supplied function
26660Sstevel@tonic-gate  * as long as the user function continues to return PO_TRUE
26670Sstevel@tonic-gate  */
26680Sstevel@tonic-gate int
26690Sstevel@tonic-gate pool_walk_resources(pool_conf_t *conf, pool_t *pp, void *arg,
26700Sstevel@tonic-gate     int (*callback)(pool_conf_t *, pool_resource_t *, void *))
26710Sstevel@tonic-gate {
26720Sstevel@tonic-gate 	pool_resource_t **rs;
26730Sstevel@tonic-gate 	int i;
26740Sstevel@tonic-gate 	uint_t size;
26750Sstevel@tonic-gate 	int error = PO_SUCCESS;
26760Sstevel@tonic-gate 
26770Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
26780Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
26790Sstevel@tonic-gate 		return (PO_FAIL);
26800Sstevel@tonic-gate 	}
26810Sstevel@tonic-gate 	if ((rs = pool_query_pool_resources(conf, pp, &size, NULL)) == NULL)
26820Sstevel@tonic-gate 		return (PO_SUCCESS); /* None */
26830Sstevel@tonic-gate 	for (i = 0; i < size; i++)
26840Sstevel@tonic-gate 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
26850Sstevel@tonic-gate 			error = PO_FAIL;
26860Sstevel@tonic-gate 			break;
26870Sstevel@tonic-gate 		}
26880Sstevel@tonic-gate 	free(rs);
26890Sstevel@tonic-gate 	return (error);
26900Sstevel@tonic-gate }
26910Sstevel@tonic-gate 
26920Sstevel@tonic-gate /*
26930Sstevel@tonic-gate  * Return a result set of all comp for the supplied res.
26940Sstevel@tonic-gate  */
26950Sstevel@tonic-gate pool_component_t **
26960Sstevel@tonic-gate pool_query_resource_components(const pool_conf_t *conf,
26970Sstevel@tonic-gate     const pool_resource_t *prs, uint_t *size, pool_value_t **props)
26980Sstevel@tonic-gate {
26990Sstevel@tonic-gate 	pool_result_set_t *rs;
27000Sstevel@tonic-gate 	pool_elem_t *pe;
27010Sstevel@tonic-gate 	pool_component_t **result = NULL;
27020Sstevel@tonic-gate 	int i = 0;
27030Sstevel@tonic-gate 
27040Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
27050Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
27060Sstevel@tonic-gate 		return (NULL);
27070Sstevel@tonic-gate 	}
27080Sstevel@tonic-gate 	pe = TO_ELEM(prs);
27090Sstevel@tonic-gate 
27100Sstevel@tonic-gate 	rs = pool_exec_query(conf, pe, NULL, PEC_QRY_COMP, props);
27110Sstevel@tonic-gate 	if (rs == NULL) {
27120Sstevel@tonic-gate 		return (NULL);
27130Sstevel@tonic-gate 	}
27140Sstevel@tonic-gate 	if ((*size = pool_rs_count(rs)) == 0) {
27150Sstevel@tonic-gate 		(void) pool_rs_close(rs);
27160Sstevel@tonic-gate 		return (NULL);
27170Sstevel@tonic-gate 	}
27180Sstevel@tonic-gate 	if ((result = malloc(sizeof (pool_component_t *) * (*size + 1)))
27190Sstevel@tonic-gate 	    == NULL) {
27200Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
27210Sstevel@tonic-gate 		(void) pool_rs_close(rs);
27220Sstevel@tonic-gate 		return (NULL);
27230Sstevel@tonic-gate 	}
27240Sstevel@tonic-gate 	(void) memset(result, 0, sizeof (pool_component_t *) * (*size + 1));
27250Sstevel@tonic-gate 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
27260Sstevel@tonic-gate 		if (pool_elem_class(pe) != PEC_COMP) {
27270Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
27280Sstevel@tonic-gate 			free(result);
27290Sstevel@tonic-gate 			(void) pool_rs_close(rs);
27300Sstevel@tonic-gate 			return (NULL);
27310Sstevel@tonic-gate 		}
27320Sstevel@tonic-gate 		result[i++] = pool_elem_comp(pe);
27330Sstevel@tonic-gate 	}
27340Sstevel@tonic-gate 	(void) pool_rs_close(rs);
27350Sstevel@tonic-gate 	return (result);
27360Sstevel@tonic-gate }
27370Sstevel@tonic-gate 
27380Sstevel@tonic-gate /*
27390Sstevel@tonic-gate  * pool_version() returns the version of this library, depending on the supplied
27400Sstevel@tonic-gate  * parameter.
27410Sstevel@tonic-gate  *
27420Sstevel@tonic-gate  * Returns: library version depening on the supplied ver parameter.
27430Sstevel@tonic-gate  */
27440Sstevel@tonic-gate uint_t
27450Sstevel@tonic-gate pool_version(uint_t ver)
27460Sstevel@tonic-gate {
27470Sstevel@tonic-gate 	switch (ver) {
27480Sstevel@tonic-gate 	case POOL_VER_NONE:
27490Sstevel@tonic-gate 		break;
27500Sstevel@tonic-gate 	case POOL_VER_CURRENT:
27510Sstevel@tonic-gate 		pool_workver = ver;
27520Sstevel@tonic-gate 		break;
27530Sstevel@tonic-gate 	default:
27540Sstevel@tonic-gate 		return (POOL_VER_NONE);
27550Sstevel@tonic-gate 	}
27560Sstevel@tonic-gate 	return (pool_workver);
27570Sstevel@tonic-gate }
27580Sstevel@tonic-gate 
27590Sstevel@tonic-gate /*
27600Sstevel@tonic-gate  * pool_associate() associates the supplied resource to the supplied pool.
27610Sstevel@tonic-gate  *
27620Sstevel@tonic-gate  * Returns: PO_SUCCESS/PO_FAIL
27630Sstevel@tonic-gate  */
27640Sstevel@tonic-gate int
27650Sstevel@tonic-gate pool_associate(pool_conf_t *conf, pool_t *pool, const pool_resource_t *res)
27660Sstevel@tonic-gate {
27670Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
27680Sstevel@tonic-gate 		return (PO_FAIL);
27690Sstevel@tonic-gate 
27700Sstevel@tonic-gate 	return (pool->pp_associate(pool, res));
27710Sstevel@tonic-gate }
27720Sstevel@tonic-gate 
27730Sstevel@tonic-gate /*
27740Sstevel@tonic-gate  * pool_dissociate() dissociates the supplied resource from the supplied pool.
27750Sstevel@tonic-gate  *
27760Sstevel@tonic-gate  * Returns: PO_SUCCESS/PO_FAIL
27770Sstevel@tonic-gate  */
27780Sstevel@tonic-gate int
27790Sstevel@tonic-gate pool_dissociate(pool_conf_t *conf, pool_t *pool, const pool_resource_t *res)
27800Sstevel@tonic-gate {
27810Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
27820Sstevel@tonic-gate 		return (PO_FAIL);
27830Sstevel@tonic-gate 
27840Sstevel@tonic-gate 	if (elem_is_default(TO_ELEM(res)))
27850Sstevel@tonic-gate 		return (PO_SUCCESS);
27860Sstevel@tonic-gate 	return (pool->pp_dissociate(pool, res));
27870Sstevel@tonic-gate }
27880Sstevel@tonic-gate 
27890Sstevel@tonic-gate /*
27900Sstevel@tonic-gate  * Compare two elements for purposes of ordering.
27910Sstevel@tonic-gate  * Return:
27920Sstevel@tonic-gate  *	< 0 if e1 is "before" e2
27930Sstevel@tonic-gate  *	0 if e1 "equals" e2
27940Sstevel@tonic-gate  *	> 0 if e1 comes after e2
27950Sstevel@tonic-gate  */
27960Sstevel@tonic-gate int
27970Sstevel@tonic-gate pool_elem_compare_name(const pool_elem_t *e1, const pool_elem_t *e2)
27980Sstevel@tonic-gate {
27990Sstevel@tonic-gate 	char *name1, *name2;
28000Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
28010Sstevel@tonic-gate 	int retval;
28020Sstevel@tonic-gate 
28030Sstevel@tonic-gate 	/*
28040Sstevel@tonic-gate 	 * We may be asked to compare two elements from different classes.
28050Sstevel@tonic-gate 	 * They are different so return (1).
28060Sstevel@tonic-gate 	 */
28070Sstevel@tonic-gate 	if (pool_elem_same_class(e1, e2) != PO_TRUE)
28080Sstevel@tonic-gate 		return (1);
28090Sstevel@tonic-gate 
28100Sstevel@tonic-gate 	/*
28110Sstevel@tonic-gate 	 * If the class is PEC_SYSTEM, always match them
28120Sstevel@tonic-gate 	 */
28130Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_SYSTEM)
28140Sstevel@tonic-gate 		return (0);
28150Sstevel@tonic-gate 
28160Sstevel@tonic-gate 	/*
28170Sstevel@tonic-gate 	 * If we are going to compare components, then use sys_id
28180Sstevel@tonic-gate 	 */
28190Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_COMP) {
28200Sstevel@tonic-gate 		int64_t sys_id1, sys_id2;
28210Sstevel@tonic-gate 
28220Sstevel@tonic-gate 		if (pool_get_ns_property(e1, c_sys_prop, &val) == POC_INVAL) {
28230Sstevel@tonic-gate 			return (-1);
28240Sstevel@tonic-gate 		}
28250Sstevel@tonic-gate 		(void) pool_value_get_int64(&val, &sys_id1);
28260Sstevel@tonic-gate 		if (pool_get_ns_property(e2, c_sys_prop, &val) == POC_INVAL) {
28270Sstevel@tonic-gate 			return (-1);
28280Sstevel@tonic-gate 		}
28290Sstevel@tonic-gate 		(void) pool_value_get_int64(&val, &sys_id2);
28300Sstevel@tonic-gate 		retval = (sys_id1 - sys_id2);
28310Sstevel@tonic-gate 	} else {
28320Sstevel@tonic-gate 		if (pool_get_ns_property(e1, "name", &val) == POC_INVAL) {
28330Sstevel@tonic-gate 			return (-1);
28340Sstevel@tonic-gate 		}
28350Sstevel@tonic-gate 		(void) pool_value_get_string(&val, (const char **)&name1);
28360Sstevel@tonic-gate 		if ((name1 = strdup(name1)) == NULL) {
28370Sstevel@tonic-gate 			return (-1);
28380Sstevel@tonic-gate 		}
28390Sstevel@tonic-gate 
28400Sstevel@tonic-gate 		if (pool_get_ns_property(e2, "name", &val) == POC_INVAL) {
28410Sstevel@tonic-gate 			return (-1);
28420Sstevel@tonic-gate 		}
28430Sstevel@tonic-gate 
28440Sstevel@tonic-gate 		(void) pool_value_get_string(&val, (const char **)&name2);
28450Sstevel@tonic-gate 		retval = strcmp(name1, name2);
28460Sstevel@tonic-gate 		free(name1);
28470Sstevel@tonic-gate 	}
28480Sstevel@tonic-gate 	return (retval);
28490Sstevel@tonic-gate }
28500Sstevel@tonic-gate 
28510Sstevel@tonic-gate /*
28520Sstevel@tonic-gate  * Compare two elements for purposes of ordering.
28530Sstevel@tonic-gate  * Return:
28540Sstevel@tonic-gate  *	< 0 if e1 is "before" e2
28550Sstevel@tonic-gate  *	0 if e1 "equals" e2
28560Sstevel@tonic-gate  *	> 0 if e1 comes after e2
28570Sstevel@tonic-gate  */
28580Sstevel@tonic-gate int
28590Sstevel@tonic-gate pool_elem_compare(const pool_elem_t *e1, const pool_elem_t *e2)
28600Sstevel@tonic-gate {
28610Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
28620Sstevel@tonic-gate 	int64_t sys_id1, sys_id2;
28630Sstevel@tonic-gate 
28640Sstevel@tonic-gate 	/*
28650Sstevel@tonic-gate 	 * We may be asked to compare two elements from different classes.
28660Sstevel@tonic-gate 	 * They are different so return the difference in their classes
28670Sstevel@tonic-gate 	 */
28680Sstevel@tonic-gate 	if (pool_elem_same_class(e1, e2) != PO_TRUE)
28690Sstevel@tonic-gate 		return (1);
28700Sstevel@tonic-gate 
28710Sstevel@tonic-gate 	/*
28720Sstevel@tonic-gate 	 * If the class is PEC_SYSTEM, always match them
28730Sstevel@tonic-gate 	 */
28740Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_SYSTEM)
28750Sstevel@tonic-gate 		return (0);
28760Sstevel@tonic-gate 
28770Sstevel@tonic-gate 	/*
28780Sstevel@tonic-gate 	 * Compare with sys_id
28790Sstevel@tonic-gate 	 */
28800Sstevel@tonic-gate 	if (pool_get_ns_property(e1, c_sys_prop, &val) == POC_INVAL) {
28810Sstevel@tonic-gate 		assert(!"no sys_id on e1\n");
28820Sstevel@tonic-gate 	}
28830Sstevel@tonic-gate 	(void) pool_value_get_int64(&val, &sys_id1);
28840Sstevel@tonic-gate 	if (pool_get_ns_property(e2, c_sys_prop, &val) == POC_INVAL) {
28850Sstevel@tonic-gate 		assert(!"no sys_id on e2\n");
28860Sstevel@tonic-gate 	}
28870Sstevel@tonic-gate 	(void) pool_value_get_int64(&val, &sys_id2);
28880Sstevel@tonic-gate 	return (sys_id1 - sys_id2);
28890Sstevel@tonic-gate }
28900Sstevel@tonic-gate 
28910Sstevel@tonic-gate /*
28920Sstevel@tonic-gate  * Return PO_TRUE if the supplied elems are of the same class.
28930Sstevel@tonic-gate  */
28940Sstevel@tonic-gate int
28950Sstevel@tonic-gate pool_elem_same_class(const pool_elem_t *e1, const pool_elem_t *e2)
28960Sstevel@tonic-gate {
28970Sstevel@tonic-gate 	if (pool_elem_class(e1) != pool_elem_class(e2))
28980Sstevel@tonic-gate 		return (PO_FALSE);
28990Sstevel@tonic-gate 
29000Sstevel@tonic-gate 	/*
29010Sstevel@tonic-gate 	 * Check to make sure the fundamental class of the elements match
29020Sstevel@tonic-gate 	 */
29030Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_RES_COMP ||
29040Sstevel@tonic-gate 	    pool_elem_class(e1) == PEC_RES_AGG)
29050Sstevel@tonic-gate 		if (pool_resource_elem_class(e1) !=
29060Sstevel@tonic-gate 		    pool_resource_elem_class(e2))
29070Sstevel@tonic-gate 			return (PO_FALSE);
29080Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_COMP)
29090Sstevel@tonic-gate 		if (pool_component_elem_class(e1) !=
29100Sstevel@tonic-gate 		    pool_component_elem_class(e2))
29110Sstevel@tonic-gate 			return (PO_FALSE);
29120Sstevel@tonic-gate 	return (PO_TRUE);
29130Sstevel@tonic-gate }
29140Sstevel@tonic-gate 
29150Sstevel@tonic-gate /*
29160Sstevel@tonic-gate  * pool_conf_check() checks that the configuration state isn't invalid
29170Sstevel@tonic-gate  * and that the configuration was opened for modification.
29180Sstevel@tonic-gate  */
29190Sstevel@tonic-gate int
29200Sstevel@tonic-gate pool_conf_check(const pool_conf_t *conf)
29210Sstevel@tonic-gate {
29220Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
29230Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
29240Sstevel@tonic-gate 		return (PO_FAIL);
29250Sstevel@tonic-gate 	}
29260Sstevel@tonic-gate 
29270Sstevel@tonic-gate 	if ((conf->pc_prov->pc_oflags & PO_RDWR) == 0) {
29280Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
29290Sstevel@tonic-gate 		return (PO_FAIL);
29300Sstevel@tonic-gate 	}
29310Sstevel@tonic-gate 	return (PO_SUCCESS);
29320Sstevel@tonic-gate }
2933