xref: /onnv-gate/usr/src/lib/libpool/common/pool.c (revision 3864:2ae506652d11)
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 /*
23*3864Sraf  * Copyright 2007 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>
34*3864Sraf #include <pthread.h>
350Sstevel@tonic-gate #include <synch.h>
360Sstevel@tonic-gate #include <unistd.h>
370Sstevel@tonic-gate #include <stropts.h>
380Sstevel@tonic-gate #include <fcntl.h>
390Sstevel@tonic-gate #include <note.h>
400Sstevel@tonic-gate #include <errno.h>
410Sstevel@tonic-gate #include <ctype.h>
420Sstevel@tonic-gate #include <libintl.h>
433251Ssl108498 #include <libscf.h>
440Sstevel@tonic-gate #include <pool.h>
450Sstevel@tonic-gate #include <signal.h>
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #include <sys/pool.h>
480Sstevel@tonic-gate #include <sys/priocntl.h>
490Sstevel@tonic-gate #include <sys/types.h>
500Sstevel@tonic-gate #include <sys/stat.h>
510Sstevel@tonic-gate #include <sys/wait.h>
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #include "pool_internal.h"
540Sstevel@tonic-gate #include "pool_impl.h"
550Sstevel@tonic-gate 
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate  * libpool Interface Routines
580Sstevel@tonic-gate  *
590Sstevel@tonic-gate  * pool.c implements (most of) the external interface to libpool
600Sstevel@tonic-gate  * users. Some of the interface is implemented in pool_internal.c for
610Sstevel@tonic-gate  * reasons of internal code organisation.  The core requirements for
620Sstevel@tonic-gate  * pool.c are:
630Sstevel@tonic-gate  *
640Sstevel@tonic-gate  * Data Abstraction
650Sstevel@tonic-gate  *
660Sstevel@tonic-gate  * The abstraction of the actual datastore so that no details of the
670Sstevel@tonic-gate  * underlying data representation mechanism are revealed to users of
680Sstevel@tonic-gate  * the library. For instance, the fact that we use the kernel or files
690Sstevel@tonic-gate  * to store our configurations is completely abstracted via the
700Sstevel@tonic-gate  * various libpool APIs.
710Sstevel@tonic-gate  *
720Sstevel@tonic-gate  * External Interaction
730Sstevel@tonic-gate  *
740Sstevel@tonic-gate  * libpool users manipulate configuration components via the API
750Sstevel@tonic-gate  * defined in pool.h. Most functions in this file act as interceptors,
760Sstevel@tonic-gate  * validating parameters before redirecting the request into a
770Sstevel@tonic-gate  * specific datastore implementation for the actual work to be done.
780Sstevel@tonic-gate  *
790Sstevel@tonic-gate  * These main sets of requirements have driven the design so that it
800Sstevel@tonic-gate  * is possible to replace the entire datastore type without having to
810Sstevel@tonic-gate  * modify the external (or internal provider) APIs. It is possible to
820Sstevel@tonic-gate  * modify the storage technology used by libpool by implementing a new
830Sstevel@tonic-gate  * set of datastore provider operations. Simply modify the
840Sstevel@tonic-gate  * pool_conf_open() routine to establish a new datastore as the
850Sstevel@tonic-gate  * provider for a configuration.
860Sstevel@tonic-gate  *
870Sstevel@tonic-gate  * The key components in a libpool configuration are :
880Sstevel@tonic-gate  * pool_conf_t - This represents a complete configuration instance
890Sstevel@tonic-gate  * pool_t - A pool inside a configuration
900Sstevel@tonic-gate  * pool_resource_t - A resource inside a configuration
910Sstevel@tonic-gate  * pool_component_t - A component of a resource
920Sstevel@tonic-gate  *
930Sstevel@tonic-gate  */
940Sstevel@tonic-gate 
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate  * Used to control transfer setup.
970Sstevel@tonic-gate  */
980Sstevel@tonic-gate #define	XFER_FAIL	PO_FAIL
990Sstevel@tonic-gate #define	XFER_SUCCESS	PO_SUCCESS
1000Sstevel@tonic-gate #define	XFER_CONTINUE	1
1010Sstevel@tonic-gate 
1021042Sgarypen #define	SMF_SVC_INSTANCE	"svc:/system/pools:default"
1030Sstevel@tonic-gate #define	E_ERROR		1		/* Exit status for error */
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate #ifndef	TEXT_DOMAIN
1060Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
1070Sstevel@tonic-gate #endif	/* TEXT_DOMAIN */
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate const char pool_info_location[] =  "/dev/pool";
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate  * Static data
1130Sstevel@tonic-gate  */
1140Sstevel@tonic-gate static const char static_location[] = "/etc/pooladm.conf";
1150Sstevel@tonic-gate static const char dynamic_location[] =  "/dev/poolctl";
116*3864Sraf static thread_key_t	errkey = THR_ONCE_KEY;
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 *
pool_static_location(void)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 *
pool_dynamic_location(void)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
pool_conf_status(const pool_conf_t * conf)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
pool_set_binding(const char * pool_name,idtype_t idtype,id_t id)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 *
pool_get_resource_binding(const char * sz_type,pid_t pid)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 *
pool_get_binding(pid_t pid)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
prop_buf_build_cb(pool_conf_t * UNUSED,pool_elem_t * pe,const char * name,pool_value_t * pval,void * user)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 *
pool_base_info(const pool_elem_t * pe,char_buf_t * cb,int deep)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 *
pool_info(const pool_conf_t * conf,const pool_t * pool,int deep)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 *
pool_resource_info(const pool_conf_t * conf,const pool_resource_t * res,int deep)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 *
pool_component_info(const pool_conf_t * conf,const pool_component_t * comp,int deep)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 *
pool_conf_info(const pool_conf_t * conf,int deep)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
pool_seterror(int errval)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 	}
613*3864Sraf 	(void) thr_keycreate_once(&errkey, 0);
6140Sstevel@tonic-gate 	(void) thr_setspecific(errkey, (void *)(intptr_t)errval);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate /*
6180Sstevel@tonic-gate  * Return the current value of the error code.
6190Sstevel@tonic-gate  * Returns: int error code
6200Sstevel@tonic-gate  */
6210Sstevel@tonic-gate int
pool_error(void)6220Sstevel@tonic-gate pool_error(void)
6230Sstevel@tonic-gate {
6240Sstevel@tonic-gate 	if (thr_main())
6250Sstevel@tonic-gate 		return (pool_errval);
626*3864Sraf 	if (errkey == THR_ONCE_KEY)
6270Sstevel@tonic-gate 		return (POE_OK);
628*3864Sraf 	return ((uintptr_t)pthread_getspecific(errkey));
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate /*
6320Sstevel@tonic-gate  * Return the text represenation for the current value of the error code.
6330Sstevel@tonic-gate  * Returns: const char * error string
6340Sstevel@tonic-gate  */
6350Sstevel@tonic-gate const char *
pool_strerror(int error)6360Sstevel@tonic-gate pool_strerror(int error)
6370Sstevel@tonic-gate {
6380Sstevel@tonic-gate 	char *str;
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	switch (error) {
6410Sstevel@tonic-gate 	case POE_OK:
6420Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Operation successful");
6430Sstevel@tonic-gate 		break;
6440Sstevel@tonic-gate 	case POE_BAD_PROP_TYPE:
6450Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN,
6460Sstevel@tonic-gate 		    "Attempted to retrieve the wrong property type");
6470Sstevel@tonic-gate 		break;
6480Sstevel@tonic-gate 	case POE_INVALID_CONF:
6490Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Invalid configuration");
6500Sstevel@tonic-gate 		break;
6510Sstevel@tonic-gate 	case POE_NOTSUP:
6520Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Operation is not supported");
6530Sstevel@tonic-gate 		break;
6540Sstevel@tonic-gate 	case POE_INVALID_SEARCH:
6550Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Invalid search");
6560Sstevel@tonic-gate 		break;
6570Sstevel@tonic-gate 	case POE_BADPARAM:
6580Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Bad parameter supplied");
6590Sstevel@tonic-gate 		break;
6600Sstevel@tonic-gate 	case POE_PUTPROP:
6610Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Error putting property");
6620Sstevel@tonic-gate 		break;
6630Sstevel@tonic-gate 	case POE_DATASTORE:
6640Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Pools repository error");
6650Sstevel@tonic-gate 		break;
6660Sstevel@tonic-gate 	case POE_SYSTEM:
6670Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "System error");
6680Sstevel@tonic-gate 		break;
6690Sstevel@tonic-gate 	case POE_ACCESS:
6700Sstevel@tonic-gate 		str = dgettext(TEXT_DOMAIN, "Permission denied");
6710Sstevel@tonic-gate 		break;
6720Sstevel@tonic-gate 	default:
6730Sstevel@tonic-gate 		errno = ESRCH;
6740Sstevel@tonic-gate 		str = NULL;
6750Sstevel@tonic-gate 	}
6760Sstevel@tonic-gate 	return (str);
6770Sstevel@tonic-gate }
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate int
pool_get_status(int * state)6800Sstevel@tonic-gate pool_get_status(int *state)
6810Sstevel@tonic-gate {
6820Sstevel@tonic-gate 	int fd;
6830Sstevel@tonic-gate 	pool_status_t status;
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 	if ((fd = open(pool_info_location, O_RDONLY)) < 0) {
6860Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
6870Sstevel@tonic-gate 		return (PO_FAIL);
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 	if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
6900Sstevel@tonic-gate 		(void) close(fd);
6910Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
6920Sstevel@tonic-gate 		return (PO_FAIL);
6930Sstevel@tonic-gate 	}
6940Sstevel@tonic-gate 	(void) close(fd);
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	*state = status.ps_io_state;
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	return (PO_SUCCESS);
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate int
pool_set_status(int state)7020Sstevel@tonic-gate pool_set_status(int state)
7030Sstevel@tonic-gate {
7040Sstevel@tonic-gate 	int old_state;
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 	if (pool_get_status(&old_state) != PO_SUCCESS) {
7070Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
7080Sstevel@tonic-gate 		return (PO_FAIL);
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 	if (old_state != state) {
7120Sstevel@tonic-gate 		int fd;
7130Sstevel@tonic-gate 		pool_status_t status;
7143251Ssl108498 		char *fmri;
7150Sstevel@tonic-gate 
7161042Sgarypen 		/*
7171042Sgarypen 		 * Changing the status of pools is performed by enabling
7181042Sgarypen 		 * or disabling the pools service instance. If this
7191042Sgarypen 		 * function has not been invoked by startd then we simply
7201042Sgarypen 		 * enable/disable the service and return success.
7211042Sgarypen 		 *
7221042Sgarypen 		 * There is no way to specify that state changes must be
7231042Sgarypen 		 * synchronous using the library API as yet, so we use
7241042Sgarypen 		 * the -s option provided by svcadm.
7251042Sgarypen 		 */
7263251Ssl108498 		fmri = getenv("SMF_FMRI");
7273251Ssl108498 		if (fmri == NULL) {
7281042Sgarypen 			FILE *p;
7292706Sgarypen 			char *cmd;
7302706Sgarypen 
7313251Ssl108498 			if (state != 0) {
7322706Sgarypen 				cmd = "/usr/sbin/svcadm enable -s " \
7331042Sgarypen 				    SMF_SVC_INSTANCE;
7341042Sgarypen 			} else {
7352706Sgarypen 				cmd = "/usr/sbin/svcadm disable -s " \
7361042Sgarypen 				    SMF_SVC_INSTANCE;
7372706Sgarypen 			}
7382706Sgarypen 			if ((p = popen(cmd, "wF")) == NULL || pclose(p) != 0) {
7392706Sgarypen 				pool_seterror(POE_SYSTEM);
7402706Sgarypen 				return (PO_FAIL);
7410Sstevel@tonic-gate 			}
7421042Sgarypen 			return (PO_SUCCESS);
7430Sstevel@tonic-gate 		}
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 		if ((fd = open(pool_dynamic_location(), O_RDWR | O_EXCL)) < 0) {
7460Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
7470Sstevel@tonic-gate 			return (PO_FAIL);
7480Sstevel@tonic-gate 		}
7490Sstevel@tonic-gate 
7503251Ssl108498 		/*
7513251Ssl108498 		 * If pools are being enabled/disabled by another smf service,
7523251Ssl108498 		 * enable the smf service instance.  This must be done
7533251Ssl108498 		 * asynchronously as one service cannot synchronously
7543251Ssl108498 		 * enable/disable another.
7553251Ssl108498 		 */
7563251Ssl108498 		if (strcmp(fmri, SMF_SVC_INSTANCE) != 0) {
7573251Ssl108498 			int res;
7583251Ssl108498 
7593251Ssl108498 			if (state != 0)
7603251Ssl108498 				res = smf_enable_instance(SMF_SVC_INSTANCE, 0);
7613251Ssl108498 			else
7623251Ssl108498 				res = smf_disable_instance(SMF_SVC_INSTANCE, 0);
7633251Ssl108498 
7643251Ssl108498 			if (res != 0) {
7653251Ssl108498 				(void) close(fd);
7663251Ssl108498 				pool_seterror(POE_SYSTEM);
7673251Ssl108498 				return (PO_FAIL);
7683251Ssl108498 			}
7693251Ssl108498 		}
7700Sstevel@tonic-gate 		status.ps_io_state = state;
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 		if (ioctl(fd, POOL_STATUS, &status) < 0) {
7730Sstevel@tonic-gate 			(void) close(fd);
7740Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
7750Sstevel@tonic-gate 			return (PO_FAIL);
7760Sstevel@tonic-gate 		}
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 		(void) close(fd);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	}
7810Sstevel@tonic-gate 	return (PO_SUCCESS);
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate /*
7850Sstevel@tonic-gate  * General Data Provider Independent Access Methods
7860Sstevel@tonic-gate  */
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate /*
7890Sstevel@tonic-gate  * Property manipulation code.
7900Sstevel@tonic-gate  *
7910Sstevel@tonic-gate  * The pool_(get|rm|set)_property() functions consult the plugins before
7920Sstevel@tonic-gate  * looking at the actual configuration. This allows plugins to provide
7930Sstevel@tonic-gate  * "virtual" properties that may not exist in the configuration file per se,
7940Sstevel@tonic-gate  * but behave like regular properties. This also allows plugins to reserve
7950Sstevel@tonic-gate  * certain properties as read-only, non-removable, etc.
7960Sstevel@tonic-gate  *
7970Sstevel@tonic-gate  * A negative value returned from the plugin denotes error, 0 means that the
7980Sstevel@tonic-gate  * property request should be forwarded to the backend, and 1 means the request
7990Sstevel@tonic-gate  * was satisfied by the plugin and should not be processed further.
8000Sstevel@tonic-gate  *
8010Sstevel@tonic-gate  * The (get|rm|set)_property() functions bypass the plugin layer completely,
8020Sstevel@tonic-gate  * and hence should not be generally used.
8030Sstevel@tonic-gate  */
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate /*
8060Sstevel@tonic-gate  * Return true if the string passed in matches the pattern
8070Sstevel@tonic-gate  * [A-Za-z][A-Za-z0-9,._-]*
8080Sstevel@tonic-gate  */
8090Sstevel@tonic-gate int
is_valid_name(const char * name)8100Sstevel@tonic-gate is_valid_name(const char *name)
8110Sstevel@tonic-gate {
8120Sstevel@tonic-gate 	int i;
8130Sstevel@tonic-gate 	char c;
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	if (name == NULL)
8160Sstevel@tonic-gate 		return (PO_FALSE);
8170Sstevel@tonic-gate 	if (!isalpha(name[0]))
8180Sstevel@tonic-gate 		return (PO_FALSE);
8190Sstevel@tonic-gate 	for (i = 1; (c = name[i]) != '\0'; i++) {
8200Sstevel@tonic-gate 		if (!isalnum(c) && c != ',' && c != '.' && c != '_' && c != '-')
8210Sstevel@tonic-gate 			return (PO_FALSE);
8220Sstevel@tonic-gate 	}
8230Sstevel@tonic-gate 	return (PO_TRUE);
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate /*
8270Sstevel@tonic-gate  * Return true if the string passed in matches the pattern
8280Sstevel@tonic-gate  * [A-Za-z_][A-Za-z0-9,._-]*
8290Sstevel@tonic-gate  * A property name starting with a '_' is an "invisible" property that does not
8300Sstevel@tonic-gate  * show up in a property walk.
8310Sstevel@tonic-gate  */
8320Sstevel@tonic-gate int
is_valid_prop_name(const char * prop_name)8330Sstevel@tonic-gate is_valid_prop_name(const char *prop_name)
8340Sstevel@tonic-gate {
8350Sstevel@tonic-gate 	int i;
8360Sstevel@tonic-gate 	char c;
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate 	if (prop_name == NULL)
8390Sstevel@tonic-gate 		return (PO_FALSE);
8400Sstevel@tonic-gate 	if (!isalpha(prop_name[0]) && prop_name[0] != '_')
8410Sstevel@tonic-gate 		return (PO_FALSE);
8420Sstevel@tonic-gate 	for (i = 1; (c = prop_name[i]) != '\0'; i++) {
8430Sstevel@tonic-gate 		if (!isalnum(c) && c != ',' && c != '.' && c != '_' && c != '-')
8440Sstevel@tonic-gate 			return (PO_FALSE);
8450Sstevel@tonic-gate 	}
8460Sstevel@tonic-gate 	return (PO_TRUE);
8470Sstevel@tonic-gate }
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate /*
8500Sstevel@tonic-gate  * Return the specified property value.
8510Sstevel@tonic-gate  *
8520Sstevel@tonic-gate  * POC_INVAL is returned if an error is detected and the error code is updated
8530Sstevel@tonic-gate  * to indicate the cause of the error.
8540Sstevel@tonic-gate  */
8550Sstevel@tonic-gate pool_value_class_t
pool_get_property(const pool_conf_t * conf,const pool_elem_t * pe,const char * name,pool_value_t * val)8560Sstevel@tonic-gate pool_get_property(const pool_conf_t *conf, const pool_elem_t *pe,
8570Sstevel@tonic-gate     const char *name, pool_value_t *val)
8580Sstevel@tonic-gate {
8590Sstevel@tonic-gate 	const pool_prop_t *prop_info;
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
8620Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
8630Sstevel@tonic-gate 		return (POC_INVAL);
8640Sstevel@tonic-gate 	}
8650Sstevel@tonic-gate 	if (pool_value_set_name(val, name) != PO_SUCCESS) {
8660Sstevel@tonic-gate 		return (POC_INVAL);
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 	/*
8690Sstevel@tonic-gate 	 * Check to see if this is a property we are managing. If it
8700Sstevel@tonic-gate 	 * is and it has an interceptor installed for property
8710Sstevel@tonic-gate 	 * retrieval, use it.
8720Sstevel@tonic-gate 	 */
8730Sstevel@tonic-gate 	if ((prop_info = provider_get_prop(pe, name)) != NULL &&
8740Sstevel@tonic-gate 	    prop_info->pp_op.ppo_get_value != NULL) {
8750Sstevel@tonic-gate 		if (prop_info->pp_op.ppo_get_value(pe, val) == PO_FAIL)
8760Sstevel@tonic-gate 			return (POC_INVAL);
8770Sstevel@tonic-gate 		else
8780Sstevel@tonic-gate 			return (pool_value_get_type(val));
8790Sstevel@tonic-gate 	}
8800Sstevel@tonic-gate 	return (pe->pe_get_prop(pe, name, val));
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate 
8830Sstevel@tonic-gate /*
8840Sstevel@tonic-gate  * Return the specified property value with the namespace prepended.
8850Sstevel@tonic-gate  * e.g. If this function is used to get the property "name" on a pool, it will
8860Sstevel@tonic-gate  * attempt to retrieve "pool.name".
8870Sstevel@tonic-gate  *
8880Sstevel@tonic-gate  * POC_INVAL is returned if an error is detected and the error code is updated
8890Sstevel@tonic-gate  * to indicate the cause of the error.
8900Sstevel@tonic-gate  */
8910Sstevel@tonic-gate pool_value_class_t
pool_get_ns_property(const pool_elem_t * pe,const char * name,pool_value_t * val)8920Sstevel@tonic-gate pool_get_ns_property(const pool_elem_t *pe, const char *name, pool_value_t *val)
8930Sstevel@tonic-gate {
8940Sstevel@tonic-gate 	int ret;
8950Sstevel@tonic-gate 	char_buf_t *cb;
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
8980Sstevel@tonic-gate 		return (POC_INVAL);
8990Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
9000Sstevel@tonic-gate 	    PO_FAIL) {
9010Sstevel@tonic-gate 		free_char_buf(cb);
9020Sstevel@tonic-gate 		return (POC_INVAL);
9030Sstevel@tonic-gate 	}
9040Sstevel@tonic-gate 	ret = pool_get_property(TO_CONF(pe), pe, cb->cb_buf, val);
9050Sstevel@tonic-gate 	free_char_buf(cb);
9060Sstevel@tonic-gate 	return (ret);
9070Sstevel@tonic-gate }
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate /*
9100Sstevel@tonic-gate  * Update the specified property value.
9110Sstevel@tonic-gate  *
9120Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
9130Sstevel@tonic-gate  * to indicate the cause of the error.
9140Sstevel@tonic-gate  */
9150Sstevel@tonic-gate int
pool_put_property(pool_conf_t * conf,pool_elem_t * pe,const char * name,const pool_value_t * val)9160Sstevel@tonic-gate pool_put_property(pool_conf_t *conf, pool_elem_t *pe, const char *name,
9170Sstevel@tonic-gate     const pool_value_t *val)
9180Sstevel@tonic-gate {
9190Sstevel@tonic-gate 	const pool_prop_t *prop_info;
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
9220Sstevel@tonic-gate 		return (PO_FAIL);
9230Sstevel@tonic-gate 
9240Sstevel@tonic-gate 	if (TO_CONF(pe) != conf) {
9250Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
9260Sstevel@tonic-gate 		return (NULL);
9270Sstevel@tonic-gate 	}
9280Sstevel@tonic-gate 
9293247Sgjelinek 	/* Don't allow (re)setting of the "temporary" property */
9303247Sgjelinek 	if (!is_valid_prop_name(name) || strstr(name, ".temporary") != NULL) {
9310Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
9320Sstevel@tonic-gate 		return (PO_FAIL);
9330Sstevel@tonic-gate 	}
9343247Sgjelinek 
9353247Sgjelinek 	/* Don't allow rename of temporary pools/resources */
9363247Sgjelinek 	if (strstr(name, ".name") != NULL && elem_is_tmp(pe)) {
9373247Sgjelinek 		boolean_t rename = B_TRUE;
9383247Sgjelinek 		pool_value_t *pv = pool_value_alloc();
9393247Sgjelinek 
9403247Sgjelinek 		if (pe->pe_get_prop(pe, name, pv) != POC_INVAL) {
9413247Sgjelinek 			const char *s1 = NULL;
9423247Sgjelinek 			const char *s2 = NULL;
9433247Sgjelinek 
9443247Sgjelinek 			(void) pool_value_get_string(pv, &s1);
9453247Sgjelinek 			(void) pool_value_get_string(val, &s2);
9463247Sgjelinek 			if (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0)
9473247Sgjelinek 				rename = B_FALSE;
9483247Sgjelinek 		}
9493247Sgjelinek 		pool_value_free(pv);
9503247Sgjelinek 
9513247Sgjelinek 		if (rename) {
9523247Sgjelinek 			pool_seterror(POE_BADPARAM);
9533247Sgjelinek 			return (PO_FAIL);
9543247Sgjelinek 		}
9553247Sgjelinek 	}
9563247Sgjelinek 
9570Sstevel@tonic-gate 	/*
9580Sstevel@tonic-gate 	 * Check to see if this is a property we are managing. If it is,
9590Sstevel@tonic-gate 	 * ensure that we are happy with what the user is doing.
9600Sstevel@tonic-gate 	 */
9610Sstevel@tonic-gate 	if ((prop_info = provider_get_prop(pe, name)) != NULL) {
9620Sstevel@tonic-gate 		if (prop_is_readonly(prop_info) == PO_TRUE) {
9630Sstevel@tonic-gate 			pool_seterror(POE_BADPARAM);
9640Sstevel@tonic-gate 			return (PO_FAIL);
9650Sstevel@tonic-gate 		}
9660Sstevel@tonic-gate 		if (prop_info->pp_op.ppo_set_value &&
9670Sstevel@tonic-gate 		    prop_info->pp_op.ppo_set_value(pe, val) == PO_FAIL)
9680Sstevel@tonic-gate 			return (PO_FAIL);
9690Sstevel@tonic-gate 	}
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate 	return (pe->pe_put_prop(pe, name, val));
9720Sstevel@tonic-gate }
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate /*
9753247Sgjelinek  * Set temporary property to flag as a temporary element.
9763247Sgjelinek  *
9773247Sgjelinek  * PO_FAIL is returned if an error is detected and the error code is updated
9783247Sgjelinek  * to indicate the cause of the error.
9793247Sgjelinek  */
9803247Sgjelinek int
pool_set_temporary(pool_conf_t * conf,pool_elem_t * pe)9813247Sgjelinek pool_set_temporary(pool_conf_t *conf, pool_elem_t *pe)
9823247Sgjelinek {
9833247Sgjelinek 	int res;
9843247Sgjelinek 	char name[128];
9853247Sgjelinek 	pool_value_t *val;
9863247Sgjelinek 
9873247Sgjelinek 	if (pool_conf_check(conf) != PO_SUCCESS)
9883247Sgjelinek 		return (PO_FAIL);
9893247Sgjelinek 
9903247Sgjelinek 	if (TO_CONF(pe) != conf) {
9913247Sgjelinek 		pool_seterror(POE_BADPARAM);
9923247Sgjelinek 		return (PO_FAIL);
9933247Sgjelinek 	}
9943247Sgjelinek 
9953247Sgjelinek 	/* create property name based on element type */
9963247Sgjelinek 	if (snprintf(name, sizeof (name), "%s.temporary",
9973247Sgjelinek 	    pool_elem_class_string(pe)) > sizeof (name)) {
9983247Sgjelinek 		pool_seterror(POE_SYSTEM);
9993247Sgjelinek 		return (PO_FAIL);
10003247Sgjelinek 	}
10013247Sgjelinek 
10023247Sgjelinek 	if ((val = pool_value_alloc()) == NULL)
10033247Sgjelinek 		return (PO_FAIL);
10043247Sgjelinek 
10053247Sgjelinek 	pool_value_set_bool(val, (uchar_t)1);
10063247Sgjelinek 
10073247Sgjelinek 	res = pe->pe_put_prop(pe, name, val);
10083247Sgjelinek 
10093247Sgjelinek 	pool_value_free(val);
10103247Sgjelinek 
10113247Sgjelinek 	return (res);
10123247Sgjelinek }
10133247Sgjelinek 
10143247Sgjelinek /*
10150Sstevel@tonic-gate  * Update the specified property value with the namespace prepended.
10160Sstevel@tonic-gate  * e.g. If this function is used to update the property "name" on a pool, it
10170Sstevel@tonic-gate  * will attempt to update "pool.name".
10180Sstevel@tonic-gate  *
10190Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
10200Sstevel@tonic-gate  * to indicate the cause of the error.
10210Sstevel@tonic-gate  */
10220Sstevel@tonic-gate int
pool_put_ns_property(pool_elem_t * pe,const char * name,const pool_value_t * val)10230Sstevel@tonic-gate pool_put_ns_property(pool_elem_t *pe, const char *name,
10240Sstevel@tonic-gate     const pool_value_t *val)
10250Sstevel@tonic-gate {
10260Sstevel@tonic-gate 	char_buf_t *cb;
10270Sstevel@tonic-gate 	int ret;
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
10300Sstevel@tonic-gate 		return (PO_FAIL);
10310Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
10320Sstevel@tonic-gate 	    PO_FAIL) {
10330Sstevel@tonic-gate 		free_char_buf(cb);
10340Sstevel@tonic-gate 		return (PO_FAIL);
10350Sstevel@tonic-gate 	}
10360Sstevel@tonic-gate 	ret = pool_put_property(TO_CONF(pe), pe, cb->cb_buf, val);
10370Sstevel@tonic-gate 	free_char_buf(cb);
10380Sstevel@tonic-gate 	return (ret);
10390Sstevel@tonic-gate }
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate /*
10420Sstevel@tonic-gate  * Update the specified property value. Do not use the property
10430Sstevel@tonic-gate  * protection mechanism. This function should only be used for cases
10440Sstevel@tonic-gate  * where the library must bypass the normal property protection
10450Sstevel@tonic-gate  * mechanism. The only known use is to update properties in the static
10460Sstevel@tonic-gate  * configuration when performing a commit.
10470Sstevel@tonic-gate  *
10480Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is
10490Sstevel@tonic-gate  * updated to indicate the cause of the error.
10500Sstevel@tonic-gate  */
10510Sstevel@tonic-gate int
pool_put_any_property(pool_elem_t * pe,const char * name,const pool_value_t * val)10520Sstevel@tonic-gate pool_put_any_property(pool_elem_t *pe, const char *name,
10530Sstevel@tonic-gate     const pool_value_t *val)
10540Sstevel@tonic-gate {
10550Sstevel@tonic-gate 	if (!is_valid_prop_name(name)) {
10560Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
10570Sstevel@tonic-gate 		return (PO_FAIL);
10580Sstevel@tonic-gate 	}
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 	return (pe->pe_put_prop(pe, name, val));
10610Sstevel@tonic-gate }
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate /*
10640Sstevel@tonic-gate  * Update the specified property value with the namespace prepended.
10650Sstevel@tonic-gate  * e.g. If this function is used to update the property "name" on a pool, it
10660Sstevel@tonic-gate  * will attempt to update "pool.name".
10670Sstevel@tonic-gate  *
10680Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
10690Sstevel@tonic-gate  * to indicate the cause of the error.
10700Sstevel@tonic-gate  */
10710Sstevel@tonic-gate int
pool_put_any_ns_property(pool_elem_t * pe,const char * name,const pool_value_t * val)10720Sstevel@tonic-gate pool_put_any_ns_property(pool_elem_t *pe, const char *name,
10730Sstevel@tonic-gate     const pool_value_t *val)
10740Sstevel@tonic-gate {
10750Sstevel@tonic-gate 	char_buf_t *cb;
10760Sstevel@tonic-gate 	int ret;
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
10790Sstevel@tonic-gate 		return (PO_FAIL);
10800Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
10810Sstevel@tonic-gate 	    PO_FAIL) {
10820Sstevel@tonic-gate 		free_char_buf(cb);
10830Sstevel@tonic-gate 		return (PO_FAIL);
10840Sstevel@tonic-gate 	}
10850Sstevel@tonic-gate 	ret = pool_put_any_property(pe, cb->cb_buf, val);
10860Sstevel@tonic-gate 	free_char_buf(cb);
10870Sstevel@tonic-gate 	return (ret);
10880Sstevel@tonic-gate }
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate /*
10910Sstevel@tonic-gate  * Remove the specified property value. Note that some properties are
10920Sstevel@tonic-gate  * mandatory and thus failure to remove these properties is inevitable.
10930Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
10940Sstevel@tonic-gate  * to indicate the cause of the error.
10950Sstevel@tonic-gate  */
10960Sstevel@tonic-gate int
pool_rm_property(pool_conf_t * conf,pool_elem_t * pe,const char * name)10970Sstevel@tonic-gate pool_rm_property(pool_conf_t *conf, pool_elem_t *pe, const char *name)
10980Sstevel@tonic-gate {
10990Sstevel@tonic-gate 	const pool_prop_t *prop_info;
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
11020Sstevel@tonic-gate 		return (PO_FAIL);
11030Sstevel@tonic-gate 
11040Sstevel@tonic-gate 	if (TO_CONF(pe) != conf) {
11050Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
11060Sstevel@tonic-gate 		return (NULL);
11070Sstevel@tonic-gate 	}
11080Sstevel@tonic-gate 
11093247Sgjelinek 	/* Don't allow removal of the "temporary" property */
11103247Sgjelinek 	if (strstr(name, ".temporary") != NULL) {
11113247Sgjelinek 		pool_seterror(POE_BADPARAM);
11123247Sgjelinek 		return (PO_FAIL);
11133247Sgjelinek 	}
11143247Sgjelinek 
11150Sstevel@tonic-gate 	/*
11160Sstevel@tonic-gate 	 * Check to see if this is a property we are managing. If it is,
11170Sstevel@tonic-gate 	 * ensure that we are happy with what the user is doing.
11180Sstevel@tonic-gate 	 */
11190Sstevel@tonic-gate 	if ((prop_info = provider_get_prop(pe, name)) != NULL) {
11200Sstevel@tonic-gate 		if (prop_is_optional(prop_info) == PO_FALSE) {
11210Sstevel@tonic-gate 			pool_seterror(POE_BADPARAM);
11220Sstevel@tonic-gate 			return (PO_FAIL);
11230Sstevel@tonic-gate 		}
11240Sstevel@tonic-gate 	}
11250Sstevel@tonic-gate 	return (pe->pe_rm_prop(pe, name));
11260Sstevel@tonic-gate }
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate /*
11290Sstevel@tonic-gate  * Check if the supplied name is a namespace protected property for the supplied
11300Sstevel@tonic-gate  * element, pe. If it is, return the prefix, otherwise just return NULL.
11310Sstevel@tonic-gate  */
11320Sstevel@tonic-gate const char *
is_ns_property(const pool_elem_t * pe,const char * name)11330Sstevel@tonic-gate is_ns_property(const pool_elem_t *pe, const char *name)
11340Sstevel@tonic-gate {
11350Sstevel@tonic-gate 	const char *prefix;
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	if ((prefix = pool_elem_class_string(pe)) != NULL) {
11380Sstevel@tonic-gate 		if (strncmp(name, prefix, strlen(prefix)) == 0)
11390Sstevel@tonic-gate 			return (prefix);
11400Sstevel@tonic-gate 	}
11410Sstevel@tonic-gate 	return (NULL);
11420Sstevel@tonic-gate }
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate /*
11450Sstevel@tonic-gate  * Check if the supplied name is a namespace protected property for the supplied
11460Sstevel@tonic-gate  * element, pe. If it is, return the property name with the namespace stripped,
11470Sstevel@tonic-gate  * otherwise just return the name.
11480Sstevel@tonic-gate  */
11490Sstevel@tonic-gate const char *
property_name_minus_ns(const pool_elem_t * pe,const char * name)11500Sstevel@tonic-gate property_name_minus_ns(const pool_elem_t *pe, const char *name)
11510Sstevel@tonic-gate {
11520Sstevel@tonic-gate 	const char *prefix;
11530Sstevel@tonic-gate 	if ((prefix = is_ns_property(pe, name)) != NULL) {
11540Sstevel@tonic-gate 		return (name + strlen(prefix) + 1);
11550Sstevel@tonic-gate 	}
11560Sstevel@tonic-gate 	return (name);
11570Sstevel@tonic-gate }
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate /*
11600Sstevel@tonic-gate  * Create an element to represent a pool and add it to the supplied
11610Sstevel@tonic-gate  * configuration.
11620Sstevel@tonic-gate  */
11630Sstevel@tonic-gate pool_t *
pool_create(pool_conf_t * conf,const char * name)11640Sstevel@tonic-gate pool_create(pool_conf_t *conf, const char *name)
11650Sstevel@tonic-gate {
11660Sstevel@tonic-gate 	pool_elem_t *pe;
11670Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
11680Sstevel@tonic-gate 	const pool_prop_t *default_props;
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
11710Sstevel@tonic-gate 		return (NULL);
11720Sstevel@tonic-gate 
11730Sstevel@tonic-gate 	if (!is_valid_name(name) || pool_get_pool(conf, name) != NULL) {
11740Sstevel@tonic-gate 		/*
11750Sstevel@tonic-gate 		 * A pool with the same name exists. Reject.
11760Sstevel@tonic-gate 		 */
11770Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
11780Sstevel@tonic-gate 		return (NULL);
11790Sstevel@tonic-gate 	}
11800Sstevel@tonic-gate 	if ((pe = conf->pc_prov->pc_elem_create(conf, PEC_POOL, PREC_INVALID,
11810Sstevel@tonic-gate 	    PCEC_INVALID)) == NULL) {
11820Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
11830Sstevel@tonic-gate 		return (NULL);
11840Sstevel@tonic-gate 	}
11850Sstevel@tonic-gate 	if ((default_props = provider_get_props(pe)) != NULL) {
11860Sstevel@tonic-gate 		int i;
11870Sstevel@tonic-gate 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
11880Sstevel@tonic-gate 			if (prop_is_init(&default_props[i]) &&
11890Sstevel@tonic-gate 			    (pool_put_any_property(pe,
11900Sstevel@tonic-gate 			    default_props[i].pp_pname,
11910Sstevel@tonic-gate 			    &default_props[i].pp_value) == PO_FAIL)) {
11920Sstevel@tonic-gate 				(void) pool_destroy(conf, pool_elem_pool(pe));
11930Sstevel@tonic-gate 				return (NULL);
11940Sstevel@tonic-gate 			}
11950Sstevel@tonic-gate 		}
11960Sstevel@tonic-gate 	}
11970Sstevel@tonic-gate 	if (pool_value_set_string(&val, name) != PO_SUCCESS) {
11980Sstevel@tonic-gate 		(void) pool_destroy(conf, pool_elem_pool(pe));
11990Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
12000Sstevel@tonic-gate 		return (NULL);
12010Sstevel@tonic-gate 	}
12020Sstevel@tonic-gate 	if (pool_put_property(conf, pe, "pool.name", &val) == PO_FAIL) {
12030Sstevel@tonic-gate 		(void) pool_destroy(conf, pool_elem_pool(pe));
12040Sstevel@tonic-gate 		pool_seterror(POE_PUTPROP);
12050Sstevel@tonic-gate 		return (NULL);
12060Sstevel@tonic-gate 	}
12073247Sgjelinek 
12083247Sgjelinek 	/*
12093247Sgjelinek 	 * If we are creating a temporary pool configuration, flag the pool.
12103247Sgjelinek 	 */
12113247Sgjelinek 	if (conf->pc_prov->pc_oflags & PO_TEMP) {
12123247Sgjelinek 		if (pool_set_temporary(conf, pe) == PO_FAIL) {
12133247Sgjelinek 			(void) pool_destroy(conf, pool_elem_pool(pe));
12143247Sgjelinek 			return (NULL);
12153247Sgjelinek 		}
12163247Sgjelinek 	}
12173247Sgjelinek 
12180Sstevel@tonic-gate 	return (pool_elem_pool(pe));
12190Sstevel@tonic-gate }
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate /*
12220Sstevel@tonic-gate  * Create an element to represent a res.
12230Sstevel@tonic-gate  */
12240Sstevel@tonic-gate pool_resource_t *
pool_resource_create(pool_conf_t * conf,const char * sz_type,const char * name)12250Sstevel@tonic-gate pool_resource_create(pool_conf_t *conf, const char *sz_type, const char *name)
12260Sstevel@tonic-gate {
12270Sstevel@tonic-gate 	pool_elem_t *pe;
12280Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
12290Sstevel@tonic-gate 	const pool_prop_t *default_props;
12300Sstevel@tonic-gate 	pool_resource_t **resources;
12310Sstevel@tonic-gate 	int is_default = 0;
12320Sstevel@tonic-gate 	uint_t nelem;
12330Sstevel@tonic-gate 	pool_elem_class_t elem_class;
12340Sstevel@tonic-gate 	pool_resource_elem_class_t type;
12350Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
12360Sstevel@tonic-gate 
12370Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
12380Sstevel@tonic-gate 		return (NULL);
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 	if ((type = pool_resource_elem_class_from_string(sz_type)) ==
12410Sstevel@tonic-gate 	    PREC_INVALID) {
12420Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
12430Sstevel@tonic-gate 		return (NULL);
12440Sstevel@tonic-gate 	}
12450Sstevel@tonic-gate 
12460Sstevel@tonic-gate 	if (strcmp(sz_type, "pset") != 0) {
12470Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
12480Sstevel@tonic-gate 		return (NULL);
12490Sstevel@tonic-gate 	}
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 	if (!is_valid_name(name) || pool_get_resource(conf, sz_type, name) !=
12520Sstevel@tonic-gate 	    NULL) {
12530Sstevel@tonic-gate 		/*
12540Sstevel@tonic-gate 		 * Resources must be unique by name+type.
12550Sstevel@tonic-gate 		 */
12560Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
12570Sstevel@tonic-gate 		return (NULL);
12580Sstevel@tonic-gate 	}
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 	props[0] = &val;
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 	if (pool_value_set_string(props[0], sz_type) != PO_SUCCESS ||
12630Sstevel@tonic-gate 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS) {
12640Sstevel@tonic-gate 		return (NULL);
12650Sstevel@tonic-gate 	}
12660Sstevel@tonic-gate 
12670Sstevel@tonic-gate 	if ((resources = pool_query_resources(conf, &nelem, props)) == NULL) {
12680Sstevel@tonic-gate 		/*
12690Sstevel@tonic-gate 		 * This is the first representative of this type; when it's
12700Sstevel@tonic-gate 		 * created it should be created with 'default' = 'true'.
12710Sstevel@tonic-gate 		 */
12720Sstevel@tonic-gate 		is_default = 1;
12730Sstevel@tonic-gate 	} else {
12740Sstevel@tonic-gate 		free(resources);
12750Sstevel@tonic-gate 	}
12760Sstevel@tonic-gate 	/*
12770Sstevel@tonic-gate 	 * TODO: If Additional PEC_RES_COMP types are added to
12780Sstevel@tonic-gate 	 * pool_impl.h, this would need to be extended.
12790Sstevel@tonic-gate 	 */
12800Sstevel@tonic-gate 	switch (type) {
12810Sstevel@tonic-gate 	case PREC_PSET:
12820Sstevel@tonic-gate 		elem_class = PEC_RES_COMP;
12830Sstevel@tonic-gate 		break;
12840Sstevel@tonic-gate 	default:
12850Sstevel@tonic-gate 		elem_class = PEC_RES_AGG;
12860Sstevel@tonic-gate 		break;
12870Sstevel@tonic-gate 	}
12880Sstevel@tonic-gate 	if ((pe = conf->pc_prov->pc_elem_create(conf, elem_class, type,
12890Sstevel@tonic-gate 	    PCEC_INVALID)) == NULL) {
12900Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
12910Sstevel@tonic-gate 		return (NULL);
12920Sstevel@tonic-gate 	}
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 	/*
12950Sstevel@tonic-gate 	 * The plugins contain a list of default properties and their values
12960Sstevel@tonic-gate 	 * for resources. The resource returned, hence, is fully initialized.
12970Sstevel@tonic-gate 	 */
12980Sstevel@tonic-gate 	if ((default_props = provider_get_props(pe)) != NULL) {
12990Sstevel@tonic-gate 		int i;
13000Sstevel@tonic-gate 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
13010Sstevel@tonic-gate 			if (prop_is_init(&default_props[i]) &&
13020Sstevel@tonic-gate 			    pool_put_any_property(pe, default_props[i].pp_pname,
13030Sstevel@tonic-gate 			    &default_props[i].pp_value) == PO_FAIL) {
13040Sstevel@tonic-gate 				(void) pool_resource_destroy(conf,
13050Sstevel@tonic-gate 				    pool_elem_res(pe));
13060Sstevel@tonic-gate 				return (NULL);
13070Sstevel@tonic-gate 			}
13080Sstevel@tonic-gate 		}
13090Sstevel@tonic-gate 	}
13100Sstevel@tonic-gate 	if (pool_value_set_string(&val, name) != PO_SUCCESS ||
13110Sstevel@tonic-gate 	    pool_put_ns_property(pe, "name", &val) != PO_SUCCESS) {
13120Sstevel@tonic-gate 		(void) pool_resource_destroy(conf, pool_elem_res(pe));
13130Sstevel@tonic-gate 		return (NULL);
13140Sstevel@tonic-gate 	}
13150Sstevel@tonic-gate 	if (is_default) {
13160Sstevel@tonic-gate 		pool_value_set_bool(&val, PO_TRUE);
13170Sstevel@tonic-gate 		if (pool_put_any_ns_property(pe, "default", &val) !=
13180Sstevel@tonic-gate 		    PO_SUCCESS) {
13190Sstevel@tonic-gate 			(void) pool_resource_destroy(conf, pool_elem_res(pe));
13200Sstevel@tonic-gate 			return (NULL);
13210Sstevel@tonic-gate 		}
13220Sstevel@tonic-gate 	}
13233247Sgjelinek 
13243247Sgjelinek 	/*
13253247Sgjelinek 	 * If we are creating a temporary pool configuration, flag the resource.
13263247Sgjelinek 	 */
13273247Sgjelinek 	if (conf->pc_prov->pc_oflags & PO_TEMP) {
13283247Sgjelinek 		if (pool_set_temporary(conf, pe) != PO_SUCCESS) {
13293247Sgjelinek 			(void) pool_resource_destroy(conf, pool_elem_res(pe));
13303247Sgjelinek 			return (NULL);
13313247Sgjelinek 		}
13323247Sgjelinek 	}
13333247Sgjelinek 
13340Sstevel@tonic-gate 	return (pool_elem_res(pe));
13350Sstevel@tonic-gate }
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate /*
13380Sstevel@tonic-gate  * Create an element to represent a resource component.
13390Sstevel@tonic-gate  */
13400Sstevel@tonic-gate pool_component_t *
pool_component_create(pool_conf_t * conf,const pool_resource_t * res,int64_t sys_id)13410Sstevel@tonic-gate pool_component_create(pool_conf_t *conf, const pool_resource_t *res,
13420Sstevel@tonic-gate     int64_t sys_id)
13430Sstevel@tonic-gate {
13440Sstevel@tonic-gate 	pool_elem_t *pe;
13450Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
13460Sstevel@tonic-gate 	const pool_prop_t *default_props;
13470Sstevel@tonic-gate 	char refbuf[KEY_BUFFER_SIZE];
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate 	if ((pe = conf->pc_prov->pc_elem_create(conf, PEC_COMP,
13500Sstevel@tonic-gate 	    PREC_INVALID, PCEC_CPU)) == NULL) {
13510Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
13520Sstevel@tonic-gate 		return (NULL);
13530Sstevel@tonic-gate 	}
13540Sstevel@tonic-gate 	/*
13550Sstevel@tonic-gate 	 * TODO: If additional PEC_COMP types are added in pool_impl.h,
13560Sstevel@tonic-gate 	 * this would need to be extended.
13570Sstevel@tonic-gate 	 */
13580Sstevel@tonic-gate 	pe->pe_component_class = PCEC_CPU;
13590Sstevel@tonic-gate 	/* Now set the container for this comp */
13600Sstevel@tonic-gate 	if (pool_set_container(TO_ELEM(res), pe) == PO_FAIL) {
13610Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13620Sstevel@tonic-gate 		return (NULL);
13630Sstevel@tonic-gate 	}
13640Sstevel@tonic-gate 	/*
13650Sstevel@tonic-gate 	 * The plugins contain a list of default properties and their values
13660Sstevel@tonic-gate 	 * for resources. The resource returned, hence, is fully initialized.
13670Sstevel@tonic-gate 	 */
13680Sstevel@tonic-gate 	if ((default_props = provider_get_props(pe)) != NULL) {
13690Sstevel@tonic-gate 		int i;
13700Sstevel@tonic-gate 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
13710Sstevel@tonic-gate 			if (prop_is_init(&default_props[i]) &&
13720Sstevel@tonic-gate 			    pool_put_any_property(pe,
13730Sstevel@tonic-gate 			    default_props[i].pp_pname,
13740Sstevel@tonic-gate 			    &default_props[i].pp_value) == PO_FAIL) {
13750Sstevel@tonic-gate 				(void) pool_component_destroy(
13760Sstevel@tonic-gate 				    pool_elem_comp(pe));
13770Sstevel@tonic-gate 				return (NULL);
13780Sstevel@tonic-gate 			}
13790Sstevel@tonic-gate 		}
13800Sstevel@tonic-gate 	}
13810Sstevel@tonic-gate 	/*
13820Sstevel@tonic-gate 	 * Set additional attributes/properties on component.
13830Sstevel@tonic-gate 	 */
13840Sstevel@tonic-gate 	pool_value_set_int64(&val, sys_id);
13850Sstevel@tonic-gate 	if (pool_put_any_ns_property(pe, c_sys_prop, &val) != PO_SUCCESS) {
13860Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13870Sstevel@tonic-gate 		return (NULL);
13880Sstevel@tonic-gate 	}
13890Sstevel@tonic-gate 	if (snprintf(refbuf, KEY_BUFFER_SIZE, "%s_%lld",
13900Sstevel@tonic-gate 	    pool_elem_class_string(pe), sys_id) > KEY_BUFFER_SIZE) {
13910Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13920Sstevel@tonic-gate 		return (NULL);
13930Sstevel@tonic-gate 	}
13940Sstevel@tonic-gate 	if (pool_value_set_string(&val, refbuf) != PO_SUCCESS) {
13950Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
13960Sstevel@tonic-gate 		return (NULL);
13970Sstevel@tonic-gate 	}
13980Sstevel@tonic-gate 	if (pool_put_any_ns_property(pe, c_ref_id, &val) != PO_SUCCESS) {
13990Sstevel@tonic-gate 		(void) pool_component_destroy(pool_elem_comp(pe));
14000Sstevel@tonic-gate 		return (NULL);
14010Sstevel@tonic-gate 	}
14020Sstevel@tonic-gate 	return (pool_elem_comp(pe));
14030Sstevel@tonic-gate }
14040Sstevel@tonic-gate 
14050Sstevel@tonic-gate /*
14060Sstevel@tonic-gate  * Return the location of a configuration.
14070Sstevel@tonic-gate  */
14080Sstevel@tonic-gate const char *
pool_conf_location(const pool_conf_t * conf)14090Sstevel@tonic-gate pool_conf_location(const pool_conf_t *conf)
14100Sstevel@tonic-gate {
14110Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
14120Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14130Sstevel@tonic-gate 		return (NULL);
14140Sstevel@tonic-gate 	}
14150Sstevel@tonic-gate 	return (conf->pc_location);
14160Sstevel@tonic-gate }
14170Sstevel@tonic-gate /*
14180Sstevel@tonic-gate  * Close a configuration, freeing all associated resources. Once a
14190Sstevel@tonic-gate  * configuration is closed, it can no longer be used.
14200Sstevel@tonic-gate  */
14210Sstevel@tonic-gate int
pool_conf_close(pool_conf_t * conf)14220Sstevel@tonic-gate pool_conf_close(pool_conf_t *conf)
14230Sstevel@tonic-gate {
14240Sstevel@tonic-gate 	int rv;
14250Sstevel@tonic-gate 
14260Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
14270Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14280Sstevel@tonic-gate 		return (PO_FAIL);
14290Sstevel@tonic-gate 	}
14300Sstevel@tonic-gate 	rv = conf->pc_prov->pc_close(conf);
14310Sstevel@tonic-gate 	conf->pc_prov = NULL;
14320Sstevel@tonic-gate 	free((void *)conf->pc_location);
14330Sstevel@tonic-gate 	conf->pc_location = NULL;
14340Sstevel@tonic-gate 	conf->pc_state = POF_INVALID;
14350Sstevel@tonic-gate 	return (rv);
14360Sstevel@tonic-gate }
14370Sstevel@tonic-gate 
14380Sstevel@tonic-gate /*
14390Sstevel@tonic-gate  * Remove a configuration, freeing all associated resources. Once a
14400Sstevel@tonic-gate  * configuration is removed, it can no longer be accessed and is forever
14410Sstevel@tonic-gate  * gone.
14420Sstevel@tonic-gate  */
14430Sstevel@tonic-gate int
pool_conf_remove(pool_conf_t * conf)14440Sstevel@tonic-gate pool_conf_remove(pool_conf_t *conf)
14450Sstevel@tonic-gate {
14460Sstevel@tonic-gate 	int rv;
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
14490Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14500Sstevel@tonic-gate 		return (PO_FAIL);
14510Sstevel@tonic-gate 	}
14520Sstevel@tonic-gate 	rv = conf->pc_prov->pc_remove(conf);
14530Sstevel@tonic-gate 	conf->pc_state = POF_INVALID;
14540Sstevel@tonic-gate 	return (rv);
14550Sstevel@tonic-gate }
14560Sstevel@tonic-gate 
14570Sstevel@tonic-gate /*
14580Sstevel@tonic-gate  * pool_conf_alloc() allocate the resources to represent a configuration.
14590Sstevel@tonic-gate  */
14600Sstevel@tonic-gate pool_conf_t *
pool_conf_alloc(void)14610Sstevel@tonic-gate pool_conf_alloc(void)
14620Sstevel@tonic-gate {
14630Sstevel@tonic-gate 	pool_conf_t *conf;
14640Sstevel@tonic-gate 
14650Sstevel@tonic-gate 	if ((conf = calloc(1, sizeof (pool_conf_t))) == NULL) {
14660Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
14670Sstevel@tonic-gate 		return (NULL);
14680Sstevel@tonic-gate 	}
14690Sstevel@tonic-gate 	conf->pc_state = POF_INVALID;
14700Sstevel@tonic-gate 	return (conf);
14710Sstevel@tonic-gate }
14720Sstevel@tonic-gate 
14730Sstevel@tonic-gate /*
14740Sstevel@tonic-gate  * pool_conf_free() frees the resources associated with a configuration.
14750Sstevel@tonic-gate  */
14760Sstevel@tonic-gate void
pool_conf_free(pool_conf_t * conf)14770Sstevel@tonic-gate pool_conf_free(pool_conf_t *conf)
14780Sstevel@tonic-gate {
14790Sstevel@tonic-gate 	free(conf);
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate /*
14830Sstevel@tonic-gate  * pool_conf_open() opens a configuration, establishing all required
14840Sstevel@tonic-gate  * connections to the data source.
14850Sstevel@tonic-gate  */
14860Sstevel@tonic-gate int
pool_conf_open(pool_conf_t * conf,const char * location,int oflags)14870Sstevel@tonic-gate pool_conf_open(pool_conf_t *conf, const char *location, int oflags)
14880Sstevel@tonic-gate {
14890Sstevel@tonic-gate 	/*
14900Sstevel@tonic-gate 	 * Since you can't do anything to a pool configuration without opening
14910Sstevel@tonic-gate 	 * it, this represents a good point to intialise structures that would
14920Sstevel@tonic-gate 	 * otherwise need to be initialised in a .init section.
14930Sstevel@tonic-gate 	 */
14940Sstevel@tonic-gate 	internal_init();
14950Sstevel@tonic-gate 
14960Sstevel@tonic-gate 	if (pool_conf_status(conf) != POF_INVALID) {
14970Sstevel@tonic-gate 		/*
14980Sstevel@tonic-gate 		 * Already opened configuration, return PO_FAIL
14990Sstevel@tonic-gate 		 */
15000Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
15010Sstevel@tonic-gate 		return (PO_FAIL);
15020Sstevel@tonic-gate 	}
15033247Sgjelinek 	if (oflags & ~(PO_RDONLY | PO_RDWR | PO_CREAT | PO_DISCO | PO_UPDATE |
15043247Sgjelinek 	    PO_TEMP)) {
15050Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
15060Sstevel@tonic-gate 		return (PO_FAIL);
15070Sstevel@tonic-gate 	}
15080Sstevel@tonic-gate 
15090Sstevel@tonic-gate 	/*
15100Sstevel@tonic-gate 	 * Creating a configuration implies read-write access, so make
15110Sstevel@tonic-gate 	 * sure that PO_RDWR is set in addition if PO_CREAT is set.
15120Sstevel@tonic-gate 	 */
15130Sstevel@tonic-gate 	if (oflags & PO_CREAT)
15140Sstevel@tonic-gate 		oflags |= PO_RDWR;
15150Sstevel@tonic-gate 
15163247Sgjelinek 	/* location is ignored when creating a temporary configuration */
15173247Sgjelinek 	if (oflags & PO_TEMP)
15183247Sgjelinek 		location = "";
15193247Sgjelinek 
15200Sstevel@tonic-gate 	if ((conf->pc_location = strdup(location)) == NULL) {
15210Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
15220Sstevel@tonic-gate 		return (PO_FAIL);
15230Sstevel@tonic-gate 	}
15240Sstevel@tonic-gate 	/*
15250Sstevel@tonic-gate 	 * This is the crossover point into the actual data provider
15260Sstevel@tonic-gate 	 * implementation, allocate a data provider of the appropriate
15273247Sgjelinek 	 * type for your data storage medium. In this case it's either a kernel
15283247Sgjelinek 	 * or xml data provider. To use a different data provider, write some
15293247Sgjelinek 	 * code to implement all the required interfaces and then change the
15303247Sgjelinek 	 * following code to allocate a data provider which uses your new code.
15313247Sgjelinek 	 * All data provider routines can be static, apart from the allocation
15323247Sgjelinek 	 * routine.
15333247Sgjelinek 	 *
15343247Sgjelinek 	 * For temporary pools (PO_TEMP) we start with a copy of the current
15353247Sgjelinek 	 * dynamic configuration and do all of the updates in-memory.
15360Sstevel@tonic-gate 	 */
15373247Sgjelinek 	if (oflags & PO_TEMP) {
15383247Sgjelinek 		if (pool_knl_connection_alloc(conf, PO_TEMP) != PO_SUCCESS) {
15393247Sgjelinek 			conf->pc_state = POF_INVALID;
15403247Sgjelinek 			return (PO_FAIL);
15413247Sgjelinek 		}
15423247Sgjelinek 		/* set rdwr flag so we can updated the in-memory config. */
15433247Sgjelinek 		conf->pc_prov->pc_oflags |= PO_RDWR;
15443247Sgjelinek 
15453247Sgjelinek 	} else if (strcmp(location, pool_dynamic_location()) == 0) {
15460Sstevel@tonic-gate 		if (pool_knl_connection_alloc(conf, oflags) != PO_SUCCESS) {
15470Sstevel@tonic-gate 			conf->pc_state = POF_INVALID;
15480Sstevel@tonic-gate 			return (PO_FAIL);
15490Sstevel@tonic-gate 		}
15500Sstevel@tonic-gate 	} else {
15510Sstevel@tonic-gate 		if (pool_xml_connection_alloc(conf, oflags) != PO_SUCCESS) {
15520Sstevel@tonic-gate 			conf->pc_state = POF_INVALID;
15530Sstevel@tonic-gate 			return (PO_FAIL);
15540Sstevel@tonic-gate 		}
15550Sstevel@tonic-gate 	}
15560Sstevel@tonic-gate 	return (PO_SUCCESS);
15570Sstevel@tonic-gate }
15580Sstevel@tonic-gate 
15590Sstevel@tonic-gate /*
15600Sstevel@tonic-gate  * Rollback a configuration. This will undo all changes to the configuration
15610Sstevel@tonic-gate  * since the last time pool_conf_commit was called.
15620Sstevel@tonic-gate  */
15630Sstevel@tonic-gate int
pool_conf_rollback(pool_conf_t * conf)15640Sstevel@tonic-gate pool_conf_rollback(pool_conf_t *conf)
15650Sstevel@tonic-gate {
15660Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
15670Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
15680Sstevel@tonic-gate 		return (PO_FAIL);
15690Sstevel@tonic-gate 	}
15700Sstevel@tonic-gate 	return (conf->pc_prov->pc_rollback(conf));
15710Sstevel@tonic-gate }
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate /*
15740Sstevel@tonic-gate  * Commit a configuration. This will apply all changes to the
15750Sstevel@tonic-gate  * configuration to the permanent data store. The active parameter
15760Sstevel@tonic-gate  * indicates whether the configuration should be used to update the
15770Sstevel@tonic-gate  * dynamic configuration from the supplied (static) configuration or
15780Sstevel@tonic-gate  * whether it should be written back to persistent store.
15790Sstevel@tonic-gate  */
15800Sstevel@tonic-gate int
pool_conf_commit(pool_conf_t * conf,int active)15810Sstevel@tonic-gate pool_conf_commit(pool_conf_t *conf, int active)
15820Sstevel@tonic-gate {
15830Sstevel@tonic-gate 	int retval;
15840Sstevel@tonic-gate 
15850Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
15860Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
15870Sstevel@tonic-gate 		return (PO_FAIL);
15880Sstevel@tonic-gate 	}
15890Sstevel@tonic-gate 	if (active) {
15900Sstevel@tonic-gate 		int oflags;
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate 		if (conf_is_dynamic(conf) == PO_TRUE) {
15930Sstevel@tonic-gate 			pool_seterror(POE_BADPARAM);
15940Sstevel@tonic-gate 			return (PO_FAIL);
15950Sstevel@tonic-gate 		}
15960Sstevel@tonic-gate 		/*
15970Sstevel@tonic-gate 		 * Pretend that the configuration was opened PO_RDWR
15980Sstevel@tonic-gate 		 * so that a configuration which was opened PO_RDONLY
15990Sstevel@tonic-gate 		 * can be committed. The original flags are preserved
16000Sstevel@tonic-gate 		 * in oflags and restored after pool_conf_commit_sys()
16010Sstevel@tonic-gate 		 * returns.
16020Sstevel@tonic-gate 		 */
16030Sstevel@tonic-gate 		oflags = conf->pc_prov->pc_oflags;
16040Sstevel@tonic-gate 		conf->pc_prov->pc_oflags |= PO_RDWR;
16050Sstevel@tonic-gate 		retval = pool_conf_commit_sys(conf, active);
16060Sstevel@tonic-gate 		conf->pc_prov->pc_oflags = oflags;
16070Sstevel@tonic-gate 	} else {
16080Sstevel@tonic-gate 		/*
16090Sstevel@tonic-gate 		 * Write the configuration back to the backing store.
16100Sstevel@tonic-gate 		 */
16110Sstevel@tonic-gate 		retval =  conf->pc_prov->pc_commit(conf);
16120Sstevel@tonic-gate 	}
16130Sstevel@tonic-gate 	return (retval);
16140Sstevel@tonic-gate }
16150Sstevel@tonic-gate 
16160Sstevel@tonic-gate /*
16170Sstevel@tonic-gate  * Export a configuration. This will export a configuration in the specified
16180Sstevel@tonic-gate  * format (fmt) to the specified location.
16190Sstevel@tonic-gate  */
16200Sstevel@tonic-gate int
pool_conf_export(const pool_conf_t * conf,const char * location,pool_export_format_t fmt)16210Sstevel@tonic-gate pool_conf_export(const pool_conf_t *conf, const char *location,
16220Sstevel@tonic-gate     pool_export_format_t fmt)
16230Sstevel@tonic-gate {
16240Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
16250Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16260Sstevel@tonic-gate 		return (PO_FAIL);
16270Sstevel@tonic-gate 	}
16280Sstevel@tonic-gate 	return (conf->pc_prov->pc_export(conf, location, fmt));
16290Sstevel@tonic-gate }
16300Sstevel@tonic-gate 
16310Sstevel@tonic-gate /*
16320Sstevel@tonic-gate  * Validate a configuration. This will validate a configuration at the
16330Sstevel@tonic-gate  * specified level.
16340Sstevel@tonic-gate  */
16350Sstevel@tonic-gate int
pool_conf_validate(const pool_conf_t * conf,pool_valid_level_t level)16360Sstevel@tonic-gate pool_conf_validate(const pool_conf_t *conf, pool_valid_level_t level)
16370Sstevel@tonic-gate {
16380Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
16390Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16400Sstevel@tonic-gate 		return (PO_FAIL);
16410Sstevel@tonic-gate 	}
16420Sstevel@tonic-gate 	return (conf->pc_prov->pc_validate(conf, level));
16430Sstevel@tonic-gate }
16440Sstevel@tonic-gate 
16450Sstevel@tonic-gate /*
16460Sstevel@tonic-gate  * Update the snapshot of a configuration. This can only be used on a
16470Sstevel@tonic-gate  * dynamic configuration.
16480Sstevel@tonic-gate  */
16490Sstevel@tonic-gate int
pool_conf_update(const pool_conf_t * conf,int * changed)16500Sstevel@tonic-gate pool_conf_update(const pool_conf_t *conf, int *changed)
16510Sstevel@tonic-gate {
16520Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID ||
16530Sstevel@tonic-gate 	    conf_is_dynamic(conf) == PO_FALSE) {
16540Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16550Sstevel@tonic-gate 		return (PO_FAIL);
16560Sstevel@tonic-gate 	}
16570Sstevel@tonic-gate 	/*
16580Sstevel@tonic-gate 	 * Since this function only makes sense for dynamic
16590Sstevel@tonic-gate 	 * configurations, just call directly into the appropriate
16600Sstevel@tonic-gate 	 * function. This could be added into the pool_connection_t
16610Sstevel@tonic-gate 	 * interface if it was ever required.
16620Sstevel@tonic-gate 	 */
16630Sstevel@tonic-gate 	if (changed)
16640Sstevel@tonic-gate 		*changed = 0;
16650Sstevel@tonic-gate 	return (pool_knl_update((pool_conf_t *)conf, changed));
16660Sstevel@tonic-gate }
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate /*
16690Sstevel@tonic-gate  * Walk the properties of the supplied elem, calling the user supplied
16700Sstevel@tonic-gate  * function repeatedly as long as the user function returns
16710Sstevel@tonic-gate  * PO_SUCCESS.
16720Sstevel@tonic-gate  */
16730Sstevel@tonic-gate int
pool_walk_properties(pool_conf_t * conf,pool_elem_t * elem,void * arg,int (* prop_callback)(pool_conf_t *,pool_elem_t *,const char *,pool_value_t *,void *))16740Sstevel@tonic-gate pool_walk_properties(pool_conf_t *conf, pool_elem_t *elem, void *arg,
16750Sstevel@tonic-gate     int (*prop_callback)(pool_conf_t *, pool_elem_t *, const char *,
16760Sstevel@tonic-gate 	pool_value_t *, void *))
16770Sstevel@tonic-gate {
16780Sstevel@tonic-gate 	return (pool_walk_any_properties(conf, elem, arg, prop_callback, 0));
16790Sstevel@tonic-gate }
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate void
free_value_list(int npvals,pool_value_t ** pvals)16820Sstevel@tonic-gate free_value_list(int npvals, pool_value_t **pvals)
16830Sstevel@tonic-gate {
16840Sstevel@tonic-gate 	int j;
16850Sstevel@tonic-gate 
16860Sstevel@tonic-gate 	for (j = 0; j < npvals; j++) {
16870Sstevel@tonic-gate 		if (pvals[j])
16880Sstevel@tonic-gate 			pool_value_free(pvals[j]);
16890Sstevel@tonic-gate 	}
16900Sstevel@tonic-gate 	free(pvals);
16910Sstevel@tonic-gate }
16920Sstevel@tonic-gate 
16930Sstevel@tonic-gate /*
16940Sstevel@tonic-gate  * Walk the properties of the supplied elem, calling the user supplied
16950Sstevel@tonic-gate  * function repeatedly as long as the user function returns
16960Sstevel@tonic-gate  * PO_SUCCESS.
16970Sstevel@tonic-gate  * The list of properties to be walked is retrieved from the element
16980Sstevel@tonic-gate  */
16990Sstevel@tonic-gate int
pool_walk_any_properties(pool_conf_t * conf,pool_elem_t * elem,void * arg,int (* prop_callback)(pool_conf_t *,pool_elem_t *,const char *,pool_value_t *,void *),int any)17000Sstevel@tonic-gate pool_walk_any_properties(pool_conf_t *conf, pool_elem_t *elem, void *arg,
17010Sstevel@tonic-gate     int (*prop_callback)(pool_conf_t *, pool_elem_t *, const char *,
17020Sstevel@tonic-gate 	pool_value_t *, void *), int any)
17030Sstevel@tonic-gate {
17040Sstevel@tonic-gate 	pool_value_t **pvals;
17050Sstevel@tonic-gate 	int i;
17060Sstevel@tonic-gate 	const pool_prop_t *props = provider_get_props(elem);
17070Sstevel@tonic-gate 	uint_t npvals;
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
17100Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
17110Sstevel@tonic-gate 		return (PO_FAIL);
17120Sstevel@tonic-gate 	}
17130Sstevel@tonic-gate 
17140Sstevel@tonic-gate 	if (props == NULL) {
17150Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
17160Sstevel@tonic-gate 		return (PO_FAIL);
17170Sstevel@tonic-gate 	}
17180Sstevel@tonic-gate 
17190Sstevel@tonic-gate 	if ((pvals = elem->pe_get_props(elem, &npvals)) == NULL)
17200Sstevel@tonic-gate 		return (PO_FAIL);
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate 	/*
17230Sstevel@tonic-gate 	 * Now walk the managed properties. As we find managed
17240Sstevel@tonic-gate 	 * properties removed them from the list of all properties to
17250Sstevel@tonic-gate 	 * prevent duplication.
17260Sstevel@tonic-gate 	 */
17270Sstevel@tonic-gate 	for (i = 0;  props[i].pp_pname != NULL; i++) {
17280Sstevel@tonic-gate 		int j;
17290Sstevel@tonic-gate 
17300Sstevel@tonic-gate 		/*
17310Sstevel@tonic-gate 		 * Special processing for type
17320Sstevel@tonic-gate 		 */
17330Sstevel@tonic-gate 		if (strcmp(props[i].pp_pname, c_type) == 0) {
17340Sstevel@tonic-gate 			pool_value_t val = POOL_VALUE_INITIALIZER;
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate 			if (pool_value_set_name(&val, props[i].pp_pname) ==
17370Sstevel@tonic-gate 			    PO_FAIL) {
17380Sstevel@tonic-gate 				free_value_list(npvals, pvals);
17390Sstevel@tonic-gate 				return (PO_FAIL);
17400Sstevel@tonic-gate 			}
17410Sstevel@tonic-gate 			if (props[i].pp_op.ppo_get_value(elem, &val) ==
17420Sstevel@tonic-gate 			    PO_FAIL) {
17430Sstevel@tonic-gate 				free_value_list(npvals, pvals);
17440Sstevel@tonic-gate 				return (PO_FAIL);
17450Sstevel@tonic-gate 			}
17460Sstevel@tonic-gate 			if (any == 1 || prop_is_hidden(&props[i]) == PO_FALSE) {
17470Sstevel@tonic-gate 				if (prop_callback(conf, elem, props[i].pp_pname,
17480Sstevel@tonic-gate 				    &val, arg) != PO_SUCCESS) {
17490Sstevel@tonic-gate 					free_value_list(npvals, pvals);
17500Sstevel@tonic-gate 					pool_seterror(POE_BADPARAM);
17510Sstevel@tonic-gate 					return (PO_FAIL);
17520Sstevel@tonic-gate 				}
17530Sstevel@tonic-gate 			}
17540Sstevel@tonic-gate 			continue;
17550Sstevel@tonic-gate 		}
17560Sstevel@tonic-gate 
17570Sstevel@tonic-gate 		for (j = 0; j < npvals; j++) {
17580Sstevel@tonic-gate 			if (pvals[j] && strcmp(pool_value_get_name(pvals[j]),
17590Sstevel@tonic-gate 			    props[i].pp_pname) == 0)
17600Sstevel@tonic-gate 				break;
17610Sstevel@tonic-gate 		}
17620Sstevel@tonic-gate 		/*
17630Sstevel@tonic-gate 		 * If we have found the property, then j < npvals. Process it
17640Sstevel@tonic-gate 		 * according to our property attributes. Otherwise, it's not
17650Sstevel@tonic-gate 		 * a managed property, so just ignore it until later.
17660Sstevel@tonic-gate 		 */
17670Sstevel@tonic-gate 		if (j < npvals) {
17680Sstevel@tonic-gate 			if (any == 1 || prop_is_hidden(&props[i]) == PO_FALSE) {
17690Sstevel@tonic-gate 				if (props[i].pp_op.ppo_get_value) {
17700Sstevel@tonic-gate 					if (pool_value_set_name(pvals[j],
17710Sstevel@tonic-gate 					props[i].pp_pname) == PO_FAIL) {
17720Sstevel@tonic-gate 						free_value_list(npvals, pvals);
17730Sstevel@tonic-gate 						return (PO_FAIL);
17740Sstevel@tonic-gate 					}
17750Sstevel@tonic-gate 					if (props[i].pp_op.ppo_get_value(elem,
17760Sstevel@tonic-gate 					    pvals[j]) == PO_FAIL) {
17770Sstevel@tonic-gate 						free_value_list(npvals, pvals);
17780Sstevel@tonic-gate 						return (PO_FAIL);
17790Sstevel@tonic-gate 					}
17800Sstevel@tonic-gate 				}
17810Sstevel@tonic-gate 				if (prop_callback(conf, elem, props[i].pp_pname,
17820Sstevel@tonic-gate 				    pvals[j], arg) != PO_SUCCESS) {
17830Sstevel@tonic-gate 					free_value_list(npvals, pvals);
17840Sstevel@tonic-gate 					pool_seterror(POE_BADPARAM);
17850Sstevel@tonic-gate 					return (PO_FAIL);
17860Sstevel@tonic-gate 				}
17870Sstevel@tonic-gate 			}
17880Sstevel@tonic-gate 			pool_value_free(pvals[j]);
17890Sstevel@tonic-gate 			pvals[j] = NULL;
17900Sstevel@tonic-gate 		}
17910Sstevel@tonic-gate 	}
17920Sstevel@tonic-gate 	for (i = 0;  i < npvals; i++) {
17930Sstevel@tonic-gate 		if (pvals[i]) {
17940Sstevel@tonic-gate 			const char *name = pool_value_get_name(pvals[i]);
17950Sstevel@tonic-gate 			char *qname = strrchr(name, '.');
17960Sstevel@tonic-gate 			if ((qname && qname[1] != '_') ||
17970Sstevel@tonic-gate 			    (!qname && name[0] != '_')) {
17980Sstevel@tonic-gate 				if (prop_callback(conf, elem, name, pvals[i],
17990Sstevel@tonic-gate 				    arg) != PO_SUCCESS) {
18000Sstevel@tonic-gate 					free_value_list(npvals, pvals);
18010Sstevel@tonic-gate 					pool_seterror(POE_BADPARAM);
18020Sstevel@tonic-gate 					return (PO_FAIL);
18030Sstevel@tonic-gate 				}
18040Sstevel@tonic-gate 			}
18050Sstevel@tonic-gate 			pool_value_free(pvals[i]);
18060Sstevel@tonic-gate 			pvals[i] = NULL;
18070Sstevel@tonic-gate 		}
18080Sstevel@tonic-gate 	}
18090Sstevel@tonic-gate 	free(pvals);
18100Sstevel@tonic-gate 	return (PO_SUCCESS);
18110Sstevel@tonic-gate }
18120Sstevel@tonic-gate 
18130Sstevel@tonic-gate /*
18140Sstevel@tonic-gate  * Return a pool, searching the supplied configuration for a pool with the
18150Sstevel@tonic-gate  * supplied name. The search is case sensitive.
18160Sstevel@tonic-gate  */
18170Sstevel@tonic-gate pool_t *
pool_get_pool(const pool_conf_t * conf,const char * name)18180Sstevel@tonic-gate pool_get_pool(const pool_conf_t *conf, const char *name)
18190Sstevel@tonic-gate {
18200Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
18210Sstevel@tonic-gate 	pool_t **rs;
18220Sstevel@tonic-gate 	pool_t *ret;
18230Sstevel@tonic-gate 	uint_t size = 0;
18240Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
18250Sstevel@tonic-gate 
18260Sstevel@tonic-gate 	props[0] = &val;
18270Sstevel@tonic-gate 
18280Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
18290Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
18300Sstevel@tonic-gate 		return (NULL);
18310Sstevel@tonic-gate 	}
18320Sstevel@tonic-gate 
18330Sstevel@tonic-gate 	if (pool_value_set_name(props[0], "pool.name") != PO_SUCCESS ||
18340Sstevel@tonic-gate 	    pool_value_set_string(props[0], name) != PO_SUCCESS) {
18350Sstevel@tonic-gate 		return (NULL);
18360Sstevel@tonic-gate 	}
18370Sstevel@tonic-gate 	rs = pool_query_pools(conf, &size, props);
18380Sstevel@tonic-gate 	if (rs == NULL) { /* Can't find a pool to match the name */
18390Sstevel@tonic-gate 		return (NULL);
18400Sstevel@tonic-gate 	}
18410Sstevel@tonic-gate 	if (size != 1) {
18420Sstevel@tonic-gate 		free(rs);
18430Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
18440Sstevel@tonic-gate 		return (NULL);
18450Sstevel@tonic-gate 	}
18460Sstevel@tonic-gate 	ret = rs[0];
18470Sstevel@tonic-gate 	free(rs);
18480Sstevel@tonic-gate 	return (ret);
18490Sstevel@tonic-gate }
18500Sstevel@tonic-gate 
18510Sstevel@tonic-gate /*
18520Sstevel@tonic-gate  * Return a result set of pools, searching the supplied configuration
18530Sstevel@tonic-gate  * for pools which match the supplied property criteria. props is a null
18540Sstevel@tonic-gate  * terminated list of properties which will be used to match qualifying
18550Sstevel@tonic-gate  * pools. size is updated with the size of the pool
18560Sstevel@tonic-gate  */
18570Sstevel@tonic-gate pool_t **
pool_query_pools(const pool_conf_t * conf,uint_t * size,pool_value_t ** props)18580Sstevel@tonic-gate pool_query_pools(const pool_conf_t *conf, uint_t *size, pool_value_t **props)
18590Sstevel@tonic-gate {
18600Sstevel@tonic-gate 	pool_result_set_t *rs;
18610Sstevel@tonic-gate 	pool_elem_t *pe;
18620Sstevel@tonic-gate 	pool_t **result = NULL;
18630Sstevel@tonic-gate 	int i = 0;
18640Sstevel@tonic-gate 
18650Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
18660Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
18670Sstevel@tonic-gate 		return (NULL);
18680Sstevel@tonic-gate 	}
18690Sstevel@tonic-gate 	rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_POOL, props);
18700Sstevel@tonic-gate 	if (rs == NULL) {
18710Sstevel@tonic-gate 		return (NULL);
18720Sstevel@tonic-gate 	}
18730Sstevel@tonic-gate 	if ((*size = pool_rs_count(rs)) == 0) {
18740Sstevel@tonic-gate 		(void) pool_rs_close(rs);
18750Sstevel@tonic-gate 		return (NULL);
18760Sstevel@tonic-gate 	}
18770Sstevel@tonic-gate 	if ((result = malloc(sizeof (pool_t *) * (*size + 1))) == NULL) {
18780Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
18790Sstevel@tonic-gate 		(void) pool_rs_close(rs);
18800Sstevel@tonic-gate 		return (NULL);
18810Sstevel@tonic-gate 	}
18820Sstevel@tonic-gate 	(void) memset(result, 0, sizeof (pool_t *) * (*size + 1));
18830Sstevel@tonic-gate 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
18840Sstevel@tonic-gate 		if (pool_elem_class(pe) != PEC_POOL) {
18850Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
18860Sstevel@tonic-gate 			free(result);
18870Sstevel@tonic-gate 			(void) pool_rs_close(rs);
18880Sstevel@tonic-gate 			return (NULL);
18890Sstevel@tonic-gate 		}
18900Sstevel@tonic-gate 		result[i++] = pool_elem_pool(pe);
18910Sstevel@tonic-gate 	}
18920Sstevel@tonic-gate 	(void) pool_rs_close(rs);
18930Sstevel@tonic-gate 	return (result);
18940Sstevel@tonic-gate }
18950Sstevel@tonic-gate 
18960Sstevel@tonic-gate /*
18970Sstevel@tonic-gate  * Return an res, searching the supplied configuration for an res with the
18980Sstevel@tonic-gate  * supplied name. The search is case sensitive.
18990Sstevel@tonic-gate  */
19000Sstevel@tonic-gate pool_resource_t *
pool_get_resource(const pool_conf_t * conf,const char * sz_type,const char * name)19010Sstevel@tonic-gate pool_get_resource(const pool_conf_t *conf, const char *sz_type,
19020Sstevel@tonic-gate     const char *name)
19030Sstevel@tonic-gate {
19040Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL, NULL };
19050Sstevel@tonic-gate 	pool_resource_t **rs;
19060Sstevel@tonic-gate 	pool_resource_t *ret;
19070Sstevel@tonic-gate 	uint_t size = 0;
19080Sstevel@tonic-gate 	char_buf_t *cb = NULL;
19090Sstevel@tonic-gate 	pool_value_t val0 = POOL_VALUE_INITIALIZER;
19100Sstevel@tonic-gate 	pool_value_t val1 = POOL_VALUE_INITIALIZER;
19110Sstevel@tonic-gate 
19120Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
19130Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
19140Sstevel@tonic-gate 		return (NULL);
19150Sstevel@tonic-gate 	}
19160Sstevel@tonic-gate 
19170Sstevel@tonic-gate 	if (sz_type == NULL) {
19180Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
19190Sstevel@tonic-gate 		return (NULL);
19200Sstevel@tonic-gate 	}
19210Sstevel@tonic-gate 
19220Sstevel@tonic-gate 	props[0] = &val0;
19230Sstevel@tonic-gate 	props[1] = &val1;
19240Sstevel@tonic-gate 
19250Sstevel@tonic-gate 	if (pool_value_set_string(props[0], sz_type) != PO_SUCCESS ||
19260Sstevel@tonic-gate 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS)
19270Sstevel@tonic-gate 		return (NULL);
19280Sstevel@tonic-gate 
19290Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
19300Sstevel@tonic-gate 		return (NULL);
19310Sstevel@tonic-gate 	}
19320Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.name", sz_type) != PO_SUCCESS) {
19330Sstevel@tonic-gate 		free_char_buf(cb);
19340Sstevel@tonic-gate 		return (NULL);
19350Sstevel@tonic-gate 	}
19360Sstevel@tonic-gate 	if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) {
19370Sstevel@tonic-gate 		free_char_buf(cb);
19380Sstevel@tonic-gate 		return (NULL);
19390Sstevel@tonic-gate 	}
19400Sstevel@tonic-gate 	if (pool_value_set_string(props[1], name) != PO_SUCCESS) {
19410Sstevel@tonic-gate 		free_char_buf(cb);
19420Sstevel@tonic-gate 		return (NULL);
19430Sstevel@tonic-gate 	}
19440Sstevel@tonic-gate 	free_char_buf(cb);
19450Sstevel@tonic-gate 	rs = pool_query_resources(conf, &size, props);
19460Sstevel@tonic-gate 	if (rs == NULL) {
19470Sstevel@tonic-gate 		return (NULL);
19480Sstevel@tonic-gate 	}
19490Sstevel@tonic-gate 	if (size != 1) {
19500Sstevel@tonic-gate 		free(rs);
19510Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
19520Sstevel@tonic-gate 		return (NULL);
19530Sstevel@tonic-gate 	}
19540Sstevel@tonic-gate 	ret = rs[0];
19550Sstevel@tonic-gate 	free(rs);
19560Sstevel@tonic-gate 	return (ret);
19570Sstevel@tonic-gate }
19580Sstevel@tonic-gate 
19590Sstevel@tonic-gate /*
19600Sstevel@tonic-gate  * Return a result set of res (actually as pool_elem_ts), searching the
19610Sstevel@tonic-gate  * supplied configuration for res which match the supplied property
19620Sstevel@tonic-gate  * criteria. props is a null terminated list of properties which will be used
19630Sstevel@tonic-gate  * to match qualifying res.
19640Sstevel@tonic-gate  */
19650Sstevel@tonic-gate pool_resource_t **
pool_query_resources(const pool_conf_t * conf,uint_t * size,pool_value_t ** props)19660Sstevel@tonic-gate pool_query_resources(const pool_conf_t *conf, uint_t *size,
19670Sstevel@tonic-gate     pool_value_t **props)
19680Sstevel@tonic-gate {
19690Sstevel@tonic-gate 	pool_result_set_t *rs;
19700Sstevel@tonic-gate 	pool_elem_t *pe;
19710Sstevel@tonic-gate 	pool_resource_t **result = NULL;
19720Sstevel@tonic-gate 	int i = 0;
19730Sstevel@tonic-gate 
19740Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
19750Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
19760Sstevel@tonic-gate 		return (NULL);
19770Sstevel@tonic-gate 	}
19780Sstevel@tonic-gate 
19790Sstevel@tonic-gate 	*size = 0;
19800Sstevel@tonic-gate 
19810Sstevel@tonic-gate 	rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_RES, props);
19820Sstevel@tonic-gate 	if (rs == NULL) {
19830Sstevel@tonic-gate 		return (NULL);
19840Sstevel@tonic-gate 	}
19850Sstevel@tonic-gate 	if ((*size = pool_rs_count(rs)) == 0) {
19860Sstevel@tonic-gate 		(void) pool_rs_close(rs);
19870Sstevel@tonic-gate 		return (NULL);
19880Sstevel@tonic-gate 	}
19890Sstevel@tonic-gate 	if ((result = malloc(sizeof (pool_resource_t *) * (*size + 1)))
19900Sstevel@tonic-gate 	    == NULL) {
19910Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
19920Sstevel@tonic-gate 		(void) pool_rs_close(rs);
19930Sstevel@tonic-gate 		return (NULL);
19940Sstevel@tonic-gate 	}
19950Sstevel@tonic-gate 	(void) memset(result, 0, sizeof (pool_resource_t *) * (*size + 1));
19960Sstevel@tonic-gate 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
19970Sstevel@tonic-gate 		if (pool_elem_class(pe) != PEC_RES_COMP &&
19980Sstevel@tonic-gate 		    pool_elem_class(pe) != PEC_RES_AGG) {
19990Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
20000Sstevel@tonic-gate 			free(result);
20010Sstevel@tonic-gate 			(void) pool_rs_close(rs);
20020Sstevel@tonic-gate 			return (NULL);
20030Sstevel@tonic-gate 		}
20040Sstevel@tonic-gate 		result[i++] = pool_elem_res(pe);
20050Sstevel@tonic-gate 	}
20060Sstevel@tonic-gate 	(void) pool_rs_close(rs);
20070Sstevel@tonic-gate 	return (result);
20080Sstevel@tonic-gate }
20090Sstevel@tonic-gate 
20100Sstevel@tonic-gate /*
20110Sstevel@tonic-gate  * Return a result set of comp (actually as pool_elem_ts), searching the
20120Sstevel@tonic-gate  * supplied configuration for comp which match the supplied property
20130Sstevel@tonic-gate  * criteria. props is a null terminated list of properties which will be used
20140Sstevel@tonic-gate  * to match qualifying comp.
20150Sstevel@tonic-gate  */
20160Sstevel@tonic-gate pool_component_t **
pool_query_components(const pool_conf_t * conf,uint_t * size,pool_value_t ** props)20170Sstevel@tonic-gate pool_query_components(const pool_conf_t *conf, uint_t *size,
20180Sstevel@tonic-gate     pool_value_t **props)
20190Sstevel@tonic-gate {
20200Sstevel@tonic-gate 	return (pool_query_resource_components(conf, NULL, size, props));
20210Sstevel@tonic-gate }
20220Sstevel@tonic-gate 
20230Sstevel@tonic-gate /*
20240Sstevel@tonic-gate  * Destroy a pool. If the pool cannot be found or removed an error is
20250Sstevel@tonic-gate  * returned. This is basically a wrapper around pool_elem_remove to ensure
20260Sstevel@tonic-gate  * some type safety for the pool subtype.
20270Sstevel@tonic-gate  */
20280Sstevel@tonic-gate int
pool_destroy(pool_conf_t * conf,pool_t * pp)20290Sstevel@tonic-gate pool_destroy(pool_conf_t *conf, pool_t *pp)
20300Sstevel@tonic-gate {
20310Sstevel@tonic-gate 	pool_elem_t *pe;
20320Sstevel@tonic-gate 
20330Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
20340Sstevel@tonic-gate 		return (PO_FAIL);
20350Sstevel@tonic-gate 
20360Sstevel@tonic-gate 	pe = TO_ELEM(pp);
20370Sstevel@tonic-gate 
20380Sstevel@tonic-gate 	/*
20390Sstevel@tonic-gate 	 * Cannot destroy the default pool.
20400Sstevel@tonic-gate 	 */
20410Sstevel@tonic-gate 	if (elem_is_default(pe) == PO_TRUE) {
20420Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
20430Sstevel@tonic-gate 		return (PO_FAIL);
20440Sstevel@tonic-gate 	}
20450Sstevel@tonic-gate 	if (pool_elem_remove(pe) != PO_SUCCESS)
20460Sstevel@tonic-gate 		return (PO_FAIL);
20470Sstevel@tonic-gate 	return (PO_SUCCESS);
20480Sstevel@tonic-gate }
20490Sstevel@tonic-gate 
20500Sstevel@tonic-gate /*
20510Sstevel@tonic-gate  * Destroy an res. If the res cannot be found or removed an error is
20520Sstevel@tonic-gate  * returned. This is basically a wrapper around pool_elem_remove to ensure
20530Sstevel@tonic-gate  * some type safety for the res subtype.
20540Sstevel@tonic-gate  */
20550Sstevel@tonic-gate int
pool_resource_destroy(pool_conf_t * conf,pool_resource_t * prs)20560Sstevel@tonic-gate pool_resource_destroy(pool_conf_t *conf, pool_resource_t *prs)
20570Sstevel@tonic-gate {
20580Sstevel@tonic-gate 	pool_elem_t *pe;
20590Sstevel@tonic-gate 	pool_component_t **rl;
20600Sstevel@tonic-gate 	uint_t res_size;
20610Sstevel@tonic-gate 	pool_t **pl;
20620Sstevel@tonic-gate 	uint_t npool;
20630Sstevel@tonic-gate 	int i;
20640Sstevel@tonic-gate 
20650Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
20660Sstevel@tonic-gate 		return (PO_FAIL);
20670Sstevel@tonic-gate 
20680Sstevel@tonic-gate 	pe = TO_ELEM(prs);
20690Sstevel@tonic-gate 
20700Sstevel@tonic-gate 	if (resource_is_system(prs) == PO_TRUE) {
20710Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
20720Sstevel@tonic-gate 		return (PO_FAIL);
20730Sstevel@tonic-gate 	}
20740Sstevel@tonic-gate 	/*
20750Sstevel@tonic-gate 	 * Walk all the pools and dissociate any pools which are using
20760Sstevel@tonic-gate 	 * this resource.
20770Sstevel@tonic-gate 	 */
20780Sstevel@tonic-gate 	if ((pl = pool_query_pools(conf, &npool, NULL)) != NULL) {
20790Sstevel@tonic-gate 		for (i = 0; i < npool; i++) {
20800Sstevel@tonic-gate 			pool_resource_t **rl;
20810Sstevel@tonic-gate 			uint_t nres;
20820Sstevel@tonic-gate 			int j;
20830Sstevel@tonic-gate 
20840Sstevel@tonic-gate 			if ((rl = pool_query_pool_resources(conf, pl[i], &nres,
20850Sstevel@tonic-gate 			    NULL)) != NULL) {
20860Sstevel@tonic-gate 				for (j = 0; j < nres; j++) {
20870Sstevel@tonic-gate 					if (rl[j] == prs) {
20880Sstevel@tonic-gate 						if (pool_dissociate(conf, pl[i],
20890Sstevel@tonic-gate 						    rl[j]) != PO_SUCCESS) {
20900Sstevel@tonic-gate 							free(rl);
20910Sstevel@tonic-gate 							free(pl);
20920Sstevel@tonic-gate 							return (PO_FAIL);
20930Sstevel@tonic-gate 						}
20940Sstevel@tonic-gate 						break;
20950Sstevel@tonic-gate 					}
20960Sstevel@tonic-gate 				}
20970Sstevel@tonic-gate 			free(rl);
20980Sstevel@tonic-gate 			}
20990Sstevel@tonic-gate 		}
21000Sstevel@tonic-gate 		free(pl);
21010Sstevel@tonic-gate 	}
21020Sstevel@tonic-gate 	if (pe->pe_class == PEC_RES_COMP) {
21030Sstevel@tonic-gate 		pool_resource_t *default_set_res;
21040Sstevel@tonic-gate 
21050Sstevel@tonic-gate 		/*
21060Sstevel@tonic-gate 		 * Use the xtransfer option to move comp around
21070Sstevel@tonic-gate 		 */
21080Sstevel@tonic-gate 		default_set_res = (pool_resource_t *)get_default_resource(prs);
21090Sstevel@tonic-gate 
21100Sstevel@tonic-gate 		if ((rl = pool_query_resource_components(conf, prs, &res_size,
21110Sstevel@tonic-gate 		    NULL)) != NULL) {
21120Sstevel@tonic-gate 			int ostate = conf->pc_state;
21130Sstevel@tonic-gate 			conf->pc_state = POF_DESTROY;
21140Sstevel@tonic-gate 			if (pool_resource_xtransfer(conf, prs, default_set_res,
21150Sstevel@tonic-gate 			    rl) == PO_FAIL) {
21160Sstevel@tonic-gate 				free(rl);
21170Sstevel@tonic-gate 				conf->pc_state = ostate;
21180Sstevel@tonic-gate 				return (PO_FAIL);
21190Sstevel@tonic-gate 			}
21200Sstevel@tonic-gate 			conf->pc_state = ostate;
21210Sstevel@tonic-gate 			free(rl);
21220Sstevel@tonic-gate 		}
21230Sstevel@tonic-gate 	}
21240Sstevel@tonic-gate 	if (pool_elem_remove(pe) != PO_SUCCESS)
21250Sstevel@tonic-gate 		return (PO_FAIL);
21260Sstevel@tonic-gate 	return (PO_SUCCESS);
21270Sstevel@tonic-gate }
21280Sstevel@tonic-gate 
21290Sstevel@tonic-gate /*
21300Sstevel@tonic-gate  * Destroy a comp. If the comp cannot be found or removed an error is
21310Sstevel@tonic-gate  * returned. This is basically a wrapper around pool_elem_remove to ensure
21320Sstevel@tonic-gate  * some type safety for the comp subtype.
21330Sstevel@tonic-gate  */
21340Sstevel@tonic-gate int
pool_component_destroy(pool_component_t * pr)21350Sstevel@tonic-gate pool_component_destroy(pool_component_t *pr)
21360Sstevel@tonic-gate {
21370Sstevel@tonic-gate 	pool_elem_t *pe = TO_ELEM(pr);
21380Sstevel@tonic-gate 
21390Sstevel@tonic-gate 	if (pool_elem_remove(pe) != PO_SUCCESS)
21400Sstevel@tonic-gate 		return (PO_FAIL);
21410Sstevel@tonic-gate 	return (PO_SUCCESS);
21420Sstevel@tonic-gate }
21430Sstevel@tonic-gate 
21440Sstevel@tonic-gate /*
21450Sstevel@tonic-gate  * Remove a pool_elem_t from a configuration. This has been "hidden" away as
21460Sstevel@tonic-gate  * a static routine since the only elements which are currently being removed
21470Sstevel@tonic-gate  * are pools, res & comp and the wrapper functions above provide type-safe
21480Sstevel@tonic-gate  * access. However, if there is a need to remove other types of elements
21490Sstevel@tonic-gate  * then this could be promoted to pool_impl.h or more wrappers could
21500Sstevel@tonic-gate  * be added to pool_impl.h.
21510Sstevel@tonic-gate  */
21520Sstevel@tonic-gate int
pool_elem_remove(pool_elem_t * pe)21530Sstevel@tonic-gate pool_elem_remove(pool_elem_t *pe)
21540Sstevel@tonic-gate {
21550Sstevel@tonic-gate 	return (pe->pe_remove(pe));
21560Sstevel@tonic-gate }
21570Sstevel@tonic-gate 
21580Sstevel@tonic-gate /*
21590Sstevel@tonic-gate  * Execute a query to search for a qualifying set of elements.
21600Sstevel@tonic-gate  */
21610Sstevel@tonic-gate pool_result_set_t *
pool_exec_query(const pool_conf_t * conf,const pool_elem_t * src,const char * src_attr,pool_elem_class_t classes,pool_value_t ** props)21620Sstevel@tonic-gate pool_exec_query(const pool_conf_t *conf, const pool_elem_t *src,
21630Sstevel@tonic-gate     const char *src_attr, pool_elem_class_t classes, pool_value_t **props)
21640Sstevel@tonic-gate {
21650Sstevel@tonic-gate 	return (conf->pc_prov->pc_exec_query(conf, src, src_attr, classes,
21660Sstevel@tonic-gate 	    props));
21670Sstevel@tonic-gate }
21680Sstevel@tonic-gate 
21690Sstevel@tonic-gate /*
21700Sstevel@tonic-gate  * Get the next result from a result set of elements.
21710Sstevel@tonic-gate  */
21720Sstevel@tonic-gate pool_elem_t *
pool_rs_next(pool_result_set_t * set)21730Sstevel@tonic-gate pool_rs_next(pool_result_set_t *set)
21740Sstevel@tonic-gate {
21750Sstevel@tonic-gate 	return (set->prs_next(set));
21760Sstevel@tonic-gate }
21770Sstevel@tonic-gate 
21780Sstevel@tonic-gate /*
21790Sstevel@tonic-gate  * Get the previous result from a result set of elements.
21800Sstevel@tonic-gate  */
21810Sstevel@tonic-gate pool_elem_t *
pool_rs_prev(pool_result_set_t * set)21820Sstevel@tonic-gate pool_rs_prev(pool_result_set_t *set)
21830Sstevel@tonic-gate {
21840Sstevel@tonic-gate 	return (set->prs_prev(set));
21850Sstevel@tonic-gate }
21860Sstevel@tonic-gate 
21870Sstevel@tonic-gate /*
21880Sstevel@tonic-gate  * Get the first result from a result set of elements.
21890Sstevel@tonic-gate  */
21900Sstevel@tonic-gate pool_elem_t *
pool_rs_first(pool_result_set_t * set)21910Sstevel@tonic-gate pool_rs_first(pool_result_set_t *set)
21920Sstevel@tonic-gate {
21930Sstevel@tonic-gate 	return (set->prs_first(set));
21940Sstevel@tonic-gate }
21950Sstevel@tonic-gate 
21960Sstevel@tonic-gate /*
21970Sstevel@tonic-gate  * Get the last result from a result set of elements.
21980Sstevel@tonic-gate  */
21990Sstevel@tonic-gate pool_elem_t *
pool_rs_last(pool_result_set_t * set)22000Sstevel@tonic-gate pool_rs_last(pool_result_set_t *set)
22010Sstevel@tonic-gate {
22020Sstevel@tonic-gate 	return (set->prs_last(set));
22030Sstevel@tonic-gate }
22040Sstevel@tonic-gate 
22050Sstevel@tonic-gate 
22060Sstevel@tonic-gate /*
22070Sstevel@tonic-gate  * Get the count for a result set of elements.
22080Sstevel@tonic-gate  */
22090Sstevel@tonic-gate int
pool_rs_count(pool_result_set_t * set)22100Sstevel@tonic-gate pool_rs_count(pool_result_set_t *set)
22110Sstevel@tonic-gate {
22120Sstevel@tonic-gate 	return (set->prs_count(set));
22130Sstevel@tonic-gate }
22140Sstevel@tonic-gate 
22150Sstevel@tonic-gate /*
22160Sstevel@tonic-gate  * Get the index for a result set of elements.
22170Sstevel@tonic-gate  */
22180Sstevel@tonic-gate int
pool_rs_get_index(pool_result_set_t * set)22190Sstevel@tonic-gate pool_rs_get_index(pool_result_set_t *set)
22200Sstevel@tonic-gate {
22210Sstevel@tonic-gate 	return (set->prs_get_index(set));
22220Sstevel@tonic-gate }
22230Sstevel@tonic-gate 
22240Sstevel@tonic-gate /*
22250Sstevel@tonic-gate  * Set the index for a result set of elements.
22260Sstevel@tonic-gate  */
22270Sstevel@tonic-gate int
pool_rs_set_index(pool_result_set_t * set,int index)22280Sstevel@tonic-gate pool_rs_set_index(pool_result_set_t *set, int index)
22290Sstevel@tonic-gate {
22300Sstevel@tonic-gate 	return (set->prs_set_index(set, index));
22310Sstevel@tonic-gate }
22320Sstevel@tonic-gate 
22330Sstevel@tonic-gate /*
22340Sstevel@tonic-gate  * Close a result set of elements, freeing all associated resources.
22350Sstevel@tonic-gate  */
22360Sstevel@tonic-gate int
pool_rs_close(pool_result_set_t * set)22370Sstevel@tonic-gate pool_rs_close(pool_result_set_t *set)
22380Sstevel@tonic-gate {
22390Sstevel@tonic-gate 	return (set->prs_close(set));
22400Sstevel@tonic-gate }
22410Sstevel@tonic-gate 
22420Sstevel@tonic-gate /*
22430Sstevel@tonic-gate  * When transferring resource components using pool_resource_transfer,
22440Sstevel@tonic-gate  * this function is invoked to choose which actual components will be
22450Sstevel@tonic-gate  * transferred.
22460Sstevel@tonic-gate  */
22470Sstevel@tonic-gate int
choose_components(pool_resource_t * src,pool_resource_t * dst,uint64_t size)22480Sstevel@tonic-gate choose_components(pool_resource_t *src, pool_resource_t *dst, uint64_t size)
22490Sstevel@tonic-gate {
22500Sstevel@tonic-gate 	pool_component_t **components = NULL, *moved[] = { NULL, NULL };
22510Sstevel@tonic-gate 	int i;
22520Sstevel@tonic-gate 	uint_t ncomponent;
22530Sstevel@tonic-gate 	pool_conf_t *conf = TO_CONF(TO_ELEM(src));
22540Sstevel@tonic-gate 
22550Sstevel@tonic-gate 	if (size == 0)
22560Sstevel@tonic-gate 		return (PO_SUCCESS);
22570Sstevel@tonic-gate 	/*
22580Sstevel@tonic-gate 	 * Get the component list from our src component.
22590Sstevel@tonic-gate 	 */
22600Sstevel@tonic-gate 	if ((components = pool_query_resource_components(conf, src, &ncomponent,
22610Sstevel@tonic-gate 	    NULL)) == NULL) {
22620Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
22630Sstevel@tonic-gate 		return (PO_FAIL);
22640Sstevel@tonic-gate 	}
22650Sstevel@tonic-gate 	qsort(components, ncomponent, sizeof (pool_elem_t *),
22660Sstevel@tonic-gate 	    qsort_elem_compare);
22670Sstevel@tonic-gate 	/*
22680Sstevel@tonic-gate 	 * Components that aren't specifically requested by the resource
22690Sstevel@tonic-gate 	 * should be transferred out first.
22700Sstevel@tonic-gate 	 */
22710Sstevel@tonic-gate 	for (i = 0; size > 0 && components[i] != NULL; i++) {
22720Sstevel@tonic-gate 		if (!cpu_is_requested(components[i])) {
22730Sstevel@tonic-gate 			moved[0] = components[i];
22740Sstevel@tonic-gate 			if (pool_resource_xtransfer(conf, src, dst, moved) ==
22750Sstevel@tonic-gate 			    PO_SUCCESS) {
22760Sstevel@tonic-gate 				size--;
22770Sstevel@tonic-gate 			}
22780Sstevel@tonic-gate 		}
22790Sstevel@tonic-gate 	}
22800Sstevel@tonic-gate 
22810Sstevel@tonic-gate 	/*
22820Sstevel@tonic-gate 	 * If we couldn't find enough "un-requested" components, select random
22830Sstevel@tonic-gate 	 * requested components.
22840Sstevel@tonic-gate 	 */
22850Sstevel@tonic-gate 	for (i = 0; size > 0 && components[i] != NULL; i++) {
22860Sstevel@tonic-gate 		if (cpu_is_requested(components[i])) {
22870Sstevel@tonic-gate 			moved[0] = components[i];
22880Sstevel@tonic-gate 			if (pool_resource_xtransfer(conf, src, dst, moved) ==
22890Sstevel@tonic-gate 			    PO_SUCCESS) {
22900Sstevel@tonic-gate 				size--;
22910Sstevel@tonic-gate 			}
22920Sstevel@tonic-gate 		}
22930Sstevel@tonic-gate 	}
22940Sstevel@tonic-gate 
22950Sstevel@tonic-gate 	free(components);
22960Sstevel@tonic-gate 	/*
22970Sstevel@tonic-gate 	 * If we couldn't transfer out all the resources we asked for, then
22980Sstevel@tonic-gate 	 * return error.
22990Sstevel@tonic-gate 	 */
23000Sstevel@tonic-gate 	return (size == 0 ? PO_SUCCESS : PO_FAIL);
23010Sstevel@tonic-gate }
23020Sstevel@tonic-gate 
23030Sstevel@tonic-gate /*
23040Sstevel@tonic-gate  * Common processing for a resource transfer (xfer or xxfer).
23050Sstevel@tonic-gate  *
23060Sstevel@tonic-gate  * - Return XFER_CONTINUE if the transfer should proceeed
23070Sstevel@tonic-gate  * - Return XFER_FAIL if the transfer should be stopped in failure
23080Sstevel@tonic-gate  * - Return XFER_SUCCESS if the transfer should be stopped in success
23090Sstevel@tonic-gate  */
23100Sstevel@tonic-gate int
setup_transfer(pool_conf_t * conf,pool_resource_t * src,pool_resource_t * tgt,uint64_t size,uint64_t * src_size,uint64_t * tgt_size)23110Sstevel@tonic-gate setup_transfer(pool_conf_t *conf, pool_resource_t *src, pool_resource_t *tgt,
23120Sstevel@tonic-gate     uint64_t size, uint64_t *src_size, uint64_t *tgt_size)
23130Sstevel@tonic-gate {
23140Sstevel@tonic-gate 	uint64_t src_min;
23150Sstevel@tonic-gate 	uint64_t tgt_max;
23160Sstevel@tonic-gate 
23170Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
23180Sstevel@tonic-gate 		return (XFER_FAIL);
23190Sstevel@tonic-gate 
23200Sstevel@tonic-gate 	/*
23210Sstevel@tonic-gate 	 * Makes sure the two resources are of the same type
23220Sstevel@tonic-gate 	 */
23230Sstevel@tonic-gate 	if (pool_resource_elem_class(TO_ELEM(src)) !=
23240Sstevel@tonic-gate 	    pool_resource_elem_class(TO_ELEM(tgt))) {
23250Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
23260Sstevel@tonic-gate 		return (XFER_FAIL);
23270Sstevel@tonic-gate 	}
23280Sstevel@tonic-gate 
23290Sstevel@tonic-gate 	/*
23300Sstevel@tonic-gate 	 * Transferring to yourself is a no-op
23310Sstevel@tonic-gate 	 */
23320Sstevel@tonic-gate 	if (src == tgt)
23330Sstevel@tonic-gate 		return (XFER_SUCCESS);
23340Sstevel@tonic-gate 
23350Sstevel@tonic-gate 	/*
23360Sstevel@tonic-gate 	 * Transferring nothing is a no-op
23370Sstevel@tonic-gate 	 */
23380Sstevel@tonic-gate 	if (size == 0)
23390Sstevel@tonic-gate 		return (XFER_SUCCESS);
23400Sstevel@tonic-gate 
23410Sstevel@tonic-gate 	if (resource_get_min(src, &src_min) != PO_SUCCESS ||
23420Sstevel@tonic-gate 	    resource_get_size(src, src_size) != PO_SUCCESS ||
23430Sstevel@tonic-gate 	    resource_get_max(tgt, &tgt_max) != PO_SUCCESS ||
23440Sstevel@tonic-gate 	    resource_get_size(tgt, tgt_size) != PO_SUCCESS) {
23450Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
23460Sstevel@tonic-gate 		return (XFER_FAIL);
23470Sstevel@tonic-gate 	}
23480Sstevel@tonic-gate 	if (pool_conf_status(conf) != POF_DESTROY) {
23490Sstevel@tonic-gate 		/*
23500Sstevel@tonic-gate 		 * src_size - donating >= src.min
23510Sstevel@tonic-gate 		 * size + receiving <= tgt.max (except for default)
23520Sstevel@tonic-gate 		 */
23530Sstevel@tonic-gate #ifdef DEBUG
23540Sstevel@tonic-gate 		dprintf("conf is %s\n", pool_conf_location(conf));
23550Sstevel@tonic-gate 		dprintf("setup_transfer: src_size %llu\n", *src_size);
23560Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(src));
23570Sstevel@tonic-gate 		dprintf("setup_transfer: tgt_size %llu\n", *tgt_size);
23580Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(tgt));
23590Sstevel@tonic-gate #endif	/* DEBUG */
23600Sstevel@tonic-gate 		if (*src_size - size < src_min ||
23610Sstevel@tonic-gate 		    (resource_is_default(tgt) == PO_FALSE &&
23620Sstevel@tonic-gate 			*tgt_size + size > tgt_max)) {
23630Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
23640Sstevel@tonic-gate 			return (XFER_FAIL);
23650Sstevel@tonic-gate 		}
23660Sstevel@tonic-gate 	}
23670Sstevel@tonic-gate 	return (XFER_CONTINUE);
23680Sstevel@tonic-gate }
23690Sstevel@tonic-gate 
23700Sstevel@tonic-gate /*
23710Sstevel@tonic-gate  * Transfer resource quantities from one resource set to another.
23720Sstevel@tonic-gate  */
23730Sstevel@tonic-gate int
pool_resource_transfer(pool_conf_t * conf,pool_resource_t * src,pool_resource_t * tgt,uint64_t size)23740Sstevel@tonic-gate pool_resource_transfer(pool_conf_t *conf, pool_resource_t *src,
23750Sstevel@tonic-gate     pool_resource_t *tgt, uint64_t size)
23760Sstevel@tonic-gate {
23770Sstevel@tonic-gate 	uint64_t src_size;
23780Sstevel@tonic-gate 	uint64_t tgt_size;
23790Sstevel@tonic-gate 	int ret;
23800Sstevel@tonic-gate 
23810Sstevel@tonic-gate 	if ((ret = setup_transfer(conf, src, tgt, size, &src_size, &tgt_size))
23820Sstevel@tonic-gate 	    != XFER_CONTINUE)
23830Sstevel@tonic-gate 		return (ret);
23840Sstevel@tonic-gate 	/*
23850Sstevel@tonic-gate 	 * If this resource is a res_comp we must call move components
23860Sstevel@tonic-gate 	 */
23870Sstevel@tonic-gate 	if (pool_elem_class(TO_ELEM(src)) == PEC_RES_COMP)
23880Sstevel@tonic-gate 		return (choose_components(src, tgt, size));
23890Sstevel@tonic-gate 	/*
23900Sstevel@tonic-gate 	 * Now do the transfer.
23910Sstevel@tonic-gate 	 */
23920Sstevel@tonic-gate 	ret = conf->pc_prov->pc_res_xfer(src, tgt, size);
23930Sstevel@tonic-gate 	/*
23940Sstevel@tonic-gate 	 * Modify the sizes of the resource sets if the process was
23950Sstevel@tonic-gate 	 * successful
23960Sstevel@tonic-gate 	 */
23970Sstevel@tonic-gate 	if (ret == PO_SUCCESS) {
23980Sstevel@tonic-gate 		pool_value_t val = POOL_VALUE_INITIALIZER;
23990Sstevel@tonic-gate 
24000Sstevel@tonic-gate 		src_size -= size;
24010Sstevel@tonic-gate 		tgt_size += size;
24020Sstevel@tonic-gate 		pool_value_set_uint64(&val, src_size);
24030Sstevel@tonic-gate 		(void) pool_put_any_ns_property(TO_ELEM(src), c_size_prop,
24040Sstevel@tonic-gate 		    &val);
24050Sstevel@tonic-gate 		pool_value_set_uint64(&val, tgt_size);
24060Sstevel@tonic-gate 		(void) pool_put_any_ns_property(TO_ELEM(tgt), c_size_prop,
24070Sstevel@tonic-gate 		    &val);
24080Sstevel@tonic-gate 	}
24090Sstevel@tonic-gate 	return (ret);
24100Sstevel@tonic-gate }
24110Sstevel@tonic-gate 
24120Sstevel@tonic-gate /*
24130Sstevel@tonic-gate  * Transfer resource components from one resource set to another.
24140Sstevel@tonic-gate  */
24150Sstevel@tonic-gate int
pool_resource_xtransfer(pool_conf_t * conf,pool_resource_t * src,pool_resource_t * tgt,pool_component_t ** rl)24160Sstevel@tonic-gate pool_resource_xtransfer(pool_conf_t *conf, pool_resource_t *src,
24170Sstevel@tonic-gate     pool_resource_t *tgt,
24180Sstevel@tonic-gate     pool_component_t **rl)
24190Sstevel@tonic-gate {
24200Sstevel@tonic-gate 	int i;
24210Sstevel@tonic-gate 	uint64_t src_size;
24220Sstevel@tonic-gate 	uint64_t tgt_size;
24230Sstevel@tonic-gate 	uint64_t size;
24240Sstevel@tonic-gate 	int ret;
24250Sstevel@tonic-gate 
24260Sstevel@tonic-gate 	/*
24270Sstevel@tonic-gate 	 * Make sure the components are all contained in 'src'. This
24280Sstevel@tonic-gate 	 * processing must be done before setup_transfer so that size
24290Sstevel@tonic-gate 	 * is known.
24300Sstevel@tonic-gate 	 */
24310Sstevel@tonic-gate 	for (i = 0; rl[i] != NULL; i++) {
24320Sstevel@tonic-gate #ifdef DEBUG
24330Sstevel@tonic-gate 		dprintf("resource xtransfer\n");
24340Sstevel@tonic-gate 		dprintf("in conf %s\n", pool_conf_location(conf));
24350Sstevel@tonic-gate 		dprintf("transferring component\n");
24360Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(rl[i]));
24370Sstevel@tonic-gate 		dprintf("from\n");
24380Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(src));
24390Sstevel@tonic-gate 		dprintf("to\n");
24400Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(tgt));
24410Sstevel@tonic-gate #endif	/* DEBUG */
24420Sstevel@tonic-gate 
24430Sstevel@tonic-gate 		if (pool_get_owning_resource(conf, rl[i]) != src) {
24440Sstevel@tonic-gate 			pool_seterror(POE_BADPARAM);
24450Sstevel@tonic-gate 			return (PO_FAIL);
24460Sstevel@tonic-gate 		}
24470Sstevel@tonic-gate 	}
24480Sstevel@tonic-gate 
24490Sstevel@tonic-gate 	size = (uint64_t)i;
24500Sstevel@tonic-gate 
24510Sstevel@tonic-gate 	if ((ret = setup_transfer(conf, src, tgt, size, &src_size, &tgt_size))
24520Sstevel@tonic-gate 	    != XFER_CONTINUE)
24530Sstevel@tonic-gate 		return (ret);
24540Sstevel@tonic-gate 
24550Sstevel@tonic-gate 	ret = conf->pc_prov->pc_res_xxfer(src, tgt, rl);
24560Sstevel@tonic-gate 	/*
24570Sstevel@tonic-gate 	 * Modify the sizes of the resource sets if the process was
24580Sstevel@tonic-gate 	 * successful
24590Sstevel@tonic-gate 	 */
24600Sstevel@tonic-gate 	if (ret == PO_SUCCESS) {
24610Sstevel@tonic-gate 		pool_value_t val = POOL_VALUE_INITIALIZER;
24620Sstevel@tonic-gate 
24630Sstevel@tonic-gate #ifdef DEBUG
24640Sstevel@tonic-gate 		dprintf("src_size %llu\n", src_size);
24650Sstevel@tonic-gate 		dprintf("tgt_size %llu\n", tgt_size);
24660Sstevel@tonic-gate 		dprintf("size %llu\n", size);
24670Sstevel@tonic-gate #endif	/* DEBUG */
24680Sstevel@tonic-gate 		src_size -= size;
24690Sstevel@tonic-gate 		tgt_size += size;
24700Sstevel@tonic-gate 		pool_value_set_uint64(&val, src_size);
24710Sstevel@tonic-gate 		(void) pool_put_any_ns_property(TO_ELEM(src), c_size_prop,
24720Sstevel@tonic-gate 		    &val);
24730Sstevel@tonic-gate 		pool_value_set_uint64(&val, tgt_size);
24740Sstevel@tonic-gate 		(void) pool_put_any_ns_property(TO_ELEM(tgt), c_size_prop,
24750Sstevel@tonic-gate 		    &val);
24760Sstevel@tonic-gate 	}
24770Sstevel@tonic-gate 	return (ret);
24780Sstevel@tonic-gate }
24790Sstevel@tonic-gate 
24800Sstevel@tonic-gate /*
24810Sstevel@tonic-gate  * Find the owning resource for a resource component.
24820Sstevel@tonic-gate  */
24830Sstevel@tonic-gate pool_resource_t *
pool_get_owning_resource(const pool_conf_t * conf,const pool_component_t * comp)24840Sstevel@tonic-gate pool_get_owning_resource(const pool_conf_t *conf, const pool_component_t *comp)
24850Sstevel@tonic-gate {
24860Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
24870Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
24880Sstevel@tonic-gate 		return (NULL);
24890Sstevel@tonic-gate 	}
24900Sstevel@tonic-gate 	return (pool_elem_res(pool_get_container(TO_ELEM(comp))));
24910Sstevel@tonic-gate }
24920Sstevel@tonic-gate 
24930Sstevel@tonic-gate /*
24940Sstevel@tonic-gate  * pool_get_container() returns the container of pc.
24950Sstevel@tonic-gate  */
24960Sstevel@tonic-gate pool_elem_t *
pool_get_container(const pool_elem_t * pc)24970Sstevel@tonic-gate pool_get_container(const pool_elem_t *pc)
24980Sstevel@tonic-gate {
24990Sstevel@tonic-gate 	return (pc->pe_get_container(pc));
25000Sstevel@tonic-gate }
25010Sstevel@tonic-gate 
25020Sstevel@tonic-gate /*
25030Sstevel@tonic-gate  * pool_set_container() moves pc so that it is contained by pp.
25040Sstevel@tonic-gate  *
25050Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
25060Sstevel@tonic-gate  */
25070Sstevel@tonic-gate int
pool_set_container(pool_elem_t * pp,pool_elem_t * pc)25080Sstevel@tonic-gate pool_set_container(pool_elem_t *pp, pool_elem_t *pc)
25090Sstevel@tonic-gate {
25100Sstevel@tonic-gate 	return (pc->pe_set_container(pp, pc));
25110Sstevel@tonic-gate }
25120Sstevel@tonic-gate 
25130Sstevel@tonic-gate /*
25140Sstevel@tonic-gate  * Conversion routines for converting to and from elem and it's various
25150Sstevel@tonic-gate  * subtypes of system, pool, res and comp.
25160Sstevel@tonic-gate  */
25170Sstevel@tonic-gate pool_elem_t *
pool_system_elem(const pool_system_t * ph)25180Sstevel@tonic-gate pool_system_elem(const pool_system_t *ph)
25190Sstevel@tonic-gate {
25200Sstevel@tonic-gate 	return ((pool_elem_t *)ph);
25210Sstevel@tonic-gate }
25220Sstevel@tonic-gate 
25230Sstevel@tonic-gate pool_elem_t *
pool_conf_to_elem(const pool_conf_t * conf)25240Sstevel@tonic-gate pool_conf_to_elem(const pool_conf_t *conf)
25250Sstevel@tonic-gate {
25260Sstevel@tonic-gate 	pool_system_t *sys;
25270Sstevel@tonic-gate 
25280Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25290Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25300Sstevel@tonic-gate 		return (NULL);
25310Sstevel@tonic-gate 	}
25320Sstevel@tonic-gate 	if ((sys = pool_conf_system(conf)) == NULL) {
25330Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25340Sstevel@tonic-gate 		return (NULL);
25350Sstevel@tonic-gate 	}
25360Sstevel@tonic-gate 	return (pool_system_elem(sys));
25370Sstevel@tonic-gate }
25380Sstevel@tonic-gate 
25390Sstevel@tonic-gate pool_elem_t *
pool_to_elem(const pool_conf_t * conf,const pool_t * pp)25400Sstevel@tonic-gate pool_to_elem(const pool_conf_t *conf, const pool_t *pp)
25410Sstevel@tonic-gate {
25420Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25430Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25440Sstevel@tonic-gate 		return (NULL);
25450Sstevel@tonic-gate 	}
25460Sstevel@tonic-gate 	return ((pool_elem_t *)pp);
25470Sstevel@tonic-gate }
25480Sstevel@tonic-gate 
25490Sstevel@tonic-gate pool_elem_t *
pool_resource_to_elem(const pool_conf_t * conf,const pool_resource_t * prs)25500Sstevel@tonic-gate pool_resource_to_elem(const pool_conf_t *conf, const pool_resource_t *prs)
25510Sstevel@tonic-gate {
25520Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25530Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25540Sstevel@tonic-gate 		return (NULL);
25550Sstevel@tonic-gate 	}
25560Sstevel@tonic-gate 	return ((pool_elem_t *)prs);
25570Sstevel@tonic-gate }
25580Sstevel@tonic-gate 
25590Sstevel@tonic-gate pool_elem_t *
pool_component_to_elem(const pool_conf_t * conf,const pool_component_t * pr)25600Sstevel@tonic-gate pool_component_to_elem(const pool_conf_t *conf, const pool_component_t *pr)
25610Sstevel@tonic-gate {
25620Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25630Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25640Sstevel@tonic-gate 		return (NULL);
25650Sstevel@tonic-gate 	}
25660Sstevel@tonic-gate 	return ((pool_elem_t *)pr);
25670Sstevel@tonic-gate }
25680Sstevel@tonic-gate 
25690Sstevel@tonic-gate /*
25700Sstevel@tonic-gate  * Walk all the pools of the configuration calling the user supplied function
25710Sstevel@tonic-gate  * as long as the user function continues to return PO_TRUE
25720Sstevel@tonic-gate  */
25730Sstevel@tonic-gate int
pool_walk_pools(pool_conf_t * conf,void * arg,int (* callback)(pool_conf_t * conf,pool_t * pool,void * arg))25740Sstevel@tonic-gate pool_walk_pools(pool_conf_t *conf, void *arg,
25750Sstevel@tonic-gate     int (*callback)(pool_conf_t *conf, pool_t *pool, void *arg))
25760Sstevel@tonic-gate {
25770Sstevel@tonic-gate 	pool_t **rs;
25780Sstevel@tonic-gate 	int i;
25790Sstevel@tonic-gate 	uint_t size;
25800Sstevel@tonic-gate 	int error = PO_SUCCESS;
25810Sstevel@tonic-gate 
25820Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
25830Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
25840Sstevel@tonic-gate 		return (PO_FAIL);
25850Sstevel@tonic-gate 	}
25860Sstevel@tonic-gate 
25870Sstevel@tonic-gate 	if ((rs = pool_query_pools(conf, &size, NULL)) == NULL) /* None */
25880Sstevel@tonic-gate 		return (PO_SUCCESS);
25890Sstevel@tonic-gate 	for (i = 0; i < size; i++)
25900Sstevel@tonic-gate 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
25910Sstevel@tonic-gate 			error = PO_FAIL;
25920Sstevel@tonic-gate 			break;
25930Sstevel@tonic-gate 		}
25940Sstevel@tonic-gate 	free(rs);
25950Sstevel@tonic-gate 	return (error);
25960Sstevel@tonic-gate }
25970Sstevel@tonic-gate 
25980Sstevel@tonic-gate /*
25990Sstevel@tonic-gate  * Walk all the comp of the res calling the user supplied function
26000Sstevel@tonic-gate  * as long as the user function continues to return PO_TRUE
26010Sstevel@tonic-gate  */
26020Sstevel@tonic-gate int
pool_walk_components(pool_conf_t * conf,pool_resource_t * prs,void * arg,int (* callback)(pool_conf_t * conf,pool_component_t * pr,void * arg))26030Sstevel@tonic-gate pool_walk_components(pool_conf_t *conf, pool_resource_t *prs, void *arg,
26040Sstevel@tonic-gate     int (*callback)(pool_conf_t *conf, pool_component_t *pr, void *arg))
26050Sstevel@tonic-gate {
26060Sstevel@tonic-gate 	pool_component_t **rs;
26070Sstevel@tonic-gate 	int i;
26080Sstevel@tonic-gate 	uint_t size;
26090Sstevel@tonic-gate 	int error = PO_SUCCESS;
26100Sstevel@tonic-gate 
26110Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
26120Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
26130Sstevel@tonic-gate 		return (PO_FAIL);
26140Sstevel@tonic-gate 	}
26150Sstevel@tonic-gate 
26160Sstevel@tonic-gate 	if ((rs = pool_query_resource_components(conf, prs, &size, NULL)) ==
26170Sstevel@tonic-gate 	    NULL)
26180Sstevel@tonic-gate 		return (PO_SUCCESS); /* None */
26190Sstevel@tonic-gate 	for (i = 0; i < size; i++)
26200Sstevel@tonic-gate 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
26210Sstevel@tonic-gate 			error = PO_FAIL;
26220Sstevel@tonic-gate 			break;
26230Sstevel@tonic-gate 		}
26240Sstevel@tonic-gate 	free(rs);
26250Sstevel@tonic-gate 	return (error);
26260Sstevel@tonic-gate }
26270Sstevel@tonic-gate 
26280Sstevel@tonic-gate /*
26290Sstevel@tonic-gate  * Return an array of all matching res for the supplied pool.
26300Sstevel@tonic-gate  */
26310Sstevel@tonic-gate pool_resource_t **
pool_query_pool_resources(const pool_conf_t * conf,const pool_t * pp,uint_t * size,pool_value_t ** props)26320Sstevel@tonic-gate pool_query_pool_resources(const pool_conf_t *conf, const pool_t *pp,
26330Sstevel@tonic-gate     uint_t *size, pool_value_t **props)
26340Sstevel@tonic-gate {
26350Sstevel@tonic-gate 	pool_result_set_t *rs;
26360Sstevel@tonic-gate 	pool_elem_t *pe;
26370Sstevel@tonic-gate 	pool_resource_t **result = NULL;
26380Sstevel@tonic-gate 	int i = 0;
26390Sstevel@tonic-gate 
26400Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
26410Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
26420Sstevel@tonic-gate 		return (NULL);
26430Sstevel@tonic-gate 	}
26440Sstevel@tonic-gate 
26450Sstevel@tonic-gate 	pe = TO_ELEM(pp);
26460Sstevel@tonic-gate 
26470Sstevel@tonic-gate 	rs = pool_exec_query(conf, pe, "res", PEC_QRY_RES, props);
26480Sstevel@tonic-gate 	if (rs == NULL) {
26490Sstevel@tonic-gate 		return (NULL);
26500Sstevel@tonic-gate 	}
26510Sstevel@tonic-gate 	if ((*size = pool_rs_count(rs)) == 0) {
26520Sstevel@tonic-gate 		(void) pool_rs_close(rs);
26530Sstevel@tonic-gate 		return (NULL);
26540Sstevel@tonic-gate 	}
26550Sstevel@tonic-gate 	if ((result = malloc(sizeof (pool_resource_t *) * (*size + 1)))
26560Sstevel@tonic-gate 	    == NULL) {
26570Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
26580Sstevel@tonic-gate 		(void) pool_rs_close(rs);
26590Sstevel@tonic-gate 		return (NULL);
26600Sstevel@tonic-gate 	}
26610Sstevel@tonic-gate 	(void) memset(result, 0, sizeof (pool_resource_t *) * (*size + 1));
26620Sstevel@tonic-gate 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
26630Sstevel@tonic-gate 		if (pool_elem_class(pe) != PEC_RES_COMP &&
26640Sstevel@tonic-gate 		    pool_elem_class(pe) != PEC_RES_AGG) {
26650Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
26660Sstevel@tonic-gate 			free(result);
26670Sstevel@tonic-gate 			(void) pool_rs_close(rs);
26680Sstevel@tonic-gate 			return (NULL);
26690Sstevel@tonic-gate 		}
26700Sstevel@tonic-gate 		result[i++] = pool_elem_res(pe);
26710Sstevel@tonic-gate 	}
26720Sstevel@tonic-gate 	(void) pool_rs_close(rs);
26730Sstevel@tonic-gate 	return (result);
26740Sstevel@tonic-gate }
26750Sstevel@tonic-gate 
26760Sstevel@tonic-gate /*
26770Sstevel@tonic-gate  * Walk all the res of the pool calling the user supplied function
26780Sstevel@tonic-gate  * as long as the user function continues to return PO_TRUE
26790Sstevel@tonic-gate  */
26800Sstevel@tonic-gate int
pool_walk_resources(pool_conf_t * conf,pool_t * pp,void * arg,int (* callback)(pool_conf_t *,pool_resource_t *,void *))26810Sstevel@tonic-gate pool_walk_resources(pool_conf_t *conf, pool_t *pp, void *arg,
26820Sstevel@tonic-gate     int (*callback)(pool_conf_t *, pool_resource_t *, void *))
26830Sstevel@tonic-gate {
26840Sstevel@tonic-gate 	pool_resource_t **rs;
26850Sstevel@tonic-gate 	int i;
26860Sstevel@tonic-gate 	uint_t size;
26870Sstevel@tonic-gate 	int error = PO_SUCCESS;
26880Sstevel@tonic-gate 
26890Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
26900Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
26910Sstevel@tonic-gate 		return (PO_FAIL);
26920Sstevel@tonic-gate 	}
26930Sstevel@tonic-gate 	if ((rs = pool_query_pool_resources(conf, pp, &size, NULL)) == NULL)
26940Sstevel@tonic-gate 		return (PO_SUCCESS); /* None */
26950Sstevel@tonic-gate 	for (i = 0; i < size; i++)
26960Sstevel@tonic-gate 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
26970Sstevel@tonic-gate 			error = PO_FAIL;
26980Sstevel@tonic-gate 			break;
26990Sstevel@tonic-gate 		}
27000Sstevel@tonic-gate 	free(rs);
27010Sstevel@tonic-gate 	return (error);
27020Sstevel@tonic-gate }
27030Sstevel@tonic-gate 
27040Sstevel@tonic-gate /*
27050Sstevel@tonic-gate  * Return a result set of all comp for the supplied res.
27060Sstevel@tonic-gate  */
27070Sstevel@tonic-gate pool_component_t **
pool_query_resource_components(const pool_conf_t * conf,const pool_resource_t * prs,uint_t * size,pool_value_t ** props)27080Sstevel@tonic-gate pool_query_resource_components(const pool_conf_t *conf,
27090Sstevel@tonic-gate     const pool_resource_t *prs, uint_t *size, pool_value_t **props)
27100Sstevel@tonic-gate {
27110Sstevel@tonic-gate 	pool_result_set_t *rs;
27120Sstevel@tonic-gate 	pool_elem_t *pe;
27130Sstevel@tonic-gate 	pool_component_t **result = NULL;
27140Sstevel@tonic-gate 	int i = 0;
27150Sstevel@tonic-gate 
27160Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
27170Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
27180Sstevel@tonic-gate 		return (NULL);
27190Sstevel@tonic-gate 	}
27200Sstevel@tonic-gate 	pe = TO_ELEM(prs);
27210Sstevel@tonic-gate 
27220Sstevel@tonic-gate 	rs = pool_exec_query(conf, pe, NULL, PEC_QRY_COMP, props);
27230Sstevel@tonic-gate 	if (rs == NULL) {
27240Sstevel@tonic-gate 		return (NULL);
27250Sstevel@tonic-gate 	}
27260Sstevel@tonic-gate 	if ((*size = pool_rs_count(rs)) == 0) {
27270Sstevel@tonic-gate 		(void) pool_rs_close(rs);
27280Sstevel@tonic-gate 		return (NULL);
27290Sstevel@tonic-gate 	}
27300Sstevel@tonic-gate 	if ((result = malloc(sizeof (pool_component_t *) * (*size + 1)))
27310Sstevel@tonic-gate 	    == NULL) {
27320Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
27330Sstevel@tonic-gate 		(void) pool_rs_close(rs);
27340Sstevel@tonic-gate 		return (NULL);
27350Sstevel@tonic-gate 	}
27360Sstevel@tonic-gate 	(void) memset(result, 0, sizeof (pool_component_t *) * (*size + 1));
27370Sstevel@tonic-gate 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
27380Sstevel@tonic-gate 		if (pool_elem_class(pe) != PEC_COMP) {
27390Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
27400Sstevel@tonic-gate 			free(result);
27410Sstevel@tonic-gate 			(void) pool_rs_close(rs);
27420Sstevel@tonic-gate 			return (NULL);
27430Sstevel@tonic-gate 		}
27440Sstevel@tonic-gate 		result[i++] = pool_elem_comp(pe);
27450Sstevel@tonic-gate 	}
27460Sstevel@tonic-gate 	(void) pool_rs_close(rs);
27470Sstevel@tonic-gate 	return (result);
27480Sstevel@tonic-gate }
27490Sstevel@tonic-gate 
27500Sstevel@tonic-gate /*
27510Sstevel@tonic-gate  * pool_version() returns the version of this library, depending on the supplied
27520Sstevel@tonic-gate  * parameter.
27530Sstevel@tonic-gate  *
27540Sstevel@tonic-gate  * Returns: library version depening on the supplied ver parameter.
27550Sstevel@tonic-gate  */
27560Sstevel@tonic-gate uint_t
pool_version(uint_t ver)27570Sstevel@tonic-gate pool_version(uint_t ver)
27580Sstevel@tonic-gate {
27590Sstevel@tonic-gate 	switch (ver) {
27600Sstevel@tonic-gate 	case POOL_VER_NONE:
27610Sstevel@tonic-gate 		break;
27620Sstevel@tonic-gate 	case POOL_VER_CURRENT:
27630Sstevel@tonic-gate 		pool_workver = ver;
27640Sstevel@tonic-gate 		break;
27650Sstevel@tonic-gate 	default:
27660Sstevel@tonic-gate 		return (POOL_VER_NONE);
27670Sstevel@tonic-gate 	}
27680Sstevel@tonic-gate 	return (pool_workver);
27690Sstevel@tonic-gate }
27700Sstevel@tonic-gate 
27710Sstevel@tonic-gate /*
27720Sstevel@tonic-gate  * pool_associate() associates the supplied resource to the supplied pool.
27730Sstevel@tonic-gate  *
27740Sstevel@tonic-gate  * Returns: PO_SUCCESS/PO_FAIL
27750Sstevel@tonic-gate  */
27760Sstevel@tonic-gate int
pool_associate(pool_conf_t * conf,pool_t * pool,const pool_resource_t * res)27770Sstevel@tonic-gate pool_associate(pool_conf_t *conf, pool_t *pool, const pool_resource_t *res)
27780Sstevel@tonic-gate {
27790Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
27800Sstevel@tonic-gate 		return (PO_FAIL);
27810Sstevel@tonic-gate 
27820Sstevel@tonic-gate 	return (pool->pp_associate(pool, res));
27830Sstevel@tonic-gate }
27840Sstevel@tonic-gate 
27850Sstevel@tonic-gate /*
27860Sstevel@tonic-gate  * pool_dissociate() dissociates the supplied resource from the supplied pool.
27870Sstevel@tonic-gate  *
27880Sstevel@tonic-gate  * Returns: PO_SUCCESS/PO_FAIL
27890Sstevel@tonic-gate  */
27900Sstevel@tonic-gate int
pool_dissociate(pool_conf_t * conf,pool_t * pool,const pool_resource_t * res)27910Sstevel@tonic-gate pool_dissociate(pool_conf_t *conf, pool_t *pool, const pool_resource_t *res)
27920Sstevel@tonic-gate {
27930Sstevel@tonic-gate 	if (pool_conf_check(conf) != PO_SUCCESS)
27940Sstevel@tonic-gate 		return (PO_FAIL);
27950Sstevel@tonic-gate 
27960Sstevel@tonic-gate 	if (elem_is_default(TO_ELEM(res)))
27970Sstevel@tonic-gate 		return (PO_SUCCESS);
27980Sstevel@tonic-gate 	return (pool->pp_dissociate(pool, res));
27990Sstevel@tonic-gate }
28000Sstevel@tonic-gate 
28010Sstevel@tonic-gate /*
28020Sstevel@tonic-gate  * Compare two elements for purposes of ordering.
28030Sstevel@tonic-gate  * Return:
28040Sstevel@tonic-gate  *	< 0 if e1 is "before" e2
28050Sstevel@tonic-gate  *	0 if e1 "equals" e2
28060Sstevel@tonic-gate  *	> 0 if e1 comes after e2
28070Sstevel@tonic-gate  */
28080Sstevel@tonic-gate int
pool_elem_compare_name(const pool_elem_t * e1,const pool_elem_t * e2)28090Sstevel@tonic-gate pool_elem_compare_name(const pool_elem_t *e1, const pool_elem_t *e2)
28100Sstevel@tonic-gate {
28110Sstevel@tonic-gate 	char *name1, *name2;
28120Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
28130Sstevel@tonic-gate 	int retval;
28140Sstevel@tonic-gate 
28150Sstevel@tonic-gate 	/*
28160Sstevel@tonic-gate 	 * We may be asked to compare two elements from different classes.
28170Sstevel@tonic-gate 	 * They are different so return (1).
28180Sstevel@tonic-gate 	 */
28190Sstevel@tonic-gate 	if (pool_elem_same_class(e1, e2) != PO_TRUE)
28200Sstevel@tonic-gate 		return (1);
28210Sstevel@tonic-gate 
28220Sstevel@tonic-gate 	/*
28230Sstevel@tonic-gate 	 * If the class is PEC_SYSTEM, always match them
28240Sstevel@tonic-gate 	 */
28250Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_SYSTEM)
28260Sstevel@tonic-gate 		return (0);
28270Sstevel@tonic-gate 
28280Sstevel@tonic-gate 	/*
28290Sstevel@tonic-gate 	 * If we are going to compare components, then use sys_id
28300Sstevel@tonic-gate 	 */
28310Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_COMP) {
28320Sstevel@tonic-gate 		int64_t sys_id1, sys_id2;
28330Sstevel@tonic-gate 
28340Sstevel@tonic-gate 		if (pool_get_ns_property(e1, c_sys_prop, &val) == POC_INVAL) {
28350Sstevel@tonic-gate 			return (-1);
28360Sstevel@tonic-gate 		}
28370Sstevel@tonic-gate 		(void) pool_value_get_int64(&val, &sys_id1);
28380Sstevel@tonic-gate 		if (pool_get_ns_property(e2, c_sys_prop, &val) == POC_INVAL) {
28390Sstevel@tonic-gate 			return (-1);
28400Sstevel@tonic-gate 		}
28410Sstevel@tonic-gate 		(void) pool_value_get_int64(&val, &sys_id2);
28420Sstevel@tonic-gate 		retval = (sys_id1 - sys_id2);
28430Sstevel@tonic-gate 	} else {
28440Sstevel@tonic-gate 		if (pool_get_ns_property(e1, "name", &val) == POC_INVAL) {
28450Sstevel@tonic-gate 			return (-1);
28460Sstevel@tonic-gate 		}
28470Sstevel@tonic-gate 		(void) pool_value_get_string(&val, (const char **)&name1);
28480Sstevel@tonic-gate 		if ((name1 = strdup(name1)) == NULL) {
28490Sstevel@tonic-gate 			return (-1);
28500Sstevel@tonic-gate 		}
28510Sstevel@tonic-gate 
28520Sstevel@tonic-gate 		if (pool_get_ns_property(e2, "name", &val) == POC_INVAL) {
28530Sstevel@tonic-gate 			return (-1);
28540Sstevel@tonic-gate 		}
28550Sstevel@tonic-gate 
28560Sstevel@tonic-gate 		(void) pool_value_get_string(&val, (const char **)&name2);
28570Sstevel@tonic-gate 		retval = strcmp(name1, name2);
28580Sstevel@tonic-gate 		free(name1);
28590Sstevel@tonic-gate 	}
28600Sstevel@tonic-gate 	return (retval);
28610Sstevel@tonic-gate }
28620Sstevel@tonic-gate 
28630Sstevel@tonic-gate /*
28640Sstevel@tonic-gate  * Compare two elements for purposes of ordering.
28650Sstevel@tonic-gate  * Return:
28660Sstevel@tonic-gate  *	< 0 if e1 is "before" e2
28670Sstevel@tonic-gate  *	0 if e1 "equals" e2
28680Sstevel@tonic-gate  *	> 0 if e1 comes after e2
28690Sstevel@tonic-gate  */
28700Sstevel@tonic-gate int
pool_elem_compare(const pool_elem_t * e1,const pool_elem_t * e2)28710Sstevel@tonic-gate pool_elem_compare(const pool_elem_t *e1, const pool_elem_t *e2)
28720Sstevel@tonic-gate {
28730Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
28740Sstevel@tonic-gate 	int64_t sys_id1, sys_id2;
28750Sstevel@tonic-gate 
28760Sstevel@tonic-gate 	/*
28770Sstevel@tonic-gate 	 * We may be asked to compare two elements from different classes.
28780Sstevel@tonic-gate 	 * They are different so return the difference in their classes
28790Sstevel@tonic-gate 	 */
28800Sstevel@tonic-gate 	if (pool_elem_same_class(e1, e2) != PO_TRUE)
28810Sstevel@tonic-gate 		return (1);
28820Sstevel@tonic-gate 
28830Sstevel@tonic-gate 	/*
28840Sstevel@tonic-gate 	 * If the class is PEC_SYSTEM, always match them
28850Sstevel@tonic-gate 	 */
28860Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_SYSTEM)
28870Sstevel@tonic-gate 		return (0);
28880Sstevel@tonic-gate 
28890Sstevel@tonic-gate 	/*
28900Sstevel@tonic-gate 	 * Compare with sys_id
28910Sstevel@tonic-gate 	 */
28920Sstevel@tonic-gate 	if (pool_get_ns_property(e1, c_sys_prop, &val) == POC_INVAL) {
28930Sstevel@tonic-gate 		assert(!"no sys_id on e1\n");
28940Sstevel@tonic-gate 	}
28950Sstevel@tonic-gate 	(void) pool_value_get_int64(&val, &sys_id1);
28960Sstevel@tonic-gate 	if (pool_get_ns_property(e2, c_sys_prop, &val) == POC_INVAL) {
28970Sstevel@tonic-gate 		assert(!"no sys_id on e2\n");
28980Sstevel@tonic-gate 	}
28990Sstevel@tonic-gate 	(void) pool_value_get_int64(&val, &sys_id2);
29000Sstevel@tonic-gate 	return (sys_id1 - sys_id2);
29010Sstevel@tonic-gate }
29020Sstevel@tonic-gate 
29030Sstevel@tonic-gate /*
29040Sstevel@tonic-gate  * Return PO_TRUE if the supplied elems are of the same class.
29050Sstevel@tonic-gate  */
29060Sstevel@tonic-gate int
pool_elem_same_class(const pool_elem_t * e1,const pool_elem_t * e2)29070Sstevel@tonic-gate pool_elem_same_class(const pool_elem_t *e1, const pool_elem_t *e2)
29080Sstevel@tonic-gate {
29090Sstevel@tonic-gate 	if (pool_elem_class(e1) != pool_elem_class(e2))
29100Sstevel@tonic-gate 		return (PO_FALSE);
29110Sstevel@tonic-gate 
29120Sstevel@tonic-gate 	/*
29130Sstevel@tonic-gate 	 * Check to make sure the fundamental class of the elements match
29140Sstevel@tonic-gate 	 */
29150Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_RES_COMP ||
29160Sstevel@tonic-gate 	    pool_elem_class(e1) == PEC_RES_AGG)
29170Sstevel@tonic-gate 		if (pool_resource_elem_class(e1) !=
29180Sstevel@tonic-gate 		    pool_resource_elem_class(e2))
29190Sstevel@tonic-gate 			return (PO_FALSE);
29200Sstevel@tonic-gate 	if (pool_elem_class(e1) == PEC_COMP)
29210Sstevel@tonic-gate 		if (pool_component_elem_class(e1) !=
29220Sstevel@tonic-gate 		    pool_component_elem_class(e2))
29230Sstevel@tonic-gate 			return (PO_FALSE);
29240Sstevel@tonic-gate 	return (PO_TRUE);
29250Sstevel@tonic-gate }
29260Sstevel@tonic-gate 
29270Sstevel@tonic-gate /*
29280Sstevel@tonic-gate  * pool_conf_check() checks that the configuration state isn't invalid
29290Sstevel@tonic-gate  * and that the configuration was opened for modification.
29300Sstevel@tonic-gate  */
29310Sstevel@tonic-gate int
pool_conf_check(const pool_conf_t * conf)29320Sstevel@tonic-gate pool_conf_check(const pool_conf_t *conf)
29330Sstevel@tonic-gate {
29340Sstevel@tonic-gate 	if (pool_conf_status(conf) == POF_INVALID) {
29350Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
29360Sstevel@tonic-gate 		return (PO_FAIL);
29370Sstevel@tonic-gate 	}
29380Sstevel@tonic-gate 
29390Sstevel@tonic-gate 	if ((conf->pc_prov->pc_oflags & PO_RDWR) == 0) {
29400Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
29410Sstevel@tonic-gate 		return (PO_FAIL);
29420Sstevel@tonic-gate 	}
29430Sstevel@tonic-gate 	return (PO_SUCCESS);
29440Sstevel@tonic-gate }
2945