/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <limits.h>
#include <pool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <synch.h>
#include <thread.h>
#include "dict.h"
#include "pool_internal.h"
#include "pool_impl.h"
/*
* Atom structure, used to reference count string atoms.
*/
typedef struct {
} atom_t;
/*
* The _internal_lock is used to lock the state of libpool during
* internal initialisation operations.
*/
/*
* Various useful constant strings which are often encountered
*/
/*
* prop_is_type() checks the supplied property and returns PO_TRUE if the
* property value is set for the property else PO_FALSE
*/
static int prop_is_type(int, const pool_prop_t *);
static int resource_get_common(const pool_resource_t *, const char *,
uint64_t *);
/*
* The following returns a malloc'ed string which must be free'd by the
* caller.
*/
static char *elem_get_expected_string(const pool_elem_t *, const char *);
static int element_props_init(pool_prop_t *);
/*
* which are used to create the element with appropriate property
* values and to ensure correct property manipulations. The details
* are all stored in the following arrays.
*/
static int elem_name_init(pool_prop_t *);
static int elem_comment_init(pool_prop_t *);
static int pool_importance_init(pool_prop_t *);
static int pool_active_init(pool_prop_t *);
static int res_max_init(pool_prop_t *);
static int res_min_init(pool_prop_t *);
static int res_size_init(pool_prop_t *);
static int res_load_init(pool_prop_t *);
static int pset_units_init(pool_prop_t *);
static int cpu_status_init(pool_prop_t *);
static const char *pool_elem_class_name[] = {
"invalid",
"system",
"pool",
"component resource",
"aggregate resource",
"component"
};
/*
* This must be kept in sync with the pool_resource_elem_ctl array and
* the "enum pool_resource_elem_class" type.
*/
static const char *pool_resource_elem_class_name[] = {
"invalid",
"pset"
};
static const char *pool_component_elem_class_name[] = {
"invalid",
"cpu"
};
{ NULL, elem_set_name } },
{ "system.ref_id", POOL_VALUE_INITIALIZER,
{ "system.version", POOL_VALUE_INITIALIZER,
{ "system.bind-default", POOL_VALUE_INITIALIZER,
{ "system.allocate-method", POOL_VALUE_INITIALIZER,
{ "system.poold.log-level", POOL_VALUE_INITIALIZER,
{ "system.poold.log-location", POOL_VALUE_INITIALIZER,
{ "system.poold.monitor-interval", POOL_VALUE_INITIALIZER,
{ "system.poold.history-file", POOL_VALUE_INITIALIZER,
{ "system.poold.objectives", POOL_VALUE_INITIALIZER,
};
{ "pool.sys_id", POOL_VALUE_INITIALIZER,
{ "pool.name", POOL_VALUE_INITIALIZER,
{ "pool.res", POOL_VALUE_INITIALIZER,
{ "pool.ref_id", POOL_VALUE_INITIALIZER,
{ "pool.default", POOL_VALUE_INITIALIZER,
{ "pool.scheduler", POOL_VALUE_INITIALIZER,
{ NULL, pool_set_scheduler } },
};
{ elem_get_type, NULL } },
{ "pset.sys_id", POOL_VALUE_INITIALIZER,
{ "pset.name", POOL_VALUE_INITIALIZER,
{ "pset.ref_id", POOL_VALUE_INITIALIZER,
{ "pset.default", POOL_VALUE_INITIALIZER,
{ NULL, res_set_min } },
{ NULL, res_set_max } },
{ "pset.units", POOL_VALUE_INITIALIZER,
res_load_init, NULL },
res_size_init, NULL },
{ "pset.poold.objectives", POOL_VALUE_INITIALIZER,
};
{ elem_get_type, NULL } },
NULL },
{ "cpu.ref_id", POOL_VALUE_INITIALIZER,
{ NULL, cpu_set_status } },
{ NULL, elem_set_bool } },
};
NULL,
NULL,
NULL,
};
/*
* This must be kept in sync with the pool_resource_elem_class_name array and
* the "enum pool_resource_elem_class" type.
*/
NULL,
};
NULL,
};
static void
atom_init(void)
{
(void) mutex_lock(&_atom_lock);
/*
* Initialize pool_value_t atom dictionary
*/
abort();
(void) mutex_unlock(&_atom_lock);
}
/*
* Initializer, called when the library is initialized.
*/
void
internal_init(void)
{
(void) mutex_lock(&_internal_lock);
if (_libpool_internal_initialised == PO_TRUE) {
(void) mutex_unlock(&_internal_lock);
return;
}
atom_init();
/*
* Initialize all available property arrays.
*/
abort();
abort();
abort();
abort();
(void) mutex_unlock(&_internal_lock);
}
static int
{
int i;
/*
* Initialise each of the properties
*/
return (PO_FAIL);
}
return (PO_FAIL);
}
}
return (PO_SUCCESS);
}
/*
* These functions intialise the properties of this plugin. The only reason
* they exist is because the ability to perform the static initialisation of
* union members properly was only introduced in the C99 standard. i.e. if you
* could do {.f = 1.0} like in the proposed C99 standard then that would
* be the preferred way to do this as it keeps the data in the array and
* minimises the scope for errors. However, until that time these functions
* are the best way to minimise the scope for errors and to maximise
* maintainability.
*
* There is one function for each property, and the initial value for each
* property is hard-coded into each function.
*/
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
static int
{
}
/*
* Individual property manipulation routines for use by the generic
*/
/*
* Many properties cannot be modified. This function prevents property
* modification.
*/
/* ARGSUSED */
static int
{
return (PO_FAIL);
}
/*
* Duplicate names for a pool or resource type are illegal.
*/
static int
{
const char *nm;
return (PO_FAIL);
}
if (!is_valid_name(nm)) {
return (PO_FAIL);
}
switch (pool_elem_class(elem)) {
case PEC_SYSTEM:
break;
case PEC_POOL:
return (PO_FAIL);
}
break;
case PEC_RES_COMP:
case PEC_RES_AGG:
return (PO_FAIL);
}
break;
default:
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Ensure the type is a string.
*/
/* ARGSUSED */
static int
{
return (PO_SUCCESS);
else {
return (PO_FAIL);
}
}
/*
* Ensure the type is a boolean.
*/
/* ARGSUSED */
static int
{
return (PO_SUCCESS);
else {
return (PO_FAIL);
}
}
/*
* Ensure the type is an unsigned int.
*/
/* ARGSUSED */
static int
{
return (PO_SUCCESS);
else {
return (PO_FAIL);
}
}
/* ARGSUSED */
int
{
const char *sval;
return (PO_FAIL);
}
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/* ARGSUSED */
int
{
return (PO_FAIL);
}
if (bval != 1) {
/*
* "active" must be true on pools for
* now.
*/
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/* ARGSUSED */
int
{
const char *sched;
return (PO_FAIL);
}
return (PO_FAIL);
}
return (PO_SUCCESS);
}
static int
{
/*
* max must be a uint
*/
return (PO_FAIL);
}
/*
* max can't be less than min (if it exists)
*/
return (PO_SUCCESS);
return (PO_FAIL);
}
return (PO_FAIL);
}
/*
* Ensure that changes to the max in a dynamic configuration
* are still valid.
*/
return (PO_FAIL);
}
return (PO_FAIL);
}
/*
* Ensure that the modified total max is >= size
* of all resources of this type
*/
}
}
return (PO_SUCCESS);
}
static int
{
/*
* min must be a uint
*/
return (PO_FAIL);
}
/*
* min can't be more than max (if it exists)
*/
return (PO_SUCCESS);
return (PO_FAIL);
}
return (PO_FAIL);
}
switch (pool_resource_elem_class(elem)) {
case PREC_PSET:
if (min < 1) {
return (PO_FAIL);
}
}
break;
default:
break;
}
/*
* Ensure that changes to the min in a dynamic configuration
* are still valid.
*/
return (PO_FAIL);
}
return (PO_FAIL);
}
/*
* Ensure that the modified total min is <= size
* of all resources of this type
*/
}
}
return (PO_SUCCESS);
}
/* ARGSUSED */
int
{
const char *status;
return (PO_FAIL);
}
return (PO_FAIL);
}
return (PO_SUCCESS);
}
static int
{
return (PO_FAIL);
return (PO_SUCCESS);
}
/*
* More general utilities
*/
/*
* Is the supplied configuration the dynamic configuration
*/
int
{
return (PO_TRUE);
return (PO_FALSE);
}
/*
* uint_init() initialises the value of the supplied property with the
* supplied value.
* Returns PO_SUCCESS
*/
int
{
return (PO_SUCCESS);
}
/*
* int_init() initialises the value of the supplied property with the
* supplied value.
* Returns PO_SUCCESS
*/
int
{
return (PO_SUCCESS);
}
/*
* double_init() initialises the value of the supplied property with the
* supplied value.
* Returns PO_SUCCESS
*/
int
{
return (PO_SUCCESS);
}
/*
* bool_init() initialises the value of the supplied property with the
* supplied value.
* Returns PO_SUCCESS
*/
int
{
return (PO_SUCCESS);
}
/*
* string_init() initialises the value of the supplied property with the
* supplied value.
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
}
/*
* pool_get_provider_count() returns the count of registered providers.
*
* Returns count of registered providers
*/
pool_get_provider_count(void)
{
int i;
for (i = 0; i < sizeof (pool_resource_elem_ctl) /
sizeof (pool_resource_elem_ctl[0]); i++) {
if (pool_resource_elem_ctl[i] != NULL)
count++;
}
return (count);
}
/*
* Return all the props for a specified provider
*/
const pool_prop_t *
{
switch (elem_class) {
case PEC_SYSTEM:
case PEC_POOL:
break;
case PEC_RES_AGG:
case PEC_RES_COMP:
break;
case PEC_COMP:
break;
}
return (prop_list);
}
/*
* provider_get_prop() return the pool_prop_t structure which
* describes the supplied property name for the supplied provider.
*
* Returns the property description or NULL if it doesn't exist.
*/
const pool_prop_t *
{
int i;
return (NULL);
return (&prop_list[i]);
}
}
return (NULL);
}
/*
* prop_is_type() checks the supplied property and returns PO_TRUE if the
* property value is 1 else PO_FALSE
*/
static int
{
}
/*
* prop_is_stored() returns PO_TRUE if the property is stored in the backing
* configuration and PO_FALSE else.
*/
int
{
}
/*
* prop_is_readonly() returns PO_TRUE if the property is a read-only property
* and PO_FALSE else.
*/
int
{
}
/*
* prop_is_init() returns PO_TRUE if the property should be
* initialised when an element of this type is created and PO_FALSE
* else.
*/
int
{
}
/*
* prop_is_hidden() returns PO_TRUE if the property should be hidden
* from access by the external property access mechanisms.
*/
int
{
}
/*
* prop_is_optional() returns PO_TRUE if the property is optional and
* can be removed by external property access mechanisms.
*/
int
{
}
int
{
return (PO_FALSE);
}
return (PO_FALSE);
}
return ((int)requested);
}
/*
* Common code for various resource get functions
*/
static int
{
*uval = 0;
#ifdef DEBUG
dprintf("can't retrieve %s\n");
#endif /* DEBUG */
}
return (retval);
}
/*
* resource_get_size() updates size with the size of the supplied resource.
*
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
}
/*
* resource_get_pinned() updates pinned with the size of the
* pinned part of a supplied resource. Resource is not available for
* allocation if it is marked as "pinned".
*
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
return (PO_FAIL);
} else
*pinned = 0;
return (PO_SUCCESS);
}
/*
* resource_get_min() updates min with the minimum size of the supplied
* resource.
*
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
}
/*
* resource_get_max() updates max with the maximum size of the supplied
* resource.
*
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
}
/*
* TODO: This is pset specific
*
* get_default_resource() returns the default resource for type of the supplied
* resource.
*
* Returns A pointer to the default resource of the same type as the supplied
* resource.
*/
const pool_resource_t *
{
}
/*
* resource_is_default() returns 1 if the supplied resource is the default
* resource for it's type.
*/
int
{
}
/*
* resource_is_system() determines if the resource is a system resource.
*/
int
{
}
/*
* resource_can_associate() determines if it is possible to associate
* with the supplied resource.
*/
int
{
}
/*
* Common code to get an int64 property.
* Unfortunately (-1) is a valid psetid, so we'll return (-2) in case of
* error.
*/
static int64_t
{
return (POOL_SYSID_BAD);
}
return (val64);
}
/*
* The following returns a malloc'ed string which must be free'd by the
* caller.
*/
static char *
{
char *retval;
return (NULL);
}
return (retval);
}
/*
* elem_get_sysid() returns the sys_id for the supplied elem.
*/
{
}
/*
* elem_get_name() returns the name for the supplied elem. Note that
* it is the caller's responsibility to free this memory.
*/
char *
{
}
/*
* elem_is_default() returns 1 if the supplied elem is the default
* elem for it's type.
*/
int
{
return (0);
}
return (0);
}
return (bval);
}
/*
* Return B_TRUE if the element has the 'temporary' property set.
*/
{
return (B_FALSE);
return (bval != 0);
}
/*
* is_a_known_prefix() determines if the supplied prop_name is a known
* name for the supplied class.
*
* Returns a pointer to the prefix if it is found or NULL
*/
const char *
{
int i;
int len;
switch (class) {
case PEC_SYSTEM:
case PEC_POOL:
return (pool_elem_class_name[class]);
break;
case PEC_RES_COMP:
case PEC_RES_AGG:
for (i = 0; i < sizeof (pool_resource_elem_class_name) /
sizeof (pool_resource_elem_class_name[0]); i++) {
pool_resource_elem_class_name[i], len) == 0 &&
return (pool_resource_elem_class_name[i]);
}
break;
case PEC_COMP:
for (i = 0; i < sizeof (pool_component_elem_class_name) /
sizeof (pool_component_elem_class_name[0]); i++) {
pool_component_elem_class_name[i], len) == 0 &&
return (pool_component_elem_class_name[i]);
}
break;
default:
break;
}
return (NULL);
}
const char *
{
switch (pool_elem_class(pe)) {
case PEC_SYSTEM:
case PEC_POOL:
case PEC_RES_COMP:
case PEC_RES_AGG:
return (pool_resource_elem_class_name
case PEC_COMP:
return (pool_component_elem_class_name
default:
return (pool_elem_class_name[PEC_INVALID]);
}
}
const char *
{
return (pool_resource_elem_class_name[type]);
}
const char *
{
return (pool_component_elem_class_name[type]);
}
/*
* resource_by_sysid() finds a resource from it's supplied sysid and type.
*
* Returns a pointer to the resource or NULL if it doesn't exist.
*/
{
return (NULL);
return (NULL);
}
return (NULL);
}
return (NULL);
}
}
return (retval);
}
{
int i;
for (i = 0; i < sizeof (pool_elem_class_name) /
sizeof (pool_elem_class_name[0]); i++) {
break;
}
if (i == sizeof (pool_elem_class_name) /
sizeof (pool_elem_class_name[0]))
return (PEC_INVALID);
return ((pool_elem_class_t)i);
}
{
int i;
for (i = 0; i < sizeof (pool_resource_elem_class_name) /
sizeof (pool_resource_elem_class_name[0]); i++) {
break;
}
if (i == sizeof (pool_resource_elem_class_name) /
sizeof (pool_resource_elem_class_name[0]))
return (PREC_INVALID);
return ((pool_resource_elem_class_t)i);
}
{
int i;
for (i = 0; i < sizeof (pool_component_elem_class_name) /
sizeof (pool_component_elem_class_name[0]); i++) {
break;
}
if (i == sizeof (pool_component_elem_class_name) /
sizeof (pool_component_elem_class_name[0]))
return (PCEC_INVALID);
return ((pool_component_elem_class_t)i);
}
/*
* pool_resource_type_list() populates the supplied array of pointers
* with the names of the available resource types on this system.
*/
int
{
int i, j;
if (types) {
for (i = 0, j = 0; i < sizeof (pool_resource_elem_ctl) /
sizeof (pool_resource_elem_ctl[0]) && j < maxnum; i++) {
if (pool_resource_elem_ctl[i] != NULL)
types[j++] = pool_resource_elem_class_name[i];
}
}
return (PO_SUCCESS);
}
/*
* Return the system element for the supplied conf.
* NULL is returned if an error is detected and the error code is updated
* to indicate the cause of the error.
*/
{
NULL) {
return (NULL);
}
/* There should only be one system record */
(void) pool_rs_close(rs);
return (NULL);
}
(void) pool_rs_close(rs);
return (pool_elem_system(system));
}
{
return (NULL);
}
return ((pool_system_t *)pe);
}
pool_t *
{
return (NULL);
}
}
{
return (NULL);
}
return ((pool_resource_t *)pe);
}
{
return (NULL);
}
return ((pool_component_t *)pe);
}
/*
* qsort_elem_compare() is used for qsort elemement comparison.
*
* Returns see qsort(3c)
*/
int
qsort_elem_compare(const void *a, const void *b)
{
/*
* Special case for handling name changes on default elements
* If both elements are default elements then always return 0
*/
return (0);
else
}
/*
* Dynamic character buffers.
*/
/*
* Resize the supplied character buffer to the new size.
*/
static int
{
return (PO_FAIL);
}
/* If inital allocation, make sure buffer is zeroed */
/* If resized smaller, make sure buffer NULL terminated */
return (PO_SUCCESS);
}
/*
* Allocate a new char_buf_t structure. If there isn't enough memory, return
* NULL. Initialise the new char_buf_t to 0 and then call resize_char_buf
* to initialise the character buffer. Return a pointer to the new
* char_buf_t if the operation succeeds.
*/
{
return (NULL);
}
return (NULL);
}
return (cb);
}
/*
* Free the character buffer and then free the char_buf_t.
*/
void
{
}
/*
* Set the character buffer to the supplied data. The user supplies a printf
* like format string and then an appropriate number of parameters for the
* specified format. The character buffer is automatically resized to fit
* the data as determined by resize_char_buf.
*/
/*PRINTFLIKE2*/
int
{
int new_size;
return (PO_FAIL);
}
}
return (PO_SUCCESS);
}
/*
* Append the supplied data to the character buffer. The user supplies a printf
* like format string and then an appropriate number of parameters for the
* specified format. The character buffer is automatically resized to fit
* the data as determined by resize_char_buf.
*/
/*PRINTFLIKE2*/
int
{
int new_len;
int old_len = 0;
PO_SUCCESS) {
return (PO_FAIL);
}
}
/*
* Resized the buffer to the right size, now append the new data
*/
return (PO_SUCCESS);
}
/*
* Return the class for the supplied elem.
* If the return is PEC_INVALID, the error code will be set to reflect cause.
*/
{
}
/*
* Return the resource class for the supplied elem.
*/
{
return (elem->pe_resource_class);
}
/*
* Return the component class for the supplied elem.
*/
{
return (elem->pe_component_class);
}
{
}
void
{
}
int
{
int i;
return (PO_FAIL);
}
/*
* Check that there are available resources on this
* system for this configuration to be applied. Find
* each resource type and then find all resources of
* each type and total ".min". Find all available
* resources and ensure >= total min.
*/
available = 0;
return (PO_FAIL);
for (i = 0; i < nelem; i++) {
return (PO_FAIL);
}
/*
* Watch out for overflow
*/
break;
} else
}
} else {
return (PO_FAIL);
PO_SUCCESS) {
return (PO_FAIL);
}
NULL) {
(void) pool_conf_close(dyn);
return (PO_FAIL);
}
}
for (i = 0; i < nelem; i++) {
(void) pool_conf_close(dyn);
}
return (PO_FAIL);
}
}
(void) pool_conf_close(dyn);
}
return (PO_FAIL);
}
} else {
return (PO_FAIL);
}
}
return (PO_SUCCESS);
}
/*
* If _libpool_debug is set, printf the debug message to stderr with an
* appropriate prefix in front of it.
*/
void
{
if (_libpool_debug) {
}
}
/*PRINTFLIKE1*/
void
{
if (_libpool_debug) {
}
}
/*
* log_alloc() allocates a new, empty transaction log.
*
* Returns a pointer to the new log or NULL on failure.
*/
log_t *
{
log_t *l;
return (NULL);
}
== NULL) {
free(l);
return (NULL);
}
return (l);
}
/*
* log_free() reclaims the resources associated with a transaction log.
*/
void
{
(void) log_walk(l, log_item_free);
(void) log_item_free(l->l_sentinel);
free(l);
}
/*
* log_empty() removes all items from a transaction log. It is the
* users responsibility to ensure that any resources associated with
* an item are reclaimed before this function is invoked.
*/
void
{
(void) log_walk(l, log_item_free);
}
/*
* log_walk() visits each log item in turn and executes the supplied action
* using the item as a parameter. If no action is supplied, then the item
* uses it's own stored action.
*
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
while (li != l->l_sentinel) {
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* log_reverse_walk() visits each log item in turn (in reverse order)
* and executes the supplied action using the item as a parameter.
*
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
while (li != l->l_sentinel) {
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* log_size() returns the size of the log, i.e. the number of items pending in
* the log.
*/
{
size++;
return (size);
}
/*
* log_append() allocates a new log item to hold the supplied details and
* appends the newly created item to the supplied log.
*
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
return (PO_FAIL);
}
/*
* Link it in
*/
return (PO_SUCCESS);
}
/*
* log_item_alloc() allocates a new transaction log item. The item should be
* used to store details about a transaction which may need to be undone if
* commit processing fails.
*
* Returns a pointer to a new transaction log item or NULL.
*/
{
return (NULL);
}
return (li);
}
/*
* log_item_free() reclaims the resources associated with a log_item_t.
*/
int
{
return (PO_SUCCESS);
}
/*
* atom_string() checks the string table to see if a string is already
* stored. If it is, return a pointer to it. If not, duplicate the
* string and return a pointer to the duplicate.
*/
const char *
atom_string(const char *s)
{
/*
* atom_init() must have completed successfully
*/
atom_init();
(void) mutex_lock(&_atom_lock);
(void) mutex_unlock(&_atom_lock);
return (NULL);
}
(void) mutex_unlock(&_atom_lock);
return (NULL);
}
}
(void) mutex_unlock(&_atom_lock);
}
/*
* atom_free() decrements the reference count for the supplied
* string. If the reference count reaches zero, then the atom is
* destroyed.
*/
void
atom_free(const char *s)
{
(void) mutex_lock(&_atom_lock);
(void) dict_remove(_pv_atoms, s);
}
}
(void) mutex_unlock(&_atom_lock);
}
#ifdef DEBUG
/*
* log_item_dprintf() prints the contents of the supplied log item using the
* pools dprintf() trace mechanism.
*
* Returns PO_SUCCESS
*/
void
{
}
/*
* log_item_dprintf() prints the contents of the supplied log item using the
* pools dprintf() trace mechanism.
*
* Returns PO_SUCCESS
*/
void
{
dprintf("element type: %s name: %s\n",
} else {
dprintf("element type: %s sys_id: %d\n",
}
}
#endif /* DEBUG */