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