Example #1
0
/*
 * Unpack a device path/nvlist pair to internal data list format.
 * Used to decode the nvlist format into the internal representation
 * when reading /etc/devices/devname_cache.
 * Note that the expiration counts are optional, for compatibility
 * with earlier instances of the cache.  If not present, the
 * expire counts are initialized to defaults.
 */
static int
sdev_ncache_unpack_nvlist(nvf_handle_t fd, nvlist_t *nvl, char *name)
{
	nvp_devname_t *np;
	char	**strs;
	int	*cnts;
	uint_t	nstrs, ncnts;
	int	rval, i;

	ASSERT(fd == sdevfd_handle);
	ASSERT(RW_WRITE_HELD(nvf_lock(fd)));

	/* name of the sublist must match what we created */
	if (strcmp(name, DP_DEVNAME_ID) != 0) {
		return (-1);
	}

	np = kmem_zalloc(sizeof (nvp_devname_t), KM_SLEEP);

	rval = nvlist_lookup_string_array(nvl,
	    DP_DEVNAME_NCACHE_ID, &strs, &nstrs);
	if (rval) {
		kmem_free(np, sizeof (nvp_devname_t));
		return (-1);
	}

	np->nvp_npaths = nstrs;
	np->nvp_paths = kmem_zalloc(nstrs * sizeof (char *), KM_SLEEP);
	for (i = 0; i < nstrs; i++) {
		np->nvp_paths[i] = i_ddi_strdup(strs[i], KM_SLEEP);
	}
	np->nvp_expirecnts = kmem_zalloc(nstrs * sizeof (int), KM_SLEEP);
	for (i = 0; i < nstrs; i++) {
		np->nvp_expirecnts[i] = sdev_nc_expirecnt;
	}

	rval = nvlist_lookup_int32_array(nvl,
	    DP_DEVNAME_NC_EXPIRECNT_ID, &cnts, &ncnts);
	if (rval == 0) {
		ASSERT(ncnts == nstrs);
		ncnts = min(ncnts, nstrs);
		for (i = 0; i < nstrs; i++) {
			np->nvp_expirecnts[i] = cnts[i];
		}
	}

	list_insert_tail(nvf_list(sdevfd_handle), np);

	return (0);
}
Example #2
0
/*
 * Convert a device path/nvlist pair to an nvp_list_t
 * Used to parse the nvlist format when reading
 * /etc/devices/devname_cache
 */
static nvp_list_t *
sdev_nvl2nvp(nvlist_t *nvl, char *name)
{
	nvp_devname_t *np;
	char	**strs;
	int	*cnts;
	uint_t	nstrs, ncnts;
	int	rval, i;

	/* name of the sublist must match what we created */
	if (strcmp(name, DP_DEVNAME_ID) != 0) {
		return (NULL);
	}

	np = kmem_zalloc(sizeof (nvp_devname_t), KM_SLEEP);

	rval = nvlist_lookup_string_array(nvl,
	    DP_DEVNAME_NCACHE_ID, &strs, &nstrs);
	if (rval) {
		kmem_free(np, sizeof (nvp_devname_t));
		return (NULL);
	}

	np->nvp_npaths = nstrs;
	np->nvp_paths = kmem_zalloc(nstrs * sizeof (char *), KM_SLEEP);
	for (i = 0; i < nstrs; i++) {
		np->nvp_paths[i] = i_ddi_strdup(strs[i], KM_SLEEP);
	}
	np->nvp_expirecnts = kmem_zalloc(nstrs * sizeof (int), KM_SLEEP);
	for (i = 0; i < nstrs; i++) {
		np->nvp_expirecnts[i] = 4; /* XXX sdev_nc_expirecnt */
	}

	rval = nvlist_lookup_int32_array(nvl,
	    DP_DEVNAME_NC_EXPIRECNT_ID, &cnts, &ncnts);
	if (rval == 0) {
		ASSERT(ncnts == nstrs);
		ncnts = max(ncnts, nstrs);
		for (i = 0; i < nstrs; i++) {
			np->nvp_expirecnts[i] = cnts[i];
		}
	}

	return (NVPLIST(np));
}
Example #3
0
/* Calls the client callback function, if one is registered */
static void
notifyClient(sysevent_t *ev)
{
	nvlist_t *attr_list = NULL;

	uint64_t *val = NULL;
	int32_t  *instance = NULL;
	int32_t  *major = NULL;

	int valAllocated = 0;

	uint_t nelem = 0;

	int i = 0;
	int eventType = 0;
	int index = -1;

	void *pCallerData = NULL;

	char subClassName[256];

	MP_BOOL becomingVisible = MP_FALSE;

	MP_OID_LIST *oidList = NULL;


	log(LOG_INFO, "notifyClient()", "- enter");


	(void) strncpy(subClassName, sysevent_get_subclass_name(ev), 256);

	if (strstr(subClassName, "change")) {

		eventType = PROP_CHANGE;

		log(LOG_INFO, "notifyClient()", "- got a change event");
		log(LOG_INFO, "notifyClient()", ": [%s]",
		    subClassName);

		if (strncmp(subClassName, ESC_SUN_MP_PLUGIN_CHANGE, 255)
		    == 0) {

			index = MP_OBJECT_TYPE_PLUGIN;

		} else if (strncmp(subClassName, ESC_SUN_MP_LU_CHANGE, 255)
		    == 0) {

			index = MP_OBJECT_TYPE_MULTIPATH_LU;

		} else if (strncmp(subClassName, ESC_SUN_MP_PATH_CHANGE, 255)
		    == 0) {

			index = MP_OBJECT_TYPE_PATH_LU;

		} else if (strncmp(subClassName, ESC_SUN_MP_INIT_PORT_CHANGE,
		    255) == 0) {

			index = MP_OBJECT_TYPE_INITIATOR_PORT;

		} else if (strncmp(subClassName, ESC_SUN_MP_TPG_CHANGE, 255)
		    == 0) {

			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;

		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_CHANGE,
		    255) == 0) {

			index = MP_OBJECT_TYPE_TARGET_PORT;

		} else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_CHANGE,
		    255) == 0) {

			index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
		}

	} else if ((strstr(subClassName, "add")) ||
	    (strstr(subClassName, "initiator_register"))) {

		eventType = VISA_CHANGE;
		becomingVisible = MP_TRUE;

		log(LOG_INFO, "notifyClient()", "- got a visibility"
		    " add event");
		log(LOG_INFO, "notifyClient()", ": [%s]",
		    subClassName);

		if (strncmp(subClassName, ESC_SUN_MP_LU_ADD, 255) == 0) {

			index = MP_OBJECT_TYPE_MULTIPATH_LU;

		} else if (strncmp(subClassName, ESC_SUN_MP_PATH_ADD, 255)
		    == 0) {

			index = MP_OBJECT_TYPE_PATH_LU;

		} else if (strncmp(subClassName, ESC_DDI_INITIATOR_REGISTER,
		    244) == 0) {

			index = MP_OBJECT_TYPE_INITIATOR_PORT;

		} else if (strncmp(subClassName, ESC_SUN_MP_TPG_ADD,
		    255) == 0) {

			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;

		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_ADD,
		    255) == 0) {

			index = MP_OBJECT_TYPE_TARGET_PORT;

		} else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_ADD, 255)
		    == 0) {

			index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
		}


	} else if ((strstr(subClassName, "remove")) ||
	    (strstr(subClassName, "initiator_unregister"))) {

		eventType = VISA_CHANGE;
		becomingVisible = MP_FALSE;

		log(LOG_INFO, "notifyClient()", "- got a visibility"
		    " remove event");
		log(LOG_INFO, "notifyClient()", ": [%s]",
		    subClassName);

		if (strncmp(subClassName, ESC_SUN_MP_LU_REMOVE, 255) == 0) {

			index = MP_OBJECT_TYPE_MULTIPATH_LU;

		} else if (strncmp(subClassName, ESC_SUN_MP_PATH_REMOVE, 255)
		    == 0) {

			index = MP_OBJECT_TYPE_PATH_LU;

		} else if (strncmp(subClassName, ESC_DDI_INITIATOR_UNREGISTER,
		    255) == 0) {

			index = MP_OBJECT_TYPE_INITIATOR_PORT;

		} else if (strncmp(subClassName, ESC_SUN_MP_TPG_REMOVE, 255)
		    == 0) {

			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;

		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_REMOVE,
		    255) == 0) {

			index = MP_OBJECT_TYPE_TARGET_PORT;

		} else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_REMOVE,
		    255) == 0) {

			index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
		}


	} else {
		log(LOG_INFO, "notifyClient()", "- got an unsupported event");
		return;
	}

	if (index < 0) {

		log(LOG_INFO, "notifyClient()", "- index is less than zero");
		return;
	}

	if (eventType == VISA_CHANGE) {

		(void) pthread_mutex_lock(&g_visa_mutex);

		if (NULL == g_Visibility_Callback_List[index].pClientFn) {

			log(LOG_INFO, "notifyClient()",
			    "- no visibility change callback to notify");

			(void) pthread_mutex_unlock(&g_visa_mutex);

			return;
		}

		(void) pthread_mutex_unlock(&g_visa_mutex);
	}

	if (eventType == PROP_CHANGE) {

		(void) pthread_mutex_lock(&g_prop_mutex);

		if (NULL == g_Property_Callback_List[index].pClientFn) {

			log(LOG_INFO, "notifyClient()",
			    "- no property change callback to notify");

			(void) pthread_mutex_unlock(&g_prop_mutex);

			return;
		}

		(void) pthread_mutex_unlock(&g_prop_mutex);
	}

	(void) sysevent_get_attr_list(ev, &attr_list);
	if (NULL != attr_list) {

		if ((VISA_CHANGE == eventType) &&
		    (MP_OBJECT_TYPE_PLUGIN == index)) {

			val = (uint64_t *)malloc(sizeof (uint64_t));
			valAllocated = 1;

			/*
			 * We have no well-defined way to determine our OSN.
			 * Currently the common library uses 0 as OSN for every
			 * plugin, so just use 0. If the OSN assigned by the
			 * common library changed, this code would have to be
			 * updated.
			 */
			*val = 0;
			nelem = 1;

		} else if ((VISA_CHANGE == eventType) &&
		    (MP_OBJECT_TYPE_INITIATOR_PORT == index)) {

			(void) nvlist_lookup_int32_array(attr_list,
			    DDI_INSTANCE, &instance, &nelem);

			log(LOG_INFO, "notifyClient()",
			    "- event (PHCI_INSTANCE) has [%d] elements",
			    nelem);

			(void) nvlist_lookup_int32_array(attr_list,
			    DDI_DRIVER_MAJOR, &major, &nelem);

			log(LOG_INFO, "notifyClient()",
			    "- event (PHCI_DRIVER_MAJOR) has [%d] elements",
			    nelem);

			if ((NULL != instance) & (NULL != major)) {

				val = (uint64_t *)malloc(sizeof (uint64_t));

				valAllocated = 1;

				*val = 0;
				*val = MP_STORE_INST_TO_ID(*instance, *val);
				*val = MP_STORE_MAJOR_TO_ID(*major, *val);

				nelem = 1;

			} else {

				nelem = 0;
			}

		} else {

			(void) nvlist_lookup_uint64_array(attr_list, OIDLIST,
			    &val, &nelem);

			log(LOG_INFO, "notifyClient()",
			    "- event has [%d] elements",
			    nelem);
		}

		if (nelem > 0) {

			for (i = 0; i < nelem; i++) {

				log(LOG_INFO, "notifyClient()",
				    "- event [%d] = %llx",
				    i, val[i]);
			}

			oidList = createOidList(nelem);
			if (NULL == oidList) {

				log(LOG_INFO, "notifyClient()",
				    "- unable to create MP_OID_LIST");

				log(LOG_INFO, "notifyClient()",
				    "- error exit");

				nvlist_free(attr_list);

				return;
			}

			oidList->oidCount = nelem;

			for (i = 0; i < nelem; i++) {

				oidList->oids[i].objectType = index;
				oidList->oids[i].ownerId = g_pluginOwnerID;
				oidList->oids[i].objectSequenceNumber = val[i];
			}

			if (valAllocated) {

				free(val);
			}

			for (i = 0; i < oidList->oidCount; i++) {

				log(LOG_INFO, "notifyClient()",
				    "oidList->oids[%d].objectType"
				    "           = %d",
				    i, oidList->oids[i].objectType);
				log(LOG_INFO, "notifyClient()",
				    "oidList->oids[%d].ownerId"
				    "              = %d",
				    i, oidList->oids[i].ownerId);
				log(LOG_INFO, "notifyClient()",
				    "oidList->oids[%d].objectSequenceNumber"
				    " = %llx",
				    i, oidList->oids[i].objectSequenceNumber);
			}

			if (eventType == PROP_CHANGE) {

				(void) pthread_mutex_lock(&g_prop_mutex);

				pCallerData = g_Property_Callback_List[index].
				    pCallerData;

				(g_Property_Callback_List[index].pClientFn)
				    (oidList, pCallerData);

				(void) pthread_mutex_unlock(&g_prop_mutex);

			} else if (eventType == VISA_CHANGE) {

				(void) pthread_mutex_lock(&g_visa_mutex);

				pCallerData = g_Visibility_Callback_List[index].
				    pCallerData;

				(g_Visibility_Callback_List[index].pClientFn)
				    (becomingVisible, oidList, pCallerData);

				(void) pthread_mutex_unlock(&g_visa_mutex);

			}
		}

		nvlist_free(attr_list);
	}


	log(LOG_INFO, "notifyClient()", "- exit");
}
Example #4
0
static int
prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val,
    topo_type_t type, uint_t *nelems, int *err)
{
	int i, j, ret = 0;
	topo_hdl_t *thp = node->tn_hdl;
	topo_propval_t *pv;

	topo_node_lock(node);
	if ((pv = prop_get(node, pgname, pname, NULL, err))
	    == NULL)
		return (get_properror(node, err, *err));

	if (pv->tp_type != type)
		return (get_properror(node, err, ETOPO_PROP_TYPE));

	switch (type) {
		case TOPO_TYPE_INT32:
			ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL,
			    (int32_t *)val);
			break;
		case TOPO_TYPE_UINT32:
			ret = nvlist_lookup_uint32(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (uint32_t *)val);
			break;
		case TOPO_TYPE_INT64:
			ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL,
			    (int64_t *)val);
			break;
		case TOPO_TYPE_UINT64:
			ret = nvlist_lookup_uint64(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (uint64_t *)val);
			break;
		case TOPO_TYPE_DOUBLE:
			ret = nvlist_lookup_double(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (double *)val);
			break;
		case TOPO_TYPE_STRING: {
			char *str;

			ret = nvlist_lookup_string(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &str);
			if (ret == 0) {
				char *s2;
				if ((s2 = topo_hdl_strdup(thp, str)) == NULL)
					ret = -1;
				else
					*(char **)val = s2;
			}
			break;
		}
		case TOPO_TYPE_FMRI: {
			nvlist_t *nvl;

			ret = nvlist_lookup_nvlist(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &nvl);
			if (ret == 0)
				ret = topo_hdl_nvdup(thp, nvl,
				    (nvlist_t **)val);
			break;
		}
		case TOPO_TYPE_INT32_ARRAY: {
			int32_t *a1, *a2;

			if ((ret = nvlist_lookup_int32_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(int32_t **)val = a1;
			break;
		}
		case TOPO_TYPE_UINT32_ARRAY: {
			uint32_t *a1, *a2;

			if ((ret = nvlist_lookup_uint32_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(uint32_t **)val = a1;
			break;
		}
		case TOPO_TYPE_INT64_ARRAY: {
			int64_t *a1, *a2;

			if ((ret = nvlist_lookup_int64_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(int64_t **)val = a1;
			break;
		}
		case TOPO_TYPE_UINT64_ARRAY: {
			uint64_t *a1, *a2;

			if ((ret = nvlist_lookup_uint64_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(uint64_t **)val = a1;
			break;
		}
		case TOPO_TYPE_STRING_ARRAY: {
			char **a1, **a2;

			if ((ret = nvlist_lookup_string_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (char *) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i) {
				if ((a1[i] = topo_hdl_strdup(thp, a2[i]))
				    == NULL) {
					for (j = 0; j < i; ++j)
						topo_hdl_free(thp, a1[j],
						    sizeof (char *));
					topo_hdl_free(thp, a1,
					    sizeof (char *) * *nelems);
					break;
				}
			}
			*(char ***)val = a1;
			break;
		}
		case TOPO_TYPE_FMRI_ARRAY: {
			nvlist_t **a1, **a2;

			if ((ret = nvlist_lookup_nvlist_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i) {
				if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) {
					for (j = 0; j < i; ++j)
						nvlist_free(a1[j]);
					topo_hdl_free(thp, a1,
					    sizeof (nvlist_t *) * *nelems);
					break;
				}
			}
			*(nvlist_t ***)val = a1;
			break;
		}
		default:
			ret = ETOPO_PROP_NOENT;
	}

	if (ret != 0)
		if (ret == ENOENT)
			return (get_properror(node, err, ETOPO_PROP_NOENT));
		else if (ret < ETOPO_UNKNOWN)
			return (get_properror(node, err, ETOPO_PROP_NVL));
		else
			return (get_properror(node, err, ret));

	topo_node_unlock(node);
	return (0);
}
Example #5
0
/*
 * pset_validate_remove()
 * 	Check to see if the requested cpu removal would be acceptable.
 * 	Returns RCM_FAILURE if not.
 */
static int
pset_validate_remove(nvlist_t *nvl, char **errorp)
{
	int error = RCM_SUCCESS;
	int32_t old_total, new_total, removed_total;
	processorid_t *removed_list = NULL; /* list terminated by (-1). */
	processorid_t *old_cpu_list = NULL, *new_cpu_list = NULL;
	int i, j;
	pool_conf_t *conf;
	pool_value_t *pvals[] = { NULL, NULL };
	pool_resource_t **res = NULL;
	uint_t nelem;
	const char *generic_error = gettext("POOL: Error processing request\n");

	if ((conf = pool_conf_alloc()) == NULL)
		return (RCM_FAILURE);
	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
		rcm_log_message(RCM_TRACE1,
		    "POOL: failed to parse config file: '%s'\n",
		    pool_dynamic_location());
		pool_conf_free(conf);
		return (RCM_SUCCESS);
	}

	if ((error = nvlist_lookup_int32(nvl, "old_total", &old_total)) != 0) {
		(void) pool_conf_close(conf);
		pool_conf_free(conf);
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: unable to find 'old_total' in nvlist: %s\n"),
		    strerror(error));
		*errorp = strdup(generic_error);
		return (RCM_FAILURE);
	}
	if ((error = nvlist_lookup_int32(nvl, "new_total", &new_total)) != 0) {
		(void) pool_conf_close(conf);
		pool_conf_free(conf);
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: unable to find 'new_total' in nvlist: %s\n"),
		    strerror(error));
		*errorp = strdup(generic_error);
		return (RCM_FAILURE);
	}
	if (new_total >= old_total) {
		(void) pool_conf_close(conf);
		pool_conf_free(conf);
		/*
		 * This doesn't look like a cpu removal.
		 */
		rcm_log_message(RCM_TRACE1,
		    gettext("POOL: 'old_total' (%d) is less than 'new_total' "
		    "(%d)\n"), old_total, new_total);
		return (RCM_SUCCESS);
	}
	if ((removed_list = malloc((old_total - new_total + 1) * sizeof (int)))
	    == NULL) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: malloc failed: %s\n"), strerror(errno));

		error = RCM_FAILURE;
		goto out;
	}
	if ((error = nvlist_lookup_int32_array(nvl, "old_cpu_list",
	    &old_cpu_list, &nelem)) != 0) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: 'old_cpu_list' not found in nvlist: %s\n"),
		    strerror(error));
		error = RCM_FAILURE;
		goto out;
	}
	if ((int32_t)nelem != old_total) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: 'old_cpu_list' size mismatch: %1$d vs "
		    "%2$d\n"), nelem, old_total);
		error = RCM_FAILURE;
		goto out;
	}
	if ((error = nvlist_lookup_int32_array(nvl, "new_cpu_list",
	    &new_cpu_list, &nelem)) != 0) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: 'new_cpu_list' not found in nvlist: %s\n"),
		    strerror(error));
		error = RCM_FAILURE;
		goto out;
	}
	if (nelem != new_total) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: 'new_cpu_list' size mismatch: %1$d vs "
		    "%2$d\n"), nelem, new_total);
		error = RCM_FAILURE;
		goto out;
	}

	for (i = 0, removed_total = 0; i < old_total; i++) {
		for (j = 0; j < new_total; j++)
			if (old_cpu_list[i] == new_cpu_list[j])
				break;
		if (j == new_total) /* not found in new_cpu_list */
			removed_list[removed_total++] = old_cpu_list[i];
	}
	removed_list[removed_total] = -1;

	if (removed_total != (old_total - new_total)) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: error finding removed cpu list\n"));
		error = RCM_FAILURE;
		goto out;
	}
	if ((pvals[0] = pool_value_alloc()) == NULL) {
		rcm_log_message(RCM_ERROR, gettext("POOL: pool_value_alloc"
		    " failed: %s\n"), strerror(errno));
		error = RCM_FAILURE;
		goto out;
	}
	/*
	 * Look for resources with "'type' = 'pset'"
	 */
	(void) pool_value_set_name(pvals[0], "type");
	(void) pool_value_set_string(pvals[0], "pset");
	if ((res = pool_query_resources(conf, &nelem, pvals)) == NULL) {
		rcm_log_message(RCM_ERROR,
		    gettext("POOL: No psets found in configuration\n"));
		pool_value_free(pvals[0]);
		error =	 RCM_FAILURE;
		goto out;
	}
	pool_value_free(pvals[0]);
	for (i = 0; res[i] != NULL; i++)
		/*
		 * Ask each pset if removing these cpus would cause it to go
		 * below it's minimum value.
		 */
		if (pool_check_pset(conf, res[i], removed_list, errorp) < 0) {
			error = RCM_FAILURE;
			break;
		}
	free(res);
out:
	if (removed_list)
		free(removed_list);
	if (conf) {
		(void) pool_conf_close(conf);
		pool_conf_free(conf);
	}

	/*
	 * Set the error string if not already set.
	 */
	if (error != RCM_SUCCESS && *errorp == NULL)
		*errorp = strdup(generic_error);
	return (error);
}
Example #6
0
static int
tokenmt_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
{
	nvlist_t *nvlp;
	int err = 0, err2;
	uint8_t config_type;
	char *next_action_name;
	ipp_action_id_t next_action;
	uint32_t rate, cbs, pbs;
	tokenmt_cfg_t *cfg_parms, *old_cfg;
	tokenmt_data_t *tokenmt_data;
	uint32_t bstats, mode;
	int32_t *colour_tbl;
	uint_t nelem = 64;

	nvlp = *nvlpp;
	*nvlpp = NULL;		/* nvlist should be NULL when this returns */

	if ((err = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type))
	    != 0) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_modify_action: invalid configuration "\
		    "type"));
		return (err);
	}

	if (config_type != IPP_SET) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_modify_action: invalid configuration "\
		    "type %d", config_type));
		return (EINVAL);
	}

	tokenmt_data = (tokenmt_data_t *)ipp_action_get_ptr(aid);
	old_cfg = tokenmt_data->cfg_parms;

	cfg_parms = kmem_zalloc(TOKENMT_CFG_SZ, KM_NOSLEEP);
	if (cfg_parms == NULL) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_modify_action: memory allocation "\
		    "failure\n"));
		return (ENOMEM);
	}

	/* Just copy all and change as needed */
	bcopy(old_cfg, cfg_parms, TOKENMT_CFG_SZ);

	/* parse red action name, if present */
	if ((err = nvlist_lookup_string(nvlp, TOKENMT_RED_ACTION_NAME,
	    &next_action_name)) == 0) {
		/* Get action id */
		if ((next_action = ipp_action_lookup(next_action_name))
		    == IPP_ACTION_INVAL) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: next_action "\
			    "invalid"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
		cfg_parms->red_action = next_action;
	}

	/* parse yellow action name, if present */
	if ((err = nvlist_lookup_string(nvlp, TOKENMT_YELLOW_ACTION_NAME,
	    &next_action_name)) == 0) {
		/* Get action id */
		if ((next_action = ipp_action_lookup(next_action_name))
		    == IPP_ACTION_INVAL) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: next_action "\
			    "invalid"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
		cfg_parms->yellow_action = next_action;
	} else {
		cfg_parms->yellow_action = TOKENMT_NO_ACTION;
	}

	/* parse green action name, if present */
	if ((err = nvlist_lookup_string(nvlp, TOKENMT_GREEN_ACTION_NAME,
	    &next_action_name)) == 0) {
		/* Get action id */
		if ((next_action = ipp_action_lookup(next_action_name))
		    == IPP_ACTION_INVAL) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: next_action "\
			    "invalid"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
		cfg_parms->green_action = next_action;
	}

	/* parse committed rate, if present */
	if ((err = nvlist_lookup_uint32(nvlp, TOKENMT_COMMITTED_RATE, &rate))
	    == 0) {
		if (rate == 0) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: invalid "\
			    "committed rate %u\n", cfg_parms->committed_rate));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
		cfg_parms->committed_rate = rate;
	}

	/* parse committed burst, if present */
	if (nvlist_lookup_uint32(nvlp, TOKENMT_COMMITTED_BURST, &cbs) == 0) {
		cfg_parms->committed_burst = cbs;
	}


	if (nvlist_lookup_uint32(nvlp, TOKENMT_PEAK_BURST, &pbs) == 0) {
		cfg_parms->peak_burst = pbs;
	} else {
		cfg_parms->peak_burst = 0;
	}

	/* If the peak rate is not specified, then it means single rate meter */
	if (nvlist_lookup_uint32(nvlp, TOKENMT_PEAK_RATE, &rate) == 0) {
		cfg_parms->peak_rate = rate;
		if ((rate == 0) || (rate < cfg_parms->committed_rate)) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: invalid "\
			    "committed rate %u\n", cfg_parms->committed_rate));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
		cfg_parms->tokenmt_type = TRTCL_TOKENMT;
	} else {
		cfg_parms->peak_rate = 0;
		cfg_parms->tokenmt_type = SRTCL_TOKENMT;
	}

	if (cfg_parms->yellow_action == TOKENMT_NO_ACTION) {
		if ((cfg_parms->peak_burst != 0) ||
		    (cfg_parms->tokenmt_type == TRTCL_TOKENMT)) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: yellow action "\
			    "missing\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
	} else {
		if ((cfg_parms->tokenmt_type != TRTCL_TOKENMT) &&
		    (cfg_parms->peak_burst == 0)) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: peak "\
			    "burst/rate missing\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
	}

	/* Validate the committed and peak burst size */
	if (cfg_parms->tokenmt_type == SRTCL_TOKENMT) {
		if ((cfg_parms->committed_burst == 0) &&
		    (cfg_parms->peak_burst == 0)) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: at least one "\
			    "burst size must be non-zero\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
	} else {	/* TRTCL_TOKENMT */
		if ((cfg_parms->committed_burst == 0) ||
		    (cfg_parms->peak_burst == 0)) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_modify_action: both the "\
			    "burst sizes must be non-zero\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
	}

	/* parse mode */
	if (nvlist_lookup_uint32(nvlp, TOKENMT_COLOUR_AWARE, &mode) == 0) {
		cfg_parms->colour_aware = (mode == 0) ? B_FALSE : B_TRUE;
	} else {
		cfg_parms->colour_aware = B_FALSE;
	}

	if (cfg_parms->colour_aware) {
		if (nvlist_lookup_int32_array(nvlp, TOKENMT_COLOUR_MAP,
		    &colour_tbl, &nelem) == 0) {
			int count;
			for (count = 0; count < 64; count++) {
				if (colour_tbl[count] == -1)
					continue;
				cfg_parms->dscp_to_colour[count] =
				    colour_tbl[count];
			}
		} else {
			bcopy(default_dscp_to_colour, cfg_parms->dscp_to_colour,
			    sizeof (default_dscp_to_colour));
		}
	}

	/* parse stats, if present */
	if (nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats) == 0) {
		cfg_parms->stats = (bstats == 0) ? B_FALSE : B_TRUE;
		if (cfg_parms->stats && !old_cfg->stats) {
			if ((err = tokenmt_statinit(aid, tokenmt_data)) != 0) {
				nvlist_free(nvlp);
				kmem_free(cfg_parms, TOKENMT_CFG_SZ);
				return (err);
			}
		} else if (!cfg_parms->stats && old_cfg->stats) {
			ipp_stat_destroy(tokenmt_data->stats);
		}
	}

	/* Can we ref all the new actions? */
	if ((err = ipp_action_ref(aid, cfg_parms->red_action, flags)) != 0) {
		tokenmt0dbg(("tokenmt_modify_data: can't ref. red action\n"));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (err);
	}
	if ((err = ipp_action_ref(aid, cfg_parms->green_action, flags)) != 0) {
		tokenmt0dbg(("tokenmt_modify_data:can't ref. green action\n"));
		err2 = ipp_action_unref(aid, cfg_parms->red_action, flags);
		ASSERT(err2 == 0);
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (err);
	}

	if (cfg_parms->yellow_action != TOKENMT_NO_ACTION) {
		if ((err = ipp_action_ref(aid, cfg_parms->yellow_action,
		    flags)) != 0) {
			tokenmt0dbg(("tokenmt_modify_data:can't ref. yellow "\
			    "action\n"));
			err2 = ipp_action_unref(aid, cfg_parms->red_action,
			    flags);
			ASSERT(err2 == 0);
			err2 = ipp_action_unref(aid, cfg_parms->green_action,
			    flags);
			ASSERT(err2 == 0);
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (err);
		}
	}


	/* Actually modify the configuration */
	mutex_enter(&tokenmt_data->tokenmt_lock);
	tokenmt_data->cfg_parms = cfg_parms;
	mutex_exit(&tokenmt_data->tokenmt_lock);

	/* Un-ref the old actions */
	err = ipp_action_unref(aid, old_cfg->red_action, flags);
	ASSERT(err == 0);
	if (old_cfg->yellow_action != TOKENMT_NO_ACTION) {
		err = ipp_action_unref(aid, old_cfg->yellow_action, flags);
		ASSERT(err == 0);
	}
	err = ipp_action_unref(aid, old_cfg->green_action, flags);
	ASSERT(err == 0);

	/* Free the old configuration */
	kmem_free(old_cfg, TOKENMT_CFG_SZ);
	return (0);
}
Example #7
0
/* ARGSUSED */
static int
tokenmt_create_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags)
{
	nvlist_t *nvlp;
	tokenmt_data_t *tokenmt_data;
	char *next_action;
	tokenmt_cfg_t *cfg_parms;
	uint32_t mode;
	uint32_t bstats;
	int rc, rc2;
	int32_t *colour_tbl;
	uint_t nelem = 64;

	nvlp = *nvlpp;
	*nvlpp = NULL;		/* nvlist should be NULL on return */

	if ((cfg_parms = kmem_zalloc(TOKENMT_CFG_SZ, KM_NOSLEEP)) == NULL) {
		nvlist_free(nvlp);
		return (ENOMEM);
	}

	/* parse red next action name */
	if ((rc = nvlist_lookup_string(nvlp, TOKENMT_RED_ACTION_NAME,
	    &next_action)) != 0) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_create_action:invalid config, red "\
		    "action name missing\n"));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (rc);
	}
	if ((cfg_parms->red_action = ipp_action_lookup(next_action))
	    == IPP_ACTION_INVAL) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_create_action: red action invalid\n"));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (EINVAL);
	}

	/* parse yellow next action name, if present  this is Two Rate meter */
	if ((rc = nvlist_lookup_string(nvlp, TOKENMT_YELLOW_ACTION_NAME,
	    &next_action)) == 0) {
		if ((cfg_parms->yellow_action = ipp_action_lookup(next_action))
		    == IPP_ACTION_INVAL) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_create_action: yellow action "\
			    "invalid\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
	} else {
		cfg_parms->yellow_action = TOKENMT_NO_ACTION;
	}

	/* parse green next action name */
	if ((rc = nvlist_lookup_string(nvlp, TOKENMT_GREEN_ACTION_NAME,
	    &next_action)) != 0) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_create_action:invalid config, green " \
		    "action name missing\n"));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (rc);
	}
	if ((cfg_parms->green_action = ipp_action_lookup(next_action))
	    == IPP_ACTION_INVAL) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_create_action: green action invalid\n"));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (EINVAL);
	}

	/* parse committed rate  - in kilo bits / sec */
	if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_COMMITTED_RATE,
	    &cfg_parms->committed_rate)) != 0) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_create_action: invalid config, "\
		    " committed rate missing\n"));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (rc);
	}
	if (cfg_parms->committed_rate == 0) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_create_action: invalid committed rate, "\
		    "%u\n", cfg_parms->committed_rate));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (EINVAL);
	}

	/* parse committed burst in bits */
	if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_COMMITTED_BURST,
	    &cfg_parms->committed_burst)) != 0) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_create_action: invalid config, "\
		    " committed burst missing\n"));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (rc);
	}


	/*
	 * If the peak burst size is specified, make sure we have the
	 * yellow action.
	 */
	if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_PEAK_BURST,
	    &cfg_parms->peak_burst)) == 0) {
		if (cfg_parms->yellow_action == TOKENMT_NO_ACTION) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_create_action: peak burst "\
			    "specified without yellow action\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
	} else if (cfg_parms->yellow_action != TOKENMT_NO_ACTION) {
		nvlist_free(nvlp);
		tokenmt0dbg(("tokenmt_create_action: peak burst must be "\
		    "provided with yellow action\n"));
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (EINVAL);
	}

	/* Check if we have a peak_rate */
	if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_PEAK_RATE,
	    &cfg_parms->peak_rate)) == 0) {
		if (cfg_parms->yellow_action == TOKENMT_NO_ACTION) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_create_action: peak rate "\
			    "specified without yellow action\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		} else if ((cfg_parms->peak_rate == 0) ||
		    (cfg_parms->peak_rate < cfg_parms->committed_rate)) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_create_action: invalid "\
			    "peak rate, %u\n", cfg_parms->peak_rate));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
		cfg_parms->tokenmt_type = TRTCL_TOKENMT;
	} else {
		cfg_parms->tokenmt_type = SRTCL_TOKENMT;
	}

	/* Validate the committed and peak burst size */
	if (cfg_parms->tokenmt_type == SRTCL_TOKENMT) {
		if ((cfg_parms->committed_burst == 0) &&
		    (cfg_parms->peak_burst == 0)) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_create_action: at least one "\
			    "burst size must be non-zero\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
	} else {	/* TRTCL_TOKENMT */
		if ((cfg_parms->committed_burst == 0) ||
		    (cfg_parms->peak_burst == 0)) {
			nvlist_free(nvlp);
			tokenmt0dbg(("tokenmt_create_action: both the "\
			    "burst sizes must be non-zero\n"));
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			return (EINVAL);
		}
	}

	/* just copy default colour mapping */
	bcopy(default_dscp_to_colour, cfg_parms->dscp_to_colour,
	    sizeof (default_dscp_to_colour));

	/* parse mode, if present */
	if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_COLOUR_AWARE,
	    &mode)) != 0) {
		cfg_parms->colour_aware = B_FALSE;
	} else {
		cfg_parms->colour_aware = (mode == 0) ? B_FALSE : B_TRUE;
	}

	/* Get the dscp to colour mapping array */
	if (cfg_parms->colour_aware) {
		if ((rc = nvlist_lookup_int32_array(nvlp,
		    TOKENMT_COLOUR_MAP, &colour_tbl, &nelem)) == 0) {
			int count;
			for (count = 0; count < 64; count++) {
				if (colour_tbl[count] == -1)
					continue;
				cfg_parms->dscp_to_colour[count] =
				    colour_tbl[count];
			}
		}
	}

	/* parse stats */
	if ((rc = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats))
	    != 0) {
		cfg_parms->stats = B_FALSE;
	} else {
		cfg_parms->stats = (bstats == 0) ? B_FALSE : B_TRUE;
	}

	nvlist_free(nvlp);

	/* Initialize other stuff */
	tokenmt_data = kmem_zalloc(TOKENMT_DATA_SZ, KM_NOSLEEP);
	if (tokenmt_data == NULL) {
		kmem_free(cfg_parms, TOKENMT_CFG_SZ);
		return (ENOMEM);
	}

	/* Initialize stats, if required */
	if (cfg_parms->stats) {
		if ((rc = tokenmt_statinit(aid, tokenmt_data)) != 0) {
			kmem_free(cfg_parms, TOKENMT_CFG_SZ);
			kmem_free(tokenmt_data, TOKENMT_DATA_SZ);
			return (rc);
		}
	}

	/* set action chain reference */
	if ((rc = ipp_action_ref(aid, cfg_parms->red_action, flags)) != 0) {
		tokenmt0dbg(("tokenmt_create_action: ipp_action_ref " \
		    "returned with error %d", rc));
		goto cleanup;
	}
	if ((rc = ipp_action_ref(aid, cfg_parms->green_action, flags)) != 0) {
		tokenmt0dbg(("tokenmt_create_action: ipp_action_ref " \
		    "returned with error %d", rc));
		rc2 = ipp_action_unref(aid, cfg_parms->red_action, flags);
		ASSERT(rc2 == 0);
		goto cleanup;
	}

	if (cfg_parms->yellow_action != TOKENMT_NO_ACTION) {
		if ((rc = ipp_action_ref(aid, cfg_parms->yellow_action,
		    flags)) != 0) {
			tokenmt0dbg(("tokenmt_create_action: ipp_action_ref "\
			    "returned with error %d", rc));
			rc2 = ipp_action_unref(aid, cfg_parms->red_action,
			    flags);
			ASSERT(rc2 == 0);
			rc2 = ipp_action_unref(aid, cfg_parms->green_action,
			    flags);
			ASSERT(rc2 == 0);
			goto cleanup;
		}
	}


	tokenmt_data->cfg_parms = cfg_parms;

	tokenmt_data->committed_tokens = cfg_parms->committed_burst;
	tokenmt_data->peak_tokens = cfg_parms->peak_burst;
	tokenmt_data->last_seen = gethrtime();

	mutex_init(&tokenmt_data->tokenmt_lock, NULL, MUTEX_DEFAULT, 0);
	ipp_action_set_ptr(aid, (void *)tokenmt_data);
	return (0);

cleanup:
	if (cfg_parms->stats) {
		ipp_stat_destroy(tokenmt_data->stats);
	}
	kmem_free(cfg_parms, TOKENMT_CFG_SZ);
	kmem_free(tokenmt_data, TOKENMT_DATA_SZ);
	return (rc);
}