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