17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5f9e2a31fSsdussud  * Common Development and Distribution License (the "License").
6f9e2a31fSsdussud  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22f9e2a31fSsdussud  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * These functions implement the process of commitment for a pool
287c478bd9Sstevel@tonic-gate  * configuration. This process can be described as taking instructions
297c478bd9Sstevel@tonic-gate  * from a static configuration file and using the information about
307c478bd9Sstevel@tonic-gate  * the target system contained in the dynamic configuration to make
317c478bd9Sstevel@tonic-gate  * decisions about how best to allocate resources to meet the
327c478bd9Sstevel@tonic-gate  * constraints specified in the static configuration file.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * Mechanically, this process relies upon ordering the individual
357c478bd9Sstevel@tonic-gate  * components of the file and stepping through the lists of components
367c478bd9Sstevel@tonic-gate  * and taking actions depending on their type and which file they are
377c478bd9Sstevel@tonic-gate  * part of.
387c478bd9Sstevel@tonic-gate  *
397c478bd9Sstevel@tonic-gate  * Configuration components can be broken down into different types
407c478bd9Sstevel@tonic-gate  * which are then treated according to the following table:
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * Element Type		Action
437c478bd9Sstevel@tonic-gate  * system || pool ||
447c478bd9Sstevel@tonic-gate  * res_comp || res_agg	If the element is a required element, then create or
457c478bd9Sstevel@tonic-gate  *			update it (don't destroy required elements in the
467c478bd9Sstevel@tonic-gate  *			static configuration) otherwise manipulate the
477c478bd9Sstevel@tonic-gate  *			dynamic configuration to create, destroy or update
487c478bd9Sstevel@tonic-gate  *			the element on the system.
497c478bd9Sstevel@tonic-gate  * comp			Create, destroy or update the static configuration
507c478bd9Sstevel@tonic-gate  *			component.
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  * The treatment of the different elements reflects the fact that all
537c478bd9Sstevel@tonic-gate  * elements other than comp are configurable and thus libpool can
547c478bd9Sstevel@tonic-gate  * create, destroy and modify these elements at will. comp elements
557c478bd9Sstevel@tonic-gate  * reflect the disposition of the system, these elements can be moved
567c478bd9Sstevel@tonic-gate  * around but they can't be created or destroyed in the dynamic
577c478bd9Sstevel@tonic-gate  * configuration in the commit process. comp elements can be created
587c478bd9Sstevel@tonic-gate  * and destroyed in the static configuration file as a result of a
597c478bd9Sstevel@tonic-gate  * commit operation, since it's possible for a comp to not appear in
607c478bd9Sstevel@tonic-gate  * the dynamic configuration. For instance, if the static
617c478bd9Sstevel@tonic-gate  * configuration file was created on a different machine or after a DR
627c478bd9Sstevel@tonic-gate  * operation which has removed or added components.
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  */
657c478bd9Sstevel@tonic-gate #include <assert.h>
667c478bd9Sstevel@tonic-gate #include <stdio.h>
677c478bd9Sstevel@tonic-gate #include <stdlib.h>
687c478bd9Sstevel@tonic-gate #include <sys/types.h>
697c478bd9Sstevel@tonic-gate #include <errno.h>
707c478bd9Sstevel@tonic-gate #include <string.h>
717c478bd9Sstevel@tonic-gate #include <limits.h>
727c478bd9Sstevel@tonic-gate #include <unistd.h>
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate #include <pool.h>
757c478bd9Sstevel@tonic-gate #include "pool_internal.h"
767c478bd9Sstevel@tonic-gate #include "pool_impl.h"
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #define	MIN(x, y) ((x) < (y) ? (x) : (y))
797c478bd9Sstevel@tonic-gate #define	MAX(x, y) ((x) > (y) ? (x) : (y))
807c478bd9Sstevel@tonic-gate #define	POA_IMPORTANCE_NUM	0
817c478bd9Sstevel@tonic-gate #define	POA_SURPLUS_TO_DEFAULT_NUM	1
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate  * This resource specific structure is used to determine allocation of resources
857c478bd9Sstevel@tonic-gate  * during resource set allocation.  Each set will receive its min, plus
867c478bd9Sstevel@tonic-gate  * some number of dealt resources based on the global allocation policy.
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate typedef struct res_info {
897c478bd9Sstevel@tonic-gate 	pool_resource_t	*ri_res;	/* Resource set */
907c478bd9Sstevel@tonic-gate 	uint64_t	ri_min;		/* Resource set's low watermark */
917c478bd9Sstevel@tonic-gate 	uint64_t	ri_max;		/* Resource set's high watermark */
927c478bd9Sstevel@tonic-gate 	uint64_t	ri_oldsize;	/* Size of resource set at the start */
937c478bd9Sstevel@tonic-gate 	uint64_t	ri_newsize;	/* New resource set size allocated */
947c478bd9Sstevel@tonic-gate 	uint64_t	ri_pinned;	/* Count of pinned resources in set */
957c478bd9Sstevel@tonic-gate 	uint64_t	ri_dealt;	/* Count of resources dealt to set */
967c478bd9Sstevel@tonic-gate 	int64_t		ri_transfer;	/* oldsize - newsize */
977c478bd9Sstevel@tonic-gate 					/* The signed quantity of resources */
987c478bd9Sstevel@tonic-gate 					/* to tranfer into or out of this */
997c478bd9Sstevel@tonic-gate 					/* resource set */
1007c478bd9Sstevel@tonic-gate 					/* + transfer: tranfer resources out */
1017c478bd9Sstevel@tonic-gate 					/* - transfer: tranfer resources in */
1027c478bd9Sstevel@tonic-gate } res_info_t;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate /*
1057c478bd9Sstevel@tonic-gate  * diff_and_fix operations
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate static int		commit_create(pool_conf_t *, pool_elem_t **);
1087c478bd9Sstevel@tonic-gate static int		commit_delete(pool_elem_t *);
1097c478bd9Sstevel@tonic-gate static int		commit_update(pool_elem_t *, pool_elem_t *, int);
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate /*
1127c478bd9Sstevel@tonic-gate  * configuration commit processing
1137c478bd9Sstevel@tonic-gate  */
1147c478bd9Sstevel@tonic-gate static int		diff_and_fix(pool_conf_t *, pool_conf_t *);
1157c478bd9Sstevel@tonic-gate static int		process_elem_lt(pool_elem_t *, pool_conf_t *);
1167c478bd9Sstevel@tonic-gate static int		process_elem_gt(pool_elem_t *, pool_conf_t *,
1177c478bd9Sstevel@tonic-gate     pool_conf_t *);
1187c478bd9Sstevel@tonic-gate static int		process_lists(int, pool_conf_t *,
1197c478bd9Sstevel@tonic-gate     pool_conf_t *, int);
1207c478bd9Sstevel@tonic-gate static pool_elem_t	**get_elem_list(const pool_conf_t *, int, uint_t *);
1217c478bd9Sstevel@tonic-gate static int		share_resources(pool_conf_t *);
1227c478bd9Sstevel@tonic-gate static int		resource_allocate(const char *, pool_resource_t **,
1237c478bd9Sstevel@tonic-gate     uint_t);
1247c478bd9Sstevel@tonic-gate static int		resource_allocate_default(pool_resource_t **, uint_t);
1257c478bd9Sstevel@tonic-gate static int		pset_allocate_imp(pool_resource_t **, uint_t);
1267c478bd9Sstevel@tonic-gate static int		resource_compare_by_descending_importance(const void *,
1277c478bd9Sstevel@tonic-gate     const void *);
1287c478bd9Sstevel@tonic-gate static int		compute_size_to_transfer(const void *, const void *);
1297c478bd9Sstevel@tonic-gate static int		set_importance_cb(pool_conf_t *, pool_t *, void *);
1307c478bd9Sstevel@tonic-gate static int		unset_importance_cb(pool_conf_t *, pool_t *, void *);
1317c478bd9Sstevel@tonic-gate static int		add_importance_props(pool_conf_t *);
1327c478bd9Sstevel@tonic-gate static int		remove_importance_props(pool_conf_t *);
1337c478bd9Sstevel@tonic-gate static int		clone_element(pool_conf_t *, pool_elem_t *,
1347c478bd9Sstevel@tonic-gate     const char *, pool_value_t *, void *);
1357c478bd9Sstevel@tonic-gate static int		clean_element(pool_conf_t *, pool_elem_t *,
1367c478bd9Sstevel@tonic-gate     const char *, pool_value_t *, void *);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate  * commit_create() is used to create a configuration element upon the
1407c478bd9Sstevel@tonic-gate  * system.  Since only pools and resource actually need to perform any
1417c478bd9Sstevel@tonic-gate  * action, other elements are ignored as a no-op.
1427c478bd9Sstevel@tonic-gate  */
1437c478bd9Sstevel@tonic-gate static int
commit_create(pool_conf_t * conf,pool_elem_t ** e1)1447c478bd9Sstevel@tonic-gate commit_create(pool_conf_t *conf, pool_elem_t **e1)
1457c478bd9Sstevel@tonic-gate {
1467c478bd9Sstevel@tonic-gate 	pool_resource_t *res;
1477c478bd9Sstevel@tonic-gate 	pool_t *pool;
1487c478bd9Sstevel@tonic-gate 	const char *res_type;
1497c478bd9Sstevel@tonic-gate 	pool_elem_t *src = *e1;
1507c478bd9Sstevel@tonic-gate 	uint64_t smin, smax, dmax;
1517c478bd9Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
1527c478bd9Sstevel@tonic-gate 	char *name;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	switch (pool_elem_class(src)) {
1557c478bd9Sstevel@tonic-gate 	case PEC_SYSTEM:	/* NO-OP */
1567c478bd9Sstevel@tonic-gate 		break;
1577c478bd9Sstevel@tonic-gate 	case PEC_POOL:
1587c478bd9Sstevel@tonic-gate 		name = elem_get_name(src);
1597c478bd9Sstevel@tonic-gate 		if ((pool = pool_create(conf, name)) == NULL) {
1607c478bd9Sstevel@tonic-gate 			free(name);
1617c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
1627c478bd9Sstevel@tonic-gate 		}
1637c478bd9Sstevel@tonic-gate 		free(name);
1647c478bd9Sstevel@tonic-gate 		/*
1657c478bd9Sstevel@tonic-gate 		 * Now copy the properties from the original pool to the
1667c478bd9Sstevel@tonic-gate 		 * new one
1677c478bd9Sstevel@tonic-gate 		 */
1687c478bd9Sstevel@tonic-gate 		if (pool_walk_properties(TO_CONF(src), src, TO_ELEM(pool),
1697c478bd9Sstevel@tonic-gate 		    clone_element) != PO_SUCCESS)
1707c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
1717c478bd9Sstevel@tonic-gate 		/*
1727c478bd9Sstevel@tonic-gate 		 * Add a pointer to the src element which can be
1737c478bd9Sstevel@tonic-gate 		 * updated with a sys_id when the sys_id is allocated
1747c478bd9Sstevel@tonic-gate 		 * to the created element.
1757c478bd9Sstevel@tonic-gate 		 */
1767c478bd9Sstevel@tonic-gate 		pool_set_pair(TO_ELEM(pool), src);
1777c478bd9Sstevel@tonic-gate 		*e1 = TO_ELEM(pool);
1787c478bd9Sstevel@tonic-gate 		break;
1797c478bd9Sstevel@tonic-gate 	case PEC_RES_COMP:
1807c478bd9Sstevel@tonic-gate 	case PEC_RES_AGG:
1817c478bd9Sstevel@tonic-gate 		name = elem_get_name(src);
1827c478bd9Sstevel@tonic-gate 		res_type = pool_elem_class_string(src);
1837c478bd9Sstevel@tonic-gate 		if ((res = pool_resource_create(conf, res_type, name)) ==
1847c478bd9Sstevel@tonic-gate 		    NULL) {
1857c478bd9Sstevel@tonic-gate 			free(name);
1867c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
1877c478bd9Sstevel@tonic-gate 		}
1887c478bd9Sstevel@tonic-gate 		free(name);
1897c478bd9Sstevel@tonic-gate 		/*
1907c478bd9Sstevel@tonic-gate 		 * Need to do some ordering of property updates.
1917c478bd9Sstevel@tonic-gate 		 * Compare the values of source min/max and
1927c478bd9Sstevel@tonic-gate 		 * destination min/max. If smin < dmax then update the
1937c478bd9Sstevel@tonic-gate 		 * smin first, else update the max first.
1947c478bd9Sstevel@tonic-gate 		 */
1957c478bd9Sstevel@tonic-gate 		if (resource_get_min(pool_elem_res(src), &smin) != PO_SUCCESS ||
1967c478bd9Sstevel@tonic-gate 		    resource_get_max(pool_elem_res(src), &smax) != PO_SUCCESS ||
1977c478bd9Sstevel@tonic-gate 		    resource_get_max(res, &dmax) != PO_SUCCESS)
1987c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
1997c478bd9Sstevel@tonic-gate 		if (smin < dmax) {
2007c478bd9Sstevel@tonic-gate 			pool_value_set_uint64(&val, smin);
2017c478bd9Sstevel@tonic-gate 			if (pool_put_ns_property(TO_ELEM(res), c_min_prop,
2027c478bd9Sstevel@tonic-gate 			    &val) != PO_SUCCESS)
2037c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
2047c478bd9Sstevel@tonic-gate 		} else {
2057c478bd9Sstevel@tonic-gate 			pool_value_set_uint64(&val, smax);
2067c478bd9Sstevel@tonic-gate 			if (pool_put_ns_property(TO_ELEM(res), c_max_prop,
2077c478bd9Sstevel@tonic-gate 			    &val) != PO_SUCCESS)
2087c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
2097c478bd9Sstevel@tonic-gate 		}
2107c478bd9Sstevel@tonic-gate 		/*
2117c478bd9Sstevel@tonic-gate 		 * Now copy the properties from the original resource
2127c478bd9Sstevel@tonic-gate 		 * to the new one
2137c478bd9Sstevel@tonic-gate 		 */
2147c478bd9Sstevel@tonic-gate 		if (pool_walk_properties(TO_CONF(src), src, TO_ELEM(res),
2157c478bd9Sstevel@tonic-gate 		    clone_element) != PO_SUCCESS)
2167c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
2177c478bd9Sstevel@tonic-gate 		/*
2187c478bd9Sstevel@tonic-gate 		 * Add a pointer to the src element which can be
2197c478bd9Sstevel@tonic-gate 		 * updated with a sys_id when the sys_id is allocated
2207c478bd9Sstevel@tonic-gate 		 * to the created element.
2217c478bd9Sstevel@tonic-gate 		 */
2227c478bd9Sstevel@tonic-gate 		pool_set_pair(TO_ELEM(res), src);
2237c478bd9Sstevel@tonic-gate 		*e1 = TO_ELEM(res);
2247c478bd9Sstevel@tonic-gate 		break;
2257c478bd9Sstevel@tonic-gate 	case PEC_COMP:		/* NO-OP */
2267c478bd9Sstevel@tonic-gate 		break;
2277c478bd9Sstevel@tonic-gate 	default:
2287c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate  * commit_delete() is used to delete a configuration element upon the
2367c478bd9Sstevel@tonic-gate  * system.  Since only pools and resources actually need to perform
2377c478bd9Sstevel@tonic-gate  * any action, other elements are ignored as a no-op.
2387c478bd9Sstevel@tonic-gate  */
2397c478bd9Sstevel@tonic-gate static int
commit_delete(pool_elem_t * pe)2407c478bd9Sstevel@tonic-gate commit_delete(pool_elem_t *pe)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 	pool_resource_t *res;
2437c478bd9Sstevel@tonic-gate 	pool_t *pool;
2447c478bd9Sstevel@tonic-gate 	int ret = 0;
2457c478bd9Sstevel@tonic-gate 
246*0209230bSgjelinek 	if (elem_is_tmp(pe))
247*0209230bSgjelinek 		return (PO_SUCCESS);
248*0209230bSgjelinek 
2497c478bd9Sstevel@tonic-gate 	switch (pool_elem_class(pe)) {
2507c478bd9Sstevel@tonic-gate 	case PEC_SYSTEM:	/* NO-OP */
2517c478bd9Sstevel@tonic-gate 		break;
2527c478bd9Sstevel@tonic-gate 	case PEC_POOL:
2537c478bd9Sstevel@tonic-gate 		pool = pool_elem_pool(pe);
2547c478bd9Sstevel@tonic-gate 		ret = pool_destroy(TO_CONF(pe), pool);
2557c478bd9Sstevel@tonic-gate 		break;
2567c478bd9Sstevel@tonic-gate 	case PEC_RES_COMP:
2577c478bd9Sstevel@tonic-gate 	case PEC_RES_AGG:
2587c478bd9Sstevel@tonic-gate 		res = pool_elem_res(pe);
2597c478bd9Sstevel@tonic-gate 		ret = pool_resource_destroy(TO_CONF(pe), res);
2607c478bd9Sstevel@tonic-gate 		break;
2617c478bd9Sstevel@tonic-gate 	case PEC_COMP:		/* NO-OP */
2627c478bd9Sstevel@tonic-gate 		break;
2637c478bd9Sstevel@tonic-gate 	default:
2647c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
2657c478bd9Sstevel@tonic-gate 	}
2667c478bd9Sstevel@tonic-gate 	return (ret);
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate /*
2707c478bd9Sstevel@tonic-gate  * commit_update() is used to update a configuration element upon the
2717c478bd9Sstevel@tonic-gate  * system or in a static configuration file. The pass parameter
2727c478bd9Sstevel@tonic-gate  * governs whether properties are being updated or associations.  In
2737c478bd9Sstevel@tonic-gate  * pass 0, properties are updated. If the element is of class
2747c478bd9Sstevel@tonic-gate  * PEC_COMP, then make sure that the element in the static
2757c478bd9Sstevel@tonic-gate  * configuration file is correctly located before proceeding with the
2767c478bd9Sstevel@tonic-gate  * update. Then, the element in the dynamic configuration file is
2777c478bd9Sstevel@tonic-gate  * updated. In pass 1, ie. pass != 0, any pool components have their
2787c478bd9Sstevel@tonic-gate  * associations updated in the dynamic configuration.
2797c478bd9Sstevel@tonic-gate  */
2807c478bd9Sstevel@tonic-gate static int
commit_update(pool_elem_t * e1,pool_elem_t * e2,int pass)2817c478bd9Sstevel@tonic-gate commit_update(pool_elem_t *e1, pool_elem_t *e2, int pass)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate 	if (pass == 0) {
2847c478bd9Sstevel@tonic-gate 		pool_resource_t *res1;
2857c478bd9Sstevel@tonic-gate 		pool_resource_t *res2;
2867c478bd9Sstevel@tonic-gate 		if (pool_elem_class(e1) == PEC_COMP) {
2877c478bd9Sstevel@tonic-gate 			res1 = pool_get_owning_resource(TO_CONF(e1),
2887c478bd9Sstevel@tonic-gate 			    pool_elem_comp(e1));
2897c478bd9Sstevel@tonic-gate 			res2 = pool_get_owning_resource(TO_CONF(e2),
2907c478bd9Sstevel@tonic-gate 			    pool_elem_comp(e2));
2917c478bd9Sstevel@tonic-gate 			if (pool_elem_compare_name(TO_ELEM(res1),
2927c478bd9Sstevel@tonic-gate 			    TO_ELEM(res2)) != 0) {
2937c478bd9Sstevel@tonic-gate 				char *name;
2947c478bd9Sstevel@tonic-gate 				const pool_resource_t *newres;
2957c478bd9Sstevel@tonic-gate 				pool_component_t *comps[2] = { NULL };
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 				comps[0] = pool_elem_comp(e2);
298f9e2a31fSsdussud 				name = elem_get_name(TO_ELEM(res1));
2997c478bd9Sstevel@tonic-gate 				newres = pool_get_resource(TO_CONF(e2),
3007c478bd9Sstevel@tonic-gate 				    pool_elem_class_string(TO_ELEM(res1)),
3017c478bd9Sstevel@tonic-gate 				    name);
3027c478bd9Sstevel@tonic-gate 				free(name);
3037c478bd9Sstevel@tonic-gate 				assert(newres);
3047c478bd9Sstevel@tonic-gate #ifdef DEBUG
3057c478bd9Sstevel@tonic-gate 				dprintf("transferring: res, comp\n");
3067c478bd9Sstevel@tonic-gate 				pool_elem_dprintf(TO_ELEM(newres));
3077c478bd9Sstevel@tonic-gate 				pool_elem_dprintf(e2);
3087c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3097c478bd9Sstevel@tonic-gate 				(void) pool_resource_xtransfer(TO_CONF(e2),
3107c478bd9Sstevel@tonic-gate 				    res2, (pool_resource_t *)newres, comps);
3117c478bd9Sstevel@tonic-gate 			}
3127c478bd9Sstevel@tonic-gate 		}
3137c478bd9Sstevel@tonic-gate 		if (pool_walk_properties(TO_CONF(e2), e2, NULL,
3147c478bd9Sstevel@tonic-gate 		    clean_element) != PO_SUCCESS) {
3157c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
3167c478bd9Sstevel@tonic-gate 		}
3177c478bd9Sstevel@tonic-gate 		/*
3187c478bd9Sstevel@tonic-gate 		 * Need to do some ordering of property updates if the
3197c478bd9Sstevel@tonic-gate 		 * element to be updated is a resource.  Compare the
3207c478bd9Sstevel@tonic-gate 		 * values of source min/max and destination
3217c478bd9Sstevel@tonic-gate 		 * min/max. If smin < dmax then update the smin first,
3227c478bd9Sstevel@tonic-gate 		 * else update the max first.
3237c478bd9Sstevel@tonic-gate 		 */
3247c478bd9Sstevel@tonic-gate 		if (pool_elem_class(e1) == PEC_RES_COMP ||
3257c478bd9Sstevel@tonic-gate 		    pool_elem_class(e1) == PEC_RES_AGG) {
3267c478bd9Sstevel@tonic-gate 			uint64_t smin, smax, dmax;
3277c478bd9Sstevel@tonic-gate 			pool_value_t val = POOL_VALUE_INITIALIZER;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 			if (resource_get_min(pool_elem_res(e1), &smin) !=
3307c478bd9Sstevel@tonic-gate 			    PO_SUCCESS ||
3317c478bd9Sstevel@tonic-gate 			    resource_get_max(pool_elem_res(e1), &smax) !=
3327c478bd9Sstevel@tonic-gate 			    PO_SUCCESS ||
3337c478bd9Sstevel@tonic-gate 			    resource_get_max(pool_elem_res(e2), &dmax) !=
3347c478bd9Sstevel@tonic-gate 			    PO_SUCCESS)
3357c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
3367c478bd9Sstevel@tonic-gate 			if (smin < dmax) {
3377c478bd9Sstevel@tonic-gate 				pool_value_set_uint64(&val, smin);
3387c478bd9Sstevel@tonic-gate 				if (pool_put_ns_property(e2, c_min_prop,
3397c478bd9Sstevel@tonic-gate 				    &val) != PO_SUCCESS)
3407c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
3417c478bd9Sstevel@tonic-gate 			} else {
3427c478bd9Sstevel@tonic-gate 				pool_value_set_uint64(&val, smax);
3437c478bd9Sstevel@tonic-gate 				if (pool_put_ns_property(e2, c_max_prop,
3447c478bd9Sstevel@tonic-gate 				    &val) != PO_SUCCESS)
3457c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
3467c478bd9Sstevel@tonic-gate 			}
3477c478bd9Sstevel@tonic-gate 		}
3487c478bd9Sstevel@tonic-gate 		/*
3497c478bd9Sstevel@tonic-gate 		 * This next couple of steps needs some
3507c478bd9Sstevel@tonic-gate 		 * explanation. The first walk, copies all the
3517c478bd9Sstevel@tonic-gate 		 * properties that are writeable from the static
3527c478bd9Sstevel@tonic-gate 		 * configuration to the dynamic configuration. The
3537c478bd9Sstevel@tonic-gate 		 * second walk copies all properties (writeable or
3547c478bd9Sstevel@tonic-gate 		 * not) from the dynamic configuration element back to
3557c478bd9Sstevel@tonic-gate 		 * the static configuration element. This ensures that
3567c478bd9Sstevel@tonic-gate 		 * updates from the static configuration element are
3577c478bd9Sstevel@tonic-gate 		 * correctly applied to the dynamic configuration and
3587c478bd9Sstevel@tonic-gate 		 * then the static configuration element is updated
3597c478bd9Sstevel@tonic-gate 		 * with the latest values of the read-only xproperties
3607c478bd9Sstevel@tonic-gate 		 * from the dynamic configuration element. The
3617c478bd9Sstevel@tonic-gate 		 * enforcing of permisssions is performed in
3627c478bd9Sstevel@tonic-gate 		 * clone_element by its choice of property
3637c478bd9Sstevel@tonic-gate 		 * manipulation function.
3647c478bd9Sstevel@tonic-gate 		 */
3657c478bd9Sstevel@tonic-gate 		if (pool_walk_properties(TO_CONF(e1), e1, e2, clone_element) !=
3667c478bd9Sstevel@tonic-gate 		    PO_SUCCESS) {
3677c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 		if (pool_walk_properties(TO_CONF(e2), e2, e1, clone_element) !=
3707c478bd9Sstevel@tonic-gate 		    PO_SUCCESS) {
3717c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
3727c478bd9Sstevel@tonic-gate 		}
3737c478bd9Sstevel@tonic-gate 	} else {
3747c478bd9Sstevel@tonic-gate 		if (pool_elem_class(e1) == PEC_POOL) {
3757c478bd9Sstevel@tonic-gate 			pool_resource_t **rs;
3767c478bd9Sstevel@tonic-gate 			uint_t nelem;
3777c478bd9Sstevel@tonic-gate 			int i;
3787c478bd9Sstevel@tonic-gate 			pool_value_t val = POOL_VALUE_INITIALIZER;
3797c478bd9Sstevel@tonic-gate 			pool_value_t *pvals[] = { NULL, NULL };
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 			pvals[0] = &val;
3827c478bd9Sstevel@tonic-gate 			if (pool_value_set_string(&val, "pset") != PO_SUCCESS ||
3837c478bd9Sstevel@tonic-gate 			    pool_value_set_name(&val, c_type) != PO_SUCCESS)
3847c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
3857c478bd9Sstevel@tonic-gate 			if ((rs = pool_query_pool_resources(TO_CONF(e1),
3867c478bd9Sstevel@tonic-gate 			    pool_elem_pool(e1), &nelem, pvals)) != NULL) {
3877c478bd9Sstevel@tonic-gate 				for (i = 0; i < nelem; i++) {
3887c478bd9Sstevel@tonic-gate 					const pool_resource_t *tgt_res;
3897c478bd9Sstevel@tonic-gate 					char *res_name =
3907c478bd9Sstevel@tonic-gate 					    elem_get_name(TO_ELEM(rs[i]));
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 					if ((tgt_res = pool_get_resource(
3937c478bd9Sstevel@tonic-gate 					    TO_CONF(e2), pool_elem_class_string(
3947c478bd9Sstevel@tonic-gate 					    TO_ELEM(rs[i])), res_name)) ==
3957c478bd9Sstevel@tonic-gate 					    NULL) {
3967c478bd9Sstevel@tonic-gate 						tgt_res = get_default_resource(
3977c478bd9Sstevel@tonic-gate 						    rs[i]);
3987c478bd9Sstevel@tonic-gate 					}
3997c478bd9Sstevel@tonic-gate 					free(res_name);
4007c478bd9Sstevel@tonic-gate 					if (pool_associate(TO_CONF(e2),
4017c478bd9Sstevel@tonic-gate 					    pool_elem_pool(e2), tgt_res) !=
4027c478bd9Sstevel@tonic-gate 					    PO_SUCCESS) {
4037c478bd9Sstevel@tonic-gate 						free(rs);
4047c478bd9Sstevel@tonic-gate 						return (PO_FAIL);
4057c478bd9Sstevel@tonic-gate 					}
4067c478bd9Sstevel@tonic-gate 				}
4077c478bd9Sstevel@tonic-gate 				free(rs);
4087c478bd9Sstevel@tonic-gate 			}
4097c478bd9Sstevel@tonic-gate 		}
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate  * diff_and_fix() works out the differences between two configurations
4167c478bd9Sstevel@tonic-gate  * and modifies the state of the system to match the operations
4177c478bd9Sstevel@tonic-gate  * required to bring the two configurations into sync.
4187c478bd9Sstevel@tonic-gate  *
4197c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL.
4207c478bd9Sstevel@tonic-gate  */
4217c478bd9Sstevel@tonic-gate static int
diff_and_fix(pool_conf_t * stc,pool_conf_t * dyn)4227c478bd9Sstevel@tonic-gate diff_and_fix(pool_conf_t *stc, pool_conf_t *dyn)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	/*
4257c478bd9Sstevel@tonic-gate 	 * The ordering of the operations is significant, we must
4267c478bd9Sstevel@tonic-gate 	 * process the system element, then the pools elements, then
4277c478bd9Sstevel@tonic-gate 	 * the resource elements, then the pools elements again and
4287c478bd9Sstevel@tonic-gate 	 * finally the resource components.
4297c478bd9Sstevel@tonic-gate 	 *
4307c478bd9Sstevel@tonic-gate 	 * TODO
4317c478bd9Sstevel@tonic-gate 	 * PEC_RES_COMP are the only type of resources
4327c478bd9Sstevel@tonic-gate 	 * currently. When PEC_RES_AGG resources are added they must
4337c478bd9Sstevel@tonic-gate 	 * also be processed.
4347c478bd9Sstevel@tonic-gate 	 */
4357c478bd9Sstevel@tonic-gate 	if (process_lists(PEC_SYSTEM, stc, dyn, 0) != PO_SUCCESS) {
4367c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate 	if (process_lists(PEC_POOL, stc, dyn, 0) != PO_SUCCESS) {
4397c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate 	if (process_lists(PEC_RES_COMP, stc, dyn, 0) != PO_SUCCESS) {
4427c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate 	if (process_lists(PEC_COMP, stc, dyn, 0) != PO_SUCCESS) {
4457c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
4467c478bd9Sstevel@tonic-gate 	}
4477c478bd9Sstevel@tonic-gate 	if (process_lists(PEC_POOL, stc, dyn, 1) != PO_SUCCESS) {
4487c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate 	/*
4517c478bd9Sstevel@tonic-gate 	 * Share the resources. It has to be called for both
4527c478bd9Sstevel@tonic-gate 	 * configurations to ensure that the configurations still look
4537c478bd9Sstevel@tonic-gate 	 * the same.
4547c478bd9Sstevel@tonic-gate 	 */
4557c478bd9Sstevel@tonic-gate 	if (share_resources(dyn) != PO_SUCCESS) {
4567c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 	if (share_resources(stc) != PO_SUCCESS) {
4597c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
4607c478bd9Sstevel@tonic-gate 	}
4617c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate static int
process_elem_lt(pool_elem_t * pe,pool_conf_t * dyn)4657c478bd9Sstevel@tonic-gate process_elem_lt(pool_elem_t *pe, pool_conf_t *dyn)
4667c478bd9Sstevel@tonic-gate {
4677c478bd9Sstevel@tonic-gate 	if (pool_elem_class(pe) == PEC_COMP) {
4687c478bd9Sstevel@tonic-gate 		if (pool_component_destroy(pool_elem_comp(pe)) == PO_FAIL) {
4697c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
4707c478bd9Sstevel@tonic-gate 		}
4717c478bd9Sstevel@tonic-gate 	} else if (! elem_is_default(pe)) {
4727c478bd9Sstevel@tonic-gate 		if (commit_create(dyn, &pe) != PO_SUCCESS) {
4737c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
4747c478bd9Sstevel@tonic-gate 		}
4757c478bd9Sstevel@tonic-gate 	}
4767c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate static int
process_elem_gt(pool_elem_t * pe,pool_conf_t * stc,pool_conf_t * dyn)4807c478bd9Sstevel@tonic-gate process_elem_gt(pool_elem_t *pe, pool_conf_t *stc, pool_conf_t *dyn)
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate 	if (pool_elem_class(pe) == PEC_COMP) {
4837c478bd9Sstevel@tonic-gate 		pool_resource_t *owner;
4847c478bd9Sstevel@tonic-gate 		const pool_resource_t *parent_res;
4857c478bd9Sstevel@tonic-gate 		pool_value_t val = POOL_VALUE_INITIALIZER;
4867c478bd9Sstevel@tonic-gate 		const pool_component_t *newcomp;
4877c478bd9Sstevel@tonic-gate 		const char *resname;
4887c478bd9Sstevel@tonic-gate 		const char *restype;
4897c478bd9Sstevel@tonic-gate 		/*
4907c478bd9Sstevel@tonic-gate 		 * I have to find the right parent in the static
4917c478bd9Sstevel@tonic-gate 		 * configuration. It may not exist, in which case it's
4927c478bd9Sstevel@tonic-gate 		 * correct to put it in the default
4937c478bd9Sstevel@tonic-gate 		 */
4947c478bd9Sstevel@tonic-gate 		owner = pool_get_owning_resource(dyn,
4957c478bd9Sstevel@tonic-gate 		    pool_elem_comp(pe));
4967c478bd9Sstevel@tonic-gate 		if (pool_get_ns_property(TO_ELEM(owner), "name", &val) ==
4977c478bd9Sstevel@tonic-gate 		    POC_INVAL)
4987c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 		if (pool_value_get_string(&val, &resname) == PO_FAIL)
5017c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 		if ((resname = strdup(resname)) == NULL)
5047c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 		restype = pool_elem_class_string(TO_ELEM(owner));
5077c478bd9Sstevel@tonic-gate 		parent_res = pool_get_resource(stc, restype, resname);
5087c478bd9Sstevel@tonic-gate 		free((void *)resname);
5097c478bd9Sstevel@tonic-gate 		if (parent_res == NULL)
5107c478bd9Sstevel@tonic-gate 			parent_res = resource_by_sysid(stc, PS_NONE, restype);
5117c478bd9Sstevel@tonic-gate 		/*
5127c478bd9Sstevel@tonic-gate 		 * Now need to make a copy of the component in the
5137c478bd9Sstevel@tonic-gate 		 * dynamic configuration in the static configuration.
5147c478bd9Sstevel@tonic-gate 		 */
5157c478bd9Sstevel@tonic-gate 		if ((newcomp = pool_component_create(stc, parent_res,
5167c478bd9Sstevel@tonic-gate 		    elem_get_sysid(pe))) == NULL)
5177c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		if (pool_walk_properties(TO_CONF(pe), pe, TO_ELEM(newcomp),
5207c478bd9Sstevel@tonic-gate 		    clone_element) != PO_SUCCESS)
5217c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
5227c478bd9Sstevel@tonic-gate 	} else if (elem_is_default(pe)) {
5237c478bd9Sstevel@tonic-gate 		pool_resource_t *newres;
5247c478bd9Sstevel@tonic-gate 		pool_t *newpool;
5257c478bd9Sstevel@tonic-gate 		char *name;
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 		if ((name = elem_get_name(pe)) == NULL)
5287c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
5297c478bd9Sstevel@tonic-gate 		switch (pool_elem_class(pe)) {
5307c478bd9Sstevel@tonic-gate 		case PEC_POOL:
5317c478bd9Sstevel@tonic-gate 			if ((newpool = pool_create(stc, name)) == NULL) {
5327c478bd9Sstevel@tonic-gate 				free(name);
5337c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5347c478bd9Sstevel@tonic-gate 			}
5357c478bd9Sstevel@tonic-gate 			free(name);
5367c478bd9Sstevel@tonic-gate 			if (pool_walk_properties(TO_CONF(pe), pe,
5377c478bd9Sstevel@tonic-gate 			    TO_ELEM(newpool), clone_element) != PO_SUCCESS)
5387c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5397c478bd9Sstevel@tonic-gate 			break;
5407c478bd9Sstevel@tonic-gate 		case PEC_RES_AGG:
5417c478bd9Sstevel@tonic-gate 		case PEC_RES_COMP:
5427c478bd9Sstevel@tonic-gate 			if ((newres = pool_resource_create(stc,
5437c478bd9Sstevel@tonic-gate 			    pool_elem_class_string(pe), name)) ==
5447c478bd9Sstevel@tonic-gate 			    NULL) {
5457c478bd9Sstevel@tonic-gate 				free(name);
5467c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5477c478bd9Sstevel@tonic-gate 			}
5487c478bd9Sstevel@tonic-gate 			free(name);
5497c478bd9Sstevel@tonic-gate 			if (pool_walk_properties(TO_CONF(pe), pe,
5507c478bd9Sstevel@tonic-gate 			    TO_ELEM(newres), clone_element) != PO_SUCCESS)
5517c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5527c478bd9Sstevel@tonic-gate 			break;
5537c478bd9Sstevel@tonic-gate 		default:
5547c478bd9Sstevel@tonic-gate 			free(name);
5557c478bd9Sstevel@tonic-gate 			break;
5567c478bd9Sstevel@tonic-gate 		}
5577c478bd9Sstevel@tonic-gate 	} else {
5587c478bd9Sstevel@tonic-gate 		if (commit_delete(pe) != PO_SUCCESS)
5597c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
5607c478bd9Sstevel@tonic-gate 	}
5617c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate /*
5657c478bd9Sstevel@tonic-gate  * This function compares the elements of the supplied type in the
5667c478bd9Sstevel@tonic-gate  * static and dynamic configurations supplied. The lists of elements
5677c478bd9Sstevel@tonic-gate  * are compared and used to create, delete and updated elements in
5687c478bd9Sstevel@tonic-gate  * both the static and dynamic configurations. The pass parameter is
5697c478bd9Sstevel@tonic-gate  * used to indicate to commit_update() whether property updates or
5707c478bd9Sstevel@tonic-gate  * association updates should be performed.
5717c478bd9Sstevel@tonic-gate  */
5727c478bd9Sstevel@tonic-gate static int
process_lists(int type,pool_conf_t * stc,pool_conf_t * dyn,int pass)5737c478bd9Sstevel@tonic-gate process_lists(int type, pool_conf_t *stc, pool_conf_t *dyn, int pass)
5747c478bd9Sstevel@tonic-gate {
5757c478bd9Sstevel@tonic-gate 	uint_t stc_nelem = 0, dyn_nelem = 0;
5767c478bd9Sstevel@tonic-gate 	pool_elem_t **stc_elems, **dyn_elems;
5777c478bd9Sstevel@tonic-gate 	int i, j;
5787c478bd9Sstevel@tonic-gate 	int status = PO_SUCCESS;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	if ((stc_elems = get_elem_list(stc, type, &stc_nelem)) == NULL)
5817c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	qsort(stc_elems, stc_nelem, sizeof (pool_elem_t *),
5847c478bd9Sstevel@tonic-gate 	    qsort_elem_compare);
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	if ((dyn_elems = get_elem_list(dyn, type, &dyn_nelem)) == NULL) {
5877c478bd9Sstevel@tonic-gate 		free(stc_elems);
5887c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	qsort(dyn_elems, dyn_nelem, sizeof (pool_elem_t *),
5927c478bd9Sstevel@tonic-gate 	    qsort_elem_compare);
5937c478bd9Sstevel@tonic-gate 	/*
5947c478bd9Sstevel@tonic-gate 	 * Step through and do the updating, remember that we are
5957c478bd9Sstevel@tonic-gate 	 * comparing using the compare function for the configuration
5967c478bd9Sstevel@tonic-gate 	 * and that is fixed.
5977c478bd9Sstevel@tonic-gate 	 */
5987c478bd9Sstevel@tonic-gate 	i = j = 0;
5997c478bd9Sstevel@tonic-gate 	while (status == PO_SUCCESS && i < stc_nelem && j < dyn_nelem) {
6007c478bd9Sstevel@tonic-gate 		int compare;
6017c478bd9Sstevel@tonic-gate 		/*
6027c478bd9Sstevel@tonic-gate 		 * We are going to do this by stepping through the static
6037c478bd9Sstevel@tonic-gate 		 * list first.
6047c478bd9Sstevel@tonic-gate 		 */
6057c478bd9Sstevel@tonic-gate 		if (elem_is_default(stc_elems[i]) &&
6067c478bd9Sstevel@tonic-gate 		    elem_is_default(dyn_elems[j]))
6077c478bd9Sstevel@tonic-gate 			compare = 0;
6087c478bd9Sstevel@tonic-gate 		else
6097c478bd9Sstevel@tonic-gate 			compare = pool_elem_compare_name(stc_elems[i],
6107c478bd9Sstevel@tonic-gate 			    dyn_elems[j]);
6117c478bd9Sstevel@tonic-gate 		if (compare < 0) {
6127c478bd9Sstevel@tonic-gate 			status = process_elem_lt(stc_elems[i], dyn);
6137c478bd9Sstevel@tonic-gate 			i++;
6147c478bd9Sstevel@tonic-gate 		} else if (compare > 0) {
6157c478bd9Sstevel@tonic-gate 			status = process_elem_gt(dyn_elems[j], stc, dyn);
6167c478bd9Sstevel@tonic-gate 			j++;
6177c478bd9Sstevel@tonic-gate 		} else {	/* compare == 0 */
6187c478bd9Sstevel@tonic-gate 			if (commit_update(stc_elems[i], dyn_elems[j], pass)
6197c478bd9Sstevel@tonic-gate 			    != PO_SUCCESS) {
6207c478bd9Sstevel@tonic-gate 				status = PO_FAIL;
6217c478bd9Sstevel@tonic-gate 			}
6227c478bd9Sstevel@tonic-gate 			i++;
6237c478bd9Sstevel@tonic-gate 			j++;
6247c478bd9Sstevel@tonic-gate 		}
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 	if (status == PO_FAIL) {
6277c478bd9Sstevel@tonic-gate 		free(stc_elems);
6287c478bd9Sstevel@tonic-gate 		free(dyn_elems);
6297c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
6307c478bd9Sstevel@tonic-gate 	}
6317c478bd9Sstevel@tonic-gate 	while (status == PO_SUCCESS && i < stc_nelem) {
6327c478bd9Sstevel@tonic-gate 		status = process_elem_lt(stc_elems[i], dyn);
6337c478bd9Sstevel@tonic-gate 		i++;
6347c478bd9Sstevel@tonic-gate 	}
6357c478bd9Sstevel@tonic-gate 	if (status == PO_FAIL) {
6367c478bd9Sstevel@tonic-gate 		free(stc_elems);
6377c478bd9Sstevel@tonic-gate 		free(dyn_elems);
6387c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 	while (status == PO_SUCCESS && j < dyn_nelem) {
6417c478bd9Sstevel@tonic-gate 		status = process_elem_gt(dyn_elems[j], stc, dyn);
6427c478bd9Sstevel@tonic-gate 		j++;
6437c478bd9Sstevel@tonic-gate 	}
6447c478bd9Sstevel@tonic-gate 	free(stc_elems);
6457c478bd9Sstevel@tonic-gate 	free(dyn_elems);
6467c478bd9Sstevel@tonic-gate 	return (status);
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate /*
6507c478bd9Sstevel@tonic-gate  * get_elem_list() returns a list of pool_elem_t's. The size of the
6517c478bd9Sstevel@tonic-gate  * list is written into nelem. The list contains elements of all types
6527c478bd9Sstevel@tonic-gate  * that pools is interested in: i.e. system, pool, resources and
6537c478bd9Sstevel@tonic-gate  * resource components. It is the caller's responsibility to free the
6547c478bd9Sstevel@tonic-gate  * list when it is finished with.
6557c478bd9Sstevel@tonic-gate  *
6567c478bd9Sstevel@tonic-gate  * The array of pointers returned by the type specific query can be
6577c478bd9Sstevel@tonic-gate  * safely cast to be an array of pool_elem_t pointers. In the case of
6587c478bd9Sstevel@tonic-gate  * PEC_RES_COMP some additional processing is required to qualify the
6597c478bd9Sstevel@tonic-gate  * list of elements.
6607c478bd9Sstevel@tonic-gate  *
6617c478bd9Sstevel@tonic-gate  * Returns a pointer to a list of pool_elem_t's or NULL on failure.
6627c478bd9Sstevel@tonic-gate  */
6637c478bd9Sstevel@tonic-gate static pool_elem_t **
get_elem_list(const pool_conf_t * conf,int type,uint_t * nelem)6647c478bd9Sstevel@tonic-gate get_elem_list(const pool_conf_t *conf, int type, uint_t *nelem)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate 	pool_resource_t **rl;
6677c478bd9Sstevel@tonic-gate 	pool_t **pl;
6687c478bd9Sstevel@tonic-gate 	pool_component_t **cl;
6697c478bd9Sstevel@tonic-gate 	pool_elem_t **elems = NULL;
6707c478bd9Sstevel@tonic-gate 	int i;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	switch (type) {
6737c478bd9Sstevel@tonic-gate 	case PEC_SYSTEM:
6747c478bd9Sstevel@tonic-gate 		if ((elems = malloc(sizeof (pool_elem_t *))) == NULL)
6757c478bd9Sstevel@tonic-gate 			return (NULL);
6767c478bd9Sstevel@tonic-gate 		*nelem = 1;
6777c478bd9Sstevel@tonic-gate 		elems[0] = pool_conf_to_elem(conf);
6787c478bd9Sstevel@tonic-gate 		break;
6797c478bd9Sstevel@tonic-gate 	case PEC_POOL:
6807c478bd9Sstevel@tonic-gate 		if ((pl = pool_query_pools(conf, nelem, NULL)) != NULL) {
6817c478bd9Sstevel@tonic-gate 			elems = (pool_elem_t **)pl;
6827c478bd9Sstevel@tonic-gate 		}
6837c478bd9Sstevel@tonic-gate 		break;
6847c478bd9Sstevel@tonic-gate 	case PEC_RES_COMP:
6857c478bd9Sstevel@tonic-gate 		if ((rl = pool_query_resources(conf, nelem, NULL)) != NULL) {
6867c478bd9Sstevel@tonic-gate 			int j = 0;
6877c478bd9Sstevel@tonic-gate 			elems = (pool_elem_t **)rl;
6887c478bd9Sstevel@tonic-gate 			for (i = 0; i < *nelem; i++) {
6897c478bd9Sstevel@tonic-gate 				if (pool_elem_class(TO_ELEM(rl[i])) ==
6907c478bd9Sstevel@tonic-gate 				    PEC_RES_COMP)
6917c478bd9Sstevel@tonic-gate 					elems[j++] = TO_ELEM(rl[i]);
6927c478bd9Sstevel@tonic-gate 			}
6937c478bd9Sstevel@tonic-gate 			*nelem = j;
6947c478bd9Sstevel@tonic-gate 		}
6957c478bd9Sstevel@tonic-gate 		break;
6967c478bd9Sstevel@tonic-gate 	case PEC_COMP:
6977c478bd9Sstevel@tonic-gate 		if ((cl = pool_query_components(conf, nelem, NULL)) != NULL) {
6987c478bd9Sstevel@tonic-gate 			elems = (pool_elem_t **)cl;
6997c478bd9Sstevel@tonic-gate 		}
7007c478bd9Sstevel@tonic-gate 		break;
7017c478bd9Sstevel@tonic-gate 	default:
7027c478bd9Sstevel@tonic-gate 		abort();
7037c478bd9Sstevel@tonic-gate 		break;
7047c478bd9Sstevel@tonic-gate 	}
7057c478bd9Sstevel@tonic-gate 	return (elems);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate /*
7097c478bd9Sstevel@tonic-gate  * share_resources() sets up the allocation of resources by each
7107c478bd9Sstevel@tonic-gate  * provider.  Firstly all resources are updated with the importance of
7117c478bd9Sstevel@tonic-gate  * each pool, then each resource provider is invoked in turn with a
7127c478bd9Sstevel@tonic-gate  * list of it's own resources.  Finally, the pool importance details
7137c478bd9Sstevel@tonic-gate  * are removed from the resources.
7147c478bd9Sstevel@tonic-gate  *
7157c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
7167c478bd9Sstevel@tonic-gate  */
7177c478bd9Sstevel@tonic-gate static int
share_resources(pool_conf_t * conf)7187c478bd9Sstevel@tonic-gate share_resources(pool_conf_t *conf)
7197c478bd9Sstevel@tonic-gate {
7207c478bd9Sstevel@tonic-gate 	pool_resource_t **resources;
7217c478bd9Sstevel@tonic-gate 	uint_t nelem;
7227c478bd9Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
7237c478bd9Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	props[0] = &val;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	/*
7287c478bd9Sstevel@tonic-gate 	 * Call an allocation function for each type of supported resource.
7297c478bd9Sstevel@tonic-gate 	 * This function is responsible for "sharing" resources to resource
7307c478bd9Sstevel@tonic-gate 	 * sets as determined by the system.allocate-method.
7317c478bd9Sstevel@tonic-gate 	 */
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	if (pool_value_set_string(props[0], "pset") != PO_SUCCESS ||
7347c478bd9Sstevel@tonic-gate 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS)
7357c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	if (add_importance_props(conf) != PO_SUCCESS) {
7387c478bd9Sstevel@tonic-gate 		(void) remove_importance_props(conf);
7397c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
7407c478bd9Sstevel@tonic-gate 	}
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	if ((resources = pool_query_resources(conf, &nelem, props)) != NULL) {
7437c478bd9Sstevel@tonic-gate 		/*
7447c478bd9Sstevel@tonic-gate 		 * 'pool.importance' defines the importance of a pool;
7457c478bd9Sstevel@tonic-gate 		 * resources inherit the importance of the pool that
7467c478bd9Sstevel@tonic-gate 		 * is associated with them. If more than one pool is
7477c478bd9Sstevel@tonic-gate 		 * associated with a resource, the importance of the
7487c478bd9Sstevel@tonic-gate 		 * resource is the maximum importance of all
7497c478bd9Sstevel@tonic-gate 		 * associated pools.  Use '_importance' on resources
7507c478bd9Sstevel@tonic-gate 		 * to determine who gets extra.
7517c478bd9Sstevel@tonic-gate 		 */
7527c478bd9Sstevel@tonic-gate 		if (resource_allocate("pset", resources, nelem) != PO_SUCCESS) {
7537c478bd9Sstevel@tonic-gate 			free(resources);
7547c478bd9Sstevel@tonic-gate 			(void) remove_importance_props(conf);
7557c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
7567c478bd9Sstevel@tonic-gate 		}
7577c478bd9Sstevel@tonic-gate 	}
7587c478bd9Sstevel@tonic-gate 	free(resources);
7597c478bd9Sstevel@tonic-gate 	(void) remove_importance_props(conf);
7607c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate /*
7657c478bd9Sstevel@tonic-gate  * Work out which allocation method to use based on the value of the
7667c478bd9Sstevel@tonic-gate  * system.allocate-method property.
7677c478bd9Sstevel@tonic-gate  */
7687c478bd9Sstevel@tonic-gate int
resource_allocate(const char * type,pool_resource_t ** res,uint_t nelem)7697c478bd9Sstevel@tonic-gate resource_allocate(const char *type, pool_resource_t **res, uint_t nelem)
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate 	pool_elem_t *pe;
7727c478bd9Sstevel@tonic-gate 	const char *method_name;
7737c478bd9Sstevel@tonic-gate 	uint64_t method;
7747c478bd9Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
7757c478bd9Sstevel@tonic-gate 	int ret;
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	pe = pool_conf_to_elem(TO_CONF(TO_ELEM(res[0])));
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	if (pool_get_ns_property(pe, "allocate-method", &val) != POC_STRING)
7807c478bd9Sstevel@tonic-gate 		method_name = POA_IMPORTANCE;
7817c478bd9Sstevel@tonic-gate 	else {
7827c478bd9Sstevel@tonic-gate 		(void) pool_value_get_string(&val, &method_name);
7837c478bd9Sstevel@tonic-gate 	}
7847c478bd9Sstevel@tonic-gate 	if (strcmp(POA_IMPORTANCE, method_name) != 0) {
7857c478bd9Sstevel@tonic-gate 		if (strcmp(POA_SURPLUS_TO_DEFAULT, method_name) != 0) {
7867c478bd9Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
7877c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
7887c478bd9Sstevel@tonic-gate 		} else {
7897c478bd9Sstevel@tonic-gate 			method = POA_SURPLUS_TO_DEFAULT_NUM;
7907c478bd9Sstevel@tonic-gate 		}
7917c478bd9Sstevel@tonic-gate 	} else {
7927c478bd9Sstevel@tonic-gate 		method = POA_IMPORTANCE_NUM;
7937c478bd9Sstevel@tonic-gate 	}
7947c478bd9Sstevel@tonic-gate 	switch (method) {
7957c478bd9Sstevel@tonic-gate 	case POA_IMPORTANCE_NUM:
7967c478bd9Sstevel@tonic-gate 		/*
7977c478bd9Sstevel@tonic-gate 		 * TODO: Add support for new resource types
7987c478bd9Sstevel@tonic-gate 		 */
7997c478bd9Sstevel@tonic-gate 		switch (pool_resource_elem_class_from_string(type)) {
8007c478bd9Sstevel@tonic-gate 		case PREC_PSET:
8017c478bd9Sstevel@tonic-gate 			ret = pset_allocate_imp(res, nelem);
8027c478bd9Sstevel@tonic-gate 			break;
8037c478bd9Sstevel@tonic-gate 		default:
8047c478bd9Sstevel@tonic-gate 			ret = PO_FAIL;
8057c478bd9Sstevel@tonic-gate 			break;
8067c478bd9Sstevel@tonic-gate 		}
8077c478bd9Sstevel@tonic-gate 		break;
8087c478bd9Sstevel@tonic-gate 	case POA_SURPLUS_TO_DEFAULT_NUM:
8097c478bd9Sstevel@tonic-gate 		ret = resource_allocate_default(res, nelem);
8107c478bd9Sstevel@tonic-gate 		break;
8117c478bd9Sstevel@tonic-gate 	}
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	return (ret);
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate /*
8177c478bd9Sstevel@tonic-gate  * Each set will get its minimum, however if there is more than the
8187c478bd9Sstevel@tonic-gate  * total minimum available, then leave this in the default set.
8197c478bd9Sstevel@tonic-gate  */
8207c478bd9Sstevel@tonic-gate int
resource_allocate_default(pool_resource_t ** res,uint_t nelem)8217c478bd9Sstevel@tonic-gate resource_allocate_default(pool_resource_t **res, uint_t nelem)
8227c478bd9Sstevel@tonic-gate {
8237c478bd9Sstevel@tonic-gate 	res_info_t *res_info;
8247c478bd9Sstevel@tonic-gate 	uint_t j;
8257c478bd9Sstevel@tonic-gate 	pool_resource_t *default_res = NULL;
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	if (nelem == 1)
8287c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	if ((res_info = calloc(nelem, sizeof (res_info_t))) == NULL) {
8317c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
8327c478bd9Sstevel@tonic-gate 	}
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 	/* Load current resource values. */
8357c478bd9Sstevel@tonic-gate 	for (j = 0; j < nelem; j++) {
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 		if (default_res == NULL &&
8387c478bd9Sstevel@tonic-gate 		    resource_is_default(res[j]) == PO_TRUE)
8397c478bd9Sstevel@tonic-gate 			default_res = res[j];
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 		if (resource_get_max(res[j],
8427c478bd9Sstevel@tonic-gate 		    &res_info[j].ri_max) == PO_FAIL ||
8437c478bd9Sstevel@tonic-gate 		    resource_get_min(res[j],
8447c478bd9Sstevel@tonic-gate 			&res_info[j].ri_min) == PO_FAIL ||
8457c478bd9Sstevel@tonic-gate 		    resource_get_size(res[j],
8467c478bd9Sstevel@tonic-gate 			&res_info[j].ri_oldsize) == PO_FAIL ||
8477c478bd9Sstevel@tonic-gate 		    resource_get_pinned(res[j],
8487c478bd9Sstevel@tonic-gate 			&res_info[j].ri_pinned) == PO_FAIL) {
8497c478bd9Sstevel@tonic-gate 			free(res_info);
8507c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
8517c478bd9Sstevel@tonic-gate 		}
8527c478bd9Sstevel@tonic-gate 		res_info[j].ri_res = res[j];
8537c478bd9Sstevel@tonic-gate 	}
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	/*
8567c478bd9Sstevel@tonic-gate 	 * Firstly, for all resources that have size greater than min,
8577c478bd9Sstevel@tonic-gate 	 * transfer all movable size above min to the default resource.
8587c478bd9Sstevel@tonic-gate 	 */
8597c478bd9Sstevel@tonic-gate 	for (j = 0; j < nelem; j++) {
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 		uint64_t real_min;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 		/* compute the real minimum number of resources */
8647c478bd9Sstevel@tonic-gate 		real_min = MAX(res_info[j].ri_pinned, res_info[j].ri_min);
8657c478bd9Sstevel@tonic-gate 		if (res_info[j].ri_res != default_res &&
8667c478bd9Sstevel@tonic-gate 		    res_info[j].ri_oldsize > real_min) {
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 			uint64_t num;
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 			num = res_info[j].ri_oldsize - real_min;
8717c478bd9Sstevel@tonic-gate 			if (pool_resource_transfer(
8727c478bd9Sstevel@tonic-gate 			    TO_CONF(TO_ELEM(default_res)),
8737c478bd9Sstevel@tonic-gate 				res_info[j].ri_res, default_res, num) !=
8747c478bd9Sstevel@tonic-gate 			    PO_SUCCESS) {
8757c478bd9Sstevel@tonic-gate 				free(res_info);
8767c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
8777c478bd9Sstevel@tonic-gate 			}
8787c478bd9Sstevel@tonic-gate 		}
8797c478bd9Sstevel@tonic-gate 	}
8807c478bd9Sstevel@tonic-gate 	/*
8817c478bd9Sstevel@tonic-gate 	 * Now, transfer resources below min from the default.
8827c478bd9Sstevel@tonic-gate 	 */
8837c478bd9Sstevel@tonic-gate 	for (j = 0; j < nelem; j++) {
8847c478bd9Sstevel@tonic-gate 		/*
8857c478bd9Sstevel@tonic-gate 		 * We don't want to interfere with resources which are reserved
8867c478bd9Sstevel@tonic-gate 		 */
8877c478bd9Sstevel@tonic-gate 		if (res_info[j].ri_res != default_res &&
8887c478bd9Sstevel@tonic-gate 		    res_info[j].ri_oldsize < res_info[j].ri_min) {
8897c478bd9Sstevel@tonic-gate 			if (pool_resource_transfer(
8907c478bd9Sstevel@tonic-gate 			    TO_CONF(TO_ELEM(default_res)),
8917c478bd9Sstevel@tonic-gate 			    default_res, res_info[j].ri_res,
8927c478bd9Sstevel@tonic-gate 			    res_info[j].ri_min - res_info[j].ri_oldsize) !=
8937c478bd9Sstevel@tonic-gate 			    PO_SUCCESS) {
8947c478bd9Sstevel@tonic-gate 				free(res_info);
8957c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
8967c478bd9Sstevel@tonic-gate 			}
8977c478bd9Sstevel@tonic-gate 		}
8987c478bd9Sstevel@tonic-gate 	}
8997c478bd9Sstevel@tonic-gate 	free(res_info);
9007c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
9017c478bd9Sstevel@tonic-gate }
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate /*
9047c478bd9Sstevel@tonic-gate  * Allocate cpus to pset resource sets, favoring sets with higher importance.
9057c478bd9Sstevel@tonic-gate  *
9067c478bd9Sstevel@tonic-gate  * Step 1: Sort resource sets by decreasing importance, and load each sets
9077c478bd9Sstevel@tonic-gate  *	   current size (oldsize), min, max, and number of pinned cpus.
9087c478bd9Sstevel@tonic-gate  *	   Compute the total number of cpus by totaling oldsize.
9097c478bd9Sstevel@tonic-gate  *
9107c478bd9Sstevel@tonic-gate  * Step 2: Compute the newsize for each set:
9117c478bd9Sstevel@tonic-gate  *
9127c478bd9Sstevel@tonic-gate  * 	Give each set its min number of cpus.  This min may be greater than
9137c478bd9Sstevel@tonic-gate  *	its pset.min due to pinned cpus. If there are more cpus than the total
9147c478bd9Sstevel@tonic-gate  *	of all mins, then the surplus cpus are dealt round-robin to all sets
9157c478bd9Sstevel@tonic-gate  *	(up to their max) in order of decreasing importance.  A set may be
9167c478bd9Sstevel@tonic-gate  *	skipped during dealing because it started with more than its min due to
9177c478bd9Sstevel@tonic-gate  * 	pinned cpus.  The dealing stops when there are no more cpus or all
9187c478bd9Sstevel@tonic-gate  *	sets are at their max. If all sets are at their max, any remaining cpus
9197c478bd9Sstevel@tonic-gate  *	are given to the default set.
9207c478bd9Sstevel@tonic-gate  *
9217c478bd9Sstevel@tonic-gate  * Step 3: Transfer cpus from sets with (oldsize > newsize) to sets with
9227c478bd9Sstevel@tonic-gate  *	   (oldsize < newsize).
9237c478bd9Sstevel@tonic-gate  */
9247c478bd9Sstevel@tonic-gate int
pset_allocate_imp(pool_resource_t ** res,uint_t nelem)9257c478bd9Sstevel@tonic-gate pset_allocate_imp(pool_resource_t **res, uint_t nelem)
9267c478bd9Sstevel@tonic-gate {
9277c478bd9Sstevel@tonic-gate 	res_info_t *res_info;
9287c478bd9Sstevel@tonic-gate 	res_info_t *default_res_info;
9297c478bd9Sstevel@tonic-gate 	const pool_resource_t *default_res = NULL;
9307c478bd9Sstevel@tonic-gate 	uint64_t tot_resources = 0;	/* total count of resources */
9317c478bd9Sstevel@tonic-gate 	uint64_t tot_min = 0;		/* total of all resource set mins */
9327c478bd9Sstevel@tonic-gate 	uint64_t num_to_deal = 0;	/* total resources above mins to deal */
9337c478bd9Sstevel@tonic-gate 	uint64_t sets_maxed = 0;	/* number of resource sets dealt to  */
9347c478bd9Sstevel@tonic-gate 					/* their max */
9357c478bd9Sstevel@tonic-gate 	uint64_t sets_finished = 0;	/* number of resource sets that have */
9367c478bd9Sstevel@tonic-gate 					/* size == newsize */
9377c478bd9Sstevel@tonic-gate 	int donor, receiver;
9387c478bd9Sstevel@tonic-gate 	int deal;
9397c478bd9Sstevel@tonic-gate 	int j;
9407c478bd9Sstevel@tonic-gate 	int ret = PO_SUCCESS;
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	/*
9437c478bd9Sstevel@tonic-gate 	 * Build list of res_info_t's
9447c478bd9Sstevel@tonic-gate 	 */
9457c478bd9Sstevel@tonic-gate 	if ((res_info = calloc(nelem, sizeof (res_info_t))) == NULL) {
9467c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
9477c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
9487c478bd9Sstevel@tonic-gate 	}
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	/* Order resources by importance, most important being first */
9517c478bd9Sstevel@tonic-gate 	qsort(res, nelem, sizeof (pool_resource_t *),
9527c478bd9Sstevel@tonic-gate 	    resource_compare_by_descending_importance);
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 	for (j = 0; j < nelem; j++) {
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 		/* Track which resource is the default */
9577c478bd9Sstevel@tonic-gate 		if (default_res == NULL &&
9587c478bd9Sstevel@tonic-gate 		    resource_is_default(res[j]) == PO_TRUE) {
9597c478bd9Sstevel@tonic-gate 			default_res = res[j];
9607c478bd9Sstevel@tonic-gate 			default_res_info = &(res_info[j]);
9617c478bd9Sstevel@tonic-gate 		}
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 		/* Load sets' current values */
9647c478bd9Sstevel@tonic-gate 		if (resource_get_max(res[j], &res_info[j].ri_max) == PO_FAIL ||
9657c478bd9Sstevel@tonic-gate 		    resource_get_min(res[j], &res_info[j].ri_min) == PO_FAIL ||
9667c478bd9Sstevel@tonic-gate 		    resource_get_size(res[j], &res_info[j].ri_oldsize) ==
9677c478bd9Sstevel@tonic-gate 		    PO_FAIL ||
9687c478bd9Sstevel@tonic-gate 		    resource_get_pinned(res[j],
9697c478bd9Sstevel@tonic-gate 		    &res_info[j].ri_pinned) == PO_FAIL) {
9707c478bd9Sstevel@tonic-gate 			free(res_info);
9717c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
9727c478bd9Sstevel@tonic-gate 		}
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate 		/* Start each set's newsize out at their min. */
9757c478bd9Sstevel@tonic-gate 		res_info[j].ri_newsize = res_info[j].ri_min;
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 		/* pre-deal pinned resources that exceed min */
9787c478bd9Sstevel@tonic-gate 		if (res_info[j].ri_pinned > res_info[j].ri_min) {
9797c478bd9Sstevel@tonic-gate 			res_info[j].ri_newsize = res_info[j].ri_pinned;
9807c478bd9Sstevel@tonic-gate 			res_info[j].ri_dealt =
9817c478bd9Sstevel@tonic-gate 			    res_info[j].ri_newsize - res_info[j].ri_min;
9827c478bd9Sstevel@tonic-gate 		}
9837c478bd9Sstevel@tonic-gate 		res_info[j].ri_res = res[j];
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 		/* Compute total number of resources to deal out */
9867c478bd9Sstevel@tonic-gate 		tot_resources += res_info[j].ri_oldsize;
9877c478bd9Sstevel@tonic-gate 		tot_min += res_info[j].ri_newsize;
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate #ifdef DEBUG
9907c478bd9Sstevel@tonic-gate 		dprintf("res allocation details\n");
9917c478bd9Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(res[j]));
9927c478bd9Sstevel@tonic-gate 		dprintf("size=%llu\n", res_info[j].ri_oldsize);
9937c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
9947c478bd9Sstevel@tonic-gate 	}
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 	num_to_deal = tot_resources - tot_min;
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 	/*
9997c478bd9Sstevel@tonic-gate 	 * Deal one resource to each set, and then another, until all
10007c478bd9Sstevel@tonic-gate 	 * resources are dealt or all sets are at their max.
10017c478bd9Sstevel@tonic-gate 	 */
10027c478bd9Sstevel@tonic-gate 	for (deal = 1; num_to_deal > 0 && sets_maxed < nelem; deal++) {
10037c478bd9Sstevel@tonic-gate 		for (j = 0; j < nelem; j++) {
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 			/*
10067c478bd9Sstevel@tonic-gate 			 * Skip this resource set if it has already been
10077c478bd9Sstevel@tonic-gate 			 * pre-dealt a resource due to pinned resources.
10087c478bd9Sstevel@tonic-gate 			 */
10097c478bd9Sstevel@tonic-gate 			if (res_info[j].ri_dealt >= deal)
10107c478bd9Sstevel@tonic-gate 				continue;
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 			if (res_info[j].ri_newsize < res_info[j].ri_max) {
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 				res_info[j].ri_dealt++;
10157c478bd9Sstevel@tonic-gate 				res_info[j].ri_newsize++;
10167c478bd9Sstevel@tonic-gate 				if (res_info[j].ri_newsize ==
10177c478bd9Sstevel@tonic-gate 				    res_info[j].ri_max)
10187c478bd9Sstevel@tonic-gate 					sets_maxed++;
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 				num_to_deal--;
10217c478bd9Sstevel@tonic-gate 				if (num_to_deal == 0)
10227c478bd9Sstevel@tonic-gate 					break;
10237c478bd9Sstevel@tonic-gate 			}
10247c478bd9Sstevel@tonic-gate 		}
10257c478bd9Sstevel@tonic-gate 	}
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	/*
10287c478bd9Sstevel@tonic-gate 	 * If all resource sets are at their max, deal the remaining to the
10297c478bd9Sstevel@tonic-gate 	 * default resource set.
10307c478bd9Sstevel@tonic-gate 	 */
10317c478bd9Sstevel@tonic-gate 	if ((sets_maxed == nelem) && (num_to_deal > 0)) {
10327c478bd9Sstevel@tonic-gate 		default_res_info->ri_dealt += num_to_deal;
10337c478bd9Sstevel@tonic-gate 		default_res_info->ri_newsize += num_to_deal;
10347c478bd9Sstevel@tonic-gate 	}
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 	/*
10377c478bd9Sstevel@tonic-gate 	 * Sort so that resource sets needing resources preced resource sets
10387c478bd9Sstevel@tonic-gate 	 * that have extra resources.  The sort function will also compute
10397c478bd9Sstevel@tonic-gate 	 * The quantity of resources that need to be transfered into or out
10407c478bd9Sstevel@tonic-gate 	 * of each set so that it's size == newsize.
10417c478bd9Sstevel@tonic-gate 	 */
10427c478bd9Sstevel@tonic-gate 	qsort(res_info, nelem, sizeof (res_info_t),
10437c478bd9Sstevel@tonic-gate 	    compute_size_to_transfer);
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	/*
10467c478bd9Sstevel@tonic-gate 	 * The donor index starts at the end of the resource set list and
10477c478bd9Sstevel@tonic-gate 	 * walks up.  The receiver index starts at the beginning of the
10487c478bd9Sstevel@tonic-gate 	 * resource set list and walks down.  Cpu's are transfered from the
10497c478bd9Sstevel@tonic-gate 	 * donors to the receivers until all sets have transfer == 0).
10507c478bd9Sstevel@tonic-gate 	 */
10517c478bd9Sstevel@tonic-gate 	donor = nelem - 1;
10527c478bd9Sstevel@tonic-gate 	receiver = 0;
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 	/* Number of sets with transfer == 0 */
10557c478bd9Sstevel@tonic-gate 	sets_finished = 0;
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 	/* Tranfer resources so that each set's size becomes newsize */
10587c478bd9Sstevel@tonic-gate 	for (;;) {
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 		uint64_t ntrans;
10617c478bd9Sstevel@tonic-gate 		if (donor == receiver) {
10627c478bd9Sstevel@tonic-gate 			if (res_info[donor].ri_transfer != 0) {
10637c478bd9Sstevel@tonic-gate 				free(res_info);
10647c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
10657c478bd9Sstevel@tonic-gate 			}
10667c478bd9Sstevel@tonic-gate 			sets_finished++;
10677c478bd9Sstevel@tonic-gate 			break;
10687c478bd9Sstevel@tonic-gate 		}
10697c478bd9Sstevel@tonic-gate 		if (res_info[donor].ri_transfer == 0) {
10707c478bd9Sstevel@tonic-gate 			sets_finished++;
10717c478bd9Sstevel@tonic-gate 			donor--;
10727c478bd9Sstevel@tonic-gate 			continue;
10737c478bd9Sstevel@tonic-gate 		}
10747c478bd9Sstevel@tonic-gate 		if (res_info[receiver].ri_transfer == 0) {
10757c478bd9Sstevel@tonic-gate 			sets_finished++;
10767c478bd9Sstevel@tonic-gate 			receiver++;
10777c478bd9Sstevel@tonic-gate 			continue;
10787c478bd9Sstevel@tonic-gate 		}
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 		/* Transfer resources from the donor set to the receiver */
10817c478bd9Sstevel@tonic-gate 		ntrans = MIN(res_info[donor].ri_transfer,
10827c478bd9Sstevel@tonic-gate 			    -res_info[receiver].ri_transfer);
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 		if (pool_resource_transfer(
10857c478bd9Sstevel@tonic-gate 			TO_CONF(TO_ELEM(res_info[donor].ri_res)),
10867c478bd9Sstevel@tonic-gate 			    res_info[donor].ri_res, res_info[receiver].ri_res,
10877c478bd9Sstevel@tonic-gate 			    ntrans) != PO_SUCCESS) {
10887c478bd9Sstevel@tonic-gate 				free(res_info);
10897c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
10907c478bd9Sstevel@tonic-gate 			}
10917c478bd9Sstevel@tonic-gate 		res_info[donor].ri_transfer -= ntrans;
10927c478bd9Sstevel@tonic-gate 		res_info[receiver].ri_transfer += ntrans;
10937c478bd9Sstevel@tonic-gate 	}
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	if (sets_finished != nelem)
10967c478bd9Sstevel@tonic-gate 		ret = PO_FAIL;
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	free(res_info);
10997c478bd9Sstevel@tonic-gate 	return (ret);
11007c478bd9Sstevel@tonic-gate }
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate /*
11037c478bd9Sstevel@tonic-gate  * Used as a qsort parameter to help order resources in terms of their
11047c478bd9Sstevel@tonic-gate  * importance, higher importance being first.
11057c478bd9Sstevel@tonic-gate  */
11067c478bd9Sstevel@tonic-gate int
resource_compare_by_descending_importance(const void * arg1,const void * arg2)11077c478bd9Sstevel@tonic-gate resource_compare_by_descending_importance(const void *arg1, const void *arg2)
11087c478bd9Sstevel@tonic-gate {
11097c478bd9Sstevel@tonic-gate 	pool_elem_t *elem1;
11107c478bd9Sstevel@tonic-gate 	pool_elem_t *elem2;
11117c478bd9Sstevel@tonic-gate 	pool_resource_t **res1 = (pool_resource_t **)arg1;
11127c478bd9Sstevel@tonic-gate 	pool_resource_t **res2 = (pool_resource_t **)arg2;
11137c478bd9Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
11147c478bd9Sstevel@tonic-gate 	int64_t i1 = 0, i2 = 0;
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 	elem1 = TO_ELEM(*res1);
11177c478bd9Sstevel@tonic-gate 	elem2 = TO_ELEM(*res2);
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	if (pool_get_property(TO_CONF(elem1), elem1, "_importance", &val) ==
11207c478bd9Sstevel@tonic-gate 	    POC_INT)
11217c478bd9Sstevel@tonic-gate 		(void) pool_value_get_int64(&val, &i1);
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	if (pool_get_property(TO_CONF(elem2), elem2, "_importance", &val) ==
11247c478bd9Sstevel@tonic-gate 	    POC_INT)
11257c478bd9Sstevel@tonic-gate 		(void) pool_value_get_int64(&val, &i2);
11267c478bd9Sstevel@tonic-gate 	return (i1 > i2 ? -1 : (i1 < i2 ? 1 : 0));
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate /*
11307c478bd9Sstevel@tonic-gate  * Sort in increasing order so that resource sets with extra resources are at
11317c478bd9Sstevel@tonic-gate  * the end and resource sets needing resources are at the beginning.
11327c478bd9Sstevel@tonic-gate  */
11337c478bd9Sstevel@tonic-gate int
compute_size_to_transfer(const void * arg1,const void * arg2)11347c478bd9Sstevel@tonic-gate compute_size_to_transfer(const void *arg1, const void *arg2)
11357c478bd9Sstevel@tonic-gate {
11367c478bd9Sstevel@tonic-gate 	res_info_t *r1 = (res_info_t *)arg1, *r2 = (res_info_t *)arg2;
11377c478bd9Sstevel@tonic-gate 	r1->ri_transfer = (int64_t)r1->ri_oldsize - (int64_t)r1->ri_newsize;
11387c478bd9Sstevel@tonic-gate 	r2->ri_transfer = (int64_t)r2->ri_oldsize - (int64_t)r2->ri_newsize;
11397c478bd9Sstevel@tonic-gate 	return (r1->ri_transfer > r2->ri_transfer ? 1 :
11407c478bd9Sstevel@tonic-gate 	    (r1->ri_transfer < r2->ri_transfer ? -1 : 0));
11417c478bd9Sstevel@tonic-gate }
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate /*
11447c478bd9Sstevel@tonic-gate  * set_importance_cb() is used to create "_importance" props on each
11457c478bd9Sstevel@tonic-gate  * resource associated with a pool.
11467c478bd9Sstevel@tonic-gate  *
11477c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
11487c478bd9Sstevel@tonic-gate  */
11497c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11507c478bd9Sstevel@tonic-gate static int
set_importance_cb(pool_conf_t * conf,pool_t * pool,void * unused)11517c478bd9Sstevel@tonic-gate set_importance_cb(pool_conf_t *conf, pool_t *pool, void *unused)
11527c478bd9Sstevel@tonic-gate {
11537c478bd9Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
11547c478bd9Sstevel@tonic-gate 	int64_t importance;
11557c478bd9Sstevel@tonic-gate 	pool_resource_t **res;
11567c478bd9Sstevel@tonic-gate 	uint_t nelem, i;
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 	if (pool_get_property(conf, TO_ELEM(pool), "pool.importance", &val) !=
11597c478bd9Sstevel@tonic-gate 	    POC_INT) {
11607c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
11617c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
11627c478bd9Sstevel@tonic-gate 	}
11637c478bd9Sstevel@tonic-gate 	(void) pool_value_get_int64(&val, &importance);
11647c478bd9Sstevel@tonic-gate 	if ((res = pool_query_pool_resources(conf, pool, &nelem, NULL)) ==
11657c478bd9Sstevel@tonic-gate 	    NULL) {
11667c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
11677c478bd9Sstevel@tonic-gate 	}
11687c478bd9Sstevel@tonic-gate 	for (i = 0; res[i] != NULL; i++) {
11697c478bd9Sstevel@tonic-gate 		int64_t old_importance = INT64_MIN;
11707c478bd9Sstevel@tonic-gate 		pool_elem_t *elem = TO_ELEM(res[i]);
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 		if (pool_get_property(conf, elem, "_importance", &val) ==
11737c478bd9Sstevel@tonic-gate 		    POC_INT)
11747c478bd9Sstevel@tonic-gate 			(void) pool_value_get_int64(&val, &old_importance);
11757c478bd9Sstevel@tonic-gate 		if (old_importance <= importance) {
11767c478bd9Sstevel@tonic-gate 			(void) pool_value_set_int64(&val, importance);
11777c478bd9Sstevel@tonic-gate 			(void) pool_put_property(conf, elem, "_importance",
11787c478bd9Sstevel@tonic-gate 			    &val);
11797c478bd9Sstevel@tonic-gate 		}
11807c478bd9Sstevel@tonic-gate 	}
11817c478bd9Sstevel@tonic-gate 	free(res);
11827c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
11837c478bd9Sstevel@tonic-gate }
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate /*
11867c478bd9Sstevel@tonic-gate  * unset_importance_cb() is used to remove "_importance" props from
11877c478bd9Sstevel@tonic-gate  * each resource associated with a pool.
11887c478bd9Sstevel@tonic-gate  *
11897c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
11907c478bd9Sstevel@tonic-gate  */
11917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11927c478bd9Sstevel@tonic-gate static int
unset_importance_cb(pool_conf_t * conf,pool_t * pool,void * unused)11937c478bd9Sstevel@tonic-gate unset_importance_cb(pool_conf_t *conf, pool_t *pool, void *unused)
11947c478bd9Sstevel@tonic-gate {
11957c478bd9Sstevel@tonic-gate 	pool_resource_t **res;
11967c478bd9Sstevel@tonic-gate 	uint_t nelem, i;
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 	if ((res = pool_query_pool_resources(conf, pool, &nelem, NULL)) ==
11997c478bd9Sstevel@tonic-gate 	    NULL) {
12007c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
12017c478bd9Sstevel@tonic-gate 	}
12027c478bd9Sstevel@tonic-gate 	for (i = 0; res[i] != NULL; i++) {
12037c478bd9Sstevel@tonic-gate 		if (pool_rm_property(conf, TO_ELEM(res[i]), "_importance") ==
12047c478bd9Sstevel@tonic-gate 		    PO_FAIL) {
12057c478bd9Sstevel@tonic-gate 			free(res);
12067c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
12077c478bd9Sstevel@tonic-gate 		}
12087c478bd9Sstevel@tonic-gate 	}
12097c478bd9Sstevel@tonic-gate 	free(res);
12107c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
12117c478bd9Sstevel@tonic-gate }
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate /*
12147c478bd9Sstevel@tonic-gate  * add_importance_props() is used to create "_importance" props on
12157c478bd9Sstevel@tonic-gate  * each resource associated with a pool.
12167c478bd9Sstevel@tonic-gate  *
12177c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
12187c478bd9Sstevel@tonic-gate  */
12197c478bd9Sstevel@tonic-gate static int
add_importance_props(pool_conf_t * conf)12207c478bd9Sstevel@tonic-gate add_importance_props(pool_conf_t *conf)
12217c478bd9Sstevel@tonic-gate {
12227c478bd9Sstevel@tonic-gate 	return (pool_walk_pools(conf, NULL, set_importance_cb));
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate /*
12267c478bd9Sstevel@tonic-gate  * remove_importance_props() is used to remove "_importance" props on
12277c478bd9Sstevel@tonic-gate  * each resource associated with a pool.
12287c478bd9Sstevel@tonic-gate  *
12297c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
12307c478bd9Sstevel@tonic-gate  */
12317c478bd9Sstevel@tonic-gate static int
remove_importance_props(pool_conf_t * conf)12327c478bd9Sstevel@tonic-gate remove_importance_props(pool_conf_t *conf)
12337c478bd9Sstevel@tonic-gate {
12347c478bd9Sstevel@tonic-gate 	return (pool_walk_pools(conf, NULL, unset_importance_cb));
12357c478bd9Sstevel@tonic-gate }
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate /*
12387c478bd9Sstevel@tonic-gate  * pool_conf_commit_sys() takes a configuration and modifies both the
12397c478bd9Sstevel@tonic-gate  * supplied configuration and the dynamic configuration. The goal of
12407c478bd9Sstevel@tonic-gate  * this modification is to generate a dynamic configuration which best
12417c478bd9Sstevel@tonic-gate  * represents the constraints laid down in the static configuration
12427c478bd9Sstevel@tonic-gate  * and to update the static configuration with the results of this
12437c478bd9Sstevel@tonic-gate  * process.
12447c478bd9Sstevel@tonic-gate  *
12457c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
12467c478bd9Sstevel@tonic-gate  */
12477c478bd9Sstevel@tonic-gate int
pool_conf_commit_sys(pool_conf_t * conf,int validate)12487c478bd9Sstevel@tonic-gate pool_conf_commit_sys(pool_conf_t *conf, int validate)
12497c478bd9Sstevel@tonic-gate {
12507c478bd9Sstevel@tonic-gate 	pool_conf_t *dyn;
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 	if ((dyn = pool_conf_alloc()) == NULL)
12537c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
12547c478bd9Sstevel@tonic-gate 	if (pool_conf_open(dyn, pool_dynamic_location(), PO_RDWR) !=
12557c478bd9Sstevel@tonic-gate 	    PO_SUCCESS) {
12567c478bd9Sstevel@tonic-gate 		pool_conf_free(dyn);
12577c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
12587c478bd9Sstevel@tonic-gate 	}
12597c478bd9Sstevel@tonic-gate 	if (validate == PO_TRUE) {
12607c478bd9Sstevel@tonic-gate 		if (pool_conf_validate(conf, POV_RUNTIME) != PO_SUCCESS) {
12617c478bd9Sstevel@tonic-gate 			(void) pool_conf_close(dyn);
12627c478bd9Sstevel@tonic-gate 			pool_conf_free(dyn);
12637c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
12647c478bd9Sstevel@tonic-gate 		}
12657c478bd9Sstevel@tonic-gate 	}
12667c478bd9Sstevel@tonic-gate 	/*
12677c478bd9Sstevel@tonic-gate 	 * Now try to make the two things "the same".
12687c478bd9Sstevel@tonic-gate 	 */
12697c478bd9Sstevel@tonic-gate 	if (diff_and_fix(conf, dyn) != PO_SUCCESS) {
12707c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(dyn);
12717c478bd9Sstevel@tonic-gate 		pool_conf_free(dyn);
12727c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
12737c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
12747c478bd9Sstevel@tonic-gate 	}
12757c478bd9Sstevel@tonic-gate 	if (dyn->pc_prov->pc_commit(dyn) != PO_SUCCESS) {
12767c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(dyn);
12777c478bd9Sstevel@tonic-gate 		pool_conf_free(dyn);
12787c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
12797c478bd9Sstevel@tonic-gate 	}
12807c478bd9Sstevel@tonic-gate 	(void) pool_conf_close(dyn);
12817c478bd9Sstevel@tonic-gate 	pool_conf_free(dyn);
12827c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
12837c478bd9Sstevel@tonic-gate }
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate /*
12867c478bd9Sstevel@tonic-gate  * Copies all properties from one element to another. If the property
12877c478bd9Sstevel@tonic-gate  * is a readonly property, then don't copy it.
12887c478bd9Sstevel@tonic-gate  */
12897c478bd9Sstevel@tonic-gate /* ARGSUSED */
12907c478bd9Sstevel@tonic-gate static int
clone_element(pool_conf_t * conf,pool_elem_t * pe,const char * name,pool_value_t * pv,void * user)12917c478bd9Sstevel@tonic-gate clone_element(pool_conf_t *conf, pool_elem_t *pe, const char *name,
12927c478bd9Sstevel@tonic-gate     pool_value_t *pv, void *user)
12937c478bd9Sstevel@tonic-gate {
12947c478bd9Sstevel@tonic-gate 	pool_elem_t *tgt = (pool_elem_t *)user;
12957c478bd9Sstevel@tonic-gate 	const pool_prop_t *prop;
12967c478bd9Sstevel@tonic-gate #ifdef DEBUG
12977c478bd9Sstevel@tonic-gate 	dprintf("Cloning %s from %s\n",
12987c478bd9Sstevel@tonic-gate 	    pool_conf_location(TO_CONF(TO_ELEM(tgt))),
12997c478bd9Sstevel@tonic-gate 	    pool_conf_location(TO_CONF(pe)));
13007c478bd9Sstevel@tonic-gate 	assert(TO_CONF(TO_ELEM(tgt)) != TO_CONF(pe));
13017c478bd9Sstevel@tonic-gate 	dprintf("clone_element: Processing %s\n", name);
13027c478bd9Sstevel@tonic-gate 	pool_value_dprintf(pv);
13037c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
13047c478bd9Sstevel@tonic-gate 	/*
13057c478bd9Sstevel@tonic-gate 	 * Some properties should be ignored
13067c478bd9Sstevel@tonic-gate 	 */
13077c478bd9Sstevel@tonic-gate 	if ((prop = provider_get_prop(pe, name)) != NULL &&
13087c478bd9Sstevel@tonic-gate 	    prop_is_readonly(prop) == PO_TRUE)
13097c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
1310*0209230bSgjelinek 
1311*0209230bSgjelinek 	/* The temporary property needs special handling */
1312*0209230bSgjelinek 	if (strstr(name, ".temporary") != NULL)
1313*0209230bSgjelinek 		return (pool_set_temporary(TO_CONF(tgt), tgt) ==
1314*0209230bSgjelinek 		    PO_FAIL ?  PO_FAIL : PO_SUCCESS);
1315*0209230bSgjelinek 	else
1316*0209230bSgjelinek 		return (pool_put_property(TO_CONF(tgt), tgt, name, pv) ==
1317*0209230bSgjelinek 		    PO_FAIL ? PO_FAIL : PO_SUCCESS);
13187c478bd9Sstevel@tonic-gate }
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate /*
13217c478bd9Sstevel@tonic-gate  * Removes all properties from one element. Properties which are
13227c478bd9Sstevel@tonic-gate  * managed by the configuration are ignored.
13237c478bd9Sstevel@tonic-gate  */
13247c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
13257c478bd9Sstevel@tonic-gate static int
clean_element(pool_conf_t * conf,pool_elem_t * pe,const char * name,pool_value_t * pv,void * user)13267c478bd9Sstevel@tonic-gate clean_element(pool_conf_t *conf, pool_elem_t *pe, const char *name,
13277c478bd9Sstevel@tonic-gate     pool_value_t *pv, void *user)
13287c478bd9Sstevel@tonic-gate {
13297c478bd9Sstevel@tonic-gate 	const pool_prop_t *prop;
13307c478bd9Sstevel@tonic-gate 	/*
13317c478bd9Sstevel@tonic-gate 	 * Some properties should be ignored
13327c478bd9Sstevel@tonic-gate 	 */
1333*0209230bSgjelinek 	if (strstr(name, ".temporary") != NULL ||
1334*0209230bSgjelinek 	    ((prop = provider_get_prop(pe, name)) != NULL &&
1335*0209230bSgjelinek 	    prop_is_optional(prop) == PO_FALSE))
13367c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
13377c478bd9Sstevel@tonic-gate 	return (pool_rm_property(conf, (pool_elem_t *)pe, name) == PO_FAIL);
13387c478bd9Sstevel@tonic-gate }
1339