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
5648495d6Svikram  * Common Development and Distribution License (the "License").
6648495d6Svikram  * 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  */
21*5ad42b1bSSurya Prakki 
227c478bd9Sstevel@tonic-gate /*
23*5ad42b1bSSurya Prakki  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate #include <errno.h>
327c478bd9Sstevel@tonic-gate #include <libintl.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate #include <rcm_module.h>
357c478bd9Sstevel@tonic-gate #include <sys/pset.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <pool.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * RCM module ops.
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate static int pool_register(rcm_handle_t *);
437c478bd9Sstevel@tonic-gate static int pool_unregister(rcm_handle_t *);
447c478bd9Sstevel@tonic-gate static int pool_get_info(rcm_handle_t *, char *, id_t, uint_t, char **,
457c478bd9Sstevel@tonic-gate     char **, nvlist_t *, rcm_info_t **);
467c478bd9Sstevel@tonic-gate static int pool_request_suspend(rcm_handle_t *, char *, id_t,
477c478bd9Sstevel@tonic-gate     timespec_t *, uint_t, char **, rcm_info_t **);
487c478bd9Sstevel@tonic-gate static int pool_notify_resume(rcm_handle_t *, char *, id_t, uint_t, char **,
497c478bd9Sstevel@tonic-gate     rcm_info_t **);
507c478bd9Sstevel@tonic-gate static int pool_notify_remove(rcm_handle_t *, char *, id_t, uint_t,
517c478bd9Sstevel@tonic-gate     char **, rcm_info_t **);
527c478bd9Sstevel@tonic-gate static int pool_request_offline(rcm_handle_t *, char *, id_t, uint_t,
537c478bd9Sstevel@tonic-gate     char **, rcm_info_t **);
547c478bd9Sstevel@tonic-gate static int pool_notify_online(rcm_handle_t *, char *, id_t, uint_t, char **,
557c478bd9Sstevel@tonic-gate     rcm_info_t **);
567c478bd9Sstevel@tonic-gate static int pool_request_capacity_change(rcm_handle_t *, char *, id_t, uint_t,
577c478bd9Sstevel@tonic-gate     nvlist_t *, char **, rcm_info_t **);
587c478bd9Sstevel@tonic-gate static int pool_notify_capacity_change(rcm_handle_t *, char *, id_t, uint_t,
597c478bd9Sstevel@tonic-gate     nvlist_t *, char **, rcm_info_t **);
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate  * Pool-specific callback functions.
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate static int pset_validate_remove(nvlist_t *, char **);
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate static struct {
677c478bd9Sstevel@tonic-gate 	const char *rsrc;
687c478bd9Sstevel@tonic-gate 	int (*capacity_change_cb)(nvlist_t *, char **);
697c478bd9Sstevel@tonic-gate } registrations[] = {
707c478bd9Sstevel@tonic-gate 	{ "SUNW_cpu", pset_validate_remove },
717c478bd9Sstevel@tonic-gate 	{ NULL, NULL }
727c478bd9Sstevel@tonic-gate };
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate static int registered = 0;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static struct rcm_mod_ops pool_ops = {
777c478bd9Sstevel@tonic-gate 	RCM_MOD_OPS_VERSION,
787c478bd9Sstevel@tonic-gate 	pool_register,
797c478bd9Sstevel@tonic-gate 	pool_unregister,
807c478bd9Sstevel@tonic-gate 	pool_get_info,
817c478bd9Sstevel@tonic-gate 	pool_request_suspend,
827c478bd9Sstevel@tonic-gate 	pool_notify_resume,
837c478bd9Sstevel@tonic-gate 	pool_request_offline,
847c478bd9Sstevel@tonic-gate 	pool_notify_online,
857c478bd9Sstevel@tonic-gate 	pool_notify_remove,
867c478bd9Sstevel@tonic-gate 	pool_request_capacity_change,
877c478bd9Sstevel@tonic-gate 	pool_notify_capacity_change,
887c478bd9Sstevel@tonic-gate 	NULL
897c478bd9Sstevel@tonic-gate };
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate struct rcm_mod_ops *
rcm_mod_init(void)927c478bd9Sstevel@tonic-gate rcm_mod_init(void)
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "Pools RCM module created\n");
957c478bd9Sstevel@tonic-gate 	return (&pool_ops);
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate int
rcm_mod_fini(void)1007c478bd9Sstevel@tonic-gate rcm_mod_fini(void)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "Pools RCM module unloaded\n");
1037c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate const char *
rcm_mod_info(void)1077c478bd9Sstevel@tonic-gate rcm_mod_info(void)
1087c478bd9Sstevel@tonic-gate {
109648495d6Svikram 	return ("Pools RCM module 1.4");
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate static int
pool_check_pset(pool_conf_t * conf,pool_resource_t * res,processorid_t * del_cpus,char ** errorp)1137c478bd9Sstevel@tonic-gate pool_check_pset(pool_conf_t *conf, pool_resource_t *res,
1147c478bd9Sstevel@tonic-gate     processorid_t *del_cpus, char **errorp)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 	int64_t tmp;
1177c478bd9Sstevel@tonic-gate 	int i, j;
1187c478bd9Sstevel@tonic-gate 	uint_t num_cpus;
1197c478bd9Sstevel@tonic-gate 	uint64_t min_cpus;
1207c478bd9Sstevel@tonic-gate 	uint_t num_found = 0;
1217c478bd9Sstevel@tonic-gate 	processorid_t *cpulist;
1227c478bd9Sstevel@tonic-gate 	psetid_t psetid;
1237c478bd9Sstevel@tonic-gate 	pool_value_t *pval;
1247c478bd9Sstevel@tonic-gate 	pool_elem_t *elem = pool_resource_to_elem(conf, res);
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	if ((pval = pool_value_alloc()) == NULL)
1277c478bd9Sstevel@tonic-gate 		return (-1);
1287c478bd9Sstevel@tonic-gate 	if (pool_get_property(conf, elem, "pset.min", pval) != POC_UINT) {
1297c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
1307c478bd9Sstevel@tonic-gate 		    gettext("POOL: cannot find property 'pset.min' in pset\n"));
1317c478bd9Sstevel@tonic-gate 		pool_value_free(pval);
1327c478bd9Sstevel@tonic-gate 		return (-1);
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 	(void) pool_value_get_uint64(pval, &min_cpus);
1357c478bd9Sstevel@tonic-gate 	if (pool_get_property(conf, elem, "pset.sys_id", pval) != POC_INT) {
1367c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
1377c478bd9Sstevel@tonic-gate 		    gettext("POOL: cannot get pset.sys_id\n"));
1387c478bd9Sstevel@tonic-gate 		pool_value_free(pval);
1397c478bd9Sstevel@tonic-gate 		return (-1);
1407c478bd9Sstevel@tonic-gate 	}
1417c478bd9Sstevel@tonic-gate 	(void) pool_value_get_int64(pval, &tmp);
1427c478bd9Sstevel@tonic-gate 	pool_value_free(pval);
1437c478bd9Sstevel@tonic-gate 	psetid = (psetid_t)tmp;
1447c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "POOL: checking pset: %d\n", psetid);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "POOL: min_cpus is %llu\n", min_cpus);
1477c478bd9Sstevel@tonic-gate 	if (pset_info(psetid, NULL, &num_cpus, NULL) != 0) {
1487c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
1497c478bd9Sstevel@tonic-gate 		    gettext("POOL: pset_info(%d) failed: %s\n"), psetid,
1507c478bd9Sstevel@tonic-gate 		    strerror(errno));
1517c478bd9Sstevel@tonic-gate 		return (-1);
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 	if ((cpulist = malloc(num_cpus * sizeof (processorid_t))) == NULL) {
1547c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
1557c478bd9Sstevel@tonic-gate 		    gettext("POOL: malloc failed: %s\n"), strerror(errno));
1567c478bd9Sstevel@tonic-gate 		return (-1);
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 	if (pset_info(psetid, NULL, &num_cpus, cpulist) != 0) {
1597c478bd9Sstevel@tonic-gate 		free(cpulist);
1607c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
1617c478bd9Sstevel@tonic-gate 		    gettext("POOL: pset_info(%d) failed: %s\n"), psetid,
1627c478bd9Sstevel@tonic-gate 		    strerror(errno));
1637c478bd9Sstevel@tonic-gate 		return (-1);
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	for (i = 0; del_cpus[i] != -1; i++)
1667c478bd9Sstevel@tonic-gate 		for (j = 0; j < num_cpus; j++)
1677c478bd9Sstevel@tonic-gate 			if (cpulist[j] == del_cpus[i])
1687c478bd9Sstevel@tonic-gate 				num_found++;
1697c478bd9Sstevel@tonic-gate 	free(cpulist);
1707c478bd9Sstevel@tonic-gate 	if (num_found > 0 && (num_cpus - num_found) < (uint_t)min_cpus) {
1717c478bd9Sstevel@tonic-gate 		int len;
1727c478bd9Sstevel@tonic-gate 		char *errval;
1737c478bd9Sstevel@tonic-gate 		const char *errfmt =
1747c478bd9Sstevel@tonic-gate 		    gettext("POOL: processor set (%1$d) would go "
1757c478bd9Sstevel@tonic-gate 		    "below its minimum value of %2$u\n");
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 		/*
1787c478bd9Sstevel@tonic-gate 		 * We would go below the min value. Fail this request.
1797c478bd9Sstevel@tonic-gate 		 */
1807c478bd9Sstevel@tonic-gate 		len = strlen(errfmt) + 4 * 2; /* 4 digits for psetid and min */
1817c478bd9Sstevel@tonic-gate 		if ((errval = malloc((len + 1) * sizeof (char))) != NULL) {
1827c478bd9Sstevel@tonic-gate 			(void) snprintf(errval, len + 1, errfmt, psetid,
1837c478bd9Sstevel@tonic-gate 			    (uint_t)min_cpus);
1847c478bd9Sstevel@tonic-gate 			*errorp = errval;
1857c478bd9Sstevel@tonic-gate 		}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, (char *)errfmt, psetid,
1887c478bd9Sstevel@tonic-gate 		    (uint_t)min_cpus);
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 		return (-1);
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "POOL: pset %d is fine\n", psetid);
1937c478bd9Sstevel@tonic-gate 	return (0);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate /*
1977c478bd9Sstevel@tonic-gate  * pset_validate_remove()
1987c478bd9Sstevel@tonic-gate  * 	Check to see if the requested cpu removal would be acceptable.
1997c478bd9Sstevel@tonic-gate  * 	Returns RCM_FAILURE if not.
2007c478bd9Sstevel@tonic-gate  */
2017c478bd9Sstevel@tonic-gate static int
pset_validate_remove(nvlist_t * nvl,char ** errorp)2027c478bd9Sstevel@tonic-gate pset_validate_remove(nvlist_t *nvl, char **errorp)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate 	int error = RCM_SUCCESS;
2057c478bd9Sstevel@tonic-gate 	int32_t old_total, new_total, removed_total;
2067c478bd9Sstevel@tonic-gate 	processorid_t *removed_list = NULL; /* list terminated by (-1). */
2077c478bd9Sstevel@tonic-gate 	processorid_t *old_cpu_list = NULL, *new_cpu_list = NULL;
2087c478bd9Sstevel@tonic-gate 	int i, j;
2097c478bd9Sstevel@tonic-gate 	pool_conf_t *conf;
2107c478bd9Sstevel@tonic-gate 	pool_value_t *pvals[] = { NULL, NULL };
2117c478bd9Sstevel@tonic-gate 	pool_resource_t **res = NULL;
2127c478bd9Sstevel@tonic-gate 	uint_t nelem;
2137c478bd9Sstevel@tonic-gate 	const char *generic_error = gettext("POOL: Error processing request\n");
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	if ((conf = pool_conf_alloc()) == NULL)
2167c478bd9Sstevel@tonic-gate 		return (RCM_FAILURE);
2177c478bd9Sstevel@tonic-gate 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
2187c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_TRACE1,
2197c478bd9Sstevel@tonic-gate 		    "POOL: failed to parse config file: '%s'\n",
2207c478bd9Sstevel@tonic-gate 		    pool_dynamic_location());
2217c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
2227c478bd9Sstevel@tonic-gate 		return (RCM_SUCCESS);
2237c478bd9Sstevel@tonic-gate 	}
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	if ((error = nvlist_lookup_int32(nvl, "old_total", &old_total)) != 0) {
2267c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
2277c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
2287c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
2297c478bd9Sstevel@tonic-gate 		    gettext("POOL: unable to find 'old_total' in nvlist: %s\n"),
2307c478bd9Sstevel@tonic-gate 		    strerror(error));
2317c478bd9Sstevel@tonic-gate 		*errorp = strdup(generic_error);
2327c478bd9Sstevel@tonic-gate 		return (RCM_FAILURE);
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 	if ((error = nvlist_lookup_int32(nvl, "new_total", &new_total)) != 0) {
2357c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
2367c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
2377c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
2387c478bd9Sstevel@tonic-gate 		    gettext("POOL: unable to find 'new_total' in nvlist: %s\n"),
2397c478bd9Sstevel@tonic-gate 		    strerror(error));
2407c478bd9Sstevel@tonic-gate 		*errorp = strdup(generic_error);
2417c478bd9Sstevel@tonic-gate 		return (RCM_FAILURE);
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 	if (new_total >= old_total) {
2447c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
2457c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
2467c478bd9Sstevel@tonic-gate 		/*
2477c478bd9Sstevel@tonic-gate 		 * This doesn't look like a cpu removal.
2487c478bd9Sstevel@tonic-gate 		 */
2497c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_TRACE1,
2507c478bd9Sstevel@tonic-gate 		    gettext("POOL: 'old_total' (%d) is less than 'new_total' "
251*5ad42b1bSSurya Prakki 		    "(%d)\n"), old_total, new_total);
2527c478bd9Sstevel@tonic-gate 		return (RCM_SUCCESS);
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate 	if ((removed_list = malloc((old_total - new_total + 1) * sizeof (int)))
2557c478bd9Sstevel@tonic-gate 	    == NULL) {
2567c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
2577c478bd9Sstevel@tonic-gate 		    gettext("POOL: malloc failed: %s\n"), strerror(errno));
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 		error = RCM_FAILURE;
2607c478bd9Sstevel@tonic-gate 		goto out;
2617c478bd9Sstevel@tonic-gate 	}
2627c478bd9Sstevel@tonic-gate 	if ((error = nvlist_lookup_int32_array(nvl, "old_cpu_list",
263*5ad42b1bSSurya Prakki 	    &old_cpu_list, &nelem)) != 0) {
2647c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
2657c478bd9Sstevel@tonic-gate 		    gettext("POOL: 'old_cpu_list' not found in nvlist: %s\n"),
2667c478bd9Sstevel@tonic-gate 		    strerror(error));
2677c478bd9Sstevel@tonic-gate 		error = RCM_FAILURE;
2687c478bd9Sstevel@tonic-gate 		goto out;
2697c478bd9Sstevel@tonic-gate 	}
2707c478bd9Sstevel@tonic-gate 	if ((int32_t)nelem != old_total) {
2717c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
2727c478bd9Sstevel@tonic-gate 		    gettext("POOL: 'old_cpu_list' size mismatch: %1$d vs "
2737c478bd9Sstevel@tonic-gate 		    "%2$d\n"), nelem, old_total);
2747c478bd9Sstevel@tonic-gate 		error = RCM_FAILURE;
2757c478bd9Sstevel@tonic-gate 		goto out;
2767c478bd9Sstevel@tonic-gate 	}
2777c478bd9Sstevel@tonic-gate 	if ((error = nvlist_lookup_int32_array(nvl, "new_cpu_list",
278*5ad42b1bSSurya Prakki 	    &new_cpu_list, &nelem)) != 0) {
2797c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
2807c478bd9Sstevel@tonic-gate 		    gettext("POOL: 'new_cpu_list' not found in nvlist: %s\n"),
2817c478bd9Sstevel@tonic-gate 		    strerror(error));
2827c478bd9Sstevel@tonic-gate 		error = RCM_FAILURE;
2837c478bd9Sstevel@tonic-gate 		goto out;
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 	if (nelem != new_total) {
2867c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
2877c478bd9Sstevel@tonic-gate 		    gettext("POOL: 'new_cpu_list' size mismatch: %1$d vs "
2887c478bd9Sstevel@tonic-gate 		    "%2$d\n"), nelem, new_total);
2897c478bd9Sstevel@tonic-gate 		error = RCM_FAILURE;
2907c478bd9Sstevel@tonic-gate 		goto out;
2917c478bd9Sstevel@tonic-gate 	}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	for (i = 0, removed_total = 0; i < old_total; i++) {
2947c478bd9Sstevel@tonic-gate 		for (j = 0; j < new_total; j++)
2957c478bd9Sstevel@tonic-gate 			if (old_cpu_list[i] == new_cpu_list[j])
2967c478bd9Sstevel@tonic-gate 				break;
2977c478bd9Sstevel@tonic-gate 		if (j == new_total) /* not found in new_cpu_list */
2987c478bd9Sstevel@tonic-gate 			removed_list[removed_total++] = old_cpu_list[i];
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 	removed_list[removed_total] = -1;
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	if (removed_total != (old_total - new_total)) {
3037c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
3047c478bd9Sstevel@tonic-gate 		    gettext("POOL: error finding removed cpu list\n"));
3057c478bd9Sstevel@tonic-gate 		error = RCM_FAILURE;
3067c478bd9Sstevel@tonic-gate 		goto out;
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 	if ((pvals[0] = pool_value_alloc()) == NULL) {
3097c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, gettext("POOL: pool_value_alloc"
3107c478bd9Sstevel@tonic-gate 		    " failed: %s\n"), strerror(errno));
3117c478bd9Sstevel@tonic-gate 		error = RCM_FAILURE;
3127c478bd9Sstevel@tonic-gate 		goto out;
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 	/*
3157c478bd9Sstevel@tonic-gate 	 * Look for resources with "'type' = 'pset'"
3167c478bd9Sstevel@tonic-gate 	 */
317*5ad42b1bSSurya Prakki 	(void) pool_value_set_name(pvals[0], "type");
318*5ad42b1bSSurya Prakki 	(void) pool_value_set_string(pvals[0], "pset");
3197c478bd9Sstevel@tonic-gate 	if ((res = pool_query_resources(conf, &nelem, pvals)) == NULL) {
3207c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
3217c478bd9Sstevel@tonic-gate 		    gettext("POOL: No psets found in configuration\n"));
3227c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
3237c478bd9Sstevel@tonic-gate 		error =	 RCM_FAILURE;
3247c478bd9Sstevel@tonic-gate 		goto out;
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 	pool_value_free(pvals[0]);
3277c478bd9Sstevel@tonic-gate 	for (i = 0; res[i] != NULL; i++)
3287c478bd9Sstevel@tonic-gate 		/*
3297c478bd9Sstevel@tonic-gate 		 * Ask each pset if removing these cpus would cause it to go
3307c478bd9Sstevel@tonic-gate 		 * below it's minimum value.
3317c478bd9Sstevel@tonic-gate 		 */
3327c478bd9Sstevel@tonic-gate 		if (pool_check_pset(conf, res[i], removed_list, errorp) < 0) {
3337c478bd9Sstevel@tonic-gate 			error = RCM_FAILURE;
3347c478bd9Sstevel@tonic-gate 			break;
3357c478bd9Sstevel@tonic-gate 		}
3367c478bd9Sstevel@tonic-gate 	free(res);
3377c478bd9Sstevel@tonic-gate out:
3387c478bd9Sstevel@tonic-gate 	if (removed_list)
3397c478bd9Sstevel@tonic-gate 		free(removed_list);
3407c478bd9Sstevel@tonic-gate 	if (conf) {
3417c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
3427c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
3437c478bd9Sstevel@tonic-gate 	}
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	/*
3467c478bd9Sstevel@tonic-gate 	 * Set the error string if not already set.
3477c478bd9Sstevel@tonic-gate 	 */
3487c478bd9Sstevel@tonic-gate 	if (error != RCM_SUCCESS && *errorp == NULL)
3497c478bd9Sstevel@tonic-gate 		*errorp = strdup(generic_error);
3507c478bd9Sstevel@tonic-gate 	return (error);
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate /*
3547c478bd9Sstevel@tonic-gate  * Returns RCM_SUCCESS in a number of error cases, since RCM_FAILURE would
3557c478bd9Sstevel@tonic-gate  * mean that the capacity change would be disallowed by this module,
3567c478bd9Sstevel@tonic-gate  * which is not what we mean.
3577c478bd9Sstevel@tonic-gate  */
3587c478bd9Sstevel@tonic-gate static int
pool_request_capacity_change(rcm_handle_t * hdl,char * rsrcname,id_t id,uint_t flags,nvlist_t * nvlist,char ** errorp,rcm_info_t ** dependent_info)3597c478bd9Sstevel@tonic-gate pool_request_capacity_change(rcm_handle_t *hdl, char *rsrcname, id_t id,
3607c478bd9Sstevel@tonic-gate     uint_t flags, nvlist_t *nvlist, char **errorp, rcm_info_t **dependent_info)
3617c478bd9Sstevel@tonic-gate {
3627c478bd9Sstevel@tonic-gate 	int i;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	*errorp = NULL;
3657c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1,
3667c478bd9Sstevel@tonic-gate 	    "POOL: requesting capacity change for: %s (flag: %d)\n",
3677c478bd9Sstevel@tonic-gate 	    rsrcname, flags);
3687c478bd9Sstevel@tonic-gate 	if (flags & RCM_FORCE) {
3697c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_TRACE1,
3707c478bd9Sstevel@tonic-gate 		    "POOL: Allowing forced operation to pass through...\n");
3717c478bd9Sstevel@tonic-gate 		return (RCM_SUCCESS);
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	for (i = 0; registrations[i].rsrc != NULL; i++) {
3747c478bd9Sstevel@tonic-gate 		if (strcmp(rsrcname, registrations[i].rsrc) == 0) {
3757c478bd9Sstevel@tonic-gate 			return ((*registrations[i].capacity_change_cb)(nvlist,
3767c478bd9Sstevel@tonic-gate 			    errorp));
3777c478bd9Sstevel@tonic-gate 		}
3787c478bd9Sstevel@tonic-gate 	}
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate static int
pool_notify_capacity_change(rcm_handle_t * hdl,char * rsrcname,id_t id,uint_t flags,nvlist_t * nvlist,char ** info,rcm_info_t ** dependent_info)3847c478bd9Sstevel@tonic-gate pool_notify_capacity_change(rcm_handle_t *hdl, char *rsrcname, id_t id,
3857c478bd9Sstevel@tonic-gate     uint_t flags, nvlist_t *nvlist, char **info, rcm_info_t **dependent_info)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1,
3887c478bd9Sstevel@tonic-gate 	    "POOL: notifying capacity change for: %s (flags: %d)\n",
3897c478bd9Sstevel@tonic-gate 	    rsrcname, flags);
3907c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate static int
pool_register(rcm_handle_t * hdl)3947c478bd9Sstevel@tonic-gate pool_register(rcm_handle_t *hdl)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate 	int i;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "Registering Pools RCM module\n");
3997c478bd9Sstevel@tonic-gate 	if (registered)
4007c478bd9Sstevel@tonic-gate 		return (RCM_SUCCESS);
4017c478bd9Sstevel@tonic-gate 	registered++;
4027c478bd9Sstevel@tonic-gate 	for (i = 0; registrations[i].rsrc != NULL; i++) {
4037c478bd9Sstevel@tonic-gate 		if (rcm_register_capacity(hdl, (char *)registrations[i].rsrc,
404*5ad42b1bSSurya Prakki 		    0, NULL) != RCM_SUCCESS) {
405*5ad42b1bSSurya Prakki 			rcm_log_message(RCM_ERROR,
406*5ad42b1bSSurya Prakki 			    gettext("POOL: failed to register capacity "
407*5ad42b1bSSurya Prakki 			    "change for '%s'\n"),
408*5ad42b1bSSurya Prakki 			    registrations[i].rsrc);
409*5ad42b1bSSurya Prakki 		}
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate static int
pool_unregister(rcm_handle_t * hdl)4157c478bd9Sstevel@tonic-gate pool_unregister(rcm_handle_t *hdl)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate 	int i;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "Pools RCM un-registered\n");
4207c478bd9Sstevel@tonic-gate 	if (registered) {
4217c478bd9Sstevel@tonic-gate 		registered--;
4227c478bd9Sstevel@tonic-gate 		for (i = 0; registrations[i].rsrc != NULL; i++)
4237c478bd9Sstevel@tonic-gate 			if (rcm_unregister_capacity(hdl,
4247c478bd9Sstevel@tonic-gate 			    (char *)registrations[i].rsrc, 0) != RCM_SUCCESS) {
4257c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_ERROR,
4267c478bd9Sstevel@tonic-gate 				    gettext("POOL: unregister capacity failed "
4277c478bd9Sstevel@tonic-gate 				    "for '%s'\n"), registrations[i].rsrc);
4287c478bd9Sstevel@tonic-gate 			}
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate static int
pool_get_info(rcm_handle_t * hdl,char * rsrcname,id_t pid,uint_t flag,char ** infop,char ** errorp,nvlist_t * props,rcm_info_t ** dependent_info)4347c478bd9Sstevel@tonic-gate pool_get_info(rcm_handle_t *hdl, char *rsrcname, id_t pid, uint_t flag,
4357c478bd9Sstevel@tonic-gate     char **infop, char **errorp, nvlist_t *props, rcm_info_t **dependent_info)
4367c478bd9Sstevel@tonic-gate {
4377c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1, "POOL: RCM get info: '%s'\n", rsrcname);
4387c478bd9Sstevel@tonic-gate 	if ((*infop = strdup(gettext("POOL: In use by pool(4) subsystem")))
4397c478bd9Sstevel@tonic-gate 	    == NULL) {
4407c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, gettext("POOL: get info(%s) malloc "
4417c478bd9Sstevel@tonic-gate 		    "failure\n"), rsrcname);
4427c478bd9Sstevel@tonic-gate 		*infop = NULL;
4437c478bd9Sstevel@tonic-gate 		*errorp = NULL;
4447c478bd9Sstevel@tonic-gate 		return (RCM_FAILURE);
4457c478bd9Sstevel@tonic-gate 	}
4467c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate static int
pool_request_suspend(rcm_handle_t * hdl,char * rsrcname,id_t id,timespec_t * time,uint_t flags,char ** reason,rcm_info_t ** dependent_info)4517c478bd9Sstevel@tonic-gate pool_request_suspend(rcm_handle_t *hdl, char *rsrcname,
4527c478bd9Sstevel@tonic-gate     id_t id, timespec_t *time, uint_t flags, char **reason,
4537c478bd9Sstevel@tonic-gate     rcm_info_t **dependent_info)
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1,
4567c478bd9Sstevel@tonic-gate 	    "POOL: requesting suspend for: %s\n", rsrcname);
4577c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate static int
pool_notify_resume(rcm_handle_t * hdl,char * rsrcname,id_t pid,uint_t flags,char ** reason,rcm_info_t ** dependent_info)4617c478bd9Sstevel@tonic-gate pool_notify_resume(rcm_handle_t *hdl, char *rsrcname,
4627c478bd9Sstevel@tonic-gate     id_t pid, uint_t flags, char **reason, rcm_info_t **dependent_info)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1,
4657c478bd9Sstevel@tonic-gate 	    "POOL: notifying resume of: %s\n", rsrcname);
4667c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate static int
pool_request_offline(rcm_handle_t * hdl,char * rsrcname,id_t pid,uint_t flag,char ** reason,rcm_info_t ** dependent_info)4707c478bd9Sstevel@tonic-gate pool_request_offline(rcm_handle_t *hdl, char *rsrcname, id_t pid, uint_t flag,
4717c478bd9Sstevel@tonic-gate     char **reason, rcm_info_t **dependent_info)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1,
4747c478bd9Sstevel@tonic-gate 	    "POOL: requesting offline for: %s\n", rsrcname);
4757c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate static int
pool_notify_online(rcm_handle_t * hdl,char * rsrcname,id_t pid,uint_t flags,char ** reason,rcm_info_t ** dependent_info)4797c478bd9Sstevel@tonic-gate pool_notify_online(rcm_handle_t *hdl, char *rsrcname, id_t pid, uint_t flags,
4807c478bd9Sstevel@tonic-gate     char **reason, rcm_info_t **dependent_info)
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1,
4837c478bd9Sstevel@tonic-gate 	    "POOL: notifying online for: %s\n", rsrcname);
4847c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate static int
pool_notify_remove(rcm_handle_t * hdl,char * rsrcname,id_t pid,uint_t flag,char ** reason,rcm_info_t ** dependent_info)4877c478bd9Sstevel@tonic-gate pool_notify_remove(rcm_handle_t *hdl, char *rsrcname, id_t pid,
4887c478bd9Sstevel@tonic-gate     uint_t flag, char **reason, rcm_info_t **dependent_info)
4897c478bd9Sstevel@tonic-gate {
4907c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_TRACE1,
4917c478bd9Sstevel@tonic-gate 	    "POOL: notifying removal of: %s\n", rsrcname);
4927c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
4937c478bd9Sstevel@tonic-gate }
494