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
load_group(pool_conf_t * conf,pool_knl_elem_t * elem,ea_object_t * ep,pool_snap_load_t * psl)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
pool_knl_snap_load_push(pool_snap_load_t * psl,pool_knl_pool_t * pkp)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
pool_knl_snap_load_update(pool_snap_load_t * psl,int type,uint_t id)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
pool_knl_snap_load_remove(pool_snap_load_t * psl,int type,uint_t id)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 *
pool_knl_find_nvpair(nvlist_t * l,const char * name)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
pool_knl_close(pool_conf_t * conf)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
remove_dead_elems(const void * key,void ** value,void * cl)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
find_dead_elems(const void * key,void ** value,void * cl)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
pool_knl_update(pool_conf_t * conf,int * changed)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
pool_knl_validate(const pool_conf_t * conf,pool_valid_level_t level)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
pool_knl_commit(pool_conf_t * conf)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
prop_build_cb(pool_conf_t * UNUSED,pool_elem_t * pe,const char * name,pool_value_t * pval,void * user)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
pool_knl_put_xml_property(pool_elem_t * pe,xmlNodePtr node,const char * name,const pool_value_t * val)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
pool_knl_export(const pool_conf_t * conf,const char * location,pool_export_format_t fmt)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 =
11227c478bd9