10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53247Sgjelinek * Common Development and Distribution License (the "License").
63247Sgjelinek * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*11411SSurya.Prakki@Sun.COM
220Sstevel@tonic-gate /*
23*11411SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <assert.h>
280Sstevel@tonic-gate #include <errno.h>
290Sstevel@tonic-gate #include <exacct.h>
300Sstevel@tonic-gate #include <fcntl.h>
310Sstevel@tonic-gate #include <libnvpair.h>
320Sstevel@tonic-gate #include <limits.h>
330Sstevel@tonic-gate #include <poll.h>
340Sstevel@tonic-gate #include <pool.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <string.h>
380Sstevel@tonic-gate #include <strings.h>
390Sstevel@tonic-gate #include <stropts.h>
400Sstevel@tonic-gate #include <thread.h>
410Sstevel@tonic-gate #include <time.h>
420Sstevel@tonic-gate #include <unistd.h>
430Sstevel@tonic-gate
440Sstevel@tonic-gate #include <libxml/tree.h>
450Sstevel@tonic-gate
460Sstevel@tonic-gate #include <sys/mman.h>
470Sstevel@tonic-gate #include <sys/pool.h>
480Sstevel@tonic-gate #include <sys/pool_impl.h>
490Sstevel@tonic-gate #include <sys/priocntl.h>
500Sstevel@tonic-gate #include <sys/stat.h>
510Sstevel@tonic-gate #include <sys/time.h>
520Sstevel@tonic-gate #include <sys/types.h>
530Sstevel@tonic-gate
540Sstevel@tonic-gate #include "dict.h"
550Sstevel@tonic-gate
560Sstevel@tonic-gate #include "pool_internal.h"
570Sstevel@tonic-gate #include "pool_impl.h"
580Sstevel@tonic-gate #include "pool_kernel_impl.h"
590Sstevel@tonic-gate
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate * libpool kernel Manipulation Routines
620Sstevel@tonic-gate *
630Sstevel@tonic-gate * pool_kernel.c implements the kernel manipulation routines used by the
640Sstevel@tonic-gate * libpool kernel datastore. The functions are grouped into the following
650Sstevel@tonic-gate * logical areas
660Sstevel@tonic-gate *
670Sstevel@tonic-gate */
680Sstevel@tonic-gate
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate * Device snapshot transfer buffer size
710Sstevel@tonic-gate */
720Sstevel@tonic-gate #define KERNEL_SNAPSHOT_BUF_SZ 65535
730Sstevel@tonic-gate
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate * Kernel result set's initial size. 8 is probably large enough for
760Sstevel@tonic-gate * most queries. Queries requiring more space are accomodated using
770Sstevel@tonic-gate * realloc on a per result set basis.
780Sstevel@tonic-gate */
790Sstevel@tonic-gate #define KERNEL_RS_INITIAL_SZ 8
800Sstevel@tonic-gate
810Sstevel@tonic-gate /*
820Sstevel@tonic-gate * Property manipulation macros
830Sstevel@tonic-gate */
840Sstevel@tonic-gate #define KERNEL_PROP_RDONLY 0x1
850Sstevel@tonic-gate
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate * Information required to evaluate qualifying elements for a query
880Sstevel@tonic-gate */
890Sstevel@tonic-gate struct query_obj {
900Sstevel@tonic-gate const pool_conf_t *conf;
910Sstevel@tonic-gate const pool_elem_t *src;
920Sstevel@tonic-gate const char *src_attr;
930Sstevel@tonic-gate pool_elem_class_t classes;
940Sstevel@tonic-gate pool_value_t **props;
950Sstevel@tonic-gate pool_knl_result_set_t *rs;
960Sstevel@tonic-gate };
970Sstevel@tonic-gate
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate * Identifies a pool element with a processor set id
1000Sstevel@tonic-gate */
1010Sstevel@tonic-gate typedef struct pool_set_xref {
1020Sstevel@tonic-gate pool_knl_pool_t *psx_pool;
1030Sstevel@tonic-gate uint_t psx_pset_id;
1040Sstevel@tonic-gate struct pool_set_xref *psx_next;
1050Sstevel@tonic-gate } pool_set_xref_t;
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate /*
1080Sstevel@tonic-gate * Controls exacct snapshot load into libpool data structure
1090Sstevel@tonic-gate */
1100Sstevel@tonic-gate typedef struct pool_snap_load {
1110Sstevel@tonic-gate int *psl_changed;
1120Sstevel@tonic-gate pool_set_xref_t *psl_xref;
1130Sstevel@tonic-gate pool_elem_t *psl_system;
1140Sstevel@tonic-gate pool_knl_resource_t *psl_pset;
1150Sstevel@tonic-gate } pool_snap_load_t;
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate * Information about an XML document which is being constructed
1190Sstevel@tonic-gate */
1200Sstevel@tonic-gate struct knl_to_xml {
1210Sstevel@tonic-gate xmlDocPtr ktx_doc;
1220Sstevel@tonic-gate xmlNodePtr ktx_node;
1230Sstevel@tonic-gate };
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate * Undo structure processing. The following structures are all used to
1270Sstevel@tonic-gate * allow changes to the libpool snapshot and kernel following an
1280Sstevel@tonic-gate * unsuccessful commit.
1290Sstevel@tonic-gate */
1300Sstevel@tonic-gate typedef struct pool_create_undo {
1310Sstevel@tonic-gate pool_create_t pcu_ioctl;
1320Sstevel@tonic-gate pool_elem_t *pcu_elem;
1330Sstevel@tonic-gate } pool_create_undo_t;
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate typedef struct pool_destroy_undo {
1360Sstevel@tonic-gate pool_destroy_t pdu_ioctl;
1370Sstevel@tonic-gate pool_elem_t *pdu_elem;
1380Sstevel@tonic-gate } pool_destroy_undo_t;
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate typedef struct pool_assoc_undo {
1410Sstevel@tonic-gate pool_assoc_t pau_ioctl;
1420Sstevel@tonic-gate pool_elem_t *pau_assoc;
1430Sstevel@tonic-gate pool_elem_t *pau_oldres;
1440Sstevel@tonic-gate pool_elem_t *pau_newres;
1450Sstevel@tonic-gate } pool_assoc_undo_t;
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate typedef struct pool_dissoc_undo {
1480Sstevel@tonic-gate pool_dissoc_t pdu_ioctl;
1490Sstevel@tonic-gate pool_elem_t *pdu_dissoc;
1500Sstevel@tonic-gate pool_elem_t *pdu_oldres;
1510Sstevel@tonic-gate pool_elem_t *pdu_newres;
1520Sstevel@tonic-gate } pool_dissoc_undo_t;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate typedef struct pool_xtransfer_undo {
1550Sstevel@tonic-gate pool_xtransfer_t pxu_ioctl;
1560Sstevel@tonic-gate pool_elem_t *pxu_src;
1570Sstevel@tonic-gate pool_elem_t *pxu_tgt;
1580Sstevel@tonic-gate pool_component_t **pxu_rl;
1590Sstevel@tonic-gate } pool_xtransfer_undo_t;
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate typedef struct pool_propput_undo {
1620Sstevel@tonic-gate pool_propput_t ppu_ioctl;
1630Sstevel@tonic-gate pool_elem_t *ppu_elem;
1640Sstevel@tonic-gate nvlist_t *ppu_alist;
1650Sstevel@tonic-gate nvlist_t *ppu_blist;
1660Sstevel@tonic-gate uchar_t ppu_doioctl;
1670Sstevel@tonic-gate } pool_propput_undo_t;
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate typedef struct pool_proprm_undo {
1700Sstevel@tonic-gate pool_proprm_t pru_ioctl;
1710Sstevel@tonic-gate pool_elem_t *pru_elem;
1720Sstevel@tonic-gate pool_value_t pru_oldval;
1730Sstevel@tonic-gate } pool_proprm_undo_t;
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate extern const char *dtd_location;
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate extern const char *element_class_tags[];
1780Sstevel@tonic-gate extern const char pool_info_location[];
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /*
1810Sstevel@tonic-gate * These functions are defined in pool_xml.c and represent the minimum
1820Sstevel@tonic-gate * XML support required to allow a pool kernel configuration to be
1830Sstevel@tonic-gate * exported as an XML document.
1840Sstevel@tonic-gate */
1850Sstevel@tonic-gate extern int pool_xml_set_attr(xmlNodePtr, xmlChar *, const pool_value_t *);
1860Sstevel@tonic-gate extern int pool_xml_set_prop(xmlNodePtr, xmlChar *, const pool_value_t *);
1870Sstevel@tonic-gate extern void xml_init(void);
1880Sstevel@tonic-gate extern xmlNodePtr node_create(xmlNodePtr, const xmlChar *);
1890Sstevel@tonic-gate extern void pool_error_func(void *, const char *, ...);
1900Sstevel@tonic-gate /*
1910Sstevel@tonic-gate * Utilities
1920Sstevel@tonic-gate */
1930Sstevel@tonic-gate static int load_group(pool_conf_t *, pool_knl_elem_t *, ea_object_t *,
1940Sstevel@tonic-gate pool_snap_load_t *);
1950Sstevel@tonic-gate static void pool_knl_elem_free(pool_knl_elem_t *, int);
1960Sstevel@tonic-gate static int pool_knl_put_xml_property(pool_elem_t *, xmlNodePtr, const char *,
1970Sstevel@tonic-gate const pool_value_t *);
1980Sstevel@tonic-gate static int pool_knl_snap_load_push(pool_snap_load_t *, pool_knl_pool_t *);
1990Sstevel@tonic-gate static int pool_knl_snap_load_update(pool_snap_load_t *, int, uint_t);
2000Sstevel@tonic-gate static int pool_knl_snap_load_remove(pool_snap_load_t *, int, uint_t);
2010Sstevel@tonic-gate static nvpair_t *pool_knl_find_nvpair(nvlist_t *, const char *);
2020Sstevel@tonic-gate static int pool_knl_nvlist_add_value(nvlist_t *, const char *,
2030Sstevel@tonic-gate const pool_value_t *);
2040Sstevel@tonic-gate static int pool_knl_recover(pool_conf_t *);
2050Sstevel@tonic-gate static uint64_t hash_id(const pool_elem_t *);
2060Sstevel@tonic-gate static int blocking_open(const char *, int);
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate /*
2090Sstevel@tonic-gate * Connections
2100Sstevel@tonic-gate */
2110Sstevel@tonic-gate static void pool_knl_connection_free(pool_knl_connection_t *);
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate * Configuration
2150Sstevel@tonic-gate */
2160Sstevel@tonic-gate static int pool_knl_close(pool_conf_t *);
2170Sstevel@tonic-gate static int pool_knl_validate(const pool_conf_t *, pool_valid_level_t);
2180Sstevel@tonic-gate static int pool_knl_commit(pool_conf_t *);
2190Sstevel@tonic-gate static int pool_knl_export(const pool_conf_t *, const char *,
2200Sstevel@tonic-gate pool_export_format_t);
2210Sstevel@tonic-gate static int pool_knl_rollback(pool_conf_t *);
2220Sstevel@tonic-gate static pool_result_set_t *pool_knl_exec_query(const pool_conf_t *,
2230Sstevel@tonic-gate const pool_elem_t *, const char *, pool_elem_class_t, pool_value_t **);
2240Sstevel@tonic-gate static int pool_knl_remove(pool_conf_t *);
2250Sstevel@tonic-gate static char *pool_knl_get_binding(pool_conf_t *, pid_t);
2260Sstevel@tonic-gate static int pool_knl_set_binding(pool_conf_t *, const char *, idtype_t, id_t);
2270Sstevel@tonic-gate static char *pool_knl_get_resource_binding(pool_conf_t *,
2280Sstevel@tonic-gate pool_resource_elem_class_t, pid_t);
2290Sstevel@tonic-gate static int pool_knl_res_transfer(pool_resource_t *, pool_resource_t *,
2300Sstevel@tonic-gate uint64_t);
2310Sstevel@tonic-gate static int pool_knl_res_xtransfer(pool_resource_t *, pool_resource_t *,
2320Sstevel@tonic-gate pool_component_t **);
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate * Result Sets
2360Sstevel@tonic-gate */
2370Sstevel@tonic-gate static pool_knl_result_set_t *pool_knl_result_set_alloc(const pool_conf_t *);
2380Sstevel@tonic-gate static int pool_knl_result_set_append(pool_knl_result_set_t *,
2390Sstevel@tonic-gate pool_knl_elem_t *);
2400Sstevel@tonic-gate static int pool_knl_result_set_realloc(pool_knl_result_set_t *);
2410Sstevel@tonic-gate static void pool_knl_result_set_free(pool_knl_result_set_t *);
2420Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_next(pool_result_set_t *);
2430Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_prev(pool_result_set_t *);
2440Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_first(pool_result_set_t *);
2450Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_last(pool_result_set_t *);
2460Sstevel@tonic-gate static int pool_knl_rs_set_index(pool_result_set_t *, int);
2470Sstevel@tonic-gate static int pool_knl_rs_get_index(pool_result_set_t *);
2480Sstevel@tonic-gate static int pool_knl_rs_count(pool_result_set_t *);
2490Sstevel@tonic-gate static int pool_knl_rs_close(pool_result_set_t *);
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate * Element (and sub-type)
2530Sstevel@tonic-gate */
2540Sstevel@tonic-gate static pool_knl_elem_t *pool_knl_elem_wrap(pool_conf_t *, pool_elem_class_t,
2550Sstevel@tonic-gate pool_resource_elem_class_t, pool_component_elem_class_t);
2560Sstevel@tonic-gate static pool_elem_t *pool_knl_elem_create(pool_conf_t *, pool_elem_class_t,
2570Sstevel@tonic-gate pool_resource_elem_class_t, pool_component_elem_class_t);
2580Sstevel@tonic-gate static int pool_knl_elem_remove(pool_elem_t *);
2590Sstevel@tonic-gate static int pool_knl_set_container(pool_elem_t *, pool_elem_t *);
2600Sstevel@tonic-gate static pool_elem_t *pool_knl_get_container(const pool_elem_t *);
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate * Pool element specific
2630Sstevel@tonic-gate */
2640Sstevel@tonic-gate static int pool_knl_pool_associate(pool_t *, const pool_resource_t *);
2650Sstevel@tonic-gate static int pool_knl_pool_dissociate(pool_t *, const pool_resource_t *);
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate /*
2680Sstevel@tonic-gate * Resource elements specific
2690Sstevel@tonic-gate */
2700Sstevel@tonic-gate static int pool_knl_resource_is_system(const pool_resource_t *);
2710Sstevel@tonic-gate static int pool_knl_resource_can_associate(const pool_resource_t *);
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate /* Properties */
2740Sstevel@tonic-gate static pool_value_class_t pool_knl_get_property(const pool_elem_t *,
2750Sstevel@tonic-gate const char *, pool_value_t *);
2760Sstevel@tonic-gate static pool_value_class_t pool_knl_get_dynamic_property(const pool_elem_t *,
2770Sstevel@tonic-gate const char *, pool_value_t *);
2780Sstevel@tonic-gate static int pool_knl_put_property(pool_elem_t *, const char *,
2790Sstevel@tonic-gate const pool_value_t *);
2800Sstevel@tonic-gate static int pool_knl_rm_property(pool_elem_t *, const char *);
2810Sstevel@tonic-gate static pool_value_t **pool_knl_get_properties(const pool_elem_t *, uint_t *);
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate /*
2840Sstevel@tonic-gate * Logging
2850Sstevel@tonic-gate */
2860Sstevel@tonic-gate static int log_item_commit(log_item_t *);
2870Sstevel@tonic-gate static int log_item_undo(log_item_t *);
2880Sstevel@tonic-gate static int log_item_release(log_item_t *);
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate /*
2910Sstevel@tonic-gate * Utilities
2920Sstevel@tonic-gate */
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate /*
2950Sstevel@tonic-gate * load_group() updates the library configuration with the kernel
2960Sstevel@tonic-gate * snapshot supplied in ep. The function is designed to be called
2970Sstevel@tonic-gate * recursively. This function depends implicitly on the ordering of
2980Sstevel@tonic-gate * the data provided in ep. Changes to the ordering of data in ep must
2990Sstevel@tonic-gate * be matched by changes to this function.
3000Sstevel@tonic-gate */
3010Sstevel@tonic-gate int
load_group(pool_conf_t * conf,pool_knl_elem_t * elem,ea_object_t * ep,pool_snap_load_t * psl)3020Sstevel@tonic-gate load_group(pool_conf_t *conf, pool_knl_elem_t *elem, ea_object_t *ep,
3030Sstevel@tonic-gate pool_snap_load_t *psl)
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate ea_object_t *eo;
3060Sstevel@tonic-gate pool_knl_elem_t *old_elem;
3070Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
3080Sstevel@tonic-gate int ret = PO_SUCCESS;
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate if ((ep->eo_catalog & EXD_DATA_MASK) == EXD_GROUP_SYSTEM) {
3110Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, PEC_SYSTEM, PREC_INVALID,
3120Sstevel@tonic-gate PCEC_INVALID)) == NULL)
3130Sstevel@tonic-gate return (PO_FAIL);
3140Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties, NV_UNIQUE_NAME_TYPE,
3150Sstevel@tonic-gate 0) != 0) {
3160Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE);
3170Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
3180Sstevel@tonic-gate return (PO_FAIL);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate /*
3210Sstevel@tonic-gate * Check to see if we already have an element
3220Sstevel@tonic-gate * for this data. If we have, free the newly
3230Sstevel@tonic-gate * created elem and continue with the old one
3240Sstevel@tonic-gate */
3250Sstevel@tonic-gate if ((old_elem = dict_get(prov->pkc_elements, elem)) != NULL) {
3260Sstevel@tonic-gate nvlist_free(old_elem->pke_properties);
3270Sstevel@tonic-gate old_elem->pke_properties = elem->pke_properties;
3280Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE);
3290Sstevel@tonic-gate elem = old_elem;
3300Sstevel@tonic-gate } else {
3310Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) != NULL) {
3320Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
3330Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
3340Sstevel@tonic-gate return (PO_FAIL);
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate psl->psl_system = (pool_elem_t *)elem;
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate for (eo = ep->eo_group.eg_objs; eo != NULL; eo = eo->eo_next) {
3410Sstevel@tonic-gate int data;
3420Sstevel@tonic-gate pool_knl_elem_t *prop_elem = NULL;
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate data = (eo->eo_catalog & EXD_DATA_MASK);
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate switch (data) {
3470Sstevel@tonic-gate case EXD_SYSTEM_TSTAMP:
3480Sstevel@tonic-gate case EXD_POOL_TSTAMP:
3490Sstevel@tonic-gate case EXD_PSET_TSTAMP:
3500Sstevel@tonic-gate case EXD_CPU_TSTAMP:
3510Sstevel@tonic-gate if (eo->eo_item.ei_uint64 > prov->pkc_lotime) {
3520Sstevel@tonic-gate if (eo->eo_item.ei_uint64 > prov->pkc_ltime)
3530Sstevel@tonic-gate prov->pkc_ltime = eo->eo_item.ei_uint64;
3540Sstevel@tonic-gate if (psl->psl_changed) {
3550Sstevel@tonic-gate switch (data) {
3560Sstevel@tonic-gate case EXD_SYSTEM_TSTAMP:
3570Sstevel@tonic-gate *psl->psl_changed |= POU_SYSTEM;
3580Sstevel@tonic-gate break;
3590Sstevel@tonic-gate case EXD_POOL_TSTAMP:
3600Sstevel@tonic-gate *psl->psl_changed |= POU_POOL;
3610Sstevel@tonic-gate break;
3620Sstevel@tonic-gate case EXD_PSET_TSTAMP:
3630Sstevel@tonic-gate *psl->psl_changed |= POU_PSET;
3640Sstevel@tonic-gate break;
3650Sstevel@tonic-gate case EXD_CPU_TSTAMP:
3660Sstevel@tonic-gate *psl->psl_changed |= POU_CPU;
3670Sstevel@tonic-gate break;
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate break;
3720Sstevel@tonic-gate case EXD_SYSTEM_PROP:
3730Sstevel@tonic-gate case EXD_POOL_PROP:
3740Sstevel@tonic-gate case EXD_PSET_PROP:
3750Sstevel@tonic-gate case EXD_CPU_PROP:
3760Sstevel@tonic-gate if (data == EXD_PSET_PROP) {
3770Sstevel@tonic-gate prop_elem = elem;
3780Sstevel@tonic-gate elem = (pool_knl_elem_t *)psl->psl_pset;
3790Sstevel@tonic-gate }
3800Sstevel@tonic-gate nvlist_free(elem->pke_properties);
3810Sstevel@tonic-gate if (nvlist_unpack(eo->eo_item.ei_raw,
3820Sstevel@tonic-gate eo->eo_item.ei_size, &elem->pke_properties, 0) !=
3830Sstevel@tonic-gate 0) {
3840Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
3850Sstevel@tonic-gate return (PO_FAIL);
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate elem->pke_ltime = prov->pkc_ltime;
3880Sstevel@tonic-gate if (data == EXD_PSET_PROP) {
3890Sstevel@tonic-gate elem = prop_elem;
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate break;
3920Sstevel@tonic-gate case EXD_POOL_POOLID:
3930Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties,
3940Sstevel@tonic-gate NV_UNIQUE_NAME_TYPE, 0) != 0) {
3950Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
3960Sstevel@tonic-gate return (PO_FAIL);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate if (nvlist_add_int64(elem->pke_properties,
3990Sstevel@tonic-gate "pool.sys_id",
4000Sstevel@tonic-gate (int64_t)eo->eo_item.ei_uint32) != 0) {
4010Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4020Sstevel@tonic-gate return (PO_FAIL);
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
4050Sstevel@tonic-gate NULL) {
4060Sstevel@tonic-gate nvlist_free(old_elem->pke_properties);
4070Sstevel@tonic-gate old_elem->pke_properties = elem->pke_properties;
4080Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE);
4090Sstevel@tonic-gate elem = old_elem;
4100Sstevel@tonic-gate } else {
4110Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) !=
4120Sstevel@tonic-gate NULL) {
4130Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
4140Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4150Sstevel@tonic-gate return (PO_FAIL);
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate if (pool_knl_snap_load_push(psl,
4190Sstevel@tonic-gate (pool_knl_pool_t *)elem) != PO_SUCCESS) {
4200Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4210Sstevel@tonic-gate return (PO_FAIL);
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate ((pool_knl_pool_t *)elem)->pkp_assoc[PREC_PSET] = NULL;
4240Sstevel@tonic-gate break;
4250Sstevel@tonic-gate case EXD_POOL_PSETID:
4260Sstevel@tonic-gate if (pool_knl_snap_load_update(psl, EXD_POOL_PSETID,
4270Sstevel@tonic-gate eo->eo_item.ei_uint32) != PO_SUCCESS) {
4280Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4290Sstevel@tonic-gate return (PO_FAIL);
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate break;
4320Sstevel@tonic-gate case EXD_PSET_PSETID:
4330Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties,
4340Sstevel@tonic-gate NV_UNIQUE_NAME_TYPE, 0) != 0) {
4350Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4360Sstevel@tonic-gate return (PO_FAIL);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate if (nvlist_add_int64(elem->pke_properties,
4390Sstevel@tonic-gate "pset.sys_id",
4400Sstevel@tonic-gate (int64_t)eo->eo_item.ei_uint32) != 0) {
4410Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4420Sstevel@tonic-gate return (PO_FAIL);
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
4450Sstevel@tonic-gate NULL) {
4460Sstevel@tonic-gate nvlist_free(old_elem->pke_properties);
4470Sstevel@tonic-gate old_elem->pke_properties = elem->pke_properties;
4480Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE);
4490Sstevel@tonic-gate elem = old_elem;
4500Sstevel@tonic-gate } else {
4510Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) !=
4520Sstevel@tonic-gate NULL) {
4530Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
4540Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4550Sstevel@tonic-gate return (PO_FAIL);
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate psl->psl_pset = (pool_knl_resource_t *)elem;
4590Sstevel@tonic-gate if (pool_knl_snap_load_remove(psl, data,
4600Sstevel@tonic-gate eo->eo_item.ei_uint32) != PO_SUCCESS) {
4610Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4620Sstevel@tonic-gate return (PO_FAIL);
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate break;
4650Sstevel@tonic-gate case EXD_CPU_CPUID:
4660Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties,
4670Sstevel@tonic-gate NV_UNIQUE_NAME_TYPE, 0) != 0) {
4680Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4690Sstevel@tonic-gate return (PO_FAIL);
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate if (nvlist_add_int64(elem->pke_properties,
4720Sstevel@tonic-gate "cpu.sys_id",
4730Sstevel@tonic-gate (int64_t)eo->eo_item.ei_uint32) != 0) {
4740Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4750Sstevel@tonic-gate return (PO_FAIL);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
4780Sstevel@tonic-gate NULL) {
4790Sstevel@tonic-gate nvlist_free(old_elem->pke_properties);
4800Sstevel@tonic-gate old_elem->pke_properties = elem->pke_properties;
4810Sstevel@tonic-gate old_elem->pke_parent = elem->pke_parent;
4820Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE);
4830Sstevel@tonic-gate elem = old_elem;
4840Sstevel@tonic-gate } else {
4850Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) !=
4860Sstevel@tonic-gate NULL) {
4870Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
4880Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
4890Sstevel@tonic-gate return (PO_FAIL);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate break;
4930Sstevel@tonic-gate case EXD_GROUP_POOL:
4940Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, PEC_POOL,
4950Sstevel@tonic-gate PREC_INVALID, PCEC_INVALID)) == NULL)
4960Sstevel@tonic-gate return (PO_FAIL);
4970Sstevel@tonic-gate if (pool_set_container(psl->psl_system,
4980Sstevel@tonic-gate (pool_elem_t *)elem) != PO_SUCCESS) {
4990Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
5000Sstevel@tonic-gate return (PO_FAIL);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate break;
5030Sstevel@tonic-gate case EXD_GROUP_PSET:
5040Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, PEC_RES_COMP,
5050Sstevel@tonic-gate PREC_PSET, PCEC_INVALID)) == NULL)
5060Sstevel@tonic-gate return (PO_FAIL);
5070Sstevel@tonic-gate if (pool_set_container(psl->psl_system,
5080Sstevel@tonic-gate (pool_elem_t *)elem) != PO_SUCCESS) {
5090Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
5100Sstevel@tonic-gate return (PO_FAIL);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate break;
5130Sstevel@tonic-gate case EXD_GROUP_CPU:
5140Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, PEC_COMP,
5150Sstevel@tonic-gate PREC_INVALID, PCEC_CPU)) == NULL)
5160Sstevel@tonic-gate return (PO_FAIL);
5170Sstevel@tonic-gate if (pool_set_container((pool_elem_t *)psl->psl_pset,
5180Sstevel@tonic-gate (pool_elem_t *)elem) != PO_SUCCESS) {
5190Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
5200Sstevel@tonic-gate return (PO_FAIL);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate break;
5230Sstevel@tonic-gate default:
5240Sstevel@tonic-gate break;
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate if (eo->eo_type == EO_GROUP) {
5290Sstevel@tonic-gate if ((ret = load_group(conf, elem, eo, psl)) == PO_FAIL)
5300Sstevel@tonic-gate break;
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate return (ret);
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate /*
5370Sstevel@tonic-gate * Push a snapshot entry onto the list of pools in the snapshot.
5380Sstevel@tonic-gate */
5390Sstevel@tonic-gate int
pool_knl_snap_load_push(pool_snap_load_t * psl,pool_knl_pool_t * pkp)5400Sstevel@tonic-gate pool_knl_snap_load_push(pool_snap_load_t *psl, pool_knl_pool_t *pkp)
5410Sstevel@tonic-gate {
5420Sstevel@tonic-gate pool_set_xref_t *psx;
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate if ((psx = malloc(sizeof (pool_set_xref_t))) == NULL) {
5450Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
5460Sstevel@tonic-gate return (PO_FAIL);
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate (void) memset(psx, 0, sizeof (pool_set_xref_t));
5490Sstevel@tonic-gate psx->psx_pool = pkp;
5500Sstevel@tonic-gate /*
5510Sstevel@tonic-gate * Push onto the list of pools
5520Sstevel@tonic-gate */
5530Sstevel@tonic-gate psx->psx_next = psl->psl_xref;
5540Sstevel@tonic-gate psl->psl_xref = psx;
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate return (PO_SUCCESS);
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate * Update the current cross-reference for the supplied type of
5610Sstevel@tonic-gate * resource.
5620Sstevel@tonic-gate */
5630Sstevel@tonic-gate int
pool_knl_snap_load_update(pool_snap_load_t * psl,int type,uint_t id)5640Sstevel@tonic-gate pool_knl_snap_load_update(pool_snap_load_t *psl, int type, uint_t id)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate switch (type) {
5670Sstevel@tonic-gate case EXD_POOL_PSETID:
5680Sstevel@tonic-gate psl->psl_xref->psx_pset_id = id;
5690Sstevel@tonic-gate break;
5700Sstevel@tonic-gate default:
5710Sstevel@tonic-gate return (PO_FAIL);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate return (PO_SUCCESS);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate /*
5780Sstevel@tonic-gate * Remove a resource entry with the supplied type and id from the
5790Sstevel@tonic-gate * snapshot list when it is no longer required.
5800Sstevel@tonic-gate */
5810Sstevel@tonic-gate int
pool_knl_snap_load_remove(pool_snap_load_t * psl,int type,uint_t id)5820Sstevel@tonic-gate pool_knl_snap_load_remove(pool_snap_load_t *psl, int type, uint_t id)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate pool_set_xref_t *current, *prev, *next;
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate for (prev = NULL, current = psl->psl_xref; current != NULL;
5870Sstevel@tonic-gate current = next) {
5880Sstevel@tonic-gate switch (type) {
5890Sstevel@tonic-gate case EXD_PSET_PSETID:
5900Sstevel@tonic-gate if (current->psx_pset_id == id)
5910Sstevel@tonic-gate current->psx_pool->pkp_assoc[PREC_PSET] =
5920Sstevel@tonic-gate psl->psl_pset;
5930Sstevel@tonic-gate break;
5940Sstevel@tonic-gate default:
5950Sstevel@tonic-gate return (PO_FAIL);
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate next = current->psx_next;
5980Sstevel@tonic-gate if (current->psx_pool->pkp_assoc[PREC_PSET] != NULL) {
5990Sstevel@tonic-gate if (prev != NULL) {
6000Sstevel@tonic-gate prev->psx_next = current->psx_next;
6010Sstevel@tonic-gate } else {
6020Sstevel@tonic-gate psl->psl_xref = current->psx_next;
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate free(current);
6050Sstevel@tonic-gate } else
6060Sstevel@tonic-gate prev = current;
6070Sstevel@tonic-gate }
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate return (PO_SUCCESS);
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate
6120Sstevel@tonic-gate /*
6130Sstevel@tonic-gate * Return the nvpair with the supplied name from the supplied list.
6140Sstevel@tonic-gate *
6150Sstevel@tonic-gate * NULL is returned if the name cannot be found in the list.
6160Sstevel@tonic-gate */
6170Sstevel@tonic-gate nvpair_t *
pool_knl_find_nvpair(nvlist_t * l,const char * name)6180Sstevel@tonic-gate pool_knl_find_nvpair(nvlist_t *l, const char *name)
6190Sstevel@tonic-gate {
6200Sstevel@tonic-gate nvpair_t *pair;
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate for (pair = nvlist_next_nvpair(l, NULL); pair != NULL;
623*11411SSurya.Prakki@Sun.COM pair = nvlist_next_nvpair(l, pair)) {
6240Sstevel@tonic-gate if (strcmp(nvpair_name(pair), name) == 0)
6250Sstevel@tonic-gate break;
6260Sstevel@tonic-gate }
6270Sstevel@tonic-gate return (pair);
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate /*
6310Sstevel@tonic-gate * Close the configuration. There are a few steps to closing a configuration:
6320Sstevel@tonic-gate * - Close the pseudo device
6330Sstevel@tonic-gate * - Free the data provider
6340Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
6350Sstevel@tonic-gate */
6360Sstevel@tonic-gate int
pool_knl_close(pool_conf_t * conf)6370Sstevel@tonic-gate pool_knl_close(pool_conf_t *conf)
6380Sstevel@tonic-gate {
6390Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate if (close(prov->pkc_fd) < 0) {
6420Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
6430Sstevel@tonic-gate return (PO_FAIL);
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate /*
6460Sstevel@tonic-gate * Rollback any pending changes before freeing the prov. This
6473247Sgjelinek * ensures there are no memory leaks from pending transactions.
6483247Sgjelinek * However, don't rollback when we've done a temporary pool since the
6493247Sgjelinek * pool/resources haven't really been committed in this case.
6503247Sgjelinek * They will all be freed in pool_knl_connection_free and we don't
6513247Sgjelinek * want to double free them.
6520Sstevel@tonic-gate */
6533247Sgjelinek if (!(conf->pc_prov->pc_oflags & PO_TEMP))
6543247Sgjelinek (void) pool_knl_rollback(conf);
6550Sstevel@tonic-gate pool_knl_connection_free(prov);
6560Sstevel@tonic-gate return (PO_SUCCESS);
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate * Remove elements in this map (previously identified as "dead") from
6610Sstevel@tonic-gate * the configuration map (prov->pkc_elements).
6620Sstevel@tonic-gate */
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate /* ARGSUSED1 */
6650Sstevel@tonic-gate static void
remove_dead_elems(const void * key,void ** value,void * cl)6660Sstevel@tonic-gate remove_dead_elems(const void *key, void **value, void *cl)
6670Sstevel@tonic-gate {
6680Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
6690Sstevel@tonic-gate pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
6700Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate assert(dict_remove(prov->pkc_elements, pke) != NULL);
6730Sstevel@tonic-gate #ifdef DEBUG
6740Sstevel@tonic-gate dprintf("remove_dead_elems:\n");
6750Sstevel@tonic-gate pool_elem_dprintf(TO_ELEM(pke));
6760Sstevel@tonic-gate #endif /* DEBUG */
6770Sstevel@tonic-gate pool_knl_elem_free(pke, PO_TRUE);
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate /*
6810Sstevel@tonic-gate * Find elements which were not updated the last time that
6820Sstevel@tonic-gate * load_group() was called. Add those elements into a separate map
6830Sstevel@tonic-gate * (passed in cl) which will be later used to remove these elements
6840Sstevel@tonic-gate * from the configuration map.
6850Sstevel@tonic-gate */
6860Sstevel@tonic-gate /* ARGSUSED1 */
6870Sstevel@tonic-gate static void
find_dead_elems(const void * key,void ** value,void * cl)6880Sstevel@tonic-gate find_dead_elems(const void *key, void **value, void *cl)
6890Sstevel@tonic-gate {
6900Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
6910Sstevel@tonic-gate pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
6920Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
6930Sstevel@tonic-gate dict_hdl_t *dead_map = (dict_hdl_t *)cl;
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate if (pke->pke_ltime < prov->pkc_ltime)
6960Sstevel@tonic-gate (void) dict_put(dead_map, pke, pke);
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate /*
7000Sstevel@tonic-gate * Update the snapshot held by the library. This function acts as the
7010Sstevel@tonic-gate * controller for the snapshot update procedure. Then snapshot is
7020Sstevel@tonic-gate * actually updated in multiple phases by the load_group() function
7030Sstevel@tonic-gate * (which updates existing elements and creates new elements as
7040Sstevel@tonic-gate * required) and then by find_dead_elems and remove_dead_elems
7050Sstevel@tonic-gate * (respectively responsible for identifying elements which are to be
7060Sstevel@tonic-gate * removed and then removing them).
7070Sstevel@tonic-gate *
7080Sstevel@tonic-gate * Returns PO_SUCCESS
7090Sstevel@tonic-gate */
7100Sstevel@tonic-gate int
pool_knl_update(pool_conf_t * conf,int * changed)7110Sstevel@tonic-gate pool_knl_update(pool_conf_t *conf, int *changed)
7120Sstevel@tonic-gate {
7130Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
7140Sstevel@tonic-gate pool_query_t query = {0};
7150Sstevel@tonic-gate ea_object_t *ep;
7160Sstevel@tonic-gate dict_hdl_t *dead_map;
7170Sstevel@tonic-gate pool_snap_load_t psl = { NULL };
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate /*
7200Sstevel@tonic-gate * Ensure the library snapshot is consistent, if there are any
7210Sstevel@tonic-gate * outstanding transactions return failure.
7220Sstevel@tonic-gate */
7230Sstevel@tonic-gate if (log_size(prov->pkc_log) != 0) {
7240Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
7250Sstevel@tonic-gate return (PO_FAIL);
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate /*
7280Sstevel@tonic-gate * Query the kernel for a snapshot of the configuration state. Use
7290Sstevel@tonic-gate * load_group to allocate the user-land representation of the
7300Sstevel@tonic-gate * data returned in the snapshot.
7310Sstevel@tonic-gate */
7320Sstevel@tonic-gate /* LINTED E_CONSTANT_CONDITION */
7330Sstevel@tonic-gate while (1) {
7340Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_QUERY, &query) < 0) {
7350Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
7360Sstevel@tonic-gate return (PO_FAIL);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate if ((query.pq_io_buf = calloc(1,
7390Sstevel@tonic-gate (query.pq_io_bufsize < KERNEL_SNAPSHOT_BUF_SZ) ?
7400Sstevel@tonic-gate query.pq_io_bufsize * 2 : query.pq_io_bufsize)) == NULL) {
7410Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
7420Sstevel@tonic-gate return (PO_FAIL);
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_QUERY, &query) < 0) {
7450Sstevel@tonic-gate free(query.pq_io_buf);
7460Sstevel@tonic-gate if (errno != ENOMEM) {
7470Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
7480Sstevel@tonic-gate return (PO_FAIL);
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate query.pq_io_bufsize = 0;
7510Sstevel@tonic-gate query.pq_io_buf = NULL;
7520Sstevel@tonic-gate } else
7530Sstevel@tonic-gate break;
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate if (ea_unpack_object(&ep, EUP_NOALLOC, query.pq_io_buf,
7560Sstevel@tonic-gate query.pq_io_bufsize) != EO_GROUP) {
7570Sstevel@tonic-gate free(query.pq_io_buf);
7580Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
7590Sstevel@tonic-gate return (PO_FAIL);
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate /*
7620Sstevel@tonic-gate * Update the library snapshot
7630Sstevel@tonic-gate */
7640Sstevel@tonic-gate psl.psl_changed = changed;
7650Sstevel@tonic-gate prov->pkc_lotime = prov->pkc_ltime;
7660Sstevel@tonic-gate if (load_group(conf, NULL, ep, &psl) != PO_SUCCESS) {
7670Sstevel@tonic-gate free(query.pq_io_buf);
7680Sstevel@tonic-gate ea_free_object(ep, EUP_NOALLOC);
7690Sstevel@tonic-gate return (PO_FAIL);
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate free(query.pq_io_buf);
7730Sstevel@tonic-gate ea_free_object(ep, EUP_NOALLOC);
7740Sstevel@tonic-gate /*
7750Sstevel@tonic-gate * Now search the dictionary for items that must be removed because
7760Sstevel@tonic-gate * they were neither created nor updated.
7770Sstevel@tonic-gate */
7780Sstevel@tonic-gate if ((dead_map = dict_new((int (*)(const void *, const void *))
7790Sstevel@tonic-gate pool_elem_compare, (uint64_t (*)(const void *))hash_id)) == NULL) {
7800Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
7810Sstevel@tonic-gate return (PO_FAIL);
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate dict_map(prov->pkc_elements, find_dead_elems, dead_map);
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate if (dict_length(dead_map) > 0) {
7860Sstevel@tonic-gate dict_map(dead_map, remove_dead_elems, NULL);
7870Sstevel@tonic-gate }
7880Sstevel@tonic-gate dict_free(&dead_map);
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate return (PO_SUCCESS);
7910Sstevel@tonic-gate }
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate /*
7940Sstevel@tonic-gate * Rely on the kernel to always keep a kernel configuration valid.
7950Sstevel@tonic-gate * Returns PO_SUCCESS
7960Sstevel@tonic-gate */
7970Sstevel@tonic-gate /* ARGSUSED */
7980Sstevel@tonic-gate int
pool_knl_validate(const pool_conf_t * conf,pool_valid_level_t level)7990Sstevel@tonic-gate pool_knl_validate(const pool_conf_t *conf, pool_valid_level_t level)
8000Sstevel@tonic-gate {
8010Sstevel@tonic-gate return ((conf->pc_state == POF_INVALID) ? PO_FAIL : PO_SUCCESS);
8020Sstevel@tonic-gate }
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate /*
8050Sstevel@tonic-gate * Process all the outstanding transactions in the log. If the processing
8060Sstevel@tonic-gate * fails, then attempt to rollback and "undo" the changes.
8070Sstevel@tonic-gate */
8080Sstevel@tonic-gate int
pool_knl_commit(pool_conf_t * conf)8090Sstevel@tonic-gate pool_knl_commit(pool_conf_t *conf)
8100Sstevel@tonic-gate {
8110Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
8120Sstevel@tonic-gate int lock = 1;
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate * Lock the kernel state for the commit
8160Sstevel@tonic-gate */
8170Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_COMMIT, lock) < 0) {
8180Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
8190Sstevel@tonic-gate return (PO_FAIL);
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate lock = 0;
8220Sstevel@tonic-gate /*
8230Sstevel@tonic-gate * If the state is LS_FAIL, then try to recover before
8240Sstevel@tonic-gate * performing the commit.
8250Sstevel@tonic-gate */
8260Sstevel@tonic-gate if (prov->pkc_log->l_state == LS_FAIL) {
8270Sstevel@tonic-gate if (pool_knl_recover(conf) == PO_FAIL) {
8280Sstevel@tonic-gate /*
8290Sstevel@tonic-gate * Unlock the kernel state for the
8300Sstevel@tonic-gate * commit. Assert that this * can't fail,
8310Sstevel@tonic-gate * since if it ever does fail the library is
8320Sstevel@tonic-gate * unusable.
8330Sstevel@tonic-gate */
8340Sstevel@tonic-gate assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate }
8370Sstevel@tonic-gate /*
8380Sstevel@tonic-gate * Commit the log
8390Sstevel@tonic-gate */
8400Sstevel@tonic-gate if (log_walk(prov->pkc_log, log_item_commit) != PO_SUCCESS) {
8410Sstevel@tonic-gate (void) pool_knl_recover(conf);
8420Sstevel@tonic-gate /*
8430Sstevel@tonic-gate * Unlock the kernel state for the commit. Assert that
8440Sstevel@tonic-gate * this can't fail, since if it ever does fail the
8450Sstevel@tonic-gate * library is unusable.
8460Sstevel@tonic-gate */
8470Sstevel@tonic-gate assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
8480Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
8490Sstevel@tonic-gate return (PO_FAIL);
8500Sstevel@tonic-gate }
8510Sstevel@tonic-gate /*
8520Sstevel@tonic-gate * Unlock the kernel state for the commit. Assert that this
8530Sstevel@tonic-gate * can't fail, since if it ever does fail the library is
8540Sstevel@tonic-gate * unusable.
8550Sstevel@tonic-gate */
8560Sstevel@tonic-gate assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
8570Sstevel@tonic-gate /*
8580Sstevel@tonic-gate * Release the log resources
8590Sstevel@tonic-gate */
8600Sstevel@tonic-gate (void) log_walk(prov->pkc_log, log_item_release);
8610Sstevel@tonic-gate log_empty(prov->pkc_log);
8620Sstevel@tonic-gate return (PO_SUCCESS);
8630Sstevel@tonic-gate }
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate /*
8660Sstevel@tonic-gate * prop_build_cb() is designed to be called from
8670Sstevel@tonic-gate * pool_walk_properties(). The property value is used to put an XML
8680Sstevel@tonic-gate * property on the supplied ktx_node. This is an essential part of the
8690Sstevel@tonic-gate * mechanism used to export a kernel configuration in libpool XML
8700Sstevel@tonic-gate * form.
8710Sstevel@tonic-gate */
8720Sstevel@tonic-gate /* ARGSUSED */
8730Sstevel@tonic-gate static int
prop_build_cb(pool_conf_t * UNUSED,pool_elem_t * pe,const char * name,pool_value_t * pval,void * user)8740Sstevel@tonic-gate prop_build_cb(pool_conf_t *UNUSED, pool_elem_t *pe, const char *name,
8750Sstevel@tonic-gate pool_value_t *pval, void *user)
8760Sstevel@tonic-gate {
8770Sstevel@tonic-gate struct knl_to_xml *info = (struct knl_to_xml *)user;
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate return (pool_knl_put_xml_property((pool_elem_t *)pe, info->ktx_node,
880*11411SSurya.Prakki@Sun.COM name, pval));
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate /*
8840Sstevel@tonic-gate * Duplicate some of the functionality from pool_xml_put_property()
8850Sstevel@tonic-gate * (see pool_xml.c) to allow a kernel configuration to add XML nodes
8860Sstevel@tonic-gate * to an XML tree which represents the kernel configuration. This is
8870Sstevel@tonic-gate * an essential part of the mechanism used to export a kernel
8880Sstevel@tonic-gate * configuration in libpool XML form.
8890Sstevel@tonic-gate */
8900Sstevel@tonic-gate int
pool_knl_put_xml_property(pool_elem_t * pe,xmlNodePtr node,const char * name,const pool_value_t * val)8910Sstevel@tonic-gate pool_knl_put_xml_property(pool_elem_t *pe, xmlNodePtr node, const char *name,
8920Sstevel@tonic-gate const pool_value_t *val)
8930Sstevel@tonic-gate {
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate /*
8960Sstevel@tonic-gate * "type" is a special attribute which is not visible ever outside of
8970Sstevel@tonic-gate * libpool. Use the specific type accessor function.
8980Sstevel@tonic-gate */
8990Sstevel@tonic-gate if (strcmp(name, c_type) == 0) {
9000Sstevel@tonic-gate return (pool_xml_set_attr(node, BAD_CAST name,
9010Sstevel@tonic-gate val));
9020Sstevel@tonic-gate }
9030Sstevel@tonic-gate if (is_ns_property(pe, name) != NULL) { /* in ns */
9040Sstevel@tonic-gate if (pool_xml_set_attr(node,
9050Sstevel@tonic-gate BAD_CAST property_name_minus_ns(pe, name), val) == PO_FAIL)
9060Sstevel@tonic-gate return (pool_xml_set_prop(node, BAD_CAST name,
9070Sstevel@tonic-gate val));
9080Sstevel@tonic-gate } else
9090Sstevel@tonic-gate return (pool_xml_set_prop(node, BAD_CAST name, val));
9100Sstevel@tonic-gate return (PO_SUCCESS);
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate /*
9140Sstevel@tonic-gate * Export the kernel configuration as an XML file. The configuration
9150Sstevel@tonic-gate * is used to build an XML document in memory. This document is then
9160Sstevel@tonic-gate * saved to the supplied location.
9170Sstevel@tonic-gate */
9180Sstevel@tonic-gate int
pool_knl_export(const pool_conf_t * conf,const char * location,pool_export_format_t fmt)9190Sstevel@tonic-gate pool_knl_export(const pool_conf_t *conf, const char *location,
9200Sstevel@tonic-gate pool_export_format_t fmt)
9210Sstevel@tonic-gate {
9220Sstevel@tonic-gate xmlNodePtr node_comment;
9230Sstevel@tonic-gate xmlNodePtr system;
9240Sstevel@tonic-gate int ret;
9250Sstevel@tonic-gate pool_t **ps;
9260Sstevel@tonic-gate pool_resource_t **rs;
9270Sstevel@tonic-gate uint_t nelem;
9280Sstevel@tonic-gate int i;
9290Sstevel@tonic-gate struct knl_to_xml info;
9300Sstevel@tonic-gate char_buf_t *cb = NULL;
9310Sstevel@tonic-gate xmlValidCtxtPtr cvp;
9320Sstevel@tonic-gate
9330Sstevel@tonic-gate xml_init();
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate switch (fmt) {
9370Sstevel@tonic-gate case POX_NATIVE:
9380Sstevel@tonic-gate info.ktx_doc = xmlNewDoc(BAD_CAST "1.0");
939*11411SSurya.Prakki@Sun.COM (void) xmlCreateIntSubset(info.ktx_doc, BAD_CAST "system",
9400Sstevel@tonic-gate BAD_CAST "-//Sun Microsystems Inc//DTD Resource "
9410Sstevel@tonic-gate "Management All//EN",
9420Sstevel@tonic-gate BAD_CAST dtd_location);
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) {
9450Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
9460Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
9470Sstevel@tonic-gate return (PO_FAIL);
9480Sstevel@tonic-gate }
9490Sstevel@tonic-gate /*
9500Sstevel@tonic-gate * Call xmlValidateDocument() to force the parsing of
9510Sstevel@tonic-gate * the DTD. Ignore errors and warning messages as we
9520Sstevel@tonic-gate * know the document isn't valid.
9530Sstevel@tonic-gate */
9540Sstevel@tonic-gate (void) xmlValidateDocument(cvp, info.ktx_doc);
9550Sstevel@tonic-gate xmlFreeValidCtxt(cvp);
9560Sstevel@tonic-gate if ((info.ktx_node = node_create(NULL, BAD_CAST "system")) ==
9570Sstevel@tonic-gate NULL) {
9580Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
9590Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
9600Sstevel@tonic-gate return (PO_FAIL);
9610Sstevel@tonic-gate }
9620Sstevel@tonic-gate
9630Sstevel@tonic-gate system = info.ktx_node;
9640Sstevel@tonic-gate info.ktx_doc->_private = (void *)conf;
9650Sstevel@tonic-gate
966*11411SSurya.Prakki@Sun.COM (void) xmlDocSetRootElement(info.ktx_doc, info.ktx_node);
967*11411SSurya.Prakki@Sun.COM (void) xmlSetProp(info.ktx_node, BAD_CAST c_ref_id,
968*11411SSurya.Prakki@Sun.COM BAD_CAST "dummy");
9690Sstevel@tonic-gate if ((node_comment = xmlNewDocComment(info.ktx_doc,
9700Sstevel@tonic-gate BAD_CAST "\nConfiguration for pools facility. Do NOT"
9710Sstevel@tonic-gate " edit this file by hand - use poolcfg(1)"
9720Sstevel@tonic-gate " or libpool(3POOL) instead.\n")) == NULL) {
9730Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
9740Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
9750Sstevel@tonic-gate return (PO_FAIL);
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate if (xmlAddPrevSibling(info.ktx_node, node_comment) == NULL) {
9780Sstevel@tonic-gate xmlFree(node_comment);
9790Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
9800Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
9810Sstevel@tonic-gate return (PO_FAIL);
9820Sstevel@tonic-gate }
9830Sstevel@tonic-gate if (pool_walk_any_properties((pool_conf_t *)conf,
9840Sstevel@tonic-gate pool_conf_to_elem(conf), &info, prop_build_cb, 1) ==
9850Sstevel@tonic-gate PO_FAIL) {
9860Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
9870Sstevel@tonic-gate return (PO_FAIL);
9880Sstevel@tonic-gate }
9890Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
9900Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
9910Sstevel@tonic-gate return (PO_FAIL);
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate /*
9940Sstevel@tonic-gate * Now add pool details
9950Sstevel@tonic-gate */
9960Sstevel@tonic-gate if ((ps = pool_query_pools(conf, &nelem, NULL)) != NULL) {
9970Sstevel@tonic-gate for (i = 0; i < nelem; i++) {
9980Sstevel@tonic-gate pool_elem_t *elem = TO_ELEM(ps[i]);
9990Sstevel@tonic-gate uint_t nreselem;
10000Sstevel@tonic-gate const char *sep = "";
10010Sstevel@tonic-gate int j;
10020Sstevel@tonic-gate
10033247Sgjelinek if (elem_is_tmp(elem))
10043247Sgjelinek continue;
10053247Sgjelinek
10060Sstevel@tonic-gate if ((info.ktx_node = node_create(system,
10070Sstevel@tonic-gate BAD_CAST element_class_tags
10080Sstevel@tonic-gate [pool_elem_class(elem)])) == NULL) {
10090Sstevel@tonic-gate free(ps);
10100Sstevel@tonic-gate free_char_buf(cb);
10110Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
10120Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
10130Sstevel@tonic-gate return (PO_FAIL);
10140Sstevel@tonic-gate }
10150Sstevel@tonic-gate if (pool_walk_any_properties(
10160Sstevel@tonic-gate (pool_conf_t *)conf,
10170Sstevel@tonic-gate elem, &info, prop_build_cb, 1) == PO_FAIL) {
10180Sstevel@tonic-gate free(ps);
10190Sstevel@tonic-gate free_char_buf(cb);
10200Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
10210Sstevel@tonic-gate return (PO_FAIL);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate /*
10240Sstevel@tonic-gate * TODO: pset specific res manipulation
10250Sstevel@tonic-gate */
10260Sstevel@tonic-gate if ((rs = pool_query_pool_resources(conf, ps[i],
10270Sstevel@tonic-gate &nreselem, NULL)) == NULL) {
10280Sstevel@tonic-gate free(ps);
10290Sstevel@tonic-gate free_char_buf(cb);
10300Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
10310Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
10320Sstevel@tonic-gate return (PO_FAIL);
10330Sstevel@tonic-gate }
10340Sstevel@tonic-gate if (set_char_buf(cb, "") == PO_FAIL) {
10350Sstevel@tonic-gate free(rs);
10360Sstevel@tonic-gate free(ps);
10370Sstevel@tonic-gate free_char_buf(cb);
10380Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
10390Sstevel@tonic-gate return (PO_FAIL);
10400Sstevel@tonic-gate }
10410Sstevel@tonic-gate for (j = 0; j < nreselem; j++) {
10420Sstevel@tonic-gate pool_elem_t *reselem = TO_ELEM(rs[j]);
10430Sstevel@tonic-gate if (append_char_buf(cb, "%s%s_%d", sep,
10440Sstevel@tonic-gate pool_elem_class_string(reselem),
10450Sstevel@tonic-gate (int)elem_get_sysid(reselem)) ==
10460Sstevel@tonic-gate PO_FAIL) {
10470Sstevel@tonic-gate free(rs);
10480Sstevel@tonic-gate free(ps);
10490Sstevel@tonic-gate free_char_buf(cb);
10500Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
10510Sstevel@tonic-gate return (PO_FAIL);
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate sep = " ";
10540Sstevel@tonic-gate }
10550Sstevel@tonic-gate free(rs);
1056*11411SSurya.Prakki@Sun.COM (void) xmlSetProp(info.ktx_node, BAD_CAST "res",
10570Sstevel@tonic-gate BAD_CAST cb->cb_buf);
10580Sstevel@tonic-gate if (set_char_buf(cb, "%s_%d",
10590Sstevel@tonic-gate pool_elem_class_string(elem),
10600Sstevel@tonic-gate (int)elem_get_sysid(elem)) == PO_FAIL) {
10610Sstevel@tonic-gate free(ps);
10620Sstevel@tonic-gate free_char_buf(cb);
10630Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
10640Sstevel@tonic-gate return (PO_FAIL);
10650Sstevel@tonic-gate }
1066*11411SSurya.Prakki@Sun.COM (void) xmlSetProp(info.ktx_node,
1067*11411SSurya.Prakki@Sun.COM BAD_CAST c_ref_id,
10680Sstevel@tonic-gate BAD_CAST cb->cb_buf);
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate free(ps);
10710Sstevel@tonic-gate }
10720Sstevel@tonic-gate /*
10730Sstevel@tonic-gate * Now add resource details (including components)
10740Sstevel@tonic-gate */
10750Sstevel@tonic-gate if ((rs = pool_query_resources(conf, &nelem, NULL)) != NULL) {
10760Sstevel@tonic-gate for (i = 0; i < nelem; i++) {
10770Sstevel@tonic-gate pool_elem_t *elem = TO_ELEM(rs[i]);
10780Sstevel@tonic-gate pool_component_t **cs = NULL;
10790Sstevel@tonic-gate uint_t ncompelem;
10800Sstevel@tonic-gate int j;
10810Sstevel@tonic-gate
10823247Sgjelinek if (elem_is_tmp(elem))
10833247Sgjelinek continue;
10843247Sgjelinek
10850Sstevel@tonic-gate if ((info.ktx_node = node_create(system,
10860Sstevel@tonic-gate BAD_CAST element_class_tags
10870Sstevel@tonic-gate [pool_elem_class(elem)])) == NULL) {
10880Sstevel@tonic-gate free(rs);
10890Sstevel@tonic-gate free_char_buf(cb);
10900Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
10910Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
10920Sstevel@tonic-gate return (PO_FAIL);
10930Sstevel@tonic-gate }
10940Sstevel@tonic-gate if (pool_walk_any_properties(
10950Sstevel@tonic-gate (pool_conf_t *)conf,
10960Sstevel@tonic-gate elem, &info, prop_build_cb, 1) == PO_FAIL) {
10970Sstevel@tonic-gate free(rs);
10980Sstevel@tonic-gate free_char_buf(cb);
10990Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
11000Sstevel@tonic-gate return (PO_FAIL);
11010Sstevel@tonic-gate }
11020Sstevel@tonic-gate if (set_char_buf(cb, "%s_%d",
11030Sstevel@tonic-gate pool_elem_class_string(elem),
11040Sstevel@tonic-gate (int)elem_get_sysid(elem)) == PO_FAIL) {
11050Sstevel@tonic-gate free(rs);
11060Sstevel@tonic-gate free_char_buf(cb);
11070Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
11080Sstevel@tonic-gate return (PO_FAIL);
11090Sstevel@tonic-gate }
1110*11411SSurya.Prakki@Sun.COM (void) xmlSetProp(info.ktx_node,
1111*11411SSurya.Prakki@Sun.COM BAD_CAST c_ref_id,
11120Sstevel@tonic-gate BAD_CAST cb->cb_buf);
11130Sstevel@tonic-gate if ((cs = pool_query_resource_components(conf,
11140Sstevel@tonic-gate rs[i], &ncompelem, NULL)) != NULL) {
11150Sstevel@tonic-gate xmlNodePtr resource = info.ktx_node;
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate for (j = 0; j < ncompelem; j++) {
11180Sstevel@tonic-gate pool_elem_t *compelem =
11190Sstevel@tonic-gate TO_ELEM(cs[j]);
11200Sstevel@tonic-gate if ((info.ktx_node =
11210Sstevel@tonic-gate node_create(resource,
11220Sstevel@tonic-gate BAD_CAST element_class_tags
11230Sstevel@tonic-gate [pool_elem_class(
11240Sstevel@tonic-gate compelem)])) == NULL) {
11250Sstevel@tonic-gate pool_seterror(
11260Sstevel@tonic-gate POE_DATASTORE);
11270Sstevel@tonic-gate free(rs);
11280Sstevel@tonic-gate free(cs);
11290Sstevel@tonic-gate free_char_buf(cb);
11300Sstevel@tonic-gate xmlFreeDoc(info.
11310Sstevel@tonic-gate ktx_doc);
11320Sstevel@tonic-gate return (PO_FAIL);
11330Sstevel@tonic-gate }
11340Sstevel@tonic-gate if (pool_walk_any_properties(
11350Sstevel@tonic-gate (pool_conf_t *)conf,
11360Sstevel@tonic-gate compelem, &info,
11370Sstevel@tonic-gate prop_build_cb, 1) ==
11380Sstevel@tonic-gate PO_FAIL) {
11390Sstevel@tonic-gate free(rs);
11400Sstevel@tonic-gate free(cs);
11410Sstevel@tonic-gate free_char_buf(cb);
11420Sstevel@tonic-gate xmlFreeDoc(info.
11430Sstevel@tonic-gate ktx_doc);
11440Sstevel@tonic-gate return (PO_FAIL);
11450Sstevel@tonic-gate }
11460Sstevel@tonic-gate if (set_char_buf(cb, "%s_%d",
11470Sstevel@tonic-gate pool_elem_class_string(
11480Sstevel@tonic-gate compelem),
11490Sstevel@tonic-gate (int)elem_get_sysid(
11500Sstevel@tonic-gate compelem)) == PO_FAIL) {
11510Sstevel@tonic-gate free(rs);
11520Sstevel@tonic-gate free(cs);
11530Sstevel@tonic-gate free_char_buf(cb);
11540Sstevel@tonic-gate xmlFreeDoc(info.
11550Sstevel@tonic-gate ktx_doc);
11560Sstevel@tonic-gate return (PO_FAIL);
11570Sstevel@tonic-gate }
1158*11411SSurya.Prakki@Sun.COM (void) xmlSetProp(info.ktx_node,
11590Sstevel@tonic-gate BAD_CAST c_ref_id,
11600Sstevel@tonic-gate BAD_CAST cb->cb_buf);
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate free(cs);
11630Sstevel@tonic-gate }
11640Sstevel@tonic-gate }
11650Sstevel@tonic-gate free(rs);
11660Sstevel@tonic-gate }
11670Sstevel@tonic-gate free_char_buf(cb);
11680Sstevel@tonic-gate /*
11690Sstevel@tonic-gate * Set up the message handlers prior to calling
11700Sstevel@tonic-gate * xmlValidateDocument()
11710Sstevel@tonic-gate */
11720Sstevel@tonic-gate if ((cvp = xmlNewValidCtxt()) == NULL) {
11730Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
11740Sstevel@tonic-gate pool_seterror(POE_DATASTORE);
11750Sstevel@tonic-gate return (PO_FAIL);
11760Sstevel@tonic-gate }
11770Sstevel@tonic-gate cvp->error = pool_error_func;
11780Sstevel@tonic-gate cvp->warning = pool_error_func;
11790Sstevel@tonic-gate if (xmlValidateDocument(cvp, info.ktx_doc) == 0) {
11800Sstevel@tonic-gate xmlFreeValidCtxt(cvp);
11810Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
11820Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
11830Sstevel@tonic-gate return (PO_FAIL);
11840Sstevel@tonic-gate }
11850Sstevel@tonic-gate xmlFreeValidCtxt(cvp);
11860Sstevel@tonic-gate ret = xmlSaveFormatFile(location, info.ktx_doc, 1);
11870Sstevel@tonic-gate xmlFreeDoc(info.ktx_doc);
11880Sstevel@tonic-gate if (ret == -1) {
11890Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
11900Sstevel@tonic-gate return (PO_FAIL);
11910Sstevel@tonic-gate }
11920Sstevel@tonic-gate return (PO_SUCCESS);
11930Sstevel@tonic-gate default:
11940Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
11950Sstevel@tonic-gate return (PO_FAIL);
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate /*
12000Sstevel@tonic-gate * Rollback the changes to the kernel
12010Sstevel@tonic-gate */
12020Sstevel@tonic-gate int
pool_knl_recover(pool_conf_t * conf)12030Sstevel@tonic-gate pool_knl_recover(pool_conf_t *conf)
12040Sstevel@tonic-gate {
12050Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
12060Sstevel@tonic-gate
12070Sstevel@tonic-gate prov->pkc_log->l_state = LS_RECOVER;
12080Sstevel@tonic-gate if (log_reverse_walk(prov->pkc_log, log_item_undo) != PO_SUCCESS) {
12090Sstevel@tonic-gate dprintf("Library configuration consistency error\n");
12100Sstevel@tonic-gate prov->pkc_log->l_state = LS_FAIL;
12110Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
12120Sstevel@tonic-gate return (PO_FAIL);
12130Sstevel@tonic-gate }
12140Sstevel@tonic-gate prov->pkc_log->l_state = LS_DO;
12150Sstevel@tonic-gate return (PO_SUCCESS);
12160Sstevel@tonic-gate }
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate /*
12190Sstevel@tonic-gate * Rollback the changes to the configuration
12200Sstevel@tonic-gate */
12210Sstevel@tonic-gate int
pool_knl_rollback(pool_conf_t * conf)12220Sstevel@tonic-gate pool_knl_rollback(pool_conf_t *conf)
12230Sstevel@tonic-gate {
12240Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
12250Sstevel@tonic-gate
12260Sstevel@tonic-gate prov->pkc_log->l_state = LS_UNDO;
12270Sstevel@tonic-gate if (log_reverse_walk(prov->pkc_log, log_item_undo) != PO_SUCCESS) {
12280Sstevel@tonic-gate dprintf("Kernel configuration consistency error\n");
12290Sstevel@tonic-gate (void) log_walk(prov->pkc_log, log_item_release);
12300Sstevel@tonic-gate log_empty(prov->pkc_log);
12310Sstevel@tonic-gate prov->pkc_log->l_state = LS_FAIL;
12320Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
12330Sstevel@tonic-gate return (PO_FAIL);
12340Sstevel@tonic-gate }
12350Sstevel@tonic-gate (void) log_walk(prov->pkc_log, log_item_release);
12360Sstevel@tonic-gate log_empty(prov->pkc_log);
12370Sstevel@tonic-gate prov->pkc_log->l_state = LS_DO;
12380Sstevel@tonic-gate return (PO_SUCCESS);
12390Sstevel@tonic-gate }
12400Sstevel@tonic-gate
12410Sstevel@tonic-gate /*
12420Sstevel@tonic-gate * Callback used to build the result set for a query. Each invocation will
12430Sstevel@tonic-gate * supply a candidate element for inclusion. The element is filtered by:
12440Sstevel@tonic-gate * - class
12450Sstevel@tonic-gate * - properties
12460Sstevel@tonic-gate * If the element "matches" the target, then it is added to the result
12470Sstevel@tonic-gate * set, otherwise it is ignored.
12480Sstevel@tonic-gate */
12490Sstevel@tonic-gate /* ARGSUSED1 */
12500Sstevel@tonic-gate static void
build_result_set(const void * key,void ** value,void * cl)12510Sstevel@tonic-gate build_result_set(const void *key, void **value, void *cl)
12520Sstevel@tonic-gate {
12530Sstevel@tonic-gate struct query_obj *qo = (struct query_obj *)cl;
12540Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
12550Sstevel@tonic-gate
12560Sstevel@tonic-gate /*
12570Sstevel@tonic-gate * Check to see if it's the right class of element
12580Sstevel@tonic-gate */
12590Sstevel@tonic-gate if (qo->classes & (1 << pool_elem_class((pool_elem_t *)key))) {
12600Sstevel@tonic-gate int i;
12610Sstevel@tonic-gate /*
12620Sstevel@tonic-gate * Now check to see if the src element is correct. If no src
12630Sstevel@tonic-gate * element is supplied, ignore this check
12640Sstevel@tonic-gate */
12650Sstevel@tonic-gate if (qo->src) {
12660Sstevel@tonic-gate pool_knl_elem_t *parent;
12670Sstevel@tonic-gate
12680Sstevel@tonic-gate for (parent = pke; parent != NULL;
12690Sstevel@tonic-gate parent = parent->pke_parent) {
12700Sstevel@tonic-gate if (parent == (pool_knl_elem_t *)qo->src)
12710Sstevel@tonic-gate break;
12720Sstevel@tonic-gate }
12730Sstevel@tonic-gate if (parent == NULL)
12740Sstevel@tonic-gate return;
12750Sstevel@tonic-gate }
12760Sstevel@tonic-gate /*
12770Sstevel@tonic-gate * Now check for property matches (if there are any specified)
12780Sstevel@tonic-gate */
12790Sstevel@tonic-gate if (qo->props) {
12800Sstevel@tonic-gate int matched = PO_TRUE;
12810Sstevel@tonic-gate for (i = 0; qo->props[i] != NULL; i++) {
12820Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
12830Sstevel@tonic-gate
12840Sstevel@tonic-gate if (pool_get_property(TO_CONF(TO_ELEM(pke)),
12850Sstevel@tonic-gate (pool_elem_t *)pke,
12860Sstevel@tonic-gate pool_value_get_name(qo->props[i]), &val) ==
12870Sstevel@tonic-gate POC_INVAL) {
12880Sstevel@tonic-gate matched = PO_FALSE;
12890Sstevel@tonic-gate break;
12900Sstevel@tonic-gate } else {
12910Sstevel@tonic-gate if (pool_value_equal(qo->props[i],
12920Sstevel@tonic-gate &val) != PO_TRUE) {
12930Sstevel@tonic-gate matched = PO_FALSE;
12940Sstevel@tonic-gate break;
12950Sstevel@tonic-gate }
12960Sstevel@tonic-gate }
12970Sstevel@tonic-gate }
12980Sstevel@tonic-gate if (matched == PO_TRUE)
12990Sstevel@tonic-gate (void) pool_knl_result_set_append(qo->rs,
1300*11411SSurya.Prakki@Sun.COM (pool_knl_elem_t *)key);
13010Sstevel@tonic-gate } else {
13020Sstevel@tonic-gate (void) pool_knl_result_set_append(qo->rs,
13030Sstevel@tonic-gate (pool_knl_elem_t *)key);
13040Sstevel@tonic-gate }
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate }
13070Sstevel@tonic-gate
13080Sstevel@tonic-gate /*
13090Sstevel@tonic-gate * Execute the supplied query and return a result set which contains
13100Sstevel@tonic-gate * all qualifying elements.
13110Sstevel@tonic-gate */
13120Sstevel@tonic-gate pool_result_set_t *
pool_knl_exec_query(const pool_conf_t * conf,const pool_elem_t * src,const char * src_attr,pool_elem_class_t classes,pool_value_t ** props)13130Sstevel@tonic-gate pool_knl_exec_query(const pool_conf_t *conf, const pool_elem_t *src,
13140Sstevel@tonic-gate const char *src_attr, pool_elem_class_t classes, pool_value_t **props)
13150Sstevel@tonic-gate {
13160Sstevel@tonic-gate pool_knl_result_set_t *rs;
13170Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
13180Sstevel@tonic-gate struct query_obj qo;
13190Sstevel@tonic-gate int matched = PO_TRUE;
13200Sstevel@tonic-gate
13210Sstevel@tonic-gate /*
13220Sstevel@tonic-gate * Have a buffer at this point, that we can use
13230Sstevel@tonic-gate */
13240Sstevel@tonic-gate if ((rs = pool_knl_result_set_alloc(conf)) == NULL) {
13250Sstevel@tonic-gate return (NULL);
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate qo.conf = conf;
13280Sstevel@tonic-gate qo.src = src;
13290Sstevel@tonic-gate qo.src_attr = src_attr;
13300Sstevel@tonic-gate qo.classes = classes;
13310Sstevel@tonic-gate qo.props = props;
13320Sstevel@tonic-gate qo.rs = rs;
13330Sstevel@tonic-gate if (src_attr != NULL) {
13340Sstevel@tonic-gate pool_knl_pool_t *pkp = (pool_knl_pool_t *)src;
13350Sstevel@tonic-gate
13360Sstevel@tonic-gate /*
13370Sstevel@tonic-gate * Note: This logic is resource specific and must be
13380Sstevel@tonic-gate * extended for additional resource types.
13390Sstevel@tonic-gate */
13400Sstevel@tonic-gate /*
13410Sstevel@tonic-gate * Check for property matches (if there are any specified)
13420Sstevel@tonic-gate */
13430Sstevel@tonic-gate if (props) {
13440Sstevel@tonic-gate int i;
13450Sstevel@tonic-gate
13460Sstevel@tonic-gate for (i = 0; props[i] != NULL; i++) {
13470Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
13480Sstevel@tonic-gate
13490Sstevel@tonic-gate if (pool_get_property(conf,
13500Sstevel@tonic-gate (pool_elem_t *)pkp->pkp_assoc[PREC_PSET],
13510Sstevel@tonic-gate pool_value_get_name(props[i]), &val) ==
13520Sstevel@tonic-gate POC_INVAL) {
13530Sstevel@tonic-gate matched = PO_FALSE;
13540Sstevel@tonic-gate break;
13550Sstevel@tonic-gate } else {
13560Sstevel@tonic-gate if (pool_value_equal(props[i],
13570Sstevel@tonic-gate &val) != PO_TRUE) {
13580Sstevel@tonic-gate matched = PO_FALSE;
13590Sstevel@tonic-gate break;
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate }
13620Sstevel@tonic-gate }
13630Sstevel@tonic-gate }
13640Sstevel@tonic-gate
13650Sstevel@tonic-gate if (matched == PO_TRUE)
13660Sstevel@tonic-gate (void) pool_knl_result_set_append(rs,
13670Sstevel@tonic-gate (pool_knl_elem_t *)pkp->pkp_assoc[PREC_PSET]);
13680Sstevel@tonic-gate } else
13690Sstevel@tonic-gate dict_map(prov->pkc_elements, build_result_set, &qo);
13700Sstevel@tonic-gate
13711042Sgarypen if (rs->pkr_count == 0)
13721042Sgarypen pool_seterror(POE_INVALID_SEARCH);
13730Sstevel@tonic-gate return ((pool_result_set_t *)rs);
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate
13760Sstevel@tonic-gate /*
13770Sstevel@tonic-gate * Callback function intended to be used from pool_walk_pools(). If
13780Sstevel@tonic-gate * the supplied pool is not the default pool attempt to destroy it.
13790Sstevel@tonic-gate */
13800Sstevel@tonic-gate /*ARGSUSED*/
13810Sstevel@tonic-gate static int
destroy_pool_cb(pool_conf_t * conf,pool_t * pool,void * unused)13820Sstevel@tonic-gate destroy_pool_cb(pool_conf_t *conf, pool_t *pool, void *unused)
13830Sstevel@tonic-gate {
13840Sstevel@tonic-gate if (elem_is_default(TO_ELEM(pool)) != PO_TRUE)
13850Sstevel@tonic-gate return (pool_destroy(conf, pool));
13860Sstevel@tonic-gate /*
13870Sstevel@tonic-gate * Return PO_SUCCESS even though we don't delete the default
13880Sstevel@tonic-gate * pool so that the walk continues
13890Sstevel@tonic-gate */
13900Sstevel@tonic-gate return (PO_SUCCESS);
13910Sstevel@tonic-gate }
13920Sstevel@tonic-gate
13930Sstevel@tonic-gate /*
13940Sstevel@tonic-gate * Remove the configuration details. This means remove all elements
13950Sstevel@tonic-gate * apart from the system elements.
13960Sstevel@tonic-gate */
13970Sstevel@tonic-gate int
pool_knl_remove(pool_conf_t * conf)13980Sstevel@tonic-gate pool_knl_remove(pool_conf_t *conf)
13990Sstevel@tonic-gate {
14000Sstevel@tonic-gate uint_t i, nelem;
14010Sstevel@tonic-gate pool_resource_t **resources;
14020Sstevel@tonic-gate
14030Sstevel@tonic-gate conf->pc_state = POF_DESTROY;
14040Sstevel@tonic-gate if ((resources = pool_query_resources(conf, &nelem, NULL)) != NULL) {
14050Sstevel@tonic-gate for (i = 0; i < nelem; i++) {
14060Sstevel@tonic-gate if (resource_is_system(resources[i]) == PO_FALSE)
14070Sstevel@tonic-gate if (pool_resource_destroy(conf, resources[i]) !=
14080Sstevel@tonic-gate PO_SUCCESS) {
14090Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
14100Sstevel@tonic-gate return (PO_FAIL);
14110Sstevel@tonic-gate }
14120Sstevel@tonic-gate }
14130Sstevel@tonic-gate free(resources);
14140Sstevel@tonic-gate }
14150Sstevel@tonic-gate (void) pool_walk_pools(conf, conf, destroy_pool_cb);
14160Sstevel@tonic-gate if (pool_conf_commit(conf, PO_FALSE) != PO_SUCCESS)
14170Sstevel@tonic-gate return (PO_FAIL);
14180Sstevel@tonic-gate
14190Sstevel@tonic-gate if (pool_conf_close(conf) != PO_SUCCESS)
14200Sstevel@tonic-gate return (PO_FAIL);
14210Sstevel@tonic-gate
14220Sstevel@tonic-gate return (PO_SUCCESS);
14230Sstevel@tonic-gate }
14240Sstevel@tonic-gate
14250Sstevel@tonic-gate /*
14260Sstevel@tonic-gate * Determine the name of the pool to which the supplied pid is
14270Sstevel@tonic-gate * bound. If it cannot be determined return NULL.
14280Sstevel@tonic-gate */
14290Sstevel@tonic-gate char *
pool_knl_get_binding(pool_conf_t * conf,pid_t pid)14300Sstevel@tonic-gate pool_knl_get_binding(pool_conf_t *conf, pid_t pid)
14310Sstevel@tonic-gate {
14320Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
14330Sstevel@tonic-gate const char *sval;
14340Sstevel@tonic-gate char *name = NULL;
14350Sstevel@tonic-gate pool_bindq_t bindq;
14360Sstevel@tonic-gate pool_value_t *props[] = { NULL, NULL };
14370Sstevel@tonic-gate uint_t nelem = 0;
14380Sstevel@tonic-gate pool_t **pools;
14390Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
14400Sstevel@tonic-gate
14410Sstevel@tonic-gate props[0] = &val;
14420Sstevel@tonic-gate
14430Sstevel@tonic-gate bindq.pb_o_id_type = P_PID;
14440Sstevel@tonic-gate bindq.pb_o_id = pid;
14450Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_BINDQ, &bindq) < 0) {
14460Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
14470Sstevel@tonic-gate return (NULL);
14480Sstevel@tonic-gate }
14490Sstevel@tonic-gate
14500Sstevel@tonic-gate if (pool_value_set_name(props[0], "pool.sys_id") != PO_SUCCESS) {
14510Sstevel@tonic-gate return (NULL);
14520Sstevel@tonic-gate }
14530Sstevel@tonic-gate pool_value_set_int64(props[0], bindq.pb_i_id);
14540Sstevel@tonic-gate if ((pools = pool_query_pools(conf, &nelem, props)) == NULL) {
14550Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
14560Sstevel@tonic-gate return (NULL);
14570Sstevel@tonic-gate }
14580Sstevel@tonic-gate
14590Sstevel@tonic-gate if (nelem != 1) {
14600Sstevel@tonic-gate free(pools);
14610Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
14620Sstevel@tonic-gate return (NULL);
14630Sstevel@tonic-gate }
14640Sstevel@tonic-gate if (pool_get_ns_property(TO_ELEM(pools[0]), c_name, props[0])
14650Sstevel@tonic-gate == POC_INVAL) {
14660Sstevel@tonic-gate free(pools);
14670Sstevel@tonic-gate return (NULL);
14680Sstevel@tonic-gate }
14690Sstevel@tonic-gate if (pool_value_get_string(props[0], &sval) != PO_SUCCESS) {
14700Sstevel@tonic-gate free(pools);
14710Sstevel@tonic-gate return (NULL);
14720Sstevel@tonic-gate }
14730Sstevel@tonic-gate if ((name = strdup(sval)) == NULL) {
14740Sstevel@tonic-gate free(pools);
14750Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
14760Sstevel@tonic-gate return (NULL);
14770Sstevel@tonic-gate }
14780Sstevel@tonic-gate return (name);
14790Sstevel@tonic-gate }
14800Sstevel@tonic-gate
14810Sstevel@tonic-gate /*
14820Sstevel@tonic-gate * Bind idtype id to the pool name.
14830Sstevel@tonic-gate */
14840Sstevel@tonic-gate int
pool_knl_set_binding(pool_conf_t * conf,const char * pool_name,idtype_t idtype,id_t id)14850Sstevel@tonic-gate pool_knl_set_binding(pool_conf_t *conf, const char *pool_name, idtype_t idtype,
14860Sstevel@tonic-gate id_t id)
14870Sstevel@tonic-gate {
14880Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
14890Sstevel@tonic-gate pool_bind_t bind;
14900Sstevel@tonic-gate pool_t *pool;
14910Sstevel@tonic-gate int ret;
14920Sstevel@tonic-gate
14930Sstevel@tonic-gate if ((pool = pool_get_pool(conf, pool_name)) == NULL)
14940Sstevel@tonic-gate return (PO_FAIL);
14950Sstevel@tonic-gate
14960Sstevel@tonic-gate bind.pb_o_id_type = idtype;
14970Sstevel@tonic-gate bind.pb_o_id = id;
14980Sstevel@tonic-gate bind.pb_o_pool_id = elem_get_sysid(TO_ELEM(pool));
14990Sstevel@tonic-gate
15000Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_BIND, &bind)) < 0 &&
1501*11411SSurya.Prakki@Sun.COM errno == EAGAIN)
1502*11411SSurya.Prakki@Sun.COM ;
15030Sstevel@tonic-gate if (ret < 0) {
15040Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
15050Sstevel@tonic-gate return (PO_FAIL);
15060Sstevel@tonic-gate }
15070Sstevel@tonic-gate return (PO_SUCCESS);
15080Sstevel@tonic-gate }
15090Sstevel@tonic-gate
15100Sstevel@tonic-gate /*
15110Sstevel@tonic-gate * pool_knl_get_resource_binding() returns the binding for a pid to
15120Sstevel@tonic-gate * the supplied type of resource. If a binding cannot be determined,
15130Sstevel@tonic-gate * NULL is returned.
15140Sstevel@tonic-gate */
15150Sstevel@tonic-gate char *
pool_knl_get_resource_binding(pool_conf_t * conf,pool_resource_elem_class_t type,pid_t pid)15160Sstevel@tonic-gate pool_knl_get_resource_binding(pool_conf_t *conf,
15170Sstevel@tonic-gate pool_resource_elem_class_t type, pid_t pid)
15180Sstevel@tonic-gate {
15190Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
15200Sstevel@tonic-gate const char *sval;
15210Sstevel@tonic-gate char *name = NULL;
15220Sstevel@tonic-gate pool_bindq_t bindq;
15230Sstevel@tonic-gate pool_value_t *props[] = { NULL, NULL };
15240Sstevel@tonic-gate uint_t nelem = 0;
15250Sstevel@tonic-gate pool_t **pools;
15260Sstevel@tonic-gate pool_resource_t **resources;
15270Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
15280Sstevel@tonic-gate
15290Sstevel@tonic-gate props[0] = &val;
15300Sstevel@tonic-gate bindq.pb_o_id_type = P_PID;
15310Sstevel@tonic-gate bindq.pb_o_id = pid;
15320Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_BINDQ, &bindq) < 0) {
15330Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
15340Sstevel@tonic-gate return (NULL);
15350Sstevel@tonic-gate }
15360Sstevel@tonic-gate
15370Sstevel@tonic-gate if (pool_value_set_name(props[0], "pool.sys_id") != PO_SUCCESS) {
15380Sstevel@tonic-gate return (NULL);
15390Sstevel@tonic-gate }
15400Sstevel@tonic-gate pool_value_set_int64(props[0], bindq.pb_i_id);
15410Sstevel@tonic-gate if ((pools = pool_query_pools(conf, &nelem, props)) == NULL) {
15420Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
15430Sstevel@tonic-gate return (NULL);
15440Sstevel@tonic-gate }
15450Sstevel@tonic-gate
15460Sstevel@tonic-gate if (nelem != 1) {
15470Sstevel@tonic-gate free(pools);
15480Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
15490Sstevel@tonic-gate return (NULL);
15500Sstevel@tonic-gate }
15510Sstevel@tonic-gate
15520Sstevel@tonic-gate if (pool_value_set_string(props[0], pool_resource_type_string(type)) !=
15530Sstevel@tonic-gate PO_SUCCESS ||
15540Sstevel@tonic-gate pool_value_set_name(props[0], c_type) != PO_SUCCESS) {
15550Sstevel@tonic-gate free(pools);
15560Sstevel@tonic-gate return (NULL);
15570Sstevel@tonic-gate }
15580Sstevel@tonic-gate
15590Sstevel@tonic-gate if ((resources = pool_query_pool_resources(conf, pools[0], &nelem,
15600Sstevel@tonic-gate NULL)) == NULL) {
15610Sstevel@tonic-gate free(pools);
15620Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
15630Sstevel@tonic-gate return (NULL);
15640Sstevel@tonic-gate }
15650Sstevel@tonic-gate free(pools);
15660Sstevel@tonic-gate if (nelem != 1) {
15670Sstevel@tonic-gate free(resources);
15680Sstevel@tonic-gate pool_seterror(POE_INVALID_CONF);
15690Sstevel@tonic-gate return (NULL);
15700Sstevel@tonic-gate }
15710Sstevel@tonic-gate if (pool_get_ns_property(TO_ELEM(resources[0]), c_name, props[0]) ==
15720Sstevel@tonic-gate POC_INVAL) {
15730Sstevel@tonic-gate free(resources);
15740Sstevel@tonic-gate return (NULL);
15750Sstevel@tonic-gate }
15760Sstevel@tonic-gate free(resources);
15770Sstevel@tonic-gate if (pool_value_get_string(props[0], &sval) != PO_SUCCESS) {
15780Sstevel@tonic-gate return (NULL);
15790Sstevel@tonic-gate }
15800Sstevel@tonic-gate if ((name = strdup(sval)) == NULL) {
15810Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
15820Sstevel@tonic-gate return (NULL);
15830Sstevel@tonic-gate }
15840Sstevel@tonic-gate return (name);
15850Sstevel@tonic-gate }
15860Sstevel@tonic-gate
15870Sstevel@tonic-gate /*
15880Sstevel@tonic-gate * Allocate the required library data structure and initialise it.
15890Sstevel@tonic-gate */
15900Sstevel@tonic-gate pool_knl_elem_t *
pool_knl_elem_wrap(pool_conf_t * conf,pool_elem_class_t class,pool_resource_elem_class_t res_class,pool_component_elem_class_t comp_class)15910Sstevel@tonic-gate pool_knl_elem_wrap(pool_conf_t *conf, pool_elem_class_t class,
15920Sstevel@tonic-gate pool_resource_elem_class_t res_class,
15930Sstevel@tonic-gate pool_component_elem_class_t comp_class)
15940Sstevel@tonic-gate {
15950Sstevel@tonic-gate pool_knl_elem_t *elem;
15960Sstevel@tonic-gate pool_elem_t *pe;
15970Sstevel@tonic-gate
15980Sstevel@tonic-gate switch (class) {
15990Sstevel@tonic-gate case PEC_SYSTEM:
16000Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_knl_system_t))) == NULL) {
16010Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
16020Sstevel@tonic-gate return (NULL);
16030Sstevel@tonic-gate }
16040Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_knl_system_t));
16050Sstevel@tonic-gate break;
16060Sstevel@tonic-gate case PEC_POOL:
16070Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_knl_pool_t))) == NULL) {
16080Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
16090Sstevel@tonic-gate return (NULL);
16100Sstevel@tonic-gate }
16110Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_knl_pool_t));
16120Sstevel@tonic-gate break;
16130Sstevel@tonic-gate case PEC_RES_COMP:
16140Sstevel@tonic-gate case PEC_RES_AGG:
16150Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_knl_resource_t))) == NULL) {
16160Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
16170Sstevel@tonic-gate return (NULL);
16180Sstevel@tonic-gate }
16190Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_knl_resource_t));
16200Sstevel@tonic-gate break;
16210Sstevel@tonic-gate case PEC_COMP:
16220Sstevel@tonic-gate if ((elem = malloc(sizeof (pool_knl_component_t))) == NULL) {
16230Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
16240Sstevel@tonic-gate return (NULL);
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate (void) memset(elem, 0, sizeof (pool_knl_component_t));
16270Sstevel@tonic-gate break;
16280Sstevel@tonic-gate default:
16290Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
16300Sstevel@tonic-gate return (NULL);
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate pe = TO_ELEM(elem);
16330Sstevel@tonic-gate pe->pe_conf = conf;
16340Sstevel@tonic-gate pe->pe_class = class;
16350Sstevel@tonic-gate pe->pe_resource_class = res_class;
16360Sstevel@tonic-gate pe->pe_component_class = comp_class;
16370Sstevel@tonic-gate /* Set up the function pointers for element manipulation */
16380Sstevel@tonic-gate pe->pe_get_prop = pool_knl_get_property;
16390Sstevel@tonic-gate pe->pe_put_prop = pool_knl_put_property;
16400Sstevel@tonic-gate pe->pe_rm_prop = pool_knl_rm_property;
16410Sstevel@tonic-gate pe->pe_get_props = pool_knl_get_properties;
16420Sstevel@tonic-gate pe->pe_remove = pool_knl_elem_remove;
16430Sstevel@tonic-gate pe->pe_get_container = pool_knl_get_container;
16440Sstevel@tonic-gate pe->pe_set_container = pool_knl_set_container;
16450Sstevel@tonic-gate /*
16460Sstevel@tonic-gate * Specific initialisation for different types of element
16470Sstevel@tonic-gate */
16480Sstevel@tonic-gate if (class == PEC_POOL) {
16490Sstevel@tonic-gate pool_knl_pool_t *pp = (pool_knl_pool_t *)elem;
16500Sstevel@tonic-gate pp->pp_associate = pool_knl_pool_associate;
16510Sstevel@tonic-gate pp->pp_dissociate = pool_knl_pool_dissociate;
16520Sstevel@tonic-gate pp->pkp_assoc[PREC_PSET] = (pool_knl_resource_t *)
16530Sstevel@tonic-gate resource_by_sysid(conf, PS_NONE, "pset");
16540Sstevel@tonic-gate }
16550Sstevel@tonic-gate if (class == PEC_RES_COMP || class == PEC_RES_AGG) {
16560Sstevel@tonic-gate pool_knl_resource_t *pr = (pool_knl_resource_t *)elem;
16570Sstevel@tonic-gate pr->pr_is_system = pool_knl_resource_is_system;
16580Sstevel@tonic-gate pr->pr_can_associate = pool_knl_resource_can_associate;
16590Sstevel@tonic-gate }
16600Sstevel@tonic-gate #if DEBUG
16610Sstevel@tonic-gate if (dict_put(((pool_knl_connection_t *)conf->pc_prov)->pkc_leaks,
16620Sstevel@tonic-gate elem, elem) != NULL)
16630Sstevel@tonic-gate assert(!"leak map put failed");
16640Sstevel@tonic-gate dprintf("allocated %p\n", elem);
16650Sstevel@tonic-gate #endif /* DEBUG */
16660Sstevel@tonic-gate return (elem);
16670Sstevel@tonic-gate }
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate /*
16700Sstevel@tonic-gate * Allocate a new pool_knl_elem_t in the supplied configuration of the
16710Sstevel@tonic-gate * specified class.
16720Sstevel@tonic-gate * Returns element pointer/NULL
16730Sstevel@tonic-gate */
16740Sstevel@tonic-gate pool_elem_t *
pool_knl_elem_create(pool_conf_t * conf,pool_elem_class_t class,pool_resource_elem_class_t res_class,pool_component_elem_class_t comp_class)16750Sstevel@tonic-gate pool_knl_elem_create(pool_conf_t *conf, pool_elem_class_t class,
16760Sstevel@tonic-gate pool_resource_elem_class_t res_class,
16770Sstevel@tonic-gate pool_component_elem_class_t comp_class)
16780Sstevel@tonic-gate {
16790Sstevel@tonic-gate pool_knl_elem_t *elem;
16800Sstevel@tonic-gate pool_create_undo_t *create;
16810Sstevel@tonic-gate pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
16820Sstevel@tonic-gate static int id = -3;
16830Sstevel@tonic-gate char_buf_t *cb;
16840Sstevel@tonic-gate
16850Sstevel@tonic-gate if ((elem = pool_knl_elem_wrap(conf, class, res_class, comp_class)) ==
16860Sstevel@tonic-gate NULL)
16870Sstevel@tonic-gate return (NULL);
16880Sstevel@tonic-gate
16890Sstevel@tonic-gate /*
16900Sstevel@tonic-gate * Allocate an nvlist to hold properties
16910Sstevel@tonic-gate */
16920Sstevel@tonic-gate if (nvlist_alloc(&elem->pke_properties, NV_UNIQUE_NAME_TYPE, 0) != 0) {
16930Sstevel@tonic-gate pool_knl_elem_free(elem, PO_FALSE);
16940Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
16950Sstevel@tonic-gate return (NULL);
16960Sstevel@tonic-gate }
16970Sstevel@tonic-gate /*
16980Sstevel@tonic-gate * Allocate a temporary ID and name until the element is
16990Sstevel@tonic-gate * created for real
17000Sstevel@tonic-gate */
17010Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
17020Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
17030Sstevel@tonic-gate return (NULL);
17040Sstevel@tonic-gate }
17050Sstevel@tonic-gate if (set_char_buf(cb, "%s.sys_id",
17060Sstevel@tonic-gate pool_elem_class_string((pool_elem_t *)elem)) != PO_SUCCESS) {
17070Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
17080Sstevel@tonic-gate free_char_buf(cb);
17090Sstevel@tonic-gate return (NULL);
17100Sstevel@tonic-gate }
17110Sstevel@tonic-gate (void) nvlist_add_int64(elem->pke_properties, cb->cb_buf, id--);
17120Sstevel@tonic-gate if (set_char_buf(cb, "%s.name",
17130Sstevel@tonic-gate pool_elem_class_string((pool_elem_t *)elem)) != PO_SUCCESS) {
17140Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
17150Sstevel@tonic-gate free_char_buf(cb);
17160Sstevel@tonic-gate return (NULL);
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate (void) nvlist_add_string(elem->pke_properties, cb->cb_buf, "");
17190Sstevel@tonic-gate /*
17200Sstevel@tonic-gate * If it's a resource class, it will need an initial size
17210Sstevel@tonic-gate */
17220Sstevel@tonic-gate if (class == PEC_RES_COMP || class == PEC_RES_AGG) {
17230Sstevel@tonic-gate if (set_char_buf(cb, "%s.size",
17240Sstevel@tonic-gate pool_elem_class_string((pool_elem_t *)elem)) !=
17250Sstevel@tonic-gate PO_SUCCESS) {
17260Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
17270Sstevel@tonic-gate free_char_buf(cb);
17280Sstevel@tonic-gate return (NULL);
17290Sstevel@tonic-gate }
17300Sstevel@tonic-gate (void) nvlist_add_uint64(elem->pke_properties, cb->cb_buf, 0);
17310Sstevel@tonic-gate }
17320Sstevel@tonic-gate free_char_buf(cb);
17330Sstevel@tonic-gate
17340Sstevel@tonic-gate /*
17350Sstevel@tonic-gate * Register the newly created element
17360Sstevel@tonic-gate */
17370Sstevel@tonic-gate if (dict_put(prov->pkc_elements, elem, elem) != NULL) {
17380Sstevel@tonic-gate pool_knl_elem_free(elem, PO_TRUE);
17390Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
17400Sstevel@tonic-gate return (NULL);
17410Sstevel@tonic-gate }
17420Sstevel@tonic-gate
17430Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO)
17440Sstevel@tonic-gate return ((pool_elem_t *)elem);
17450Sstevel@tonic-gate
17460Sstevel@tonic-gate /*
17470Sstevel@tonic-gate * The remaining logic is setting up the arguments for the
17480Sstevel@tonic-gate * POOL_CREATE ioctl and appending the details into the log.
17490Sstevel@tonic-gate */
17500Sstevel@tonic-gate if ((create = malloc(sizeof (pool_create_undo_t))) == NULL) {
17510Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
17520Sstevel@tonic-gate return (NULL);
17530Sstevel@tonic-gate }
17540Sstevel@tonic-gate create->pcu_ioctl.pc_o_type = class;
17550Sstevel@tonic-gate switch (class) {
17560Sstevel@tonic-gate case PEC_SYSTEM:
17570Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
17580Sstevel@tonic-gate free(create);
17590Sstevel@tonic-gate return (NULL);
17600Sstevel@tonic-gate case PEC_POOL: /* NO-OP */
17610Sstevel@tonic-gate break;
17620Sstevel@tonic-gate case PEC_RES_COMP:
17630Sstevel@tonic-gate case PEC_RES_AGG:
17640Sstevel@tonic-gate create->pcu_ioctl.pc_o_sub_type = res_class;
17650Sstevel@tonic-gate break;
17660Sstevel@tonic-gate case PEC_COMP:
17670Sstevel@tonic-gate create->pcu_ioctl.pc_o_sub_type = comp_class;
17680Sstevel@tonic-gate break;
17690Sstevel@tonic-gate default:
17700Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
17710Sstevel@tonic-gate free(create);
17720Sstevel@tonic-gate return (NULL);
17730Sstevel@tonic-gate }
17740Sstevel@tonic-gate
17750Sstevel@tonic-gate create->pcu_elem = (pool_elem_t *)elem;
17760Sstevel@tonic-gate
17770Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_CREATE, (void *)create) !=
17780Sstevel@tonic-gate PO_SUCCESS) {
17790Sstevel@tonic-gate free(create);
17800Sstevel@tonic-gate return (NULL);
17810Sstevel@tonic-gate }
17820Sstevel@tonic-gate return ((pool_elem_t *)elem);
17830Sstevel@tonic-gate }
17840Sstevel@tonic-gate
17850Sstevel@tonic-gate /*
17860Sstevel@tonic-gate * Remove the details of the element from our userland copy and destroy
17870Sstevel@tonic-gate * the element (if appropriate) in the kernel.
17880Sstevel@tonic-gate */
17890Sstevel@tonic-gate int
pool_knl_elem_remove(pool_elem_t * pe)17900Sstevel@tonic-gate pool_knl_elem_remove(pool_elem_t *pe)
17910Sstevel@tonic-gate {
17920Sstevel@tonic-gate pool_knl_connection_t *prov;
17930Sstevel@tonic-gate pool_destroy_undo_t *destroy;
17940Sstevel@tonic-gate
17950Sstevel@tonic-gate prov = (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
17960Sstevel@tonic-gate
17970Sstevel@tonic-gate if (dict_remove(prov->pkc_elements, pe) == NULL) {
17980Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
17990Sstevel@tonic-gate return (PO_FAIL);
18000Sstevel@tonic-gate }
18010Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) {
18020Sstevel@tonic-gate return (PO_SUCCESS);
18030Sstevel@tonic-gate }
18040Sstevel@tonic-gate
18050Sstevel@tonic-gate /*
18060Sstevel@tonic-gate * The remaining logic is setting up the arguments for the
18070Sstevel@tonic-gate * POOL_DESTROY ioctl and appending the details into the log.
18080Sstevel@tonic-gate */
18090Sstevel@tonic-gate if ((destroy = malloc(sizeof (pool_destroy_undo_t))) == NULL) {
18100Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
18110Sstevel@tonic-gate return (PO_FAIL);
18120Sstevel@tonic-gate }
18130Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_type = pool_elem_class(pe);
18140Sstevel@tonic-gate
18150Sstevel@tonic-gate if (destroy->pdu_ioctl.pd_o_type == PEC_RES_COMP ||
18160Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_type == PEC_RES_AGG)
18170Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_sub_type = pool_resource_elem_class(pe);
18180Sstevel@tonic-gate
18190Sstevel@tonic-gate if (destroy->pdu_ioctl.pd_o_type == PEC_COMP)
18200Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_sub_type =
18210Sstevel@tonic-gate pool_component_elem_class(pe);
18220Sstevel@tonic-gate
18230Sstevel@tonic-gate destroy->pdu_elem = pe;
18240Sstevel@tonic-gate
18250Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_DESTROY, (void *)destroy) !=
18260Sstevel@tonic-gate PO_SUCCESS) {
18270Sstevel@tonic-gate free(destroy);
18280Sstevel@tonic-gate return (PO_FAIL);
18290Sstevel@tonic-gate }
18300Sstevel@tonic-gate return (PO_SUCCESS);
18310Sstevel@tonic-gate }
18320Sstevel@tonic-gate
18330Sstevel@tonic-gate /*
18340Sstevel@tonic-gate * Set the parent of the supplied child to the supplied parent
18350Sstevel@tonic-gate */
18360Sstevel@tonic-gate int
pool_knl_set_container(pool_elem_t * pp,pool_elem_t * pc)18370Sstevel@tonic-gate pool_knl_set_container(pool_elem_t *pp, pool_elem_t *pc)
18380Sstevel@tonic-gate {
18390Sstevel@tonic-gate pool_knl_elem_t *pkp = (pool_knl_elem_t *)pp;
18400Sstevel@tonic-gate pool_knl_elem_t *pkc = (pool_knl_elem_t *)pc;
18410Sstevel@tonic-gate
18420Sstevel@tonic-gate pkc->pke_parent = pkp;
18430Sstevel@tonic-gate return (PO_SUCCESS);
18440Sstevel@tonic-gate }
18450Sstevel@tonic-gate
18460Sstevel@tonic-gate /*
18470Sstevel@tonic-gate * TODO: Needed for msets and ssets.
18480Sstevel@tonic-gate */
18490Sstevel@tonic-gate /* ARGSUSED */
18500Sstevel@tonic-gate int
pool_knl_res_transfer(pool_resource_t * src,pool_resource_t * tgt,uint64_t size)18510Sstevel@tonic-gate pool_knl_res_transfer(pool_resource_t *src, pool_resource_t *tgt,
18520Sstevel@tonic-gate uint64_t size) {
18530Sstevel@tonic-gate return (PO_FAIL);
18540Sstevel@tonic-gate }
18550Sstevel@tonic-gate
18560Sstevel@tonic-gate /*
18570Sstevel@tonic-gate * Transfer resource components from one resource set to another.
18580Sstevel@tonic-gate */
18590Sstevel@tonic-gate int
pool_knl_res_xtransfer(pool_resource_t * src,pool_resource_t * tgt,pool_component_t ** rl)18600Sstevel@tonic-gate pool_knl_res_xtransfer(pool_resource_t *src, pool_resource_t *tgt,
18610Sstevel@tonic-gate pool_component_t **rl) {
18620Sstevel@tonic-gate pool_elem_t *src_e = TO_ELEM(src);
18630Sstevel@tonic-gate pool_elem_t *tgt_e = TO_ELEM(tgt);
18640Sstevel@tonic-gate pool_xtransfer_undo_t *xtransfer;
18650Sstevel@tonic-gate size_t size;
18660Sstevel@tonic-gate pool_knl_connection_t *prov =
18670Sstevel@tonic-gate (pool_knl_connection_t *)TO_CONF(src_e)->pc_prov;
18680Sstevel@tonic-gate
18690Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) {
18700Sstevel@tonic-gate /*
18710Sstevel@tonic-gate * Walk the Result Set and move the resource components
18720Sstevel@tonic-gate */
18730Sstevel@tonic-gate for (size = 0; rl[size] != NULL; size++) {
18740Sstevel@tonic-gate if (pool_set_container(TO_ELEM(tgt),
18750Sstevel@tonic-gate TO_ELEM(rl[size])) == PO_FAIL) {
18760Sstevel@tonic-gate return (PO_FAIL);
18770Sstevel@tonic-gate }
18780Sstevel@tonic-gate }
18790Sstevel@tonic-gate return (PO_SUCCESS);
18800Sstevel@tonic-gate }
18810Sstevel@tonic-gate
18820Sstevel@tonic-gate /*
18830Sstevel@tonic-gate * The remaining logic is setting up the arguments for the
18840Sstevel@tonic-gate * POOL_XTRANSFER ioctl and appending the details into the log.
18850Sstevel@tonic-gate */
18860Sstevel@tonic-gate if ((xtransfer = malloc(sizeof (pool_xtransfer_undo_t))) == NULL) {
18870Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
18880Sstevel@tonic-gate return (PO_FAIL);
18890Sstevel@tonic-gate }
18900Sstevel@tonic-gate
18910Sstevel@tonic-gate if (pool_elem_class(src_e) == PEC_RES_COMP) {
18920Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_id_type =
18930Sstevel@tonic-gate pool_resource_elem_class(src_e);
18940Sstevel@tonic-gate } else {
18950Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
18960Sstevel@tonic-gate return (PO_FAIL);
18970Sstevel@tonic-gate }
18980Sstevel@tonic-gate
18990Sstevel@tonic-gate
19000Sstevel@tonic-gate for (xtransfer->pxu_ioctl.px_o_complist_size = 0;
19010Sstevel@tonic-gate rl[xtransfer->pxu_ioctl.px_o_complist_size] != NULL;
19020Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_complist_size++)
19030Sstevel@tonic-gate /* calculate the size using the terminating NULL */;
19040Sstevel@tonic-gate if ((xtransfer->pxu_ioctl.px_o_comp_list =
19050Sstevel@tonic-gate calloc(xtransfer->pxu_ioctl.px_o_complist_size,
19060Sstevel@tonic-gate sizeof (id_t))) == NULL) {
19070Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
19080Sstevel@tonic-gate return (PO_FAIL);
19090Sstevel@tonic-gate }
19100Sstevel@tonic-gate if ((xtransfer->pxu_rl = calloc(
19110Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_complist_size + 1,
19120Sstevel@tonic-gate sizeof (pool_component_t *))) == NULL) {
19130Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
19140Sstevel@tonic-gate return (PO_FAIL);
19150Sstevel@tonic-gate }
19160Sstevel@tonic-gate (void) memcpy(xtransfer->pxu_rl, rl,
19170Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_complist_size *
19180Sstevel@tonic-gate sizeof (pool_component_t *));
19190Sstevel@tonic-gate xtransfer->pxu_src = src_e;
19200Sstevel@tonic-gate xtransfer->pxu_tgt = tgt_e;
19210Sstevel@tonic-gate
19220Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_XTRANSFER, (void *)xtransfer) !=
19230Sstevel@tonic-gate PO_SUCCESS) {
19240Sstevel@tonic-gate free(xtransfer);
19250Sstevel@tonic-gate return (PO_FAIL);
19260Sstevel@tonic-gate }
19270Sstevel@tonic-gate for (size = 0; rl[size] != NULL; size++) {
19280Sstevel@tonic-gate if (pool_set_container(TO_ELEM(tgt), TO_ELEM(rl[size])) ==
19290Sstevel@tonic-gate PO_FAIL) {
19300Sstevel@tonic-gate return (PO_FAIL);
19310Sstevel@tonic-gate }
19320Sstevel@tonic-gate }
19330Sstevel@tonic-gate return (PO_SUCCESS);
19340Sstevel@tonic-gate }
19350Sstevel@tonic-gate
19360Sstevel@tonic-gate /*
19370Sstevel@tonic-gate * Return the parent of an element.
19380Sstevel@tonic-gate */
19390Sstevel@tonic-gate pool_elem_t *
pool_knl_get_container(const pool_elem_t * pe)19400Sstevel@tonic-gate pool_knl_get_container(const pool_elem_t *pe)
19410Sstevel@tonic-gate {
19420Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
19430Sstevel@tonic-gate
19440Sstevel@tonic-gate return ((pool_elem_t *)pke->pke_parent);
19450Sstevel@tonic-gate }
19460Sstevel@tonic-gate
19470Sstevel@tonic-gate /*
19480Sstevel@tonic-gate * Note: This function is resource specific, needs extending for other
19490Sstevel@tonic-gate * resource types
19500Sstevel@tonic-gate */
19510Sstevel@tonic-gate int
pool_knl_resource_is_system(const pool_resource_t * pr)19520Sstevel@tonic-gate pool_knl_resource_is_system(const pool_resource_t *pr)
19530Sstevel@tonic-gate {
19540Sstevel@tonic-gate switch (pool_resource_elem_class(TO_ELEM(pr))) {
19550Sstevel@tonic-gate case PREC_PSET:
19560Sstevel@tonic-gate return (PSID_IS_SYSSET(
19570Sstevel@tonic-gate elem_get_sysid(TO_ELEM(pr))));
19580Sstevel@tonic-gate default:
19590Sstevel@tonic-gate return (PO_FALSE);
19600Sstevel@tonic-gate }
19610Sstevel@tonic-gate }
19620Sstevel@tonic-gate
19630Sstevel@tonic-gate /*
19640Sstevel@tonic-gate * Note: This function is resource specific, needs extending for other
19650Sstevel@tonic-gate * resource types
19660Sstevel@tonic-gate */
19670Sstevel@tonic-gate int
pool_knl_resource_can_associate(const pool_resource_t * pr)19680Sstevel@tonic-gate pool_knl_resource_can_associate(const pool_resource_t *pr)
19690Sstevel@tonic-gate {
19700Sstevel@tonic-gate switch (pool_resource_elem_class(TO_ELEM(pr))) {
19710Sstevel@tonic-gate case PREC_PSET:
19720Sstevel@tonic-gate return (PO_TRUE);
19730Sstevel@tonic-gate default:
19740Sstevel@tonic-gate return (PO_FALSE);
19750Sstevel@tonic-gate }
19760Sstevel@tonic-gate }
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate /*
19790Sstevel@tonic-gate * pool_knl_pool_associate() associates the supplied resource to the
19800Sstevel@tonic-gate * supplied pool.
19810Sstevel@tonic-gate *
19820Sstevel@tonic-gate * Returns: PO_SUCCESS/PO_FAIL
19830Sstevel@tonic-gate */
19840Sstevel@tonic-gate int
pool_knl_pool_associate(pool_t * pool,const pool_resource_t * resource)19850Sstevel@tonic-gate pool_knl_pool_associate(pool_t *pool, const pool_resource_t *resource)
19860Sstevel@tonic-gate {
19870Sstevel@tonic-gate pool_knl_connection_t *prov;
19880Sstevel@tonic-gate pool_knl_pool_t *pkp = (pool_knl_pool_t *)pool;
19890Sstevel@tonic-gate pool_resource_elem_class_t res_class =
19900Sstevel@tonic-gate pool_resource_elem_class(TO_ELEM(resource));
19910Sstevel@tonic-gate pool_assoc_undo_t *assoc;
19920Sstevel@tonic-gate pool_knl_resource_t *orig_res = pkp->pkp_assoc[res_class];
19930Sstevel@tonic-gate
19940Sstevel@tonic-gate /*
19950Sstevel@tonic-gate * Are we allowed to associate with this target?
19960Sstevel@tonic-gate */
19970Sstevel@tonic-gate if (pool_knl_resource_can_associate(resource) == PO_FALSE) {
19980Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
19990Sstevel@tonic-gate return (PO_FAIL);
20000Sstevel@tonic-gate }
20010Sstevel@tonic-gate prov = (pool_knl_connection_t *)(TO_CONF(TO_ELEM(pool)))->pc_prov;
20020Sstevel@tonic-gate
20030Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) {
20040Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
20050Sstevel@tonic-gate return (PO_SUCCESS);
20060Sstevel@tonic-gate }
20070Sstevel@tonic-gate
20080Sstevel@tonic-gate /*
20090Sstevel@tonic-gate * The remaining logic is setting up the arguments for the
20100Sstevel@tonic-gate * POOL_ASSOC ioctl and appending the details into the log.
20110Sstevel@tonic-gate */
20120Sstevel@tonic-gate if ((assoc = malloc(sizeof (pool_assoc_undo_t))) == NULL) {
20130Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
20140Sstevel@tonic-gate return (PO_FAIL);
20150Sstevel@tonic-gate }
20160Sstevel@tonic-gate assoc->pau_assoc = TO_ELEM(pool);
20170Sstevel@tonic-gate assoc->pau_oldres = (pool_elem_t *)orig_res;
20180Sstevel@tonic-gate assoc->pau_newres = TO_ELEM(resource);
20190Sstevel@tonic-gate
20200Sstevel@tonic-gate assoc->pau_ioctl.pa_o_id_type = res_class;
20210Sstevel@tonic-gate
20220Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_ASSOC, (void *)assoc) !=
20230Sstevel@tonic-gate PO_SUCCESS) {
20240Sstevel@tonic-gate free(assoc);
20250Sstevel@tonic-gate pkp->pkp_assoc[res_class] = orig_res;
20260Sstevel@tonic-gate return (PO_FAIL);
20270Sstevel@tonic-gate }
20280Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
20290Sstevel@tonic-gate return (PO_SUCCESS);
20300Sstevel@tonic-gate }
20310Sstevel@tonic-gate
20320Sstevel@tonic-gate /*
20330Sstevel@tonic-gate * pool_knl_pool_dissociate() dissociates the supplied resource from
20340Sstevel@tonic-gate * the supplied pool.
20350Sstevel@tonic-gate *
20360Sstevel@tonic-gate * Returns: PO_SUCCESS/PO_FAIL
20370Sstevel@tonic-gate */
20380Sstevel@tonic-gate int
pool_knl_pool_dissociate(pool_t * pool,const pool_resource_t * resource)20390Sstevel@tonic-gate pool_knl_pool_dissociate(pool_t *pool, const pool_resource_t *resource)
20400Sstevel@tonic-gate {
20410Sstevel@tonic-gate pool_knl_connection_t *prov;
20420Sstevel@tonic-gate pool_dissoc_undo_t *dissoc;
20430Sstevel@tonic-gate pool_knl_pool_t *pkp = (pool_knl_pool_t *)pool;
20440Sstevel@tonic-gate pool_resource_t *default_res = (pool_resource_t *)get_default_resource(
20450Sstevel@tonic-gate resource);
20460Sstevel@tonic-gate pool_resource_elem_class_t res_class =
20470Sstevel@tonic-gate pool_resource_elem_class(TO_ELEM(resource));
20480Sstevel@tonic-gate
20490Sstevel@tonic-gate prov = (pool_knl_connection_t *)(TO_CONF(TO_ELEM(pool)))->pc_prov;
20500Sstevel@tonic-gate
20510Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) {
20520Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)default_res;
20530Sstevel@tonic-gate return (PO_SUCCESS);
20540Sstevel@tonic-gate }
20550Sstevel@tonic-gate /*
20560Sstevel@tonic-gate * The remaining logic is setting up the arguments for the
20570Sstevel@tonic-gate * POOL_DISSOC ioctl and appending the details into the log.
20580Sstevel@tonic-gate */
20590Sstevel@tonic-gate if ((dissoc = malloc(sizeof (pool_dissoc_undo_t))) == NULL) {
20600Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
20610Sstevel@tonic-gate return (PO_FAIL);
20620Sstevel@tonic-gate }
20630Sstevel@tonic-gate dissoc->pdu_dissoc = TO_ELEM(pool);
20640Sstevel@tonic-gate dissoc->pdu_oldres = TO_ELEM(resource);
20650Sstevel@tonic-gate dissoc->pdu_newres = TO_ELEM(default_res);
20660Sstevel@tonic-gate
20670Sstevel@tonic-gate dissoc->pdu_ioctl.pd_o_id_type = res_class;
20680Sstevel@tonic-gate
20690Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_DISSOC, (void *)dissoc) !=
20700Sstevel@tonic-gate PO_SUCCESS) {
20710Sstevel@tonic-gate free(dissoc);
20720Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
20730Sstevel@tonic-gate return (PO_FAIL);
20740Sstevel@tonic-gate }
20750Sstevel@tonic-gate
20760Sstevel@tonic-gate /*
20770Sstevel@tonic-gate * Update our local copy
20780Sstevel@tonic-gate */
20790Sstevel@tonic-gate pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)default_res;
20800Sstevel@tonic-gate return (PO_SUCCESS);
20810Sstevel@tonic-gate }
20820Sstevel@tonic-gate
20830Sstevel@tonic-gate /*
20840Sstevel@tonic-gate * Allocate a data provider for the supplied configuration and optionally
20850Sstevel@tonic-gate * discover resources.
20860Sstevel@tonic-gate * The data provider is the cross over point from the "abstract" configuration
20870Sstevel@tonic-gate * functions into the data representation specific manipulation routines.
20880Sstevel@tonic-gate * This function sets up all the required pointers to create a kernel aware
20890Sstevel@tonic-gate * data provider.
20900Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
20910Sstevel@tonic-gate */
20920Sstevel@tonic-gate int
pool_knl_connection_alloc(pool_conf_t * conf,int oflags)20930Sstevel@tonic-gate pool_knl_connection_alloc(pool_conf_t *conf, int oflags)
20940Sstevel@tonic-gate {
20950Sstevel@tonic-gate pool_knl_connection_t *prov;
20960Sstevel@tonic-gate
20970Sstevel@tonic-gate if ((prov = malloc(sizeof (pool_knl_connection_t))) == NULL) {
20980Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
20990Sstevel@tonic-gate return (PO_FAIL);
21000Sstevel@tonic-gate }
21010Sstevel@tonic-gate (void) memset(prov, 0, sizeof (pool_knl_connection_t));
21020Sstevel@tonic-gate /*
21030Sstevel@tonic-gate * Initialise data members
21040Sstevel@tonic-gate */
21050Sstevel@tonic-gate prov->pc_name = strdup("kernel");
21060Sstevel@tonic-gate prov->pc_store_type = KERNEL_DATA_STORE;
21070Sstevel@tonic-gate prov->pc_oflags = oflags;
21080Sstevel@tonic-gate /*
21090Sstevel@tonic-gate * Initialise function pointers
21100Sstevel@tonic-gate */
21110Sstevel@tonic-gate prov->pc_close = pool_knl_close;
21120Sstevel@tonic-gate prov->pc_validate = pool_knl_validate;
21130Sstevel@tonic-gate prov->pc_commit = pool_knl_commit;
21140Sstevel@tonic-gate prov->pc_export = pool_knl_export;
21150Sstevel@tonic-gate prov->pc_rollback = pool_knl_rollback;
21160Sstevel@tonic-gate prov->pc_exec_query = pool_knl_exec_query;
21170Sstevel@tonic-gate prov->pc_elem_create = pool_knl_elem_create;
21180Sstevel@tonic-gate prov->pc_remove = pool_knl_remove;
21190Sstevel@tonic-gate prov->pc_res_xfer = pool_knl_res_transfer;
21200Sstevel@tonic-gate prov->pc_res_xxfer = pool_knl_res_xtransfer;
21210Sstevel@tonic-gate prov->pc_get_binding = pool_knl_get_binding;
21220Sstevel@tonic-gate prov->pc_set_binding = pool_knl_set_binding;
21230Sstevel@tonic-gate prov->pc_get_resource_binding = pool_knl_get_resource_binding;
21240Sstevel@tonic-gate /*
21250Sstevel@tonic-gate * Associate the provider to it's configuration
21260Sstevel@tonic-gate */
21270Sstevel@tonic-gate conf->pc_prov = (pool_connection_t *)prov;
21280Sstevel@tonic-gate /*
21290Sstevel@tonic-gate * End of common initialisation
21300Sstevel@tonic-gate */
21310Sstevel@tonic-gate /*
21320Sstevel@tonic-gate * Attempt to open the pseudo device, if the configuration is opened
21330Sstevel@tonic-gate * readonly then try to open an info device, otherwise try to open
21340Sstevel@tonic-gate * the writeable device.
21350Sstevel@tonic-gate */
21360Sstevel@tonic-gate if (oflags & PO_RDWR) {
21370Sstevel@tonic-gate if ((prov->pkc_fd = blocking_open(pool_dynamic_location(),
21380Sstevel@tonic-gate O_RDWR)) < 0) {
21390Sstevel@tonic-gate free(prov);
21400Sstevel@tonic-gate conf->pc_prov = NULL;
21410Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
21420Sstevel@tonic-gate return (PO_FAIL);
21430Sstevel@tonic-gate }
21440Sstevel@tonic-gate } else {
21450Sstevel@tonic-gate if ((prov->pkc_fd = open(pool_info_location, O_RDWR)) < 0) {
21460Sstevel@tonic-gate free(prov);
21470Sstevel@tonic-gate conf->pc_prov = NULL;
21480Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
21490Sstevel@tonic-gate return (PO_FAIL);
21500Sstevel@tonic-gate }
21510Sstevel@tonic-gate }
21520Sstevel@tonic-gate /*
21530Sstevel@tonic-gate * Allocate the element dictionary
21540Sstevel@tonic-gate */
21550Sstevel@tonic-gate if ((prov->pkc_elements = dict_new((int (*)(const void *, const void *))
21560Sstevel@tonic-gate pool_elem_compare, (uint64_t (*)(const void *))hash_id)) == NULL) {
21570Sstevel@tonic-gate (void) close(prov->pkc_fd);
21580Sstevel@tonic-gate free(prov);
21590Sstevel@tonic-gate conf->pc_prov = NULL;
21600Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
21610Sstevel@tonic-gate return (PO_FAIL);
21620Sstevel@tonic-gate }
21630Sstevel@tonic-gate #if DEBUG
21640Sstevel@tonic-gate if ((prov->pkc_leaks = dict_new(NULL, NULL)) == NULL) {
21650Sstevel@tonic-gate dict_free(&prov->pkc_elements);
21660Sstevel@tonic-gate (void) close(prov->pkc_fd);
21670Sstevel@tonic-gate free(prov);
21680Sstevel@tonic-gate conf->pc_prov = NULL;
21690Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
21700Sstevel@tonic-gate return (PO_FAIL);
21710Sstevel@tonic-gate }
21720Sstevel@tonic-gate #endif /* DEBUG */
21730Sstevel@tonic-gate /*
21740Sstevel@tonic-gate * Allocate the transaction log
21750Sstevel@tonic-gate */
21760Sstevel@tonic-gate if ((prov->pkc_log = log_alloc(conf)) == NULL) {
21770Sstevel@tonic-gate #if DEBUG
21780Sstevel@tonic-gate dict_free(&prov->pkc_leaks);
21790Sstevel@tonic-gate #endif /* DEBUG */
21800Sstevel@tonic-gate dict_free(&prov->pkc_elements);
21810Sstevel@tonic-gate (void) close(prov->pkc_fd);
21820Sstevel@tonic-gate free(prov);
21830Sstevel@tonic-gate conf->pc_prov = NULL;
21840Sstevel@tonic-gate return (PO_FAIL);
21850Sstevel@tonic-gate }
21860Sstevel@tonic-gate /*
21870Sstevel@tonic-gate * At this point the configuration provider has been initialized,
21880Sstevel@tonic-gate * mark the configuration as valid so that the various routines
21890Sstevel@tonic-gate * which rely on a valid configuration will work correctly.
21900Sstevel@tonic-gate */
21910Sstevel@tonic-gate conf->pc_state = POF_VALID;
21920Sstevel@tonic-gate /*
21930Sstevel@tonic-gate * Update the library snapshot from the kernel
21940Sstevel@tonic-gate */
21950Sstevel@tonic-gate if (pool_knl_update(conf, NULL) != PO_SUCCESS) {
21960Sstevel@tonic-gate #if DEBUG
21970Sstevel@tonic-gate dict_free(&prov->pkc_leaks);
21980Sstevel@tonic-gate #endif /* DEBUG */
21990Sstevel@tonic-gate dict_free(&prov->pkc_elements);
22000Sstevel@tonic-gate (void) close(prov->pkc_fd);
22010Sstevel@tonic-gate free(prov);
22020Sstevel@tonic-gate conf->pc_prov = NULL;
22030Sstevel@tonic-gate conf->pc_state = POF_INVALID;
22040Sstevel@tonic-gate return (PO_FAIL);
22050Sstevel@tonic-gate }
22060Sstevel@tonic-gate return (PO_SUCCESS);
22070Sstevel@tonic-gate }
22080Sstevel@tonic-gate
22090Sstevel@tonic-gate #if DEBUG
22100Sstevel@tonic-gate static void
pool_knl_elem_printf_cb(const void * key,void ** value,void * cl)22110Sstevel@tonic-gate pool_knl_elem_printf_cb(const void *key, void **value, void *cl)
22120Sstevel@tonic-gate {
22130Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
22140Sstevel@tonic-gate dict_hdl_t *map = (dict_hdl_t *)cl;
22150Sstevel@tonic-gate
22160Sstevel@tonic-gate dprintf("leak elem:%p\n", pke);
22170Sstevel@tonic-gate if (pke->pke_properties != NULL) {
22180Sstevel@tonic-gate nvlist_print(stdout, pke->pke_properties);
22190Sstevel@tonic-gate } else
22200Sstevel@tonic-gate dprintf("no properties\n");
22210Sstevel@tonic-gate assert(dict_get(map, pke) == NULL);
22220Sstevel@tonic-gate }
22230Sstevel@tonic-gate #endif /* DEBUG */
22240Sstevel@tonic-gate /*
22250Sstevel@tonic-gate * pool_knl_elem_free() releases the resources associated with the
22260Sstevel@tonic-gate * supplied element.
22270Sstevel@tonic-gate */
22280Sstevel@tonic-gate static void
pool_knl_elem_free(pool_knl_elem_t * pke,int freeprop)22290Sstevel@tonic-gate pool_knl_elem_free(pool_knl_elem_t *pke, int freeprop)
22300Sstevel@tonic-gate {
22310Sstevel@tonic-gate #if DEBUG
22320Sstevel@tonic-gate pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
22330Sstevel@tonic-gate if (dict_remove(((pool_knl_connection_t *)conf->pc_prov)->pkc_leaks,
22340Sstevel@tonic-gate pke) == NULL)
22350Sstevel@tonic-gate dprintf("%p, wasn't in the leak map\n", pke);
22360Sstevel@tonic-gate if (freeprop == PO_TRUE) {
22370Sstevel@tonic-gate pool_elem_dprintf(TO_ELEM(pke));
22380Sstevel@tonic-gate }
22390Sstevel@tonic-gate dprintf("released %p\n", pke);
22400Sstevel@tonic-gate #endif /* DEBUG */
22410Sstevel@tonic-gate if (freeprop == PO_TRUE) {
22420Sstevel@tonic-gate nvlist_free(pke->pke_properties);
22430Sstevel@tonic-gate }
22440Sstevel@tonic-gate free(pke);
22450Sstevel@tonic-gate }
22460Sstevel@tonic-gate
22470Sstevel@tonic-gate /*
22480Sstevel@tonic-gate * pool_knl_elem_free_cb() is designed to be used with
22490Sstevel@tonic-gate * dict_map(). When a connection is freed, this function is used to
22500Sstevel@tonic-gate * free all element resources.
22510Sstevel@tonic-gate */
22520Sstevel@tonic-gate /* ARGSUSED1 */
22530Sstevel@tonic-gate static void
pool_knl_elem_free_cb(const void * key,void ** value,void * cl)22540Sstevel@tonic-gate pool_knl_elem_free_cb(const void *key, void **value, void *cl)
22550Sstevel@tonic-gate {
22560Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
22570Sstevel@tonic-gate
22580Sstevel@tonic-gate #ifdef DEBUG
22590Sstevel@tonic-gate dprintf("pool_knl_elem_free_cb:\n");
22600Sstevel@tonic-gate dprintf("about to release %p ", pke);
22610Sstevel@tonic-gate pool_elem_dprintf(TO_ELEM(pke));
22620Sstevel@tonic-gate #endif /* DEBUG */
22630Sstevel@tonic-gate pool_knl_elem_free(pke, PO_TRUE);
22640Sstevel@tonic-gate }
22650Sstevel@tonic-gate
22660Sstevel@tonic-gate /*
22670Sstevel@tonic-gate * Free the resources for a kernel data provider.
22680Sstevel@tonic-gate */
22690Sstevel@tonic-gate void
pool_knl_connection_free(pool_knl_connection_t * prov)22700Sstevel@tonic-gate pool_knl_connection_free(pool_knl_connection_t *prov)
22710Sstevel@tonic-gate {
22720Sstevel@tonic-gate if (prov->pkc_log != NULL) {
22730Sstevel@tonic-gate (void) log_walk(prov->pkc_log, log_item_release);
22740Sstevel@tonic-gate log_free(prov->pkc_log);
22750Sstevel@tonic-gate }
22760Sstevel@tonic-gate if (prov->pkc_elements != NULL) {
22770Sstevel@tonic-gate dict_map(prov->pkc_elements, pool_knl_elem_free_cb, NULL);
22780Sstevel@tonic-gate #if DEBUG
22790Sstevel@tonic-gate dprintf("dict length is %llu\n", dict_length(prov->pkc_leaks));
22800Sstevel@tonic-gate dict_map(prov->pkc_leaks, pool_knl_elem_printf_cb,
22810Sstevel@tonic-gate prov->pkc_elements);
22820Sstevel@tonic-gate assert(dict_length(prov->pkc_leaks) == 0);
22830Sstevel@tonic-gate dict_free(&prov->pkc_leaks);
22840Sstevel@tonic-gate #endif /* DEBUG */
22850Sstevel@tonic-gate dict_free(&prov->pkc_elements);
22860Sstevel@tonic-gate }
22870Sstevel@tonic-gate free((void *)prov->pc_name);
22880Sstevel@tonic-gate free(prov);
22890Sstevel@tonic-gate }
22900Sstevel@tonic-gate
22910Sstevel@tonic-gate /*
22920Sstevel@tonic-gate * Return the specified property value.
22930Sstevel@tonic-gate *
22940Sstevel@tonic-gate * POC_INVAL is returned if an error is detected and the error code is updated
22950Sstevel@tonic-gate * to indicate the cause of the error.
22960Sstevel@tonic-gate */
22970Sstevel@tonic-gate pool_value_class_t
pool_knl_get_property(const pool_elem_t * pe,const char * name,pool_value_t * val)22980Sstevel@tonic-gate pool_knl_get_property(const pool_elem_t *pe, const char *name,
22990Sstevel@tonic-gate pool_value_t *val)
23000Sstevel@tonic-gate {
23010Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
23020Sstevel@tonic-gate nvpair_t *pair;
23030Sstevel@tonic-gate const pool_prop_t *prop;
23040Sstevel@tonic-gate
23050Sstevel@tonic-gate if ((prop = provider_get_prop(pe, name)) != NULL)
23060Sstevel@tonic-gate if (prop_is_stored(prop) == PO_FALSE)
23070Sstevel@tonic-gate return (pool_knl_get_dynamic_property(pe, name, val));
23080Sstevel@tonic-gate
23090Sstevel@tonic-gate if ((pair = pool_knl_find_nvpair(pke->pke_properties, name)) == NULL) {
23100Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
23110Sstevel@tonic-gate return (POC_INVAL);
23120Sstevel@tonic-gate }
23130Sstevel@tonic-gate
23140Sstevel@tonic-gate if (pool_value_from_nvpair(val, pair) == PO_FAIL) {
23150Sstevel@tonic-gate return (POC_INVAL);
23160Sstevel@tonic-gate }
23170Sstevel@tonic-gate
23180Sstevel@tonic-gate return (pool_value_get_type(val));
23190Sstevel@tonic-gate }
23200Sstevel@tonic-gate
23210Sstevel@tonic-gate /*
23220Sstevel@tonic-gate * Return the specified property value.
23230Sstevel@tonic-gate *
23240Sstevel@tonic-gate * If a property is designated as dynamic, then this function will
23250Sstevel@tonic-gate * always try to return the latest value of the property from the
23260Sstevel@tonic-gate * kernel.
23270Sstevel@tonic-gate *
23280Sstevel@tonic-gate * POC_INVAL is returned if an error is detected and the error code is updated
23290Sstevel@tonic-gate * to indicate the cause of the error.
23300Sstevel@tonic-gate */
23310Sstevel@tonic-gate pool_value_class_t
pool_knl_get_dynamic_property(const pool_elem_t * pe,const char * name,pool_value_t * val)23320Sstevel@tonic-gate pool_knl_get_dynamic_property(const pool_elem_t *pe, const char *name,
23330Sstevel@tonic-gate pool_value_t *val)
23340Sstevel@tonic-gate {
23350Sstevel@tonic-gate pool_knl_connection_t *prov;
23360Sstevel@tonic-gate pool_propget_t propget = { 0 };
23370Sstevel@tonic-gate nvlist_t *proplist;
23380Sstevel@tonic-gate nvpair_t *pair;
23390Sstevel@tonic-gate
23400Sstevel@tonic-gate propget.pp_o_id_type = pool_elem_class(pe);
23410Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_RES_COMP ||
23420Sstevel@tonic-gate pool_elem_class(pe) == PEC_RES_AGG)
23430Sstevel@tonic-gate propget.pp_o_id_subtype = pool_resource_elem_class(pe);
23440Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_COMP)
23450Sstevel@tonic-gate propget.pp_o_id_subtype =
23460Sstevel@tonic-gate (pool_resource_elem_class_t)pool_component_elem_class(pe);
23470Sstevel@tonic-gate
23480Sstevel@tonic-gate propget.pp_o_id = elem_get_sysid(pe);
23490Sstevel@tonic-gate propget.pp_o_prop_name_size = strlen(name);
23500Sstevel@tonic-gate propget.pp_o_prop_name = (char *)name;
23510Sstevel@tonic-gate propget.pp_i_bufsize = KERNEL_SNAPSHOT_BUF_SZ;
23520Sstevel@tonic-gate propget.pp_i_buf = malloc(KERNEL_SNAPSHOT_BUF_SZ);
23530Sstevel@tonic-gate bzero(propget.pp_i_buf, KERNEL_SNAPSHOT_BUF_SZ);
23540Sstevel@tonic-gate
23550Sstevel@tonic-gate prov = (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
23560Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPGET, &propget) < 0) {
23570Sstevel@tonic-gate free(propget.pp_i_buf);
23580Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
23590Sstevel@tonic-gate return (POC_INVAL);
23600Sstevel@tonic-gate }
23610Sstevel@tonic-gate if (nvlist_unpack(propget.pp_i_buf, propget.pp_i_bufsize,
23620Sstevel@tonic-gate &proplist, 0) != 0) {
23630Sstevel@tonic-gate free(propget.pp_i_buf);
23640Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
23650Sstevel@tonic-gate return (POC_INVAL);
23660Sstevel@tonic-gate }
23670Sstevel@tonic-gate free(propget.pp_i_buf);
23680Sstevel@tonic-gate
23690Sstevel@tonic-gate if ((pair = nvlist_next_nvpair(proplist, NULL)) == NULL) {
23700Sstevel@tonic-gate nvlist_free(proplist);
23710Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
23720Sstevel@tonic-gate return (POC_INVAL);
23730Sstevel@tonic-gate }
23740Sstevel@tonic-gate
23750Sstevel@tonic-gate if (pool_value_from_nvpair(val, pair) == PO_FAIL) {
23760Sstevel@tonic-gate nvlist_free(proplist);
23770Sstevel@tonic-gate return (POC_INVAL);
23780Sstevel@tonic-gate }
23790Sstevel@tonic-gate nvlist_free(proplist);
23800Sstevel@tonic-gate return (pool_value_get_type(val));
23810Sstevel@tonic-gate }
23820Sstevel@tonic-gate
23830Sstevel@tonic-gate /*
23840Sstevel@tonic-gate * Update the specified property value.
23850Sstevel@tonic-gate *
23860Sstevel@tonic-gate * PO_FAIL is returned if an error is detected and the error code is updated
23870Sstevel@tonic-gate * to indicate the cause of the error.
23880Sstevel@tonic-gate */
23890Sstevel@tonic-gate int
pool_knl_put_property(pool_elem_t * pe,const char * name,const pool_value_t * val)23900Sstevel@tonic-gate pool_knl_put_property(pool_elem_t *pe, const char *name,
23910Sstevel@tonic-gate const pool_value_t *val)
23920Sstevel@tonic-gate {
23930Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
23940Sstevel@tonic-gate pool_knl_connection_t *prov =
23950Sstevel@tonic-gate (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
23960Sstevel@tonic-gate nvpair_t *bp, *ap;
23970Sstevel@tonic-gate pool_propput_undo_t *propput;
23980Sstevel@tonic-gate nvlist_t *bl = NULL;
23990Sstevel@tonic-gate const pool_prop_t *prop;
24000Sstevel@tonic-gate
24010Sstevel@tonic-gate if ((bp = pool_knl_find_nvpair(pke->pke_properties, name)) != NULL) {
24020Sstevel@tonic-gate if (nvlist_alloc(&bl, NV_UNIQUE_NAME_TYPE, 0) != 0) {
24030Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
24040Sstevel@tonic-gate return (PO_FAIL);
24050Sstevel@tonic-gate }
24060Sstevel@tonic-gate if (nvlist_add_nvpair(bl, bp) != 0) {
24070Sstevel@tonic-gate nvlist_free(bl);
24080Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
24090Sstevel@tonic-gate return (PO_FAIL);
24100Sstevel@tonic-gate }
24110Sstevel@tonic-gate }
24120Sstevel@tonic-gate if (pool_knl_nvlist_add_value(pke->pke_properties, name, val) !=
24130Sstevel@tonic-gate PO_SUCCESS)
24140Sstevel@tonic-gate return (PO_FAIL);
24150Sstevel@tonic-gate
24160Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) {
24170Sstevel@tonic-gate if (bl)
24180Sstevel@tonic-gate nvlist_free(bl);
24190Sstevel@tonic-gate return (PO_SUCCESS);
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate /*
24220Sstevel@tonic-gate * The remaining logic is setting up the arguments for the
24230Sstevel@tonic-gate * POOL_PROPPUT ioctl and appending the details into the log.
24240Sstevel@tonic-gate */
24250Sstevel@tonic-gate if ((propput = malloc(sizeof (pool_propput_undo_t))) == NULL) {
24260Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
24270Sstevel@tonic-gate return (PO_FAIL);
24280Sstevel@tonic-gate }
24290Sstevel@tonic-gate (void) memset(propput, 0, sizeof (pool_propput_undo_t));
24300Sstevel@tonic-gate propput->ppu_blist = bl;
24310Sstevel@tonic-gate
24320Sstevel@tonic-gate ap = pool_knl_find_nvpair(pke->pke_properties, name);
24330Sstevel@tonic-gate
24340Sstevel@tonic-gate if (nvlist_alloc(&propput->ppu_alist, NV_UNIQUE_NAME_TYPE, 0) != 0) {
24350Sstevel@tonic-gate nvlist_free(propput->ppu_blist);
24360Sstevel@tonic-gate free(propput);
24370Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
24380Sstevel@tonic-gate return (PO_FAIL);
24390Sstevel@tonic-gate }
24400Sstevel@tonic-gate if (nvlist_add_nvpair(propput->ppu_alist, ap) != 0) {
24410Sstevel@tonic-gate nvlist_free(propput->ppu_blist);
24420Sstevel@tonic-gate nvlist_free(propput->ppu_alist);
24430Sstevel@tonic-gate free(propput);
24440Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
24450Sstevel@tonic-gate return (PO_FAIL);
24460Sstevel@tonic-gate }
24470Sstevel@tonic-gate
24480Sstevel@tonic-gate if (nvlist_pack(propput->ppu_alist,
24490Sstevel@tonic-gate (char **)&propput->ppu_ioctl.pp_o_buf,
24500Sstevel@tonic-gate &propput->ppu_ioctl.pp_o_bufsize, NV_ENCODE_NATIVE, 0) != 0) {
24510Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
24520Sstevel@tonic-gate return (PO_FAIL);
24530Sstevel@tonic-gate }
24540Sstevel@tonic-gate nvlist_free(propput->ppu_alist);
24550Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_type = pool_elem_class(pe);
24560Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_RES_COMP ||
24570Sstevel@tonic-gate pool_elem_class(pe) == PEC_RES_AGG)
24580Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_sub_type =
24590Sstevel@tonic-gate pool_resource_elem_class(pe);
24600Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_COMP)
24610Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_sub_type =
24620Sstevel@tonic-gate (pool_resource_elem_class_t)pool_component_elem_class(pe);
24630Sstevel@tonic-gate
24640Sstevel@tonic-gate propput->ppu_elem = pe;
24650Sstevel@tonic-gate if ((prop = provider_get_prop(propput->ppu_elem, name)) != NULL) {
24660Sstevel@tonic-gate if (prop_is_readonly(prop) == PO_TRUE)
24670Sstevel@tonic-gate propput->ppu_doioctl |= KERNEL_PROP_RDONLY;
24680Sstevel@tonic-gate }
24690Sstevel@tonic-gate
24700Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_PROPPUT, (void *)propput) !=
24710Sstevel@tonic-gate PO_SUCCESS) {
24720Sstevel@tonic-gate nvlist_free(propput->ppu_blist);
24730Sstevel@tonic-gate free(propput);
24740Sstevel@tonic-gate return (PO_FAIL);
24750Sstevel@tonic-gate }
24760Sstevel@tonic-gate return (PO_SUCCESS);
24770Sstevel@tonic-gate }
24780Sstevel@tonic-gate
24790Sstevel@tonic-gate /*
24800Sstevel@tonic-gate * Remove the specified property value.
24810Sstevel@tonic-gate *
24820Sstevel@tonic-gate * PO_FAIL is returned if an error is detected and the error code is
24830Sstevel@tonic-gate * updated to indicate the cause of the error.
24840Sstevel@tonic-gate */
24850Sstevel@tonic-gate int
pool_knl_rm_property(pool_elem_t * pe,const char * name)24860Sstevel@tonic-gate pool_knl_rm_property(pool_elem_t *pe, const char *name)
24870Sstevel@tonic-gate {
24880Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
24890Sstevel@tonic-gate pool_knl_connection_t *prov =
24900Sstevel@tonic-gate (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
24910Sstevel@tonic-gate pool_proprm_undo_t *proprm;
24920Sstevel@tonic-gate
24930Sstevel@tonic-gate if (pool_knl_find_nvpair(pke->pke_properties, name) == NULL) {
24940Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
24950Sstevel@tonic-gate return (PO_FAIL);
24960Sstevel@tonic-gate }
24970Sstevel@tonic-gate
24980Sstevel@tonic-gate if ((proprm = malloc(sizeof (pool_proprm_undo_t))) == NULL) {
24990Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
25000Sstevel@tonic-gate return (PO_FAIL);
25010Sstevel@tonic-gate }
25020Sstevel@tonic-gate (void) memset(proprm, 0, sizeof (pool_proprm_undo_t));
25030Sstevel@tonic-gate proprm->pru_oldval.pv_class = POC_INVAL;
25040Sstevel@tonic-gate (void) pool_get_property(TO_CONF(pe), pe, name, &proprm->pru_oldval);
25050Sstevel@tonic-gate
25060Sstevel@tonic-gate if (prov->pkc_log->l_state != LS_DO) {
25070Sstevel@tonic-gate free(proprm);
25080Sstevel@tonic-gate (void) nvlist_remove_all(pke->pke_properties, (char *)name);
25090Sstevel@tonic-gate return (PO_SUCCESS);
25100Sstevel@tonic-gate }
25110Sstevel@tonic-gate /*
25120Sstevel@tonic-gate * The remaining logic is setting up the arguments for the
25130Sstevel@tonic-gate * POOL_PROPRM ioctl and appending the details into the log.
25140Sstevel@tonic-gate */
25150Sstevel@tonic-gate
25160Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id_type = pool_elem_class(pe);
25170Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_RES_COMP ||
25180Sstevel@tonic-gate pool_elem_class(pe) == PEC_RES_AGG)
25190Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id_sub_type =
25200Sstevel@tonic-gate pool_resource_elem_class(pe);
25210Sstevel@tonic-gate
25220Sstevel@tonic-gate if (pool_elem_class(pe) == PEC_COMP)
25230Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id_sub_type =
25240Sstevel@tonic-gate (pool_resource_elem_class_t)pool_component_elem_class(pe);
25250Sstevel@tonic-gate
25260Sstevel@tonic-gate proprm->pru_ioctl.pp_o_prop_name_size = strlen(name);
25270Sstevel@tonic-gate proprm->pru_ioctl.pp_o_prop_name =
25280Sstevel@tonic-gate (char *)pool_value_get_name(&proprm->pru_oldval);
25290Sstevel@tonic-gate proprm->pru_elem = pe;
25300Sstevel@tonic-gate
25310Sstevel@tonic-gate if (log_append(prov->pkc_log, POOL_PROPRM, (void *)proprm) !=
25320Sstevel@tonic-gate PO_SUCCESS) {
25330Sstevel@tonic-gate free(proprm);
25340Sstevel@tonic-gate return (PO_FAIL);
25350Sstevel@tonic-gate }
25360Sstevel@tonic-gate
25370Sstevel@tonic-gate (void) nvlist_remove_all(pke->pke_properties, (char *)name);
25380Sstevel@tonic-gate return (PO_SUCCESS);
25390Sstevel@tonic-gate }
25400Sstevel@tonic-gate
25410Sstevel@tonic-gate /*
25420Sstevel@tonic-gate * Return a NULL terminated array of pool_value_t which represents all
25430Sstevel@tonic-gate * of the properties stored for an element
25440Sstevel@tonic-gate *
25450Sstevel@tonic-gate * Return NULL on failure. It is the caller's responsibility to free
25460Sstevel@tonic-gate * the returned array of values.
25470Sstevel@tonic-gate */
25480Sstevel@tonic-gate pool_value_t **
pool_knl_get_properties(const pool_elem_t * pe,uint_t * nprops)25490Sstevel@tonic-gate pool_knl_get_properties(const pool_elem_t *pe, uint_t *nprops)
25500Sstevel@tonic-gate {
25510Sstevel@tonic-gate nvpair_t *pair;
25520Sstevel@tonic-gate pool_value_t **result;
25530Sstevel@tonic-gate pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
25540Sstevel@tonic-gate int i = 0;
25550Sstevel@tonic-gate
25560Sstevel@tonic-gate *nprops = 0;
25570Sstevel@tonic-gate
25580Sstevel@tonic-gate for (pair = nvlist_next_nvpair(pke->pke_properties, NULL); pair != NULL;
2559*11411SSurya.Prakki@Sun.COM pair = nvlist_next_nvpair(pke->pke_properties, pair))
25600Sstevel@tonic-gate (*nprops)++;
25610Sstevel@tonic-gate if ((result = calloc(*nprops + 1, sizeof (pool_value_t *))) == NULL) {
25620Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
25630Sstevel@tonic-gate return (NULL);
25640Sstevel@tonic-gate }
25650Sstevel@tonic-gate for (pair = nvlist_next_nvpair(pke->pke_properties, NULL); pair != NULL;
25660Sstevel@tonic-gate pair = nvlist_next_nvpair(pke->pke_properties, pair), i++) {
25670Sstevel@tonic-gate result[i] = pool_value_alloc();
25680Sstevel@tonic-gate if (pool_value_from_nvpair(result[i], pair) == PO_FAIL) {
25690Sstevel@tonic-gate while (i-- >= 0)
25700Sstevel@tonic-gate pool_value_free(result[i]);
25710Sstevel@tonic-gate free(result);
25720Sstevel@tonic-gate return (NULL);
25730Sstevel@tonic-gate }
25740Sstevel@tonic-gate }
25750Sstevel@tonic-gate return (result);
25760Sstevel@tonic-gate }
25770Sstevel@tonic-gate
25780Sstevel@tonic-gate /*
25790Sstevel@tonic-gate * Append an entry to a result set. Reallocate the array used to store
25800Sstevel@tonic-gate * results if it's full.
25810Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
25820Sstevel@tonic-gate */
25830Sstevel@tonic-gate int
pool_knl_result_set_append(pool_knl_result_set_t * rs,pool_knl_elem_t * pke)25840Sstevel@tonic-gate pool_knl_result_set_append(pool_knl_result_set_t *rs, pool_knl_elem_t *pke)
25850Sstevel@tonic-gate {
25860Sstevel@tonic-gate if (rs->pkr_count == rs->pkr_size)
25870Sstevel@tonic-gate if (pool_knl_result_set_realloc(rs) != PO_SUCCESS)
25880Sstevel@tonic-gate return (PO_FAIL);
25890Sstevel@tonic-gate
25900Sstevel@tonic-gate rs->pkr_list[rs->pkr_count++] = pke;
25910Sstevel@tonic-gate
25920Sstevel@tonic-gate return (PO_SUCCESS);
25930Sstevel@tonic-gate }
25940Sstevel@tonic-gate
25950Sstevel@tonic-gate /*
25960Sstevel@tonic-gate * Resize the array used to store results. A simple doubling strategy
25970Sstevel@tonic-gate * is used.
25980Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
25990Sstevel@tonic-gate */
26000Sstevel@tonic-gate int
pool_knl_result_set_realloc(pool_knl_result_set_t * rs)26010Sstevel@tonic-gate pool_knl_result_set_realloc(pool_knl_result_set_t *rs)
26020Sstevel@tonic-gate {
26030Sstevel@tonic-gate pool_knl_elem_t **old_list = rs->pkr_list;
26040Sstevel@tonic-gate int new_size = rs->pkr_size * 2;
26050Sstevel@tonic-gate
26060Sstevel@tonic-gate if ((rs->pkr_list = realloc(rs->pkr_list,
26070Sstevel@tonic-gate new_size * sizeof (pool_knl_elem_t *))) == NULL) {
26080Sstevel@tonic-gate rs->pkr_list = old_list;
26090Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
26100Sstevel@tonic-gate return (PO_FAIL);
26110Sstevel@tonic-gate }
26120Sstevel@tonic-gate rs->pkr_size = new_size;
26130Sstevel@tonic-gate
26140Sstevel@tonic-gate return (PO_SUCCESS);
26150Sstevel@tonic-gate }
26160Sstevel@tonic-gate
26170Sstevel@tonic-gate /*
26180Sstevel@tonic-gate * Allocate a result set. The Result Set stores the result of a query.
26190Sstevel@tonic-gate * Returns pool_knl_result_set_t pointer/NULL
26200Sstevel@tonic-gate */
26210Sstevel@tonic-gate pool_knl_result_set_t *
pool_knl_result_set_alloc(const pool_conf_t * conf)26220Sstevel@tonic-gate pool_knl_result_set_alloc(const pool_conf_t *conf)
26230Sstevel@tonic-gate {
26240Sstevel@tonic-gate pool_knl_result_set_t *rs;
26250Sstevel@tonic-gate
26260Sstevel@tonic-gate if ((rs = malloc(sizeof (pool_knl_result_set_t))) == NULL) {
26270Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
26280Sstevel@tonic-gate return (NULL);
26290Sstevel@tonic-gate }
26300Sstevel@tonic-gate (void) memset(rs, 0, sizeof (pool_knl_result_set_t));
26310Sstevel@tonic-gate rs->pkr_size = KERNEL_RS_INITIAL_SZ;
26320Sstevel@tonic-gate if (pool_knl_result_set_realloc(rs) == PO_FAIL) {
26330Sstevel@tonic-gate free(rs);
26340Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
26350Sstevel@tonic-gate return (NULL);
26360Sstevel@tonic-gate }
26370Sstevel@tonic-gate rs->prs_conf = conf;
26380Sstevel@tonic-gate rs->prs_index = -1;
26390Sstevel@tonic-gate rs->prs_active = PO_TRUE;
26400Sstevel@tonic-gate /* Fix up the result set accessor functions to the knl specfic ones */
26410Sstevel@tonic-gate rs->prs_next = pool_knl_rs_next;
26420Sstevel@tonic-gate rs->prs_prev = pool_knl_rs_prev;
26430Sstevel@tonic-gate rs->prs_first = pool_knl_rs_first;
26440Sstevel@tonic-gate rs->prs_last = pool_knl_rs_last;
26450Sstevel@tonic-gate rs->prs_get_index = pool_knl_rs_get_index;
26460Sstevel@tonic-gate rs->prs_set_index = pool_knl_rs_set_index;
26470Sstevel@tonic-gate rs->prs_close = pool_knl_rs_close;
26480Sstevel@tonic-gate rs->prs_count = pool_knl_rs_count;
26490Sstevel@tonic-gate return (rs);
26500Sstevel@tonic-gate }
26510Sstevel@tonic-gate
26520Sstevel@tonic-gate /*
26530Sstevel@tonic-gate * Free a result set. Ensure that the resources are all released at
26540Sstevel@tonic-gate * this point.
26550Sstevel@tonic-gate */
26560Sstevel@tonic-gate void
pool_knl_result_set_free(pool_knl_result_set_t * rs)26570Sstevel@tonic-gate pool_knl_result_set_free(pool_knl_result_set_t *rs)
26580Sstevel@tonic-gate {
26590Sstevel@tonic-gate free(rs->pkr_list);
26600Sstevel@tonic-gate free(rs);
26610Sstevel@tonic-gate }
26620Sstevel@tonic-gate /*
26630Sstevel@tonic-gate * Return the next element in a result set.
26640Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
26650Sstevel@tonic-gate */
26660Sstevel@tonic-gate pool_elem_t *
pool_knl_rs_next(pool_result_set_t * set)26670Sstevel@tonic-gate pool_knl_rs_next(pool_result_set_t *set)
26680Sstevel@tonic-gate {
26690Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
26700Sstevel@tonic-gate
26710Sstevel@tonic-gate if (kset->prs_index == kset->pkr_count - 1)
26720Sstevel@tonic-gate return (NULL);
26730Sstevel@tonic-gate return ((pool_elem_t *)kset->pkr_list[++kset->prs_index]);
26740Sstevel@tonic-gate }
26750Sstevel@tonic-gate
26760Sstevel@tonic-gate /*
26770Sstevel@tonic-gate * Return the previous element in a result set.
26780Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
26790Sstevel@tonic-gate */
26800Sstevel@tonic-gate pool_elem_t *
pool_knl_rs_prev(pool_result_set_t * set)26810Sstevel@tonic-gate pool_knl_rs_prev(pool_result_set_t *set)
26820Sstevel@tonic-gate {
26830Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
26840Sstevel@tonic-gate
26850Sstevel@tonic-gate if (kset->prs_index < 0)
26860Sstevel@tonic-gate return (NULL);
26870Sstevel@tonic-gate return ((pool_elem_t *)kset->pkr_list[kset->prs_index--]);
26880Sstevel@tonic-gate }
26890Sstevel@tonic-gate
26900Sstevel@tonic-gate /*
26910Sstevel@tonic-gate * Sets the current index in a result set.
26920Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
26930Sstevel@tonic-gate */
26940Sstevel@tonic-gate int
pool_knl_rs_set_index(pool_result_set_t * set,int index)26950Sstevel@tonic-gate pool_knl_rs_set_index(pool_result_set_t *set, int index)
26960Sstevel@tonic-gate {
26970Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
26980Sstevel@tonic-gate
26990Sstevel@tonic-gate if (index < 0 || index >= kset->pkr_count) {
27000Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
27010Sstevel@tonic-gate return (PO_FAIL);
27020Sstevel@tonic-gate }
27030Sstevel@tonic-gate kset->prs_index = index;
27040Sstevel@tonic-gate return (PO_SUCCESS);
27050Sstevel@tonic-gate }
27060Sstevel@tonic-gate
27070Sstevel@tonic-gate /*
27080Sstevel@tonic-gate * Return the current index in a result set.
27090Sstevel@tonic-gate * Returns current index
27100Sstevel@tonic-gate */
27110Sstevel@tonic-gate int
pool_knl_rs_get_index(pool_result_set_t * set)27120Sstevel@tonic-gate pool_knl_rs_get_index(pool_result_set_t *set)
27130Sstevel@tonic-gate {
27140Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27150Sstevel@tonic-gate
27160Sstevel@tonic-gate return (kset->prs_index);
27170Sstevel@tonic-gate }
27180Sstevel@tonic-gate
27190Sstevel@tonic-gate /*
27200Sstevel@tonic-gate * Return the first element in a result set.
27210Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
27220Sstevel@tonic-gate */
27230Sstevel@tonic-gate pool_elem_t *
pool_knl_rs_first(pool_result_set_t * set)27240Sstevel@tonic-gate pool_knl_rs_first(pool_result_set_t *set)
27250Sstevel@tonic-gate {
27260Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27270Sstevel@tonic-gate
27280Sstevel@tonic-gate return ((pool_elem_t *)kset->pkr_list[0]);
27290Sstevel@tonic-gate }
27300Sstevel@tonic-gate
27310Sstevel@tonic-gate /*
27320Sstevel@tonic-gate * Return the last element in a result set.
27330Sstevel@tonic-gate * Returns pool_elem_t pointer/NULL
27340Sstevel@tonic-gate */
27350Sstevel@tonic-gate pool_elem_t *
pool_knl_rs_last(pool_result_set_t * set)27360Sstevel@tonic-gate pool_knl_rs_last(pool_result_set_t *set)
27370Sstevel@tonic-gate {
27380Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27390Sstevel@tonic-gate
27400Sstevel@tonic-gate return ((pool_elem_t *)kset->pkr_list[kset->pkr_count - 1]);
27410Sstevel@tonic-gate }
27420Sstevel@tonic-gate
27430Sstevel@tonic-gate /*
27440Sstevel@tonic-gate * Return the number of results in a result set.
27450Sstevel@tonic-gate * Returns result count
27460Sstevel@tonic-gate */
27470Sstevel@tonic-gate int
pool_knl_rs_count(pool_result_set_t * set)27480Sstevel@tonic-gate pool_knl_rs_count(pool_result_set_t *set)
27490Sstevel@tonic-gate {
27500Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27510Sstevel@tonic-gate
27520Sstevel@tonic-gate return (kset->pkr_count);
27530Sstevel@tonic-gate }
27540Sstevel@tonic-gate
27550Sstevel@tonic-gate
27560Sstevel@tonic-gate /*
27570Sstevel@tonic-gate * Close a result set. Free the resources
27580Sstevel@tonic-gate * Returns PO_SUCCESS/PO_FAIL
27590Sstevel@tonic-gate */
27600Sstevel@tonic-gate int
pool_knl_rs_close(pool_result_set_t * set)27610Sstevel@tonic-gate pool_knl_rs_close(pool_result_set_t *set)
27620Sstevel@tonic-gate {
27630Sstevel@tonic-gate pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27640Sstevel@tonic-gate
27650Sstevel@tonic-gate pool_knl_result_set_free(kset);
27660Sstevel@tonic-gate return (PO_SUCCESS);
27670Sstevel@tonic-gate }
27680Sstevel@tonic-gate
27690Sstevel@tonic-gate /*
27700Sstevel@tonic-gate * Commit an individual transaction log item(). This processing is
27710Sstevel@tonic-gate * essential to the pool_conf_commit() logic. When pool_conf_commit()
27720Sstevel@tonic-gate * is invoked, the pending transaction log for the configuration is
27730Sstevel@tonic-gate * walked and all pending changes to the kernel are invoked. If a
27740Sstevel@tonic-gate * change succeeds it is marked in the log as successful and
27750Sstevel@tonic-gate * processing continues, if it fails then failure is returned and the
27760Sstevel@tonic-gate * log will be "rolled back" to undo changes to the library snapshot
27770Sstevel@tonic-gate * and the kernel.
27780Sstevel@tonic-gate */
27790Sstevel@tonic-gate int
log_item_commit(log_item_t * li)27800Sstevel@tonic-gate log_item_commit(log_item_t *li)
27810Sstevel@tonic-gate {
27820Sstevel@tonic-gate pool_knl_connection_t *prov =
27830Sstevel@tonic-gate (pool_knl_connection_t *)li->li_log->l_conf->pc_prov;
27840Sstevel@tonic-gate pool_create_undo_t *create;
27850Sstevel@tonic-gate pool_destroy_undo_t *destroy;
27860Sstevel@tonic-gate pool_assoc_undo_t *assoc;
27870Sstevel@tonic-gate pool_dissoc_undo_t *dissoc;
27880Sstevel@tonic-gate pool_propput_undo_t *propput;
27890Sstevel@tonic-gate pool_proprm_undo_t *proprm;
27900Sstevel@tonic-gate pool_xtransfer_undo_t *xtransfer;
27910Sstevel@tonic-gate char_buf_t *cb;
27920Sstevel@tonic-gate size_t size;
27930Sstevel@tonic-gate pool_elem_t *pair;
27940Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
27950Sstevel@tonic-gate int ret;
27960Sstevel@tonic-gate
27970Sstevel@tonic-gate switch (li->li_op) {
27980Sstevel@tonic-gate case POOL_CREATE:
27990Sstevel@tonic-gate create = (pool_create_undo_t *)li->li_details;
28000Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
28010Sstevel@tonic-gate return (PO_FAIL);
28020Sstevel@tonic-gate if (set_char_buf(cb, "%s.sys_id",
28030Sstevel@tonic-gate pool_elem_class_string(create->pcu_elem)) != PO_SUCCESS) {
28040Sstevel@tonic-gate free_char_buf(cb);
28050Sstevel@tonic-gate return (PO_FAIL);
28060Sstevel@tonic-gate }
28070Sstevel@tonic-gate #ifdef DEBUG
28080Sstevel@tonic-gate dprintf("log_item_commit: POOL_CREATE, remove from dict\n");
28090Sstevel@tonic-gate pool_elem_dprintf(create->pcu_elem);
28100Sstevel@tonic-gate #endif /* DEBUG */
28110Sstevel@tonic-gate /*
28120Sstevel@tonic-gate * May not need to remove the element if it was
28130Sstevel@tonic-gate * already destroyed before commit. Just cast the
28140Sstevel@tonic-gate * return to void.
28150Sstevel@tonic-gate */
28160Sstevel@tonic-gate (void) dict_remove(prov->pkc_elements,
28170Sstevel@tonic-gate (pool_knl_elem_t *)create->pcu_elem);
28180Sstevel@tonic-gate
28190Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_CREATE, &create->pcu_ioctl) < 0) {
28200Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
28210Sstevel@tonic-gate return (PO_FAIL);
28220Sstevel@tonic-gate }
28230Sstevel@tonic-gate /*
28240Sstevel@tonic-gate * Now that we have created our element in the kernel,
28250Sstevel@tonic-gate * it has a valid allocated system id. Remove the
28260Sstevel@tonic-gate * element from the element dictionary, using the
28270Sstevel@tonic-gate * current key, and then re-insert under the new key.
28280Sstevel@tonic-gate */
28290Sstevel@tonic-gate #ifdef DEBUG
28300Sstevel@tonic-gate pool_elem_dprintf(create->pcu_elem);
28310Sstevel@tonic-gate #endif /* DEBUG */
28320Sstevel@tonic-gate assert(nvlist_add_int64(
28330Sstevel@tonic-gate ((pool_knl_elem_t *)create->pcu_elem)->pke_properties,
28340Sstevel@tonic-gate cb->cb_buf, create->pcu_ioctl.pc_i_id) == 0);
28350Sstevel@tonic-gate free_char_buf(cb);
28360Sstevel@tonic-gate assert(dict_put(prov->pkc_elements, create->pcu_elem,
28370Sstevel@tonic-gate create->pcu_elem) == NULL);
28380Sstevel@tonic-gate /*
28390Sstevel@tonic-gate * If the element has a pair in the static
28400Sstevel@tonic-gate * configuration, update it with the sys_id
28410Sstevel@tonic-gate */
28420Sstevel@tonic-gate if ((pair = pool_get_pair(create->pcu_elem)) != NULL) {
28430Sstevel@tonic-gate pool_value_set_int64(&val, create->pcu_ioctl.pc_i_id);
28440Sstevel@tonic-gate assert(pool_put_any_ns_property(pair, c_sys_prop, &val)
28450Sstevel@tonic-gate == PO_SUCCESS);
28460Sstevel@tonic-gate }
28470Sstevel@tonic-gate li->li_state = LS_UNDO;
28480Sstevel@tonic-gate break;
28490Sstevel@tonic-gate case POOL_DESTROY:
28500Sstevel@tonic-gate destroy = (pool_destroy_undo_t *)li->li_details;
28510Sstevel@tonic-gate
28520Sstevel@tonic-gate destroy->pdu_ioctl.pd_o_id = elem_get_sysid(destroy->pdu_elem);
28530Sstevel@tonic-gate
28540Sstevel@tonic-gate /*
28550Sstevel@tonic-gate * It may be that this element was created in the last
28560Sstevel@tonic-gate * transaction. In which case POOL_CREATE, above, will
28570Sstevel@tonic-gate * have re-inserted the element in the dictionary. Try
28580Sstevel@tonic-gate * to remove it just in case this has occurred.
28590Sstevel@tonic-gate */
28600Sstevel@tonic-gate (void) dict_remove(prov->pkc_elements,
28610Sstevel@tonic-gate (pool_knl_elem_t *)destroy->pdu_elem);
28620Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_DESTROY,
2863*11411SSurya.Prakki@Sun.COM &destroy->pdu_ioctl)) < 0 && errno == EAGAIN)
2864*11411SSurya.Prakki@Sun.COM ;
28650Sstevel@tonic-gate if (ret < 0) {
28660Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
28670Sstevel@tonic-gate return (PO_FAIL);
28680Sstevel@tonic-gate }
28690Sstevel@tonic-gate #ifdef DEBUG
28700Sstevel@tonic-gate dprintf("log_item_commit: POOL_DESTROY\n");
28710Sstevel@tonic-gate pool_elem_dprintf(destroy->pdu_elem);
28720Sstevel@tonic-gate #endif /* DEBUG */
28730Sstevel@tonic-gate li->li_state = LS_UNDO;
28740Sstevel@tonic-gate break;
28750Sstevel@tonic-gate case POOL_ASSOC:
28760Sstevel@tonic-gate assoc = (pool_assoc_undo_t *)li->li_details;
28770Sstevel@tonic-gate
28780Sstevel@tonic-gate assoc->pau_ioctl.pa_o_pool_id =
28790Sstevel@tonic-gate elem_get_sysid(assoc->pau_assoc);
28800Sstevel@tonic-gate assoc->pau_ioctl.pa_o_res_id =
28810Sstevel@tonic-gate elem_get_sysid(assoc->pau_newres);
28820Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC,
2883*11411SSurya.Prakki@Sun.COM &assoc->pau_ioctl)) < 0 && errno == EAGAIN)
2884*11411SSurya.Prakki@Sun.COM ;
28850Sstevel@tonic-gate if (ret < 0) {
28860Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
28870Sstevel@tonic-gate return (PO_FAIL);
28880Sstevel@tonic-gate }
28890Sstevel@tonic-gate li->li_state = LS_UNDO;
28900Sstevel@tonic-gate break;
28910Sstevel@tonic-gate case POOL_DISSOC:
28920Sstevel@tonic-gate dissoc = (pool_dissoc_undo_t *)li->li_details;
28930Sstevel@tonic-gate
28940Sstevel@tonic-gate dissoc->pdu_ioctl.pd_o_pool_id =
28950Sstevel@tonic-gate elem_get_sysid(dissoc->pdu_dissoc);
28960Sstevel@tonic-gate
28970Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_DISSOC,
2898*11411SSurya.Prakki@Sun.COM &dissoc->pdu_ioctl)) < 0 && errno == EAGAIN)
2899*11411SSurya.Prakki@Sun.COM ;
29000Sstevel@tonic-gate if (ret < 0) {
29010Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
29020Sstevel@tonic-gate return (PO_FAIL);
29030Sstevel@tonic-gate }
29040Sstevel@tonic-gate li->li_state = LS_UNDO;
29050Sstevel@tonic-gate break;
29060Sstevel@tonic-gate case POOL_TRANSFER:
29070Sstevel@tonic-gate li->li_state = LS_UNDO;
29080Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
29090Sstevel@tonic-gate return (PO_FAIL);
29100Sstevel@tonic-gate break;
29110Sstevel@tonic-gate case POOL_XTRANSFER:
29120Sstevel@tonic-gate xtransfer = (pool_xtransfer_undo_t *)li->li_details;
29130Sstevel@tonic-gate
29140Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_src_id =
29150Sstevel@tonic-gate elem_get_sysid(xtransfer->pxu_src);
29160Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_tgt_id =
29170Sstevel@tonic-gate elem_get_sysid(xtransfer->pxu_tgt);
29180Sstevel@tonic-gate for (size = 0; xtransfer->pxu_rl[size] != NULL; size ++) {
29190Sstevel@tonic-gate xtransfer->pxu_ioctl.px_o_comp_list[size] =
29200Sstevel@tonic-gate elem_get_sysid(TO_ELEM(xtransfer->pxu_rl[size]));
29210Sstevel@tonic-gate #ifdef DEBUG
29220Sstevel@tonic-gate dprintf("log_item_commit: POOL_XTRANSFER\n");
29230Sstevel@tonic-gate pool_elem_dprintf(TO_ELEM(xtransfer->pxu_rl[size]));
29240Sstevel@tonic-gate #endif /* DEBUG */
29250Sstevel@tonic-gate }
29260Sstevel@tonic-gate
29270Sstevel@tonic-gate /*
29280Sstevel@tonic-gate * Don't actually transfer resources if the configuration
29290Sstevel@tonic-gate * is in POF_DESTROY state. This is to prevent problems
29300Sstevel@tonic-gate * relating to transferring off-line CPUs. Instead rely
29310Sstevel@tonic-gate * on the POOL_DESTROY ioctl to transfer the CPUS.
29320Sstevel@tonic-gate */
29330Sstevel@tonic-gate if (li->li_log->l_conf->pc_state != POF_DESTROY &&
29340Sstevel@tonic-gate ioctl(prov->pkc_fd, POOL_XTRANSFER,
29350Sstevel@tonic-gate &xtransfer->pxu_ioctl) < 0) {
29360Sstevel@tonic-gate #ifdef DEBUG
29370Sstevel@tonic-gate dprintf("log_item_commit: POOL_XTRANSFER, ioctl "
29380Sstevel@tonic-gate "failed\n");
29390Sstevel@tonic-gate #endif /* DEBUG */
29400Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
29410Sstevel@tonic-gate return (PO_FAIL);
29420Sstevel@tonic-gate }
29430Sstevel@tonic-gate li->li_state = LS_UNDO;
29440Sstevel@tonic-gate break;
29450Sstevel@tonic-gate case POOL_PROPPUT:
29460Sstevel@tonic-gate propput = (pool_propput_undo_t *)li->li_details;
29470Sstevel@tonic-gate
29480Sstevel@tonic-gate if (pool_elem_class(propput->ppu_elem) != PEC_SYSTEM) {
29490Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id =
29500Sstevel@tonic-gate elem_get_sysid(propput->ppu_elem);
29510Sstevel@tonic-gate }
29520Sstevel@tonic-gate /*
29530Sstevel@tonic-gate * Some properties, e.g. pset.size, are read-only in the
29540Sstevel@tonic-gate * kernel and attempting to change them will fail and cause
29550Sstevel@tonic-gate * problems. Although this property is read-only through the
29560Sstevel@tonic-gate * public interface, the library needs to modify it's value.
29570Sstevel@tonic-gate */
29580Sstevel@tonic-gate if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) {
29590Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPPUT,
29600Sstevel@tonic-gate &propput->ppu_ioctl) < 0) {
29610Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
29620Sstevel@tonic-gate return (PO_FAIL);
29630Sstevel@tonic-gate }
29640Sstevel@tonic-gate }
29650Sstevel@tonic-gate li->li_state = LS_UNDO;
29660Sstevel@tonic-gate break;
29670Sstevel@tonic-gate case POOL_PROPRM:
29680Sstevel@tonic-gate proprm = (pool_proprm_undo_t *)li->li_details;
29690Sstevel@tonic-gate
29700Sstevel@tonic-gate if (pool_elem_class(proprm->pru_elem) != PEC_SYSTEM) {
29710Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id =
29720Sstevel@tonic-gate elem_get_sysid(proprm->pru_elem);
29730Sstevel@tonic-gate }
29740Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPRM, &proprm->pru_ioctl) < 0) {
29750Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
29760Sstevel@tonic-gate return (PO_FAIL);
29770Sstevel@tonic-gate }
29780Sstevel@tonic-gate li->li_state = LS_UNDO;
29790Sstevel@tonic-gate break;
29800Sstevel@tonic-gate default:
29810Sstevel@tonic-gate return (PO_FAIL);
29820Sstevel@tonic-gate }
29830Sstevel@tonic-gate return (PO_SUCCESS);
29840Sstevel@tonic-gate }
29850Sstevel@tonic-gate
29860Sstevel@tonic-gate /*
29870Sstevel@tonic-gate * Undo an individual transaction log item(). This processing is
29880Sstevel@tonic-gate * essential to the pool_conf_commit() and pool_conf_rollback()
29890Sstevel@tonic-gate * logic. Changes to the libpool snapshot and the kernel are carried
29900Sstevel@tonic-gate * out separately. The library snapshot is updated synchronously,
29910Sstevel@tonic-gate * however the kernel update is delayed until the user calls
29920Sstevel@tonic-gate * pool_conf_commit().
29930Sstevel@tonic-gate *
29940Sstevel@tonic-gate * When undoing transactions, library changes will be undone unless
29950Sstevel@tonic-gate * this invocation is as a result of a commit failure, in which case
29960Sstevel@tonic-gate * the log state will be LS_RECOVER. Kernel changes will only be
29970Sstevel@tonic-gate * undone if they are marked as having been done, in which case the
29980Sstevel@tonic-gate * log item state will be LS_UNDO.
29990Sstevel@tonic-gate */
30000Sstevel@tonic-gate int
log_item_undo(log_item_t * li)30010Sstevel@tonic-gate log_item_undo(log_item_t *li)
30020Sstevel@tonic-gate {
30030Sstevel@tonic-gate pool_knl_connection_t *prov =
30040Sstevel@tonic-gate (pool_knl_connection_t *)li->li_log->l_conf->pc_prov;
30050Sstevel@tonic-gate pool_create_undo_t *create;
30060Sstevel@tonic-gate pool_destroy_undo_t *destroy;
30070Sstevel@tonic-gate pool_assoc_undo_t *assoc;
30080Sstevel@tonic-gate pool_dissoc_undo_t *dissoc;
30090Sstevel@tonic-gate pool_propput_undo_t *propput;
30100Sstevel@tonic-gate pool_proprm_undo_t *proprm;
30110Sstevel@tonic-gate pool_xtransfer_undo_t *xtransfer;
30120Sstevel@tonic-gate char_buf_t *cb;
30130Sstevel@tonic-gate size_t size;
30140Sstevel@tonic-gate pool_destroy_t u_destroy;
30150Sstevel@tonic-gate pool_create_t u_create;
30160Sstevel@tonic-gate pool_assoc_t u_assoc;
30170Sstevel@tonic-gate pool_xtransfer_t u_xtransfer;
30180Sstevel@tonic-gate pool_propput_t u_propput;
30190Sstevel@tonic-gate pool_proprm_t u_proprm;
30200Sstevel@tonic-gate pool_conf_t *conf = li->li_log->l_conf;
30210Sstevel@tonic-gate nvpair_t *pair;
30220Sstevel@tonic-gate nvlist_t *tmplist;
30230Sstevel@tonic-gate int ret;
30240Sstevel@tonic-gate
30250Sstevel@tonic-gate if (li->li_log->l_state != LS_RECOVER) {
30260Sstevel@tonic-gate switch (li->li_op) {
30270Sstevel@tonic-gate case POOL_CREATE:
30280Sstevel@tonic-gate create = (pool_create_undo_t *)li->li_details;
30290Sstevel@tonic-gate
30300Sstevel@tonic-gate (void) dict_remove(prov->pkc_elements, create->pcu_elem);
30310Sstevel@tonic-gate #ifdef DEBUG
30320Sstevel@tonic-gate dprintf("log_item_undo: POOL_CREATE\n");
30330Sstevel@tonic-gate assert(create->pcu_elem != NULL);
30340Sstevel@tonic-gate dprintf("log_item_undo: POOL_CREATE %p\n", create->pcu_elem);
30350Sstevel@tonic-gate pool_elem_dprintf(create->pcu_elem);
30360Sstevel@tonic-gate #endif /* DEBUG */
30370Sstevel@tonic-gate pool_knl_elem_free((pool_knl_elem_t *)create->pcu_elem,
30380Sstevel@tonic-gate PO_TRUE);
30390Sstevel@tonic-gate break;
30400Sstevel@tonic-gate case POOL_DESTROY:
30410Sstevel@tonic-gate destroy = (pool_destroy_undo_t *)li->li_details;
30420Sstevel@tonic-gate
30430Sstevel@tonic-gate assert(dict_put(prov->pkc_elements, destroy->pdu_elem,
30440Sstevel@tonic-gate destroy->pdu_elem) == NULL);
30450Sstevel@tonic-gate break;
30460Sstevel@tonic-gate case POOL_ASSOC:
30470Sstevel@tonic-gate assoc = (pool_assoc_undo_t *)li->li_details;
30480Sstevel@tonic-gate
30490Sstevel@tonic-gate if (assoc->pau_oldres != NULL)
30500Sstevel@tonic-gate ((pool_knl_pool_t *)assoc->pau_assoc)->pkp_assoc
30510Sstevel@tonic-gate [pool_resource_elem_class(assoc->pau_oldres)] =
30520Sstevel@tonic-gate (pool_knl_resource_t *)assoc->pau_oldres;
30530Sstevel@tonic-gate break;
30540Sstevel@tonic-gate case POOL_DISSOC:
30550Sstevel@tonic-gate dissoc = (pool_dissoc_undo_t *)li->li_details;
30560Sstevel@tonic-gate
30570Sstevel@tonic-gate if (dissoc->pdu_oldres != NULL)
30580Sstevel@tonic-gate ((pool_knl_pool_t *)dissoc->pdu_dissoc)->pkp_assoc
30590Sstevel@tonic-gate [pool_resource_elem_class(dissoc->pdu_oldres)] =
30600Sstevel@tonic-gate (pool_knl_resource_t *)dissoc->pdu_oldres;
30610Sstevel@tonic-gate break;
30620Sstevel@tonic-gate case POOL_TRANSFER:
30630Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
30640Sstevel@tonic-gate return (PO_FAIL);
30650Sstevel@tonic-gate break;
30660Sstevel@tonic-gate case POOL_XTRANSFER:
30670Sstevel@tonic-gate xtransfer = (pool_xtransfer_undo_t *)li->li_details;
30680Sstevel@tonic-gate
30690Sstevel@tonic-gate for (size = 0; xtransfer->pxu_rl[size] != NULL; size++) {
30700Sstevel@tonic-gate pool_value_t val = POOL_VALUE_INITIALIZER;
30710Sstevel@tonic-gate uint64_t src_size;
30720Sstevel@tonic-gate uint64_t tgt_size;
30730Sstevel@tonic-gate
30740Sstevel@tonic-gate if (pool_set_container(xtransfer->pxu_src,
30750Sstevel@tonic-gate TO_ELEM(xtransfer->pxu_rl[size])) == PO_FAIL) {
30760Sstevel@tonic-gate return (PO_FAIL);
30770Sstevel@tonic-gate }
30780Sstevel@tonic-gate /*
30790Sstevel@tonic-gate * Maintain the library view of the size
30800Sstevel@tonic-gate */
30810Sstevel@tonic-gate if (resource_get_size(pool_elem_res(xtransfer->pxu_src),
30820Sstevel@tonic-gate &src_size) != PO_SUCCESS ||
30830Sstevel@tonic-gate resource_get_size(pool_elem_res(xtransfer->pxu_tgt),
30840Sstevel@tonic-gate &tgt_size) != PO_SUCCESS) {
30850Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
30860Sstevel@tonic-gate return (PO_FAIL);
30870Sstevel@tonic-gate }
30880Sstevel@tonic-gate src_size++;
30890Sstevel@tonic-gate tgt_size--;
30900Sstevel@tonic-gate pool_value_set_uint64(&val, src_size);
30910Sstevel@tonic-gate (void) pool_put_any_ns_property(xtransfer->pxu_src,
30920Sstevel@tonic-gate c_size_prop, &val);
30930Sstevel@tonic-gate pool_value_set_uint64(&val, tgt_size);
30940Sstevel@tonic-gate (void) pool_put_any_ns_property(xtransfer->pxu_tgt,
30950Sstevel@tonic-gate c_size_prop, &val);
30960Sstevel@tonic-gate }
30970Sstevel@tonic-gate break;
30980Sstevel@tonic-gate case POOL_PROPPUT:
30990Sstevel@tonic-gate propput = (pool_propput_undo_t *)li->li_details;
31000Sstevel@tonic-gate
31010Sstevel@tonic-gate if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) {
31020Sstevel@tonic-gate if (propput->ppu_blist != NULL) {
31030Sstevel@tonic-gate if (nvlist_merge(
31040Sstevel@tonic-gate ((pool_knl_elem_t *)propput->ppu_elem)->
31050Sstevel@tonic-gate pke_properties, propput->ppu_blist, 0)
31060Sstevel@tonic-gate != 0) {
31070Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
31080Sstevel@tonic-gate return (PO_FAIL);
31090Sstevel@tonic-gate }
31100Sstevel@tonic-gate } else {
31110Sstevel@tonic-gate if (nvlist_unpack(propput->ppu_ioctl.pp_o_buf,
31120Sstevel@tonic-gate propput->ppu_ioctl.pp_o_bufsize,
31130Sstevel@tonic-gate &propput->ppu_alist, 0) != 0) {
31140Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
31150Sstevel@tonic-gate return (PO_FAIL);
31160Sstevel@tonic-gate }
31170Sstevel@tonic-gate pair = nvlist_next_nvpair(propput->ppu_alist,
31180Sstevel@tonic-gate NULL);
31190Sstevel@tonic-gate (void) nvlist_remove_all(((pool_knl_elem_t *)
31200Sstevel@tonic-gate propput->ppu_elem)->pke_properties,
31210Sstevel@tonic-gate nvpair_name(pair));
31220Sstevel@tonic-gate nvlist_free(propput->ppu_alist);
31230Sstevel@tonic-gate }
31240Sstevel@tonic-gate }
31250Sstevel@tonic-gate break;
31260Sstevel@tonic-gate case POOL_PROPRM:
31270Sstevel@tonic-gate proprm = (pool_proprm_undo_t *)li->li_details;
31280Sstevel@tonic-gate
31290Sstevel@tonic-gate if (pool_value_get_type(&proprm->pru_oldval) != POC_INVAL) {
31300Sstevel@tonic-gate if (pool_put_property(conf, proprm->pru_elem,
31310Sstevel@tonic-gate proprm->pru_ioctl.pp_o_prop_name,
31320Sstevel@tonic-gate &proprm->pru_oldval) != PO_SUCCESS) {
31330Sstevel@tonic-gate return (PO_FAIL);
31340Sstevel@tonic-gate }
31350Sstevel@tonic-gate }
31360Sstevel@tonic-gate break;
31370Sstevel@tonic-gate default:
31380Sstevel@tonic-gate return (PO_FAIL);
31390Sstevel@tonic-gate }
31400Sstevel@tonic-gate }
31410Sstevel@tonic-gate /*
31420Sstevel@tonic-gate * Only try to undo the state of the kernel if we modified it.
31430Sstevel@tonic-gate */
31440Sstevel@tonic-gate if (li->li_state == LS_DO) {
31450Sstevel@tonic-gate return (PO_SUCCESS);
31460Sstevel@tonic-gate }
31470Sstevel@tonic-gate
31480Sstevel@tonic-gate switch (li->li_op) {
31490Sstevel@tonic-gate case POOL_CREATE:
31500Sstevel@tonic-gate create = (pool_create_undo_t *)li->li_details;
31510Sstevel@tonic-gate
31520Sstevel@tonic-gate u_destroy.pd_o_type = create->pcu_ioctl.pc_o_type;
31530Sstevel@tonic-gate u_destroy.pd_o_sub_type = create->pcu_ioctl.pc_o_sub_type;
31540Sstevel@tonic-gate u_destroy.pd_o_id = create->pcu_ioctl.pc_i_id;
31550Sstevel@tonic-gate
31560Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_DESTROY,
3157*11411SSurya.Prakki@Sun.COM &u_destroy)) < 0 && errno == EAGAIN)
3158*11411SSurya.Prakki@Sun.COM ;
31590Sstevel@tonic-gate if (ret < 0) {
31600Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
31610Sstevel@tonic-gate return (PO_FAIL);
31620Sstevel@tonic-gate }
31630Sstevel@tonic-gate li->li_state = LS_DO;
31640Sstevel@tonic-gate break;
31650Sstevel@tonic-gate case POOL_DESTROY:
31660Sstevel@tonic-gate destroy = (pool_destroy_undo_t *)li->li_details;
31670Sstevel@tonic-gate
31680Sstevel@tonic-gate u_create.pc_o_type = destroy->pdu_ioctl.pd_o_type;
31690Sstevel@tonic-gate u_create.pc_o_sub_type = destroy->pdu_ioctl.pd_o_sub_type;
31700Sstevel@tonic-gate
31710Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_CREATE, &u_create) < 0) {
31720Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
31730Sstevel@tonic-gate return (PO_FAIL);
31740Sstevel@tonic-gate }
31750Sstevel@tonic-gate
31760Sstevel@tonic-gate if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
31770Sstevel@tonic-gate return (PO_FAIL);
31780Sstevel@tonic-gate }
31790Sstevel@tonic-gate if (set_char_buf(cb, "%s.sys_id",
31800Sstevel@tonic-gate pool_elem_class_string(destroy->pdu_elem)) != PO_SUCCESS) {
31810Sstevel@tonic-gate free_char_buf(cb);
31820Sstevel@tonic-gate return (PO_FAIL);
31830Sstevel@tonic-gate }
31840Sstevel@tonic-gate (void) nvlist_add_int64(
31850Sstevel@tonic-gate ((pool_knl_elem_t *)destroy->pdu_elem)->pke_properties,
31860Sstevel@tonic-gate cb->cb_buf, u_create.pc_i_id);
31870Sstevel@tonic-gate free_char_buf(cb);
31880Sstevel@tonic-gate if (dict_put(prov->pkc_elements, destroy->pdu_elem,
31890Sstevel@tonic-gate destroy->pdu_elem) != NULL) {
31900Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
31910Sstevel@tonic-gate return (PO_FAIL);
31920Sstevel@tonic-gate }
31930Sstevel@tonic-gate /*
31940Sstevel@tonic-gate * Now we need to reset all the properties and
31950Sstevel@tonic-gate * associations in the kernel for this newly created
31960Sstevel@tonic-gate * replacement.
31970Sstevel@tonic-gate */
31980Sstevel@tonic-gate u_propput.pp_o_id_type = destroy->pdu_ioctl.pd_o_type;
31990Sstevel@tonic-gate u_propput.pp_o_id_sub_type = destroy->pdu_ioctl.pd_o_sub_type;
32000Sstevel@tonic-gate u_propput.pp_o_id = u_create.pc_i_id;
32010Sstevel@tonic-gate u_propput.pp_o_buf = NULL;
32020Sstevel@tonic-gate /*
32030Sstevel@tonic-gate * Remove the read-only properties before attempting
32040Sstevel@tonic-gate * to restore the state of the newly created property
32050Sstevel@tonic-gate */
32060Sstevel@tonic-gate (void) nvlist_dup(((pool_knl_elem_t *)destroy->pdu_elem)->
3207*11411SSurya.Prakki@Sun.COM pke_properties, &tmplist, 0);
32080Sstevel@tonic-gate for (pair = nvlist_next_nvpair(tmplist, NULL); pair != NULL;
32090Sstevel@tonic-gate pair = nvlist_next_nvpair(tmplist, pair)) {
32100Sstevel@tonic-gate const pool_prop_t *prop;
32110Sstevel@tonic-gate char *name = nvpair_name(pair);
32120Sstevel@tonic-gate if ((prop = provider_get_prop(destroy->pdu_elem,
32130Sstevel@tonic-gate name)) != NULL)
32140Sstevel@tonic-gate if (prop_is_readonly(prop) == PO_TRUE)
32150Sstevel@tonic-gate (void) nvlist_remove_all(tmplist, name);
32160Sstevel@tonic-gate }
32170Sstevel@tonic-gate if (nvlist_pack(tmplist, (char **)&u_propput.pp_o_buf,
32180Sstevel@tonic-gate &u_propput.pp_o_bufsize, NV_ENCODE_NATIVE, 0) != 0) {
32190Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
32200Sstevel@tonic-gate return (PO_FAIL);
32210Sstevel@tonic-gate }
32220Sstevel@tonic-gate nvlist_free(tmplist);
32230Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPPUT, &u_propput) < 0) {
32240Sstevel@tonic-gate free(u_propput.pp_o_buf);
32250Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
32260Sstevel@tonic-gate return (PO_FAIL);
32270Sstevel@tonic-gate }
32280Sstevel@tonic-gate free(u_propput.pp_o_buf);
32290Sstevel@tonic-gate /*
32300Sstevel@tonic-gate * Now reset the associations for all the resource
32310Sstevel@tonic-gate * types if the thing which we are recreating is a
32320Sstevel@tonic-gate * pool
32330Sstevel@tonic-gate *
32340Sstevel@tonic-gate * TODO: This is resource specific and must be
32350Sstevel@tonic-gate * extended for additional resource types.
32360Sstevel@tonic-gate */
32370Sstevel@tonic-gate if (destroy->pdu_ioctl.pd_o_type == PEC_POOL) {
32380Sstevel@tonic-gate u_assoc.pa_o_pool_id = u_create.pc_i_id;
32390Sstevel@tonic-gate u_assoc.pa_o_res_id =
32400Sstevel@tonic-gate elem_get_sysid(
32410Sstevel@tonic-gate TO_ELEM(((pool_knl_pool_t *)destroy->pdu_elem)->
32420Sstevel@tonic-gate pkp_assoc[PREC_PSET]));
32430Sstevel@tonic-gate u_assoc.pa_o_id_type = PREC_PSET;
32440Sstevel@tonic-gate
32450Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc) < 0) {
32460Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
32470Sstevel@tonic-gate return (PO_FAIL);
32480Sstevel@tonic-gate }
32490Sstevel@tonic-gate }
32500Sstevel@tonic-gate li->li_state = LS_DO;
32510Sstevel@tonic-gate break;
32520Sstevel@tonic-gate case POOL_ASSOC:
32530Sstevel@tonic-gate assoc = (pool_assoc_undo_t *)li->li_details;
32540Sstevel@tonic-gate
32550Sstevel@tonic-gate u_assoc.pa_o_pool_id = elem_get_sysid(assoc->pau_assoc);
32560Sstevel@tonic-gate u_assoc.pa_o_res_id = elem_get_sysid(assoc->pau_oldres);
32570Sstevel@tonic-gate u_assoc.pa_o_id_type = assoc->pau_ioctl.pa_o_id_type;
32580Sstevel@tonic-gate
32590Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc)) < 0 &&
3260*11411SSurya.Prakki@Sun.COM errno == EAGAIN)
3261*11411SSurya.Prakki@Sun.COM ;
32620Sstevel@tonic-gate if (ret < 0) {
32630Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
32640Sstevel@tonic-gate return (PO_FAIL);
32650Sstevel@tonic-gate }
32660Sstevel@tonic-gate li->li_state = LS_DO;
32670Sstevel@tonic-gate break;
32680Sstevel@tonic-gate case POOL_DISSOC:
32690Sstevel@tonic-gate dissoc = (pool_dissoc_undo_t *)li->li_details;
32700Sstevel@tonic-gate
32710Sstevel@tonic-gate u_assoc.pa_o_pool_id = elem_get_sysid(dissoc->pdu_dissoc);
32720Sstevel@tonic-gate u_assoc.pa_o_res_id = elem_get_sysid(dissoc->pdu_oldres);
32730Sstevel@tonic-gate u_assoc.pa_o_id_type = dissoc->pdu_ioctl.pd_o_id_type;
32740Sstevel@tonic-gate
32750Sstevel@tonic-gate while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc)) < 0 &&
3276*11411SSurya.Prakki@Sun.COM errno == EAGAIN)
3277*11411SSurya.Prakki@Sun.COM ;
32780Sstevel@tonic-gate if (ret < 0) {
32790Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
32800Sstevel@tonic-gate return (PO_FAIL);
32810Sstevel@tonic-gate }
32820Sstevel@tonic-gate li->li_state = LS_DO;
32830Sstevel@tonic-gate break;
32840Sstevel@tonic-gate case POOL_TRANSFER:
32850Sstevel@tonic-gate li->li_state = LS_DO;
32860Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
32870Sstevel@tonic-gate return (PO_FAIL);
32880Sstevel@tonic-gate break;
32890Sstevel@tonic-gate case POOL_XTRANSFER:
32900Sstevel@tonic-gate xtransfer = (pool_xtransfer_undo_t *)li->li_details;
32910Sstevel@tonic-gate
32920Sstevel@tonic-gate (void) memcpy(&u_xtransfer, &xtransfer->pxu_ioctl,
32930Sstevel@tonic-gate sizeof (pool_xtransfer_t));
32940Sstevel@tonic-gate u_xtransfer.px_o_src_id = elem_get_sysid(xtransfer->pxu_tgt);
32950Sstevel@tonic-gate u_xtransfer.px_o_tgt_id = elem_get_sysid(xtransfer->pxu_src);
32960Sstevel@tonic-gate
32970Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_XTRANSFER, &u_xtransfer) < 0) {
32980Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
32990Sstevel@tonic-gate return (PO_FAIL);
33000Sstevel@tonic-gate }
33010Sstevel@tonic-gate li->li_state = LS_DO;
33020Sstevel@tonic-gate break;
33030Sstevel@tonic-gate case POOL_PROPPUT:
33040Sstevel@tonic-gate propput = (pool_propput_undo_t *)li->li_details;
33050Sstevel@tonic-gate
33060Sstevel@tonic-gate if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) {
33070Sstevel@tonic-gate if (propput->ppu_blist) {
33080Sstevel@tonic-gate (void) memcpy(&u_propput, &propput->ppu_ioctl,
33090Sstevel@tonic-gate sizeof (pool_propput_t));
33100Sstevel@tonic-gate u_propput.pp_o_id =
33110Sstevel@tonic-gate elem_get_sysid(propput->ppu_elem);
33120Sstevel@tonic-gate u_propput.pp_o_buf = NULL;
33130Sstevel@tonic-gate if (nvlist_pack(propput->ppu_blist,
33140Sstevel@tonic-gate (char **)&u_propput.pp_o_buf,
33150Sstevel@tonic-gate &u_propput.pp_o_bufsize,
33160Sstevel@tonic-gate NV_ENCODE_NATIVE, 0) != 0) {
33170Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
33180Sstevel@tonic-gate return (PO_FAIL);
33190Sstevel@tonic-gate }
33200Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPPUT,
33210Sstevel@tonic-gate &u_propput) < 0) {
33220Sstevel@tonic-gate free(u_propput.pp_o_buf);
33230Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
33240Sstevel@tonic-gate return (PO_FAIL);
33250Sstevel@tonic-gate }
33260Sstevel@tonic-gate free(u_propput.pp_o_buf);
33270Sstevel@tonic-gate } else {
33280Sstevel@tonic-gate if (nvlist_unpack(propput->
33290Sstevel@tonic-gate ppu_ioctl.pp_o_buf,
33300Sstevel@tonic-gate propput->ppu_ioctl.pp_o_bufsize,
33310Sstevel@tonic-gate &propput->ppu_alist, 0) != 0) {
33320Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
33330Sstevel@tonic-gate return (PO_FAIL);
33340Sstevel@tonic-gate }
33350Sstevel@tonic-gate u_proprm.pp_o_id_type =
33360Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_type;
33370Sstevel@tonic-gate u_proprm.pp_o_id_sub_type =
33380Sstevel@tonic-gate propput->ppu_ioctl.pp_o_id_sub_type;
33390Sstevel@tonic-gate u_proprm.pp_o_id =
33400Sstevel@tonic-gate elem_get_sysid(propput->ppu_elem);
33410Sstevel@tonic-gate pair = nvlist_next_nvpair(propput->ppu_alist,
33420Sstevel@tonic-gate NULL);
33430Sstevel@tonic-gate u_proprm.pp_o_prop_name = nvpair_name(pair);
33440Sstevel@tonic-gate u_proprm.pp_o_prop_name_size =
33450Sstevel@tonic-gate strlen(u_proprm.pp_o_prop_name);
33460Sstevel@tonic-gate
33470Sstevel@tonic-gate if (provider_get_prop(propput->ppu_elem,
33480Sstevel@tonic-gate u_proprm.pp_o_prop_name) == NULL) {
33490Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPRM,
33500Sstevel@tonic-gate &u_proprm) < 0) {
33510Sstevel@tonic-gate nvlist_free(propput->ppu_alist);
33520Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
33530Sstevel@tonic-gate return (PO_FAIL);
33540Sstevel@tonic-gate }
33550Sstevel@tonic-gate }
33560Sstevel@tonic-gate nvlist_free(propput->ppu_alist);
33570Sstevel@tonic-gate }
33580Sstevel@tonic-gate }
33590Sstevel@tonic-gate li->li_state = LS_DO;
33600Sstevel@tonic-gate break;
33610Sstevel@tonic-gate case POOL_PROPRM:
33620Sstevel@tonic-gate proprm = (pool_proprm_undo_t *)li->li_details;
33630Sstevel@tonic-gate
33640Sstevel@tonic-gate u_propput.pp_o_id_type = proprm->pru_ioctl.pp_o_id_type;
33650Sstevel@tonic-gate u_propput.pp_o_id_sub_type =
33660Sstevel@tonic-gate proprm->pru_ioctl.pp_o_id_sub_type;
33670Sstevel@tonic-gate u_propput.pp_o_id = elem_get_sysid(proprm->pru_elem);
33680Sstevel@tonic-gate u_propput.pp_o_buf = NULL;
33690Sstevel@tonic-gate /*
33700Sstevel@tonic-gate * Only try to remove the appropriate property
33710Sstevel@tonic-gate */
33720Sstevel@tonic-gate if (nvlist_alloc(&tmplist, NV_UNIQUE_NAME_TYPE, 0) !=
33730Sstevel@tonic-gate 0) {
33740Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
33750Sstevel@tonic-gate return (PO_FAIL);
33760Sstevel@tonic-gate }
33770Sstevel@tonic-gate if (pool_knl_nvlist_add_value(tmplist,
33780Sstevel@tonic-gate pool_value_get_name(&proprm->pru_oldval),
33790Sstevel@tonic-gate &proprm->pru_oldval) != PO_SUCCESS)
33800Sstevel@tonic-gate return (PO_FAIL);
33810Sstevel@tonic-gate
33820Sstevel@tonic-gate if (nvlist_pack(tmplist,
33830Sstevel@tonic-gate (char **)&u_propput.pp_o_buf, &u_propput.pp_o_bufsize,
33840Sstevel@tonic-gate NV_ENCODE_NATIVE, 0) != 0) {
33850Sstevel@tonic-gate nvlist_free(tmplist);
33860Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
33870Sstevel@tonic-gate return (PO_FAIL);
33880Sstevel@tonic-gate }
33890Sstevel@tonic-gate nvlist_free(tmplist);
33900Sstevel@tonic-gate if (ioctl(prov->pkc_fd, POOL_PROPPUT, &u_propput) < 0) {
33910Sstevel@tonic-gate free(u_propput.pp_o_buf);
33920Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
33930Sstevel@tonic-gate return (PO_FAIL);
33940Sstevel@tonic-gate }
33950Sstevel@tonic-gate free(u_propput.pp_o_buf);
33960Sstevel@tonic-gate li->li_state = LS_DO;
33970Sstevel@tonic-gate break;
33980Sstevel@tonic-gate default:
33990Sstevel@tonic-gate return (PO_FAIL);
34000Sstevel@tonic-gate }
34010Sstevel@tonic-gate return (PO_SUCCESS);
34020Sstevel@tonic-gate }
34030Sstevel@tonic-gate
34040Sstevel@tonic-gate /*
34050Sstevel@tonic-gate * A log item stores state about the transaction it represents. This
34060Sstevel@tonic-gate * function releases the resources associated with the transaction and
34070Sstevel@tonic-gate * used to store the transaction state.
34080Sstevel@tonic-gate */
34090Sstevel@tonic-gate int
log_item_release(log_item_t * li)34100Sstevel@tonic-gate log_item_release(log_item_t *li)
34110Sstevel@tonic-gate {
34120Sstevel@tonic-gate pool_create_undo_t *create;
34130Sstevel@tonic-gate pool_destroy_undo_t *destroy;
34140Sstevel@tonic-gate pool_assoc_undo_t *assoc;
34150Sstevel@tonic-gate pool_dissoc_undo_t *dissoc;
34160Sstevel@tonic-gate pool_propput_undo_t *propput;
34170Sstevel@tonic-gate pool_proprm_undo_t *proprm;
34180Sstevel@tonic-gate pool_xtransfer_undo_t *xtransfer;
34190Sstevel@tonic-gate
34200Sstevel@tonic-gate switch (li->li_op) {
34210Sstevel@tonic-gate case POOL_CREATE:
34220Sstevel@tonic-gate create = (pool_create_undo_t *)li->li_details;
34230Sstevel@tonic-gate
34240Sstevel@tonic-gate free(create);
34250Sstevel@tonic-gate break;
34260Sstevel@tonic-gate case POOL_DESTROY:
34270Sstevel@tonic-gate destroy = (pool_destroy_undo_t *)li->li_details;
34280Sstevel@tonic-gate
34290Sstevel@tonic-gate #ifdef DEBUG
34300Sstevel@tonic-gate dprintf("log_item_release: POOL_DESTROY\n");
34310Sstevel@tonic-gate #endif /* DEBUG */
34320Sstevel@tonic-gate
34330Sstevel@tonic-gate if (li->li_state == LS_UNDO) {
34340Sstevel@tonic-gate #ifdef DEBUG
34350Sstevel@tonic-gate pool_elem_dprintf(destroy->pdu_elem);
34360Sstevel@tonic-gate #endif /* DEBUG */
34370Sstevel@tonic-gate pool_knl_elem_free((pool_knl_elem_t *)destroy->
34380Sstevel@tonic-gate pdu_elem, PO_TRUE);
34390Sstevel@tonic-gate }
34400Sstevel@tonic-gate free(destroy);
34410Sstevel@tonic-gate break;
34420Sstevel@tonic-gate case POOL_ASSOC:
34430Sstevel@tonic-gate assoc = (pool_assoc_undo_t *)li->li_details;
34440Sstevel@tonic-gate
34450Sstevel@tonic-gate free(assoc);
34460Sstevel@tonic-gate break;
34470Sstevel@tonic-gate case POOL_DISSOC:
34480Sstevel@tonic-gate dissoc = (pool_dissoc_undo_t *)li->li_details;
34490Sstevel@tonic-gate
34500Sstevel@tonic-gate free(dissoc);
34510Sstevel@tonic-gate break;
34520Sstevel@tonic-gate case POOL_TRANSFER:
34530Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
34540Sstevel@tonic-gate return (PO_FAIL);
34550Sstevel@tonic-gate break;
34560Sstevel@tonic-gate case POOL_XTRANSFER:
34570Sstevel@tonic-gate xtransfer = (pool_xtransfer_undo_t *)li->li_details;
34580Sstevel@tonic-gate
34590Sstevel@tonic-gate free(xtransfer->pxu_rl);
34600Sstevel@tonic-gate free(xtransfer->pxu_ioctl.px_o_comp_list);
34610Sstevel@tonic-gate free(xtransfer);
34620Sstevel@tonic-gate break;
34630Sstevel@tonic-gate case POOL_PROPPUT:
34640Sstevel@tonic-gate propput = (pool_propput_undo_t *)li->li_details;
34650Sstevel@tonic-gate
34660Sstevel@tonic-gate if (propput->ppu_blist)
34670Sstevel@tonic-gate nvlist_free(propput->ppu_blist);
34680Sstevel@tonic-gate free(propput->ppu_ioctl.pp_o_buf);
34690Sstevel@tonic-gate free(propput);
34700Sstevel@tonic-gate break;
34710Sstevel@tonic-gate case POOL_PROPRM:
34720Sstevel@tonic-gate proprm = (pool_proprm_undo_t *)li->li_details;
34730Sstevel@tonic-gate
34740Sstevel@tonic-gate free(proprm);
34750Sstevel@tonic-gate break;
34760Sstevel@tonic-gate default:
34770Sstevel@tonic-gate return (PO_FAIL);
34780Sstevel@tonic-gate }
34790Sstevel@tonic-gate return (PO_SUCCESS);
34800Sstevel@tonic-gate }
34810Sstevel@tonic-gate
34820Sstevel@tonic-gate /*
34830Sstevel@tonic-gate * pool_knl_nvlist_add_value() adds a pool_value_t to an nvlist.
34840Sstevel@tonic-gate */
34850Sstevel@tonic-gate int
pool_knl_nvlist_add_value(nvlist_t * list,const char * name,const pool_value_t * pv)34860Sstevel@tonic-gate pool_knl_nvlist_add_value(nvlist_t *list, const char *name,
34870Sstevel@tonic-gate const pool_value_t *pv)
34880Sstevel@tonic-gate {
34890Sstevel@tonic-gate uint64_t uval;
34900Sstevel@tonic-gate int64_t ival;
34910Sstevel@tonic-gate double dval;
34920Sstevel@tonic-gate uchar_t dval_b[sizeof (double)];
34930Sstevel@tonic-gate uchar_t bval;
34940Sstevel@tonic-gate const char *sval;
34950Sstevel@tonic-gate pool_value_class_t type;
34960Sstevel@tonic-gate char *nv_name;
34970Sstevel@tonic-gate
34980Sstevel@tonic-gate if ((type = pool_value_get_type(pv)) == POC_INVAL) {
34990Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
35000Sstevel@tonic-gate return (PO_FAIL);
35010Sstevel@tonic-gate }
35020Sstevel@tonic-gate nv_name = (char *)name;
35030Sstevel@tonic-gate
35040Sstevel@tonic-gate switch (type) {
35050Sstevel@tonic-gate case POC_UINT:
35060Sstevel@tonic-gate if (pool_value_get_uint64(pv, &uval) == POC_INVAL) {
35070Sstevel@tonic-gate return (PO_FAIL);
35080Sstevel@tonic-gate }
35090Sstevel@tonic-gate if (nvlist_add_uint64(list, nv_name, uval) != 0) {
35100Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
35110Sstevel@tonic-gate return (PO_FAIL);
35120Sstevel@tonic-gate }
35130Sstevel@tonic-gate break;
35140Sstevel@tonic-gate case POC_INT:
35150Sstevel@tonic-gate if (pool_value_get_int64(pv, &ival) == POC_INVAL) {
35160Sstevel@tonic-gate return (PO_FAIL);
35170Sstevel@tonic-gate }
35180Sstevel@tonic-gate if (nvlist_add_int64(list, nv_name, ival) != 0) {
35190Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
35200Sstevel@tonic-gate return (PO_FAIL);
35210Sstevel@tonic-gate }
35220Sstevel@tonic-gate break;
35230Sstevel@tonic-gate case POC_DOUBLE:
35240Sstevel@tonic-gate if (pool_value_get_double(pv, &dval) == POC_INVAL) {
35250Sstevel@tonic-gate return (PO_FAIL);
35260Sstevel@tonic-gate }
35270Sstevel@tonic-gate /*
35280Sstevel@tonic-gate * Since there is no support for doubles in the
35290Sstevel@tonic-gate * kernel, store the double value in a byte array.
35300Sstevel@tonic-gate */
35310Sstevel@tonic-gate (void) memcpy(dval_b, &dval, sizeof (double));
35320Sstevel@tonic-gate if (nvlist_add_byte_array(list, nv_name, dval_b,
35330Sstevel@tonic-gate sizeof (double)) != 0) {
35340Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
35350Sstevel@tonic-gate return (PO_FAIL);
35360Sstevel@tonic-gate }
35370Sstevel@tonic-gate break;
35380Sstevel@tonic-gate case POC_BOOL:
35390Sstevel@tonic-gate if (pool_value_get_bool(pv, &bval) == POC_INVAL) {
35400Sstevel@tonic-gate return (PO_FAIL);
35410Sstevel@tonic-gate }
35420Sstevel@tonic-gate if (nvlist_add_byte(list, nv_name, bval) != 0) {
35430Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
35440Sstevel@tonic-gate return (PO_FAIL);
35450Sstevel@tonic-gate }
35460Sstevel@tonic-gate break;
35470Sstevel@tonic-gate case POC_STRING:
35480Sstevel@tonic-gate if (pool_value_get_string(pv, &sval) == POC_INVAL) {
35490Sstevel@tonic-gate return (PO_FAIL);
35500Sstevel@tonic-gate }
35510Sstevel@tonic-gate if (nvlist_add_string(list, nv_name, (char *)sval) != 0) {
35520Sstevel@tonic-gate pool_seterror(POE_SYSTEM);
35530Sstevel@tonic-gate return (PO_FAIL);
35540Sstevel@tonic-gate }
35550Sstevel@tonic-gate break;
35560Sstevel@tonic-gate default:
35570Sstevel@tonic-gate pool_seterror(POE_BADPARAM);
35580Sstevel@tonic-gate return (PO_FAIL);
35590Sstevel@tonic-gate }
35600Sstevel@tonic-gate return (PO_SUCCESS);
35610Sstevel@tonic-gate }
35620Sstevel@tonic-gate
35630Sstevel@tonic-gate /*
35640Sstevel@tonic-gate * hash_id() hashes all elements in a pool configuration using the
35650Sstevel@tonic-gate * "sys_id" property. Not all elements have a "sys_id" property,
35660Sstevel@tonic-gate * however elem_get_sysid() caters for this by always returning a
35670Sstevel@tonic-gate * constant value for those elements. This isn't anticipated to lead
35680Sstevel@tonic-gate * to a performance degradation in the hash, since those elements
35690Sstevel@tonic-gate * which are likely to be most prevalent in a configuration do have
35700Sstevel@tonic-gate * "sys_id" as a property.
35710Sstevel@tonic-gate */
35720Sstevel@tonic-gate uint64_t
hash_id(const pool_elem_t * pe)35730Sstevel@tonic-gate hash_id(const pool_elem_t *pe)
35740Sstevel@tonic-gate {
35750Sstevel@tonic-gate id_t id;
35760Sstevel@tonic-gate
35770Sstevel@tonic-gate id = elem_get_sysid(pe);
35780Sstevel@tonic-gate return (hash_buf(&id, sizeof (id)));
35790Sstevel@tonic-gate }
35800Sstevel@tonic-gate
35810Sstevel@tonic-gate /*
35820Sstevel@tonic-gate * blocking_open() guarantees access to the pool device, if open()
35830Sstevel@tonic-gate * is failing with EBUSY.
35840Sstevel@tonic-gate */
35850Sstevel@tonic-gate int
blocking_open(const char * path,int oflag)35860Sstevel@tonic-gate blocking_open(const char *path, int oflag)
35870Sstevel@tonic-gate {
35880Sstevel@tonic-gate int fd;
35890Sstevel@tonic-gate
35900Sstevel@tonic-gate while ((fd = open(path, oflag)) == -1 && errno == EBUSY)
35910Sstevel@tonic-gate (void) poll(NULL, 0, 1 * MILLISEC);
35920Sstevel@tonic-gate
35930Sstevel@tonic-gate return (fd);
35940Sstevel@tonic-gate }
3595