Home | History | Annotate | Download | only in common
      1     0    stevel /*
      2     0    stevel  * CDDL HEADER START
      3     0    stevel  *
      4     0    stevel  * The contents of this file are subject to the terms of the
      5  1823   garypen  * Common Development and Distribution License (the "License").
      6  1823   garypen  * You may not use this file except in compliance with the License.
      7     0    stevel  *
      8     0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0    stevel  * or http://www.opensolaris.org/os/licensing.
     10     0    stevel  * See the License for the specific language governing permissions
     11     0    stevel  * and limitations under the License.
     12     0    stevel  *
     13     0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0    stevel  *
     19     0    stevel  * CDDL HEADER END
     20     0    stevel  */
     21  1823   garypen 
     22     0    stevel /*
     23  3864       raf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     24     0    stevel  * Use is subject to license terms.
     25     0    stevel  */
     26     0    stevel 
     27     0    stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28     0    stevel 
     29     0    stevel #include <assert.h>
     30     0    stevel #include <stdio.h>
     31     0    stevel #include <stdlib.h>
     32     0    stevel #include <string.h>
     33     0    stevel #include <thread.h>
     34  3864       raf #include <pthread.h>
     35     0    stevel #include <synch.h>
     36     0    stevel #include <unistd.h>
     37     0    stevel #include <stropts.h>
     38     0    stevel #include <fcntl.h>
     39     0    stevel #include <note.h>
     40     0    stevel #include <errno.h>
     41     0    stevel #include <ctype.h>
     42     0    stevel #include <libintl.h>
     43  3251  sl108498 #include <libscf.h>
     44     0    stevel #include <pool.h>
     45     0    stevel #include <signal.h>
     46     0    stevel 
     47     0    stevel #include <sys/pool.h>
     48     0    stevel #include <sys/priocntl.h>
     49     0    stevel #include <sys/types.h>
     50     0    stevel #include <sys/stat.h>
     51     0    stevel #include <sys/wait.h>
     52     0    stevel 
     53     0    stevel #include "pool_internal.h"
     54     0    stevel #include "pool_impl.h"
     55     0    stevel 
     56     0    stevel /*
     57     0    stevel  * libpool Interface Routines
     58     0    stevel  *
     59     0    stevel  * pool.c implements (most of) the external interface to libpool
     60     0    stevel  * users. Some of the interface is implemented in pool_internal.c for
     61     0    stevel  * reasons of internal code organisation.  The core requirements for
     62     0    stevel  * pool.c are:
     63     0    stevel  *
     64     0    stevel  * Data Abstraction
     65     0    stevel  *
     66     0    stevel  * The abstraction of the actual datastore so that no details of the
     67     0    stevel  * underlying data representation mechanism are revealed to users of
     68     0    stevel  * the library. For instance, the fact that we use the kernel or files
     69     0    stevel  * to store our configurations is completely abstracted via the
     70     0    stevel  * various libpool APIs.
     71     0    stevel  *
     72     0    stevel  * External Interaction
     73     0    stevel  *
     74     0    stevel  * libpool users manipulate configuration components via the API
     75     0    stevel  * defined in pool.h. Most functions in this file act as interceptors,
     76     0    stevel  * validating parameters before redirecting the request into a
     77     0    stevel  * specific datastore implementation for the actual work to be done.
     78     0    stevel  *
     79     0    stevel  * These main sets of requirements have driven the design so that it
     80     0    stevel  * is possible to replace the entire datastore type without having to
     81     0    stevel  * modify the external (or internal provider) APIs. It is possible to
     82     0    stevel  * modify the storage technology used by libpool by implementing a new
     83     0    stevel  * set of datastore provider operations. Simply modify the
     84     0    stevel  * pool_conf_open() routine to establish a new datastore as the
     85     0    stevel  * provider for a configuration.
     86     0    stevel  *
     87     0    stevel  * The key components in a libpool configuration are :
     88     0    stevel  * pool_conf_t - This represents a complete configuration instance
     89     0    stevel  * pool_t - A pool inside a configuration
     90     0    stevel  * pool_resource_t - A resource inside a configuration
     91     0    stevel  * pool_component_t - A component of a resource
     92     0    stevel  *
     93     0    stevel  */
     94     0    stevel 
     95     0    stevel /*
     96     0    stevel  * Used to control transfer setup.
     97     0    stevel  */
     98     0    stevel #define	XFER_FAIL	PO_FAIL
     99     0    stevel #define	XFER_SUCCESS	PO_SUCCESS
    100     0    stevel #define	XFER_CONTINUE	1
    101     0    stevel 
    102  1042   garypen #define	SMF_SVC_INSTANCE	"svc:/system/pools:default"
    103     0    stevel #define	E_ERROR		1		/* Exit status for error */
    104     0    stevel 
    105     0    stevel #ifndef	TEXT_DOMAIN
    106     0    stevel #define	TEXT_DOMAIN	"SYS_TEST"
    107     0    stevel #endif	/* TEXT_DOMAIN */
    108     0    stevel 
    109     0    stevel const char pool_info_location[] =  "/dev/pool";
    110     0    stevel 
    111     0    stevel /*
    112     0    stevel  * Static data
    113     0    stevel  */
    114     0    stevel static const char static_location[] = "/etc/pooladm.conf";
    115     0    stevel static const char dynamic_location[] =  "/dev/poolctl";
    116  3864       raf static thread_key_t	errkey = THR_ONCE_KEY;
    117     0    stevel 
    118     0    stevel /*
    119     0    stevel  * libpool error code
    120     0    stevel  */
    121     0    stevel static int pool_errval = POE_OK;
    122     0    stevel 
    123     0    stevel /*
    124     0    stevel  * libpool version
    125     0    stevel  */
    126     0    stevel static uint_t pool_workver = POOL_VER_CURRENT;
    127     0    stevel 
    128     0    stevel static const char *data_type_tags[] = {
    129     0    stevel 	"uint",
    130     0    stevel 	"int",
    131     0    stevel 	"float",
    132     0    stevel 	"boolean",
    133     0    stevel 	"string"
    134     0    stevel };
    135     0    stevel 
    136     0    stevel /*
    137     0    stevel  * static functions
    138     0    stevel  */
    139     0    stevel static int pool_elem_remove(pool_elem_t *);
    140     0    stevel static int is_valid_prop_name(const char *);
    141     0    stevel static int prop_buf_build_cb(pool_conf_t *, pool_elem_t *, const char *,
    142     0    stevel     pool_value_t *, void *);
    143     0    stevel static char *pool_base_info(const pool_elem_t *, char_buf_t *, int);
    144     0    stevel static int choose_components(pool_resource_t *, pool_resource_t *, uint64_t);
    145     0    stevel static int pool_conf_check(const pool_conf_t *);
    146     0    stevel static void free_value_list(int, pool_value_t **);
    147     0    stevel static int setup_transfer(pool_conf_t *, pool_resource_t *, pool_resource_t *,
    148     0    stevel     uint64_t, uint64_t *, uint64_t *);
    149     0    stevel 
    150     0    stevel /*
    151     0    stevel  * Return the "static" location string for libpool.
    152     0    stevel  */
    153     0    stevel const char *
    154     0    stevel pool_static_location(void)
    155     0    stevel {
    156     0    stevel 	return (static_location);
    157     0    stevel }
    158     0    stevel 
    159     0    stevel /*
    160     0    stevel  * Return the "dynamic" location string for libpool.
    161     0    stevel  */
    162     0    stevel const char *
    163     0    stevel pool_dynamic_location(void)
    164     0    stevel {
    165     0    stevel 	return (dynamic_location);
    166     0    stevel }
    167     0    stevel 
    168     0    stevel /*
    169     0    stevel  * Return the status for a configuration. If the configuration has
    170     0    stevel  * been successfully opened, then the status will be POF_VALID or
    171     0    stevel  * POF_DESTROY.  If the configuration failed to open properly or has
    172     0    stevel  * been closed or removed, then the status will be POF_INVALID.
    173     0    stevel  */
    174     0    stevel pool_conf_state_t
    175     0    stevel pool_conf_status(const pool_conf_t *conf)
    176     0    stevel {
    177     0    stevel 	return (conf->pc_state);
    178     0    stevel }
    179     0    stevel 
    180     0    stevel /*
    181     0    stevel  * Bind idtype id to the pool name.
    182     0    stevel  */
    183     0    stevel int
    184     0    stevel pool_set_binding(const char *pool_name, idtype_t idtype, id_t id)
    185     0    stevel {
    186     0    stevel 	pool_conf_t *conf;
    187     0    stevel 	int result;
    188     0    stevel 
    189     0    stevel 	if ((conf = pool_conf_alloc()) == NULL)
    190     0    stevel 		return (PO_FAIL);
    191     0    stevel 
    192     0    stevel 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
    193     0    stevel 		pool_conf_free(conf);
    194     0    stevel 		pool_seterror(POE_INVALID_CONF);
    195     0    stevel 		return (PO_FAIL);
    196     0    stevel 	}
    197     0    stevel 
    198     0    stevel 	result = conf->pc_prov->pc_set_binding(conf, pool_name, idtype, id);
    199     0    stevel 
    200     0    stevel 	(void) pool_conf_close(conf);
    201     0    stevel 	pool_conf_free(conf);
    202     0    stevel 	return (result);
    203     0    stevel }
    204     0    stevel 
    205     0    stevel /*
    206     0    stevel  * pool_get_resource_binding() returns the binding for a pid to the supplied
    207     0    stevel  * type of resource. If a binding cannot be determined, NULL is returned.
    208     0    stevel  */
    209     0    stevel char *
    210     0    stevel pool_get_resource_binding(const char *sz_type, pid_t pid)
    211     0    stevel {
    212     0    stevel 	pool_conf_t *conf;
    213     0    stevel 	char *result;
    214     0    stevel 	pool_resource_elem_class_t type;
    215     0    stevel 
    216     0    stevel 	if ((type = pool_resource_elem_class_from_string(sz_type)) ==
    217     0    stevel 	    PREC_INVALID) {
    218     0    stevel 		pool_seterror(POE_BADPARAM);
    219     0    stevel 		return (NULL);
    220     0    stevel 	}
    221     0    stevel 
    222     0    stevel 	if ((conf = pool_conf_alloc()) == NULL)
    223     0    stevel 		return (NULL);
    224     0    stevel 
    225     0    stevel 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY)
    226     0    stevel 	    != PO_SUCCESS) {
    227     0    stevel 		pool_seterror(POE_INVALID_CONF);
    228     0    stevel 		pool_conf_free(conf);
    229     0    stevel 		return (NULL);
    230     0    stevel 	}
    231     0    stevel 	result = conf->pc_prov->pc_get_resource_binding(conf, type, pid);
    232     0    stevel 	(void) pool_conf_close(conf);
    233     0    stevel 	pool_conf_free(conf);
    234     0    stevel 	return (result);
    235     0    stevel }
    236     0    stevel 
    237     0    stevel /*
    238     0    stevel  * pool_get_binding() returns the binding for a pid to a pool. If a
    239     0    stevel  * binding cannot be determined, NULL is returned.
    240     0    stevel  */
    241     0    stevel char *
    242     0    stevel pool_get_binding(pid_t pid)
    243     0    stevel {
    244     0    stevel 	pool_conf_t *conf;
    245     0    stevel 	char *result;
    246     0    stevel 
    247     0    stevel 	if ((conf = pool_conf_alloc()) == NULL)
    248     0    stevel 		return (NULL);
    249     0    stevel 
    250     0    stevel 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY)
    251     0    stevel 	    != PO_SUCCESS) {
    252     0    stevel 		pool_seterror(POE_INVALID_CONF);
    253     0    stevel 		pool_conf_free(conf);
    254     0    stevel 		return (NULL);
    255     0    stevel 	}
    256     0    stevel 	result = conf->pc_prov->pc_get_binding(conf, pid);
    257     0    stevel 	(void) pool_conf_close(conf);
    258     0    stevel 	pool_conf_free(conf);
    259     0    stevel 	return (result);
    260     0    stevel }
    261     0    stevel 
    262     0    stevel /*ARGSUSED*/
    263     0    stevel int
    264     0    stevel prop_buf_build_cb(pool_conf_t *UNUSED, pool_elem_t *pe, const char *name,
    265     0    stevel     pool_value_t *pval, void *user)
    266     0    stevel {
    267     0    stevel 	uint64_t u;
    268     0    stevel 	int64_t i;
    269     0    stevel 	uchar_t bool;
    270     0    stevel 	const char *str;
    271     0    stevel 	double d;
    272     0    stevel 	char_buf_t *cb = (char_buf_t *)user;
    273     0    stevel 	int type = pool_value_get_type(pval);
    274     0    stevel 
    275     0    stevel 	/*
    276     0    stevel 	 * Ignore "type" and "<type>.name" properties as these are not
    277     0    stevel 	 * to be displayed by this function
    278     0    stevel 	 */
    279     0    stevel 	if (strcmp(name, c_type) == 0 ||
    280     0    stevel 	    strcmp(property_name_minus_ns(pe, name), c_name) == 0)
    281     0    stevel 		return (PO_SUCCESS);
    282     0    stevel 	if (append_char_buf(cb, "\n%s\t%s\t%s ", cb->cb_tab_buf,
    283     0    stevel 	    data_type_tags[type], name) == PO_FAIL)
    284     0    stevel 		return (PO_FAIL);
    285     0    stevel 	switch (type) {
    286     0    stevel 	case POC_UINT:
    287     0    stevel 		(void) pool_value_get_uint64(pval, &u);
    288     0    stevel 		if (append_char_buf(cb, "%llu", (u_longlong_t)u) == PO_FAIL)
    289     0    stevel 			return (PO_FAIL);
    290     0    stevel 		break;
    291     0    stevel 	case POC_INT:
    292     0    stevel 		(void) pool_value_get_int64(pval, &i);
    293     0    stevel 		if (append_char_buf(cb, "%lld", (longlong_t)i) == PO_FAIL)
    294     0    stevel 			return (PO_FAIL);
    295     0    stevel 		break;
    296     0    stevel 	case POC_STRING:
    297     0    stevel 		(void) pool_value_get_string(pval, &str);
    298     0    stevel 		if (append_char_buf(cb, "%s", str) == PO_FAIL)
    299     0    stevel 			return (PO_FAIL);
    300     0    stevel 		break;
    301     0    stevel 	case POC_BOOL:
    302     0    stevel 		(void) pool_value_get_bool(pval, &bool);
    303     0    stevel 		if (bool == 0) {
    304     0    stevel 			if (append_char_buf(cb, "%s", "false") == PO_FAIL)
    305     0    stevel 				return (PO_FAIL);
    306     0    stevel 		} else {
    307     0    stevel 			if (append_char_buf(cb, "%s", "true") == PO_FAIL)
    308     0    stevel 				return (PO_FAIL);
    309     0    stevel 		}
    310     0    stevel 		break;
    311     0    stevel 	case POC_DOUBLE:
    312     0    stevel 		(void) pool_value_get_double(pval, &d);
    313     0    stevel 		if (append_char_buf(cb, "%g", d) == PO_FAIL)
    314     0    stevel 			return (PO_FAIL);
    315     0    stevel 		break;
    316     0    stevel 	case POC_INVAL: /* Do nothing */
    317     0    stevel 		break;
    318     0    stevel 	default:
    319     0    stevel 		return (PO_FAIL);
    320     0    stevel 	}
    321     0    stevel 	return (PO_SUCCESS);
    322     0    stevel }
    323     0    stevel 
    324     0    stevel /*
    325     0    stevel  * Return a buffer which describes the element
    326     0    stevel  * pe is a pointer to the element
    327     0    stevel  * deep is PO_TRUE/PO_FALSE to indicate whether children should be included
    328     0    stevel  */
    329     0    stevel char *
    330     0    stevel pool_base_info(const pool_elem_t *pe, char_buf_t *cb, int deep)
    331     0    stevel {
    332     0    stevel 	const char *sres;
    333     0    stevel 	uint_t i;
    334     0    stevel 	uint_t nelem;
    335     0    stevel 
    336     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
    337     0    stevel 	pool_resource_t **rs;
    338     0    stevel 	pool_elem_t *elem;
    339     0    stevel 	pool_conf_t *conf = TO_CONF(pe);
    340     0    stevel 
    341     0    stevel 	if (cb == NULL) {
    342     0    stevel 		char *ret = NULL;
    343     0    stevel 
    344     0    stevel 		if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
    345     0    stevel 			return (NULL);
    346     0    stevel 
    347     0    stevel 		/*
    348     0    stevel 		 * Populate the buffer with element details
    349     0    stevel 		 */
    350     0    stevel 		(void) pool_base_info(pe, cb, deep);
    351     0    stevel 		if (cb->cb_buf)
    352     0    stevel 			ret = strdup(cb->cb_buf);
    353     0    stevel 		free_char_buf(cb);
    354     0    stevel 		return (ret);
    355     0    stevel 	}
    356     0    stevel 
    357     0    stevel 	if (append_char_buf(cb, "\n%s%s", cb->cb_tab_buf,
    358     0    stevel 		pool_elem_class_string(pe)) == PO_FAIL) {
    359     0    stevel 		return (NULL);
    360     0    stevel 	}
    361     0    stevel 
    362     0    stevel 	if (pool_get_ns_property(pe, c_name, &val) == POC_STRING) {
    363     0    stevel 		(void) pool_value_get_string(&val, &sres);
    364     0    stevel 		if (append_char_buf(cb, " %s", sres) == PO_FAIL) {
    365     0    stevel 			return (NULL);
    366     0    stevel 		}
    367     0    stevel 	}
    368     0    stevel 
    369     0    stevel 	/*
    370     0    stevel 	 * Add in some details about the element
    371     0    stevel 	 */
    372     0    stevel 	if (pool_walk_properties(conf, (pool_elem_t *)pe, cb,
    373     0    stevel 	    prop_buf_build_cb) == PO_FAIL) {
    374     0    stevel 		(void) append_char_buf(cb, "\n%s%s\n", cb->cb_tab_buf,
    375     0    stevel 		    "Cannot access the properties of this element.");
    376     0    stevel 		return (NULL);
    377     0    stevel 	}
    378     0    stevel 	if (append_char_buf(cb, "%s", "\n") == PO_FAIL)
    379     0    stevel 		return (NULL);
    380     0    stevel 
    381     0    stevel 	if (pe->pe_class == PEC_POOL) {
    382     0    stevel 		/*
    383     0    stevel 		 * A shallow display of a pool only lists the resources by name
    384     0    stevel 		 */
    385     0    stevel 
    386     0    stevel 		if ((rs = pool_query_pool_resources(conf, pool_elem_pool(pe),
    387     0    stevel 		    &nelem, NULL)) == NULL) {
    388     0    stevel 			return (NULL);
    389     0    stevel 		}
    390     0    stevel 
    391     0    stevel 		for (i = 0; i < nelem; i++) {
    392     0    stevel 			const char *str;
    393     0    stevel 
    394     0    stevel 			elem = TO_ELEM(rs[i]);
    395     0    stevel 
    396     0    stevel 			if (append_char_buf(cb, "\t%s%s", cb->cb_tab_buf,
    397     0    stevel 			    pool_elem_class_string(elem)) == PO_FAIL) {
    398     0    stevel 				free(rs);
    399     0    stevel 				return (NULL);
    400     0    stevel 			}
    401     0    stevel 
    402     0    stevel 			if (pool_get_ns_property(elem, c_name, &val) !=
    403     0    stevel 			    POC_STRING) {
    404     0    stevel 				free(rs);
    405     0    stevel 				pool_seterror(POE_INVALID_CONF);
    406     0    stevel 				return (NULL);
    407     0    stevel 			}
    408     0    stevel 			(void) pool_value_get_string(&val, &str);
    409     0    stevel 			if (append_char_buf(cb, "\t%s\n", str) == PO_FAIL) {
    410     0    stevel 				free(rs);
    411     0    stevel 				return (NULL);
    412     0    stevel 			}
    413     0    stevel 		}
    414     0    stevel 		free(rs);
    415     0    stevel 	}
    416     0    stevel 	if (deep == PO_TRUE) {
    417     0    stevel 		pool_t **ps;
    418     0    stevel 		pool_component_t **cs;
    419     0    stevel 
    420     0    stevel 		if (strlcat(cb->cb_tab_buf, "\t", CB_TAB_BUF_SIZE)
    421     0    stevel 		    >= CB_TAB_BUF_SIZE) {
    422     0    stevel 			pool_seterror(POE_SYSTEM);
    423     0    stevel 			return (NULL);
    424     0    stevel 		}
    425     0    stevel 		switch (pe->pe_class) {
    426     0    stevel 		case PEC_SYSTEM:
    427     0    stevel 			if ((ps = pool_query_pools(conf, &nelem, NULL)) !=
    428     0    stevel 			    NULL) { /* process the pools */
    429     0    stevel 				for (i = 0; i < nelem; i++) {
    430     0    stevel 					elem = TO_ELEM(ps[i]);
    431     0    stevel 					if (pool_base_info(elem, cb,
    432     0    stevel 					    PO_FALSE) == NULL) {
    433     0    stevel 						free(ps);
    434     0    stevel 						return (NULL);
    435     0    stevel 					}
    436     0    stevel 				}
    437     0    stevel 				free(ps);
    438     0    stevel 			}
    439     0    stevel 			if ((rs = pool_query_resources(conf, &nelem, NULL)) !=
    440     0    stevel 			    NULL) {
    441     0    stevel 				for (i = 0; i < nelem; i++) {
    442     0    stevel 					elem = TO_ELEM(rs[i]);
    443     0    stevel 					if (pool_base_info(elem, cb,
    444     0    stevel 					    PO_TRUE) == NULL) {
    445     0    stevel 						free(rs);
    446     0    stevel 						return (NULL);
    447     0    stevel 					}
    448     0    stevel 				}
    449     0    stevel 				free(rs);
    450     0    stevel 			}
    451     0    stevel 			break;
    452     0    stevel 		case PEC_POOL:
    453     0    stevel 			if ((rs = pool_query_pool_resources(conf,
    454     0    stevel 			    pool_elem_pool(pe), &nelem, NULL)) == NULL)
    455     0    stevel 				return (NULL);
    456     0    stevel 			for (i = 0; i < nelem; i++) {
    457     0    stevel 				elem = TO_ELEM(rs[i]);
    458     0    stevel 				if (pool_base_info(elem, cb, PO_TRUE) == NULL) {
    459     0    stevel 					free(rs);
    460     0    stevel 					return (NULL);
    461     0    stevel 				}
    462     0    stevel 			}
    463     0    stevel 			free(rs);
    464     0    stevel 			break;
    465     0    stevel 		case PEC_RES_COMP:
    466     0    stevel 			if ((cs = pool_query_resource_components(conf,
    467     0    stevel 			    pool_elem_res(pe), &nelem, NULL)) != NULL) {
    468     0    stevel 				for (i = 0; i < nelem; i++) {
    469     0    stevel 					elem = TO_ELEM(cs[i]);
    470     0    stevel 					if (pool_base_info(elem, cb,
    471     0    stevel 					    PO_FALSE) == NULL) {
    472     0    stevel 						free(cs);
    473     0    stevel 						return (NULL);
    474     0    stevel 					}
    475     0    stevel 				}
    476     0    stevel 				free(cs);
    477     0    stevel 			}
    478     0    stevel 			break;
    479     0    stevel 		case PEC_RES_AGG:
    480     0    stevel 		case PEC_COMP:
    481     0    stevel 			break;
    482     0    stevel 		default:
    483     0    stevel 			/*NOTREACHED*/
    484     0    stevel 			break;
    485     0    stevel 		}
    486     0    stevel 		if (cb->cb_tab_buf[0] != 0)
    487     0    stevel 			cb->cb_tab_buf[strlen(cb->cb_tab_buf) - 1] = 0;
    488     0    stevel 	}
    489     0    stevel 	return (cb->cb_buf);
    490     0    stevel }
    491     0    stevel 
    492     0    stevel /*
    493     0    stevel  * Returns	The information on the specified pool or NULL.
    494     0    stevel  *
    495     0    stevel  * Errors	If the status of the conf is INVALID or the supplied
    496     0    stevel  *		value of deep is illegal, POE_BADPARAM.
    497     0    stevel  *
    498     0    stevel  * The caller is responsible for free(3c)ing the string returned.
    499     0    stevel  */
    500     0    stevel char *
    501     0    stevel pool_info(const pool_conf_t *conf, const pool_t *pool, int deep)
    502     0    stevel {
    503     0    stevel 	pool_elem_t *pe;
    504     0    stevel 
    505     0    stevel 	pe = TO_ELEM(pool);
    506     0    stevel 
    507     0    stevel 	if (TO_CONF(pe) != conf) {
    508     0    stevel 		pool_seterror(POE_BADPARAM);
    509     0    stevel 		return (NULL);
    510     0    stevel 	}
    511     0    stevel 
    512     0    stevel 	if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) {
    513     0    stevel 		pool_seterror(POE_BADPARAM);
    514     0    stevel 		return (NULL);
    515     0    stevel 	}
    516     0    stevel 
    517     0    stevel 	return (pool_base_info(pe, NULL, deep));
    518     0    stevel }
    519     0    stevel 
    520     0    stevel /*
    521     0    stevel  * Returns	The information on the specified resource or NULL.
    522     0    stevel  *
    523     0    stevel  * Errors	If the status of the conf is INVALID or the supplied
    524     0    stevel  *		value of deep is illegal, POE_BADPARAM.
    525     0    stevel  *
    526     0    stevel  * The caller is responsible for free(3c)ing the string returned.
    527     0    stevel  */
    528     0    stevel char *
    529     0    stevel pool_resource_info(const pool_conf_t *conf, const pool_resource_t *res,
    530     0    stevel     int deep)
    531     0    stevel {
    532     0    stevel 	pool_elem_t *pe;
    533     0    stevel 
    534     0    stevel 	pe = TO_ELEM(res);
    535     0    stevel 
    536     0    stevel 	if (TO_CONF(pe) != conf) {
    537     0    stevel 		pool_seterror(POE_BADPARAM);
    538     0    stevel 		return (NULL);
    539     0    stevel 	}
    540     0    stevel 
    541     0    stevel 	if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) {
    542     0    stevel 		pool_seterror(POE_BADPARAM);
    543     0    stevel 		return (NULL);
    544     0    stevel 	}
    545     0    stevel 
    546     0    stevel 	return (pool_base_info(pe, NULL, deep));
    547     0    stevel }
    548     0    stevel 
    549     0    stevel /*
    550     0    stevel  * Returns	The information on the specified component or NULL.
    551     0    stevel  *
    552     0    stevel  * Errors	If the status of the conf is INVALID or the supplied
    553     0    stevel  *		value of deep is illegal, POE_BADPARAM.
    554     0    stevel  *
    555     0    stevel  * The caller is responsible for free(3c)ing the string returned.
    556     0    stevel  */
    557     0    stevel char *
    558     0    stevel pool_component_info(const pool_conf_t *conf, const pool_component_t *comp,
    559     0    stevel     int deep)
    560     0    stevel {
    561     0    stevel 	pool_elem_t *pe;
    562     0    stevel 
    563     0    stevel 	pe = TO_ELEM(comp);
    564     0    stevel 
    565     0    stevel 	if (TO_CONF(pe) != conf) {
    566     0    stevel 		pool_seterror(POE_BADPARAM);
    567     0    stevel 		return (NULL);
    568     0    stevel 	}
    569     0    stevel 
    570     0    stevel 	if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) {
    571     0    stevel 		pool_seterror(POE_BADPARAM);
    572     0    stevel 		return (NULL);
    573     0    stevel 	}
    574     0    stevel 
    575     0    stevel 	return (pool_base_info(pe, NULL, deep));
    576     0    stevel }
    577     0    stevel 
    578     0    stevel /*
    579     0    stevel  * Returns	The information on the specified conf or NULL.
    580     0    stevel  *
    581     0    stevel  * Errors	If the status of the conf is INVALID or the supplied
    582     0    stevel  *		value of deep is illegal, POE_BADPARAM.
    583     0    stevel  *
    584     0    stevel  * The caller is responsible for free(3c)ing the string returned.
    585     0    stevel  */
    586     0    stevel char *
    587     0    stevel pool_conf_info(const pool_conf_t *conf, int deep)
    588     0    stevel {
    589     0    stevel 	pool_elem_t *pe;
    590     0    stevel 
    591     0    stevel 	if (pool_conf_status(conf) == POF_INVALID || (deep & ~1)) {
    592     0    stevel 		pool_seterror(POE_BADPARAM);
    593     0    stevel 		return (NULL);
    594     0    stevel 	}
    595     0    stevel 	if ((pe = pool_conf_to_elem(conf)) == NULL) {
    596     0    stevel 		pool_seterror(POE_BADPARAM);
    597     0    stevel 		return (NULL);
    598     0    stevel 	}
    599     0    stevel 	return (pool_base_info(pe, NULL, deep));
    600     0    stevel }
    601     0    stevel 
    602     0    stevel 
    603     0    stevel /*
    604     0    stevel  * Set the thread specific error value.
    605     0    stevel  */
    606     0    stevel void
    607     0    stevel pool_seterror(int errval)
    608     0    stevel {
    609     0    stevel 	if (thr_main()) {
    610     0    stevel 		pool_errval = errval;
    611     0    stevel 		return;
    612     0    stevel 	}
    613  3864       raf 	(void) thr_keycreate_once(&errkey, 0);
    614     0    stevel 	(void) thr_setspecific(errkey, (void *)(intptr_t)errval);
    615     0    stevel }
    616     0    stevel 
    617     0    stevel /*
    618     0    stevel  * Return the current value of the error code.
    619     0    stevel  * Returns: int error code
    620     0    stevel  */
    621     0    stevel int
    622     0    stevel pool_error(void)
    623     0    stevel {
    624     0    stevel 	if (thr_main())
    625     0    stevel 		return (pool_errval);
    626  3864       raf 	if (errkey == THR_ONCE_KEY)
    627     0    stevel 		return (POE_OK);
    628  3864       raf 	return ((uintptr_t)pthread_getspecific(errkey));
    629     0    stevel }
    630     0    stevel 
    631     0    stevel /*
    632     0    stevel  * Return the text represenation for the current value of the error code.
    633     0    stevel  * Returns: const char * error string
    634     0    stevel  */
    635     0    stevel const char *
    636     0    stevel pool_strerror(int error)
    637     0    stevel {
    638     0    stevel 	char *str;
    639     0    stevel 
    640     0    stevel 	switch (error) {
    641     0    stevel 	case POE_OK:
    642     0    stevel 		str = dgettext(TEXT_DOMAIN, "Operation successful");
    643     0    stevel 		break;
    644     0    stevel 	case POE_BAD_PROP_TYPE:
    645     0    stevel 		str = dgettext(TEXT_DOMAIN,
    646     0    stevel 		    "Attempted to retrieve the wrong property type");
    647     0    stevel 		break;
    648     0    stevel 	case POE_INVALID_CONF:
    649     0    stevel 		str = dgettext(TEXT_DOMAIN, "Invalid configuration");
    650     0    stevel 		break;
    651     0    stevel 	case POE_NOTSUP:
    652     0    stevel 		str = dgettext(TEXT_DOMAIN, "Operation is not supported");
    653     0    stevel 		break;
    654     0    stevel 	case POE_INVALID_SEARCH:
    655     0    stevel 		str = dgettext(TEXT_DOMAIN, "Invalid search");
    656     0    stevel 		break;
    657     0    stevel 	case POE_BADPARAM:
    658     0    stevel 		str = dgettext(TEXT_DOMAIN, "Bad parameter supplied");
    659     0    stevel 		break;
    660     0    stevel 	case POE_PUTPROP:
    661     0    stevel 		str = dgettext(TEXT_DOMAIN, "Error putting property");
    662     0    stevel 		break;
    663     0    stevel 	case POE_DATASTORE:
    664     0    stevel 		str = dgettext(TEXT_DOMAIN, "Pools repository error");
    665     0    stevel 		break;
    666     0    stevel 	case POE_SYSTEM:
    667     0    stevel 		str = dgettext(TEXT_DOMAIN, "System error");
    668     0    stevel 		break;
    669     0    stevel 	case POE_ACCESS:
    670     0    stevel 		str = dgettext(TEXT_DOMAIN, "Permission denied");
    671     0    stevel 		break;
    672     0    stevel 	default:
    673     0    stevel 		errno = ESRCH;
    674     0    stevel 		str = NULL;
    675     0    stevel 	}
    676     0    stevel 	return (str);
    677     0    stevel }
    678     0    stevel 
    679     0    stevel int
    680     0    stevel pool_get_status(int *state)
    681     0    stevel {
    682     0    stevel 	int fd;
    683     0    stevel 	pool_status_t status;
    684     0    stevel 
    685     0    stevel 	if ((fd = open(pool_info_location, O_RDONLY)) < 0) {
    686     0    stevel 		pool_seterror(POE_SYSTEM);
    687     0    stevel 		return (PO_FAIL);
    688     0    stevel 	}
    689     0    stevel 	if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
    690     0    stevel 		(void) close(fd);
    691     0    stevel 		pool_seterror(POE_SYSTEM);
    692     0    stevel 		return (PO_FAIL);
    693     0    stevel 	}
    694     0    stevel 	(void) close(fd);
    695     0    stevel 
    696     0    stevel 	*state = status.ps_io_state;
    697     0    stevel 
    698     0    stevel 	return (PO_SUCCESS);
    699     0    stevel }
    700     0    stevel 
    701     0    stevel int
    702     0    stevel pool_set_status(int state)
    703     0    stevel {
    704     0    stevel 	int old_state;
    705     0    stevel 
    706     0    stevel 	if (pool_get_status(&old_state) != PO_SUCCESS) {
    707     0    stevel 		pool_seterror(POE_SYSTEM);
    708     0    stevel 		return (PO_FAIL);
    709     0    stevel 	}
    710     0    stevel 
    711     0    stevel 	if (old_state != state) {
    712     0    stevel 		int fd;
    713     0    stevel 		pool_status_t status;
    714  3251  sl108498 		char *fmri;
    715     0    stevel 
    716  1042   garypen 		/*
    717  1042   garypen 		 * Changing the status of pools is performed by enabling
    718  1042   garypen 		 * or disabling the pools service instance. If this
    719  1042   garypen 		 * function has not been invoked by startd then we simply
    720  1042   garypen 		 * enable/disable the service and return success.
    721  1042   garypen 		 *
    722  1042   garypen 		 * There is no way to specify that state changes must be
    723  1042   garypen 		 * synchronous using the library API as yet, so we use
    724  1042   garypen 		 * the -s option provided by svcadm.
    725  1042   garypen 		 */
    726  3251  sl108498 		fmri = getenv("SMF_FMRI");
    727  3251  sl108498 		if (fmri == NULL) {
    728  1042   garypen 			FILE *p;
    729  2706   garypen 			char *cmd;
    730  2706   garypen 
    731  3251  sl108498 			if (state != 0) {
    732  2706   garypen 				cmd = "/usr/sbin/svcadm enable -s " \
    733  1042   garypen 				    SMF_SVC_INSTANCE;
    734  1042   garypen 			} else {
    735  2706   garypen 				cmd = "/usr/sbin/svcadm disable -s " \
    736  1042   garypen 				    SMF_SVC_INSTANCE;
    737  2706   garypen 			}
    738  2706   garypen 			if ((p = popen(cmd, "wF")) == NULL || pclose(p) != 0) {
    739  2706   garypen 				pool_seterror(POE_SYSTEM);
    740  2706   garypen 				return (PO_FAIL);
    741     0    stevel 			}
    742  1042   garypen 			return (PO_SUCCESS);
    743     0    stevel 		}
    744     0    stevel 
    745     0    stevel 		if ((fd = open(pool_dynamic_location(), O_RDWR | O_EXCL)) < 0) {
    746     0    stevel 			pool_seterror(POE_SYSTEM);
    747     0    stevel 			return (PO_FAIL);
    748     0    stevel 		}
    749     0    stevel 
    750  3251  sl108498 		/*
    751  3251  sl108498 		 * If pools are being enabled/disabled by another smf service,
    752  3251  sl108498 		 * enable the smf service instance.  This must be done
    753  3251  sl108498 		 * asynchronously as one service cannot synchronously
    754  3251  sl108498 		 * enable/disable another.
    755  3251  sl108498 		 */
    756  3251  sl108498 		if (strcmp(fmri, SMF_SVC_INSTANCE) != 0) {
    757  3251  sl108498 			int res;
    758  3251  sl108498 
    759  3251  sl108498 			if (state != 0)
    760  3251  sl108498 				res = smf_enable_instance(SMF_SVC_INSTANCE, 0);
    761  3251  sl108498 			else
    762  3251  sl108498 				res = smf_disable_instance(SMF_SVC_INSTANCE, 0);
    763  3251  sl108498 
    764  3251  sl108498 			if (res != 0) {
    765  3251  sl108498 				(void) close(fd);
    766  3251  sl108498 				pool_seterror(POE_SYSTEM);
    767  3251  sl108498 				return (PO_FAIL);
    768  3251  sl108498 			}
    769  3251  sl108498 		}
    770     0    stevel 		status.ps_io_state = state;
    771     0    stevel 
    772     0    stevel 		if (ioctl(fd, POOL_STATUS, &status) < 0) {
    773     0    stevel 			(void) close(fd);
    774     0    stevel 			pool_seterror(POE_SYSTEM);
    775     0    stevel 			return (PO_FAIL);
    776     0    stevel 		}
    777     0    stevel 
    778     0    stevel 		(void) close(fd);
    779     0    stevel 
    780     0    stevel 	}
    781     0    stevel 	return (PO_SUCCESS);
    782     0    stevel }
    783     0    stevel 
    784     0    stevel /*
    785     0    stevel  * General Data Provider Independent Access Methods
    786     0    stevel  */
    787     0    stevel 
    788     0    stevel /*
    789     0    stevel  * Property manipulation code.
    790     0    stevel  *
    791     0    stevel  * The pool_(get|rm|set)_property() functions consult the plugins before
    792     0    stevel  * looking at the actual configuration. This allows plugins to provide
    793     0    stevel  * "virtual" properties that may not exist in the configuration file per se,
    794     0    stevel  * but behave like regular properties. This also allows plugins to reserve
    795     0    stevel  * certain properties as read-only, non-removable, etc.
    796     0    stevel  *
    797     0    stevel  * A negative value returned from the plugin denotes error, 0 means that the
    798     0    stevel  * property request should be forwarded to the backend, and 1 means the request
    799     0    stevel  * was satisfied by the plugin and should not be processed further.
    800     0    stevel  *
    801     0    stevel  * The (get|rm|set)_property() functions bypass the plugin layer completely,
    802     0    stevel  * and hence should not be generally used.
    803     0    stevel  */
    804     0    stevel 
    805     0    stevel /*
    806     0    stevel  * Return true if the string passed in matches the pattern
    807     0    stevel  * [A-Za-z][A-Za-z0-9,._-]*
    808     0    stevel  */
    809     0    stevel int
    810     0    stevel is_valid_name(const char *name)
    811     0    stevel {
    812     0    stevel 	int i;
    813     0    stevel 	char c;
    814     0    stevel 
    815     0    stevel 	if (name == NULL)
    816     0    stevel 		return (PO_FALSE);
    817     0    stevel 	if (!isalpha(name[0]))
    818     0    stevel 		return (PO_FALSE);
    819     0    stevel 	for (i = 1; (c = name[i]) != '\0'; i++) {
    820     0    stevel 		if (!isalnum(c) && c != ',' && c != '.' && c != '_' && c != '-')
    821     0    stevel 			return (PO_FALSE);
    822     0    stevel 	}
    823     0    stevel 	return (PO_TRUE);
    824     0    stevel }
    825     0    stevel 
    826     0    stevel /*
    827     0    stevel  * Return true if the string passed in matches the pattern
    828     0    stevel  * [A-Za-z_][A-Za-z0-9,._-]*
    829     0    stevel  * A property name starting with a '_' is an "invisible" property that does not
    830     0    stevel  * show up in a property walk.
    831     0    stevel  */
    832     0    stevel int
    833     0    stevel is_valid_prop_name(const char *prop_name)
    834     0    stevel {
    835     0    stevel 	int i;
    836     0    stevel 	char c;
    837     0    stevel 
    838     0    stevel 	if (prop_name == NULL)
    839     0    stevel 		return (PO_FALSE);
    840     0    stevel 	if (!isalpha(prop_name[0]) && prop_name[0] != '_')
    841     0    stevel 		return (PO_FALSE);
    842     0    stevel 	for (i = 1; (c = prop_name[i]) != '\0'; i++) {
    843     0    stevel 		if (!isalnum(c) && c != ',' && c != '.' && c != '_' && c != '-')
    844     0    stevel 			return (PO_FALSE);
    845     0    stevel 	}
    846     0    stevel 	return (PO_TRUE);
    847     0    stevel }
    848     0    stevel 
    849     0    stevel /*
    850     0    stevel  * Return the specified property value.
    851     0    stevel  *
    852     0    stevel  * POC_INVAL is returned if an error is detected and the error code is updated
    853     0    stevel  * to indicate the cause of the error.
    854     0    stevel  */
    855     0    stevel pool_value_class_t
    856     0    stevel pool_get_property(const pool_conf_t *conf, const pool_elem_t *pe,
    857     0    stevel     const char *name, pool_value_t *val)
    858     0    stevel {
    859     0    stevel 	const pool_prop_t *prop_info;
    860     0    stevel 
    861     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
    862     0    stevel 		pool_seterror(POE_BADPARAM);
    863     0    stevel 		return (POC_INVAL);
    864     0    stevel 	}
    865     0    stevel 	if (pool_value_set_name(val, name) != PO_SUCCESS) {
    866     0    stevel 		return (POC_INVAL);
    867     0    stevel 	}
    868     0    stevel 	/*
    869     0    stevel 	 * Check to see if this is a property we are managing. If it
    870     0    stevel 	 * is and it has an interceptor installed for property
    871     0    stevel 	 * retrieval, use it.
    872     0    stevel 	 */
    873     0    stevel 	if ((prop_info = provider_get_prop(pe, name)) != NULL &&
    874     0    stevel 	    prop_info->pp_op.ppo_get_value != NULL) {
    875     0    stevel 		if (prop_info->pp_op.ppo_get_value(pe, val) == PO_FAIL)
    876     0    stevel 			return (POC_INVAL);
    877     0    stevel 		else
    878     0    stevel 			return (pool_value_get_type(val));
    879     0    stevel 	}
    880     0    stevel 	return (pe->pe_get_prop(pe, name, val));
    881     0    stevel }
    882     0    stevel 
    883     0    stevel /*
    884     0    stevel  * Return the specified property value with the namespace prepended.
    885     0    stevel  * e.g. If this function is used to get the property "name" on a pool, it will
    886     0    stevel  * attempt to retrieve "pool.name".
    887     0    stevel  *
    888     0    stevel  * POC_INVAL is returned if an error is detected and the error code is updated
    889     0    stevel  * to indicate the cause of the error.
    890     0    stevel  */
    891     0    stevel pool_value_class_t
    892     0    stevel pool_get_ns_property(const pool_elem_t *pe, const char *name, pool_value_t *val)
    893     0    stevel {
    894     0    stevel 	int ret;
    895     0    stevel 	char_buf_t *cb;
    896     0    stevel 
    897     0    stevel 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
    898     0    stevel 		return (POC_INVAL);
    899     0    stevel 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
    900     0    stevel 	    PO_FAIL) {
    901     0    stevel 		free_char_buf(cb);
    902     0    stevel 		return (POC_INVAL);
    903     0    stevel 	}
    904     0    stevel 	ret = pool_get_property(TO_CONF(pe), pe, cb->cb_buf, val);
    905     0    stevel 	free_char_buf(cb);
    906     0    stevel 	return (ret);
    907     0    stevel }
    908     0    stevel 
    909     0    stevel /*
    910     0    stevel  * Update the specified property value.
    911     0    stevel  *
    912     0    stevel  * PO_FAIL is returned if an error is detected and the error code is updated
    913     0    stevel  * to indicate the cause of the error.
    914     0    stevel  */
    915     0    stevel int
    916     0    stevel pool_put_property(pool_conf_t *conf, pool_elem_t *pe, const char *name,
    917     0    stevel     const pool_value_t *val)
    918     0    stevel {
    919     0    stevel 	const pool_prop_t *prop_info;
    920     0    stevel 
    921     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
    922     0    stevel 		return (PO_FAIL);
    923     0    stevel 
    924     0    stevel 	if (TO_CONF(pe) != conf) {
    925     0    stevel 		pool_seterror(POE_BADPARAM);
    926     0    stevel 		return (NULL);
    927     0    stevel 	}
    928     0    stevel 
    929  3247  gjelinek 	/* Don't allow (re)setting of the "temporary" property */
    930  3247  gjelinek 	if (!is_valid_prop_name(name) || strstr(name, ".temporary") != NULL) {
    931     0    stevel 		pool_seterror(POE_BADPARAM);
    932     0    stevel 		return (PO_FAIL);
    933     0    stevel 	}
    934  3247  gjelinek 
    935  3247  gjelinek 	/* Don't allow rename of temporary pools/resources */
    936  3247  gjelinek 	if (strstr(name, ".name") != NULL && elem_is_tmp(pe)) {
    937  3247  gjelinek 		boolean_t rename = B_TRUE;
    938  3247  gjelinek 		pool_value_t *pv = pool_value_alloc();
    939  3247  gjelinek 
    940  3247  gjelinek 		if (pe->pe_get_prop(pe, name, pv) != POC_INVAL) {
    941  3247  gjelinek 			const char *s1 = NULL;
    942  3247  gjelinek 			const char *s2 = NULL;
    943  3247  gjelinek 
    944  3247  gjelinek 			(void) pool_value_get_string(pv, &s1);
    945  3247  gjelinek 			(void) pool_value_get_string(val, &s2);
    946  3247  gjelinek 			if (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0)
    947  3247  gjelinek 				rename = B_FALSE;
    948  3247  gjelinek 		}
    949  3247  gjelinek 		pool_value_free(pv);
    950  3247  gjelinek 
    951  3247  gjelinek 		if (rename) {
    952  3247  gjelinek 			pool_seterror(POE_BADPARAM);
    953  3247  gjelinek 			return (PO_FAIL);
    954  3247  gjelinek 		}
    955  3247  gjelinek 	}
    956  3247  gjelinek 
    957     0    stevel 	/*
    958     0    stevel 	 * Check to see if this is a property we are managing. If it is,
    959     0    stevel 	 * ensure that we are happy with what the user is doing.
    960     0    stevel 	 */
    961     0    stevel 	if ((prop_info = provider_get_prop(pe, name)) != NULL) {
    962     0    stevel 		if (prop_is_readonly(prop_info) == PO_TRUE) {
    963     0    stevel 			pool_seterror(POE_BADPARAM);
    964     0    stevel 			return (PO_FAIL);
    965     0    stevel 		}
    966     0    stevel 		if (prop_info->pp_op.ppo_set_value &&
    967     0    stevel 		    prop_info->pp_op.ppo_set_value(pe, val) == PO_FAIL)
    968     0    stevel 			return (PO_FAIL);
    969     0    stevel 	}
    970     0    stevel 
    971     0    stevel 	return (pe->pe_put_prop(pe, name, val));
    972  3247  gjelinek }
    973  3247  gjelinek 
    974  3247  gjelinek /*
    975  3247  gjelinek  * Set temporary property to flag as a temporary element.
    976  3247  gjelinek  *
    977  3247  gjelinek  * PO_FAIL is returned if an error is detected and the error code is updated
    978  3247  gjelinek  * to indicate the cause of the error.
    979  3247  gjelinek  */
    980  3247  gjelinek int
    981  3247  gjelinek pool_set_temporary(pool_conf_t *conf, pool_elem_t *pe)
    982  3247  gjelinek {
    983  3247  gjelinek 	int res;
    984  3247  gjelinek 	char name[128];
    985  3247  gjelinek 	pool_value_t *val;
    986  3247  gjelinek 
    987  3247  gjelinek 	if (pool_conf_check(conf) != PO_SUCCESS)
    988  3247  gjelinek 		return (PO_FAIL);
    989  3247  gjelinek 
    990  3247  gjelinek 	if (TO_CONF(pe) != conf) {
    991  3247  gjelinek 		pool_seterror(POE_BADPARAM);
    992  3247  gjelinek 		return (PO_FAIL);
    993  3247  gjelinek 	}
    994  3247  gjelinek 
    995  3247  gjelinek 	/* create property name based on element type */
    996  3247  gjelinek 	if (snprintf(name, sizeof (name), "%s.temporary",
    997  3247  gjelinek 	    pool_elem_class_string(pe)) > sizeof (name)) {
    998  3247  gjelinek 		pool_seterror(POE_SYSTEM);
    999  3247  gjelinek 		return (PO_FAIL);
   1000  3247  gjelinek 	}
   1001  3247  gjelinek 
   1002  3247  gjelinek 	if ((val = pool_value_alloc()) == NULL)
   1003  3247  gjelinek 		return (PO_FAIL);
   1004  3247  gjelinek 
   1005  3247  gjelinek 	pool_value_set_bool(val, (uchar_t)1);
   1006  3247  gjelinek 
   1007  3247  gjelinek 	res = pe->pe_put_prop(pe, name, val);
   1008  3247  gjelinek 
   1009  3247  gjelinek 	pool_value_free(val);
   1010  3247  gjelinek 
   1011  3247  gjelinek 	return (res);
   1012     0    stevel }
   1013     0    stevel 
   1014     0    stevel /*
   1015     0    stevel  * Update the specified property value with the namespace prepended.
   1016     0    stevel  * e.g. If this function is used to update the property "name" on a pool, it
   1017     0    stevel  * will attempt to update "pool.name".
   1018     0    stevel  *
   1019     0    stevel  * PO_FAIL is returned if an error is detected and the error code is updated
   1020     0    stevel  * to indicate the cause of the error.
   1021     0    stevel  */
   1022     0    stevel int
   1023     0    stevel pool_put_ns_property(pool_elem_t *pe, const char *name,
   1024     0    stevel     const pool_value_t *val)
   1025     0    stevel {
   1026     0    stevel 	char_buf_t *cb;
   1027     0    stevel 	int ret;
   1028     0    stevel 
   1029     0    stevel 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
   1030     0    stevel 		return (PO_FAIL);
   1031     0    stevel 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
   1032     0    stevel 	    PO_FAIL) {
   1033     0    stevel 		free_char_buf(cb);
   1034     0    stevel 		return (PO_FAIL);
   1035     0    stevel 	}
   1036     0    stevel 	ret = pool_put_property(TO_CONF(pe), pe, cb->cb_buf, val);
   1037     0    stevel 	free_char_buf(cb);
   1038     0    stevel 	return (ret);
   1039     0    stevel }
   1040     0    stevel 
   1041     0    stevel /*
   1042     0    stevel  * Update the specified property value. Do not use the property
   1043     0    stevel  * protection mechanism. This function should only be used for cases
   1044     0    stevel  * where the library must bypass the normal property protection
   1045     0    stevel  * mechanism. The only known use is to update properties in the static
   1046     0    stevel  * configuration when performing a commit.
   1047     0    stevel  *
   1048     0    stevel  * PO_FAIL is returned if an error is detected and the error code is
   1049     0    stevel  * updated to indicate the cause of the error.
   1050     0    stevel  */
   1051     0    stevel int
   1052     0    stevel pool_put_any_property(pool_elem_t *pe, const char *name,
   1053     0    stevel     const pool_value_t *val)
   1054     0    stevel {
   1055     0    stevel 	if (!is_valid_prop_name(name)) {
   1056     0    stevel 		pool_seterror(POE_BADPARAM);
   1057     0    stevel 		return (PO_FAIL);
   1058     0    stevel 	}
   1059     0    stevel 
   1060     0    stevel 	return (pe->pe_put_prop(pe, name, val));
   1061     0    stevel }
   1062     0    stevel 
   1063     0    stevel /*
   1064     0    stevel  * Update the specified property value with the namespace prepended.
   1065     0    stevel  * e.g. If this function is used to update the property "name" on a pool, it
   1066     0    stevel  * will attempt to update "pool.name".
   1067     0    stevel  *
   1068     0    stevel  * PO_FAIL is returned if an error is detected and the error code is updated
   1069     0    stevel  * to indicate the cause of the error.
   1070     0    stevel  */
   1071     0    stevel int
   1072     0    stevel pool_put_any_ns_property(pool_elem_t *pe, const char *name,
   1073     0    stevel     const pool_value_t *val)
   1074     0    stevel {
   1075     0    stevel 	char_buf_t *cb;
   1076     0    stevel 	int ret;
   1077     0    stevel 
   1078     0    stevel 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
   1079     0    stevel 		return (PO_FAIL);
   1080     0    stevel 	if (set_char_buf(cb, "%s.%s", pool_elem_class_string(pe), name) ==
   1081     0    stevel 	    PO_FAIL) {
   1082     0    stevel 		free_char_buf(cb);
   1083     0    stevel 		return (PO_FAIL);
   1084     0    stevel 	}
   1085     0    stevel 	ret = pool_put_any_property(pe, cb->cb_buf, val);
   1086     0    stevel 	free_char_buf(cb);
   1087     0    stevel 	return (ret);
   1088     0    stevel }
   1089     0    stevel 
   1090     0    stevel /*
   1091     0    stevel  * Remove the specified property value. Note that some properties are
   1092     0    stevel  * mandatory and thus failure to remove these properties is inevitable.
   1093     0    stevel  * PO_FAIL is returned if an error is detected and the error code is updated
   1094     0    stevel  * to indicate the cause of the error.
   1095     0    stevel  */
   1096     0    stevel int
   1097     0    stevel pool_rm_property(pool_conf_t *conf, pool_elem_t *pe, const char *name)
   1098     0    stevel {
   1099     0    stevel 	const pool_prop_t *prop_info;
   1100     0    stevel 
   1101     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
   1102     0    stevel 		return (PO_FAIL);
   1103     0    stevel 
   1104     0    stevel 	if (TO_CONF(pe) != conf) {
   1105     0    stevel 		pool_seterror(POE_BADPARAM);
   1106     0    stevel 		return (NULL);
   1107     0    stevel 	}
   1108     0    stevel 
   1109  3247  gjelinek 	/* Don't allow removal of the "temporary" property */
   1110  3247  gjelinek 	if (strstr(name, ".temporary") != NULL) {
   1111  3247  gjelinek 		pool_seterror(POE_BADPARAM);
   1112  3247  gjelinek 		return (PO_FAIL);
   1113  3247  gjelinek 	}
   1114  3247  gjelinek 
   1115     0    stevel 	/*
   1116     0    stevel 	 * Check to see if this is a property we are managing. If it is,
   1117     0    stevel 	 * ensure that we are happy with what the user is doing.
   1118     0    stevel 	 */
   1119     0    stevel 	if ((prop_info = provider_get_prop(pe, name)) != NULL) {
   1120     0    stevel 		if (prop_is_optional(prop_info) == PO_FALSE) {
   1121     0    stevel 			pool_seterror(POE_BADPARAM);
   1122     0    stevel 			return (PO_FAIL);
   1123     0    stevel 		}
   1124     0    stevel 	}
   1125     0    stevel 	return (pe->pe_rm_prop(pe, name));
   1126     0    stevel }
   1127     0    stevel 
   1128     0    stevel /*
   1129     0    stevel  * Check if the supplied name is a namespace protected property for the supplied
   1130     0    stevel  * element, pe. If it is, return the prefix, otherwise just return NULL.
   1131     0    stevel  */
   1132     0    stevel const char *
   1133     0    stevel is_ns_property(const pool_elem_t *pe, const char *name)
   1134     0    stevel {
   1135     0    stevel 	const char *prefix;
   1136     0    stevel 
   1137     0    stevel 	if ((prefix = pool_elem_class_string(pe)) != NULL) {
   1138     0    stevel 		if (strncmp(name, prefix, strlen(prefix)) == 0)
   1139     0    stevel 			return (prefix);
   1140     0    stevel 	}
   1141     0    stevel 	return (NULL);
   1142     0    stevel }
   1143     0    stevel 
   1144     0    stevel /*
   1145     0    stevel  * Check if the supplied name is a namespace protected property for the supplied
   1146     0    stevel  * element, pe. If it is, return the property name with the namespace stripped,
   1147     0    stevel  * otherwise just return the name.
   1148     0    stevel  */
   1149     0    stevel const char *
   1150     0    stevel property_name_minus_ns(const pool_elem_t *pe, const char *name)
   1151     0    stevel {
   1152     0    stevel 	const char *prefix;
   1153     0    stevel 	if ((prefix = is_ns_property(pe, name)) != NULL) {
   1154     0    stevel 		return (name + strlen(prefix) + 1);
   1155     0    stevel 	}
   1156     0    stevel 	return (name);
   1157     0    stevel }
   1158     0    stevel 
   1159     0    stevel /*
   1160     0    stevel  * Create an element to represent a pool and add it to the supplied
   1161     0    stevel  * configuration.
   1162     0    stevel  */
   1163     0    stevel pool_t *
   1164     0    stevel pool_create(pool_conf_t *conf, const char *name)
   1165     0    stevel {
   1166     0    stevel 	pool_elem_t *pe;
   1167     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   1168     0    stevel 	const pool_prop_t *default_props;
   1169     0    stevel 
   1170     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
   1171     0    stevel 		return (NULL);
   1172     0    stevel 
   1173     0    stevel 	if (!is_valid_name(name) || pool_get_pool(conf, name) != NULL) {
   1174     0    stevel 		/*
   1175     0    stevel 		 * A pool with the same name exists. Reject.
   1176     0    stevel 		 */
   1177     0    stevel 		pool_seterror(POE_BADPARAM);
   1178     0    stevel 		return (NULL);
   1179     0    stevel 	}
   1180     0    stevel 	if ((pe = conf->pc_prov->pc_elem_create(conf, PEC_POOL, PREC_INVALID,
   1181     0    stevel 	    PCEC_INVALID)) == NULL) {
   1182     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1183     0    stevel 		return (NULL);
   1184     0    stevel 	}
   1185     0    stevel 	if ((default_props = provider_get_props(pe)) != NULL) {
   1186     0    stevel 		int i;
   1187     0    stevel 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
   1188     0    stevel 			if (prop_is_init(&default_props[i]) &&
   1189     0    stevel 			    (pool_put_any_property(pe,
   1190     0    stevel 			    default_props[i].pp_pname,
   1191     0    stevel 			    &default_props[i].pp_value) == PO_FAIL)) {
   1192     0    stevel 				(void) pool_destroy(conf, pool_elem_pool(pe));
   1193     0    stevel 				return (NULL);
   1194     0    stevel 			}
   1195     0    stevel 		}
   1196     0    stevel 	}
   1197     0    stevel 	if (pool_value_set_string(&val, name) != PO_SUCCESS) {
   1198     0    stevel 		(void) pool_destroy(conf, pool_elem_pool(pe));
   1199     0    stevel 		pool_seterror(POE_SYSTEM);
   1200     0    stevel 		return (NULL);
   1201     0    stevel 	}
   1202     0    stevel 	if (pool_put_property(conf, pe, "pool.name", &val) == PO_FAIL) {
   1203     0    stevel 		(void) pool_destroy(conf, pool_elem_pool(pe));
   1204     0    stevel 		pool_seterror(POE_PUTPROP);
   1205     0    stevel 		return (NULL);
   1206     0    stevel 	}
   1207  3247  gjelinek 
   1208  3247  gjelinek 	/*
   1209  3247  gjelinek 	 * If we are creating a temporary pool configuration, flag the pool.
   1210  3247  gjelinek 	 */
   1211  3247  gjelinek 	if (conf->pc_prov->pc_oflags & PO_TEMP) {
   1212  3247  gjelinek 		if (pool_set_temporary(conf, pe) == PO_FAIL) {
   1213  3247  gjelinek 			(void) pool_destroy(conf, pool_elem_pool(pe));
   1214  3247  gjelinek 			return (NULL);
   1215  3247  gjelinek 		}
   1216  3247  gjelinek 	}
   1217  3247  gjelinek 
   1218     0    stevel 	return (pool_elem_pool(pe));
   1219     0    stevel }
   1220     0    stevel 
   1221     0    stevel /*
   1222     0    stevel  * Create an element to represent a res.
   1223     0    stevel  */
   1224     0    stevel pool_resource_t *
   1225     0    stevel pool_resource_create(pool_conf_t *conf, const char *sz_type, const char *name)
   1226     0    stevel {
   1227     0    stevel 	pool_elem_t *pe;
   1228     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   1229     0    stevel 	const pool_prop_t *default_props;
   1230     0    stevel 	pool_resource_t **resources;
   1231     0    stevel 	int is_default = 0;
   1232     0    stevel 	uint_t nelem;
   1233     0    stevel 	pool_elem_class_t elem_class;
   1234     0    stevel 	pool_resource_elem_class_t type;
   1235     0    stevel 	pool_value_t *props[] = { NULL, NULL };
   1236     0    stevel 
   1237     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
   1238     0    stevel 		return (NULL);
   1239     0    stevel 
   1240     0    stevel 	if ((type = pool_resource_elem_class_from_string(sz_type)) ==
   1241     0    stevel 	    PREC_INVALID) {
   1242     0    stevel 		pool_seterror(POE_BADPARAM);
   1243     0    stevel 		return (NULL);
   1244     0    stevel 	}
   1245     0    stevel 
   1246     0    stevel 	if (strcmp(sz_type, "pset") != 0) {
   1247     0    stevel 		pool_seterror(POE_BADPARAM);
   1248     0    stevel 		return (NULL);
   1249     0    stevel 	}
   1250     0    stevel 
   1251     0    stevel 	if (!is_valid_name(name) || pool_get_resource(conf, sz_type, name) !=
   1252     0    stevel 	    NULL) {
   1253     0    stevel 		/*
   1254     0    stevel 		 * Resources must be unique by name+type.
   1255     0    stevel 		 */
   1256     0    stevel 		pool_seterror(POE_BADPARAM);
   1257     0    stevel 		return (NULL);
   1258     0    stevel 	}
   1259     0    stevel 
   1260     0    stevel 	props[0] = &val;
   1261     0    stevel 
   1262     0    stevel 	if (pool_value_set_string(props[0], sz_type) != PO_SUCCESS ||
   1263     0    stevel 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS) {
   1264     0    stevel 		return (NULL);
   1265     0    stevel 	}
   1266     0    stevel 
   1267     0    stevel 	if ((resources = pool_query_resources(conf, &nelem, props)) == NULL) {
   1268     0    stevel 		/*
   1269     0    stevel 		 * This is the first representative of this type; when it's
   1270     0    stevel 		 * created it should be created with 'default' = 'true'.
   1271     0    stevel 		 */
   1272     0    stevel 		is_default = 1;
   1273     0    stevel 	} else {
   1274     0    stevel 		free(resources);
   1275     0    stevel 	}
   1276     0    stevel 	/*
   1277     0    stevel 	 * TODO: If Additional PEC_RES_COMP types are added to
   1278     0    stevel 	 * pool_impl.h, this would need to be extended.
   1279     0    stevel 	 */
   1280     0    stevel 	switch (type) {
   1281     0    stevel 	case PREC_PSET:
   1282     0    stevel 		elem_class = PEC_RES_COMP;
   1283     0    stevel 		break;
   1284     0    stevel 	default:
   1285     0    stevel 		elem_class = PEC_RES_AGG;
   1286     0    stevel 		break;
   1287     0    stevel 	}
   1288     0    stevel 	if ((pe = conf->pc_prov->pc_elem_create(conf, elem_class, type,
   1289     0    stevel 	    PCEC_INVALID)) == NULL) {
   1290     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1291     0    stevel 		return (NULL);
   1292     0    stevel 	}
   1293     0    stevel 
   1294     0    stevel 	/*
   1295     0    stevel 	 * The plugins contain a list of default properties and their values
   1296     0    stevel 	 * for resources. The resource returned, hence, is fully initialized.
   1297     0    stevel 	 */
   1298     0    stevel 	if ((default_props = provider_get_props(pe)) != NULL) {
   1299     0    stevel 		int i;
   1300     0    stevel 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
   1301     0    stevel 			if (prop_is_init(&default_props[i]) &&
   1302     0    stevel 			    pool_put_any_property(pe, default_props[i].pp_pname,
   1303     0    stevel 			    &default_props[i].pp_value) == PO_FAIL) {
   1304     0    stevel 				(void) pool_resource_destroy(conf,
   1305     0    stevel 				    pool_elem_res(pe));
   1306     0    stevel 				return (NULL);
   1307     0    stevel 			}
   1308     0    stevel 		}
   1309     0    stevel 	}
   1310     0    stevel 	if (pool_value_set_string(&val, name) != PO_SUCCESS ||
   1311     0    stevel 	    pool_put_ns_property(pe, "name", &val) != PO_SUCCESS) {
   1312     0    stevel 		(void) pool_resource_destroy(conf, pool_elem_res(pe));
   1313     0    stevel 		return (NULL);
   1314     0    stevel 	}
   1315     0    stevel 	if (is_default) {
   1316     0    stevel 		pool_value_set_bool(&val, PO_TRUE);
   1317     0    stevel 		if (pool_put_any_ns_property(pe, "default", &val) !=
   1318     0    stevel 		    PO_SUCCESS) {
   1319     0    stevel 			(void) pool_resource_destroy(conf, pool_elem_res(pe));
   1320     0    stevel 			return (NULL);
   1321     0    stevel 		}
   1322     0    stevel 	}
   1323  3247  gjelinek 
   1324  3247  gjelinek 	/*
   1325  3247  gjelinek 	 * If we are creating a temporary pool configuration, flag the resource.
   1326  3247  gjelinek 	 */
   1327  3247  gjelinek 	if (conf->pc_prov->pc_oflags & PO_TEMP) {
   1328  3247  gjelinek 		if (pool_set_temporary(conf, pe) != PO_SUCCESS) {
   1329  3247  gjelinek 			(void) pool_resource_destroy(conf, pool_elem_res(pe));
   1330  3247  gjelinek 			return (NULL);
   1331  3247  gjelinek 		}
   1332  3247  gjelinek 	}
   1333  3247  gjelinek 
   1334     0    stevel 	return (pool_elem_res(pe));
   1335     0    stevel }
   1336     0    stevel 
   1337     0    stevel /*
   1338     0    stevel  * Create an element to represent a resource component.
   1339     0    stevel  */
   1340     0    stevel pool_component_t *
   1341     0    stevel pool_component_create(pool_conf_t *conf, const pool_resource_t *res,
   1342     0    stevel     int64_t sys_id)
   1343     0    stevel {
   1344     0    stevel 	pool_elem_t *pe;
   1345     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   1346     0    stevel 	const pool_prop_t *default_props;
   1347     0    stevel 	char refbuf[KEY_BUFFER_SIZE];
   1348     0    stevel 
   1349     0    stevel 	if ((pe = conf->pc_prov->pc_elem_create(conf, PEC_COMP,
   1350     0    stevel 	    PREC_INVALID, PCEC_CPU)) == NULL) {
   1351     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1352     0    stevel 		return (NULL);
   1353     0    stevel 	}
   1354     0    stevel 	/*
   1355     0    stevel 	 * TODO: If additional PEC_COMP types are added in pool_impl.h,
   1356     0    stevel 	 * this would need to be extended.
   1357     0    stevel 	 */
   1358     0    stevel 	pe->pe_component_class = PCEC_CPU;
   1359     0    stevel 	/* Now set the container for this comp */
   1360     0    stevel 	if (pool_set_container(TO_ELEM(res), pe) == PO_FAIL) {
   1361     0    stevel 		(void) pool_component_destroy(pool_elem_comp(pe));
   1362     0    stevel 		return (NULL);
   1363     0    stevel 	}
   1364     0    stevel 	/*
   1365     0    stevel 	 * The plugins contain a list of default properties and their values
   1366     0    stevel 	 * for resources. The resource returned, hence, is fully initialized.
   1367     0    stevel 	 */
   1368     0    stevel 	if ((default_props = provider_get_props(pe)) != NULL) {
   1369     0    stevel 		int i;
   1370     0    stevel 		for (i = 0; default_props[i].pp_pname != NULL; i++) {
   1371     0    stevel 			if (prop_is_init(&default_props[i]) &&
   1372     0    stevel 			    pool_put_any_property(pe,
   1373     0    stevel 			    default_props[i].pp_pname,
   1374     0    stevel 			    &default_props[i].pp_value) == PO_FAIL) {
   1375     0    stevel 				(void) pool_component_destroy(
   1376     0    stevel 				    pool_elem_comp(pe));
   1377     0    stevel 				return (NULL);
   1378     0    stevel 			}
   1379     0    stevel 		}
   1380     0    stevel 	}
   1381     0    stevel 	/*
   1382     0    stevel 	 * Set additional attributes/properties on component.
   1383     0    stevel 	 */
   1384     0    stevel 	pool_value_set_int64(&val, sys_id);
   1385     0    stevel 	if (pool_put_any_ns_property(pe, c_sys_prop, &val) != PO_SUCCESS) {
   1386     0    stevel 		(void) pool_component_destroy(pool_elem_comp(pe));
   1387     0    stevel 		return (NULL);
   1388     0    stevel 	}
   1389     0    stevel 	if (snprintf(refbuf, KEY_BUFFER_SIZE, "%s_%lld",
   1390     0    stevel 	    pool_elem_class_string(pe), sys_id) > KEY_BUFFER_SIZE) {
   1391     0    stevel 		(void) pool_component_destroy(pool_elem_comp(pe));
   1392     0    stevel 		return (NULL);
   1393     0    stevel 	}
   1394     0    stevel 	if (pool_value_set_string(&val, refbuf) != PO_SUCCESS) {
   1395     0    stevel 		(void) pool_component_destroy(pool_elem_comp(pe));
   1396     0    stevel 		return (NULL);
   1397     0    stevel 	}
   1398     0    stevel 	if (pool_put_any_ns_property(pe, c_ref_id, &val) != PO_SUCCESS) {
   1399     0    stevel 		(void) pool_component_destroy(pool_elem_comp(pe));
   1400     0    stevel 		return (NULL);
   1401     0    stevel 	}
   1402     0    stevel 	return (pool_elem_comp(pe));
   1403     0    stevel }
   1404     0    stevel 
   1405     0    stevel /*
   1406     0    stevel  * Return the location of a configuration.
   1407     0    stevel  */
   1408     0    stevel const char *
   1409     0    stevel pool_conf_location(const pool_conf_t *conf)
   1410     0    stevel {
   1411     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1412     0    stevel 		pool_seterror(POE_BADPARAM);
   1413     0    stevel 		return (NULL);
   1414     0    stevel 	}
   1415     0    stevel 	return (conf->pc_location);
   1416     0    stevel }
   1417     0    stevel /*
   1418     0    stevel  * Close a configuration, freeing all associated resources. Once a
   1419     0    stevel  * configuration is closed, it can no longer be used.
   1420     0    stevel  */
   1421     0    stevel int
   1422     0    stevel pool_conf_close(pool_conf_t *conf)
   1423     0    stevel {
   1424     0    stevel 	int rv;
   1425     0    stevel 
   1426     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1427     0    stevel 		pool_seterror(POE_BADPARAM);
   1428     0    stevel 		return (PO_FAIL);
   1429     0    stevel 	}
   1430     0    stevel 	rv = conf->pc_prov->pc_close(conf);
   1431     0    stevel 	conf->pc_prov = NULL;
   1432     0    stevel 	free((void *)conf->pc_location);
   1433     0    stevel 	conf->pc_location = NULL;
   1434     0    stevel 	conf->pc_state = POF_INVALID;
   1435     0    stevel 	return (rv);
   1436     0    stevel }
   1437     0    stevel 
   1438     0    stevel /*
   1439     0    stevel  * Remove a configuration, freeing all associated resources. Once a
   1440     0    stevel  * configuration is removed, it can no longer be accessed and is forever
   1441     0    stevel  * gone.
   1442     0    stevel  */
   1443     0    stevel int
   1444     0    stevel pool_conf_remove(pool_conf_t *conf)
   1445     0    stevel {
   1446     0    stevel 	int rv;
   1447     0    stevel 
   1448     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1449     0    stevel 		pool_seterror(POE_BADPARAM);
   1450     0    stevel 		return (PO_FAIL);
   1451     0    stevel 	}
   1452     0    stevel 	rv = conf->pc_prov->pc_remove(conf);
   1453     0    stevel 	conf->pc_state = POF_INVALID;
   1454     0    stevel 	return (rv);
   1455     0    stevel }
   1456     0    stevel 
   1457     0    stevel /*
   1458     0    stevel  * pool_conf_alloc() allocate the resources to represent a configuration.
   1459     0    stevel  */
   1460     0    stevel pool_conf_t *
   1461     0    stevel pool_conf_alloc(void)
   1462     0    stevel {
   1463     0    stevel 	pool_conf_t *conf;
   1464     0    stevel 
   1465     0    stevel 	if ((conf = calloc(1, sizeof (pool_conf_t))) == NULL) {
   1466     0    stevel 		pool_seterror(POE_SYSTEM);
   1467     0    stevel 		return (NULL);
   1468     0    stevel 	}
   1469     0    stevel 	conf->pc_state = POF_INVALID;
   1470     0    stevel 	return (conf);
   1471     0    stevel }
   1472     0    stevel 
   1473     0    stevel /*
   1474     0    stevel  * pool_conf_free() frees the resources associated with a configuration.
   1475     0    stevel  */
   1476     0    stevel void
   1477     0    stevel pool_conf_free(pool_conf_t *conf)
   1478     0    stevel {
   1479     0    stevel 	free(conf);
   1480     0    stevel }
   1481     0    stevel 
   1482     0    stevel /*
   1483     0    stevel  * pool_conf_open() opens a configuration, establishing all required
   1484     0    stevel  * connections to the data source.
   1485     0    stevel  */
   1486     0    stevel int
   1487     0    stevel pool_conf_open(pool_conf_t *conf, const char *location, int oflags)
   1488     0    stevel {
   1489     0    stevel 	/*
   1490     0    stevel 	 * Since you can't do anything to a pool configuration without opening
   1491     0    stevel 	 * it, this represents a good point to intialise structures that would
   1492     0    stevel 	 * otherwise need to be initialised in a .init section.
   1493     0    stevel 	 */
   1494     0    stevel 	internal_init();
   1495     0    stevel 
   1496     0    stevel 	if (pool_conf_status(conf) != POF_INVALID) {
   1497     0    stevel 		/*
   1498     0    stevel 		 * Already opened configuration, return PO_FAIL
   1499     0    stevel 		 */
   1500     0    stevel 		pool_seterror(POE_BADPARAM);
   1501     0    stevel 		return (PO_FAIL);
   1502     0    stevel 	}
   1503  3247  gjelinek 	if (oflags & ~(PO_RDONLY | PO_RDWR | PO_CREAT | PO_DISCO | PO_UPDATE |
   1504  3247  gjelinek 	    PO_TEMP)) {
   1505     0    stevel 		pool_seterror(POE_BADPARAM);
   1506     0    stevel 		return (PO_FAIL);
   1507     0    stevel 	}
   1508     0    stevel 
   1509     0    stevel 	/*
   1510     0    stevel 	 * Creating a configuration implies read-write access, so make
   1511     0    stevel 	 * sure that PO_RDWR is set in addition if PO_CREAT is set.
   1512     0    stevel 	 */
   1513     0    stevel 	if (oflags & PO_CREAT)
   1514     0    stevel 		oflags |= PO_RDWR;
   1515     0    stevel 
   1516  3247  gjelinek 	/* location is ignored when creating a temporary configuration */
   1517  3247  gjelinek 	if (oflags & PO_TEMP)
   1518  3247  gjelinek 		location = "";
   1519  3247  gjelinek 
   1520     0    stevel 	if ((conf->pc_location = strdup(location)) == NULL) {
   1521     0    stevel 		pool_seterror(POE_SYSTEM);
   1522     0    stevel 		return (PO_FAIL);
   1523     0    stevel 	}
   1524     0    stevel 	/*
   1525     0    stevel 	 * This is the crossover point into the actual data provider
   1526     0    stevel 	 * implementation, allocate a data provider of the appropriate
   1527  3247  gjelinek 	 * type for your data storage medium. In this case it's either a kernel
   1528  3247  gjelinek 	 * or xml data provider. To use a different data provider, write some
   1529  3247  gjelinek 	 * code to implement all the required interfaces and then change the
   1530  3247  gjelinek 	 * following code to allocate a data provider which uses your new code.
   1531  3247  gjelinek 	 * All data provider routines can be static, apart from the allocation
   1532  3247  gjelinek 	 * routine.
   1533  3247  gjelinek 	 *
   1534  3247  gjelinek 	 * For temporary pools (PO_TEMP) we start with a copy of the current
   1535  3247  gjelinek 	 * dynamic configuration and do all of the updates in-memory.
   1536     0    stevel 	 */
   1537  3247  gjelinek 	if (oflags & PO_TEMP) {
   1538  3247  gjelinek 		if (pool_knl_connection_alloc(conf, PO_TEMP) != PO_SUCCESS) {
   1539  3247  gjelinek 			conf->pc_state = POF_INVALID;
   1540  3247  gjelinek 			return (PO_FAIL);
   1541  3247  gjelinek 		}
   1542  3247  gjelinek 		/* set rdwr flag so we can updated the in-memory config. */
   1543  3247  gjelinek 		conf->pc_prov->pc_oflags |= PO_RDWR;
   1544  3247  gjelinek 
   1545  3247  gjelinek 	} else if (strcmp(location, pool_dynamic_location()) == 0) {
   1546     0    stevel 		if (pool_knl_connection_alloc(conf, oflags) != PO_SUCCESS) {
   1547     0    stevel 			conf->pc_state = POF_INVALID;
   1548     0    stevel 			return (PO_FAIL);
   1549     0    stevel 		}
   1550     0    stevel 	} else {
   1551     0    stevel 		if (pool_xml_connection_alloc(conf, oflags) != PO_SUCCESS) {
   1552     0    stevel 			conf->pc_state = POF_INVALID;
   1553     0    stevel 			return (PO_FAIL);
   1554     0    stevel 		}
   1555     0    stevel 	}
   1556     0    stevel 	return (PO_SUCCESS);
   1557     0    stevel }
   1558     0    stevel 
   1559     0    stevel /*
   1560     0    stevel  * Rollback a configuration. This will undo all changes to the configuration
   1561     0    stevel  * since the last time pool_conf_commit was called.
   1562     0    stevel  */
   1563     0    stevel int
   1564     0    stevel pool_conf_rollback(pool_conf_t *conf)
   1565     0    stevel {
   1566     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1567     0    stevel 		pool_seterror(POE_BADPARAM);
   1568     0    stevel 		return (PO_FAIL);
   1569     0    stevel 	}
   1570     0    stevel 	return (conf->pc_prov->pc_rollback(conf));
   1571     0    stevel }
   1572     0    stevel 
   1573     0    stevel /*
   1574     0    stevel  * Commit a configuration. This will apply all changes to the
   1575     0    stevel  * configuration to the permanent data store. The active parameter
   1576     0    stevel  * indicates whether the configuration should be used to update the
   1577     0    stevel  * dynamic configuration from the supplied (static) configuration or
   1578     0    stevel  * whether it should be written back to persistent store.
   1579     0    stevel  */
   1580     0    stevel int
   1581     0    stevel pool_conf_commit(pool_conf_t *conf, int active)
   1582     0    stevel {
   1583     0    stevel 	int retval;
   1584     0    stevel 
   1585     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1586     0    stevel 		pool_seterror(POE_BADPARAM);
   1587     0    stevel 		return (PO_FAIL);
   1588     0    stevel 	}
   1589     0    stevel 	if (active) {
   1590     0    stevel 		int oflags;
   1591     0    stevel 
   1592     0    stevel 		if (conf_is_dynamic(conf) == PO_TRUE) {
   1593     0    stevel 			pool_seterror(POE_BADPARAM);
   1594     0    stevel 			return (PO_FAIL);
   1595     0    stevel 		}
   1596     0    stevel 		/*
   1597     0    stevel 		 * Pretend that the configuration was opened PO_RDWR
   1598     0    stevel 		 * so that a configuration which was opened PO_RDONLY
   1599     0    stevel 		 * can be committed. The original flags are preserved
   1600     0    stevel 		 * in oflags and restored after pool_conf_commit_sys()
   1601     0    stevel 		 * returns.
   1602     0    stevel 		 */
   1603     0    stevel 		oflags = conf->pc_prov->pc_oflags;
   1604     0    stevel 		conf->pc_prov->pc_oflags |= PO_RDWR;
   1605     0    stevel 		retval = pool_conf_commit_sys(conf, active);
   1606     0    stevel 		conf->pc_prov->pc_oflags = oflags;
   1607     0    stevel 	} else {
   1608     0    stevel 		/*
   1609     0    stevel 		 * Write the configuration back to the backing store.
   1610     0    stevel 		 */
   1611     0    stevel 		retval =  conf->pc_prov->pc_commit(conf);
   1612     0    stevel 	}
   1613     0    stevel 	return (retval);
   1614     0    stevel }
   1615     0    stevel 
   1616     0    stevel /*
   1617     0    stevel  * Export a configuration. This will export a configuration in the specified
   1618     0    stevel  * format (fmt) to the specified location.
   1619     0    stevel  */
   1620     0    stevel int
   1621     0    stevel pool_conf_export(const pool_conf_t *conf, const char *location,
   1622     0    stevel     pool_export_format_t fmt)
   1623     0    stevel {
   1624     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1625     0    stevel 		pool_seterror(POE_BADPARAM);
   1626     0    stevel 		return (PO_FAIL);
   1627     0    stevel 	}
   1628     0    stevel 	return (conf->pc_prov->pc_export(conf, location, fmt));
   1629     0    stevel }
   1630     0    stevel 
   1631     0    stevel /*
   1632     0    stevel  * Validate a configuration. This will validate a configuration at the
   1633     0    stevel  * specified level.
   1634     0    stevel  */
   1635     0    stevel int
   1636     0    stevel pool_conf_validate(const pool_conf_t *conf, pool_valid_level_t level)
   1637     0    stevel {
   1638     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1639     0    stevel 		pool_seterror(POE_BADPARAM);
   1640     0    stevel 		return (PO_FAIL);
   1641     0    stevel 	}
   1642     0    stevel 	return (conf->pc_prov->pc_validate(conf, level));
   1643     0    stevel }
   1644     0    stevel 
   1645     0    stevel /*
   1646     0    stevel  * Update the snapshot of a configuration. This can only be used on a
   1647     0    stevel  * dynamic configuration.
   1648     0    stevel  */
   1649     0    stevel int
   1650     0    stevel pool_conf_update(const pool_conf_t *conf, int *changed)
   1651     0    stevel {
   1652     0    stevel 	if (pool_conf_status(conf) == POF_INVALID ||
   1653     0    stevel 	    conf_is_dynamic(conf) == PO_FALSE) {
   1654     0    stevel 		pool_seterror(POE_BADPARAM);
   1655     0    stevel 		return (PO_FAIL);
   1656     0    stevel 	}
   1657     0    stevel 	/*
   1658     0    stevel 	 * Since this function only makes sense for dynamic
   1659     0    stevel 	 * configurations, just call directly into the appropriate
   1660     0    stevel 	 * function. This could be added into the pool_connection_t
   1661     0    stevel 	 * interface if it was ever required.
   1662     0    stevel 	 */
   1663     0    stevel 	if (changed)
   1664     0    stevel 		*changed = 0;
   1665     0    stevel 	return (pool_knl_update((pool_conf_t *)conf, changed));
   1666     0    stevel }
   1667     0    stevel 
   1668     0    stevel /*
   1669     0    stevel  * Walk the properties of the supplied elem, calling the user supplied
   1670     0    stevel  * function repeatedly as long as the user function returns
   1671     0    stevel  * PO_SUCCESS.
   1672     0    stevel  */
   1673     0    stevel int
   1674     0    stevel pool_walk_properties(pool_conf_t *conf, pool_elem_t *elem, void *arg,
   1675     0    stevel     int (*prop_callback)(pool_conf_t *, pool_elem_t *, const char *,
   1676     0    stevel 	pool_value_t *, void *))
   1677     0    stevel {
   1678     0    stevel 	return (pool_walk_any_properties(conf, elem, arg, prop_callback, 0));
   1679     0    stevel }
   1680     0    stevel 
   1681     0    stevel void
   1682     0    stevel free_value_list(int npvals, pool_value_t **pvals)
   1683     0    stevel {
   1684     0    stevel 	int j;
   1685     0    stevel 
   1686     0    stevel 	for (j = 0; j < npvals; j++) {
   1687     0    stevel 		if (pvals[j])
   1688     0    stevel 			pool_value_free(pvals[j]);
   1689     0    stevel 	}
   1690     0    stevel 	free(pvals);
   1691     0    stevel }
   1692     0    stevel 
   1693     0    stevel /*
   1694     0    stevel  * Walk the properties of the supplied elem, calling the user supplied
   1695     0    stevel  * function repeatedly as long as the user function returns
   1696     0    stevel  * PO_SUCCESS.
   1697     0    stevel  * The list of properties to be walked is retrieved from the element
   1698     0    stevel  */
   1699     0    stevel int
   1700     0    stevel pool_walk_any_properties(pool_conf_t *conf, pool_elem_t *elem, void *arg,
   1701     0    stevel     int (*prop_callback)(pool_conf_t *, pool_elem_t *, const char *,
   1702     0    stevel 	pool_value_t *, void *), int any)
   1703     0    stevel {
   1704     0    stevel 	pool_value_t **pvals;
   1705     0    stevel 	int i;
   1706     0    stevel 	const pool_prop_t *props = provider_get_props(elem);
   1707     0    stevel 	uint_t npvals;
   1708     0    stevel 
   1709     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1710     0    stevel 		pool_seterror(POE_BADPARAM);
   1711     0    stevel 		return (PO_FAIL);
   1712     0    stevel 	}
   1713     0    stevel 
   1714     0    stevel 	if (props == NULL) {
   1715     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1716     0    stevel 		return (PO_FAIL);
   1717     0    stevel 	}
   1718     0    stevel 
   1719     0    stevel 	if ((pvals = elem->pe_get_props(elem, &npvals)) == NULL)
   1720     0    stevel 		return (PO_FAIL);
   1721     0    stevel 
   1722     0    stevel 	/*
   1723     0    stevel 	 * Now walk the managed properties. As we find managed
   1724     0    stevel 	 * properties removed them from the list of all properties to
   1725     0    stevel 	 * prevent duplication.
   1726     0    stevel 	 */
   1727     0    stevel 	for (i = 0;  props[i].pp_pname != NULL; i++) {
   1728     0    stevel 		int j;
   1729     0    stevel 
   1730     0    stevel 		/*
   1731     0    stevel 		 * Special processing for type
   1732     0    stevel 		 */
   1733     0    stevel 		if (strcmp(props[i].pp_pname, c_type) == 0) {
   1734     0    stevel 			pool_value_t val = POOL_VALUE_INITIALIZER;
   1735     0    stevel 
   1736     0    stevel 			if (pool_value_set_name(&val, props[i].pp_pname) ==
   1737     0    stevel 			    PO_FAIL) {
   1738     0    stevel 				free_value_list(npvals, pvals);
   1739     0    stevel 				return (PO_FAIL);
   1740     0    stevel 			}
   1741     0    stevel 			if (props[i].pp_op.ppo_get_value(elem, &val) ==
   1742     0    stevel 			    PO_FAIL) {
   1743     0    stevel 				free_value_list(npvals, pvals);
   1744     0    stevel 				return (PO_FAIL);
   1745     0    stevel 			}
   1746     0    stevel 			if (any == 1 || prop_is_hidden(&props[i]) == PO_FALSE) {
   1747     0    stevel 				if (prop_callback(conf, elem, props[i].pp_pname,
   1748     0    stevel 				    &val, arg) != PO_SUCCESS) {
   1749     0    stevel 					free_value_list(npvals, pvals);
   1750     0    stevel 					pool_seterror(POE_BADPARAM);
   1751     0    stevel 					return (PO_FAIL);
   1752     0    stevel 				}
   1753     0    stevel 			}
   1754     0    stevel 			continue;
   1755     0    stevel 		}
   1756     0    stevel 
   1757     0    stevel 		for (j = 0; j < npvals; j++) {
   1758     0    stevel 			if (pvals[j] && strcmp(pool_value_get_name(pvals[j]),
   1759     0    stevel 			    props[i].pp_pname) == 0)
   1760     0    stevel 				break;
   1761     0    stevel 		}
   1762     0    stevel 		/*
   1763     0    stevel 		 * If we have found the property, then j < npvals. Process it
   1764     0    stevel 		 * according to our property attributes. Otherwise, it's not
   1765     0    stevel 		 * a managed property, so just ignore it until later.
   1766     0    stevel 		 */
   1767     0    stevel 		if (j < npvals) {
   1768     0    stevel 			if (any == 1 || prop_is_hidden(&props[i]) == PO_FALSE) {
   1769     0    stevel 				if (props[i].pp_op.ppo_get_value) {
   1770     0    stevel 					if (pool_value_set_name(pvals[j],
   1771     0    stevel 					props[i].pp_pname) == PO_FAIL) {
   1772     0    stevel 						free_value_list(npvals, pvals);
   1773     0    stevel 						return (PO_FAIL);
   1774     0    stevel 					}
   1775     0    stevel 					if (props[i].pp_op.ppo_get_value(elem,
   1776     0    stevel 					    pvals[j]) == PO_FAIL) {
   1777     0    stevel 						free_value_list(npvals, pvals);
   1778     0    stevel 						return (PO_FAIL);
   1779     0    stevel 					}
   1780     0    stevel 				}
   1781     0    stevel 				if (prop_callback(conf, elem, props[i].pp_pname,
   1782     0    stevel 				    pvals[j], arg) != PO_SUCCESS) {
   1783     0    stevel 					free_value_list(npvals, pvals);
   1784     0    stevel 					pool_seterror(POE_BADPARAM);
   1785     0    stevel 					return (PO_FAIL);
   1786     0    stevel 				}
   1787     0    stevel 			}
   1788     0    stevel 			pool_value_free(pvals[j]);
   1789     0    stevel 			pvals[j] = NULL;
   1790     0    stevel 		}
   1791     0    stevel 	}
   1792     0    stevel 	for (i = 0;  i < npvals; i++) {
   1793     0    stevel 		if (pvals[i]) {
   1794     0    stevel 			const char *name = pool_value_get_name(pvals[i]);
   1795     0    stevel 			char *qname = strrchr(name, '.');
   1796     0    stevel 			if ((qname && qname[1] != '_') ||
   1797     0    stevel 			    (!qname && name[0] != '_')) {
   1798     0    stevel 				if (prop_callback(conf, elem, name, pvals[i],
   1799     0    stevel 				    arg) != PO_SUCCESS) {
   1800     0    stevel 					free_value_list(npvals, pvals);
   1801     0    stevel 					pool_seterror(POE_BADPARAM);
   1802     0    stevel 					return (PO_FAIL);
   1803     0    stevel 				}
   1804     0    stevel 			}
   1805     0    stevel 			pool_value_free(pvals[i]);
   1806     0    stevel 			pvals[i] = NULL;
   1807     0    stevel 		}
   1808     0    stevel 	}
   1809     0    stevel 	free(pvals);
   1810     0    stevel 	return (PO_SUCCESS);
   1811     0    stevel }
   1812     0    stevel 
   1813     0    stevel /*
   1814     0    stevel  * Return a pool, searching the supplied configuration for a pool with the
   1815     0    stevel  * supplied name. The search is case sensitive.
   1816     0    stevel  */
   1817     0    stevel pool_t *
   1818     0    stevel pool_get_pool(const pool_conf_t *conf, const char *name)
   1819     0    stevel {
   1820     0    stevel 	pool_value_t *props[] = { NULL, NULL };
   1821     0    stevel 	pool_t **rs;
   1822     0    stevel 	pool_t *ret;
   1823     0    stevel 	uint_t size = 0;
   1824     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   1825     0    stevel 
   1826     0    stevel 	props[0] = &val;
   1827     0    stevel 
   1828     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1829     0    stevel 		pool_seterror(POE_BADPARAM);
   1830     0    stevel 		return (NULL);
   1831     0    stevel 	}
   1832     0    stevel 
   1833     0    stevel 	if (pool_value_set_name(props[0], "pool.name") != PO_SUCCESS ||
   1834     0    stevel 	    pool_value_set_string(props[0], name) != PO_SUCCESS) {
   1835     0    stevel 		return (NULL);
   1836     0    stevel 	}
   1837     0    stevel 	rs = pool_query_pools(conf, &size, props);
   1838     0    stevel 	if (rs == NULL) { /* Can't find a pool to match the name */
   1839     0    stevel 		return (NULL);
   1840     0    stevel 	}
   1841     0    stevel 	if (size != 1) {
   1842     0    stevel 		free(rs);
   1843     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1844     0    stevel 		return (NULL);
   1845     0    stevel 	}
   1846     0    stevel 	ret = rs[0];
   1847     0    stevel 	free(rs);
   1848     0    stevel 	return (ret);
   1849     0    stevel }
   1850     0    stevel 
   1851     0    stevel /*
   1852     0    stevel  * Return a result set of pools, searching the supplied configuration
   1853     0    stevel  * for pools which match the supplied property criteria. props is a null
   1854     0    stevel  * terminated list of properties which will be used to match qualifying
   1855     0    stevel  * pools. size is updated with the size of the pool
   1856     0    stevel  */
   1857     0    stevel pool_t **
   1858     0    stevel pool_query_pools(const pool_conf_t *conf, uint_t *size, pool_value_t **props)
   1859     0    stevel {
   1860     0    stevel 	pool_result_set_t *rs;
   1861     0    stevel 	pool_elem_t *pe;
   1862     0    stevel 	pool_t **result = NULL;
   1863     0    stevel 	int i = 0;
   1864     0    stevel 
   1865     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1866     0    stevel 		pool_seterror(POE_BADPARAM);
   1867     0    stevel 		return (NULL);
   1868     0    stevel 	}
   1869     0    stevel 	rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_POOL, props);
   1870     0    stevel 	if (rs == NULL) {
   1871     0    stevel 		return (NULL);
   1872     0    stevel 	}
   1873     0    stevel 	if ((*size = pool_rs_count(rs)) == 0) {
   1874     0    stevel 		(void) pool_rs_close(rs);
   1875     0    stevel 		return (NULL);
   1876     0    stevel 	}
   1877     0    stevel 	if ((result = malloc(sizeof (pool_t *) * (*size + 1))) == NULL) {
   1878     0    stevel 		pool_seterror(POE_SYSTEM);
   1879     0    stevel 		(void) pool_rs_close(rs);
   1880     0    stevel 		return (NULL);
   1881     0    stevel 	}
   1882     0    stevel 	(void) memset(result, 0, sizeof (pool_t *) * (*size + 1));
   1883     0    stevel 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
   1884     0    stevel 		if (pool_elem_class(pe) != PEC_POOL) {
   1885     0    stevel 			pool_seterror(POE_INVALID_CONF);
   1886     0    stevel 			free(result);
   1887     0    stevel 			(void) pool_rs_close(rs);
   1888     0    stevel 			return (NULL);
   1889     0    stevel 		}
   1890     0    stevel 		result[i++] = pool_elem_pool(pe);
   1891     0    stevel 	}
   1892     0    stevel 	(void) pool_rs_close(rs);
   1893     0    stevel 	return (result);
   1894     0    stevel }
   1895     0    stevel 
   1896     0    stevel /*
   1897     0    stevel  * Return an res, searching the supplied configuration for an res with the
   1898     0    stevel  * supplied name. The search is case sensitive.
   1899     0    stevel  */
   1900     0    stevel pool_resource_t *
   1901     0    stevel pool_get_resource(const pool_conf_t *conf, const char *sz_type,
   1902     0    stevel     const char *name)
   1903     0    stevel {
   1904     0    stevel 	pool_value_t *props[] = { NULL, NULL, NULL };
   1905     0    stevel 	pool_resource_t **rs;
   1906     0    stevel 	pool_resource_t *ret;
   1907     0    stevel 	uint_t size = 0;
   1908     0    stevel 	char_buf_t *cb = NULL;
   1909     0    stevel 	pool_value_t val0 = POOL_VALUE_INITIALIZER;
   1910     0    stevel 	pool_value_t val1 = POOL_VALUE_INITIALIZER;
   1911     0    stevel 
   1912     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1913     0    stevel 		pool_seterror(POE_BADPARAM);
   1914     0    stevel 		return (NULL);
   1915     0    stevel 	}
   1916     0    stevel 
   1917     0    stevel 	if (sz_type == NULL) {
   1918     0    stevel 		pool_seterror(POE_BADPARAM);
   1919     0    stevel 		return (NULL);
   1920     0    stevel 	}
   1921     0    stevel 
   1922     0    stevel 	props[0] = &val0;
   1923     0    stevel 	props[1] = &val1;
   1924     0    stevel 
   1925     0    stevel 	if (pool_value_set_string(props[0], sz_type) != PO_SUCCESS ||
   1926     0    stevel 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS)
   1927     0    stevel 		return (NULL);
   1928     0    stevel 
   1929     0    stevel 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
   1930     0    stevel 		return (NULL);
   1931     0    stevel 	}
   1932     0    stevel 	if (set_char_buf(cb, "%s.name", sz_type) != PO_SUCCESS) {
   1933     0    stevel 		free_char_buf(cb);
   1934     0    stevel 		return (NULL);
   1935     0    stevel 	}
   1936     0    stevel 	if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) {
   1937     0    stevel 		free_char_buf(cb);
   1938     0    stevel 		return (NULL);
   1939     0    stevel 	}
   1940     0    stevel 	if (pool_value_set_string(props[1], name) != PO_SUCCESS) {
   1941     0    stevel 		free_char_buf(cb);
   1942     0    stevel 		return (NULL);
   1943     0    stevel 	}
   1944     0    stevel 	free_char_buf(cb);
   1945     0    stevel 	rs = pool_query_resources(conf, &size, props);
   1946     0    stevel 	if (rs == NULL) {
   1947     0    stevel 		return (NULL);
   1948     0    stevel 	}
   1949     0    stevel 	if (size != 1) {
   1950     0    stevel 		free(rs);
   1951     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1952     0    stevel 		return (NULL);
   1953     0    stevel 	}
   1954     0    stevel 	ret = rs[0];
   1955     0    stevel 	free(rs);
   1956     0    stevel 	return (ret);
   1957     0    stevel }
   1958     0    stevel 
   1959     0    stevel /*
   1960     0    stevel  * Return a result set of res (actually as pool_elem_ts), searching the
   1961     0    stevel  * supplied configuration for res which match the supplied property
   1962     0    stevel  * criteria. props is a null terminated list of properties which will be used
   1963     0    stevel  * to match qualifying res.
   1964     0    stevel  */
   1965     0    stevel pool_resource_t **
   1966     0    stevel pool_query_resources(const pool_conf_t *conf, uint_t *size,
   1967     0    stevel     pool_value_t **props)
   1968     0    stevel {
   1969     0    stevel 	pool_result_set_t *rs;
   1970     0    stevel 	pool_elem_t *pe;
   1971     0    stevel 	pool_resource_t **result = NULL;
   1972     0    stevel 	int i = 0;
   1973     0    stevel 
   1974     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   1975     0    stevel 		pool_seterror(POE_BADPARAM);
   1976     0    stevel 		return (NULL);
   1977     0    stevel 	}
   1978     0    stevel 
   1979     0    stevel 	*size = 0;
   1980     0    stevel 
   1981     0    stevel 	rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_RES, props);
   1982     0    stevel 	if (rs == NULL) {
   1983     0    stevel 		return (NULL);
   1984     0    stevel 	}
   1985     0    stevel 	if ((*size = pool_rs_count(rs)) == 0) {
   1986     0    stevel 		(void) pool_rs_close(rs);
   1987     0    stevel 		return (NULL);
   1988     0    stevel 	}
   1989     0    stevel 	if ((result = malloc(sizeof (pool_resource_t *) * (*size + 1)))
   1990     0    stevel 	    == NULL) {
   1991     0    stevel 		pool_seterror(POE_SYSTEM);
   1992     0    stevel 		(void) pool_rs_close(rs);
   1993     0    stevel 		return (NULL);
   1994     0    stevel 	}
   1995     0    stevel 	(void) memset(result, 0, sizeof (pool_resource_t *) * (*size + 1));
   1996     0    stevel 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
   1997     0    stevel 		if (pool_elem_class(pe) != PEC_RES_COMP &&
   1998     0    stevel 		    pool_elem_class(pe) != PEC_RES_AGG) {
   1999     0    stevel 			pool_seterror(POE_INVALID_CONF);
   2000     0    stevel 			free(result);
   2001     0    stevel 			(void) pool_rs_close(rs);
   2002     0    stevel 			return (NULL);
   2003     0    stevel 		}
   2004     0    stevel 		result[i++] = pool_elem_res(pe);
   2005     0    stevel 	}
   2006     0    stevel 	(void) pool_rs_close(rs);
   2007     0    stevel 	return (result);
   2008     0    stevel }
   2009     0    stevel 
   2010     0    stevel /*
   2011     0    stevel  * Return a result set of comp (actually as pool_elem_ts), searching the
   2012     0    stevel  * supplied configuration for comp which match the supplied property
   2013     0    stevel  * criteria. props is a null terminated list of properties which will be used
   2014     0    stevel  * to match qualifying comp.
   2015     0    stevel  */
   2016     0    stevel pool_component_t **
   2017     0    stevel pool_query_components(const pool_conf_t *conf, uint_t *size,
   2018     0    stevel     pool_value_t **props)
   2019     0    stevel {
   2020     0    stevel 	return (pool_query_resource_components(conf, NULL, size, props));
   2021     0    stevel }
   2022     0    stevel 
   2023     0    stevel /*
   2024     0    stevel  * Destroy a pool. If the pool cannot be found or removed an error is
   2025     0    stevel  * returned. This is basically a wrapper around pool_elem_remove to ensure
   2026     0    stevel  * some type safety for the pool subtype.
   2027     0    stevel  */
   2028     0    stevel int
   2029     0    stevel pool_destroy(pool_conf_t *conf, pool_t *pp)
   2030     0    stevel {
   2031     0    stevel 	pool_elem_t *pe;
   2032     0    stevel 
   2033     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
   2034     0    stevel 		return (PO_FAIL);
   2035     0    stevel 
   2036     0    stevel 	pe = TO_ELEM(pp);
   2037     0    stevel 
   2038     0    stevel 	/*
   2039     0    stevel 	 * Cannot destroy the default pool.
   2040     0    stevel 	 */
   2041     0    stevel 	if (elem_is_default(pe) == PO_TRUE) {
   2042     0    stevel 		pool_seterror(POE_BADPARAM);
   2043     0    stevel 		return (PO_FAIL);
   2044     0    stevel 	}
   2045     0    stevel 	if (pool_elem_remove(pe) != PO_SUCCESS)
   2046     0    stevel 		return (PO_FAIL);
   2047     0    stevel 	return (PO_SUCCESS);
   2048     0    stevel }
   2049     0    stevel 
   2050     0    stevel /*
   2051     0    stevel  * Destroy an res. If the res cannot be found or removed an error is
   2052     0    stevel  * returned. This is basically a wrapper around pool_elem_remove to ensure
   2053     0    stevel  * some type safety for the res subtype.
   2054     0    stevel  */
   2055     0    stevel int
   2056     0    stevel pool_resource_destroy(pool_conf_t *conf, pool_resource_t *prs)
   2057     0    stevel {
   2058     0    stevel 	pool_elem_t *pe;
   2059     0    stevel 	pool_component_t **rl;
   2060     0    stevel 	uint_t res_size;
   2061     0    stevel 	pool_t **pl;
   2062     0    stevel 	uint_t npool;
   2063     0    stevel 	int i;
   2064     0    stevel 
   2065     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
   2066     0    stevel 		return (PO_FAIL);
   2067     0    stevel 
   2068     0    stevel 	pe = TO_ELEM(prs);
   2069     0    stevel 
   2070     0    stevel 	if (resource_is_system(prs) == PO_TRUE) {
   2071     0    stevel 		pool_seterror(POE_BADPARAM);
   2072     0    stevel 		return (PO_FAIL);
   2073     0    stevel 	}
   2074     0    stevel 	/*
   2075     0    stevel 	 * Walk all the pools and dissociate any pools which are using
   2076     0    stevel 	 * this resource.
   2077     0    stevel 	 */
   2078     0    stevel 	if ((pl = pool_query_pools(conf, &npool, NULL)) != NULL) {
   2079     0    stevel 		for (i = 0; i < npool; i++) {
   2080     0    stevel 			pool_resource_t **rl;
   2081     0    stevel 			uint_t nres;
   2082     0    stevel 			int j;
   2083     0    stevel 
   2084     0    stevel 			if ((rl = pool_query_pool_resources(conf, pl[i], &nres,
   2085     0    stevel 			    NULL)) != NULL) {
   2086     0    stevel 				for (j = 0; j < nres; j++) {
   2087     0    stevel 					if (rl[j] == prs) {
   2088     0    stevel 						if (pool_dissociate(conf, pl[i],
   2089     0    stevel 						    rl[j]) != PO_SUCCESS) {
   2090     0    stevel 							free(rl);
   2091     0    stevel 							free(pl);
   2092     0    stevel 							return (PO_FAIL);
   2093     0    stevel 						}
   2094     0    stevel 						break;
   2095     0    stevel 					}
   2096     0    stevel 				}
   2097     0    stevel 			free(rl);
   2098     0    stevel 			}
   2099     0    stevel 		}
   2100     0    stevel 		free(pl);
   2101     0    stevel 	}
   2102     0    stevel 	if (pe->pe_class == PEC_RES_COMP) {
   2103     0    stevel 		pool_resource_t *default_set_res;
   2104     0    stevel 
   2105     0    stevel 		/*
   2106     0    stevel 		 * Use the xtransfer option to move comp around
   2107     0    stevel 		 */
   2108     0    stevel 		default_set_res = (pool_resource_t *)get_default_resource(prs);
   2109     0    stevel 
   2110     0    stevel 		if ((rl = pool_query_resource_components(conf, prs, &res_size,
   2111     0    stevel 		    NULL)) != NULL) {
   2112     0    stevel 			int ostate = conf->pc_state;
   2113     0    stevel 			conf->pc_state = POF_DESTROY;
   2114     0    stevel 			if (pool_resource_xtransfer(conf, prs, default_set_res,
   2115     0    stevel 			    rl) == PO_FAIL) {
   2116     0    stevel 				free(rl);
   2117     0    stevel 				conf->pc_state = ostate;
   2118     0    stevel 				return (PO_FAIL);
   2119     0    stevel 			}
   2120     0    stevel 			conf->pc_state = ostate;
   2121     0    stevel 			free(rl);
   2122     0    stevel 		}
   2123     0    stevel 	}
   2124     0    stevel 	if (pool_elem_remove(pe) != PO_SUCCESS)
   2125     0    stevel 		return (PO_FAIL);
   2126     0    stevel 	return (PO_SUCCESS);
   2127     0    stevel }
   2128     0    stevel 
   2129     0    stevel /*
   2130     0    stevel  * Destroy a comp. If the comp cannot be found or removed an error is
   2131     0    stevel  * returned. This is basically a wrapper around pool_elem_remove to ensure
   2132     0    stevel  * some type safety for the comp subtype.
   2133     0    stevel  */
   2134     0    stevel int
   2135     0    stevel pool_component_destroy(pool_component_t *pr)
   2136     0    stevel {
   2137     0    stevel 	pool_elem_t *pe = TO_ELEM(pr);
   2138     0    stevel 
   2139     0    stevel 	if (pool_elem_remove(pe) != PO_SUCCESS)
   2140     0    stevel 		return (PO_FAIL);
   2141     0    stevel 	return (PO_SUCCESS);
   2142     0    stevel }
   2143     0    stevel 
   2144     0    stevel /*
   2145     0    stevel  * Remove a pool_elem_t from a configuration. This has been "hidden" away as
   2146     0    stevel  * a static routine since the only elements which are currently being removed
   2147     0    stevel  * are pools, res & comp and the wrapper functions above provide type-safe
   2148     0    stevel  * access. However, if there is a need to remove other types of elements
   2149     0    stevel  * then this could be promoted to pool_impl.h or more wrappers could
   2150     0    stevel  * be added to pool_impl.h.
   2151     0    stevel  */
   2152     0    stevel int
   2153     0    stevel pool_elem_remove(pool_elem_t *pe)
   2154     0    stevel {
   2155     0    stevel 	return (pe->pe_remove(pe));
   2156     0    stevel }
   2157     0    stevel 
   2158     0    stevel /*
   2159     0    stevel  * Execute a query to search for a qualifying set of elements.
   2160     0    stevel  */
   2161     0    stevel pool_result_set_t *
   2162     0    stevel pool_exec_query(const pool_conf_t *conf, const pool_elem_t *src,
   2163     0    stevel     const char *src_attr, pool_elem_class_t classes, pool_value_t **props)
   2164     0    stevel {
   2165     0    stevel 	return (conf->pc_prov->pc_exec_query(conf, src, src_attr, classes,
   2166     0    stevel 	    props));
   2167     0    stevel }
   2168     0    stevel 
   2169     0    stevel /*
   2170     0    stevel  * Get the next result from a result set of elements.
   2171     0    stevel  */
   2172     0    stevel pool_elem_t *
   2173     0    stevel pool_rs_next(pool_result_set_t *set)
   2174     0    stevel {
   2175     0    stevel 	return (set->prs_next(set));
   2176     0    stevel }
   2177     0    stevel 
   2178     0    stevel /*
   2179     0    stevel  * Get the previous result from a result set of elements.
   2180     0    stevel  */
   2181     0    stevel pool_elem_t *
   2182     0    stevel pool_rs_prev(pool_result_set_t *set)
   2183     0    stevel {
   2184     0    stevel 	return (set->prs_prev(set));
   2185     0    stevel }
   2186     0    stevel 
   2187     0    stevel /*
   2188     0    stevel  * Get the first result from a result set of elements.
   2189     0    stevel  */
   2190     0    stevel pool_elem_t *
   2191     0    stevel pool_rs_first(pool_result_set_t *set)
   2192     0    stevel {
   2193     0    stevel 	return (set->prs_first(set));
   2194     0    stevel }
   2195     0    stevel 
   2196     0    stevel /*
   2197     0    stevel  * Get the last result from a result set of elements.
   2198     0    stevel  */
   2199     0    stevel pool_elem_t *
   2200     0    stevel pool_rs_last(pool_result_set_t *set)
   2201     0    stevel {
   2202     0    stevel 	return (set->prs_last(set));
   2203     0    stevel }
   2204     0    stevel 
   2205     0    stevel 
   2206     0    stevel /*
   2207     0    stevel  * Get the count for a result set of elements.
   2208     0    stevel  */
   2209     0    stevel int
   2210     0    stevel pool_rs_count(pool_result_set_t *set)
   2211     0    stevel {
   2212     0    stevel 	return (set->prs_count(set));
   2213     0    stevel }
   2214     0    stevel 
   2215     0    stevel /*
   2216     0    stevel  * Get the index for a result set of elements.
   2217     0    stevel  */
   2218     0    stevel int
   2219     0    stevel pool_rs_get_index(pool_result_set_t *set)
   2220     0    stevel {
   2221     0    stevel 	return (set->prs_get_index(set));
   2222     0    stevel }
   2223     0    stevel 
   2224     0    stevel /*
   2225     0    stevel  * Set the index for a result set of elements.
   2226     0    stevel  */
   2227     0    stevel int
   2228     0    stevel pool_rs_set_index(pool_result_set_t *set, int index)
   2229     0    stevel {
   2230     0    stevel 	return (set->prs_set_index(set, index));
   2231     0    stevel }
   2232     0    stevel 
   2233     0    stevel /*
   2234     0    stevel  * Close a result set of elements, freeing all associated resources.
   2235     0    stevel  */
   2236     0    stevel int
   2237     0    stevel pool_rs_close(pool_result_set_t *set)
   2238     0    stevel {
   2239     0    stevel 	return (set->prs_close(set));
   2240     0    stevel }
   2241     0    stevel 
   2242     0    stevel /*
   2243     0    stevel  * When transferring resource components using pool_resource_transfer,
   2244     0    stevel  * this function is invoked to choose which actual components will be
   2245     0    stevel  * transferred.
   2246     0    stevel  */
   2247     0    stevel int
   2248     0    stevel choose_components(pool_resource_t *src, pool_resource_t *dst, uint64_t size)
   2249     0    stevel {
   2250     0    stevel 	pool_component_t **components = NULL, *moved[] = { NULL, NULL };
   2251     0    stevel 	int i;
   2252     0    stevel 	uint_t ncomponent;
   2253     0    stevel 	pool_conf_t *conf = TO_CONF(TO_ELEM(src));
   2254     0    stevel 
   2255     0    stevel 	if (size == 0)
   2256     0    stevel 		return (PO_SUCCESS);
   2257     0    stevel 	/*
   2258     0    stevel 	 * Get the component list from our src component.
   2259     0    stevel 	 */
   2260     0    stevel 	if ((components = pool_query_resource_components(conf, src, &ncomponent,
   2261     0    stevel 	    NULL)) == NULL) {
   2262     0    stevel 		pool_seterror(POE_BADPARAM);
   2263     0    stevel 		return (PO_FAIL);
   2264     0    stevel 	}
   2265     0    stevel 	qsort(components, ncomponent, sizeof (pool_elem_t *),
   2266     0    stevel 	    qsort_elem_compare);
   2267     0    stevel 	/*
   2268     0    stevel 	 * Components that aren't specifically requested by the resource
   2269     0    stevel 	 * should be transferred out first.
   2270     0    stevel 	 */
   2271     0    stevel 	for (i = 0; size > 0 && components[i] != NULL; i++) {
   2272     0    stevel 		if (!cpu_is_requested(components[i])) {
   2273     0    stevel 			moved[0] = components[i];
   2274     0    stevel 			if (pool_resource_xtransfer(conf, src, dst, moved) ==
   2275     0    stevel 			    PO_SUCCESS) {
   2276     0    stevel 				size--;
   2277     0    stevel 			}
   2278     0    stevel 		}
   2279     0    stevel 	}
   2280     0    stevel 
   2281     0    stevel 	/*
   2282     0    stevel 	 * If we couldn't find enough "un-requested" components, select random
   2283     0    stevel 	 * requested components.
   2284     0    stevel 	 */
   2285     0    stevel 	for (i = 0; size > 0 && components[i] != NULL; i++) {
   2286     0    stevel 		if (cpu_is_requested(components[i])) {
   2287     0    stevel 			moved[0] = components[i];
   2288     0    stevel 			if (pool_resource_xtransfer(conf, src, dst, moved) ==
   2289     0    stevel 			    PO_SUCCESS) {
   2290     0    stevel 				size--;
   2291     0    stevel 			}
   2292     0    stevel 		}
   2293     0    stevel 	}
   2294     0    stevel 
   2295     0    stevel 	free(components);
   2296     0    stevel 	/*
   2297     0    stevel 	 * If we couldn't transfer out all the resources we asked for, then
   2298     0    stevel 	 * return error.
   2299     0    stevel 	 */
   2300     0    stevel 	return (size == 0 ? PO_SUCCESS : PO_FAIL);
   2301     0    stevel }
   2302     0    stevel 
   2303     0    stevel /*
   2304     0    stevel  * Common processing for a resource transfer (xfer or xxfer).
   2305     0    stevel  *
   2306     0    stevel  * - Return XFER_CONTINUE if the transfer should proceeed
   2307     0    stevel  * - Return XFER_FAIL if the transfer should be stopped in failure
   2308     0    stevel  * - Return XFER_SUCCESS if the transfer should be stopped in success
   2309     0    stevel  */
   2310     0    stevel int
   2311     0    stevel setup_transfer(pool_conf_t *conf, pool_resource_t *src, pool_resource_t *tgt,
   2312     0    stevel     uint64_t size, uint64_t *src_size, uint64_t *tgt_size)
   2313     0    stevel {
   2314     0    stevel 	uint64_t src_min;
   2315     0    stevel 	uint64_t tgt_max;
   2316     0    stevel 
   2317     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
   2318     0    stevel 		return (XFER_FAIL);
   2319     0    stevel 
   2320     0    stevel 	/*
   2321     0    stevel 	 * Makes sure the two resources are of the same type
   2322     0    stevel 	 */
   2323     0    stevel 	if (pool_resource_elem_class(TO_ELEM(src)) !=
   2324     0    stevel 	    pool_resource_elem_class(TO_ELEM(tgt))) {
   2325     0    stevel 		pool_seterror(POE_BADPARAM);
   2326     0    stevel 		return (XFER_FAIL);
   2327     0    stevel 	}
   2328     0    stevel 
   2329     0    stevel 	/*
   2330     0    stevel 	 * Transferring to yourself is a no-op
   2331     0    stevel 	 */
   2332     0    stevel 	if (src == tgt)
   2333     0    stevel 		return (XFER_SUCCESS);
   2334     0    stevel 
   2335     0    stevel 	/*
   2336     0    stevel 	 * Transferring nothing is a no-op
   2337     0    stevel 	 */
   2338     0    stevel 	if (size == 0)
   2339     0    stevel 		return (XFER_SUCCESS);
   2340     0    stevel 
   2341     0    stevel 	if (resource_get_min(src, &src_min) != PO_SUCCESS ||
   2342     0    stevel 	    resource_get_size(src, src_size) != PO_SUCCESS ||
   2343     0    stevel 	    resource_get_max(tgt, &tgt_max) != PO_SUCCESS ||
   2344     0    stevel 	    resource_get_size(tgt, tgt_size) != PO_SUCCESS) {
   2345     0    stevel 		pool_seterror(POE_BADPARAM);
   2346     0    stevel 		return (XFER_FAIL);
   2347     0    stevel 	}
   2348     0    stevel 	if (pool_conf_status(conf) != POF_DESTROY) {
   2349     0    stevel 		/*
   2350     0    stevel 		 * src_size - donating >= src.min
   2351     0    stevel 		 * size + receiving <= tgt.max (except for default)
   2352     0    stevel 		 */
   2353     0    stevel #ifdef DEBUG
   2354     0    stevel 		dprintf("conf is %s\n", pool_conf_location(conf));
   2355     0    stevel 		dprintf("setup_transfer: src_size %llu\n", *src_size);
   2356     0    stevel 		pool_elem_dprintf(TO_ELEM(src));
   2357     0    stevel 		dprintf("setup_transfer: tgt_size %llu\n", *tgt_size);
   2358     0    stevel 		pool_elem_dprintf(TO_ELEM(tgt));
   2359     0    stevel #endif	/* DEBUG */
   2360     0    stevel 		if (*src_size - size < src_min ||
   2361     0    stevel 		    (resource_is_default(tgt) == PO_FALSE &&
   2362     0    stevel 			*tgt_size + size > tgt_max)) {
   2363     0    stevel 			pool_seterror(POE_INVALID_CONF);
   2364     0    stevel 			return (XFER_FAIL);
   2365     0    stevel 		}
   2366     0    stevel 	}
   2367     0    stevel 	return (XFER_CONTINUE);
   2368     0    stevel }
   2369     0    stevel 
   2370     0    stevel /*
   2371     0    stevel  * Transfer resource quantities from one resource set to another.
   2372     0    stevel  */
   2373     0    stevel int
   2374     0    stevel pool_resource_transfer(pool_conf_t *conf, pool_resource_t *src,
   2375     0    stevel     pool_resource_t *tgt, uint64_t size)
   2376     0    stevel {
   2377     0    stevel 	uint64_t src_size;
   2378     0    stevel 	uint64_t tgt_size;
   2379     0    stevel 	int ret;
   2380     0    stevel 
   2381     0    stevel 	if ((ret = setup_transfer(conf, src, tgt, size, &src_size, &tgt_size))
   2382     0    stevel 	    != XFER_CONTINUE)
   2383     0    stevel 		return (ret);
   2384     0    stevel 	/*
   2385     0    stevel 	 * If this resource is a res_comp we must call move components
   2386     0    stevel 	 */
   2387     0    stevel 	if (pool_elem_class(TO_ELEM(src)) == PEC_RES_COMP)
   2388     0    stevel 		return (choose_components(src, tgt, size));
   2389     0    stevel 	/*
   2390     0    stevel 	 * Now do the transfer.
   2391     0    stevel 	 */
   2392     0    stevel 	ret = conf->pc_prov->pc_res_xfer(src, tgt, size);
   2393     0    stevel 	/*
   2394     0    stevel 	 * Modify the sizes of the resource sets if the process was
   2395     0    stevel 	 * successful
   2396     0    stevel 	 */
   2397     0    stevel 	if (ret == PO_SUCCESS) {
   2398     0    stevel 		pool_value_t val = POOL_VALUE_INITIALIZER;
   2399     0    stevel 
   2400     0    stevel 		src_size -= size;
   2401     0    stevel 		tgt_size += size;
   2402     0    stevel 		pool_value_set_uint64(&val, src_size);
   2403     0    stevel 		(void) pool_put_any_ns_property(TO_ELEM(src), c_size_prop,
   2404     0    stevel 		    &val);
   2405     0    stevel 		pool_value_set_uint64(&val, tgt_size);
   2406     0    stevel 		(void) pool_put_any_ns_property(TO_ELEM(tgt), c_size_prop,
   2407     0    stevel 		    &val);
   2408     0    stevel 	}
   2409     0    stevel 	return (ret);
   2410     0    stevel }
   2411     0    stevel 
   2412     0    stevel /*
   2413     0    stevel  * Transfer resource components from one resource set to another.
   2414     0    stevel  */
   2415     0    stevel int
   2416     0    stevel pool_resource_xtransfer(pool_conf_t *conf, pool_resource_t *src,
   2417     0    stevel     pool_resource_t *tgt,
   2418     0    stevel     pool_component_t **rl)
   2419     0    stevel {
   2420     0    stevel 	int i;
   2421     0    stevel 	uint64_t src_size;
   2422     0    stevel 	uint64_t tgt_size;
   2423     0    stevel 	uint64_t size;
   2424     0    stevel 	int ret;
   2425     0    stevel 
   2426     0    stevel 	/*
   2427     0    stevel 	 * Make sure the components are all contained in 'src'. This
   2428     0    stevel 	 * processing must be done before setup_transfer so that size
   2429     0    stevel 	 * is known.
   2430     0    stevel 	 */
   2431     0    stevel 	for (i = 0; rl[i] != NULL; i++) {
   2432     0    stevel #ifdef DEBUG
   2433     0    stevel 		dprintf("resource xtransfer\n");
   2434     0    stevel 		dprintf("in conf %s\n", pool_conf_location(conf));
   2435     0    stevel 		dprintf("transferring component\n");
   2436     0    stevel 		pool_elem_dprintf(TO_ELEM(rl[i]));
   2437     0    stevel 		dprintf("from\n");
   2438     0    stevel 		pool_elem_dprintf(TO_ELEM(src));
   2439     0    stevel 		dprintf("to\n");
   2440     0    stevel 		pool_elem_dprintf(TO_ELEM(tgt));
   2441     0    stevel #endif	/* DEBUG */
   2442     0    stevel 
   2443     0    stevel 		if (pool_get_owning_resource(conf, rl[i]) != src) {
   2444     0    stevel 			pool_seterror(POE_BADPARAM);
   2445     0    stevel 			return (PO_FAIL);
   2446     0    stevel 		}
   2447     0    stevel 	}
   2448     0    stevel 
   2449     0    stevel 	size = (uint64_t)i;
   2450     0    stevel 
   2451     0    stevel 	if ((ret = setup_transfer(conf, src, tgt, size, &src_size, &tgt_size))
   2452     0    stevel 	    != XFER_CONTINUE)
   2453     0    stevel 		return (ret);
   2454     0    stevel 
   2455     0    stevel 	ret = conf->pc_prov->pc_res_xxfer(src, tgt, rl);
   2456     0    stevel 	/*
   2457     0    stevel 	 * Modify the sizes of the resource sets if the process was
   2458     0    stevel 	 * successful
   2459     0    stevel 	 */
   2460     0    stevel 	if (ret == PO_SUCCESS) {
   2461     0    stevel 		pool_value_t val = POOL_VALUE_INITIALIZER;
   2462     0    stevel 
   2463     0    stevel #ifdef DEBUG
   2464     0    stevel 		dprintf("src_size %llu\n", src_size);
   2465     0    stevel 		dprintf("tgt_size %llu\n", tgt_size);
   2466     0    stevel 		dprintf("size %llu\n", size);
   2467     0    stevel #endif	/* DEBUG */
   2468     0    stevel 		src_size -= size;
   2469     0    stevel 		tgt_size += size;
   2470     0    stevel 		pool_value_set_uint64(&val, src_size);
   2471     0    stevel 		(void) pool_put_any_ns_property(TO_ELEM(src), c_size_prop,
   2472     0    stevel 		    &val);
   2473     0    stevel 		pool_value_set_uint64(&val, tgt_size);
   2474     0    stevel 		(void) pool_put_any_ns_property(TO_ELEM(tgt), c_size_prop,
   2475     0    stevel 		    &val);
   2476     0    stevel 	}
   2477     0    stevel 	return (ret);
   2478     0    stevel }
   2479     0    stevel 
   2480     0    stevel /*
   2481     0    stevel  * Find the owning resource for a resource component.
   2482     0    stevel  */
   2483     0    stevel pool_resource_t *
   2484     0    stevel pool_get_owning_resource(const pool_conf_t *conf, const pool_component_t *comp)
   2485     0    stevel {
   2486     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2487     0    stevel 		pool_seterror(POE_BADPARAM);
   2488     0    stevel 		return (NULL);
   2489     0    stevel 	}
   2490     0    stevel 	return (pool_elem_res(pool_get_container(TO_ELEM(comp))));
   2491     0    stevel }
   2492     0    stevel 
   2493     0    stevel /*
   2494     0    stevel  * pool_get_container() returns the container of pc.
   2495     0    stevel  */
   2496     0    stevel pool_elem_t *
   2497     0    stevel pool_get_container(const pool_elem_t *pc)
   2498     0    stevel {
   2499     0    stevel 	return (pc->pe_get_container(pc));
   2500     0    stevel }
   2501     0    stevel 
   2502     0    stevel /*
   2503     0    stevel  * pool_set_container() moves pc so that it is contained by pp.
   2504     0    stevel  *
   2505     0    stevel  * Returns PO_SUCCESS/PO_FAIL
   2506     0    stevel  */
   2507     0    stevel int
   2508     0    stevel pool_set_container(pool_elem_t *pp, pool_elem_t *pc)
   2509     0    stevel {
   2510     0    stevel 	return (pc->pe_set_container(pp, pc));
   2511     0    stevel }
   2512     0    stevel 
   2513     0    stevel /*
   2514     0    stevel  * Conversion routines for converting to and from elem and it's various
   2515     0    stevel  * subtypes of system, pool, res and comp.
   2516     0    stevel  */
   2517     0    stevel pool_elem_t *
   2518     0    stevel pool_system_elem(const pool_system_t *ph)
   2519     0    stevel {
   2520     0    stevel 	return ((pool_elem_t *)ph);
   2521     0    stevel }
   2522     0    stevel 
   2523     0    stevel pool_elem_t *
   2524     0    stevel pool_conf_to_elem(const pool_conf_t *conf)
   2525     0    stevel {
   2526     0    stevel 	pool_system_t *sys;
   2527     0    stevel 
   2528     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2529     0    stevel 		pool_seterror(POE_BADPARAM);
   2530     0    stevel 		return (NULL);
   2531     0    stevel 	}
   2532     0    stevel 	if ((sys = pool_conf_system(conf)) == NULL) {
   2533     0    stevel 		pool_seterror(POE_BADPARAM);
   2534     0    stevel 		return (NULL);
   2535     0    stevel 	}
   2536     0    stevel 	return (pool_system_elem(sys));
   2537     0    stevel }
   2538     0    stevel 
   2539     0    stevel pool_elem_t *
   2540     0    stevel pool_to_elem(const pool_conf_t *conf, const pool_t *pp)
   2541     0    stevel {
   2542     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2543     0    stevel 		pool_seterror(POE_BADPARAM);
   2544     0    stevel 		return (NULL);
   2545     0    stevel 	}
   2546     0    stevel 	return ((pool_elem_t *)pp);
   2547     0    stevel }
   2548     0    stevel 
   2549     0    stevel pool_elem_t *
   2550     0    stevel pool_resource_to_elem(const pool_conf_t *conf, const pool_resource_t *prs)
   2551     0    stevel {
   2552     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2553     0    stevel 		pool_seterror(POE_BADPARAM);
   2554     0    stevel 		return (NULL);
   2555     0    stevel 	}
   2556     0    stevel 	return ((pool_elem_t *)prs);
   2557     0    stevel }
   2558     0    stevel 
   2559     0    stevel pool_elem_t *
   2560     0    stevel pool_component_to_elem(const pool_conf_t *conf, const pool_component_t *pr)
   2561     0    stevel {
   2562     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2563     0    stevel 		pool_seterror(POE_BADPARAM);
   2564     0    stevel 		return (NULL);
   2565     0    stevel 	}
   2566     0    stevel 	return ((pool_elem_t *)pr);
   2567     0    stevel }
   2568     0    stevel 
   2569     0    stevel /*
   2570     0    stevel  * Walk all the pools of the configuration calling the user supplied function
   2571     0    stevel  * as long as the user function continues to return PO_TRUE
   2572     0    stevel  */
   2573     0    stevel int
   2574     0    stevel pool_walk_pools(pool_conf_t *conf, void *arg,
   2575     0    stevel     int (*callback)(pool_conf_t *conf, pool_t *pool, void *arg))
   2576     0    stevel {
   2577     0    stevel 	pool_t **rs;
   2578     0    stevel 	int i;
   2579     0    stevel 	uint_t size;
   2580     0    stevel 	int error = PO_SUCCESS;
   2581     0    stevel 
   2582     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2583     0    stevel 		pool_seterror(POE_BADPARAM);
   2584     0    stevel 		return (PO_FAIL);
   2585     0    stevel 	}
   2586     0    stevel 
   2587     0    stevel 	if ((rs = pool_query_pools(conf, &size, NULL)) == NULL) /* None */
   2588     0    stevel 		return (PO_SUCCESS);
   2589     0    stevel 	for (i = 0; i < size; i++)
   2590     0    stevel 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
   2591     0    stevel 			error = PO_FAIL;
   2592     0    stevel 			break;
   2593     0    stevel 		}
   2594     0    stevel 	free(rs);
   2595     0    stevel 	return (error);
   2596     0    stevel }
   2597     0    stevel 
   2598     0    stevel /*
   2599     0    stevel  * Walk all the comp of the res calling the user supplied function
   2600     0    stevel  * as long as the user function continues to return PO_TRUE
   2601     0    stevel  */
   2602     0    stevel int
   2603     0    stevel pool_walk_components(pool_conf_t *conf, pool_resource_t *prs, void *arg,
   2604     0    stevel     int (*callback)(pool_conf_t *conf, pool_component_t *pr, void *arg))
   2605     0    stevel {
   2606     0    stevel 	pool_component_t **rs;
   2607     0    stevel 	int i;
   2608     0    stevel 	uint_t size;
   2609     0    stevel 	int error = PO_SUCCESS;
   2610     0    stevel 
   2611     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2612     0    stevel 		pool_seterror(POE_BADPARAM);
   2613     0    stevel 		return (PO_FAIL);
   2614     0    stevel 	}
   2615     0    stevel 
   2616     0    stevel 	if ((rs = pool_query_resource_components(conf, prs, &size, NULL)) ==
   2617     0    stevel 	    NULL)
   2618     0    stevel 		return (PO_SUCCESS); /* None */
   2619     0    stevel 	for (i = 0; i < size; i++)
   2620     0    stevel 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
   2621     0    stevel 			error = PO_FAIL;
   2622     0    stevel 			break;
   2623     0    stevel 		}
   2624     0    stevel 	free(rs);
   2625     0    stevel 	return (error);
   2626     0    stevel }
   2627     0    stevel 
   2628     0    stevel /*
   2629     0    stevel  * Return an array of all matching res for the supplied pool.
   2630     0    stevel  */
   2631     0    stevel pool_resource_t **
   2632     0    stevel pool_query_pool_resources(const pool_conf_t *conf, const pool_t *pp,
   2633     0    stevel     uint_t *size, pool_value_t **props)
   2634     0    stevel {
   2635     0    stevel 	pool_result_set_t *rs;
   2636     0    stevel 	pool_elem_t *pe;
   2637     0    stevel 	pool_resource_t **result = NULL;
   2638     0    stevel 	int i = 0;
   2639     0    stevel 
   2640     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2641     0    stevel 		pool_seterror(POE_BADPARAM);
   2642     0    stevel 		return (NULL);
   2643     0    stevel 	}
   2644     0    stevel 
   2645     0    stevel 	pe = TO_ELEM(pp);
   2646     0    stevel 
   2647     0    stevel 	rs = pool_exec_query(conf, pe, "res", PEC_QRY_RES, props);
   2648     0    stevel 	if (rs == NULL) {
   2649     0    stevel 		return (NULL);
   2650     0    stevel 	}
   2651     0    stevel 	if ((*size = pool_rs_count(rs)) == 0) {
   2652     0    stevel 		(void) pool_rs_close(rs);
   2653     0    stevel 		return (NULL);
   2654     0    stevel 	}
   2655     0    stevel 	if ((result = malloc(sizeof (pool_resource_t *) * (*size + 1)))
   2656     0    stevel 	    == NULL) {
   2657     0    stevel 		pool_seterror(POE_SYSTEM);
   2658     0    stevel 		(void) pool_rs_close(rs);
   2659     0    stevel 		return (NULL);
   2660     0    stevel 	}
   2661     0    stevel 	(void) memset(result, 0, sizeof (pool_resource_t *) * (*size + 1));
   2662     0    stevel 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
   2663     0    stevel 		if (pool_elem_class(pe) != PEC_RES_COMP &&
   2664     0    stevel 		    pool_elem_class(pe) != PEC_RES_AGG) {
   2665     0    stevel 			pool_seterror(POE_INVALID_CONF);
   2666     0    stevel 			free(result);
   2667     0    stevel 			(void) pool_rs_close(rs);
   2668     0    stevel 			return (NULL);
   2669     0    stevel 		}
   2670     0    stevel 		result[i++] = pool_elem_res(pe);
   2671     0    stevel 	}
   2672     0    stevel 	(void) pool_rs_close(rs);
   2673     0    stevel 	return (result);
   2674     0    stevel }
   2675     0    stevel 
   2676     0    stevel /*
   2677     0    stevel  * Walk all the res of the pool calling the user supplied function
   2678     0    stevel  * as long as the user function continues to return PO_TRUE
   2679     0    stevel  */
   2680     0    stevel int
   2681     0    stevel pool_walk_resources(pool_conf_t *conf, pool_t *pp, void *arg,
   2682     0    stevel     int (*callback)(pool_conf_t *, pool_resource_t *, void *))
   2683     0    stevel {
   2684     0    stevel 	pool_resource_t **rs;
   2685     0    stevel 	int i;
   2686     0    stevel 	uint_t size;
   2687     0    stevel 	int error = PO_SUCCESS;
   2688     0    stevel 
   2689     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2690     0    stevel 		pool_seterror(POE_BADPARAM);
   2691     0    stevel 		return (PO_FAIL);
   2692     0    stevel 	}
   2693     0    stevel 	if ((rs = pool_query_pool_resources(conf, pp, &size, NULL)) == NULL)
   2694     0    stevel 		return (PO_SUCCESS); /* None */
   2695     0    stevel 	for (i = 0; i < size; i++)
   2696     0    stevel 		if (callback(conf, rs[i], arg) != PO_SUCCESS) {
   2697     0    stevel 			error = PO_FAIL;
   2698     0    stevel 			break;
   2699     0    stevel 		}
   2700     0    stevel 	free(rs);
   2701     0    stevel 	return (error);
   2702     0    stevel }
   2703     0    stevel 
   2704     0    stevel /*
   2705     0    stevel  * Return a result set of all comp for the supplied res.
   2706     0    stevel  */
   2707     0    stevel pool_component_t **
   2708     0    stevel pool_query_resource_components(const pool_conf_t *conf,
   2709     0    stevel     const pool_resource_t *prs, uint_t *size, pool_value_t **props)
   2710     0    stevel {
   2711     0    stevel 	pool_result_set_t *rs;
   2712     0    stevel 	pool_elem_t *pe;
   2713     0    stevel 	pool_component_t **result = NULL;
   2714     0    stevel 	int i = 0;
   2715     0    stevel 
   2716     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2717     0    stevel 		pool_seterror(POE_BADPARAM);
   2718     0    stevel 		return (NULL);
   2719     0    stevel 	}
   2720     0    stevel 	pe = TO_ELEM(prs);
   2721     0    stevel 
   2722     0    stevel 	rs = pool_exec_query(conf, pe, NULL, PEC_QRY_COMP, props);
   2723     0    stevel 	if (rs == NULL) {
   2724     0    stevel 		return (NULL);
   2725     0    stevel 	}
   2726     0    stevel 	if ((*size = pool_rs_count(rs)) == 0) {
   2727     0    stevel 		(void) pool_rs_close(rs);
   2728     0    stevel 		return (NULL);
   2729     0    stevel 	}
   2730     0    stevel 	if ((result = malloc(sizeof (pool_component_t *) * (*size + 1)))
   2731     0    stevel 	    == NULL) {
   2732     0    stevel 		pool_seterror(POE_SYSTEM);
   2733     0    stevel 		(void) pool_rs_close(rs);
   2734     0    stevel 		return (NULL);
   2735     0    stevel 	}
   2736     0    stevel 	(void) memset(result, 0, sizeof (pool_component_t *) * (*size + 1));
   2737     0    stevel 	for (pe = rs->prs_next(rs); pe != NULL; pe = rs->prs_next(rs)) {
   2738     0    stevel 		if (pool_elem_class(pe) != PEC_COMP) {
   2739     0    stevel 			pool_seterror(POE_INVALID_CONF);
   2740     0    stevel 			free(result);
   2741     0    stevel 			(void) pool_rs_close(rs);
   2742     0    stevel 			return (NULL);
   2743     0    stevel 		}
   2744     0    stevel 		result[i++] = pool_elem_comp(pe);
   2745     0    stevel 	}
   2746     0    stevel 	(void) pool_rs_close(rs);
   2747     0    stevel 	return (result);
   2748     0    stevel }
   2749     0    stevel 
   2750     0    stevel /*
   2751     0    stevel  * pool_version() returns the version of this library, depending on the supplied
   2752     0    stevel  * parameter.
   2753     0    stevel  *
   2754     0    stevel  * Returns: library version depening on the supplied ver parameter.
   2755     0    stevel  */
   2756     0    stevel uint_t
   2757     0    stevel pool_version(uint_t ver)
   2758     0    stevel {
   2759     0    stevel 	switch (ver) {
   2760     0    stevel 	case POOL_VER_NONE:
   2761     0    stevel 		break;
   2762     0    stevel 	case POOL_VER_CURRENT:
   2763     0    stevel 		pool_workver = ver;
   2764     0    stevel 		break;
   2765     0    stevel 	default:
   2766     0    stevel 		return (POOL_VER_NONE);
   2767     0    stevel 	}
   2768     0    stevel 	return (pool_workver);
   2769     0    stevel }
   2770     0    stevel 
   2771     0    stevel /*
   2772     0    stevel  * pool_associate() associates the supplied resource to the supplied pool.
   2773     0    stevel  *
   2774     0    stevel  * Returns: PO_SUCCESS/PO_FAIL
   2775     0    stevel  */
   2776     0    stevel int
   2777     0    stevel pool_associate(pool_conf_t *conf, pool_t *pool, const pool_resource_t *res)
   2778     0    stevel {
   2779     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
   2780     0    stevel 		return (PO_FAIL);
   2781     0    stevel 
   2782     0    stevel 	return (pool->pp_associate(pool, res));
   2783     0    stevel }
   2784     0    stevel 
   2785     0    stevel /*
   2786     0    stevel  * pool_dissociate() dissociates the supplied resource from the supplied pool.
   2787     0    stevel  *
   2788     0    stevel  * Returns: PO_SUCCESS/PO_FAIL
   2789     0    stevel  */
   2790     0    stevel int
   2791     0    stevel pool_dissociate(pool_conf_t *conf, pool_t *pool, const pool_resource_t *res)
   2792     0    stevel {
   2793     0    stevel 	if (pool_conf_check(conf) != PO_SUCCESS)
   2794     0    stevel 		return (PO_FAIL);
   2795     0    stevel 
   2796     0    stevel 	if (elem_is_default(TO_ELEM(res)))
   2797     0    stevel 		return (PO_SUCCESS);
   2798     0    stevel 	return (pool->pp_dissociate(pool, res));
   2799     0    stevel }
   2800     0    stevel 
   2801     0    stevel /*
   2802     0    stevel  * Compare two elements for purposes of ordering.
   2803     0    stevel  * Return:
   2804     0    stevel  *	< 0 if e1 is "before" e2
   2805     0    stevel  *	0 if e1 "equals" e2
   2806     0    stevel  *	> 0 if e1 comes after e2
   2807     0    stevel  */
   2808     0    stevel int
   2809     0    stevel pool_elem_compare_name(const pool_elem_t *e1, const pool_elem_t *e2)
   2810     0    stevel {
   2811     0    stevel 	char *name1, *name2;
   2812     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   2813     0    stevel 	int retval;
   2814     0    stevel 
   2815     0    stevel 	/*
   2816     0    stevel 	 * We may be asked to compare two elements from different classes.
   2817     0    stevel 	 * They are different so return (1).
   2818     0    stevel 	 */
   2819     0    stevel 	if (pool_elem_same_class(e1, e2) != PO_TRUE)
   2820     0    stevel 		return (1);
   2821     0    stevel 
   2822     0    stevel 	/*
   2823     0    stevel 	 * If the class is PEC_SYSTEM, always match them
   2824     0    stevel 	 */
   2825     0    stevel 	if (pool_elem_class(e1) == PEC_SYSTEM)
   2826     0    stevel 		return (0);
   2827     0    stevel 
   2828     0    stevel 	/*
   2829     0    stevel 	 * If we are going to compare components, then use sys_id
   2830     0    stevel 	 */
   2831     0    stevel 	if (pool_elem_class(e1) == PEC_COMP) {
   2832     0    stevel 		int64_t sys_id1, sys_id2;
   2833     0    stevel 
   2834     0    stevel 		if (pool_get_ns_property(e1, c_sys_prop, &val) == POC_INVAL) {
   2835     0    stevel 			return (-1);
   2836     0    stevel 		}
   2837     0    stevel 		(void) pool_value_get_int64(&val, &sys_id1);
   2838     0    stevel 		if (pool_get_ns_property(e2, c_sys_prop, &val) == POC_INVAL) {
   2839     0    stevel 			return (-1);
   2840     0    stevel 		}
   2841     0    stevel 		(void) pool_value_get_int64(&val, &sys_id2);
   2842     0    stevel 		retval = (sys_id1 - sys_id2);
   2843     0    stevel 	} else {
   2844     0    stevel 		if (pool_get_ns_property(e1, "name", &val) == POC_INVAL) {
   2845     0    stevel 			return (-1);
   2846     0    stevel 		}
   2847     0    stevel 		(void) pool_value_get_string(&val, (const char **)&name1);
   2848     0    stevel 		if ((name1 = strdup(name1)) == NULL) {
   2849     0    stevel 			return (-1);
   2850     0    stevel 		}
   2851     0    stevel 
   2852     0    stevel 		if (pool_get_ns_property(e2, "name", &val) == POC_INVAL) {
   2853     0    stevel 			return (-1);
   2854     0    stevel 		}
   2855     0    stevel 
   2856     0    stevel 		(void) pool_value_get_string(&val, (const char **)&name2);
   2857     0    stevel 		retval = strcmp(name1, name2);
   2858     0    stevel 		free(name1);
   2859     0    stevel 	}
   2860     0    stevel 	return (retval);
   2861     0    stevel }
   2862     0    stevel 
   2863     0    stevel /*
   2864     0    stevel  * Compare two elements for purposes of ordering.
   2865     0    stevel  * Return:
   2866     0    stevel  *	< 0 if e1 is "before" e2
   2867     0    stevel  *	0 if e1 "equals" e2
   2868     0    stevel  *	> 0 if e1 comes after e2
   2869     0    stevel  */
   2870     0    stevel int
   2871     0    stevel pool_elem_compare(const pool_elem_t *e1, const pool_elem_t *e2)
   2872     0    stevel {
   2873     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   2874     0    stevel 	int64_t sys_id1, sys_id2;
   2875     0    stevel 
   2876     0    stevel 	/*
   2877     0    stevel 	 * We may be asked to compare two elements from different classes.
   2878     0    stevel 	 * They are different so return the difference in their classes
   2879     0    stevel 	 */
   2880     0    stevel 	if (pool_elem_same_class(e1, e2) != PO_TRUE)
   2881     0    stevel 		return (1);
   2882     0    stevel 
   2883     0    stevel 	/*
   2884     0    stevel 	 * If the class is PEC_SYSTEM, always match them
   2885     0    stevel 	 */
   2886     0    stevel 	if (pool_elem_class(e1) == PEC_SYSTEM)
   2887     0    stevel 		return (0);
   2888     0    stevel 
   2889     0    stevel 	/*
   2890     0    stevel 	 * Compare with sys_id
   2891     0    stevel 	 */
   2892     0    stevel 	if (pool_get_ns_property(e1, c_sys_prop, &val) == POC_INVAL) {
   2893     0    stevel 		assert(!"no sys_id on e1\n");
   2894     0    stevel 	}
   2895     0    stevel 	(void) pool_value_get_int64(&val, &sys_id1);
   2896     0    stevel 	if (pool_get_ns_property(e2, c_sys_prop, &val) == POC_INVAL) {
   2897     0    stevel 		assert(!"no sys_id on e2\n");
   2898     0    stevel 	}
   2899     0    stevel 	(void) pool_value_get_int64(&val, &sys_id2);
   2900     0    stevel 	return (sys_id1 - sys_id2);
   2901     0    stevel }
   2902     0    stevel 
   2903     0    stevel /*
   2904     0    stevel  * Return PO_TRUE if the supplied elems are of the same class.
   2905     0    stevel  */
   2906     0    stevel int
   2907     0    stevel pool_elem_same_class(const pool_elem_t *e1, const pool_elem_t *e2)
   2908     0    stevel {
   2909     0    stevel 	if (pool_elem_class(e1) != pool_elem_class(e2))
   2910     0    stevel 		return (PO_FALSE);
   2911     0    stevel 
   2912     0    stevel 	/*
   2913     0    stevel 	 * Check to make sure the fundamental class of the elements match
   2914     0    stevel 	 */
   2915     0    stevel 	if (pool_elem_class(e1) == PEC_RES_COMP ||
   2916     0    stevel 	    pool_elem_class(e1) == PEC_RES_AGG)
   2917     0    stevel 		if (pool_resource_elem_class(e1) !=
   2918     0    stevel 		    pool_resource_elem_class(e2))
   2919     0    stevel 			return (PO_FALSE);
   2920     0    stevel 	if (pool_elem_class(e1) == PEC_COMP)
   2921     0    stevel 		if (pool_component_elem_class(e1) !=
   2922     0    stevel 		    pool_component_elem_class(e2))
   2923     0    stevel 			return (PO_FALSE);
   2924     0    stevel 	return (PO_TRUE);
   2925     0    stevel }
   2926     0    stevel 
   2927     0    stevel /*
   2928     0    stevel  * pool_conf_check() checks that the configuration state isn't invalid
   2929     0    stevel  * and that the configuration was opened for modification.
   2930     0    stevel  */
   2931     0    stevel int
   2932     0    stevel pool_conf_check(const pool_conf_t *conf)
   2933     0    stevel {
   2934     0    stevel 	if (pool_conf_status(conf) == POF_INVALID) {
   2935     0    stevel 		pool_seterror(POE_BADPARAM);
   2936     0    stevel 		return (PO_FAIL);
   2937     0    stevel 	}
   2938     0    stevel 
   2939     0    stevel 	if ((conf->pc_prov->pc_oflags & PO_RDWR) == 0) {
   2940     0    stevel 		pool_seterror(POE_BADPARAM);
   2941     0    stevel 		return (PO_FAIL);
   2942     0    stevel 	}
   2943     0    stevel 	return (PO_SUCCESS);
   2944     0    stevel }
   2945