Home | History | Annotate | Download | only in common
      1     0    stevel /*
      2     0    stevel  * CDDL HEADER START
      3     0    stevel  *
      4     0    stevel  * The contents of this file are subject to the terms of the
      5  3247  gjelinek  * Common Development and Distribution License (the "License").
      6  3247  gjelinek  * You may not use this file except in compliance with the License.
      7     0    stevel  *
      8     0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0    stevel  * or http://www.opensolaris.org/os/licensing.
     10     0    stevel  * See the License for the specific language governing permissions
     11     0    stevel  * and limitations under the License.
     12     0    stevel  *
     13     0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0    stevel  *
     19     0    stevel  * CDDL HEADER END
     20     0    stevel  */
     21     0    stevel /*
     22  3247  gjelinek  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     23     0    stevel  * Use is subject to license terms.
     24     0    stevel  */
     25     0    stevel 
     26     0    stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27     0    stevel 
     28     0    stevel #include <assert.h>
     29     0    stevel #include <errno.h>
     30     0    stevel #include <exacct.h>
     31     0    stevel #include <fcntl.h>
     32     0    stevel #include <libnvpair.h>
     33     0    stevel #include <limits.h>
     34     0    stevel #include <poll.h>
     35     0    stevel #include <pool.h>
     36     0    stevel #include <stdlib.h>
     37     0    stevel #include <stdio.h>
     38     0    stevel #include <string.h>
     39     0    stevel #include <strings.h>
     40     0    stevel #include <stropts.h>
     41     0    stevel #include <thread.h>
     42     0    stevel #include <time.h>
     43     0    stevel #include <unistd.h>
     44     0    stevel 
     45     0    stevel #include <libxml/tree.h>
     46     0    stevel 
     47     0    stevel #include <sys/mman.h>
     48     0    stevel #include <sys/pool.h>
     49     0    stevel #include <sys/pool_impl.h>
     50     0    stevel #include <sys/priocntl.h>
     51     0    stevel #include <sys/stat.h>
     52     0    stevel #include <sys/time.h>
     53     0    stevel #include <sys/types.h>
     54     0    stevel 
     55     0    stevel #include "dict.h"
     56     0    stevel 
     57     0    stevel #include "pool_internal.h"
     58     0    stevel #include "pool_impl.h"
     59     0    stevel #include "pool_kernel_impl.h"
     60     0    stevel 
     61     0    stevel /*
     62     0    stevel  * libpool kernel Manipulation Routines
     63     0    stevel  *
     64     0    stevel  * pool_kernel.c implements the kernel manipulation routines used by the
     65     0    stevel  * libpool kernel datastore. The functions are grouped into the following
     66     0    stevel  * logical areas
     67     0    stevel  *
     68     0    stevel  */
     69     0    stevel 
     70     0    stevel /*
     71     0    stevel  * Device snapshot transfer buffer size
     72     0    stevel  */
     73     0    stevel #define	KERNEL_SNAPSHOT_BUF_SZ	65535
     74     0    stevel 
     75     0    stevel /*
     76     0    stevel  * Kernel result set's initial size. 8 is probably large enough for
     77     0    stevel  * most queries. Queries requiring more space are accomodated using
     78     0    stevel  * realloc on a per result set basis.
     79     0    stevel  */
     80     0    stevel #define	KERNEL_RS_INITIAL_SZ	8
     81     0    stevel 
     82     0    stevel /*
     83     0    stevel  * Property manipulation macros
     84     0    stevel  */
     85     0    stevel #define	KERNEL_PROP_RDONLY	0x1
     86     0    stevel 
     87     0    stevel /*
     88     0    stevel  * Information required to evaluate qualifying elements for a query
     89     0    stevel  */
     90     0    stevel struct query_obj {
     91     0    stevel 	const pool_conf_t *conf;
     92     0    stevel 	const pool_elem_t *src;
     93     0    stevel 	const char *src_attr;
     94     0    stevel 	pool_elem_class_t classes;
     95     0    stevel 	pool_value_t **props;
     96     0    stevel 	pool_knl_result_set_t *rs;
     97     0    stevel };
     98     0    stevel 
     99     0    stevel /*
    100     0    stevel  * Identifies a pool element with a processor set id
    101     0    stevel  */
    102     0    stevel typedef struct pool_set_xref {
    103     0    stevel 	pool_knl_pool_t	*psx_pool;
    104     0    stevel 	uint_t		psx_pset_id;
    105     0    stevel 	struct pool_set_xref *psx_next;
    106     0    stevel } pool_set_xref_t;
    107     0    stevel 
    108     0    stevel /*
    109     0    stevel  * Controls exacct snapshot load into libpool data structure
    110     0    stevel  */
    111     0    stevel typedef struct pool_snap_load {
    112     0    stevel 	int *psl_changed;
    113     0    stevel 	pool_set_xref_t *psl_xref;
    114     0    stevel 	pool_elem_t *psl_system;
    115     0    stevel 	pool_knl_resource_t *psl_pset;
    116     0    stevel } pool_snap_load_t;
    117     0    stevel 
    118     0    stevel /*
    119     0    stevel  * Information about an XML document which is being constructed
    120     0    stevel  */
    121     0    stevel struct knl_to_xml {
    122     0    stevel 	xmlDocPtr ktx_doc;
    123     0    stevel 	xmlNodePtr ktx_node;
    124     0    stevel };
    125     0    stevel 
    126     0    stevel /*
    127     0    stevel  * Undo structure processing. The following structures are all used to
    128     0    stevel  * allow changes to the libpool snapshot and kernel following an
    129     0    stevel  * unsuccessful commit.
    130     0    stevel  */
    131     0    stevel typedef struct pool_create_undo {
    132     0    stevel 	pool_create_t pcu_ioctl;
    133     0    stevel 	pool_elem_t *pcu_elem;
    134     0    stevel } pool_create_undo_t;
    135     0    stevel 
    136     0    stevel typedef struct pool_destroy_undo {
    137     0    stevel 	pool_destroy_t pdu_ioctl;
    138     0    stevel 	pool_elem_t *pdu_elem;
    139     0    stevel } pool_destroy_undo_t;
    140     0    stevel 
    141     0    stevel typedef struct pool_assoc_undo {
    142     0    stevel 	pool_assoc_t pau_ioctl;
    143     0    stevel 	pool_elem_t *pau_assoc;
    144     0    stevel 	pool_elem_t *pau_oldres;
    145     0    stevel 	pool_elem_t *pau_newres;
    146     0    stevel } pool_assoc_undo_t;
    147     0    stevel 
    148     0    stevel typedef struct pool_dissoc_undo {
    149     0    stevel 	pool_dissoc_t pdu_ioctl;
    150     0    stevel 	pool_elem_t *pdu_dissoc;
    151     0    stevel 	pool_elem_t *pdu_oldres;
    152     0    stevel 	pool_elem_t *pdu_newres;
    153     0    stevel } pool_dissoc_undo_t;
    154     0    stevel 
    155     0    stevel typedef struct pool_xtransfer_undo {
    156     0    stevel 	pool_xtransfer_t pxu_ioctl;
    157     0    stevel 	pool_elem_t *pxu_src;
    158     0    stevel 	pool_elem_t *pxu_tgt;
    159     0    stevel 	pool_component_t **pxu_rl;
    160     0    stevel } pool_xtransfer_undo_t;
    161     0    stevel 
    162     0    stevel typedef struct pool_propput_undo {
    163     0    stevel 	pool_propput_t ppu_ioctl;
    164     0    stevel 	pool_elem_t *ppu_elem;
    165     0    stevel 	nvlist_t *ppu_alist;
    166     0    stevel 	nvlist_t *ppu_blist;
    167     0    stevel 	uchar_t ppu_doioctl;
    168     0    stevel } pool_propput_undo_t;
    169     0    stevel 
    170     0    stevel typedef struct pool_proprm_undo {
    171     0    stevel 	pool_proprm_t pru_ioctl;
    172     0    stevel 	pool_elem_t *pru_elem;
    173     0    stevel 	pool_value_t pru_oldval;
    174     0    stevel } pool_proprm_undo_t;
    175     0    stevel 
    176     0    stevel extern const char *dtd_location;
    177     0    stevel 
    178     0    stevel extern const char *element_class_tags[];
    179     0    stevel extern const char pool_info_location[];
    180     0    stevel 
    181     0    stevel /*
    182     0    stevel  * These functions are defined in pool_xml.c and represent the minimum
    183     0    stevel  * XML support required to allow a pool kernel configuration to be
    184     0    stevel  * exported as an XML document.
    185     0    stevel  */
    186     0    stevel extern int pool_xml_set_attr(xmlNodePtr, xmlChar *, const pool_value_t *);
    187     0    stevel extern int pool_xml_set_prop(xmlNodePtr, xmlChar *, const pool_value_t *);
    188     0    stevel extern void xml_init(void);
    189     0    stevel extern xmlNodePtr node_create(xmlNodePtr, const xmlChar *);
    190     0    stevel extern void pool_error_func(void *, const char *, ...);
    191     0    stevel /*
    192     0    stevel  * Utilities
    193     0    stevel  */
    194     0    stevel static int load_group(pool_conf_t *, pool_knl_elem_t *, ea_object_t *,
    195     0    stevel     pool_snap_load_t *);
    196     0    stevel static void pool_knl_elem_free(pool_knl_elem_t *, int);
    197     0    stevel static int pool_knl_put_xml_property(pool_elem_t *, xmlNodePtr, const char *,
    198     0    stevel     const pool_value_t *);
    199     0    stevel static int pool_knl_snap_load_push(pool_snap_load_t *, pool_knl_pool_t *);
    200     0    stevel static int pool_knl_snap_load_update(pool_snap_load_t *, int, uint_t);
    201     0    stevel static int pool_knl_snap_load_remove(pool_snap_load_t *, int, uint_t);
    202     0    stevel static nvpair_t *pool_knl_find_nvpair(nvlist_t *, const char *);
    203     0    stevel static int pool_knl_nvlist_add_value(nvlist_t *, const char *,
    204     0    stevel     const pool_value_t *);
    205     0    stevel static int pool_knl_recover(pool_conf_t *);
    206     0    stevel static uint64_t hash_id(const pool_elem_t *);
    207     0    stevel static int blocking_open(const char *, int);
    208     0    stevel 
    209     0    stevel /*
    210     0    stevel  * Connections
    211     0    stevel  */
    212     0    stevel static void pool_knl_connection_free(pool_knl_connection_t *);
    213     0    stevel 
    214     0    stevel /*
    215     0    stevel  * Configuration
    216     0    stevel  */
    217     0    stevel static int pool_knl_close(pool_conf_t *);
    218     0    stevel static int pool_knl_validate(const pool_conf_t *, pool_valid_level_t);
    219     0    stevel static int pool_knl_commit(pool_conf_t *);
    220     0    stevel static int pool_knl_export(const pool_conf_t *, const char *,
    221     0    stevel     pool_export_format_t);
    222     0    stevel static int pool_knl_rollback(pool_conf_t *);
    223     0    stevel static pool_result_set_t *pool_knl_exec_query(const pool_conf_t *,
    224     0    stevel     const pool_elem_t *, const char *, pool_elem_class_t, pool_value_t **);
    225     0    stevel static int pool_knl_remove(pool_conf_t *);
    226     0    stevel static char *pool_knl_get_binding(pool_conf_t *, pid_t);
    227     0    stevel static int pool_knl_set_binding(pool_conf_t *, const char *, idtype_t, id_t);
    228     0    stevel static char *pool_knl_get_resource_binding(pool_conf_t *,
    229     0    stevel     pool_resource_elem_class_t, pid_t);
    230     0    stevel static int pool_knl_res_transfer(pool_resource_t *, pool_resource_t *,
    231     0    stevel     uint64_t);
    232     0    stevel static int pool_knl_res_xtransfer(pool_resource_t *, pool_resource_t *,
    233     0    stevel     pool_component_t **);
    234     0    stevel 
    235     0    stevel /*
    236     0    stevel  * Result Sets
    237     0    stevel  */
    238     0    stevel static pool_knl_result_set_t *pool_knl_result_set_alloc(const pool_conf_t *);
    239     0    stevel static int pool_knl_result_set_append(pool_knl_result_set_t *,
    240     0    stevel     pool_knl_elem_t *);
    241     0    stevel static int pool_knl_result_set_realloc(pool_knl_result_set_t *);
    242     0    stevel static void pool_knl_result_set_free(pool_knl_result_set_t *);
    243     0    stevel static pool_elem_t *pool_knl_rs_next(pool_result_set_t *);
    244     0    stevel static pool_elem_t *pool_knl_rs_prev(pool_result_set_t *);
    245     0    stevel static pool_elem_t *pool_knl_rs_first(pool_result_set_t *);
    246     0    stevel static pool_elem_t *pool_knl_rs_last(pool_result_set_t *);
    247     0    stevel static int pool_knl_rs_set_index(pool_result_set_t *, int);
    248     0    stevel static int pool_knl_rs_get_index(pool_result_set_t *);
    249     0    stevel static int pool_knl_rs_count(pool_result_set_t *);
    250     0    stevel static int pool_knl_rs_close(pool_result_set_t *);
    251     0    stevel 
    252     0    stevel /*
    253     0    stevel  * Element (and sub-type)
    254     0    stevel  */
    255     0    stevel static pool_knl_elem_t *pool_knl_elem_wrap(pool_conf_t *, pool_elem_class_t,
    256     0    stevel     pool_resource_elem_class_t, pool_component_elem_class_t);
    257     0    stevel static pool_elem_t *pool_knl_elem_create(pool_conf_t *, pool_elem_class_t,
    258     0    stevel     pool_resource_elem_class_t, pool_component_elem_class_t);
    259     0    stevel static int pool_knl_elem_remove(pool_elem_t *);
    260     0    stevel static int pool_knl_set_container(pool_elem_t *, pool_elem_t *);
    261     0    stevel static pool_elem_t *pool_knl_get_container(const pool_elem_t *);
    262     0    stevel /*
    263     0    stevel  * Pool element specific
    264     0    stevel  */
    265     0    stevel static int pool_knl_pool_associate(pool_t *, const pool_resource_t *);
    266     0    stevel static int pool_knl_pool_dissociate(pool_t *, const pool_resource_t *);
    267     0    stevel 
    268     0    stevel /*
    269     0    stevel  * Resource elements specific
    270     0    stevel  */
    271     0    stevel static int pool_knl_resource_is_system(const pool_resource_t *);
    272     0    stevel static int pool_knl_resource_can_associate(const pool_resource_t *);
    273     0    stevel 
    274     0    stevel /* Properties */
    275     0    stevel static pool_value_class_t pool_knl_get_property(const pool_elem_t *,
    276     0    stevel     const char *, pool_value_t *);
    277     0    stevel static pool_value_class_t pool_knl_get_dynamic_property(const pool_elem_t *,
    278     0    stevel     const char *, pool_value_t *);
    279     0    stevel static int pool_knl_put_property(pool_elem_t *, const char *,
    280     0    stevel     const pool_value_t *);
    281     0    stevel static int pool_knl_rm_property(pool_elem_t *, const char *);
    282     0    stevel static pool_value_t **pool_knl_get_properties(const pool_elem_t *, uint_t *);
    283     0    stevel 
    284     0    stevel /*
    285     0    stevel  * Logging
    286     0    stevel  */
    287     0    stevel static int log_item_commit(log_item_t *);
    288     0    stevel static int log_item_undo(log_item_t *);
    289     0    stevel static int log_item_release(log_item_t *);
    290     0    stevel 
    291     0    stevel /*
    292     0    stevel  * Utilities
    293     0    stevel  */
    294     0    stevel 
    295     0    stevel /*
    296     0    stevel  * load_group() updates the library configuration with the kernel
    297     0    stevel  * snapshot supplied in ep. The function is designed to be called
    298     0    stevel  * recursively. This function depends implicitly on the ordering of
    299     0    stevel  * the data provided in ep. Changes to the ordering of data in ep must
    300     0    stevel  * be matched by changes to this function.
    301     0    stevel  */
    302     0    stevel int
    303     0    stevel load_group(pool_conf_t *conf, pool_knl_elem_t *elem, ea_object_t *ep,
    304     0    stevel     pool_snap_load_t *psl)
    305     0    stevel {
    306     0    stevel 	ea_object_t *eo;
    307     0    stevel 	pool_knl_elem_t *old_elem;
    308     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
    309     0    stevel 	int ret = PO_SUCCESS;
    310     0    stevel 
    311     0    stevel 	if ((ep->eo_catalog & EXD_DATA_MASK) == EXD_GROUP_SYSTEM) {
    312     0    stevel 		if ((elem = pool_knl_elem_wrap(conf, PEC_SYSTEM, PREC_INVALID,
    313     0    stevel 		    PCEC_INVALID)) == NULL)
    314     0    stevel 			return (PO_FAIL);
    315     0    stevel 		if (nvlist_alloc(&elem->pke_properties, NV_UNIQUE_NAME_TYPE,
    316     0    stevel 		    0) != 0) {
    317     0    stevel 			pool_knl_elem_free(elem, PO_FALSE);
    318     0    stevel 			pool_seterror(POE_SYSTEM);
    319     0    stevel 			return (PO_FAIL);
    320     0    stevel 		}
    321     0    stevel 		/*
    322     0    stevel 		 * Check to see if we already have an element
    323     0    stevel 		 * for this data. If we have, free the newly
    324     0    stevel 		 * created elem and continue with the old one
    325     0    stevel 		 */
    326     0    stevel 		if ((old_elem = dict_get(prov->pkc_elements, elem)) != NULL) {
    327     0    stevel 			nvlist_free(old_elem->pke_properties);
    328     0    stevel 			old_elem->pke_properties = elem->pke_properties;
    329     0    stevel 			pool_knl_elem_free(elem, PO_FALSE);
    330     0    stevel 			elem = old_elem;
    331     0    stevel 		} else {
    332     0    stevel 			if (dict_put(prov->pkc_elements, elem, elem) != NULL) {
    333     0    stevel 				pool_knl_elem_free(elem, PO_TRUE);
    334     0    stevel 				pool_seterror(POE_SYSTEM);
    335     0    stevel 				return (PO_FAIL);
    336     0    stevel 			}
    337     0    stevel 		}
    338     0    stevel 		psl->psl_system = (pool_elem_t *)elem;
    339     0    stevel 	}
    340     0    stevel 
    341     0    stevel 	for (eo = ep->eo_group.eg_objs; eo != NULL; eo = eo->eo_next) {
    342     0    stevel 		int data;
    343     0    stevel 		pool_knl_elem_t *prop_elem = NULL;
    344     0    stevel 
    345     0    stevel 		data = (eo->eo_catalog & EXD_DATA_MASK);
    346     0    stevel 
    347     0    stevel 		switch (data) {
    348     0    stevel 		case EXD_SYSTEM_TSTAMP:
    349     0    stevel 		case EXD_POOL_TSTAMP:
    350     0    stevel 		case EXD_PSET_TSTAMP:
    351     0    stevel 		case EXD_CPU_TSTAMP:
    352     0    stevel 			if (eo->eo_item.ei_uint64 > prov->pkc_lotime) {
    353     0    stevel 				if (eo->eo_item.ei_uint64 > prov->pkc_ltime)
    354     0    stevel 					prov->pkc_ltime = eo->eo_item.ei_uint64;
    355     0    stevel 				if (psl->psl_changed) {
    356     0    stevel 					switch (data) {
    357     0    stevel 					case EXD_SYSTEM_TSTAMP:
    358     0    stevel 						*psl->psl_changed |= POU_SYSTEM;
    359     0    stevel 						break;
    360     0    stevel 					case EXD_POOL_TSTAMP:
    361     0    stevel 						*psl->psl_changed |= POU_POOL;
    362     0    stevel 						break;
    363     0    stevel 					case EXD_PSET_TSTAMP:
    364     0    stevel 						*psl->psl_changed |= POU_PSET;
    365     0    stevel 						break;
    366     0    stevel 					case EXD_CPU_TSTAMP:
    367     0    stevel 						*psl->psl_changed |= POU_CPU;
    368     0    stevel 						break;
    369     0    stevel 					}
    370     0    stevel 				}
    371     0    stevel 			}
    372     0    stevel 			break;
    373     0    stevel 		case EXD_SYSTEM_PROP:
    374     0    stevel 		case EXD_POOL_PROP:
    375     0    stevel 		case EXD_PSET_PROP:
    376     0    stevel 		case EXD_CPU_PROP:
    377     0    stevel 			if (data == EXD_PSET_PROP) {
    378     0    stevel 				prop_elem = elem;
    379     0    stevel 				elem = (pool_knl_elem_t *)psl->psl_pset;
    380     0    stevel 			}
    381     0    stevel 			nvlist_free(elem->pke_properties);
    382     0    stevel 			if (nvlist_unpack(eo->eo_item.ei_raw,
    383     0    stevel 			    eo->eo_item.ei_size, &elem->pke_properties, 0) !=
    384     0    stevel 			    0) {
    385     0    stevel 				pool_seterror(POE_SYSTEM);
    386     0    stevel 				return (PO_FAIL);
    387     0    stevel 			}
    388     0    stevel 			elem->pke_ltime = prov->pkc_ltime;
    389     0    stevel 			if (data == EXD_PSET_PROP) {
    390     0    stevel 				elem = prop_elem;
    391     0    stevel 			}
    392     0    stevel 			break;
    393     0    stevel 		case EXD_POOL_POOLID:
    394     0    stevel 			if (nvlist_alloc(&elem->pke_properties,
    395     0    stevel 			    NV_UNIQUE_NAME_TYPE, 0) != 0) {
    396     0    stevel 				pool_seterror(POE_SYSTEM);
    397     0    stevel 				return (PO_FAIL);
    398     0    stevel 			}
    399     0    stevel 			if (nvlist_add_int64(elem->pke_properties,
    400     0    stevel 			    "pool.sys_id",
    401     0    stevel 			    (int64_t)eo->eo_item.ei_uint32) != 0) {
    402     0    stevel 				pool_seterror(POE_SYSTEM);
    403     0    stevel 				return (PO_FAIL);
    404     0    stevel 			}
    405     0    stevel 			if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
    406     0    stevel 			    NULL) {
    407     0    stevel 				nvlist_free(old_elem->pke_properties);
    408     0    stevel 				old_elem->pke_properties = elem->pke_properties;
    409     0    stevel 				pool_knl_elem_free(elem, PO_FALSE);
    410     0    stevel 				elem = old_elem;
    411     0    stevel 			} else {
    412     0    stevel 				if (dict_put(prov->pkc_elements, elem, elem) !=
    413     0    stevel 				    NULL) {
    414     0    stevel 					pool_knl_elem_free(elem, PO_TRUE);
    415     0    stevel 					pool_seterror(POE_SYSTEM);
    416     0    stevel 					return (PO_FAIL);
    417     0    stevel 				}
    418     0    stevel 			}
    419     0    stevel 			if (pool_knl_snap_load_push(psl,
    420     0    stevel 			    (pool_knl_pool_t *)elem) != PO_SUCCESS) {
    421     0    stevel 				pool_seterror(POE_SYSTEM);
    422     0    stevel 				return (PO_FAIL);
    423     0    stevel 			}
    424     0    stevel 			((pool_knl_pool_t *)elem)->pkp_assoc[PREC_PSET] = NULL;
    425     0    stevel 			break;
    426     0    stevel 		case EXD_POOL_PSETID:
    427     0    stevel 			if (pool_knl_snap_load_update(psl, EXD_POOL_PSETID,
    428     0    stevel 			    eo->eo_item.ei_uint32) != PO_SUCCESS) {
    429     0    stevel 				pool_seterror(POE_SYSTEM);
    430     0    stevel 				return (PO_FAIL);
    431     0    stevel 			}
    432     0    stevel 			break;
    433     0    stevel 		case EXD_PSET_PSETID:
    434     0    stevel 			if (nvlist_alloc(&elem->pke_properties,
    435     0    stevel 			    NV_UNIQUE_NAME_TYPE, 0) != 0) {
    436     0    stevel 				pool_seterror(POE_SYSTEM);
    437     0    stevel 				return (PO_FAIL);
    438     0    stevel 			}
    439     0    stevel 			if (nvlist_add_int64(elem->pke_properties,
    440     0    stevel 			    "pset.sys_id",
    441     0    stevel 			    (int64_t)eo->eo_item.ei_uint32) != 0) {
    442     0    stevel 				pool_seterror(POE_SYSTEM);
    443     0    stevel 				return (PO_FAIL);
    444     0    stevel 			}
    445     0    stevel 			if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
    446     0    stevel 			    NULL) {
    447     0    stevel 				nvlist_free(old_elem->pke_properties);
    448     0    stevel 				old_elem->pke_properties = elem->pke_properties;
    449     0    stevel 				pool_knl_elem_free(elem, PO_FALSE);
    450     0    stevel 				elem = old_elem;
    451     0    stevel 			} else {
    452     0    stevel 				if (dict_put(prov->pkc_elements, elem, elem) !=
    453     0    stevel 				    NULL) {
    454     0    stevel 					pool_knl_elem_free(elem, PO_TRUE);
    455     0    stevel 					pool_seterror(POE_SYSTEM);
    456     0    stevel 					return (PO_FAIL);
    457     0    stevel 				}
    458     0    stevel 			}
    459     0    stevel 			psl->psl_pset = (pool_knl_resource_t *)elem;
    460     0    stevel 			if (pool_knl_snap_load_remove(psl, data,
    461     0    stevel 			    eo->eo_item.ei_uint32) != PO_SUCCESS) {
    462     0    stevel 				pool_seterror(POE_SYSTEM);
    463     0    stevel 				return (PO_FAIL);
    464     0    stevel 			}
    465     0    stevel 			break;
    466     0    stevel 		case EXD_CPU_CPUID:
    467     0    stevel 			if (nvlist_alloc(&elem->pke_properties,
    468     0    stevel 			    NV_UNIQUE_NAME_TYPE, 0) != 0) {
    469     0    stevel 				pool_seterror(POE_SYSTEM);
    470     0    stevel 				return (PO_FAIL);
    471     0    stevel 			}
    472     0    stevel 			if (nvlist_add_int64(elem->pke_properties,
    473     0    stevel 			    "cpu.sys_id",
    474     0    stevel 			    (int64_t)eo->eo_item.ei_uint32) != 0) {
    475     0    stevel 				pool_seterror(POE_SYSTEM);
    476     0    stevel 				return (PO_FAIL);
    477     0    stevel 			}
    478     0    stevel 			if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
    479     0    stevel 			    NULL) {
    480     0    stevel 				nvlist_free(old_elem->pke_properties);
    481     0    stevel 				old_elem->pke_properties = elem->pke_properties;
    482     0    stevel 				old_elem->pke_parent = elem->pke_parent;
    483     0    stevel 				pool_knl_elem_free(elem, PO_FALSE);
    484     0    stevel 				elem = old_elem;
    485     0    stevel 			} else {
    486     0    stevel 				if (dict_put(prov->pkc_elements, elem, elem) !=
    487     0    stevel 				    NULL) {
    488     0    stevel 					pool_knl_elem_free(elem, PO_TRUE);
    489     0    stevel 					pool_seterror(POE_SYSTEM);
    490     0    stevel 					return (PO_FAIL);
    491     0    stevel 				}
    492     0    stevel 			}
    493     0    stevel 			break;
    494     0    stevel 		case EXD_GROUP_POOL:
    495     0    stevel 			if ((elem = pool_knl_elem_wrap(conf, PEC_POOL,
    496     0    stevel 			    PREC_INVALID, PCEC_INVALID)) == NULL)
    497     0    stevel 				return (PO_FAIL);
    498     0    stevel 			if (pool_set_container(psl->psl_system,
    499     0    stevel 			    (pool_elem_t *)elem) != PO_SUCCESS) {
    500     0    stevel 				pool_seterror(POE_SYSTEM);
    501     0    stevel 				return (PO_FAIL);
    502     0    stevel 			}
    503     0    stevel 			break;
    504     0    stevel 		case EXD_GROUP_PSET:
    505     0    stevel 			if ((elem = pool_knl_elem_wrap(conf, PEC_RES_COMP,
    506     0    stevel 			    PREC_PSET, PCEC_INVALID)) == NULL)
    507     0    stevel 				return (PO_FAIL);
    508     0    stevel 			if (pool_set_container(psl->psl_system,
    509     0    stevel 			    (pool_elem_t *)elem) != PO_SUCCESS) {
    510     0    stevel 				pool_seterror(POE_SYSTEM);
    511     0    stevel 				return (PO_FAIL);
    512     0    stevel 			}
    513     0    stevel 			break;
    514     0    stevel 		case EXD_GROUP_CPU:
    515     0    stevel 			if ((elem = pool_knl_elem_wrap(conf, PEC_COMP,
    516     0    stevel 			    PREC_INVALID, PCEC_CPU)) == NULL)
    517     0    stevel 				return (PO_FAIL);
    518     0    stevel 			if (pool_set_container((pool_elem_t *)psl->psl_pset,
    519     0    stevel 			    (pool_elem_t *)elem) != PO_SUCCESS) {
    520     0    stevel 				pool_seterror(POE_SYSTEM);
    521     0    stevel 				return (PO_FAIL);
    522     0    stevel 			}
    523     0    stevel 			break;
    524     0    stevel 		default:
    525     0    stevel 			break;
    526     0    stevel 		}
    527     0    stevel 
    528     0    stevel 
    529     0    stevel 		if (eo->eo_type == EO_GROUP) {
    530     0    stevel 			if ((ret = load_group(conf, elem, eo, psl)) == PO_FAIL)
    531     0    stevel 				break;
    532     0    stevel 		}
    533     0    stevel 	}
    534     0    stevel 	return (ret);
    535     0    stevel }
    536     0    stevel 
    537     0    stevel /*
    538     0    stevel  * Push a snapshot entry onto the list of pools in the snapshot.
    539     0    stevel  */
    540     0    stevel int
    541     0    stevel pool_knl_snap_load_push(pool_snap_load_t *psl, pool_knl_pool_t *pkp)
    542     0    stevel {
    543     0    stevel 	pool_set_xref_t *psx;
    544     0    stevel 
    545     0    stevel 	if ((psx = malloc(sizeof (pool_set_xref_t))) == NULL) {
    546     0    stevel 		pool_seterror(POE_SYSTEM);
    547     0    stevel 		return (PO_FAIL);
    548     0    stevel 	}
    549     0    stevel 	(void) memset(psx, 0, sizeof (pool_set_xref_t));
    550     0    stevel 	psx->psx_pool = pkp;
    551     0    stevel 	/*
    552     0    stevel 	 * Push onto the list of pools
    553     0    stevel 	 */
    554     0    stevel 	psx->psx_next = psl->psl_xref;
    555     0    stevel 	psl->psl_xref = psx;
    556     0    stevel 
    557     0    stevel 	return (PO_SUCCESS);
    558     0    stevel }
    559     0    stevel 
    560     0    stevel /*
    561     0    stevel  * Update the current cross-reference for the supplied type of
    562     0    stevel  * resource.
    563     0    stevel  */
    564     0    stevel int
    565     0    stevel pool_knl_snap_load_update(pool_snap_load_t *psl, int type, uint_t id)
    566     0    stevel {
    567     0    stevel 	switch (type) {
    568     0    stevel 	case EXD_POOL_PSETID:
    569     0    stevel 		psl->psl_xref->psx_pset_id = id;
    570     0    stevel 		break;
    571     0    stevel 	default:
    572     0    stevel 		return (PO_FAIL);
    573     0    stevel 	}
    574     0    stevel 
    575     0    stevel 	return (PO_SUCCESS);
    576     0    stevel }
    577     0    stevel 
    578     0    stevel /*
    579     0    stevel  * Remove a resource entry with the supplied type and id from the
    580     0    stevel  * snapshot list when it is no longer required.
    581     0    stevel  */
    582     0    stevel int
    583     0    stevel pool_knl_snap_load_remove(pool_snap_load_t *psl, int type, uint_t id)
    584     0    stevel {
    585     0    stevel 	pool_set_xref_t *current, *prev, *next;
    586     0    stevel 
    587     0    stevel 	for (prev = NULL, current = psl->psl_xref; current != NULL;
    588     0    stevel 	    current = next) {
    589     0    stevel 		switch (type) {
    590     0    stevel 		case EXD_PSET_PSETID:
    591     0    stevel 			if (current->psx_pset_id == id)
    592     0    stevel 				current->psx_pool->pkp_assoc[PREC_PSET] =
    593     0    stevel 				    psl->psl_pset;
    594     0    stevel 			break;
    595     0    stevel 		default:
    596     0    stevel 			return (PO_FAIL);
    597     0    stevel 		}
    598     0    stevel 		next = current->psx_next;
    599     0    stevel 		if (current->psx_pool->pkp_assoc[PREC_PSET] != NULL) {
    600     0    stevel 			if (prev != NULL) {
    601     0    stevel 				prev->psx_next = current->psx_next;
    602     0    stevel 			} else {
    603     0    stevel 				psl->psl_xref = current->psx_next;
    604     0    stevel 			}
    605     0    stevel 			free(current);
    606     0    stevel 		} else
    607     0    stevel 			prev = current;
    608     0    stevel 	}
    609     0    stevel 
    610     0    stevel 	return (PO_SUCCESS);
    611     0    stevel }
    612     0    stevel 
    613     0    stevel /*
    614     0    stevel  * Return the nvpair with the supplied name from the supplied list.
    615     0    stevel  *
    616     0    stevel  * NULL is returned if the name cannot be found in the list.
    617     0    stevel  */
    618     0    stevel nvpair_t *
    619     0    stevel pool_knl_find_nvpair(nvlist_t *l, const char *name)
    620     0    stevel {
    621     0    stevel 	nvpair_t *pair;
    622     0    stevel 
    623     0    stevel 	for (pair = nvlist_next_nvpair(l, NULL); pair != NULL;
    624     0    stevel 		pair = nvlist_next_nvpair(l, pair)) {
    625     0    stevel 		if (strcmp(nvpair_name(pair), name) == 0)
    626     0    stevel 			break;
    627     0    stevel 	}
    628     0    stevel 	return (pair);
    629     0    stevel }
    630     0    stevel 
    631     0    stevel /*
    632     0    stevel  * Close the configuration. There are a few steps to closing a configuration:
    633     0    stevel  * - Close the pseudo device
    634     0    stevel  * - Free the data provider
    635     0    stevel  * Returns PO_SUCCESS/PO_FAIL
    636     0    stevel  */
    637     0    stevel int
    638     0    stevel pool_knl_close(pool_conf_t *conf)
    639     0    stevel {
    640     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
    641     0    stevel 
    642     0    stevel 	if (close(prov->pkc_fd) < 0) {
    643     0    stevel 		pool_seterror(POE_SYSTEM);
    644     0    stevel 		return (PO_FAIL);
    645     0    stevel 	}
    646     0    stevel 	/*
    647     0    stevel 	 * Rollback any pending changes before freeing the prov. This
    648  3247  gjelinek 	 * ensures there are no memory leaks from pending transactions.
    649  3247  gjelinek 	 * However, don't rollback when we've done a temporary pool since the
    650  3247  gjelinek 	 * pool/resources haven't really been committed in this case.
    651  3247  gjelinek 	 * They will all be freed in pool_knl_connection_free and we don't
    652  3247  gjelinek 	 * want to double free them.
    653     0    stevel 	 */
    654  3247  gjelinek 	if (!(conf->pc_prov->pc_oflags & PO_TEMP))
    655  3247  gjelinek 		(void) pool_knl_rollback(conf);
    656     0    stevel 	pool_knl_connection_free(prov);
    657     0    stevel 	return (PO_SUCCESS);
    658     0    stevel }
    659     0    stevel 
    660     0    stevel /*
    661     0    stevel  * Remove elements in this map (previously identified as "dead") from
    662     0    stevel  * the configuration map (prov->pkc_elements).
    663     0    stevel  */
    664     0    stevel 
    665     0    stevel /* ARGSUSED1 */
    666     0    stevel static void
    667     0    stevel remove_dead_elems(const void *key, void **value, void *cl)
    668     0    stevel {
    669     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
    670     0    stevel 	pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
    671     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
    672     0    stevel 
    673     0    stevel 	assert(dict_remove(prov->pkc_elements, pke) != NULL);
    674     0    stevel #ifdef DEBUG
    675     0    stevel 	dprintf("remove_dead_elems:\n");
    676     0    stevel 	pool_elem_dprintf(TO_ELEM(pke));
    677     0    stevel #endif	/* DEBUG */
    678     0    stevel 	pool_knl_elem_free(pke, PO_TRUE);
    679     0    stevel }
    680     0    stevel 
    681     0    stevel /*
    682     0    stevel  * Find elements which were not updated the last time that
    683     0    stevel  * load_group() was called. Add those elements into a separate map
    684     0    stevel  * (passed in cl) which will be later used to remove these elements
    685     0    stevel  * from the configuration map.
    686     0    stevel  */
    687     0    stevel /* ARGSUSED1 */
    688     0    stevel static void
    689     0    stevel find_dead_elems(const void *key, void **value, void *cl)
    690     0    stevel {
    691     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
    692     0    stevel 	pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
    693     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
    694     0    stevel 	dict_hdl_t *dead_map = (dict_hdl_t *)cl;
    695     0    stevel 
    696     0    stevel 	if (pke->pke_ltime < prov->pkc_ltime)
    697     0    stevel 		(void) dict_put(dead_map, pke, pke);
    698     0    stevel }
    699     0    stevel 
    700     0    stevel /*
    701     0    stevel  * Update the snapshot held by the library. This function acts as the
    702     0    stevel  * controller for the snapshot update procedure. Then snapshot is
    703     0    stevel  * actually updated in multiple phases by the load_group() function
    704     0    stevel  * (which updates existing elements and creates new elements as
    705     0    stevel  * required) and then by find_dead_elems and remove_dead_elems
    706     0    stevel  * (respectively responsible for identifying elements which are to be
    707     0    stevel  * removed and then removing them).
    708     0    stevel  *
    709     0    stevel  * Returns PO_SUCCESS
    710     0    stevel  */
    711     0    stevel int
    712     0    stevel pool_knl_update(pool_conf_t *conf, int *changed)
    713     0    stevel {
    714     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
    715     0    stevel 	pool_query_t query = {0};
    716     0    stevel 	ea_object_t *ep;
    717     0    stevel 	dict_hdl_t *dead_map;
    718     0    stevel 	pool_snap_load_t psl = { NULL };
    719     0    stevel 
    720     0    stevel 	/*
    721     0    stevel 	 * Ensure the library snapshot is consistent, if there are any
    722     0    stevel 	 * outstanding transactions return failure.
    723     0    stevel 	 */
    724     0    stevel 	if (log_size(prov->pkc_log) != 0) {
    725     0    stevel 		pool_seterror(POE_INVALID_CONF);
    726     0    stevel 		return (PO_FAIL);
    727     0    stevel 	}
    728     0    stevel 	/*
    729     0    stevel 	 * Query the kernel for a snapshot of the configuration state. Use
    730     0    stevel 	 * load_group to allocate the user-land representation of the
    731     0    stevel 	 * data returned in the snapshot.
    732     0    stevel 	 */
    733     0    stevel 	/* LINTED E_CONSTANT_CONDITION */
    734     0    stevel 	while (1) {
    735     0    stevel 		if (ioctl(prov->pkc_fd, POOL_QUERY, &query) < 0) {
    736     0    stevel 			pool_seterror(POE_SYSTEM);
    737     0    stevel 			return (PO_FAIL);
    738     0    stevel 		}
    739     0    stevel 		if ((query.pq_io_buf = calloc(1,
    740     0    stevel 		    (query.pq_io_bufsize < KERNEL_SNAPSHOT_BUF_SZ) ?
    741     0    stevel 		    query.pq_io_bufsize * 2 : query.pq_io_bufsize)) == NULL) {
    742     0    stevel 			pool_seterror(POE_SYSTEM);
    743     0    stevel 			return (PO_FAIL);
    744     0    stevel 		}
    745     0    stevel 		if (ioctl(prov->pkc_fd, POOL_QUERY, &query) < 0) {
    746     0    stevel 			free(query.pq_io_buf);
    747     0    stevel 			if (errno != ENOMEM) {
    748     0    stevel 				pool_seterror(POE_SYSTEM);
    749     0    stevel 				return (PO_FAIL);
    750     0    stevel 			}
    751     0    stevel 			query.pq_io_bufsize = 0;
    752     0    stevel 			query.pq_io_buf = NULL;
    753     0    stevel 		} else
    754     0    stevel 			break;
    755     0    stevel 	}
    756     0    stevel 	if (ea_unpack_object(&ep, EUP_NOALLOC, query.pq_io_buf,
    757     0    stevel 	    query.pq_io_bufsize) != EO_GROUP) {
    758     0    stevel 		free(query.pq_io_buf);
    759     0    stevel 		pool_seterror(POE_DATASTORE);
    760     0    stevel 		return (PO_FAIL);
    761     0    stevel 	}
    762     0    stevel 	/*
    763     0    stevel 	 * Update the library snapshot
    764     0    stevel 	 */
    765     0    stevel 	psl.psl_changed = changed;
    766     0    stevel 	prov->pkc_lotime = prov->pkc_ltime;
    767     0    stevel 	if (load_group(conf, NULL, ep, &psl) != PO_SUCCESS) {
    768     0    stevel 		free(query.pq_io_buf);
    769     0    stevel 		ea_free_object(ep, EUP_NOALLOC);
    770     0    stevel 		return (PO_FAIL);
    771     0    stevel 	}
    772     0    stevel 
    773     0    stevel 	free(query.pq_io_buf);
    774     0    stevel 	ea_free_object(ep, EUP_NOALLOC);
    775     0    stevel 	/*
    776     0    stevel 	 * Now search the dictionary for items that must be removed because
    777     0    stevel 	 * they were neither created nor updated.
    778     0    stevel 	 */
    779     0    stevel 	if ((dead_map = dict_new((int (*)(const void *, const void *))
    780     0    stevel 	    pool_elem_compare, (uint64_t (*)(const void *))hash_id)) == NULL) {
    781     0    stevel 		pool_seterror(POE_SYSTEM);
    782     0    stevel 		return (PO_FAIL);
    783     0    stevel 	}
    784     0    stevel 	dict_map(prov->pkc_elements, find_dead_elems, dead_map);
    785     0    stevel 
    786     0    stevel 	if (dict_length(dead_map) > 0) {
    787     0    stevel 		dict_map(dead_map, remove_dead_elems, NULL);
    788     0    stevel 	}
    789     0    stevel 	dict_free(&dead_map);
    790     0    stevel 
    791     0    stevel 	return (PO_SUCCESS);
    792     0    stevel }
    793     0    stevel 
    794     0    stevel /*
    795     0    stevel  * Rely on the kernel to always keep a kernel configuration valid.
    796     0    stevel  * Returns PO_SUCCESS
    797     0    stevel  */
    798     0    stevel /* ARGSUSED */
    799     0    stevel int
    800     0    stevel pool_knl_validate(const pool_conf_t *conf, pool_valid_level_t level)
    801     0    stevel {
    802     0    stevel 	return ((conf->pc_state == POF_INVALID) ? PO_FAIL : PO_SUCCESS);
    803     0    stevel }
    804     0    stevel 
    805     0    stevel /*
    806     0    stevel  * Process all the outstanding transactions in the log. If the processing
    807     0    stevel  * fails, then attempt to rollback and "undo" the changes.
    808     0    stevel  */
    809     0    stevel int
    810     0    stevel pool_knl_commit(pool_conf_t *conf)
    811     0    stevel {
    812     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
    813     0    stevel 	int lock = 1;
    814     0    stevel 
    815     0    stevel 	/*
    816     0    stevel 	 * Lock the kernel state for the commit
    817     0    stevel 	 */
    818     0    stevel 	if (ioctl(prov->pkc_fd, POOL_COMMIT, lock) < 0) {
    819     0    stevel 		pool_seterror(POE_SYSTEM);
    820     0    stevel 		return (PO_FAIL);
    821     0    stevel 	}
    822     0    stevel 	lock = 0;
    823     0    stevel 	/*
    824     0    stevel 	 * If the state is LS_FAIL, then try to recover before
    825     0    stevel 	 * performing the commit.
    826     0    stevel 	 */
    827     0    stevel 	if (prov->pkc_log->l_state == LS_FAIL) {
    828     0    stevel 		if (pool_knl_recover(conf) == PO_FAIL) {
    829     0    stevel 			/*
    830     0    stevel 			 * Unlock the kernel state for the
    831     0    stevel 			 * commit. Assert that this * can't fail,
    832     0    stevel 			 * since if it ever does fail the library is
    833     0    stevel 			 * unusable.
    834     0    stevel 			 */
    835     0    stevel 			assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
    836     0    stevel 		}
    837     0    stevel 	}
    838     0    stevel 	/*
    839     0    stevel 	 * Commit the log
    840     0    stevel 	 */
    841     0    stevel 	if (log_walk(prov->pkc_log, log_item_commit) != PO_SUCCESS) {
    842     0    stevel 		(void) pool_knl_recover(conf);
    843     0    stevel 		/*
    844     0    stevel 		 * Unlock the kernel state for the commit. Assert that
    845     0    stevel 		 * this can't fail, since if it ever does fail the
    846     0    stevel 		 * library is unusable.
    847     0    stevel 		 */
    848     0    stevel 		assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
    849     0    stevel 		pool_seterror(POE_SYSTEM);
    850     0    stevel 		return (PO_FAIL);
    851     0    stevel 	}
    852     0    stevel 	/*
    853     0    stevel 	 * Unlock the kernel state for the commit. Assert that this
    854     0    stevel 	 * can't fail, since if it ever does fail the library is
    855     0    stevel 	 * unusable.
    856     0    stevel 	 */
    857     0    stevel 	assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
    858     0    stevel 	/*
    859     0    stevel 	 * Release the log resources
    860     0    stevel 	 */
    861     0    stevel 	(void) log_walk(prov->pkc_log, log_item_release);
    862     0    stevel 	log_empty(prov->pkc_log);
    863     0    stevel 	return (PO_SUCCESS);
    864     0    stevel }
    865     0    stevel 
    866     0    stevel /*
    867     0    stevel  * prop_build_cb() is designed to be called from
    868     0    stevel  * pool_walk_properties(). The property value is used to put an XML
    869     0    stevel  * property on the supplied ktx_node. This is an essential part of the
    870     0    stevel  * mechanism used to export a kernel configuration in libpool XML
    871     0    stevel  * form.
    872     0    stevel  */
    873     0    stevel /* ARGSUSED */
    874     0    stevel static int
    875     0    stevel prop_build_cb(pool_conf_t *UNUSED, pool_elem_t *pe, const char *name,
    876     0    stevel     pool_value_t *pval, void *user)
    877     0    stevel {
    878     0    stevel 	struct knl_to_xml *info = (struct knl_to_xml *)user;
    879     0    stevel 
    880     0    stevel 	return (pool_knl_put_xml_property((pool_elem_t *)pe, info->ktx_node,
    881     0    stevel 		name, pval));
    882     0    stevel }
    883     0    stevel 
    884     0    stevel /*
    885     0    stevel  * Duplicate some of the functionality from pool_xml_put_property()
    886     0    stevel  * (see pool_xml.c) to allow a kernel configuration to add XML nodes
    887     0    stevel  * to an XML tree which represents the kernel configuration. This is
    888     0    stevel  * an essential part of the mechanism used to export a kernel
    889     0    stevel  * configuration in libpool XML form.
    890     0    stevel  */
    891     0    stevel int
    892     0    stevel pool_knl_put_xml_property(pool_elem_t *pe, xmlNodePtr node, const char *name,
    893     0    stevel     const pool_value_t *val)
    894     0    stevel {
    895     0    stevel 
    896     0    stevel 	/*
    897     0    stevel 	 * "type" is a special attribute which is not visible ever outside of
    898     0    stevel 	 * libpool. Use the specific type accessor function.
    899     0    stevel 	 */
    900     0    stevel 	if (strcmp(name, c_type) == 0) {
    901     0    stevel 		return (pool_xml_set_attr(node, BAD_CAST name,
    902     0    stevel 		    val));
    903     0    stevel 	}
    904     0    stevel 	if (is_ns_property(pe, name) != NULL) {	/* in ns */
    905     0    stevel 		if (pool_xml_set_attr(node,
    906     0    stevel 		    BAD_CAST property_name_minus_ns(pe, name), val) == PO_FAIL)
    907     0    stevel 			return (pool_xml_set_prop(node, BAD_CAST name,
    908     0    stevel 			    val));
    909     0    stevel 	} else
    910     0    stevel 		return (pool_xml_set_prop(node, BAD_CAST name, val));
    911     0    stevel 	return (PO_SUCCESS);
    912     0    stevel }
    913     0    stevel 
    914     0    stevel /*
    915     0    stevel  * Export the kernel configuration as an XML file. The configuration
    916     0    stevel  * is used to build an XML document in memory. This document is then
    917     0    stevel  * saved to the supplied location.
    918     0    stevel  */
    919     0    stevel int
    920     0    stevel pool_knl_export(const pool_conf_t *conf, const char *location,
    921     0    stevel     pool_export_format_t fmt)
    922     0    stevel {
    923     0    stevel 	xmlNodePtr node_comment;
    924     0    stevel 	xmlNodePtr system;
    925     0    stevel 	int ret;
    926     0    stevel 	pool_t **ps;
    927     0    stevel 	pool_resource_t **rs;
    928     0    stevel 	uint_t nelem;
    929     0    stevel 	int i;
    930     0    stevel 	struct knl_to_xml info;
    931     0    stevel 	char_buf_t *cb = NULL;
    932     0    stevel 	xmlValidCtxtPtr cvp;
    933     0    stevel 
    934     0    stevel 	xml_init();
    935     0    stevel 
    936     0    stevel 
    937     0    stevel 	switch (fmt) {
    938     0    stevel 	case POX_NATIVE:
    939     0    stevel 		info.ktx_doc = xmlNewDoc(BAD_CAST "1.0");
    940     0    stevel 		xmlCreateIntSubset(info.ktx_doc, BAD_CAST "system",
    941     0    stevel 		    BAD_CAST "-//Sun Microsystems Inc//DTD Resource "
    942     0    stevel 		    "Management All//EN",
    943     0    stevel 		    BAD_CAST dtd_location);
    944     0    stevel 
    945     0    stevel 		if ((cvp = xmlNewValidCtxt()) == NULL) {
    946     0    stevel 			xmlFreeDoc(info.ktx_doc);
    947     0    stevel 			pool_seterror(POE_DATASTORE);
    948     0    stevel 			return (PO_FAIL);
    949     0    stevel 		}
    950     0    stevel 		/*
    951     0    stevel 		 * Call xmlValidateDocument() to force the parsing of
    952     0    stevel 		 * the DTD. Ignore errors and warning messages as we
    953     0    stevel 		 * know the document isn't valid.
    954     0    stevel 		 */
    955     0    stevel 		(void) xmlValidateDocument(cvp, info.ktx_doc);
    956     0    stevel 		xmlFreeValidCtxt(cvp);
    957     0    stevel 		if ((info.ktx_node = node_create(NULL, BAD_CAST "system")) ==
    958     0    stevel 		    NULL) {
    959     0    stevel 			xmlFreeDoc(info.ktx_doc);
    960     0    stevel 			pool_seterror(POE_DATASTORE);
    961     0    stevel 			return (PO_FAIL);
    962     0    stevel 		}
    963     0    stevel 
    964     0    stevel 		system = info.ktx_node;
    965     0    stevel 		info.ktx_doc->_private = (void *)conf;
    966     0    stevel 
    967     0    stevel 		xmlDocSetRootElement(info.ktx_doc, info.ktx_node);
    968     0    stevel 		xmlSetProp(info.ktx_node, BAD_CAST c_ref_id, BAD_CAST "dummy");
    969     0    stevel 		if ((node_comment = xmlNewDocComment(info.ktx_doc,
    970     0    stevel 		    BAD_CAST "\nConfiguration for pools facility. Do NOT"
    971     0    stevel 		    " edit this file by hand - use poolcfg(1)"
    972     0    stevel 		    " or libpool(3POOL) instead.\n")) == NULL) {
    973     0    stevel 			xmlFreeDoc(info.ktx_doc);
    974     0    stevel 			pool_seterror(POE_DATASTORE);
    975     0    stevel 			return (PO_FAIL);
    976     0    stevel 		}
    977     0    stevel 		if (xmlAddPrevSibling(info.ktx_node, node_comment) == NULL) {
    978     0    stevel 			xmlFree(node_comment);
    979     0    stevel 			xmlFreeDoc(info.ktx_doc);
    980     0    stevel 			pool_seterror(POE_DATASTORE);
    981     0    stevel 			return (PO_FAIL);
    982     0    stevel 		}
    983     0    stevel 		if (pool_walk_any_properties((pool_conf_t *)conf,
    984     0    stevel 		    pool_conf_to_elem(conf), &info, prop_build_cb, 1) ==
    985     0    stevel 		    PO_FAIL) {
    986     0    stevel 			xmlFreeDoc(info.ktx_doc);
    987     0    stevel 			return (PO_FAIL);
    988     0    stevel 		}
    989     0    stevel 		if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
    990     0    stevel 			xmlFreeDoc(info.ktx_doc);
    991     0    stevel 			return (PO_FAIL);
    992     0    stevel 		}
    993     0    stevel 		/*
    994     0    stevel 		 * Now add pool details
    995     0    stevel 		 */
    996     0    stevel 		if ((ps = pool_query_pools(conf, &nelem, NULL)) != NULL) {
    997     0    stevel 			for (i = 0; i < nelem; i++) {
    998     0    stevel 				pool_elem_t *elem = TO_ELEM(ps[i]);
    999     0    stevel 				uint_t nreselem;
   1000     0    stevel 				const char *sep = "";
   1001     0    stevel 				int j;
   1002     0    stevel 
   1003  3247  gjelinek 				if (elem_is_tmp(elem))
   1004  3247  gjelinek 					continue;
   1005  3247  gjelinek 
   1006     0    stevel 				if ((info.ktx_node = node_create(system,
   1007     0    stevel 				    BAD_CAST element_class_tags
   1008     0    stevel 				    [pool_elem_class(elem)])) == NULL) {
   1009     0    stevel 					free(ps);
   1010     0    stevel 					free_char_buf(cb);
   1011     0    stevel 					xmlFreeDoc(info.ktx_doc);
   1012     0    stevel 					pool_seterror(POE_DATASTORE);
   1013     0    stevel 					return (PO_FAIL);
   1014     0    stevel 				}
   1015     0    stevel 				if (pool_walk_any_properties(
   1016     0    stevel 				    (pool_conf_t *)conf,
   1017     0    stevel 				    elem, &info, prop_build_cb, 1) == PO_FAIL) {
   1018     0    stevel 					free(ps);
   1019     0    stevel 					free_char_buf(cb);
   1020     0    stevel 					xmlFreeDoc(info.ktx_doc);
   1021     0    stevel 					return (PO_FAIL);
   1022     0    stevel 				}
   1023     0    stevel 				/*
   1024     0    stevel 				 * TODO: pset specific res manipulation
   1025     0    stevel 				 */
   1026     0    stevel 				if ((rs = pool_query_pool_resources(conf, ps[i],
   1027     0    stevel 				    &nreselem, NULL)) == NULL) {
   1028     0    stevel 					free(ps);
   1029     0    stevel 					free_char_buf(cb);
   1030     0    stevel 					xmlFreeDoc(info.ktx_doc);
   1031     0    stevel 					pool_seterror(POE_INVALID_CONF);
   1032     0    stevel 					return (PO_FAIL);
   1033     0    stevel 				}
   1034     0    stevel 				if (set_char_buf(cb, "") == PO_FAIL) {
   1035     0    stevel 					free(rs);
   1036     0    stevel 					free(ps);
   1037     0    stevel 					free_char_buf(cb);
   1038     0    stevel 					xmlFreeDoc(info.ktx_doc);
   1039     0    stevel 					return (PO_FAIL);
   1040     0    stevel 				}
   1041     0    stevel 				for (j = 0; j < nreselem; j++) {
   1042     0    stevel 					pool_elem_t *reselem = TO_ELEM(rs[j]);
   1043     0    stevel 					if (append_char_buf(cb, "%s%s_%d", sep,
   1044     0    stevel 					    pool_elem_class_string(reselem),
   1045     0    stevel 					    (int)elem_get_sysid(reselem)) ==
   1046     0    stevel 					    PO_FAIL) {
   1047     0    stevel 						free(rs);
   1048     0    stevel 						free(ps);
   1049     0    stevel 						free_char_buf(cb);
   1050     0    stevel 						xmlFreeDoc(info.ktx_doc);
   1051     0    stevel 						return (PO_FAIL);
   1052     0    stevel 					}
   1053     0    stevel 					sep = " ";
   1054     0    stevel 				}
   1055     0    stevel 				free(rs);
   1056     0    stevel 				xmlSetProp(info.ktx_node, BAD_CAST "res",
   1057     0    stevel 				    BAD_CAST cb->cb_buf);
   1058     0    stevel 				if (set_char_buf(cb, "%s_%d",
   1059     0    stevel 				    pool_elem_class_string(elem),
   1060     0    stevel 				    (int)elem_get_sysid(elem)) == PO_FAIL) {
   1061     0    stevel 					free(ps);
   1062     0    stevel 					free_char_buf(cb);
   1063     0    stevel 					xmlFreeDoc(info.ktx_doc);
   1064     0    stevel 					return (PO_FAIL);
   1065     0    stevel 				}
   1066     0    stevel 				xmlSetProp(info.ktx_node, BAD_CAST c_ref_id,
   1067     0    stevel 				    BAD_CAST  cb->cb_buf);
   1068     0    stevel 			}
   1069     0    stevel 			free(ps);
   1070     0    stevel 		}
   1071     0    stevel 		/*
   1072     0    stevel 		 * Now add resource details (including components)
   1073     0    stevel 		 */
   1074     0    stevel 		if ((rs = pool_query_resources(conf, &nelem, NULL)) != NULL) {
   1075     0    stevel 			for (i = 0; i < nelem; i++) {
   1076     0    stevel 				pool_elem_t *elem = TO_ELEM(rs[i]);
   1077     0    stevel 				pool_component_t **cs = NULL;
   1078     0    stevel 				uint_t ncompelem;
   1079     0    stevel 				int j;
   1080  3247  gjelinek 
   1081  3247  gjelinek 				if (elem_is_tmp(elem))
   1082  3247  gjelinek 					continue;
   1083     0    stevel 
   1084     0    stevel 				if ((info.ktx_node = node_create(system,
   1085     0    stevel 				    BAD_CAST element_class_tags
   1086     0    stevel 				    [pool_elem_class(elem)])) == NULL) {
   1087     0    stevel 					free(rs);
   1088     0    stevel 					free_char_buf(cb);
   1089     0    stevel 					xmlFreeDoc(info.ktx_doc);
   1090     0    stevel 					pool_seterror(POE_DATASTORE);
   1091     0    stevel 					return (PO_FAIL);
   1092     0    stevel 				}
   1093     0    stevel 				if (pool_walk_any_properties(
   1094     0    stevel 				    (pool_conf_t *)conf,
   1095     0    stevel 				    elem, &info, prop_build_cb, 1) == PO_FAIL) {
   1096     0    stevel 					free(rs);
   1097     0    stevel 					free_char_buf(cb);
   1098     0    stevel 					xmlFreeDoc(info.ktx_doc);
   1099     0    stevel 					return (PO_FAIL);
   1100     0    stevel 				}
   1101     0    stevel 				if (set_char_buf(cb, "%s_%d",
   1102     0    stevel 				    pool_elem_class_string(elem),
   1103     0    stevel 				    (int)elem_get_sysid(elem)) == PO_FAIL) {
   1104     0    stevel 					free(rs);
   1105     0    stevel 					free_char_buf(cb);
   1106     0    stevel 					xmlFreeDoc(info.ktx_doc);
   1107     0    stevel 					return (PO_FAIL);
   1108     0    stevel 				}
   1109     0    stevel 				xmlSetProp(info.ktx_node, BAD_CAST c_ref_id,
   1110     0    stevel 				    BAD_CAST  cb->cb_buf);
   1111     0    stevel 				if ((cs = pool_query_resource_components(conf,
   1112     0    stevel 				    rs[i], &ncompelem, NULL)) != NULL) {
   1113     0    stevel 					xmlNodePtr resource = info.ktx_node;
   1114     0    stevel 
   1115     0    stevel 					for (j = 0; j < ncompelem; j++) {
   1116     0    stevel 						pool_elem_t *compelem =
   1117     0    stevel 						    TO_ELEM(cs[j]);
   1118     0    stevel 						if ((info.ktx_node =
   1119     0    stevel 						    node_create(resource,
   1120     0    stevel 						    BAD_CAST element_class_tags
   1121     0    stevel 						    [pool_elem_class(
   1122     0    stevel 						    compelem)])) == NULL) {
   1123     0    stevel 							pool_seterror(
   1124     0    stevel 							    POE_DATASTORE);
   1125     0    stevel 							free(rs);
   1126     0    stevel 							free(cs);
   1127     0    stevel 							free_char_buf(cb);
   1128     0    stevel 							xmlFreeDoc(info.
   1129     0    stevel 							    ktx_doc);
   1130     0    stevel 							return (PO_FAIL);
   1131     0    stevel 						}
   1132     0    stevel 						if (pool_walk_any_properties(
   1133     0    stevel 						    (pool_conf_t *)conf,
   1134     0    stevel 						    compelem, &info,
   1135     0    stevel 						    prop_build_cb, 1) ==
   1136     0    stevel 						    PO_FAIL) {
   1137     0    stevel 							free(rs);
   1138     0    stevel 							free(cs);
   1139     0    stevel 							free_char_buf(cb);
   1140     0    stevel 							xmlFreeDoc(info.
   1141     0    stevel 							    ktx_doc);
   1142     0    stevel 							return (PO_FAIL);
   1143     0    stevel 						}
   1144     0    stevel 						if (set_char_buf(cb, "%s_%d",
   1145     0    stevel 						    pool_elem_class_string(
   1146     0    stevel 						    compelem),
   1147     0    stevel 						    (int)elem_get_sysid(
   1148     0    stevel 						    compelem)) == PO_FAIL) {
   1149     0    stevel 							free(rs);
   1150     0    stevel 							free(cs);
   1151     0    stevel 							free_char_buf(cb);
   1152     0    stevel 							xmlFreeDoc(info.
   1153     0    stevel 							    ktx_doc);
   1154     0    stevel 							return (PO_FAIL);
   1155     0    stevel 						}
   1156     0    stevel 						xmlSetProp(info.ktx_node,
   1157     0    stevel 						    BAD_CAST c_ref_id,
   1158     0    stevel 						    BAD_CAST  cb->cb_buf);
   1159     0    stevel 					}
   1160     0    stevel 					free(cs);
   1161     0    stevel 				}
   1162     0    stevel 			}
   1163     0    stevel 			free(rs);
   1164     0    stevel 		}
   1165     0    stevel 		free_char_buf(cb);
   1166     0    stevel 		/*
   1167     0    stevel 		 * Set up the message handlers prior to calling
   1168     0    stevel 		 * xmlValidateDocument()
   1169     0    stevel 		 */
   1170     0    stevel 		if ((cvp = xmlNewValidCtxt()) == NULL) {
   1171     0    stevel 			xmlFreeDoc(info.ktx_doc);
   1172     0    stevel 			pool_seterror(POE_DATASTORE);
   1173     0    stevel 			return (PO_FAIL);
   1174     0    stevel 		}
   1175     0    stevel 		cvp->error    = pool_error_func;
   1176     0    stevel 		cvp->warning  = pool_error_func;
   1177     0    stevel 		if (xmlValidateDocument(cvp, info.ktx_doc) == 0) {
   1178     0    stevel 			xmlFreeValidCtxt(cvp);
   1179     0    stevel 			xmlFreeDoc(info.ktx_doc);
   1180     0    stevel 			pool_seterror(POE_INVALID_CONF);
   1181     0    stevel 			return (PO_FAIL);
   1182     0    stevel 		}
   1183     0    stevel 		xmlFreeValidCtxt(cvp);
   1184     0    stevel 		ret = xmlSaveFormatFile(location, info.ktx_doc, 1);
   1185     0    stevel 		xmlFreeDoc(info.ktx_doc);
   1186     0    stevel 		if (ret == -1) {
   1187     0    stevel 			pool_seterror(POE_SYSTEM);
   1188     0    stevel 			return (PO_FAIL);
   1189     0    stevel 		}
   1190     0    stevel 		return (PO_SUCCESS);
   1191     0    stevel 	default:
   1192     0    stevel 		pool_seterror(POE_BADPARAM);
   1193     0    stevel 		return (PO_FAIL);
   1194     0    stevel 	}
   1195     0    stevel }
   1196     0    stevel 
   1197     0    stevel /*
   1198     0    stevel  * Rollback the changes to the kernel
   1199     0    stevel  */
   1200     0    stevel int
   1201     0    stevel pool_knl_recover(pool_conf_t *conf)
   1202     0    stevel {
   1203     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
   1204     0    stevel 
   1205     0    stevel 	prov->pkc_log->l_state = LS_RECOVER;
   1206     0    stevel 	if (log_reverse_walk(prov->pkc_log, log_item_undo) != PO_SUCCESS) {
   1207     0    stevel 		dprintf("Library configuration consistency error\n");
   1208     0    stevel 		prov->pkc_log->l_state = LS_FAIL;
   1209     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1210     0    stevel 		return (PO_FAIL);
   1211     0    stevel 	}
   1212     0    stevel 	prov->pkc_log->l_state = LS_DO;
   1213     0    stevel 	return (PO_SUCCESS);
   1214     0    stevel }
   1215     0    stevel 
   1216     0    stevel /*
   1217     0    stevel  * Rollback the changes to the configuration
   1218     0    stevel  */
   1219     0    stevel int
   1220     0    stevel pool_knl_rollback(pool_conf_t *conf)
   1221     0    stevel {
   1222     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
   1223     0    stevel 
   1224     0    stevel 	prov->pkc_log->l_state = LS_UNDO;
   1225     0    stevel 	if (log_reverse_walk(prov->pkc_log, log_item_undo) != PO_SUCCESS) {
   1226     0    stevel 		dprintf("Kernel configuration consistency error\n");
   1227     0    stevel 		(void) log_walk(prov->pkc_log, log_item_release);
   1228     0    stevel 		log_empty(prov->pkc_log);
   1229     0    stevel 		prov->pkc_log->l_state = LS_FAIL;
   1230     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1231     0    stevel 		return (PO_FAIL);
   1232     0    stevel 	}
   1233     0    stevel 	(void) log_walk(prov->pkc_log, log_item_release);
   1234     0    stevel 	log_empty(prov->pkc_log);
   1235     0    stevel 	prov->pkc_log->l_state = LS_DO;
   1236     0    stevel 	return (PO_SUCCESS);
   1237     0    stevel }
   1238     0    stevel 
   1239     0    stevel /*
   1240     0    stevel  * Callback used to build the result set for a query. Each invocation will
   1241     0    stevel  * supply a candidate element for inclusion. The element is filtered by:
   1242     0    stevel  * - class
   1243     0    stevel  * - properties
   1244     0    stevel  * If the element "matches" the target, then it is added to the result
   1245     0    stevel  * set, otherwise it is ignored.
   1246     0    stevel  */
   1247     0    stevel /* ARGSUSED1 */
   1248     0    stevel static void
   1249     0    stevel build_result_set(const void *key, void **value, void *cl)
   1250     0    stevel {
   1251     0    stevel 	struct query_obj *qo = (struct query_obj *)cl;
   1252     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
   1253     0    stevel 
   1254     0    stevel 	/*
   1255     0    stevel 	 * Check to see if it's the right class of element
   1256     0    stevel 	 */
   1257     0    stevel 	if (qo->classes & (1 << pool_elem_class((pool_elem_t *)key))) {
   1258     0    stevel 		int i;
   1259     0    stevel 		/*
   1260     0    stevel 		 * Now check to see if the src element is correct. If no src
   1261     0    stevel 		 * element is supplied, ignore this check
   1262     0    stevel 		 */
   1263     0    stevel 		if (qo->src) {
   1264     0    stevel 			pool_knl_elem_t *parent;
   1265     0    stevel 
   1266     0    stevel 			for (parent = pke; parent != NULL;
   1267     0    stevel 			    parent = parent->pke_parent) {
   1268     0    stevel 				if (parent == (pool_knl_elem_t *)qo->src)
   1269     0    stevel 					break;
   1270     0    stevel 			}
   1271     0    stevel 			if (parent == NULL)
   1272     0    stevel 				return;
   1273     0    stevel 		}
   1274     0    stevel 		/*
   1275     0    stevel 		 * Now check for property matches (if there are any specified)
   1276     0    stevel 		 */
   1277     0    stevel 		if (qo->props) {
   1278     0    stevel 			int matched = PO_TRUE;
   1279     0    stevel 			for (i = 0; qo->props[i] != NULL; i++) {
   1280     0    stevel 				pool_value_t val = POOL_VALUE_INITIALIZER;
   1281     0    stevel 
   1282     0    stevel 				if (pool_get_property(TO_CONF(TO_ELEM(pke)),
   1283     0    stevel 				    (pool_elem_t *)pke,
   1284     0    stevel 				    pool_value_get_name(qo->props[i]), &val) ==
   1285     0    stevel 				    POC_INVAL) {
   1286     0    stevel 					matched = PO_FALSE;
   1287     0    stevel 					break;
   1288     0    stevel 				} else {
   1289     0    stevel 					if (pool_value_equal(qo->props[i],
   1290     0    stevel 					    &val) != PO_TRUE) {
   1291     0    stevel 						matched = PO_FALSE;
   1292     0    stevel 						break;
   1293     0    stevel 					}
   1294     0    stevel 				}
   1295     0    stevel 			}
   1296     0    stevel 			if (matched == PO_TRUE)
   1297     0    stevel 				(void) pool_knl_result_set_append(qo->rs,
   1298     0    stevel 				(pool_knl_elem_t *)key);
   1299     0    stevel 		} else {
   1300     0    stevel 			(void) pool_knl_result_set_append(qo->rs,
   1301     0    stevel 			    (pool_knl_elem_t *)key);
   1302     0    stevel 		}
   1303     0    stevel 	}
   1304     0    stevel }
   1305     0    stevel 
   1306     0    stevel /*
   1307     0    stevel  * Execute the supplied query and return a result set which contains
   1308     0    stevel  * all qualifying elements.
   1309     0    stevel  */
   1310     0    stevel pool_result_set_t *
   1311     0    stevel pool_knl_exec_query(const pool_conf_t *conf, const pool_elem_t *src,
   1312     0    stevel     const char *src_attr, pool_elem_class_t classes, pool_value_t **props)
   1313     0    stevel {
   1314     0    stevel 	pool_knl_result_set_t *rs;
   1315     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
   1316     0    stevel 	struct query_obj qo;
   1317     0    stevel 	int matched = PO_TRUE;
   1318     0    stevel 
   1319     0    stevel 	/*
   1320     0    stevel 	 * Have a buffer at this point, that we can use
   1321     0    stevel 	 */
   1322     0    stevel 	if ((rs = pool_knl_result_set_alloc(conf)) == NULL) {
   1323     0    stevel 		return (NULL);
   1324     0    stevel 	}
   1325     0    stevel 	qo.conf = conf;
   1326     0    stevel 	qo.src = src;
   1327     0    stevel 	qo.src_attr = src_attr;
   1328     0    stevel 	qo.classes = classes;
   1329     0    stevel 	qo.props = props;
   1330     0    stevel 	qo.rs = rs;
   1331     0    stevel 	if (src_attr != NULL) {
   1332     0    stevel 		pool_knl_pool_t *pkp = (pool_knl_pool_t *)src;
   1333     0    stevel 
   1334     0    stevel 		/*
   1335     0    stevel 		 * Note: This logic is resource specific and must be
   1336     0    stevel 		 * extended for additional resource types.
   1337     0    stevel 		 */
   1338     0    stevel 		/*
   1339     0    stevel 		 * Check for property matches (if there are any specified)
   1340     0    stevel 		 */
   1341     0    stevel 		if (props) {
   1342     0    stevel 			int i;
   1343     0    stevel 
   1344     0    stevel 			for (i = 0; props[i] != NULL; i++) {
   1345     0    stevel 				pool_value_t val = POOL_VALUE_INITIALIZER;
   1346     0    stevel 
   1347     0    stevel 				if (pool_get_property(conf,
   1348     0    stevel 				    (pool_elem_t *)pkp->pkp_assoc[PREC_PSET],
   1349     0    stevel 				    pool_value_get_name(props[i]), &val) ==
   1350     0    stevel 				    POC_INVAL) {
   1351     0    stevel 					matched = PO_FALSE;
   1352     0    stevel 					break;
   1353     0    stevel 				} else {
   1354     0    stevel 					if (pool_value_equal(props[i],
   1355     0    stevel 					    &val) != PO_TRUE) {
   1356     0    stevel 						matched = PO_FALSE;
   1357     0    stevel 						break;
   1358     0    stevel 					}
   1359     0    stevel 				}
   1360     0    stevel 			}
   1361     0    stevel 		}
   1362     0    stevel 
   1363     0    stevel 		if (matched == PO_TRUE)
   1364     0    stevel 			(void) pool_knl_result_set_append(rs,
   1365     0    stevel 			    (pool_knl_elem_t *)pkp->pkp_assoc[PREC_PSET]);
   1366     0    stevel 	} else
   1367     0    stevel 		dict_map(prov->pkc_elements, build_result_set, &qo);
   1368     0    stevel 
   1369  1042   garypen 	if (rs->pkr_count == 0)
   1370  1042   garypen 		pool_seterror(POE_INVALID_SEARCH);
   1371     0    stevel 	return ((pool_result_set_t *)rs);
   1372     0    stevel }
   1373     0    stevel 
   1374     0    stevel /*
   1375     0    stevel  * Callback function intended to be used from pool_walk_pools(). If
   1376     0    stevel  * the supplied pool is not the default pool attempt to destroy it.
   1377     0    stevel  */
   1378     0    stevel /*ARGSUSED*/
   1379     0    stevel static int
   1380     0    stevel destroy_pool_cb(pool_conf_t *conf, pool_t *pool, void *unused)
   1381     0    stevel {
   1382     0    stevel 	if (elem_is_default(TO_ELEM(pool)) != PO_TRUE)
   1383     0    stevel 		return (pool_destroy(conf, pool));
   1384     0    stevel 	/*
   1385     0    stevel 	 * Return PO_SUCCESS even though we don't delete the default
   1386     0    stevel 	 * pool so that the walk continues
   1387     0    stevel 	 */
   1388     0    stevel 	return (PO_SUCCESS);
   1389     0    stevel }
   1390     0    stevel 
   1391     0    stevel /*
   1392     0    stevel  * Remove the configuration details. This means remove all elements
   1393     0    stevel  * apart from the system elements.
   1394     0    stevel  */
   1395     0    stevel int
   1396     0    stevel pool_knl_remove(pool_conf_t *conf)
   1397     0    stevel {
   1398     0    stevel 	uint_t i, nelem;
   1399     0    stevel 	pool_resource_t **resources;
   1400     0    stevel 
   1401     0    stevel 	conf->pc_state = POF_DESTROY;
   1402     0    stevel 	if ((resources = pool_query_resources(conf, &nelem, NULL)) != NULL) {
   1403     0    stevel 		for (i = 0; i < nelem; i++) {
   1404     0    stevel 			if (resource_is_system(resources[i]) == PO_FALSE)
   1405     0    stevel 				if (pool_resource_destroy(conf, resources[i]) !=
   1406     0    stevel 				    PO_SUCCESS) {
   1407     0    stevel 					pool_seterror(POE_INVALID_CONF);
   1408     0    stevel 					return (PO_FAIL);
   1409     0    stevel 				}
   1410     0    stevel 		}
   1411     0    stevel 		free(resources);
   1412     0    stevel 	}
   1413     0    stevel 	(void) pool_walk_pools(conf, conf, destroy_pool_cb);
   1414     0    stevel 	if (pool_conf_commit(conf, PO_FALSE) != PO_SUCCESS)
   1415     0    stevel 		return (PO_FAIL);
   1416     0    stevel 
   1417     0    stevel 	if (pool_conf_close(conf) != PO_SUCCESS)
   1418     0    stevel 		return (PO_FAIL);
   1419     0    stevel 
   1420     0    stevel 	return (PO_SUCCESS);
   1421     0    stevel }
   1422     0    stevel 
   1423     0    stevel /*
   1424     0    stevel  * Determine the name of the pool to which the supplied pid is
   1425     0    stevel  * bound. If it cannot be determined return NULL.
   1426     0    stevel  */
   1427     0    stevel char *
   1428     0    stevel pool_knl_get_binding(pool_conf_t *conf, pid_t pid)
   1429     0    stevel {
   1430     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
   1431     0    stevel 	const char *sval;
   1432     0    stevel 	char *name = NULL;
   1433     0    stevel 	pool_bindq_t bindq;
   1434     0    stevel 	pool_value_t *props[] = { NULL, NULL };
   1435     0    stevel 	uint_t nelem = 0;
   1436     0    stevel 	pool_t **pools;
   1437     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   1438     0    stevel 
   1439     0    stevel 	props[0] = &val;
   1440     0    stevel 
   1441     0    stevel 	bindq.pb_o_id_type = P_PID;
   1442     0    stevel 	bindq.pb_o_id = pid;
   1443     0    stevel 	if (ioctl(prov->pkc_fd, POOL_BINDQ, &bindq) < 0) {
   1444     0    stevel 		pool_seterror(POE_SYSTEM);
   1445     0    stevel 		return (NULL);
   1446     0    stevel 	}
   1447     0    stevel 
   1448     0    stevel 	if (pool_value_set_name(props[0], "pool.sys_id") != PO_SUCCESS) {
   1449     0    stevel 		return (NULL);
   1450     0    stevel 	}
   1451     0    stevel 	pool_value_set_int64(props[0], bindq.pb_i_id);
   1452     0    stevel 	if ((pools = pool_query_pools(conf, &nelem, props)) == NULL) {
   1453     0    stevel 		pool_seterror(POE_BADPARAM);
   1454     0    stevel 		return (NULL);
   1455     0    stevel 	}
   1456     0    stevel 
   1457     0    stevel 	if (nelem != 1) {
   1458     0    stevel 		free(pools);
   1459     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1460     0    stevel 		return (NULL);
   1461     0    stevel 	}
   1462     0    stevel 	if (pool_get_ns_property(TO_ELEM(pools[0]), c_name, props[0])
   1463     0    stevel 	    == POC_INVAL) {
   1464     0    stevel 		free(pools);
   1465     0    stevel 		return (NULL);
   1466     0    stevel 	}
   1467     0    stevel 	if (pool_value_get_string(props[0], &sval) != PO_SUCCESS) {
   1468     0    stevel 		free(pools);
   1469     0    stevel 		return (NULL);
   1470     0    stevel 	}
   1471     0    stevel 	if ((name = strdup(sval)) == NULL) {
   1472     0    stevel 		free(pools);
   1473     0    stevel 		pool_seterror(POE_SYSTEM);
   1474     0    stevel 		return (NULL);
   1475     0    stevel 	}
   1476     0    stevel 	return (name);
   1477     0    stevel }
   1478     0    stevel 
   1479     0    stevel /*
   1480     0    stevel  * Bind idtype id to the pool name.
   1481     0    stevel  */
   1482     0    stevel int
   1483     0    stevel pool_knl_set_binding(pool_conf_t *conf, const char *pool_name, idtype_t idtype,
   1484     0    stevel     id_t id)
   1485     0    stevel {
   1486     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
   1487     0    stevel 	pool_bind_t bind;
   1488     0    stevel 	pool_t *pool;
   1489     0    stevel 	int ret;
   1490     0    stevel 
   1491     0    stevel 	if ((pool = pool_get_pool(conf, pool_name)) == NULL)
   1492     0    stevel 		return (PO_FAIL);
   1493     0    stevel 
   1494     0    stevel 	bind.pb_o_id_type = idtype;
   1495     0    stevel 	bind.pb_o_id = id;
   1496     0    stevel 	bind.pb_o_pool_id = elem_get_sysid(TO_ELEM(pool));
   1497     0    stevel 
   1498     0    stevel 	while ((ret = ioctl(prov->pkc_fd, POOL_BIND, &bind)) < 0 &&
   1499     0    stevel 	    errno == EAGAIN);
   1500     0    stevel 	if (ret < 0) {
   1501     0    stevel 		pool_seterror(POE_SYSTEM);
   1502     0    stevel 		return (PO_FAIL);
   1503     0    stevel 	}
   1504     0    stevel 	return (PO_SUCCESS);
   1505     0    stevel }
   1506     0    stevel 
   1507     0    stevel /*
   1508     0    stevel  * pool_knl_get_resource_binding() returns the binding for a pid to
   1509     0    stevel  * the supplied type of resource. If a binding cannot be determined,
   1510     0    stevel  * NULL is returned.
   1511     0    stevel  */
   1512     0    stevel char *
   1513     0    stevel pool_knl_get_resource_binding(pool_conf_t *conf,
   1514     0    stevel     pool_resource_elem_class_t type, pid_t pid)
   1515     0    stevel {
   1516     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
   1517     0    stevel 	const char *sval;
   1518     0    stevel 	char *name = NULL;
   1519     0    stevel 	pool_bindq_t bindq;
   1520     0    stevel 	pool_value_t *props[] = { NULL, NULL };
   1521     0    stevel 	uint_t nelem = 0;
   1522     0    stevel 	pool_t **pools;
   1523     0    stevel 	pool_resource_t **resources;
   1524     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   1525     0    stevel 
   1526     0    stevel 	props[0] = &val;
   1527     0    stevel 	bindq.pb_o_id_type = P_PID;
   1528     0    stevel 	bindq.pb_o_id = pid;
   1529     0    stevel 	if (ioctl(prov->pkc_fd, POOL_BINDQ, &bindq) < 0) {
   1530     0    stevel 		pool_seterror(POE_SYSTEM);
   1531     0    stevel 		return (NULL);
   1532     0    stevel 	}
   1533     0    stevel 
   1534     0    stevel 	if (pool_value_set_name(props[0], "pool.sys_id") != PO_SUCCESS) {
   1535     0    stevel 		return (NULL);
   1536     0    stevel 	}
   1537     0    stevel 	pool_value_set_int64(props[0], bindq.pb_i_id);
   1538     0    stevel 	if ((pools = pool_query_pools(conf, &nelem, props)) == NULL) {
   1539     0    stevel 		pool_seterror(POE_BADPARAM);
   1540     0    stevel 		return (NULL);
   1541     0    stevel 	}
   1542     0    stevel 
   1543     0    stevel 	if (nelem != 1) {
   1544     0    stevel 		free(pools);
   1545     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1546     0    stevel 		return (NULL);
   1547     0    stevel 	}
   1548     0    stevel 
   1549     0    stevel 	if (pool_value_set_string(props[0], pool_resource_type_string(type)) !=
   1550     0    stevel 	    PO_SUCCESS ||
   1551     0    stevel 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS) {
   1552     0    stevel 		free(pools);
   1553     0    stevel 		return (NULL);
   1554     0    stevel 	}
   1555     0    stevel 
   1556     0    stevel 	if ((resources = pool_query_pool_resources(conf, pools[0], &nelem,
   1557     0    stevel 	    NULL)) == NULL) {
   1558     0    stevel 		free(pools);
   1559     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1560     0    stevel 		return (NULL);
   1561     0    stevel 	}
   1562     0    stevel 	free(pools);
   1563     0    stevel 	if (nelem != 1) {
   1564     0    stevel 		free(resources);
   1565     0    stevel 		pool_seterror(POE_INVALID_CONF);
   1566     0    stevel 		return (NULL);
   1567     0    stevel 	}
   1568     0    stevel 	if (pool_get_ns_property(TO_ELEM(resources[0]), c_name, props[0]) ==
   1569     0    stevel 	    POC_INVAL) {
   1570     0    stevel 		free(resources);
   1571     0    stevel 		return (NULL);
   1572     0    stevel 	}
   1573     0    stevel 	free(resources);
   1574     0    stevel 	if (pool_value_get_string(props[0], &sval) != PO_SUCCESS) {
   1575     0    stevel 		return (NULL);
   1576     0    stevel 	}
   1577     0    stevel 	if ((name = strdup(sval)) == NULL) {
   1578     0    stevel 		pool_seterror(POE_SYSTEM);
   1579     0    stevel 		return (NULL);
   1580     0    stevel 	}
   1581     0    stevel 	return (name);
   1582     0    stevel }
   1583     0    stevel 
   1584     0    stevel /*
   1585     0    stevel  * Allocate the required library data structure and initialise it.
   1586     0    stevel  */
   1587     0    stevel pool_knl_elem_t *
   1588     0    stevel pool_knl_elem_wrap(pool_conf_t *conf, pool_elem_class_t class,
   1589     0    stevel     pool_resource_elem_class_t res_class,
   1590     0    stevel     pool_component_elem_class_t comp_class)
   1591     0    stevel {
   1592     0    stevel 	pool_knl_elem_t *elem;
   1593     0    stevel 	pool_elem_t *pe;
   1594     0    stevel 
   1595     0    stevel 	switch (class) {
   1596     0    stevel 	case PEC_SYSTEM:
   1597     0    stevel 		if ((elem = malloc(sizeof (pool_knl_system_t))) == NULL) {
   1598     0    stevel 			pool_seterror(POE_SYSTEM);
   1599     0    stevel 			return (NULL);
   1600     0    stevel 		}
   1601     0    stevel 		(void) memset(elem, 0, sizeof (pool_knl_system_t));
   1602     0    stevel 		break;
   1603     0    stevel 	case PEC_POOL:
   1604     0    stevel 		if ((elem = malloc(sizeof (pool_knl_pool_t))) == NULL) {
   1605     0    stevel 			pool_seterror(POE_SYSTEM);
   1606     0    stevel 			return (NULL);
   1607     0    stevel 		}
   1608     0    stevel 		(void) memset(elem, 0, sizeof (pool_knl_pool_t));
   1609     0    stevel 		break;
   1610     0    stevel 	case PEC_RES_COMP:
   1611     0    stevel 	case PEC_RES_AGG:
   1612     0    stevel 		if ((elem = malloc(sizeof (pool_knl_resource_t))) == NULL) {
   1613     0    stevel 			pool_seterror(POE_SYSTEM);
   1614     0    stevel 			return (NULL);
   1615     0    stevel 		}
   1616     0    stevel 		(void) memset(elem, 0, sizeof (pool_knl_resource_t));
   1617     0    stevel 		break;
   1618     0    stevel 	case PEC_COMP:
   1619     0    stevel 		if ((elem = malloc(sizeof (pool_knl_component_t))) == NULL) {
   1620     0    stevel 			pool_seterror(POE_SYSTEM);
   1621     0    stevel 			return (NULL);
   1622     0    stevel 		}
   1623     0    stevel 		(void) memset(elem, 0, sizeof (pool_knl_component_t));
   1624     0    stevel 		break;
   1625     0    stevel 	default:
   1626     0    stevel 		pool_seterror(POE_BADPARAM);
   1627     0    stevel 		return (NULL);
   1628     0    stevel 	}
   1629     0    stevel 	pe = TO_ELEM(elem);
   1630     0    stevel 	pe->pe_conf = conf;
   1631     0    stevel 	pe->pe_class = class;
   1632     0    stevel 	pe->pe_resource_class = res_class;
   1633     0    stevel 	pe->pe_component_class = comp_class;
   1634     0    stevel 	/* Set up the function pointers for element manipulation */
   1635     0    stevel 	pe->pe_get_prop = pool_knl_get_property;
   1636     0    stevel 	pe->pe_put_prop = pool_knl_put_property;
   1637     0    stevel 	pe->pe_rm_prop = pool_knl_rm_property;
   1638     0    stevel 	pe->pe_get_props = pool_knl_get_properties;
   1639     0    stevel 	pe->pe_remove = pool_knl_elem_remove;
   1640     0    stevel 	pe->pe_get_container = pool_knl_get_container;
   1641     0    stevel 	pe->pe_set_container = pool_knl_set_container;
   1642     0    stevel 	/*
   1643     0    stevel 	 * Specific initialisation for different types of element
   1644     0    stevel 	 */
   1645     0    stevel 	if (class == PEC_POOL) {
   1646     0    stevel 		pool_knl_pool_t *pp = (pool_knl_pool_t *)elem;
   1647     0    stevel 		pp->pp_associate = pool_knl_pool_associate;
   1648     0    stevel 		pp->pp_dissociate = pool_knl_pool_dissociate;
   1649     0    stevel 		pp->pkp_assoc[PREC_PSET] = (pool_knl_resource_t *)
   1650     0    stevel 		    resource_by_sysid(conf, PS_NONE, "pset");
   1651     0    stevel 	}
   1652     0    stevel 	if (class == PEC_RES_COMP || class == PEC_RES_AGG) {
   1653     0    stevel 		pool_knl_resource_t *pr = (pool_knl_resource_t *)elem;
   1654     0    stevel 		pr->pr_is_system = pool_knl_resource_is_system;
   1655     0    stevel 		pr->pr_can_associate = pool_knl_resource_can_associate;
   1656     0    stevel 	}
   1657     0    stevel #if DEBUG
   1658     0    stevel 	if (dict_put(((pool_knl_connection_t *)conf->pc_prov)->pkc_leaks,
   1659     0    stevel 	    elem, elem) != NULL)
   1660     0    stevel 		assert(!"leak map put failed");
   1661     0    stevel 	dprintf("allocated %p\n", elem);
   1662     0    stevel #endif	/* DEBUG */
   1663     0    stevel 	return (elem);
   1664     0    stevel }
   1665     0    stevel 
   1666     0    stevel /*
   1667     0    stevel  * Allocate a new pool_knl_elem_t in the supplied configuration of the
   1668     0    stevel  * specified class.
   1669     0    stevel  * Returns element pointer/NULL
   1670     0    stevel  */
   1671     0    stevel pool_elem_t *
   1672     0    stevel pool_knl_elem_create(pool_conf_t *conf, pool_elem_class_t class,
   1673     0    stevel     pool_resource_elem_class_t res_class,
   1674     0    stevel     pool_component_elem_class_t comp_class)
   1675     0    stevel {
   1676     0    stevel 	pool_knl_elem_t *elem;
   1677     0    stevel 	pool_create_undo_t *create;
   1678     0    stevel 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
   1679     0    stevel 	static int id = -3;
   1680     0    stevel 	char_buf_t *cb;
   1681     0    stevel 
   1682     0    stevel 	if ((elem = pool_knl_elem_wrap(conf, class, res_class, comp_class)) ==
   1683     0    stevel 	    NULL)
   1684     0    stevel 		return (NULL);
   1685     0    stevel 
   1686     0    stevel 	/*
   1687     0    stevel 	 * Allocate an nvlist to hold properties
   1688     0    stevel 	 */
   1689     0    stevel 	if (nvlist_alloc(&elem->pke_properties, NV_UNIQUE_NAME_TYPE, 0) != 0) {
   1690     0    stevel 		pool_knl_elem_free(elem, PO_FALSE);
   1691     0    stevel 		pool_seterror(POE_SYSTEM);
   1692     0    stevel 		return (NULL);
   1693     0    stevel 	}
   1694     0    stevel 	/*
   1695     0    stevel 	 * Allocate a temporary ID and name until the element is
   1696     0    stevel 	 * created for real
   1697     0    stevel 	 */
   1698     0    stevel 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
   1699     0    stevel 		pool_knl_elem_free(elem, PO_TRUE);
   1700     0    stevel 		return (NULL);
   1701     0    stevel 	}
   1702     0    stevel 	if (set_char_buf(cb, "%s.sys_id",
   1703     0    stevel 	    pool_elem_class_string((pool_elem_t *)elem)) != PO_SUCCESS) {
   1704     0    stevel 		pool_knl_elem_free(elem, PO_TRUE);
   1705     0    stevel 		free_char_buf(cb);
   1706     0    stevel 		return (NULL);
   1707     0    stevel 	}
   1708     0    stevel 	(void) nvlist_add_int64(elem->pke_properties, cb->cb_buf, id--);
   1709     0    stevel 	if (set_char_buf(cb, "%s.name",
   1710     0    stevel 	    pool_elem_class_string((pool_elem_t *)elem)) != PO_SUCCESS) {
   1711     0    stevel 		pool_knl_elem_free(elem, PO_TRUE);
   1712     0    stevel 		free_char_buf(cb);
   1713     0    stevel 		return (NULL);
   1714     0    stevel 	}
   1715     0    stevel 	(void) nvlist_add_string(elem->pke_properties, cb->cb_buf, "");
   1716     0    stevel 	/*
   1717     0    stevel 	 * If it's a resource class, it will need an initial size
   1718     0    stevel 	 */
   1719     0    stevel 	if (class == PEC_RES_COMP || class == PEC_RES_AGG) {
   1720     0    stevel 		if (set_char_buf(cb, "%s.size",
   1721     0    stevel 		    pool_elem_class_string((pool_elem_t *)elem)) !=
   1722     0    stevel 		    PO_SUCCESS) {
   1723     0    stevel 			pool_knl_elem_free(elem, PO_TRUE);
   1724     0    stevel 			free_char_buf(cb);
   1725     0    stevel 			return (NULL);
   1726     0    stevel 		}
   1727     0    stevel 		(void) nvlist_add_uint64(elem->pke_properties, cb->cb_buf, 0);
   1728     0    stevel 	}
   1729     0    stevel 	free_char_buf(cb);
   1730     0    stevel 
   1731     0    stevel 	/*
   1732     0    stevel 	 * Register the newly created element
   1733     0    stevel 	 */
   1734     0    stevel 	if (dict_put(prov->pkc_elements, elem, elem) != NULL) {
   1735     0    stevel 		pool_knl_elem_free(elem, PO_TRUE);
   1736     0    stevel 		pool_seterror(POE_SYSTEM);
   1737     0    stevel 		return (NULL);
   1738     0    stevel 	}
   1739     0    stevel 
   1740     0    stevel 	if (prov->pkc_log->l_state != LS_DO)
   1741     0    stevel 		return ((pool_elem_t *)elem);
   1742     0    stevel 
   1743     0    stevel 	/*
   1744     0    stevel 	 * The remaining logic is setting up the arguments for the
   1745     0    stevel 	 * POOL_CREATE ioctl and appending the details into the log.
   1746     0    stevel 	 */
   1747     0    stevel 	if ((create = malloc(sizeof (pool_create_undo_t))) == NULL) {
   1748     0    stevel 		pool_seterror(POE_SYSTEM);
   1749     0    stevel 		return (NULL);
   1750     0    stevel 	}
   1751     0    stevel 	create->pcu_ioctl.pc_o_type = class;
   1752     0    stevel 	switch (class) {
   1753     0    stevel 	case PEC_SYSTEM:
   1754     0    stevel 		pool_seterror(POE_BADPARAM);
   1755     0    stevel 		free(create);
   1756     0    stevel 		return (NULL);
   1757     0    stevel 	case PEC_POOL: /* NO-OP */
   1758     0    stevel 		break;
   1759     0    stevel 	case PEC_RES_COMP:
   1760     0    stevel 	case PEC_RES_AGG:
   1761     0    stevel 		create->pcu_ioctl.pc_o_sub_type = res_class;
   1762     0    stevel 		break;
   1763     0    stevel 	case PEC_COMP:
   1764     0    stevel 		create->pcu_ioctl.pc_o_sub_type = comp_class;
   1765     0    stevel 		break;
   1766     0    stevel 	default:
   1767     0    stevel 		pool_seterror(POE_BADPARAM);
   1768     0    stevel 		free(create);
   1769     0    stevel 		return (NULL);
   1770     0    stevel 	}
   1771     0    stevel 
   1772     0    stevel 	create->pcu_elem = (pool_elem_t *)elem;
   1773     0    stevel 
   1774     0    stevel 	if (log_append(prov->pkc_log, POOL_CREATE, (void *)create) !=
   1775     0    stevel 	    PO_SUCCESS) {
   1776     0    stevel 		free(create);
   1777     0    stevel 		return (NULL);
   1778     0    stevel 	}
   1779     0    stevel 	return ((pool_elem_t *)elem);
   1780     0    stevel }
   1781     0    stevel 
   1782     0    stevel /*
   1783     0    stevel  * Remove the details of the element from our userland copy and destroy
   1784     0    stevel  * the element (if appropriate) in the kernel.
   1785     0    stevel  */
   1786     0    stevel int
   1787     0    stevel pool_knl_elem_remove(pool_elem_t *pe)
   1788     0    stevel {
   1789     0    stevel 	pool_knl_connection_t *prov;
   1790     0    stevel 	pool_destroy_undo_t *destroy;
   1791     0    stevel 
   1792     0    stevel 	prov = (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
   1793     0    stevel 
   1794     0    stevel 	if (dict_remove(prov->pkc_elements, pe) == NULL) {
   1795     0    stevel 		pool_seterror(POE_SYSTEM);
   1796     0    stevel 		return (PO_FAIL);
   1797     0    stevel 	}
   1798     0    stevel 	if (prov->pkc_log->l_state != LS_DO) {
   1799     0    stevel 		return (PO_SUCCESS);
   1800     0    stevel 	}
   1801     0    stevel 
   1802     0    stevel 	/*
   1803     0    stevel 	 * The remaining logic is setting up the arguments for the
   1804     0    stevel 	 * POOL_DESTROY ioctl and appending the details into the log.
   1805     0    stevel 	 */
   1806     0    stevel 	if ((destroy = malloc(sizeof (pool_destroy_undo_t))) == NULL) {
   1807     0    stevel 		pool_seterror(POE_SYSTEM);
   1808     0    stevel 		return (PO_FAIL);
   1809     0    stevel 	}
   1810     0    stevel 	destroy->pdu_ioctl.pd_o_type = pool_elem_class(pe);
   1811     0    stevel 
   1812     0    stevel 	if (destroy->pdu_ioctl.pd_o_type == PEC_RES_COMP ||
   1813     0    stevel 	    destroy->pdu_ioctl.pd_o_type == PEC_RES_AGG)
   1814     0    stevel 		destroy->pdu_ioctl.pd_o_sub_type = pool_resource_elem_class(pe);
   1815     0    stevel 
   1816     0    stevel 	if (destroy->pdu_ioctl.pd_o_type == PEC_COMP)
   1817     0    stevel 		destroy->pdu_ioctl.pd_o_sub_type =
   1818     0    stevel 		    pool_component_elem_class(pe);
   1819     0    stevel 
   1820     0    stevel 	destroy->pdu_elem = pe;
   1821     0    stevel 
   1822     0    stevel 	if (log_append(prov->pkc_log, POOL_DESTROY, (void *)destroy) !=
   1823     0    stevel 	    PO_SUCCESS) {
   1824     0    stevel 		free(destroy);
   1825     0    stevel 		return (PO_FAIL);
   1826     0    stevel 	}
   1827     0    stevel 	return (PO_SUCCESS);
   1828     0    stevel }
   1829     0    stevel 
   1830     0    stevel /*
   1831     0    stevel  * Set the parent of the supplied child to the supplied parent
   1832     0    stevel  */
   1833     0    stevel int
   1834     0    stevel pool_knl_set_container(pool_elem_t *pp, pool_elem_t *pc)
   1835     0    stevel {
   1836     0    stevel 	pool_knl_elem_t *pkp = (pool_knl_elem_t *)pp;
   1837     0    stevel 	pool_knl_elem_t *pkc = (pool_knl_elem_t *)pc;
   1838     0    stevel 
   1839     0    stevel 	pkc->pke_parent = pkp;
   1840     0    stevel 	return (PO_SUCCESS);
   1841     0    stevel }
   1842     0    stevel 
   1843     0    stevel /*
   1844     0    stevel  * TODO: Needed for msets and ssets.
   1845     0    stevel  */
   1846     0    stevel /* ARGSUSED */
   1847     0    stevel int
   1848     0    stevel pool_knl_res_transfer(pool_resource_t *src, pool_resource_t *tgt,
   1849     0    stevel     uint64_t size) {
   1850     0    stevel 	return (PO_FAIL);
   1851     0    stevel }
   1852     0    stevel 
   1853     0    stevel /*
   1854     0    stevel  * Transfer resource components from one resource set to another.
   1855     0    stevel  */
   1856     0    stevel int
   1857     0    stevel pool_knl_res_xtransfer(pool_resource_t *src, pool_resource_t *tgt,
   1858     0    stevel     pool_component_t **rl) {
   1859     0    stevel 	pool_elem_t *src_e = TO_ELEM(src);
   1860     0    stevel 	pool_elem_t *tgt_e = TO_ELEM(tgt);
   1861     0    stevel 	pool_xtransfer_undo_t *xtransfer;
   1862     0    stevel 	size_t size;
   1863     0    stevel 	pool_knl_connection_t *prov =
   1864     0    stevel 	    (pool_knl_connection_t *)TO_CONF(src_e)->pc_prov;
   1865     0    stevel 
   1866     0    stevel 	if (prov->pkc_log->l_state != LS_DO) {
   1867     0    stevel 		/*
   1868     0    stevel 		 * Walk the Result Set and move the resource components
   1869     0    stevel 		 */
   1870     0    stevel 		for (size = 0; rl[size] != NULL; size++) {
   1871     0    stevel 			if (pool_set_container(TO_ELEM(tgt),
   1872     0    stevel 			    TO_ELEM(rl[size])) == PO_FAIL) {
   1873     0    stevel 				return (PO_FAIL);
   1874     0    stevel 			}
   1875     0    stevel 		}
   1876     0    stevel 		return (PO_SUCCESS);
   1877     0    stevel 	}
   1878     0    stevel 
   1879     0    stevel 	/*
   1880     0    stevel 	 * The remaining logic is setting up the arguments for the
   1881     0    stevel 	 * POOL_XTRANSFER ioctl and appending the details into the log.
   1882     0    stevel 	 */
   1883     0    stevel 	if ((xtransfer = malloc(sizeof (pool_xtransfer_undo_t))) == NULL) {
   1884     0    stevel 		pool_seterror(POE_SYSTEM);
   1885     0    stevel 		return (PO_FAIL);
   1886     0    stevel 	}
   1887     0    stevel 
   1888     0    stevel 	if (pool_elem_class(src_e) == PEC_RES_COMP) {
   1889     0    stevel 		xtransfer->pxu_ioctl.px_o_id_type =
   1890     0    stevel 		    pool_resource_elem_class(src_e);
   1891     0    stevel 	} else {
   1892     0    stevel 		pool_seterror(POE_BADPARAM);
   1893     0    stevel 		return (PO_FAIL);
   1894     0    stevel 	}
   1895     0    stevel 
   1896     0    stevel 
   1897     0    stevel 	for (xtransfer->pxu_ioctl.px_o_complist_size = 0;
   1898     0    stevel 	    rl[xtransfer->pxu_ioctl.px_o_complist_size] != NULL;
   1899     0    stevel 	    xtransfer->pxu_ioctl.px_o_complist_size++)
   1900     0    stevel 		/* calculate the size using the terminating NULL */;
   1901     0    stevel 	if ((xtransfer->pxu_ioctl.px_o_comp_list =
   1902     0    stevel 		calloc(xtransfer->pxu_ioctl.px_o_complist_size,
   1903     0    stevel 		sizeof (id_t))) == NULL) {
   1904     0    stevel 		pool_seterror(POE_SYSTEM);
   1905     0    stevel 		return (PO_FAIL);
   1906     0    stevel 	}
   1907     0    stevel 	if ((xtransfer->pxu_rl = calloc(
   1908     0    stevel 	    xtransfer->pxu_ioctl.px_o_complist_size + 1,
   1909     0    stevel 	    sizeof (pool_component_t *))) == NULL) {
   1910     0    stevel 		pool_seterror(POE_SYSTEM);
   1911     0    stevel 		return (PO_FAIL);
   1912     0    stevel 	}
   1913     0    stevel 	(void) memcpy(xtransfer->pxu_rl, rl,
   1914     0    stevel 	    xtransfer->pxu_ioctl.px_o_complist_size *
   1915     0    stevel 	    sizeof (pool_component_t *));
   1916     0    stevel 	xtransfer->pxu_src = src_e;
   1917     0    stevel 	xtransfer->pxu_tgt = tgt_e;
   1918     0    stevel 
   1919     0    stevel 	if (log_append(prov->pkc_log, POOL_XTRANSFER, (void *)xtransfer) !=
   1920     0    stevel 	    PO_SUCCESS) {
   1921     0    stevel 		free(xtransfer);
   1922     0    stevel 		return (PO_FAIL);
   1923     0    stevel 	}
   1924     0    stevel 	for (size = 0; rl[size] != NULL; size++) {
   1925     0    stevel 		if (pool_set_container(TO_ELEM(tgt), TO_ELEM(rl[size])) ==
   1926     0    stevel 		    PO_FAIL) {
   1927     0    stevel 			return (PO_FAIL);
   1928     0    stevel 		}
   1929     0    stevel 	}
   1930     0    stevel 	return (PO_SUCCESS);
   1931     0    stevel }
   1932     0    stevel 
   1933     0    stevel /*
   1934     0    stevel  * Return the parent of an element.
   1935     0    stevel  */
   1936     0    stevel pool_elem_t *
   1937     0    stevel pool_knl_get_container(const pool_elem_t *pe)
   1938     0    stevel {
   1939     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
   1940     0    stevel 
   1941     0    stevel 	return ((pool_elem_t *)pke->pke_parent);
   1942     0    stevel }
   1943     0    stevel 
   1944     0    stevel /*
   1945     0    stevel  * Note: This function is resource specific, needs extending for other
   1946     0    stevel  * resource types
   1947     0    stevel  */
   1948     0    stevel int
   1949     0    stevel pool_knl_resource_is_system(const pool_resource_t *pr)
   1950     0    stevel {
   1951     0    stevel 	switch (pool_resource_elem_class(TO_ELEM(pr))) {
   1952     0    stevel 	case PREC_PSET:
   1953     0    stevel 		return (PSID_IS_SYSSET(
   1954     0    stevel 		    elem_get_sysid(TO_ELEM(pr))));
   1955     0    stevel 	default:
   1956     0    stevel 		return (PO_FALSE);
   1957     0    stevel 	}
   1958     0    stevel }
   1959     0    stevel 
   1960     0    stevel /*
   1961     0    stevel  * Note: This function is resource specific, needs extending for other
   1962     0    stevel  * resource types
   1963     0    stevel  */
   1964     0    stevel int
   1965     0    stevel pool_knl_resource_can_associate(const pool_resource_t *pr)
   1966     0    stevel {
   1967     0    stevel 	switch (pool_resource_elem_class(TO_ELEM(pr))) {
   1968     0    stevel 	case PREC_PSET:
   1969     0    stevel 		return (PO_TRUE);
   1970     0    stevel 	default:
   1971     0    stevel 		return (PO_FALSE);
   1972     0    stevel 	}
   1973     0    stevel }
   1974     0    stevel 
   1975     0    stevel /*
   1976     0    stevel  * pool_knl_pool_associate() associates the supplied resource to the
   1977     0    stevel  * supplied pool.
   1978     0    stevel  *
   1979     0    stevel  * Returns: PO_SUCCESS/PO_FAIL
   1980     0    stevel  */
   1981     0    stevel int
   1982     0    stevel pool_knl_pool_associate(pool_t *pool, const pool_resource_t *resource)
   1983     0    stevel {
   1984     0    stevel 	pool_knl_connection_t *prov;
   1985     0    stevel 	pool_knl_pool_t *pkp = (pool_knl_pool_t *)pool;
   1986     0    stevel 	pool_resource_elem_class_t res_class =
   1987     0    stevel 	    pool_resource_elem_class(TO_ELEM(resource));
   1988     0    stevel 	pool_assoc_undo_t *assoc;
   1989     0    stevel 	pool_knl_resource_t *orig_res = pkp->pkp_assoc[res_class];
   1990     0    stevel 
   1991     0    stevel 	/*
   1992     0    stevel 	 * Are we allowed to associate with this target?
   1993     0    stevel 	 */
   1994     0    stevel 	if (pool_knl_resource_can_associate(resource) == PO_FALSE) {
   1995     0    stevel 		pool_seterror(POE_BADPARAM);
   1996     0    stevel 		return (PO_FAIL);
   1997     0    stevel 	}
   1998     0    stevel 	prov = (pool_knl_connection_t *)(TO_CONF(TO_ELEM(pool)))->pc_prov;
   1999     0    stevel 
   2000     0    stevel 	if (prov->pkc_log->l_state != LS_DO) {
   2001     0    stevel 		pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
   2002     0    stevel 		return (PO_SUCCESS);
   2003     0    stevel 	}
   2004     0    stevel 
   2005     0    stevel 	/*
   2006     0    stevel 	 * The remaining logic is setting up the arguments for the
   2007     0    stevel 	 * POOL_ASSOC ioctl and appending the details into the log.
   2008     0    stevel 	 */
   2009     0    stevel 	if ((assoc = malloc(sizeof (pool_assoc_undo_t))) == NULL) {
   2010     0    stevel 		pool_seterror(POE_SYSTEM);
   2011     0    stevel 		return (PO_FAIL);
   2012     0    stevel 	}
   2013     0    stevel 	assoc->pau_assoc = TO_ELEM(pool);
   2014     0    stevel 	assoc->pau_oldres = (pool_elem_t *)orig_res;
   2015     0    stevel 	assoc->pau_newres = TO_ELEM(resource);
   2016     0    stevel 
   2017     0    stevel 	assoc->pau_ioctl.pa_o_id_type = res_class;
   2018     0    stevel 
   2019     0    stevel 	if (log_append(prov->pkc_log, POOL_ASSOC, (void *)assoc) !=
   2020     0    stevel 	    PO_SUCCESS) {
   2021     0    stevel 		free(assoc);
   2022     0    stevel 		pkp->pkp_assoc[res_class] = orig_res;
   2023     0    stevel 		return (PO_FAIL);
   2024     0    stevel 	}
   2025     0    stevel 	pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
   2026     0    stevel 	return (PO_SUCCESS);
   2027     0    stevel }
   2028     0    stevel 
   2029     0    stevel /*
   2030     0    stevel  * pool_knl_pool_dissociate() dissociates the supplied resource from
   2031     0    stevel  * the supplied pool.
   2032     0    stevel  *
   2033     0    stevel  * Returns: PO_SUCCESS/PO_FAIL
   2034     0    stevel  */
   2035     0    stevel int
   2036     0    stevel pool_knl_pool_dissociate(pool_t *pool, const pool_resource_t *resource)
   2037     0    stevel {
   2038     0    stevel 	pool_knl_connection_t *prov;
   2039     0    stevel 	pool_dissoc_undo_t *dissoc;
   2040     0    stevel 	pool_knl_pool_t *pkp = (pool_knl_pool_t *)pool;
   2041     0    stevel 	pool_resource_t *default_res = (pool_resource_t *)get_default_resource(
   2042     0    stevel 	    resource);
   2043     0    stevel 	pool_resource_elem_class_t res_class =
   2044     0    stevel 	    pool_resource_elem_class(TO_ELEM(resource));
   2045     0    stevel 
   2046     0    stevel 	prov = (pool_knl_connection_t *)(TO_CONF(TO_ELEM(pool)))->pc_prov;
   2047     0    stevel 
   2048     0    stevel 	if (prov->pkc_log->l_state != LS_DO) {
   2049     0    stevel 		pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)default_res;
   2050     0    stevel 		return (PO_SUCCESS);
   2051     0    stevel 	}
   2052     0    stevel 	/*
   2053     0    stevel 	 * The remaining logic is setting up the arguments for the
   2054     0    stevel 	 * POOL_DISSOC ioctl and appending the details into the log.
   2055     0    stevel 	 */
   2056     0    stevel 	if ((dissoc = malloc(sizeof (pool_dissoc_undo_t))) == NULL) {
   2057     0    stevel 		pool_seterror(POE_SYSTEM);
   2058     0    stevel 		return (PO_FAIL);
   2059     0    stevel 	}
   2060     0    stevel 	dissoc->pdu_dissoc = TO_ELEM(pool);
   2061     0    stevel 	dissoc->pdu_oldres = TO_ELEM(resource);
   2062     0    stevel 	dissoc->pdu_newres = TO_ELEM(default_res);
   2063     0    stevel 
   2064     0    stevel 	dissoc->pdu_ioctl.pd_o_id_type = res_class;
   2065     0    stevel 
   2066     0    stevel 	if (log_append(prov->pkc_log, POOL_DISSOC, (void *)dissoc) !=
   2067     0    stevel 	    PO_SUCCESS) {
   2068     0    stevel 		free(dissoc);
   2069     0    stevel 		pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
   2070     0    stevel 		return (PO_FAIL);
   2071     0    stevel 	}
   2072     0    stevel 
   2073     0    stevel 	/*
   2074     0    stevel 	 * Update our local copy
   2075     0    stevel 	 */
   2076     0    stevel 	pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)default_res;
   2077     0    stevel 	return (PO_SUCCESS);
   2078     0    stevel }
   2079     0    stevel 
   2080     0    stevel /*
   2081     0    stevel  * Allocate a data provider for the supplied configuration and optionally
   2082     0    stevel  * discover resources.
   2083     0    stevel  * The data provider is the cross over point from the "abstract" configuration
   2084     0    stevel  * functions into the data representation specific manipulation routines.
   2085     0    stevel  * This function sets up all the required pointers to create a kernel aware
   2086     0    stevel  * data provider.
   2087     0    stevel  * Returns PO_SUCCESS/PO_FAIL
   2088     0    stevel  */
   2089     0    stevel int
   2090     0    stevel pool_knl_connection_alloc(pool_conf_t *conf, int oflags)
   2091     0    stevel {
   2092     0    stevel 	pool_knl_connection_t *prov;
   2093     0    stevel 
   2094     0    stevel 	if ((prov = malloc(sizeof (pool_knl_connection_t))) == NULL) {
   2095     0    stevel 		pool_seterror(POE_SYSTEM);
   2096     0    stevel 		return (PO_FAIL);
   2097     0    stevel 	}
   2098     0    stevel 	(void) memset(prov, 0, sizeof (pool_knl_connection_t));
   2099     0    stevel 	/*
   2100     0    stevel 	 * Initialise data members
   2101     0    stevel 	 */
   2102     0    stevel 	prov->pc_name = strdup("kernel");
   2103     0    stevel 	prov->pc_store_type = KERNEL_DATA_STORE;
   2104     0    stevel 	prov->pc_oflags = oflags;
   2105     0    stevel 	/*
   2106     0    stevel 	 * Initialise function pointers
   2107     0    stevel 	 */
   2108     0    stevel 	prov->pc_close = pool_knl_close;
   2109     0    stevel 	prov->pc_validate = pool_knl_validate;
   2110     0    stevel 	prov->pc_commit = pool_knl_commit;
   2111     0    stevel 	prov->pc_export = pool_knl_export;
   2112     0    stevel 	prov->pc_rollback = pool_knl_rollback;
   2113     0    stevel 	prov->pc_exec_query = pool_knl_exec_query;
   2114     0    stevel 	prov->pc_elem_create = pool_knl_elem_create;
   2115     0    stevel 	prov->pc_remove = pool_knl_remove;
   2116     0    stevel 	prov->pc_res_xfer = pool_knl_res_transfer;
   2117     0    stevel 	prov->pc_res_xxfer = pool_knl_res_xtransfer;
   2118     0    stevel 	prov->pc_get_binding = pool_knl_get_binding;
   2119     0    stevel 	prov->pc_set_binding = pool_knl_set_binding;
   2120     0    stevel 	prov->pc_get_resource_binding = pool_knl_get_resource_binding;
   2121     0    stevel 	/*
   2122     0    stevel 	 * Associate the provider to it's configuration
   2123     0    stevel 	 */
   2124     0    stevel 	conf->pc_prov = (pool_connection_t *)prov;
   2125     0    stevel 	/*
   2126     0    stevel 	 * End of common initialisation
   2127     0    stevel 	 */
   2128     0    stevel 	/*
   2129     0    stevel 	 * Attempt to open the pseudo device, if the configuration is opened
   2130     0    stevel 	 * readonly then try to open an info device, otherwise try to open
   2131     0    stevel 	 * the writeable device.
   2132     0    stevel 	 */
   2133     0    stevel 	if (oflags & PO_RDWR) {
   2134     0    stevel 		if ((prov->pkc_fd = blocking_open(pool_dynamic_location(),
   2135     0    stevel 		    O_RDWR)) < 0) {
   2136     0    stevel 			free(prov);
   2137     0    stevel 			conf->pc_prov = NULL;
   2138     0    stevel 			pool_seterror(POE_SYSTEM);
   2139     0    stevel 			return (PO_FAIL);
   2140     0    stevel 		}
   2141     0    stevel 	} else {
   2142     0    stevel 		if ((prov->pkc_fd = open(pool_info_location, O_RDWR)) < 0) {
   2143     0    stevel 			free(prov);
   2144     0    stevel 			conf->pc_prov = NULL;
   2145     0    stevel 			pool_seterror(POE_SYSTEM);
   2146     0    stevel 			return (PO_FAIL);
   2147     0    stevel 		}
   2148     0    stevel 	}
   2149     0    stevel 	/*
   2150     0    stevel 	 * Allocate the element dictionary
   2151     0    stevel 	 */
   2152     0    stevel 	if ((prov->pkc_elements = dict_new((int (*)(const void *, const void *))
   2153     0    stevel 	    pool_elem_compare, (uint64_t (*)(const void *))hash_id)) == NULL) {
   2154     0    stevel 		(void) close(prov->pkc_fd);
   2155     0    stevel 		free(prov);
   2156     0    stevel 		conf->pc_prov = NULL;
   2157     0    stevel 		pool_seterror(POE_SYSTEM);
   2158     0    stevel 		return (PO_FAIL);
   2159     0    stevel 	}
   2160     0    stevel #if DEBUG
   2161     0    stevel 	if ((prov->pkc_leaks = dict_new(NULL, NULL)) == NULL) {
   2162     0    stevel 		dict_free(&prov->pkc_elements);
   2163     0    stevel 		(void) close(prov->pkc_fd);
   2164     0    stevel 		free(prov);
   2165     0    stevel 		conf->pc_prov = NULL;
   2166     0    stevel 		pool_seterror(POE_SYSTEM);
   2167     0    stevel 		return (PO_FAIL);
   2168     0    stevel 	}
   2169     0    stevel #endif	/* DEBUG */
   2170     0    stevel 	/*
   2171     0    stevel 	 * Allocate the transaction log
   2172     0    stevel 	 */
   2173     0    stevel 	if ((prov->pkc_log = log_alloc(conf)) == NULL) {
   2174     0    stevel #if DEBUG
   2175     0    stevel 		dict_free(&prov->pkc_leaks);
   2176     0    stevel #endif	/* DEBUG */
   2177     0    stevel 		dict_free(&prov->pkc_elements);
   2178     0    stevel 		(void) close(prov->pkc_fd);
   2179     0    stevel 		free(prov);
   2180     0    stevel 		conf->pc_prov = NULL;
   2181     0    stevel 		return (PO_FAIL);
   2182     0    stevel 	}
   2183     0    stevel 	/*
   2184     0    stevel 	 * At this point the configuration provider has been initialized,
   2185     0    stevel 	 * mark the configuration as valid so that the various routines
   2186     0    stevel 	 * which rely on a valid configuration will work correctly.
   2187     0    stevel 	 */
   2188     0    stevel 	conf->pc_state = POF_VALID;
   2189     0    stevel 	/*
   2190     0    stevel 	 * Update the library snapshot from the kernel
   2191     0    stevel 	 */
   2192     0    stevel 	if (pool_knl_update(conf, NULL) != PO_SUCCESS) {
   2193     0    stevel #if DEBUG
   2194     0    stevel 		dict_free(&prov->pkc_leaks);
   2195     0    stevel #endif	/* DEBUG */
   2196     0    stevel 		dict_free(&prov->pkc_elements);
   2197     0    stevel 		(void) close(prov->pkc_fd);
   2198     0    stevel 		free(prov);
   2199     0    stevel 		conf->pc_prov = NULL;
   2200     0    stevel 		conf->pc_state = POF_INVALID;
   2201     0    stevel 		return (PO_FAIL);
   2202     0    stevel 	}
   2203     0    stevel 	return (PO_SUCCESS);
   2204     0    stevel }
   2205     0    stevel 
   2206     0    stevel #if DEBUG
   2207     0    stevel static void
   2208     0    stevel pool_knl_elem_printf_cb(const void *key, void **value, void *cl)
   2209     0    stevel {
   2210     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
   2211     0    stevel 	dict_hdl_t *map = (dict_hdl_t *)cl;
   2212     0    stevel 
   2213     0    stevel 	dprintf("leak elem:%p\n", pke);
   2214     0    stevel 	if (pke->pke_properties != NULL) {
   2215     0    stevel 		nvlist_print(stdout, pke->pke_properties);
   2216     0    stevel 	} else
   2217     0    stevel 		dprintf("no properties\n");
   2218     0    stevel 	assert(dict_get(map, pke) == NULL);
   2219     0    stevel }
   2220     0    stevel #endif	/* DEBUG */
   2221     0    stevel /*
   2222     0    stevel  * pool_knl_elem_free() releases the resources associated with the
   2223     0    stevel  * supplied element.
   2224     0    stevel  */
   2225     0    stevel static void
   2226     0    stevel pool_knl_elem_free(pool_knl_elem_t *pke, int freeprop)
   2227     0    stevel {
   2228     0    stevel #if DEBUG
   2229     0    stevel 	pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
   2230     0    stevel 	if (dict_remove(((pool_knl_connection_t *)conf->pc_prov)->pkc_leaks,
   2231     0    stevel 	    pke) == NULL)
   2232     0    stevel 		dprintf("%p, wasn't in the leak map\n", pke);
   2233     0    stevel 	if (freeprop == PO_TRUE) {
   2234     0    stevel 		pool_elem_dprintf(TO_ELEM(pke));
   2235     0    stevel 	}
   2236     0    stevel 	dprintf("released %p\n", pke);
   2237     0    stevel #endif	/* DEBUG */
   2238     0    stevel 	if (freeprop == PO_TRUE) {
   2239     0    stevel 		nvlist_free(pke->pke_properties);
   2240     0    stevel 	}
   2241     0    stevel 	free(pke);
   2242     0    stevel }
   2243     0    stevel 
   2244     0    stevel /*
   2245     0    stevel  * pool_knl_elem_free_cb() is designed to be used with
   2246     0    stevel  * dict_map(). When a connection is freed, this function is used to
   2247     0    stevel  * free all element resources.
   2248     0    stevel  */
   2249     0    stevel /* ARGSUSED1 */
   2250     0    stevel static void
   2251     0    stevel pool_knl_elem_free_cb(const void *key, void **value, void *cl)
   2252     0    stevel {
   2253     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
   2254     0    stevel 
   2255     0    stevel #ifdef DEBUG
   2256     0    stevel 	dprintf("pool_knl_elem_free_cb:\n");
   2257     0    stevel 	dprintf("about to release %p ", pke);
   2258     0    stevel 	pool_elem_dprintf(TO_ELEM(pke));
   2259     0    stevel #endif	/* DEBUG */
   2260     0    stevel 	pool_knl_elem_free(pke, PO_TRUE);
   2261     0    stevel }
   2262     0    stevel 
   2263     0    stevel /*
   2264     0    stevel  * Free the resources for a kernel data provider.
   2265     0    stevel  */
   2266     0    stevel void
   2267     0    stevel pool_knl_connection_free(pool_knl_connection_t *prov)
   2268     0    stevel {
   2269     0    stevel 	if (prov->pkc_log != NULL) {
   2270     0    stevel 		(void) log_walk(prov->pkc_log, log_item_release);
   2271     0    stevel 		log_free(prov->pkc_log);
   2272     0    stevel 	}
   2273     0    stevel 	if (prov->pkc_elements != NULL) {
   2274     0    stevel 		dict_map(prov->pkc_elements, pool_knl_elem_free_cb, NULL);
   2275     0    stevel #if DEBUG
   2276     0    stevel 		dprintf("dict length is %llu\n", dict_length(prov->pkc_leaks));
   2277     0    stevel 		dict_map(prov->pkc_leaks, pool_knl_elem_printf_cb,
   2278     0    stevel 		    prov->pkc_elements);
   2279     0    stevel 		assert(dict_length(prov->pkc_leaks) == 0);
   2280     0    stevel 		dict_free(&prov->pkc_leaks);
   2281     0    stevel #endif	/* DEBUG */
   2282     0    stevel 		dict_free(&prov->pkc_elements);
   2283     0    stevel 	}
   2284     0    stevel 	free((void *)prov->pc_name);
   2285     0    stevel 	free(prov);
   2286     0    stevel }
   2287     0    stevel 
   2288     0    stevel /*
   2289     0    stevel  * Return the specified property value.
   2290     0    stevel  *
   2291     0    stevel  * POC_INVAL is returned if an error is detected and the error code is updated
   2292     0    stevel  * to indicate the cause of the error.
   2293     0    stevel  */
   2294     0    stevel pool_value_class_t
   2295     0    stevel pool_knl_get_property(const pool_elem_t *pe, const char *name,
   2296     0    stevel     pool_value_t *val)
   2297     0    stevel {
   2298     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
   2299     0    stevel 	nvpair_t *pair;
   2300     0    stevel 	const pool_prop_t *prop;
   2301     0    stevel 
   2302     0    stevel 	if ((prop = provider_get_prop(pe, name)) != NULL)
   2303     0    stevel 		if (prop_is_stored(prop) == PO_FALSE)
   2304     0    stevel 			return (pool_knl_get_dynamic_property(pe, name, val));
   2305     0    stevel 
   2306     0    stevel 	if ((pair = pool_knl_find_nvpair(pke->pke_properties, name)) == NULL) {
   2307     0    stevel 		pool_seterror(POE_BADPARAM);
   2308     0    stevel 		return (POC_INVAL);
   2309     0    stevel 	}
   2310     0    stevel 
   2311     0    stevel 	if (pool_value_from_nvpair(val, pair) == PO_FAIL) {
   2312     0    stevel 		return (POC_INVAL);
   2313     0    stevel 	}
   2314     0    stevel 
   2315     0    stevel 	return (pool_value_get_type(val));
   2316     0    stevel }
   2317     0    stevel 
   2318     0    stevel /*
   2319     0    stevel  * Return the specified property value.
   2320     0    stevel  *
   2321     0    stevel  * If a property is designated as dynamic, then this function will
   2322     0    stevel  * always try to return the latest value of the property from the
   2323     0    stevel  * kernel.
   2324     0    stevel  *
   2325     0    stevel  * POC_INVAL is returned if an error is detected and the error code is updated
   2326     0    stevel  * to indicate the cause of the error.
   2327     0    stevel  */
   2328     0    stevel pool_value_class_t
   2329     0    stevel pool_knl_get_dynamic_property(const pool_elem_t *pe, const char *name,
   2330     0    stevel     pool_value_t *val)
   2331     0    stevel {
   2332     0    stevel 	pool_knl_connection_t *prov;
   2333     0    stevel 	pool_propget_t propget = { 0 };
   2334     0    stevel 	nvlist_t *proplist;
   2335     0    stevel 	nvpair_t *pair;
   2336     0    stevel 
   2337     0    stevel 	propget.pp_o_id_type = pool_elem_class(pe);
   2338     0    stevel 	if (pool_elem_class(pe) == PEC_RES_COMP ||
   2339     0    stevel 	    pool_elem_class(pe) == PEC_RES_AGG)
   2340     0    stevel 		propget.pp_o_id_subtype = pool_resource_elem_class(pe);
   2341     0    stevel 	if (pool_elem_class(pe) == PEC_COMP)
   2342     0    stevel 		propget.pp_o_id_subtype =
   2343     0    stevel 		    (pool_resource_elem_class_t)pool_component_elem_class(pe);
   2344     0    stevel 
   2345     0    stevel 	propget.pp_o_id = elem_get_sysid(pe);
   2346     0    stevel 	propget.pp_o_prop_name_size = strlen(name);
   2347     0    stevel 	propget.pp_o_prop_name = (char *)name;
   2348     0    stevel 	propget.pp_i_bufsize = KERNEL_SNAPSHOT_BUF_SZ;
   2349     0    stevel 	propget.pp_i_buf = malloc(KERNEL_SNAPSHOT_BUF_SZ);
   2350     0    stevel 	bzero(propget.pp_i_buf, KERNEL_SNAPSHOT_BUF_SZ);
   2351     0    stevel 
   2352     0    stevel 	prov = (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
   2353     0    stevel 	if (ioctl(prov->pkc_fd, POOL_PROPGET, &propget) < 0) {
   2354     0    stevel 		free(propget.pp_i_buf);
   2355     0    stevel 		pool_seterror(POE_SYSTEM);
   2356     0    stevel 		return (POC_INVAL);
   2357     0    stevel 	}
   2358     0    stevel 	if (nvlist_unpack(propget.pp_i_buf, propget.pp_i_bufsize,
   2359     0    stevel 	    &proplist, 0) != 0) {
   2360     0    stevel 		free(propget.pp_i_buf);
   2361     0    stevel 		pool_seterror(POE_SYSTEM);
   2362     0    stevel 		return (POC_INVAL);
   2363     0    stevel 	}
   2364     0    stevel 	free(propget.pp_i_buf);
   2365     0    stevel 
   2366     0    stevel 	if ((pair = nvlist_next_nvpair(proplist, NULL)) == NULL) {
   2367     0    stevel 		nvlist_free(proplist);
   2368     0    stevel 		pool_seterror(POE_SYSTEM);
   2369     0    stevel 		return (POC_INVAL);
   2370     0    stevel 	}
   2371     0    stevel 
   2372     0    stevel 	if (pool_value_from_nvpair(val, pair) == PO_FAIL) {
   2373     0    stevel 		nvlist_free(proplist);
   2374     0    stevel 		return (POC_INVAL);
   2375     0    stevel 	}
   2376     0    stevel 	nvlist_free(proplist);
   2377     0    stevel 	return (pool_value_get_type(val));
   2378     0    stevel }
   2379     0    stevel 
   2380     0    stevel /*
   2381     0    stevel  * Update the specified property value.
   2382     0    stevel  *
   2383     0    stevel  * PO_FAIL is returned if an error is detected and the error code is updated
   2384     0    stevel  * to indicate the cause of the error.
   2385     0    stevel  */
   2386     0    stevel int
   2387     0    stevel pool_knl_put_property(pool_elem_t *pe, const char *name,
   2388     0    stevel     const pool_value_t *val)
   2389     0    stevel {
   2390     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
   2391     0    stevel 	pool_knl_connection_t *prov =
   2392     0    stevel 	    (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
   2393     0    stevel 	nvpair_t *bp, *ap;
   2394     0    stevel 	pool_propput_undo_t *propput;
   2395     0    stevel 	nvlist_t *bl = NULL;
   2396     0    stevel 	const pool_prop_t *prop;
   2397     0    stevel 
   2398     0    stevel 	if ((bp = pool_knl_find_nvpair(pke->pke_properties, name)) != NULL) {
   2399     0    stevel 		if (nvlist_alloc(&bl, NV_UNIQUE_NAME_TYPE, 0) != 0) {
   2400     0    stevel 			pool_seterror(POE_SYSTEM);
   2401     0    stevel 			return (PO_FAIL);
   2402     0    stevel 		}
   2403     0    stevel 		if (nvlist_add_nvpair(bl, bp) != 0) {
   2404     0    stevel 			nvlist_free(bl);
   2405     0    stevel 			pool_seterror(POE_SYSTEM);
   2406     0    stevel 			return (PO_FAIL);
   2407     0    stevel 		}
   2408     0    stevel 	}
   2409     0    stevel 	if (pool_knl_nvlist_add_value(pke->pke_properties, name, val) !=
   2410     0    stevel 	    PO_SUCCESS)
   2411     0    stevel 		return (PO_FAIL);
   2412     0    stevel 
   2413     0    stevel 	if (prov->pkc_log->l_state != LS_DO) {
   2414     0    stevel 		if (bl)
   2415     0    stevel 			nvlist_free(bl);
   2416     0    stevel 		return (PO_SUCCESS);
   2417     0    stevel 	}
   2418     0    stevel 	/*
   2419     0    stevel 	 * The remaining logic is setting up the arguments for the
   2420     0    stevel 	 * POOL_PROPPUT ioctl and appending the details into the log.
   2421     0    stevel 	 */
   2422     0    stevel 	if ((propput = malloc(sizeof (pool_propput_undo_t))) == NULL) {
   2423     0    stevel 		pool_seterror(POE_SYSTEM);
   2424     0    stevel 		return (PO_FAIL);
   2425     0    stevel 	}
   2426     0    stevel 	(void) memset(propput, 0, sizeof (pool_propput_undo_t));
   2427     0    stevel 	propput->ppu_blist = bl;
   2428     0    stevel 
   2429     0    stevel 	ap = pool_knl_find_nvpair(pke->pke_properties, name);
   2430     0    stevel 
   2431     0    stevel 	if (nvlist_alloc(&propput->ppu_alist, NV_UNIQUE_NAME_TYPE, 0) != 0) {
   2432     0    stevel 		nvlist_free(propput->ppu_blist);
   2433     0    stevel 		free(propput);
   2434     0    stevel 		pool_seterror(POE_SYSTEM);
   2435     0    stevel 		return (PO_FAIL);
   2436     0    stevel 	}
   2437     0    stevel 	if (nvlist_add_nvpair(propput->ppu_alist, ap) != 0) {
   2438     0    stevel 		nvlist_free(propput->ppu_blist);
   2439     0    stevel 		nvlist_free(propput->ppu_alist);
   2440     0    stevel 		free(propput);
   2441     0    stevel 		pool_seterror(POE_SYSTEM);
   2442     0    stevel 		return (PO_FAIL);
   2443     0    stevel 	}
   2444     0    stevel 
   2445     0    stevel 	if (nvlist_pack(propput->ppu_alist,
   2446     0    stevel 	    (char **)&propput->ppu_ioctl.pp_o_buf,
   2447     0    stevel 	    &propput->ppu_ioctl.pp_o_bufsize, NV_ENCODE_NATIVE, 0) != 0) {
   2448     0    stevel 		pool_seterror(POE_SYSTEM);
   2449     0    stevel 		return (PO_FAIL);
   2450     0    stevel 	}
   2451     0    stevel 	nvlist_free(propput->ppu_alist);
   2452     0    stevel 	propput->ppu_ioctl.pp_o_id_type = pool_elem_class(pe);
   2453     0    stevel 	if (pool_elem_class(pe) == PEC_RES_COMP ||
   2454     0    stevel 	    pool_elem_class(pe) == PEC_RES_AGG)
   2455     0    stevel 		propput->ppu_ioctl.pp_o_id_sub_type =
   2456     0    stevel 		    pool_resource_elem_class(pe);
   2457     0    stevel 	if (pool_elem_class(pe) == PEC_COMP)
   2458     0    stevel 		propput->ppu_ioctl.pp_o_id_sub_type =
   2459     0    stevel 		    (pool_resource_elem_class_t)pool_component_elem_class(pe);
   2460     0    stevel 
   2461     0    stevel 	propput->ppu_elem = pe;
   2462     0    stevel 	if ((prop = provider_get_prop(propput->ppu_elem, name)) != NULL) {
   2463     0    stevel 		if (prop_is_readonly(prop) == PO_TRUE)
   2464     0    stevel 			propput->ppu_doioctl |= KERNEL_PROP_RDONLY;
   2465     0    stevel 	}
   2466     0    stevel 
   2467     0    stevel 	if (log_append(prov->pkc_log, POOL_PROPPUT, (void *)propput) !=
   2468     0    stevel 	    PO_SUCCESS) {
   2469     0    stevel 		nvlist_free(propput->ppu_blist);
   2470     0    stevel 		free(propput);
   2471     0    stevel 		return (PO_FAIL);
   2472     0    stevel 	}
   2473     0    stevel 	return (PO_SUCCESS);
   2474     0    stevel }
   2475     0    stevel 
   2476     0    stevel /*
   2477     0    stevel  * Remove the specified property value.
   2478     0    stevel  *
   2479     0    stevel  * PO_FAIL is returned if an error is detected and the error code is
   2480     0    stevel  * updated to indicate the cause of the error.
   2481     0    stevel  */
   2482     0    stevel int
   2483     0    stevel pool_knl_rm_property(pool_elem_t *pe, const char *name)
   2484     0    stevel {
   2485     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
   2486     0    stevel 	pool_knl_connection_t *prov =
   2487     0    stevel 	    (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
   2488     0    stevel 	pool_proprm_undo_t *proprm;
   2489     0    stevel 
   2490     0    stevel 	if (pool_knl_find_nvpair(pke->pke_properties, name) == NULL) {
   2491     0    stevel 		pool_seterror(POE_BADPARAM);
   2492     0    stevel 		return (PO_FAIL);
   2493     0    stevel 	}
   2494     0    stevel 
   2495     0    stevel 	if ((proprm = malloc(sizeof (pool_proprm_undo_t))) == NULL) {
   2496     0    stevel 		pool_seterror(POE_SYSTEM);
   2497     0    stevel 		return (PO_FAIL);
   2498     0    stevel 	}
   2499     0    stevel 	(void) memset(proprm, 0, sizeof (pool_proprm_undo_t));
   2500     0    stevel 	proprm->pru_oldval.pv_class = POC_INVAL;
   2501     0    stevel 	(void) pool_get_property(TO_CONF(pe), pe, name, &proprm->pru_oldval);
   2502     0    stevel 
   2503     0    stevel 	if (prov->pkc_log->l_state != LS_DO) {
   2504     0    stevel 		free(proprm);
   2505     0    stevel 		(void) nvlist_remove_all(pke->pke_properties, (char *)name);
   2506     0    stevel 		return (PO_SUCCESS);
   2507     0    stevel 	}
   2508     0    stevel 	/*
   2509     0    stevel 	 * The remaining logic is setting up the arguments for the
   2510     0    stevel 	 * POOL_PROPRM ioctl and appending the details into the log.
   2511     0    stevel 	 */
   2512     0    stevel 
   2513     0    stevel 	proprm->pru_ioctl.pp_o_id_type = pool_elem_class(pe);
   2514     0    stevel 	if (pool_elem_class(pe) == PEC_RES_COMP ||
   2515     0    stevel 	    pool_elem_class(pe) == PEC_RES_AGG)
   2516     0    stevel 		proprm->pru_ioctl.pp_o_id_sub_type =
   2517     0    stevel 		    pool_resource_elem_class(pe);
   2518     0    stevel 
   2519     0    stevel 	if (pool_elem_class(pe) == PEC_COMP)
   2520     0    stevel 		proprm->pru_ioctl.pp_o_id_sub_type =
   2521     0    stevel 		    (pool_resource_elem_class_t)pool_component_elem_class(pe);
   2522     0    stevel 
   2523     0    stevel 	proprm->pru_ioctl.pp_o_prop_name_size = strlen(name);
   2524     0    stevel 	proprm->pru_ioctl.pp_o_prop_name =
   2525     0    stevel 	    (char *)pool_value_get_name(&proprm->pru_oldval);
   2526     0    stevel 	proprm->pru_elem = pe;
   2527     0    stevel 
   2528     0    stevel 	if (log_append(prov->pkc_log, POOL_PROPRM, (void *)proprm) !=
   2529     0    stevel 	    PO_SUCCESS) {
   2530     0    stevel 		free(proprm);
   2531     0    stevel 		return (PO_FAIL);
   2532     0    stevel 	}
   2533     0    stevel 
   2534     0    stevel 	(void) nvlist_remove_all(pke->pke_properties, (char *)name);
   2535     0    stevel 	return (PO_SUCCESS);
   2536     0    stevel }
   2537     0    stevel 
   2538     0    stevel /*
   2539     0    stevel  * Return a NULL terminated array of pool_value_t which represents all
   2540     0    stevel  * of the properties stored for an element
   2541     0    stevel  *
   2542     0    stevel  * Return NULL on failure. It is the caller's responsibility to free
   2543     0    stevel  * the returned array of values.
   2544     0    stevel  */
   2545     0    stevel pool_value_t **
   2546     0    stevel pool_knl_get_properties(const pool_elem_t *pe, uint_t *nprops)
   2547     0    stevel {
   2548     0    stevel 	nvpair_t *pair;
   2549     0    stevel 	pool_value_t **result;
   2550     0    stevel 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
   2551     0    stevel 	int i = 0;
   2552     0    stevel 
   2553     0    stevel 	*nprops = 0;
   2554     0    stevel 
   2555     0    stevel 	for (pair = nvlist_next_nvpair(pke->pke_properties, NULL); pair != NULL;
   2556     0    stevel 		pair = nvlist_next_nvpair(pke->pke_properties, pair))
   2557     0    stevel 		(*nprops)++;
   2558     0    stevel 	if ((result = calloc(*nprops + 1, sizeof (pool_value_t *))) == NULL) {
   2559     0    stevel 		pool_seterror(POE_SYSTEM);
   2560     0    stevel 		return (NULL);
   2561     0    stevel 	}
   2562     0    stevel 	for (pair = nvlist_next_nvpair(pke->pke_properties, NULL); pair != NULL;
   2563     0    stevel 	    pair = nvlist_next_nvpair(pke->pke_properties, pair), i++) {
   2564     0    stevel 		result[i] = pool_value_alloc();
   2565     0    stevel 		if (pool_value_from_nvpair(result[i], pair) == PO_FAIL) {
   2566     0    stevel 			while (i-- >= 0)
   2567     0    stevel 				pool_value_free(result[i]);
   2568     0    stevel 			free(result);
   2569     0    stevel 			return (NULL);
   2570     0    stevel 		}
   2571     0    stevel 	}
   2572     0    stevel 	return (result);
   2573     0    stevel }
   2574     0    stevel 
   2575     0    stevel /*
   2576     0    stevel  * Append an entry to a result set. Reallocate the array used to store
   2577     0    stevel  * results if it's full.
   2578     0    stevel  * Returns PO_SUCCESS/PO_FAIL
   2579     0    stevel  */
   2580     0    stevel int
   2581     0    stevel pool_knl_result_set_append(pool_knl_result_set_t *rs, pool_knl_elem_t *pke)
   2582     0    stevel {
   2583     0    stevel 	if (rs->pkr_count == rs->pkr_size)
   2584     0    stevel 		if (pool_knl_result_set_realloc(rs) != PO_SUCCESS)
   2585     0    stevel 			return (PO_FAIL);
   2586     0    stevel 
   2587     0    stevel 	rs->pkr_list[rs->pkr_count++] = pke;
   2588     0    stevel 
   2589     0    stevel 	return (PO_SUCCESS);
   2590     0    stevel }
   2591     0    stevel 
   2592     0    stevel /*
   2593     0    stevel  * Resize the array used to store results. A simple doubling strategy
   2594     0    stevel  * is used.
   2595     0    stevel  * Returns PO_SUCCESS/PO_FAIL
   2596     0    stevel  */
   2597     0    stevel int
   2598     0    stevel pool_knl_result_set_realloc(pool_knl_result_set_t *rs)
   2599     0    stevel {
   2600     0    stevel 	pool_knl_elem_t **old_list = rs->pkr_list;
   2601     0    stevel 	int new_size = rs->pkr_size * 2;
   2602     0    stevel 
   2603     0    stevel 	if ((rs->pkr_list = realloc(rs->pkr_list,
   2604     0    stevel 	    new_size * sizeof (pool_knl_elem_t *))) == NULL) {
   2605     0    stevel 		rs->pkr_list = old_list;
   2606     0    stevel 		pool_seterror(POE_SYSTEM);
   2607     0    stevel 		return (PO_FAIL);
   2608     0    stevel 	}
   2609     0    stevel 	rs->pkr_size = new_size;
   2610     0    stevel 
   2611     0    stevel 	return (PO_SUCCESS);
   2612     0    stevel }
   2613     0    stevel 
   2614     0    stevel /*
   2615     0    stevel  * Allocate a result set. The Result Set stores the result of a query.
   2616     0    stevel  * Returns pool_knl_result_set_t pointer/NULL
   2617     0    stevel  */
   2618     0    stevel pool_knl_result_set_t *
   2619     0    stevel pool_knl_result_set_alloc(const pool_conf_t *conf)
   2620     0    stevel {
   2621     0    stevel 	pool_knl_result_set_t *rs;
   2622     0    stevel 
   2623     0    stevel 	if ((rs = malloc(sizeof (pool_knl_result_set_t))) == NULL) {
   2624     0    stevel 		pool_seterror(POE_SYSTEM);
   2625     0    stevel 		return (NULL);
   2626     0    stevel 	}
   2627     0    stevel 	(void) memset(rs, 0, sizeof (pool_knl_result_set_t));
   2628     0    stevel 	rs->pkr_size = KERNEL_RS_INITIAL_SZ;
   2629     0    stevel 	if (pool_knl_result_set_realloc(rs) == PO_FAIL) {
   2630     0    stevel 		free(rs);
   2631     0    stevel 		pool_seterror(POE_SYSTEM);
   2632     0    stevel 		return (NULL);
   2633     0    stevel 	}
   2634     0    stevel 	rs->prs_conf = conf;
   2635     0    stevel 	rs->prs_index = -1;
   2636     0    stevel 	rs->prs_active = PO_TRUE;
   2637     0    stevel 	/* Fix up the result set accessor functions to the knl specfic ones */
   2638     0    stevel 	rs->prs_next = pool_knl_rs_next;
   2639     0    stevel 	rs->prs_prev = pool_knl_rs_prev;
   2640     0    stevel 	rs->prs_first = pool_knl_rs_first;
   2641     0    stevel 	rs->prs_last = pool_knl_rs_last;
   2642     0    stevel 	rs->prs_get_index = pool_knl_rs_get_index;
   2643     0    stevel 	rs->prs_set_index = pool_knl_rs_set_index;
   2644     0    stevel 	rs->prs_close = pool_knl_rs_close;
   2645     0    stevel 	rs->prs_count = pool_knl_rs_count;
   2646     0    stevel 	return (rs);
   2647     0    stevel }
   2648     0    stevel 
   2649     0    stevel /*
   2650     0    stevel  * Free a result set. Ensure that the resources are all released at
   2651     0    stevel  * this point.
   2652     0    stevel  */
   2653     0    stevel void
   2654     0    stevel pool_knl_result_set_free(pool_knl_result_set_t *rs)
   2655     0    stevel {
   2656     0    stevel 	free(rs->pkr_list);
   2657     0    stevel 	free(rs);
   2658     0    stevel }
   2659     0    stevel /*
   2660     0    stevel  * Return the next element in a result set.
   2661     0    stevel  * Returns pool_elem_t pointer/NULL
   2662     0    stevel  */
   2663     0    stevel pool_elem_t *
   2664     0    stevel pool_knl_rs_next(pool_result_set_t *set)
   2665     0    stevel {
   2666     0    stevel 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
   2667     0    stevel 
   2668     0    stevel 	if (kset->prs_index == kset->pkr_count - 1)
   2669     0    stevel 		return (NULL);
   2670     0    stevel 	return ((pool_elem_t *)kset->pkr_list[++kset->prs_index]);
   2671     0    stevel }
   2672     0    stevel 
   2673     0    stevel /*
   2674     0    stevel  * Return the previous element in a result set.
   2675     0    stevel  * Returns pool_elem_t pointer/NULL
   2676     0    stevel  */
   2677     0    stevel pool_elem_t *
   2678     0    stevel pool_knl_rs_prev(pool_result_set_t *set)
   2679     0    stevel {
   2680     0    stevel 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
   2681     0    stevel 
   2682     0    stevel 	if (kset->prs_index < 0)
   2683     0    stevel 		return (NULL);
   2684     0    stevel 	return ((pool_elem_t *)kset->pkr_list[kset->prs_index--]);
   2685     0    stevel }
   2686     0    stevel 
   2687     0    stevel /*
   2688     0    stevel  * Sets the current index in a result set.
   2689     0    stevel  * Returns PO_SUCCESS/PO_FAIL
   2690     0    stevel  */
   2691     0    stevel int
   2692     0    stevel pool_knl_rs_set_index(pool_result_set_t *set, int index)
   2693     0    stevel {
   2694     0    stevel 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
   2695     0    stevel 
   2696     0    stevel 	if (index < 0 || index >= kset->pkr_count) {
   2697     0    stevel 		pool_seterror(POE_BADPARAM);
   2698     0    stevel 		return (PO_FAIL);
   2699     0    stevel 	}
   2700     0    stevel 	kset->prs_index = index;
   2701     0    stevel 	return (PO_SUCCESS);
   2702     0    stevel }
   2703     0    stevel 
   2704     0    stevel /*
   2705     0    stevel  * Return the current index in a result set.
   2706     0    stevel  * Returns current index
   2707     0    stevel  */
   2708     0    stevel int
   2709     0    stevel pool_knl_rs_get_index(pool_result_set_t *set)
   2710     0    stevel {
   2711     0    stevel 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
   2712     0    stevel 
   2713     0    stevel 	return (kset->prs_index);
   2714     0    stevel }
   2715     0    stevel 
   2716     0    stevel /*
   2717     0    stevel  * Return the first element in a result set.
   2718     0    stevel  * Returns pool_elem_t pointer/NULL
   2719     0    stevel  */
   2720     0    stevel pool_elem_t *
   2721     0    stevel pool_knl_rs_first(pool_result_set_t *set)
   2722     0    stevel {
   2723     0    stevel 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
   2724     0    stevel 
   2725     0    stevel 	return ((pool_elem_t *)kset->pkr_list[0]);
   2726     0    stevel }
   2727     0    stevel 
   2728     0    stevel /*
   2729     0    stevel  * Return the last element in a result set.
   2730     0    stevel  * Returns pool_elem_t pointer/NULL
   2731     0    stevel  */
   2732     0    stevel pool_elem_t *
   2733     0    stevel pool_knl_rs_last(pool_result_set_t *set)
   2734     0    stevel {
   2735     0    stevel 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
   2736     0    stevel 
   2737     0    stevel 	return ((pool_elem_t *)kset->pkr_list[kset->pkr_count - 1]);
   2738     0    stevel }
   2739     0    stevel 
   2740     0    stevel /*
   2741     0    stevel  * Return the number of results in a result set.
   2742     0    stevel  * Returns result count
   2743     0    stevel  */
   2744     0    stevel int
   2745     0    stevel pool_knl_rs_count(pool_result_set_t *set)
   2746     0    stevel {
   2747     0    stevel 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
   2748     0    stevel 
   2749     0    stevel 	return (kset->pkr_count);
   2750     0    stevel }
   2751     0    stevel 
   2752     0    stevel 
   2753     0    stevel /*
   2754     0    stevel  * Close a result set. Free the resources
   2755     0    stevel  * Returns PO_SUCCESS/PO_FAIL
   2756     0    stevel  */
   2757     0    stevel int
   2758     0    stevel pool_knl_rs_close(pool_result_set_t *set)
   2759     0    stevel {
   2760     0    stevel 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
   2761     0    stevel 
   2762     0    stevel 	pool_knl_result_set_free(kset);
   2763     0    stevel 	return (PO_SUCCESS);
   2764     0    stevel }
   2765     0    stevel 
   2766     0    stevel /*
   2767     0    stevel  * Commit an individual transaction log item(). This processing is
   2768     0    stevel  * essential to the pool_conf_commit() logic. When pool_conf_commit()
   2769     0    stevel  * is invoked, the pending transaction log for the configuration is
   2770     0    stevel  * walked and all pending changes to the kernel are invoked. If a
   2771     0    stevel  * change succeeds it is marked in the log as successful and
   2772     0    stevel  * processing continues, if it fails then failure is returned and the
   2773     0    stevel  * log will be "rolled back" to undo changes to the library snapshot
   2774     0    stevel  * and the kernel.
   2775     0    stevel  */
   2776     0    stevel int
   2777     0    stevel log_item_commit(log_item_t *li)
   2778     0    stevel {
   2779     0    stevel 	pool_knl_connection_t *prov =
   2780     0    stevel 	    (pool_knl_connection_t *)li->li_log->l_conf->pc_prov;
   2781     0    stevel 	pool_create_undo_t *create;
   2782     0    stevel 	pool_destroy_undo_t *destroy;
   2783     0    stevel 	pool_assoc_undo_t *assoc;
   2784     0    stevel 	pool_dissoc_undo_t *dissoc;
   2785     0    stevel 	pool_propput_undo_t *propput;
   2786     0    stevel 	pool_proprm_undo_t *proprm;
   2787     0    stevel 	pool_xtransfer_undo_t *xtransfer;
   2788     0    stevel 	char_buf_t *cb;
   2789     0    stevel 	size_t size;
   2790     0    stevel 	pool_elem_t *pair;
   2791     0    stevel 	pool_value_t val = POOL_VALUE_INITIALIZER;
   2792     0    stevel 	int ret;
   2793     0    stevel 
   2794     0    stevel 	switch (li->li_op) {
   2795     0    stevel 	case POOL_CREATE:
   2796     0    stevel 		create = (pool_create_undo_t *)li->li_details;
   2797     0    stevel 		if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
   2798     0    stevel 			return (PO_FAIL);
   2799     0    stevel 		if (set_char_buf(cb, "%s.sys_id",
   2800     0    stevel 		    pool_elem_class_string(create->pcu_elem)) != PO_SUCCESS) {
   2801     0    stevel 			free_char_buf(cb);
   2802     0    stevel 			return (PO_FAIL);
   2803     0    stevel 		}
   2804     0    stevel #ifdef DEBUG
   2805     0    stevel 		dprintf("log_item_commit: POOL_CREATE, remove from dict\n");
   2806     0    stevel 		pool_elem_dprintf(create->pcu_elem);
   2807     0    stevel #endif	/* DEBUG */
   2808     0    stevel 		/*
   2809     0    stevel 		 * May not need to remove the element if it was
   2810     0    stevel 		 * already destroyed before commit. Just cast the
   2811     0    stevel 		 * return to void.
   2812     0    stevel 		 */
   2813     0    stevel 		(void) dict_remove(prov->pkc_elements,
   2814     0    stevel 		    (pool_knl_elem_t *)create->pcu_elem);
   2815     0    stevel 
   2816     0    stevel 		if (ioctl(prov->pkc_fd, POOL_CREATE, &create->pcu_ioctl) < 0) {
   2817     0    stevel 			pool_seterror(POE_SYSTEM);
   2818     0    stevel 			return (PO_FAIL);
   2819     0    stevel 		}
   2820     0    stevel 		/*
   2821     0    stevel 		 * Now that we have created our element in the kernel,
   2822     0    stevel 		 * it has a valid allocated system id. Remove the
   2823     0    stevel 		 * element from the element dictionary, using the
   2824     0    stevel 		 * current key, and then re-insert under the new key.
   2825     0    stevel 		 */
   2826     0    stevel #ifdef DEBUG
   2827     0    stevel 		pool_elem_dprintf(create->pcu_elem);
   2828     0    stevel #endif	/* DEBUG */
   2829     0    stevel 		assert(nvlist_add_int64(
   2830     0    stevel 		    ((pool_knl_elem_t *)create->pcu_elem)->pke_properties,
   2831     0    stevel 		    cb->cb_buf, create->pcu_ioctl.pc_i_id) == 0);
   2832     0    stevel 		free_char_buf(cb);
   2833     0    stevel 		assert(dict_put(prov->pkc_elements, create->pcu_elem,
   2834     0    stevel 		    create->pcu_elem) == NULL);
   2835     0    stevel 		/*
   2836     0    stevel 		 * If the element has a pair in the static
   2837     0    stevel 		 * configuration, update it with the sys_id
   2838     0    stevel 		 */
   2839     0    stevel 		if ((pair = pool_get_pair(create->pcu_elem)) != NULL) {
   2840     0    stevel 			pool_value_set_int64(&val, create->pcu_ioctl.pc_i_id);
   2841     0    stevel 			assert(pool_put_any_ns_property(pair, c_sys_prop, &val)
   2842     0    stevel 			    == PO_SUCCESS);
   2843     0    stevel 		}
   2844     0    stevel 		li->li_state = LS_UNDO;
   2845     0    stevel 		break;
   2846     0    stevel 	case POOL_DESTROY:
   2847     0    stevel 		destroy = (pool_destroy_undo_t *)li->li_details;
   2848     0    stevel 
   2849     0    stevel 		destroy->pdu_ioctl.pd_o_id = elem_get_sysid(destroy->pdu_elem);
   2850     0    stevel 
   2851     0    stevel 		/*
   2852     0    stevel 		 * It may be that this element was created in the last
   2853     0    stevel 		 * transaction. In which case POOL_CREATE, above, will
   2854     0    stevel 		 * have re-inserted the element in the dictionary. Try
   2855     0    stevel 		 * to remove it just in case this has occurred.
   2856     0    stevel 		 */
   2857     0    stevel 		(void) dict_remove(prov->pkc_elements,
   2858     0    stevel 		    (pool_knl_elem_t *)destroy->pdu_elem);
   2859     0    stevel 		while ((ret = ioctl(prov->pkc_fd, POOL_DESTROY,
   2860     0    stevel 		    &destroy->pdu_ioctl)) < 0 && errno == EAGAIN);
   2861     0    stevel 		if (ret < 0) {
   2862     0    stevel 			pool_seterror(POE_SYSTEM);
   2863     0    stevel 			return (PO_FAIL);
   2864     0    stevel 		}
   2865     0    stevel #ifdef DEBUG
   2866     0    stevel 		dprintf("log_item_commit: POOL_DESTROY\n");
   2867     0    stevel 		pool_elem_dprintf(destroy->pdu_elem);
   2868     0    stevel #endif	/* DEBUG */
   2869     0    stevel 		li->li_state = LS_UNDO;
   2870     0    stevel 		break;
   2871     0    stevel 	case POOL_ASSOC:
   2872     0    stevel 		assoc = (pool_assoc_undo_t *)li->li_details;
   2873     0    stevel 
   2874     0    stevel 		assoc->pau_ioctl.pa_o_pool_id =
   2875     0    stevel 		    elem_get_sysid(assoc->pau_assoc);
   2876     0    stevel 		assoc->pau_ioctl.pa_o_res_id =
   2877     0    stevel 		    elem_get_sysid(assoc->pau_newres);
   2878     0    stevel 		while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC,
   2879     0    stevel 		    &assoc->pau_ioctl)) < 0 && errno == EAGAIN);
   2880     0    stevel 		if (ret < 0) {
   2881     0    stevel 			pool_seterror(POE_SYSTEM);
   2882     0    stevel 			return (PO_FAIL);
   2883     0    stevel 		}
   2884     0    stevel 		li->li_state = LS_UNDO;
   2885     0    stevel 		break;
   2886     0    stevel 	case POOL_DISSOC:
   2887     0    stevel 		dissoc = (pool_dissoc_undo_t *)li->li_details;
   2888     0    stevel 
   2889     0    stevel 		dissoc->pdu_ioctl.pd_o_pool_id =
   2890     0    stevel 		    elem_get_sysid(dissoc->pdu_dissoc);
   2891     0    stevel 
   2892     0    stevel 		while ((ret = ioctl(prov->pkc_fd, POOL_DISSOC,
   2893     0    stevel 		    &dissoc->pdu_ioctl)) < 0 && errno == EAGAIN);
   2894     0    stevel 		if (ret < 0) {
   2895     0    stevel 			pool_seterror(POE_SYSTEM);
   2896     0    stevel 			return (PO_FAIL);
   2897     0    stevel 		}
   2898     0    stevel 		li->li_state = LS_UNDO;
   2899     0    stevel 		break;
   2900     0    stevel 	case POOL_TRANSFER:
   2901     0    stevel 		li->li_state = LS_UNDO;
   2902     0    stevel 		pool_seterror(POE_BADPARAM);
   2903     0    stevel 		return (PO_FAIL);
   2904     0    stevel 		break;
   2905     0    stevel 	case POOL_XTRANSFER:
   2906     0    stevel 		xtransfer = (pool_xtransfer_undo_t *)li->li_details;
   2907     0    stevel 
   2908     0    stevel 		xtransfer->pxu_ioctl.px_o_src_id =
   2909     0    stevel 		    elem_get_sysid(xtransfer->pxu_src);
   2910     0    stevel 		xtransfer->pxu_ioctl.px_o_tgt_id =
   2911     0    stevel 		    elem_get_sysid(xtransfer->pxu_tgt);
   2912     0    stevel 		for (size = 0; xtransfer->pxu_rl[size] != NULL; size ++) {
   2913     0    stevel 			xtransfer->pxu_ioctl.px_o_comp_list[size] =
   2914     0    stevel 			    elem_get_sysid(TO_ELEM(xtransfer->pxu_rl[size]));
   2915     0    stevel #ifdef DEBUG
   2916     0    stevel 			dprintf("log_item_commit: POOL_XTRANSFER\n");
   2917     0    stevel 			pool_elem_dprintf(TO_ELEM(xtransfer->pxu_rl[size]));
   2918     0    stevel #endif	/* DEBUG */
   2919     0    stevel 		}
   2920     0    stevel 
   2921     0    stevel 		/*
   2922     0    stevel 		 * Don't actually transfer resources if the configuration
   2923     0    stevel 		 * is in POF_DESTROY state. This is to prevent problems
   2924     0    stevel 		 * relating to transferring off-line CPUs. Instead rely
   2925     0    stevel 		 * on the POOL_DESTROY ioctl to transfer the CPUS.
   2926     0    stevel 		 */
   2927     0    stevel 		if (li->li_log->l_conf->pc_state != POF_DESTROY &&
   2928     0    stevel 		    ioctl(prov->pkc_fd, POOL_XTRANSFER,
   2929     0    stevel 		    &xtransfer->pxu_ioctl) < 0) {
   2930     0    stevel #ifdef DEBUG
   2931     0    stevel 			dprintf("log_item_commit: POOL_XTRANSFER, ioctl "
   2932     0    stevel 			    "failed\n");
   2933     0    stevel #endif	/* DEBUG */
   2934     0    stevel 			pool_seterror(POE_SYSTEM);
   2935     0    stevel 			return (PO_FAIL);
   2936     0    stevel 		}
   2937     0    stevel 		li->li_state = LS_UNDO;
   2938     0    stevel 		break;
   2939     0    stevel 	case POOL_PROPPUT:
   2940     0    stevel 		propput = (pool_propput_undo_t *)li->li_details;
   2941     0    stevel 
   2942     0    stevel 		if (pool_elem_class(propput->ppu_elem) != PEC_SYSTEM) {
   2943     0    stevel 			propput->ppu_ioctl.pp_o_id =
   2944     0    stevel 			    elem_get_sysid(propput->ppu_elem);
   2945     0    stevel 		}
   2946     0    stevel 		/*
   2947     0    stevel 		 * Some properties, e.g. pset.size, are read-only in the
   2948     0    stevel 		 * kernel and attempting to change them will fail and cause
   2949     0    stevel 		 * problems. Although this property is read-only through the
   2950     0    stevel 		 * public interface, the library needs to modify it's value.
   2951     0    stevel 		 */
   2952     0    stevel 		if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) {
   2953     0    stevel 			if (ioctl(prov->pkc_fd, POOL_PROPPUT,
   2954     0    stevel 			    &propput->ppu_ioctl) < 0) {
   2955     0    stevel 				pool_seterror(POE_SYSTEM);
   2956     0    stevel 				return (PO_FAIL);
   2957     0    stevel 			}
   2958     0    stevel 		}
   2959     0    stevel 		li->li_state = LS_UNDO;
   2960     0    stevel 		break;
   2961     0    stevel 	case POOL_PROPRM:
   2962     0    stevel 		proprm = (pool_proprm_undo_t *)li->li_details;
   2963     0    stevel 
   2964     0    stevel 		if (pool_elem_class(proprm->pru_elem) != PEC_SYSTEM) {
   2965     0    stevel 			proprm->pru_ioctl.pp_o_id =
   2966     0    stevel 			    elem_get_sysid(proprm->pru_elem);
   2967     0    stevel 		}
   2968     0    stevel 		if (ioctl(prov->pkc_fd, POOL_PROPRM, &proprm->pru_ioctl) < 0) {
   2969     0    stevel 			pool_seterror(POE_SYSTEM);
   2970     0    stevel 			return (PO_FAIL);
   2971     0    stevel 		}
   2972     0    stevel 		li->li_state = LS_UNDO;
   2973     0    stevel 		break;
   2974     0    stevel 	default:
   2975     0    stevel 		return (PO_FAIL);
   2976     0    stevel 	}
   2977     0    stevel 	return (PO_SUCCESS);
   2978     0    stevel }
   2979     0    stevel 
   2980     0    stevel /*
   2981     0    stevel  * Undo an individual transaction log item(). This processing is
   2982     0    stevel  * essential to the pool_conf_commit() and pool_conf_rollback()
   2983     0    stevel  * logic. Changes to the libpool snapshot and the kernel are carried
   2984     0    stevel  * out separately. The library snapshot is updated synchronously,
   2985     0    stevel  * however the kernel update is delayed until the user calls
   2986     0    stevel  * pool_conf_commit().
   2987     0    stevel  *
   2988     0    stevel  * When undoing transactions, library changes will be undone unless
   2989     0    stevel  * this invocation is as a result of a commit failure, in which case
   2990     0    stevel  * the log state will be LS_RECOVER. Kernel changes will only be
   2991     0    stevel  * undone if they are marked as having been done, in which case the
   2992     0    stevel  * log item state will be LS_UNDO.
   2993     0    stevel  */
   2994     0    stevel int
   2995     0    stevel log_item_undo(log_item_t *li)
   2996     0    stevel {
   2997     0