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