xref: /onnv-gate/usr/src/lib/libraidcfg/common/raidcfg.c (revision 8855:1e92cda06d35)
13457Sjc156560 /*
23457Sjc156560  * CDDL HEADER START
33457Sjc156560  *
43457Sjc156560  * The contents of this file are subject to the terms of the
53457Sjc156560  * Common Development and Distribution License (the "License").
63457Sjc156560  * You may not use this file except in compliance with the License.
73457Sjc156560  *
83457Sjc156560  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93457Sjc156560  * or http://www.opensolaris.org/os/licensing.
103457Sjc156560  * See the License for the specific language governing permissions
113457Sjc156560  * and limitations under the License.
123457Sjc156560  *
133457Sjc156560  * When distributing Covered Code, include this CDDL HEADER in each
143457Sjc156560  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153457Sjc156560  * If applicable, add the following below this CDDL HEADER, with the
163457Sjc156560  * fields enclosed by brackets "[]" replaced with your own identifying
173457Sjc156560  * information: Portions Copyright [yyyy] [name of copyright owner]
183457Sjc156560  *
193457Sjc156560  * CDDL HEADER END
203457Sjc156560  */
213457Sjc156560 
223457Sjc156560 /*
23*8855SMilan.Jurik@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
243457Sjc156560  * Use is subject to license terms.
253457Sjc156560  */
263457Sjc156560 
273457Sjc156560 #include <fcntl.h>
283457Sjc156560 #include <sys/types.h>
293457Sjc156560 #include <sys/stat.h>
303457Sjc156560 #include <stddef.h>
313457Sjc156560 #include <stdlib.h>
323457Sjc156560 #include <dirent.h>
333457Sjc156560 #include <dlfcn.h>
343457Sjc156560 #include <link.h>
353457Sjc156560 #include <strings.h>
363457Sjc156560 #include <stdio.h>
373457Sjc156560 #include <unistd.h>
383457Sjc156560 #include <sys/mnttab.h>
393457Sjc156560 #include <config_admin.h>
403457Sjc156560 #include <sys/param.h>
413457Sjc156560 #include <libintl.h>
423457Sjc156560 #include <libdevinfo.h>
433457Sjc156560 #include <raidcfg.h>
443457Sjc156560 #include <thread.h>
453457Sjc156560 #include <synch.h>
463457Sjc156560 
473457Sjc156560 #ifndef TEXT_DOMAIN
483457Sjc156560 #define	TEXT_DOMAIN	"SYS_TEST"
493457Sjc156560 #endif
503457Sjc156560 
513457Sjc156560 #define	HASH_SLOTS	16
523457Sjc156560 #define	HANDLER_SLOTS	256
533457Sjc156560 
543457Sjc156560 /*
553457Sjc156560  * Raid object status;
563457Sjc156560  */
573457Sjc156560 #define	OBJ_STATUS_CMD_CLEAN	-1
583457Sjc156560 #define	OBJ_STATUS_OPENED	1
593457Sjc156560 #define	OBJ_STATUS_SCANCOMP	1 << 1
603457Sjc156560 
613457Sjc156560 #if defined(__sparcv9)
623457Sjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg/sparcv9"
633457Sjc156560 #elif defined(__amd64)
643457Sjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg/amd64"
653457Sjc156560 #else
663457Sjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg"
673457Sjc156560 #endif
683457Sjc156560 
693457Sjc156560 /*
703457Sjc156560  * Basic types
713457Sjc156560  */
723457Sjc156560 typedef	int raid_obj_id_t;
733457Sjc156560 typedef	int raid_obj_status_t;
743457Sjc156560 
753457Sjc156560 /*
763457Sjc156560  * Data structures used for object maintennance
773457Sjc156560  */
783457Sjc156560 typedef	struct {
793457Sjc156560 	void *head;
803457Sjc156560 	void *tail;
813457Sjc156560 	size_t offset;	/* offset of double-linked element (raid_list_el_t) */
823457Sjc156560 			/* in the linked data structures (objects) */
833457Sjc156560 } raid_list_t;
843457Sjc156560 
853457Sjc156560 typedef	struct {
863457Sjc156560 	void *prev;
873457Sjc156560 	void *next;
883457Sjc156560 } raid_list_el_t;
893457Sjc156560 
903457Sjc156560 typedef	struct {
913457Sjc156560 	raid_obj_id_t obj_id_cnt;	/* id 0 is reserved */
923457Sjc156560 	size_t slots;			/* How many lists linked by *table */
933457Sjc156560 	raid_list_t *table;
943457Sjc156560 } raid_obj_tab_t;
953457Sjc156560 
963457Sjc156560 /*
973457Sjc156560  * Object type structure containing function pointers;
983457Sjc156560  */
993457Sjc156560 typedef	struct {
1003457Sjc156560 	int (*compnum)(raid_obj_tab_t *, raid_obj_id_t, raid_obj_type_id_t);
1013457Sjc156560 	int (*complist)(raid_obj_tab_t *, raid_obj_id_t, int, raid_obj_id_t *,
1023457Sjc156560 		raid_obj_type_id_t);
1033457Sjc156560 	int (*get_attr)(raid_obj_tab_t *, raid_obj_id_t);
1043457Sjc156560 	int (*set_attr)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, uint32_t *,
1053457Sjc156560 		char **);
1063457Sjc156560 	int (*act)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, void *, char **);
1073457Sjc156560 	int (*create_obj)(raid_obj_tab_t *, raid_obj_id_t, int,
1083457Sjc156560 		raid_obj_id_t *, char **);
1093457Sjc156560 	int (*delete_obj)(raid_obj_tab_t *, raid_obj_id_t, char **);
1108263SRyan.Wang@Sun.COM 	int (*bind_obj)(raid_obj_tab_t *, raid_obj_id_t *, char **);
1118263SRyan.Wang@Sun.COM 	int (*unbind_obj)(raid_obj_tab_t *, raid_obj_id_t *, char **);
1123457Sjc156560 } raid_obj_op_t;
1133457Sjc156560 
1143457Sjc156560 /*
1153457Sjc156560  * Common object data structure
1163457Sjc156560  */
1173457Sjc156560 typedef	struct {
1183457Sjc156560 	raid_list_el_t		el;	/* double-links */
1193457Sjc156560 
1203457Sjc156560 	raid_obj_type_id_t	obj_type_id;
1213457Sjc156560 	raid_obj_id_t		obj_id;
1223457Sjc156560 	raid_obj_status_t	status;
1233457Sjc156560 
1243457Sjc156560 	raid_obj_id_t		container;
1253457Sjc156560 	raid_obj_id_t		sibling;
1263457Sjc156560 	raid_obj_id_t		component;
1273457Sjc156560 
1283457Sjc156560 	void			*data;	/* Pointer to attribute structure */
1293457Sjc156560 	raid_obj_handle_t	handle;
1303457Sjc156560 } raid_obj_t;
1313457Sjc156560 
1323457Sjc156560 /*
1333457Sjc156560  * Definition about handle
1343457Sjc156560  */
1353457Sjc156560 typedef	struct {
1363457Sjc156560 	uint32_t	next;
1373457Sjc156560 	uint32_t	type;
1383457Sjc156560 	uint32_t	controller_id;
1393457Sjc156560 	uint32_t	array_id;
1403457Sjc156560 	uint32_t	disk_id;
1413457Sjc156560 	uint64_t	seq_id;
1423457Sjc156560 	uint32_t	task_id;
1437233Syw161884 	uint32_t	prop_id;
1443457Sjc156560 	uint32_t	fd;		/* Only for controller */
1453457Sjc156560 	raid_lib_t	*raid_lib;	/* Only for controller */
1463457Sjc156560 } handle_attr_t;
1473457Sjc156560 
1483457Sjc156560 #define	LIST_OBJ_TO_EL(list, obj)	\
1493457Sjc156560 	((void *)((char *)(obj) + (list)->offset))
1503457Sjc156560 #define	OBJ_TAB_SLOT(tab, id)	\
1513457Sjc156560 	((tab)->table + ((id)%(tab)->slots))
1523457Sjc156560 
1533457Sjc156560 #pragma init(raidcfg_init)
1543457Sjc156560 #pragma fini(raidcfg_fini)
1553457Sjc156560 
1563457Sjc156560 /*
1573457Sjc156560  * Function prototypes
1583457Sjc156560  */
1593457Sjc156560 static int intcompare(const void *p1, const void *p2);
1603457Sjc156560 static uint64_t raid_space_noalign(raid_obj_tab_t *, uint32_t, int,
1613457Sjc156560 	raid_obj_id_t *, arraypart_attr_t *);
1623457Sjc156560 static int raid_handle_init();
1633457Sjc156560 static void raid_handle_fini();
1643457Sjc156560 static raid_obj_handle_t raid_handle_new(raid_obj_type_id_t);
1653457Sjc156560 static void raid_handle_delete(raid_obj_handle_t);
1663457Sjc156560 static void raid_handle_delete_controller_comp(uint32_t);
1673457Sjc156560 static raid_obj_id_t raid_handle_to_obj(raid_obj_tab_t *,
1683457Sjc156560 	raid_obj_handle_t);
1693457Sjc156560 static raid_obj_handle_t raid_obj_to_handle(raid_obj_tab_t *,
1703457Sjc156560 	raid_obj_id_t);
1713457Sjc156560 static raid_lib_t *raid_obj_get_lib(raid_obj_tab_t *, raid_obj_id_t);
1723457Sjc156560 static int raid_obj_set_lib(raid_obj_tab_t *, raid_obj_id_t, raid_lib_t *);
1733457Sjc156560 static int raid_obj_get_fd(raid_obj_tab_t *, raid_obj_id_t);
1743457Sjc156560 static int raid_obj_set_fd(raid_obj_tab_t *, raid_obj_id_t, int);
1753457Sjc156560 static int obj_scan_comp(raid_obj_tab_t *, raid_obj_id_t);
1763457Sjc156560 static int obj_rescan(raid_obj_tab_t *);
1773457Sjc156560 static raid_obj_id_t obj_get_comp(raid_obj_tab_t *, raid_obj_id_t,
1783457Sjc156560 	raid_obj_type_id_t);
1793457Sjc156560 static raid_obj_id_t obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
1803457Sjc156560 static int obj_get_attr(raid_obj_tab_t *, raid_obj_id_t, void **);
1813457Sjc156560 static raid_obj_id_t obj_locate_controller(raid_obj_tab_t *, uint32_t);
1823457Sjc156560 static raid_obj_id_t obj_locate_array(raid_obj_tab_t *, uint32_t, uint32_t);
1833457Sjc156560 static raid_obj_id_t obj_locate_array_recur(raid_obj_tab_t *, raid_obj_id_t,
1843457Sjc156560 	uint32_t);
1853457Sjc156560 static raid_obj_id_t obj_locate_hsp(raid_obj_tab_t *, uint32_t,
1863457Sjc156560 	uint32_t, uint32_t);
1873457Sjc156560 static raid_obj_id_t obj_locate_disk(raid_obj_tab_t *, uint32_t, uint32_t);
1883457Sjc156560 static raid_obj_id_t obj_locate_arraypart(raid_obj_tab_t *, uint32_t,
1893457Sjc156560 	uint32_t, uint32_t);
1903457Sjc156560 static raid_obj_id_t obj_locate_diskseg(raid_obj_tab_t *, uint32_t,
1913457Sjc156560 	uint32_t, uint32_t);
1923457Sjc156560 static raid_obj_id_t obj_locate_task(raid_obj_tab_t *, uint32_t, uint32_t);
1937233Syw161884 static raid_obj_id_t obj_locate_prop(raid_obj_tab_t *, uint32_t, uint32_t,
1947233Syw161884 	uint32_t);
1953457Sjc156560 static raid_obj_id_t obj_get_controller(raid_obj_tab_t *, raid_obj_id_t);
1963457Sjc156560 
1973457Sjc156560 static int obj_sys_compnum(raid_obj_tab_t *, raid_obj_id_t,
1983457Sjc156560 	raid_obj_type_id_t);
1993457Sjc156560 static int obj_sys_complist(raid_obj_tab_t *, raid_obj_id_t, int,
2003457Sjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
2013457Sjc156560 static int obj_controller_compnum(raid_obj_tab_t *, raid_obj_id_t,
2023457Sjc156560 	raid_obj_type_id_t);
2033457Sjc156560 static int obj_controller_complist(raid_obj_tab_t *, raid_obj_id_t, int,
2043457Sjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
2053457Sjc156560 static int obj_controller_get_attr(raid_obj_tab_t *, raid_obj_id_t);
2063457Sjc156560 static int obj_controller_act(raid_obj_tab_t *, raid_obj_id_t,
2073457Sjc156560 	uint32_t, void *, char **);
2083457Sjc156560 static int obj_array_compnum(raid_obj_tab_t *, raid_obj_id_t,
2093457Sjc156560 	raid_obj_type_id_t);
2103457Sjc156560 static int obj_array_complist(raid_obj_tab_t *, raid_obj_id_t, int,
2113457Sjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
2123457Sjc156560 static int obj_array_get_attr(raid_obj_tab_t *, raid_obj_id_t);
2133457Sjc156560 static int obj_array_set_attr(raid_obj_tab_t *, raid_obj_id_t,
2143457Sjc156560 	uint32_t, uint32_t *, char **);
2153457Sjc156560 static int obj_disk_compnum(raid_obj_tab_t *, raid_obj_id_t,
2163457Sjc156560 	raid_obj_type_id_t);
2173457Sjc156560 static int obj_disk_complist(raid_obj_tab_t *, raid_obj_id_t, int,
2183457Sjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
2193457Sjc156560 static int obj_disk_get_attr(raid_obj_tab_t *, raid_obj_id_t);
2203457Sjc156560 static int obj_hsp_get_attr(raid_obj_tab_t *, raid_obj_id_t);
2213457Sjc156560 static int obj_arraypart_get_attr(raid_obj_tab_t *, raid_obj_id_t);
2223457Sjc156560 static int obj_diskseg_get_attr(raid_obj_tab_t *, raid_obj_id_t);
2233457Sjc156560 static int obj_task_get_attr(raid_obj_tab_t *, raid_obj_id_t);
2247233Syw161884 static int obj_prop_get_attr(raid_obj_tab_t *, raid_obj_id_t);
2253457Sjc156560 static int obj_array_create(raid_obj_tab_t *, raid_obj_id_t, int,
2263457Sjc156560 	raid_obj_id_t *, char **);
2273457Sjc156560 static int obj_array_delete(raid_obj_tab_t *, raid_obj_id_t, char **);
2288263SRyan.Wang@Sun.COM static int obj_hsp_bind(raid_obj_tab_t *, raid_obj_id_t *, char **);
2298263SRyan.Wang@Sun.COM static int obj_hsp_unbind(raid_obj_tab_t *, raid_obj_id_t *, char **);
2303457Sjc156560 
2313457Sjc156560 static int raid_obj_create_system_obj(raid_obj_tab_t *);
2323457Sjc156560 static raid_obj_id_t raid_obj_id_new(raid_obj_tab_t *);
2333457Sjc156560 static void *raid_obj_attr_new(raid_obj_type_id_t);
2343457Sjc156560 static raid_obj_id_t raid_obj_create(raid_obj_tab_t *, raid_obj_type_id_t);
2353457Sjc156560 static int raid_obj_delete(raid_obj_tab_t *, raid_obj_id_t);
2363457Sjc156560 static int raid_obj_add_org(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
2373457Sjc156560 static raid_obj_type_id_t raid_obj_get_type(raid_obj_tab_t *, raid_obj_id_t);
2383457Sjc156560 static int raid_obj_set_type(raid_obj_tab_t *, raid_obj_id_t,
2393457Sjc156560 	raid_obj_type_id_t);
2403457Sjc156560 static raid_obj_status_t raid_obj_get_status(raid_obj_tab_t *, raid_obj_id_t);
2413457Sjc156560 static int raid_obj_set_status(raid_obj_tab_t *, raid_obj_id_t,
2423457Sjc156560 	raid_obj_status_t);
2433457Sjc156560 static int raid_obj_clear_status(raid_obj_tab_t *, raid_obj_id_t,
2443457Sjc156560 	raid_obj_status_t);
2453457Sjc156560 static raid_obj_id_t raid_obj_get_container(raid_obj_tab_t *, raid_obj_id_t);
2463457Sjc156560 static int raid_obj_set_container(raid_obj_tab_t *, raid_obj_id_t,
2473457Sjc156560 	raid_obj_id_t);
2483457Sjc156560 static raid_obj_id_t raid_obj_get_comp(raid_obj_tab_t *, raid_obj_id_t);
2493457Sjc156560 static int raid_obj_set_comp(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
2503457Sjc156560 static raid_obj_id_t raid_obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
2513457Sjc156560 static int raid_obj_set_sibling(raid_obj_tab_t *, raid_obj_id_t,
2523457Sjc156560 	raid_obj_id_t);
2533457Sjc156560 static void *raid_obj_get_data_ptr(raid_obj_tab_t *, raid_obj_id_t);
2543457Sjc156560 static int raid_obj_set_data_ptr(raid_obj_tab_t *, raid_obj_id_t, void *);
2553457Sjc156560 static raid_obj_handle_t raid_obj_get_handle(raid_obj_tab_t *,
2563457Sjc156560 	raid_obj_id_t);
2573457Sjc156560 static int raid_obj_set_handle(raid_obj_tab_t *, raid_obj_id_t,
2583457Sjc156560 	raid_obj_handle_t);
2593457Sjc156560 
2603457Sjc156560 static void raid_list_create(raid_list_t *, size_t);
2613457Sjc156560 static void *raid_list_head(raid_list_t *);
2623457Sjc156560 static void *raid_list_next(raid_list_t *, void *);
2633457Sjc156560 static void raid_list_insert_tail(raid_list_t *, void *);
2643457Sjc156560 static void raid_list_remove(raid_list_t *, void *);
2653457Sjc156560 static void *raid_list_remove_head(raid_list_t *);
2663457Sjc156560 static void *raid_list_find(raid_list_t *, raid_obj_id_t);
2673457Sjc156560 static int raid_obj_tab_create(raid_obj_tab_t *, size_t);
2683457Sjc156560 static void raid_obj_tab_destroy(raid_obj_tab_t *);
2693457Sjc156560 static int raid_obj_tab_insert(raid_obj_tab_t *, raid_obj_id_t, void *);
2703457Sjc156560 static void *raid_obj_tab_remove(raid_obj_tab_t *, raid_obj_id_t);
2713457Sjc156560 static void *raid_obj_tab_find(raid_obj_tab_t *, raid_obj_id_t);
2723457Sjc156560 static void raid_list_destroy(raid_list_t *);
2733457Sjc156560 
2743457Sjc156560 static int controller_id_to_path(uint32_t, char *);
2753457Sjc156560 static char *controller_id_to_driver_name(uint32_t);
2763457Sjc156560 static void raid_plugin_init();
2773457Sjc156560 static raid_lib_t *raid_plugin_load(char *);
2783457Sjc156560 static raid_lib_t *raid_find_lib(raid_obj_tab_t *, raid_obj_id_t);
2793457Sjc156560 
2803457Sjc156560 /* Global object table */
2813457Sjc156560 static raid_obj_tab_t raid_tab_sys = {0, 0, NULL};
2823457Sjc156560 
2833457Sjc156560 /* Plug-in modules maintenance data structures */
2843457Sjc156560 static raid_lib_t *raid_lib_sys = NULL;
2853457Sjc156560 
2863457Sjc156560 /* Handle table definition */
2873457Sjc156560 static struct {
2883457Sjc156560 	int		handle_num;
2893457Sjc156560 	int		used;
2903457Sjc156560 	int		unused;
2913457Sjc156560 	handle_attr_t	*handles;
2923457Sjc156560 } raid_handle_sys = {0, 0, 0, NULL};
2933457Sjc156560 
2943457Sjc156560 /*
2953457Sjc156560  * RAID object method table definition
2963457Sjc156560  */
2973457Sjc156560 static raid_obj_op_t raid_obj_op_sys[OBJ_TYPE_ALL] = {
2983457Sjc156560 	{obj_sys_compnum, obj_sys_complist, NULL, NULL, NULL,
2993457Sjc156560 		NULL, NULL, NULL, NULL},	/* system object methods */
3003457Sjc156560 	{obj_controller_compnum, obj_controller_complist,
3013457Sjc156560 		obj_controller_get_attr, NULL, obj_controller_act,
3023457Sjc156560 		NULL, NULL, NULL, NULL},	/* controller object methods */
3033457Sjc156560 	{obj_array_compnum, obj_array_complist, obj_array_get_attr,
3043457Sjc156560 		obj_array_set_attr, NULL, obj_array_create,
3053457Sjc156560 		obj_array_delete, NULL, NULL},	/* array object methods */
3063457Sjc156560 	{obj_disk_compnum, obj_disk_complist, obj_disk_get_attr, NULL,
3073457Sjc156560 		NULL, NULL, NULL, NULL, NULL},	/* disk object methods */
3083457Sjc156560 	{NULL, NULL, obj_hsp_get_attr, NULL, NULL, NULL, NULL, obj_hsp_bind,
3093457Sjc156560 		obj_hsp_unbind},		/* hsp object methods */
3103457Sjc156560 	{NULL, NULL, obj_arraypart_get_attr, NULL, NULL, NULL, NULL,
3113457Sjc156560 		NULL, NULL},			/* array part object methods */
3123457Sjc156560 	{NULL, NULL, obj_diskseg_get_attr, NULL, NULL, NULL, NULL, NULL, NULL},
3133457Sjc156560 	{NULL, NULL, obj_task_get_attr, NULL, NULL, NULL, NULL,
3147233Syw161884 		NULL, NULL},			/* disk seg object methods */
3157233Syw161884 	{NULL, NULL, obj_prop_get_attr, NULL, NULL, NULL, NULL,
3167233Syw161884 		NULL, NULL}			/* property object methods */
3173457Sjc156560 };
3183457Sjc156560 
3193457Sjc156560 /*
3203457Sjc156560  * Mutex for multithread safe
3213457Sjc156560  */
3223457Sjc156560 static mutex_t raidcfg_mp;
3233457Sjc156560 
3243457Sjc156560 /*
3253457Sjc156560  * RaidCfg library APIs
3263457Sjc156560  */
3273457Sjc156560 const char *
raidcfg_errstr(int err_code)3283457Sjc156560 raidcfg_errstr(int err_code)
3293457Sjc156560 {
3303457Sjc156560 	char *ret_val;
3313457Sjc156560 
3323457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
3333457Sjc156560 	switch (err_code) {
3343457Sjc156560 	case	SUCCESS:
3353457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Operation succeeded.\n");
3363457Sjc156560 		break;
3373457Sjc156560 	case	STD_IOCTL:
3383457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
3394563Syw161884 		    "Request standard IOCTL service.\n");
3403457Sjc156560 		break;
3413457Sjc156560 	case	ERR_DRIVER_NOT_FOUND:
3423457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
3434563Syw161884 		    "Controller device can not be found.\n");
3443457Sjc156560 		break;
3453457Sjc156560 	case	ERR_DRIVER_OPEN:
3463457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Can not open controller.\n");
3473457Sjc156560 		break;
3483457Sjc156560 	case	ERR_DRIVER_LOCK:
3493457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Controller is locked.\n");
3503457Sjc156560 		break;
3513457Sjc156560 	case	ERR_DRIVER_CLOSED:
3523457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Controller is not opened.\n");
3533457Sjc156560 		break;
3543457Sjc156560 	case	ERR_DRIVER_ACROSS:
3553457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
3564563Syw161884 		    "Operation across multiple controllers.\n");
3573457Sjc156560 		break;
3583457Sjc156560 	case	ERR_ARRAY_LEVEL:
3593457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
3604563Syw161884 		    "Operation not support with volume of this level.\n");
3613457Sjc156560 		break;
3623457Sjc156560 	case	ERR_ARRAY_SIZE:
3633457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
3644563Syw161884 		    "Capacity of array out of range.\n");
3653457Sjc156560 		break;
3663457Sjc156560 	case	ERR_ARRAY_STRIPE_SIZE:
3673457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal stripe size.\n");
3683457Sjc156560 		break;
3693457Sjc156560 	case	ERR_ARRAY_CACHE_POLICY:
3703457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
3714563Syw161884 		    "Illegal cache-write policy.\n");
3723457Sjc156560 		break;
3733457Sjc156560 	case	ERR_ARRAY_IN_USE:
3744369Syw161884 		ret_val = dgettext(TEXT_DOMAIN, "Array or disk in use.\n");
3753457Sjc156560 		break;
3763457Sjc156560 	case	ERR_ARRAY_TASK:
3773457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Array has background task.\n");
3783457Sjc156560 		break;
3793457Sjc156560 	case	ERR_ARRAY_CONFIG:
3803457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
3814563Syw161884 		    "Configuration over device node failed.\n");
3823457Sjc156560 		break;
3833457Sjc156560 	case	ERR_ARRAY_DISKNUM:
3843457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Incorrect number of disks.\n");
3853457Sjc156560 		break;
3863457Sjc156560 	case	ERR_ARRAY_LAYOUT:
3873457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal array layout.\n");
3883457Sjc156560 		break;
3893457Sjc156560 	case	ERR_ARRAY_AMOUNT:
3903457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many arrays.\n");
3913457Sjc156560 		break;
3923457Sjc156560 	case	ERR_DISK_STATE:
3933457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
3944563Syw161884 		    "Incorrect disk status for current operation.\n");
3953457Sjc156560 		break;
3963457Sjc156560 	case	ERR_DISK_SPACE:
3973457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "No enough disk space.\n");
3983457Sjc156560 		break;
3993457Sjc156560 	case	ERR_DISK_SEG_AMOUNT:
4003457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many disk segments.\n");
4013457Sjc156560 		break;
4023457Sjc156560 	case	ERR_DISK_NOT_EMPTY:
4033457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Disk has occupied space.\n");
4043457Sjc156560 		break;
4053457Sjc156560 	case	ERR_DISK_TASK:
4063457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Disk has background task.\n");
4073457Sjc156560 		break;
4083457Sjc156560 	case	ERR_TASK_STATE:
4093457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
4104563Syw161884 		    "Incorrect task state for current operation.\n");
4113457Sjc156560 		break;
4123457Sjc156560 	case	ERR_OP_ILLEGAL:
4133457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal operation.\n");
4143457Sjc156560 		break;
4153457Sjc156560 	case	ERR_OP_NO_IMPL:
4163457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
4174563Syw161884 		    "Operation is not implemented.\n");
4183457Sjc156560 		break;
4193457Sjc156560 	case	ERR_OP_FAILED:
4204369Syw161884 		ret_val = dgettext(TEXT_DOMAIN, "Operation failed.\n");
4213457Sjc156560 		break;
4223457Sjc156560 	case	ERR_DEVICE_NOENT:
4233457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device not found.\n");
4243457Sjc156560 		break;
4253457Sjc156560 	case	ERR_DEVICE_TYPE:
4263457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal type of device.\n");
4273457Sjc156560 		break;
4283457Sjc156560 	case	ERR_DEVICE_DUP:
4293457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device record duplicated.\n");
4303457Sjc156560 		break;
4313457Sjc156560 	case	ERR_DEVICE_OVERFLOW:
4323457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many devices.\n");
4333457Sjc156560 		break;
4343457Sjc156560 	case	ERR_DEVICE_UNCLEAN:
4353457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device pool is not clean.\n");
4363457Sjc156560 		break;
4373457Sjc156560 	case	ERR_DEVICE_INVALID:
4383457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device record is invalid.\n");
4393457Sjc156560 		break;
4403457Sjc156560 	case	ERR_NOMEM:
4413457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN,
4424563Syw161884 		    "Can not allocate more memory space.\n");
4433457Sjc156560 		break;
4443457Sjc156560 	case	ERR_PRIV:
4453457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "No privilege.\n");
4463457Sjc156560 		break;
4473457Sjc156560 	default:
4483457Sjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Undefined error.\n");
4493457Sjc156560 	}
4503457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
4513457Sjc156560 
4523457Sjc156560 	return (ret_val);
4533457Sjc156560 }
4543457Sjc156560 
4553457Sjc156560 int
raidcfg_get_controller(uint32_t controller_id)4563457Sjc156560 raidcfg_get_controller(uint32_t controller_id)
4573457Sjc156560 {
4583457Sjc156560 	raid_obj_id_t obj_id;
4593457Sjc156560 	int ret_val;
4603457Sjc156560 
4613457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
4623457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
4633457Sjc156560 	obj_id = obj_locate_controller(&raid_tab_sys, controller_id);
4643457Sjc156560 	if (obj_id < OBJ_NONE) {
4653457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
4663457Sjc156560 		return (obj_id);
4673457Sjc156560 	}
4683457Sjc156560 
4693457Sjc156560 	if (obj_id == OBJ_NONE) {
4703457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
4713457Sjc156560 		return (ERR_DEVICE_NOENT);
4723457Sjc156560 	}
4733457Sjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
4743457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
4753457Sjc156560 
4763457Sjc156560 	return (ret_val);
4773457Sjc156560 }
4783457Sjc156560 
4793457Sjc156560 int
raidcfg_get_array(int controller_handle,uint64_t target_id,uint64_t lun)4803457Sjc156560 raidcfg_get_array(int controller_handle, uint64_t target_id, uint64_t lun)
4813457Sjc156560 {
4823457Sjc156560 	raid_obj_id_t obj_id;
4833457Sjc156560 	raidcfg_array_t *attr;
4843457Sjc156560 	int ret_val;
4853457Sjc156560 
4863457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
4873457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
4883457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
4893457Sjc156560 	if (obj_id < OBJ_NONE) {
4903457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
4913457Sjc156560 		return (obj_id);
4923457Sjc156560 	}
4933457Sjc156560 
4943457Sjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_ARRAY);
4953457Sjc156560 
4963457Sjc156560 	while (obj_id > OBJ_NONE) {
4973457Sjc156560 		(void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
4983457Sjc156560 		if (attr->tag.idl.target_id == target_id &&
4994563Syw161884 		    attr->tag.idl.lun == lun)
5003457Sjc156560 			break;
5013457Sjc156560 
5023457Sjc156560 		obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
5033457Sjc156560 	}
5043457Sjc156560 
5053457Sjc156560 	if (obj_id < OBJ_NONE) {
5063457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
5073457Sjc156560 		return (obj_id);
5083457Sjc156560 	}
5093457Sjc156560 	if (obj_id == OBJ_NONE) {
5103457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
5113457Sjc156560 		return (ERR_DEVICE_NOENT);
5123457Sjc156560 	}
5133457Sjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
5143457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
5153457Sjc156560 
5163457Sjc156560 	return (ret_val);
5173457Sjc156560 }
5183457Sjc156560 
5193457Sjc156560 int
raidcfg_get_disk(int controller_handle,disk_tag_t tag)5203457Sjc156560 raidcfg_get_disk(int controller_handle, disk_tag_t tag)
5213457Sjc156560 {
5223457Sjc156560 	raid_obj_id_t obj_id;
5233457Sjc156560 	raidcfg_disk_t *attr;
5243457Sjc156560 	int ret_val;
5253457Sjc156560 
5263457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
5273457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
5283457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
5293457Sjc156560 	if (obj_id < OBJ_NONE) {
5303457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
5313457Sjc156560 		return (obj_id);
5323457Sjc156560 	}
5333457Sjc156560 
5343457Sjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_DISK);
5353457Sjc156560 
5363457Sjc156560 	while (obj_id > OBJ_NONE) {
5373457Sjc156560 		(void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
5383457Sjc156560 		if (attr->tag.cidl.bus == tag.cidl.bus &&
5393457Sjc156560 		    attr->tag.cidl.target_id == tag.cidl.target_id &&
5403457Sjc156560 		    attr->tag.cidl.lun == tag.cidl.lun)
5413457Sjc156560 			break;
5423457Sjc156560 
5433457Sjc156560 		obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
5443457Sjc156560 	}
5453457Sjc156560 
5463457Sjc156560 	if (obj_id < OBJ_NONE) {
5473457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
5483457Sjc156560 		return (obj_id);
5493457Sjc156560 	}
5503457Sjc156560 	if (obj_id == OBJ_NONE) {
5513457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
5523457Sjc156560 		return (ERR_DEVICE_NOENT);
5533457Sjc156560 	}
5543457Sjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
5553457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
5563457Sjc156560 
5573457Sjc156560 	return (ret_val);
5583457Sjc156560 }
5593457Sjc156560 
5603457Sjc156560 int
raidcfg_open_controller(int handle,char ** plugin_err_str)5613457Sjc156560 raidcfg_open_controller(int handle, char **plugin_err_str)
5623457Sjc156560 {
5633457Sjc156560 	raid_obj_id_t obj_id;
5643457Sjc156560 	int ret;
5653457Sjc156560 
5663457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
5673457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
5683457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
5693457Sjc156560 	if (obj_id < OBJ_NONE) {
5703457Sjc156560 		raid_handle_delete(handle);
5713457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
5723457Sjc156560 		return (ERR_DEVICE_NOENT);
5733457Sjc156560 	}
5743457Sjc156560 
5753457Sjc156560 	ret = obj_controller_act(&raid_tab_sys, obj_id,
5764563Syw161884 	    ACT_CONTROLLER_OPEN, NULL, plugin_err_str);
5773457Sjc156560 	if (ret < SUCCESS) {
5783457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
5793457Sjc156560 		return (ret);
5803457Sjc156560 	}
5813457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
5823457Sjc156560 
5833457Sjc156560 	return (SUCCESS);
5843457Sjc156560 }
5853457Sjc156560 
5863457Sjc156560 int
raidcfg_close_controller(int handle,char ** plugin_err_str)5873457Sjc156560 raidcfg_close_controller(int handle, char **plugin_err_str)
5883457Sjc156560 {
5893457Sjc156560 	raid_obj_id_t obj_id;
5903457Sjc156560 	int ret;
5913457Sjc156560 
5923457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
5933457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
5943457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
5953457Sjc156560 	if (obj_id < OBJ_NONE) {
5963457Sjc156560 		raid_handle_delete(handle);
5973457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
5983457Sjc156560 		return (ERR_DEVICE_NOENT);
5993457Sjc156560 	}
6003457Sjc156560 
6013457Sjc156560 	ret = obj_controller_act(&raid_tab_sys, obj_id,
6024563Syw161884 	    ACT_CONTROLLER_CLOSE, NULL, plugin_err_str);
6033457Sjc156560 	if (ret < SUCCESS) {
6043457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
6053457Sjc156560 		return (ret);
6063457Sjc156560 	}
6073457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
6083457Sjc156560 
6093457Sjc156560 	return (SUCCESS);
6103457Sjc156560 }
6113457Sjc156560 
6123457Sjc156560 int
raidcfg_get_type(int handle)6133457Sjc156560 raidcfg_get_type(int handle)
6143457Sjc156560 {
6153457Sjc156560 	raid_obj_id_t obj_id;
6163457Sjc156560 	int ret_val;
6173457Sjc156560 
6183457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
6193457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
6203457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
6213457Sjc156560 	if (obj_id < OBJ_NONE) {
6223457Sjc156560 		raid_handle_delete(handle);
6233457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
6243457Sjc156560 		return (ERR_DEVICE_NOENT);
6253457Sjc156560 	}
6263457Sjc156560 	ret_val = raid_obj_get_type(&raid_tab_sys, obj_id);
6273457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
6283457Sjc156560 
6293457Sjc156560 	return (ret_val);
6303457Sjc156560 }
6313457Sjc156560 
6323457Sjc156560 int
raidcfg_get_attr(int handle,void * attr)6333457Sjc156560 raidcfg_get_attr(int handle, void *attr)
6343457Sjc156560 {
6353457Sjc156560 	raid_obj_id_t obj_id;
6363457Sjc156560 	raid_obj_type_id_t type;
6373457Sjc156560 	void *data;
6383457Sjc156560 	int ret, size;
6393457Sjc156560 
6403457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
6413457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
6423457Sjc156560 	if (attr == NULL) {
6433457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
6443457Sjc156560 		return (ERR_DEVICE_INVALID);
6453457Sjc156560 	}
6463457Sjc156560 
6473457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
6483457Sjc156560 	if (obj_id < OBJ_NONE) {
6493457Sjc156560 		raid_handle_delete(handle);
6503457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
6513457Sjc156560 		return (ERR_DEVICE_NOENT);
6523457Sjc156560 	}
6533457Sjc156560 
6543457Sjc156560 	type = raid_obj_get_type(&raid_tab_sys, obj_id);
6553457Sjc156560 	ret = obj_get_attr(&raid_tab_sys, obj_id, &data);
6563457Sjc156560 	if (ret < SUCCESS) {
6573457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
6583457Sjc156560 		return (ret);
6593457Sjc156560 	}
6603457Sjc156560 
6613457Sjc156560 	switch (type) {
6623457Sjc156560 	case	OBJ_TYPE_CONTROLLER:
6633457Sjc156560 		size = sizeof (controller_attr_t);
6643457Sjc156560 		break;
6653457Sjc156560 	case	OBJ_TYPE_ARRAY:
6663457Sjc156560 		size = sizeof (array_attr_t);
6673457Sjc156560 		break;
6683457Sjc156560 	case	OBJ_TYPE_HSP:
6693457Sjc156560 		{
6703457Sjc156560 			raidcfg_hsp_t *dst = attr;
6713457Sjc156560 			hsp_attr_t *src = data;
6723457Sjc156560 			controller_attr_t *ctlr_attr;
6733457Sjc156560 			array_attr_t *array_attr;
6743457Sjc156560 
6753457Sjc156560 			dst->associated_id = src->associated_id;
6763457Sjc156560 			dst->type = src->type;
6773457Sjc156560 
6783457Sjc156560 			obj_id = obj_get_controller(&raid_tab_sys, obj_id);
6793457Sjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
6804563Syw161884 			    (void **)(&ctlr_attr));
6813457Sjc156560 			if (ret < SUCCESS) {
6823457Sjc156560 				(void) mutex_unlock(&raidcfg_mp);
6833457Sjc156560 				return (ret);
6843457Sjc156560 			}
6853457Sjc156560 
6863457Sjc156560 			if (src->type == HSP_TYPE_LOCAL) {
6873457Sjc156560 				obj_id = obj_locate_array(&raid_tab_sys,
6884563Syw161884 				    ctlr_attr->controller_id,
6894563Syw161884 				    src->associated_id);
6903457Sjc156560 				ret = obj_get_attr(&raid_tab_sys, obj_id,
6914563Syw161884 				    (void **)(&array_attr));
6923457Sjc156560 				if (ret < SUCCESS) {
6933457Sjc156560 					(void) mutex_unlock(&raidcfg_mp);
6943457Sjc156560 					return (ret);
6953457Sjc156560 				}
6963457Sjc156560 
6973457Sjc156560 				dst->tag.idl.target_id =
6984563Syw161884 				    array_attr->tag.idl.target_id;
6993457Sjc156560 				dst->tag.idl.lun = array_attr->tag.idl.lun;
7003457Sjc156560 			}
7013457Sjc156560 		}
7023457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
7033457Sjc156560 		return (SUCCESS);
7043457Sjc156560 	case	OBJ_TYPE_DISK:
7053457Sjc156560 		size = sizeof (disk_attr_t);
7063457Sjc156560 		break;
7073457Sjc156560 	case	OBJ_TYPE_ARRAY_PART:
7083457Sjc156560 		{
7093457Sjc156560 			raidcfg_arraypart_t *dst = attr;
7103457Sjc156560 			arraypart_attr_t *src = data;
7113457Sjc156560 			controller_attr_t *ctlr_attr;
7123457Sjc156560 			disk_attr_t *disk_attr;
7133457Sjc156560 
7143457Sjc156560 			dst->disk_id = src->disk_id;
7153457Sjc156560 			dst->offset = src->offset;
7163457Sjc156560 			dst->size = src->size;
7173457Sjc156560 			dst->state = src->state;
7183457Sjc156560 
7193457Sjc156560 			obj_id = obj_get_controller(&raid_tab_sys, obj_id);
7203457Sjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
7214563Syw161884 			    (void **)(&ctlr_attr));
7223457Sjc156560 			if (ret < SUCCESS) {
7233457Sjc156560 				(void) mutex_unlock(&raidcfg_mp);
7243457Sjc156560 				return (ret);
7253457Sjc156560 			}
7263457Sjc156560 
7273457Sjc156560 			obj_id = obj_locate_disk(&raid_tab_sys,
7284563Syw161884 			    ctlr_attr->controller_id, src->disk_id);
7293457Sjc156560 			if (obj_id <= OBJ_NONE) {
7303457Sjc156560 				dst->tag.cidl.bus = (uint64_t)OBJ_ATTR_NONE;
7313457Sjc156560 				dst->tag.cidl.target_id =
7323457Sjc156560 				    (uint64_t)OBJ_ATTR_NONE;
7333457Sjc156560 				dst->tag.cidl.lun = (uint64_t)OBJ_ATTR_NONE;
7343457Sjc156560 				(void) mutex_unlock(&raidcfg_mp);
7353457Sjc156560 				return (SUCCESS);
7363457Sjc156560 			}
7373457Sjc156560 
7383457Sjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
7394563Syw161884 			    (void **)(&disk_attr));
7403457Sjc156560 			if (ret < SUCCESS) {
7413457Sjc156560 				(void) mutex_unlock(&raidcfg_mp);
7423457Sjc156560 				return (ret);
7433457Sjc156560 			}
7443457Sjc156560 
7453457Sjc156560 			dst->tag.cidl.bus = disk_attr->tag.cidl.bus;
7463457Sjc156560 			dst->tag.cidl.target_id = disk_attr->tag.cidl.target_id;
7473457Sjc156560 			dst->tag.cidl.lun = disk_attr->tag.cidl.lun;
7483457Sjc156560 		}
7493457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
7503457Sjc156560 		return (SUCCESS);
7513457Sjc156560 	case	OBJ_TYPE_DISK_SEG:
7523457Sjc156560 		size = sizeof (diskseg_attr_t);
7533457Sjc156560 		break;
7543457Sjc156560 	case	OBJ_TYPE_TASK:
7553457Sjc156560 		size = sizeof (task_attr_t);
7563457Sjc156560 		break;
7577233Syw161884 	case	OBJ_TYPE_PROP:
7587233Syw161884 		{
7597233Syw161884 			property_attr_t *src = data, *dst = attr;
7607233Syw161884 
7617233Syw161884 			dst->prop_id = src->prop_id;
7627233Syw161884 			dst->prop_type = src->prop_type;
7637233Syw161884 			if (dst->prop_size == 0) {
7647233Syw161884 				dst->prop_size = src->prop_size;
7657233Syw161884 				(void) mutex_unlock(&raidcfg_mp);
7667233Syw161884 				return (SUCCESS);
7677233Syw161884 			}
7687233Syw161884 
7697233Syw161884 			if (dst->prop_size < src->prop_size)
7707233Syw161884 				size = dst->prop_size;
7717233Syw161884 			else
7727233Syw161884 				size = src->prop_size;
7737233Syw161884 
7747233Syw161884 			(void) memcpy(dst->prop, src->prop, size);
7757233Syw161884 			(void) mutex_unlock(&raidcfg_mp);
7767233Syw161884 			return (SUCCESS);
7777233Syw161884 		}
7787233Syw161884 		break;
7793457Sjc156560 	default:
7803457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
7813457Sjc156560 		return (ERR_DEVICE_TYPE);
7823457Sjc156560 	}
7833457Sjc156560 
7843457Sjc156560 	(void) memcpy(attr, data, size);
7853457Sjc156560 
7863457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
7873457Sjc156560 	return (ret);
7883457Sjc156560 }
7893457Sjc156560 
7903457Sjc156560 int
raidcfg_get_container(int handle)7913457Sjc156560 raidcfg_get_container(int handle)
7923457Sjc156560 {
7933457Sjc156560 	raid_obj_id_t obj_id;
7943457Sjc156560 	int ret_val;
7953457Sjc156560 
7963457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
7973457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
7983457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
7993457Sjc156560 	if (obj_id < OBJ_NONE) {
8003457Sjc156560 		raid_handle_delete(handle);
8013457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
8023457Sjc156560 		return (ERR_DEVICE_NOENT);
8033457Sjc156560 	}
8043457Sjc156560 
8053457Sjc156560 	obj_id = raid_obj_get_container(&raid_tab_sys, obj_id);
8063457Sjc156560 	if (obj_id < OBJ_NONE) {
8073457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
8083457Sjc156560 		return (obj_id);
8093457Sjc156560 	}
8103457Sjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
8113457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
8123457Sjc156560 
8133457Sjc156560 	return (ret_val);
8143457Sjc156560 }
8153457Sjc156560 
8163457Sjc156560 int
raidcfg_list_head(int handle,raid_obj_type_id_t type)8173457Sjc156560 raidcfg_list_head(int handle, raid_obj_type_id_t type)
8183457Sjc156560 {
8193457Sjc156560 	raid_obj_id_t obj_id;
8203457Sjc156560 	int ret_val;
8213457Sjc156560 
8223457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
8233457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
8243457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
8253457Sjc156560 	if (obj_id < OBJ_NONE) {
8263457Sjc156560 		raid_handle_delete(handle);
8273457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
8283457Sjc156560 		return (ERR_DEVICE_NOENT);
8293457Sjc156560 	}
8303457Sjc156560 
8313457Sjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, type);
8323457Sjc156560 	if (obj_id < OBJ_NONE) {
8333457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
8343457Sjc156560 		return (obj_id);
8353457Sjc156560 	}
8363457Sjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
8373457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
8383457Sjc156560 
8393457Sjc156560 	return (ret_val);
8403457Sjc156560 }
8413457Sjc156560 
8423457Sjc156560 int
raidcfg_list_next(int handle)8433457Sjc156560 raidcfg_list_next(int handle)
8443457Sjc156560 {
8453457Sjc156560 	raid_obj_id_t obj_id;
8463457Sjc156560 	int ret_val;
8473457Sjc156560 
8483457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
8493457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
8503457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
8513457Sjc156560 	if (obj_id < OBJ_NONE) {
8523457Sjc156560 		raid_handle_delete(handle);
8533457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
8543457Sjc156560 		return (ERR_DEVICE_NOENT);
8553457Sjc156560 	}
8563457Sjc156560 
8573457Sjc156560 	obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
8583457Sjc156560 	if (obj_id < OBJ_NONE) {
8593457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
8603457Sjc156560 		return (obj_id);
8613457Sjc156560 	}
8623457Sjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
8633457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
8643457Sjc156560 
8653457Sjc156560 	return (ret_val);
8663457Sjc156560 }
8673457Sjc156560 
8683457Sjc156560 int
raidcfg_set_attr(int handle,uint32_t set_cmd,void * value,char ** plugin_err_str)8693457Sjc156560 raidcfg_set_attr(int handle, uint32_t set_cmd, void *value,
8703457Sjc156560 	char **plugin_err_str)
8713457Sjc156560 {
8723457Sjc156560 	raid_obj_id_t obj_id;
8733457Sjc156560 	raid_obj_type_id_t type;
8743457Sjc156560 	int ret;
8753457Sjc156560 
8763457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
8773457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
8783457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
8793457Sjc156560 	if (obj_id < OBJ_NONE) {
8803457Sjc156560 		raid_handle_delete(handle);
8813457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
8823457Sjc156560 		return (ERR_DEVICE_NOENT);
8833457Sjc156560 	}
8843457Sjc156560 
8853457Sjc156560 	type = raid_obj_get_type(&raid_tab_sys, obj_id);
8863457Sjc156560 	if (raid_obj_op_sys[type].set_attr == NULL) {
8873457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
8883457Sjc156560 		return (ERR_OP_NO_IMPL);
8893457Sjc156560 	}
8903457Sjc156560 
8913457Sjc156560 	ret = raid_obj_op_sys[type].set_attr(&raid_tab_sys,
8924563Syw161884 	    obj_id, set_cmd, value, plugin_err_str);
8933457Sjc156560 
8943457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
8953457Sjc156560 	return (ret);
8963457Sjc156560 }
8973457Sjc156560 
8983457Sjc156560 int
raidcfg_update_fw(int handle,char * file,char ** plugin_err_str)8993457Sjc156560 raidcfg_update_fw(int handle, char *file, char **plugin_err_str)
9003457Sjc156560 {
9013457Sjc156560 	raid_obj_id_t obj_id;
9023457Sjc156560 	int ret;
9033457Sjc156560 
9043457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
9053457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
9063457Sjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
9073457Sjc156560 	if (obj_id < OBJ_NONE) {
9083457Sjc156560 		raid_handle_delete(handle);
9093457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
9103457Sjc156560 		return (ERR_DEVICE_NOENT);
9113457Sjc156560 	}
9123457Sjc156560 
9133457Sjc156560 	if (raid_obj_get_type(&raid_tab_sys, obj_id) != OBJ_TYPE_CONTROLLER) {
9143457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
9153457Sjc156560 		return (ERR_OP_NO_IMPL);
9163457Sjc156560 	}
9173457Sjc156560 
9183457Sjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_CONTROLLER].act(&raid_tab_sys,
9194563Syw161884 	    obj_id, ACT_CONTROLLER_FLASH_FW, file, plugin_err_str);
9203457Sjc156560 
9213457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
9223457Sjc156560 	return (ret);
9233457Sjc156560 }
9243457Sjc156560 
9253457Sjc156560 int
raidcfg_create_array(int num_of_comps,int * disk_handles,uint32_t raid_level,uint64_t size,uint32_t stripe_size,char ** plugin_err_str)9263457Sjc156560 raidcfg_create_array(int num_of_comps, int *disk_handles,
9273457Sjc156560 	uint32_t raid_level, uint64_t size, uint32_t stripe_size,
9283457Sjc156560 	char **plugin_err_str)
9293457Sjc156560 {
9303457Sjc156560 	raid_obj_id_t *disk_obj_ids, obj_id;
9313457Sjc156560 	array_attr_t *array_attr;
9323457Sjc156560 	raid_obj_handle_t array_handle;
9333457Sjc156560 	int i, ret;
9343457Sjc156560 
9353457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
9363457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
9373457Sjc156560 
9383457Sjc156560 	disk_obj_ids = calloc(num_of_comps, sizeof (raid_obj_id_t));
9393457Sjc156560 	if (disk_obj_ids == NULL) {
9403457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
9413457Sjc156560 		return (ERR_NOMEM);
9423457Sjc156560 	}
9433457Sjc156560 
9443457Sjc156560 	/* convert disk handles into disk object ids; */
9453457Sjc156560 	for (i = 0; i < num_of_comps; ++i) {
9463457Sjc156560 		if (*(disk_handles + i) == OBJ_SEPARATOR_BEGIN ||
9474563Syw161884 		    *(disk_handles + i) == OBJ_SEPARATOR_END) {
9483457Sjc156560 			*(disk_obj_ids + i) = *(disk_handles + i);
9493457Sjc156560 			continue;
9503457Sjc156560 		}
9513457Sjc156560 
9523457Sjc156560 		*(disk_obj_ids + i) = raid_handle_to_obj(&raid_tab_sys,
9534563Syw161884 		    *(disk_handles + i));
9543457Sjc156560 		if (raid_obj_get_type(&raid_tab_sys, *(disk_obj_ids + i)) !=
9554563Syw161884 		    OBJ_TYPE_DISK) {
9563457Sjc156560 			free(disk_obj_ids);
9573457Sjc156560 			(void) obj_rescan(&raid_tab_sys);
9583457Sjc156560 			(void) mutex_unlock(&raidcfg_mp);
9593457Sjc156560 			return (ERR_DEVICE_TYPE);
9603457Sjc156560 		}
9613457Sjc156560 	}
9623457Sjc156560 
9633457Sjc156560 	/* Create an empty array object */
9643457Sjc156560 	obj_id = raid_obj_create(&raid_tab_sys, OBJ_TYPE_ARRAY);
9653457Sjc156560 	if (obj_id < OBJ_NONE) {
9663457Sjc156560 		free(disk_obj_ids);
9673457Sjc156560 		(void) obj_rescan(&raid_tab_sys);
9683457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
9693457Sjc156560 		return (obj_id);
9703457Sjc156560 	}
9713457Sjc156560 	(void) raid_obj_clear_status(&raid_tab_sys, obj_id,
9724563Syw161884 	    OBJ_STATUS_CMD_CLEAN);
9733457Sjc156560 
9743457Sjc156560 	array_attr = raid_obj_get_data_ptr(&raid_tab_sys, obj_id);
9753457Sjc156560 	array_attr->array_id = (uint32_t)OBJ_ATTR_NONE;
9763457Sjc156560 	array_attr->raid_level = raid_level;
9773457Sjc156560 	array_attr->capacity = size;
9783457Sjc156560 	array_attr->stripe_size = stripe_size;
9793457Sjc156560 	array_attr->write_policy = CACHE_WR_ON;
9803457Sjc156560 	array_attr->read_policy = CACHE_RD_ON;
9813457Sjc156560 
9823457Sjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].create_obj(&raid_tab_sys, obj_id,
9834563Syw161884 	    num_of_comps, disk_obj_ids, plugin_err_str);
9843457Sjc156560 	free(disk_obj_ids);
9853457Sjc156560 
9863457Sjc156560 	if (ret < SUCCESS) {
9873457Sjc156560 		(void) obj_rescan(&raid_tab_sys);
9883457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
9893457Sjc156560 		return (ret);
9903457Sjc156560 	}
9913457Sjc156560 
9923457Sjc156560 	/* create_obj() method should put the array object in the device tree */
9933457Sjc156560 	array_handle = raid_obj_to_handle(&raid_tab_sys, obj_id);
9943457Sjc156560 
9953457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
9963457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
9973457Sjc156560 	return (array_handle);
9983457Sjc156560 }
9993457Sjc156560 
10003457Sjc156560 int
raidcfg_delete_array(int array_handle,char ** plugin_err_str)10013457Sjc156560 raidcfg_delete_array(int array_handle, char **plugin_err_str)
10023457Sjc156560 {
10033457Sjc156560 	raid_obj_id_t array_obj_id;
10043457Sjc156560 	int ret;
10053457Sjc156560 
10063457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
10073457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
10083457Sjc156560 
10093457Sjc156560 	if (raidcfg_get_type(array_handle) != OBJ_TYPE_ARRAY) {
10103457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
10113457Sjc156560 		return (ERR_DEVICE_TYPE);
10123457Sjc156560 	}
10133457Sjc156560 
10143457Sjc156560 	array_obj_id = raid_handle_to_obj(&raid_tab_sys, array_handle);
10153457Sjc156560 	if (array_obj_id < OBJ_NONE) {
10163457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
10173457Sjc156560 		return (array_obj_id);
10183457Sjc156560 	}
10193457Sjc156560 	if (array_obj_id == OBJ_NONE) {
10203457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
10213457Sjc156560 		return (ERR_DEVICE_INVALID);
10223457Sjc156560 	}
10233457Sjc156560 
10243457Sjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].delete_obj(&raid_tab_sys,
10254563Syw161884 	    array_obj_id, plugin_err_str);
10263457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
10273457Sjc156560 
10283457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
10293457Sjc156560 	return (ret);
10303457Sjc156560 }
10313457Sjc156560 
10323457Sjc156560 int
raidcfg_set_hsp(raidcfg_hsp_relation_t * hsp_relations,char ** plugin_err_str)10338263SRyan.Wang@Sun.COM raidcfg_set_hsp(raidcfg_hsp_relation_t *hsp_relations,
10343457Sjc156560 	char **plugin_err_str)
10353457Sjc156560 {
10363457Sjc156560 	raid_obj_id_t disk_obj_id, array_obj_id;
10373457Sjc156560 	raid_obj_id_t *hsp_relation_objs;
10388263SRyan.Wang@Sun.COM 	int ret;
10393457Sjc156560 
10403457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
10413457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
10428263SRyan.Wang@Sun.COM 	if (hsp_relations == NULL) {
10433457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
10443457Sjc156560 		return (ERR_OP_ILLEGAL);
10453457Sjc156560 	}
10463457Sjc156560 
10478263SRyan.Wang@Sun.COM 	hsp_relation_objs = malloc(2 * sizeof (raid_obj_id_t));
10483457Sjc156560 	if (hsp_relation_objs == NULL) {
10493457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
10503457Sjc156560 		return (ERR_NOMEM);
10513457Sjc156560 	}
10523457Sjc156560 
10533457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
10543457Sjc156560 
10558263SRyan.Wang@Sun.COM 	if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
10568263SRyan.Wang@Sun.COM 		array_obj_id = raid_handle_to_obj(&raid_tab_sys,
10578263SRyan.Wang@Sun.COM 		    hsp_relations->array_handle);
10588263SRyan.Wang@Sun.COM 		if (array_obj_id < OBJ_NONE) {
10593457Sjc156560 			free(hsp_relation_objs);
10603457Sjc156560 			(void) mutex_unlock(&raidcfg_mp);
10618263SRyan.Wang@Sun.COM 			return (array_obj_id);
10623457Sjc156560 		}
10638263SRyan.Wang@Sun.COM 		if (array_obj_id == OBJ_NONE) {
10648263SRyan.Wang@Sun.COM 			(void) free(hsp_relation_objs);
10653457Sjc156560 			(void) mutex_unlock(&raidcfg_mp);
10663457Sjc156560 			return (ERR_DEVICE_NOENT);
10673457Sjc156560 		}
10688263SRyan.Wang@Sun.COM 		if (raidcfg_get_type(hsp_relations->array_handle) !=
10698263SRyan.Wang@Sun.COM 		    OBJ_TYPE_ARRAY) {
10703457Sjc156560 			free(hsp_relation_objs);
10713457Sjc156560 			(void) mutex_unlock(&raidcfg_mp);
10723457Sjc156560 			return (ERR_DEVICE_TYPE);
10733457Sjc156560 		}
10748263SRyan.Wang@Sun.COM 	} else
10758263SRyan.Wang@Sun.COM 		array_obj_id = OBJ_ATTR_NONE;
10768263SRyan.Wang@Sun.COM 
10778263SRyan.Wang@Sun.COM 	disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
10788263SRyan.Wang@Sun.COM 	    hsp_relations->disk_handle);
10798263SRyan.Wang@Sun.COM 	if (disk_obj_id < OBJ_NONE) {
10808263SRyan.Wang@Sun.COM 		free(hsp_relation_objs);
10818263SRyan.Wang@Sun.COM 		(void) mutex_unlock(&raidcfg_mp);
10828263SRyan.Wang@Sun.COM 		return (disk_obj_id);
10833457Sjc156560 	}
10848263SRyan.Wang@Sun.COM 	if (disk_obj_id == OBJ_NONE) {
10858263SRyan.Wang@Sun.COM 		free(hsp_relation_objs);
10868263SRyan.Wang@Sun.COM 		(void) mutex_unlock(&raidcfg_mp);
10878263SRyan.Wang@Sun.COM 		return (ERR_DEVICE_NOENT);
10888263SRyan.Wang@Sun.COM 	}
10898263SRyan.Wang@Sun.COM 	if (raidcfg_get_type(hsp_relations->disk_handle) !=
10908263SRyan.Wang@Sun.COM 	    OBJ_TYPE_DISK) {
10918263SRyan.Wang@Sun.COM 		free(hsp_relation_objs);
10928263SRyan.Wang@Sun.COM 		(void) mutex_unlock(&raidcfg_mp);
10938263SRyan.Wang@Sun.COM 		return (ERR_DEVICE_TYPE);
10948263SRyan.Wang@Sun.COM 	}
10958263SRyan.Wang@Sun.COM 
10968263SRyan.Wang@Sun.COM 	hsp_relation_objs[0] = array_obj_id;
10978263SRyan.Wang@Sun.COM 	hsp_relation_objs[1] = disk_obj_id;
10988263SRyan.Wang@Sun.COM 
10998263SRyan.Wang@Sun.COM 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].bind_obj(&raid_tab_sys,
11004563Syw161884 	    hsp_relation_objs, plugin_err_str);
11013457Sjc156560 
11023457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
11033457Sjc156560 	free(hsp_relation_objs);
11043457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
11053457Sjc156560 
11063457Sjc156560 	return (ret);
11073457Sjc156560 }
11083457Sjc156560 
11093457Sjc156560 int
raidcfg_unset_hsp(raidcfg_hsp_relation_t * hsp_relations,char ** plugin_err_str)11108263SRyan.Wang@Sun.COM raidcfg_unset_hsp(raidcfg_hsp_relation_t *hsp_relations,
11113457Sjc156560 	char **plugin_err_str)
11123457Sjc156560 {
11133457Sjc156560 	raid_obj_id_t disk_obj_id, array_obj_id;
11143457Sjc156560 	raid_obj_id_t *hsp_relation_objs;
11158263SRyan.Wang@Sun.COM 	int ret;
11163457Sjc156560 
11173457Sjc156560 	(void) mutex_lock(&raidcfg_mp);
11183457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
11198263SRyan.Wang@Sun.COM 	if (hsp_relations == NULL) {
11203457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
11213457Sjc156560 		return (ERR_OP_ILLEGAL);
11223457Sjc156560 	}
11233457Sjc156560 
11248263SRyan.Wang@Sun.COM 	hsp_relation_objs = malloc(2 * sizeof (raid_obj_id_t));
11253457Sjc156560 	if (hsp_relation_objs == NULL) {
11263457Sjc156560 		(void) mutex_unlock(&raidcfg_mp);
11273457Sjc156560 		return (ERR_NOMEM);
11283457Sjc156560 	}
11293457Sjc156560 
11303457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
11313457Sjc156560 
11328263SRyan.Wang@Sun.COM 	if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
11338263SRyan.Wang@Sun.COM 		array_obj_id = raid_handle_to_obj(&raid_tab_sys,
11348263SRyan.Wang@Sun.COM 		    hsp_relations->array_handle);
11358263SRyan.Wang@Sun.COM 		if (array_obj_id < OBJ_NONE) {
11363457Sjc156560 			free(hsp_relation_objs);
11373457Sjc156560 			(void) mutex_unlock(&raidcfg_mp);
11388263SRyan.Wang@Sun.COM 			return (array_obj_id);
11393457Sjc156560 		}
11408263SRyan.Wang@Sun.COM 		if (array_obj_id == OBJ_NONE) {
11413457Sjc156560 			free(hsp_relation_objs);
11423457Sjc156560 			(void) mutex_unlock(&raidcfg_mp);
11433457Sjc156560 			return (ERR_DEVICE_NOENT);
11443457Sjc156560 		}
11458263SRyan.Wang@Sun.COM 		if (raidcfg_get_type(hsp_relations->array_handle) !=
11468263SRyan.Wang@Sun.COM 		    OBJ_TYPE_ARRAY) {
11473457Sjc156560 			free(hsp_relation_objs);
11483457Sjc156560 			(void) mutex_unlock(&raidcfg_mp);
11493457Sjc156560 			return (ERR_DEVICE_TYPE);
11503457Sjc156560 		}
11518263SRyan.Wang@Sun.COM 	} else
11528263SRyan.Wang@Sun.COM 		array_obj_id = OBJ_ATTR_NONE;
11538263SRyan.Wang@Sun.COM 
11548263SRyan.Wang@Sun.COM 	disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
11558263SRyan.Wang@Sun.COM 	    hsp_relations->disk_handle);
11568263SRyan.Wang@Sun.COM 	if (disk_obj_id < OBJ_NONE) {
11578263SRyan.Wang@Sun.COM 		free(hsp_relation_objs);
11588263SRyan.Wang@Sun.COM 		(void) mutex_unlock(&raidcfg_mp);
11598263SRyan.Wang@Sun.COM 		return (disk_obj_id);
11603457Sjc156560 	}
11618263SRyan.Wang@Sun.COM 	if (disk_obj_id == OBJ_NONE) {
11628263SRyan.Wang@Sun.COM 		free(hsp_relation_objs);
11638263SRyan.Wang@Sun.COM 		(void) mutex_unlock(&raidcfg_mp);
11648263SRyan.Wang@Sun.COM 		return (ERR_DEVICE_NOENT);
11658263SRyan.Wang@Sun.COM 	}
11668263SRyan.Wang@Sun.COM 	if (raidcfg_get_type(hsp_relations->disk_handle) !=
11678263SRyan.Wang@Sun.COM 	    OBJ_TYPE_DISK) {
11688263SRyan.Wang@Sun.COM 		free(hsp_relation_objs);
11698263SRyan.Wang@Sun.COM 		(void) mutex_unlock(&raidcfg_mp);
11708263SRyan.Wang@Sun.COM 		return (ERR_DEVICE_TYPE);
11718263SRyan.Wang@Sun.COM 	}
11728263SRyan.Wang@Sun.COM 
11738263SRyan.Wang@Sun.COM 	hsp_relation_objs[0] = array_obj_id;
11748263SRyan.Wang@Sun.COM 	hsp_relation_objs[1] = disk_obj_id;
11753457Sjc156560 
11763457Sjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].unbind_obj(&raid_tab_sys,
11778263SRyan.Wang@Sun.COM 	    hsp_relation_objs, plugin_err_str);
11783457Sjc156560 
11793457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
11803457Sjc156560 	free(hsp_relation_objs);
11813457Sjc156560 	(void) mutex_unlock(&raidcfg_mp);
11823457Sjc156560 
11833457Sjc156560 	return (ret);
11843457Sjc156560 }
11853457Sjc156560 
11863457Sjc156560 /*
11873457Sjc156560  * RaidCfg lib routines
11883457Sjc156560  */
11893457Sjc156560 void
raidcfg_init(void)11903457Sjc156560 raidcfg_init(void)
11913457Sjc156560 {
11923457Sjc156560 	(void) mutex_init(&raidcfg_mp, NULL, NULL);
11933457Sjc156560 	raid_plugin_init();
11943457Sjc156560 	(void) raid_handle_init();
11953457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
11963457Sjc156560 }
11973457Sjc156560 
11983457Sjc156560 void
raidcfg_fini(void)11993457Sjc156560 raidcfg_fini(void)
12003457Sjc156560 {
12013457Sjc156560 	/*
12023457Sjc156560 	 * Need to close all opened controllers before destroying object table
12033457Sjc156560 	 */
12043457Sjc156560 	(void) obj_rescan(&raid_tab_sys);
12053457Sjc156560 	raid_handle_fini();
12063457Sjc156560 	raid_obj_tab_destroy(&raid_tab_sys);
12073457Sjc156560 	raid_plugin_init();
12083457Sjc156560 	(void) mutex_destroy(&raidcfg_mp);
12093457Sjc156560 }
12103457Sjc156560 
12113457Sjc156560 /*
12123457Sjc156560  * Support routines
12133457Sjc156560  */
12143457Sjc156560 static int
intcompare(const void * p1,const void * p2)12153457Sjc156560 intcompare(const void *p1, const void *p2)
12163457Sjc156560 {
12173457Sjc156560 	int i, j;
12183457Sjc156560 	i = *((int *)p1);
12193457Sjc156560 	j = *((int *)p2);
12203457Sjc156560 	return (i - j);
12213457Sjc156560 }
12223457Sjc156560 
12233457Sjc156560 static uint64_t
raid_space_noalign(raid_obj_tab_t * raid_tab,uint32_t raid_level,int num,raid_obj_id_t * disk_objs,arraypart_attr_t * arraypart_attrs)12243457Sjc156560 raid_space_noalign(raid_obj_tab_t *raid_tab, uint32_t raid_level, int num,
12253457Sjc156560 	raid_obj_id_t *disk_objs, arraypart_attr_t *arraypart_attrs)
12263457Sjc156560 {
12273457Sjc156560 	disk_attr_t *disk_attr;
12283457Sjc156560 	diskseg_attr_t *diskseg_attr;
12293457Sjc156560 	raid_obj_id_t obj_id;
12303457Sjc156560 	uint64_t offset, capacity;
12313457Sjc156560 	int i, disk_num, sub_array_num, disk_layer;
12323457Sjc156560 
12333457Sjc156560 	/* Find out the maximum available space for all disks */
12343457Sjc156560 	for (i = 0; i < num; ++i) {
12353457Sjc156560 		if ((disk_objs[i] == OBJ_SEPARATOR_BEGIN) ||
12364563Syw161884 		    (disk_objs[i] == OBJ_SEPARATOR_END))
12373457Sjc156560 			continue;
12383457Sjc156560 
12393457Sjc156560 		(void) obj_get_attr(raid_tab, disk_objs[i],
12404563Syw161884 		    (void **)(&disk_attr));
12413457Sjc156560 		obj_id = obj_get_comp(raid_tab, disk_objs[i],
12424563Syw161884 		    OBJ_TYPE_DISK_SEG);
12433457Sjc156560 		if (obj_id == OBJ_NONE) {
12443457Sjc156560 			arraypart_attrs[i].offset = 0;
12453457Sjc156560 			arraypart_attrs[i].size = disk_attr->capacity;
12463457Sjc156560 			continue;
12473457Sjc156560 		}
12483457Sjc156560 
12493457Sjc156560 		(void) obj_get_attr(raid_tab, obj_id, (void **)
12504563Syw161884 		    (&diskseg_attr));
12513457Sjc156560 		arraypart_attrs[i].offset = 0;
12523457Sjc156560 		arraypart_attrs[i].size = diskseg_attr->offset;
12533457Sjc156560 		offset = diskseg_attr->offset + diskseg_attr->size;
12543457Sjc156560 
12553457Sjc156560 		while ((obj_id = obj_get_sibling(raid_tab, obj_id)) !=
12563457Sjc156560 		    OBJ_NONE) {
12573457Sjc156560 			(void) obj_get_attr(raid_tab, obj_id,
12584563Syw161884 			    (void **)(&diskseg_attr));
12593457Sjc156560 			if ((diskseg_attr->offset - offset) >
12604563Syw161884 			    arraypart_attrs[i].size) {
12613457Sjc156560 				arraypart_attrs[i].offset = offset;
12624563Syw161884 				arraypart_attrs[i].size = diskseg_attr->offset -
12634563Syw161884 				    offset;
12643457Sjc156560 			}
12653457Sjc156560 
12663457Sjc156560 			offset = diskseg_attr->offset + diskseg_attr->size;
12673457Sjc156560 		}
12683457Sjc156560 
12693457Sjc156560 		if ((disk_attr->capacity - offset) > arraypart_attrs[i].size) {
12703457Sjc156560 			arraypart_attrs[i].offset = offset;
12714563Syw161884 			arraypart_attrs[i].size = disk_attr->capacity -
12724563Syw161884 			    offset;
12733457Sjc156560 		}
12743457Sjc156560 	}
12753457Sjc156560 
12763457Sjc156560 	capacity = OBJ_ATTR_NONE;
12773457Sjc156560 	disk_num = 0;
12783457Sjc156560 	disk_layer = 0;
12793457Sjc156560 	sub_array_num = 0;
12803457Sjc156560 	for (i = 0; i < num; ++i) {
12813457Sjc156560 		if (disk_objs[i] == OBJ_SEPARATOR_BEGIN) {
12823457Sjc156560 			++ disk_layer;
12833457Sjc156560 			continue;
12843457Sjc156560 		}
12853457Sjc156560 		if (disk_objs[i] == OBJ_SEPARATOR_END) {
12863457Sjc156560 			-- disk_layer;
12873457Sjc156560 			if (disk_layer != 0)
12883457Sjc156560 				++ sub_array_num;
12893457Sjc156560 			continue;
12903457Sjc156560 		}
12913457Sjc156560 
12923457Sjc156560 		if (capacity > arraypart_attrs[i].size)
12933457Sjc156560 			capacity = arraypart_attrs[i].size;
12943457Sjc156560 		++disk_num;
12953457Sjc156560 	}
12963457Sjc156560 
12973457Sjc156560 	switch (raid_level) {
12983457Sjc156560 	case	RAID_LEVEL_0:
12993457Sjc156560 		capacity = capacity * disk_num;
13003457Sjc156560 		break;
13013457Sjc156560 	case	RAID_LEVEL_1:
13023457Sjc156560 		capacity = capacity * disk_num / 2;
13033457Sjc156560 		break;
13043457Sjc156560 	case	RAID_LEVEL_1E:
13053457Sjc156560 		capacity = capacity * disk_num / 2;
13063457Sjc156560 		break;
13073457Sjc156560 	case	RAID_LEVEL_5:
13083457Sjc156560 		capacity = capacity * (disk_num - 1);
13093457Sjc156560 		break;
13103457Sjc156560 	case	RAID_LEVEL_10:
13113457Sjc156560 		capacity = capacity * disk_num / 2;
13123457Sjc156560 		break;
13133457Sjc156560 	case	RAID_LEVEL_50:
13143457Sjc156560 		capacity = capacity * (disk_num - sub_array_num);
13153457Sjc156560 		break;
13163457Sjc156560 	default:
13173457Sjc156560 		return (ERR_ARRAY_LEVEL);
13183457Sjc156560 		break;
13193457Sjc156560 	}
13203457Sjc156560 
13213457Sjc156560 	return (capacity);
13223457Sjc156560 }
13233457Sjc156560 
13243457Sjc156560 /*
13253457Sjc156560  * Raid handle maintenance routines
13263457Sjc156560  */
13273457Sjc156560 static int
raid_handle_init()13283457Sjc156560 raid_handle_init()
13293457Sjc156560 {
13303457Sjc156560 	int i;
13313457Sjc156560 	void *ptr;
13323457Sjc156560 
13333457Sjc156560 	raid_handle_sys.handle_num += HANDLER_SLOTS;
13343457Sjc156560 	ptr = realloc(raid_handle_sys.handles,
13354563Syw161884 	    raid_handle_sys.handle_num * sizeof (handle_attr_t));
13363457Sjc156560 	if (ptr == NULL)
13373457Sjc156560 		return (ERR_NOMEM);
13383457Sjc156560 	raid_handle_sys.handles = ptr;
13393457Sjc156560 
13403457Sjc156560 	/* Clean up the new allocated handles */
13413457Sjc156560 	for (i = raid_handle_sys.handle_num - HANDLER_SLOTS;
13424563Syw161884 	    i < raid_handle_sys.handle_num; ++i) {
13438405SZachary.Kissel@Sun.COM 		bzero(&raid_handle_sys.handles[i], sizeof (handle_attr_t));
13443457Sjc156560 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
13453457Sjc156560 		raid_handle_sys.handles[i].next = i + 1;
13463457Sjc156560 	}
13473457Sjc156560 
13483457Sjc156560 	/* For the first time of allocation, set up the system object handle */
13493457Sjc156560 	if (raid_handle_sys.handle_num == HANDLER_SLOTS) {
13503457Sjc156560 		raid_handle_sys.handles[0].type = OBJ_TYPE_SYSTEM;
13513457Sjc156560 		raid_handle_sys.handles[0].next = 0;
13523457Sjc156560 		raid_handle_sys.unused = 1;
13533457Sjc156560 		raid_handle_sys.used = 0;
13543457Sjc156560 	}
13553457Sjc156560 	return (SUCCESS);
13563457Sjc156560 }
13573457Sjc156560 
13583457Sjc156560 static void
raid_handle_fini()13593457Sjc156560 raid_handle_fini()
13603457Sjc156560 {
13613457Sjc156560 	raid_obj_handle_t i;
13623457Sjc156560 
13633457Sjc156560 	i = raid_handle_sys.used;
13643457Sjc156560 
13653457Sjc156560 	/* Close all opened controllers */
13663457Sjc156560 	while (i != 0) {
13673457Sjc156560 		if ((raid_handle_sys.handles[i].type == OBJ_TYPE_CONTROLLER) &&
13684563Syw161884 		    (raid_handle_sys.handles[i].fd != 0) &&
13694563Syw161884 		    (raid_handle_sys.handles[i].raid_lib != NULL))
13703457Sjc156560 			raid_handle_sys.handles[i].raid_lib->close_controller(
13714563Syw161884 			    raid_handle_sys.handles[i].controller_id, NULL);
13723457Sjc156560 		i = raid_handle_sys.handles[i].next;
13733457Sjc156560 	}
13743457Sjc156560 
13753457Sjc156560 	/* Clean up handle space */
13763457Sjc156560 	raid_handle_sys.handle_num = 0;
13773457Sjc156560 	raid_handle_sys.unused = 0;
13783457Sjc156560 	raid_handle_sys.used = 0;
13793457Sjc156560 	free(raid_handle_sys.handles);
13803457Sjc156560 	raid_handle_sys.handles = NULL;
13813457Sjc156560 }
13823457Sjc156560 
13833457Sjc156560 static raid_obj_handle_t
raid_handle_new(raid_obj_type_id_t type)13843457Sjc156560 raid_handle_new(raid_obj_type_id_t type)
13853457Sjc156560 {
13863457Sjc156560 	int ret;
13873457Sjc156560 
13883457Sjc156560 	if (raid_handle_sys.unused == raid_handle_sys.handle_num - 1) {
13893457Sjc156560 		ret = raid_handle_init();
13903457Sjc156560 		if (ret < SUCCESS)
13913457Sjc156560 			return (ret);
13923457Sjc156560 	}
13933457Sjc156560 
13943457Sjc156560 	ret = raid_handle_sys.unused;
13953457Sjc156560 	raid_handle_sys.unused = raid_handle_sys.handles[ret].next;
13963457Sjc156560 
13973457Sjc156560 	raid_handle_sys.handles[ret].next = raid_handle_sys.used;
13983457Sjc156560 	raid_handle_sys.used = ret;
13993457Sjc156560 	raid_handle_sys.handles[ret].type = type;
14003457Sjc156560 
14013457Sjc156560 	return (ret);
14023457Sjc156560 }
14033457Sjc156560 
14043457Sjc156560 static void
raid_handle_delete(raid_obj_handle_t handle)14053457Sjc156560 raid_handle_delete(raid_obj_handle_t handle)
14063457Sjc156560 {
14073457Sjc156560 	int i = raid_handle_sys.used, j = 0;
14083457Sjc156560 
14093457Sjc156560 	if (handle == 0)
14103457Sjc156560 		return;
14113457Sjc156560 
14123457Sjc156560 	while (i != 0 && i != handle) {
14133457Sjc156560 		j = i;
14143457Sjc156560 		i = raid_handle_sys.handles[i].next;
14153457Sjc156560 	}
14163457Sjc156560 
14173457Sjc156560 	if (i == handle) {
14183457Sjc156560 		if (j != 0)
14193457Sjc156560 			raid_handle_sys.handles[j].next =
14204563Syw161884 			    raid_handle_sys.handles[i].next;
14213457Sjc156560 		else
14223457Sjc156560 			raid_handle_sys.used =
14234563Syw161884 			    raid_handle_sys.handles[i].next;
14243457Sjc156560 
14253457Sjc156560 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
14263457Sjc156560 		raid_handle_sys.handles[i].next =
14274563Syw161884 		    raid_handle_sys.unused;
14283457Sjc156560 		raid_handle_sys.unused = i;
14293457Sjc156560 	}
14303457Sjc156560 }
14313457Sjc156560 
14323457Sjc156560 static void
raid_handle_delete_controller_comp(uint32_t controller_id)14333457Sjc156560 raid_handle_delete_controller_comp(uint32_t controller_id)
14343457Sjc156560 {
14353457Sjc156560 	int i = raid_handle_sys.used, j;
14363457Sjc156560 
14373457Sjc156560 	while (i != 0) {
14384563Syw161884 		j = i;
14394563Syw161884 		i = raid_handle_sys.handles[i].next;
14404563Syw161884 		if ((raid_handle_sys.handles[j].controller_id ==
14414563Syw161884 		    controller_id) &&
14424563Syw161884 		    (raid_handle_sys.handles[j].type !=
14434563Syw161884 		    OBJ_TYPE_CONTROLLER))
14443457Sjc156560 		raid_handle_delete(j);
14453457Sjc156560 	}
14463457Sjc156560 }
14473457Sjc156560 
14483457Sjc156560 static raid_obj_id_t
raid_handle_to_obj(raid_obj_tab_t * raid_tab,raid_obj_handle_t handle)14493457Sjc156560 raid_handle_to_obj(raid_obj_tab_t *raid_tab, raid_obj_handle_t handle)
14503457Sjc156560 {
14513457Sjc156560 	handle_attr_t *handle_attr;
14523457Sjc156560 	raid_obj_id_t obj_id;
14533457Sjc156560 
14543457Sjc156560 	if (handle == OBJ_SYSTEM)
14553457Sjc156560 		return (OBJ_SYSTEM);
14563457Sjc156560 
14573457Sjc156560 	handle_attr = raid_handle_sys.handles + handle;
14583457Sjc156560 
14593457Sjc156560 	switch (handle_attr->type) {
14603457Sjc156560 	case	OBJ_TYPE_SYSTEM:
14613457Sjc156560 		return (OBJ_SYSTEM);
14623457Sjc156560 	case	OBJ_TYPE_CONTROLLER:
14633457Sjc156560 		obj_id = obj_locate_controller(raid_tab,
14644563Syw161884 		    handle_attr->controller_id);
14653457Sjc156560 		break;
14663457Sjc156560 	case	OBJ_TYPE_ARRAY:
14673457Sjc156560 		obj_id = obj_locate_array(raid_tab,
14684563Syw161884 		    handle_attr->controller_id, handle_attr->array_id);
14693457Sjc156560 		break;
14703457Sjc156560 	case	OBJ_TYPE_HSP:
14713457Sjc156560 		obj_id = obj_locate_hsp(raid_tab,
14724563Syw161884 		    handle_attr->controller_id, handle_attr->disk_id,
14734563Syw161884 		    handle_attr->array_id);
14743457Sjc156560 		break;
14753457Sjc156560 	case	OBJ_TYPE_DISK:
14763457Sjc156560 		obj_id = obj_locate_disk(raid_tab,
14774563Syw161884 		    handle_attr->controller_id, handle_attr->disk_id);
14783457Sjc156560 		break;
14793457Sjc156560 	case	OBJ_TYPE_ARRAY_PART:
14803457Sjc156560 		obj_id = obj_locate_arraypart(raid_tab,
14814563Syw161884 		    handle_attr->controller_id, handle_attr->array_id,
14824563Syw161884 		    handle_attr->disk_id);
14833457Sjc156560 		break;
14843457Sjc156560 	case	OBJ_TYPE_DISK_SEG:
14853457Sjc156560 		obj_id = obj_locate_diskseg(raid_tab,
14864563Syw161884 		    handle_attr->controller_id,
14874563Syw161884 		    handle_attr->disk_id, handle_attr->seq_id);
14883457Sjc156560 		break;
14893457Sjc156560 	case	OBJ_TYPE_TASK:
14903457Sjc156560 		obj_id = obj_locate_task(raid_tab,
14914563Syw161884 		    handle_attr->controller_id, handle_attr->task_id);
14923457Sjc156560 		break;
14937233Syw161884 	case	OBJ_TYPE_PROP:
14947233Syw161884 		obj_id = obj_locate_prop(raid_tab,
14957233Syw161884 		    handle_attr->controller_id, handle_attr->disk_id,
14967233Syw161884 		    handle_attr->prop_id);
14977233Syw161884 		break;
14983457Sjc156560 	default:
14993457Sjc156560 		return (ERR_DEVICE_INVALID);
15003457Sjc156560 	}
15013457Sjc156560 
15023457Sjc156560 	if (obj_id < OBJ_NONE)
15033457Sjc156560 		return (obj_id);
15043457Sjc156560 	if (obj_id == OBJ_NONE)
15053457Sjc156560 		return (ERR_DEVICE_NOENT);
15063457Sjc156560 
15073457Sjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
15083457Sjc156560 	return (obj_id);
15093457Sjc156560 }
15103457Sjc156560 
15113457Sjc156560 static raid_obj_handle_t
raid_obj_to_handle(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)15123457Sjc156560 raid_obj_to_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
15133457Sjc156560 {
15143457Sjc156560 	raid_obj_id_t obj_id_backup = obj_id;
15153457Sjc156560 	raid_obj_type_id_t type;
15163457Sjc156560 	raid_obj_handle_t handle;
15173457Sjc156560 	controller_attr_t *controller_attr;
15183457Sjc156560 	array_attr_t *array_attr;
15193457Sjc156560 	hsp_attr_t *hsp_attr;
15203457Sjc156560 	disk_attr_t *disk_attr;
15213457Sjc156560 	arraypart_attr_t *arraypart_attr;
15223457Sjc156560 	diskseg_attr_t *diskseg_attr;
15233457Sjc156560 	task_attr_t *task_attr;
15247233Syw161884 	property_attr_t *prop_attr;
15253457Sjc156560 
15263457Sjc156560 	if (obj_id == OBJ_SYSTEM)
15273457Sjc156560 		return (OBJ_SYSTEM);
15283457Sjc156560 
15293457Sjc156560 	/* If the object mapped by a handle */
15303457Sjc156560 	handle = raid_obj_get_handle(raid_tab, obj_id);
15313457Sjc156560 	if (handle != 0)
15323457Sjc156560 		return (handle);
15333457Sjc156560 
15343457Sjc156560 	/* Search for existing handles */
15353457Sjc156560 	for (handle = raid_handle_sys.used; handle != 0;
15364563Syw161884 	    handle = raid_handle_sys.handles[handle].next)
15373457Sjc156560 		if (raid_handle_to_obj(raid_tab, handle) == obj_id)
15383457Sjc156560 			break;
15393457Sjc156560 
15403457Sjc156560 	if (handle != 0)
15413457Sjc156560 		return (handle);
15423457Sjc156560 
15433457Sjc156560 	/* Allocate new handle for this object */
15443457Sjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
15453457Sjc156560 	handle = raid_handle_new(type);
15463457Sjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
15473457Sjc156560 	raid_handle_sys.handles[handle].type = type;
15483457Sjc156560 
15493457Sjc156560 	switch (type) {
15503457Sjc156560 	case OBJ_TYPE_SYSTEM:
15513457Sjc156560 		break;
15523457Sjc156560 	case OBJ_TYPE_CONTROLLER:
15533457Sjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15543457Sjc156560 		raid_handle_sys.handles[handle].controller_id =
15554563Syw161884 		    controller_attr->controller_id;
15563457Sjc156560 		break;
15573457Sjc156560 	case OBJ_TYPE_ARRAY:
15583457Sjc156560 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15593457Sjc156560 		raid_handle_sys.handles[handle].array_id = array_attr->array_id;
15603457Sjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
15613457Sjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15623457Sjc156560 		raid_handle_sys.handles[handle].controller_id =
15634563Syw161884 		    controller_attr->controller_id;
15643457Sjc156560 		break;
15653457Sjc156560 	case OBJ_TYPE_HSP:
15663457Sjc156560 		hsp_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15673457Sjc156560 		raid_handle_sys.handles[handle].array_id =
15684563Syw161884 		    hsp_attr->associated_id;
15693457Sjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
15703457Sjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15713457Sjc156560 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
15723457Sjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
15733457Sjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15743457Sjc156560 		raid_handle_sys.handles[handle].controller_id =
15754563Syw161884 		    controller_attr->controller_id;
15763457Sjc156560 		break;
15773457Sjc156560 	case OBJ_TYPE_DISK:
15783457Sjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15793457Sjc156560 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
15803457Sjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
15813457Sjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15823457Sjc156560 		raid_handle_sys.handles[handle].controller_id =
15834563Syw161884 		    controller_attr->controller_id;
15843457Sjc156560 		break;
15853457Sjc156560 	case OBJ_TYPE_ARRAY_PART:
15863457Sjc156560 		arraypart_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15873457Sjc156560 		raid_handle_sys.handles[handle].disk_id =
15884563Syw161884 		    arraypart_attr->disk_id;
15893457Sjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
15903457Sjc156560 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15913457Sjc156560 		raid_handle_sys.handles[handle].array_id =
15924563Syw161884 		    array_attr->array_id;
15933457Sjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
15943457Sjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
15953457Sjc156560 		raid_handle_sys.handles[handle].controller_id =
15964563Syw161884 		    controller_attr->controller_id;
15973457Sjc156560 		break;
15983457Sjc156560 	case OBJ_TYPE_DISK_SEG:
15993457Sjc156560 		diskseg_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16003457Sjc156560 		raid_handle_sys.handles[handle].seq_id = diskseg_attr->seq_no;
16013457Sjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
16023457Sjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16033457Sjc156560 		raid_handle_sys.handles[handle].disk_id =
16044563Syw161884 		    disk_attr->disk_id;
16053457Sjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
16063457Sjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16073457Sjc156560 		raid_handle_sys.handles[handle].controller_id =
16084563Syw161884 		    controller_attr->controller_id;
16093457Sjc156560 		break;
16103457Sjc156560 	case OBJ_TYPE_TASK:
16113457Sjc156560 		task_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16123457Sjc156560 		raid_handle_sys.handles[handle].task_id = task_attr->task_id;
16133457Sjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
16143457Sjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16153457Sjc156560 		raid_handle_sys.handles[handle].controller_id =
16164563Syw161884 		    controller_attr->controller_id;
16173457Sjc156560 		break;
16187233Syw161884 	case OBJ_TYPE_PROP:
16197233Syw161884 		prop_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16207233Syw161884 		raid_handle_sys.handles[handle].prop_id =
16217233Syw161884 		    prop_attr->prop_id;
16227233Syw161884 		obj_id = raid_obj_get_container(raid_tab, obj_id);
16237233Syw161884 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16247233Syw161884 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
16257233Syw161884 		obj_id = obj_get_controller(raid_tab, obj_id);
16267233Syw161884 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16277233Syw161884 		raid_handle_sys.handles[handle].controller_id =
16287233Syw161884 		    controller_attr->controller_id;
16297233Syw161884 		break;
16303457Sjc156560 	default:
16313457Sjc156560 		return (ERR_DEVICE_INVALID);
16323457Sjc156560 	}
16333457Sjc156560 
16343457Sjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id_backup, handle);
16353457Sjc156560 	return (handle);
16363457Sjc156560 }
16373457Sjc156560 
16383457Sjc156560 static raid_lib_t *
raid_obj_get_lib(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)16393457Sjc156560 raid_obj_get_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
16403457Sjc156560 {
16413457Sjc156560 	raid_obj_handle_t handle;
16423457Sjc156560 	controller_attr_t *attr;
16433457Sjc156560 
16443457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
16453457Sjc156560 		return (NULL);
16463457Sjc156560 
16473457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16483457Sjc156560 	handle = raid_handle_sys.used;
16493457Sjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
16504563Syw161884 	    raid_handle_sys.handles[handle].controller_id !=
16514563Syw161884 	    attr->controller_id)
16523457Sjc156560 		handle = raid_handle_sys.handles[handle].next;
16533457Sjc156560 
16543457Sjc156560 	if (handle == 0)
16553457Sjc156560 		return (NULL);
16563457Sjc156560 
16573457Sjc156560 	return (raid_handle_sys.handles[handle].raid_lib);
16583457Sjc156560 }
16593457Sjc156560 
16603457Sjc156560 static int
raid_obj_set_lib(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_lib_t * raid_lib)16613457Sjc156560 raid_obj_set_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
16623457Sjc156560 	raid_lib_t *raid_lib)
16633457Sjc156560 {
16643457Sjc156560 	raid_obj_handle_t handle;
16653457Sjc156560 	controller_attr_t *attr;
16663457Sjc156560 
16673457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
16683457Sjc156560 		return (ERR_DEVICE_TYPE);
16693457Sjc156560 
16703457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16713457Sjc156560 	handle = raid_handle_sys.used;
16723457Sjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
16734563Syw161884 	    raid_handle_sys.handles[handle].controller_id !=
16744563Syw161884 	    attr->controller_id)
16753457Sjc156560 		handle = raid_handle_sys.handles[handle].next;
16763457Sjc156560 
16773457Sjc156560 	if (handle == 0)
16783457Sjc156560 		return (ERR_DEVICE_NOENT);
16793457Sjc156560 
16803457Sjc156560 	raid_handle_sys.handles[handle].raid_lib = raid_lib;
16813457Sjc156560 	return (SUCCESS);
16823457Sjc156560 }
16833457Sjc156560 
16843457Sjc156560 static int
raid_obj_get_fd(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)16853457Sjc156560 raid_obj_get_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
16863457Sjc156560 {
16873457Sjc156560 	raid_obj_handle_t handle;
16883457Sjc156560 	controller_attr_t *attr;
16893457Sjc156560 
16903457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
16913457Sjc156560 		return (ERR_DEVICE_TYPE);
16923457Sjc156560 
16933457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
16943457Sjc156560 	handle = raid_handle_sys.used;
16953457Sjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
16964563Syw161884 	    raid_handle_sys.handles[handle].controller_id !=
16974563Syw161884 	    attr->controller_id)
16983457Sjc156560 		handle = raid_handle_sys.handles[handle].next;
16993457Sjc156560 
17003457Sjc156560 	if (handle == 0)
17013457Sjc156560 		return (ERR_DEVICE_NOENT);
17023457Sjc156560 
17033457Sjc156560 	return (raid_handle_sys.handles[handle].fd);
17043457Sjc156560 }
17053457Sjc156560 
17063457Sjc156560 static int
raid_obj_set_fd(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int fd)17073457Sjc156560 raid_obj_set_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, int fd)
17083457Sjc156560 {
17093457Sjc156560 	raid_obj_handle_t handle;
17103457Sjc156560 	controller_attr_t *attr;
17113457Sjc156560 
17123457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
17133457Sjc156560 		return (ERR_DEVICE_TYPE);
17143457Sjc156560 
17153457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
17163457Sjc156560 	handle = raid_handle_sys.used;
17173457Sjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
17184563Syw161884 	    raid_handle_sys.handles[handle].controller_id !=
17194563Syw161884 	    attr->controller_id)
17203457Sjc156560 		handle = raid_handle_sys.handles[handle].next;
17213457Sjc156560 
17223457Sjc156560 	if (handle == 0)
17233457Sjc156560 		return (ERR_DEVICE_NOENT);
17243457Sjc156560 
17253457Sjc156560 	raid_handle_sys.handles[handle].fd = fd;
17263457Sjc156560 	return (SUCCESS);
17273457Sjc156560 }
17283457Sjc156560 
17293457Sjc156560 /*
17303457Sjc156560  * Raid object maintenance routines
17313457Sjc156560  */
17323457Sjc156560 static int
obj_scan_comp(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)17333457Sjc156560 obj_scan_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
17343457Sjc156560 {
17353457Sjc156560 	raid_obj_status_t status;
17363457Sjc156560 	raid_obj_type_id_t type;
17373457Sjc156560 	int ret, i, obj_type_cnt, comp_num;
17383457Sjc156560 	raid_obj_id_t *comp_list;
17393457Sjc156560 
17403457Sjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
17413457Sjc156560 	if (status < SUCCESS)
17423457Sjc156560 		return (status);
17433457Sjc156560 
17443457Sjc156560 	if (status & OBJ_STATUS_SCANCOMP)
17453457Sjc156560 		return (SUCCESS);
17463457Sjc156560 
17473457Sjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
1748*8855SMilan.Jurik@Sun.COM 	/* type less than OBJ_TYPE_SYSTEM means error */
1749*8855SMilan.Jurik@Sun.COM 	if (type < OBJ_TYPE_SYSTEM)
17503457Sjc156560 		return (ERR_DEVICE_INVALID);
17513457Sjc156560 
17523457Sjc156560 	for (obj_type_cnt = OBJ_SYSTEM; obj_type_cnt < OBJ_TYPE_ALL;
17534563Syw161884 	    ++obj_type_cnt) {
17543457Sjc156560 		if (raid_obj_op_sys[type].compnum != NULL)
17553457Sjc156560 			comp_num = raid_obj_op_sys[type].compnum(
17564563Syw161884 			    raid_tab, obj_id, obj_type_cnt);
17573457Sjc156560 		else
17583457Sjc156560 			comp_num = 0;
17593457Sjc156560 
17603457Sjc156560 		if (comp_num < SUCCESS)
17613457Sjc156560 			return (comp_num);
17623457Sjc156560 		if (comp_num == 0)
17633457Sjc156560 			continue;
17643457Sjc156560 
17653457Sjc156560 		comp_list = calloc(comp_num, sizeof (raid_obj_id_t));
17663457Sjc156560 		if (comp_list == NULL)
17673457Sjc156560 			return (ERR_NOMEM);
17683457Sjc156560 
17693457Sjc156560 		for (i = 0; i < comp_num; ++i) {
17703457Sjc156560 			*(comp_list + i) = raid_obj_create(raid_tab,
17714563Syw161884 			    obj_type_cnt);
17723457Sjc156560 			if (*(comp_list + i) < SUCCESS) {
17733457Sjc156560 				ret = *(comp_list + i);
17743457Sjc156560 				free(comp_list);
17753457Sjc156560 				return (ret);
17763457Sjc156560 			}
17773457Sjc156560 
17783457Sjc156560 			(void) raid_obj_clear_status(raid_tab,
17794563Syw161884 			    *(comp_list + i), OBJ_STATUS_CMD_CLEAN);
17803457Sjc156560 			(void) raid_obj_add_org(raid_tab, *(comp_list + i),
17814563Syw161884 			    obj_id);
17823457Sjc156560 		}
17833457Sjc156560 
17843457Sjc156560 		if (raid_obj_op_sys[type].complist != NULL)
17853457Sjc156560 			raid_obj_op_sys[type].complist(raid_tab,
17864563Syw161884 			    obj_id, comp_num, comp_list, obj_type_cnt);
17873457Sjc156560 		free(comp_list);
17883457Sjc156560 	}
17893457Sjc156560 
17903457Sjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_SCANCOMP);
17913457Sjc156560 	return (SUCCESS);
17923457Sjc156560 }
17933457Sjc156560 
17943457Sjc156560 static int
obj_rescan(raid_obj_tab_t * raid_tab)17953457Sjc156560 obj_rescan(raid_obj_tab_t *raid_tab)
17963457Sjc156560 {
17973457Sjc156560 	int ret;
17983457Sjc156560 
17993457Sjc156560 	raid_obj_tab_destroy(raid_tab);
18003457Sjc156560 
18013457Sjc156560 	if (raid_obj_tab_create(raid_tab, HASH_SLOTS) != SUCCESS)
18023457Sjc156560 		return (ERR_NOMEM);
18033457Sjc156560 
18043457Sjc156560 	if ((ret = raid_obj_create_system_obj(raid_tab)) != SUCCESS) {
18053457Sjc156560 		raid_obj_tab_destroy(raid_tab);
18063457Sjc156560 		return (ret);
18073457Sjc156560 	}
18083457Sjc156560 
18093457Sjc156560 	return (SUCCESS);
18103457Sjc156560 }
18113457Sjc156560 
18123457Sjc156560 static raid_obj_id_t
obj_get_comp(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t obj_type)18133457Sjc156560 obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
18143457Sjc156560 	raid_obj_type_id_t obj_type)
18153457Sjc156560 {
18163457Sjc156560 	raid_obj_id_t id;
18173457Sjc156560 	raid_obj_type_id_t type;
18183457Sjc156560 	raid_obj_status_t status;
18193457Sjc156560 	int ret;
18203457Sjc156560 
18213457Sjc156560 	if ((obj_type < OBJ_TYPE_SYSTEM) || (obj_type > OBJ_TYPE_ALL))
18223457Sjc156560 		return (ERR_DEVICE_TYPE);
18233457Sjc156560 
18243457Sjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
18253457Sjc156560 	if (status < SUCCESS)
18263457Sjc156560 		return (status);
18273457Sjc156560 
18283457Sjc156560 	if (!(status & OBJ_STATUS_SCANCOMP)) {
18293457Sjc156560 		ret = obj_scan_comp(raid_tab, obj_id);
18303457Sjc156560 		if (ret < SUCCESS)
18313457Sjc156560 			return (ret);
18323457Sjc156560 	}
18333457Sjc156560 
18343457Sjc156560 	id = raid_obj_get_comp(raid_tab, obj_id);
18353457Sjc156560 	if (id <= OBJ_NONE)
18363457Sjc156560 		return (id);
18373457Sjc156560 
18383457Sjc156560 	type = raid_obj_get_type(raid_tab, id);
18393457Sjc156560 	if (type < OBJ_TYPE_SYSTEM)
18403457Sjc156560 		return (type);
18413457Sjc156560 
18423457Sjc156560 	if (type == obj_type)
18433457Sjc156560 		return (id);
18443457Sjc156560 
18453457Sjc156560 	while (id > OBJ_NONE) {
18463457Sjc156560 		id = raid_obj_get_sibling(raid_tab, id);
18473457Sjc156560 		if (id <= OBJ_NONE)
18483457Sjc156560 			return (id);
18493457Sjc156560 
18503457Sjc156560 		type = raid_obj_get_type(raid_tab, id);
18513457Sjc156560 		if (type < OBJ_TYPE_SYSTEM)
18523457Sjc156560 			return (type);
18533457Sjc156560 
18543457Sjc156560 		if (type == obj_type)
18553457Sjc156560 			break;
18563457Sjc156560 	};
18573457Sjc156560 
18583457Sjc156560 	return (id);
18593457Sjc156560 }
18603457Sjc156560 
18613457Sjc156560 static raid_obj_id_t
obj_get_sibling(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)18623457Sjc156560 obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
18633457Sjc156560 {
18643457Sjc156560 	raid_obj_id_t id;
18653457Sjc156560 	raid_obj_type_id_t type, obj_type;
18663457Sjc156560 
18673457Sjc156560 	id = obj_id;
18683457Sjc156560 	obj_type = raid_obj_get_type(raid_tab, id);
18693457Sjc156560 	if (obj_type < OBJ_TYPE_SYSTEM)
18703457Sjc156560 		return (obj_type);
18713457Sjc156560 
18723457Sjc156560 	do {
18733457Sjc156560 		id = raid_obj_get_sibling(raid_tab, id);
18743457Sjc156560 		if (id < OBJ_NONE)
18753457Sjc156560 			return (id);
18763457Sjc156560 
18773457Sjc156560 		type = raid_obj_get_type(raid_tab, id);
18783457Sjc156560 		if (type < OBJ_TYPE_SYSTEM)
18793457Sjc156560 			return (type);
18803457Sjc156560 	} while ((type != obj_type) && (id != OBJ_NONE));
18813457Sjc156560 
18823457Sjc156560 	return (id);
18833457Sjc156560 }
18843457Sjc156560 
18853457Sjc156560 static int
obj_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,void ** data)18863457Sjc156560 obj_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, void **data)
18873457Sjc156560 {
18883457Sjc156560 	raid_obj_type_id_t type;
18893457Sjc156560 	raid_obj_status_t status;
18903457Sjc156560 	void *attr;
18913457Sjc156560 	int ret = SUCCESS;
18923457Sjc156560 
18933457Sjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
18943457Sjc156560 	if (status < SUCCESS)
18953457Sjc156560 		return (status);
18963457Sjc156560 
18973457Sjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
18983457Sjc156560 	if (type < OBJ_TYPE_SYSTEM)
18993457Sjc156560 		return (type);
19003457Sjc156560 
19013457Sjc156560 	if (!(status & OBJ_STATUS_OPENED)) {
19023457Sjc156560 		if (raid_obj_op_sys[type].get_attr == NULL)
19033457Sjc156560 			(void) raid_obj_set_status(raid_tab, obj_id,
19044563Syw161884 			    OBJ_STATUS_OPENED);
19053457Sjc156560 		else
19063457Sjc156560 			ret = raid_obj_op_sys[type].get_attr(raid_tab, obj_id);
19073457Sjc156560 	}
19083457Sjc156560 	if (ret < SUCCESS)
19093457Sjc156560 		return (ret);
19103457Sjc156560 
19113457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
19123457Sjc156560 	if (attr == NULL && type != OBJ_TYPE_SYSTEM)
19133457Sjc156560 		return (ERR_DEVICE_INVALID);
19143457Sjc156560 
19153457Sjc156560 	*data = attr;
19163457Sjc156560 	return (SUCCESS);
19173457Sjc156560 }
19183457Sjc156560 
19193457Sjc156560 static raid_obj_id_t
obj_locate_controller(raid_obj_tab_t * raid_tab,uint32_t controller_id)19203457Sjc156560 obj_locate_controller(raid_obj_tab_t *raid_tab, uint32_t controller_id)
19213457Sjc156560 {
19223457Sjc156560 	raid_obj_id_t obj_id;
19233457Sjc156560 	controller_attr_t *attr;
19243457Sjc156560 
19253457Sjc156560 	obj_id = obj_get_comp(raid_tab, OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
19263457Sjc156560 	if (obj_id <= OBJ_NONE)
19273457Sjc156560 		return (obj_id);
19283457Sjc156560 
19293457Sjc156560 	do {
19303457Sjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
19313457Sjc156560 		if (attr == NULL)
19323457Sjc156560 			return (ERR_DEVICE_INVALID);
19333457Sjc156560 
19343457Sjc156560 		if (attr->controller_id == controller_id)
19353457Sjc156560 			break;
19363457Sjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) != OBJ_NONE);
19373457Sjc156560 
19383457Sjc156560 	return (obj_id);
19393457Sjc156560 }
19403457Sjc156560 
19413457Sjc156560 static raid_obj_id_t
obj_locate_array(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t array_id)19423457Sjc156560 obj_locate_array(raid_obj_tab_t *raid_tab, uint32_t controller_id,
19433457Sjc156560 	uint32_t array_id)
19443457Sjc156560 {
19453457Sjc156560 	raid_obj_id_t obj_id;
19463457Sjc156560 
19473457Sjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
19483457Sjc156560 	if (obj_id < OBJ_NONE)
19493457Sjc156560 		return (obj_id);
19503457Sjc156560 
19513457Sjc156560 	obj_id = obj_locate_array_recur(raid_tab, obj_id, array_id);
19523457Sjc156560 
19533457Sjc156560 	return (obj_id);
19543457Sjc156560 }
19553457Sjc156560 
19563457Sjc156560 static raid_obj_id_t
obj_locate_array_recur(raid_obj_tab_t * raid_tab,raid_obj_id_t container_obj_id,uint32_t array_id)19573457Sjc156560 obj_locate_array_recur(raid_obj_tab_t *raid_tab,
19583457Sjc156560 	raid_obj_id_t container_obj_id, uint32_t array_id)
19593457Sjc156560 {
19603457Sjc156560 	raid_obj_id_t obj_id, ret;
19613457Sjc156560 	array_attr_t *attr;
19623457Sjc156560 
19633457Sjc156560 	obj_id = obj_get_comp(raid_tab, container_obj_id, OBJ_TYPE_ARRAY);
19643457Sjc156560 	if (obj_id <= OBJ_NONE)
19653457Sjc156560 		return (obj_id);
19663457Sjc156560 
19673457Sjc156560 	do {
19683457Sjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
19693457Sjc156560 		if (attr == NULL)
19703457Sjc156560 			return (ERR_DEVICE_INVALID);
19713457Sjc156560 
19723457Sjc156560 		if (attr->array_id == array_id)
19733457Sjc156560 			break;
19743457Sjc156560 
19753457Sjc156560 		ret = obj_locate_array_recur(raid_tab, obj_id, array_id);
19763457Sjc156560 		if (ret != OBJ_NONE)
19773457Sjc156560 			return (ret);
19783457Sjc156560 
19793457Sjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
19803457Sjc156560 
19813457Sjc156560 	return (obj_id);
19823457Sjc156560 }
19833457Sjc156560 
19843457Sjc156560 static raid_obj_id_t
obj_locate_hsp(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t disk_id,uint32_t array_id)19853457Sjc156560 obj_locate_hsp(raid_obj_tab_t *raid_tab, uint32_t controller_id,
19863457Sjc156560 	uint32_t disk_id, uint32_t array_id)
19873457Sjc156560 {
19883457Sjc156560 	raid_obj_id_t obj_id;
19893457Sjc156560 	hsp_attr_t *hsp_attr;
19903457Sjc156560 
19913457Sjc156560 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
19923457Sjc156560 	if (obj_id <= OBJ_NONE)
19933457Sjc156560 		return (obj_id);
19943457Sjc156560 
19953457Sjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_HSP);
19963457Sjc156560 	if (obj_id <= OBJ_NONE)
19973457Sjc156560 		return (obj_id);
19983457Sjc156560 
19993457Sjc156560 	do {
20003457Sjc156560 		(void) obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
20013457Sjc156560 		if (hsp_attr->associated_id == array_id)
20023457Sjc156560 			break;
20033457Sjc156560 
20043457Sjc156560 		obj_id = obj_get_sibling(raid_tab, obj_id);
20053457Sjc156560 		if (obj_id < OBJ_NONE)
20063457Sjc156560 			return (obj_id);
20073457Sjc156560 	} while (obj_id > OBJ_NONE);
20083457Sjc156560 
20093457Sjc156560 	return (obj_id);
20103457Sjc156560 }
20113457Sjc156560 
20123457Sjc156560 static raid_obj_id_t
obj_locate_disk(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t disk_id)20133457Sjc156560 obj_locate_disk(raid_obj_tab_t *raid_tab, uint32_t controller_id,
20143457Sjc156560 	uint32_t disk_id)
20153457Sjc156560 {
20163457Sjc156560 	raid_obj_id_t obj_id;
20173457Sjc156560 	disk_attr_t *attr;
20183457Sjc156560 
20193457Sjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
20203457Sjc156560 	if (obj_id <= OBJ_NONE)
20213457Sjc156560 		return (obj_id);
20223457Sjc156560 
20233457Sjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
20243457Sjc156560 	if (obj_id <= OBJ_NONE)
20253457Sjc156560 		return (obj_id);
20263457Sjc156560 
20273457Sjc156560 	do {
20283457Sjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
20293457Sjc156560 		if (attr == NULL)
20303457Sjc156560 			return (ERR_DEVICE_INVALID);
20313457Sjc156560 
20323457Sjc156560 		if (attr->disk_id == disk_id)
20333457Sjc156560 			break;
20343457Sjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
20353457Sjc156560 
20363457Sjc156560 	return (obj_id);
20373457Sjc156560 }
20383457Sjc156560 
20393457Sjc156560 static raid_obj_id_t
obj_locate_arraypart(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t array_id,uint32_t disk_id)20403457Sjc156560 obj_locate_arraypart(raid_obj_tab_t *raid_tab, uint32_t controller_id,
20413457Sjc156560 	uint32_t array_id, uint32_t disk_id)
20423457Sjc156560 {
20433457Sjc156560 	raid_obj_id_t obj_id;
20443457Sjc156560 
20453457Sjc156560 	arraypart_attr_t *attr;
20463457Sjc156560 
20473457Sjc156560 	obj_id = obj_locate_array(raid_tab, controller_id, array_id);
20483457Sjc156560 	if (obj_id <= OBJ_NONE)
20493457Sjc156560 		return (obj_id);
20503457Sjc156560 
20513457Sjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY_PART);
20523457Sjc156560 	if (obj_id <= OBJ_NONE)
20533457Sjc156560 		return (obj_id);
20543457Sjc156560 
20553457Sjc156560 	do {
20563457Sjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
20573457Sjc156560 		if (attr == NULL)
20583457Sjc156560 			return (ERR_DEVICE_INVALID);
20593457Sjc156560 
20603457Sjc156560 		if (attr->disk_id == disk_id)
20613457Sjc156560 			break;
20623457Sjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) >
20634563Syw161884 	    OBJ_NONE);
20643457Sjc156560 
20653457Sjc156560 	return (obj_id);
20663457Sjc156560 }
20673457Sjc156560 
20683457Sjc156560 static raid_obj_id_t
obj_locate_diskseg(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t disk_id,uint32_t seq_no)20693457Sjc156560 obj_locate_diskseg(raid_obj_tab_t *raid_tab, uint32_t controller_id,
20703457Sjc156560 	uint32_t disk_id, uint32_t seq_no)
20713457Sjc156560 {
20723457Sjc156560 	raid_obj_id_t obj_id;
20733457Sjc156560 	diskseg_attr_t *attr;
20743457Sjc156560 
20753457Sjc156560 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
20763457Sjc156560 	if (obj_id <= OBJ_NONE)
20773457Sjc156560 		return (obj_id);
20783457Sjc156560 
20793457Sjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK_SEG);
20803457Sjc156560 	if (obj_id <= OBJ_NONE)
20813457Sjc156560 		return (obj_id);
20823457Sjc156560 
20833457Sjc156560 	do {
20843457Sjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
20853457Sjc156560 		if (attr == NULL)
20863457Sjc156560 			return (ERR_DEVICE_INVALID);
20873457Sjc156560 
20883457Sjc156560 		if (attr->seq_no == seq_no)
20893457Sjc156560 			break;
20903457Sjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
20913457Sjc156560 
20923457Sjc156560 	return (obj_id);
20933457Sjc156560 }
20943457Sjc156560 
20953457Sjc156560 static raid_obj_id_t
obj_locate_task(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t task_id)20963457Sjc156560 obj_locate_task(raid_obj_tab_t *raid_tab, uint32_t controller_id,
20973457Sjc156560 	uint32_t task_id)
20983457Sjc156560 {
20993457Sjc156560 	raid_obj_id_t obj_id, obj_id2, task_obj_id;
21003457Sjc156560 	task_attr_t *attr;
21013457Sjc156560 
21023457Sjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
21033457Sjc156560 	if (obj_id <= OBJ_NONE)
21043457Sjc156560 		return (obj_id);
21053457Sjc156560 
21063457Sjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
21073457Sjc156560 	if (obj_id < OBJ_NONE)
21083457Sjc156560 		return (obj_id);
21093457Sjc156560 
21103457Sjc156560 	do {
21113457Sjc156560 		obj_id2 = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
21123457Sjc156560 		while (obj_id2 != OBJ_NONE) {
21133457Sjc156560 			task_obj_id = obj_get_comp(raid_tab, obj_id2,
21144563Syw161884 			    OBJ_TYPE_TASK);
21153457Sjc156560 
21163457Sjc156560 			if (task_obj_id < OBJ_NONE)
21173457Sjc156560 				return (task_obj_id);
21183457Sjc156560 
21193457Sjc156560 			if (task_obj_id == OBJ_NONE) {
21203457Sjc156560 				obj_id2 = obj_get_sibling(raid_tab, obj_id2);
21213457Sjc156560 				continue;
21223457Sjc156560 			}
21233457Sjc156560 
21243457Sjc156560 			attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
21253457Sjc156560 			if (attr == NULL)
21263457Sjc156560 				return (ERR_DEVICE_INVALID);
21273457Sjc156560 
21283457Sjc156560 			if (attr->task_id == task_id)
21293457Sjc156560 				return (task_obj_id);
21303457Sjc156560 
21313457Sjc156560 			obj_id2 = obj_get_sibling(raid_tab, obj_id2);
21323457Sjc156560 		}
21333457Sjc156560 
21343457Sjc156560 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
21353457Sjc156560 		if (task_obj_id < OBJ_NONE)
21363457Sjc156560 			return (task_obj_id);
21373457Sjc156560 
21383457Sjc156560 		if (task_obj_id == OBJ_NONE)
21393457Sjc156560 			continue;
21403457Sjc156560 
21413457Sjc156560 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
21423457Sjc156560 		if (attr == NULL)
21433457Sjc156560 			return (ERR_DEVICE_INVALID);
21443457Sjc156560 
21453457Sjc156560 		if (attr->task_id == task_id)
21463457Sjc156560 			return (task_obj_id);
21473457Sjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
21483457Sjc156560 
21493457Sjc156560 	if (obj_id < OBJ_NONE)
21503457Sjc156560 		return (obj_id);
21513457Sjc156560 
21523457Sjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
21533457Sjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
21543457Sjc156560 	if (obj_id < OBJ_NONE)
21553457Sjc156560 		return (obj_id);
21563457Sjc156560 
21573457Sjc156560 	do {
21583457Sjc156560 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
21593457Sjc156560 		if (task_obj_id < OBJ_NONE)
21603457Sjc156560 			return (task_obj_id);
21613457Sjc156560 
21623457Sjc156560 		if (task_obj_id == OBJ_NONE)
21633457Sjc156560 			continue;
21643457Sjc156560 
21653457Sjc156560 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
21663457Sjc156560 		if (attr == NULL)
21673457Sjc156560 			return (ERR_DEVICE_INVALID);
21683457Sjc156560 
21693457Sjc156560 		if (attr->task_id == task_id)
21703457Sjc156560 			return (task_obj_id);
21713457Sjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
21723457Sjc156560 
21733457Sjc156560 	return (obj_id);
21747233Syw161884 }
21757233Syw161884 
21767233Syw161884 static raid_obj_id_t
obj_locate_prop(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t disk_id,uint32_t prop_id)21777233Syw161884 obj_locate_prop(raid_obj_tab_t *raid_tab, uint32_t controller_id,
21787233Syw161884 	uint32_t disk_id, uint32_t prop_id)
21797233Syw161884 {
21807233Syw161884 	raid_obj_id_t obj_id;
21817233Syw161884 	property_attr_t *prop_attr;
21827233Syw161884 
21837233Syw161884 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
21847233Syw161884 	if (obj_id < OBJ_NONE)
21857233Syw161884 		return (obj_id);
21867233Syw161884 
21877233Syw161884 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_PROP);
21887233Syw161884 	if (obj_id <= OBJ_NONE)
21897233Syw161884 		return (obj_id);
21907233Syw161884 
21917233Syw161884 	do {
21927233Syw161884 		(void) obj_get_attr(raid_tab, obj_id, (void **)(&prop_attr));
21937233Syw161884 		if (prop_attr->prop_id == prop_id)
21947233Syw161884 			break;
21957233Syw161884 
21967233Syw161884 		obj_id = obj_get_sibling(raid_tab, obj_id);
21977233Syw161884 		if (obj_id < OBJ_NONE)
21987233Syw161884 			return (obj_id);
21997233Syw161884 	} while (obj_id > OBJ_NONE);
22007233Syw161884 
22017233Syw161884 	return (obj_id);
22023457Sjc156560 }
22033457Sjc156560 
22043457Sjc156560 static raid_obj_id_t
obj_get_controller(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)22053457Sjc156560 obj_get_controller(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
22063457Sjc156560 {
22073457Sjc156560 	raid_obj_id_t id = obj_id;
22083457Sjc156560 
22093457Sjc156560 	while (raid_obj_get_type(raid_tab, id) != OBJ_TYPE_CONTROLLER) {
22103457Sjc156560 		id = raid_obj_get_container(raid_tab, id);
22113457Sjc156560 		if ((id == OBJ_SYSTEM) || (id < OBJ_NONE))
22123457Sjc156560 			return (ERR_DEVICE_INVALID);
22133457Sjc156560 	}
22143457Sjc156560 
22153457Sjc156560 	return (id);
22163457Sjc156560 }
22173457Sjc156560 
22183457Sjc156560 /*
22193457Sjc156560  * Raid object operation routines
22203457Sjc156560  */
22213457Sjc156560 static int
obj_sys_compnum(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t comp_type)22223457Sjc156560 obj_sys_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
22233457Sjc156560 	raid_obj_type_id_t comp_type)
22243457Sjc156560 {
22253457Sjc156560 	DIR *dir;
22263457Sjc156560 	struct dirent *dp;
22273457Sjc156560 	int num = 0;
22283457Sjc156560 
22293457Sjc156560 	if ((raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM))
22303457Sjc156560 		return (ERR_DEVICE_TYPE);
22313457Sjc156560 
22323457Sjc156560 	if (comp_type != OBJ_TYPE_CONTROLLER)
22333457Sjc156560 		return (0);
22343457Sjc156560 
22353457Sjc156560 	if ((dir = opendir(CFGDIR)) == NULL)
22363457Sjc156560 		return (ERR_DRIVER_NOT_FOUND);
22373457Sjc156560 
22383457Sjc156560 	while ((dp = readdir(dir)) != NULL) {
22393457Sjc156560 		uint32_t controller_id;
22403457Sjc156560 		char path[MAX_PATH_LEN];
22413457Sjc156560 
22423457Sjc156560 		if (strcmp(dp->d_name, ".") == 0 ||
22434563Syw161884 		    strcmp(dp->d_name, "..") == 0)
22443457Sjc156560 			continue;
22453457Sjc156560 
22463457Sjc156560 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
22473457Sjc156560 			continue;
22483457Sjc156560 
22493457Sjc156560 		if (controller_id_to_path(controller_id, path) == SUCCESS)
22503457Sjc156560 			++ num;
22513457Sjc156560 	}
22523457Sjc156560 
22533457Sjc156560 	(void) closedir(dir);
22543457Sjc156560 	return (num);
22553457Sjc156560 }
22563457Sjc156560 
22573457Sjc156560 static int
obj_sys_complist(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int num,raid_obj_id_t * comp_list,raid_obj_type_id_t comp_type)22583457Sjc156560 obj_sys_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
22593457Sjc156560 	int num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
22603457Sjc156560 {
22613457Sjc156560 	DIR *dir;
22623457Sjc156560 	struct dirent *dp;
22633457Sjc156560 	controller_attr_t *attr;
22643457Sjc156560 	uint32_t controller_id;
22653457Sjc156560 	uint32_t *tmplist;
22663457Sjc156560 	char path[MAX_PATH_LEN];
22673457Sjc156560 	int i = 0;
22683457Sjc156560 
22693457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM)
22703457Sjc156560 		return (ERR_DEVICE_TYPE);
22713457Sjc156560 	if ((num <= 0) || (comp_list == NULL))
22723457Sjc156560 		return (ERR_OP_ILLEGAL);
22733457Sjc156560 
22743457Sjc156560 	if (comp_type != OBJ_TYPE_CONTROLLER)
22753457Sjc156560 		return (0);
22763457Sjc156560 
22773457Sjc156560 	if ((dir = opendir(CFGDIR)) == NULL)
22783457Sjc156560 		return (ERR_DRIVER_NOT_FOUND);
22793457Sjc156560 	tmplist = calloc(num, sizeof (uint32_t));
22803457Sjc156560 	if (tmplist == NULL) {
22813457Sjc156560 		return (ERR_NOMEM);
22823457Sjc156560 	}
22833457Sjc156560 	while ((dp = readdir(dir)) != NULL) {
22843457Sjc156560 		if (strcmp(dp->d_name, ".") == 0 ||
22854563Syw161884 		    strcmp(dp->d_name, "..") == 0)
22863457Sjc156560 			continue;
22873457Sjc156560 
22883457Sjc156560 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
22893457Sjc156560 			continue;
22903457Sjc156560 
22913457Sjc156560 		if (controller_id_to_path(controller_id, path) == SUCCESS) {
22923457Sjc156560 			tmplist[i] = controller_id;
22933457Sjc156560 			++ i;
22943457Sjc156560 		}
22953457Sjc156560 	}
22963457Sjc156560 	qsort((void *)tmplist, num, sizeof (uint32_t), intcompare);
22973457Sjc156560 	for (i = 0; i < num; i++) {
22983457Sjc156560 		attr = raid_obj_get_data_ptr(raid_tab,
22994563Syw161884 		    *(comp_list + i));
23003457Sjc156560 
23013457Sjc156560 		if (attr == NULL) {
23023457Sjc156560 			free(tmplist);
23033457Sjc156560 			return (ERR_DEVICE_INVALID);
23043457Sjc156560 		}
23053457Sjc156560 
23063457Sjc156560 		attr->controller_id = tmplist[i];
23073457Sjc156560 	}
23083457Sjc156560 	free(tmplist);
23093457Sjc156560 	(void) closedir(dir);
23103457Sjc156560 	return (SUCCESS);
23113457Sjc156560 }
23123457Sjc156560 
23133457Sjc156560 static int
obj_controller_compnum(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t comp_type)23143457Sjc156560 obj_controller_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
23153457Sjc156560 	raid_obj_type_id_t comp_type)
23163457Sjc156560 {
23173457Sjc156560 	raid_lib_t *raid_lib;
23183457Sjc156560 	int ret = SUCCESS, fd;
23193457Sjc156560 	controller_attr_t *ctl_attrp;
23203457Sjc156560 
23213457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
23223457Sjc156560 		return (ERR_DEVICE_TYPE);
23233457Sjc156560 
23243457Sjc156560 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
23253457Sjc156560 		return (0);
23263457Sjc156560 
23273457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
23283457Sjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
23293457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
23303457Sjc156560 	if ((raid_lib == NULL) || (ctl_attrp == NULL) || (fd == 0))
23313457Sjc156560 		return (ERR_DRIVER_CLOSED);
23323457Sjc156560 
23333457Sjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id, 0,
23344563Syw161884 	    OBJ_TYPE_CONTROLLER, comp_type);
23353457Sjc156560 
23363457Sjc156560 	return (ret);
23373457Sjc156560 }
23383457Sjc156560 
23393457Sjc156560 static int
obj_controller_complist(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int comp_num,raid_obj_id_t * comp_list,raid_obj_type_id_t comp_type)23403457Sjc156560 obj_controller_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
23413457Sjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
23423457Sjc156560 {
23433457Sjc156560 	raid_lib_t *raid_lib;
23443457Sjc156560 	controller_attr_t *ctl_attrp;
23453457Sjc156560 	int ret, i, fd;
23463457Sjc156560 	uint32_t *ids;
23473457Sjc156560 
23483457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
23493457Sjc156560 		return (ERR_DEVICE_TYPE);
23503457Sjc156560 
23513457Sjc156560 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
23523457Sjc156560 		return (0);
23533457Sjc156560 
23543457Sjc156560 	if ((comp_num <= 0) || (comp_list == NULL))
23553457Sjc156560 		return (ERR_OP_ILLEGAL);
23563457Sjc156560 
23573457Sjc156560 	for (i = 0; i < comp_num; ++i)
23583457Sjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
23594563Syw161884 		    comp_type)
23603457Sjc156560 			return (ERR_DEVICE_TYPE);
23613457Sjc156560 
23623457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
23633457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
23643457Sjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
23653457Sjc156560 	if ((raid_lib == NULL) || (ctl_attrp == NULL)|| (fd == 0))
23663457Sjc156560 		return (ERR_DRIVER_CLOSED);
23673457Sjc156560 
23683457Sjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
23693457Sjc156560 	if (ids == NULL)
23703457Sjc156560 		return (ERR_NOMEM);
23713457Sjc156560 
23723457Sjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id, 0,
23734563Syw161884 	    OBJ_TYPE_CONTROLLER, comp_type, comp_num, ids);
23743457Sjc156560 	if (ret < SUCCESS) {
23753457Sjc156560 		free(ids);
23763457Sjc156560 		return (ret);
23773457Sjc156560 	}
23783457Sjc156560 	qsort((void *)ids, comp_num, sizeof (uint32_t), intcompare);
23793457Sjc156560 	for (i = 0; i < comp_num; ++ i) {
23803457Sjc156560 		array_attr_t *array_attr;
23813457Sjc156560 		disk_attr_t *disk_attr;
23823457Sjc156560 		void *attr_buf;
23833457Sjc156560 
23843457Sjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
23853457Sjc156560 		if (attr_buf == NULL) {
23863457Sjc156560 			free(ids);
23873457Sjc156560 			return (ERR_DEVICE_INVALID);
23883457Sjc156560 		}
23893457Sjc156560 
23903457Sjc156560 		switch (comp_type) {
23913457Sjc156560 		case OBJ_TYPE_ARRAY:
23923457Sjc156560 			array_attr = attr_buf;
23933457Sjc156560 			array_attr->array_id = *(ids + i);
23943457Sjc156560 			break;
23953457Sjc156560 		case OBJ_TYPE_DISK:
23963457Sjc156560 			disk_attr = attr_buf;
23973457Sjc156560 			disk_attr->disk_id = *(ids + i);
23983457Sjc156560 			break;
23993457Sjc156560 		default:
24003457Sjc156560 			free(ids);
24013457Sjc156560 			return (ERR_DEVICE_INVALID);
24023457Sjc156560 		}
24033457Sjc156560 	}
24043457Sjc156560 
24053457Sjc156560 	free(ids);
24063457Sjc156560 	return (SUCCESS);
24073457Sjc156560 }
24083457Sjc156560 
24093457Sjc156560 static int
obj_controller_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)24103457Sjc156560 obj_controller_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
24113457Sjc156560 {
24123457Sjc156560 	controller_attr_t *attr;
24133457Sjc156560 	raid_lib_t *raid_lib;
24143457Sjc156560 	int ret = SUCCESS, fd;
24153457Sjc156560 
24163457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
24173457Sjc156560 		return (ERR_DEVICE_TYPE);
24183457Sjc156560 
24193457Sjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
24203457Sjc156560 		return (SUCCESS);
24213457Sjc156560 
24223457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
24233457Sjc156560 	if (attr == NULL)
24243457Sjc156560 		return (ERR_DEVICE_INVALID);
24253457Sjc156560 
24263457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
24273457Sjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
24283457Sjc156560 
24293457Sjc156560 	/*
24303457Sjc156560 	 * For a controller, even it's not opened, we can still
24313457Sjc156560 	 * get the driver name
24323457Sjc156560 	 */
24333457Sjc156560 
24343457Sjc156560 	if (fd == 0)
24353457Sjc156560 		return (SUCCESS);
24363457Sjc156560 
24373457Sjc156560 	if (raid_lib == NULL) {
24383457Sjc156560 		return (SUCCESS);
24393457Sjc156560 	}
24403457Sjc156560 
24413457Sjc156560 	ret = raid_lib->get_attr(attr->controller_id, OBJ_ATTR_NONE,
24424563Syw161884 	    OBJ_ATTR_NONE, OBJ_TYPE_CONTROLLER, attr);
24433457Sjc156560 	if (ret < SUCCESS)
24443457Sjc156560 		return (ret);
24453457Sjc156560 
24463457Sjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
24473457Sjc156560 
24483457Sjc156560 	return (ret);
24493457Sjc156560 }
24503457Sjc156560 
24513457Sjc156560 static int
obj_controller_act(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,uint32_t sub_cmd,void * prop_list,char ** plugin_err_str)24523457Sjc156560 obj_controller_act(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
24533457Sjc156560 	uint32_t sub_cmd, void *prop_list, char **plugin_err_str)
24543457Sjc156560 {
24553457Sjc156560 	controller_attr_t *attr;
24563457Sjc156560 	raid_lib_t *raid_lib;
24573457Sjc156560 	int ret, fd;
24583457Sjc156560 
24593457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
24603457Sjc156560 		return (ERR_DEVICE_TYPE);
24613457Sjc156560 
24623457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
24633457Sjc156560 
24643457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
24653457Sjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
24663457Sjc156560 
24673457Sjc156560 	switch (sub_cmd) {
24683457Sjc156560 	case ACT_CONTROLLER_OPEN:
24693457Sjc156560 		/* Check if already opened */
24703457Sjc156560 
24713457Sjc156560 		if (fd > 0)
24723457Sjc156560 			return (SUCCESS);
24733457Sjc156560 
24743457Sjc156560 		/* Check if plugin is already attached */
24753457Sjc156560 		if (raid_lib == NULL) {
24763457Sjc156560 			raid_lib = raid_find_lib(raid_tab, obj_id);
24773457Sjc156560 			if (raid_lib == NULL)
24783457Sjc156560 				return (ERR_DRIVER_NOT_FOUND);
24793457Sjc156560 		}
24803457Sjc156560 
24813457Sjc156560 		ret = raid_lib->open_controller(attr->controller_id,
24824563Syw161884 		    plugin_err_str);
24833457Sjc156560 		if (ret == SUCCESS) {
24843457Sjc156560 			(void) raid_obj_set_lib(raid_tab, obj_id, raid_lib);
24853457Sjc156560 			(void) raid_obj_set_fd(raid_tab, obj_id, 1);
24863457Sjc156560 		}
24873457Sjc156560 		break;
24883457Sjc156560 	case ACT_CONTROLLER_CLOSE:
24893457Sjc156560 
24903457Sjc156560 		if (fd <= 0)
24913457Sjc156560 			return (SUCCESS);
24923457Sjc156560 
24933457Sjc156560 		if (raid_lib == NULL) {
24943457Sjc156560 			return (SUCCESS);
24953457Sjc156560 		}
24963457Sjc156560 		ret = raid_lib->close_controller(attr->controller_id,
24974563Syw161884 		    plugin_err_str);
24983457Sjc156560 		if (ret == SUCCESS) {
24993457Sjc156560 			(void) raid_obj_set_fd(raid_tab, obj_id, 0);
25003457Sjc156560 			(void) raid_obj_set_lib(raid_tab, obj_id, NULL);
25013457Sjc156560 			raid_handle_delete_controller_comp(attr->controller_id);
25023457Sjc156560 		}
25033457Sjc156560 		break;
25043457Sjc156560 	case ACT_CONTROLLER_FLASH_FW:
25053457Sjc156560 		{
25063457Sjc156560 			char		*filebuf;
25073457Sjc156560 			int		image_fd;
25083457Sjc156560 			uint32_t	size;
25093457Sjc156560 			struct stat	statbuf;
25103457Sjc156560 
25113457Sjc156560 			if (prop_list == NULL)
25123457Sjc156560 				return (ERR_OP_ILLEGAL);
25133457Sjc156560 
25143457Sjc156560 			/* Open firmware image file */
25153457Sjc156560 			image_fd = open((const char *)prop_list,
25164563Syw161884 			    O_RDONLY | O_NDELAY);
25173457Sjc156560 			if (image_fd == -1)
25183457Sjc156560 				return (ERR_OP_FAILED);
25193457Sjc156560 
25203457Sjc156560 			if (fstat(image_fd, &statbuf) != 0) {
25213457Sjc156560 				(void) close(image_fd);
25223457Sjc156560 				return (ERR_OP_FAILED);
25233457Sjc156560 			}
25243457Sjc156560 
25253457Sjc156560 			filebuf = malloc(statbuf.st_size);
25263457Sjc156560 			if (filebuf == NULL) {
25273457Sjc156560 				(void) close(image_fd);
25283457Sjc156560 				return (ERR_NOMEM);
25293457Sjc156560 			}
25303457Sjc156560 
25313457Sjc156560 			size = read(image_fd, filebuf, statbuf.st_size);
25323457Sjc156560 			if (size != statbuf.st_size) {
25333457Sjc156560 				(void) close(image_fd);
25343457Sjc156560 				free(filebuf);
25353457Sjc156560 				return (ERR_OP_FAILED);
25363457Sjc156560 			}
25373457Sjc156560 
25383457Sjc156560 			if (fd <= 0) {
25393457Sjc156560 				(void) close(image_fd);
25403457Sjc156560 				free(filebuf);
25413457Sjc156560 				return (ERR_DRIVER_CLOSED);
25423457Sjc156560 			}
25433457Sjc156560 
25443457Sjc156560 			if (raid_lib == NULL) {
25453457Sjc156560 				(void) close(image_fd);
25463457Sjc156560 				free(filebuf);
25473457Sjc156560 				return (ERR_DRIVER_CLOSED);
25483457Sjc156560 			}
25493457Sjc156560 			if (raid_lib->flash_fw == NULL) {
25503457Sjc156560 				(void) close(image_fd);
25513457Sjc156560 				free(filebuf);
25523457Sjc156560 				return (ERR_OP_NO_IMPL);
25533457Sjc156560 			}
25543457Sjc156560 
25553457Sjc156560 			ret = raid_lib->flash_fw(attr->controller_id,
25564563Syw161884 			    filebuf, size, plugin_err_str);
25573457Sjc156560 		}
25583457Sjc156560 		break;
25593457Sjc156560 	default:
25603457Sjc156560 		return (ERR_OP_ILLEGAL);
25613457Sjc156560 	}
25623457Sjc156560 
25633457Sjc156560 	return (ret);
25643457Sjc156560 }
25653457Sjc156560 
25663457Sjc156560 static int
obj_array_compnum(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t comp_type)25673457Sjc156560 obj_array_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
25683457Sjc156560 	raid_obj_type_id_t comp_type)
25693457Sjc156560 {
25703457Sjc156560 	array_attr_t *attr;
25713457Sjc156560 	controller_attr_t *ctl_attrp;
25723457Sjc156560 	raid_obj_id_t controller_obj_id;
25733457Sjc156560 	raid_lib_t *raid_lib;
25743457Sjc156560 	int ret = SUCCESS, fd;
25753457Sjc156560 
25763457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
25773457Sjc156560 		return (ERR_DEVICE_TYPE);
25783457Sjc156560 
25793457Sjc156560 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
25804563Syw161884 	    comp_type != OBJ_TYPE_ARRAY &&
25814563Syw161884 	    comp_type != OBJ_TYPE_TASK)
25823457Sjc156560 		return (0);
25833457Sjc156560 
25843457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
25853457Sjc156560 	if (attr == NULL)
25863457Sjc156560 		return (ERR_DEVICE_INVALID);
25873457Sjc156560 
25883457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
25893457Sjc156560 	if (controller_obj_id < OBJ_NONE)
25903457Sjc156560 		return (ERR_DEVICE_INVALID);
25913457Sjc156560 
25923457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
25933457Sjc156560 	if (ctl_attrp == NULL) {
25943457Sjc156560 		return (ERR_DEVICE_INVALID);
25953457Sjc156560 	}
25963457Sjc156560 
25973457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
25983457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
25993457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
26003457Sjc156560 		return (ERR_DRIVER_CLOSED);
26013457Sjc156560 
26023457Sjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id, attr->array_id,
26034563Syw161884 	    OBJ_TYPE_ARRAY, comp_type);
26043457Sjc156560 
26053457Sjc156560 	return (ret);
26063457Sjc156560 }
26073457Sjc156560 
26083457Sjc156560 static int
obj_array_complist(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int comp_num,raid_obj_id_t * comp_list,raid_obj_type_id_t comp_type)26093457Sjc156560 obj_array_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
26103457Sjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
26113457Sjc156560 {
26123457Sjc156560 	array_attr_t *attr;
26133457Sjc156560 	controller_attr_t *ctl_attrp;
26143457Sjc156560 	raid_obj_id_t controller_obj_id;
26153457Sjc156560 	raid_lib_t *raid_lib;
26163457Sjc156560 	int ret, i, fd;
26173457Sjc156560 	uint32_t *ids;
26183457Sjc156560 
26193457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
26203457Sjc156560 		return (ERR_DEVICE_TYPE);
26213457Sjc156560 
26223457Sjc156560 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
26234563Syw161884 	    comp_type != OBJ_TYPE_ARRAY &&
26244563Syw161884 	    comp_type != OBJ_TYPE_TASK)
26253457Sjc156560 		return (0);
26263457Sjc156560 
26273457Sjc156560 	if (comp_num <= 0 || comp_list == NULL)
26283457Sjc156560 		return (ERR_OP_ILLEGAL);
26293457Sjc156560 
26303457Sjc156560 	for (i = 0; i < comp_num; ++i)
26313457Sjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
26324563Syw161884 		    comp_type)
26333457Sjc156560 			return (ERR_DEVICE_TYPE);
26343457Sjc156560 
26353457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
26363457Sjc156560 	if (attr == NULL)
26373457Sjc156560 		return (ERR_DEVICE_INVALID);
26383457Sjc156560 
26393457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
26403457Sjc156560 	if (controller_obj_id < OBJ_NONE)
26413457Sjc156560 		return (ERR_DEVICE_INVALID);
26423457Sjc156560 
26433457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
26443457Sjc156560 	if (ctl_attrp == NULL) {
26453457Sjc156560 		return (ERR_DEVICE_INVALID);
26463457Sjc156560 	}
26473457Sjc156560 
26483457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
26493457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
26503457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
26513457Sjc156560 		return (ERR_DRIVER_CLOSED);
26523457Sjc156560 
26533457Sjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
26543457Sjc156560 	if (ids == NULL)
26553457Sjc156560 		return (ERR_NOMEM);
26563457Sjc156560 
26573457Sjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id,
26584563Syw161884 	    attr->array_id, OBJ_TYPE_ARRAY, comp_type, comp_num, ids);
26593457Sjc156560 
26603457Sjc156560 	if (ret < SUCCESS) {
26613457Sjc156560 		free(ids);
26623457Sjc156560 		return (ret);
26633457Sjc156560 	}
26643457Sjc156560 
26653457Sjc156560 	for (i = 0; i < comp_num; ++ i) {
26663457Sjc156560 		array_attr_t *array_attr;
26673457Sjc156560 		arraypart_attr_t *arraypart_attr;
26683457Sjc156560 		task_attr_t *task_attr;
26693457Sjc156560 		void *attr_buf;
26703457Sjc156560 
26713457Sjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
26723457Sjc156560 		if (attr_buf == NULL) {
26733457Sjc156560 			free(ids);
26743457Sjc156560 			return (ERR_DEVICE_INVALID);
26753457Sjc156560 		}
26763457Sjc156560 
26773457Sjc156560 		switch (comp_type) {
26783457Sjc156560 		case OBJ_TYPE_ARRAY:
26793457Sjc156560 			array_attr = attr_buf;
26803457Sjc156560 			array_attr->array_id = *(ids + i);
26813457Sjc156560 			break;
26823457Sjc156560 		case OBJ_TYPE_ARRAY_PART:
26833457Sjc156560 			arraypart_attr = attr_buf;
26843457Sjc156560 			arraypart_attr->disk_id = *(ids + i);
26853457Sjc156560 			break;
26863457Sjc156560 		case OBJ_TYPE_TASK:
26873457Sjc156560 			task_attr = attr_buf;
26883457Sjc156560 			task_attr->task_id = *(ids + i);
26893457Sjc156560 			break;
26903457Sjc156560 		default:
26913457Sjc156560 			free(ids);
26923457Sjc156560 			return (ERR_DEVICE_INVALID);
26933457Sjc156560 		}
26943457Sjc156560 	}
26953457Sjc156560 
26963457Sjc156560 
26973457Sjc156560 	free(ids);
26983457Sjc156560 	return (ret);
26993457Sjc156560 }
27003457Sjc156560 
27013457Sjc156560 static int
obj_array_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)27023457Sjc156560 obj_array_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
27033457Sjc156560 {
27043457Sjc156560 	array_attr_t *attr;
27053457Sjc156560 	controller_attr_t *ctl_attrp;
27063457Sjc156560 	raid_lib_t *raid_lib;
27073457Sjc156560 	int ret = SUCCESS, fd;
27083457Sjc156560 	raid_obj_id_t controller_obj_id;
27093457Sjc156560 
27103457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
27113457Sjc156560 		return (ERR_DEVICE_TYPE);
27123457Sjc156560 
27133457Sjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
27143457Sjc156560 		return (SUCCESS);
27153457Sjc156560 
27163457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
27173457Sjc156560 	if (attr == NULL)
27183457Sjc156560 		return (ERR_DEVICE_INVALID);
27193457Sjc156560 
27203457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
27213457Sjc156560 	if (controller_obj_id < OBJ_NONE)
27223457Sjc156560 		return (ERR_DEVICE_INVALID);
27233457Sjc156560 
27243457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
27253457Sjc156560 	if (ctl_attrp == NULL) {
27263457Sjc156560 		return (ERR_DEVICE_INVALID);
27273457Sjc156560 	}
27283457Sjc156560 
27293457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
27303457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
27313457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
27323457Sjc156560 		return (ERR_DRIVER_CLOSED);
27333457Sjc156560 
27343457Sjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
27354563Syw161884 	    attr->array_id, 0, OBJ_TYPE_ARRAY, attr);
27363457Sjc156560 
27373457Sjc156560 	if (ret < SUCCESS)
27383457Sjc156560 		return (ret);
27393457Sjc156560 
27403457Sjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
27413457Sjc156560 
27423457Sjc156560 	return (ret);
27433457Sjc156560 }
27443457Sjc156560 
27453457Sjc156560 static int
obj_array_set_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,uint32_t sub_cmd,uint32_t * value,char ** plugin_err_str)27463457Sjc156560 obj_array_set_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
27473457Sjc156560 	uint32_t sub_cmd, uint32_t *value, char **plugin_err_str)
27483457Sjc156560 {
27493457Sjc156560 	array_attr_t *attr;
27503457Sjc156560 	controller_attr_t *ctl_attrp;
27513457Sjc156560 	raid_lib_t *raid_lib;
27523457Sjc156560 	int ret = SUCCESS, fd;
27533457Sjc156560 	raid_obj_id_t controller_obj_id;
27543457Sjc156560 
27553457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
27563457Sjc156560 		return (ERR_DEVICE_TYPE);
27573457Sjc156560 
27583457Sjc156560 	switch (sub_cmd) {
27593457Sjc156560 	case SET_CACHE_WR_PLY:
27603457Sjc156560 		if (*value != CACHE_WR_OFF &&
27614563Syw161884 		    *value != CACHE_WR_ON)
27623457Sjc156560 			return (ERR_OP_ILLEGAL);
27633457Sjc156560 		break;
27643457Sjc156560 	case SET_CACHE_RD_PLY:
27653457Sjc156560 		if (*value != CACHE_RD_OFF &&
27664563Syw161884 		    *value != CACHE_RD_ON)
27673457Sjc156560 			return (ERR_OP_ILLEGAL);
27683457Sjc156560 		break;
27697233Syw161884 	case SET_ACTIVATION_PLY:
27707233Syw161884 		if (*value != ARRAY_ACT_ACTIVATE)
27717233Syw161884 			return (ERR_OP_ILLEGAL);
27727233Syw161884 		break;
27733457Sjc156560 	default:
27743457Sjc156560 		return (ERR_OP_ILLEGAL);
27753457Sjc156560 	}
27763457Sjc156560 
27773457Sjc156560 	(void) obj_get_attr(raid_tab, obj_id, (void **)(&attr));
27783457Sjc156560 
27793457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
27803457Sjc156560 	if (controller_obj_id < OBJ_NONE)
27813457Sjc156560 		return (ERR_DEVICE_INVALID);
27823457Sjc156560 
27833457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
27843457Sjc156560 	if (ctl_attrp == NULL) {
27853457Sjc156560 		return (ERR_DEVICE_INVALID);
27863457Sjc156560 	}
27873457Sjc156560 
27883457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
27893457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
27903457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
27913457Sjc156560 		return (ERR_DRIVER_CLOSED);
27923457Sjc156560 
27933457Sjc156560 	if (raid_lib->set_attr == NULL)
27943457Sjc156560 		return (ERR_OP_NO_IMPL);
27953457Sjc156560 
27963457Sjc156560 	ret = raid_lib->set_attr(ctl_attrp->controller_id,
27974563Syw161884 	    attr->array_id, sub_cmd, value, plugin_err_str);
27983457Sjc156560 
27993457Sjc156560 	return (ret);
28003457Sjc156560 }
28013457Sjc156560 
28023457Sjc156560 static int
obj_disk_compnum(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t comp_type)28033457Sjc156560 obj_disk_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
28043457Sjc156560 	raid_obj_type_id_t comp_type)
28053457Sjc156560 {
28063457Sjc156560 	disk_attr_t *attr;
28073457Sjc156560 	controller_attr_t *ctl_attrp;
28083457Sjc156560 	raid_obj_id_t controller_obj_id;
28093457Sjc156560 	raid_lib_t *raid_lib;
28103457Sjc156560 	int ret = SUCCESS, fd;
28113457Sjc156560 
28123457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
28133457Sjc156560 		return (ERR_DEVICE_TYPE);
28143457Sjc156560 
28153457Sjc156560 	if (comp_type != OBJ_TYPE_DISK_SEG &&
28164563Syw161884 	    comp_type != OBJ_TYPE_HSP &&
28177233Syw161884 	    comp_type != OBJ_TYPE_TASK &&
28187233Syw161884 	    comp_type != OBJ_TYPE_PROP)
28193457Sjc156560 		return (0);
28203457Sjc156560 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
28213457Sjc156560 	if ((ret != SUCCESS) || (attr == NULL)) {
28223457Sjc156560 		return (ERR_DEVICE_INVALID);
28233457Sjc156560 	}
28243457Sjc156560 	if (attr->state == DISK_STATE_FAILED) {
28253457Sjc156560 		return (SUCCESS);
28263457Sjc156560 	}
28273457Sjc156560 
28283457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
28293457Sjc156560 	if (controller_obj_id < OBJ_NONE)
28303457Sjc156560 		return (ERR_DEVICE_INVALID);
28313457Sjc156560 
28323457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
28333457Sjc156560 	if (ctl_attrp == NULL) {
28343457Sjc156560 		return (ERR_DEVICE_INVALID);
28353457Sjc156560 	}
28363457Sjc156560 
28373457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
28383457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
28393457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
28403457Sjc156560 		return (ERR_DRIVER_CLOSED);
28413457Sjc156560 
28423457Sjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id,
28434563Syw161884 	    attr->disk_id, OBJ_TYPE_DISK, comp_type);
28443457Sjc156560 
28453457Sjc156560 	return (ret);
28463457Sjc156560 }
28473457Sjc156560 
28483457Sjc156560 static int
obj_disk_complist(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int comp_num,raid_obj_id_t * comp_list,raid_obj_type_id_t comp_type)28493457Sjc156560 obj_disk_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
28503457Sjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
28513457Sjc156560 {
28523457Sjc156560 	disk_attr_t *attr;
28533457Sjc156560 	controller_attr_t *ctl_attrp;
28543457Sjc156560 	raid_obj_id_t controller_obj_id;
28553457Sjc156560 	raid_lib_t *raid_lib;
28563457Sjc156560 	int ret, i, fd;
28573457Sjc156560 	uint32_t *ids;
28583457Sjc156560 
28593457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
28603457Sjc156560 		return (ERR_DEVICE_TYPE);
28613457Sjc156560 
28623457Sjc156560 	if (comp_type != OBJ_TYPE_DISK_SEG &&
28634563Syw161884 	    comp_type != OBJ_TYPE_HSP &&
28647233Syw161884 	    comp_type != OBJ_TYPE_TASK &&
28657233Syw161884 	    comp_type != OBJ_TYPE_PROP)
28663457Sjc156560 		return (0);
28673457Sjc156560 
28683457Sjc156560 	if (comp_num <= 0 || comp_list == NULL)
28693457Sjc156560 		return (ERR_OP_ILLEGAL);
28703457Sjc156560 
28713457Sjc156560 	for (i = 0; i < comp_num; ++i)
28723457Sjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
28734563Syw161884 		    comp_type)
28743457Sjc156560 			return (ERR_DEVICE_TYPE);
28753457Sjc156560 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
28763457Sjc156560 	if ((ret != SUCCESS) || (attr == NULL)) {
28773457Sjc156560 		return (ERR_DEVICE_INVALID);
28783457Sjc156560 	}
28793457Sjc156560 	if (attr->state == DISK_STATE_FAILED) {
28803457Sjc156560 		return (SUCCESS);
28813457Sjc156560 	}
28823457Sjc156560 
28833457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
28843457Sjc156560 	if (controller_obj_id < OBJ_NONE)
28853457Sjc156560 		return (ERR_DEVICE_INVALID);
28863457Sjc156560 
28873457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
28883457Sjc156560 	if (ctl_attrp == NULL) {
28893457Sjc156560 		return (ERR_DEVICE_INVALID);
28903457Sjc156560 	}
28913457Sjc156560 
28923457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
28933457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
28943457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
28953457Sjc156560 		return (ERR_DRIVER_CLOSED);
28963457Sjc156560 
28973457Sjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
28983457Sjc156560 	if (ids == NULL)
28993457Sjc156560 		return (ERR_NOMEM);
29003457Sjc156560 
29013457Sjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id,
29024563Syw161884 	    attr->disk_id, OBJ_TYPE_DISK, comp_type, comp_num, ids);
29033457Sjc156560 
29043457Sjc156560 	if (ret < SUCCESS) {
29053457Sjc156560 		free(ids);
29063457Sjc156560 		return (ret);
29073457Sjc156560 	}
29083457Sjc156560 
29093457Sjc156560 	for (i = 0; i < comp_num; ++ i) {
29103457Sjc156560 		diskseg_attr_t *diskseg_attr;
29113457Sjc156560 		hsp_attr_t *hsp_attr;
29123457Sjc156560 		task_attr_t *task_attr;
29137233Syw161884 		property_attr_t *prop_attr;
29143457Sjc156560 		void *attr_buf;
29153457Sjc156560 
29163457Sjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
29173457Sjc156560 		if (attr_buf == NULL) {
29183457Sjc156560 			free(ids);
29193457Sjc156560 			return (ERR_DEVICE_INVALID);
29203457Sjc156560 		}
29213457Sjc156560 
29223457Sjc156560 		switch (comp_type) {
29233457Sjc156560 		case OBJ_TYPE_DISK_SEG:
29243457Sjc156560 			diskseg_attr = attr_buf;
29253457Sjc156560 			diskseg_attr->seq_no = *(ids + i);
29263457Sjc156560 			break;
29273457Sjc156560 		case OBJ_TYPE_HSP:
29283457Sjc156560 			hsp_attr = attr_buf;
29293457Sjc156560 			hsp_attr->associated_id = *(ids + i);
29303457Sjc156560 			break;
29313457Sjc156560 		case OBJ_TYPE_TASK:
29323457Sjc156560 			task_attr = attr_buf;
29333457Sjc156560 			task_attr->task_id = *(ids + i);
29343457Sjc156560 			break;
29357233Syw161884 		case OBJ_TYPE_PROP:
29367233Syw161884 			prop_attr = attr_buf;
29377233Syw161884 			prop_attr->prop_id = *(ids + i);
29387233Syw161884 			break;
29393457Sjc156560 		default:
29403457Sjc156560 			free(ids);
29413457Sjc156560 			return (ERR_DEVICE_INVALID);
29423457Sjc156560 		}
29433457Sjc156560 	}
29443457Sjc156560 
29453457Sjc156560 
29463457Sjc156560 	free(ids);
29473457Sjc156560 	return (ret);
29483457Sjc156560 }
29493457Sjc156560 
29503457Sjc156560 static int
obj_disk_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)29513457Sjc156560 obj_disk_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
29523457Sjc156560 {
29533457Sjc156560 	disk_attr_t *attr;
29543457Sjc156560 	controller_attr_t *ctl_attrp;
29553457Sjc156560 	raid_lib_t *raid_lib;
29563457Sjc156560 	int ret = SUCCESS, fd;
29573457Sjc156560 	raid_obj_id_t controller_obj_id;
29583457Sjc156560 
29593457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
29603457Sjc156560 		return (ERR_DEVICE_TYPE);
29613457Sjc156560 
29623457Sjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
29633457Sjc156560 		return (SUCCESS);
29643457Sjc156560 
29653457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
29663457Sjc156560 	if (attr == NULL)
29673457Sjc156560 		return (ERR_DEVICE_INVALID);
29683457Sjc156560 
29693457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
29703457Sjc156560 	if (controller_obj_id < OBJ_NONE)
29713457Sjc156560 		return (ERR_DEVICE_INVALID);
29723457Sjc156560 
29733457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
29743457Sjc156560 	if (ctl_attrp == NULL) {
29753457Sjc156560 		return (ERR_DEVICE_INVALID);
29763457Sjc156560 	}
29773457Sjc156560 
29783457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
29793457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
29803457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
29813457Sjc156560 		return (ERR_DRIVER_CLOSED);
29823457Sjc156560 
29833457Sjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
29844563Syw161884 	    attr->disk_id, 0, OBJ_TYPE_DISK, attr);
29853457Sjc156560 
29863457Sjc156560 	if (ret < SUCCESS)
29873457Sjc156560 		return (ret);
29883457Sjc156560 
29893457Sjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
29903457Sjc156560 
29913457Sjc156560 	return (ret);
29923457Sjc156560 }
29933457Sjc156560 
29943457Sjc156560 static int
obj_hsp_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)29953457Sjc156560 obj_hsp_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
29963457Sjc156560 {
29973457Sjc156560 	hsp_attr_t *attr;
29983457Sjc156560 
29993457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_HSP)
30003457Sjc156560 		return (ERR_DEVICE_TYPE);
30013457Sjc156560 
30023457Sjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
30033457Sjc156560 		return (SUCCESS);
30043457Sjc156560 
30053457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
30063457Sjc156560 	if (attr == NULL)
30073457Sjc156560 		return (ERR_DEVICE_INVALID);
30083457Sjc156560 
30093457Sjc156560 	if (attr->associated_id == (uint32_t)OBJ_ATTR_NONE)
30103457Sjc156560 		attr->type = HSP_TYPE_GLOBAL;
30113457Sjc156560 	else
30123457Sjc156560 		attr->type = HSP_TYPE_LOCAL;
30133457Sjc156560 
30143457Sjc156560 	return (SUCCESS);
30153457Sjc156560 }
30163457Sjc156560 
30173457Sjc156560 static int
obj_arraypart_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)30183457Sjc156560 obj_arraypart_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
30193457Sjc156560 {
30203457Sjc156560 	arraypart_attr_t *attr;
30213457Sjc156560 	array_attr_t *array_attr;
30223457Sjc156560 	controller_attr_t *ctl_attrp;
30233457Sjc156560 	raid_lib_t *raid_lib;
30243457Sjc156560 	int ret = SUCCESS, fd;
30253457Sjc156560 	raid_obj_id_t controller_obj_id, array_obj_id;
30263457Sjc156560 
30273457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY_PART)
30283457Sjc156560 		return (ERR_DEVICE_TYPE);
30293457Sjc156560 
30303457Sjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
30313457Sjc156560 		return (SUCCESS);
30323457Sjc156560 
30333457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
30343457Sjc156560 	if (attr == NULL)
30353457Sjc156560 		return (ERR_DEVICE_INVALID);
30363457Sjc156560 
30373457Sjc156560 	array_obj_id = raid_obj_get_container(raid_tab, obj_id);
30383457Sjc156560 	if (array_obj_id < OBJ_NONE)
30393457Sjc156560 		return (ERR_DEVICE_INVALID);
30403457Sjc156560 
30413457Sjc156560 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
30423457Sjc156560 	if (array_attr == NULL)
30433457Sjc156560 		return (ERR_DEVICE_INVALID);
30443457Sjc156560 
30453457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
30463457Sjc156560 	if (controller_obj_id < OBJ_NONE)
30473457Sjc156560 		return (ERR_DEVICE_INVALID);
30483457Sjc156560 
30493457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
30503457Sjc156560 	if (ctl_attrp == NULL) {
30513457Sjc156560 		return (ERR_DEVICE_INVALID);
30523457Sjc156560 	}
30533457Sjc156560 
30543457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
30553457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
30563457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
30573457Sjc156560 		return (ERR_DRIVER_CLOSED);
30583457Sjc156560 
30593457Sjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
30604563Syw161884 	    array_attr->array_id, attr->disk_id,
30614563Syw161884 	    OBJ_TYPE_ARRAY_PART, attr);
30623457Sjc156560 
30633457Sjc156560 	if (ret < SUCCESS)
30643457Sjc156560 		return (ret);
30653457Sjc156560 
30663457Sjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
30673457Sjc156560 
30683457Sjc156560 	return (ret);
30693457Sjc156560 }
30703457Sjc156560 
30713457Sjc156560 static int
obj_diskseg_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)30723457Sjc156560 obj_diskseg_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
30733457Sjc156560 {
30743457Sjc156560 	diskseg_attr_t *attr;
30753457Sjc156560 	disk_attr_t *disk_attr;
30763457Sjc156560 	controller_attr_t *ctl_attrp;
30773457Sjc156560 	raid_lib_t *raid_lib;
30783457Sjc156560 	int ret = SUCCESS, fd;
30793457Sjc156560 	raid_obj_id_t controller_obj_id, disk_obj_id;
30803457Sjc156560 
30813457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK_SEG)
30823457Sjc156560 		return (ERR_DEVICE_TYPE);
30833457Sjc156560 
30843457Sjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
30853457Sjc156560 		return (SUCCESS);
30863457Sjc156560 
30873457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
30883457Sjc156560 	if (attr == NULL)
30893457Sjc156560 		return (ERR_DEVICE_INVALID);
30903457Sjc156560 
30913457Sjc156560 	disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
30923457Sjc156560 	if (disk_obj_id < OBJ_NONE)
30933457Sjc156560 		return (ERR_DEVICE_INVALID);
30943457Sjc156560 
30953457Sjc156560 	disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
30963457Sjc156560 	if (disk_attr == NULL)
30973457Sjc156560 		return (ERR_DEVICE_INVALID);
30983457Sjc156560 
30993457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
31003457Sjc156560 	if (controller_obj_id < OBJ_NONE)
31013457Sjc156560 		return (ERR_DEVICE_INVALID);
31023457Sjc156560 
31033457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
31043457Sjc156560 	if (ctl_attrp == NULL) {
31053457Sjc156560 		return (ERR_DEVICE_INVALID);
31063457Sjc156560 	}
31073457Sjc156560 
31083457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
31093457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
31103457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
31113457Sjc156560 		return (ERR_DRIVER_CLOSED);
31123457Sjc156560 
31133457Sjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
31144563Syw161884 	    disk_attr->disk_id, attr->seq_no, OBJ_TYPE_DISK_SEG, attr);
31153457Sjc156560 
31163457Sjc156560 	if (ret < SUCCESS)
31173457Sjc156560 		return (ret);
31183457Sjc156560 
31193457Sjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
31203457Sjc156560 
31213457Sjc156560 	return (ret);
31223457Sjc156560 }
31233457Sjc156560 
31243457Sjc156560 static int
obj_task_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)31253457Sjc156560 obj_task_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
31263457Sjc156560 {
31273457Sjc156560 	task_attr_t *attr;
31283457Sjc156560 	controller_attr_t *ctl_attrp;
31293457Sjc156560 	raid_lib_t *raid_lib;
31303457Sjc156560 	int ret = SUCCESS, fd;
31313457Sjc156560 	raid_obj_id_t controller_obj_id;
31323457Sjc156560 
31333457Sjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_TASK)
31343457Sjc156560 		return (ERR_DEVICE_TYPE);
31353457Sjc156560 
31363457Sjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
31373457Sjc156560 	if (attr == NULL)
31383457Sjc156560 		return (ERR_DEVICE_INVALID);
31393457Sjc156560 
31403457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
31413457Sjc156560 	if (controller_obj_id < OBJ_NONE)
31423457Sjc156560 		return (ERR_DEVICE_INVALID);
31433457Sjc156560 
31443457Sjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
31453457Sjc156560 	if (ctl_attrp == NULL) {
31463457Sjc156560 		return (ERR_DEVICE_INVALID);
31473457Sjc156560 	}
31483457Sjc156560 
31493457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
31503457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
31513457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
31523457Sjc156560 		return (ERR_DRIVER_CLOSED);
31533457Sjc156560 
31543457Sjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
31554563Syw161884 	    attr->task_id, OBJ_ATTR_NONE, OBJ_TYPE_TASK, attr);
31563457Sjc156560 
31573457Sjc156560 	return (ret);
31583457Sjc156560 }
31593457Sjc156560 
31603457Sjc156560 static int
obj_prop_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)31617233Syw161884 obj_prop_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
31627233Syw161884 {
31637233Syw161884 	property_attr_t *attr, *attr_new;
31647233Syw161884 	disk_attr_t *disk_attr;
31657233Syw161884 	controller_attr_t *ctl_attrp;
31667233Syw161884 	raid_lib_t *raid_lib;
31677233Syw161884 	int ret = SUCCESS, fd;
31687233Syw161884 	raid_obj_id_t controller_obj_id, disk_obj_id;
31697233Syw161884 
31707233Syw161884 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_PROP)
31717233Syw161884 		return (ERR_DEVICE_TYPE);
31727233Syw161884 
31737233Syw161884 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
31747233Syw161884 		return (SUCCESS);
31757233Syw161884 
31767233Syw161884 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
31777233Syw161884 	if (attr == NULL)
31787233Syw161884 		return (ERR_DEVICE_INVALID);
31797233Syw161884 
31807233Syw161884 	disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
31817233Syw161884 	if (disk_obj_id < OBJ_NONE)
31827233Syw161884 		return (ERR_DEVICE_INVALID);
31837233Syw161884 
31847233Syw161884 	disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
31857233Syw161884 	if (disk_attr == NULL)
31867233Syw161884 		return (ERR_DEVICE_INVALID);
31877233Syw161884 
31887233Syw161884 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
31897233Syw161884 	if (controller_obj_id < OBJ_NONE)
31907233Syw161884 		return (ERR_DEVICE_INVALID);
31917233Syw161884 
31927233Syw161884 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
31937233Syw161884 	if (ctl_attrp == NULL) {
31947233Syw161884 		return (ERR_DEVICE_INVALID);
31957233Syw161884 	}
31967233Syw161884 
31977233Syw161884 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
31987233Syw161884 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
31997233Syw161884 	if ((raid_lib == NULL) || (fd == 0))
32007233Syw161884 		return (ERR_DRIVER_CLOSED);
32017233Syw161884 
32027233Syw161884 	/* Get the property size at first */
32037233Syw161884 	attr->prop_size = 0;
32047233Syw161884 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
32057233Syw161884 	    disk_attr->disk_id, OBJ_ATTR_NONE, OBJ_TYPE_PROP, attr);
32067233Syw161884 
32077233Syw161884 	if (ret < SUCCESS)
32087233Syw161884 		return (ret);
32097233Syw161884 
32107233Syw161884 	/* Allocate memory for property and fill the buffer */
32117233Syw161884 	attr_new = realloc(attr, sizeof (property_attr_t) + attr->prop_size);
32127233Syw161884 	if (attr_new == NULL)
32137233Syw161884 		return (ERR_NOMEM);
32147233Syw161884 
32157233Syw161884 	(void) raid_obj_set_data_ptr(raid_tab, obj_id, attr_new);
32167233Syw161884 
32177233Syw161884 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
32187233Syw161884 	    disk_attr->disk_id, OBJ_ATTR_NONE, OBJ_TYPE_PROP, attr_new);
32197233Syw161884 
32207233Syw161884 	if (ret < SUCCESS)
32217233Syw161884 		return (ret);
32227233Syw161884 
32237233Syw161884 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
32247233Syw161884 
32257233Syw161884 	return (ret);
32267233Syw161884 }
32277233Syw161884 
32287233Syw161884 static int
obj_array_create(raid_obj_tab_t * raid_tab,raid_obj_id_t array_obj_id,int num_of_comp,raid_obj_id_t * disk_list,char ** plugin_err_str)32293457Sjc156560 obj_array_create(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
32303457Sjc156560 	int num_of_comp, raid_obj_id_t *disk_list, char **plugin_err_str)
32313457Sjc156560 {
32323457Sjc156560 	controller_attr_t *controller_attr;
32333457Sjc156560 	array_attr_t *array_attr, array_attr2;
32343457Sjc156560 	disk_attr_t *disk_attr;
32353457Sjc156560 	arraypart_attr_t *arraypart_attrs;
32363457Sjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
32373457Sjc156560 	raid_lib_t *raid_lib;
32383457Sjc156560 	int i, j, ret, fd;
32393457Sjc156560 	int disk_cnt = 0, disk_set_num = 0, set_num = 0, layer_cnt = 0;
32403457Sjc156560 	uint64_t min_disk_capacity = 0;
32413457Sjc156560 
32423457Sjc156560 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
32433457Sjc156560 	if (array_attr == NULL)
32443457Sjc156560 		return (ERR_DEVICE_INVALID);
32453457Sjc156560 
32463457Sjc156560 	/* Check the disk layout expression */
32473457Sjc156560 	if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
32484563Syw161884 	    disk_list[num_of_comp - 1] != OBJ_SEPARATOR_END)
32493457Sjc156560 		return (ERR_ARRAY_LAYOUT);
32503457Sjc156560 	for (i = 0; i < num_of_comp; ++i) {
32513457Sjc156560 		if (disk_list[i] == OBJ_SEPARATOR_BEGIN) {
32523457Sjc156560 			if (disk_cnt != 0)
32533457Sjc156560 				return (ERR_ARRAY_LAYOUT);
32543457Sjc156560 			++layer_cnt;
32553457Sjc156560 			continue;
32563457Sjc156560 		}
32573457Sjc156560 		if (disk_list[i] == OBJ_SEPARATOR_END) {
32583457Sjc156560 			if (disk_set_num == 0)
32593457Sjc156560 				disk_set_num = disk_cnt;
32603457Sjc156560 			else if (disk_set_num != disk_cnt && disk_cnt != 0)
32613457Sjc156560 				return (ERR_ARRAY_LAYOUT);
32623457Sjc156560 			disk_cnt = 0;
32633457Sjc156560 			++set_num;
32643457Sjc156560 			--layer_cnt;
32653457Sjc156560 			continue;
32663457Sjc156560 		}
32673457Sjc156560 		switch (array_attr->raid_level) {
32683457Sjc156560 		case RAID_LEVEL_0:
32693457Sjc156560 		case RAID_LEVEL_1:
32703457Sjc156560 		case RAID_LEVEL_1E:
32713457Sjc156560 		case RAID_LEVEL_5:
32723457Sjc156560 			if (layer_cnt != 1)
32733457Sjc156560 				return (ERR_ARRAY_LAYOUT);
32743457Sjc156560 			break;
32753457Sjc156560 		case RAID_LEVEL_10:
32763457Sjc156560 		case RAID_LEVEL_50:
32773457Sjc156560 			if (layer_cnt != 2)
32783457Sjc156560 				return (ERR_ARRAY_LAYOUT);
32793457Sjc156560 			break;
32803457Sjc156560 		default:
32813457Sjc156560 			return (ERR_ARRAY_LEVEL);
32823457Sjc156560 		}
32833457Sjc156560 		++disk_cnt;
32843457Sjc156560 	}
32853457Sjc156560 
32863457Sjc156560 	if (layer_cnt != 0)
32873457Sjc156560 		return (ERR_ARRAY_LAYOUT);
32883457Sjc156560 
32893457Sjc156560 	switch (array_attr->raid_level) {
32903457Sjc156560 	case RAID_LEVEL_0:
32913457Sjc156560 		if (disk_set_num < 2 || set_num != 1)
32923457Sjc156560 			return (ERR_ARRAY_LAYOUT);
32933457Sjc156560 		break;
32943457Sjc156560 	case RAID_LEVEL_1:
32953457Sjc156560 		if (disk_set_num != 2 || set_num != 1)
32963457Sjc156560 			return (ERR_ARRAY_LAYOUT);
32973457Sjc156560 		break;
32983457Sjc156560 	case RAID_LEVEL_1E:
32993457Sjc156560 	case RAID_LEVEL_5:
33003457Sjc156560 		if (disk_set_num < 3 || set_num != 1)
33013457Sjc156560 			return (ERR_ARRAY_LAYOUT);
33023457Sjc156560 		break;
33033457Sjc156560 	case RAID_LEVEL_10:
33043457Sjc156560 		if (disk_set_num != 2 || set_num < 2)
33053457Sjc156560 			return (ERR_ARRAY_LAYOUT);
33063457Sjc156560 		break;
33073457Sjc156560 	case RAID_LEVEL_50:
33083457Sjc156560 		if (disk_set_num < 3 || set_num < 2)
33093457Sjc156560 			return (ERR_ARRAY_LAYOUT);
33103457Sjc156560 		break;
33113457Sjc156560 	default:
33123457Sjc156560 		return (ERR_ARRAY_LEVEL);
33133457Sjc156560 	}
33143457Sjc156560 
33153457Sjc156560 	arraypart_attrs = calloc(num_of_comp, sizeof (arraypart_attr_t));
33163457Sjc156560 	if (arraypart_attrs == NULL)
33173457Sjc156560 		return (ERR_NOMEM);
33183457Sjc156560 
33193457Sjc156560 	for (i = 0; i < num_of_comp; ++i) {
33203457Sjc156560 		/* Keep seperators */
33213457Sjc156560 		if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
33223457Sjc156560 			arraypart_attrs[i].disk_id =
33234563Syw161884 			    (uint32_t)OBJ_SEPARATOR_BEGIN;
33243457Sjc156560 			continue;
33253457Sjc156560 		}
33263457Sjc156560 
33273457Sjc156560 		if (*(disk_list + i) == OBJ_SEPARATOR_END) {
33283457Sjc156560 			arraypart_attrs[i].disk_id =
33294563Syw161884 			    (uint32_t)OBJ_SEPARATOR_END;
33303457Sjc156560 			continue;
33313457Sjc156560 		}
33323457Sjc156560 
33333457Sjc156560 		disk_cnt++;
33343457Sjc156560 		/* Check if it's a disk */
33353457Sjc156560 		if (raid_obj_get_type(raid_tab, *(disk_list + i)) !=
33364563Syw161884 		    OBJ_TYPE_DISK)
33373457Sjc156560 			return (ERR_DEVICE_TYPE);
33383457Sjc156560 
33393457Sjc156560 		/* Check if it's duplicated with other disks */
33403457Sjc156560 		for (j = 0; j < i; ++j)
33413457Sjc156560 			if (*(disk_list + j) == *(disk_list + i)) {
33423457Sjc156560 				free(arraypart_attrs);
33433457Sjc156560 				return (ERR_DEVICE_DUP);
33443457Sjc156560 			}
33453457Sjc156560 
33463457Sjc156560 		/* Check disk status */
33473457Sjc156560 		ret = obj_get_attr(raid_tab, *(disk_list + i),
33484563Syw161884 		    (void **)(&disk_attr));
33493457Sjc156560 		if (ret != SUCCESS)
33503457Sjc156560 			return (ret);
33513457Sjc156560 
33523457Sjc156560 		if (disk_attr->state != DISK_STATE_GOOD) {
33533457Sjc156560 			free(arraypart_attrs);
33543457Sjc156560 			return (ERR_DISK_STATE);
33553457Sjc156560 		}
33563457Sjc156560 
33573457Sjc156560 		/* All disks must belong to the same controller */
33583457Sjc156560 		obj_id = obj_get_controller(raid_tab, *(disk_list + i));
33593457Sjc156560 		if (obj_id <= OBJ_NONE)
33603457Sjc156560 			return (obj_id);
33613457Sjc156560 		if (controller_obj_id == OBJ_NONE) {
33623457Sjc156560 			controller_obj_id = obj_id;
33633457Sjc156560 			ret = obj_get_attr(raid_tab, controller_obj_id,
33644563Syw161884 			    (void **)(&controller_attr));
33653457Sjc156560 		} else if (obj_id != controller_obj_id) {
33663457Sjc156560 			free(arraypart_attrs);
33673457Sjc156560 			return (ERR_DRIVER_ACROSS);
33683457Sjc156560 		}
33693457Sjc156560 
33703457Sjc156560 		/* Check if the disk contains too many segments */
33713457Sjc156560 		obj_id = obj_get_comp(raid_tab, *(disk_list + i),
33724563Syw161884 		    OBJ_TYPE_DISK_SEG);
33733457Sjc156560 		j = 0;
33743457Sjc156560 		while (obj_id > OBJ_NONE) {
33753457Sjc156560 			++j;
33763457Sjc156560 			obj_id = obj_get_sibling(raid_tab, obj_id);
33773457Sjc156560 		}
33783457Sjc156560 		if (j > controller_attr->max_seg_per_disk) {
33793457Sjc156560 			free(arraypart_attrs);
33803457Sjc156560 			return (ERR_DISK_SEG_AMOUNT);
33813457Sjc156560 		}
33823457Sjc156560 
33833457Sjc156560 		/* Check if controller is a hostraid controller */
33843457Sjc156560 		if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
33853457Sjc156560 			/*
33863457Sjc156560 			 * For hostraid, the first disk should
33873457Sjc156560 			 * be with of minimum capacity
33883457Sjc156560 			 */
33893457Sjc156560 			if (min_disk_capacity == 0) {
33903457Sjc156560 				min_disk_capacity = disk_attr->capacity;
33913457Sjc156560 
33923457Sjc156560 				/* Can not specify capacity for hostraid */
33933457Sjc156560 				if (array_attr->capacity != 0) {
33943457Sjc156560 					free(arraypart_attrs);
33954563Syw161884 					return (ERR_OP_ILLEGAL);
33963457Sjc156560 				}
33973457Sjc156560 			} else if (min_disk_capacity > disk_attr->capacity) {
33983457Sjc156560 				free(arraypart_attrs);
33993457Sjc156560 				return (ERR_DISK_SPACE);
34003457Sjc156560 			}
34013457Sjc156560 
34023457Sjc156560 			/* Disk should not be used for hostraid */
34033457Sjc156560 			obj_id = obj_get_comp(raid_tab, *(disk_list + i),
34044563Syw161884 			    OBJ_TYPE_DISK_SEG);
34053457Sjc156560 			if (obj_id < OBJ_NONE) {
34063457Sjc156560 				free(arraypart_attrs);
34073457Sjc156560 				return (obj_id);
34083457Sjc156560 			} else if (obj_id > OBJ_NONE) {
34093457Sjc156560 				free(arraypart_attrs);
34103457Sjc156560 				return (ERR_DISK_NOT_EMPTY);
34113457Sjc156560 			}
34123457Sjc156560 		}
34133457Sjc156560 
34143457Sjc156560 		arraypart_attrs[i].disk_id = disk_attr->disk_id;
34153457Sjc156560 		arraypart_attrs[i].offset = OBJ_ATTR_NONE;
34163457Sjc156560 		arraypart_attrs[i].size = OBJ_ATTR_NONE;
34173457Sjc156560 	}
34183457Sjc156560 
34193457Sjc156560 	/* Check if array amount exceeds limit */
34203457Sjc156560 	if (controller_attr->max_array_num <=
34214563Syw161884 	    obj_controller_compnum(raid_tab, controller_obj_id,
34224563Syw161884 	    OBJ_TYPE_ARRAY))
34233457Sjc156560 		return (ERR_ARRAY_AMOUNT);
34243457Sjc156560 
34253457Sjc156560 
34263457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
34273457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
34283457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
34293457Sjc156560 		return (ERR_DRIVER_CLOSED);
34303457Sjc156560 
34313457Sjc156560 	/* Check if the controller can support the array RAID level */
34323457Sjc156560 	switch (array_attr->raid_level) {
34333457Sjc156560 	case	RAID_LEVEL_0:
34343457Sjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID0)) {
34353457Sjc156560 			free(arraypart_attrs);
34363457Sjc156560 			return (ERR_ARRAY_LEVEL);
34373457Sjc156560 		}
34383457Sjc156560 		break;
34393457Sjc156560 	case	RAID_LEVEL_1:
34403457Sjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID1)) {
34413457Sjc156560 			free(arraypart_attrs);
34423457Sjc156560 			return (ERR_ARRAY_LEVEL);
34433457Sjc156560 		}
34443457Sjc156560 		break;
34453457Sjc156560 	case	RAID_LEVEL_1E:
34463457Sjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID1E)) {
34473457Sjc156560 			free(arraypart_attrs);
34483457Sjc156560 			return (ERR_ARRAY_LEVEL);
34493457Sjc156560 		}
34503457Sjc156560 		break;
34513457Sjc156560 	case	RAID_LEVEL_5:
34523457Sjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID5)) {
34533457Sjc156560 			free(arraypart_attrs);
34543457Sjc156560 			return (ERR_ARRAY_LEVEL);
34553457Sjc156560 		}
34563457Sjc156560 		break;
34573457Sjc156560 	case	RAID_LEVEL_10:
34583457Sjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID10)) {
34593457Sjc156560 			free(arraypart_attrs);
34603457Sjc156560 			return (ERR_ARRAY_LEVEL);
34613457Sjc156560 		}
34623457Sjc156560 		break;
34633457Sjc156560 	case	RAID_LEVEL_50:
34643457Sjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID50)) {
34653457Sjc156560 			free(arraypart_attrs);
34663457Sjc156560 			return (ERR_ARRAY_LEVEL);
34673457Sjc156560 		}
34683457Sjc156560 		break;
34693457Sjc156560 	default:
34703457Sjc156560 		free(arraypart_attrs);
34713457Sjc156560 		return (ERR_ARRAY_LEVEL);
34723457Sjc156560 	}
34733457Sjc156560 
34743457Sjc156560 	/* Check if plug in can calculate the maximum size */
34753457Sjc156560 	(void) memcpy(&array_attr2, array_attr, sizeof (array_attr_t));
34763457Sjc156560 	array_attr2.capacity = OBJ_ATTR_NONE;
34773457Sjc156560 	ret = raid_lib->array_create(controller_attr->controller_id,
34784563Syw161884 	    &array_attr2, num_of_comp, arraypart_attrs, plugin_err_str);
34793457Sjc156560 
34803457Sjc156560 	/* If plugin/driver will not calculate space */
34813457Sjc156560 	if (ret == ERR_OP_NO_IMPL) {
34823457Sjc156560 		/* Calculate the maximum capacity */
34833457Sjc156560 		array_attr2.capacity = raid_space_noalign(raid_tab,
34844563Syw161884 		    array_attr2.raid_level, num_of_comp, disk_list,
34854563Syw161884 		    arraypart_attrs);
34863457Sjc156560 
34873457Sjc156560 		/*
34883457Sjc156560 		 * If controller is capable to allocate space,
34893457Sjc156560 		 * set offset and size attributes to OBJ_ATTR_NONE
34903457Sjc156560 		 * and let the controller to determine these value
34913457Sjc156560 		 */
34923457Sjc156560 		if (controller_attr->capability & RAID_CAP_SMART_ALLOC)
34933457Sjc156560 			for (i = 0; i < num_of_comp; ++i) {
34943457Sjc156560 				arraypart_attrs[i].offset =
34954563Syw161884 				    OBJ_ATTR_NONE;
34963457Sjc156560 				arraypart_attrs[i].size =
34974563Syw161884 				    OBJ_ATTR_NONE;
34983457Sjc156560 			}
34993457Sjc156560 
35003457Sjc156560 		/* There's no enough space for specified capacity */
35013457Sjc156560 		if (array_attr->capacity > array_attr2.capacity) {
35023457Sjc156560 			free(arraypart_attrs);
35033457Sjc156560 			return (ERR_ARRAY_SIZE);
35043457Sjc156560 		}
35053457Sjc156560 
35063457Sjc156560 		/* capacity == 0, allocate maximum space */
35073457Sjc156560 		if (array_attr->capacity == 0)
35083457Sjc156560 			array_attr->capacity = array_attr2.capacity;
35093457Sjc156560 	} else if (ret < SUCCESS) {
35103457Sjc156560 		free(arraypart_attrs);
35113457Sjc156560 		return (ret);
35123457Sjc156560 	} else if (array_attr2.capacity < array_attr->capacity) {
35133457Sjc156560 		/* Return the maximum size */
35143457Sjc156560 		array_attr->capacity = array_attr2.capacity;
35153457Sjc156560 		free(arraypart_attrs);
35163457Sjc156560 		return (ERR_ARRAY_SIZE);
35173457Sjc156560 	}
35183457Sjc156560 
35193457Sjc156560 	if (array_attr->capacity < ARRAYPART_MIN_SIZE * disk_cnt) {
35203457Sjc156560 		free(arraypart_attrs);
35213457Sjc156560 		return (ERR_ARRAY_SIZE);
35223457Sjc156560 	}
35233457Sjc156560 
35243457Sjc156560 
35253457Sjc156560 	ret = raid_lib->array_create(controller_attr->controller_id,
35264563Syw161884 	    array_attr, num_of_comp, arraypart_attrs, plugin_err_str);
35273457Sjc156560 	free(arraypart_attrs);
35283457Sjc156560 
35293457Sjc156560 	if (ret != SUCCESS)
35303457Sjc156560 		return (ret);
35313457Sjc156560 
35323457Sjc156560 	/* Add array object into device tree so that we can map the handle */
35333457Sjc156560 	(void) raid_obj_add_org(raid_tab, array_obj_id, controller_obj_id);
35343457Sjc156560 
35353457Sjc156560 	return (ret);
35363457Sjc156560 }
35373457Sjc156560 
35383457Sjc156560 static int
obj_array_delete(raid_obj_tab_t * raid_tab,raid_obj_id_t array_obj_id,char ** plugin_err_str)35393457Sjc156560 obj_array_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
35403457Sjc156560 	char **plugin_err_str)
35413457Sjc156560 {
35423457Sjc156560 	raid_obj_id_t controller_obj_id;
35433457Sjc156560 	controller_attr_t *controller_attr;
35443457Sjc156560 	array_attr_t *array_attr;
35453457Sjc156560 	raid_lib_t *raid_lib;
35466348Sjc156560 	int ret, fd;
35473457Sjc156560 	uint32_t *disk_ids = NULL;
35483457Sjc156560 
35493457Sjc156560 	controller_obj_id = obj_get_controller(raid_tab, array_obj_id);
35503457Sjc156560 	if (controller_obj_id <= OBJ_NONE)
35513457Sjc156560 		return (controller_obj_id);
35523457Sjc156560 
35533457Sjc156560 	ret = obj_get_attr(raid_tab, controller_obj_id,
35544563Syw161884 	    (void **)(&controller_attr));
35553457Sjc156560 	if (ret < SUCCESS) {
35563457Sjc156560 		return (ret);
35573457Sjc156560 	}
35583457Sjc156560 	ret = obj_get_attr(raid_tab, array_obj_id, (void **)(&array_attr));
35593457Sjc156560 	if (ret < SUCCESS)
35603457Sjc156560 		return (ret);
35613457Sjc156560 
35623457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
35633457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
35643457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
35653457Sjc156560 		return (ERR_DRIVER_CLOSED);
35663457Sjc156560 
35673457Sjc156560 	ret = raid_lib->array_delete(controller_attr->controller_id,
35684563Syw161884 	    array_attr->array_id, plugin_err_str);
35693457Sjc156560 	if (ret < SUCCESS) {
35703457Sjc156560 		if (disk_ids)
35713457Sjc156560 			free(disk_ids);
35723457Sjc156560 		return (ret);
35733457Sjc156560 	}
35743457Sjc156560 
35753457Sjc156560 	if (disk_ids)
35763457Sjc156560 		free(disk_ids);
35773457Sjc156560 	return (ret);
35783457Sjc156560 }
35793457Sjc156560 
35803457Sjc156560 static int
obj_hsp_bind(raid_obj_tab_t * raid_tab,raid_obj_id_t * obj_ids,char ** plugin_err_str)35818263SRyan.Wang@Sun.COM obj_hsp_bind(raid_obj_tab_t *raid_tab, raid_obj_id_t *obj_ids,
35823457Sjc156560 	char **plugin_err_str)
35833457Sjc156560 {
35843457Sjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
35853457Sjc156560 	raid_obj_id_t array_obj_id, disk_obj_id;
35863457Sjc156560 	hsp_relation_t *hsp_relation;
35873457Sjc156560 	controller_attr_t *controller_attr;
35883457Sjc156560 	array_attr_t *array_attr;
35893457Sjc156560 	arraypart_attr_t *arraypart_attr;
35903457Sjc156560 	disk_attr_t *disk_attr;
35913457Sjc156560 	diskseg_attr_t *diskseg_attr;
35923457Sjc156560 	hsp_attr_t *hsp_attr;
35933457Sjc156560 	raid_lib_t *raid_lib;
35948263SRyan.Wang@Sun.COM 	int ret, fd;
35958263SRyan.Wang@Sun.COM 
35968263SRyan.Wang@Sun.COM 	hsp_relation = malloc(sizeof (hsp_relation_t));
35973457Sjc156560 	if (hsp_relation == NULL)
35983457Sjc156560 		return (ERR_NOMEM);
35993457Sjc156560 
36008263SRyan.Wang@Sun.COM 	array_obj_id = *(obj_ids);
36018263SRyan.Wang@Sun.COM 	disk_obj_id = *(obj_ids + 1);
36028263SRyan.Wang@Sun.COM 
36038263SRyan.Wang@Sun.COM 	if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK ||
36048263SRyan.Wang@Sun.COM 	    (array_obj_id != OBJ_ATTR_NONE &&
36058263SRyan.Wang@Sun.COM 	    raid_obj_get_type(raid_tab, array_obj_id) !=
36068263SRyan.Wang@Sun.COM 	    OBJ_TYPE_ARRAY)) {
36078263SRyan.Wang@Sun.COM 		free(hsp_relation);
36088263SRyan.Wang@Sun.COM 		return (ERR_DEVICE_TYPE);
36098263SRyan.Wang@Sun.COM 	}
36108263SRyan.Wang@Sun.COM 
36118263SRyan.Wang@Sun.COM 	/* Get controller attributes */
36128263SRyan.Wang@Sun.COM 	if (controller_obj_id == OBJ_NONE)
36138263SRyan.Wang@Sun.COM 		controller_obj_id = obj_get_controller(raid_tab,
36148263SRyan.Wang@Sun.COM 		    disk_obj_id);
36158263SRyan.Wang@Sun.COM 	else if (controller_obj_id != obj_get_controller(raid_tab,
36168263SRyan.Wang@Sun.COM 	    disk_obj_id)) {
36178263SRyan.Wang@Sun.COM 		free(hsp_relation);
36188263SRyan.Wang@Sun.COM 		return (ERR_DRIVER_ACROSS);
36198263SRyan.Wang@Sun.COM 	}
36208263SRyan.Wang@Sun.COM 
36218263SRyan.Wang@Sun.COM 	ret = obj_get_attr(raid_tab, controller_obj_id,
36228263SRyan.Wang@Sun.COM 	    (void **)(&controller_attr));
36238263SRyan.Wang@Sun.COM 
36248263SRyan.Wang@Sun.COM 	/* Get disk attributes */
36258263SRyan.Wang@Sun.COM 	ret = obj_get_attr(raid_tab,  disk_obj_id,
36268263SRyan.Wang@Sun.COM 	    (void **)(&disk_attr));
36278263SRyan.Wang@Sun.COM 	if (disk_attr->state == DISK_STATE_FAILED) {
36288263SRyan.Wang@Sun.COM 		free(hsp_relation);
36298263SRyan.Wang@Sun.COM 		return (ERR_DISK_STATE);
36308263SRyan.Wang@Sun.COM 	}
36318263SRyan.Wang@Sun.COM 
36328263SRyan.Wang@Sun.COM 	/* If it's not a hsp disk, check if there's occupied space */
36338263SRyan.Wang@Sun.COM 	if (obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP) ==
36348263SRyan.Wang@Sun.COM 	    OBJ_NONE) {
36358263SRyan.Wang@Sun.COM 		obj_id = obj_get_comp(raid_tab, disk_obj_id,
36368263SRyan.Wang@Sun.COM 		    OBJ_TYPE_DISK_SEG);
36378263SRyan.Wang@Sun.COM 		while (obj_id != OBJ_NONE) {
36388263SRyan.Wang@Sun.COM 			ret = obj_get_attr(raid_tab, obj_id,
36398263SRyan.Wang@Sun.COM 			    (void **)(&diskseg_attr));
36408263SRyan.Wang@Sun.COM 			if (!(diskseg_attr->state &
36418263SRyan.Wang@Sun.COM 			    DISKSEG_STATE_RESERVED)) {
36428263SRyan.Wang@Sun.COM 				free(hsp_relation);
36438263SRyan.Wang@Sun.COM 				return (ERR_DISK_NOT_EMPTY);
36448263SRyan.Wang@Sun.COM 			}
36458263SRyan.Wang@Sun.COM 			obj_id = obj_get_sibling(raid_tab, obj_id);
36468263SRyan.Wang@Sun.COM 		}
36478263SRyan.Wang@Sun.COM 	}
36488263SRyan.Wang@Sun.COM 
36498263SRyan.Wang@Sun.COM 	if (array_obj_id != OBJ_ATTR_NONE) {
36508263SRyan.Wang@Sun.COM 		/* If local hsp is supported */
36518263SRyan.Wang@Sun.COM 		if (!(controller_attr->capability & RAID_CAP_L_HSP)) {
36528263SRyan.Wang@Sun.COM 			free(hsp_relation);
36538263SRyan.Wang@Sun.COM 			return (ERR_OP_ILLEGAL);
36548263SRyan.Wang@Sun.COM 		}
36558263SRyan.Wang@Sun.COM 
36568263SRyan.Wang@Sun.COM 		if (raid_obj_get_type(raid_tab, array_obj_id) !=
36578263SRyan.Wang@Sun.COM 		    OBJ_TYPE_ARRAY) {
36583457Sjc156560 			free(hsp_relation);
36593457Sjc156560 			return (ERR_DEVICE_TYPE);
36603457Sjc156560 		}
36613457Sjc156560 
36628263SRyan.Wang@Sun.COM 		/* Get array attributes */
36638263SRyan.Wang@Sun.COM 		ret = obj_get_attr(raid_tab, array_obj_id,
36648263SRyan.Wang@Sun.COM 		    (void **)(&array_attr));
36658263SRyan.Wang@Sun.COM 		/* RAID 0 array can not use hsp */
36668263SRyan.Wang@Sun.COM 		if (array_attr->raid_level == RAID_LEVEL_0) {
36678263SRyan.Wang@Sun.COM 			free(hsp_relation);
36688263SRyan.Wang@Sun.COM 			return (ERR_ARRAY_LEVEL);
36698263SRyan.Wang@Sun.COM 		}
36708263SRyan.Wang@Sun.COM 
36718263SRyan.Wang@Sun.COM 		/* If It's belong to another controller */
36728263SRyan.Wang@Sun.COM 		if (controller_obj_id != obj_get_controller(raid_tab,
36738263SRyan.Wang@Sun.COM 		    array_obj_id)) {
36743457Sjc156560 			free(hsp_relation);
36753457Sjc156560 			return (ERR_DRIVER_ACROSS);
36763457Sjc156560 		}
36773457Sjc156560 
36788263SRyan.Wang@Sun.COM 		/* Get an array part attributes */
36798263SRyan.Wang@Sun.COM 		if ((array_attr->raid_level == RAID_LEVEL_10) ||
36808263SRyan.Wang@Sun.COM 		    (array_attr->raid_level == RAID_LEVEL_50))
36818263SRyan.Wang@Sun.COM 			obj_id = obj_get_comp(raid_tab, array_obj_id,
36828263SRyan.Wang@Sun.COM 			    OBJ_TYPE_ARRAY);
36838263SRyan.Wang@Sun.COM 		else
36848263SRyan.Wang@Sun.COM 			obj_id = array_obj_id;
36858263SRyan.Wang@Sun.COM 		obj_id = obj_get_comp(raid_tab, obj_id,
36868263SRyan.Wang@Sun.COM 		    OBJ_TYPE_ARRAY_PART);
36878263SRyan.Wang@Sun.COM 		ret = obj_get_attr(raid_tab, obj_id,
36888263SRyan.Wang@Sun.COM 		    (void **)(&arraypart_attr));
36898263SRyan.Wang@Sun.COM 
36908263SRyan.Wang@Sun.COM 		/* Check if disk space is enough for array */
36918263SRyan.Wang@Sun.COM 		if (arraypart_attr->size > disk_attr->capacity) {
36923457Sjc156560 			free(hsp_relation);
36938263SRyan.Wang@Sun.COM 			return (ERR_DISK_SPACE);
36943457Sjc156560 		}
36958263SRyan.Wang@Sun.COM 		if (controller_attr->capability & RAID_CAP_ARRAY_ALIGN)
36968263SRyan.Wang@Sun.COM 			if ((arraypart_attr->size +
36978263SRyan.Wang@Sun.COM 			    arraypart_attr->offset) >
36988263SRyan.Wang@Sun.COM 			    disk_attr->capacity) {
36998263SRyan.Wang@Sun.COM 			free(hsp_relation);
37008263SRyan.Wang@Sun.COM 			return (ERR_DISK_SPACE);
37013457Sjc156560 			}
37028263SRyan.Wang@Sun.COM 	} else if (!(controller_attr->capability & RAID_CAP_G_HSP)) {
37038263SRyan.Wang@Sun.COM 		/* if global hsp is supported */
37048263SRyan.Wang@Sun.COM 		free(hsp_relation);
37058263SRyan.Wang@Sun.COM 		return (ERR_OP_ILLEGAL);
37068263SRyan.Wang@Sun.COM 	}
37078263SRyan.Wang@Sun.COM 
37088263SRyan.Wang@Sun.COM 	/*
37098263SRyan.Wang@Sun.COM 	 * If the array is already associated with the
37108263SRyan.Wang@Sun.COM 	 * local hsp, or it's a global hsp, ignore it
37118263SRyan.Wang@Sun.COM 	 */
37128263SRyan.Wang@Sun.COM 	obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
37138263SRyan.Wang@Sun.COM 	if (obj_id > OBJ_NONE) {
37148263SRyan.Wang@Sun.COM 		if (obj_get_attr(raid_tab, obj_id,
37158263SRyan.Wang@Sun.COM 		    (void **)&hsp_attr) >= SUCCESS) {
37168263SRyan.Wang@Sun.COM 			if (((hsp_attr->type == HSP_TYPE_GLOBAL) &&
37178263SRyan.Wang@Sun.COM 			    (array_obj_id != OBJ_ATTR_NONE)) ||
37188263SRyan.Wang@Sun.COM 			    ((hsp_attr->type == HSP_TYPE_LOCAL) &&
37198263SRyan.Wang@Sun.COM 			    (array_obj_id == OBJ_ATTR_NONE))) {
37203457Sjc156560 				free(hsp_relation);
37213457Sjc156560 				return (ERR_OP_ILLEGAL);
37223457Sjc156560 			}
37233457Sjc156560 		}
37243457Sjc156560 	}
37253457Sjc156560 
37268263SRyan.Wang@Sun.COM 	if (array_obj_id != OBJ_ATTR_NONE)
37278263SRyan.Wang@Sun.COM 		hsp_relation->array_id = array_attr->array_id;
37288263SRyan.Wang@Sun.COM 	else
37298263SRyan.Wang@Sun.COM 		hsp_relation->array_id = (uint32_t)OBJ_ATTR_NONE;
37308263SRyan.Wang@Sun.COM 	hsp_relation->disk_id = disk_attr->disk_id;
37313457Sjc156560 
37323457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
37333457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
37343457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
37353457Sjc156560 		return (ERR_DRIVER_CLOSED);
37363457Sjc156560 
37373457Sjc156560 	if (raid_lib->hsp_bind == NULL) {
37383457Sjc156560 		free(hsp_relation);
37393457Sjc156560 		return (ERR_OP_NO_IMPL);
37403457Sjc156560 	}
37413457Sjc156560 
37423457Sjc156560 	ret = raid_lib->hsp_bind(controller_attr->controller_id,
37438263SRyan.Wang@Sun.COM 	    hsp_relation, plugin_err_str);
37443457Sjc156560 
37453457Sjc156560 	free(hsp_relation);
37463457Sjc156560 	return (ret);
37473457Sjc156560 }
37483457Sjc156560 
37493457Sjc156560 static int
obj_hsp_unbind(raid_obj_tab_t * raid_tab,raid_obj_id_t * obj_ids,char ** plugin_err_str)37508263SRyan.Wang@Sun.COM obj_hsp_unbind(raid_obj_tab_t *raid_tab, raid_obj_id_t *obj_ids,
37513457Sjc156560 	char **plugin_err_str)
37523457Sjc156560 {
37533457Sjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
37543457Sjc156560 	raid_obj_id_t array_obj_id, disk_obj_id;
37553457Sjc156560 	hsp_relation_t *hsp_relation;
37563457Sjc156560 	controller_attr_t *controller_attr;
37573457Sjc156560 	array_attr_t *array_attr;
37583457Sjc156560 	disk_attr_t *disk_attr;
37593457Sjc156560 	hsp_attr_t *hsp_attr;
37603457Sjc156560 	raid_lib_t *raid_lib;
37618263SRyan.Wang@Sun.COM 	int ret, fd;
37628263SRyan.Wang@Sun.COM 
37638263SRyan.Wang@Sun.COM 	hsp_relation = malloc(sizeof (hsp_relation_t));
37643457Sjc156560 	if (hsp_relation == NULL)
37653457Sjc156560 		return (ERR_NOMEM);
37663457Sjc156560 
37678263SRyan.Wang@Sun.COM 	array_obj_id = *(obj_ids);
37688263SRyan.Wang@Sun.COM 	disk_obj_id = *(obj_ids + 1);
37698263SRyan.Wang@Sun.COM 
37708263SRyan.Wang@Sun.COM 	if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK) {
37718263SRyan.Wang@Sun.COM 		free(hsp_relation);
37728263SRyan.Wang@Sun.COM 		return (ERR_DEVICE_TYPE);
37738263SRyan.Wang@Sun.COM 	}
37748263SRyan.Wang@Sun.COM 
37758263SRyan.Wang@Sun.COM 	/* Get controller attributes */
37768263SRyan.Wang@Sun.COM 	if (controller_obj_id == OBJ_NONE)
37778263SRyan.Wang@Sun.COM 		controller_obj_id = obj_get_controller(raid_tab,
37788263SRyan.Wang@Sun.COM 		    disk_obj_id);
37798263SRyan.Wang@Sun.COM 	else if (controller_obj_id != obj_get_controller(raid_tab,
37808263SRyan.Wang@Sun.COM 	    disk_obj_id)) {
37818263SRyan.Wang@Sun.COM 		free(hsp_relation);
37828263SRyan.Wang@Sun.COM 		return (ERR_DRIVER_ACROSS);
37838263SRyan.Wang@Sun.COM 	}
37848263SRyan.Wang@Sun.COM 
37858263SRyan.Wang@Sun.COM 	ret = obj_get_attr(raid_tab, controller_obj_id,
37868263SRyan.Wang@Sun.COM 	    (void **)(&controller_attr));
37878263SRyan.Wang@Sun.COM 
37888263SRyan.Wang@Sun.COM 	/* Get disk attributes */
37898263SRyan.Wang@Sun.COM 	ret = obj_get_attr(raid_tab,  disk_obj_id,
37908263SRyan.Wang@Sun.COM 	    (void **)(&disk_attr));
37918263SRyan.Wang@Sun.COM 	if (disk_attr->state == DISK_STATE_FAILED) {
37928263SRyan.Wang@Sun.COM 		free(hsp_relation);
37938263SRyan.Wang@Sun.COM 		return (ERR_DISK_STATE);
37948263SRyan.Wang@Sun.COM 	}
37958263SRyan.Wang@Sun.COM 
37968263SRyan.Wang@Sun.COM 	/* If it's not a hsp disk */
37978263SRyan.Wang@Sun.COM 	obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
37988263SRyan.Wang@Sun.COM 	if (obj_id == OBJ_NONE) {
37998263SRyan.Wang@Sun.COM 		free(hsp_relation);
38008263SRyan.Wang@Sun.COM 		return (ERR_DISK_STATE);
38018263SRyan.Wang@Sun.COM 	}
38028263SRyan.Wang@Sun.COM 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
38038263SRyan.Wang@Sun.COM 
38048263SRyan.Wang@Sun.COM 	if (array_obj_id != OBJ_ATTR_NONE) {
38058263SRyan.Wang@Sun.COM 		if (raid_obj_get_type(raid_tab, array_obj_id) !=
38068263SRyan.Wang@Sun.COM 		    OBJ_TYPE_ARRAY) {
38073457Sjc156560 			free(hsp_relation);
38083457Sjc156560 			return (ERR_DEVICE_TYPE);
38093457Sjc156560 		}
38103457Sjc156560 
38118263SRyan.Wang@Sun.COM 		/* Get array attributes */
38128263SRyan.Wang@Sun.COM 		ret = obj_get_attr(raid_tab, array_obj_id,
38138263SRyan.Wang@Sun.COM 		    (void **)(&array_attr));
38148263SRyan.Wang@Sun.COM 
38158263SRyan.Wang@Sun.COM 		/* If It's belong to another controller */
38168263SRyan.Wang@Sun.COM 		if (controller_obj_id != obj_get_controller(raid_tab,
38178263SRyan.Wang@Sun.COM 		    array_obj_id)) {
38183457Sjc156560 			free(hsp_relation);
38193457Sjc156560 			return (ERR_DRIVER_ACROSS);
38203457Sjc156560 		}
38213457Sjc156560 
38228263SRyan.Wang@Sun.COM 		/* If want to remove an array from a global hsp */
38238263SRyan.Wang@Sun.COM 		if (hsp_attr->type == HSP_TYPE_GLOBAL) {
38243457Sjc156560 			free(hsp_relation);
38253457Sjc156560 			return (ERR_OP_ILLEGAL);
38263457Sjc156560 		}
38273457Sjc156560 
38288263SRyan.Wang@Sun.COM 		do {
38298263SRyan.Wang@Sun.COM 			(void) obj_get_attr(raid_tab, obj_id,
38308263SRyan.Wang@Sun.COM 			    (void **)(&hsp_attr));
38318263SRyan.Wang@Sun.COM 
38328263SRyan.Wang@Sun.COM 			if (hsp_attr->associated_id ==
38338263SRyan.Wang@Sun.COM 			    array_attr->array_id ||
38348263SRyan.Wang@Sun.COM 			    hsp_attr->type == HSP_TYPE_GLOBAL)
38358263SRyan.Wang@Sun.COM 				break;
38368263SRyan.Wang@Sun.COM 
38378263SRyan.Wang@Sun.COM 			obj_id = obj_get_sibling(raid_tab, obj_id);
38388263SRyan.Wang@Sun.COM 		} while (obj_id > OBJ_NONE);
38398263SRyan.Wang@Sun.COM 	} else if (hsp_attr->type != HSP_TYPE_GLOBAL) {
38408263SRyan.Wang@Sun.COM 		/* if global hsp is supported */
38418263SRyan.Wang@Sun.COM 		free(hsp_relation);
38428263SRyan.Wang@Sun.COM 		return (ERR_OP_ILLEGAL);
38433457Sjc156560 	}
38443457Sjc156560 
38458263SRyan.Wang@Sun.COM 	/*
38468263SRyan.Wang@Sun.COM 	 * If array is associated with a local hsp, or remove a
38478263SRyan.Wang@Sun.COM 	 * global hsp disk
38488263SRyan.Wang@Sun.COM 	 */
38498263SRyan.Wang@Sun.COM 	if ((obj_id && (array_obj_id != OBJ_ATTR_NONE)) ||
38508263SRyan.Wang@Sun.COM 	    (array_obj_id == OBJ_ATTR_NONE)) {
38518263SRyan.Wang@Sun.COM 		if (array_obj_id != OBJ_ATTR_NONE)
38528263SRyan.Wang@Sun.COM 			hsp_relation->array_id = array_attr->array_id;
38538263SRyan.Wang@Sun.COM 		else
38548263SRyan.Wang@Sun.COM 			hsp_relation->array_id =
38558263SRyan.Wang@Sun.COM 			    (uint32_t)OBJ_ATTR_NONE;
38568263SRyan.Wang@Sun.COM 		hsp_relation->disk_id = disk_attr->disk_id;
38578263SRyan.Wang@Sun.COM 	} else {
38588263SRyan.Wang@Sun.COM 		free(hsp_relation);
38598263SRyan.Wang@Sun.COM 		return (ERR_OP_ILLEGAL);
38608263SRyan.Wang@Sun.COM 	}
38613457Sjc156560 
38623457Sjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
38633457Sjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
38643457Sjc156560 	if ((raid_lib == NULL) || (fd == 0))
38653457Sjc156560 		return (ERR_DRIVER_CLOSED);
38663457Sjc156560 
38673457Sjc156560 	if (raid_lib->hsp_unbind == NULL) {
38683457Sjc156560 		free(hsp_relation);
38693457Sjc156560 		return (ERR_OP_NO_IMPL);
38703457Sjc156560 	}
38713457Sjc156560 
38723457Sjc156560 	ret = raid_lib->hsp_unbind(controller_attr->controller_id,
38738263SRyan.Wang@Sun.COM 	    hsp_relation, plugin_err_str);
38743457Sjc156560 
38753457Sjc156560 	free(hsp_relation);
38763457Sjc156560 	return (ret);
38773457Sjc156560 }
38783457Sjc156560 
38793457Sjc156560 /*
38803457Sjc156560  * Object maintennance routines
38813457Sjc156560  */
38823457Sjc156560 static int
raid_obj_create_system_obj(raid_obj_tab_t * raid_tab)38833457Sjc156560 raid_obj_create_system_obj(raid_obj_tab_t *raid_tab)
38843457Sjc156560 {
38853457Sjc156560 	raid_obj_t *raid_obj;
38863457Sjc156560 	int ret;
38873457Sjc156560 
38883457Sjc156560 	raid_obj = calloc(1, sizeof (raid_obj_t));
38893457Sjc156560 	if (raid_obj == NULL)
38903457Sjc156560 		return (ERR_NOMEM);
38913457Sjc156560 
38923457Sjc156560 	raid_obj->obj_id = OBJ_SYSTEM;
38933457Sjc156560 	raid_obj->obj_type_id = OBJ_TYPE_SYSTEM;
38943457Sjc156560 	raid_obj->data = NULL;
38953457Sjc156560 
38963457Sjc156560 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
38973457Sjc156560 	if (ret == ERR_DEVICE_DUP) {
38983457Sjc156560 		free(raid_obj);
38993457Sjc156560 		return (ERR_DEVICE_UNCLEAN);
39003457Sjc156560 	}
39013457Sjc156560 
39023457Sjc156560 	return (SUCCESS);
39033457Sjc156560 }
39043457Sjc156560 
39053457Sjc156560 static raid_obj_id_t
raid_obj_id_new(raid_obj_tab_t * raid_tab)39063457Sjc156560 raid_obj_id_new(raid_obj_tab_t *raid_tab)
39073457Sjc156560 {
39083457Sjc156560 	++ raid_tab->obj_id_cnt;
39093457Sjc156560 	if (raid_tab->obj_id_cnt <= 0)
39103457Sjc156560 		return (ERR_DEVICE_OVERFLOW);
39113457Sjc156560 
39123457Sjc156560 	return (raid_tab->obj_id_cnt);
39133457Sjc156560 }
39143457Sjc156560 
39153457Sjc156560 static void *
raid_obj_attr_new(raid_obj_type_id_t obj_type)39163457Sjc156560 raid_obj_attr_new(raid_obj_type_id_t obj_type)
39173457Sjc156560 {
39183457Sjc156560 	void *obj_attr = NULL;
39193457Sjc156560 
39203457Sjc156560 	switch (obj_type) {
39213457Sjc156560 	case	OBJ_TYPE_CONTROLLER:
39223457Sjc156560 		obj_attr = calloc(1, sizeof (controller_attr_t));
39233457Sjc156560 		break;
39243457Sjc156560 	case	OBJ_TYPE_ARRAY:
39253457Sjc156560 		obj_attr = calloc(1, sizeof (array_attr_t));
39263457Sjc156560 		break;
39273457Sjc156560 	case	OBJ_TYPE_DISK:
39283457Sjc156560 		obj_attr = calloc(1, sizeof (disk_attr_t));
39293457Sjc156560 		break;
39303457Sjc156560 	case	OBJ_TYPE_HSP:
39313457Sjc156560 		obj_attr = calloc(1, sizeof (hsp_attr_t));
39323457Sjc156560 		break;
39333457Sjc156560 	case	OBJ_TYPE_ARRAY_PART:
39343457Sjc156560 		obj_attr = calloc(1, sizeof (arraypart_attr_t));
39353457Sjc156560 		break;
39363457Sjc156560 	case	OBJ_TYPE_DISK_SEG:
39373457Sjc156560 		obj_attr = calloc(1, sizeof (diskseg_attr_t));
39383457Sjc156560 		break;
39393457Sjc156560 	case	OBJ_TYPE_TASK:
39403457Sjc156560 		obj_attr = calloc(1, sizeof (task_attr_t));
39413457Sjc156560 		break;
39427233Syw161884 	case	OBJ_TYPE_PROP:
39437233Syw161884 		obj_attr = calloc(1, sizeof (property_attr_t));
39447233Syw161884 		break;
39453457Sjc156560 	default:
39463457Sjc156560 		break;
39473457Sjc156560 	}
39483457Sjc156560 
39493457Sjc156560 	return (obj_attr);
39503457Sjc156560 }
39513457Sjc156560 
39523457Sjc156560 static raid_obj_id_t
raid_obj_create(raid_obj_tab_t * raid_tab,raid_obj_type_id_t obj_type)39533457Sjc156560 raid_obj_create(raid_obj_tab_t *raid_tab, raid_obj_type_id_t obj_type)
39543457Sjc156560 {
39553457Sjc156560 	raid_obj_t *raid_obj;
39563457Sjc156560 	int ret;
39573457Sjc156560 	void *data_ptr;
39583457Sjc156560 
39593457Sjc156560 	raid_obj = calloc(1, sizeof (raid_obj_t));
39603457Sjc156560 	if (raid_obj == NULL)
39613457Sjc156560 		return (ERR_NOMEM);
39623457Sjc156560 
39633457Sjc156560 	raid_obj->obj_id = raid_obj_id_new(raid_tab);
39643457Sjc156560 	if (raid_obj->obj_id < OBJ_NONE)
39653457Sjc156560 		return (ERR_DEVICE_OVERFLOW);
39663457Sjc156560 
39673457Sjc156560 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
39683457Sjc156560 	if (ret == ERR_DEVICE_DUP) {
39693457Sjc156560 		free(raid_obj);
39703457Sjc156560 		return (ERR_DEVICE_DUP);
39713457Sjc156560 	}
39723457Sjc156560 
39733457Sjc156560 	data_ptr = raid_obj_attr_new(obj_type);
39743457Sjc156560 	if (data_ptr == NULL) {
39753457Sjc156560 		(void) raid_obj_delete(raid_tab, raid_obj->obj_id);
39763457Sjc156560 		return (ERR_NOMEM);
39773457Sjc156560 	}
39783457Sjc156560 
39793457Sjc156560 	(void) raid_obj_set_data_ptr(raid_tab, raid_obj->obj_id, data_ptr);
39803457Sjc156560 
39813457Sjc156560 	(void) raid_obj_set_type(raid_tab, raid_obj->obj_id, obj_type);
39823457Sjc156560 	return (raid_obj->obj_id);
39833457Sjc156560 }
39843457Sjc156560 
39853457Sjc156560 static int
raid_obj_delete(raid_obj_tab_t * raid_tab,raid_obj_id_t raid_obj_id)39863457Sjc156560 raid_obj_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t raid_obj_id)
39873457Sjc156560 {
39883457Sjc156560 	raid_obj_t *obj;
39893457Sjc156560 
39903457Sjc156560 	obj = raid_obj_tab_remove(raid_tab, raid_obj_id);
39913457Sjc156560 	if (obj != NULL) {
39923457Sjc156560 		free(obj->data);
39933457Sjc156560 		free(obj);
39943457Sjc156560 		return (SUCCESS);
39953457Sjc156560 	}
39963457Sjc156560 
39973457Sjc156560 	return (ERR_DEVICE_NOENT);
39983457Sjc156560 }
39993457Sjc156560 
40003457Sjc156560 static int
raid_obj_add_org(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_id_t container_id)40013457Sjc156560 raid_obj_add_org(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
40023457Sjc156560 	raid_obj_id_t container_id)
40033457Sjc156560 {
40043457Sjc156560 	raid_obj_id_t tmp, tmp1;
40053457Sjc156560 
40063457Sjc156560 	tmp = raid_obj_get_comp(raid_tab, container_id);
40073457Sjc156560 	if (tmp < OBJ_NONE)
40083457Sjc156560 		return (ERR_DEVICE_NOENT);
40093457Sjc156560 
40103457Sjc156560 	if (tmp == OBJ_NONE) {
40113457Sjc156560 		(void) raid_obj_set_container(raid_tab, obj_id, container_id);
40123457Sjc156560 		(void) raid_obj_set_comp(raid_tab, container_id, obj_id);
40133457Sjc156560 		return (SUCCESS);
40143457Sjc156560 	}
40153457Sjc156560 
40163457Sjc156560 	while ((tmp1 = raid_obj_get_sibling(raid_tab, tmp)) != OBJ_NONE)
40173457Sjc156560 		tmp = tmp1;
40183457Sjc156560 
40193457Sjc156560 	if (raid_obj_set_sibling(raid_tab, tmp, obj_id) < SUCCESS)
40203457Sjc156560 		return (ERR_DEVICE_NOENT);
40213457Sjc156560 	(void) raid_obj_set_container(raid_tab, obj_id, container_id);
40223457Sjc156560 
40233457Sjc156560 	return (SUCCESS);
40243457Sjc156560 }
40253457Sjc156560 
40263457Sjc156560 static raid_obj_type_id_t
raid_obj_get_type(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)40273457Sjc156560 raid_obj_get_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
40283457Sjc156560 {
40293457Sjc156560 	raid_obj_t *obj;
40303457Sjc156560 
40313457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
40323457Sjc156560 	if (obj == NULL)
40333457Sjc156560 		return (ERR_DEVICE_NOENT);
40343457Sjc156560 
40353457Sjc156560 	if ((obj->obj_type_id < OBJ_TYPE_SYSTEM) ||
40364563Syw161884 	    (obj->obj_type_id >= OBJ_TYPE_ALL))
40373457Sjc156560 		return (ERR_DEVICE_INVALID);
40383457Sjc156560 
40393457Sjc156560 	return (obj->obj_type_id);
40403457Sjc156560 }
40413457Sjc156560 
40423457Sjc156560 static int
raid_obj_set_type(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t type)40433457Sjc156560 raid_obj_set_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
40443457Sjc156560 	raid_obj_type_id_t type)
40453457Sjc156560 {
40463457Sjc156560 	raid_obj_t *obj;
40473457Sjc156560 
40483457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
40493457Sjc156560 	if (obj == NULL)
40503457Sjc156560 		return (ERR_DEVICE_NOENT);
40513457Sjc156560 
40523457Sjc156560 	if ((type < OBJ_TYPE_SYSTEM) || (type >= OBJ_TYPE_ALL))
40533457Sjc156560 		return (ERR_DEVICE_TYPE);
40543457Sjc156560 
40553457Sjc156560 	obj->obj_type_id = type;
40563457Sjc156560 	return (SUCCESS);
40573457Sjc156560 }
40583457Sjc156560 
40593457Sjc156560 static raid_obj_status_t
raid_obj_get_status(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)40603457Sjc156560 raid_obj_get_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
40613457Sjc156560 {
40623457Sjc156560 	raid_obj_t *obj;
40633457Sjc156560 
40643457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
40653457Sjc156560 	if (obj == NULL)
40663457Sjc156560 		return (ERR_DEVICE_NOENT);
40673457Sjc156560 
40683457Sjc156560 	return (obj->status);
40693457Sjc156560 }
40703457Sjc156560 
40713457Sjc156560 static int
raid_obj_set_status(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_status_t status)40723457Sjc156560 raid_obj_set_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
40733457Sjc156560 	raid_obj_status_t status)
40743457Sjc156560 {
40753457Sjc156560 	raid_obj_t *obj;
40763457Sjc156560 
40773457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
40783457Sjc156560 	if (obj == NULL)
40793457Sjc156560 		return (ERR_DEVICE_NOENT);
40803457Sjc156560 
40813457Sjc156560 	obj->status = obj->status | status;
40823457Sjc156560 
40833457Sjc156560 	return (SUCCESS);
40843457Sjc156560 }
40853457Sjc156560 
40863457Sjc156560 static int
raid_obj_clear_status(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_status_t status)40873457Sjc156560 raid_obj_clear_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
40883457Sjc156560 	raid_obj_status_t status)
40893457Sjc156560 {
40903457Sjc156560 	raid_obj_t *obj;
40913457Sjc156560 
40923457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
40933457Sjc156560 	if (obj == NULL)
40943457Sjc156560 		return (ERR_DEVICE_NOENT);
40953457Sjc156560 
40963457Sjc156560 	obj->status = obj->status & ~status;
40973457Sjc156560 
40983457Sjc156560 	return (SUCCESS);
40993457Sjc156560 }
41003457Sjc156560 
41013457Sjc156560 static raid_obj_id_t
raid_obj_get_container(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)41023457Sjc156560 raid_obj_get_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
41033457Sjc156560 {
41043457Sjc156560 	raid_obj_t *obj;
41053457Sjc156560 
41063457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
41073457Sjc156560 	if (obj == NULL)
41083457Sjc156560 		return (ERR_DEVICE_NOENT);
41093457Sjc156560 
41103457Sjc156560 	return (obj->container);
41113457Sjc156560 }
41123457Sjc156560 
41133457Sjc156560 static int
raid_obj_set_container(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_id_t container_id)41143457Sjc156560 raid_obj_set_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
41153457Sjc156560 	raid_obj_id_t container_id)
41163457Sjc156560 {
41173457Sjc156560 	raid_obj_t *obj;
41183457Sjc156560 
41193457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
41203457Sjc156560 	if (obj == NULL)
41213457Sjc156560 		return (ERR_DEVICE_NOENT);
41223457Sjc156560 
41233457Sjc156560 	obj->container = container_id;
41243457Sjc156560 	return (SUCCESS);
41253457Sjc156560 }
41263457Sjc156560 
41273457Sjc156560 static raid_obj_id_t
raid_obj_get_comp(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)41283457Sjc156560 raid_obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
41293457Sjc156560 {
41303457Sjc156560 	raid_obj_t *obj;
41313457Sjc156560 
41323457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
41333457Sjc156560 	if (obj == NULL)
41343457Sjc156560 		return (ERR_DEVICE_NOENT);
41353457Sjc156560 
41363457Sjc156560 	return (obj->component);
41373457Sjc156560 }
41383457Sjc156560 
41393457Sjc156560 static int
raid_obj_set_comp(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_id_t comp)41403457Sjc156560 raid_obj_set_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
41413457Sjc156560 	raid_obj_id_t comp)
41423457Sjc156560 {
41433457Sjc156560 	raid_obj_t *obj;
41443457Sjc156560 
41453457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
41463457Sjc156560 	if (obj == NULL)
41473457Sjc156560 		return (ERR_DEVICE_NOENT);
41483457Sjc156560 
41493457Sjc156560 	obj->component = comp;
41503457Sjc156560 	return (SUCCESS);
41513457Sjc156560 }
41523457Sjc156560 
41533457Sjc156560 static raid_obj_id_t
raid_obj_get_sibling(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)41543457Sjc156560 raid_obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
41553457Sjc156560 {
41563457Sjc156560 	raid_obj_t *obj;
41573457Sjc156560 
41583457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
41593457Sjc156560 	if (obj == NULL)
41603457Sjc156560 		return (ERR_DEVICE_NOENT);
41613457Sjc156560 
41623457Sjc156560 	return (obj->sibling);
41633457Sjc156560 }
41643457Sjc156560 
41653457Sjc156560 static int
raid_obj_set_sibling(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_id_t sibling)41663457Sjc156560 raid_obj_set_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
41673457Sjc156560 	raid_obj_id_t sibling)
41683457Sjc156560 {
41693457Sjc156560 	raid_obj_t *obj;
41703457Sjc156560 
41713457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
41723457Sjc156560 	if (obj == NULL)
41733457Sjc156560 		return (ERR_DEVICE_NOENT);
41743457Sjc156560 
41753457Sjc156560 	obj->sibling = sibling;
41763457Sjc156560 
41773457Sjc156560 	return (SUCCESS);
41783457Sjc156560 }
41793457Sjc156560 
41803457Sjc156560 static void *
raid_obj_get_data_ptr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)41813457Sjc156560 raid_obj_get_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
41823457Sjc156560 {
41833457Sjc156560 	raid_obj_t *obj;
41843457Sjc156560 
41853457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
41863457Sjc156560 	if (obj == NULL)
41873457Sjc156560 		return (NULL);
41883457Sjc156560 
41893457Sjc156560 	return (obj->data);
41903457Sjc156560 }
41913457Sjc156560 
41923457Sjc156560 static int
raid_obj_set_data_ptr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,void * data)41933457Sjc156560 raid_obj_set_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
41943457Sjc156560 	void *data)
41953457Sjc156560 {
41963457Sjc156560 	raid_obj_t *obj;
41973457Sjc156560 
41983457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
41993457Sjc156560 	if (obj == NULL)
42003457Sjc156560 		return (ERR_DEVICE_NOENT);
42013457Sjc156560 
42023457Sjc156560 	obj->data = data;
42033457Sjc156560 
42043457Sjc156560 	return (SUCCESS);
42053457Sjc156560 }
42063457Sjc156560 
42073457Sjc156560 static raid_obj_handle_t
raid_obj_get_handle(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)42083457Sjc156560 raid_obj_get_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
42093457Sjc156560 {
42103457Sjc156560 	raid_obj_t *obj;
42113457Sjc156560 
42123457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
42133457Sjc156560 	if (obj == NULL)
42143457Sjc156560 		return (ERR_DEVICE_NOENT);
42153457Sjc156560 
42163457Sjc156560 	return (obj->handle);
42173457Sjc156560 }
42183457Sjc156560 
42193457Sjc156560 static int
raid_obj_set_handle(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_handle_t handle)42203457Sjc156560 raid_obj_set_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
42213457Sjc156560 	raid_obj_handle_t handle)
42223457Sjc156560 {
42233457Sjc156560 	raid_obj_t *obj;
42243457Sjc156560 
42253457Sjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
42263457Sjc156560 	if (obj == NULL)
42273457Sjc156560 		return (ERR_DEVICE_NOENT);
42283457Sjc156560 
42293457Sjc156560 	obj->handle = handle;
42303457Sjc156560 	return (SUCCESS);
42313457Sjc156560 }
42323457Sjc156560 /*
42333457Sjc156560  * Object list maintennance routines
42343457Sjc156560  */
42353457Sjc156560 static void
raid_list_create(raid_list_t * list,size_t offset)42363457Sjc156560 raid_list_create(raid_list_t *list, size_t offset)
42373457Sjc156560 {
42383457Sjc156560 	list->head = NULL;
42393457Sjc156560 	list->tail = NULL;
42403457Sjc156560 	list->offset = offset;
42413457Sjc156560 }
42423457Sjc156560 
42433457Sjc156560 static void *
raid_list_head(raid_list_t * list)42443457Sjc156560 raid_list_head(raid_list_t *list)
42453457Sjc156560 {
42463457Sjc156560 	return (list->head);
42473457Sjc156560 }
42483457Sjc156560 
42493457Sjc156560 static void *
raid_list_next(raid_list_t * list,void * obj)42503457Sjc156560 raid_list_next(raid_list_t *list, void *obj)
42513457Sjc156560 {
42523457Sjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj);
42533457Sjc156560 
42543457Sjc156560 	return (el->next);
42553457Sjc156560 }
42563457Sjc156560 
42573457Sjc156560 static void
raid_list_insert_tail(raid_list_t * list,void * obj)42583457Sjc156560 raid_list_insert_tail(raid_list_t *list, void *obj)
42593457Sjc156560 {
42603457Sjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
42613457Sjc156560 
42623457Sjc156560 	el->prev = list->tail;
42633457Sjc156560 	list->tail = obj;
42643457Sjc156560 
42653457Sjc156560 	el->next = NULL;
42663457Sjc156560 
42673457Sjc156560 	if (list->head == NULL)
42683457Sjc156560 		list->head = obj;
42693457Sjc156560 
42703457Sjc156560 	if (el->prev != NULL) {
42713457Sjc156560 		el1 = LIST_OBJ_TO_EL(list, el->prev);
42723457Sjc156560 		el1->next = obj;
42733457Sjc156560 	}
42743457Sjc156560 }
42753457Sjc156560 
42763457Sjc156560 static void
raid_list_remove(raid_list_t * list,void * obj)42773457Sjc156560 raid_list_remove(raid_list_t *list, void *obj)
42783457Sjc156560 {
42793457Sjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
42803457Sjc156560 
42813457Sjc156560 	if (list->head == obj)
42823457Sjc156560 		list->head = el->next;
42833457Sjc156560 
42843457Sjc156560 	if (list->tail == obj)
42853457Sjc156560 		list->tail = el->prev;
42863457Sjc156560 
42873457Sjc156560 	if (el->next != NULL) {
42883457Sjc156560 		el1 = LIST_OBJ_TO_EL(list, el->next);
42893457Sjc156560 		el1->prev = el->prev;
42903457Sjc156560 	}
42913457Sjc156560 
42923457Sjc156560 	if (el->prev != NULL) {
42933457Sjc156560 		el1 = LIST_OBJ_TO_EL(list, el->prev);
42943457Sjc156560 		el1->next = el->next;
42953457Sjc156560 	}
42963457Sjc156560 
42973457Sjc156560 	el->prev = el->next = NULL;
42983457Sjc156560 }
42993457Sjc156560 
43003457Sjc156560 static void *
raid_list_remove_head(raid_list_t * list)43013457Sjc156560 raid_list_remove_head(raid_list_t *list)
43023457Sjc156560 {
43033457Sjc156560 	void *obj = list->head;
43043457Sjc156560 
43053457Sjc156560 	if (obj != NULL)
43063457Sjc156560 		raid_list_remove(list, obj);
43073457Sjc156560 
43083457Sjc156560 	return (obj);
43093457Sjc156560 }
43103457Sjc156560 
43113457Sjc156560 static void *
raid_list_find(raid_list_t * list,raid_obj_id_t obj_id)43123457Sjc156560 raid_list_find(raid_list_t *list, raid_obj_id_t obj_id)
43133457Sjc156560 {
43143457Sjc156560 	raid_obj_t *obj;
43153457Sjc156560 
43163457Sjc156560 	for (obj = raid_list_head(list); obj != NULL;
43174563Syw161884 	    obj = raid_list_next(list, obj))
43183457Sjc156560 			if (obj->obj_id == obj_id)
43193457Sjc156560 				break;
43203457Sjc156560 
43213457Sjc156560 	return (obj);
43223457Sjc156560 }
43233457Sjc156560 
43243457Sjc156560 static int
raid_obj_tab_create(raid_obj_tab_t * tab,size_t hash_slots)43253457Sjc156560 raid_obj_tab_create(raid_obj_tab_t *tab, size_t hash_slots)
43263457Sjc156560 {
43273457Sjc156560 	unsigned i;
43283457Sjc156560 
43293457Sjc156560 	if (hash_slots == 0)
43303457Sjc156560 		return (ERR_OP_ILLEGAL);
43313457Sjc156560 
43323457Sjc156560 	tab->slots = hash_slots;
43333457Sjc156560 
43343457Sjc156560 	if ((tab->table = calloc(hash_slots, sizeof (raid_list_t))) == NULL)
43353457Sjc156560 		return (ERR_NOMEM);
43363457Sjc156560 
43373457Sjc156560 	for (i = 0; i < hash_slots; i++)
43383457Sjc156560 		raid_list_create(&tab->table[i], offsetof(raid_obj_t, el));
43393457Sjc156560 
43403457Sjc156560 	return (SUCCESS);
43413457Sjc156560 }
43423457Sjc156560 
43433457Sjc156560 static void
raid_obj_tab_destroy(raid_obj_tab_t * tab)43443457Sjc156560 raid_obj_tab_destroy(raid_obj_tab_t *tab)
43453457Sjc156560 {
43463457Sjc156560 	unsigned i;
43473457Sjc156560 
43483457Sjc156560 	for (i = 0; i < tab->slots; i++) {
43493457Sjc156560 		struct raid_obj_t *obj;
43503457Sjc156560 
43513457Sjc156560 		while ((obj = raid_list_remove_head(&tab->table[i])) != NULL)
43523457Sjc156560 			free(obj);
43533457Sjc156560 
43543457Sjc156560 		raid_list_destroy(&tab->table[i]);
43553457Sjc156560 	}
43563457Sjc156560 
43573457Sjc156560 	if (tab->table)
43583457Sjc156560 		free(tab->table);
43593457Sjc156560 
43603457Sjc156560 	tab->table = NULL;
43613457Sjc156560 	tab->slots = 0;
43623457Sjc156560 	tab->obj_id_cnt = 0;
43633457Sjc156560 }
43643457Sjc156560 
43653457Sjc156560 static int
raid_obj_tab_insert(raid_obj_tab_t * tab,raid_obj_id_t id,void * obj)43663457Sjc156560 raid_obj_tab_insert(raid_obj_tab_t *tab, raid_obj_id_t id, void *obj)
43673457Sjc156560 {
43683457Sjc156560 	raid_list_t *list;
43693457Sjc156560 
43703457Sjc156560 	list = OBJ_TAB_SLOT(tab, id);
43713457Sjc156560 
43723457Sjc156560 	if (raid_list_find(list, id) != NULL)
43733457Sjc156560 		return (ERR_DEVICE_DUP);
43743457Sjc156560 
43753457Sjc156560 	raid_list_insert_tail(list, obj);
43763457Sjc156560 
43773457Sjc156560 	return (SUCCESS);
43783457Sjc156560 }
43793457Sjc156560 
43803457Sjc156560 static void *
raid_obj_tab_remove(raid_obj_tab_t * tab,raid_obj_id_t id)43813457Sjc156560 raid_obj_tab_remove(raid_obj_tab_t *tab, raid_obj_id_t id)
43823457Sjc156560 {
43833457Sjc156560 	raid_list_t *list;
43843457Sjc156560 	raid_obj_t *obj;
43853457Sjc156560 
43863457Sjc156560 	list = OBJ_TAB_SLOT(tab, id);
43873457Sjc156560 
43883457Sjc156560 	if ((obj = raid_list_find(list, id)) != NULL)
43893457Sjc156560 		raid_list_remove(list, obj);
43903457Sjc156560 
43913457Sjc156560 	return (obj);
43923457Sjc156560 }
43933457Sjc156560 
43943457Sjc156560 static void *
raid_obj_tab_find(raid_obj_tab_t * tab,raid_obj_id_t id)43953457Sjc156560 raid_obj_tab_find(raid_obj_tab_t *tab, raid_obj_id_t id)
43963457Sjc156560 {
43973457Sjc156560 	raid_list_t *list;
43983457Sjc156560 	raid_obj_t *obj;
43993457Sjc156560 
44003457Sjc156560 	list = OBJ_TAB_SLOT(tab, id);
44013457Sjc156560 	obj = raid_list_find(list, id);
44023457Sjc156560 
44033457Sjc156560 	return (obj);
44043457Sjc156560 }
44053457Sjc156560 
44063457Sjc156560 static void
raid_list_destroy(raid_list_t * list)44073457Sjc156560 raid_list_destroy(raid_list_t *list)
44083457Sjc156560 {
44093457Sjc156560 	list->head = NULL;
44103457Sjc156560 	list->tail = NULL;
44113457Sjc156560 	list->offset = 0;
44123457Sjc156560 }
44133457Sjc156560 
44143457Sjc156560 /*
44153457Sjc156560  * Plug-in maintennance routines
44163457Sjc156560  */
44173457Sjc156560 static int
controller_id_to_path(uint32_t controller_id,char * path)44183457Sjc156560 controller_id_to_path(uint32_t controller_id, char *path)
44193457Sjc156560 {
44207336SRyan.Wang@Sun.COM 	int fd;
44213457Sjc156560 	char buf[MAX_PATH_LEN] = {0}, buf1[MAX_PATH_LEN] = {0}, *colon;
44223457Sjc156560 
44233457Sjc156560 	(void) snprintf(buf, MAX_PATH_LEN, "%s/c%d", CFGDIR, controller_id);
44243457Sjc156560 	if (readlink(buf, buf1, sizeof (buf1)) < 0)
44253457Sjc156560 		return (ERR_DRIVER_NOT_FOUND);
44263457Sjc156560 
44273457Sjc156560 	if (buf1[0] != '/')
44283457Sjc156560 		(void) snprintf(buf, sizeof (buf), "%s/", CFGDIR);
44293457Sjc156560 	else
44303457Sjc156560 		buf[0] = 0;
44313457Sjc156560 	(void) strlcat(buf, buf1, MAX_PATH_LEN);
44323457Sjc156560 
44333457Sjc156560 	colon = strrchr(buf, ':');
44343457Sjc156560 	if (colon == NULL)
44353457Sjc156560 		return (ERR_DRIVER_NOT_FOUND);
44363457Sjc156560 	else
44373457Sjc156560 		*colon = 0;
44383457Sjc156560 
44393457Sjc156560 	(void) snprintf(path, MAX_PATH_LEN, "%s:devctl", buf);
44403457Sjc156560 
44417336SRyan.Wang@Sun.COM 	fd = open(path, O_RDONLY | O_NDELAY);
44427336SRyan.Wang@Sun.COM 
44437336SRyan.Wang@Sun.COM 	if (fd < 0)
44443457Sjc156560 		return (ERR_DRIVER_NOT_FOUND);
44453457Sjc156560 
44467336SRyan.Wang@Sun.COM 	(void) close(fd);
44477336SRyan.Wang@Sun.COM 
44483457Sjc156560 	return (SUCCESS);
44493457Sjc156560 }
44503457Sjc156560 
44513457Sjc156560 static char *
controller_id_to_driver_name(uint32_t controller_id)44523457Sjc156560 controller_id_to_driver_name(uint32_t controller_id)
44533457Sjc156560 {
44543457Sjc156560 	char buf[MAX_PATH_LEN];
44553457Sjc156560 	di_node_t di_node;
44563457Sjc156560 	char *name, *tmp;
44573457Sjc156560 	int ret;
44583457Sjc156560 
44593457Sjc156560 	ret = controller_id_to_path(controller_id, buf);
44603457Sjc156560 	if (ret < SUCCESS)
44613457Sjc156560 		return (NULL);
44623457Sjc156560 
44633457Sjc156560 	tmp = strrchr(buf, ':');
44643457Sjc156560 	if (tmp != NULL)
44653457Sjc156560 		*tmp = 0;
44663457Sjc156560 
44673457Sjc156560 	tmp = strstr(buf, "pci");
44683457Sjc156560 	if (tmp == NULL)
44693457Sjc156560 		return (NULL);
44703457Sjc156560 
44713457Sjc156560 	di_node = di_init(tmp, DINFOPROP);
44723457Sjc156560 	if (di_node == DI_NODE_NIL)
44733457Sjc156560 		return (NULL);
44743457Sjc156560 
44753457Sjc156560 	name = di_driver_name(di_node);
44763457Sjc156560 
44773457Sjc156560 	return (name);
44783457Sjc156560 }
44793457Sjc156560 
44803457Sjc156560 static void
raid_plugin_init()44813457Sjc156560 raid_plugin_init()
44823457Sjc156560 {
44833457Sjc156560 	raid_lib_t *raid_lib = raid_lib_sys;
44843457Sjc156560 
44853457Sjc156560 	while (raid_lib) {
44863457Sjc156560 		raid_lib_sys = raid_lib->next;
44873457Sjc156560 		(void) dlclose(raid_lib->lib_handle);
44883457Sjc156560 		free(raid_lib);
44893457Sjc156560 		raid_lib = raid_lib_sys;
44903457Sjc156560 	}
44913457Sjc156560 }
44923457Sjc156560 
44933457Sjc156560 static raid_lib_t *
raid_plugin_load(char * driver_name)44943457Sjc156560 raid_plugin_load(char *driver_name)
44953457Sjc156560 {
44963457Sjc156560 	char buf[MAX_PATH_LEN] = {0};
44973457Sjc156560 	raid_lib_t *supplib;
44983457Sjc156560 	void *sym;
44993457Sjc156560 
45003457Sjc156560 	supplib = calloc(1, sizeof (raid_lib_t));
45013457Sjc156560 	if (supplib == NULL)
45023457Sjc156560 		return (NULL);
45033457Sjc156560 
45043457Sjc156560 	(void) snprintf(buf, MAX_PATH_LEN, "%s/%s.so.1",
45054563Syw161884 	    SUPP_PLUGIN_DIR, driver_name);
45063457Sjc156560 
45073457Sjc156560 	supplib->lib_handle = dlopen(buf, RTLD_LAZY);
45083457Sjc156560 	if (supplib->lib_handle == NULL) {
45093457Sjc156560 		free(supplib);
45103457Sjc156560 		return (NULL);
45113457Sjc156560 	}
45123457Sjc156560 
45133457Sjc156560 	supplib->name = driver_name;
45143457Sjc156560 
45153457Sjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_version")) == NULL)
45163457Sjc156560 		supplib->version = RDCFG_PLUGIN_V1;
45173457Sjc156560 	else {
45183457Sjc156560 		supplib->version = *((uint32_t *)sym);
45193457Sjc156560 		if (supplib->version != RDCFG_PLUGIN_V1) {
45203457Sjc156560 			(void) dlclose(supplib->lib_handle);
45213457Sjc156560 			free(supplib);
45223457Sjc156560 			return (NULL);
45233457Sjc156560 		}
45243457Sjc156560 	}
45253457Sjc156560 
45263457Sjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_open_controller")) ==
45274563Syw161884 	    NULL) {
45283457Sjc156560 		(void) dlclose(supplib->lib_handle);
45293457Sjc156560 		free(supplib);
45303457Sjc156560 		return (NULL);
45313457Sjc156560 	} else
45323457Sjc156560 		supplib->open_controller = (int(*)(uint32_t, char **))sym;
45333457Sjc156560 
45343457Sjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_close_controller")) ==
45354563Syw161884 	    NULL) {
45363457Sjc156560 		(void) dlclose(supplib->lib_handle);
45373457Sjc156560 		free(supplib);
45383457Sjc156560 		return (NULL);
45393457Sjc156560 	} else
45403457Sjc156560 		supplib->close_controller = (int (*)(uint32_t, char **))sym;
45413457Sjc156560 
45423457Sjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_compnum")) == NULL) {
45433457Sjc156560 		(void) dlclose(supplib->lib_handle);
45443457Sjc156560 		free(supplib);
45453457Sjc156560 		return (NULL);
45463457Sjc156560 	} else
45473457Sjc156560 		supplib->compnum = (int (*)(uint32_t, uint32_t,
45483457Sjc156560 		    raid_obj_type_id_t, raid_obj_type_id_t))sym;
45493457Sjc156560 
45503457Sjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_complist")) == NULL) {
45513457Sjc156560 		(void) dlclose(supplib->lib_handle);
45523457Sjc156560 		free(supplib);
45533457Sjc156560 		return (NULL);
45543457Sjc156560 	} else
45553457Sjc156560 		supplib->complist = (int (*)(uint32_t, uint32_t,
45563457Sjc156560 		    raid_obj_type_id_t, raid_obj_type_id_t, int, void *))sym;
45573457Sjc156560 
45583457Sjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_get_attr")) == NULL) {
45593457Sjc156560 		(void) dlclose(supplib->lib_handle);
45603457Sjc156560 		free(supplib);
45613457Sjc156560 		return (NULL);
45623457Sjc156560 	} else
45633457Sjc156560 		supplib->get_attr = (int (*)(uint32_t, uint32_t, uint32_t,
45643457Sjc156560 		    raid_obj_type_id_t, void*))sym;
45653457Sjc156560 
45663457Sjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_create")) == NULL) {
45673457Sjc156560 		(void) dlclose(supplib->lib_handle);
45683457Sjc156560 		free(supplib);
45693457Sjc156560 		return (NULL);
45703457Sjc156560 	} else
45713457Sjc156560 		supplib->array_create = (int (*)(uint32_t, array_attr_t *, int,
45723457Sjc156560 		    arraypart_attr_t *, char **))sym;
45733457Sjc156560 
45743457Sjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_delete")) == NULL) {
45753457Sjc156560 		(void) dlclose(supplib->lib_handle);
45763457Sjc156560 		free(supplib);
45773457Sjc156560 		return (NULL);
45783457Sjc156560 	} else
45793457Sjc156560 		supplib->array_delete =
45803457Sjc156560 		    (int (*)(uint32_t, uint32_t, char **))sym;
45813457Sjc156560 
45828263SRyan.Wang@Sun.COM 	supplib->hsp_bind = (int (*)(uint32_t, hsp_relation_t *,
45833457Sjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_bind");
45848263SRyan.Wang@Sun.COM 	supplib->hsp_unbind = (int (*)(uint32_t, hsp_relation_t *,
45853457Sjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_unbind");
45863457Sjc156560 	supplib->set_attr = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t *,
45873457Sjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_set_attr");
45883457Sjc156560 	supplib->flash_fw = (int (*)(uint32_t, char *, uint32_t, char **))
45893457Sjc156560 	    dlsym(supplib->lib_handle, "rdcfg_flash_fw");
45903457Sjc156560 
45913457Sjc156560 	supplib->next = raid_lib_sys;
45923457Sjc156560 	raid_lib_sys = supplib;
45933457Sjc156560 	return (supplib);
45943457Sjc156560 }
45953457Sjc156560 
45963457Sjc156560 static raid_lib_t *
raid_find_lib(raid_obj_tab_t * raid_tab,raid_obj_id_t controller_obj_id)45973457Sjc156560 raid_find_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t controller_obj_id)
45983457Sjc156560 {
45993457Sjc156560 	controller_attr_t *controller_attr;
46003457Sjc156560 	raid_lib_t *raid_lib;
46013457Sjc156560 	char *driver_name;
46023457Sjc156560 	raid_obj_handle_t handle;
46033457Sjc156560 
46043457Sjc156560 	/* Check if it's mapped to handle structure */
46053457Sjc156560 	handle = raid_obj_to_handle(raid_tab, controller_obj_id);
46063457Sjc156560 	if (raid_handle_sys.handles[handle].raid_lib != NULL)
46073457Sjc156560 		return (raid_handle_sys.handles[handle].raid_lib);
46083457Sjc156560 
46093457Sjc156560 	(void) obj_get_attr(raid_tab, controller_obj_id,
46104563Syw161884 	    (void **)(&controller_attr));
46113457Sjc156560 
46123457Sjc156560 	/* Check if the plugin module is already loaded */
46133457Sjc156560 	driver_name = controller_id_to_driver_name(
46144563Syw161884 	    controller_attr->controller_id);
46153457Sjc156560 	if (driver_name == NULL)
46163457Sjc156560 		return (NULL);
46173457Sjc156560 
46183457Sjc156560 	raid_lib = raid_lib_sys;
46193457Sjc156560 	while (raid_lib != NULL) {
46203457Sjc156560 		if (raid_lib->name != NULL &&
46214563Syw161884 		    strcmp(driver_name, raid_lib->name) == 0)
46223457Sjc156560 			return (raid_lib);
46233457Sjc156560 
46243457Sjc156560 		raid_lib = raid_lib->next;
46253457Sjc156560 	}
46263457Sjc156560 
46273457Sjc156560 	/* Loading the plugin module */
46283457Sjc156560 	raid_lib = raid_plugin_load(driver_name);
46293457Sjc156560 
46303457Sjc156560 	return (raid_lib);
46313457Sjc156560 }
4632