17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50209230bSgjelinek  * Common Development and Distribution License (the "License").
60209230bSgjelinek  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*5ad42b1bSSurya Prakki 
227c478bd9Sstevel@tonic-gate /*
23*5ad42b1bSSurya Prakki  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <assert.h>
287c478bd9Sstevel@tonic-gate #include <errno.h>
297c478bd9Sstevel@tonic-gate #include <exacct.h>
307c478bd9Sstevel@tonic-gate #include <fcntl.h>
317c478bd9Sstevel@tonic-gate #include <libnvpair.h>
327c478bd9Sstevel@tonic-gate #include <limits.h>
337c478bd9Sstevel@tonic-gate #include <poll.h>
347c478bd9Sstevel@tonic-gate #include <pool.h>
357c478bd9Sstevel@tonic-gate #include <stdlib.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <strings.h>
397c478bd9Sstevel@tonic-gate #include <stropts.h>
407c478bd9Sstevel@tonic-gate #include <thread.h>
417c478bd9Sstevel@tonic-gate #include <time.h>
427c478bd9Sstevel@tonic-gate #include <unistd.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include <libxml/tree.h>
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #include <sys/mman.h>
477c478bd9Sstevel@tonic-gate #include <sys/pool.h>
487c478bd9Sstevel@tonic-gate #include <sys/pool_impl.h>
497c478bd9Sstevel@tonic-gate #include <sys/priocntl.h>
507c478bd9Sstevel@tonic-gate #include <sys/stat.h>
517c478bd9Sstevel@tonic-gate #include <sys/time.h>
527c478bd9Sstevel@tonic-gate #include <sys/types.h>
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #include "dict.h"
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include "pool_internal.h"
577c478bd9Sstevel@tonic-gate #include "pool_impl.h"
587c478bd9Sstevel@tonic-gate #include "pool_kernel_impl.h"
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate  * libpool kernel Manipulation Routines
627c478bd9Sstevel@tonic-gate  *
637c478bd9Sstevel@tonic-gate  * pool_kernel.c implements the kernel manipulation routines used by the
647c478bd9Sstevel@tonic-gate  * libpool kernel datastore. The functions are grouped into the following
657c478bd9Sstevel@tonic-gate  * logical areas
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Device snapshot transfer buffer size
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate #define	KERNEL_SNAPSHOT_BUF_SZ	65535
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * Kernel result set's initial size. 8 is probably large enough for
767c478bd9Sstevel@tonic-gate  * most queries. Queries requiring more space are accomodated using
777c478bd9Sstevel@tonic-gate  * realloc on a per result set basis.
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate #define	KERNEL_RS_INITIAL_SZ	8
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * Property manipulation macros
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate #define	KERNEL_PROP_RDONLY	0x1
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * Information required to evaluate qualifying elements for a query
887c478bd9Sstevel@tonic-gate  */
897c478bd9Sstevel@tonic-gate struct query_obj {
907c478bd9Sstevel@tonic-gate 	const pool_conf_t *conf;
917c478bd9Sstevel@tonic-gate 	const pool_elem_t *src;
927c478bd9Sstevel@tonic-gate 	const char *src_attr;
937c478bd9Sstevel@tonic-gate 	pool_elem_class_t classes;
947c478bd9Sstevel@tonic-gate 	pool_value_t **props;
957c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *rs;
967c478bd9Sstevel@tonic-gate };
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * Identifies a pool element with a processor set id
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate typedef struct pool_set_xref {
1027c478bd9Sstevel@tonic-gate 	pool_knl_pool_t	*psx_pool;
1037c478bd9Sstevel@tonic-gate 	uint_t		psx_pset_id;
1047c478bd9Sstevel@tonic-gate 	struct pool_set_xref *psx_next;
1057c478bd9Sstevel@tonic-gate } pool_set_xref_t;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * Controls exacct snapshot load into libpool data structure
1097c478bd9Sstevel@tonic-gate  */
1107c478bd9Sstevel@tonic-gate typedef struct pool_snap_load {
1117c478bd9Sstevel@tonic-gate 	int *psl_changed;
1127c478bd9Sstevel@tonic-gate 	pool_set_xref_t *psl_xref;
1137c478bd9Sstevel@tonic-gate 	pool_elem_t *psl_system;
1147c478bd9Sstevel@tonic-gate 	pool_knl_resource_t *psl_pset;
1157c478bd9Sstevel@tonic-gate } pool_snap_load_t;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * Information about an XML document which is being constructed
1197c478bd9Sstevel@tonic-gate  */
1207c478bd9Sstevel@tonic-gate struct knl_to_xml {
1217c478bd9Sstevel@tonic-gate 	xmlDocPtr ktx_doc;
1227c478bd9Sstevel@tonic-gate 	xmlNodePtr ktx_node;
1237c478bd9Sstevel@tonic-gate };
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * Undo structure processing. The following structures are all used to
1277c478bd9Sstevel@tonic-gate  * allow changes to the libpool snapshot and kernel following an
1287c478bd9Sstevel@tonic-gate  * unsuccessful commit.
1297c478bd9Sstevel@tonic-gate  */
1307c478bd9Sstevel@tonic-gate typedef struct pool_create_undo {
1317c478bd9Sstevel@tonic-gate 	pool_create_t pcu_ioctl;
1327c478bd9Sstevel@tonic-gate 	pool_elem_t *pcu_elem;
1337c478bd9Sstevel@tonic-gate } pool_create_undo_t;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate typedef struct pool_destroy_undo {
1367c478bd9Sstevel@tonic-gate 	pool_destroy_t pdu_ioctl;
1377c478bd9Sstevel@tonic-gate 	pool_elem_t *pdu_elem;
1387c478bd9Sstevel@tonic-gate } pool_destroy_undo_t;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate typedef struct pool_assoc_undo {
1417c478bd9Sstevel@tonic-gate 	pool_assoc_t pau_ioctl;
1427c478bd9Sstevel@tonic-gate 	pool_elem_t *pau_assoc;
1437c478bd9Sstevel@tonic-gate 	pool_elem_t *pau_oldres;
1447c478bd9Sstevel@tonic-gate 	pool_elem_t *pau_newres;
1457c478bd9Sstevel@tonic-gate } pool_assoc_undo_t;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate typedef struct pool_dissoc_undo {
1487c478bd9Sstevel@tonic-gate 	pool_dissoc_t pdu_ioctl;
1497c478bd9Sstevel@tonic-gate 	pool_elem_t *pdu_dissoc;
1507c478bd9Sstevel@tonic-gate 	pool_elem_t *pdu_oldres;
1517c478bd9Sstevel@tonic-gate 	pool_elem_t *pdu_newres;
1527c478bd9Sstevel@tonic-gate } pool_dissoc_undo_t;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate typedef struct pool_xtransfer_undo {
1557c478bd9Sstevel@tonic-gate 	pool_xtransfer_t pxu_ioctl;
1567c478bd9Sstevel@tonic-gate 	pool_elem_t *pxu_src;
1577c478bd9Sstevel@tonic-gate 	pool_elem_t *pxu_tgt;
1587c478bd9Sstevel@tonic-gate 	pool_component_t **pxu_rl;
1597c478bd9Sstevel@tonic-gate } pool_xtransfer_undo_t;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate typedef struct pool_propput_undo {
1627c478bd9Sstevel@tonic-gate 	pool_propput_t ppu_ioctl;
1637c478bd9Sstevel@tonic-gate 	pool_elem_t *ppu_elem;
1647c478bd9Sstevel@tonic-gate 	nvlist_t *ppu_alist;
1657c478bd9Sstevel@tonic-gate 	nvlist_t *ppu_blist;
1667c478bd9Sstevel@tonic-gate 	uchar_t ppu_doioctl;
1677c478bd9Sstevel@tonic-gate } pool_propput_undo_t;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate typedef struct pool_proprm_undo {
1707c478bd9Sstevel@tonic-gate 	pool_proprm_t pru_ioctl;
1717c478bd9Sstevel@tonic-gate 	pool_elem_t *pru_elem;
1727c478bd9Sstevel@tonic-gate 	pool_value_t pru_oldval;
1737c478bd9Sstevel@tonic-gate } pool_proprm_undo_t;
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate extern const char *dtd_location;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate extern const char *element_class_tags[];
1787c478bd9Sstevel@tonic-gate extern const char pool_info_location[];
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate  * These functions are defined in pool_xml.c and represent the minimum
1827c478bd9Sstevel@tonic-gate  * XML support required to allow a pool kernel configuration to be
1837c478bd9Sstevel@tonic-gate  * exported as an XML document.
1847c478bd9Sstevel@tonic-gate  */
1857c478bd9Sstevel@tonic-gate extern int pool_xml_set_attr(xmlNodePtr, xmlChar *, const pool_value_t *);
1867c478bd9Sstevel@tonic-gate extern int pool_xml_set_prop(xmlNodePtr, xmlChar *, const pool_value_t *);
1877c478bd9Sstevel@tonic-gate extern void xml_init(void);
1887c478bd9Sstevel@tonic-gate extern xmlNodePtr node_create(xmlNodePtr, const xmlChar *);
1897c478bd9Sstevel@tonic-gate extern void pool_error_func(void *, const char *, ...);
1907c478bd9Sstevel@tonic-gate /*
1917c478bd9Sstevel@tonic-gate  * Utilities
1927c478bd9Sstevel@tonic-gate  */
1937c478bd9Sstevel@tonic-gate static int load_group(pool_conf_t *, pool_knl_elem_t *, ea_object_t *,
1947c478bd9Sstevel@tonic-gate     pool_snap_load_t *);
1957c478bd9Sstevel@tonic-gate static void pool_knl_elem_free(pool_knl_elem_t *, int);
1967c478bd9Sstevel@tonic-gate static int pool_knl_put_xml_property(pool_elem_t *, xmlNodePtr, const char *,
1977c478bd9Sstevel@tonic-gate     const pool_value_t *);
1987c478bd9Sstevel@tonic-gate static int pool_knl_snap_load_push(pool_snap_load_t *, pool_knl_pool_t *);
1997c478bd9Sstevel@tonic-gate static int pool_knl_snap_load_update(pool_snap_load_t *, int, uint_t);
2007c478bd9Sstevel@tonic-gate static int pool_knl_snap_load_remove(pool_snap_load_t *, int, uint_t);
2017c478bd9Sstevel@tonic-gate static nvpair_t *pool_knl_find_nvpair(nvlist_t *, const char *);
2027c478bd9Sstevel@tonic-gate static int pool_knl_nvlist_add_value(nvlist_t *, const char *,
2037c478bd9Sstevel@tonic-gate     const pool_value_t *);
2047c478bd9Sstevel@tonic-gate static int pool_knl_recover(pool_conf_t *);
2057c478bd9Sstevel@tonic-gate static uint64_t hash_id(const pool_elem_t *);
2067c478bd9Sstevel@tonic-gate static int blocking_open(const char *, int);
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate  * Connections
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate static void pool_knl_connection_free(pool_knl_connection_t *);
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate  * Configuration
2157c478bd9Sstevel@tonic-gate  */
2167c478bd9Sstevel@tonic-gate static int pool_knl_close(pool_conf_t *);
2177c478bd9Sstevel@tonic-gate static int pool_knl_validate(const pool_conf_t *, pool_valid_level_t);
2187c478bd9Sstevel@tonic-gate static int pool_knl_commit(pool_conf_t *);
2197c478bd9Sstevel@tonic-gate static int pool_knl_export(const pool_conf_t *, const char *,
2207c478bd9Sstevel@tonic-gate     pool_export_format_t);
2217c478bd9Sstevel@tonic-gate static int pool_knl_rollback(pool_conf_t *);
2227c478bd9Sstevel@tonic-gate static pool_result_set_t *pool_knl_exec_query(const pool_conf_t *,
2237c478bd9Sstevel@tonic-gate     const pool_elem_t *, const char *, pool_elem_class_t, pool_value_t **);
2247c478bd9Sstevel@tonic-gate static int pool_knl_remove(pool_conf_t *);
2257c478bd9Sstevel@tonic-gate static char *pool_knl_get_binding(pool_conf_t *, pid_t);
2267c478bd9Sstevel@tonic-gate static int pool_knl_set_binding(pool_conf_t *, const char *, idtype_t, id_t);
2277c478bd9Sstevel@tonic-gate static char *pool_knl_get_resource_binding(pool_conf_t *,
2287c478bd9Sstevel@tonic-gate     pool_resource_elem_class_t, pid_t);
2297c478bd9Sstevel@tonic-gate static int pool_knl_res_transfer(pool_resource_t *, pool_resource_t *,
2307c478bd9Sstevel@tonic-gate     uint64_t);
2317c478bd9Sstevel@tonic-gate static int pool_knl_res_xtransfer(pool_resource_t *, pool_resource_t *,
2327c478bd9Sstevel@tonic-gate     pool_component_t **);
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate  * Result Sets
2367c478bd9Sstevel@tonic-gate  */
2377c478bd9Sstevel@tonic-gate static pool_knl_result_set_t *pool_knl_result_set_alloc(const pool_conf_t *);
2387c478bd9Sstevel@tonic-gate static int pool_knl_result_set_append(pool_knl_result_set_t *,
2397c478bd9Sstevel@tonic-gate     pool_knl_elem_t *);
2407c478bd9Sstevel@tonic-gate static int pool_knl_result_set_realloc(pool_knl_result_set_t *);
2417c478bd9Sstevel@tonic-gate static void pool_knl_result_set_free(pool_knl_result_set_t *);
2427c478bd9Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_next(pool_result_set_t *);
2437c478bd9Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_prev(pool_result_set_t *);
2447c478bd9Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_first(pool_result_set_t *);
2457c478bd9Sstevel@tonic-gate static pool_elem_t *pool_knl_rs_last(pool_result_set_t *);
2467c478bd9Sstevel@tonic-gate static int pool_knl_rs_set_index(pool_result_set_t *, int);
2477c478bd9Sstevel@tonic-gate static int pool_knl_rs_get_index(pool_result_set_t *);
2487c478bd9Sstevel@tonic-gate static int pool_knl_rs_count(pool_result_set_t *);
2497c478bd9Sstevel@tonic-gate static int pool_knl_rs_close(pool_result_set_t *);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate  * Element (and sub-type)
2537c478bd9Sstevel@tonic-gate  */
2547c478bd9Sstevel@tonic-gate static pool_knl_elem_t *pool_knl_elem_wrap(pool_conf_t *, pool_elem_class_t,
2557c478bd9Sstevel@tonic-gate     pool_resource_elem_class_t, pool_component_elem_class_t);
2567c478bd9Sstevel@tonic-gate static pool_elem_t *pool_knl_elem_create(pool_conf_t *, pool_elem_class_t,
2577c478bd9Sstevel@tonic-gate     pool_resource_elem_class_t, pool_component_elem_class_t);
2587c478bd9Sstevel@tonic-gate static int pool_knl_elem_remove(pool_elem_t *);
2597c478bd9Sstevel@tonic-gate static int pool_knl_set_container(pool_elem_t *, pool_elem_t *);
2607c478bd9Sstevel@tonic-gate static pool_elem_t *pool_knl_get_container(const pool_elem_t *);
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate  * Pool element specific
2637c478bd9Sstevel@tonic-gate  */
2647c478bd9Sstevel@tonic-gate static int pool_knl_pool_associate(pool_t *, const pool_resource_t *);
2657c478bd9Sstevel@tonic-gate static int pool_knl_pool_dissociate(pool_t *, const pool_resource_t *);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate  * Resource elements specific
2697c478bd9Sstevel@tonic-gate  */
2707c478bd9Sstevel@tonic-gate static int pool_knl_resource_is_system(const pool_resource_t *);
2717c478bd9Sstevel@tonic-gate static int pool_knl_resource_can_associate(const pool_resource_t *);
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate /* Properties */
2747c478bd9Sstevel@tonic-gate static pool_value_class_t pool_knl_get_property(const pool_elem_t *,
2757c478bd9Sstevel@tonic-gate     const char *, pool_value_t *);
2767c478bd9Sstevel@tonic-gate static pool_value_class_t pool_knl_get_dynamic_property(const pool_elem_t *,
2777c478bd9Sstevel@tonic-gate     const char *, pool_value_t *);
2787c478bd9Sstevel@tonic-gate static int pool_knl_put_property(pool_elem_t *, const char *,
2797c478bd9Sstevel@tonic-gate     const pool_value_t *);
2807c478bd9Sstevel@tonic-gate static int pool_knl_rm_property(pool_elem_t *, const char *);
2817c478bd9Sstevel@tonic-gate static pool_value_t **pool_knl_get_properties(const pool_elem_t *, uint_t *);
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate  * Logging
2857c478bd9Sstevel@tonic-gate  */
2867c478bd9Sstevel@tonic-gate static int log_item_commit(log_item_t *);
2877c478bd9Sstevel@tonic-gate static int log_item_undo(log_item_t *);
2887c478bd9Sstevel@tonic-gate static int log_item_release(log_item_t *);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate /*
2917c478bd9Sstevel@tonic-gate  * Utilities
2927c478bd9Sstevel@tonic-gate  */
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate  * load_group() updates the library configuration with the kernel
2967c478bd9Sstevel@tonic-gate  * snapshot supplied in ep. The function is designed to be called
2977c478bd9Sstevel@tonic-gate  * recursively. This function depends implicitly on the ordering of
2987c478bd9Sstevel@tonic-gate  * the data provided in ep. Changes to the ordering of data in ep must
2997c478bd9Sstevel@tonic-gate  * be matched by changes to this function.
3007c478bd9Sstevel@tonic-gate  */
3017c478bd9Sstevel@tonic-gate int
3027c478bd9Sstevel@tonic-gate load_group(pool_conf_t *conf, pool_knl_elem_t *elem, ea_object_t *ep,
3037c478bd9Sstevel@tonic-gate     pool_snap_load_t *psl)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	ea_object_t *eo;
3067c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *old_elem;
3077c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
3087c478bd9Sstevel@tonic-gate 	int ret = PO_SUCCESS;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	if ((ep->eo_catalog & EXD_DATA_MASK) == EXD_GROUP_SYSTEM) {
3117c478bd9Sstevel@tonic-gate 		if ((elem = pool_knl_elem_wrap(conf, PEC_SYSTEM, PREC_INVALID,
3127c478bd9Sstevel@tonic-gate 		    PCEC_INVALID)) == NULL)
3137c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
3147c478bd9Sstevel@tonic-gate 		if (nvlist_alloc(&elem->pke_properties, NV_UNIQUE_NAME_TYPE,
3157c478bd9Sstevel@tonic-gate 		    0) != 0) {
3167c478bd9Sstevel@tonic-gate 			pool_knl_elem_free(elem, PO_FALSE);
3177c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
3187c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
3197c478bd9Sstevel@tonic-gate 		}
3207c478bd9Sstevel@tonic-gate 		/*
3217c478bd9Sstevel@tonic-gate 		 * Check to see if we already have an element
3227c478bd9Sstevel@tonic-gate 		 * for this data. If we have, free the newly
3237c478bd9Sstevel@tonic-gate 		 * created elem and continue with the old one
3247c478bd9Sstevel@tonic-gate 		 */
3257c478bd9Sstevel@tonic-gate 		if ((old_elem = dict_get(prov->pkc_elements, elem)) != NULL) {
3267c478bd9Sstevel@tonic-gate 			nvlist_free(old_elem->pke_properties);
3277c478bd9Sstevel@tonic-gate 			old_elem->pke_properties = elem->pke_properties;
3287c478bd9Sstevel@tonic-gate 			pool_knl_elem_free(elem, PO_FALSE);
3297c478bd9Sstevel@tonic-gate 			elem = old_elem;
3307c478bd9Sstevel@tonic-gate 		} else {
3317c478bd9Sstevel@tonic-gate 			if (dict_put(prov->pkc_elements, elem, elem) != NULL) {
3327c478bd9Sstevel@tonic-gate 				pool_knl_elem_free(elem, PO_TRUE);
3337c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
3347c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
3357c478bd9Sstevel@tonic-gate 			}
3367c478bd9Sstevel@tonic-gate 		}
3377c478bd9Sstevel@tonic-gate 		psl->psl_system = (pool_elem_t *)elem;
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	for (eo = ep->eo_group.eg_objs; eo != NULL; eo = eo->eo_next) {
3417c478bd9Sstevel@tonic-gate 		int data;
3427c478bd9Sstevel@tonic-gate 		pool_knl_elem_t *prop_elem = NULL;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 		data = (eo->eo_catalog & EXD_DATA_MASK);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 		switch (data) {
3477c478bd9Sstevel@tonic-gate 		case EXD_SYSTEM_TSTAMP:
3487c478bd9Sstevel@tonic-gate 		case EXD_POOL_TSTAMP:
3497c478bd9Sstevel@tonic-gate 		case EXD_PSET_TSTAMP:
3507c478bd9Sstevel@tonic-gate 		case EXD_CPU_TSTAMP:
3517c478bd9Sstevel@tonic-gate 			if (eo->eo_item.ei_uint64 > prov->pkc_lotime) {
3527c478bd9Sstevel@tonic-gate 				if (eo->eo_item.ei_uint64 > prov->pkc_ltime)
3537c478bd9Sstevel@tonic-gate 					prov->pkc_ltime = eo->eo_item.ei_uint64;
3547c478bd9Sstevel@tonic-gate 				if (psl->psl_changed) {
3557c478bd9Sstevel@tonic-gate 					switch (data) {
3567c478bd9Sstevel@tonic-gate 					case EXD_SYSTEM_TSTAMP:
3577c478bd9Sstevel@tonic-gate 						*psl->psl_changed |= POU_SYSTEM;
3587c478bd9Sstevel@tonic-gate 						break;
3597c478bd9Sstevel@tonic-gate 					case EXD_POOL_TSTAMP:
3607c478bd9Sstevel@tonic-gate 						*psl->psl_changed |= POU_POOL;
3617c478bd9Sstevel@tonic-gate 						break;
3627c478bd9Sstevel@tonic-gate 					case EXD_PSET_TSTAMP:
3637c478bd9Sstevel@tonic-gate 						*psl->psl_changed |= POU_PSET;
3647c478bd9Sstevel@tonic-gate 						break;
3657c478bd9Sstevel@tonic-gate 					case EXD_CPU_TSTAMP:
3667c478bd9Sstevel@tonic-gate 						*psl->psl_changed |= POU_CPU;
3677c478bd9Sstevel@tonic-gate 						break;
3687c478bd9Sstevel@tonic-gate 					}
3697c478bd9Sstevel@tonic-gate 				}
3707c478bd9Sstevel@tonic-gate 			}
3717c478bd9Sstevel@tonic-gate 			break;
3727c478bd9Sstevel@tonic-gate 		case EXD_SYSTEM_PROP:
3737c478bd9Sstevel@tonic-gate 		case EXD_POOL_PROP:
3747c478bd9Sstevel@tonic-gate 		case EXD_PSET_PROP:
3757c478bd9Sstevel@tonic-gate 		case EXD_CPU_PROP:
3767c478bd9Sstevel@tonic-gate 			if (data == EXD_PSET_PROP) {
3777c478bd9Sstevel@tonic-gate 				prop_elem = elem;
3787c478bd9Sstevel@tonic-gate 				elem = (pool_knl_elem_t *)psl->psl_pset;
3797c478bd9Sstevel@tonic-gate 			}
3807c478bd9Sstevel@tonic-gate 			nvlist_free(elem->pke_properties);
3817c478bd9Sstevel@tonic-gate 			if (nvlist_unpack(eo->eo_item.ei_raw,
3827c478bd9Sstevel@tonic-gate 			    eo->eo_item.ei_size, &elem->pke_properties, 0) !=
3837c478bd9Sstevel@tonic-gate 			    0) {
3847c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
3857c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
3867c478bd9Sstevel@tonic-gate 			}
3877c478bd9Sstevel@tonic-gate 			elem->pke_ltime = prov->pkc_ltime;
3887c478bd9Sstevel@tonic-gate 			if (data == EXD_PSET_PROP) {
3897c478bd9Sstevel@tonic-gate 				elem = prop_elem;
3907c478bd9Sstevel@tonic-gate 			}
3917c478bd9Sstevel@tonic-gate 			break;
3927c478bd9Sstevel@tonic-gate 		case EXD_POOL_POOLID:
3937c478bd9Sstevel@tonic-gate 			if (nvlist_alloc(&elem->pke_properties,
3947c478bd9Sstevel@tonic-gate 			    NV_UNIQUE_NAME_TYPE, 0) != 0) {
3957c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
3967c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
3977c478bd9Sstevel@tonic-gate 			}
3987c478bd9Sstevel@tonic-gate 			if (nvlist_add_int64(elem->pke_properties,
3997c478bd9Sstevel@tonic-gate 			    "pool.sys_id",
4007c478bd9Sstevel@tonic-gate 			    (int64_t)eo->eo_item.ei_uint32) != 0) {
4017c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
4027c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4037c478bd9Sstevel@tonic-gate 			}
4047c478bd9Sstevel@tonic-gate 			if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
4057c478bd9Sstevel@tonic-gate 			    NULL) {
4067c478bd9Sstevel@tonic-gate 				nvlist_free(old_elem->pke_properties);
4077c478bd9Sstevel@tonic-gate 				old_elem->pke_properties = elem->pke_properties;
4087c478bd9Sstevel@tonic-gate 				pool_knl_elem_free(elem, PO_FALSE);
4097c478bd9Sstevel@tonic-gate 				elem = old_elem;
4107c478bd9Sstevel@tonic-gate 			} else {
4117c478bd9Sstevel@tonic-gate 				if (dict_put(prov->pkc_elements, elem, elem) !=
4127c478bd9Sstevel@tonic-gate 				    NULL) {
4137c478bd9Sstevel@tonic-gate 					pool_knl_elem_free(elem, PO_TRUE);
4147c478bd9Sstevel@tonic-gate 					pool_seterror(POE_SYSTEM);
4157c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
4167c478bd9Sstevel@tonic-gate 				}
4177c478bd9Sstevel@tonic-gate 			}
4187c478bd9Sstevel@tonic-gate 			if (pool_knl_snap_load_push(psl,
4197c478bd9Sstevel@tonic-gate 			    (pool_knl_pool_t *)elem) != PO_SUCCESS) {
4207c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
4217c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4227c478bd9Sstevel@tonic-gate 			}
4237c478bd9Sstevel@tonic-gate 			((pool_knl_pool_t *)elem)->pkp_assoc[PREC_PSET] = NULL;
4247c478bd9Sstevel@tonic-gate 			break;
4257c478bd9Sstevel@tonic-gate 		case EXD_POOL_PSETID:
4267c478bd9Sstevel@tonic-gate 			if (pool_knl_snap_load_update(psl, EXD_POOL_PSETID,
4277c478bd9Sstevel@tonic-gate 			    eo->eo_item.ei_uint32) != PO_SUCCESS) {
4287c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
4297c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4307c478bd9Sstevel@tonic-gate 			}
4317c478bd9Sstevel@tonic-gate 			break;
4327c478bd9Sstevel@tonic-gate 		case EXD_PSET_PSETID:
4337c478bd9Sstevel@tonic-gate 			if (nvlist_alloc(&elem->pke_properties,
4347c478bd9Sstevel@tonic-gate 			    NV_UNIQUE_NAME_TYPE, 0) != 0) {
4357c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
4367c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4377c478bd9Sstevel@tonic-gate 			}
4387c478bd9Sstevel@tonic-gate 			if (nvlist_add_int64(elem->pke_properties,
4397c478bd9Sstevel@tonic-gate 			    "pset.sys_id",
4407c478bd9Sstevel@tonic-gate 			    (int64_t)eo->eo_item.ei_uint32) != 0) {
4417c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
4427c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4437c478bd9Sstevel@tonic-gate 			}
4447c478bd9Sstevel@tonic-gate 			if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
4457c478bd9Sstevel@tonic-gate 			    NULL) {
4467c478bd9Sstevel@tonic-gate 				nvlist_free(old_elem->pke_properties);
4477c478bd9Sstevel@tonic-gate 				old_elem->pke_properties = elem->pke_properties;
4487c478bd9Sstevel@tonic-gate 				pool_knl_elem_free(elem, PO_FALSE);
4497c478bd9Sstevel@tonic-gate 				elem = old_elem;
4507c478bd9Sstevel@tonic-gate 			} else {
4517c478bd9Sstevel@tonic-gate 				if (dict_put(prov->pkc_elements, elem, elem) !=
4527c478bd9Sstevel@tonic-gate 				    NULL) {
4537c478bd9Sstevel@tonic-gate 					pool_knl_elem_free(elem, PO_TRUE);
4547c478bd9Sstevel@tonic-gate 					pool_seterror(POE_SYSTEM);
4557c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
4567c478bd9Sstevel@tonic-gate 				}
4577c478bd9Sstevel@tonic-gate 			}
4587c478bd9Sstevel@tonic-gate 			psl->psl_pset = (pool_knl_resource_t *)elem;
4597c478bd9Sstevel@tonic-gate 			if (pool_knl_snap_load_remove(psl, data,
4607c478bd9Sstevel@tonic-gate 			    eo->eo_item.ei_uint32) != PO_SUCCESS) {
4617c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
4627c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4637c478bd9Sstevel@tonic-gate 			}
4647c478bd9Sstevel@tonic-gate 			break;
4657c478bd9Sstevel@tonic-gate 		case EXD_CPU_CPUID:
4667c478bd9Sstevel@tonic-gate 			if (nvlist_alloc(&elem->pke_properties,
4677c478bd9Sstevel@tonic-gate 			    NV_UNIQUE_NAME_TYPE, 0) != 0) {
4687c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
4697c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4707c478bd9Sstevel@tonic-gate 			}
4717c478bd9Sstevel@tonic-gate 			if (nvlist_add_int64(elem->pke_properties,
4727c478bd9Sstevel@tonic-gate 			    "cpu.sys_id",
4737c478bd9Sstevel@tonic-gate 			    (int64_t)eo->eo_item.ei_uint32) != 0) {
4747c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
4757c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4767c478bd9Sstevel@tonic-gate 			}
4777c478bd9Sstevel@tonic-gate 			if ((old_elem = dict_get(prov->pkc_elements, elem)) !=
4787c478bd9Sstevel@tonic-gate 			    NULL) {
4797c478bd9Sstevel@tonic-gate 				nvlist_free(old_elem->pke_properties);
4807c478bd9Sstevel@tonic-gate 				old_elem->pke_properties = elem->pke_properties;
4817c478bd9Sstevel@tonic-gate 				old_elem->pke_parent = elem->pke_parent;
4827c478bd9Sstevel@tonic-gate 				pool_knl_elem_free(elem, PO_FALSE);
4837c478bd9Sstevel@tonic-gate 				elem = old_elem;
4847c478bd9Sstevel@tonic-gate 			} else {
4857c478bd9Sstevel@tonic-gate 				if (dict_put(prov->pkc_elements, elem, elem) !=
4867c478bd9Sstevel@tonic-gate 				    NULL) {
4877c478bd9Sstevel@tonic-gate 					pool_knl_elem_free(elem, PO_TRUE);
4887c478bd9Sstevel@tonic-gate 					pool_seterror(POE_SYSTEM);
4897c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
4907c478bd9Sstevel@tonic-gate 				}
4917c478bd9Sstevel@tonic-gate 			}
4927c478bd9Sstevel@tonic-gate 			break;
4937c478bd9Sstevel@tonic-gate 		case EXD_GROUP_POOL:
4947c478bd9Sstevel@tonic-gate 			if ((elem = pool_knl_elem_wrap(conf, PEC_POOL,
4957c478bd9Sstevel@tonic-gate 			    PREC_INVALID, PCEC_INVALID)) == NULL)
4967c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
4977c478bd9Sstevel@tonic-gate 			if (pool_set_container(psl->psl_system,
4987c478bd9Sstevel@tonic-gate 			    (pool_elem_t *)elem) != PO_SUCCESS) {
4997c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
5007c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5017c478bd9Sstevel@tonic-gate 			}
5027c478bd9Sstevel@tonic-gate 			break;
5037c478bd9Sstevel@tonic-gate 		case EXD_GROUP_PSET:
5047c478bd9Sstevel@tonic-gate 			if ((elem = pool_knl_elem_wrap(conf, PEC_RES_COMP,
5057c478bd9Sstevel@tonic-gate 			    PREC_PSET, PCEC_INVALID)) == NULL)
5067c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5077c478bd9Sstevel@tonic-gate 			if (pool_set_container(psl->psl_system,
5087c478bd9Sstevel@tonic-gate 			    (pool_elem_t *)elem) != PO_SUCCESS) {
5097c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
5107c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5117c478bd9Sstevel@tonic-gate 			}
5127c478bd9Sstevel@tonic-gate 			break;
5137c478bd9Sstevel@tonic-gate 		case EXD_GROUP_CPU:
5147c478bd9Sstevel@tonic-gate 			if ((elem = pool_knl_elem_wrap(conf, PEC_COMP,
5157c478bd9Sstevel@tonic-gate 			    PREC_INVALID, PCEC_CPU)) == NULL)
5167c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5177c478bd9Sstevel@tonic-gate 			if (pool_set_container((pool_elem_t *)psl->psl_pset,
5187c478bd9Sstevel@tonic-gate 			    (pool_elem_t *)elem) != PO_SUCCESS) {
5197c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
5207c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
5217c478bd9Sstevel@tonic-gate 			}
5227c478bd9Sstevel@tonic-gate 			break;
5237c478bd9Sstevel@tonic-gate 		default:
5247c478bd9Sstevel@tonic-gate 			break;
5257c478bd9Sstevel@tonic-gate 		}
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 		if (eo->eo_type == EO_GROUP) {
5297c478bd9Sstevel@tonic-gate 			if ((ret = load_group(conf, elem, eo, psl)) == PO_FAIL)
5307c478bd9Sstevel@tonic-gate 				break;
5317c478bd9Sstevel@tonic-gate 		}
5327c478bd9Sstevel@tonic-gate 	}
5337c478bd9Sstevel@tonic-gate 	return (ret);
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate /*
5377c478bd9Sstevel@tonic-gate  * Push a snapshot entry onto the list of pools in the snapshot.
5387c478bd9Sstevel@tonic-gate  */
5397c478bd9Sstevel@tonic-gate int
5407c478bd9Sstevel@tonic-gate pool_knl_snap_load_push(pool_snap_load_t *psl, pool_knl_pool_t *pkp)
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate 	pool_set_xref_t *psx;
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	if ((psx = malloc(sizeof (pool_set_xref_t))) == NULL) {
5457c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
5467c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
5477c478bd9Sstevel@tonic-gate 	}
5487c478bd9Sstevel@tonic-gate 	(void) memset(psx, 0, sizeof (pool_set_xref_t));
5497c478bd9Sstevel@tonic-gate 	psx->psx_pool = pkp;
5507c478bd9Sstevel@tonic-gate 	/*
5517c478bd9Sstevel@tonic-gate 	 * Push onto the list of pools
5527c478bd9Sstevel@tonic-gate 	 */
5537c478bd9Sstevel@tonic-gate 	psx->psx_next = psl->psl_xref;
5547c478bd9Sstevel@tonic-gate 	psl->psl_xref = psx;
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate  * Update the current cross-reference for the supplied type of
5617c478bd9Sstevel@tonic-gate  * resource.
5627c478bd9Sstevel@tonic-gate  */
5637c478bd9Sstevel@tonic-gate int
5647c478bd9Sstevel@tonic-gate pool_knl_snap_load_update(pool_snap_load_t *psl, int type, uint_t id)
5657c478bd9Sstevel@tonic-gate {
5667c478bd9Sstevel@tonic-gate 	switch (type) {
5677c478bd9Sstevel@tonic-gate 	case EXD_POOL_PSETID:
5687c478bd9Sstevel@tonic-gate 		psl->psl_xref->psx_pset_id = id;
5697c478bd9Sstevel@tonic-gate 		break;
5707c478bd9Sstevel@tonic-gate 	default:
5717c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
5727c478bd9Sstevel@tonic-gate 	}
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate /*
5787c478bd9Sstevel@tonic-gate  * Remove a resource entry with the supplied type and id from the
5797c478bd9Sstevel@tonic-gate  * snapshot list when it is no longer required.
5807c478bd9Sstevel@tonic-gate  */
5817c478bd9Sstevel@tonic-gate int
5827c478bd9Sstevel@tonic-gate pool_knl_snap_load_remove(pool_snap_load_t *psl, int type, uint_t id)
5837c478bd9Sstevel@tonic-gate {
5847c478bd9Sstevel@tonic-gate 	pool_set_xref_t *current, *prev, *next;
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	for (prev = NULL, current = psl->psl_xref; current != NULL;
5877c478bd9Sstevel@tonic-gate 	    current = next) {
5887c478bd9Sstevel@tonic-gate 		switch (type) {
5897c478bd9Sstevel@tonic-gate 		case EXD_PSET_PSETID:
5907c478bd9Sstevel@tonic-gate 			if (current->psx_pset_id == id)
5917c478bd9Sstevel@tonic-gate 				current->psx_pool->pkp_assoc[PREC_PSET] =
5927c478bd9Sstevel@tonic-gate 				    psl->psl_pset;
5937c478bd9Sstevel@tonic-gate 			break;
5947c478bd9Sstevel@tonic-gate 		default:
5957c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
5967c478bd9Sstevel@tonic-gate 		}
5977c478bd9Sstevel@tonic-gate 		next = current->psx_next;
5987c478bd9Sstevel@tonic-gate 		if (current->psx_pool->pkp_assoc[PREC_PSET] != NULL) {
5997c478bd9Sstevel@tonic-gate 			if (prev != NULL) {
6007c478bd9Sstevel@tonic-gate 				prev->psx_next = current->psx_next;
6017c478bd9Sstevel@tonic-gate 			} else {
6027c478bd9Sstevel@tonic-gate 				psl->psl_xref = current->psx_next;
6037c478bd9Sstevel@tonic-gate 			}
6047c478bd9Sstevel@tonic-gate 			free(current);
6057c478bd9Sstevel@tonic-gate 		} else
6067c478bd9Sstevel@tonic-gate 			prev = current;
6077c478bd9Sstevel@tonic-gate 	}
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate /*
6137c478bd9Sstevel@tonic-gate  * Return the nvpair with the supplied name from the supplied list.
6147c478bd9Sstevel@tonic-gate  *
6157c478bd9Sstevel@tonic-gate  * NULL is returned if the name cannot be found in the list.
6167c478bd9Sstevel@tonic-gate  */
6177c478bd9Sstevel@tonic-gate nvpair_t *
6187c478bd9Sstevel@tonic-gate pool_knl_find_nvpair(nvlist_t *l, const char *name)
6197c478bd9Sstevel@tonic-gate {
6207c478bd9Sstevel@tonic-gate 	nvpair_t *pair;
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	for (pair = nvlist_next_nvpair(l, NULL); pair != NULL;
623*5ad42b1bSSurya Prakki 	    pair = nvlist_next_nvpair(l, pair)) {
6247c478bd9Sstevel@tonic-gate 		if (strcmp(nvpair_name(pair), name) == 0)
6257c478bd9Sstevel@tonic-gate 			break;
6267c478bd9Sstevel@tonic-gate 	}
6277c478bd9Sstevel@tonic-gate 	return (pair);
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate /*
6317c478bd9Sstevel@tonic-gate  * Close the configuration. There are a few steps to closing a configuration:
6327c478bd9Sstevel@tonic-gate  * - Close the pseudo device
6337c478bd9Sstevel@tonic-gate  * - Free the data provider
6347c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
6357c478bd9Sstevel@tonic-gate  */
6367c478bd9Sstevel@tonic-gate int
6377c478bd9Sstevel@tonic-gate pool_knl_close(pool_conf_t *conf)
6387c478bd9Sstevel@tonic-gate {
6397c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	if (close(prov->pkc_fd) < 0) {
6427c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
6437c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
6447c478bd9Sstevel@tonic-gate 	}
6457c478bd9Sstevel@tonic-gate 	/*
6467c478bd9Sstevel@tonic-gate 	 * Rollback any pending changes before freeing the prov. This
6470209230bSgjelinek 	 * ensures there are no memory leaks from pending transactions.
6480209230bSgjelinek 	 * However, don't rollback when we've done a temporary pool since the
6490209230bSgjelinek 	 * pool/resources haven't really been committed in this case.
6500209230bSgjelinek 	 * They will all be freed in pool_knl_connection_free and we don't
6510209230bSgjelinek 	 * want to double free them.
6527c478bd9Sstevel@tonic-gate 	 */
6530209230bSgjelinek 	if (!(conf->pc_prov->pc_oflags & PO_TEMP))
6540209230bSgjelinek 		(void) pool_knl_rollback(conf);
6557c478bd9Sstevel@tonic-gate 	pool_knl_connection_free(prov);
6567c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate /*
6607c478bd9Sstevel@tonic-gate  * Remove elements in this map (previously identified as "dead") from
6617c478bd9Sstevel@tonic-gate  * the configuration map (prov->pkc_elements).
6627c478bd9Sstevel@tonic-gate  */
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
6657c478bd9Sstevel@tonic-gate static void
6667c478bd9Sstevel@tonic-gate remove_dead_elems(const void *key, void **value, void *cl)
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
6697c478bd9Sstevel@tonic-gate 	pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
6707c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	assert(dict_remove(prov->pkc_elements, pke) != NULL);
6737c478bd9Sstevel@tonic-gate #ifdef DEBUG
6747c478bd9Sstevel@tonic-gate 	dprintf("remove_dead_elems:\n");
6757c478bd9Sstevel@tonic-gate 	pool_elem_dprintf(TO_ELEM(pke));
6767c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
6777c478bd9Sstevel@tonic-gate 	pool_knl_elem_free(pke, PO_TRUE);
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /*
6817c478bd9Sstevel@tonic-gate  * Find elements which were not updated the last time that
6827c478bd9Sstevel@tonic-gate  * load_group() was called. Add those elements into a separate map
6837c478bd9Sstevel@tonic-gate  * (passed in cl) which will be later used to remove these elements
6847c478bd9Sstevel@tonic-gate  * from the configuration map.
6857c478bd9Sstevel@tonic-gate  */
6867c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
6877c478bd9Sstevel@tonic-gate static void
6887c478bd9Sstevel@tonic-gate find_dead_elems(const void *key, void **value, void *cl)
6897c478bd9Sstevel@tonic-gate {
6907c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
6917c478bd9Sstevel@tonic-gate 	pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
6927c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
6937c478bd9Sstevel@tonic-gate 	dict_hdl_t *dead_map = (dict_hdl_t *)cl;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	if (pke->pke_ltime < prov->pkc_ltime)
6967c478bd9Sstevel@tonic-gate 		(void) dict_put(dead_map, pke, pke);
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate  * Update the snapshot held by the library. This function acts as the
7017c478bd9Sstevel@tonic-gate  * controller for the snapshot update procedure. Then snapshot is
7027c478bd9Sstevel@tonic-gate  * actually updated in multiple phases by the load_group() function
7037c478bd9Sstevel@tonic-gate  * (which updates existing elements and creates new elements as
7047c478bd9Sstevel@tonic-gate  * required) and then by find_dead_elems and remove_dead_elems
7057c478bd9Sstevel@tonic-gate  * (respectively responsible for identifying elements which are to be
7067c478bd9Sstevel@tonic-gate  * removed and then removing them).
7077c478bd9Sstevel@tonic-gate  *
7087c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS
7097c478bd9Sstevel@tonic-gate  */
7107c478bd9Sstevel@tonic-gate int
7117c478bd9Sstevel@tonic-gate pool_knl_update(pool_conf_t *conf, int *changed)
7127c478bd9Sstevel@tonic-gate {
7137c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
7147c478bd9Sstevel@tonic-gate 	pool_query_t query = {0};
7157c478bd9Sstevel@tonic-gate 	ea_object_t *ep;
7167c478bd9Sstevel@tonic-gate 	dict_hdl_t *dead_map;
7177c478bd9Sstevel@tonic-gate 	pool_snap_load_t psl = { NULL };
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	/*
7207c478bd9Sstevel@tonic-gate 	 * Ensure the library snapshot is consistent, if there are any
7217c478bd9Sstevel@tonic-gate 	 * outstanding transactions return failure.
7227c478bd9Sstevel@tonic-gate 	 */
7237c478bd9Sstevel@tonic-gate 	if (log_size(prov->pkc_log) != 0) {
7247c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
7257c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 	/*
7287c478bd9Sstevel@tonic-gate 	 * Query the kernel for a snapshot of the configuration state. Use
7297c478bd9Sstevel@tonic-gate 	 * load_group to allocate the user-land representation of the
7307c478bd9Sstevel@tonic-gate 	 * data returned in the snapshot.
7317c478bd9Sstevel@tonic-gate 	 */
7327c478bd9Sstevel@tonic-gate 	/* LINTED E_CONSTANT_CONDITION */
7337c478bd9Sstevel@tonic-gate 	while (1) {
7347c478bd9Sstevel@tonic-gate 		if (ioctl(prov->pkc_fd, POOL_QUERY, &query) < 0) {
7357c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
7367c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
7377c478bd9Sstevel@tonic-gate 		}
7387c478bd9Sstevel@tonic-gate 		if ((query.pq_io_buf = calloc(1,
7397c478bd9Sstevel@tonic-gate 		    (query.pq_io_bufsize < KERNEL_SNAPSHOT_BUF_SZ) ?
7407c478bd9Sstevel@tonic-gate 		    query.pq_io_bufsize * 2 : query.pq_io_bufsize)) == NULL) {
7417c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
7427c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
7437c478bd9Sstevel@tonic-gate 		}
7447c478bd9Sstevel@tonic-gate 		if (ioctl(prov->pkc_fd, POOL_QUERY, &query) < 0) {
7457c478bd9Sstevel@tonic-gate 			free(query.pq_io_buf);
7467c478bd9Sstevel@tonic-gate 			if (errno != ENOMEM) {
7477c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
7487c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
7497c478bd9Sstevel@tonic-gate 			}
7507c478bd9Sstevel@tonic-gate 			query.pq_io_bufsize = 0;
7517c478bd9Sstevel@tonic-gate 			query.pq_io_buf = NULL;
7527c478bd9Sstevel@tonic-gate 		} else
7537c478bd9Sstevel@tonic-gate 			break;
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 	if (ea_unpack_object(&ep, EUP_NOALLOC, query.pq_io_buf,
7567c478bd9Sstevel@tonic-gate 	    query.pq_io_bufsize) != EO_GROUP) {
7577c478bd9Sstevel@tonic-gate 		free(query.pq_io_buf);
7587c478bd9Sstevel@tonic-gate 		pool_seterror(POE_DATASTORE);
7597c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
7607c478bd9Sstevel@tonic-gate 	}
7617c478bd9Sstevel@tonic-gate 	/*
7627c478bd9Sstevel@tonic-gate 	 * Update the library snapshot
7637c478bd9Sstevel@tonic-gate 	 */
7647c478bd9Sstevel@tonic-gate 	psl.psl_changed = changed;
7657c478bd9Sstevel@tonic-gate 	prov->pkc_lotime = prov->pkc_ltime;
7667c478bd9Sstevel@tonic-gate 	if (load_group(conf, NULL, ep, &psl) != PO_SUCCESS) {
7677c478bd9Sstevel@tonic-gate 		free(query.pq_io_buf);
7687c478bd9Sstevel@tonic-gate 		ea_free_object(ep, EUP_NOALLOC);
7697c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
7707c478bd9Sstevel@tonic-gate 	}
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	free(query.pq_io_buf);
7737c478bd9Sstevel@tonic-gate 	ea_free_object(ep, EUP_NOALLOC);
7747c478bd9Sstevel@tonic-gate 	/*
7757c478bd9Sstevel@tonic-gate 	 * Now search the dictionary for items that must be removed because
7767c478bd9Sstevel@tonic-gate 	 * they were neither created nor updated.
7777c478bd9Sstevel@tonic-gate 	 */
7787c478bd9Sstevel@tonic-gate 	if ((dead_map = dict_new((int (*)(const void *, const void *))
7797c478bd9Sstevel@tonic-gate 	    pool_elem_compare, (uint64_t (*)(const void *))hash_id)) == NULL) {
7807c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
7817c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
7827c478bd9Sstevel@tonic-gate 	}
7837c478bd9Sstevel@tonic-gate 	dict_map(prov->pkc_elements, find_dead_elems, dead_map);
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	if (dict_length(dead_map) > 0) {
7867c478bd9Sstevel@tonic-gate 		dict_map(dead_map, remove_dead_elems, NULL);
7877c478bd9Sstevel@tonic-gate 	}
7887c478bd9Sstevel@tonic-gate 	dict_free(&dead_map);
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate /*
7947c478bd9Sstevel@tonic-gate  * Rely on the kernel to always keep a kernel configuration valid.
7957c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS
7967c478bd9Sstevel@tonic-gate  */
7977c478bd9Sstevel@tonic-gate /* ARGSUSED */
7987c478bd9Sstevel@tonic-gate int
7997c478bd9Sstevel@tonic-gate pool_knl_validate(const pool_conf_t *conf, pool_valid_level_t level)
8007c478bd9Sstevel@tonic-gate {
8017c478bd9Sstevel@tonic-gate 	return ((conf->pc_state == POF_INVALID) ? PO_FAIL : PO_SUCCESS);
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate /*
8057c478bd9Sstevel@tonic-gate  * Process all the outstanding transactions in the log. If the processing
8067c478bd9Sstevel@tonic-gate  * fails, then attempt to rollback and "undo" the changes.
8077c478bd9Sstevel@tonic-gate  */
8087c478bd9Sstevel@tonic-gate int
8097c478bd9Sstevel@tonic-gate pool_knl_commit(pool_conf_t *conf)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
8127c478bd9Sstevel@tonic-gate 	int lock = 1;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	/*
8157c478bd9Sstevel@tonic-gate 	 * Lock the kernel state for the commit
8167c478bd9Sstevel@tonic-gate 	 */
8177c478bd9Sstevel@tonic-gate 	if (ioctl(prov->pkc_fd, POOL_COMMIT, lock) < 0) {
8187c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
8197c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
8207c478bd9Sstevel@tonic-gate 	}
8217c478bd9Sstevel@tonic-gate 	lock = 0;
8227c478bd9Sstevel@tonic-gate 	/*
8237c478bd9Sstevel@tonic-gate 	 * If the state is LS_FAIL, then try to recover before
8247c478bd9Sstevel@tonic-gate 	 * performing the commit.
8257c478bd9Sstevel@tonic-gate 	 */
8267c478bd9Sstevel@tonic-gate 	if (prov->pkc_log->l_state == LS_FAIL) {
8277c478bd9Sstevel@tonic-gate 		if (pool_knl_recover(conf) == PO_FAIL) {
8287c478bd9Sstevel@tonic-gate 			/*
8297c478bd9Sstevel@tonic-gate 			 * Unlock the kernel state for the
8307c478bd9Sstevel@tonic-gate 			 * commit. Assert that this * can't fail,
8317c478bd9Sstevel@tonic-gate 			 * since if it ever does fail the library is
8327c478bd9Sstevel@tonic-gate 			 * unusable.
8337c478bd9Sstevel@tonic-gate 			 */
8347c478bd9Sstevel@tonic-gate 			assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
8357c478bd9Sstevel@tonic-gate 		}
8367c478bd9Sstevel@tonic-gate 	}
8377c478bd9Sstevel@tonic-gate 	/*
8387c478bd9Sstevel@tonic-gate 	 * Commit the log
8397c478bd9Sstevel@tonic-gate 	 */
8407c478bd9Sstevel@tonic-gate 	if (log_walk(prov->pkc_log, log_item_commit) != PO_SUCCESS) {
8417c478bd9Sstevel@tonic-gate 		(void) pool_knl_recover(conf);
8427c478bd9Sstevel@tonic-gate 		/*
8437c478bd9Sstevel@tonic-gate 		 * Unlock the kernel state for the commit. Assert that
8447c478bd9Sstevel@tonic-gate 		 * this can't fail, since if it ever does fail the
8457c478bd9Sstevel@tonic-gate 		 * library is unusable.
8467c478bd9Sstevel@tonic-gate 		 */
8477c478bd9Sstevel@tonic-gate 		assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
8487c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
8497c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
8507c478bd9Sstevel@tonic-gate 	}
8517c478bd9Sstevel@tonic-gate 	/*
8527c478bd9Sstevel@tonic-gate 	 * Unlock the kernel state for the commit. Assert that this
8537c478bd9Sstevel@tonic-gate 	 * can't fail, since if it ever does fail the library is
8547c478bd9Sstevel@tonic-gate 	 * unusable.
8557c478bd9Sstevel@tonic-gate 	 */
8567c478bd9Sstevel@tonic-gate 	assert(ioctl(prov->pkc_fd, POOL_COMMIT, lock) >= 0);
8577c478bd9Sstevel@tonic-gate 	/*
8587c478bd9Sstevel@tonic-gate 	 * Release the log resources
8597c478bd9Sstevel@tonic-gate 	 */
8607c478bd9Sstevel@tonic-gate 	(void) log_walk(prov->pkc_log, log_item_release);
8617c478bd9Sstevel@tonic-gate 	log_empty(prov->pkc_log);
8627c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate /*
8667c478bd9Sstevel@tonic-gate  * prop_build_cb() is designed to be called from
8677c478bd9Sstevel@tonic-gate  * pool_walk_properties(). The property value is used to put an XML
8687c478bd9Sstevel@tonic-gate  * property on the supplied ktx_node. This is an essential part of the
8697c478bd9Sstevel@tonic-gate  * mechanism used to export a kernel configuration in libpool XML
8707c478bd9Sstevel@tonic-gate  * form.
8717c478bd9Sstevel@tonic-gate  */
8727c478bd9Sstevel@tonic-gate /* ARGSUSED */
8737c478bd9Sstevel@tonic-gate static int
8747c478bd9Sstevel@tonic-gate prop_build_cb(pool_conf_t *UNUSED, pool_elem_t *pe, const char *name,
8757c478bd9Sstevel@tonic-gate     pool_value_t *pval, void *user)
8767c478bd9Sstevel@tonic-gate {
8777c478bd9Sstevel@tonic-gate 	struct knl_to_xml *info = (struct knl_to_xml *)user;
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	return (pool_knl_put_xml_property((pool_elem_t *)pe, info->ktx_node,
880*5ad42b1bSSurya Prakki 	    name, pval));
8817c478bd9Sstevel@tonic-gate }
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate /*
8847c478bd9Sstevel@tonic-gate  * Duplicate some of the functionality from pool_xml_put_property()
8857c478bd9Sstevel@tonic-gate  * (see pool_xml.c) to allow a kernel configuration to add XML nodes
8867c478bd9Sstevel@tonic-gate  * to an XML tree which represents the kernel configuration. This is
8877c478bd9Sstevel@tonic-gate  * an essential part of the mechanism used to export a kernel
8887c478bd9Sstevel@tonic-gate  * configuration in libpool XML form.
8897c478bd9Sstevel@tonic-gate  */
8907c478bd9Sstevel@tonic-gate int
8917c478bd9Sstevel@tonic-gate pool_knl_put_xml_property(pool_elem_t *pe, xmlNodePtr node, const char *name,
8927c478bd9Sstevel@tonic-gate     const pool_value_t *val)
8937c478bd9Sstevel@tonic-gate {
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 	/*
8967c478bd9Sstevel@tonic-gate 	 * "type" is a special attribute which is not visible ever outside of
8977c478bd9Sstevel@tonic-gate 	 * libpool. Use the specific type accessor function.
8987c478bd9Sstevel@tonic-gate 	 */
8997c478bd9Sstevel@tonic-gate 	if (strcmp(name, c_type) == 0) {
9007c478bd9Sstevel@tonic-gate 		return (pool_xml_set_attr(node, BAD_CAST name,
9017c478bd9Sstevel@tonic-gate 		    val));
9027c478bd9Sstevel@tonic-gate 	}
9037c478bd9Sstevel@tonic-gate 	if (is_ns_property(pe, name) != NULL) {	/* in ns */
9047c478bd9Sstevel@tonic-gate 		if (pool_xml_set_attr(node,
9057c478bd9Sstevel@tonic-gate 		    BAD_CAST property_name_minus_ns(pe, name), val) == PO_FAIL)
9067c478bd9Sstevel@tonic-gate 			return (pool_xml_set_prop(node, BAD_CAST name,
9077c478bd9Sstevel@tonic-gate 			    val));
9087c478bd9Sstevel@tonic-gate 	} else
9097c478bd9Sstevel@tonic-gate 		return (pool_xml_set_prop(node, BAD_CAST name, val));
9107c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
9117c478bd9Sstevel@tonic-gate }
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate /*
9147c478bd9Sstevel@tonic-gate  * Export the kernel configuration as an XML file. The configuration
9157c478bd9Sstevel@tonic-gate  * is used to build an XML document in memory. This document is then
9167c478bd9Sstevel@tonic-gate  * saved to the supplied location.
9177c478bd9Sstevel@tonic-gate  */
9187c478bd9Sstevel@tonic-gate int
9197c478bd9Sstevel@tonic-gate pool_knl_export(const pool_conf_t *conf, const char *location,
9207c478bd9Sstevel@tonic-gate     pool_export_format_t fmt)
9217c478bd9Sstevel@tonic-gate {
9227c478bd9Sstevel@tonic-gate 	xmlNodePtr node_comment;
9237c478bd9Sstevel@tonic-gate 	xmlNodePtr system;
9247c478bd9Sstevel@tonic-gate 	int ret;
9257c478bd9Sstevel@tonic-gate 	pool_t **ps;
9267c478bd9Sstevel@tonic-gate 	pool_resource_t **rs;
9277c478bd9Sstevel@tonic-gate 	uint_t nelem;
9287c478bd9Sstevel@tonic-gate 	int i;
9297c478bd9Sstevel@tonic-gate 	struct knl_to_xml info;
9307c478bd9Sstevel@tonic-gate 	char_buf_t *cb = NULL;
9317c478bd9Sstevel@tonic-gate 	xmlValidCtxtPtr cvp;
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 	xml_init();
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	switch (fmt) {
9377c478bd9Sstevel@tonic-gate 	case POX_NATIVE:
9387c478bd9Sstevel@tonic-gate 		info.ktx_doc = xmlNewDoc(BAD_CAST "1.0");
939*5ad42b1bSSurya Prakki 		(void) xmlCreateIntSubset(info.ktx_doc, BAD_CAST "system",
9407c478bd9Sstevel@tonic-gate 		    BAD_CAST "-//Sun Microsystems Inc//DTD Resource "
9417c478bd9Sstevel@tonic-gate 		    "Management All//EN",
9427c478bd9Sstevel@tonic-gate 		    BAD_CAST dtd_location);
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 		if ((cvp = xmlNewValidCtxt()) == NULL) {
9457c478bd9Sstevel@tonic-gate 			xmlFreeDoc(info.ktx_doc);
9467c478bd9Sstevel@tonic-gate 			pool_seterror(POE_DATASTORE);
9477c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
9487c478bd9Sstevel@tonic-gate 		}
9497c478bd9Sstevel@tonic-gate 		/*
9507c478bd9Sstevel@tonic-gate 		 * Call xmlValidateDocument() to force the parsing of
9517c478bd9Sstevel@tonic-gate 		 * the DTD. Ignore errors and warning messages as we
9527c478bd9Sstevel@tonic-gate 		 * know the document isn't valid.
9537c478bd9Sstevel@tonic-gate 		 */
9547c478bd9Sstevel@tonic-gate 		(void) xmlValidateDocument(cvp, info.ktx_doc);
9557c478bd9Sstevel@tonic-gate 		xmlFreeValidCtxt(cvp);
9567c478bd9Sstevel@tonic-gate 		if ((info.ktx_node = node_create(NULL, BAD_CAST "system")) ==
9577c478bd9Sstevel@tonic-gate 		    NULL) {
9587c478bd9Sstevel@tonic-gate 			xmlFreeDoc(info.ktx_doc);
9597c478bd9Sstevel@tonic-gate 			pool_seterror(POE_DATASTORE);
9607c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
9617c478bd9Sstevel@tonic-gate 		}
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 		system = info.ktx_node;
9647c478bd9Sstevel@tonic-gate 		info.ktx_doc->_private = (void *)conf;
9657c478bd9Sstevel@tonic-gate 
966*5ad42b1bSSurya Prakki 		(void) xmlDocSetRootElement(info.ktx_doc, info.ktx_node);
967*5ad42b1bSSurya Prakki 		(void) xmlSetProp(info.ktx_node, BAD_CAST c_ref_id,
968*5ad42b1bSSurya Prakki 		    BAD_CAST "dummy");
9697c478bd9Sstevel@tonic-gate 		if ((node_comment = xmlNewDocComment(info.ktx_doc,
9707c478bd9Sstevel@tonic-gate 		    BAD_CAST "\nConfiguration for pools facility. Do NOT"
9717c478bd9Sstevel@tonic-gate 		    " edit this file by hand - use poolcfg(1)"
9727c478bd9Sstevel@tonic-gate 		    " or libpool(3POOL) instead.\n")) == NULL) {
9737c478bd9Sstevel@tonic-gate 			xmlFreeDoc(info.ktx_doc);
9747c478bd9Sstevel@tonic-gate 			pool_seterror(POE_DATASTORE);
9757c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
9767c478bd9Sstevel@tonic-gate 		}
9777c478bd9Sstevel@tonic-gate 		if (xmlAddPrevSibling(info.ktx_node, node_comment) == NULL) {
9787c478bd9Sstevel@tonic-gate 			xmlFree(node_comment);
9797c478bd9Sstevel@tonic-gate 			xmlFreeDoc(info.ktx_doc);
9807c478bd9Sstevel@tonic-gate 			pool_seterror(POE_DATASTORE);
9817c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
9827c478bd9Sstevel@tonic-gate 		}
9837c478bd9Sstevel@tonic-gate 		if (pool_walk_any_properties((pool_conf_t *)conf,
9847c478bd9Sstevel@tonic-gate 		    pool_conf_to_elem(conf), &info, prop_build_cb, 1) ==
9857c478bd9Sstevel@tonic-gate 		    PO_FAIL) {
9867c478bd9Sstevel@tonic-gate 			xmlFreeDoc(info.ktx_doc);
9877c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
9887c478bd9Sstevel@tonic-gate 		}
9897c478bd9Sstevel@tonic-gate 		if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
9907c478bd9Sstevel@tonic-gate 			xmlFreeDoc(info.ktx_doc);
9917c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
9927c478bd9Sstevel@tonic-gate 		}
9937c478bd9Sstevel@tonic-gate 		/*
9947c478bd9Sstevel@tonic-gate 		 * Now add pool details
9957c478bd9Sstevel@tonic-gate 		 */
9967c478bd9Sstevel@tonic-gate 		if ((ps = pool_query_pools(conf, &nelem, NULL)) != NULL) {
9977c478bd9Sstevel@tonic-gate 			for (i = 0; i < nelem; i++) {
9987c478bd9Sstevel@tonic-gate 				pool_elem_t *elem = TO_ELEM(ps[i]);
9997c478bd9Sstevel@tonic-gate 				uint_t nreselem;
10007c478bd9Sstevel@tonic-gate 				const char *sep = "";
10017c478bd9Sstevel@tonic-gate 				int j;
10027c478bd9Sstevel@tonic-gate 
10030209230bSgjelinek 				if (elem_is_tmp(elem))
10040209230bSgjelinek 					continue;
10050209230bSgjelinek 
10067c478bd9Sstevel@tonic-gate 				if ((info.ktx_node = node_create(system,
10077c478bd9Sstevel@tonic-gate 				    BAD_CAST element_class_tags
10087c478bd9Sstevel@tonic-gate 				    [pool_elem_class(elem)])) == NULL) {
10097c478bd9Sstevel@tonic-gate 					free(ps);
10107c478bd9Sstevel@tonic-gate 					free_char_buf(cb);
10117c478bd9Sstevel@tonic-gate 					xmlFreeDoc(info.ktx_doc);
10127c478bd9Sstevel@tonic-gate 					pool_seterror(POE_DATASTORE);
10137c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
10147c478bd9Sstevel@tonic-gate 				}
10157c478bd9Sstevel@tonic-gate 				if (pool_walk_any_properties(
10167c478bd9Sstevel@tonic-gate 				    (pool_conf_t *)conf,
10177c478bd9Sstevel@tonic-gate 				    elem, &info, prop_build_cb, 1) == PO_FAIL) {
10187c478bd9Sstevel@tonic-gate 					free(ps);
10197c478bd9Sstevel@tonic-gate 					free_char_buf(cb);
10207c478bd9Sstevel@tonic-gate 					xmlFreeDoc(info.ktx_doc);
10217c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
10227c478bd9Sstevel@tonic-gate 				}
10237c478bd9Sstevel@tonic-gate 				/*
10247c478bd9Sstevel@tonic-gate 				 * TODO: pset specific res manipulation
10257c478bd9Sstevel@tonic-gate 				 */
10267c478bd9Sstevel@tonic-gate 				if ((rs = pool_query_pool_resources(conf, ps[i],
10277c478bd9Sstevel@tonic-gate 				    &nreselem, NULL)) == NULL) {
10287c478bd9Sstevel@tonic-gate 					free(ps);
10297c478bd9Sstevel@tonic-gate 					free_char_buf(cb);
10307c478bd9Sstevel@tonic-gate 					xmlFreeDoc(info.ktx_doc);
10317c478bd9Sstevel@tonic-gate 					pool_seterror(POE_INVALID_CONF);
10327c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
10337c478bd9Sstevel@tonic-gate 				}
10347c478bd9Sstevel@tonic-gate 				if (set_char_buf(cb, "") == PO_FAIL) {
10357c478bd9Sstevel@tonic-gate 					free(rs);
10367c478bd9Sstevel@tonic-gate 					free(ps);
10377c478bd9Sstevel@tonic-gate 					free_char_buf(cb);
10387c478bd9Sstevel@tonic-gate 					xmlFreeDoc(info.ktx_doc);
10397c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
10407c478bd9Sstevel@tonic-gate 				}
10417c478bd9Sstevel@tonic-gate 				for (j = 0; j < nreselem; j++) {
10427c478bd9Sstevel@tonic-gate 					pool_elem_t *reselem = TO_ELEM(rs[j]);
10437c478bd9Sstevel@tonic-gate 					if (append_char_buf(cb, "%s%s_%d", sep,
10447c478bd9Sstevel@tonic-gate 					    pool_elem_class_string(reselem),
10457c478bd9Sstevel@tonic-gate 					    (int)elem_get_sysid(reselem)) ==
10467c478bd9Sstevel@tonic-gate 					    PO_FAIL) {
10477c478bd9Sstevel@tonic-gate 						free(rs);
10487c478bd9Sstevel@tonic-gate 						free(ps);
10497c478bd9Sstevel@tonic-gate 						free_char_buf(cb);
10507c478bd9Sstevel@tonic-gate 						xmlFreeDoc(info.ktx_doc);
10517c478bd9Sstevel@tonic-gate 						return (PO_FAIL);
10527c478bd9Sstevel@tonic-gate 					}
10537c478bd9Sstevel@tonic-gate 					sep = " ";
10547c478bd9Sstevel@tonic-gate 				}
10557c478bd9Sstevel@tonic-gate 				free(rs);
1056*5ad42b1bSSurya Prakki 				(void) xmlSetProp(info.ktx_node, BAD_CAST "res",
10577c478bd9Sstevel@tonic-gate 				    BAD_CAST cb->cb_buf);
10587c478bd9Sstevel@tonic-gate 				if (set_char_buf(cb, "%s_%d",
10597c478bd9Sstevel@tonic-gate 				    pool_elem_class_string(elem),
10607c478bd9Sstevel@tonic-gate 				    (int)elem_get_sysid(elem)) == PO_FAIL) {
10617c478bd9Sstevel@tonic-gate 					free(ps);
10627c478bd9Sstevel@tonic-gate 					free_char_buf(cb);
10637c478bd9Sstevel@tonic-gate 					xmlFreeDoc(info.ktx_doc);
10647c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
10657c478bd9Sstevel@tonic-gate 				}
1066*5ad42b1bSSurya Prakki 				(void) xmlSetProp(info.ktx_node,
1067*5ad42b1bSSurya Prakki 				    BAD_CAST c_ref_id,
10687c478bd9Sstevel@tonic-gate 				    BAD_CAST  cb->cb_buf);
10697c478bd9Sstevel@tonic-gate 			}
10707c478bd9Sstevel@tonic-gate 			free(ps);
10717c478bd9Sstevel@tonic-gate 		}
10727c478bd9Sstevel@tonic-gate 		/*
10737c478bd9Sstevel@tonic-gate 		 * Now add resource details (including components)
10747c478bd9Sstevel@tonic-gate 		 */
10757c478bd9Sstevel@tonic-gate 		if ((rs = pool_query_resources(conf, &nelem, NULL)) != NULL) {
10767c478bd9Sstevel@tonic-gate 			for (i = 0; i < nelem; i++) {
10777c478bd9Sstevel@tonic-gate 				pool_elem_t *elem = TO_ELEM(rs[i]);
10787c478bd9Sstevel@tonic-gate 				pool_component_t **cs = NULL;
10797c478bd9Sstevel@tonic-gate 				uint_t ncompelem;
10807c478bd9Sstevel@tonic-gate 				int j;
10817c478bd9Sstevel@tonic-gate 
10820209230bSgjelinek 				if (elem_is_tmp(elem))
10830209230bSgjelinek 					continue;
10840209230bSgjelinek 
10857c478bd9Sstevel@tonic-gate 				if ((info.ktx_node = node_create(system,
10867c478bd9Sstevel@tonic-gate 				    BAD_CAST element_class_tags
10877c478bd9Sstevel@tonic-gate 				    [pool_elem_class(elem)])) == NULL) {
10887c478bd9Sstevel@tonic-gate 					free(rs);
10897c478bd9Sstevel@tonic-gate 					free_char_buf(cb);
10907c478bd9Sstevel@tonic-gate 					xmlFreeDoc(info.ktx_doc);
10917c478bd9Sstevel@tonic-gate 					pool_seterror(POE_DATASTORE);
10927c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
10937c478bd9Sstevel@tonic-gate 				}
10947c478bd9Sstevel@tonic-gate 				if (pool_walk_any_properties(
10957c478bd9Sstevel@tonic-gate 				    (pool_conf_t *)conf,
10967c478bd9Sstevel@tonic-gate 				    elem, &info, prop_build_cb, 1) == PO_FAIL) {
10977c478bd9Sstevel@tonic-gate 					free(rs);
10987c478bd9Sstevel@tonic-gate 					free_char_buf(cb);
10997c478bd9Sstevel@tonic-gate 					xmlFreeDoc(info.ktx_doc);
11007c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
11017c478bd9Sstevel@tonic-gate 				}
11027c478bd9Sstevel@tonic-gate 				if (set_char_buf(cb, "%s_%d",
11037c478bd9Sstevel@tonic-gate 				    pool_elem_class_string(elem),
11047c478bd9Sstevel@tonic-gate 				    (int)elem_get_sysid(elem)) == PO_FAIL) {
11057c478bd9Sstevel@tonic-gate 					free(rs);
11067c478bd9Sstevel@tonic-gate 					free_char_buf(cb);
11077c478bd9Sstevel@tonic-gate 					xmlFreeDoc(info.ktx_doc);
11087c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
11097c478bd9Sstevel@tonic-gate 				}
1110*5ad42b1bSSurya Prakki 				(void) xmlSetProp(info.ktx_node,
1111*5ad42b1bSSurya Prakki 				    BAD_CAST c_ref_id,
11127c478bd9Sstevel@tonic-gate 				    BAD_CAST  cb->cb_buf);
11137c478bd9Sstevel@tonic-gate 				if ((cs = pool_query_resource_components(conf,
11147c478bd9Sstevel@tonic-gate 				    rs[i], &ncompelem, NULL)) != NULL) {
11157c478bd9Sstevel@tonic-gate 					xmlNodePtr resource = info.ktx_node;
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 					for (j = 0; j < ncompelem; j++) {
11187c478bd9Sstevel@tonic-gate 						pool_elem_t *compelem =
11197c478bd9Sstevel@tonic-gate 						    TO_ELEM(cs[j]);
11207c478bd9Sstevel@tonic-gate 						if ((info.ktx_node =
11217c478bd9Sstevel@tonic-gate 						    node_create(resource,
11227c478bd9Sstevel@tonic-gate 						    BAD_CAST element_class_tags
11237c478bd9Sstevel@tonic-gate 						    [pool_elem_class(
11247c478bd9Sstevel@tonic-gate 						    compelem)])) == NULL) {
11257c478bd9Sstevel@tonic-gate 							pool_seterror(
11267c478bd9Sstevel@tonic-gate 							    POE_DATASTORE);
11277c478bd9Sstevel@tonic-gate 							free(rs);
11287c478bd9Sstevel@tonic-gate 							free(cs);
11297c478bd9Sstevel@tonic-gate 							free_char_buf(cb);
11307c478bd9Sstevel@tonic-gate 							xmlFreeDoc(info.
11317c478bd9Sstevel@tonic-gate 							    ktx_doc);
11327c478bd9Sstevel@tonic-gate 							return (PO_FAIL);
11337c478bd9Sstevel@tonic-gate 						}
11347c478bd9Sstevel@tonic-gate 						if (pool_walk_any_properties(
11357c478bd9Sstevel@tonic-gate 						    (pool_conf_t *)conf,
11367c478bd9Sstevel@tonic-gate 						    compelem, &info,
11377c478bd9Sstevel@tonic-gate 						    prop_build_cb, 1) ==
11387c478bd9Sstevel@tonic-gate 						    PO_FAIL) {
11397c478bd9Sstevel@tonic-gate 							free(rs);
11407c478bd9Sstevel@tonic-gate 							free(cs);
11417c478bd9Sstevel@tonic-gate 							free_char_buf(cb);
11427c478bd9Sstevel@tonic-gate 							xmlFreeDoc(info.
11437c478bd9Sstevel@tonic-gate 							    ktx_doc);
11447c478bd9Sstevel@tonic-gate 							return (PO_FAIL);
11457c478bd9Sstevel@tonic-gate 						}
11467c478bd9Sstevel@tonic-gate 						if (set_char_buf(cb, "%s_%d",
11477c478bd9Sstevel@tonic-gate 						    pool_elem_class_string(
11487c478bd9Sstevel@tonic-gate 						    compelem),
11497c478bd9Sstevel@tonic-gate 						    (int)elem_get_sysid(
11507c478bd9Sstevel@tonic-gate 						    compelem)) == PO_FAIL) {
11517c478bd9Sstevel@tonic-gate 							free(rs);
11527c478bd9Sstevel@tonic-gate 							free(cs);
11537c478bd9Sstevel@tonic-gate 							free_char_buf(cb);
11547c478bd9Sstevel@tonic-gate 							xmlFreeDoc(info.
11557c478bd9Sstevel@tonic-gate 							    ktx_doc);
11567c478bd9Sstevel@tonic-gate 							return (PO_FAIL);
11577c478bd9Sstevel@tonic-gate 						}
1158*5ad42b1bSSurya Prakki 						(void) xmlSetProp(info.ktx_node,
11597c478bd9Sstevel@tonic-gate 						    BAD_CAST c_ref_id,
11607c478bd9Sstevel@tonic-gate 						    BAD_CAST  cb->cb_buf);
11617c478bd9Sstevel@tonic-gate 					}
11627c478bd9Sstevel@tonic-gate 					free(cs);
11637c478bd9Sstevel@tonic-gate 				}
11647c478bd9Sstevel@tonic-gate 			}
11657c478bd9Sstevel@tonic-gate 			free(rs);
11667c478bd9Sstevel@tonic-gate 		}
11677c478bd9Sstevel@tonic-gate 		free_char_buf(cb);
11687c478bd9Sstevel@tonic-gate 		/*
11697c478bd9Sstevel@tonic-gate 		 * Set up the message handlers prior to calling
11707c478bd9Sstevel@tonic-gate 		 * xmlValidateDocument()
11717c478bd9Sstevel@tonic-gate 		 */
11727c478bd9Sstevel@tonic-gate 		if ((cvp = xmlNewValidCtxt()) == NULL) {
11737c478bd9Sstevel@tonic-gate 			xmlFreeDoc(info.ktx_doc);
11747c478bd9Sstevel@tonic-gate 			pool_seterror(POE_DATASTORE);
11757c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
11767c478bd9Sstevel@tonic-gate 		}
11777c478bd9Sstevel@tonic-gate 		cvp->error    = pool_error_func;
11787c478bd9Sstevel@tonic-gate 		cvp->warning  = pool_error_func;
11797c478bd9Sstevel@tonic-gate 		if (xmlValidateDocument(cvp, info.ktx_doc) == 0) {
11807c478bd9Sstevel@tonic-gate 			xmlFreeValidCtxt(cvp);
11817c478bd9Sstevel@tonic-gate 			xmlFreeDoc(info.ktx_doc);
11827c478bd9Sstevel@tonic-gate 			pool_seterror(POE_INVALID_CONF);
11837c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
11847c478bd9Sstevel@tonic-gate 		}
11857c478bd9Sstevel@tonic-gate 		xmlFreeValidCtxt(cvp);
11867c478bd9Sstevel@tonic-gate 		ret = xmlSaveFormatFile(location, info.ktx_doc, 1);
11877c478bd9Sstevel@tonic-gate 		xmlFreeDoc(info.ktx_doc);
11887c478bd9Sstevel@tonic-gate 		if (ret == -1) {
11897c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
11907c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
11917c478bd9Sstevel@tonic-gate 		}
11927c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
11937c478bd9Sstevel@tonic-gate 	default:
11947c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
11957c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
11967c478bd9Sstevel@tonic-gate 	}
11977c478bd9Sstevel@tonic-gate }
11987c478bd9Sstevel@tonic-gate 
11997c478bd9Sstevel@tonic-gate /*
12007c478bd9Sstevel@tonic-gate  * Rollback the changes to the kernel
12017c478bd9Sstevel@tonic-gate  */
12027c478bd9Sstevel@tonic-gate int
12037c478bd9Sstevel@tonic-gate pool_knl_recover(pool_conf_t *conf)
12047c478bd9Sstevel@tonic-gate {
12057c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	prov->pkc_log->l_state = LS_RECOVER;
12087c478bd9Sstevel@tonic-gate 	if (log_reverse_walk(prov->pkc_log, log_item_undo) != PO_SUCCESS) {
12097c478bd9Sstevel@tonic-gate 		dprintf("Library configuration consistency error\n");
12107c478bd9Sstevel@tonic-gate 		prov->pkc_log->l_state = LS_FAIL;
12117c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
12127c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
12137c478bd9Sstevel@tonic-gate 	}
12147c478bd9Sstevel@tonic-gate 	prov->pkc_log->l_state = LS_DO;
12157c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate /*
12197c478bd9Sstevel@tonic-gate  * Rollback the changes to the configuration
12207c478bd9Sstevel@tonic-gate  */
12217c478bd9Sstevel@tonic-gate int
12227c478bd9Sstevel@tonic-gate pool_knl_rollback(pool_conf_t *conf)
12237c478bd9Sstevel@tonic-gate {
12247c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 	prov->pkc_log->l_state = LS_UNDO;
12277c478bd9Sstevel@tonic-gate 	if (log_reverse_walk(prov->pkc_log, log_item_undo) != PO_SUCCESS) {
12287c478bd9Sstevel@tonic-gate 		dprintf("Kernel configuration consistency error\n");
12297c478bd9Sstevel@tonic-gate 		(void) log_walk(prov->pkc_log, log_item_release);
12307c478bd9Sstevel@tonic-gate 		log_empty(prov->pkc_log);
12317c478bd9Sstevel@tonic-gate 		prov->pkc_log->l_state = LS_FAIL;
12327c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
12337c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
12347c478bd9Sstevel@tonic-gate 	}
12357c478bd9Sstevel@tonic-gate 	(void) log_walk(prov->pkc_log, log_item_release);
12367c478bd9Sstevel@tonic-gate 	log_empty(prov->pkc_log);
12377c478bd9Sstevel@tonic-gate 	prov->pkc_log->l_state = LS_DO;
12387c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
12397c478bd9Sstevel@tonic-gate }
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate /*
12427c478bd9Sstevel@tonic-gate  * Callback used to build the result set for a query. Each invocation will
12437c478bd9Sstevel@tonic-gate  * supply a candidate element for inclusion. The element is filtered by:
12447c478bd9Sstevel@tonic-gate  * - class
12457c478bd9Sstevel@tonic-gate  * - properties
12467c478bd9Sstevel@tonic-gate  * If the element "matches" the target, then it is added to the result
12477c478bd9Sstevel@tonic-gate  * set, otherwise it is ignored.
12487c478bd9Sstevel@tonic-gate  */
12497c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
12507c478bd9Sstevel@tonic-gate static void
12517c478bd9Sstevel@tonic-gate build_result_set(const void *key, void **value, void *cl)
12527c478bd9Sstevel@tonic-gate {
12537c478bd9Sstevel@tonic-gate 	struct query_obj *qo = (struct query_obj *)cl;
12547c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 	/*
12577c478bd9Sstevel@tonic-gate 	 * Check to see if it's the right class of element
12587c478bd9Sstevel@tonic-gate 	 */
12597c478bd9Sstevel@tonic-gate 	if (qo->classes & (1 << pool_elem_class((pool_elem_t *)key))) {
12607c478bd9Sstevel@tonic-gate 		int i;
12617c478bd9Sstevel@tonic-gate 		/*
12627c478bd9Sstevel@tonic-gate 		 * Now check to see if the src element is correct. If no src
12637c478bd9Sstevel@tonic-gate 		 * element is supplied, ignore this check
12647c478bd9Sstevel@tonic-gate 		 */
12657c478bd9Sstevel@tonic-gate 		if (qo->src) {
12667c478bd9Sstevel@tonic-gate 			pool_knl_elem_t *parent;
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 			for (parent = pke; parent != NULL;
12697c478bd9Sstevel@tonic-gate 			    parent = parent->pke_parent) {
12707c478bd9Sstevel@tonic-gate 				if (parent == (pool_knl_elem_t *)qo->src)
12717c478bd9Sstevel@tonic-gate 					break;
12727c478bd9Sstevel@tonic-gate 			}
12737c478bd9Sstevel@tonic-gate 			if (parent == NULL)
12747c478bd9Sstevel@tonic-gate 				return;
12757c478bd9Sstevel@tonic-gate 		}
12767c478bd9Sstevel@tonic-gate 		/*
12777c478bd9Sstevel@tonic-gate 		 * Now check for property matches (if there are any specified)
12787c478bd9Sstevel@tonic-gate 		 */
12797c478bd9Sstevel@tonic-gate 		if (qo->props) {
12807c478bd9Sstevel@tonic-gate 			int matched = PO_TRUE;
12817c478bd9Sstevel@tonic-gate 			for (i = 0; qo->props[i] != NULL; i++) {
12827c478bd9Sstevel@tonic-gate 				pool_value_t val = POOL_VALUE_INITIALIZER;
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 				if (pool_get_property(TO_CONF(TO_ELEM(pke)),
12857c478bd9Sstevel@tonic-gate 				    (pool_elem_t *)pke,
12867c478bd9Sstevel@tonic-gate 				    pool_value_get_name(qo->props[i]), &val) ==
12877c478bd9Sstevel@tonic-gate 				    POC_INVAL) {
12887c478bd9Sstevel@tonic-gate 					matched = PO_FALSE;
12897c478bd9Sstevel@tonic-gate 					break;
12907c478bd9Sstevel@tonic-gate 				} else {
12917c478bd9Sstevel@tonic-gate 					if (pool_value_equal(qo->props[i],
12927c478bd9Sstevel@tonic-gate 					    &val) != PO_TRUE) {
12937c478bd9Sstevel@tonic-gate 						matched = PO_FALSE;
12947c478bd9Sstevel@tonic-gate 						break;
12957c478bd9Sstevel@tonic-gate 					}
12967c478bd9Sstevel@tonic-gate 				}
12977c478bd9Sstevel@tonic-gate 			}
12987c478bd9Sstevel@tonic-gate 			if (matched == PO_TRUE)
12997c478bd9Sstevel@tonic-gate 				(void) pool_knl_result_set_append(qo->rs,
1300*5ad42b1bSSurya Prakki 				    (pool_knl_elem_t *)key);
13017c478bd9Sstevel@tonic-gate 		} else {
13027c478bd9Sstevel@tonic-gate 			(void) pool_knl_result_set_append(qo->rs,
13037c478bd9Sstevel@tonic-gate 			    (pool_knl_elem_t *)key);
13047c478bd9Sstevel@tonic-gate 		}
13057c478bd9Sstevel@tonic-gate 	}
13067c478bd9Sstevel@tonic-gate }
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate /*
13097c478bd9Sstevel@tonic-gate  * Execute the supplied query and return a result set which contains
13107c478bd9Sstevel@tonic-gate  * all qualifying elements.
13117c478bd9Sstevel@tonic-gate  */
13127c478bd9Sstevel@tonic-gate pool_result_set_t *
13137c478bd9Sstevel@tonic-gate pool_knl_exec_query(const pool_conf_t *conf, const pool_elem_t *src,
13147c478bd9Sstevel@tonic-gate     const char *src_attr, pool_elem_class_t classes, pool_value_t **props)
13157c478bd9Sstevel@tonic-gate {
13167c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *rs;
13177c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
13187c478bd9Sstevel@tonic-gate 	struct query_obj qo;
13197c478bd9Sstevel@tonic-gate 	int matched = PO_TRUE;
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate 	/*
13227c478bd9Sstevel@tonic-gate 	 * Have a buffer at this point, that we can use
13237c478bd9Sstevel@tonic-gate 	 */
13247c478bd9Sstevel@tonic-gate 	if ((rs = pool_knl_result_set_alloc(conf)) == NULL) {
13257c478bd9Sstevel@tonic-gate 		return (NULL);
13267c478bd9Sstevel@tonic-gate 	}
13277c478bd9Sstevel@tonic-gate 	qo.conf = conf;
13287c478bd9Sstevel@tonic-gate 	qo.src = src;
13297c478bd9Sstevel@tonic-gate 	qo.src_attr = src_attr;
13307c478bd9Sstevel@tonic-gate 	qo.classes = classes;
13317c478bd9Sstevel@tonic-gate 	qo.props = props;
13327c478bd9Sstevel@tonic-gate 	qo.rs = rs;
13337c478bd9Sstevel@tonic-gate 	if (src_attr != NULL) {
13347c478bd9Sstevel@tonic-gate 		pool_knl_pool_t *pkp = (pool_knl_pool_t *)src;
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate 		/*
13377c478bd9Sstevel@tonic-gate 		 * Note: This logic is resource specific and must be
13387c478bd9Sstevel@tonic-gate 		 * extended for additional resource types.
13397c478bd9Sstevel@tonic-gate 		 */
13407c478bd9Sstevel@tonic-gate 		/*
13417c478bd9Sstevel@tonic-gate 		 * Check for property matches (if there are any specified)
13427c478bd9Sstevel@tonic-gate 		 */
13437c478bd9Sstevel@tonic-gate 		if (props) {
13447c478bd9Sstevel@tonic-gate 			int i;
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 			for (i = 0; props[i] != NULL; i++) {
13477c478bd9Sstevel@tonic-gate 				pool_value_t val = POOL_VALUE_INITIALIZER;
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 				if (pool_get_property(conf,
13507c478bd9Sstevel@tonic-gate 				    (pool_elem_t *)pkp->pkp_assoc[PREC_PSET],
13517c478bd9Sstevel@tonic-gate 				    pool_value_get_name(props[i]), &val) ==
13527c478bd9Sstevel@tonic-gate 				    POC_INVAL) {
13537c478bd9Sstevel@tonic-gate 					matched = PO_FALSE;
13547c478bd9Sstevel@tonic-gate 					break;
13557c478bd9Sstevel@tonic-gate 				} else {
13567c478bd9Sstevel@tonic-gate 					if (pool_value_equal(props[i],
13577c478bd9Sstevel@tonic-gate 					    &val) != PO_TRUE) {
13587c478bd9Sstevel@tonic-gate 						matched = PO_FALSE;
13597c478bd9Sstevel@tonic-gate 						break;
13607c478bd9Sstevel@tonic-gate 					}
13617c478bd9Sstevel@tonic-gate 				}
13627c478bd9Sstevel@tonic-gate 			}
13637c478bd9Sstevel@tonic-gate 		}
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate 		if (matched == PO_TRUE)
13667c478bd9Sstevel@tonic-gate 			(void) pool_knl_result_set_append(rs,
13677c478bd9Sstevel@tonic-gate 			    (pool_knl_elem_t *)pkp->pkp_assoc[PREC_PSET]);
13687c478bd9Sstevel@tonic-gate 	} else
13697c478bd9Sstevel@tonic-gate 		dict_map(prov->pkc_elements, build_result_set, &qo);
13707c478bd9Sstevel@tonic-gate 
137126d8ba22Sgarypen 	if (rs->pkr_count == 0)
137226d8ba22Sgarypen 		pool_seterror(POE_INVALID_SEARCH);
13737c478bd9Sstevel@tonic-gate 	return ((pool_result_set_t *)rs);
13747c478bd9Sstevel@tonic-gate }
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate /*
13777c478bd9Sstevel@tonic-gate  * Callback function intended to be used from pool_walk_pools(). If
13787c478bd9Sstevel@tonic-gate  * the supplied pool is not the default pool attempt to destroy it.
13797c478bd9Sstevel@tonic-gate  */
13807c478bd9Sstevel@tonic-gate /*ARGSUSED*/
13817c478bd9Sstevel@tonic-gate static int
13827c478bd9Sstevel@tonic-gate destroy_pool_cb(pool_conf_t *conf, pool_t *pool, void *unused)
13837c478bd9Sstevel@tonic-gate {
13847c478bd9Sstevel@tonic-gate 	if (elem_is_default(TO_ELEM(pool)) != PO_TRUE)
13857c478bd9Sstevel@tonic-gate 		return (pool_destroy(conf, pool));
13867c478bd9Sstevel@tonic-gate 	/*
13877c478bd9Sstevel@tonic-gate 	 * Return PO_SUCCESS even though we don't delete the default
13887c478bd9Sstevel@tonic-gate 	 * pool so that the walk continues
13897c478bd9Sstevel@tonic-gate 	 */
13907c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
13917c478bd9Sstevel@tonic-gate }
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate /*
13947c478bd9Sstevel@tonic-gate  * Remove the configuration details. This means remove all elements
13957c478bd9Sstevel@tonic-gate  * apart from the system elements.
13967c478bd9Sstevel@tonic-gate  */
13977c478bd9Sstevel@tonic-gate int
13987c478bd9Sstevel@tonic-gate pool_knl_remove(pool_conf_t *conf)
13997c478bd9Sstevel@tonic-gate {
14007c478bd9Sstevel@tonic-gate 	uint_t i, nelem;
14017c478bd9Sstevel@tonic-gate 	pool_resource_t **resources;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	conf->pc_state = POF_DESTROY;
14047c478bd9Sstevel@tonic-gate 	if ((resources = pool_query_resources(conf, &nelem, NULL)) != NULL) {
14057c478bd9Sstevel@tonic-gate 		for (i = 0; i < nelem; i++) {
14067c478bd9Sstevel@tonic-gate 			if (resource_is_system(resources[i]) == PO_FALSE)
14077c478bd9Sstevel@tonic-gate 				if (pool_resource_destroy(conf, resources[i]) !=
14087c478bd9Sstevel@tonic-gate 				    PO_SUCCESS) {
14097c478bd9Sstevel@tonic-gate 					pool_seterror(POE_INVALID_CONF);
14107c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
14117c478bd9Sstevel@tonic-gate 				}
14127c478bd9Sstevel@tonic-gate 		}
14137c478bd9Sstevel@tonic-gate 		free(resources);
14147c478bd9Sstevel@tonic-gate 	}
14157c478bd9Sstevel@tonic-gate 	(void) pool_walk_pools(conf, conf, destroy_pool_cb);
14167c478bd9Sstevel@tonic-gate 	if (pool_conf_commit(conf, PO_FALSE) != PO_SUCCESS)
14177c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate 	if (pool_conf_close(conf) != PO_SUCCESS)
14207c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate /*
14267c478bd9Sstevel@tonic-gate  * Determine the name of the pool to which the supplied pid is
14277c478bd9Sstevel@tonic-gate  * bound. If it cannot be determined return NULL.
14287c478bd9Sstevel@tonic-gate  */
14297c478bd9Sstevel@tonic-gate char *
14307c478bd9Sstevel@tonic-gate pool_knl_get_binding(pool_conf_t *conf, pid_t pid)
14317c478bd9Sstevel@tonic-gate {
14327c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
14337c478bd9Sstevel@tonic-gate 	const char *sval;
14347c478bd9Sstevel@tonic-gate 	char *name = NULL;
14357c478bd9Sstevel@tonic-gate 	pool_bindq_t bindq;
14367c478bd9Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
14377c478bd9Sstevel@tonic-gate 	uint_t nelem = 0;
14387c478bd9Sstevel@tonic-gate 	pool_t **pools;
14397c478bd9Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate 	props[0] = &val;
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	bindq.pb_o_id_type = P_PID;
14447c478bd9Sstevel@tonic-gate 	bindq.pb_o_id = pid;
14457c478bd9Sstevel@tonic-gate 	if (ioctl(prov->pkc_fd, POOL_BINDQ, &bindq) < 0) {
14467c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
14477c478bd9Sstevel@tonic-gate 		return (NULL);
14487c478bd9Sstevel@tonic-gate 	}
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 	if (pool_value_set_name(props[0], "pool.sys_id") != PO_SUCCESS) {
14517c478bd9Sstevel@tonic-gate 		return (NULL);
14527c478bd9Sstevel@tonic-gate 	}
14537c478bd9Sstevel@tonic-gate 	pool_value_set_int64(props[0], bindq.pb_i_id);
14547c478bd9Sstevel@tonic-gate 	if ((pools = pool_query_pools(conf, &nelem, props)) == NULL) {
14557c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
14567c478bd9Sstevel@tonic-gate 		return (NULL);
14577c478bd9Sstevel@tonic-gate 	}
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate 	if (nelem != 1) {
14607c478bd9Sstevel@tonic-gate 		free(pools);
14617c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
14627c478bd9Sstevel@tonic-gate 		return (NULL);
14637c478bd9Sstevel@tonic-gate 	}
14647c478bd9Sstevel@tonic-gate 	if (pool_get_ns_property(TO_ELEM(pools[0]), c_name, props[0])
14657c478bd9Sstevel@tonic-gate 	    == POC_INVAL) {
14667c478bd9Sstevel@tonic-gate 		free(pools);
14677c478bd9Sstevel@tonic-gate 		return (NULL);
14687c478bd9Sstevel@tonic-gate 	}
14697c478bd9Sstevel@tonic-gate 	if (pool_value_get_string(props[0], &sval) != PO_SUCCESS) {
14707c478bd9Sstevel@tonic-gate 		free(pools);
14717c478bd9Sstevel@tonic-gate 		return (NULL);
14727c478bd9Sstevel@tonic-gate 	}
14737c478bd9Sstevel@tonic-gate 	if ((name = strdup(sval)) == NULL) {
14747c478bd9Sstevel@tonic-gate 		free(pools);
14757c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
14767c478bd9Sstevel@tonic-gate 		return (NULL);
14777c478bd9Sstevel@tonic-gate 	}
14787c478bd9Sstevel@tonic-gate 	return (name);
14797c478bd9Sstevel@tonic-gate }
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate /*
14827c478bd9Sstevel@tonic-gate  * Bind idtype id to the pool name.
14837c478bd9Sstevel@tonic-gate  */
14847c478bd9Sstevel@tonic-gate int
14857c478bd9Sstevel@tonic-gate pool_knl_set_binding(pool_conf_t *conf, const char *pool_name, idtype_t idtype,
14867c478bd9Sstevel@tonic-gate     id_t id)
14877c478bd9Sstevel@tonic-gate {
14887c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
14897c478bd9Sstevel@tonic-gate 	pool_bind_t bind;
14907c478bd9Sstevel@tonic-gate 	pool_t *pool;
14917c478bd9Sstevel@tonic-gate 	int ret;
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 	if ((pool = pool_get_pool(conf, pool_name)) == NULL)
14947c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	bind.pb_o_id_type = idtype;
14977c478bd9Sstevel@tonic-gate 	bind.pb_o_id = id;
14987c478bd9Sstevel@tonic-gate 	bind.pb_o_pool_id = elem_get_sysid(TO_ELEM(pool));
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate 	while ((ret = ioctl(prov->pkc_fd, POOL_BIND, &bind)) < 0 &&
1501*5ad42b1bSSurya Prakki 	    errno == EAGAIN)
1502*5ad42b1bSSurya Prakki 		;
15037c478bd9Sstevel@tonic-gate 	if (ret < 0) {
15047c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
15057c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
15067c478bd9Sstevel@tonic-gate 	}
15077c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
15087c478bd9Sstevel@tonic-gate }
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate /*
15117c478bd9Sstevel@tonic-gate  * pool_knl_get_resource_binding() returns the binding for a pid to
15127c478bd9Sstevel@tonic-gate  * the supplied type of resource. If a binding cannot be determined,
15137c478bd9Sstevel@tonic-gate  * NULL is returned.
15147c478bd9Sstevel@tonic-gate  */
15157c478bd9Sstevel@tonic-gate char *
15167c478bd9Sstevel@tonic-gate pool_knl_get_resource_binding(pool_conf_t *conf,
15177c478bd9Sstevel@tonic-gate     pool_resource_elem_class_t type, pid_t pid)
15187c478bd9Sstevel@tonic-gate {
15197c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
15207c478bd9Sstevel@tonic-gate 	const char *sval;
15217c478bd9Sstevel@tonic-gate 	char *name = NULL;
15227c478bd9Sstevel@tonic-gate 	pool_bindq_t bindq;
15237c478bd9Sstevel@tonic-gate 	pool_value_t *props[] = { NULL, NULL };
15247c478bd9Sstevel@tonic-gate 	uint_t nelem = 0;
15257c478bd9Sstevel@tonic-gate 	pool_t **pools;
15267c478bd9Sstevel@tonic-gate 	pool_resource_t **resources;
15277c478bd9Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate 	props[0] = &val;
15307c478bd9Sstevel@tonic-gate 	bindq.pb_o_id_type = P_PID;
15317c478bd9Sstevel@tonic-gate 	bindq.pb_o_id = pid;
15327c478bd9Sstevel@tonic-gate 	if (ioctl(prov->pkc_fd, POOL_BINDQ, &bindq) < 0) {
15337c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
15347c478bd9Sstevel@tonic-gate 		return (NULL);
15357c478bd9Sstevel@tonic-gate 	}
15367c478bd9Sstevel@tonic-gate 
15377c478bd9Sstevel@tonic-gate 	if (pool_value_set_name(props[0], "pool.sys_id") != PO_SUCCESS) {
15387c478bd9Sstevel@tonic-gate 		return (NULL);
15397c478bd9Sstevel@tonic-gate 	}
15407c478bd9Sstevel@tonic-gate 	pool_value_set_int64(props[0], bindq.pb_i_id);
15417c478bd9Sstevel@tonic-gate 	if ((pools = pool_query_pools(conf, &nelem, props)) == NULL) {
15427c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
15437c478bd9Sstevel@tonic-gate 		return (NULL);
15447c478bd9Sstevel@tonic-gate 	}
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate 	if (nelem != 1) {
15477c478bd9Sstevel@tonic-gate 		free(pools);
15487c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
15497c478bd9Sstevel@tonic-gate 		return (NULL);
15507c478bd9Sstevel@tonic-gate 	}
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 	if (pool_value_set_string(props[0], pool_resource_type_string(type)) !=
15537c478bd9Sstevel@tonic-gate 	    PO_SUCCESS ||
15547c478bd9Sstevel@tonic-gate 	    pool_value_set_name(props[0], c_type) != PO_SUCCESS) {
15557c478bd9Sstevel@tonic-gate 		free(pools);
15567c478bd9Sstevel@tonic-gate 		return (NULL);
15577c478bd9Sstevel@tonic-gate 	}
15587c478bd9Sstevel@tonic-gate 
15597c478bd9Sstevel@tonic-gate 	if ((resources = pool_query_pool_resources(conf, pools[0], &nelem,
15607c478bd9Sstevel@tonic-gate 	    NULL)) == NULL) {
15617c478bd9Sstevel@tonic-gate 		free(pools);
15627c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
15637c478bd9Sstevel@tonic-gate 		return (NULL);
15647c478bd9Sstevel@tonic-gate 	}
15657c478bd9Sstevel@tonic-gate 	free(pools);
15667c478bd9Sstevel@tonic-gate 	if (nelem != 1) {
15677c478bd9Sstevel@tonic-gate 		free(resources);
15687c478bd9Sstevel@tonic-gate 		pool_seterror(POE_INVALID_CONF);
15697c478bd9Sstevel@tonic-gate 		return (NULL);
15707c478bd9Sstevel@tonic-gate 	}
15717c478bd9Sstevel@tonic-gate 	if (pool_get_ns_property(TO_ELEM(resources[0]), c_name, props[0]) ==
15727c478bd9Sstevel@tonic-gate 	    POC_INVAL) {
15737c478bd9Sstevel@tonic-gate 		free(resources);
15747c478bd9Sstevel@tonic-gate 		return (NULL);
15757c478bd9Sstevel@tonic-gate 	}
15767c478bd9Sstevel@tonic-gate 	free(resources);
15777c478bd9Sstevel@tonic-gate 	if (pool_value_get_string(props[0], &sval) != PO_SUCCESS) {
15787c478bd9Sstevel@tonic-gate 		return (NULL);
15797c478bd9Sstevel@tonic-gate 	}
15807c478bd9Sstevel@tonic-gate 	if ((name = strdup(sval)) == NULL) {
15817c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
15827c478bd9Sstevel@tonic-gate 		return (NULL);
15837c478bd9Sstevel@tonic-gate 	}
15847c478bd9Sstevel@tonic-gate 	return (name);
15857c478bd9Sstevel@tonic-gate }
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate /*
15887c478bd9Sstevel@tonic-gate  * Allocate the required library data structure and initialise it.
15897c478bd9Sstevel@tonic-gate  */
15907c478bd9Sstevel@tonic-gate pool_knl_elem_t *
15917c478bd9Sstevel@tonic-gate pool_knl_elem_wrap(pool_conf_t *conf, pool_elem_class_t class,
15927c478bd9Sstevel@tonic-gate     pool_resource_elem_class_t res_class,
15937c478bd9Sstevel@tonic-gate     pool_component_elem_class_t comp_class)
15947c478bd9Sstevel@tonic-gate {
15957c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *elem;
15967c478bd9Sstevel@tonic-gate 	pool_elem_t *pe;
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 	switch (class) {
15997c478bd9Sstevel@tonic-gate 	case PEC_SYSTEM:
16007c478bd9Sstevel@tonic-gate 		if ((elem = malloc(sizeof (pool_knl_system_t))) == NULL) {
16017c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
16027c478bd9Sstevel@tonic-gate 			return (NULL);
16037c478bd9Sstevel@tonic-gate 		}
16047c478bd9Sstevel@tonic-gate 		(void) memset(elem, 0, sizeof (pool_knl_system_t));
16057c478bd9Sstevel@tonic-gate 		break;
16067c478bd9Sstevel@tonic-gate 	case PEC_POOL:
16077c478bd9Sstevel@tonic-gate 		if ((elem = malloc(sizeof (pool_knl_pool_t))) == NULL) {
16087c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
16097c478bd9Sstevel@tonic-gate 			return (NULL);
16107c478bd9Sstevel@tonic-gate 		}
16117c478bd9Sstevel@tonic-gate 		(void) memset(elem, 0, sizeof (pool_knl_pool_t));
16127c478bd9Sstevel@tonic-gate 		break;
16137c478bd9Sstevel@tonic-gate 	case PEC_RES_COMP:
16147c478bd9Sstevel@tonic-gate 	case PEC_RES_AGG:
16157c478bd9Sstevel@tonic-gate 		if ((elem = malloc(sizeof (pool_knl_resource_t))) == NULL) {
16167c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
16177c478bd9Sstevel@tonic-gate 			return (NULL);
16187c478bd9Sstevel@tonic-gate 		}
16197c478bd9Sstevel@tonic-gate 		(void) memset(elem, 0, sizeof (pool_knl_resource_t));
16207c478bd9Sstevel@tonic-gate 		break;
16217c478bd9Sstevel@tonic-gate 	case PEC_COMP:
16227c478bd9Sstevel@tonic-gate 		if ((elem = malloc(sizeof (pool_knl_component_t))) == NULL) {
16237c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
16247c478bd9Sstevel@tonic-gate 			return (NULL);
16257c478bd9Sstevel@tonic-gate 		}
16267c478bd9Sstevel@tonic-gate 		(void) memset(elem, 0, sizeof (pool_knl_component_t));
16277c478bd9Sstevel@tonic-gate 		break;
16287c478bd9Sstevel@tonic-gate 	default:
16297c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
16307c478bd9Sstevel@tonic-gate 		return (NULL);
16317c478bd9Sstevel@tonic-gate 	}
16327c478bd9Sstevel@tonic-gate 	pe = TO_ELEM(elem);
16337c478bd9Sstevel@tonic-gate 	pe->pe_conf = conf;
16347c478bd9Sstevel@tonic-gate 	pe->pe_class = class;
16357c478bd9Sstevel@tonic-gate 	pe->pe_resource_class = res_class;
16367c478bd9Sstevel@tonic-gate 	pe->pe_component_class = comp_class;
16377c478bd9Sstevel@tonic-gate 	/* Set up the function pointers for element manipulation */
16387c478bd9Sstevel@tonic-gate 	pe->pe_get_prop = pool_knl_get_property;
16397c478bd9Sstevel@tonic-gate 	pe->pe_put_prop = pool_knl_put_property;
16407c478bd9Sstevel@tonic-gate 	pe->pe_rm_prop = pool_knl_rm_property;
16417c478bd9Sstevel@tonic-gate 	pe->pe_get_props = pool_knl_get_properties;
16427c478bd9Sstevel@tonic-gate 	pe->pe_remove = pool_knl_elem_remove;
16437c478bd9Sstevel@tonic-gate 	pe->pe_get_container = pool_knl_get_container;
16447c478bd9Sstevel@tonic-gate 	pe->pe_set_container = pool_knl_set_container;
16457c478bd9Sstevel@tonic-gate 	/*
16467c478bd9Sstevel@tonic-gate 	 * Specific initialisation for different types of element
16477c478bd9Sstevel@tonic-gate 	 */
16487c478bd9Sstevel@tonic-gate 	if (class == PEC_POOL) {
16497c478bd9Sstevel@tonic-gate 		pool_knl_pool_t *pp = (pool_knl_pool_t *)elem;
16507c478bd9Sstevel@tonic-gate 		pp->pp_associate = pool_knl_pool_associate;
16517c478bd9Sstevel@tonic-gate 		pp->pp_dissociate = pool_knl_pool_dissociate;
16527c478bd9Sstevel@tonic-gate 		pp->pkp_assoc[PREC_PSET] = (pool_knl_resource_t *)
16537c478bd9Sstevel@tonic-gate 		    resource_by_sysid(conf, PS_NONE, "pset");
16547c478bd9Sstevel@tonic-gate 	}
16557c478bd9Sstevel@tonic-gate 	if (class == PEC_RES_COMP || class == PEC_RES_AGG) {
16567c478bd9Sstevel@tonic-gate 		pool_knl_resource_t *pr = (pool_knl_resource_t *)elem;
16577c478bd9Sstevel@tonic-gate 		pr->pr_is_system = pool_knl_resource_is_system;
16587c478bd9Sstevel@tonic-gate 		pr->pr_can_associate = pool_knl_resource_can_associate;
16597c478bd9Sstevel@tonic-gate 	}
16607c478bd9Sstevel@tonic-gate #if DEBUG
16617c478bd9Sstevel@tonic-gate 	if (dict_put(((pool_knl_connection_t *)conf->pc_prov)->pkc_leaks,
16627c478bd9Sstevel@tonic-gate 	    elem, elem) != NULL)
16637c478bd9Sstevel@tonic-gate 		assert(!"leak map put failed");
16647c478bd9Sstevel@tonic-gate 	dprintf("allocated %p\n", elem);
16657c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
16667c478bd9Sstevel@tonic-gate 	return (elem);
16677c478bd9Sstevel@tonic-gate }
16687c478bd9Sstevel@tonic-gate 
16697c478bd9Sstevel@tonic-gate /*
16707c478bd9Sstevel@tonic-gate  * Allocate a new pool_knl_elem_t in the supplied configuration of the
16717c478bd9Sstevel@tonic-gate  * specified class.
16727c478bd9Sstevel@tonic-gate  * Returns element pointer/NULL
16737c478bd9Sstevel@tonic-gate  */
16747c478bd9Sstevel@tonic-gate pool_elem_t *
16757c478bd9Sstevel@tonic-gate pool_knl_elem_create(pool_conf_t *conf, pool_elem_class_t class,
16767c478bd9Sstevel@tonic-gate     pool_resource_elem_class_t res_class,
16777c478bd9Sstevel@tonic-gate     pool_component_elem_class_t comp_class)
16787c478bd9Sstevel@tonic-gate {
16797c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *elem;
16807c478bd9Sstevel@tonic-gate 	pool_create_undo_t *create;
16817c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov = (pool_knl_connection_t *)conf->pc_prov;
16827c478bd9Sstevel@tonic-gate 	static int id = -3;
16837c478bd9Sstevel@tonic-gate 	char_buf_t *cb;
16847c478bd9Sstevel@tonic-gate 
16857c478bd9Sstevel@tonic-gate 	if ((elem = pool_knl_elem_wrap(conf, class, res_class, comp_class)) ==
16867c478bd9Sstevel@tonic-gate 	    NULL)
16877c478bd9Sstevel@tonic-gate 		return (NULL);
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate 	/*
16907c478bd9Sstevel@tonic-gate 	 * Allocate an nvlist to hold properties
16917c478bd9Sstevel@tonic-gate 	 */
16927c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&elem->pke_properties, NV_UNIQUE_NAME_TYPE, 0) != 0) {
16937c478bd9Sstevel@tonic-gate 		pool_knl_elem_free(elem, PO_FALSE);
16947c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
16957c478bd9Sstevel@tonic-gate 		return (NULL);
16967c478bd9Sstevel@tonic-gate 	}
16977c478bd9Sstevel@tonic-gate 	/*
16987c478bd9Sstevel@tonic-gate 	 * Allocate a temporary ID and name until the element is
16997c478bd9Sstevel@tonic-gate 	 * created for real
17007c478bd9Sstevel@tonic-gate 	 */
17017c478bd9Sstevel@tonic-gate 	if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
17027c478bd9Sstevel@tonic-gate 		pool_knl_elem_free(elem, PO_TRUE);
17037c478bd9Sstevel@tonic-gate 		return (NULL);
17047c478bd9Sstevel@tonic-gate 	}
17057c478bd9Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.sys_id",
17067c478bd9Sstevel@tonic-gate 	    pool_elem_class_string((pool_elem_t *)elem)) != PO_SUCCESS) {
17077c478bd9Sstevel@tonic-gate 		pool_knl_elem_free(elem, PO_TRUE);
17087c478bd9Sstevel@tonic-gate 		free_char_buf(cb);
17097c478bd9Sstevel@tonic-gate 		return (NULL);
17107c478bd9Sstevel@tonic-gate 	}
17117c478bd9Sstevel@tonic-gate 	(void) nvlist_add_int64(elem->pke_properties, cb->cb_buf, id--);
17127c478bd9Sstevel@tonic-gate 	if (set_char_buf(cb, "%s.name",
17137c478bd9Sstevel@tonic-gate 	    pool_elem_class_string((pool_elem_t *)elem)) != PO_SUCCESS) {
17147c478bd9Sstevel@tonic-gate 		pool_knl_elem_free(elem, PO_TRUE);
17157c478bd9Sstevel@tonic-gate 		free_char_buf(cb);
17167c478bd9Sstevel@tonic-gate 		return (NULL);
17177c478bd9Sstevel@tonic-gate 	}
17187c478bd9Sstevel@tonic-gate 	(void) nvlist_add_string(elem->pke_properties, cb->cb_buf, "");
17197c478bd9Sstevel@tonic-gate 	/*
17207c478bd9Sstevel@tonic-gate 	 * If it's a resource class, it will need an initial size
17217c478bd9Sstevel@tonic-gate 	 */
17227c478bd9Sstevel@tonic-gate 	if (class == PEC_RES_COMP || class == PEC_RES_AGG) {
17237c478bd9Sstevel@tonic-gate 		if (set_char_buf(cb, "%s.size",
17247c478bd9Sstevel@tonic-gate 		    pool_elem_class_string((pool_elem_t *)elem)) !=
17257c478bd9Sstevel@tonic-gate 		    PO_SUCCESS) {
17267c478bd9Sstevel@tonic-gate 			pool_knl_elem_free(elem, PO_TRUE);
17277c478bd9Sstevel@tonic-gate 			free_char_buf(cb);
17287c478bd9Sstevel@tonic-gate 			return (NULL);
17297c478bd9Sstevel@tonic-gate 		}
17307c478bd9Sstevel@tonic-gate 		(void) nvlist_add_uint64(elem->pke_properties, cb->cb_buf, 0);
17317c478bd9Sstevel@tonic-gate 	}
17327c478bd9Sstevel@tonic-gate 	free_char_buf(cb);
17337c478bd9Sstevel@tonic-gate 
17347c478bd9Sstevel@tonic-gate 	/*
17357c478bd9Sstevel@tonic-gate 	 * Register the newly created element
17367c478bd9Sstevel@tonic-gate 	 */
17377c478bd9Sstevel@tonic-gate 	if (dict_put(prov->pkc_elements, elem, elem) != NULL) {
17387c478bd9Sstevel@tonic-gate 		pool_knl_elem_free(elem, PO_TRUE);
17397c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
17407c478bd9Sstevel@tonic-gate 		return (NULL);
17417c478bd9Sstevel@tonic-gate 	}
17427c478bd9Sstevel@tonic-gate 
17437c478bd9Sstevel@tonic-gate 	if (prov->pkc_log->l_state != LS_DO)
17447c478bd9Sstevel@tonic-gate 		return ((pool_elem_t *)elem);
17457c478bd9Sstevel@tonic-gate 
17467c478bd9Sstevel@tonic-gate 	/*
17477c478bd9Sstevel@tonic-gate 	 * The remaining logic is setting up the arguments for the
17487c478bd9Sstevel@tonic-gate 	 * POOL_CREATE ioctl and appending the details into the log.
17497c478bd9Sstevel@tonic-gate 	 */
17507c478bd9Sstevel@tonic-gate 	if ((create = malloc(sizeof (pool_create_undo_t))) == NULL) {
17517c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
17527c478bd9Sstevel@tonic-gate 		return (NULL);
17537c478bd9Sstevel@tonic-gate 	}
17547c478bd9Sstevel@tonic-gate 	create->pcu_ioctl.pc_o_type = class;
17557c478bd9Sstevel@tonic-gate 	switch (class) {
17567c478bd9Sstevel@tonic-gate 	case PEC_SYSTEM:
17577c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
17587c478bd9Sstevel@tonic-gate 		free(create);
17597c478bd9Sstevel@tonic-gate 		return (NULL);
17607c478bd9Sstevel@tonic-gate 	case PEC_POOL: /* NO-OP */
17617c478bd9Sstevel@tonic-gate 		break;
17627c478bd9Sstevel@tonic-gate 	case PEC_RES_COMP:
17637c478bd9Sstevel@tonic-gate 	case PEC_RES_AGG:
17647c478bd9Sstevel@tonic-gate 		create->pcu_ioctl.pc_o_sub_type = res_class;
17657c478bd9Sstevel@tonic-gate 		break;
17667c478bd9Sstevel@tonic-gate 	case PEC_COMP:
17677c478bd9Sstevel@tonic-gate 		create->pcu_ioctl.pc_o_sub_type = comp_class;
17687c478bd9Sstevel@tonic-gate 		break;
17697c478bd9Sstevel@tonic-gate 	default:
17707c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
17717c478bd9Sstevel@tonic-gate 		free(create);
17727c478bd9Sstevel@tonic-gate 		return (NULL);
17737c478bd9Sstevel@tonic-gate 	}
17747c478bd9Sstevel@tonic-gate 
17757c478bd9Sstevel@tonic-gate 	create->pcu_elem = (pool_elem_t *)elem;
17767c478bd9Sstevel@tonic-gate 
17777c478bd9Sstevel@tonic-gate 	if (log_append(prov->pkc_log, POOL_CREATE, (void *)create) !=
17787c478bd9Sstevel@tonic-gate 	    PO_SUCCESS) {
17797c478bd9Sstevel@tonic-gate 		free(create);
17807c478bd9Sstevel@tonic-gate 		return (NULL);
17817c478bd9Sstevel@tonic-gate 	}
17827c478bd9Sstevel@tonic-gate 	return ((pool_elem_t *)elem);
17837c478bd9Sstevel@tonic-gate }
17847c478bd9Sstevel@tonic-gate 
17857c478bd9Sstevel@tonic-gate /*
17867c478bd9Sstevel@tonic-gate  * Remove the details of the element from our userland copy and destroy
17877c478bd9Sstevel@tonic-gate  * the element (if appropriate) in the kernel.
17887c478bd9Sstevel@tonic-gate  */
17897c478bd9Sstevel@tonic-gate int
17907c478bd9Sstevel@tonic-gate pool_knl_elem_remove(pool_elem_t *pe)
17917c478bd9Sstevel@tonic-gate {
17927c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov;
17937c478bd9Sstevel@tonic-gate 	pool_destroy_undo_t *destroy;
17947c478bd9Sstevel@tonic-gate 
17957c478bd9Sstevel@tonic-gate 	prov = (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
17967c478bd9Sstevel@tonic-gate 
17977c478bd9Sstevel@tonic-gate 	if (dict_remove(prov->pkc_elements, pe) == NULL) {
17987c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
17997c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
18007c478bd9Sstevel@tonic-gate 	}
18017c478bd9Sstevel@tonic-gate 	if (prov->pkc_log->l_state != LS_DO) {
18027c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
18037c478bd9Sstevel@tonic-gate 	}
18047c478bd9Sstevel@tonic-gate 
18057c478bd9Sstevel@tonic-gate 	/*
18067c478bd9Sstevel@tonic-gate 	 * The remaining logic is setting up the arguments for the
18077c478bd9Sstevel@tonic-gate 	 * POOL_DESTROY ioctl and appending the details into the log.
18087c478bd9Sstevel@tonic-gate 	 */
18097c478bd9Sstevel@tonic-gate 	if ((destroy = malloc(sizeof (pool_destroy_undo_t))) == NULL) {
18107c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
18117c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
18127c478bd9Sstevel@tonic-gate 	}
18137c478bd9Sstevel@tonic-gate 	destroy->pdu_ioctl.pd_o_type = pool_elem_class(pe);
18147c478bd9Sstevel@tonic-gate 
18157c478bd9Sstevel@tonic-gate 	if (destroy->pdu_ioctl.pd_o_type == PEC_RES_COMP ||
18167c478bd9Sstevel@tonic-gate 	    destroy->pdu_ioctl.pd_o_type == PEC_RES_AGG)
18177c478bd9Sstevel@tonic-gate 		destroy->pdu_ioctl.pd_o_sub_type = pool_resource_elem_class(pe);
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 	if (destroy->pdu_ioctl.pd_o_type == PEC_COMP)
18207c478bd9Sstevel@tonic-gate 		destroy->pdu_ioctl.pd_o_sub_type =
18217c478bd9Sstevel@tonic-gate 		    pool_component_elem_class(pe);
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate 	destroy->pdu_elem = pe;
18247c478bd9Sstevel@tonic-gate 
18257c478bd9Sstevel@tonic-gate 	if (log_append(prov->pkc_log, POOL_DESTROY, (void *)destroy) !=
18267c478bd9Sstevel@tonic-gate 	    PO_SUCCESS) {
18277c478bd9Sstevel@tonic-gate 		free(destroy);
18287c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
18297c478bd9Sstevel@tonic-gate 	}
18307c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
18317c478bd9Sstevel@tonic-gate }
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate /*
18347c478bd9Sstevel@tonic-gate  * Set the parent of the supplied child to the supplied parent
18357c478bd9Sstevel@tonic-gate  */
18367c478bd9Sstevel@tonic-gate int
18377c478bd9Sstevel@tonic-gate pool_knl_set_container(pool_elem_t *pp, pool_elem_t *pc)
18387c478bd9Sstevel@tonic-gate {
18397c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pkp = (pool_knl_elem_t *)pp;
18407c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pkc = (pool_knl_elem_t *)pc;
18417c478bd9Sstevel@tonic-gate 
18427c478bd9Sstevel@tonic-gate 	pkc->pke_parent = pkp;
18437c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
18447c478bd9Sstevel@tonic-gate }
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate /*
18477c478bd9Sstevel@tonic-gate  * TODO: Needed for msets and ssets.
18487c478bd9Sstevel@tonic-gate  */
18497c478bd9Sstevel@tonic-gate /* ARGSUSED */
18507c478bd9Sstevel@tonic-gate int
18517c478bd9Sstevel@tonic-gate pool_knl_res_transfer(pool_resource_t *src, pool_resource_t *tgt,
18527c478bd9Sstevel@tonic-gate     uint64_t size) {
18537c478bd9Sstevel@tonic-gate 	return (PO_FAIL);
18547c478bd9Sstevel@tonic-gate }
18557c478bd9Sstevel@tonic-gate 
18567c478bd9Sstevel@tonic-gate /*
18577c478bd9Sstevel@tonic-gate  * Transfer resource components from one resource set to another.
18587c478bd9Sstevel@tonic-gate  */
18597c478bd9Sstevel@tonic-gate int
18607c478bd9Sstevel@tonic-gate pool_knl_res_xtransfer(pool_resource_t *src, pool_resource_t *tgt,
18617c478bd9Sstevel@tonic-gate     pool_component_t **rl) {
18627c478bd9Sstevel@tonic-gate 	pool_elem_t *src_e = TO_ELEM(src);
18637c478bd9Sstevel@tonic-gate 	pool_elem_t *tgt_e = TO_ELEM(tgt);
18647c478bd9Sstevel@tonic-gate 	pool_xtransfer_undo_t *xtransfer;
18657c478bd9Sstevel@tonic-gate 	size_t size;
18667c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov =
18677c478bd9Sstevel@tonic-gate 	    (pool_knl_connection_t *)TO_CONF(src_e)->pc_prov;
18687c478bd9Sstevel@tonic-gate 
18697c478bd9Sstevel@tonic-gate 	if (prov->pkc_log->l_state != LS_DO) {
18707c478bd9Sstevel@tonic-gate 		/*
18717c478bd9Sstevel@tonic-gate 		 * Walk the Result Set and move the resource components
18727c478bd9Sstevel@tonic-gate 		 */
18737c478bd9Sstevel@tonic-gate 		for (size = 0; rl[size] != NULL; size++) {
18747c478bd9Sstevel@tonic-gate 			if (pool_set_container(TO_ELEM(tgt),
18757c478bd9Sstevel@tonic-gate 			    TO_ELEM(rl[size])) == PO_FAIL) {
18767c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
18777c478bd9Sstevel@tonic-gate 			}
18787c478bd9Sstevel@tonic-gate 		}
18797c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
18807c478bd9Sstevel@tonic-gate 	}
18817c478bd9Sstevel@tonic-gate 
18827c478bd9Sstevel@tonic-gate 	/*
18837c478bd9Sstevel@tonic-gate 	 * The remaining logic is setting up the arguments for the
18847c478bd9Sstevel@tonic-gate 	 * POOL_XTRANSFER ioctl and appending the details into the log.
18857c478bd9Sstevel@tonic-gate 	 */
18867c478bd9Sstevel@tonic-gate 	if ((xtransfer = malloc(sizeof (pool_xtransfer_undo_t))) == NULL) {
18877c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
18887c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
18897c478bd9Sstevel@tonic-gate 	}
18907c478bd9Sstevel@tonic-gate 
18917c478bd9Sstevel@tonic-gate 	if (pool_elem_class(src_e) == PEC_RES_COMP) {
18927c478bd9Sstevel@tonic-gate 		xtransfer->pxu_ioctl.px_o_id_type =
18937c478bd9Sstevel@tonic-gate 		    pool_resource_elem_class(src_e);
18947c478bd9Sstevel@tonic-gate 	} else {
18957c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
18967c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
18977c478bd9Sstevel@tonic-gate 	}
18987c478bd9Sstevel@tonic-gate 
18997c478bd9Sstevel@tonic-gate 
19007c478bd9Sstevel@tonic-gate 	for (xtransfer->pxu_ioctl.px_o_complist_size = 0;
19017c478bd9Sstevel@tonic-gate 	    rl[xtransfer->pxu_ioctl.px_o_complist_size] != NULL;
19027c478bd9Sstevel@tonic-gate 	    xtransfer->pxu_ioctl.px_o_complist_size++)
19037c478bd9Sstevel@tonic-gate 		/* calculate the size using the terminating NULL */;
19047c478bd9Sstevel@tonic-gate 	if ((xtransfer->pxu_ioctl.px_o_comp_list =
19057c478bd9Sstevel@tonic-gate 		calloc(xtransfer->pxu_ioctl.px_o_complist_size,
19067c478bd9Sstevel@tonic-gate 		sizeof (id_t))) == NULL) {
19077c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
19087c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
19097c478bd9Sstevel@tonic-gate 	}
19107c478bd9Sstevel@tonic-gate 	if ((xtransfer->pxu_rl = calloc(
19117c478bd9Sstevel@tonic-gate 	    xtransfer->pxu_ioctl.px_o_complist_size + 1,
19127c478bd9Sstevel@tonic-gate 	    sizeof (pool_component_t *))) == NULL) {
19137c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
19147c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
19157c478bd9Sstevel@tonic-gate 	}
19167c478bd9Sstevel@tonic-gate 	(void) memcpy(xtransfer->pxu_rl, rl,
19177c478bd9Sstevel@tonic-gate 	    xtransfer->pxu_ioctl.px_o_complist_size *
19187c478bd9Sstevel@tonic-gate 	    sizeof (pool_component_t *));
19197c478bd9Sstevel@tonic-gate 	xtransfer->pxu_src = src_e;
19207c478bd9Sstevel@tonic-gate 	xtransfer->pxu_tgt = tgt_e;
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate 	if (log_append(prov->pkc_log, POOL_XTRANSFER, (void *)xtransfer) !=
19237c478bd9Sstevel@tonic-gate 	    PO_SUCCESS) {
19247c478bd9Sstevel@tonic-gate 		free(xtransfer);
19257c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
19267c478bd9Sstevel@tonic-gate 	}
19277c478bd9Sstevel@tonic-gate 	for (size = 0; rl[size] != NULL; size++) {
19287c478bd9Sstevel@tonic-gate 		if (pool_set_container(TO_ELEM(tgt), TO_ELEM(rl[size])) ==
19297c478bd9Sstevel@tonic-gate 		    PO_FAIL) {
19307c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
19317c478bd9Sstevel@tonic-gate 		}
19327c478bd9Sstevel@tonic-gate 	}
19337c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
19347c478bd9Sstevel@tonic-gate }
19357c478bd9Sstevel@tonic-gate 
19367c478bd9Sstevel@tonic-gate /*
19377c478bd9Sstevel@tonic-gate  * Return the parent of an element.
19387c478bd9Sstevel@tonic-gate  */
19397c478bd9Sstevel@tonic-gate pool_elem_t *
19407c478bd9Sstevel@tonic-gate pool_knl_get_container(const pool_elem_t *pe)
19417c478bd9Sstevel@tonic-gate {
19427c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
19437c478bd9Sstevel@tonic-gate 
19447c478bd9Sstevel@tonic-gate 	return ((pool_elem_t *)pke->pke_parent);
19457c478bd9Sstevel@tonic-gate }
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate /*
19487c478bd9Sstevel@tonic-gate  * Note: This function is resource specific, needs extending for other
19497c478bd9Sstevel@tonic-gate  * resource types
19507c478bd9Sstevel@tonic-gate  */
19517c478bd9Sstevel@tonic-gate int
19527c478bd9Sstevel@tonic-gate pool_knl_resource_is_system(const pool_resource_t *pr)
19537c478bd9Sstevel@tonic-gate {
19547c478bd9Sstevel@tonic-gate 	switch (pool_resource_elem_class(TO_ELEM(pr))) {
19557c478bd9Sstevel@tonic-gate 	case PREC_PSET:
19567c478bd9Sstevel@tonic-gate 		return (PSID_IS_SYSSET(
19577c478bd9Sstevel@tonic-gate 		    elem_get_sysid(TO_ELEM(pr))));
19587c478bd9Sstevel@tonic-gate 	default:
19597c478bd9Sstevel@tonic-gate 		return (PO_FALSE);
19607c478bd9Sstevel@tonic-gate 	}
19617c478bd9Sstevel@tonic-gate }
19627c478bd9Sstevel@tonic-gate 
19637c478bd9Sstevel@tonic-gate /*
19647c478bd9Sstevel@tonic-gate  * Note: This function is resource specific, needs extending for other
19657c478bd9Sstevel@tonic-gate  * resource types
19667c478bd9Sstevel@tonic-gate  */
19677c478bd9Sstevel@tonic-gate int
19687c478bd9Sstevel@tonic-gate pool_knl_resource_can_associate(const pool_resource_t *pr)
19697c478bd9Sstevel@tonic-gate {
19707c478bd9Sstevel@tonic-gate 	switch (pool_resource_elem_class(TO_ELEM(pr))) {
19717c478bd9Sstevel@tonic-gate 	case PREC_PSET:
19727c478bd9Sstevel@tonic-gate 		return (PO_TRUE);
19737c478bd9Sstevel@tonic-gate 	default:
19747c478bd9Sstevel@tonic-gate 		return (PO_FALSE);
19757c478bd9Sstevel@tonic-gate 	}
19767c478bd9Sstevel@tonic-gate }
19777c478bd9Sstevel@tonic-gate 
19787c478bd9Sstevel@tonic-gate /*
19797c478bd9Sstevel@tonic-gate  * pool_knl_pool_associate() associates the supplied resource to the
19807c478bd9Sstevel@tonic-gate  * supplied pool.
19817c478bd9Sstevel@tonic-gate  *
19827c478bd9Sstevel@tonic-gate  * Returns: PO_SUCCESS/PO_FAIL
19837c478bd9Sstevel@tonic-gate  */
19847c478bd9Sstevel@tonic-gate int
19857c478bd9Sstevel@tonic-gate pool_knl_pool_associate(pool_t *pool, const pool_resource_t *resource)
19867c478bd9Sstevel@tonic-gate {
19877c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov;
19887c478bd9Sstevel@tonic-gate 	pool_knl_pool_t *pkp = (pool_knl_pool_t *)pool;
19897c478bd9Sstevel@tonic-gate 	pool_resource_elem_class_t res_class =
19907c478bd9Sstevel@tonic-gate 	    pool_resource_elem_class(TO_ELEM(resource));
19917c478bd9Sstevel@tonic-gate 	pool_assoc_undo_t *assoc;
19927c478bd9Sstevel@tonic-gate 	pool_knl_resource_t *orig_res = pkp->pkp_assoc[res_class];
19937c478bd9Sstevel@tonic-gate 
19947c478bd9Sstevel@tonic-gate 	/*
19957c478bd9Sstevel@tonic-gate 	 * Are we allowed to associate with this target?
19967c478bd9Sstevel@tonic-gate 	 */
19977c478bd9Sstevel@tonic-gate 	if (pool_knl_resource_can_associate(resource) == PO_FALSE) {
19987c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
19997c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
20007c478bd9Sstevel@tonic-gate 	}
20017c478bd9Sstevel@tonic-gate 	prov = (pool_knl_connection_t *)(TO_CONF(TO_ELEM(pool)))->pc_prov;
20027c478bd9Sstevel@tonic-gate 
20037c478bd9Sstevel@tonic-gate 	if (prov->pkc_log->l_state != LS_DO) {
20047c478bd9Sstevel@tonic-gate 		pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
20057c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
20067c478bd9Sstevel@tonic-gate 	}
20077c478bd9Sstevel@tonic-gate 
20087c478bd9Sstevel@tonic-gate 	/*
20097c478bd9Sstevel@tonic-gate 	 * The remaining logic is setting up the arguments for the
20107c478bd9Sstevel@tonic-gate 	 * POOL_ASSOC ioctl and appending the details into the log.
20117c478bd9Sstevel@tonic-gate 	 */
20127c478bd9Sstevel@tonic-gate 	if ((assoc = malloc(sizeof (pool_assoc_undo_t))) == NULL) {
20137c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
20147c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
20157c478bd9Sstevel@tonic-gate 	}
20167c478bd9Sstevel@tonic-gate 	assoc->pau_assoc = TO_ELEM(pool);
20177c478bd9Sstevel@tonic-gate 	assoc->pau_oldres = (pool_elem_t *)orig_res;
20187c478bd9Sstevel@tonic-gate 	assoc->pau_newres = TO_ELEM(resource);
20197c478bd9Sstevel@tonic-gate 
20207c478bd9Sstevel@tonic-gate 	assoc->pau_ioctl.pa_o_id_type = res_class;
20217c478bd9Sstevel@tonic-gate 
20227c478bd9Sstevel@tonic-gate 	if (log_append(prov->pkc_log, POOL_ASSOC, (void *)assoc) !=
20237c478bd9Sstevel@tonic-gate 	    PO_SUCCESS) {
20247c478bd9Sstevel@tonic-gate 		free(assoc);
20257c478bd9Sstevel@tonic-gate 		pkp->pkp_assoc[res_class] = orig_res;
20267c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
20277c478bd9Sstevel@tonic-gate 	}
20287c478bd9Sstevel@tonic-gate 	pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
20297c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
20307c478bd9Sstevel@tonic-gate }
20317c478bd9Sstevel@tonic-gate 
20327c478bd9Sstevel@tonic-gate /*
20337c478bd9Sstevel@tonic-gate  * pool_knl_pool_dissociate() dissociates the supplied resource from
20347c478bd9Sstevel@tonic-gate  * the supplied pool.
20357c478bd9Sstevel@tonic-gate  *
20367c478bd9Sstevel@tonic-gate  * Returns: PO_SUCCESS/PO_FAIL
20377c478bd9Sstevel@tonic-gate  */
20387c478bd9Sstevel@tonic-gate int
20397c478bd9Sstevel@tonic-gate pool_knl_pool_dissociate(pool_t *pool, const pool_resource_t *resource)
20407c478bd9Sstevel@tonic-gate {
20417c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov;
20427c478bd9Sstevel@tonic-gate 	pool_dissoc_undo_t *dissoc;
20437c478bd9Sstevel@tonic-gate 	pool_knl_pool_t *pkp = (pool_knl_pool_t *)pool;
20447c478bd9Sstevel@tonic-gate 	pool_resource_t *default_res = (pool_resource_t *)get_default_resource(
20457c478bd9Sstevel@tonic-gate 	    resource);
20467c478bd9Sstevel@tonic-gate 	pool_resource_elem_class_t res_class =
20477c478bd9Sstevel@tonic-gate 	    pool_resource_elem_class(TO_ELEM(resource));
20487c478bd9Sstevel@tonic-gate 
20497c478bd9Sstevel@tonic-gate 	prov = (pool_knl_connection_t *)(TO_CONF(TO_ELEM(pool)))->pc_prov;
20507c478bd9Sstevel@tonic-gate 
20517c478bd9Sstevel@tonic-gate 	if (prov->pkc_log->l_state != LS_DO) {
20527c478bd9Sstevel@tonic-gate 		pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)default_res;
20537c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
20547c478bd9Sstevel@tonic-gate 	}
20557c478bd9Sstevel@tonic-gate 	/*
20567c478bd9Sstevel@tonic-gate 	 * The remaining logic is setting up the arguments for the
20577c478bd9Sstevel@tonic-gate 	 * POOL_DISSOC ioctl and appending the details into the log.
20587c478bd9Sstevel@tonic-gate 	 */
20597c478bd9Sstevel@tonic-gate 	if ((dissoc = malloc(sizeof (pool_dissoc_undo_t))) == NULL) {
20607c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
20617c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
20627c478bd9Sstevel@tonic-gate 	}
20637c478bd9Sstevel@tonic-gate 	dissoc->pdu_dissoc = TO_ELEM(pool);
20647c478bd9Sstevel@tonic-gate 	dissoc->pdu_oldres = TO_ELEM(resource);
20657c478bd9Sstevel@tonic-gate 	dissoc->pdu_newres = TO_ELEM(default_res);
20667c478bd9Sstevel@tonic-gate 
20677c478bd9Sstevel@tonic-gate 	dissoc->pdu_ioctl.pd_o_id_type = res_class;
20687c478bd9Sstevel@tonic-gate 
20697c478bd9Sstevel@tonic-gate 	if (log_append(prov->pkc_log, POOL_DISSOC, (void *)dissoc) !=
20707c478bd9Sstevel@tonic-gate 	    PO_SUCCESS) {
20717c478bd9Sstevel@tonic-gate 		free(dissoc);
20727c478bd9Sstevel@tonic-gate 		pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)resource;
20737c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
20747c478bd9Sstevel@tonic-gate 	}
20757c478bd9Sstevel@tonic-gate 
20767c478bd9Sstevel@tonic-gate 	/*
20777c478bd9Sstevel@tonic-gate 	 * Update our local copy
20787c478bd9Sstevel@tonic-gate 	 */
20797c478bd9Sstevel@tonic-gate 	pkp->pkp_assoc[res_class] = (pool_knl_resource_t *)default_res;
20807c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
20817c478bd9Sstevel@tonic-gate }
20827c478bd9Sstevel@tonic-gate 
20837c478bd9Sstevel@tonic-gate /*
20847c478bd9Sstevel@tonic-gate  * Allocate a data provider for the supplied configuration and optionally
20857c478bd9Sstevel@tonic-gate  * discover resources.
20867c478bd9Sstevel@tonic-gate  * The data provider is the cross over point from the "abstract" configuration
20877c478bd9Sstevel@tonic-gate  * functions into the data representation specific manipulation routines.
20887c478bd9Sstevel@tonic-gate  * This function sets up all the required pointers to create a kernel aware
20897c478bd9Sstevel@tonic-gate  * data provider.
20907c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
20917c478bd9Sstevel@tonic-gate  */
20927c478bd9Sstevel@tonic-gate int
20937c478bd9Sstevel@tonic-gate pool_knl_connection_alloc(pool_conf_t *conf, int oflags)
20947c478bd9Sstevel@tonic-gate {
20957c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov;
20967c478bd9Sstevel@tonic-gate 
20977c478bd9Sstevel@tonic-gate 	if ((prov = malloc(sizeof (pool_knl_connection_t))) == NULL) {
20987c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
20997c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
21007c478bd9Sstevel@tonic-gate 	}
21017c478bd9Sstevel@tonic-gate 	(void) memset(prov, 0, sizeof (pool_knl_connection_t));
21027c478bd9Sstevel@tonic-gate 	/*
21037c478bd9Sstevel@tonic-gate 	 * Initialise data members
21047c478bd9Sstevel@tonic-gate 	 */
21057c478bd9Sstevel@tonic-gate 	prov->pc_name = strdup("kernel");
21067c478bd9Sstevel@tonic-gate 	prov->pc_store_type = KERNEL_DATA_STORE;
21077c478bd9Sstevel@tonic-gate 	prov->pc_oflags = oflags;
21087c478bd9Sstevel@tonic-gate 	/*
21097c478bd9Sstevel@tonic-gate 	 * Initialise function pointers
21107c478bd9Sstevel@tonic-gate 	 */
21117c478bd9Sstevel@tonic-gate 	prov->pc_close = pool_knl_close;
21127c478bd9Sstevel@tonic-gate 	prov->pc_validate = pool_knl_validate;
21137c478bd9Sstevel@tonic-gate 	prov->pc_commit = pool_knl_commit;
21147c478bd9Sstevel@tonic-gate 	prov->pc_export = pool_knl_export;
21157c478bd9Sstevel@tonic-gate 	prov->pc_rollback = pool_knl_rollback;
21167c478bd9Sstevel@tonic-gate 	prov->pc_exec_query = pool_knl_exec_query;
21177c478bd9Sstevel@tonic-gate 	prov->pc_elem_create = pool_knl_elem_create;
21187c478bd9Sstevel@tonic-gate 	prov->pc_remove = pool_knl_remove;
21197c478bd9Sstevel@tonic-gate 	prov->pc_res_xfer = pool_knl_res_transfer;
21207c478bd9Sstevel@tonic-gate 	prov->pc_res_xxfer = pool_knl_res_xtransfer;
21217c478bd9Sstevel@tonic-gate 	prov->pc_get_binding = pool_knl_get_binding;
21227c478bd9Sstevel@tonic-gate 	prov->pc_set_binding = pool_knl_set_binding;
21237c478bd9Sstevel@tonic-gate 	prov->pc_get_resource_binding = pool_knl_get_resource_binding;
21247c478bd9Sstevel@tonic-gate 	/*
21257c478bd9Sstevel@tonic-gate 	 * Associate the provider to it's configuration
21267c478bd9Sstevel@tonic-gate 	 */
21277c478bd9Sstevel@tonic-gate 	conf->pc_prov = (pool_connection_t *)prov;
21287c478bd9Sstevel@tonic-gate 	/*
21297c478bd9Sstevel@tonic-gate 	 * End of common initialisation
21307c478bd9Sstevel@tonic-gate 	 */
21317c478bd9Sstevel@tonic-gate 	/*
21327c478bd9Sstevel@tonic-gate 	 * Attempt to open the pseudo device, if the configuration is opened
21337c478bd9Sstevel@tonic-gate 	 * readonly then try to open an info device, otherwise try to open
21347c478bd9Sstevel@tonic-gate 	 * the writeable device.
21357c478bd9Sstevel@tonic-gate 	 */
21367c478bd9Sstevel@tonic-gate 	if (oflags & PO_RDWR) {
21377c478bd9Sstevel@tonic-gate 		if ((prov->pkc_fd = blocking_open(pool_dynamic_location(),
21387c478bd9Sstevel@tonic-gate 		    O_RDWR)) < 0) {
21397c478bd9Sstevel@tonic-gate 			free(prov);
21407c478bd9Sstevel@tonic-gate 			conf->pc_prov = NULL;
21417c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
21427c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
21437c478bd9Sstevel@tonic-gate 		}
21447c478bd9Sstevel@tonic-gate 	} else {
21457c478bd9Sstevel@tonic-gate 		if ((prov->pkc_fd = open(pool_info_location, O_RDWR)) < 0) {
21467c478bd9Sstevel@tonic-gate 			free(prov);
21477c478bd9Sstevel@tonic-gate 			conf->pc_prov = NULL;
21487c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
21497c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
21507c478bd9Sstevel@tonic-gate 		}
21517c478bd9Sstevel@tonic-gate 	}
21527c478bd9Sstevel@tonic-gate 	/*
21537c478bd9Sstevel@tonic-gate 	 * Allocate the element dictionary
21547c478bd9Sstevel@tonic-gate 	 */
21557c478bd9Sstevel@tonic-gate 	if ((prov->pkc_elements = dict_new((int (*)(const void *, const void *))
21567c478bd9Sstevel@tonic-gate 	    pool_elem_compare, (uint64_t (*)(const void *))hash_id)) == NULL) {
21577c478bd9Sstevel@tonic-gate 		(void) close(prov->pkc_fd);
21587c478bd9Sstevel@tonic-gate 		free(prov);
21597c478bd9Sstevel@tonic-gate 		conf->pc_prov = NULL;
21607c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
21617c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
21627c478bd9Sstevel@tonic-gate 	}
21637c478bd9Sstevel@tonic-gate #if DEBUG
21647c478bd9Sstevel@tonic-gate 	if ((prov->pkc_leaks = dict_new(NULL, NULL)) == NULL) {
21657c478bd9Sstevel@tonic-gate 		dict_free(&prov->pkc_elements);
21667c478bd9Sstevel@tonic-gate 		(void) close(prov->pkc_fd);
21677c478bd9Sstevel@tonic-gate 		free(prov);
21687c478bd9Sstevel@tonic-gate 		conf->pc_prov = NULL;
21697c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
21707c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
21717c478bd9Sstevel@tonic-gate 	}
21727c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
21737c478bd9Sstevel@tonic-gate 	/*
21747c478bd9Sstevel@tonic-gate 	 * Allocate the transaction log
21757c478bd9Sstevel@tonic-gate 	 */
21767c478bd9Sstevel@tonic-gate 	if ((prov->pkc_log = log_alloc(conf)) == NULL) {
21777c478bd9Sstevel@tonic-gate #if DEBUG
21787c478bd9Sstevel@tonic-gate 		dict_free(&prov->pkc_leaks);
21797c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
21807c478bd9Sstevel@tonic-gate 		dict_free(&prov->pkc_elements);
21817c478bd9Sstevel@tonic-gate 		(void) close(prov->pkc_fd);
21827c478bd9Sstevel@tonic-gate 		free(prov);
21837c478bd9Sstevel@tonic-gate 		conf->pc_prov = NULL;
21847c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
21857c478bd9Sstevel@tonic-gate 	}
21867c478bd9Sstevel@tonic-gate 	/*
21877c478bd9Sstevel@tonic-gate 	 * At this point the configuration provider has been initialized,
21887c478bd9Sstevel@tonic-gate 	 * mark the configuration as valid so that the various routines
21897c478bd9Sstevel@tonic-gate 	 * which rely on a valid configuration will work correctly.
21907c478bd9Sstevel@tonic-gate 	 */
21917c478bd9Sstevel@tonic-gate 	conf->pc_state = POF_VALID;
21927c478bd9Sstevel@tonic-gate 	/*
21937c478bd9Sstevel@tonic-gate 	 * Update the library snapshot from the kernel
21947c478bd9Sstevel@tonic-gate 	 */
21957c478bd9Sstevel@tonic-gate 	if (pool_knl_update(conf, NULL) != PO_SUCCESS) {
21967c478bd9Sstevel@tonic-gate #if DEBUG
21977c478bd9Sstevel@tonic-gate 		dict_free(&prov->pkc_leaks);
21987c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
21997c478bd9Sstevel@tonic-gate 		dict_free(&prov->pkc_elements);
22007c478bd9Sstevel@tonic-gate 		(void) close(prov->pkc_fd);
22017c478bd9Sstevel@tonic-gate 		free(prov);
22027c478bd9Sstevel@tonic-gate 		conf->pc_prov = NULL;
22037c478bd9Sstevel@tonic-gate 		conf->pc_state = POF_INVALID;
22047c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
22057c478bd9Sstevel@tonic-gate 	}
22067c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
22077c478bd9Sstevel@tonic-gate }
22087c478bd9Sstevel@tonic-gate 
22097c478bd9Sstevel@tonic-gate #if DEBUG
22107c478bd9Sstevel@tonic-gate static void
22117c478bd9Sstevel@tonic-gate pool_knl_elem_printf_cb(const void *key, void **value, void *cl)
22127c478bd9Sstevel@tonic-gate {
22137c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
22147c478bd9Sstevel@tonic-gate 	dict_hdl_t *map = (dict_hdl_t *)cl;
22157c478bd9Sstevel@tonic-gate 
22167c478bd9Sstevel@tonic-gate 	dprintf("leak elem:%p\n", pke);
22177c478bd9Sstevel@tonic-gate 	if (pke->pke_properties != NULL) {
22187c478bd9Sstevel@tonic-gate 		nvlist_print(stdout, pke->pke_properties);
22197c478bd9Sstevel@tonic-gate 	} else
22207c478bd9Sstevel@tonic-gate 		dprintf("no properties\n");
22217c478bd9Sstevel@tonic-gate 	assert(dict_get(map, pke) == NULL);
22227c478bd9Sstevel@tonic-gate }
22237c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
22247c478bd9Sstevel@tonic-gate /*
22257c478bd9Sstevel@tonic-gate  * pool_knl_elem_free() releases the resources associated with the
22267c478bd9Sstevel@tonic-gate  * supplied element.
22277c478bd9Sstevel@tonic-gate  */
22287c478bd9Sstevel@tonic-gate static void
22297c478bd9Sstevel@tonic-gate pool_knl_elem_free(pool_knl_elem_t *pke, int freeprop)
22307c478bd9Sstevel@tonic-gate {
22317c478bd9Sstevel@tonic-gate #if DEBUG
22327c478bd9Sstevel@tonic-gate 	pool_conf_t *conf = TO_CONF(TO_ELEM(pke));
22337c478bd9Sstevel@tonic-gate 	if (dict_remove(((pool_knl_connection_t *)conf->pc_prov)->pkc_leaks,
22347c478bd9Sstevel@tonic-gate 	    pke) == NULL)
22357c478bd9Sstevel@tonic-gate 		dprintf("%p, wasn't in the leak map\n", pke);
22367c478bd9Sstevel@tonic-gate 	if (freeprop == PO_TRUE) {
22377c478bd9Sstevel@tonic-gate 		pool_elem_dprintf(TO_ELEM(pke));
22387c478bd9Sstevel@tonic-gate 	}
22397c478bd9Sstevel@tonic-gate 	dprintf("released %p\n", pke);
22407c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
22417c478bd9Sstevel@tonic-gate 	if (freeprop == PO_TRUE) {
22427c478bd9Sstevel@tonic-gate 		nvlist_free(pke->pke_properties);
22437c478bd9Sstevel@tonic-gate 	}
22447c478bd9Sstevel@tonic-gate 	free(pke);
22457c478bd9Sstevel@tonic-gate }
22467c478bd9Sstevel@tonic-gate 
22477c478bd9Sstevel@tonic-gate /*
22487c478bd9Sstevel@tonic-gate  * pool_knl_elem_free_cb() is designed to be used with
22497c478bd9Sstevel@tonic-gate  * dict_map(). When a connection is freed, this function is used to
22507c478bd9Sstevel@tonic-gate  * free all element resources.
22517c478bd9Sstevel@tonic-gate  */
22527c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
22537c478bd9Sstevel@tonic-gate static void
22547c478bd9Sstevel@tonic-gate pool_knl_elem_free_cb(const void *key, void **value, void *cl)
22557c478bd9Sstevel@tonic-gate {
22567c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)key;
22577c478bd9Sstevel@tonic-gate 
22587c478bd9Sstevel@tonic-gate #ifdef DEBUG
22597c478bd9Sstevel@tonic-gate 	dprintf("pool_knl_elem_free_cb:\n");
22607c478bd9Sstevel@tonic-gate 	dprintf("about to release %p ", pke);
22617c478bd9Sstevel@tonic-gate 	pool_elem_dprintf(TO_ELEM(pke));
22627c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
22637c478bd9Sstevel@tonic-gate 	pool_knl_elem_free(pke, PO_TRUE);
22647c478bd9Sstevel@tonic-gate }
22657c478bd9Sstevel@tonic-gate 
22667c478bd9Sstevel@tonic-gate /*
22677c478bd9Sstevel@tonic-gate  * Free the resources for a kernel data provider.
22687c478bd9Sstevel@tonic-gate  */
22697c478bd9Sstevel@tonic-gate void
22707c478bd9Sstevel@tonic-gate pool_knl_connection_free(pool_knl_connection_t *prov)
22717c478bd9Sstevel@tonic-gate {
22727c478bd9Sstevel@tonic-gate 	if (prov->pkc_log != NULL) {
22737c478bd9Sstevel@tonic-gate 		(void) log_walk(prov->pkc_log, log_item_release);
22747c478bd9Sstevel@tonic-gate 		log_free(prov->pkc_log);
22757c478bd9Sstevel@tonic-gate 	}
22767c478bd9Sstevel@tonic-gate 	if (prov->pkc_elements != NULL) {
22777c478bd9Sstevel@tonic-gate 		dict_map(prov->pkc_elements, pool_knl_elem_free_cb, NULL);
22787c478bd9Sstevel@tonic-gate #if DEBUG
22797c478bd9Sstevel@tonic-gate 		dprintf("dict length is %llu\n", dict_length(prov->pkc_leaks));
22807c478bd9Sstevel@tonic-gate 		dict_map(prov->pkc_leaks, pool_knl_elem_printf_cb,
22817c478bd9Sstevel@tonic-gate 		    prov->pkc_elements);
22827c478bd9Sstevel@tonic-gate 		assert(dict_length(prov->pkc_leaks) == 0);
22837c478bd9Sstevel@tonic-gate 		dict_free(&prov->pkc_leaks);
22847c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
22857c478bd9Sstevel@tonic-gate 		dict_free(&prov->pkc_elements);
22867c478bd9Sstevel@tonic-gate 	}
22877c478bd9Sstevel@tonic-gate 	free((void *)prov->pc_name);
22887c478bd9Sstevel@tonic-gate 	free(prov);
22897c478bd9Sstevel@tonic-gate }
22907c478bd9Sstevel@tonic-gate 
22917c478bd9Sstevel@tonic-gate /*
22927c478bd9Sstevel@tonic-gate  * Return the specified property value.
22937c478bd9Sstevel@tonic-gate  *
22947c478bd9Sstevel@tonic-gate  * POC_INVAL is returned if an error is detected and the error code is updated
22957c478bd9Sstevel@tonic-gate  * to indicate the cause of the error.
22967c478bd9Sstevel@tonic-gate  */
22977c478bd9Sstevel@tonic-gate pool_value_class_t
22987c478bd9Sstevel@tonic-gate pool_knl_get_property(const pool_elem_t *pe, const char *name,
22997c478bd9Sstevel@tonic-gate     pool_value_t *val)
23007c478bd9Sstevel@tonic-gate {
23017c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
23027c478bd9Sstevel@tonic-gate 	nvpair_t *pair;
23037c478bd9Sstevel@tonic-gate 	const pool_prop_t *prop;
23047c478bd9Sstevel@tonic-gate 
23057c478bd9Sstevel@tonic-gate 	if ((prop = provider_get_prop(pe, name)) != NULL)
23067c478bd9Sstevel@tonic-gate 		if (prop_is_stored(prop) == PO_FALSE)
23077c478bd9Sstevel@tonic-gate 			return (pool_knl_get_dynamic_property(pe, name, val));
23087c478bd9Sstevel@tonic-gate 
23097c478bd9Sstevel@tonic-gate 	if ((pair = pool_knl_find_nvpair(pke->pke_properties, name)) == NULL) {
23107c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
23117c478bd9Sstevel@tonic-gate 		return (POC_INVAL);
23127c478bd9Sstevel@tonic-gate 	}
23137c478bd9Sstevel@tonic-gate 
23147c478bd9Sstevel@tonic-gate 	if (pool_value_from_nvpair(val, pair) == PO_FAIL) {
23157c478bd9Sstevel@tonic-gate 		return (POC_INVAL);
23167c478bd9Sstevel@tonic-gate 	}
23177c478bd9Sstevel@tonic-gate 
23187c478bd9Sstevel@tonic-gate 	return (pool_value_get_type(val));
23197c478bd9Sstevel@tonic-gate }
23207c478bd9Sstevel@tonic-gate 
23217c478bd9Sstevel@tonic-gate /*
23227c478bd9Sstevel@tonic-gate  * Return the specified property value.
23237c478bd9Sstevel@tonic-gate  *
23247c478bd9Sstevel@tonic-gate  * If a property is designated as dynamic, then this function will
23257c478bd9Sstevel@tonic-gate  * always try to return the latest value of the property from the
23267c478bd9Sstevel@tonic-gate  * kernel.
23277c478bd9Sstevel@tonic-gate  *
23287c478bd9Sstevel@tonic-gate  * POC_INVAL is returned if an error is detected and the error code is updated
23297c478bd9Sstevel@tonic-gate  * to indicate the cause of the error.
23307c478bd9Sstevel@tonic-gate  */
23317c478bd9Sstevel@tonic-gate pool_value_class_t
23327c478bd9Sstevel@tonic-gate pool_knl_get_dynamic_property(const pool_elem_t *pe, const char *name,
23337c478bd9Sstevel@tonic-gate     pool_value_t *val)
23347c478bd9Sstevel@tonic-gate {
23357c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov;
23367c478bd9Sstevel@tonic-gate 	pool_propget_t propget = { 0 };
23377c478bd9Sstevel@tonic-gate 	nvlist_t *proplist;
23387c478bd9Sstevel@tonic-gate 	nvpair_t *pair;
23397c478bd9Sstevel@tonic-gate 
23407c478bd9Sstevel@tonic-gate 	propget.pp_o_id_type = pool_elem_class(pe);
23417c478bd9Sstevel@tonic-gate 	if (pool_elem_class(pe) == PEC_RES_COMP ||
23427c478bd9Sstevel@tonic-gate 	    pool_elem_class(pe) == PEC_RES_AGG)
23437c478bd9Sstevel@tonic-gate 		propget.pp_o_id_subtype = pool_resource_elem_class(pe);
23447c478bd9Sstevel@tonic-gate 	if (pool_elem_class(pe) == PEC_COMP)
23457c478bd9Sstevel@tonic-gate 		propget.pp_o_id_subtype =
23467c478bd9Sstevel@tonic-gate 		    (pool_resource_elem_class_t)pool_component_elem_class(pe);
23477c478bd9Sstevel@tonic-gate 
23487c478bd9Sstevel@tonic-gate 	propget.pp_o_id = elem_get_sysid(pe);
23497c478bd9Sstevel@tonic-gate 	propget.pp_o_prop_name_size = strlen(name);
23507c478bd9Sstevel@tonic-gate 	propget.pp_o_prop_name = (char *)name;
23517c478bd9Sstevel@tonic-gate 	propget.pp_i_bufsize = KERNEL_SNAPSHOT_BUF_SZ;
23527c478bd9Sstevel@tonic-gate 	propget.pp_i_buf = malloc(KERNEL_SNAPSHOT_BUF_SZ);
23537c478bd9Sstevel@tonic-gate 	bzero(propget.pp_i_buf, KERNEL_SNAPSHOT_BUF_SZ);
23547c478bd9Sstevel@tonic-gate 
23557c478bd9Sstevel@tonic-gate 	prov = (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
23567c478bd9Sstevel@tonic-gate 	if (ioctl(prov->pkc_fd, POOL_PROPGET, &propget) < 0) {
23577c478bd9Sstevel@tonic-gate 		free(propget.pp_i_buf);
23587c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
23597c478bd9Sstevel@tonic-gate 		return (POC_INVAL);
23607c478bd9Sstevel@tonic-gate 	}
23617c478bd9Sstevel@tonic-gate 	if (nvlist_unpack(propget.pp_i_buf, propget.pp_i_bufsize,
23627c478bd9Sstevel@tonic-gate 	    &proplist, 0) != 0) {
23637c478bd9Sstevel@tonic-gate 		free(propget.pp_i_buf);
23647c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
23657c478bd9Sstevel@tonic-gate 		return (POC_INVAL);
23667c478bd9Sstevel@tonic-gate 	}
23677c478bd9Sstevel@tonic-gate 	free(propget.pp_i_buf);
23687c478bd9Sstevel@tonic-gate 
23697c478bd9Sstevel@tonic-gate 	if ((pair = nvlist_next_nvpair(proplist, NULL)) == NULL) {
23707c478bd9Sstevel@tonic-gate 		nvlist_free(proplist);
23717c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
23727c478bd9Sstevel@tonic-gate 		return (POC_INVAL);
23737c478bd9Sstevel@tonic-gate 	}
23747c478bd9Sstevel@tonic-gate 
23757c478bd9Sstevel@tonic-gate 	if (pool_value_from_nvpair(val, pair) == PO_FAIL) {
23767c478bd9Sstevel@tonic-gate 		nvlist_free(proplist);
23777c478bd9Sstevel@tonic-gate 		return (POC_INVAL);
23787c478bd9Sstevel@tonic-gate 	}
23797c478bd9Sstevel@tonic-gate 	nvlist_free(proplist);
23807c478bd9Sstevel@tonic-gate 	return (pool_value_get_type(val));
23817c478bd9Sstevel@tonic-gate }
23827c478bd9Sstevel@tonic-gate 
23837c478bd9Sstevel@tonic-gate /*
23847c478bd9Sstevel@tonic-gate  * Update the specified property value.
23857c478bd9Sstevel@tonic-gate  *
23867c478bd9Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is updated
23877c478bd9Sstevel@tonic-gate  * to indicate the cause of the error.
23887c478bd9Sstevel@tonic-gate  */
23897c478bd9Sstevel@tonic-gate int
23907c478bd9Sstevel@tonic-gate pool_knl_put_property(pool_elem_t *pe, const char *name,
23917c478bd9Sstevel@tonic-gate     const pool_value_t *val)
23927c478bd9Sstevel@tonic-gate {
23937c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
23947c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov =
23957c478bd9Sstevel@tonic-gate 	    (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
23967c478bd9Sstevel@tonic-gate 	nvpair_t *bp, *ap;
23977c478bd9Sstevel@tonic-gate 	pool_propput_undo_t *propput;
23987c478bd9Sstevel@tonic-gate 	nvlist_t *bl = NULL;
23997c478bd9Sstevel@tonic-gate 	const pool_prop_t *prop;
24007c478bd9Sstevel@tonic-gate 
24017c478bd9Sstevel@tonic-gate 	if ((bp = pool_knl_find_nvpair(pke->pke_properties, name)) != NULL) {
24027c478bd9Sstevel@tonic-gate 		if (nvlist_alloc(&bl, NV_UNIQUE_NAME_TYPE, 0) != 0) {
24037c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
24047c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
24057c478bd9Sstevel@tonic-gate 		}
24067c478bd9Sstevel@tonic-gate 		if (nvlist_add_nvpair(bl, bp) != 0) {
24077c478bd9Sstevel@tonic-gate 			nvlist_free(bl);
24087c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
24097c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
24107c478bd9Sstevel@tonic-gate 		}
24117c478bd9Sstevel@tonic-gate 	}
24127c478bd9Sstevel@tonic-gate 	if (pool_knl_nvlist_add_value(pke->pke_properties, name, val) !=
24137c478bd9Sstevel@tonic-gate 	    PO_SUCCESS)
24147c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
24157c478bd9Sstevel@tonic-gate 
24167c478bd9Sstevel@tonic-gate 	if (prov->pkc_log->l_state != LS_DO) {
24177c478bd9Sstevel@tonic-gate 		if (bl)
24187c478bd9Sstevel@tonic-gate 			nvlist_free(bl);
24197c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
24207c478bd9Sstevel@tonic-gate 	}
24217c478bd9Sstevel@tonic-gate 	/*
24227c478bd9Sstevel@tonic-gate 	 * The remaining logic is setting up the arguments for the
24237c478bd9Sstevel@tonic-gate 	 * POOL_PROPPUT ioctl and appending the details into the log.
24247c478bd9Sstevel@tonic-gate 	 */
24257c478bd9Sstevel@tonic-gate 	if ((propput = malloc(sizeof (pool_propput_undo_t))) == NULL) {
24267c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
24277c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
24287c478bd9Sstevel@tonic-gate 	}
24297c478bd9Sstevel@tonic-gate 	(void) memset(propput, 0, sizeof (pool_propput_undo_t));
24307c478bd9Sstevel@tonic-gate 	propput->ppu_blist = bl;
24317c478bd9Sstevel@tonic-gate 
24327c478bd9Sstevel@tonic-gate 	ap = pool_knl_find_nvpair(pke->pke_properties, name);
24337c478bd9Sstevel@tonic-gate 
24347c478bd9Sstevel@tonic-gate 	if (nvlist_alloc(&propput->ppu_alist, NV_UNIQUE_NAME_TYPE, 0) != 0) {
24357c478bd9Sstevel@tonic-gate 		nvlist_free(propput->ppu_blist);
24367c478bd9Sstevel@tonic-gate 		free(propput);
24377c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
24387c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
24397c478bd9Sstevel@tonic-gate 	}
24407c478bd9Sstevel@tonic-gate 	if (nvlist_add_nvpair(propput->ppu_alist, ap) != 0) {
24417c478bd9Sstevel@tonic-gate 		nvlist_free(propput->ppu_blist);
24427c478bd9Sstevel@tonic-gate 		nvlist_free(propput->ppu_alist);
24437c478bd9Sstevel@tonic-gate 		free(propput);
24447c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
24457c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
24467c478bd9Sstevel@tonic-gate 	}
24477c478bd9Sstevel@tonic-gate 
24487c478bd9Sstevel@tonic-gate 	if (nvlist_pack(propput->ppu_alist,
24497c478bd9Sstevel@tonic-gate 	    (char **)&propput->ppu_ioctl.pp_o_buf,
24507c478bd9Sstevel@tonic-gate 	    &propput->ppu_ioctl.pp_o_bufsize, NV_ENCODE_NATIVE, 0) != 0) {
24517c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
24527c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
24537c478bd9Sstevel@tonic-gate 	}
24547c478bd9Sstevel@tonic-gate 	nvlist_free(propput->ppu_alist);
24557c478bd9Sstevel@tonic-gate 	propput->ppu_ioctl.pp_o_id_type = pool_elem_class(pe);
24567c478bd9Sstevel@tonic-gate 	if (pool_elem_class(pe) == PEC_RES_COMP ||
24577c478bd9Sstevel@tonic-gate 	    pool_elem_class(pe) == PEC_RES_AGG)
24587c478bd9Sstevel@tonic-gate 		propput->ppu_ioctl.pp_o_id_sub_type =
24597c478bd9Sstevel@tonic-gate 		    pool_resource_elem_class(pe);
24607c478bd9Sstevel@tonic-gate 	if (pool_elem_class(pe) == PEC_COMP)
24617c478bd9Sstevel@tonic-gate 		propput->ppu_ioctl.pp_o_id_sub_type =
24627c478bd9Sstevel@tonic-gate 		    (pool_resource_elem_class_t)pool_component_elem_class(pe);
24637c478bd9Sstevel@tonic-gate 
24647c478bd9Sstevel@tonic-gate 	propput->ppu_elem = pe;
24657c478bd9Sstevel@tonic-gate 	if ((prop = provider_get_prop(propput->ppu_elem, name)) != NULL) {
24667c478bd9Sstevel@tonic-gate 		if (prop_is_readonly(prop) == PO_TRUE)
24677c478bd9Sstevel@tonic-gate 			propput->ppu_doioctl |= KERNEL_PROP_RDONLY;
24687c478bd9Sstevel@tonic-gate 	}
24697c478bd9Sstevel@tonic-gate 
24707c478bd9Sstevel@tonic-gate 	if (log_append(prov->pkc_log, POOL_PROPPUT, (void *)propput) !=
24717c478bd9Sstevel@tonic-gate 	    PO_SUCCESS) {
24727c478bd9Sstevel@tonic-gate 		nvlist_free(propput->ppu_blist);
24737c478bd9Sstevel@tonic-gate 		free(propput);
24747c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
24757c478bd9Sstevel@tonic-gate 	}
24767c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
24777c478bd9Sstevel@tonic-gate }
24787c478bd9Sstevel@tonic-gate 
24797c478bd9Sstevel@tonic-gate /*
24807c478bd9Sstevel@tonic-gate  * Remove the specified property value.
24817c478bd9Sstevel@tonic-gate  *
24827c478bd9Sstevel@tonic-gate  * PO_FAIL is returned if an error is detected and the error code is
24837c478bd9Sstevel@tonic-gate  * updated to indicate the cause of the error.
24847c478bd9Sstevel@tonic-gate  */
24857c478bd9Sstevel@tonic-gate int
24867c478bd9Sstevel@tonic-gate pool_knl_rm_property(pool_elem_t *pe, const char *name)
24877c478bd9Sstevel@tonic-gate {
24887c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
24897c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov =
24907c478bd9Sstevel@tonic-gate 	    (pool_knl_connection_t *)(TO_CONF(pe))->pc_prov;
24917c478bd9Sstevel@tonic-gate 	pool_proprm_undo_t *proprm;
24927c478bd9Sstevel@tonic-gate 
24937c478bd9Sstevel@tonic-gate 	if (pool_knl_find_nvpair(pke->pke_properties, name) == NULL) {
24947c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
24957c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
24967c478bd9Sstevel@tonic-gate 	}
24977c478bd9Sstevel@tonic-gate 
24987c478bd9Sstevel@tonic-gate 	if ((proprm = malloc(sizeof (pool_proprm_undo_t))) == NULL) {
24997c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
25007c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
25017c478bd9Sstevel@tonic-gate 	}
25027c478bd9Sstevel@tonic-gate 	(void) memset(proprm, 0, sizeof (pool_proprm_undo_t));
25037c478bd9Sstevel@tonic-gate 	proprm->pru_oldval.pv_class = POC_INVAL;
25047c478bd9Sstevel@tonic-gate 	(void) pool_get_property(TO_CONF(pe), pe, name, &proprm->pru_oldval);
25057c478bd9Sstevel@tonic-gate 
25067c478bd9Sstevel@tonic-gate 	if (prov->pkc_log->l_state != LS_DO) {
25077c478bd9Sstevel@tonic-gate 		free(proprm);
25087c478bd9Sstevel@tonic-gate 		(void) nvlist_remove_all(pke->pke_properties, (char *)name);
25097c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
25107c478bd9Sstevel@tonic-gate 	}
25117c478bd9Sstevel@tonic-gate 	/*
25127c478bd9Sstevel@tonic-gate 	 * The remaining logic is setting up the arguments for the
25137c478bd9Sstevel@tonic-gate 	 * POOL_PROPRM ioctl and appending the details into the log.
25147c478bd9Sstevel@tonic-gate 	 */
25157c478bd9Sstevel@tonic-gate 
25167c478bd9Sstevel@tonic-gate 	proprm->pru_ioctl.pp_o_id_type = pool_elem_class(pe);
25177c478bd9Sstevel@tonic-gate 	if (pool_elem_class(pe) == PEC_RES_COMP ||
25187c478bd9Sstevel@tonic-gate 	    pool_elem_class(pe) == PEC_RES_AGG)
25197c478bd9Sstevel@tonic-gate 		proprm->pru_ioctl.pp_o_id_sub_type =
25207c478bd9Sstevel@tonic-gate 		    pool_resource_elem_class(pe);
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate 	if (pool_elem_class(pe) == PEC_COMP)
25237c478bd9Sstevel@tonic-gate 		proprm->pru_ioctl.pp_o_id_sub_type =
25247c478bd9Sstevel@tonic-gate 		    (pool_resource_elem_class_t)pool_component_elem_class(pe);
25257c478bd9Sstevel@tonic-gate 
25267c478bd9Sstevel@tonic-gate 	proprm->pru_ioctl.pp_o_prop_name_size = strlen(name);
25277c478bd9Sstevel@tonic-gate 	proprm->pru_ioctl.pp_o_prop_name =
25287c478bd9Sstevel@tonic-gate 	    (char *)pool_value_get_name(&proprm->pru_oldval);
25297c478bd9Sstevel@tonic-gate 	proprm->pru_elem = pe;
25307c478bd9Sstevel@tonic-gate 
25317c478bd9Sstevel@tonic-gate 	if (log_append(prov->pkc_log, POOL_PROPRM, (void *)proprm) !=
25327c478bd9Sstevel@tonic-gate 	    PO_SUCCESS) {
25337c478bd9Sstevel@tonic-gate 		free(proprm);
25347c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
25357c478bd9Sstevel@tonic-gate 	}
25367c478bd9Sstevel@tonic-gate 
25377c478bd9Sstevel@tonic-gate 	(void) nvlist_remove_all(pke->pke_properties, (char *)name);
25387c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
25397c478bd9Sstevel@tonic-gate }
25407c478bd9Sstevel@tonic-gate 
25417c478bd9Sstevel@tonic-gate /*
25427c478bd9Sstevel@tonic-gate  * Return a NULL terminated array of pool_value_t which represents all
25437c478bd9Sstevel@tonic-gate  * of the properties stored for an element
25447c478bd9Sstevel@tonic-gate  *
25457c478bd9Sstevel@tonic-gate  * Return NULL on failure. It is the caller's responsibility to free
25467c478bd9Sstevel@tonic-gate  * the returned array of values.
25477c478bd9Sstevel@tonic-gate  */
25487c478bd9Sstevel@tonic-gate pool_value_t **
25497c478bd9Sstevel@tonic-gate pool_knl_get_properties(const pool_elem_t *pe, uint_t *nprops)
25507c478bd9Sstevel@tonic-gate {
25517c478bd9Sstevel@tonic-gate 	nvpair_t *pair;
25527c478bd9Sstevel@tonic-gate 	pool_value_t **result;
25537c478bd9Sstevel@tonic-gate 	pool_knl_elem_t *pke = (pool_knl_elem_t *)pe;
25547c478bd9Sstevel@tonic-gate 	int i = 0;
25557c478bd9Sstevel@tonic-gate 
25567c478bd9Sstevel@tonic-gate 	*nprops = 0;
25577c478bd9Sstevel@tonic-gate 
25587c478bd9Sstevel@tonic-gate 	for (pair = nvlist_next_nvpair(pke->pke_properties, NULL); pair != NULL;
2559*5ad42b1bSSurya Prakki 	    pair = nvlist_next_nvpair(pke->pke_properties, pair))
25607c478bd9Sstevel@tonic-gate 		(*nprops)++;
25617c478bd9Sstevel@tonic-gate 	if ((result = calloc(*nprops + 1, sizeof (pool_value_t *))) == NULL) {
25627c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
25637c478bd9Sstevel@tonic-gate 		return (NULL);
25647c478bd9Sstevel@tonic-gate 	}
25657c478bd9Sstevel@tonic-gate 	for (pair = nvlist_next_nvpair(pke->pke_properties, NULL); pair != NULL;
25667c478bd9Sstevel@tonic-gate 	    pair = nvlist_next_nvpair(pke->pke_properties, pair), i++) {
25677c478bd9Sstevel@tonic-gate 		result[i] = pool_value_alloc();
25687c478bd9Sstevel@tonic-gate 		if (pool_value_from_nvpair(result[i], pair) == PO_FAIL) {
25697c478bd9Sstevel@tonic-gate 			while (i-- >= 0)
25707c478bd9Sstevel@tonic-gate 				pool_value_free(result[i]);
25717c478bd9Sstevel@tonic-gate 			free(result);
25727c478bd9Sstevel@tonic-gate 			return (NULL);
25737c478bd9Sstevel@tonic-gate 		}
25747c478bd9Sstevel@tonic-gate 	}
25757c478bd9Sstevel@tonic-gate 	return (result);
25767c478bd9Sstevel@tonic-gate }
25777c478bd9Sstevel@tonic-gate 
25787c478bd9Sstevel@tonic-gate /*
25797c478bd9Sstevel@tonic-gate  * Append an entry to a result set. Reallocate the array used to store
25807c478bd9Sstevel@tonic-gate  * results if it's full.
25817c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
25827c478bd9Sstevel@tonic-gate  */
25837c478bd9Sstevel@tonic-gate int
25847c478bd9Sstevel@tonic-gate pool_knl_result_set_append(pool_knl_result_set_t *rs, pool_knl_elem_t *pke)
25857c478bd9Sstevel@tonic-gate {
25867c478bd9Sstevel@tonic-gate 	if (rs->pkr_count == rs->pkr_size)
25877c478bd9Sstevel@tonic-gate 		if (pool_knl_result_set_realloc(rs) != PO_SUCCESS)
25887c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
25897c478bd9Sstevel@tonic-gate 
25907c478bd9Sstevel@tonic-gate 	rs->pkr_list[rs->pkr_count++] = pke;
25917c478bd9Sstevel@tonic-gate 
25927c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
25937c478bd9Sstevel@tonic-gate }
25947c478bd9Sstevel@tonic-gate 
25957c478bd9Sstevel@tonic-gate /*
25967c478bd9Sstevel@tonic-gate  * Resize the array used to store results. A simple doubling strategy
25977c478bd9Sstevel@tonic-gate  * is used.
25987c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
25997c478bd9Sstevel@tonic-gate  */
26007c478bd9Sstevel@tonic-gate int
26017c478bd9Sstevel@tonic-gate pool_knl_result_set_realloc(pool_knl_result_set_t *rs)
26027c478bd9Sstevel@tonic-gate {
26037c478bd9Sstevel@tonic-gate 	pool_knl_elem_t **old_list = rs->pkr_list;
26047c478bd9Sstevel@tonic-gate 	int new_size = rs->pkr_size * 2;
26057c478bd9Sstevel@tonic-gate 
26067c478bd9Sstevel@tonic-gate 	if ((rs->pkr_list = realloc(rs->pkr_list,
26077c478bd9Sstevel@tonic-gate 	    new_size * sizeof (pool_knl_elem_t *))) == NULL) {
26087c478bd9Sstevel@tonic-gate 		rs->pkr_list = old_list;
26097c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
26107c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
26117c478bd9Sstevel@tonic-gate 	}
26127c478bd9Sstevel@tonic-gate 	rs->pkr_size = new_size;
26137c478bd9Sstevel@tonic-gate 
26147c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
26157c478bd9Sstevel@tonic-gate }
26167c478bd9Sstevel@tonic-gate 
26177c478bd9Sstevel@tonic-gate /*
26187c478bd9Sstevel@tonic-gate  * Allocate a result set. The Result Set stores the result of a query.
26197c478bd9Sstevel@tonic-gate  * Returns pool_knl_result_set_t pointer/NULL
26207c478bd9Sstevel@tonic-gate  */
26217c478bd9Sstevel@tonic-gate pool_knl_result_set_t *
26227c478bd9Sstevel@tonic-gate pool_knl_result_set_alloc(const pool_conf_t *conf)
26237c478bd9Sstevel@tonic-gate {
26247c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *rs;
26257c478bd9Sstevel@tonic-gate 
26267c478bd9Sstevel@tonic-gate 	if ((rs = malloc(sizeof (pool_knl_result_set_t))) == NULL) {
26277c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
26287c478bd9Sstevel@tonic-gate 		return (NULL);
26297c478bd9Sstevel@tonic-gate 	}
26307c478bd9Sstevel@tonic-gate 	(void) memset(rs, 0, sizeof (pool_knl_result_set_t));
26317c478bd9Sstevel@tonic-gate 	rs->pkr_size = KERNEL_RS_INITIAL_SZ;
26327c478bd9Sstevel@tonic-gate 	if (pool_knl_result_set_realloc(rs) == PO_FAIL) {
26337c478bd9Sstevel@tonic-gate 		free(rs);
26347c478bd9Sstevel@tonic-gate 		pool_seterror(POE_SYSTEM);
26357c478bd9Sstevel@tonic-gate 		return (NULL);
26367c478bd9Sstevel@tonic-gate 	}
26377c478bd9Sstevel@tonic-gate 	rs->prs_conf = conf;
26387c478bd9Sstevel@tonic-gate 	rs->prs_index = -1;
26397c478bd9Sstevel@tonic-gate 	rs->prs_active = PO_TRUE;
26407c478bd9Sstevel@tonic-gate 	/* Fix up the result set accessor functions to the knl specfic ones */
26417c478bd9Sstevel@tonic-gate 	rs->prs_next = pool_knl_rs_next;
26427c478bd9Sstevel@tonic-gate 	rs->prs_prev = pool_knl_rs_prev;
26437c478bd9Sstevel@tonic-gate 	rs->prs_first = pool_knl_rs_first;
26447c478bd9Sstevel@tonic-gate 	rs->prs_last = pool_knl_rs_last;
26457c478bd9Sstevel@tonic-gate 	rs->prs_get_index = pool_knl_rs_get_index;
26467c478bd9Sstevel@tonic-gate 	rs->prs_set_index = pool_knl_rs_set_index;
26477c478bd9Sstevel@tonic-gate 	rs->prs_close = pool_knl_rs_close;
26487c478bd9Sstevel@tonic-gate 	rs->prs_count = pool_knl_rs_count;
26497c478bd9Sstevel@tonic-gate 	return (rs);
26507c478bd9Sstevel@tonic-gate }
26517c478bd9Sstevel@tonic-gate 
26527c478bd9Sstevel@tonic-gate /*
26537c478bd9Sstevel@tonic-gate  * Free a result set. Ensure that the resources are all released at
26547c478bd9Sstevel@tonic-gate  * this point.
26557c478bd9Sstevel@tonic-gate  */
26567c478bd9Sstevel@tonic-gate void
26577c478bd9Sstevel@tonic-gate pool_knl_result_set_free(pool_knl_result_set_t *rs)
26587c478bd9Sstevel@tonic-gate {
26597c478bd9Sstevel@tonic-gate 	free(rs->pkr_list);
26607c478bd9Sstevel@tonic-gate 	free(rs);
26617c478bd9Sstevel@tonic-gate }
26627c478bd9Sstevel@tonic-gate /*
26637c478bd9Sstevel@tonic-gate  * Return the next element in a result set.
26647c478bd9Sstevel@tonic-gate  * Returns pool_elem_t pointer/NULL
26657c478bd9Sstevel@tonic-gate  */
26667c478bd9Sstevel@tonic-gate pool_elem_t *
26677c478bd9Sstevel@tonic-gate pool_knl_rs_next(pool_result_set_t *set)
26687c478bd9Sstevel@tonic-gate {
26697c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
26707c478bd9Sstevel@tonic-gate 
26717c478bd9Sstevel@tonic-gate 	if (kset->prs_index == kset->pkr_count - 1)
26727c478bd9Sstevel@tonic-gate 		return (NULL);
26737c478bd9Sstevel@tonic-gate 	return ((pool_elem_t *)kset->pkr_list[++kset->prs_index]);
26747c478bd9Sstevel@tonic-gate }
26757c478bd9Sstevel@tonic-gate 
26767c478bd9Sstevel@tonic-gate /*
26777c478bd9Sstevel@tonic-gate  * Return the previous element in a result set.
26787c478bd9Sstevel@tonic-gate  * Returns pool_elem_t pointer/NULL
26797c478bd9Sstevel@tonic-gate  */
26807c478bd9Sstevel@tonic-gate pool_elem_t *
26817c478bd9Sstevel@tonic-gate pool_knl_rs_prev(pool_result_set_t *set)
26827c478bd9Sstevel@tonic-gate {
26837c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
26847c478bd9Sstevel@tonic-gate 
26857c478bd9Sstevel@tonic-gate 	if (kset->prs_index < 0)
26867c478bd9Sstevel@tonic-gate 		return (NULL);
26877c478bd9Sstevel@tonic-gate 	return ((pool_elem_t *)kset->pkr_list[kset->prs_index--]);
26887c478bd9Sstevel@tonic-gate }
26897c478bd9Sstevel@tonic-gate 
26907c478bd9Sstevel@tonic-gate /*
26917c478bd9Sstevel@tonic-gate  * Sets the current index in a result set.
26927c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
26937c478bd9Sstevel@tonic-gate  */
26947c478bd9Sstevel@tonic-gate int
26957c478bd9Sstevel@tonic-gate pool_knl_rs_set_index(pool_result_set_t *set, int index)
26967c478bd9Sstevel@tonic-gate {
26977c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
26987c478bd9Sstevel@tonic-gate 
26997c478bd9Sstevel@tonic-gate 	if (index < 0 || index >= kset->pkr_count) {
27007c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
27017c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
27027c478bd9Sstevel@tonic-gate 	}
27037c478bd9Sstevel@tonic-gate 	kset->prs_index = index;
27047c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
27057c478bd9Sstevel@tonic-gate }
27067c478bd9Sstevel@tonic-gate 
27077c478bd9Sstevel@tonic-gate /*
27087c478bd9Sstevel@tonic-gate  * Return the current index in a result set.
27097c478bd9Sstevel@tonic-gate  * Returns current index
27107c478bd9Sstevel@tonic-gate  */
27117c478bd9Sstevel@tonic-gate int
27127c478bd9Sstevel@tonic-gate pool_knl_rs_get_index(pool_result_set_t *set)
27137c478bd9Sstevel@tonic-gate {
27147c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27157c478bd9Sstevel@tonic-gate 
27167c478bd9Sstevel@tonic-gate 	return (kset->prs_index);
27177c478bd9Sstevel@tonic-gate }
27187c478bd9Sstevel@tonic-gate 
27197c478bd9Sstevel@tonic-gate /*
27207c478bd9Sstevel@tonic-gate  * Return the first element in a result set.
27217c478bd9Sstevel@tonic-gate  * Returns pool_elem_t pointer/NULL
27227c478bd9Sstevel@tonic-gate  */
27237c478bd9Sstevel@tonic-gate pool_elem_t *
27247c478bd9Sstevel@tonic-gate pool_knl_rs_first(pool_result_set_t *set)
27257c478bd9Sstevel@tonic-gate {
27267c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27277c478bd9Sstevel@tonic-gate 
27287c478bd9Sstevel@tonic-gate 	return ((pool_elem_t *)kset->pkr_list[0]);
27297c478bd9Sstevel@tonic-gate }
27307c478bd9Sstevel@tonic-gate 
27317c478bd9Sstevel@tonic-gate /*
27327c478bd9Sstevel@tonic-gate  * Return the last element in a result set.
27337c478bd9Sstevel@tonic-gate  * Returns pool_elem_t pointer/NULL
27347c478bd9Sstevel@tonic-gate  */
27357c478bd9Sstevel@tonic-gate pool_elem_t *
27367c478bd9Sstevel@tonic-gate pool_knl_rs_last(pool_result_set_t *set)
27377c478bd9Sstevel@tonic-gate {
27387c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27397c478bd9Sstevel@tonic-gate 
27407c478bd9Sstevel@tonic-gate 	return ((pool_elem_t *)kset->pkr_list[kset->pkr_count - 1]);
27417c478bd9Sstevel@tonic-gate }
27427c478bd9Sstevel@tonic-gate 
27437c478bd9Sstevel@tonic-gate /*
27447c478bd9Sstevel@tonic-gate  * Return the number of results in a result set.
27457c478bd9Sstevel@tonic-gate  * Returns result count
27467c478bd9Sstevel@tonic-gate  */
27477c478bd9Sstevel@tonic-gate int
27487c478bd9Sstevel@tonic-gate pool_knl_rs_count(pool_result_set_t *set)
27497c478bd9Sstevel@tonic-gate {
27507c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27517c478bd9Sstevel@tonic-gate 
27527c478bd9Sstevel@tonic-gate 	return (kset->pkr_count);
27537c478bd9Sstevel@tonic-gate }
27547c478bd9Sstevel@tonic-gate 
27557c478bd9Sstevel@tonic-gate 
27567c478bd9Sstevel@tonic-gate /*
27577c478bd9Sstevel@tonic-gate  * Close a result set. Free the resources
27587c478bd9Sstevel@tonic-gate  * Returns PO_SUCCESS/PO_FAIL
27597c478bd9Sstevel@tonic-gate  */
27607c478bd9Sstevel@tonic-gate int
27617c478bd9Sstevel@tonic-gate pool_knl_rs_close(pool_result_set_t *set)
27627c478bd9Sstevel@tonic-gate {
27637c478bd9Sstevel@tonic-gate 	pool_knl_result_set_t *kset = (pool_knl_result_set_t *)set;
27647c478bd9Sstevel@tonic-gate 
27657c478bd9Sstevel@tonic-gate 	pool_knl_result_set_free(kset);
27667c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
27677c478bd9Sstevel@tonic-gate }
27687c478bd9Sstevel@tonic-gate 
27697c478bd9Sstevel@tonic-gate /*
27707c478bd9Sstevel@tonic-gate  * Commit an individual transaction log item(). This processing is
27717c478bd9Sstevel@tonic-gate  * essential to the pool_conf_commit() logic. When pool_conf_commit()
27727c478bd9Sstevel@tonic-gate  * is invoked, the pending transaction log for the configuration is
27737c478bd9Sstevel@tonic-gate  * walked and all pending changes to the kernel are invoked. If a
27747c478bd9Sstevel@tonic-gate  * change succeeds it is marked in the log as successful and
27757c478bd9Sstevel@tonic-gate  * processing continues, if it fails then failure is returned and the
27767c478bd9Sstevel@tonic-gate  * log will be "rolled back" to undo changes to the library snapshot
27777c478bd9Sstevel@tonic-gate  * and the kernel.
27787c478bd9Sstevel@tonic-gate  */
27797c478bd9Sstevel@tonic-gate int
27807c478bd9Sstevel@tonic-gate log_item_commit(log_item_t *li)
27817c478bd9Sstevel@tonic-gate {
27827c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov =
27837c478bd9Sstevel@tonic-gate 	    (pool_knl_connection_t *)li->li_log->l_conf->pc_prov;
27847c478bd9Sstevel@tonic-gate 	pool_create_undo_t *create;
27857c478bd9Sstevel@tonic-gate 	pool_destroy_undo_t *destroy;
27867c478bd9Sstevel@tonic-gate 	pool_assoc_undo_t *assoc;
27877c478bd9Sstevel@tonic-gate 	pool_dissoc_undo_t *dissoc;
27887c478bd9Sstevel@tonic-gate 	pool_propput_undo_t *propput;
27897c478bd9Sstevel@tonic-gate 	pool_proprm_undo_t *proprm;
27907c478bd9Sstevel@tonic-gate 	pool_xtransfer_undo_t *xtransfer;
27917c478bd9Sstevel@tonic-gate 	char_buf_t *cb;
27927c478bd9Sstevel@tonic-gate 	size_t size;
27937c478bd9Sstevel@tonic-gate 	pool_elem_t *pair;
27947c478bd9Sstevel@tonic-gate 	pool_value_t val = POOL_VALUE_INITIALIZER;
27957c478bd9Sstevel@tonic-gate 	int ret;
27967c478bd9Sstevel@tonic-gate 
27977c478bd9Sstevel@tonic-gate 	switch (li->li_op) {
27987c478bd9Sstevel@tonic-gate 	case POOL_CREATE:
27997c478bd9Sstevel@tonic-gate 		create = (pool_create_undo_t *)li->li_details;
28007c478bd9Sstevel@tonic-gate 		if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL)
28017c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
28027c478bd9Sstevel@tonic-gate 		if (set_char_buf(cb, "%s.sys_id",
28037c478bd9Sstevel@tonic-gate 		    pool_elem_class_string(create->pcu_elem)) != PO_SUCCESS) {
28047c478bd9Sstevel@tonic-gate 			free_char_buf(cb);
28057c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
28067c478bd9Sstevel@tonic-gate 		}
28077c478bd9Sstevel@tonic-gate #ifdef DEBUG
28087c478bd9Sstevel@tonic-gate 		dprintf("log_item_commit: POOL_CREATE, remove from dict\n");
28097c478bd9Sstevel@tonic-gate 		pool_elem_dprintf(create->pcu_elem);
28107c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
28117c478bd9Sstevel@tonic-gate 		/*
28127c478bd9Sstevel@tonic-gate 		 * May not need to remove the element if it was
28137c478bd9Sstevel@tonic-gate 		 * already destroyed before commit. Just cast the
28147c478bd9Sstevel@tonic-gate 		 * return to void.
28157c478bd9Sstevel@tonic-gate 		 */
28167c478bd9Sstevel@tonic-gate 		(void) dict_remove(prov->pkc_elements,
28177c478bd9Sstevel@tonic-gate 		    (pool_knl_elem_t *)create->pcu_elem);
28187c478bd9Sstevel@tonic-gate 
28197c478bd9Sstevel@tonic-gate 		if (ioctl(prov->pkc_fd, POOL_CREATE, &create->pcu_ioctl) < 0) {
28207c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
28217c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
28227c478bd9Sstevel@tonic-gate 		}
28237c478bd9Sstevel@tonic-gate 		/*
28247c478bd9Sstevel@tonic-gate 		 * Now that we have created our element in the kernel,
28257c478bd9Sstevel@tonic-gate 		 * it has a valid allocated system id. Remove the
28267c478bd9Sstevel@tonic-gate 		 * element from the element dictionary, using the
28277c478bd9Sstevel@tonic-gate 		 * current key, and then re-insert under the new key.
28287c478bd9Sstevel@tonic-gate 		 */
28297c478bd9Sstevel@tonic-gate #ifdef DEBUG
28307c478bd9Sstevel@tonic-gate 		pool_elem_dprintf(create->pcu_elem);
28317c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
28327c478bd9Sstevel@tonic-gate 		assert(nvlist_add_int64(
28337c478bd9Sstevel@tonic-gate 		    ((pool_knl_elem_t *)create->pcu_elem)->pke_properties,
28347c478bd9Sstevel@tonic-gate 		    cb->cb_buf, create->pcu_ioctl.pc_i_id) == 0);
28357c478bd9Sstevel@tonic-gate 		free_char_buf(cb);
28367c478bd9Sstevel@tonic-gate 		assert(dict_put(prov->pkc_elements, create->pcu_elem,
28377c478bd9Sstevel@tonic-gate 		    create->pcu_elem) == NULL);
28387c478bd9Sstevel@tonic-gate 		/*
28397c478bd9Sstevel@tonic-gate 		 * If the element has a pair in the static
28407c478bd9Sstevel@tonic-gate 		 * configuration, update it with the sys_id
28417c478bd9Sstevel@tonic-gate 		 */
28427c478bd9Sstevel@tonic-gate 		if ((pair = pool_get_pair(create->pcu_elem)) != NULL) {
28437c478bd9Sstevel@tonic-gate 			pool_value_set_int64(&val, create->pcu_ioctl.pc_i_id);
28447c478bd9Sstevel@tonic-gate 			assert(pool_put_any_ns_property(pair, c_sys_prop, &val)
28457c478bd9Sstevel@tonic-gate 			    == PO_SUCCESS);
28467c478bd9Sstevel@tonic-gate 		}
28477c478bd9Sstevel@tonic-gate 		li->li_state = LS_UNDO;
28487c478bd9Sstevel@tonic-gate 		break;
28497c478bd9Sstevel@tonic-gate 	case POOL_DESTROY:
28507c478bd9Sstevel@tonic-gate 		destroy = (pool_destroy_undo_t *)li->li_details;
28517c478bd9Sstevel@tonic-gate 
28527c478bd9Sstevel@tonic-gate 		destroy->pdu_ioctl.pd_o_id = elem_get_sysid(destroy->pdu_elem);
28537c478bd9Sstevel@tonic-gate 
28547c478bd9Sstevel@tonic-gate 		/*
28557c478bd9Sstevel@tonic-gate 		 * It may be that this element was created in the last
28567c478bd9Sstevel@tonic-gate 		 * transaction. In which case POOL_CREATE, above, will
28577c478bd9Sstevel@tonic-gate 		 * have re-inserted the element in the dictionary. Try
28587c478bd9Sstevel@tonic-gate 		 * to remove it just in case this has occurred.
28597c478bd9Sstevel@tonic-gate 		 */
28607c478bd9Sstevel@tonic-gate 		(void) dict_remove(prov->pkc_elements,
28617c478bd9Sstevel@tonic-gate 		    (pool_knl_elem_t *)destroy->pdu_elem);
28627c478bd9Sstevel@tonic-gate 		while ((ret = ioctl(prov->pkc_fd, POOL_DESTROY,
2863*5ad42b1bSSurya Prakki 		    &destroy->pdu_ioctl)) < 0 && errno == EAGAIN)
2864*5ad42b1bSSurya Prakki 			;
28657c478bd9Sstevel@tonic-gate 		if (ret < 0) {
28667c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
28677c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
28687c478bd9Sstevel@tonic-gate 		}
28697c478bd9Sstevel@tonic-gate #ifdef DEBUG
28707c478bd9Sstevel@tonic-gate 		dprintf("log_item_commit: POOL_DESTROY\n");
28717c478bd9Sstevel@tonic-gate 		pool_elem_dprintf(destroy->pdu_elem);
28727c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
28737c478bd9Sstevel@tonic-gate 		li->li_state = LS_UNDO;
28747c478bd9Sstevel@tonic-gate 		break;
28757c478bd9Sstevel@tonic-gate 	case POOL_ASSOC:
28767c478bd9Sstevel@tonic-gate 		assoc = (pool_assoc_undo_t *)li->li_details;
28777c478bd9Sstevel@tonic-gate 
28787c478bd9Sstevel@tonic-gate 		assoc->pau_ioctl.pa_o_pool_id =
28797c478bd9Sstevel@tonic-gate 		    elem_get_sysid(assoc->pau_assoc);
28807c478bd9Sstevel@tonic-gate 		assoc->pau_ioctl.pa_o_res_id =
28817c478bd9Sstevel@tonic-gate 		    elem_get_sysid(assoc->pau_newres);
28827c478bd9Sstevel@tonic-gate 		while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC,
2883*5ad42b1bSSurya Prakki 		    &assoc->pau_ioctl)) < 0 && errno == EAGAIN)
2884*5ad42b1bSSurya Prakki 			;
28857c478bd9Sstevel@tonic-gate 		if (ret < 0) {
28867c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
28877c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
28887c478bd9Sstevel@tonic-gate 		}
28897c478bd9Sstevel@tonic-gate 		li->li_state = LS_UNDO;
28907c478bd9Sstevel@tonic-gate 		break;
28917c478bd9Sstevel@tonic-gate 	case POOL_DISSOC:
28927c478bd9Sstevel@tonic-gate 		dissoc = (pool_dissoc_undo_t *)li->li_details;
28937c478bd9Sstevel@tonic-gate 
28947c478bd9Sstevel@tonic-gate 		dissoc->pdu_ioctl.pd_o_pool_id =
28957c478bd9Sstevel@tonic-gate 		    elem_get_sysid(dissoc->pdu_dissoc);
28967c478bd9Sstevel@tonic-gate 
28977c478bd9Sstevel@tonic-gate 		while ((ret = ioctl(prov->pkc_fd, POOL_DISSOC,
2898*5ad42b1bSSurya Prakki 		    &dissoc->pdu_ioctl)) < 0 && errno == EAGAIN)
2899*5ad42b1bSSurya Prakki 			;
29007c478bd9Sstevel@tonic-gate 		if (ret < 0) {
29017c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
29027c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
29037c478bd9Sstevel@tonic-gate 		}
29047c478bd9Sstevel@tonic-gate 		li->li_state = LS_UNDO;
29057c478bd9Sstevel@tonic-gate 		break;
29067c478bd9Sstevel@tonic-gate 	case POOL_TRANSFER:
29077c478bd9Sstevel@tonic-gate 		li->li_state = LS_UNDO;
29087c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
29097c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
29107c478bd9Sstevel@tonic-gate 		break;
29117c478bd9Sstevel@tonic-gate 	case POOL_XTRANSFER:
29127c478bd9Sstevel@tonic-gate 		xtransfer = (pool_xtransfer_undo_t *)li->li_details;
29137c478bd9Sstevel@tonic-gate 
29147c478bd9Sstevel@tonic-gate 		xtransfer->pxu_ioctl.px_o_src_id =
29157c478bd9Sstevel@tonic-gate 		    elem_get_sysid(xtransfer->pxu_src);
29167c478bd9Sstevel@tonic-gate 		xtransfer->pxu_ioctl.px_o_tgt_id =
29177c478bd9Sstevel@tonic-gate 		    elem_get_sysid(xtransfer->pxu_tgt);
29187c478bd9Sstevel@tonic-gate 		for (size = 0; xtransfer->pxu_rl[size] != NULL; size ++) {
29197c478bd9Sstevel@tonic-gate 			xtransfer->pxu_ioctl.px_o_comp_list[size] =
29207c478bd9Sstevel@tonic-gate 			    elem_get_sysid(TO_ELEM(xtransfer->pxu_rl[size]));
29217c478bd9Sstevel@tonic-gate #ifdef DEBUG
29227c478bd9Sstevel@tonic-gate 			dprintf("log_item_commit: POOL_XTRANSFER\n");
29237c478bd9Sstevel@tonic-gate 			pool_elem_dprintf(TO_ELEM(xtransfer->pxu_rl[size]));
29247c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
29257c478bd9Sstevel@tonic-gate 		}
29267c478bd9Sstevel@tonic-gate 
29277c478bd9Sstevel@tonic-gate 		/*
29287c478bd9Sstevel@tonic-gate 		 * Don't actually transfer resources if the configuration
29297c478bd9Sstevel@tonic-gate 		 * is in POF_DESTROY state. This is to prevent problems
29307c478bd9Sstevel@tonic-gate 		 * relating to transferring off-line CPUs. Instead rely
29317c478bd9Sstevel@tonic-gate 		 * on the POOL_DESTROY ioctl to transfer the CPUS.
29327c478bd9Sstevel@tonic-gate 		 */
29337c478bd9Sstevel@tonic-gate 		if (li->li_log->l_conf->pc_state != POF_DESTROY &&
29347c478bd9Sstevel@tonic-gate 		    ioctl(prov->pkc_fd, POOL_XTRANSFER,
29357c478bd9Sstevel@tonic-gate 		    &xtransfer->pxu_ioctl) < 0) {
29367c478bd9Sstevel@tonic-gate #ifdef DEBUG
29377c478bd9Sstevel@tonic-gate 			dprintf("log_item_commit: POOL_XTRANSFER, ioctl "
29387c478bd9Sstevel@tonic-gate 			    "failed\n");
29397c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
29407c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
29417c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
29427c478bd9Sstevel@tonic-gate 		}
29437c478bd9Sstevel@tonic-gate 		li->li_state = LS_UNDO;
29447c478bd9Sstevel@tonic-gate 		break;
29457c478bd9Sstevel@tonic-gate 	case POOL_PROPPUT:
29467c478bd9Sstevel@tonic-gate 		propput = (pool_propput_undo_t *)li->li_details;
29477c478bd9Sstevel@tonic-gate 
29487c478bd9Sstevel@tonic-gate 		if (pool_elem_class(propput->ppu_elem) != PEC_SYSTEM) {
29497c478bd9Sstevel@tonic-gate 			propput->ppu_ioctl.pp_o_id =
29507c478bd9Sstevel@tonic-gate 			    elem_get_sysid(propput->ppu_elem);
29517c478bd9Sstevel@tonic-gate 		}
29527c478bd9Sstevel@tonic-gate 		/*
29537c478bd9Sstevel@tonic-gate 		 * Some properties, e.g. pset.size, are read-only in the
29547c478bd9Sstevel@tonic-gate 		 * kernel and attempting to change them will fail and cause
29557c478bd9Sstevel@tonic-gate 		 * problems. Although this property is read-only through the
29567c478bd9Sstevel@tonic-gate 		 * public interface, the library needs to modify it's value.
29577c478bd9Sstevel@tonic-gate 		 */
29587c478bd9Sstevel@tonic-gate 		if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) {
29597c478bd9Sstevel@tonic-gate 			if (ioctl(prov->pkc_fd, POOL_PROPPUT,
29607c478bd9Sstevel@tonic-gate 			    &propput->ppu_ioctl) < 0) {
29617c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
29627c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
29637c478bd9Sstevel@tonic-gate 			}
29647c478bd9Sstevel@tonic-gate 		}
29657c478bd9Sstevel@tonic-gate 		li->li_state = LS_UNDO;
29667c478bd9Sstevel@tonic-gate 		break;
29677c478bd9Sstevel@tonic-gate 	case POOL_PROPRM:
29687c478bd9Sstevel@tonic-gate 		proprm = (pool_proprm_undo_t *)li->li_details;
29697c478bd9Sstevel@tonic-gate 
29707c478bd9Sstevel@tonic-gate 		if (pool_elem_class(proprm->pru_elem) != PEC_SYSTEM) {
29717c478bd9Sstevel@tonic-gate 			proprm->pru_ioctl.pp_o_id =
29727c478bd9Sstevel@tonic-gate 			    elem_get_sysid(proprm->pru_elem);
29737c478bd9Sstevel@tonic-gate 		}
29747c478bd9Sstevel@tonic-gate 		if (ioctl(prov->pkc_fd, POOL_PROPRM, &proprm->pru_ioctl) < 0) {
29757c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
29767c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
29777c478bd9Sstevel@tonic-gate 		}
29787c478bd9Sstevel@tonic-gate 		li->li_state = LS_UNDO;
29797c478bd9Sstevel@tonic-gate 		break;
29807c478bd9Sstevel@tonic-gate 	default:
29817c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
29827c478bd9Sstevel@tonic-gate 	}
29837c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
29847c478bd9Sstevel@tonic-gate }
29857c478bd9Sstevel@tonic-gate 
29867c478bd9Sstevel@tonic-gate /*
29877c478bd9Sstevel@tonic-gate  * Undo an individual transaction log item(). This processing is
29887c478bd9Sstevel@tonic-gate  * essential to the pool_conf_commit() and pool_conf_rollback()
29897c478bd9Sstevel@tonic-gate  * logic. Changes to the libpool snapshot and the kernel are carried
29907c478bd9Sstevel@tonic-gate  * out separately. The library snapshot is updated synchronously,
29917c478bd9Sstevel@tonic-gate  * however the kernel update is delayed until the user calls
29927c478bd9Sstevel@tonic-gate  * pool_conf_commit().
29937c478bd9Sstevel@tonic-gate  *
29947c478bd9Sstevel@tonic-gate  * When undoing transactions, library changes will be undone unless
29957c478bd9Sstevel@tonic-gate  * this invocation is as a result of a commit failure, in which case
29967c478bd9Sstevel@tonic-gate  * the log state will be LS_RECOVER. Kernel changes will only be
29977c478bd9Sstevel@tonic-gate  * undone if they are marked as having been done, in which case the
29987c478bd9Sstevel@tonic-gate  * log item state will be LS_UNDO.
29997c478bd9Sstevel@tonic-gate  */
30007c478bd9Sstevel@tonic-gate int
30017c478bd9Sstevel@tonic-gate log_item_undo(log_item_t *li)
30027c478bd9Sstevel@tonic-gate {
30037c478bd9Sstevel@tonic-gate 	pool_knl_connection_t *prov =
30047c478bd9Sstevel@tonic-gate 	    (pool_knl_connection_t *)li->li_log->l_conf->pc_prov;
30057c478bd9Sstevel@tonic-gate 	pool_create_undo_t *create;
30067c478bd9Sstevel@tonic-gate 	pool_destroy_undo_t *destroy;
30077c478bd9Sstevel@tonic-gate 	pool_assoc_undo_t *assoc;
30087c478bd9Sstevel@tonic-gate 	pool_dissoc_undo_t *dissoc;
30097c478bd9Sstevel@tonic-gate 	pool_propput_undo_t *propput;
30107c478bd9Sstevel@tonic-gate 	pool_proprm_undo_t *proprm;
30117c478bd9Sstevel@tonic-gate 	pool_xtransfer_undo_t *xtransfer;
30127c478bd9Sstevel@tonic-gate 	char_buf_t *cb;
30137c478bd9Sstevel@tonic-gate 	size_t size;
30147c478bd9Sstevel@tonic-gate 	pool_destroy_t u_destroy;
30157c478bd9Sstevel@tonic-gate 	pool_create_t u_create;
30167c478bd9Sstevel@tonic-gate 	pool_assoc_t u_assoc;
30177c478bd9Sstevel@tonic-gate 	pool_xtransfer_t u_xtransfer;
30187c478bd9Sstevel@tonic-gate 	pool_propput_t u_propput;
30197c478bd9Sstevel@tonic-gate 	pool_proprm_t u_proprm;
30207c478bd9Sstevel@tonic-gate 	pool_conf_t *conf = li->li_log->l_conf;
30217c478bd9Sstevel@tonic-gate 	nvpair_t *pair;
30227c478bd9Sstevel@tonic-gate 	nvlist_t *tmplist;
30237c478bd9Sstevel@tonic-gate 	int ret;
30247c478bd9Sstevel@tonic-gate 
30257c478bd9Sstevel@tonic-gate 	if (li->li_log->l_state != LS_RECOVER) {
30267c478bd9Sstevel@tonic-gate 	switch (li->li_op) {
30277c478bd9Sstevel@tonic-gate 	case POOL_CREATE:
30287c478bd9Sstevel@tonic-gate 		create = (pool_create_undo_t *)li->li_details;
30297c478bd9Sstevel@tonic-gate 
30307c478bd9Sstevel@tonic-gate 		(void) dict_remove(prov->pkc_elements, create->pcu_elem);
30317c478bd9Sstevel@tonic-gate #ifdef DEBUG
30327c478bd9Sstevel@tonic-gate 		dprintf("log_item_undo: POOL_CREATE\n");
30337c478bd9Sstevel@tonic-gate 		assert(create->pcu_elem != NULL);
30347c478bd9Sstevel@tonic-gate 		dprintf("log_item_undo: POOL_CREATE %p\n", create->pcu_elem);
30357c478bd9Sstevel@tonic-gate 		pool_elem_dprintf(create->pcu_elem);
30367c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
30377c478bd9Sstevel@tonic-gate 		pool_knl_elem_free((pool_knl_elem_t *)create->pcu_elem,
30387c478bd9Sstevel@tonic-gate 		    PO_TRUE);
30397c478bd9Sstevel@tonic-gate 		break;
30407c478bd9Sstevel@tonic-gate 	case POOL_DESTROY:
30417c478bd9Sstevel@tonic-gate 		destroy = (pool_destroy_undo_t *)li->li_details;
30427c478bd9Sstevel@tonic-gate 
30437c478bd9Sstevel@tonic-gate 		assert(dict_put(prov->pkc_elements, destroy->pdu_elem,
30447c478bd9Sstevel@tonic-gate 		    destroy->pdu_elem) == NULL);
30457c478bd9Sstevel@tonic-gate 		break;
30467c478bd9Sstevel@tonic-gate 	case POOL_ASSOC:
30477c478bd9Sstevel@tonic-gate 		assoc = (pool_assoc_undo_t *)li->li_details;
30487c478bd9Sstevel@tonic-gate 
30497c478bd9Sstevel@tonic-gate 		if (assoc->pau_oldres != NULL)
30507c478bd9Sstevel@tonic-gate 			((pool_knl_pool_t *)assoc->pau_assoc)->pkp_assoc
30517c478bd9Sstevel@tonic-gate 			    [pool_resource_elem_class(assoc->pau_oldres)] =
30527c478bd9Sstevel@tonic-gate 			    (pool_knl_resource_t *)assoc->pau_oldres;
30537c478bd9Sstevel@tonic-gate 		break;
30547c478bd9Sstevel@tonic-gate 	case POOL_DISSOC:
30557c478bd9Sstevel@tonic-gate 		dissoc = (pool_dissoc_undo_t *)li->li_details;
30567c478bd9Sstevel@tonic-gate 
30577c478bd9Sstevel@tonic-gate 		if (dissoc->pdu_oldres != NULL)
30587c478bd9Sstevel@tonic-gate 			((pool_knl_pool_t *)dissoc->pdu_dissoc)->pkp_assoc
30597c478bd9Sstevel@tonic-gate 			    [pool_resource_elem_class(dissoc->pdu_oldres)] =
30607c478bd9Sstevel@tonic-gate 			    (pool_knl_resource_t *)dissoc->pdu_oldres;
30617c478bd9Sstevel@tonic-gate 		break;
30627c478bd9Sstevel@tonic-gate 	case POOL_TRANSFER:
30637c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
30647c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
30657c478bd9Sstevel@tonic-gate 		break;
30667c478bd9Sstevel@tonic-gate 	case POOL_XTRANSFER:
30677c478bd9Sstevel@tonic-gate 		xtransfer = (pool_xtransfer_undo_t *)li->li_details;
30687c478bd9Sstevel@tonic-gate 
30697c478bd9Sstevel@tonic-gate 		for (size = 0; xtransfer->pxu_rl[size] != NULL; size++) {
30707c478bd9Sstevel@tonic-gate 			pool_value_t val = POOL_VALUE_INITIALIZER;
30717c478bd9Sstevel@tonic-gate 			uint64_t src_size;
30727c478bd9Sstevel@tonic-gate 			uint64_t tgt_size;
30737c478bd9Sstevel@tonic-gate 
30747c478bd9Sstevel@tonic-gate 			if (pool_set_container(xtransfer->pxu_src,
30757c478bd9Sstevel@tonic-gate 			    TO_ELEM(xtransfer->pxu_rl[size])) == PO_FAIL) {
30767c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
30777c478bd9Sstevel@tonic-gate 			}
30787c478bd9Sstevel@tonic-gate 			/*
30797c478bd9Sstevel@tonic-gate 			 * Maintain the library view of the size
30807c478bd9Sstevel@tonic-gate 			 */
30817c478bd9Sstevel@tonic-gate 			if (resource_get_size(pool_elem_res(xtransfer->pxu_src),
30827c478bd9Sstevel@tonic-gate 			    &src_size) != PO_SUCCESS ||
30837c478bd9Sstevel@tonic-gate 			    resource_get_size(pool_elem_res(xtransfer->pxu_tgt),
30847c478bd9Sstevel@tonic-gate 			    &tgt_size) != PO_SUCCESS) {
30857c478bd9Sstevel@tonic-gate 				pool_seterror(POE_BADPARAM);
30867c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
30877c478bd9Sstevel@tonic-gate 			}
30887c478bd9Sstevel@tonic-gate 			src_size++;
30897c478bd9Sstevel@tonic-gate 			tgt_size--;
30907c478bd9Sstevel@tonic-gate 			pool_value_set_uint64(&val, src_size);
30917c478bd9Sstevel@tonic-gate 			(void) pool_put_any_ns_property(xtransfer->pxu_src,
30927c478bd9Sstevel@tonic-gate 			    c_size_prop, &val);
30937c478bd9Sstevel@tonic-gate 			pool_value_set_uint64(&val, tgt_size);
30947c478bd9Sstevel@tonic-gate 			(void) pool_put_any_ns_property(xtransfer->pxu_tgt,
30957c478bd9Sstevel@tonic-gate 			    c_size_prop, &val);
30967c478bd9Sstevel@tonic-gate 		}
30977c478bd9Sstevel@tonic-gate 		break;
30987c478bd9Sstevel@tonic-gate 	case POOL_PROPPUT:
30997c478bd9Sstevel@tonic-gate 		propput = (pool_propput_undo_t *)li->li_details;
31007c478bd9Sstevel@tonic-gate 
31017c478bd9Sstevel@tonic-gate 		if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) {
31027c478bd9Sstevel@tonic-gate 			if (propput->ppu_blist != NULL) {
31037c478bd9Sstevel@tonic-gate 				if (nvlist_merge(
31047c478bd9Sstevel@tonic-gate 				    ((pool_knl_elem_t *)propput->ppu_elem)->
31057c478bd9Sstevel@tonic-gate 				    pke_properties, propput->ppu_blist, 0)
31067c478bd9Sstevel@tonic-gate 				    != 0) {
31077c478bd9Sstevel@tonic-gate 					pool_seterror(POE_SYSTEM);
31087c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
31097c478bd9Sstevel@tonic-gate 				}
31107c478bd9Sstevel@tonic-gate 			} else {
31117c478bd9Sstevel@tonic-gate 				if (nvlist_unpack(propput->ppu_ioctl.pp_o_buf,
31127c478bd9Sstevel@tonic-gate 				    propput->ppu_ioctl.pp_o_bufsize,
31137c478bd9Sstevel@tonic-gate 				    &propput->ppu_alist, 0) != 0) {
31147c478bd9Sstevel@tonic-gate 					pool_seterror(POE_SYSTEM);
31157c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
31167c478bd9Sstevel@tonic-gate 				}
31177c478bd9Sstevel@tonic-gate 				pair = nvlist_next_nvpair(propput->ppu_alist,
31187c478bd9Sstevel@tonic-gate 				    NULL);
31197c478bd9Sstevel@tonic-gate 				(void) nvlist_remove_all(((pool_knl_elem_t *)
31207c478bd9Sstevel@tonic-gate 				    propput->ppu_elem)->pke_properties,
31217c478bd9Sstevel@tonic-gate 				    nvpair_name(pair));
31227c478bd9Sstevel@tonic-gate 				nvlist_free(propput->ppu_alist);
31237c478bd9Sstevel@tonic-gate 			}
31247c478bd9Sstevel@tonic-gate 		}
31257c478bd9Sstevel@tonic-gate 		break;
31267c478bd9Sstevel@tonic-gate 	case POOL_PROPRM:
31277c478bd9Sstevel@tonic-gate 		proprm = (pool_proprm_undo_t *)li->li_details;
31287c478bd9Sstevel@tonic-gate 
31297c478bd9Sstevel@tonic-gate 		if (pool_value_get_type(&proprm->pru_oldval) != POC_INVAL) {
31307c478bd9Sstevel@tonic-gate 			if (pool_put_property(conf, proprm->pru_elem,
31317c478bd9Sstevel@tonic-gate 			    proprm->pru_ioctl.pp_o_prop_name,
31327c478bd9Sstevel@tonic-gate 			    &proprm->pru_oldval) != PO_SUCCESS) {
31337c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
31347c478bd9Sstevel@tonic-gate 			}
31357c478bd9Sstevel@tonic-gate 		}
31367c478bd9Sstevel@tonic-gate 		break;
31377c478bd9Sstevel@tonic-gate 	default:
31387c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
31397c478bd9Sstevel@tonic-gate 	}
31407c478bd9Sstevel@tonic-gate 	}
31417c478bd9Sstevel@tonic-gate 	/*
31427c478bd9Sstevel@tonic-gate 	 * Only try to undo the state of the kernel if we modified it.
31437c478bd9Sstevel@tonic-gate 	 */
31447c478bd9Sstevel@tonic-gate 	if (li->li_state == LS_DO) {
31457c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
31467c478bd9Sstevel@tonic-gate 	}
31477c478bd9Sstevel@tonic-gate 
31487c478bd9Sstevel@tonic-gate 	switch (li->li_op) {
31497c478bd9Sstevel@tonic-gate 	case POOL_CREATE:
31507c478bd9Sstevel@tonic-gate 		create = (pool_create_undo_t *)li->li_details;
31517c478bd9Sstevel@tonic-gate 
31527c478bd9Sstevel@tonic-gate 		u_destroy.pd_o_type = create->pcu_ioctl.pc_o_type;
31537c478bd9Sstevel@tonic-gate 		u_destroy.pd_o_sub_type = create->pcu_ioctl.pc_o_sub_type;
31547c478bd9Sstevel@tonic-gate 		u_destroy.pd_o_id = create->pcu_ioctl.pc_i_id;
31557c478bd9Sstevel@tonic-gate 
31567c478bd9Sstevel@tonic-gate 		while ((ret = ioctl(prov->pkc_fd, POOL_DESTROY,
3157*5ad42b1bSSurya Prakki 		    &u_destroy)) < 0 && errno == EAGAIN)
3158*5ad42b1bSSurya Prakki 			;
31597c478bd9Sstevel@tonic-gate 		if (ret < 0) {
31607c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
31617c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
31627c478bd9Sstevel@tonic-gate 		}
31637c478bd9Sstevel@tonic-gate 		li->li_state = LS_DO;
31647c478bd9Sstevel@tonic-gate 		break;
31657c478bd9Sstevel@tonic-gate 	case POOL_DESTROY:
31667c478bd9Sstevel@tonic-gate 		destroy = (pool_destroy_undo_t *)li->li_details;
31677c478bd9Sstevel@tonic-gate 
31687c478bd9Sstevel@tonic-gate 		u_create.pc_o_type = destroy->pdu_ioctl.pd_o_type;
31697c478bd9Sstevel@tonic-gate 		u_create.pc_o_sub_type = destroy->pdu_ioctl.pd_o_sub_type;
31707c478bd9Sstevel@tonic-gate 
31717c478bd9Sstevel@tonic-gate 		if (ioctl(prov->pkc_fd, POOL_CREATE, &u_create) < 0) {
31727c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
31737c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
31747c478bd9Sstevel@tonic-gate 		}
31757c478bd9Sstevel@tonic-gate 
31767c478bd9Sstevel@tonic-gate 		if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
31777c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
31787c478bd9Sstevel@tonic-gate 		}
31797c478bd9Sstevel@tonic-gate 		if (set_char_buf(cb, "%s.sys_id",
31807c478bd9Sstevel@tonic-gate 		    pool_elem_class_string(destroy->pdu_elem)) != PO_SUCCESS) {
31817c478bd9Sstevel@tonic-gate 			free_char_buf(cb);
31827c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
31837c478bd9Sstevel@tonic-gate 		}
31847c478bd9Sstevel@tonic-gate 		(void) nvlist_add_int64(
31857c478bd9Sstevel@tonic-gate 		    ((pool_knl_elem_t *)destroy->pdu_elem)->pke_properties,
31867c478bd9Sstevel@tonic-gate 		    cb->cb_buf, u_create.pc_i_id);
31877c478bd9Sstevel@tonic-gate 		free_char_buf(cb);
31887c478bd9Sstevel@tonic-gate 		if (dict_put(prov->pkc_elements, destroy->pdu_elem,
31897c478bd9Sstevel@tonic-gate 		    destroy->pdu_elem) != NULL) {
31907c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
31917c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
31927c478bd9Sstevel@tonic-gate 		}
31937c478bd9Sstevel@tonic-gate 		/*
31947c478bd9Sstevel@tonic-gate 		 * Now we need to reset all the properties and
31957c478bd9Sstevel@tonic-gate 		 * associations in the kernel for this newly created
31967c478bd9Sstevel@tonic-gate 		 * replacement.
31977c478bd9Sstevel@tonic-gate 		 */
31987c478bd9Sstevel@tonic-gate 		u_propput.pp_o_id_type = destroy->pdu_ioctl.pd_o_type;
31997c478bd9Sstevel@tonic-gate 		u_propput.pp_o_id_sub_type = destroy->pdu_ioctl.pd_o_sub_type;
32007c478bd9Sstevel@tonic-gate 		u_propput.pp_o_id = u_create.pc_i_id;
32017c478bd9Sstevel@tonic-gate 		u_propput.pp_o_buf = NULL;
32027c478bd9Sstevel@tonic-gate 		/*
32037c478bd9Sstevel@tonic-gate 		 * Remove the read-only properties before attempting
32047c478bd9Sstevel@tonic-gate 		 * to restore the state of the newly created property
32057c478bd9Sstevel@tonic-gate 		 */
32067c478bd9Sstevel@tonic-gate 		(void) nvlist_dup(((pool_knl_elem_t *)destroy->pdu_elem)->
3207*5ad42b1bSSurya Prakki 		    pke_properties, &tmplist, 0);
32087c478bd9Sstevel@tonic-gate 		for (pair = nvlist_next_nvpair(tmplist, NULL); pair != NULL;
32097c478bd9Sstevel@tonic-gate 		    pair = nvlist_next_nvpair(tmplist, pair)) {
32107c478bd9Sstevel@tonic-gate 			const pool_prop_t *prop;
32117c478bd9Sstevel@tonic-gate 			char *name = nvpair_name(pair);
32127c478bd9Sstevel@tonic-gate 			if ((prop = provider_get_prop(destroy->pdu_elem,
32137c478bd9Sstevel@tonic-gate 			    name)) != NULL)
32147c478bd9Sstevel@tonic-gate 				if (prop_is_readonly(prop) == PO_TRUE)
32157c478bd9Sstevel@tonic-gate 					(void) nvlist_remove_all(tmplist, name);
32167c478bd9Sstevel@tonic-gate 		}
32177c478bd9Sstevel@tonic-gate 		if (nvlist_pack(tmplist, (char **)&u_propput.pp_o_buf,
32187c478bd9Sstevel@tonic-gate 		    &u_propput.pp_o_bufsize, NV_ENCODE_NATIVE, 0) != 0) {
32197c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
32207c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
32217c478bd9Sstevel@tonic-gate 		}
32227c478bd9Sstevel@tonic-gate 		nvlist_free(tmplist);
32237c478bd9Sstevel@tonic-gate 		if (ioctl(prov->pkc_fd, POOL_PROPPUT, &u_propput) < 0) {
32247c478bd9Sstevel@tonic-gate 			free(u_propput.pp_o_buf);
32257c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
32267c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
32277c478bd9Sstevel@tonic-gate 		}
32287c478bd9Sstevel@tonic-gate 		free(u_propput.pp_o_buf);
32297c478bd9Sstevel@tonic-gate 		/*
32307c478bd9Sstevel@tonic-gate 		 * Now reset the associations for all the resource
32317c478bd9Sstevel@tonic-gate 		 * types if the thing which we are recreating is a
32327c478bd9Sstevel@tonic-gate 		 * pool
32337c478bd9Sstevel@tonic-gate 		 *
32347c478bd9Sstevel@tonic-gate 		 * TODO: This is resource specific and must be
32357c478bd9Sstevel@tonic-gate 		 * extended for additional resource types.
32367c478bd9Sstevel@tonic-gate 		 */
32377c478bd9Sstevel@tonic-gate 		if (destroy->pdu_ioctl.pd_o_type == PEC_POOL) {
32387c478bd9Sstevel@tonic-gate 			u_assoc.pa_o_pool_id = u_create.pc_i_id;
32397c478bd9Sstevel@tonic-gate 			u_assoc.pa_o_res_id =
32407c478bd9Sstevel@tonic-gate 			    elem_get_sysid(
32417c478bd9Sstevel@tonic-gate 			    TO_ELEM(((pool_knl_pool_t *)destroy->pdu_elem)->
32427c478bd9Sstevel@tonic-gate 			    pkp_assoc[PREC_PSET]));
32437c478bd9Sstevel@tonic-gate 			u_assoc.pa_o_id_type = PREC_PSET;
32447c478bd9Sstevel@tonic-gate 
32457c478bd9Sstevel@tonic-gate 			if (ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc) < 0) {
32467c478bd9Sstevel@tonic-gate 				pool_seterror(POE_SYSTEM);
32477c478bd9Sstevel@tonic-gate 				return (PO_FAIL);
32487c478bd9Sstevel@tonic-gate 			}
32497c478bd9Sstevel@tonic-gate 		}
32507c478bd9Sstevel@tonic-gate 		li->li_state = LS_DO;
32517c478bd9Sstevel@tonic-gate 		break;
32527c478bd9Sstevel@tonic-gate 	case POOL_ASSOC:
32537c478bd9Sstevel@tonic-gate 		assoc = (pool_assoc_undo_t *)li->li_details;
32547c478bd9Sstevel@tonic-gate 
32557c478bd9Sstevel@tonic-gate 		u_assoc.pa_o_pool_id = elem_get_sysid(assoc->pau_assoc);
32567c478bd9Sstevel@tonic-gate 		u_assoc.pa_o_res_id = elem_get_sysid(assoc->pau_oldres);
32577c478bd9Sstevel@tonic-gate 		u_assoc.pa_o_id_type = assoc->pau_ioctl.pa_o_id_type;
32587c478bd9Sstevel@tonic-gate 
32597c478bd9Sstevel@tonic-gate 		while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc)) < 0 &&
3260*5ad42b1bSSurya Prakki 		    errno == EAGAIN)
3261*5ad42b1bSSurya Prakki 			;
32627c478bd9Sstevel@tonic-gate 		if (ret < 0) {
32637c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
32647c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
32657c478bd9Sstevel@tonic-gate 		}
32667c478bd9Sstevel@tonic-gate 		li->li_state = LS_DO;
32677c478bd9Sstevel@tonic-gate 		break;
32687c478bd9Sstevel@tonic-gate 	case POOL_DISSOC:
32697c478bd9Sstevel@tonic-gate 		dissoc = (pool_dissoc_undo_t *)li->li_details;
32707c478bd9Sstevel@tonic-gate 
32717c478bd9Sstevel@tonic-gate 		u_assoc.pa_o_pool_id = elem_get_sysid(dissoc->pdu_dissoc);
32727c478bd9Sstevel@tonic-gate 		u_assoc.pa_o_res_id = elem_get_sysid(dissoc->pdu_oldres);
32737c478bd9Sstevel@tonic-gate 		u_assoc.pa_o_id_type = dissoc->pdu_ioctl.pd_o_id_type;
32747c478bd9Sstevel@tonic-gate 
32757c478bd9Sstevel@tonic-gate 		while ((ret = ioctl(prov->pkc_fd, POOL_ASSOC, &u_assoc)) < 0 &&
3276*5ad42b1bSSurya Prakki 		    errno == EAGAIN)
3277*5ad42b1bSSurya Prakki 			;
32787c478bd9Sstevel@tonic-gate 		if (ret < 0) {
32797c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
32807c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
32817c478bd9Sstevel@tonic-gate 		}
32827c478bd9Sstevel@tonic-gate 		li->li_state = LS_DO;
32837c478bd9Sstevel@tonic-gate 		break;
32847c478bd9Sstevel@tonic-gate 	case POOL_TRANSFER:
32857c478bd9Sstevel@tonic-gate 		li->li_state = LS_DO;
32867c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
32877c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
32887c478bd9Sstevel@tonic-gate 		break;
32897c478bd9Sstevel@tonic-gate 	case POOL_XTRANSFER:
32907c478bd9Sstevel@tonic-gate 		xtransfer = (pool_xtransfer_undo_t *)li->li_details;
32917c478bd9Sstevel@tonic-gate 
32927c478bd9Sstevel@tonic-gate 		(void) memcpy(&u_xtransfer, &xtransfer->pxu_ioctl,
32937c478bd9Sstevel@tonic-gate 		    sizeof (pool_xtransfer_t));
32947c478bd9Sstevel@tonic-gate 		u_xtransfer.px_o_src_id = elem_get_sysid(xtransfer->pxu_tgt);
32957c478bd9Sstevel@tonic-gate 		u_xtransfer.px_o_tgt_id = elem_get_sysid(xtransfer->pxu_src);
32967c478bd9Sstevel@tonic-gate 
32977c478bd9Sstevel@tonic-gate 		if (ioctl(prov->pkc_fd, POOL_XTRANSFER, &u_xtransfer) < 0) {
32987c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
32997c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
33007c478bd9Sstevel@tonic-gate 		}
33017c478bd9Sstevel@tonic-gate 		li->li_state = LS_DO;
33027c478bd9Sstevel@tonic-gate 		break;
33037c478bd9Sstevel@tonic-gate 	case POOL_PROPPUT:
33047c478bd9Sstevel@tonic-gate 		propput = (pool_propput_undo_t *)li->li_details;
33057c478bd9Sstevel@tonic-gate 
33067c478bd9Sstevel@tonic-gate 		if ((propput->ppu_doioctl & KERNEL_PROP_RDONLY) == 0) {
33077c478bd9Sstevel@tonic-gate 			if (propput->ppu_blist) {
33087c478bd9Sstevel@tonic-gate 				(void) memcpy(&u_propput, &propput->ppu_ioctl,
33097c478bd9Sstevel@tonic-gate 				    sizeof (pool_propput_t));
33107c478bd9Sstevel@tonic-gate 				u_propput.pp_o_id =
33117c478bd9Sstevel@tonic-gate 				    elem_get_sysid(propput->ppu_elem);
33127c478bd9Sstevel@tonic-gate 				u_propput.pp_o_buf = NULL;
33137c478bd9Sstevel@tonic-gate 				if (nvlist_pack(propput->ppu_blist,
33147c478bd9Sstevel@tonic-gate 				    (char **)&u_propput.pp_o_buf,
33157c478bd9Sstevel@tonic-gate 				    &u_propput.pp_o_bufsize,
33167c478bd9Sstevel@tonic-gate 				    NV_ENCODE_NATIVE, 0) != 0) {
33177c478bd9Sstevel@tonic-gate 					pool_seterror(POE_SYSTEM);
33187c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
33197c478bd9Sstevel@tonic-gate 				}
33207c478bd9Sstevel@tonic-gate 				if (ioctl(prov->pkc_fd, POOL_PROPPUT,
33217c478bd9Sstevel@tonic-gate 				    &u_propput) < 0) {
33227c478bd9Sstevel@tonic-gate 					free(u_propput.pp_o_buf);
33237c478bd9Sstevel@tonic-gate 					pool_seterror(POE_SYSTEM);
33247c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
33257c478bd9Sstevel@tonic-gate 				}
33267c478bd9Sstevel@tonic-gate 				free(u_propput.pp_o_buf);
33277c478bd9Sstevel@tonic-gate 			} else {
33287c478bd9Sstevel@tonic-gate 				if (nvlist_unpack(propput->
33297c478bd9Sstevel@tonic-gate 				    ppu_ioctl.pp_o_buf,
33307c478bd9Sstevel@tonic-gate 				    propput->ppu_ioctl.pp_o_bufsize,
33317c478bd9Sstevel@tonic-gate 				    &propput->ppu_alist, 0) != 0) {
33327c478bd9Sstevel@tonic-gate 					pool_seterror(POE_SYSTEM);
33337c478bd9Sstevel@tonic-gate 					return (PO_FAIL);
33347c478bd9Sstevel@tonic-gate 				}
33357c478bd9Sstevel@tonic-gate 				u_proprm.pp_o_id_type =
33367c478bd9Sstevel@tonic-gate 				    propput->ppu_ioctl.pp_o_id_type;
33377c478bd9Sstevel@tonic-gate 				u_proprm.pp_o_id_sub_type =
33387c478bd9Sstevel@tonic-gate 				    propput->ppu_ioctl.pp_o_id_sub_type;
33397c478bd9Sstevel@tonic-gate 				u_proprm.pp_o_id =
33407c478bd9Sstevel@tonic-gate 				    elem_get_sysid(propput->ppu_elem);
33417c478bd9Sstevel@tonic-gate 				pair = nvlist_next_nvpair(propput->ppu_alist,
33427c478bd9Sstevel@tonic-gate 				    NULL);
33437c478bd9Sstevel@tonic-gate 				u_proprm.pp_o_prop_name = nvpair_name(pair);
33447c478bd9Sstevel@tonic-gate 				u_proprm.pp_o_prop_name_size =
33457c478bd9Sstevel@tonic-gate 				    strlen(u_proprm.pp_o_prop_name);
33467c478bd9Sstevel@tonic-gate 
33477c478bd9Sstevel@tonic-gate 				if (provider_get_prop(propput->ppu_elem,
33487c478bd9Sstevel@tonic-gate 				    u_proprm.pp_o_prop_name) == NULL) {
33497c478bd9Sstevel@tonic-gate 					if (ioctl(prov->pkc_fd, POOL_PROPRM,
33507c478bd9Sstevel@tonic-gate 					    &u_proprm) < 0) {
33517c478bd9Sstevel@tonic-gate 						nvlist_free(propput->ppu_alist);
33527c478bd9Sstevel@tonic-gate 						pool_seterror(POE_SYSTEM);
33537c478bd9Sstevel@tonic-gate 						return (PO_FAIL);
33547c478bd9Sstevel@tonic-gate 					}
33557c478bd9Sstevel@tonic-gate 				}
33567c478bd9Sstevel@tonic-gate 				nvlist_free(propput->ppu_alist);
33577c478bd9Sstevel@tonic-gate 			}
33587c478bd9Sstevel@tonic-gate 		}
33597c478bd9Sstevel@tonic-gate 		li->li_state = LS_DO;
33607c478bd9Sstevel@tonic-gate 		break;
33617c478bd9Sstevel@tonic-gate 	case POOL_PROPRM:
33627c478bd9Sstevel@tonic-gate 		proprm = (pool_proprm_undo_t *)li->li_details;
33637c478bd9Sstevel@tonic-gate 
33647c478bd9Sstevel@tonic-gate 		u_propput.pp_o_id_type = proprm->pru_ioctl.pp_o_id_type;
33657c478bd9Sstevel@tonic-gate 		u_propput.pp_o_id_sub_type =
33667c478bd9Sstevel@tonic-gate 		    proprm->pru_ioctl.pp_o_id_sub_type;
33677c478bd9Sstevel@tonic-gate 		u_propput.pp_o_id = elem_get_sysid(proprm->pru_elem);
33687c478bd9Sstevel@tonic-gate 		u_propput.pp_o_buf = NULL;
33697c478bd9Sstevel@tonic-gate 		/*
33707c478bd9Sstevel@tonic-gate 		 * Only try to remove the appropriate property
33717c478bd9Sstevel@tonic-gate 		 */
33727c478bd9Sstevel@tonic-gate 		if (nvlist_alloc(&tmplist, NV_UNIQUE_NAME_TYPE, 0) !=
33737c478bd9Sstevel@tonic-gate 		    0) {
33747c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
33757c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
33767c478bd9Sstevel@tonic-gate 		}
33777c478bd9Sstevel@tonic-gate 		if (pool_knl_nvlist_add_value(tmplist,
33787c478bd9Sstevel@tonic-gate 		    pool_value_get_name(&proprm->pru_oldval),
33797c478bd9Sstevel@tonic-gate 		    &proprm->pru_oldval) != PO_SUCCESS)
33807c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
33817c478bd9Sstevel@tonic-gate 
33827c478bd9Sstevel@tonic-gate 		if (nvlist_pack(tmplist,
33837c478bd9Sstevel@tonic-gate 		    (char **)&u_propput.pp_o_buf, &u_propput.pp_o_bufsize,
33847c478bd9Sstevel@tonic-gate 		    NV_ENCODE_NATIVE, 0) != 0) {
33857c478bd9Sstevel@tonic-gate 			nvlist_free(tmplist);
33867c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
33877c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
33887c478bd9Sstevel@tonic-gate 		}
33897c478bd9Sstevel@tonic-gate 		nvlist_free(tmplist);
33907c478bd9Sstevel@tonic-gate 		if (ioctl(prov->pkc_fd, POOL_PROPPUT, &u_propput) < 0) {
33917c478bd9Sstevel@tonic-gate 			free(u_propput.pp_o_buf);
33927c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
33937c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
33947c478bd9Sstevel@tonic-gate 		}
33957c478bd9Sstevel@tonic-gate 		free(u_propput.pp_o_buf);
33967c478bd9Sstevel@tonic-gate 		li->li_state = LS_DO;
33977c478bd9Sstevel@tonic-gate 		break;
33987c478bd9Sstevel@tonic-gate 	default:
33997c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
34007c478bd9Sstevel@tonic-gate 	}
34017c478bd9Sstevel@tonic-gate 		return (PO_SUCCESS);
34027c478bd9Sstevel@tonic-gate }
34037c478bd9Sstevel@tonic-gate 
34047c478bd9Sstevel@tonic-gate /*
34057c478bd9Sstevel@tonic-gate  * A log item stores state about the transaction it represents. This
34067c478bd9Sstevel@tonic-gate  * function releases the resources associated with the transaction and
34077c478bd9Sstevel@tonic-gate  * used to store the transaction state.
34087c478bd9Sstevel@tonic-gate  */
34097c478bd9Sstevel@tonic-gate int
34107c478bd9Sstevel@tonic-gate log_item_release(log_item_t *li)
34117c478bd9Sstevel@tonic-gate {
34127c478bd9Sstevel@tonic-gate 	pool_create_undo_t *create;
34137c478bd9Sstevel@tonic-gate 	pool_destroy_undo_t *destroy;
34147c478bd9Sstevel@tonic-gate 	pool_assoc_undo_t *assoc;
34157c478bd9Sstevel@tonic-gate 	pool_dissoc_undo_t *dissoc;
34167c478bd9Sstevel@tonic-gate 	pool_propput_undo_t *propput;
34177c478bd9Sstevel@tonic-gate 	pool_proprm_undo_t *proprm;
34187c478bd9Sstevel@tonic-gate 	pool_xtransfer_undo_t *xtransfer;
34197c478bd9Sstevel@tonic-gate 
34207c478bd9Sstevel@tonic-gate 	switch (li->li_op) {
34217c478bd9Sstevel@tonic-gate 	case POOL_CREATE:
34227c478bd9Sstevel@tonic-gate 		create = (pool_create_undo_t *)li->li_details;
34237c478bd9Sstevel@tonic-gate 
34247c478bd9Sstevel@tonic-gate 		free(create);
34257c478bd9Sstevel@tonic-gate 		break;
34267c478bd9Sstevel@tonic-gate 	case POOL_DESTROY:
34277c478bd9Sstevel@tonic-gate 		destroy = (pool_destroy_undo_t *)li->li_details;
34287c478bd9Sstevel@tonic-gate 
34297c478bd9Sstevel@tonic-gate #ifdef DEBUG
34307c478bd9Sstevel@tonic-gate 		dprintf("log_item_release: POOL_DESTROY\n");
34317c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
34327c478bd9Sstevel@tonic-gate 
34337c478bd9Sstevel@tonic-gate 		if (li->li_state == LS_UNDO) {
34347c478bd9Sstevel@tonic-gate #ifdef DEBUG
34357c478bd9Sstevel@tonic-gate 			pool_elem_dprintf(destroy->pdu_elem);
34367c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
34377c478bd9Sstevel@tonic-gate 			pool_knl_elem_free((pool_knl_elem_t *)destroy->
34387c478bd9Sstevel@tonic-gate 			    pdu_elem, PO_TRUE);
34397c478bd9Sstevel@tonic-gate 		}
34407c478bd9Sstevel@tonic-gate 		free(destroy);
34417c478bd9Sstevel@tonic-gate 		break;
34427c478bd9Sstevel@tonic-gate 	case POOL_ASSOC:
34437c478bd9Sstevel@tonic-gate 		assoc = (pool_assoc_undo_t *)li->li_details;
34447c478bd9Sstevel@tonic-gate 
34457c478bd9Sstevel@tonic-gate 		free(assoc);
34467c478bd9Sstevel@tonic-gate 		break;
34477c478bd9Sstevel@tonic-gate 	case POOL_DISSOC:
34487c478bd9Sstevel@tonic-gate 		dissoc = (pool_dissoc_undo_t *)li->li_details;
34497c478bd9Sstevel@tonic-gate 
34507c478bd9Sstevel@tonic-gate 		free(dissoc);
34517c478bd9Sstevel@tonic-gate 		break;
34527c478bd9Sstevel@tonic-gate 	case POOL_TRANSFER:
34537c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
34547c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
34557c478bd9Sstevel@tonic-gate 		break;
34567c478bd9Sstevel@tonic-gate 	case POOL_XTRANSFER:
34577c478bd9Sstevel@tonic-gate 		xtransfer = (pool_xtransfer_undo_t *)li->li_details;
34587c478bd9Sstevel@tonic-gate 
34597c478bd9Sstevel@tonic-gate 		free(xtransfer->pxu_rl);
34607c478bd9Sstevel@tonic-gate 		free(xtransfer->pxu_ioctl.px_o_comp_list);
34617c478bd9Sstevel@tonic-gate 		free(xtransfer);
34627c478bd9Sstevel@tonic-gate 		break;
34637c478bd9Sstevel@tonic-gate 	case POOL_PROPPUT:
34647c478bd9Sstevel@tonic-gate 		propput = (pool_propput_undo_t *)li->li_details;
34657c478bd9Sstevel@tonic-gate 
34667c478bd9Sstevel@tonic-gate 		if (propput->ppu_blist)
34677c478bd9Sstevel@tonic-gate 			nvlist_free(propput->ppu_blist);
34687c478bd9Sstevel@tonic-gate 		free(propput->ppu_ioctl.pp_o_buf);
34697c478bd9Sstevel@tonic-gate 		free(propput);
34707c478bd9Sstevel@tonic-gate 		break;
34717c478bd9Sstevel@tonic-gate 	case POOL_PROPRM:
34727c478bd9Sstevel@tonic-gate 		proprm = (pool_proprm_undo_t *)li->li_details;
34737c478bd9Sstevel@tonic-gate 
34747c478bd9Sstevel@tonic-gate 		free(proprm);
34757c478bd9Sstevel@tonic-gate 		break;
34767c478bd9Sstevel@tonic-gate 	default:
34777c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
34787c478bd9Sstevel@tonic-gate 	}
34797c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
34807c478bd9Sstevel@tonic-gate }
34817c478bd9Sstevel@tonic-gate 
34827c478bd9Sstevel@tonic-gate /*
34837c478bd9Sstevel@tonic-gate  * pool_knl_nvlist_add_value() adds a pool_value_t to an nvlist.
34847c478bd9Sstevel@tonic-gate  */
34857c478bd9Sstevel@tonic-gate int
34867c478bd9Sstevel@tonic-gate pool_knl_nvlist_add_value(nvlist_t *list, const char *name,
34877c478bd9Sstevel@tonic-gate     const pool_value_t *pv)
34887c478bd9Sstevel@tonic-gate {
34897c478bd9Sstevel@tonic-gate 	uint64_t uval;
34907c478bd9Sstevel@tonic-gate 	int64_t ival;
34917c478bd9Sstevel@tonic-gate 	double dval;
34927c478bd9Sstevel@tonic-gate 	uchar_t dval_b[sizeof (double)];
34937c478bd9Sstevel@tonic-gate 	uchar_t bval;
34947c478bd9Sstevel@tonic-gate 	const char *sval;
34957c478bd9Sstevel@tonic-gate 	pool_value_class_t type;
34967c478bd9Sstevel@tonic-gate 	char *nv_name;
34977c478bd9Sstevel@tonic-gate 
34987c478bd9Sstevel@tonic-gate 	if ((type = pool_value_get_type(pv)) == POC_INVAL) {
34997c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
35007c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
35017c478bd9Sstevel@tonic-gate 	}
35027c478bd9Sstevel@tonic-gate 	nv_name = (char *)name;
35037c478bd9Sstevel@tonic-gate 
35047c478bd9Sstevel@tonic-gate 	switch (type) {
35057c478bd9Sstevel@tonic-gate 	case POC_UINT:
35067c478bd9Sstevel@tonic-gate 		if (pool_value_get_uint64(pv, &uval) == POC_INVAL) {
35077c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35087c478bd9Sstevel@tonic-gate 		}
35097c478bd9Sstevel@tonic-gate 		if (nvlist_add_uint64(list, nv_name, uval) != 0) {
35107c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
35117c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35127c478bd9Sstevel@tonic-gate 		}
35137c478bd9Sstevel@tonic-gate 		break;
35147c478bd9Sstevel@tonic-gate 	case POC_INT:
35157c478bd9Sstevel@tonic-gate 		if (pool_value_get_int64(pv, &ival) == POC_INVAL) {
35167c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35177c478bd9Sstevel@tonic-gate 		}
35187c478bd9Sstevel@tonic-gate 		if (nvlist_add_int64(list, nv_name, ival) != 0) {
35197c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
35207c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35217c478bd9Sstevel@tonic-gate 		}
35227c478bd9Sstevel@tonic-gate 		break;
35237c478bd9Sstevel@tonic-gate 	case POC_DOUBLE:
35247c478bd9Sstevel@tonic-gate 		if (pool_value_get_double(pv, &dval) == POC_INVAL) {
35257c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35267c478bd9Sstevel@tonic-gate 		}
35277c478bd9Sstevel@tonic-gate 		/*
35287c478bd9Sstevel@tonic-gate 		 * Since there is no support for doubles in the
35297c478bd9Sstevel@tonic-gate 		 * kernel, store the double value in a byte array.
35307c478bd9Sstevel@tonic-gate 		 */
35317c478bd9Sstevel@tonic-gate 		(void) memcpy(dval_b, &dval, sizeof (double));
35327c478bd9Sstevel@tonic-gate 		if (nvlist_add_byte_array(list, nv_name, dval_b,
35337c478bd9Sstevel@tonic-gate 		    sizeof (double)) != 0) {
35347c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
35357c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35367c478bd9Sstevel@tonic-gate 		}
35377c478bd9Sstevel@tonic-gate 		break;
35387c478bd9Sstevel@tonic-gate 	case POC_BOOL:
35397c478bd9Sstevel@tonic-gate 		if (pool_value_get_bool(pv, &bval) == POC_INVAL) {
35407c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35417c478bd9Sstevel@tonic-gate 		}
35427c478bd9Sstevel@tonic-gate 		if (nvlist_add_byte(list, nv_name, bval) != 0) {
35437c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
35447c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35457c478bd9Sstevel@tonic-gate 		}
35467c478bd9Sstevel@tonic-gate 		break;
35477c478bd9Sstevel@tonic-gate 	case POC_STRING:
35487c478bd9Sstevel@tonic-gate 		if (pool_value_get_string(pv, &sval) == POC_INVAL) {
35497c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35507c478bd9Sstevel@tonic-gate 		}
35517c478bd9Sstevel@tonic-gate 		if (nvlist_add_string(list, nv_name, (char *)sval) != 0) {
35527c478bd9Sstevel@tonic-gate 			pool_seterror(POE_SYSTEM);
35537c478bd9Sstevel@tonic-gate 			return (PO_FAIL);
35547c478bd9Sstevel@tonic-gate 		}
35557c478bd9Sstevel@tonic-gate 		break;
35567c478bd9Sstevel@tonic-gate 	default:
35577c478bd9Sstevel@tonic-gate 		pool_seterror(POE_BADPARAM);
35587c478bd9Sstevel@tonic-gate 		return (PO_FAIL);
35597c478bd9Sstevel@tonic-gate 	}
35607c478bd9Sstevel@tonic-gate 	return (PO_SUCCESS);
35617c478bd9Sstevel@tonic-gate }
35627c478bd9Sstevel@tonic-gate 
35637c478bd9Sstevel@tonic-gate /*
35647c478bd9Sstevel@tonic-gate  * hash_id() hashes all elements in a pool configuration using the
35657c478bd9Sstevel@tonic-gate  * "sys_id" property. Not all elements have a "sys_id" property,
35667c478bd9Sstevel@tonic-gate  * however elem_get_sysid() caters for this by always returning a
35677c478bd9Sstevel@tonic-gate  * constant value for those elements. This isn't anticipated to lead
35687c478bd9Sstevel@tonic-gate  * to a performance degradation in the hash, since those elements
35697c478bd9Sstevel@tonic-gate  * which are likely to be most prevalent in a configuration do have
35707c478bd9Sstevel@tonic-gate  * "sys_id" as a property.
35717c478bd9Sstevel@tonic-gate  */
35727c478bd9Sstevel@tonic-gate uint64_t
35737c478bd9Sstevel@tonic-gate hash_id(const pool_elem_t *pe)
35747c478bd9Sstevel@tonic-gate {
35757c478bd9Sstevel@tonic-gate 	id_t id;
35767c478bd9Sstevel@tonic-gate 
35777c478bd9Sstevel@tonic-gate 	id = elem_get_sysid(pe);
35787c478bd9Sstevel@tonic-gate 	return (hash_buf(&id, sizeof (id)));
35797c478bd9Sstevel@tonic-gate }
35807c478bd9Sstevel@tonic-gate 
35817c478bd9Sstevel@tonic-gate /*
35827c478bd9Sstevel@tonic-gate  *  blocking_open() guarantees access to the pool device, if open()
35837c478bd9Sstevel@tonic-gate  * is failing with EBUSY.
35847c478bd9Sstevel@tonic-gate  */
35857c478bd9Sstevel@tonic-gate int
35867c478bd9Sstevel@tonic-gate blocking_open(const char *path, int oflag)
35877c478bd9Sstevel@tonic-gate {
35887c478bd9Sstevel@tonic-gate 	int fd;
35897c478bd9Sstevel@tonic-gate 
35907c478bd9Sstevel@tonic-gate 	while ((fd = open(path, oflag)) == -1 && errno == EBUSY)
35917c478bd9Sstevel@tonic-gate 		(void) poll(NULL, 0, 1 * MILLISEC);
35927c478bd9Sstevel@tonic-gate 
35937c478bd9Sstevel@tonic-gate 	return (fd);
35947c478bd9Sstevel@tonic-gate }
3595