/*
* 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 <assert.h>
#include <errno.h>
#include <exacct.h>
#include <fcntl.h>
#include <libnvpair.h>
#include <limits.h>
#include <poll.h>
#include <pool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stropts.h>
#include <thread.h>
#include <time.h>
#include <unistd.h>
#include <sys/pool_impl.h>
#include <sys/priocntl.h>
#include "dict.h"
#include "pool_internal.h"
#include "pool_impl.h"
#include "pool_kernel_impl.h"
/*
* libpool kernel Manipulation Routines
*
* pool_kernel.c implements the kernel manipulation routines used by the
* libpool kernel datastore. The functions are grouped into the following
* logical areas
*
*/
/*
* Device snapshot transfer buffer size
*/
/*
* Kernel result set's initial size. 8 is probably large enough for
* most queries. Queries requiring more space are accomodated using
* realloc on a per result set basis.
*/
/*
* Property manipulation macros
*/
/*
* Information required to evaluate qualifying elements for a query
*/
struct query_obj {
const char *src_attr;
};
/*
* Identifies a pool element with a processor set id
*/
typedef struct pool_set_xref {
/*
* Controls exacct snapshot load into libpool data structure
*/
typedef struct pool_snap_load {
int *psl_changed;
/*
* Information about an XML document which is being constructed
*/
struct knl_to_xml {
};
/*
* Undo structure processing. The following structures are all used to
* allow changes to the libpool snapshot and kernel following an
* unsuccessful commit.
*/
typedef struct pool_create_undo {
typedef struct pool_destroy_undo {
typedef struct pool_assoc_undo {
typedef struct pool_dissoc_undo {
typedef struct pool_xtransfer_undo {
typedef struct pool_propput_undo {
typedef struct pool_proprm_undo {
extern const char *dtd_location;
extern const char *element_class_tags[];
extern const char pool_info_location[];
/*
* These functions are defined in pool_xml.c and represent the minimum
* XML support required to allow a pool kernel configuration to be
* exported as an XML document.
*/
extern void xml_init(void);
extern void pool_error_func(void *, const char *, ...);
/*
* Utilities
*/
pool_snap_load_t *);
static void pool_knl_elem_free(pool_knl_elem_t *, int);
const pool_value_t *);
static int pool_knl_nvlist_add_value(nvlist_t *, const char *,
const pool_value_t *);
static int pool_knl_recover(pool_conf_t *);
static int blocking_open(const char *, int);
/*
* Connections
*/
static void pool_knl_connection_free(pool_knl_connection_t *);
/*
* Configuration
*/
static int pool_knl_close(pool_conf_t *);
static int pool_knl_commit(pool_conf_t *);
static int pool_knl_export(const pool_conf_t *, const char *,
static int pool_knl_rollback(pool_conf_t *);
static int pool_knl_remove(pool_conf_t *);
static char *pool_knl_get_resource_binding(pool_conf_t *,
uint64_t);
pool_component_t **);
/*
* Result Sets
*/
static int pool_knl_result_set_append(pool_knl_result_set_t *,
pool_knl_elem_t *);
static int pool_knl_result_set_realloc(pool_knl_result_set_t *);
static void pool_knl_result_set_free(pool_knl_result_set_t *);
static int pool_knl_rs_set_index(pool_result_set_t *, int);
static int pool_knl_rs_get_index(pool_result_set_t *);
static int pool_knl_rs_count(pool_result_set_t *);
static int pool_knl_rs_close(pool_result_set_t *);
/*
* Element (and sub-type)
*/
static int pool_knl_elem_remove(pool_elem_t *);
/*
* Pool element specific
*/
/*
* Resource elements specific
*/
static int pool_knl_resource_is_system(const pool_resource_t *);
static int pool_knl_resource_can_associate(const pool_resource_t *);
/* Properties */
const char *, pool_value_t *);
const char *, pool_value_t *);
static int pool_knl_put_property(pool_elem_t *, const char *,
const pool_value_t *);
static int pool_knl_rm_property(pool_elem_t *, const char *);
/*
* Logging
*/
static int log_item_commit(log_item_t *);
static int log_item_undo(log_item_t *);
static int log_item_release(log_item_t *);
/*
* Utilities
*/
/*
* load_group() updates the library configuration with the kernel
* snapshot supplied in ep. The function is designed to be called
* recursively. This function depends implicitly on the ordering of
* the data provided in ep. Changes to the ordering of data in ep must
* be matched by changes to this function.
*/
int
{
PCEC_INVALID)) == NULL)
return (PO_FAIL);
0) != 0) {
return (PO_FAIL);
}
/*
* Check to see if we already have an element
* for this data. If we have, free the newly
* created elem and continue with the old one
*/
} else {
return (PO_FAIL);
}
}
}
int data;
switch (data) {
case EXD_SYSTEM_TSTAMP:
case EXD_POOL_TSTAMP:
case EXD_PSET_TSTAMP:
case EXD_CPU_TSTAMP:
if (psl->psl_changed) {
switch (data) {
case EXD_SYSTEM_TSTAMP:
break;
case EXD_POOL_TSTAMP:
break;
case EXD_PSET_TSTAMP:
break;
case EXD_CPU_TSTAMP:
break;
}
}
}
break;
case EXD_SYSTEM_PROP:
case EXD_POOL_PROP:
case EXD_PSET_PROP:
case EXD_CPU_PROP:
if (data == EXD_PSET_PROP) {
}
0) {
return (PO_FAIL);
}
if (data == EXD_PSET_PROP) {
}
break;
case EXD_POOL_POOLID:
NV_UNIQUE_NAME_TYPE, 0) != 0) {
return (PO_FAIL);
}
"pool.sys_id",
return (PO_FAIL);
}
NULL) {
} else {
NULL) {
return (PO_FAIL);
}
}
return (PO_FAIL);
}
break;
case EXD_POOL_PSETID:
return (PO_FAIL);
}
break;
case EXD_PSET_PSETID:
NV_UNIQUE_NAME_TYPE, 0) != 0) {
return (PO_FAIL);
}
"pset.sys_id",
return (PO_FAIL);
}
NULL) {
} else {
NULL) {
return (PO_FAIL);
}
}
return (PO_FAIL);
}
break;
case EXD_CPU_CPUID:
NV_UNIQUE_NAME_TYPE, 0) != 0) {
return (PO_FAIL);
}
"cpu.sys_id",
return (PO_FAIL);
}
NULL) {
} else {
NULL) {
return (PO_FAIL);
}
}
break;
case EXD_GROUP_POOL:
return (PO_FAIL);
return (PO_FAIL);
}
break;
case EXD_GROUP_PSET:
return (PO_FAIL);
return (PO_FAIL);
}
break;
case EXD_GROUP_CPU:
return (PO_FAIL);
return (PO_FAIL);
}
break;
default:
break;
}
break;
}
}
return (ret);
}
/*
* Push a snapshot entry onto the list of pools in the snapshot.
*/
int
{
return (PO_FAIL);
}
/*
* Push onto the list of pools
*/
return (PO_SUCCESS);
}
/*
* Update the current cross-reference for the supplied type of
* resource.
*/
int
{
switch (type) {
case EXD_POOL_PSETID:
break;
default:
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Remove a resource entry with the supplied type and id from the
* snapshot list when it is no longer required.
*/
int
{
switch (type) {
case EXD_PSET_PSETID:
break;
default:
return (PO_FAIL);
}
} else {
}
} else
}
return (PO_SUCCESS);
}
/*
* Return the nvpair with the supplied name from the supplied list.
*
* NULL is returned if the name cannot be found in the list.
*/
nvpair_t *
{
break;
}
return (pair);
}
/*
* Close the configuration. There are a few steps to closing a configuration:
* - Close the pseudo device
* - Free the data provider
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
return (PO_FAIL);
}
/*
* Rollback any pending changes before freeing the prov. This
* ensures there are no memory leaks from pending transactions.
* However, don't rollback when we've done a temporary pool since the
* They will all be freed in pool_knl_connection_free and we don't
* want to double free them.
*/
(void) pool_knl_rollback(conf);
return (PO_SUCCESS);
}
/*
* Remove elements in this map (previously identified as "dead") from
* the configuration map (prov->pkc_elements).
*/
/* ARGSUSED1 */
static void
{
#ifdef DEBUG
dprintf("remove_dead_elems:\n");
#endif /* DEBUG */
}
/*
* Find elements which were not updated the last time that
* load_group() was called. Add those elements into a separate map
* (passed in cl) which will be later used to remove these elements
* from the configuration map.
*/
/* ARGSUSED1 */
static void
{
}
/*
* Update the snapshot held by the library. This function acts as the
* controller for the snapshot update procedure. Then snapshot is
* actually updated in multiple phases by the load_group() function
* (which updates existing elements and creates new elements as
* required) and then by find_dead_elems and remove_dead_elems
* (respectively responsible for identifying elements which are to be
* removed and then removing them).
*
* Returns PO_SUCCESS
*/
int
{
/*
* Ensure the library snapshot is consistent, if there are any
* outstanding transactions return failure.
*/
return (PO_FAIL);
}
/*
* Query the kernel for a snapshot of the configuration state. Use
* load_group to allocate the user-land representation of the
* data returned in the snapshot.
*/
/* LINTED E_CONSTANT_CONDITION */
while (1) {
return (PO_FAIL);
}
return (PO_FAIL);
}
return (PO_FAIL);
}
query.pq_io_bufsize = 0;
} else
break;
}
return (PO_FAIL);
}
/*
* Update the library snapshot
*/
return (PO_FAIL);
}
/*
* Now search the dictionary for items that must be removed because
* they were neither created nor updated.
*/
return (PO_FAIL);
}
if (dict_length(dead_map) > 0) {
}
return (PO_SUCCESS);
}
/*
* Rely on the kernel to always keep a kernel configuration valid.
* Returns PO_SUCCESS
*/
/* ARGSUSED */
int
{
}
/*
* Process all the outstanding transactions in the log. If the processing
* fails, then attempt to rollback and "undo" the changes.
*/
int
{
/*
* Lock the kernel state for the commit
*/
return (PO_FAIL);
}
lock = 0;
/*
* If the state is LS_FAIL, then try to recover before
* performing the commit.
*/
/*
* Unlock the kernel state for the
* commit. Assert that this * can't fail,
* since if it ever does fail the library is
* unusable.
*/
}
}
/*
* Commit the log
*/
(void) pool_knl_recover(conf);
/*
* Unlock the kernel state for the commit. Assert that
* this can't fail, since if it ever does fail the
* library is unusable.
*/
return (PO_FAIL);
}
/*
* Unlock the kernel state for the commit. Assert that this
* can't fail, since if it ever does fail the library is
* unusable.
*/
/*
* Release the log resources
*/
return (PO_SUCCESS);
}
/*
* prop_build_cb() is designed to be called from
* pool_walk_properties(). The property value is used to put an XML
* property on the supplied ktx_node. This is an essential part of the
* mechanism used to export a kernel configuration in libpool XML
* form.
*/
/* ARGSUSED */
static int
{
}
/*
* Duplicate some of the functionality from pool_xml_put_property()
* (see pool_xml.c) to allow a kernel configuration to add XML nodes
* to an XML tree which represents the kernel configuration. This is
* an essential part of the mechanism used to export a kernel
* configuration in libpool XML form.
*/
int
const pool_value_t *val)
{
/*
* "type" is a special attribute which is not visible ever outside of
* libpool. Use the specific type accessor function.
*/
val));
}
if (pool_xml_set_attr(node,
val));
} else
return (PO_SUCCESS);
}
/*
* Export the kernel configuration as an XML file. The configuration
* is used to build an XML document in memory. This document is then
* saved to the supplied location.
*/
int
{
int ret;
int i;
xml_init();
switch (fmt) {
case POX_NATIVE:
BAD_CAST "-//Sun Microsystems Inc//DTD Resource "
"Management All//EN",
return (PO_FAIL);
}
/*
* Call xmlValidateDocument() to force the parsing of
* the DTD. Ignore errors and warning messages as we
* know the document isn't valid.
*/
NULL) {
return (PO_FAIL);
}
BAD_CAST "dummy");
BAD_CAST "\nConfiguration for pools facility. Do NOT"
" edit this file by hand - use poolcfg(1)"
" or libpool(3POOL) instead.\n")) == NULL) {
return (PO_FAIL);
}
return (PO_FAIL);
}
PO_FAIL) {
return (PO_FAIL);
}
return (PO_FAIL);
}
/*
* Now add pool details
*/
for (i = 0; i < nelem; i++) {
int j;
if (elem_is_tmp(elem))
continue;
return (PO_FAIL);
}
(pool_conf_t *)conf,
return (PO_FAIL);
}
/*
* TODO: pset specific res manipulation
*/
return (PO_FAIL);
}
return (PO_FAIL);
}
for (j = 0; j < nreselem; j++) {
(int)elem_get_sysid(reselem)) ==
PO_FAIL) {
return (PO_FAIL);
}
sep = " ";
}
return (PO_FAIL);
}
}
}
/*
* Now add resource details (including components)
*/
for (i = 0; i < nelem; i++) {
int j;
if (elem_is_tmp(elem))
continue;
return (PO_FAIL);
}
(pool_conf_t *)conf,
return (PO_FAIL);
}
return (PO_FAIL);
}
for (j = 0; j < ncompelem; j++) {
ktx_doc);
return (PO_FAIL);
}
(pool_conf_t *)conf,
prop_build_cb, 1) ==
PO_FAIL) {
ktx_doc);
return (PO_FAIL);
}
compelem),
(int)elem_get_sysid(
ktx_doc);
return (PO_FAIL);
}
}
}
}
}
/*
* Set up the message handlers prior to calling
* xmlValidateDocument()
*/
return (PO_FAIL);
}
return (PO_FAIL);
}
if (ret == -1) {
return (PO_FAIL);
}
return (PO_SUCCESS);
default:
return (PO_FAIL);
}
}
/*
* Rollback the changes to the kernel
*/
int
{
dprintf("Library configuration consistency error\n");
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Rollback the changes to the configuration
*/
int
{
dprintf("Kernel configuration consistency error\n");
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Callback used to build the result set for a query. Each invocation will
* supply a candidate element for inclusion. The element is filtered by:
* - class
* - properties
* If the element "matches" the target, then it is added to the result
* set, otherwise it is ignored.
*/
/* ARGSUSED1 */
static void
{
/*
* Check to see if it's the right class of element
*/
int i;
/*
* Now check to see if the src element is correct. If no src
* element is supplied, ignore this check
*/
break;
}
return;
}
/*
* Now check for property matches (if there are any specified)
*/
(pool_elem_t *)pke,
POC_INVAL) {
break;
} else {
break;
}
}
}
(pool_knl_elem_t *)key);
} else {
(pool_knl_elem_t *)key);
}
}
}
/*
* Execute the supplied query and return a result set which contains
* all qualifying elements.
*/
{
/*
* Have a buffer at this point, that we can use
*/
return (NULL);
}
/*
* Note: This logic is resource specific and must be
* extended for additional resource types.
*/
/*
* Check for property matches (if there are any specified)
*/
if (props) {
int i;
if (pool_get_property(conf,
POC_INVAL) {
break;
} else {
if (pool_value_equal(props[i],
break;
}
}
}
}
(void) pool_knl_result_set_append(rs,
} else
return ((pool_result_set_t *)rs);
}
/*
* Callback function intended to be used from pool_walk_pools(). If
* the supplied pool is not the default pool attempt to destroy it.
*/
/*ARGSUSED*/
static int
{
/*
* Return PO_SUCCESS even though we don't delete the default
* pool so that the walk continues
*/
return (PO_SUCCESS);
}
/*
* Remove the configuration details. This means remove all elements
* apart from the system elements.
*/
int
{
for (i = 0; i < nelem; i++) {
PO_SUCCESS) {
return (PO_FAIL);
}
}
}
return (PO_FAIL);
return (PO_FAIL);
return (PO_SUCCESS);
}
/*
* Determine the name of the pool to which the supplied pid is
* bound. If it cannot be determined return NULL.
*/
char *
{
const char *sval;
return (NULL);
}
return (NULL);
}
return (NULL);
}
if (nelem != 1) {
return (NULL);
}
== POC_INVAL) {
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (name);
}
/*
* Bind idtype id to the pool name.
*/
int
{
int ret;
return (PO_FAIL);
;
if (ret < 0) {
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* pool_knl_get_resource_binding() returns the binding for a pid to
* the supplied type of resource. If a binding cannot be determined,
* NULL is returned.
*/
char *
{
const char *sval;
return (NULL);
}
return (NULL);
}
return (NULL);
}
if (nelem != 1) {
return (NULL);
}
PO_SUCCESS ||
return (NULL);
}
return (NULL);
}
if (nelem != 1) {
return (NULL);
}
POC_INVAL) {
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (name);
}
/*
* Allocate the required library data structure and initialise it.
*/
{
switch (class) {
case PEC_SYSTEM:
return (NULL);
}
break;
case PEC_POOL:
return (NULL);
}
break;
case PEC_RES_COMP:
case PEC_RES_AGG:
return (NULL);
}
break;
case PEC_COMP:
return (NULL);
}
break;
default:
return (NULL);
}
/* Set up the function pointers for element manipulation */
/*
* Specific initialisation for different types of element
*/
}
}
#if DEBUG
assert(!"leak map put failed");
#endif /* DEBUG */
return (elem);
}
/*
* Allocate a new pool_knl_elem_t in the supplied configuration of the
* specified class.
*/
{
NULL)
return (NULL);
/*
* Allocate an nvlist to hold properties
*/
return (NULL);
}
/*
* Allocate a temporary ID and name until the element is
* created for real
*/
return (NULL);
}
return (NULL);
}
return (NULL);
}
/*
* If it's a resource class, it will need an initial size
*/
PO_SUCCESS) {
return (NULL);
}
}
/*
* Register the newly created element
*/
return (NULL);
}
return ((pool_elem_t *)elem);
/*
* The remaining logic is setting up the arguments for the
* POOL_CREATE ioctl and appending the details into the log.
*/
return (NULL);
}
switch (class) {
case PEC_SYSTEM:
return (NULL);
case PEC_POOL: /* NO-OP */
break;
case PEC_RES_COMP:
case PEC_RES_AGG:
break;
case PEC_COMP:
break;
default:
return (NULL);
}
PO_SUCCESS) {
return (NULL);
}
return ((pool_elem_t *)elem);
}
/*
* Remove the details of the element from our userland copy and destroy
* the element (if appropriate) in the kernel.
*/
int
{
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* The remaining logic is setting up the arguments for the
* POOL_DESTROY ioctl and appending the details into the log.
*/
return (PO_FAIL);
}
PO_SUCCESS) {
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Set the parent of the supplied child to the supplied parent
*/
int
{
return (PO_SUCCESS);
}
/*
* TODO: Needed for msets and ssets.
*/
/* ARGSUSED */
int
return (PO_FAIL);
}
/*
* Transfer resource components from one resource set to another.
*/
int
pool_component_t **rl) {
/*
* Walk the Result Set and move the resource components
*/
return (PO_FAIL);
}
}
return (PO_SUCCESS);
}
/*
* The remaining logic is setting up the arguments for the
* POOL_XTRANSFER ioctl and appending the details into the log.
*/
return (PO_FAIL);
}
} else {
return (PO_FAIL);
}
/* calculate the size using the terminating NULL */;
return (PO_FAIL);
}
sizeof (pool_component_t *))) == NULL) {
return (PO_FAIL);
}
sizeof (pool_component_t *));
PO_SUCCESS) {
return (PO_FAIL);
}
PO_FAIL) {
return (PO_FAIL);
}
}
return (PO_SUCCESS);
}
/*
* Return the parent of an element.
*/
{
}
/*
* Note: This function is resource specific, needs extending for other
* resource types
*/
int
{
case PREC_PSET:
return (PSID_IS_SYSSET(
default:
return (PO_FALSE);
}
}
/*
* Note: This function is resource specific, needs extending for other
* resource types
*/
int
{
case PREC_PSET:
return (PO_TRUE);
default:
return (PO_FALSE);
}
}
/*
* pool_knl_pool_associate() associates the supplied resource to the
* supplied pool.
*
* Returns: PO_SUCCESS/PO_FAIL
*/
int
{
/*
* Are we allowed to associate with this target?
*/
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* The remaining logic is setting up the arguments for the
* POOL_ASSOC ioctl and appending the details into the log.
*/
return (PO_FAIL);
}
PO_SUCCESS) {
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* pool_knl_pool_dissociate() dissociates the supplied resource from
* the supplied pool.
*
* Returns: PO_SUCCESS/PO_FAIL
*/
int
{
resource);
return (PO_SUCCESS);
}
/*
* The remaining logic is setting up the arguments for the
* POOL_DISSOC ioctl and appending the details into the log.
*/
return (PO_FAIL);
}
PO_SUCCESS) {
return (PO_FAIL);
}
/*
* Update our local copy
*/
return (PO_SUCCESS);
}
/*
* Allocate a data provider for the supplied configuration and optionally
* discover resources.
* The data provider is the cross over point from the "abstract" configuration
* functions into the data representation specific manipulation routines.
* This function sets up all the required pointers to create a kernel aware
* data provider.
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
return (PO_FAIL);
}
/*
* Initialise data members
*/
/*
* Initialise function pointers
*/
/*
* Associate the provider to it's configuration
*/
/*
* End of common initialisation
*/
/*
* Attempt to open the pseudo device, if the configuration is opened
* readonly then try to open an info device, otherwise try to open
* the writeable device.
*/
O_RDWR)) < 0) {
return (PO_FAIL);
}
} else {
return (PO_FAIL);
}
}
/*
* Allocate the element dictionary
*/
return (PO_FAIL);
}
#if DEBUG
return (PO_FAIL);
}
#endif /* DEBUG */
/*
* Allocate the transaction log
*/
#if DEBUG
#endif /* DEBUG */
return (PO_FAIL);
}
/*
* At this point the configuration provider has been initialized,
* mark the configuration as valid so that the various routines
* which rely on a valid configuration will work correctly.
*/
/*
* Update the library snapshot from the kernel
*/
#if DEBUG
#endif /* DEBUG */
return (PO_FAIL);
}
return (PO_SUCCESS);
}
#if DEBUG
static void
{
} else
dprintf("no properties\n");
}
#endif /* DEBUG */
/*
* pool_knl_elem_free() releases the resources associated with the
* supplied element.
*/
static void
{
#if DEBUG
}
#endif /* DEBUG */
}
}
/*
* pool_knl_elem_free_cb() is designed to be used with
* dict_map(). When a connection is freed, this function is used to
* free all element resources.
*/
/* ARGSUSED1 */
static void
{
#ifdef DEBUG
dprintf("pool_knl_elem_free_cb:\n");
#endif /* DEBUG */
}
/*
* Free the resources for a kernel data provider.
*/
void
{
}
#if DEBUG
prov->pkc_elements);
#endif /* DEBUG */
}
}
/*
* Return the specified property value.
*
* POC_INVAL is returned if an error is detected and the error code is updated
* to indicate the cause of the error.
*/
{
return (POC_INVAL);
}
return (POC_INVAL);
}
return (pool_value_get_type(val));
}
/*
* Return the specified property value.
*
* If a property is designated as dynamic, then this function will
* always try to return the latest value of the property from the
* kernel.
*
* POC_INVAL is returned if an error is detected and the error code is updated
* to indicate the cause of the error.
*/
{
return (POC_INVAL);
}
&proplist, 0) != 0) {
return (POC_INVAL);
}
return (POC_INVAL);
}
return (POC_INVAL);
}
return (pool_value_get_type(val));
}
/*
* Update the specified property value.
*
* PO_FAIL is returned if an error is detected and the error code is updated
* to indicate the cause of the error.
*/
int
const pool_value_t *val)
{
return (PO_FAIL);
}
return (PO_FAIL);
}
}
return (PO_FAIL);
if (bl)
return (PO_SUCCESS);
}
/*
* The remaining logic is setting up the arguments for the
* POOL_PROPPUT ioctl and appending the details into the log.
*/
return (PO_FAIL);
}
return (PO_FAIL);
}
return (PO_FAIL);
}
return (PO_FAIL);
}
}
PO_SUCCESS) {
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Remove the specified property value.
*
* PO_FAIL is returned if an error is detected and the error code is
* updated to indicate the cause of the error.
*/
int
{
return (PO_FAIL);
}
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* The remaining logic is setting up the arguments for the
* POOL_PROPRM ioctl and appending the details into the log.
*/
PO_SUCCESS) {
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Return a NULL terminated array of pool_value_t which represents all
* of the properties stored for an element
*
* Return NULL on failure. It is the caller's responsibility to free
* the returned array of values.
*/
pool_value_t **
{
int i = 0;
*nprops = 0;
(*nprops)++;
return (NULL);
}
result[i] = pool_value_alloc();
while (i-- >= 0)
pool_value_free(result[i]);
return (NULL);
}
}
return (result);
}
/*
* Append an entry to a result set. Reallocate the array used to store
* results if it's full.
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
return (PO_FAIL);
return (PO_SUCCESS);
}
/*
* Resize the array used to store results. A simple doubling strategy
* is used.
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Allocate a result set. The Result Set stores the result of a query.
*/
{
return (NULL);
}
return (NULL);
}
/* Fix up the result set accessor functions to the knl specfic ones */
return (rs);
}
/*
* Free a result set. Ensure that the resources are all released at
* this point.
*/
void
{
}
/*
* Return the next element in a result set.
*/
{
return (NULL);
}
/*
* Return the previous element in a result set.
*/
{
return (NULL);
}
/*
* Sets the current index in a result set.
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Return the current index in a result set.
* Returns current index
*/
int
{
}
/*
* Return the first element in a result set.
*/
{
}
/*
* Return the last element in a result set.
*/
{
}
/*
* Return the number of results in a result set.
* Returns result count
*/
int
{
}
/*
* Close a result set. Free the resources
* Returns PO_SUCCESS/PO_FAIL
*/
int
{
return (PO_SUCCESS);
}
/*
* Commit an individual transaction log item(). This processing is
* essential to the pool_conf_commit() logic. When pool_conf_commit()
* is invoked, the pending transaction log for the configuration is
* walked and all pending changes to the kernel are invoked. If a
* change succeeds it is marked in the log as successful and
* processing continues, if it fails then failure is returned and the
* log will be "rolled back" to undo changes to the library snapshot
* and the kernel.
*/
int
{
int ret;
case POOL_CREATE:
return (PO_FAIL);
return (PO_FAIL);
}
#ifdef DEBUG
dprintf("log_item_commit: POOL_CREATE, remove from dict\n");
#endif /* DEBUG */
/*
* May not need to remove the element if it was
* already destroyed before commit. Just cast the
* return to void.
*/
return (PO_FAIL);
}
/*
* Now that we have created our element in the kernel,
* it has a valid allocated system id. Remove the
* element from the element dictionary, using the
* current key, and then re-insert under the new key.
*/
#ifdef DEBUG
#endif /* DEBUG */
/*
* If the element has a pair in the static
* configuration, update it with the sys_id
*/
== PO_SUCCESS);
}
break;
case POOL_DESTROY:
/*
* It may be that this element was created in the last
* transaction. In which case POOL_CREATE, above, will
* have re-inserted the element in the dictionary. Try
* to remove it just in case this has occurred.
*/
;
if (ret < 0) {
return (PO_FAIL);
}
#ifdef DEBUG
dprintf("log_item_commit: POOL_DESTROY\n");
#endif /* DEBUG */
break;
case POOL_ASSOC:
;
if (ret < 0) {
return (PO_FAIL);
}
break;
case POOL_DISSOC:
;
if (ret < 0) {
return (PO_FAIL);
}
break;
case POOL_TRANSFER:
return (PO_FAIL);
/* NOTREACHED */
break;
case POOL_XTRANSFER:
#ifdef DEBUG
dprintf("log_item_commit: POOL_XTRANSFER\n");
#endif /* DEBUG */
}
/*
* Don't actually transfer resources if the configuration
* is in POF_DESTROY state. This is to prevent problems
* relating to transferring off-line CPUs. Instead rely
* on the POOL_DESTROY ioctl to transfer the CPUS.
*/
#ifdef DEBUG
dprintf("log_item_commit: POOL_XTRANSFER, ioctl "
"failed\n");
#endif /* DEBUG */
return (PO_FAIL);
}
break;
case POOL_PROPPUT:
}
/*
* Some properties, e.g. pset.size, are read-only in the
* kernel and attempting to change them will fail and cause
* problems. Although this property is read-only through the
* public interface, the library needs to modify it's value.
*/
return (PO_FAIL);
}
}
break;
case POOL_PROPRM:
}
return (PO_FAIL);
}
break;
default:
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* Undo an individual transaction log item(). This processing is
* essential to the pool_conf_commit() and pool_conf_rollback()
* logic. Changes to the libpool snapshot and the kernel are carried
* out separately. The library snapshot is updated synchronously,
* however the kernel update is delayed until the user calls
* pool_conf_commit().
*
* When undoing transactions, library changes will be undone unless
* this invocation is as a result of a commit failure, in which case
* the log state will be LS_RECOVER. Kernel changes will only be
* undone if they are marked as having been done, in which case the
* log item state will be LS_UNDO.
*/
int
{
int ret;
case POOL_CREATE:
#ifdef DEBUG
dprintf("log_item_undo: POOL_CREATE\n");
#endif /* DEBUG */
PO_TRUE);
break;
case POOL_DESTROY:
break;
case POOL_ASSOC:
break;
case POOL_DISSOC:
break;
case POOL_TRANSFER:
return (PO_FAIL);
/* NOTREACHED */
break;
case POOL_XTRANSFER:
return (PO_FAIL);
}
/*
* Maintain the library view of the size
*/
&src_size) != PO_SUCCESS ||
&tgt_size) != PO_SUCCESS) {
return (PO_FAIL);
}
src_size++;
tgt_size--;
c_size_prop, &val);
c_size_prop, &val);
}
break;
case POOL_PROPPUT:
if (nvlist_merge(
!= 0) {
return (PO_FAIL);
}
} else {
return (PO_FAIL);
}
NULL);
(void) nvlist_remove_all(((pool_knl_elem_t *)
nvpair_name(pair));
}
}
break;
case POOL_PROPRM:
return (PO_FAIL);
}
}
break;
default:
return (PO_FAIL);
}
}
/*
* Only try to undo the state of the kernel if we modified it.
*/
return (PO_SUCCESS);
}
case POOL_CREATE:
;
if (ret < 0) {
return (PO_FAIL);
}
break;
case POOL_DESTROY:
return (PO_FAIL);
}
return (PO_FAIL);
}
return (PO_FAIL);
}
(void) nvlist_add_int64(
return (PO_FAIL);
}
/*
* Now we need to reset all the properties and
* associations in the kernel for this newly created
* replacement.
*/
/*
* Remove the read-only properties before attempting
* to restore the state of the newly created property
*/
pke_properties, &tmplist, 0);
}
return (PO_FAIL);
}
return (PO_FAIL);
}
/*
* Now reset the associations for all the resource
* types if the thing which we are recreating is a
* pool
*
* TODO: This is resource specific and must be
* extended for additional resource types.
*/
return (PO_FAIL);
}
}
break;
case POOL_ASSOC:
;
if (ret < 0) {
return (PO_FAIL);
}
break;
case POOL_DISSOC:
;
if (ret < 0) {
return (PO_FAIL);
}
break;
case POOL_TRANSFER:
return (PO_FAIL);
/* NOTREACHED */
break;
case POOL_XTRANSFER:
sizeof (pool_xtransfer_t));
return (PO_FAIL);
}
break;
case POOL_PROPPUT:
sizeof (pool_propput_t));
NV_ENCODE_NATIVE, 0) != 0) {
return (PO_FAIL);
}
&u_propput) < 0) {
return (PO_FAIL);
}
} else {
if (nvlist_unpack(propput->
return (PO_FAIL);
}
NULL);
&u_proprm) < 0) {
return (PO_FAIL);
}
}
}
}
break;
case POOL_PROPRM:
/*
* Only try to remove the appropriate property
*/
0) {
return (PO_FAIL);
}
return (PO_FAIL);
if (nvlist_pack(tmplist,
NV_ENCODE_NATIVE, 0) != 0) {
return (PO_FAIL);
}
return (PO_FAIL);
}
break;
default:
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* A log item stores state about the transaction it represents. This
* function releases the resources associated with the transaction and
* used to store the transaction state.
*/
int
{
case POOL_CREATE:
break;
case POOL_DESTROY:
#ifdef DEBUG
dprintf("log_item_release: POOL_DESTROY\n");
#endif /* DEBUG */
#ifdef DEBUG
#endif /* DEBUG */
}
break;
case POOL_ASSOC:
break;
case POOL_DISSOC:
break;
case POOL_TRANSFER:
return (PO_FAIL);
/* NOTREACHED */
break;
case POOL_XTRANSFER:
break;
case POOL_PROPPUT:
break;
case POOL_PROPRM:
break;
default:
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* pool_knl_nvlist_add_value() adds a pool_value_t to an nvlist.
*/
int
const pool_value_t *pv)
{
double dval;
const char *sval;
char *nv_name;
return (PO_FAIL);
}
switch (type) {
case POC_UINT:
return (PO_FAIL);
}
return (PO_FAIL);
}
break;
case POC_INT:
return (PO_FAIL);
}
return (PO_FAIL);
}
break;
case POC_DOUBLE:
return (PO_FAIL);
}
/*
* Since there is no support for doubles in the
* kernel, store the double value in a byte array.
*/
sizeof (double)) != 0) {
return (PO_FAIL);
}
break;
case POC_BOOL:
return (PO_FAIL);
}
return (PO_FAIL);
}
break;
case POC_STRING:
return (PO_FAIL);
}
return (PO_FAIL);
}
break;
default:
return (PO_FAIL);
}
return (PO_SUCCESS);
}
/*
* hash_id() hashes all elements in a pool configuration using the
* "sys_id" property. Not all elements have a "sys_id" property,
* however elem_get_sysid() caters for this by always returning a
* constant value for those elements. This isn't anticipated to lead
* to a performance degradation in the hash, since those elements
* which are likely to be most prevalent in a configuration do have
* "sys_id" as a property.
*/
{
}
/*
* blocking_open() guarantees access to the pool device, if open()
* is failing with EBUSY.
*/
int
{
int fd;
return (fd);
}