xref: /titanic_50/usr/src/lib/libraidcfg/common/raidcfg.c (revision 700682b83aee7f7b038d7f1d7f262ff4bff575d5)
1711890bcSjc156560 /*
2711890bcSjc156560  * CDDL HEADER START
3711890bcSjc156560  *
4711890bcSjc156560  * The contents of this file are subject to the terms of the
5711890bcSjc156560  * Common Development and Distribution License (the "License").
6711890bcSjc156560  * You may not use this file except in compliance with the License.
7711890bcSjc156560  *
8711890bcSjc156560  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9711890bcSjc156560  * or http://www.opensolaris.org/os/licensing.
10711890bcSjc156560  * See the License for the specific language governing permissions
11711890bcSjc156560  * and limitations under the License.
12711890bcSjc156560  *
13711890bcSjc156560  * When distributing Covered Code, include this CDDL HEADER in each
14711890bcSjc156560  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15711890bcSjc156560  * If applicable, add the following below this CDDL HEADER, with the
16711890bcSjc156560  * fields enclosed by brackets "[]" replaced with your own identifying
17711890bcSjc156560  * information: Portions Copyright [yyyy] [name of copyright owner]
18711890bcSjc156560  *
19711890bcSjc156560  * CDDL HEADER END
20711890bcSjc156560  */
21711890bcSjc156560 
22711890bcSjc156560 /*
23711890bcSjc156560  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24711890bcSjc156560  * Use is subject to license terms.
25711890bcSjc156560  */
26711890bcSjc156560 
27711890bcSjc156560 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28711890bcSjc156560 
29711890bcSjc156560 #include <fcntl.h>
30711890bcSjc156560 #include <sys/types.h>
31711890bcSjc156560 #include <sys/stat.h>
32711890bcSjc156560 #include <stddef.h>
33711890bcSjc156560 #include <stdlib.h>
34711890bcSjc156560 #include <dirent.h>
35711890bcSjc156560 #include <dlfcn.h>
36711890bcSjc156560 #include <link.h>
37711890bcSjc156560 #include <strings.h>
38711890bcSjc156560 #include <stdio.h>
39711890bcSjc156560 #include <unistd.h>
40711890bcSjc156560 #include <sys/mnttab.h>
41711890bcSjc156560 #include <config_admin.h>
42711890bcSjc156560 #include <sys/param.h>
43711890bcSjc156560 #include <libintl.h>
44711890bcSjc156560 #include <libdevinfo.h>
45711890bcSjc156560 #include <raidcfg.h>
46711890bcSjc156560 #include <thread.h>
47711890bcSjc156560 #include <synch.h>
48711890bcSjc156560 
49711890bcSjc156560 #ifndef TEXT_DOMAIN
50711890bcSjc156560 #define	TEXT_DOMAIN	"SYS_TEST"
51711890bcSjc156560 #endif
52711890bcSjc156560 
53711890bcSjc156560 #define	HASH_SLOTS	16
54711890bcSjc156560 #define	HANDLER_SLOTS	256
55711890bcSjc156560 
56711890bcSjc156560 /*
57711890bcSjc156560  * Raid object status;
58711890bcSjc156560  */
59711890bcSjc156560 #define	OBJ_STATUS_CMD_CLEAN	-1
60711890bcSjc156560 #define	OBJ_STATUS_OPENED	1
61711890bcSjc156560 #define	OBJ_STATUS_SCANCOMP	1 << 1
62711890bcSjc156560 
63711890bcSjc156560 #if defined(__sparcv9)
64711890bcSjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg/sparcv9"
65711890bcSjc156560 #elif defined(__amd64)
66711890bcSjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg/amd64"
67711890bcSjc156560 #else
68711890bcSjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg"
69711890bcSjc156560 #endif
70711890bcSjc156560 
71711890bcSjc156560 /*
72711890bcSjc156560  * Basic types
73711890bcSjc156560  */
74711890bcSjc156560 typedef	int raid_obj_id_t;
75711890bcSjc156560 typedef	int raid_obj_status_t;
76711890bcSjc156560 
77711890bcSjc156560 /*
78711890bcSjc156560  * Data structures used for object maintennance
79711890bcSjc156560  */
80711890bcSjc156560 typedef	struct {
81711890bcSjc156560 	void *head;
82711890bcSjc156560 	void *tail;
83711890bcSjc156560 	size_t offset;	/* offset of double-linked element (raid_list_el_t) */
84711890bcSjc156560 			/* in the linked data structures (objects) */
85711890bcSjc156560 } raid_list_t;
86711890bcSjc156560 
87711890bcSjc156560 typedef	struct {
88711890bcSjc156560 	void *prev;
89711890bcSjc156560 	void *next;
90711890bcSjc156560 } raid_list_el_t;
91711890bcSjc156560 
92711890bcSjc156560 typedef	struct {
93711890bcSjc156560 	raid_obj_id_t obj_id_cnt;	/* id 0 is reserved */
94711890bcSjc156560 	size_t slots;			/* How many lists linked by *table */
95711890bcSjc156560 	raid_list_t *table;
96711890bcSjc156560 } raid_obj_tab_t;
97711890bcSjc156560 
98711890bcSjc156560 /*
99711890bcSjc156560  * Object type structure containing function pointers;
100711890bcSjc156560  */
101711890bcSjc156560 typedef	struct {
102711890bcSjc156560 	int (*compnum)(raid_obj_tab_t *, raid_obj_id_t, raid_obj_type_id_t);
103711890bcSjc156560 	int (*complist)(raid_obj_tab_t *, raid_obj_id_t, int, raid_obj_id_t *,
104711890bcSjc156560 		raid_obj_type_id_t);
105711890bcSjc156560 	int (*get_attr)(raid_obj_tab_t *, raid_obj_id_t);
106711890bcSjc156560 	int (*set_attr)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, uint32_t *,
107711890bcSjc156560 		char **);
108711890bcSjc156560 	int (*act)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, void *, char **);
109711890bcSjc156560 	int (*create_obj)(raid_obj_tab_t *, raid_obj_id_t, int,
110711890bcSjc156560 		raid_obj_id_t *, char **);
111711890bcSjc156560 	int (*delete_obj)(raid_obj_tab_t *, raid_obj_id_t, char **);
112711890bcSjc156560 	int (*bind_obj)(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
113711890bcSjc156560 	int (*unbind_obj)(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
114711890bcSjc156560 } raid_obj_op_t;
115711890bcSjc156560 
116711890bcSjc156560 /*
117711890bcSjc156560  * Common object data structure
118711890bcSjc156560  */
119711890bcSjc156560 typedef	struct {
120711890bcSjc156560 	raid_list_el_t		el;	/* double-links */
121711890bcSjc156560 
122711890bcSjc156560 	raid_obj_type_id_t	obj_type_id;
123711890bcSjc156560 	raid_obj_id_t		obj_id;
124711890bcSjc156560 	raid_obj_status_t	status;
125711890bcSjc156560 
126711890bcSjc156560 	raid_obj_id_t		container;
127711890bcSjc156560 	raid_obj_id_t		sibling;
128711890bcSjc156560 	raid_obj_id_t		component;
129711890bcSjc156560 
130711890bcSjc156560 	void			*data;	/* Pointer to attribute structure */
131711890bcSjc156560 	raid_obj_handle_t	handle;
132711890bcSjc156560 } raid_obj_t;
133711890bcSjc156560 
134711890bcSjc156560 /*
135711890bcSjc156560  * Definition about handle
136711890bcSjc156560  */
137711890bcSjc156560 typedef	struct {
138711890bcSjc156560 	uint32_t	next;
139711890bcSjc156560 	uint32_t	type;
140711890bcSjc156560 	uint32_t	controller_id;
141711890bcSjc156560 	uint32_t	array_id;
142711890bcSjc156560 	uint32_t	disk_id;
143711890bcSjc156560 	uint64_t	seq_id;
144711890bcSjc156560 	uint32_t	task_id;
145711890bcSjc156560 	uint32_t	fd;		/* Only for controller */
146711890bcSjc156560 	raid_lib_t	*raid_lib;	/* Only for controller */
147711890bcSjc156560 } handle_attr_t;
148711890bcSjc156560 
149711890bcSjc156560 #define	LIST_OBJ_TO_EL(list, obj)	\
150711890bcSjc156560 	((void *)((char *)(obj) + (list)->offset))
151711890bcSjc156560 #define	OBJ_TAB_SLOT(tab, id)	\
152711890bcSjc156560 	((tab)->table + ((id)%(tab)->slots))
153711890bcSjc156560 
154711890bcSjc156560 #pragma init(raidcfg_init)
155711890bcSjc156560 #pragma fini(raidcfg_fini)
156711890bcSjc156560 
157711890bcSjc156560 /*
158711890bcSjc156560  * Function prototypes
159711890bcSjc156560  */
160711890bcSjc156560 static int intcompare(const void *p1, const void *p2);
161711890bcSjc156560 static uint64_t raid_space_noalign(raid_obj_tab_t *, uint32_t, int,
162711890bcSjc156560 	raid_obj_id_t *, arraypart_attr_t *);
163711890bcSjc156560 static int raid_dev_config(cfga_cmd_t, uint32_t, uint32_t, uint8_t);
164711890bcSjc156560 static int raid_handle_init();
165711890bcSjc156560 static void raid_handle_fini();
166711890bcSjc156560 static raid_obj_handle_t raid_handle_new(raid_obj_type_id_t);
167711890bcSjc156560 static void raid_handle_delete(raid_obj_handle_t);
168711890bcSjc156560 static void raid_handle_delete_controller_comp(uint32_t);
169711890bcSjc156560 static raid_obj_id_t raid_handle_to_obj(raid_obj_tab_t *,
170711890bcSjc156560 	raid_obj_handle_t);
171711890bcSjc156560 static raid_obj_handle_t raid_obj_to_handle(raid_obj_tab_t *,
172711890bcSjc156560 	raid_obj_id_t);
173711890bcSjc156560 static raid_lib_t *raid_obj_get_lib(raid_obj_tab_t *, raid_obj_id_t);
174711890bcSjc156560 static int raid_obj_set_lib(raid_obj_tab_t *, raid_obj_id_t, raid_lib_t *);
175711890bcSjc156560 static int raid_obj_get_fd(raid_obj_tab_t *, raid_obj_id_t);
176711890bcSjc156560 static int raid_obj_set_fd(raid_obj_tab_t *, raid_obj_id_t, int);
177711890bcSjc156560 static int obj_scan_comp(raid_obj_tab_t *, raid_obj_id_t);
178711890bcSjc156560 static int obj_rescan(raid_obj_tab_t *);
179711890bcSjc156560 static raid_obj_id_t obj_get_comp(raid_obj_tab_t *, raid_obj_id_t,
180711890bcSjc156560 	raid_obj_type_id_t);
181711890bcSjc156560 static raid_obj_id_t obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
182711890bcSjc156560 static int obj_get_attr(raid_obj_tab_t *, raid_obj_id_t, void **);
183711890bcSjc156560 static raid_obj_id_t obj_locate_controller(raid_obj_tab_t *, uint32_t);
184711890bcSjc156560 static raid_obj_id_t obj_locate_array(raid_obj_tab_t *, uint32_t, uint32_t);
185711890bcSjc156560 static raid_obj_id_t obj_locate_array_recur(raid_obj_tab_t *, raid_obj_id_t,
186711890bcSjc156560 	uint32_t);
187711890bcSjc156560 static raid_obj_id_t obj_locate_hsp(raid_obj_tab_t *, uint32_t,
188711890bcSjc156560 	uint32_t, uint32_t);
189711890bcSjc156560 static raid_obj_id_t obj_locate_disk(raid_obj_tab_t *, uint32_t, uint32_t);
190711890bcSjc156560 static raid_obj_id_t obj_locate_arraypart(raid_obj_tab_t *, uint32_t,
191711890bcSjc156560 	uint32_t, uint32_t);
192711890bcSjc156560 static raid_obj_id_t obj_locate_diskseg(raid_obj_tab_t *, uint32_t,
193711890bcSjc156560 	uint32_t, uint32_t);
194711890bcSjc156560 static raid_obj_id_t obj_locate_task(raid_obj_tab_t *, uint32_t, uint32_t);
195711890bcSjc156560 static raid_obj_id_t obj_get_controller(raid_obj_tab_t *, raid_obj_id_t);
196711890bcSjc156560 
197711890bcSjc156560 static int obj_sys_compnum(raid_obj_tab_t *, raid_obj_id_t,
198711890bcSjc156560 	raid_obj_type_id_t);
199711890bcSjc156560 static int obj_sys_complist(raid_obj_tab_t *, raid_obj_id_t, int,
200711890bcSjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
201711890bcSjc156560 static int obj_controller_compnum(raid_obj_tab_t *, raid_obj_id_t,
202711890bcSjc156560 	raid_obj_type_id_t);
203711890bcSjc156560 static int obj_controller_complist(raid_obj_tab_t *, raid_obj_id_t, int,
204711890bcSjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
205711890bcSjc156560 static int obj_controller_get_attr(raid_obj_tab_t *, raid_obj_id_t);
206711890bcSjc156560 static int obj_controller_act(raid_obj_tab_t *, raid_obj_id_t,
207711890bcSjc156560 	uint32_t, void *, char **);
208711890bcSjc156560 static int obj_array_compnum(raid_obj_tab_t *, raid_obj_id_t,
209711890bcSjc156560 	raid_obj_type_id_t);
210711890bcSjc156560 static int obj_array_complist(raid_obj_tab_t *, raid_obj_id_t, int,
211711890bcSjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
212711890bcSjc156560 static int obj_array_get_attr(raid_obj_tab_t *, raid_obj_id_t);
213711890bcSjc156560 static int obj_array_set_attr(raid_obj_tab_t *, raid_obj_id_t,
214711890bcSjc156560 	uint32_t, uint32_t *, char **);
215711890bcSjc156560 static int obj_disk_compnum(raid_obj_tab_t *, raid_obj_id_t,
216711890bcSjc156560 	raid_obj_type_id_t);
217711890bcSjc156560 static int obj_disk_complist(raid_obj_tab_t *, raid_obj_id_t, int,
218711890bcSjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
219711890bcSjc156560 static int obj_disk_get_attr(raid_obj_tab_t *, raid_obj_id_t);
220711890bcSjc156560 static int obj_hsp_get_attr(raid_obj_tab_t *, raid_obj_id_t);
221711890bcSjc156560 static int obj_arraypart_get_attr(raid_obj_tab_t *, raid_obj_id_t);
222711890bcSjc156560 static int obj_diskseg_get_attr(raid_obj_tab_t *, raid_obj_id_t);
223711890bcSjc156560 static int obj_task_get_attr(raid_obj_tab_t *, raid_obj_id_t);
224711890bcSjc156560 static int obj_array_create(raid_obj_tab_t *, raid_obj_id_t, int,
225711890bcSjc156560 	raid_obj_id_t *, char **);
226711890bcSjc156560 static int obj_array_delete(raid_obj_tab_t *, raid_obj_id_t, char **);
227711890bcSjc156560 static int obj_hsp_bind(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
228711890bcSjc156560 static int obj_hsp_unbind(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
229711890bcSjc156560 
230711890bcSjc156560 static int raid_obj_create_system_obj(raid_obj_tab_t *);
231711890bcSjc156560 static raid_obj_id_t raid_obj_id_new(raid_obj_tab_t *);
232711890bcSjc156560 static void *raid_obj_attr_new(raid_obj_type_id_t);
233711890bcSjc156560 static raid_obj_id_t raid_obj_create(raid_obj_tab_t *, raid_obj_type_id_t);
234711890bcSjc156560 static int raid_obj_delete(raid_obj_tab_t *, raid_obj_id_t);
235711890bcSjc156560 static int raid_obj_add_org(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
236711890bcSjc156560 static raid_obj_type_id_t raid_obj_get_type(raid_obj_tab_t *, raid_obj_id_t);
237711890bcSjc156560 static int raid_obj_set_type(raid_obj_tab_t *, raid_obj_id_t,
238711890bcSjc156560 	raid_obj_type_id_t);
239711890bcSjc156560 static raid_obj_status_t raid_obj_get_status(raid_obj_tab_t *, raid_obj_id_t);
240711890bcSjc156560 static int raid_obj_set_status(raid_obj_tab_t *, raid_obj_id_t,
241711890bcSjc156560 	raid_obj_status_t);
242711890bcSjc156560 static int raid_obj_clear_status(raid_obj_tab_t *, raid_obj_id_t,
243711890bcSjc156560 	raid_obj_status_t);
244711890bcSjc156560 static raid_obj_id_t raid_obj_get_container(raid_obj_tab_t *, raid_obj_id_t);
245711890bcSjc156560 static int raid_obj_set_container(raid_obj_tab_t *, raid_obj_id_t,
246711890bcSjc156560 	raid_obj_id_t);
247711890bcSjc156560 static raid_obj_id_t raid_obj_get_comp(raid_obj_tab_t *, raid_obj_id_t);
248711890bcSjc156560 static int raid_obj_set_comp(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
249711890bcSjc156560 static raid_obj_id_t raid_obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
250711890bcSjc156560 static int raid_obj_set_sibling(raid_obj_tab_t *, raid_obj_id_t,
251711890bcSjc156560 	raid_obj_id_t);
252711890bcSjc156560 static void *raid_obj_get_data_ptr(raid_obj_tab_t *, raid_obj_id_t);
253711890bcSjc156560 static int raid_obj_set_data_ptr(raid_obj_tab_t *, raid_obj_id_t, void *);
254711890bcSjc156560 static raid_obj_handle_t raid_obj_get_handle(raid_obj_tab_t *,
255711890bcSjc156560 	raid_obj_id_t);
256711890bcSjc156560 static int raid_obj_set_handle(raid_obj_tab_t *, raid_obj_id_t,
257711890bcSjc156560 	raid_obj_handle_t);
258711890bcSjc156560 
259711890bcSjc156560 static void raid_list_create(raid_list_t *, size_t);
260711890bcSjc156560 static void *raid_list_head(raid_list_t *);
261711890bcSjc156560 static void *raid_list_next(raid_list_t *, void *);
262711890bcSjc156560 static void raid_list_insert_tail(raid_list_t *, void *);
263711890bcSjc156560 static void raid_list_remove(raid_list_t *, void *);
264711890bcSjc156560 static void *raid_list_remove_head(raid_list_t *);
265711890bcSjc156560 static void *raid_list_find(raid_list_t *, raid_obj_id_t);
266711890bcSjc156560 static int raid_obj_tab_create(raid_obj_tab_t *, size_t);
267711890bcSjc156560 static void raid_obj_tab_destroy(raid_obj_tab_t *);
268711890bcSjc156560 static int raid_obj_tab_insert(raid_obj_tab_t *, raid_obj_id_t, void *);
269711890bcSjc156560 static void *raid_obj_tab_remove(raid_obj_tab_t *, raid_obj_id_t);
270711890bcSjc156560 static void *raid_obj_tab_find(raid_obj_tab_t *, raid_obj_id_t);
271711890bcSjc156560 static void raid_list_destroy(raid_list_t *);
272711890bcSjc156560 
273711890bcSjc156560 static int controller_id_to_path(uint32_t, char *);
274711890bcSjc156560 static char *controller_id_to_driver_name(uint32_t);
275711890bcSjc156560 static void raid_plugin_init();
276711890bcSjc156560 static raid_lib_t *raid_plugin_load(char *);
277711890bcSjc156560 static raid_lib_t *raid_find_lib(raid_obj_tab_t *, raid_obj_id_t);
278711890bcSjc156560 
279711890bcSjc156560 /* Global object table */
280711890bcSjc156560 static raid_obj_tab_t raid_tab_sys = {0, 0, NULL};
281711890bcSjc156560 
282711890bcSjc156560 /* Plug-in modules maintenance data structures */
283711890bcSjc156560 static raid_lib_t *raid_lib_sys = NULL;
284711890bcSjc156560 
285711890bcSjc156560 /* Handle table definition */
286711890bcSjc156560 static struct {
287711890bcSjc156560 	int		handle_num;
288711890bcSjc156560 	int		used;
289711890bcSjc156560 	int		unused;
290711890bcSjc156560 	handle_attr_t	*handles;
291711890bcSjc156560 } raid_handle_sys = {0, 0, 0, NULL};
292711890bcSjc156560 
293711890bcSjc156560 /*
294711890bcSjc156560  * RAID object method table definition
295711890bcSjc156560  */
296711890bcSjc156560 static raid_obj_op_t raid_obj_op_sys[OBJ_TYPE_ALL] = {
297711890bcSjc156560 	{obj_sys_compnum, obj_sys_complist, NULL, NULL, NULL,
298711890bcSjc156560 		NULL, NULL, NULL, NULL},	/* system object methods */
299711890bcSjc156560 	{obj_controller_compnum, obj_controller_complist,
300711890bcSjc156560 		obj_controller_get_attr, NULL, obj_controller_act,
301711890bcSjc156560 		NULL, NULL, NULL, NULL},	/* controller object methods */
302711890bcSjc156560 	{obj_array_compnum, obj_array_complist, obj_array_get_attr,
303711890bcSjc156560 		obj_array_set_attr, NULL, obj_array_create,
304711890bcSjc156560 		obj_array_delete, NULL, NULL},	/* array object methods */
305711890bcSjc156560 	{obj_disk_compnum, obj_disk_complist, obj_disk_get_attr, NULL,
306711890bcSjc156560 		NULL, NULL, NULL, NULL, NULL},	/* disk object methods */
307711890bcSjc156560 	{NULL, NULL, obj_hsp_get_attr, NULL, NULL, NULL, NULL, obj_hsp_bind,
308711890bcSjc156560 		obj_hsp_unbind},		/* hsp object methods */
309711890bcSjc156560 	{NULL, NULL, obj_arraypart_get_attr, NULL, NULL, NULL, NULL,
310711890bcSjc156560 		NULL, NULL},			/* array part object methods */
311711890bcSjc156560 	{NULL, NULL, obj_diskseg_get_attr, NULL, NULL, NULL, NULL, NULL, NULL},
312711890bcSjc156560 	{NULL, NULL, obj_task_get_attr, NULL, NULL, NULL, NULL,
313711890bcSjc156560 		NULL, NULL}			/* disk seg object methods */
314711890bcSjc156560 };
315711890bcSjc156560 
316711890bcSjc156560 /*
317711890bcSjc156560  * Mutex for multithread safe
318711890bcSjc156560  */
319711890bcSjc156560 static mutex_t raidcfg_mp;
320711890bcSjc156560 
321711890bcSjc156560 /*
322711890bcSjc156560  * RaidCfg library APIs
323711890bcSjc156560  */
324711890bcSjc156560 const char *
325711890bcSjc156560 raidcfg_errstr(int err_code)
326711890bcSjc156560 {
327711890bcSjc156560 	char *ret_val;
328711890bcSjc156560 
329711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
330711890bcSjc156560 	switch (err_code) {
331711890bcSjc156560 	case	SUCCESS:
332711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Operation succeeded.\n");
333711890bcSjc156560 		break;
334711890bcSjc156560 	case	STD_IOCTL:
335711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
336711890bcSjc156560 		    "Request standard IOCTL service.\n");
337711890bcSjc156560 		break;
338711890bcSjc156560 	case	ERR_DRIVER_NOT_FOUND:
339711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
340711890bcSjc156560 		    "Controller device can not be found.\n");
341711890bcSjc156560 		break;
342711890bcSjc156560 	case	ERR_DRIVER_OPEN:
343711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Can not open controller.\n");
344711890bcSjc156560 		break;
345711890bcSjc156560 	case	ERR_DRIVER_LOCK:
346711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Controller is locked.\n");
347711890bcSjc156560 		break;
348711890bcSjc156560 	case	ERR_DRIVER_CLOSED:
349711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Controller is not opened.\n");
350711890bcSjc156560 		break;
351711890bcSjc156560 	case	ERR_DRIVER_ACROSS:
352711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
353711890bcSjc156560 		    "Operation across multiple controllers.\n");
354711890bcSjc156560 		break;
355711890bcSjc156560 	case	ERR_ARRAY_LEVEL:
356711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
357711890bcSjc156560 		    "Operation not support with volume of this level.\n");
358711890bcSjc156560 		break;
359711890bcSjc156560 	case	ERR_ARRAY_SIZE:
360711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
361711890bcSjc156560 		    "Capacity of array out of range.\n");
362711890bcSjc156560 		break;
363711890bcSjc156560 	case	ERR_ARRAY_STRIPE_SIZE:
364711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal stripe size.\n");
365711890bcSjc156560 		break;
366711890bcSjc156560 	case	ERR_ARRAY_CACHE_POLICY:
367711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
368711890bcSjc156560 		    "Illegal cache-write policy.\n");
369711890bcSjc156560 		break;
370711890bcSjc156560 	case	ERR_ARRAY_IN_USE:
371474adcbbSyw161884 		ret_val = dgettext(TEXT_DOMAIN, "Array or disk in use.\n");
372711890bcSjc156560 		break;
373711890bcSjc156560 	case	ERR_ARRAY_TASK:
374711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Array has background task.\n");
375711890bcSjc156560 		break;
376711890bcSjc156560 	case	ERR_ARRAY_CONFIG:
377711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
378711890bcSjc156560 		    "Configuration over device node failed.\n");
379711890bcSjc156560 		break;
380711890bcSjc156560 	case	ERR_ARRAY_DISKNUM:
381711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Incorrect number of disks.\n");
382711890bcSjc156560 		break;
383711890bcSjc156560 	case	ERR_ARRAY_LAYOUT:
384711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal array layout.\n");
385711890bcSjc156560 		break;
386711890bcSjc156560 	case	ERR_ARRAY_AMOUNT:
387711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many arrays.\n");
388711890bcSjc156560 		break;
389711890bcSjc156560 	case	ERR_DISK_STATE:
390711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
391711890bcSjc156560 		    "Incorrect disk status for current operation.\n");
392711890bcSjc156560 		break;
393711890bcSjc156560 	case	ERR_DISK_SPACE:
394711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "No enough disk space.\n");
395711890bcSjc156560 		break;
396711890bcSjc156560 	case	ERR_DISK_SEG_AMOUNT:
397711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many disk segments.\n");
398711890bcSjc156560 		break;
399711890bcSjc156560 	case	ERR_DISK_NOT_EMPTY:
400711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Disk has occupied space.\n");
401711890bcSjc156560 		break;
402711890bcSjc156560 	case	ERR_DISK_TASK:
403711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Disk has background task.\n");
404711890bcSjc156560 		break;
405711890bcSjc156560 	case	ERR_TASK_STATE:
406711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
407711890bcSjc156560 		    "Incorrect task state for current operation.\n");
408711890bcSjc156560 		break;
409711890bcSjc156560 	case	ERR_OP_ILLEGAL:
410711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal operation.\n");
411711890bcSjc156560 		break;
412711890bcSjc156560 	case	ERR_OP_NO_IMPL:
413711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
414711890bcSjc156560 		    "Operation is not implemented.\n");
415711890bcSjc156560 		break;
416711890bcSjc156560 	case	ERR_OP_FAILED:
417474adcbbSyw161884 		ret_val = dgettext(TEXT_DOMAIN, "Operation failed.\n");
418711890bcSjc156560 		break;
419711890bcSjc156560 	case	ERR_DEVICE_NOENT:
420711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device not found.\n");
421711890bcSjc156560 		break;
422711890bcSjc156560 	case	ERR_DEVICE_TYPE:
423711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal type of device.\n");
424711890bcSjc156560 		break;
425711890bcSjc156560 	case	ERR_DEVICE_DUP:
426711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device record duplicated.\n");
427711890bcSjc156560 		break;
428711890bcSjc156560 	case	ERR_DEVICE_OVERFLOW:
429711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many devices.\n");
430711890bcSjc156560 		break;
431711890bcSjc156560 	case	ERR_DEVICE_UNCLEAN:
432711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device pool is not clean.\n");
433711890bcSjc156560 		break;
434711890bcSjc156560 	case	ERR_DEVICE_INVALID:
435711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device record is invalid.\n");
436711890bcSjc156560 		break;
437711890bcSjc156560 	case	ERR_NOMEM:
438711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
439711890bcSjc156560 		    "Can not allocate more memory space.\n");
440711890bcSjc156560 		break;
441711890bcSjc156560 	case	ERR_PRIV:
442711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "No privilege.\n");
443711890bcSjc156560 		break;
444711890bcSjc156560 	default:
445711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Undefined error.\n");
446711890bcSjc156560 	}
447711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
448711890bcSjc156560 
449711890bcSjc156560 	return (ret_val);
450711890bcSjc156560 }
451711890bcSjc156560 
452711890bcSjc156560 int
453711890bcSjc156560 raidcfg_get_controller(uint32_t controller_id)
454711890bcSjc156560 {
455711890bcSjc156560 	raid_obj_id_t obj_id;
456711890bcSjc156560 	int ret_val;
457711890bcSjc156560 
458711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
459711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
460711890bcSjc156560 	obj_id = obj_locate_controller(&raid_tab_sys, controller_id);
461711890bcSjc156560 	if (obj_id < OBJ_NONE) {
462711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
463711890bcSjc156560 		return (obj_id);
464711890bcSjc156560 	}
465711890bcSjc156560 
466711890bcSjc156560 	if (obj_id == OBJ_NONE) {
467711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
468711890bcSjc156560 		return (ERR_DEVICE_NOENT);
469711890bcSjc156560 	}
470711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
471711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
472711890bcSjc156560 
473711890bcSjc156560 	return (ret_val);
474711890bcSjc156560 }
475711890bcSjc156560 
476711890bcSjc156560 int
477711890bcSjc156560 raidcfg_get_array(int controller_handle, uint64_t target_id, uint64_t lun)
478711890bcSjc156560 {
479711890bcSjc156560 	raid_obj_id_t obj_id;
480711890bcSjc156560 	raidcfg_array_t *attr;
481711890bcSjc156560 	int ret_val;
482711890bcSjc156560 
483711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
484711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
485711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
486711890bcSjc156560 	if (obj_id < OBJ_NONE) {
487711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
488711890bcSjc156560 		return (obj_id);
489711890bcSjc156560 	}
490711890bcSjc156560 
491711890bcSjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_ARRAY);
492711890bcSjc156560 
493711890bcSjc156560 	while (obj_id > OBJ_NONE) {
494711890bcSjc156560 		(void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
495711890bcSjc156560 		if (attr->tag.idl.target_id == target_id &&
496711890bcSjc156560 		    attr->tag.idl.lun == lun)
497711890bcSjc156560 			break;
498711890bcSjc156560 
499711890bcSjc156560 		obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
500711890bcSjc156560 	}
501711890bcSjc156560 
502711890bcSjc156560 	if (obj_id < OBJ_NONE) {
503711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
504711890bcSjc156560 		return (obj_id);
505711890bcSjc156560 	}
506711890bcSjc156560 	if (obj_id == OBJ_NONE) {
507711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
508711890bcSjc156560 		return (ERR_DEVICE_NOENT);
509711890bcSjc156560 	}
510711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
511711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
512711890bcSjc156560 
513711890bcSjc156560 	return (ret_val);
514711890bcSjc156560 }
515711890bcSjc156560 
516711890bcSjc156560 int
517711890bcSjc156560 raidcfg_get_disk(int controller_handle, disk_tag_t tag)
518711890bcSjc156560 {
519711890bcSjc156560 	raid_obj_id_t obj_id;
520711890bcSjc156560 	raidcfg_disk_t *attr;
521711890bcSjc156560 	int ret_val;
522711890bcSjc156560 
523711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
524711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
525711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
526711890bcSjc156560 	if (obj_id < OBJ_NONE) {
527711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
528711890bcSjc156560 		return (obj_id);
529711890bcSjc156560 	}
530711890bcSjc156560 
531711890bcSjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_DISK);
532711890bcSjc156560 
533711890bcSjc156560 	while (obj_id > OBJ_NONE) {
534711890bcSjc156560 		(void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
535711890bcSjc156560 		if (attr->tag.cidl.bus == tag.cidl.bus &&
536711890bcSjc156560 		    attr->tag.cidl.target_id == tag.cidl.target_id &&
537711890bcSjc156560 		    attr->tag.cidl.lun == tag.cidl.lun)
538711890bcSjc156560 			break;
539711890bcSjc156560 
540711890bcSjc156560 		obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
541711890bcSjc156560 	}
542711890bcSjc156560 
543711890bcSjc156560 	if (obj_id < OBJ_NONE) {
544711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
545711890bcSjc156560 		return (obj_id);
546711890bcSjc156560 	}
547711890bcSjc156560 	if (obj_id == OBJ_NONE) {
548711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
549711890bcSjc156560 		return (ERR_DEVICE_NOENT);
550711890bcSjc156560 	}
551711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
552711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
553711890bcSjc156560 
554711890bcSjc156560 	return (ret_val);
555711890bcSjc156560 }
556711890bcSjc156560 
557711890bcSjc156560 int
558711890bcSjc156560 raidcfg_open_controller(int handle, char **plugin_err_str)
559711890bcSjc156560 {
560711890bcSjc156560 	raid_obj_id_t obj_id;
561711890bcSjc156560 	int ret;
562711890bcSjc156560 
563711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
564711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
565711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
566711890bcSjc156560 	if (obj_id < OBJ_NONE) {
567711890bcSjc156560 		raid_handle_delete(handle);
568711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
569711890bcSjc156560 		return (ERR_DEVICE_NOENT);
570711890bcSjc156560 	}
571711890bcSjc156560 
572711890bcSjc156560 	ret = obj_controller_act(&raid_tab_sys, obj_id,
573711890bcSjc156560 	    ACT_CONTROLLER_OPEN, NULL, plugin_err_str);
574711890bcSjc156560 	if (ret < SUCCESS) {
575711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
576711890bcSjc156560 		return (ret);
577711890bcSjc156560 	}
578711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
579711890bcSjc156560 
580711890bcSjc156560 	return (SUCCESS);
581711890bcSjc156560 }
582711890bcSjc156560 
583711890bcSjc156560 int
584711890bcSjc156560 raidcfg_close_controller(int handle, char **plugin_err_str)
585711890bcSjc156560 {
586711890bcSjc156560 	raid_obj_id_t obj_id;
587711890bcSjc156560 	int ret;
588711890bcSjc156560 
589711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
590711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
591711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
592711890bcSjc156560 	if (obj_id < OBJ_NONE) {
593711890bcSjc156560 		raid_handle_delete(handle);
594711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
595711890bcSjc156560 		return (ERR_DEVICE_NOENT);
596711890bcSjc156560 	}
597711890bcSjc156560 
598711890bcSjc156560 	ret = obj_controller_act(&raid_tab_sys, obj_id,
599711890bcSjc156560 	    ACT_CONTROLLER_CLOSE, NULL, plugin_err_str);
600711890bcSjc156560 	if (ret < SUCCESS) {
601711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
602711890bcSjc156560 		return (ret);
603711890bcSjc156560 	}
604711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
605711890bcSjc156560 
606711890bcSjc156560 	return (SUCCESS);
607711890bcSjc156560 }
608711890bcSjc156560 
609711890bcSjc156560 int
610711890bcSjc156560 raidcfg_get_type(int handle)
611711890bcSjc156560 {
612711890bcSjc156560 	raid_obj_id_t obj_id;
613711890bcSjc156560 	int ret_val;
614711890bcSjc156560 
615711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
616711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
617711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
618711890bcSjc156560 	if (obj_id < OBJ_NONE) {
619711890bcSjc156560 		raid_handle_delete(handle);
620711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
621711890bcSjc156560 		return (ERR_DEVICE_NOENT);
622711890bcSjc156560 	}
623711890bcSjc156560 	ret_val = raid_obj_get_type(&raid_tab_sys, obj_id);
624711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
625711890bcSjc156560 
626711890bcSjc156560 	return (ret_val);
627711890bcSjc156560 }
628711890bcSjc156560 
629711890bcSjc156560 int
630711890bcSjc156560 raidcfg_get_attr(int handle, void *attr)
631711890bcSjc156560 {
632711890bcSjc156560 	raid_obj_id_t obj_id;
633711890bcSjc156560 	raid_obj_type_id_t type;
634711890bcSjc156560 	void *data;
635711890bcSjc156560 	int ret, size;
636711890bcSjc156560 
637711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
638711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
639711890bcSjc156560 	if (attr == NULL) {
640711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
641711890bcSjc156560 		return (ERR_DEVICE_INVALID);
642711890bcSjc156560 	}
643711890bcSjc156560 
644711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
645711890bcSjc156560 	if (obj_id < OBJ_NONE) {
646711890bcSjc156560 		raid_handle_delete(handle);
647711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
648711890bcSjc156560 		return (ERR_DEVICE_NOENT);
649711890bcSjc156560 	}
650711890bcSjc156560 
651711890bcSjc156560 	type = raid_obj_get_type(&raid_tab_sys, obj_id);
652711890bcSjc156560 	ret = obj_get_attr(&raid_tab_sys, obj_id, &data);
653711890bcSjc156560 	if (ret < SUCCESS) {
654711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
655711890bcSjc156560 		return (ret);
656711890bcSjc156560 	}
657711890bcSjc156560 
658711890bcSjc156560 	switch (type) {
659711890bcSjc156560 	case	OBJ_TYPE_CONTROLLER:
660711890bcSjc156560 		size = sizeof (controller_attr_t);
661711890bcSjc156560 		break;
662711890bcSjc156560 	case	OBJ_TYPE_ARRAY:
663711890bcSjc156560 		size = sizeof (array_attr_t);
664711890bcSjc156560 		break;
665711890bcSjc156560 	case	OBJ_TYPE_HSP:
666711890bcSjc156560 		{
667711890bcSjc156560 			raidcfg_hsp_t *dst = attr;
668711890bcSjc156560 			hsp_attr_t *src = data;
669711890bcSjc156560 			controller_attr_t *ctlr_attr;
670711890bcSjc156560 			array_attr_t *array_attr;
671711890bcSjc156560 
672711890bcSjc156560 			dst->associated_id = src->associated_id;
673711890bcSjc156560 			dst->type = src->type;
674711890bcSjc156560 
675711890bcSjc156560 			obj_id = obj_get_controller(&raid_tab_sys, obj_id);
676711890bcSjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
677711890bcSjc156560 			    (void **)(&ctlr_attr));
678711890bcSjc156560 			if (ret < SUCCESS) {
679711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
680711890bcSjc156560 				return (ret);
681711890bcSjc156560 			}
682711890bcSjc156560 
683711890bcSjc156560 			if (src->type == HSP_TYPE_LOCAL) {
684711890bcSjc156560 				obj_id = obj_locate_array(&raid_tab_sys,
685711890bcSjc156560 				    ctlr_attr->controller_id,
686711890bcSjc156560 				    src->associated_id);
687711890bcSjc156560 				ret = obj_get_attr(&raid_tab_sys, obj_id,
688711890bcSjc156560 				    (void **)(&array_attr));
689711890bcSjc156560 				if (ret < SUCCESS) {
690711890bcSjc156560 					(void) mutex_unlock(&raidcfg_mp);
691711890bcSjc156560 					return (ret);
692711890bcSjc156560 				}
693711890bcSjc156560 
694711890bcSjc156560 				dst->tag.idl.target_id =
695711890bcSjc156560 				    array_attr->tag.idl.target_id;
696711890bcSjc156560 				dst->tag.idl.lun = array_attr->tag.idl.lun;
697711890bcSjc156560 			}
698711890bcSjc156560 		}
699711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
700711890bcSjc156560 		return (SUCCESS);
701711890bcSjc156560 	case	OBJ_TYPE_DISK:
702711890bcSjc156560 		size = sizeof (disk_attr_t);
703711890bcSjc156560 		break;
704711890bcSjc156560 	case	OBJ_TYPE_ARRAY_PART:
705711890bcSjc156560 		{
706711890bcSjc156560 			raidcfg_arraypart_t *dst = attr;
707711890bcSjc156560 			arraypart_attr_t *src = data;
708711890bcSjc156560 			controller_attr_t *ctlr_attr;
709711890bcSjc156560 			disk_attr_t *disk_attr;
710711890bcSjc156560 
711711890bcSjc156560 			dst->disk_id = src->disk_id;
712711890bcSjc156560 			dst->offset = src->offset;
713711890bcSjc156560 			dst->size = src->size;
714711890bcSjc156560 			dst->state = src->state;
715711890bcSjc156560 
716711890bcSjc156560 			obj_id = obj_get_controller(&raid_tab_sys, obj_id);
717711890bcSjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
718711890bcSjc156560 			    (void **)(&ctlr_attr));
719711890bcSjc156560 			if (ret < SUCCESS) {
720711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
721711890bcSjc156560 				return (ret);
722711890bcSjc156560 			}
723711890bcSjc156560 
724711890bcSjc156560 			obj_id = obj_locate_disk(&raid_tab_sys,
725711890bcSjc156560 			    ctlr_attr->controller_id, src->disk_id);
726711890bcSjc156560 			if (obj_id <= OBJ_NONE) {
727711890bcSjc156560 				dst->tag.cidl.bus = (uint64_t)OBJ_ATTR_NONE;
728711890bcSjc156560 				dst->tag.cidl.target_id =
729711890bcSjc156560 				    (uint64_t)OBJ_ATTR_NONE;
730711890bcSjc156560 				dst->tag.cidl.lun = (uint64_t)OBJ_ATTR_NONE;
731711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
732711890bcSjc156560 				return (SUCCESS);
733711890bcSjc156560 			}
734711890bcSjc156560 
735711890bcSjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
736711890bcSjc156560 			    (void **)(&disk_attr));
737711890bcSjc156560 			if (ret < SUCCESS) {
738711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
739711890bcSjc156560 				return (ret);
740711890bcSjc156560 			}
741711890bcSjc156560 
742711890bcSjc156560 			dst->tag.cidl.bus = disk_attr->tag.cidl.bus;
743711890bcSjc156560 			dst->tag.cidl.target_id = disk_attr->tag.cidl.target_id;
744711890bcSjc156560 			dst->tag.cidl.lun = disk_attr->tag.cidl.lun;
745711890bcSjc156560 		}
746711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
747711890bcSjc156560 		return (SUCCESS);
748711890bcSjc156560 	case	OBJ_TYPE_DISK_SEG:
749711890bcSjc156560 		size = sizeof (diskseg_attr_t);
750711890bcSjc156560 		break;
751711890bcSjc156560 	case	OBJ_TYPE_TASK:
752711890bcSjc156560 		size = sizeof (task_attr_t);
753711890bcSjc156560 		break;
754711890bcSjc156560 	default:
755711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
756711890bcSjc156560 		return (ERR_DEVICE_TYPE);
757711890bcSjc156560 	}
758711890bcSjc156560 
759711890bcSjc156560 	(void) memcpy(attr, data, size);
760711890bcSjc156560 
761711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
762711890bcSjc156560 	return (ret);
763711890bcSjc156560 }
764711890bcSjc156560 
765711890bcSjc156560 int
766711890bcSjc156560 raidcfg_get_container(int handle)
767711890bcSjc156560 {
768711890bcSjc156560 	raid_obj_id_t obj_id;
769711890bcSjc156560 	int ret_val;
770711890bcSjc156560 
771711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
772711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
773711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
774711890bcSjc156560 	if (obj_id < OBJ_NONE) {
775711890bcSjc156560 		raid_handle_delete(handle);
776711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
777711890bcSjc156560 		return (ERR_DEVICE_NOENT);
778711890bcSjc156560 	}
779711890bcSjc156560 
780711890bcSjc156560 	obj_id = raid_obj_get_container(&raid_tab_sys, obj_id);
781711890bcSjc156560 	if (obj_id < OBJ_NONE) {
782711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
783711890bcSjc156560 		return (obj_id);
784711890bcSjc156560 	}
785711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
786711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
787711890bcSjc156560 
788711890bcSjc156560 	return (ret_val);
789711890bcSjc156560 }
790711890bcSjc156560 
791711890bcSjc156560 int
792711890bcSjc156560 raidcfg_list_head(int handle, raid_obj_type_id_t type)
793711890bcSjc156560 {
794711890bcSjc156560 	raid_obj_id_t obj_id;
795711890bcSjc156560 	int ret_val;
796711890bcSjc156560 
797711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
798711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
799711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
800711890bcSjc156560 	if (obj_id < OBJ_NONE) {
801711890bcSjc156560 		raid_handle_delete(handle);
802711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
803711890bcSjc156560 		return (ERR_DEVICE_NOENT);
804711890bcSjc156560 	}
805711890bcSjc156560 
806711890bcSjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, type);
807711890bcSjc156560 	if (obj_id < OBJ_NONE) {
808711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
809711890bcSjc156560 		return (obj_id);
810711890bcSjc156560 	}
811711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
812711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
813711890bcSjc156560 
814711890bcSjc156560 	return (ret_val);
815711890bcSjc156560 }
816711890bcSjc156560 
817711890bcSjc156560 int
818711890bcSjc156560 raidcfg_list_next(int handle)
819711890bcSjc156560 {
820711890bcSjc156560 	raid_obj_id_t obj_id;
821711890bcSjc156560 	int ret_val;
822711890bcSjc156560 
823711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
824711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
825711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
826711890bcSjc156560 	if (obj_id < OBJ_NONE) {
827711890bcSjc156560 		raid_handle_delete(handle);
828711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
829711890bcSjc156560 		return (ERR_DEVICE_NOENT);
830711890bcSjc156560 	}
831711890bcSjc156560 
832711890bcSjc156560 	obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
833711890bcSjc156560 	if (obj_id < OBJ_NONE) {
834711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
835711890bcSjc156560 		return (obj_id);
836711890bcSjc156560 	}
837711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
838711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
839711890bcSjc156560 
840711890bcSjc156560 	return (ret_val);
841711890bcSjc156560 }
842711890bcSjc156560 
843711890bcSjc156560 int
844711890bcSjc156560 raidcfg_set_attr(int handle, uint32_t set_cmd, void *value,
845711890bcSjc156560 	char **plugin_err_str)
846711890bcSjc156560 {
847711890bcSjc156560 	raid_obj_id_t obj_id;
848711890bcSjc156560 	raid_obj_type_id_t type;
849711890bcSjc156560 	int ret;
850711890bcSjc156560 
851711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
852711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
853711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
854711890bcSjc156560 	if (obj_id < OBJ_NONE) {
855711890bcSjc156560 		raid_handle_delete(handle);
856711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
857711890bcSjc156560 		return (ERR_DEVICE_NOENT);
858711890bcSjc156560 	}
859711890bcSjc156560 
860711890bcSjc156560 	type = raid_obj_get_type(&raid_tab_sys, obj_id);
861711890bcSjc156560 	if (raid_obj_op_sys[type].set_attr == NULL) {
862711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
863711890bcSjc156560 		return (ERR_OP_NO_IMPL);
864711890bcSjc156560 	}
865711890bcSjc156560 
866711890bcSjc156560 	ret = raid_obj_op_sys[type].set_attr(&raid_tab_sys,
867711890bcSjc156560 	    obj_id, set_cmd, value, plugin_err_str);
868711890bcSjc156560 
869711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
870711890bcSjc156560 	return (ret);
871711890bcSjc156560 }
872711890bcSjc156560 
873711890bcSjc156560 int
874711890bcSjc156560 raidcfg_update_fw(int handle, char *file, char **plugin_err_str)
875711890bcSjc156560 {
876711890bcSjc156560 	raid_obj_id_t obj_id;
877711890bcSjc156560 	int ret;
878711890bcSjc156560 
879711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
880711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
881711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
882711890bcSjc156560 	if (obj_id < OBJ_NONE) {
883711890bcSjc156560 		raid_handle_delete(handle);
884711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
885711890bcSjc156560 		return (ERR_DEVICE_NOENT);
886711890bcSjc156560 	}
887711890bcSjc156560 
888711890bcSjc156560 	if (raid_obj_get_type(&raid_tab_sys, obj_id) != OBJ_TYPE_CONTROLLER) {
889711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
890711890bcSjc156560 		return (ERR_OP_NO_IMPL);
891711890bcSjc156560 	}
892711890bcSjc156560 
893711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_CONTROLLER].act(&raid_tab_sys,
894711890bcSjc156560 	    obj_id, ACT_CONTROLLER_FLASH_FW, file, plugin_err_str);
895711890bcSjc156560 
896711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
897711890bcSjc156560 	return (ret);
898711890bcSjc156560 }
899711890bcSjc156560 
900711890bcSjc156560 int
901711890bcSjc156560 raidcfg_create_array(int num_of_comps, int *disk_handles,
902711890bcSjc156560 	uint32_t raid_level, uint64_t size, uint32_t stripe_size,
903711890bcSjc156560 	char **plugin_err_str)
904711890bcSjc156560 {
905711890bcSjc156560 	raid_obj_id_t *disk_obj_ids, obj_id;
906711890bcSjc156560 	array_attr_t *array_attr;
907711890bcSjc156560 	raid_obj_handle_t array_handle;
908711890bcSjc156560 	int i, ret;
909711890bcSjc156560 
910711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
911711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
912711890bcSjc156560 
913711890bcSjc156560 	disk_obj_ids = calloc(num_of_comps, sizeof (raid_obj_id_t));
914711890bcSjc156560 	if (disk_obj_ids == NULL) {
915711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
916711890bcSjc156560 		return (ERR_NOMEM);
917711890bcSjc156560 	}
918711890bcSjc156560 
919711890bcSjc156560 	/* convert disk handles into disk object ids; */
920711890bcSjc156560 	for (i = 0; i < num_of_comps; ++i) {
921711890bcSjc156560 		if (*(disk_handles + i) == OBJ_SEPARATOR_BEGIN ||
922711890bcSjc156560 		    *(disk_handles + i) == OBJ_SEPARATOR_END) {
923711890bcSjc156560 			*(disk_obj_ids + i) = *(disk_handles + i);
924711890bcSjc156560 			continue;
925711890bcSjc156560 		}
926711890bcSjc156560 
927711890bcSjc156560 		*(disk_obj_ids + i) = raid_handle_to_obj(&raid_tab_sys,
928711890bcSjc156560 		    *(disk_handles + i));
929711890bcSjc156560 		if (raid_obj_get_type(&raid_tab_sys, *(disk_obj_ids + i)) !=
930711890bcSjc156560 		    OBJ_TYPE_DISK) {
931711890bcSjc156560 			free(disk_obj_ids);
932711890bcSjc156560 			(void) obj_rescan(&raid_tab_sys);
933711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
934711890bcSjc156560 			return (ERR_DEVICE_TYPE);
935711890bcSjc156560 		}
936711890bcSjc156560 	}
937711890bcSjc156560 
938711890bcSjc156560 	/* Create an empty array object */
939711890bcSjc156560 	obj_id = raid_obj_create(&raid_tab_sys, OBJ_TYPE_ARRAY);
940711890bcSjc156560 	if (obj_id < OBJ_NONE) {
941711890bcSjc156560 		free(disk_obj_ids);
942711890bcSjc156560 		(void) obj_rescan(&raid_tab_sys);
943711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
944711890bcSjc156560 		return (obj_id);
945711890bcSjc156560 	}
946711890bcSjc156560 	(void) raid_obj_clear_status(&raid_tab_sys, obj_id,
947711890bcSjc156560 	    OBJ_STATUS_CMD_CLEAN);
948711890bcSjc156560 
949711890bcSjc156560 	array_attr = raid_obj_get_data_ptr(&raid_tab_sys, obj_id);
950711890bcSjc156560 	array_attr->array_id = (uint32_t)OBJ_ATTR_NONE;
951711890bcSjc156560 	array_attr->raid_level = raid_level;
952711890bcSjc156560 	array_attr->capacity = size;
953711890bcSjc156560 	array_attr->stripe_size = stripe_size;
954711890bcSjc156560 	array_attr->write_policy = CACHE_WR_ON;
955711890bcSjc156560 	array_attr->read_policy = CACHE_RD_ON;
956711890bcSjc156560 
957711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].create_obj(&raid_tab_sys, obj_id,
958711890bcSjc156560 	    num_of_comps, disk_obj_ids, plugin_err_str);
959711890bcSjc156560 	free(disk_obj_ids);
960711890bcSjc156560 
961711890bcSjc156560 	if (ret < SUCCESS) {
962711890bcSjc156560 		(void) obj_rescan(&raid_tab_sys);
963711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
964711890bcSjc156560 		return (ret);
965711890bcSjc156560 	}
966711890bcSjc156560 
967711890bcSjc156560 	/* create_obj() method should put the array object in the device tree */
968711890bcSjc156560 	array_handle = raid_obj_to_handle(&raid_tab_sys, obj_id);
969711890bcSjc156560 
970711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
971711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
972711890bcSjc156560 	return (array_handle);
973711890bcSjc156560 }
974711890bcSjc156560 
975711890bcSjc156560 int
976711890bcSjc156560 raidcfg_delete_array(int array_handle, char **plugin_err_str)
977711890bcSjc156560 {
978711890bcSjc156560 	raid_obj_id_t array_obj_id;
979711890bcSjc156560 	int ret;
980711890bcSjc156560 
981711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
982711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
983711890bcSjc156560 
984711890bcSjc156560 	if (raidcfg_get_type(array_handle) != OBJ_TYPE_ARRAY) {
985711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
986711890bcSjc156560 		return (ERR_DEVICE_TYPE);
987711890bcSjc156560 	}
988711890bcSjc156560 
989711890bcSjc156560 	array_obj_id = raid_handle_to_obj(&raid_tab_sys, array_handle);
990711890bcSjc156560 	if (array_obj_id < OBJ_NONE) {
991711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
992711890bcSjc156560 		return (array_obj_id);
993711890bcSjc156560 	}
994711890bcSjc156560 	if (array_obj_id == OBJ_NONE) {
995711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
996711890bcSjc156560 		return (ERR_DEVICE_INVALID);
997711890bcSjc156560 	}
998711890bcSjc156560 
999711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].delete_obj(&raid_tab_sys,
1000711890bcSjc156560 	    array_obj_id, plugin_err_str);
1001711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1002711890bcSjc156560 
1003711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
1004711890bcSjc156560 	return (ret);
1005711890bcSjc156560 }
1006711890bcSjc156560 
1007711890bcSjc156560 int
1008711890bcSjc156560 raidcfg_set_hsp(int num, raidcfg_hsp_relation_t *hsp_relations,
1009711890bcSjc156560 	char **plugin_err_str)
1010711890bcSjc156560 {
1011711890bcSjc156560 	raid_obj_id_t disk_obj_id, array_obj_id;
1012711890bcSjc156560 	raid_obj_id_t *hsp_relation_objs;
1013711890bcSjc156560 	int ret, i;
1014711890bcSjc156560 
1015711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
1016711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1017711890bcSjc156560 	if ((num == 0) || (hsp_relations == NULL)) {
1018711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
1019711890bcSjc156560 		return (ERR_OP_ILLEGAL);
1020711890bcSjc156560 	}
1021711890bcSjc156560 
1022711890bcSjc156560 	hsp_relation_objs = malloc(2 * num * sizeof (raid_obj_id_t));
1023711890bcSjc156560 	if (hsp_relation_objs == NULL) {
1024711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
1025711890bcSjc156560 		return (ERR_NOMEM);
1026711890bcSjc156560 	}
1027711890bcSjc156560 
1028711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1029711890bcSjc156560 
1030711890bcSjc156560 	for (i = 0; i < num; ++ i) {
1031711890bcSjc156560 		if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
1032711890bcSjc156560 			array_obj_id = raid_handle_to_obj(&raid_tab_sys,
1033711890bcSjc156560 			    hsp_relations[i].array_handle);
1034711890bcSjc156560 			if (array_obj_id < OBJ_NONE) {
1035711890bcSjc156560 				free(hsp_relation_objs);
1036711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1037711890bcSjc156560 				return (array_obj_id);
1038711890bcSjc156560 			}
1039711890bcSjc156560 			if (array_obj_id == OBJ_NONE) {
1040711890bcSjc156560 				(void) free(hsp_relation_objs);
1041711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1042711890bcSjc156560 				return (ERR_DEVICE_NOENT);
1043711890bcSjc156560 			}
1044711890bcSjc156560 			if (raidcfg_get_type(hsp_relations[i].array_handle) !=
1045711890bcSjc156560 			    OBJ_TYPE_ARRAY) {
1046711890bcSjc156560 				free(hsp_relation_objs);
1047711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1048711890bcSjc156560 				return (ERR_DEVICE_TYPE);
1049711890bcSjc156560 			}
1050711890bcSjc156560 		} else
1051711890bcSjc156560 			array_obj_id = OBJ_ATTR_NONE;
1052711890bcSjc156560 
1053711890bcSjc156560 		disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
1054711890bcSjc156560 		    hsp_relations[i].disk_handle);
1055711890bcSjc156560 		if (disk_obj_id < OBJ_NONE) {
1056711890bcSjc156560 			free(hsp_relation_objs);
1057711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1058711890bcSjc156560 			return (disk_obj_id);
1059711890bcSjc156560 		}
1060711890bcSjc156560 		if (disk_obj_id == OBJ_NONE) {
1061711890bcSjc156560 			free(hsp_relation_objs);
1062711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1063711890bcSjc156560 			return (ERR_DEVICE_NOENT);
1064711890bcSjc156560 		}
1065711890bcSjc156560 		if (raidcfg_get_type(hsp_relations[i].disk_handle) !=
1066711890bcSjc156560 		    OBJ_TYPE_DISK) {
1067711890bcSjc156560 			free(hsp_relation_objs);
1068711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1069711890bcSjc156560 			return (ERR_DEVICE_TYPE);
1070711890bcSjc156560 		}
1071711890bcSjc156560 
1072711890bcSjc156560 		hsp_relation_objs[2 * i] = array_obj_id;
1073711890bcSjc156560 		hsp_relation_objs[2 * i + 1] = disk_obj_id;
1074711890bcSjc156560 	}
1075711890bcSjc156560 
1076711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].bind_obj(&raid_tab_sys, num,
1077711890bcSjc156560 	    hsp_relation_objs, plugin_err_str);
1078711890bcSjc156560 
1079711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1080711890bcSjc156560 	free(hsp_relation_objs);
1081711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
1082711890bcSjc156560 
1083711890bcSjc156560 	return (ret);
1084711890bcSjc156560 }
1085711890bcSjc156560 
1086711890bcSjc156560 int
1087711890bcSjc156560 raidcfg_unset_hsp(int num, raidcfg_hsp_relation_t *hsp_relations,
1088711890bcSjc156560 	char **plugin_err_str)
1089711890bcSjc156560 {
1090711890bcSjc156560 	raid_obj_id_t disk_obj_id, array_obj_id;
1091711890bcSjc156560 	raid_obj_id_t *hsp_relation_objs;
1092711890bcSjc156560 	int ret, i;
1093711890bcSjc156560 
1094711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
1095711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1096711890bcSjc156560 	if ((num == 0) || (hsp_relations == NULL)) {
1097711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
1098711890bcSjc156560 		return (ERR_OP_ILLEGAL);
1099711890bcSjc156560 	}
1100711890bcSjc156560 
1101711890bcSjc156560 	hsp_relation_objs = malloc(2 * num * sizeof (raid_obj_id_t));
1102711890bcSjc156560 	if (hsp_relation_objs == NULL) {
1103711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
1104711890bcSjc156560 		return (ERR_NOMEM);
1105711890bcSjc156560 	}
1106711890bcSjc156560 
1107711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1108711890bcSjc156560 
1109711890bcSjc156560 	for (i = 0; i < num; ++ i) {
1110711890bcSjc156560 		if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
1111711890bcSjc156560 			array_obj_id = raid_handle_to_obj(&raid_tab_sys,
1112711890bcSjc156560 			    hsp_relations[i].array_handle);
1113711890bcSjc156560 			if (array_obj_id < OBJ_NONE) {
1114711890bcSjc156560 				free(hsp_relation_objs);
1115711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1116711890bcSjc156560 				return (array_obj_id);
1117711890bcSjc156560 			}
1118711890bcSjc156560 			if (array_obj_id == OBJ_NONE) {
1119711890bcSjc156560 				free(hsp_relation_objs);
1120711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1121711890bcSjc156560 				return (ERR_DEVICE_NOENT);
1122711890bcSjc156560 			}
1123711890bcSjc156560 			if (raidcfg_get_type(hsp_relations[i].array_handle) !=
1124711890bcSjc156560 			    OBJ_TYPE_ARRAY) {
1125711890bcSjc156560 				free(hsp_relation_objs);
1126711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1127711890bcSjc156560 				return (ERR_DEVICE_TYPE);
1128711890bcSjc156560 			}
1129711890bcSjc156560 		} else
1130711890bcSjc156560 			array_obj_id = OBJ_ATTR_NONE;
1131711890bcSjc156560 
1132711890bcSjc156560 		disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
1133711890bcSjc156560 		    hsp_relations[i].disk_handle);
1134711890bcSjc156560 		if (disk_obj_id < OBJ_NONE) {
1135711890bcSjc156560 			free(hsp_relation_objs);
1136711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1137711890bcSjc156560 			return (disk_obj_id);
1138711890bcSjc156560 		}
1139711890bcSjc156560 		if (disk_obj_id == OBJ_NONE) {
1140711890bcSjc156560 			free(hsp_relation_objs);
1141711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1142711890bcSjc156560 			return (ERR_DEVICE_NOENT);
1143711890bcSjc156560 		}
1144711890bcSjc156560 		if (raidcfg_get_type(hsp_relations[i].disk_handle) !=
1145711890bcSjc156560 		    OBJ_TYPE_DISK) {
1146711890bcSjc156560 			free(hsp_relation_objs);
1147711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1148711890bcSjc156560 			return (ERR_DEVICE_TYPE);
1149711890bcSjc156560 		}
1150711890bcSjc156560 
1151711890bcSjc156560 		hsp_relation_objs[2 * i] = array_obj_id;
1152711890bcSjc156560 		hsp_relation_objs[2 * i + 1] = disk_obj_id;
1153711890bcSjc156560 	}
1154711890bcSjc156560 
1155711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].unbind_obj(&raid_tab_sys,
1156711890bcSjc156560 	    num, hsp_relation_objs, plugin_err_str);
1157711890bcSjc156560 
1158711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1159711890bcSjc156560 	free(hsp_relation_objs);
1160711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
1161711890bcSjc156560 
1162711890bcSjc156560 	return (ret);
1163711890bcSjc156560 }
1164711890bcSjc156560 
1165711890bcSjc156560 /*
1166711890bcSjc156560  * RaidCfg lib routines
1167711890bcSjc156560  */
1168711890bcSjc156560 void
1169711890bcSjc156560 raidcfg_init(void)
1170711890bcSjc156560 {
1171711890bcSjc156560 	(void) mutex_init(&raidcfg_mp, NULL, NULL);
1172711890bcSjc156560 	raid_plugin_init();
1173711890bcSjc156560 	(void) raid_handle_init();
1174711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1175711890bcSjc156560 }
1176711890bcSjc156560 
1177711890bcSjc156560 void
1178711890bcSjc156560 raidcfg_fini(void)
1179711890bcSjc156560 {
1180711890bcSjc156560 	/*
1181711890bcSjc156560 	 * Need to close all opened controllers before destroying object table
1182711890bcSjc156560 	 */
1183711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1184711890bcSjc156560 	raid_handle_fini();
1185711890bcSjc156560 	raid_obj_tab_destroy(&raid_tab_sys);
1186711890bcSjc156560 	raid_plugin_init();
1187711890bcSjc156560 	(void) mutex_destroy(&raidcfg_mp);
1188711890bcSjc156560 }
1189711890bcSjc156560 
1190711890bcSjc156560 /*
1191711890bcSjc156560  * Support routines
1192711890bcSjc156560  */
1193711890bcSjc156560 static int
1194711890bcSjc156560 intcompare(const void *p1, const void *p2)
1195711890bcSjc156560 {
1196711890bcSjc156560 	int i, j;
1197711890bcSjc156560 	i = *((int *)p1);
1198711890bcSjc156560 	j = *((int *)p2);
1199711890bcSjc156560 	return (i - j);
1200711890bcSjc156560 }
1201711890bcSjc156560 
1202711890bcSjc156560 static uint64_t
1203711890bcSjc156560 raid_space_noalign(raid_obj_tab_t *raid_tab, uint32_t raid_level, int num,
1204711890bcSjc156560 	raid_obj_id_t *disk_objs, arraypart_attr_t *arraypart_attrs)
1205711890bcSjc156560 {
1206711890bcSjc156560 	disk_attr_t *disk_attr;
1207711890bcSjc156560 	diskseg_attr_t *diskseg_attr;
1208711890bcSjc156560 	raid_obj_id_t obj_id;
1209711890bcSjc156560 	uint64_t offset, capacity;
1210711890bcSjc156560 	int i, disk_num, sub_array_num, disk_layer;
1211711890bcSjc156560 
1212711890bcSjc156560 	/* Find out the maximum available space for all disks */
1213711890bcSjc156560 	for (i = 0; i < num; ++i) {
1214711890bcSjc156560 		if ((disk_objs[i] == OBJ_SEPARATOR_BEGIN) ||
1215711890bcSjc156560 		    (disk_objs[i] == OBJ_SEPARATOR_END))
1216711890bcSjc156560 			continue;
1217711890bcSjc156560 
1218711890bcSjc156560 		(void) obj_get_attr(raid_tab, disk_objs[i],
1219711890bcSjc156560 		    (void **)(&disk_attr));
1220711890bcSjc156560 		obj_id = obj_get_comp(raid_tab, disk_objs[i],
1221711890bcSjc156560 		    OBJ_TYPE_DISK_SEG);
1222711890bcSjc156560 		if (obj_id == OBJ_NONE) {
1223711890bcSjc156560 			arraypart_attrs[i].offset = 0;
1224711890bcSjc156560 			arraypart_attrs[i].size = disk_attr->capacity;
1225711890bcSjc156560 			continue;
1226711890bcSjc156560 		}
1227711890bcSjc156560 
1228711890bcSjc156560 		(void) obj_get_attr(raid_tab, obj_id, (void **)
1229711890bcSjc156560 		    (&diskseg_attr));
1230711890bcSjc156560 		arraypart_attrs[i].offset = 0;
1231711890bcSjc156560 		arraypart_attrs[i].size = diskseg_attr->offset;
1232711890bcSjc156560 		offset = diskseg_attr->offset + diskseg_attr->size;
1233711890bcSjc156560 
1234711890bcSjc156560 		while ((obj_id = obj_get_sibling(raid_tab, obj_id)) !=
1235711890bcSjc156560 		    OBJ_NONE) {
1236711890bcSjc156560 			(void) obj_get_attr(raid_tab, obj_id,
1237711890bcSjc156560 			    (void **)(&diskseg_attr));
1238711890bcSjc156560 			if ((diskseg_attr->offset - offset) >
1239711890bcSjc156560 			    arraypart_attrs[i].size) {
1240711890bcSjc156560 				arraypart_attrs[i].offset = offset;
1241*700682b8Syw161884 				arraypart_attrs[i].size = diskseg_attr->offset -
1242*700682b8Syw161884 				    offset;
1243711890bcSjc156560 			}
1244711890bcSjc156560 
1245711890bcSjc156560 			offset = diskseg_attr->offset + diskseg_attr->size;
1246711890bcSjc156560 		}
1247711890bcSjc156560 
1248711890bcSjc156560 		if ((disk_attr->capacity - offset) > arraypart_attrs[i].size) {
1249711890bcSjc156560 			arraypart_attrs[i].offset = offset;
1250*700682b8Syw161884 			arraypart_attrs[i].size = disk_attr->capacity -
1251*700682b8Syw161884 			    offset;
1252711890bcSjc156560 		}
1253711890bcSjc156560 	}
1254711890bcSjc156560 
1255711890bcSjc156560 	capacity = OBJ_ATTR_NONE;
1256711890bcSjc156560 	disk_num = 0;
1257711890bcSjc156560 	disk_layer = 0;
1258711890bcSjc156560 	sub_array_num = 0;
1259711890bcSjc156560 	for (i = 0; i < num; ++i) {
1260711890bcSjc156560 		if (disk_objs[i] == OBJ_SEPARATOR_BEGIN) {
1261711890bcSjc156560 			++ disk_layer;
1262711890bcSjc156560 			continue;
1263711890bcSjc156560 		}
1264711890bcSjc156560 		if (disk_objs[i] == OBJ_SEPARATOR_END) {
1265711890bcSjc156560 			-- disk_layer;
1266711890bcSjc156560 			if (disk_layer != 0)
1267711890bcSjc156560 				++ sub_array_num;
1268711890bcSjc156560 			continue;
1269711890bcSjc156560 		}
1270711890bcSjc156560 
1271711890bcSjc156560 		if (capacity > arraypart_attrs[i].size)
1272711890bcSjc156560 			capacity = arraypart_attrs[i].size;
1273711890bcSjc156560 		++disk_num;
1274711890bcSjc156560 	}
1275711890bcSjc156560 
1276711890bcSjc156560 	switch (raid_level) {
1277711890bcSjc156560 	case	RAID_LEVEL_0:
1278711890bcSjc156560 		capacity = capacity * disk_num;
1279711890bcSjc156560 		break;
1280711890bcSjc156560 	case	RAID_LEVEL_1:
1281711890bcSjc156560 		capacity = capacity * disk_num / 2;
1282711890bcSjc156560 		break;
1283711890bcSjc156560 	case	RAID_LEVEL_1E:
1284711890bcSjc156560 		capacity = capacity * disk_num / 2;
1285711890bcSjc156560 		break;
1286711890bcSjc156560 	case	RAID_LEVEL_5:
1287711890bcSjc156560 		capacity = capacity * (disk_num - 1);
1288711890bcSjc156560 		break;
1289711890bcSjc156560 	case	RAID_LEVEL_10:
1290711890bcSjc156560 		capacity = capacity * disk_num / 2;
1291711890bcSjc156560 		break;
1292711890bcSjc156560 	case	RAID_LEVEL_50:
1293711890bcSjc156560 		capacity = capacity * (disk_num - sub_array_num);
1294711890bcSjc156560 		break;
1295711890bcSjc156560 	default:
1296711890bcSjc156560 		return (ERR_ARRAY_LEVEL);
1297711890bcSjc156560 		break;
1298711890bcSjc156560 	}
1299711890bcSjc156560 
1300711890bcSjc156560 	return (capacity);
1301711890bcSjc156560 }
1302711890bcSjc156560 
1303711890bcSjc156560 static int
1304711890bcSjc156560 raid_dev_config(cfga_cmd_t cmd, uint32_t controller_id, uint32_t target_id,
1305711890bcSjc156560 	uint8_t type)
1306711890bcSjc156560 {
1307711890bcSjc156560 	cfga_err_t cfga_err;
1308711890bcSjc156560 	char *ap_id;
1309711890bcSjc156560 	int count = 0;
1310711890bcSjc156560 
1311711890bcSjc156560 	ap_id = (char *)malloc(MAX_PATH_LEN);
1312711890bcSjc156560 	if (ap_id == NULL)
1313711890bcSjc156560 		return (ERR_NOMEM);
1314711890bcSjc156560 
1315711890bcSjc156560 	if (type == 0) {
1316711890bcSjc156560 		(void) snprintf(ap_id, MAX_PATH_LEN, "c%d::dsk/c%dt%dd0",
1317711890bcSjc156560 		    controller_id, controller_id, target_id);
1318711890bcSjc156560 	} else
1319711890bcSjc156560 		(void) snprintf(ap_id, MAX_PATH_LEN, "c%d", controller_id);
1320711890bcSjc156560 
1321711890bcSjc156560 	do {
1322711890bcSjc156560 		cfga_err = config_change_state(cmd, 1, &ap_id, "disable_rcm",
1323711890bcSjc156560 		    NULL, NULL, NULL, 0);
1324711890bcSjc156560 		count++;
1325711890bcSjc156560 	} while (cfga_err != CFGA_OK && count < 2);
1326711890bcSjc156560 
1327711890bcSjc156560 	if (cfga_err != CFGA_OK) {
1328711890bcSjc156560 		free(ap_id);
1329711890bcSjc156560 		return (ERR_ARRAY_CONFIG);
1330711890bcSjc156560 	}
1331711890bcSjc156560 
1332711890bcSjc156560 	free(ap_id);
1333711890bcSjc156560 	return (SUCCESS);
1334711890bcSjc156560 }
1335711890bcSjc156560 
1336711890bcSjc156560 /*
1337711890bcSjc156560  * Raid handle maintenance routines
1338711890bcSjc156560  */
1339711890bcSjc156560 static int
1340711890bcSjc156560 raid_handle_init()
1341711890bcSjc156560 {
1342711890bcSjc156560 	int i;
1343711890bcSjc156560 	void *ptr;
1344711890bcSjc156560 
1345711890bcSjc156560 	raid_handle_sys.handle_num += HANDLER_SLOTS;
1346711890bcSjc156560 	ptr = realloc(raid_handle_sys.handles,
1347711890bcSjc156560 	    raid_handle_sys.handle_num * sizeof (handle_attr_t));
1348711890bcSjc156560 	if (ptr == NULL)
1349711890bcSjc156560 		return (ERR_NOMEM);
1350711890bcSjc156560 	raid_handle_sys.handles = ptr;
1351711890bcSjc156560 
1352711890bcSjc156560 	/* Clean up the new allocated handles */
1353711890bcSjc156560 	for (i = raid_handle_sys.handle_num - HANDLER_SLOTS;
1354711890bcSjc156560 	    i < raid_handle_sys.handle_num; ++i) {
1355711890bcSjc156560 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1356711890bcSjc156560 		raid_handle_sys.handles[i].next = i + 1;
1357711890bcSjc156560 	}
1358711890bcSjc156560 
1359711890bcSjc156560 	/* For the first time of allocation, set up the system object handle */
1360711890bcSjc156560 	if (raid_handle_sys.handle_num == HANDLER_SLOTS) {
1361711890bcSjc156560 		raid_handle_sys.handles[0].type = OBJ_TYPE_SYSTEM;
1362711890bcSjc156560 		raid_handle_sys.handles[0].next = 0;
1363711890bcSjc156560 		raid_handle_sys.unused = 1;
1364711890bcSjc156560 		raid_handle_sys.used = 0;
1365711890bcSjc156560 	}
1366711890bcSjc156560 	return (SUCCESS);
1367711890bcSjc156560 }
1368711890bcSjc156560 
1369711890bcSjc156560 static void
1370711890bcSjc156560 raid_handle_fini()
1371711890bcSjc156560 {
1372711890bcSjc156560 	raid_obj_handle_t i;
1373711890bcSjc156560 
1374711890bcSjc156560 	i = raid_handle_sys.used;
1375711890bcSjc156560 
1376711890bcSjc156560 	/* Close all opened controllers */
1377711890bcSjc156560 	while (i != 0) {
1378711890bcSjc156560 		if ((raid_handle_sys.handles[i].type == OBJ_TYPE_CONTROLLER) &&
1379711890bcSjc156560 		    (raid_handle_sys.handles[i].fd != 0) &&
1380711890bcSjc156560 		    (raid_handle_sys.handles[i].raid_lib != NULL))
1381711890bcSjc156560 			raid_handle_sys.handles[i].raid_lib->close_controller(
1382711890bcSjc156560 			    raid_handle_sys.handles[i].controller_id, NULL);
1383711890bcSjc156560 		i = raid_handle_sys.handles[i].next;
1384711890bcSjc156560 	}
1385711890bcSjc156560 
1386711890bcSjc156560 	/* Clean up handle space */
1387711890bcSjc156560 	raid_handle_sys.handle_num = 0;
1388711890bcSjc156560 	raid_handle_sys.unused = 0;
1389711890bcSjc156560 	raid_handle_sys.used = 0;
1390711890bcSjc156560 	free(raid_handle_sys.handles);
1391711890bcSjc156560 	raid_handle_sys.handles = NULL;
1392711890bcSjc156560 }
1393711890bcSjc156560 
1394711890bcSjc156560 static raid_obj_handle_t
1395711890bcSjc156560 raid_handle_new(raid_obj_type_id_t type)
1396711890bcSjc156560 {
1397711890bcSjc156560 	int ret;
1398711890bcSjc156560 
1399711890bcSjc156560 	if (raid_handle_sys.unused == raid_handle_sys.handle_num - 1) {
1400711890bcSjc156560 		ret = raid_handle_init();
1401711890bcSjc156560 		if (ret < SUCCESS)
1402711890bcSjc156560 			return (ret);
1403711890bcSjc156560 	}
1404711890bcSjc156560 
1405711890bcSjc156560 	ret = raid_handle_sys.unused;
1406711890bcSjc156560 	raid_handle_sys.unused = raid_handle_sys.handles[ret].next;
1407711890bcSjc156560 
1408711890bcSjc156560 	raid_handle_sys.handles[ret].next = raid_handle_sys.used;
1409711890bcSjc156560 	raid_handle_sys.used = ret;
1410711890bcSjc156560 	raid_handle_sys.handles[ret].type = type;
1411711890bcSjc156560 
1412711890bcSjc156560 	return (ret);
1413711890bcSjc156560 }
1414711890bcSjc156560 
1415711890bcSjc156560 static void
1416711890bcSjc156560 raid_handle_delete(raid_obj_handle_t handle)
1417711890bcSjc156560 {
1418711890bcSjc156560 	int i = raid_handle_sys.used, j = 0;
1419711890bcSjc156560 
1420711890bcSjc156560 	if (handle == 0)
1421711890bcSjc156560 		return;
1422711890bcSjc156560 
1423711890bcSjc156560 	while (i != 0 && i != handle) {
1424711890bcSjc156560 		j = i;
1425711890bcSjc156560 		i = raid_handle_sys.handles[i].next;
1426711890bcSjc156560 	}
1427711890bcSjc156560 
1428711890bcSjc156560 	if (i == handle) {
1429711890bcSjc156560 		if (j != 0)
1430711890bcSjc156560 			raid_handle_sys.handles[j].next =
1431711890bcSjc156560 			    raid_handle_sys.handles[i].next;
1432711890bcSjc156560 		else
1433711890bcSjc156560 			raid_handle_sys.used =
1434711890bcSjc156560 			    raid_handle_sys.handles[i].next;
1435711890bcSjc156560 
1436711890bcSjc156560 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1437711890bcSjc156560 		raid_handle_sys.handles[i].next =
1438711890bcSjc156560 		    raid_handle_sys.unused;
1439711890bcSjc156560 		raid_handle_sys.unused = i;
1440711890bcSjc156560 	}
1441711890bcSjc156560 }
1442711890bcSjc156560 
1443711890bcSjc156560 static void
1444711890bcSjc156560 raid_handle_delete_controller_comp(uint32_t controller_id)
1445711890bcSjc156560 {
1446711890bcSjc156560 	int i = raid_handle_sys.used, j;
1447711890bcSjc156560 
1448711890bcSjc156560 	while (i != 0) {
1449711890bcSjc156560 		j = i;
1450711890bcSjc156560 		i = raid_handle_sys.handles[i].next;
1451*700682b8Syw161884 		if ((raid_handle_sys.handles[j].controller_id ==
1452*700682b8Syw161884 		    controller_id) &&
1453*700682b8Syw161884 		    (raid_handle_sys.handles[j].type !=
1454*700682b8Syw161884 		    OBJ_TYPE_CONTROLLER))
1455711890bcSjc156560 		raid_handle_delete(j);
1456711890bcSjc156560 	}
1457711890bcSjc156560 }
1458711890bcSjc156560 
1459711890bcSjc156560 static raid_obj_id_t
1460711890bcSjc156560 raid_handle_to_obj(raid_obj_tab_t *raid_tab, raid_obj_handle_t handle)
1461711890bcSjc156560 {
1462711890bcSjc156560 	handle_attr_t *handle_attr;
1463711890bcSjc156560 	raid_obj_id_t obj_id;
1464711890bcSjc156560 
1465711890bcSjc156560 	if (handle == OBJ_SYSTEM)
1466711890bcSjc156560 		return (OBJ_SYSTEM);
1467711890bcSjc156560 
1468711890bcSjc156560 	handle_attr = raid_handle_sys.handles + handle;
1469711890bcSjc156560 
1470711890bcSjc156560 	switch (handle_attr->type) {
1471711890bcSjc156560 	case	OBJ_TYPE_SYSTEM:
1472711890bcSjc156560 		return (OBJ_SYSTEM);
1473711890bcSjc156560 	case	OBJ_TYPE_CONTROLLER:
1474711890bcSjc156560 		obj_id = obj_locate_controller(raid_tab,
1475711890bcSjc156560 		    handle_attr->controller_id);
1476711890bcSjc156560 		break;
1477711890bcSjc156560 	case	OBJ_TYPE_ARRAY:
1478711890bcSjc156560 		obj_id = obj_locate_array(raid_tab,
1479711890bcSjc156560 		    handle_attr->controller_id, handle_attr->array_id);
1480711890bcSjc156560 		break;
1481711890bcSjc156560 	case	OBJ_TYPE_HSP:
1482711890bcSjc156560 		obj_id = obj_locate_hsp(raid_tab,
1483711890bcSjc156560 		    handle_attr->controller_id, handle_attr->disk_id,
1484711890bcSjc156560 		    handle_attr->array_id);
1485711890bcSjc156560 		break;
1486711890bcSjc156560 	case	OBJ_TYPE_DISK:
1487711890bcSjc156560 		obj_id = obj_locate_disk(raid_tab,
1488711890bcSjc156560 		    handle_attr->controller_id, handle_attr->disk_id);
1489711890bcSjc156560 		break;
1490711890bcSjc156560 	case	OBJ_TYPE_ARRAY_PART:
1491711890bcSjc156560 		obj_id = obj_locate_arraypart(raid_tab,
1492711890bcSjc156560 		    handle_attr->controller_id, handle_attr->array_id,
1493711890bcSjc156560 		    handle_attr->disk_id);
1494711890bcSjc156560 		break;
1495711890bcSjc156560 	case	OBJ_TYPE_DISK_SEG:
1496711890bcSjc156560 		obj_id = obj_locate_diskseg(raid_tab,
1497711890bcSjc156560 		    handle_attr->controller_id,
1498711890bcSjc156560 		    handle_attr->disk_id, handle_attr->seq_id);
1499711890bcSjc156560 		break;
1500711890bcSjc156560 	case	OBJ_TYPE_TASK:
1501711890bcSjc156560 		obj_id = obj_locate_task(raid_tab,
1502711890bcSjc156560 		    handle_attr->controller_id, handle_attr->task_id);
1503711890bcSjc156560 		break;
1504711890bcSjc156560 	default:
1505711890bcSjc156560 		return (ERR_DEVICE_INVALID);
1506711890bcSjc156560 	}
1507711890bcSjc156560 
1508711890bcSjc156560 	if (obj_id < OBJ_NONE)
1509711890bcSjc156560 		return (obj_id);
1510711890bcSjc156560 	if (obj_id == OBJ_NONE)
1511711890bcSjc156560 		return (ERR_DEVICE_NOENT);
1512711890bcSjc156560 
1513711890bcSjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
1514711890bcSjc156560 	return (obj_id);
1515711890bcSjc156560 }
1516711890bcSjc156560 
1517711890bcSjc156560 static raid_obj_handle_t
1518711890bcSjc156560 raid_obj_to_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1519711890bcSjc156560 {
1520711890bcSjc156560 	raid_obj_id_t obj_id_backup = obj_id;
1521711890bcSjc156560 	raid_obj_type_id_t type;
1522711890bcSjc156560 	raid_obj_handle_t handle;
1523711890bcSjc156560 	controller_attr_t *controller_attr;
1524711890bcSjc156560 	array_attr_t *array_attr;
1525711890bcSjc156560 	hsp_attr_t *hsp_attr;
1526711890bcSjc156560 	disk_attr_t *disk_attr;
1527711890bcSjc156560 	arraypart_attr_t *arraypart_attr;
1528711890bcSjc156560 	diskseg_attr_t *diskseg_attr;
1529711890bcSjc156560 	task_attr_t *task_attr;
1530711890bcSjc156560 
1531711890bcSjc156560 	if (obj_id == OBJ_SYSTEM)
1532711890bcSjc156560 		return (OBJ_SYSTEM);
1533711890bcSjc156560 
1534711890bcSjc156560 	/* If the object mapped by a handle */
1535711890bcSjc156560 	handle = raid_obj_get_handle(raid_tab, obj_id);
1536711890bcSjc156560 	if (handle != 0)
1537711890bcSjc156560 		return (handle);
1538711890bcSjc156560 
1539711890bcSjc156560 	/* Search for existing handles */
1540711890bcSjc156560 	for (handle = raid_handle_sys.used; handle != 0;
1541711890bcSjc156560 	    handle = raid_handle_sys.handles[handle].next)
1542711890bcSjc156560 		if (raid_handle_to_obj(raid_tab, handle) == obj_id)
1543711890bcSjc156560 			break;
1544711890bcSjc156560 
1545711890bcSjc156560 	if (handle != 0)
1546711890bcSjc156560 		return (handle);
1547711890bcSjc156560 
1548711890bcSjc156560 	/* Allocate new handle for this object */
1549711890bcSjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
1550711890bcSjc156560 	handle = raid_handle_new(type);
1551711890bcSjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
1552711890bcSjc156560 	raid_handle_sys.handles[handle].type = type;
1553711890bcSjc156560 
1554711890bcSjc156560 	switch (type) {
1555711890bcSjc156560 	case OBJ_TYPE_SYSTEM:
1556711890bcSjc156560 		break;
1557711890bcSjc156560 	case OBJ_TYPE_CONTROLLER:
1558711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1559711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1560711890bcSjc156560 		    controller_attr->controller_id;
1561711890bcSjc156560 		break;
1562711890bcSjc156560 	case OBJ_TYPE_ARRAY:
1563711890bcSjc156560 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1564711890bcSjc156560 		raid_handle_sys.handles[handle].array_id = array_attr->array_id;
1565711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1566711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1567711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1568711890bcSjc156560 		    controller_attr->controller_id;
1569711890bcSjc156560 		break;
1570711890bcSjc156560 	case OBJ_TYPE_HSP:
1571711890bcSjc156560 		hsp_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1572711890bcSjc156560 		raid_handle_sys.handles[handle].array_id =
1573711890bcSjc156560 		    hsp_attr->associated_id;
1574711890bcSjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1575711890bcSjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1576711890bcSjc156560 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1577711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1578711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1579711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1580711890bcSjc156560 		    controller_attr->controller_id;
1581711890bcSjc156560 		break;
1582711890bcSjc156560 	case OBJ_TYPE_DISK:
1583711890bcSjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1584711890bcSjc156560 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1585711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1586711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1587711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1588711890bcSjc156560 		    controller_attr->controller_id;
1589711890bcSjc156560 		break;
1590711890bcSjc156560 	case OBJ_TYPE_ARRAY_PART:
1591711890bcSjc156560 		arraypart_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1592711890bcSjc156560 		raid_handle_sys.handles[handle].disk_id =
1593711890bcSjc156560 		    arraypart_attr->disk_id;
1594711890bcSjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1595711890bcSjc156560 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1596711890bcSjc156560 		raid_handle_sys.handles[handle].array_id =
1597711890bcSjc156560 		    array_attr->array_id;
1598711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1599711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1600711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1601711890bcSjc156560 		    controller_attr->controller_id;
1602711890bcSjc156560 		break;
1603711890bcSjc156560 	case OBJ_TYPE_DISK_SEG:
1604711890bcSjc156560 		diskseg_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1605711890bcSjc156560 		raid_handle_sys.handles[handle].seq_id = diskseg_attr->seq_no;
1606711890bcSjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1607711890bcSjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1608711890bcSjc156560 		raid_handle_sys.handles[handle].disk_id =
1609711890bcSjc156560 		    disk_attr->disk_id;
1610711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1611711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1612711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1613711890bcSjc156560 		    controller_attr->controller_id;
1614711890bcSjc156560 		break;
1615711890bcSjc156560 	case OBJ_TYPE_TASK:
1616711890bcSjc156560 		task_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1617711890bcSjc156560 		raid_handle_sys.handles[handle].task_id = task_attr->task_id;
1618711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1619711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1620711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1621711890bcSjc156560 		    controller_attr->controller_id;
1622711890bcSjc156560 		break;
1623711890bcSjc156560 	default:
1624711890bcSjc156560 		return (ERR_DEVICE_INVALID);
1625711890bcSjc156560 	}
1626711890bcSjc156560 
1627711890bcSjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id_backup, handle);
1628711890bcSjc156560 	return (handle);
1629711890bcSjc156560 }
1630711890bcSjc156560 
1631711890bcSjc156560 static raid_lib_t *
1632711890bcSjc156560 raid_obj_get_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1633711890bcSjc156560 {
1634711890bcSjc156560 	raid_obj_handle_t handle;
1635711890bcSjc156560 	controller_attr_t *attr;
1636711890bcSjc156560 
1637711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1638711890bcSjc156560 		return (NULL);
1639711890bcSjc156560 
1640711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1641711890bcSjc156560 	handle = raid_handle_sys.used;
1642711890bcSjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1643711890bcSjc156560 	    raid_handle_sys.handles[handle].controller_id !=
1644711890bcSjc156560 	    attr->controller_id)
1645711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next;
1646711890bcSjc156560 
1647711890bcSjc156560 	if (handle == 0)
1648711890bcSjc156560 		return (NULL);
1649711890bcSjc156560 
1650711890bcSjc156560 	return (raid_handle_sys.handles[handle].raid_lib);
1651711890bcSjc156560 }
1652711890bcSjc156560 
1653711890bcSjc156560 static int
1654711890bcSjc156560 raid_obj_set_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1655711890bcSjc156560 	raid_lib_t *raid_lib)
1656711890bcSjc156560 {
1657711890bcSjc156560 	raid_obj_handle_t handle;
1658711890bcSjc156560 	controller_attr_t *attr;
1659711890bcSjc156560 
1660711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1661711890bcSjc156560 		return (ERR_DEVICE_TYPE);
1662711890bcSjc156560 
1663711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1664711890bcSjc156560 	handle = raid_handle_sys.used;
1665711890bcSjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1666711890bcSjc156560 	    raid_handle_sys.handles[handle].controller_id !=
1667711890bcSjc156560 	    attr->controller_id)
1668711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next;
1669711890bcSjc156560 
1670711890bcSjc156560 	if (handle == 0)
1671711890bcSjc156560 		return (ERR_DEVICE_NOENT);
1672711890bcSjc156560 
1673711890bcSjc156560 	raid_handle_sys.handles[handle].raid_lib = raid_lib;
1674711890bcSjc156560 	return (SUCCESS);
1675711890bcSjc156560 }
1676711890bcSjc156560 
1677711890bcSjc156560 static int
1678711890bcSjc156560 raid_obj_get_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1679711890bcSjc156560 {
1680711890bcSjc156560 	raid_obj_handle_t handle;
1681711890bcSjc156560 	controller_attr_t *attr;
1682711890bcSjc156560 
1683711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1684711890bcSjc156560 		return (ERR_DEVICE_TYPE);
1685711890bcSjc156560 
1686711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1687711890bcSjc156560 	handle = raid_handle_sys.used;
1688711890bcSjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1689711890bcSjc156560 	    raid_handle_sys.handles[handle].controller_id !=
1690711890bcSjc156560 	    attr->controller_id)
1691711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next;
1692711890bcSjc156560 
1693711890bcSjc156560 	if (handle == 0)
1694711890bcSjc156560 		return (ERR_DEVICE_NOENT);
1695711890bcSjc156560 
1696711890bcSjc156560 	return (raid_handle_sys.handles[handle].fd);
1697711890bcSjc156560 }
1698711890bcSjc156560 
1699711890bcSjc156560 static int
1700711890bcSjc156560 raid_obj_set_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, int fd)
1701711890bcSjc156560 {
1702711890bcSjc156560 	raid_obj_handle_t handle;
1703711890bcSjc156560 	controller_attr_t *attr;
1704711890bcSjc156560 
1705711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1706711890bcSjc156560 		return (ERR_DEVICE_TYPE);
1707711890bcSjc156560 
1708711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1709711890bcSjc156560 	handle = raid_handle_sys.used;
1710711890bcSjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1711711890bcSjc156560 	    raid_handle_sys.handles[handle].controller_id !=
1712711890bcSjc156560 	    attr->controller_id)
1713711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next;
1714711890bcSjc156560 
1715711890bcSjc156560 	if (handle == 0)
1716711890bcSjc156560 		return (ERR_DEVICE_NOENT);
1717711890bcSjc156560 
1718711890bcSjc156560 	raid_handle_sys.handles[handle].fd = fd;
1719711890bcSjc156560 	return (SUCCESS);
1720711890bcSjc156560 }
1721711890bcSjc156560 
1722711890bcSjc156560 /*
1723711890bcSjc156560  * Raid object maintenance routines
1724711890bcSjc156560  */
1725711890bcSjc156560 static int
1726711890bcSjc156560 obj_scan_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1727711890bcSjc156560 {
1728711890bcSjc156560 	raid_obj_status_t status;
1729711890bcSjc156560 	raid_obj_type_id_t type;
1730711890bcSjc156560 	int ret, i, obj_type_cnt, comp_num;
1731711890bcSjc156560 	raid_obj_id_t *comp_list;
1732711890bcSjc156560 
1733711890bcSjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
1734711890bcSjc156560 	if (status < SUCCESS)
1735711890bcSjc156560 		return (status);
1736711890bcSjc156560 
1737711890bcSjc156560 	if (status & OBJ_STATUS_SCANCOMP)
1738711890bcSjc156560 		return (SUCCESS);
1739711890bcSjc156560 
1740711890bcSjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
1741711890bcSjc156560 	if (type < OBJ_TYPE_SYSTEM || type > OBJ_TYPE_ALL)
1742711890bcSjc156560 		return (ERR_DEVICE_INVALID);
1743711890bcSjc156560 
1744711890bcSjc156560 	for (obj_type_cnt = OBJ_SYSTEM; obj_type_cnt < OBJ_TYPE_ALL;
1745711890bcSjc156560 	    ++obj_type_cnt) {
1746711890bcSjc156560 		if (raid_obj_op_sys[type].compnum != NULL)
1747711890bcSjc156560 			comp_num = raid_obj_op_sys[type].compnum(
1748711890bcSjc156560 			    raid_tab, obj_id, obj_type_cnt);
1749711890bcSjc156560 		else
1750711890bcSjc156560 			comp_num = 0;
1751711890bcSjc156560 
1752711890bcSjc156560 		if (comp_num < SUCCESS)
1753711890bcSjc156560 			return (comp_num);
1754711890bcSjc156560 		if (comp_num == 0)
1755711890bcSjc156560 			continue;
1756711890bcSjc156560 
1757711890bcSjc156560 		comp_list = calloc(comp_num, sizeof (raid_obj_id_t));
1758711890bcSjc156560 		if (comp_list == NULL)
1759711890bcSjc156560 			return (ERR_NOMEM);
1760711890bcSjc156560 
1761711890bcSjc156560 		for (i = 0; i < comp_num; ++i) {
1762711890bcSjc156560 			*(comp_list + i) = raid_obj_create(raid_tab,
1763711890bcSjc156560 			    obj_type_cnt);
1764711890bcSjc156560 			if (*(comp_list + i) < SUCCESS) {
1765711890bcSjc156560 				ret = *(comp_list + i);
1766711890bcSjc156560 				free(comp_list);
1767711890bcSjc156560 				return (ret);
1768711890bcSjc156560 			}
1769711890bcSjc156560 
1770711890bcSjc156560 			(void) raid_obj_clear_status(raid_tab,
1771711890bcSjc156560 			    *(comp_list + i), OBJ_STATUS_CMD_CLEAN);
1772711890bcSjc156560 			(void) raid_obj_add_org(raid_tab, *(comp_list + i),
1773711890bcSjc156560 			    obj_id);
1774711890bcSjc156560 		}
1775711890bcSjc156560 
1776711890bcSjc156560 		if (raid_obj_op_sys[type].complist != NULL)
1777711890bcSjc156560 			raid_obj_op_sys[type].complist(raid_tab,
1778711890bcSjc156560 			    obj_id, comp_num, comp_list, obj_type_cnt);
1779711890bcSjc156560 		free(comp_list);
1780711890bcSjc156560 	}
1781711890bcSjc156560 
1782711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_SCANCOMP);
1783711890bcSjc156560 	return (SUCCESS);
1784711890bcSjc156560 }
1785711890bcSjc156560 
1786711890bcSjc156560 static int
1787711890bcSjc156560 obj_rescan(raid_obj_tab_t *raid_tab)
1788711890bcSjc156560 {
1789711890bcSjc156560 	int ret;
1790711890bcSjc156560 
1791711890bcSjc156560 	raid_obj_tab_destroy(raid_tab);
1792711890bcSjc156560 
1793711890bcSjc156560 	if (raid_obj_tab_create(raid_tab, HASH_SLOTS) != SUCCESS)
1794711890bcSjc156560 		return (ERR_NOMEM);
1795711890bcSjc156560 
1796711890bcSjc156560 	if ((ret = raid_obj_create_system_obj(raid_tab)) != SUCCESS) {
1797711890bcSjc156560 		raid_obj_tab_destroy(raid_tab);
1798711890bcSjc156560 		return (ret);
1799711890bcSjc156560 	}
1800711890bcSjc156560 
1801711890bcSjc156560 	return (SUCCESS);
1802711890bcSjc156560 }
1803711890bcSjc156560 
1804711890bcSjc156560 static raid_obj_id_t
1805711890bcSjc156560 obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1806711890bcSjc156560 	raid_obj_type_id_t obj_type)
1807711890bcSjc156560 {
1808711890bcSjc156560 	raid_obj_id_t id;
1809711890bcSjc156560 	raid_obj_type_id_t type;
1810711890bcSjc156560 	raid_obj_status_t status;
1811711890bcSjc156560 	int ret;
1812711890bcSjc156560 
1813711890bcSjc156560 	if ((obj_type < OBJ_TYPE_SYSTEM) || (obj_type > OBJ_TYPE_ALL))
1814711890bcSjc156560 		return (ERR_DEVICE_TYPE);
1815711890bcSjc156560 
1816711890bcSjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
1817711890bcSjc156560 	if (status < SUCCESS)
1818711890bcSjc156560 		return (status);
1819711890bcSjc156560 
1820711890bcSjc156560 	if (!(status & OBJ_STATUS_SCANCOMP)) {
1821711890bcSjc156560 		ret = obj_scan_comp(raid_tab, obj_id);
1822711890bcSjc156560 		if (ret < SUCCESS)
1823711890bcSjc156560 			return (ret);
1824711890bcSjc156560 	}
1825711890bcSjc156560 
1826711890bcSjc156560 	id = raid_obj_get_comp(raid_tab, obj_id);
1827711890bcSjc156560 	if (id <= OBJ_NONE)
1828711890bcSjc156560 		return (id);
1829711890bcSjc156560 
1830711890bcSjc156560 	type = raid_obj_get_type(raid_tab, id);
1831711890bcSjc156560 	if (type < OBJ_TYPE_SYSTEM)
1832711890bcSjc156560 		return (type);
1833711890bcSjc156560 
1834711890bcSjc156560 	if (type == obj_type)
1835711890bcSjc156560 		return (id);
1836711890bcSjc156560 
1837711890bcSjc156560 	while (id > OBJ_NONE) {
1838711890bcSjc156560 		id = raid_obj_get_sibling(raid_tab, id);
1839711890bcSjc156560 		if (id <= OBJ_NONE)
1840711890bcSjc156560 			return (id);
1841711890bcSjc156560 
1842711890bcSjc156560 		type = raid_obj_get_type(raid_tab, id);
1843711890bcSjc156560 		if (type < OBJ_TYPE_SYSTEM)
1844711890bcSjc156560 			return (type);
1845711890bcSjc156560 
1846711890bcSjc156560 		if (type == obj_type)
1847711890bcSjc156560 			break;
1848711890bcSjc156560 	};
1849711890bcSjc156560 
1850711890bcSjc156560 	return (id);
1851711890bcSjc156560 }
1852711890bcSjc156560 
1853711890bcSjc156560 static raid_obj_id_t
1854711890bcSjc156560 obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1855711890bcSjc156560 {
1856711890bcSjc156560 	raid_obj_id_t id;
1857711890bcSjc156560 	raid_obj_type_id_t type, obj_type;
1858711890bcSjc156560 
1859711890bcSjc156560 	id = obj_id;
1860711890bcSjc156560 	obj_type = raid_obj_get_type(raid_tab, id);
1861711890bcSjc156560 	if (obj_type < OBJ_TYPE_SYSTEM)
1862711890bcSjc156560 		return (obj_type);
1863711890bcSjc156560 
1864711890bcSjc156560 	do {
1865711890bcSjc156560 		id = raid_obj_get_sibling(raid_tab, id);
1866711890bcSjc156560 		if (id < OBJ_NONE)
1867711890bcSjc156560 			return (id);
1868711890bcSjc156560 
1869711890bcSjc156560 		type = raid_obj_get_type(raid_tab, id);
1870711890bcSjc156560 		if (type < OBJ_TYPE_SYSTEM)
1871711890bcSjc156560 			return (type);
1872711890bcSjc156560 	} while ((type != obj_type) && (id != OBJ_NONE));
1873711890bcSjc156560 
1874711890bcSjc156560 	return (id);
1875711890bcSjc156560 }
1876711890bcSjc156560 
1877711890bcSjc156560 static int
1878711890bcSjc156560 obj_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, void **data)
1879711890bcSjc156560 {
1880711890bcSjc156560 	raid_obj_type_id_t type;
1881711890bcSjc156560 	raid_obj_status_t status;
1882711890bcSjc156560 	void *attr;
1883711890bcSjc156560 	int ret = SUCCESS;
1884711890bcSjc156560 
1885711890bcSjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
1886711890bcSjc156560 	if (status < SUCCESS)
1887711890bcSjc156560 		return (status);
1888711890bcSjc156560 
1889711890bcSjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
1890711890bcSjc156560 	if (type < OBJ_TYPE_SYSTEM)
1891711890bcSjc156560 		return (type);
1892711890bcSjc156560 
1893711890bcSjc156560 	if (!(status & OBJ_STATUS_OPENED)) {
1894711890bcSjc156560 		if (raid_obj_op_sys[type].get_attr == NULL)
1895711890bcSjc156560 			(void) raid_obj_set_status(raid_tab, obj_id,
1896711890bcSjc156560 			    OBJ_STATUS_OPENED);
1897711890bcSjc156560 		else
1898711890bcSjc156560 			ret = raid_obj_op_sys[type].get_attr(raid_tab, obj_id);
1899711890bcSjc156560 	}
1900711890bcSjc156560 	if (ret < SUCCESS)
1901711890bcSjc156560 		return (ret);
1902711890bcSjc156560 
1903711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1904711890bcSjc156560 	if (attr == NULL && type != OBJ_TYPE_SYSTEM)
1905711890bcSjc156560 		return (ERR_DEVICE_INVALID);
1906711890bcSjc156560 
1907711890bcSjc156560 	*data = attr;
1908711890bcSjc156560 	return (SUCCESS);
1909711890bcSjc156560 }
1910711890bcSjc156560 
1911711890bcSjc156560 static raid_obj_id_t
1912711890bcSjc156560 obj_locate_controller(raid_obj_tab_t *raid_tab, uint32_t controller_id)
1913711890bcSjc156560 {
1914711890bcSjc156560 	raid_obj_id_t obj_id;
1915711890bcSjc156560 	controller_attr_t *attr;
1916711890bcSjc156560 
1917711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
1918711890bcSjc156560 	if (obj_id <= OBJ_NONE)
1919711890bcSjc156560 		return (obj_id);
1920711890bcSjc156560 
1921711890bcSjc156560 	do {
1922711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1923711890bcSjc156560 		if (attr == NULL)
1924711890bcSjc156560 			return (ERR_DEVICE_INVALID);
1925711890bcSjc156560 
1926711890bcSjc156560 		if (attr->controller_id == controller_id)
1927711890bcSjc156560 			break;
1928711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) != OBJ_NONE);
1929711890bcSjc156560 
1930711890bcSjc156560 	return (obj_id);
1931711890bcSjc156560 }
1932711890bcSjc156560 
1933711890bcSjc156560 static raid_obj_id_t
1934711890bcSjc156560 obj_locate_array(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1935711890bcSjc156560 	uint32_t array_id)
1936711890bcSjc156560 {
1937711890bcSjc156560 	raid_obj_id_t obj_id;
1938711890bcSjc156560 
1939711890bcSjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
1940711890bcSjc156560 	if (obj_id < OBJ_NONE)
1941711890bcSjc156560 		return (obj_id);
1942711890bcSjc156560 
1943711890bcSjc156560 	obj_id = obj_locate_array_recur(raid_tab, obj_id, array_id);
1944711890bcSjc156560 
1945711890bcSjc156560 	return (obj_id);
1946711890bcSjc156560 }
1947711890bcSjc156560 
1948711890bcSjc156560 static raid_obj_id_t
1949711890bcSjc156560 obj_locate_array_recur(raid_obj_tab_t *raid_tab,
1950711890bcSjc156560 	raid_obj_id_t container_obj_id, uint32_t array_id)
1951711890bcSjc156560 {
1952711890bcSjc156560 	raid_obj_id_t obj_id, ret;
1953711890bcSjc156560 	array_attr_t *attr;
1954711890bcSjc156560 
1955711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, container_obj_id, OBJ_TYPE_ARRAY);
1956711890bcSjc156560 	if (obj_id <= OBJ_NONE)
1957711890bcSjc156560 		return (obj_id);
1958711890bcSjc156560 
1959711890bcSjc156560 	do {
1960711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1961711890bcSjc156560 		if (attr == NULL)
1962711890bcSjc156560 			return (ERR_DEVICE_INVALID);
1963711890bcSjc156560 
1964711890bcSjc156560 		if (attr->array_id == array_id)
1965711890bcSjc156560 			break;
1966711890bcSjc156560 
1967711890bcSjc156560 		ret = obj_locate_array_recur(raid_tab, obj_id, array_id);
1968711890bcSjc156560 		if (ret != OBJ_NONE)
1969711890bcSjc156560 			return (ret);
1970711890bcSjc156560 
1971711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
1972711890bcSjc156560 
1973711890bcSjc156560 	return (obj_id);
1974711890bcSjc156560 }
1975711890bcSjc156560 
1976711890bcSjc156560 static raid_obj_id_t
1977711890bcSjc156560 obj_locate_hsp(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1978711890bcSjc156560 	uint32_t disk_id, uint32_t array_id)
1979711890bcSjc156560 {
1980711890bcSjc156560 	raid_obj_id_t obj_id;
1981711890bcSjc156560 	hsp_attr_t *hsp_attr;
1982711890bcSjc156560 
1983711890bcSjc156560 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
1984711890bcSjc156560 	if (obj_id <= OBJ_NONE)
1985711890bcSjc156560 		return (obj_id);
1986711890bcSjc156560 
1987711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_HSP);
1988711890bcSjc156560 	if (obj_id <= OBJ_NONE)
1989711890bcSjc156560 		return (obj_id);
1990711890bcSjc156560 
1991711890bcSjc156560 	do {
1992711890bcSjc156560 		(void) obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
1993711890bcSjc156560 		if (hsp_attr->associated_id == array_id)
1994711890bcSjc156560 			break;
1995711890bcSjc156560 
1996711890bcSjc156560 		obj_id = obj_get_sibling(raid_tab, obj_id);
1997711890bcSjc156560 		if (obj_id < OBJ_NONE)
1998711890bcSjc156560 			return (obj_id);
1999711890bcSjc156560 	} while (obj_id > OBJ_NONE);
2000711890bcSjc156560 
2001711890bcSjc156560 	return (obj_id);
2002711890bcSjc156560 }
2003711890bcSjc156560 
2004711890bcSjc156560 static raid_obj_id_t
2005711890bcSjc156560 obj_locate_disk(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2006711890bcSjc156560 	uint32_t disk_id)
2007711890bcSjc156560 {
2008711890bcSjc156560 	raid_obj_id_t obj_id;
2009711890bcSjc156560 	disk_attr_t *attr;
2010711890bcSjc156560 
2011711890bcSjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
2012711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2013711890bcSjc156560 		return (obj_id);
2014711890bcSjc156560 
2015711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2016711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2017711890bcSjc156560 		return (obj_id);
2018711890bcSjc156560 
2019711890bcSjc156560 	do {
2020711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2021711890bcSjc156560 		if (attr == NULL)
2022711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2023711890bcSjc156560 
2024711890bcSjc156560 		if (attr->disk_id == disk_id)
2025711890bcSjc156560 			break;
2026711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2027711890bcSjc156560 
2028711890bcSjc156560 	return (obj_id);
2029711890bcSjc156560 }
2030711890bcSjc156560 
2031711890bcSjc156560 static raid_obj_id_t
2032711890bcSjc156560 obj_locate_arraypart(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2033711890bcSjc156560 	uint32_t array_id, uint32_t disk_id)
2034711890bcSjc156560 {
2035711890bcSjc156560 	raid_obj_id_t obj_id;
2036711890bcSjc156560 
2037711890bcSjc156560 	arraypart_attr_t *attr;
2038711890bcSjc156560 
2039711890bcSjc156560 	obj_id = obj_locate_array(raid_tab, controller_id, array_id);
2040711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2041711890bcSjc156560 		return (obj_id);
2042711890bcSjc156560 
2043711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY_PART);
2044711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2045711890bcSjc156560 		return (obj_id);
2046711890bcSjc156560 
2047711890bcSjc156560 	do {
2048711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2049711890bcSjc156560 		if (attr == NULL)
2050711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2051711890bcSjc156560 
2052711890bcSjc156560 		if (attr->disk_id == disk_id)
2053711890bcSjc156560 			break;
2054711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) >
2055711890bcSjc156560 	    OBJ_NONE);
2056711890bcSjc156560 
2057711890bcSjc156560 	return (obj_id);
2058711890bcSjc156560 }
2059711890bcSjc156560 
2060711890bcSjc156560 static raid_obj_id_t
2061711890bcSjc156560 obj_locate_diskseg(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2062711890bcSjc156560 	uint32_t disk_id, uint32_t seq_no)
2063711890bcSjc156560 {
2064711890bcSjc156560 	raid_obj_id_t obj_id;
2065711890bcSjc156560 	diskseg_attr_t *attr;
2066711890bcSjc156560 
2067711890bcSjc156560 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2068711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2069711890bcSjc156560 		return (obj_id);
2070711890bcSjc156560 
2071711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK_SEG);
2072711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2073711890bcSjc156560 		return (obj_id);
2074711890bcSjc156560 
2075711890bcSjc156560 	do {
2076711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2077711890bcSjc156560 		if (attr == NULL)
2078711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2079711890bcSjc156560 
2080711890bcSjc156560 		if (attr->seq_no == seq_no)
2081711890bcSjc156560 			break;
2082711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2083711890bcSjc156560 
2084711890bcSjc156560 	return (obj_id);
2085711890bcSjc156560 }
2086711890bcSjc156560 
2087711890bcSjc156560 static raid_obj_id_t
2088711890bcSjc156560 obj_locate_task(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2089711890bcSjc156560 	uint32_t task_id)
2090711890bcSjc156560 {
2091711890bcSjc156560 	raid_obj_id_t obj_id, obj_id2, task_obj_id;
2092711890bcSjc156560 	task_attr_t *attr;
2093711890bcSjc156560 
2094711890bcSjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
2095711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2096711890bcSjc156560 		return (obj_id);
2097711890bcSjc156560 
2098711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2099711890bcSjc156560 	if (obj_id < OBJ_NONE)
2100711890bcSjc156560 		return (obj_id);
2101711890bcSjc156560 
2102711890bcSjc156560 	do {
2103711890bcSjc156560 		obj_id2 = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2104711890bcSjc156560 		while (obj_id2 != OBJ_NONE) {
2105711890bcSjc156560 			task_obj_id = obj_get_comp(raid_tab, obj_id2,
2106711890bcSjc156560 			    OBJ_TYPE_TASK);
2107711890bcSjc156560 
2108711890bcSjc156560 			if (task_obj_id < OBJ_NONE)
2109711890bcSjc156560 				return (task_obj_id);
2110711890bcSjc156560 
2111711890bcSjc156560 			if (task_obj_id == OBJ_NONE) {
2112711890bcSjc156560 				obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2113711890bcSjc156560 				continue;
2114711890bcSjc156560 			}
2115711890bcSjc156560 
2116711890bcSjc156560 			attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2117711890bcSjc156560 			if (attr == NULL)
2118711890bcSjc156560 				return (ERR_DEVICE_INVALID);
2119711890bcSjc156560 
2120711890bcSjc156560 			if (attr->task_id == task_id)
2121711890bcSjc156560 				return (task_obj_id);
2122711890bcSjc156560 
2123711890bcSjc156560 			obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2124711890bcSjc156560 		}
2125711890bcSjc156560 
2126711890bcSjc156560 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2127711890bcSjc156560 		if (task_obj_id < OBJ_NONE)
2128711890bcSjc156560 			return (task_obj_id);
2129711890bcSjc156560 
2130711890bcSjc156560 		if (task_obj_id == OBJ_NONE)
2131711890bcSjc156560 			continue;
2132711890bcSjc156560 
2133711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2134711890bcSjc156560 		if (attr == NULL)
2135711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2136711890bcSjc156560 
2137711890bcSjc156560 		if (attr->task_id == task_id)
2138711890bcSjc156560 			return (task_obj_id);
2139711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2140711890bcSjc156560 
2141711890bcSjc156560 	if (obj_id < OBJ_NONE)
2142711890bcSjc156560 		return (obj_id);
2143711890bcSjc156560 
2144711890bcSjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
2145711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2146711890bcSjc156560 	if (obj_id < OBJ_NONE)
2147711890bcSjc156560 		return (obj_id);
2148711890bcSjc156560 
2149711890bcSjc156560 	do {
2150711890bcSjc156560 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2151711890bcSjc156560 		if (task_obj_id < OBJ_NONE)
2152711890bcSjc156560 			return (task_obj_id);
2153711890bcSjc156560 
2154711890bcSjc156560 		if (task_obj_id == OBJ_NONE)
2155711890bcSjc156560 			continue;
2156711890bcSjc156560 
2157711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2158711890bcSjc156560 		if (attr == NULL)
2159711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2160711890bcSjc156560 
2161711890bcSjc156560 		if (attr->task_id == task_id)
2162711890bcSjc156560 			return (task_obj_id);
2163711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2164711890bcSjc156560 
2165711890bcSjc156560 	return (obj_id);
2166711890bcSjc156560 
2167711890bcSjc156560 }
2168711890bcSjc156560 
2169711890bcSjc156560 static raid_obj_id_t
2170711890bcSjc156560 obj_get_controller(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2171711890bcSjc156560 {
2172711890bcSjc156560 	raid_obj_id_t id = obj_id;
2173711890bcSjc156560 
2174711890bcSjc156560 	while (raid_obj_get_type(raid_tab, id) != OBJ_TYPE_CONTROLLER) {
2175711890bcSjc156560 		id = raid_obj_get_container(raid_tab, id);
2176711890bcSjc156560 		if ((id == OBJ_SYSTEM) || (id < OBJ_NONE))
2177711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2178711890bcSjc156560 	}
2179711890bcSjc156560 
2180711890bcSjc156560 	return (id);
2181711890bcSjc156560 }
2182711890bcSjc156560 
2183711890bcSjc156560 /*
2184711890bcSjc156560  * Raid object operation routines
2185711890bcSjc156560  */
2186711890bcSjc156560 static int
2187711890bcSjc156560 obj_sys_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2188711890bcSjc156560 	raid_obj_type_id_t comp_type)
2189711890bcSjc156560 {
2190711890bcSjc156560 	DIR *dir;
2191711890bcSjc156560 	struct dirent *dp;
2192711890bcSjc156560 	int num = 0;
2193711890bcSjc156560 
2194711890bcSjc156560 	if ((raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM))
2195711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2196711890bcSjc156560 
2197711890bcSjc156560 	if (comp_type != OBJ_TYPE_CONTROLLER)
2198711890bcSjc156560 		return (0);
2199711890bcSjc156560 
2200711890bcSjc156560 	if ((dir = opendir(CFGDIR)) == NULL)
2201711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
2202711890bcSjc156560 
2203711890bcSjc156560 	while ((dp = readdir(dir)) != NULL) {
2204711890bcSjc156560 		uint32_t controller_id;
2205711890bcSjc156560 		char path[MAX_PATH_LEN];
2206711890bcSjc156560 
2207711890bcSjc156560 		if (strcmp(dp->d_name, ".") == 0 ||
2208711890bcSjc156560 		    strcmp(dp->d_name, "..") == 0)
2209711890bcSjc156560 			continue;
2210711890bcSjc156560 
2211711890bcSjc156560 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2212711890bcSjc156560 			continue;
2213711890bcSjc156560 
2214711890bcSjc156560 		if (controller_id_to_path(controller_id, path) == SUCCESS)
2215711890bcSjc156560 			++ num;
2216711890bcSjc156560 	}
2217711890bcSjc156560 
2218711890bcSjc156560 	(void) closedir(dir);
2219711890bcSjc156560 	return (num);
2220711890bcSjc156560 }
2221711890bcSjc156560 
2222711890bcSjc156560 static int
2223711890bcSjc156560 obj_sys_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2224711890bcSjc156560 	int num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2225711890bcSjc156560 {
2226711890bcSjc156560 	DIR *dir;
2227711890bcSjc156560 	struct dirent *dp;
2228711890bcSjc156560 	controller_attr_t *attr;
2229711890bcSjc156560 	uint32_t controller_id;
2230711890bcSjc156560 	uint32_t *tmplist;
2231711890bcSjc156560 	char path[MAX_PATH_LEN];
2232711890bcSjc156560 	int i = 0;
2233711890bcSjc156560 
2234711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM)
2235711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2236711890bcSjc156560 	if ((num <= 0) || (comp_list == NULL))
2237711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2238711890bcSjc156560 
2239711890bcSjc156560 	if (comp_type != OBJ_TYPE_CONTROLLER)
2240711890bcSjc156560 		return (0);
2241711890bcSjc156560 
2242711890bcSjc156560 	if ((dir = opendir(CFGDIR)) == NULL)
2243711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
2244711890bcSjc156560 	tmplist = calloc(num, sizeof (uint32_t));
2245711890bcSjc156560 	if (tmplist == NULL) {
2246711890bcSjc156560 		return (ERR_NOMEM);
2247711890bcSjc156560 	}
2248711890bcSjc156560 	while ((dp = readdir(dir)) != NULL) {
2249711890bcSjc156560 		if (strcmp(dp->d_name, ".") == 0 ||
2250711890bcSjc156560 		    strcmp(dp->d_name, "..") == 0)
2251711890bcSjc156560 			continue;
2252711890bcSjc156560 
2253711890bcSjc156560 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2254711890bcSjc156560 			continue;
2255711890bcSjc156560 
2256711890bcSjc156560 		if (controller_id_to_path(controller_id, path) == SUCCESS) {
2257711890bcSjc156560 			tmplist[i] = controller_id;
2258711890bcSjc156560 			++ i;
2259711890bcSjc156560 		}
2260711890bcSjc156560 	}
2261711890bcSjc156560 	qsort((void *)tmplist, num, sizeof (uint32_t), intcompare);
2262711890bcSjc156560 	for (i = 0; i < num; i++) {
2263711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab,
2264711890bcSjc156560 		    *(comp_list + i));
2265711890bcSjc156560 
2266711890bcSjc156560 		if (attr == NULL) {
2267711890bcSjc156560 			free(tmplist);
2268711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2269711890bcSjc156560 		}
2270711890bcSjc156560 
2271711890bcSjc156560 		attr->controller_id = tmplist[i];
2272711890bcSjc156560 	}
2273711890bcSjc156560 	free(tmplist);
2274711890bcSjc156560 	(void) closedir(dir);
2275711890bcSjc156560 	return (SUCCESS);
2276711890bcSjc156560 }
2277711890bcSjc156560 
2278711890bcSjc156560 static int
2279711890bcSjc156560 obj_controller_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2280711890bcSjc156560 	raid_obj_type_id_t comp_type)
2281711890bcSjc156560 {
2282711890bcSjc156560 	raid_lib_t *raid_lib;
2283711890bcSjc156560 	int ret = SUCCESS, fd;
2284711890bcSjc156560 	controller_attr_t *ctl_attrp;
2285711890bcSjc156560 
2286711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2287711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2288711890bcSjc156560 
2289711890bcSjc156560 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2290711890bcSjc156560 		return (0);
2291711890bcSjc156560 
2292711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2293711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
2294711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2295711890bcSjc156560 	if ((raid_lib == NULL) || (ctl_attrp == NULL) || (fd == 0))
2296711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2297711890bcSjc156560 
2298711890bcSjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id, 0,
2299711890bcSjc156560 	    OBJ_TYPE_CONTROLLER, comp_type);
2300711890bcSjc156560 
2301711890bcSjc156560 	return (ret);
2302711890bcSjc156560 }
2303711890bcSjc156560 
2304711890bcSjc156560 static int
2305711890bcSjc156560 obj_controller_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2306711890bcSjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2307711890bcSjc156560 {
2308711890bcSjc156560 	raid_lib_t *raid_lib;
2309711890bcSjc156560 	controller_attr_t *ctl_attrp;
2310711890bcSjc156560 	int ret, i, fd;
2311711890bcSjc156560 	uint32_t *ids;
2312711890bcSjc156560 
2313711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2314711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2315711890bcSjc156560 
2316711890bcSjc156560 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2317711890bcSjc156560 		return (0);
2318711890bcSjc156560 
2319711890bcSjc156560 	if ((comp_num <= 0) || (comp_list == NULL))
2320711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2321711890bcSjc156560 
2322711890bcSjc156560 	for (i = 0; i < comp_num; ++i)
2323711890bcSjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2324711890bcSjc156560 		    comp_type)
2325711890bcSjc156560 			return (ERR_DEVICE_TYPE);
2326711890bcSjc156560 
2327711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2328711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2329711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
2330711890bcSjc156560 	if ((raid_lib == NULL) || (ctl_attrp == NULL)|| (fd == 0))
2331711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2332711890bcSjc156560 
2333711890bcSjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
2334711890bcSjc156560 	if (ids == NULL)
2335711890bcSjc156560 		return (ERR_NOMEM);
2336711890bcSjc156560 
2337711890bcSjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id, 0,
2338711890bcSjc156560 	    OBJ_TYPE_CONTROLLER, comp_type, comp_num, ids);
2339711890bcSjc156560 	if (ret < SUCCESS) {
2340711890bcSjc156560 		free(ids);
2341711890bcSjc156560 		return (ret);
2342711890bcSjc156560 	}
2343711890bcSjc156560 	qsort((void *)ids, comp_num, sizeof (uint32_t), intcompare);
2344711890bcSjc156560 	for (i = 0; i < comp_num; ++ i) {
2345711890bcSjc156560 		array_attr_t *array_attr;
2346711890bcSjc156560 		disk_attr_t *disk_attr;
2347711890bcSjc156560 		void *attr_buf;
2348711890bcSjc156560 
2349711890bcSjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2350711890bcSjc156560 		if (attr_buf == NULL) {
2351711890bcSjc156560 			free(ids);
2352711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2353711890bcSjc156560 		}
2354711890bcSjc156560 
2355711890bcSjc156560 		switch (comp_type) {
2356711890bcSjc156560 		case OBJ_TYPE_ARRAY:
2357711890bcSjc156560 			array_attr = attr_buf;
2358711890bcSjc156560 			array_attr->array_id = *(ids + i);
2359711890bcSjc156560 			break;
2360711890bcSjc156560 		case OBJ_TYPE_DISK:
2361711890bcSjc156560 			disk_attr = attr_buf;
2362711890bcSjc156560 			disk_attr->disk_id = *(ids + i);
2363711890bcSjc156560 			break;
2364711890bcSjc156560 		default:
2365711890bcSjc156560 			free(ids);
2366711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2367711890bcSjc156560 		}
2368711890bcSjc156560 	}
2369711890bcSjc156560 
2370711890bcSjc156560 	free(ids);
2371711890bcSjc156560 	return (SUCCESS);
2372711890bcSjc156560 }
2373711890bcSjc156560 
2374711890bcSjc156560 static int
2375711890bcSjc156560 obj_controller_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2376711890bcSjc156560 {
2377711890bcSjc156560 	controller_attr_t *attr;
2378711890bcSjc156560 	raid_lib_t *raid_lib;
2379711890bcSjc156560 	int ret = SUCCESS, fd;
2380711890bcSjc156560 
2381711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2382711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2383711890bcSjc156560 
2384711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2385711890bcSjc156560 		return (SUCCESS);
2386711890bcSjc156560 
2387711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2388711890bcSjc156560 	if (attr == NULL)
2389711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2390711890bcSjc156560 
2391711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2392711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
2393711890bcSjc156560 
2394711890bcSjc156560 	/*
2395711890bcSjc156560 	 * For a controller, even it's not opened, we can still
2396711890bcSjc156560 	 * get the driver name
2397711890bcSjc156560 	 */
2398711890bcSjc156560 
2399711890bcSjc156560 	if (fd == 0)
2400711890bcSjc156560 		return (SUCCESS);
2401711890bcSjc156560 
2402711890bcSjc156560 	if (raid_lib == NULL) {
2403711890bcSjc156560 		return (SUCCESS);
2404711890bcSjc156560 	}
2405711890bcSjc156560 
2406711890bcSjc156560 	ret = raid_lib->get_attr(attr->controller_id, OBJ_ATTR_NONE,
2407711890bcSjc156560 	    OBJ_ATTR_NONE, OBJ_TYPE_CONTROLLER, attr);
2408711890bcSjc156560 	if (ret < SUCCESS)
2409711890bcSjc156560 		return (ret);
2410711890bcSjc156560 
2411711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2412711890bcSjc156560 
2413711890bcSjc156560 	return (ret);
2414711890bcSjc156560 }
2415711890bcSjc156560 
2416711890bcSjc156560 static int
2417711890bcSjc156560 obj_controller_act(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2418711890bcSjc156560 	uint32_t sub_cmd, void *prop_list, char **plugin_err_str)
2419711890bcSjc156560 {
2420711890bcSjc156560 	controller_attr_t *attr;
2421711890bcSjc156560 	raid_lib_t *raid_lib;
2422711890bcSjc156560 	int ret, fd;
2423711890bcSjc156560 
2424711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2425711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2426711890bcSjc156560 
2427711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2428711890bcSjc156560 
2429711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2430711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
2431711890bcSjc156560 
2432711890bcSjc156560 	switch (sub_cmd) {
2433711890bcSjc156560 	case ACT_CONTROLLER_OPEN:
2434711890bcSjc156560 		/* Check if already opened */
2435711890bcSjc156560 
2436711890bcSjc156560 		if (fd > 0)
2437711890bcSjc156560 			return (SUCCESS);
2438711890bcSjc156560 
2439711890bcSjc156560 		/* Check if plugin is already attached */
2440711890bcSjc156560 		if (raid_lib == NULL) {
2441711890bcSjc156560 			raid_lib = raid_find_lib(raid_tab, obj_id);
2442711890bcSjc156560 			if (raid_lib == NULL)
2443711890bcSjc156560 				return (ERR_DRIVER_NOT_FOUND);
2444711890bcSjc156560 		}
2445711890bcSjc156560 
2446711890bcSjc156560 		ret = raid_lib->open_controller(attr->controller_id,
2447711890bcSjc156560 		    plugin_err_str);
2448711890bcSjc156560 		if (ret == SUCCESS) {
2449711890bcSjc156560 			(void) raid_obj_set_lib(raid_tab, obj_id, raid_lib);
2450711890bcSjc156560 			(void) raid_obj_set_fd(raid_tab, obj_id, 1);
2451711890bcSjc156560 		}
2452711890bcSjc156560 		break;
2453711890bcSjc156560 	case ACT_CONTROLLER_CLOSE:
2454711890bcSjc156560 
2455711890bcSjc156560 		if (fd <= 0)
2456711890bcSjc156560 			return (SUCCESS);
2457711890bcSjc156560 
2458711890bcSjc156560 		if (raid_lib == NULL) {
2459711890bcSjc156560 			return (SUCCESS);
2460711890bcSjc156560 		}
2461711890bcSjc156560 		ret = raid_lib->close_controller(attr->controller_id,
2462711890bcSjc156560 		    plugin_err_str);
2463711890bcSjc156560 		if (ret == SUCCESS) {
2464711890bcSjc156560 			(void) raid_obj_set_fd(raid_tab, obj_id, 0);
2465711890bcSjc156560 			(void) raid_obj_set_lib(raid_tab, obj_id, NULL);
2466711890bcSjc156560 			raid_handle_delete_controller_comp(attr->controller_id);
2467711890bcSjc156560 		}
2468711890bcSjc156560 		break;
2469711890bcSjc156560 	case ACT_CONTROLLER_FLASH_FW:
2470711890bcSjc156560 		{
2471711890bcSjc156560 			char		*filebuf;
2472711890bcSjc156560 			int		image_fd;
2473711890bcSjc156560 			uint32_t	size;
2474711890bcSjc156560 			struct stat	statbuf;
2475711890bcSjc156560 
2476711890bcSjc156560 			if (prop_list == NULL)
2477711890bcSjc156560 				return (ERR_OP_ILLEGAL);
2478711890bcSjc156560 
2479711890bcSjc156560 			/* Open firmware image file */
2480711890bcSjc156560 			image_fd = open((const char *)prop_list,
2481711890bcSjc156560 			    O_RDONLY | O_NDELAY);
2482711890bcSjc156560 			if (image_fd == -1)
2483711890bcSjc156560 				return (ERR_OP_FAILED);
2484711890bcSjc156560 
2485711890bcSjc156560 			if (fstat(image_fd, &statbuf) != 0) {
2486711890bcSjc156560 				(void) close(image_fd);
2487711890bcSjc156560 				return (ERR_OP_FAILED);
2488711890bcSjc156560 			}
2489711890bcSjc156560 
2490711890bcSjc156560 			filebuf = malloc(statbuf.st_size);
2491711890bcSjc156560 			if (filebuf == NULL) {
2492711890bcSjc156560 				(void) close(image_fd);
2493711890bcSjc156560 				return (ERR_NOMEM);
2494711890bcSjc156560 			}
2495711890bcSjc156560 
2496711890bcSjc156560 			size = read(image_fd, filebuf, statbuf.st_size);
2497711890bcSjc156560 			if (size != statbuf.st_size) {
2498711890bcSjc156560 				(void) close(image_fd);
2499711890bcSjc156560 				free(filebuf);
2500711890bcSjc156560 				return (ERR_OP_FAILED);
2501711890bcSjc156560 			}
2502711890bcSjc156560 
2503711890bcSjc156560 			if (fd <= 0) {
2504711890bcSjc156560 				(void) close(image_fd);
2505711890bcSjc156560 				free(filebuf);
2506711890bcSjc156560 				return (ERR_DRIVER_CLOSED);
2507711890bcSjc156560 			}
2508711890bcSjc156560 
2509711890bcSjc156560 			if (raid_lib == NULL) {
2510711890bcSjc156560 				(void) close(image_fd);
2511711890bcSjc156560 				free(filebuf);
2512711890bcSjc156560 				return (ERR_DRIVER_CLOSED);
2513711890bcSjc156560 			}
2514711890bcSjc156560 			if (raid_lib->flash_fw == NULL) {
2515711890bcSjc156560 				(void) close(image_fd);
2516711890bcSjc156560 				free(filebuf);
2517711890bcSjc156560 				return (ERR_OP_NO_IMPL);
2518711890bcSjc156560 			}
2519711890bcSjc156560 
2520711890bcSjc156560 			ret = raid_lib->flash_fw(attr->controller_id,
2521711890bcSjc156560 			    filebuf, size, plugin_err_str);
2522711890bcSjc156560 		}
2523711890bcSjc156560 		break;
2524711890bcSjc156560 	default:
2525711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2526711890bcSjc156560 	}
2527711890bcSjc156560 
2528711890bcSjc156560 	return (ret);
2529711890bcSjc156560 }
2530711890bcSjc156560 
2531711890bcSjc156560 static int
2532711890bcSjc156560 obj_array_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2533711890bcSjc156560 	raid_obj_type_id_t comp_type)
2534711890bcSjc156560 {
2535711890bcSjc156560 	array_attr_t *attr;
2536711890bcSjc156560 	controller_attr_t *ctl_attrp;
2537711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2538711890bcSjc156560 	raid_lib_t *raid_lib;
2539711890bcSjc156560 	int ret = SUCCESS, fd;
2540711890bcSjc156560 
2541711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2542711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2543711890bcSjc156560 
2544711890bcSjc156560 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
2545711890bcSjc156560 	    comp_type != OBJ_TYPE_ARRAY &&
2546711890bcSjc156560 	    comp_type != OBJ_TYPE_TASK)
2547711890bcSjc156560 		return (0);
2548711890bcSjc156560 
2549711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2550711890bcSjc156560 	if (attr == NULL)
2551711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2552711890bcSjc156560 
2553711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2554711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2555711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2556711890bcSjc156560 
2557711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2558711890bcSjc156560 	if (ctl_attrp == NULL) {
2559711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2560711890bcSjc156560 	}
2561711890bcSjc156560 
2562711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2563711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2564711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2565711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2566711890bcSjc156560 
2567711890bcSjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id, attr->array_id,
2568711890bcSjc156560 	    OBJ_TYPE_ARRAY, comp_type);
2569711890bcSjc156560 
2570711890bcSjc156560 	return (ret);
2571711890bcSjc156560 }
2572711890bcSjc156560 
2573711890bcSjc156560 static int
2574711890bcSjc156560 obj_array_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2575711890bcSjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2576711890bcSjc156560 {
2577711890bcSjc156560 	array_attr_t *attr;
2578711890bcSjc156560 	controller_attr_t *ctl_attrp;
2579711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2580711890bcSjc156560 	raid_lib_t *raid_lib;
2581711890bcSjc156560 	int ret, i, fd;
2582711890bcSjc156560 	uint32_t *ids;
2583711890bcSjc156560 
2584711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2585711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2586711890bcSjc156560 
2587711890bcSjc156560 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
2588711890bcSjc156560 	    comp_type != OBJ_TYPE_ARRAY &&
2589711890bcSjc156560 	    comp_type != OBJ_TYPE_TASK)
2590711890bcSjc156560 		return (0);
2591711890bcSjc156560 
2592711890bcSjc156560 	if (comp_num <= 0 || comp_list == NULL)
2593711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2594711890bcSjc156560 
2595711890bcSjc156560 	for (i = 0; i < comp_num; ++i)
2596711890bcSjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2597711890bcSjc156560 		    comp_type)
2598711890bcSjc156560 			return (ERR_DEVICE_TYPE);
2599711890bcSjc156560 
2600711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2601711890bcSjc156560 	if (attr == NULL)
2602711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2603711890bcSjc156560 
2604711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2605711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2606711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2607711890bcSjc156560 
2608711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2609711890bcSjc156560 	if (ctl_attrp == NULL) {
2610711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2611711890bcSjc156560 	}
2612711890bcSjc156560 
2613711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2614711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2615711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2616711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2617711890bcSjc156560 
2618711890bcSjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
2619711890bcSjc156560 	if (ids == NULL)
2620711890bcSjc156560 		return (ERR_NOMEM);
2621711890bcSjc156560 
2622711890bcSjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id,
2623711890bcSjc156560 	    attr->array_id, OBJ_TYPE_ARRAY, comp_type, comp_num, ids);
2624711890bcSjc156560 
2625711890bcSjc156560 	if (ret < SUCCESS) {
2626711890bcSjc156560 		free(ids);
2627711890bcSjc156560 		return (ret);
2628711890bcSjc156560 	}
2629711890bcSjc156560 
2630711890bcSjc156560 	for (i = 0; i < comp_num; ++ i) {
2631711890bcSjc156560 		array_attr_t *array_attr;
2632711890bcSjc156560 		arraypart_attr_t *arraypart_attr;
2633711890bcSjc156560 		task_attr_t *task_attr;
2634711890bcSjc156560 		void *attr_buf;
2635711890bcSjc156560 
2636711890bcSjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2637711890bcSjc156560 		if (attr_buf == NULL) {
2638711890bcSjc156560 			free(ids);
2639711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2640711890bcSjc156560 		}
2641711890bcSjc156560 
2642711890bcSjc156560 		switch (comp_type) {
2643711890bcSjc156560 		case OBJ_TYPE_ARRAY:
2644711890bcSjc156560 			array_attr = attr_buf;
2645711890bcSjc156560 			array_attr->array_id = *(ids + i);
2646711890bcSjc156560 			break;
2647711890bcSjc156560 		case OBJ_TYPE_ARRAY_PART:
2648711890bcSjc156560 			arraypart_attr = attr_buf;
2649711890bcSjc156560 			arraypart_attr->disk_id = *(ids + i);
2650711890bcSjc156560 			break;
2651711890bcSjc156560 		case OBJ_TYPE_TASK:
2652711890bcSjc156560 			task_attr = attr_buf;
2653711890bcSjc156560 			task_attr->task_id = *(ids + i);
2654711890bcSjc156560 			break;
2655711890bcSjc156560 		default:
2656711890bcSjc156560 			free(ids);
2657711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2658711890bcSjc156560 		}
2659711890bcSjc156560 	}
2660711890bcSjc156560 
2661711890bcSjc156560 
2662711890bcSjc156560 	free(ids);
2663711890bcSjc156560 	return (ret);
2664711890bcSjc156560 }
2665711890bcSjc156560 
2666711890bcSjc156560 static int
2667711890bcSjc156560 obj_array_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2668711890bcSjc156560 {
2669711890bcSjc156560 	array_attr_t *attr;
2670711890bcSjc156560 	controller_attr_t *ctl_attrp;
2671711890bcSjc156560 	raid_lib_t *raid_lib;
2672711890bcSjc156560 	int ret = SUCCESS, fd;
2673711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2674711890bcSjc156560 
2675711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2676711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2677711890bcSjc156560 
2678711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2679711890bcSjc156560 		return (SUCCESS);
2680711890bcSjc156560 
2681711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2682711890bcSjc156560 	if (attr == NULL)
2683711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2684711890bcSjc156560 
2685711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2686711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2687711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2688711890bcSjc156560 
2689711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2690711890bcSjc156560 	if (ctl_attrp == NULL) {
2691711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2692711890bcSjc156560 	}
2693711890bcSjc156560 
2694711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2695711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2696711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2697711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2698711890bcSjc156560 
2699711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
2700711890bcSjc156560 	    attr->array_id, 0, OBJ_TYPE_ARRAY, attr);
2701711890bcSjc156560 
2702711890bcSjc156560 	if (ret < SUCCESS)
2703711890bcSjc156560 		return (ret);
2704711890bcSjc156560 
2705711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2706711890bcSjc156560 
2707711890bcSjc156560 	return (ret);
2708711890bcSjc156560 }
2709711890bcSjc156560 
2710711890bcSjc156560 static int
2711711890bcSjc156560 obj_array_set_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2712711890bcSjc156560 	uint32_t sub_cmd, uint32_t *value, char **plugin_err_str)
2713711890bcSjc156560 {
2714711890bcSjc156560 	array_attr_t *attr;
2715711890bcSjc156560 	controller_attr_t *ctl_attrp;
2716711890bcSjc156560 	raid_lib_t *raid_lib;
2717711890bcSjc156560 	int ret = SUCCESS, fd;
2718711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2719711890bcSjc156560 
2720711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2721711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2722711890bcSjc156560 
2723711890bcSjc156560 	switch (sub_cmd) {
2724711890bcSjc156560 	case SET_CACHE_WR_PLY:
2725711890bcSjc156560 		if (*value != CACHE_WR_OFF &&
2726711890bcSjc156560 		    *value != CACHE_WR_ON)
2727711890bcSjc156560 			return (ERR_OP_ILLEGAL);
2728711890bcSjc156560 		break;
2729711890bcSjc156560 	case SET_CACHE_RD_PLY:
2730711890bcSjc156560 		if (*value != CACHE_RD_OFF &&
2731711890bcSjc156560 		    *value != CACHE_RD_ON)
2732711890bcSjc156560 			return (ERR_OP_ILLEGAL);
2733711890bcSjc156560 		break;
2734711890bcSjc156560 	default:
2735711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2736711890bcSjc156560 	}
2737711890bcSjc156560 
2738711890bcSjc156560 	(void) obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2739711890bcSjc156560 
2740711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2741711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2742711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2743711890bcSjc156560 
2744711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2745711890bcSjc156560 	if (ctl_attrp == NULL) {
2746711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2747711890bcSjc156560 	}
2748711890bcSjc156560 
2749711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2750711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2751711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2752711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2753711890bcSjc156560 
2754711890bcSjc156560 	if (raid_lib->set_attr == NULL)
2755711890bcSjc156560 		return (ERR_OP_NO_IMPL);
2756711890bcSjc156560 
2757711890bcSjc156560 	ret = raid_lib->set_attr(ctl_attrp->controller_id,
2758711890bcSjc156560 	    attr->array_id, sub_cmd, value, plugin_err_str);
2759711890bcSjc156560 
2760711890bcSjc156560 	return (ret);
2761711890bcSjc156560 }
2762711890bcSjc156560 
2763711890bcSjc156560 static int
2764711890bcSjc156560 obj_disk_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2765711890bcSjc156560 	raid_obj_type_id_t comp_type)
2766711890bcSjc156560 {
2767711890bcSjc156560 	disk_attr_t *attr;
2768711890bcSjc156560 	controller_attr_t *ctl_attrp;
2769711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2770711890bcSjc156560 	raid_lib_t *raid_lib;
2771711890bcSjc156560 	int ret = SUCCESS, fd;
2772711890bcSjc156560 
2773711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2774711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2775711890bcSjc156560 
2776711890bcSjc156560 	if (comp_type != OBJ_TYPE_DISK_SEG &&
2777711890bcSjc156560 	    comp_type != OBJ_TYPE_HSP &&
2778711890bcSjc156560 	    comp_type != OBJ_TYPE_TASK)
2779711890bcSjc156560 		return (0);
2780711890bcSjc156560 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2781711890bcSjc156560 	if ((ret != SUCCESS) || (attr == NULL)) {
2782711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2783711890bcSjc156560 	}
2784711890bcSjc156560 	if (attr->state == DISK_STATE_FAILED) {
2785711890bcSjc156560 		return (SUCCESS);
2786711890bcSjc156560 	}
2787711890bcSjc156560 
2788711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2789711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2790711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2791711890bcSjc156560 
2792711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2793711890bcSjc156560 	if (ctl_attrp == NULL) {
2794711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2795711890bcSjc156560 	}
2796711890bcSjc156560 
2797711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2798711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2799711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2800711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2801711890bcSjc156560 
2802711890bcSjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id,
2803711890bcSjc156560 	    attr->disk_id, OBJ_TYPE_DISK, comp_type);
2804711890bcSjc156560 
2805711890bcSjc156560 	return (ret);
2806711890bcSjc156560 }
2807711890bcSjc156560 
2808711890bcSjc156560 static int
2809711890bcSjc156560 obj_disk_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2810711890bcSjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2811711890bcSjc156560 {
2812711890bcSjc156560 	disk_attr_t *attr;
2813711890bcSjc156560 	controller_attr_t *ctl_attrp;
2814711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2815711890bcSjc156560 	raid_lib_t *raid_lib;
2816711890bcSjc156560 	int ret, i, fd;
2817711890bcSjc156560 	uint32_t *ids;
2818711890bcSjc156560 
2819711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2820711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2821711890bcSjc156560 
2822711890bcSjc156560 	if (comp_type != OBJ_TYPE_DISK_SEG &&
2823711890bcSjc156560 	    comp_type != OBJ_TYPE_HSP &&
2824711890bcSjc156560 	    comp_type != OBJ_TYPE_TASK)
2825711890bcSjc156560 		return (0);
2826711890bcSjc156560 
2827711890bcSjc156560 	if (comp_num <= 0 || comp_list == NULL)
2828711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2829711890bcSjc156560 
2830711890bcSjc156560 	for (i = 0; i < comp_num; ++i)
2831711890bcSjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2832711890bcSjc156560 		    comp_type)
2833711890bcSjc156560 			return (ERR_DEVICE_TYPE);
2834711890bcSjc156560 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2835711890bcSjc156560 	if ((ret != SUCCESS) || (attr == NULL)) {
2836711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2837711890bcSjc156560 	}
2838711890bcSjc156560 	if (attr->state == DISK_STATE_FAILED) {
2839711890bcSjc156560 		return (SUCCESS);
2840711890bcSjc156560 	}
2841711890bcSjc156560 
2842711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2843711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2844711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2845711890bcSjc156560 
2846711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2847711890bcSjc156560 	if (ctl_attrp == NULL) {
2848711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2849711890bcSjc156560 	}
2850711890bcSjc156560 
2851711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2852711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2853711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2854711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2855711890bcSjc156560 
2856711890bcSjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
2857711890bcSjc156560 	if (ids == NULL)
2858711890bcSjc156560 		return (ERR_NOMEM);
2859711890bcSjc156560 
2860711890bcSjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id,
2861711890bcSjc156560 	    attr->disk_id, OBJ_TYPE_DISK, comp_type, comp_num, ids);
2862711890bcSjc156560 
2863711890bcSjc156560 	if (ret < SUCCESS) {
2864711890bcSjc156560 		free(ids);
2865711890bcSjc156560 		return (ret);
2866711890bcSjc156560 	}
2867711890bcSjc156560 
2868711890bcSjc156560 	for (i = 0; i < comp_num; ++ i) {
2869711890bcSjc156560 		diskseg_attr_t *diskseg_attr;
2870711890bcSjc156560 		hsp_attr_t *hsp_attr;
2871711890bcSjc156560 		task_attr_t *task_attr;
2872711890bcSjc156560 		void *attr_buf;
2873711890bcSjc156560 
2874711890bcSjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2875711890bcSjc156560 		if (attr_buf == NULL) {
2876711890bcSjc156560 			free(ids);
2877711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2878711890bcSjc156560 		}
2879711890bcSjc156560 
2880711890bcSjc156560 		switch (comp_type) {
2881711890bcSjc156560 		case OBJ_TYPE_DISK_SEG:
2882711890bcSjc156560 			diskseg_attr = attr_buf;
2883711890bcSjc156560 			diskseg_attr->seq_no = *(ids + i);
2884711890bcSjc156560 			break;
2885711890bcSjc156560 		case OBJ_TYPE_HSP:
2886711890bcSjc156560 			hsp_attr = attr_buf;
2887711890bcSjc156560 			hsp_attr->associated_id = *(ids + i);
2888711890bcSjc156560 			break;
2889711890bcSjc156560 		case OBJ_TYPE_TASK:
2890711890bcSjc156560 			task_attr = attr_buf;
2891711890bcSjc156560 			task_attr->task_id = *(ids + i);
2892711890bcSjc156560 			break;
2893711890bcSjc156560 		default:
2894711890bcSjc156560 			free(ids);
2895711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2896711890bcSjc156560 		}
2897711890bcSjc156560 	}
2898711890bcSjc156560 
2899711890bcSjc156560 
2900711890bcSjc156560 	free(ids);
2901711890bcSjc156560 	return (ret);
2902711890bcSjc156560 }
2903711890bcSjc156560 
2904711890bcSjc156560 static int
2905711890bcSjc156560 obj_disk_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2906711890bcSjc156560 {
2907711890bcSjc156560 	disk_attr_t *attr;
2908711890bcSjc156560 	controller_attr_t *ctl_attrp;
2909711890bcSjc156560 	raid_lib_t *raid_lib;
2910711890bcSjc156560 	int ret = SUCCESS, fd;
2911711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2912711890bcSjc156560 
2913711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2914711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2915711890bcSjc156560 
2916711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2917711890bcSjc156560 		return (SUCCESS);
2918711890bcSjc156560 
2919711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2920711890bcSjc156560 	if (attr == NULL)
2921711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2922711890bcSjc156560 
2923711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2924711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2925711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2926711890bcSjc156560 
2927711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2928711890bcSjc156560 	if (ctl_attrp == NULL) {
2929711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2930711890bcSjc156560 	}
2931711890bcSjc156560 
2932711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2933711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2934711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2935711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2936711890bcSjc156560 
2937711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
2938711890bcSjc156560 	    attr->disk_id, 0, OBJ_TYPE_DISK, attr);
2939711890bcSjc156560 
2940711890bcSjc156560 	if (ret < SUCCESS)
2941711890bcSjc156560 		return (ret);
2942711890bcSjc156560 
2943711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2944711890bcSjc156560 
2945711890bcSjc156560 	return (ret);
2946711890bcSjc156560 }
2947711890bcSjc156560 
2948711890bcSjc156560 static int
2949711890bcSjc156560 obj_hsp_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2950711890bcSjc156560 {
2951711890bcSjc156560 	hsp_attr_t *attr;
2952711890bcSjc156560 
2953711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_HSP)
2954711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2955711890bcSjc156560 
2956711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2957711890bcSjc156560 		return (SUCCESS);
2958711890bcSjc156560 
2959711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2960711890bcSjc156560 	if (attr == NULL)
2961711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2962711890bcSjc156560 
2963711890bcSjc156560 	if (attr->associated_id == (uint32_t)OBJ_ATTR_NONE)
2964711890bcSjc156560 		attr->type = HSP_TYPE_GLOBAL;
2965711890bcSjc156560 	else
2966711890bcSjc156560 		attr->type = HSP_TYPE_LOCAL;
2967711890bcSjc156560 
2968711890bcSjc156560 	return (SUCCESS);
2969711890bcSjc156560 }
2970711890bcSjc156560 
2971711890bcSjc156560 static int
2972711890bcSjc156560 obj_arraypart_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2973711890bcSjc156560 {
2974711890bcSjc156560 	arraypart_attr_t *attr;
2975711890bcSjc156560 	array_attr_t *array_attr;
2976711890bcSjc156560 	controller_attr_t *ctl_attrp;
2977711890bcSjc156560 	raid_lib_t *raid_lib;
2978711890bcSjc156560 	int ret = SUCCESS, fd;
2979711890bcSjc156560 	raid_obj_id_t controller_obj_id, array_obj_id;
2980711890bcSjc156560 
2981711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY_PART)
2982711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2983711890bcSjc156560 
2984711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2985711890bcSjc156560 		return (SUCCESS);
2986711890bcSjc156560 
2987711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2988711890bcSjc156560 	if (attr == NULL)
2989711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2990711890bcSjc156560 
2991711890bcSjc156560 	array_obj_id = raid_obj_get_container(raid_tab, obj_id);
2992711890bcSjc156560 	if (array_obj_id < OBJ_NONE)
2993711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2994711890bcSjc156560 
2995711890bcSjc156560 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
2996711890bcSjc156560 	if (array_attr == NULL)
2997711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2998711890bcSjc156560 
2999711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3000711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
3001711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3002711890bcSjc156560 
3003711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3004711890bcSjc156560 	if (ctl_attrp == NULL) {
3005711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3006711890bcSjc156560 	}
3007711890bcSjc156560 
3008711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3009711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3010711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3011711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3012711890bcSjc156560 
3013711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3014711890bcSjc156560 	    array_attr->array_id, attr->disk_id,
3015711890bcSjc156560 	    OBJ_TYPE_ARRAY_PART, attr);
3016711890bcSjc156560 
3017711890bcSjc156560 	if (ret < SUCCESS)
3018711890bcSjc156560 		return (ret);
3019711890bcSjc156560 
3020711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3021711890bcSjc156560 
3022711890bcSjc156560 	return (ret);
3023711890bcSjc156560 }
3024711890bcSjc156560 
3025711890bcSjc156560 static int
3026711890bcSjc156560 obj_diskseg_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3027711890bcSjc156560 {
3028711890bcSjc156560 	diskseg_attr_t *attr;
3029711890bcSjc156560 	disk_attr_t *disk_attr;
3030711890bcSjc156560 	controller_attr_t *ctl_attrp;
3031711890bcSjc156560 	raid_lib_t *raid_lib;
3032711890bcSjc156560 	int ret = SUCCESS, fd;
3033711890bcSjc156560 	raid_obj_id_t controller_obj_id, disk_obj_id;
3034711890bcSjc156560 
3035711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK_SEG)
3036711890bcSjc156560 		return (ERR_DEVICE_TYPE);
3037711890bcSjc156560 
3038711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3039711890bcSjc156560 		return (SUCCESS);
3040711890bcSjc156560 
3041711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3042711890bcSjc156560 	if (attr == NULL)
3043711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3044711890bcSjc156560 
3045711890bcSjc156560 	disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
3046711890bcSjc156560 	if (disk_obj_id < OBJ_NONE)
3047711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3048711890bcSjc156560 
3049711890bcSjc156560 	disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
3050711890bcSjc156560 	if (disk_attr == NULL)
3051711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3052711890bcSjc156560 
3053711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3054711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
3055711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3056711890bcSjc156560 
3057711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3058711890bcSjc156560 	if (ctl_attrp == NULL) {
3059711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3060711890bcSjc156560 	}
3061711890bcSjc156560 
3062711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3063711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3064711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3065711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3066711890bcSjc156560 
3067711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3068711890bcSjc156560 	    disk_attr->disk_id, attr->seq_no, OBJ_TYPE_DISK_SEG, attr);
3069711890bcSjc156560 
3070711890bcSjc156560 	if (ret < SUCCESS)
3071711890bcSjc156560 		return (ret);
3072711890bcSjc156560 
3073711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3074711890bcSjc156560 
3075711890bcSjc156560 	return (ret);
3076711890bcSjc156560 }
3077711890bcSjc156560 
3078711890bcSjc156560 static int
3079711890bcSjc156560 obj_task_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3080711890bcSjc156560 {
3081711890bcSjc156560 	task_attr_t *attr;
3082711890bcSjc156560 	controller_attr_t *ctl_attrp;
3083711890bcSjc156560 	raid_lib_t *raid_lib;
3084711890bcSjc156560 	int ret = SUCCESS, fd;
3085711890bcSjc156560 	raid_obj_id_t controller_obj_id;
3086711890bcSjc156560 
3087711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_TASK)
3088711890bcSjc156560 		return (ERR_DEVICE_TYPE);
3089711890bcSjc156560 
3090711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3091711890bcSjc156560 	if (attr == NULL)
3092711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3093711890bcSjc156560 
3094711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3095711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
3096711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3097711890bcSjc156560 
3098711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3099711890bcSjc156560 	if (ctl_attrp == NULL) {
3100711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3101711890bcSjc156560 	}
3102711890bcSjc156560 
3103711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3104711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3105711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3106711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3107711890bcSjc156560 
3108711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3109711890bcSjc156560 	    attr->task_id, OBJ_ATTR_NONE, OBJ_TYPE_TASK, attr);
3110711890bcSjc156560 
3111711890bcSjc156560 	return (ret);
3112711890bcSjc156560 }
3113711890bcSjc156560 
3114711890bcSjc156560 static int
3115711890bcSjc156560 obj_array_create(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3116711890bcSjc156560 	int num_of_comp, raid_obj_id_t *disk_list, char **plugin_err_str)
3117711890bcSjc156560 {
3118711890bcSjc156560 	controller_attr_t *controller_attr;
3119711890bcSjc156560 	array_attr_t *array_attr, array_attr2;
3120711890bcSjc156560 	disk_attr_t *disk_attr;
3121711890bcSjc156560 	arraypart_attr_t *arraypart_attrs;
3122711890bcSjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3123711890bcSjc156560 	raid_lib_t *raid_lib;
3124711890bcSjc156560 	int i, j, ret, fd;
3125711890bcSjc156560 	int disk_cnt = 0, disk_set_num = 0, set_num = 0, layer_cnt = 0;
3126711890bcSjc156560 	uint64_t min_disk_capacity = 0;
3127711890bcSjc156560 	uint32_t *diskid_list;
3128711890bcSjc156560 
3129711890bcSjc156560 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3130711890bcSjc156560 	if (array_attr == NULL)
3131711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3132711890bcSjc156560 
3133711890bcSjc156560 	/* Check the disk layout expression */
3134711890bcSjc156560 	if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
3135711890bcSjc156560 	    disk_list[num_of_comp - 1] != OBJ_SEPARATOR_END)
3136711890bcSjc156560 		return (ERR_ARRAY_LAYOUT);
3137711890bcSjc156560 	for (i = 0; i < num_of_comp; ++i) {
3138711890bcSjc156560 		if (disk_list[i] == OBJ_SEPARATOR_BEGIN) {
3139711890bcSjc156560 			if (disk_cnt != 0)
3140711890bcSjc156560 				return (ERR_ARRAY_LAYOUT);
3141711890bcSjc156560 			++layer_cnt;
3142711890bcSjc156560 			continue;
3143711890bcSjc156560 		}
3144711890bcSjc156560 		if (disk_list[i] == OBJ_SEPARATOR_END) {
3145711890bcSjc156560 			if (disk_set_num == 0)
3146711890bcSjc156560 				disk_set_num = disk_cnt;
3147711890bcSjc156560 			else if (disk_set_num != disk_cnt && disk_cnt != 0)
3148711890bcSjc156560 				return (ERR_ARRAY_LAYOUT);
3149711890bcSjc156560 			disk_cnt = 0;
3150711890bcSjc156560 			++set_num;
3151711890bcSjc156560 			--layer_cnt;
3152711890bcSjc156560 			continue;
3153711890bcSjc156560 		}
3154711890bcSjc156560 		switch (array_attr->raid_level) {
3155711890bcSjc156560 		case RAID_LEVEL_0:
3156711890bcSjc156560 		case RAID_LEVEL_1:
3157711890bcSjc156560 		case RAID_LEVEL_1E:
3158711890bcSjc156560 		case RAID_LEVEL_5:
3159711890bcSjc156560 			if (layer_cnt != 1)
3160711890bcSjc156560 				return (ERR_ARRAY_LAYOUT);
3161711890bcSjc156560 			break;
3162711890bcSjc156560 		case RAID_LEVEL_10:
3163711890bcSjc156560 		case RAID_LEVEL_50:
3164711890bcSjc156560 			if (layer_cnt != 2)
3165711890bcSjc156560 				return (ERR_ARRAY_LAYOUT);
3166711890bcSjc156560 			break;
3167711890bcSjc156560 		default:
3168711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3169711890bcSjc156560 		}
3170711890bcSjc156560 		++disk_cnt;
3171711890bcSjc156560 	}
3172711890bcSjc156560 
3173711890bcSjc156560 	if (layer_cnt != 0)
3174711890bcSjc156560 		return (ERR_ARRAY_LAYOUT);
3175711890bcSjc156560 
3176711890bcSjc156560 	switch (array_attr->raid_level) {
3177711890bcSjc156560 	case RAID_LEVEL_0:
3178711890bcSjc156560 		if (disk_set_num < 2 || set_num != 1)
3179711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3180711890bcSjc156560 		break;
3181711890bcSjc156560 	case RAID_LEVEL_1:
3182711890bcSjc156560 		if (disk_set_num != 2 || set_num != 1)
3183711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3184711890bcSjc156560 		break;
3185711890bcSjc156560 	case RAID_LEVEL_1E:
3186711890bcSjc156560 	case RAID_LEVEL_5:
3187711890bcSjc156560 		if (disk_set_num < 3 || set_num != 1)
3188711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3189711890bcSjc156560 		break;
3190711890bcSjc156560 	case RAID_LEVEL_10:
3191711890bcSjc156560 		if (disk_set_num != 2 || set_num < 2)
3192711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3193711890bcSjc156560 		break;
3194711890bcSjc156560 	case RAID_LEVEL_50:
3195711890bcSjc156560 		if (disk_set_num < 3 || set_num < 2)
3196711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3197711890bcSjc156560 		break;
3198711890bcSjc156560 	default:
3199711890bcSjc156560 		return (ERR_ARRAY_LEVEL);
3200711890bcSjc156560 	}
3201711890bcSjc156560 
3202711890bcSjc156560 	arraypart_attrs = calloc(num_of_comp, sizeof (arraypart_attr_t));
3203711890bcSjc156560 	if (arraypart_attrs == NULL)
3204711890bcSjc156560 		return (ERR_NOMEM);
3205711890bcSjc156560 
3206711890bcSjc156560 	for (i = 0; i < num_of_comp; ++i) {
3207711890bcSjc156560 		/* Keep seperators */
3208711890bcSjc156560 		if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3209711890bcSjc156560 			arraypart_attrs[i].disk_id =
3210711890bcSjc156560 			    (uint32_t)OBJ_SEPARATOR_BEGIN;
3211711890bcSjc156560 			continue;
3212711890bcSjc156560 		}
3213711890bcSjc156560 
3214711890bcSjc156560 		if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3215711890bcSjc156560 			arraypart_attrs[i].disk_id =
3216711890bcSjc156560 			    (uint32_t)OBJ_SEPARATOR_END;
3217711890bcSjc156560 			continue;
3218711890bcSjc156560 		}
3219711890bcSjc156560 
3220711890bcSjc156560 		disk_cnt++;
3221711890bcSjc156560 		/* Check if it's a disk */
3222711890bcSjc156560 		if (raid_obj_get_type(raid_tab, *(disk_list + i)) !=
3223711890bcSjc156560 		    OBJ_TYPE_DISK)
3224711890bcSjc156560 			return (ERR_DEVICE_TYPE);
3225711890bcSjc156560 
3226711890bcSjc156560 		/* Check if it's duplicated with other disks */
3227711890bcSjc156560 		for (j = 0; j < i; ++j)
3228711890bcSjc156560 			if (*(disk_list + j) == *(disk_list + i)) {
3229711890bcSjc156560 				free(arraypart_attrs);
3230711890bcSjc156560 				return (ERR_DEVICE_DUP);
3231711890bcSjc156560 			}
3232711890bcSjc156560 
3233711890bcSjc156560 		/* Check disk status */
3234711890bcSjc156560 		ret = obj_get_attr(raid_tab, *(disk_list + i),
3235711890bcSjc156560 		    (void **)(&disk_attr));
3236711890bcSjc156560 		if (ret != SUCCESS)
3237711890bcSjc156560 			return (ret);
3238711890bcSjc156560 
3239711890bcSjc156560 		if (disk_attr->state != DISK_STATE_GOOD) {
3240711890bcSjc156560 			free(arraypart_attrs);
3241711890bcSjc156560 			return (ERR_DISK_STATE);
3242711890bcSjc156560 		}
3243711890bcSjc156560 
3244711890bcSjc156560 		/* All disks must belong to the same controller */
3245711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, *(disk_list + i));
3246711890bcSjc156560 		if (obj_id <= OBJ_NONE)
3247711890bcSjc156560 			return (obj_id);
3248711890bcSjc156560 		if (controller_obj_id == OBJ_NONE) {
3249711890bcSjc156560 			controller_obj_id = obj_id;
3250711890bcSjc156560 			ret = obj_get_attr(raid_tab, controller_obj_id,
3251711890bcSjc156560 			    (void **)(&controller_attr));
3252711890bcSjc156560 		} else if (obj_id != controller_obj_id) {
3253711890bcSjc156560 			free(arraypart_attrs);
3254711890bcSjc156560 			return (ERR_DRIVER_ACROSS);
3255711890bcSjc156560 		}
3256711890bcSjc156560 
3257711890bcSjc156560 		/* Check if the disk contains too many segments */
3258711890bcSjc156560 		obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3259711890bcSjc156560 		    OBJ_TYPE_DISK_SEG);
3260711890bcSjc156560 		j = 0;
3261711890bcSjc156560 		while (obj_id > OBJ_NONE) {
3262711890bcSjc156560 			++j;
3263711890bcSjc156560 			obj_id = obj_get_sibling(raid_tab, obj_id);
3264711890bcSjc156560 		}
3265711890bcSjc156560 		if (j > controller_attr->max_seg_per_disk) {
3266711890bcSjc156560 			free(arraypart_attrs);
3267711890bcSjc156560 			return (ERR_DISK_SEG_AMOUNT);
3268711890bcSjc156560 		}
3269711890bcSjc156560 
3270711890bcSjc156560 		/* Check if controller is a hostraid controller */
3271711890bcSjc156560 		if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3272711890bcSjc156560 			/*
3273711890bcSjc156560 			 * For hostraid, the first disk should
3274711890bcSjc156560 			 * be with of minimum capacity
3275711890bcSjc156560 			 */
3276711890bcSjc156560 			if (min_disk_capacity == 0) {
3277711890bcSjc156560 				min_disk_capacity = disk_attr->capacity;
3278711890bcSjc156560 
3279711890bcSjc156560 				/* Can not specify capacity for hostraid */
3280711890bcSjc156560 				if (array_attr->capacity != 0) {
3281711890bcSjc156560 					free(arraypart_attrs);
3282*700682b8Syw161884 					return (ERR_OP_ILLEGAL);
3283711890bcSjc156560 				}
3284711890bcSjc156560 			} else if (min_disk_capacity > disk_attr->capacity) {
3285711890bcSjc156560 				free(arraypart_attrs);
3286711890bcSjc156560 				return (ERR_DISK_SPACE);
3287711890bcSjc156560 			}
3288711890bcSjc156560 
3289711890bcSjc156560 			/* Disk should not be used for hostraid */
3290711890bcSjc156560 			obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3291711890bcSjc156560 			    OBJ_TYPE_DISK_SEG);
3292711890bcSjc156560 			if (obj_id < OBJ_NONE) {
3293711890bcSjc156560 				free(arraypart_attrs);
3294711890bcSjc156560 				return (obj_id);
3295711890bcSjc156560 			} else if (obj_id > OBJ_NONE) {
3296711890bcSjc156560 				free(arraypart_attrs);
3297711890bcSjc156560 				return (ERR_DISK_NOT_EMPTY);
3298711890bcSjc156560 			}
3299711890bcSjc156560 		}
3300711890bcSjc156560 
3301711890bcSjc156560 		arraypart_attrs[i].disk_id = disk_attr->disk_id;
3302711890bcSjc156560 		arraypart_attrs[i].offset = OBJ_ATTR_NONE;
3303711890bcSjc156560 		arraypart_attrs[i].size = OBJ_ATTR_NONE;
3304711890bcSjc156560 	}
3305711890bcSjc156560 
3306711890bcSjc156560 	/* Check if array amount exceeds limit */
3307711890bcSjc156560 	if (controller_attr->max_array_num <=
3308711890bcSjc156560 	    obj_controller_compnum(raid_tab, controller_obj_id,
3309711890bcSjc156560 	    OBJ_TYPE_ARRAY))
3310711890bcSjc156560 		return (ERR_ARRAY_AMOUNT);
3311711890bcSjc156560 
3312711890bcSjc156560 
3313711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3314711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3315711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3316711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3317711890bcSjc156560 
3318711890bcSjc156560 	/* Check if the controller can support the array RAID level */
3319711890bcSjc156560 	switch (array_attr->raid_level) {
3320711890bcSjc156560 	case	RAID_LEVEL_0:
3321711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID0)) {
3322711890bcSjc156560 			free(arraypart_attrs);
3323711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3324711890bcSjc156560 		}
3325711890bcSjc156560 		break;
3326711890bcSjc156560 	case	RAID_LEVEL_1:
3327711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID1)) {
3328711890bcSjc156560 			free(arraypart_attrs);
3329711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3330711890bcSjc156560 		}
3331711890bcSjc156560 		break;
3332711890bcSjc156560 	case	RAID_LEVEL_1E:
3333711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID1E)) {
3334711890bcSjc156560 			free(arraypart_attrs);
3335711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3336711890bcSjc156560 		}
3337711890bcSjc156560 		break;
3338711890bcSjc156560 	case	RAID_LEVEL_5:
3339711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID5)) {
3340711890bcSjc156560 			free(arraypart_attrs);
3341711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3342711890bcSjc156560 		}
3343711890bcSjc156560 		break;
3344711890bcSjc156560 	case	RAID_LEVEL_10:
3345711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID10)) {
3346711890bcSjc156560 			free(arraypart_attrs);
3347711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3348711890bcSjc156560 		}
3349711890bcSjc156560 		break;
3350711890bcSjc156560 	case	RAID_LEVEL_50:
3351711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID50)) {
3352711890bcSjc156560 			free(arraypart_attrs);
3353711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3354711890bcSjc156560 		}
3355711890bcSjc156560 		break;
3356711890bcSjc156560 	default:
3357711890bcSjc156560 		free(arraypart_attrs);
3358711890bcSjc156560 		return (ERR_ARRAY_LEVEL);
3359711890bcSjc156560 	}
3360711890bcSjc156560 
3361711890bcSjc156560 	/* Check if plug in can calculate the maximum size */
3362711890bcSjc156560 	(void) memcpy(&array_attr2, array_attr, sizeof (array_attr_t));
3363711890bcSjc156560 	array_attr2.capacity = OBJ_ATTR_NONE;
3364711890bcSjc156560 	ret = raid_lib->array_create(controller_attr->controller_id,
3365711890bcSjc156560 	    &array_attr2, num_of_comp, arraypart_attrs, plugin_err_str);
3366711890bcSjc156560 
3367711890bcSjc156560 	/* If plugin/driver will not calculate space */
3368711890bcSjc156560 	if (ret == ERR_OP_NO_IMPL) {
3369711890bcSjc156560 		/* Calculate the maximum capacity */
3370711890bcSjc156560 		array_attr2.capacity = raid_space_noalign(raid_tab,
3371711890bcSjc156560 		    array_attr2.raid_level, num_of_comp, disk_list,
3372711890bcSjc156560 		    arraypart_attrs);
3373711890bcSjc156560 
3374711890bcSjc156560 		/*
3375711890bcSjc156560 		 * If controller is capable to allocate space,
3376711890bcSjc156560 		 * set offset and size attributes to OBJ_ATTR_NONE
3377711890bcSjc156560 		 * and let the controller to determine these value
3378711890bcSjc156560 		 */
3379711890bcSjc156560 		if (controller_attr->capability & RAID_CAP_SMART_ALLOC)
3380711890bcSjc156560 			for (i = 0; i < num_of_comp; ++i) {
3381711890bcSjc156560 				arraypart_attrs[i].offset =
3382711890bcSjc156560 				    OBJ_ATTR_NONE;
3383711890bcSjc156560 				arraypart_attrs[i].size =
3384711890bcSjc156560 				    OBJ_ATTR_NONE;
3385711890bcSjc156560 			}
3386711890bcSjc156560 
3387711890bcSjc156560 		/* There's no enough space for specified capacity */
3388711890bcSjc156560 		if (array_attr->capacity > array_attr2.capacity) {
3389711890bcSjc156560 			free(arraypart_attrs);
3390711890bcSjc156560 			return (ERR_ARRAY_SIZE);
3391711890bcSjc156560 		}
3392711890bcSjc156560 
3393711890bcSjc156560 		/* capacity == 0, allocate maximum space */
3394711890bcSjc156560 		if (array_attr->capacity == 0)
3395711890bcSjc156560 			array_attr->capacity = array_attr2.capacity;
3396711890bcSjc156560 	} else if (ret < SUCCESS) {
3397711890bcSjc156560 		free(arraypart_attrs);
3398711890bcSjc156560 		return (ret);
3399711890bcSjc156560 	} else if (array_attr2.capacity < array_attr->capacity) {
3400711890bcSjc156560 		/* Return the maximum size */
3401711890bcSjc156560 		array_attr->capacity = array_attr2.capacity;
3402711890bcSjc156560 		free(arraypart_attrs);
3403711890bcSjc156560 		return (ERR_ARRAY_SIZE);
3404711890bcSjc156560 	}
3405711890bcSjc156560 
3406711890bcSjc156560 	if (array_attr->capacity < ARRAYPART_MIN_SIZE * disk_cnt) {
3407711890bcSjc156560 		free(arraypart_attrs);
3408711890bcSjc156560 		return (ERR_ARRAY_SIZE);
3409711890bcSjc156560 	}
3410711890bcSjc156560 
3411711890bcSjc156560 
3412711890bcSjc156560 	ret = raid_lib->array_create(controller_attr->controller_id,
3413711890bcSjc156560 	    array_attr, num_of_comp, arraypart_attrs, plugin_err_str);
3414711890bcSjc156560 	free(arraypart_attrs);
3415711890bcSjc156560 
3416711890bcSjc156560 	if (ret != SUCCESS)
3417711890bcSjc156560 		return (ret);
3418711890bcSjc156560 
3419711890bcSjc156560 	/* Add array object into device tree so that we can map the handle */
3420711890bcSjc156560 	(void) raid_obj_add_org(raid_tab, array_obj_id, controller_obj_id);
3421711890bcSjc156560 
3422711890bcSjc156560 	/* unconfig disk minor nodes if it's hostraid */
3423711890bcSjc156560 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3424711890bcSjc156560 		diskid_list = (uint32_t *)calloc(num_of_comp,
3425711890bcSjc156560 		    sizeof (uint32_t));
3426711890bcSjc156560 		if (diskid_list == NULL) {
3427711890bcSjc156560 			return (ERR_NOMEM);
3428711890bcSjc156560 		}
3429711890bcSjc156560 
3430711890bcSjc156560 		for (i = 0; i < num_of_comp; ++i) {
3431711890bcSjc156560 			if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3432711890bcSjc156560 				diskid_list[i] = (uint32_t)OBJ_SEPARATOR_BEGIN;
3433711890bcSjc156560 			} else if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3434711890bcSjc156560 				diskid_list[i] = (uint32_t)OBJ_SEPARATOR_END;
3435711890bcSjc156560 			} else {
3436711890bcSjc156560 				ret = obj_get_attr(raid_tab, *(disk_list + i),
3437711890bcSjc156560 				    (void **)(&disk_attr));
3438711890bcSjc156560 				if (ret != SUCCESS) {
3439711890bcSjc156560 					free(diskid_list);
3440711890bcSjc156560 					return (ret);
3441711890bcSjc156560 				}
3442711890bcSjc156560 				diskid_list[i] = disk_attr->disk_id;
3443711890bcSjc156560 			}
3444711890bcSjc156560 		}
3445711890bcSjc156560 
3446711890bcSjc156560 		for (i = 0; i < num_of_comp; ++i) {
3447711890bcSjc156560 			if (diskid_list[i] == (uint32_t)OBJ_SEPARATOR_BEGIN ||
3448711890bcSjc156560 			    diskid_list[i] == (uint32_t)OBJ_SEPARATOR_END) {
3449711890bcSjc156560 				continue;
3450711890bcSjc156560 			}
3451711890bcSjc156560 
3452711890bcSjc156560 			if (TARGET(diskid_list[i]) ==
3453711890bcSjc156560 			    ARRAY_TARGET(array_attr->array_id) &&
3454711890bcSjc156560 			    LUN(diskid_list[i]) ==
3455711890bcSjc156560 			    ARRAY_LUN(array_attr->array_id))
3456711890bcSjc156560 				continue;
3457711890bcSjc156560 
3458711890bcSjc156560 			ret = raid_dev_config(CFGA_CMD_UNCONFIGURE,
3459711890bcSjc156560 			    controller_attr->controller_id, diskid_list[i], 0);
3460711890bcSjc156560 			if (ret != SUCCESS) {
3461711890bcSjc156560 				free(diskid_list);
3462711890bcSjc156560 				return (ret);
3463711890bcSjc156560 			}
3464711890bcSjc156560 		}
3465711890bcSjc156560 		free(diskid_list);
3466711890bcSjc156560 	} else {
3467711890bcSjc156560 		/* for HW raid */
3468711890bcSjc156560 		ret = raid_dev_config(CFGA_CMD_CONFIGURE,
3469711890bcSjc156560 		    controller_attr->controller_id, array_attr->array_id, 1);
3470711890bcSjc156560 	}
3471711890bcSjc156560 
3472711890bcSjc156560 	return (ret);
3473711890bcSjc156560 }
3474711890bcSjc156560 
3475711890bcSjc156560 static int
3476711890bcSjc156560 obj_array_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3477711890bcSjc156560 	char **plugin_err_str)
3478711890bcSjc156560 {
3479711890bcSjc156560 	raid_obj_id_t controller_obj_id;
3480711890bcSjc156560 	controller_attr_t *controller_attr;
3481711890bcSjc156560 	array_attr_t *array_attr;
3482711890bcSjc156560 	arraypart_attr_t *arraypart_attr;
3483711890bcSjc156560 	raid_obj_id_t arraypart_obj_id;
3484711890bcSjc156560 	raid_lib_t *raid_lib;
3485711890bcSjc156560 	int i = 0, j = 0, ret, fd;
3486711890bcSjc156560 	uint32_t *disk_ids = NULL;
3487711890bcSjc156560 
3488711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, array_obj_id);
3489711890bcSjc156560 	if (controller_obj_id <= OBJ_NONE)
3490711890bcSjc156560 		return (controller_obj_id);
3491711890bcSjc156560 
3492711890bcSjc156560 	ret = obj_get_attr(raid_tab, controller_obj_id,
3493711890bcSjc156560 	    (void **)(&controller_attr));
3494711890bcSjc156560 	if (ret < SUCCESS) {
3495711890bcSjc156560 		return (ret);
3496711890bcSjc156560 	}
3497711890bcSjc156560 	ret = obj_get_attr(raid_tab, array_obj_id, (void **)(&array_attr));
3498711890bcSjc156560 	if (ret < SUCCESS)
3499711890bcSjc156560 		return (ret);
3500711890bcSjc156560 
3501711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3502711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3503711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3504711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3505711890bcSjc156560 
3506711890bcSjc156560 	/* change minor nodes state for disks */
3507711890bcSjc156560 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3508711890bcSjc156560 		arraypart_obj_id = obj_get_comp(raid_tab, array_obj_id,
3509711890bcSjc156560 		    OBJ_TYPE_ARRAY_PART);
3510711890bcSjc156560 		if (arraypart_obj_id < OBJ_NONE) {
3511711890bcSjc156560 			return (arraypart_obj_id);
3512711890bcSjc156560 		}
3513711890bcSjc156560 
3514711890bcSjc156560 		/*
3515711890bcSjc156560 		 * Check how many disks in volume and malloc space for
3516711890bcSjc156560 		 * disk_ids; note that the number should be the disk
3517711890bcSjc156560 		 * number minors 1 since the primary disk should not
3518711890bcSjc156560 		 * be counted in.
3519711890bcSjc156560 		 */
3520711890bcSjc156560 		while (arraypart_obj_id = obj_get_sibling(raid_tab,
3521711890bcSjc156560 		    arraypart_obj_id)) {
3522711890bcSjc156560 			if (arraypart_obj_id < OBJ_NONE)
3523711890bcSjc156560 				return (arraypart_obj_id);
3524711890bcSjc156560 			++i;
3525711890bcSjc156560 		}
3526711890bcSjc156560 		disk_ids = calloc(i, sizeof (uint32_t));
3527711890bcSjc156560 		if (disk_ids == NULL)
3528711890bcSjc156560 			return (ERR_NOMEM);
3529711890bcSjc156560 
3530711890bcSjc156560 		/* Stor all member disk ids into disk_ids */
3531711890bcSjc156560 		arraypart_obj_id = obj_get_comp(raid_tab, array_obj_id,
3532711890bcSjc156560 		    OBJ_TYPE_ARRAY_PART);
3533711890bcSjc156560 
3534711890bcSjc156560 		while (arraypart_obj_id > OBJ_NONE) {
3535711890bcSjc156560 			ret = obj_get_attr(raid_tab, arraypart_obj_id,
3536711890bcSjc156560 			    (void **)(&arraypart_attr));
3537711890bcSjc156560 			if (ret != SUCCESS) {
3538711890bcSjc156560 				return (ret);
3539711890bcSjc156560 			}
3540711890bcSjc156560 			if (TARGET(arraypart_attr->disk_id) ==
3541711890bcSjc156560 			    ARRAY_TARGET(array_attr->array_id) &&
3542711890bcSjc156560 			    LUN(arraypart_attr->disk_id) ==
3543711890bcSjc156560 			    ARRAY_LUN(array_attr->array_id)) {
3544711890bcSjc156560 				arraypart_obj_id = obj_get_sibling(raid_tab,
3545711890bcSjc156560 				    arraypart_obj_id);
3546711890bcSjc156560 				continue;
3547711890bcSjc156560 			}
3548711890bcSjc156560 
3549711890bcSjc156560 			disk_ids[j] = arraypart_attr->disk_id;
3550711890bcSjc156560 			++j;
3551711890bcSjc156560 			arraypart_obj_id = obj_get_sibling(raid_tab,
3552711890bcSjc156560 			    arraypart_obj_id);
3553711890bcSjc156560 		}
3554711890bcSjc156560 	} else {
3555711890bcSjc156560 		ret = raid_dev_config(CFGA_CMD_UNCONFIGURE,
3556711890bcSjc156560 		    controller_attr->controller_id, array_attr->array_id, 1);
3557711890bcSjc156560 		if (ret != SUCCESS)
3558711890bcSjc156560 			return (ret);
3559711890bcSjc156560 	}
3560711890bcSjc156560 
3561711890bcSjc156560 	ret = raid_lib->array_delete(controller_attr->controller_id,
3562711890bcSjc156560 	    array_attr->array_id, plugin_err_str);
3563711890bcSjc156560 	if (ret < SUCCESS) {
3564711890bcSjc156560 		if (disk_ids)
3565711890bcSjc156560 			free(disk_ids);
3566711890bcSjc156560 		return (ret);
3567711890bcSjc156560 	}
3568711890bcSjc156560 
3569711890bcSjc156560 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3570711890bcSjc156560 		for (i = 0; i < j; ++i)
3571711890bcSjc156560 			ret = raid_dev_config(CFGA_CMD_CONFIGURE,
3572711890bcSjc156560 			    controller_attr->controller_id,
3573711890bcSjc156560 			    disk_ids[i], 0);
3574711890bcSjc156560 			if (ret < SUCCESS) {
3575711890bcSjc156560 				free(disk_ids);
3576711890bcSjc156560 				return (ret);
3577711890bcSjc156560 			}
3578711890bcSjc156560 	}
3579711890bcSjc156560 
3580711890bcSjc156560 	if (disk_ids)
3581711890bcSjc156560 		free(disk_ids);
3582711890bcSjc156560 	return (ret);
3583711890bcSjc156560 }
3584711890bcSjc156560 
3585711890bcSjc156560 static int
3586711890bcSjc156560 obj_hsp_bind(raid_obj_tab_t *raid_tab, int num, raid_obj_id_t *obj_ids,
3587711890bcSjc156560 	char **plugin_err_str)
3588711890bcSjc156560 {
3589711890bcSjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3590711890bcSjc156560 	raid_obj_id_t array_obj_id, disk_obj_id;
3591711890bcSjc156560 	hsp_relation_t *hsp_relation;
3592711890bcSjc156560 	controller_attr_t *controller_attr;
3593711890bcSjc156560 	array_attr_t *array_attr;
3594711890bcSjc156560 	arraypart_attr_t *arraypart_attr;
3595711890bcSjc156560 	disk_attr_t *disk_attr;
3596711890bcSjc156560 	diskseg_attr_t *diskseg_attr;
3597711890bcSjc156560 	hsp_attr_t *hsp_attr;
3598711890bcSjc156560 	raid_lib_t *raid_lib;
3599711890bcSjc156560 	int ret, fd, i, j = 0;
3600711890bcSjc156560 
3601711890bcSjc156560 	hsp_relation = malloc(sizeof (hsp_relation_t) * num);
3602711890bcSjc156560 	if (hsp_relation == NULL)
3603711890bcSjc156560 		return (ERR_NOMEM);
3604711890bcSjc156560 
3605711890bcSjc156560 	for (i = 0; i < num; ++i) {
3606711890bcSjc156560 		array_obj_id = *(obj_ids + i * 2);
3607711890bcSjc156560 		disk_obj_id = *(obj_ids + i * 2 + 1);
3608711890bcSjc156560 
3609711890bcSjc156560 		if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK ||
3610711890bcSjc156560 		    (array_obj_id != OBJ_ATTR_NONE &&
3611711890bcSjc156560 		    raid_obj_get_type(raid_tab, array_obj_id) !=
3612711890bcSjc156560 		    OBJ_TYPE_ARRAY)) {
3613711890bcSjc156560 			free(hsp_relation);
3614711890bcSjc156560 			return (ERR_DEVICE_TYPE);
3615711890bcSjc156560 		}
3616711890bcSjc156560 
3617711890bcSjc156560 		/* Get controller attributes */
3618711890bcSjc156560 		if (controller_obj_id == OBJ_NONE)
3619711890bcSjc156560 			controller_obj_id = obj_get_controller(raid_tab,
3620711890bcSjc156560 			    disk_obj_id);
3621711890bcSjc156560 		else if (controller_obj_id != obj_get_controller(raid_tab,
3622711890bcSjc156560 		    disk_obj_id)) {
3623711890bcSjc156560 			free(hsp_relation);
3624711890bcSjc156560 			return (ERR_DRIVER_ACROSS);
3625711890bcSjc156560 		}
3626711890bcSjc156560 
3627711890bcSjc156560 		ret = obj_get_attr(raid_tab, controller_obj_id,
3628711890bcSjc156560 		    (void **)(&controller_attr));
3629711890bcSjc156560 
3630711890bcSjc156560 		/* Get disk attributes */
3631711890bcSjc156560 		ret = obj_get_attr(raid_tab,  disk_obj_id,
3632711890bcSjc156560 		    (void **)(&disk_attr));
3633711890bcSjc156560 		if (disk_attr->state == DISK_STATE_FAILED) {
3634711890bcSjc156560 			free(hsp_relation);
3635711890bcSjc156560 			return (ERR_DISK_STATE);
3636711890bcSjc156560 		}
3637711890bcSjc156560 
3638711890bcSjc156560 		/* If it's not a hsp disk, check if there's occupied space */
3639711890bcSjc156560 		if (obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP) ==
3640711890bcSjc156560 		    OBJ_NONE) {
3641711890bcSjc156560 			obj_id = obj_get_comp(raid_tab, disk_obj_id,
3642711890bcSjc156560 			    OBJ_TYPE_DISK_SEG);
3643711890bcSjc156560 			while (obj_id != OBJ_NONE) {
3644711890bcSjc156560 				ret = obj_get_attr(raid_tab, obj_id,
3645711890bcSjc156560 				    (void **)(&diskseg_attr));
3646711890bcSjc156560 				if (!(diskseg_attr->state &
3647711890bcSjc156560 				    DISKSEG_STATE_RESERVED)) {
3648711890bcSjc156560 					free(hsp_relation);
3649711890bcSjc156560 					return (ERR_DISK_NOT_EMPTY);
3650711890bcSjc156560 				}
3651711890bcSjc156560 				obj_id = obj_get_sibling(raid_tab, obj_id);
3652711890bcSjc156560 			}
3653711890bcSjc156560 		}
3654711890bcSjc156560 
3655711890bcSjc156560 		if (array_obj_id != OBJ_ATTR_NONE) {
3656711890bcSjc156560 			/* If local hsp is supported */
3657711890bcSjc156560 			if (!(controller_attr->capability & RAID_CAP_L_HSP)) {
3658711890bcSjc156560 				free(hsp_relation);
3659711890bcSjc156560 				return (ERR_OP_ILLEGAL);
3660711890bcSjc156560 			}
3661711890bcSjc156560 
3662711890bcSjc156560 			if (raid_obj_get_type(raid_tab, array_obj_id) !=
3663711890bcSjc156560 			    OBJ_TYPE_ARRAY) {
3664711890bcSjc156560 				free(hsp_relation);
3665711890bcSjc156560 				return (ERR_DEVICE_TYPE);
3666711890bcSjc156560 			}
3667711890bcSjc156560 
3668711890bcSjc156560 			/* Get array attributes */
3669711890bcSjc156560 			ret = obj_get_attr(raid_tab, array_obj_id,
3670711890bcSjc156560 			    (void **)(&array_attr));
3671711890bcSjc156560 			/* RAID 0 array can not use hsp */
3672711890bcSjc156560 			if (array_attr->raid_level == RAID_LEVEL_0) {
3673711890bcSjc156560 				free(hsp_relation);
3674711890bcSjc156560 				return (ERR_ARRAY_LEVEL);
3675711890bcSjc156560 			}
3676711890bcSjc156560 
3677711890bcSjc156560 			/* If It's belong to another controller */
3678711890bcSjc156560 			if (controller_obj_id != obj_get_controller(raid_tab,
3679711890bcSjc156560 			    array_obj_id)) {
3680711890bcSjc156560 				free(hsp_relation);
3681711890bcSjc156560 				return (ERR_DRIVER_ACROSS);
3682711890bcSjc156560 			}
3683711890bcSjc156560 
3684711890bcSjc156560 			/* Get an array part attributes */
3685711890bcSjc156560 			if ((array_attr->raid_level == RAID_LEVEL_10) ||
3686711890bcSjc156560 			    (array_attr->raid_level == RAID_LEVEL_50))
3687711890bcSjc156560 				obj_id = obj_get_comp(raid_tab, array_obj_id,
3688711890bcSjc156560 				    OBJ_TYPE_ARRAY);
3689711890bcSjc156560 			else
3690711890bcSjc156560 				obj_id = array_obj_id;
3691711890bcSjc156560 			obj_id = obj_get_comp(raid_tab, obj_id,
3692711890bcSjc156560 			    OBJ_TYPE_ARRAY_PART);
3693711890bcSjc156560 			ret = obj_get_attr(raid_tab, obj_id,
3694711890bcSjc156560 			    (void **)(&arraypart_attr));
3695711890bcSjc156560 
3696711890bcSjc156560 			/* Check if disk space is enough for array */
3697711890bcSjc156560 			if (arraypart_attr->size > disk_attr->capacity) {
3698711890bcSjc156560 				free(hsp_relation);
3699711890bcSjc156560 				return (ERR_DISK_SPACE);
3700711890bcSjc156560 			}
3701711890bcSjc156560 			if (controller_attr->capability & RAID_CAP_ARRAY_ALIGN)
3702711890bcSjc156560 				if ((arraypart_attr->size +
3703711890bcSjc156560 				    arraypart_attr->offset) >
3704711890bcSjc156560 				    disk_attr->capacity) {
3705711890bcSjc156560 				free(hsp_relation);
3706711890bcSjc156560 				return (ERR_DISK_SPACE);
3707711890bcSjc156560 				}
3708711890bcSjc156560 		} else if (!(controller_attr->capability & RAID_CAP_G_HSP)) {
3709711890bcSjc156560 			/* if global hsp is supported */
3710711890bcSjc156560 			free(hsp_relation);
3711711890bcSjc156560 			return (ERR_OP_ILLEGAL);
3712711890bcSjc156560 		}
3713711890bcSjc156560 
3714711890bcSjc156560 		/*
3715711890bcSjc156560 		 * If the array is already associated with the
3716711890bcSjc156560 		 * local hsp, or it's a global hsp, ignore it
3717711890bcSjc156560 		 */
3718711890bcSjc156560 		obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3719711890bcSjc156560 		if (obj_id > OBJ_NONE) {
3720711890bcSjc156560 			if (obj_get_attr(raid_tab, obj_id,
3721711890bcSjc156560 			    (void **)&hsp_attr) >= SUCCESS) {
3722711890bcSjc156560 				if (((hsp_attr->type == HSP_TYPE_GLOBAL) &&
3723711890bcSjc156560 				    (array_obj_id != OBJ_ATTR_NONE)) ||
3724711890bcSjc156560 				    ((hsp_attr->type == HSP_TYPE_LOCAL) &&
3725711890bcSjc156560 				    (array_obj_id == OBJ_ATTR_NONE))) {
3726711890bcSjc156560 					free(hsp_relation);
3727711890bcSjc156560 					return (ERR_OP_ILLEGAL);
3728711890bcSjc156560 				}
3729711890bcSjc156560 			}
3730711890bcSjc156560 		}
3731711890bcSjc156560 
3732711890bcSjc156560 		if (array_obj_id != OBJ_ATTR_NONE)
3733711890bcSjc156560 			hsp_relation[j].array_id = array_attr->array_id;
3734711890bcSjc156560 		else
3735711890bcSjc156560 			hsp_relation[j].array_id = (uint32_t)OBJ_ATTR_NONE;
3736711890bcSjc156560 		hsp_relation[j].disk_id = disk_attr->disk_id;
3737711890bcSjc156560 		++ j;
3738711890bcSjc156560 	}
3739711890bcSjc156560 
3740711890bcSjc156560 
3741711890bcSjc156560 	if (j == 0)
3742711890bcSjc156560 		return (SUCCESS);
3743711890bcSjc156560 
3744711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3745711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3746711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3747711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3748711890bcSjc156560 
3749711890bcSjc156560 	if (raid_lib->hsp_bind == NULL) {
3750711890bcSjc156560 		free(hsp_relation);
3751711890bcSjc156560 		return (ERR_OP_NO_IMPL);
3752711890bcSjc156560 	}
3753711890bcSjc156560 
3754711890bcSjc156560 	ret = raid_lib->hsp_bind(controller_attr->controller_id,
3755711890bcSjc156560 	    j, hsp_relation, plugin_err_str);
3756711890bcSjc156560 
3757711890bcSjc156560 	free(hsp_relation);
3758711890bcSjc156560 	return (ret);
3759711890bcSjc156560 }
3760711890bcSjc156560 
3761711890bcSjc156560 static int
3762711890bcSjc156560 obj_hsp_unbind(raid_obj_tab_t *raid_tab, int num, raid_obj_id_t *obj_ids,
3763711890bcSjc156560 	char **plugin_err_str)
3764711890bcSjc156560 {
3765711890bcSjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3766711890bcSjc156560 	raid_obj_id_t array_obj_id, disk_obj_id;
3767711890bcSjc156560 	hsp_relation_t *hsp_relation;
3768711890bcSjc156560 	controller_attr_t *controller_attr;
3769711890bcSjc156560 	array_attr_t *array_attr;
3770711890bcSjc156560 	disk_attr_t *disk_attr;
3771711890bcSjc156560 	hsp_attr_t *hsp_attr;
3772711890bcSjc156560 	raid_lib_t *raid_lib;
3773711890bcSjc156560 	int ret, fd, i, j = 0;
3774711890bcSjc156560 
3775711890bcSjc156560 	hsp_relation = malloc(sizeof (hsp_relation_t) * num);
3776711890bcSjc156560 	if (hsp_relation == NULL)
3777711890bcSjc156560 		return (ERR_NOMEM);
3778711890bcSjc156560 
3779711890bcSjc156560 	for (i = 0; i < num; ++i) {
3780711890bcSjc156560 		array_obj_id = *(obj_ids + i * 2);
3781711890bcSjc156560 		disk_obj_id = *(obj_ids + i * 2 + 1);
3782711890bcSjc156560 
3783711890bcSjc156560 		if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK) {
3784711890bcSjc156560 			free(hsp_relation);
3785711890bcSjc156560 			return (ERR_DEVICE_TYPE);
3786711890bcSjc156560 		}
3787711890bcSjc156560 
3788711890bcSjc156560 		/* Get controller attributes */
3789711890bcSjc156560 		if (controller_obj_id == OBJ_NONE)
3790711890bcSjc156560 			controller_obj_id = obj_get_controller(raid_tab,
3791711890bcSjc156560 			    disk_obj_id);
3792711890bcSjc156560 		else if (controller_obj_id != obj_get_controller(raid_tab,
3793711890bcSjc156560 		    disk_obj_id)) {
3794711890bcSjc156560 			free(hsp_relation);
3795711890bcSjc156560 			return (ERR_DRIVER_ACROSS);
3796711890bcSjc156560 		}
3797711890bcSjc156560 
3798711890bcSjc156560 		ret = obj_get_attr(raid_tab, controller_obj_id,
3799711890bcSjc156560 		    (void **)(&controller_attr));
3800711890bcSjc156560 
3801711890bcSjc156560 		/* Get disk attributes */
3802711890bcSjc156560 		ret = obj_get_attr(raid_tab,  disk_obj_id,
3803711890bcSjc156560 		    (void **)(&disk_attr));
3804711890bcSjc156560 		if (disk_attr->state == DISK_STATE_FAILED) {
3805711890bcSjc156560 			free(hsp_relation);
3806711890bcSjc156560 			return (ERR_DISK_STATE);
3807711890bcSjc156560 		}
3808711890bcSjc156560 
3809711890bcSjc156560 		/* If it's not a hsp disk */
3810711890bcSjc156560 		obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3811711890bcSjc156560 		if (obj_id == OBJ_NONE) {
3812711890bcSjc156560 			free(hsp_relation);
3813711890bcSjc156560 			return (ERR_DISK_STATE);
3814711890bcSjc156560 		}
3815711890bcSjc156560 		ret = obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
3816711890bcSjc156560 
3817711890bcSjc156560 		if (array_obj_id != OBJ_ATTR_NONE) {
3818711890bcSjc156560 			if (raid_obj_get_type(raid_tab, array_obj_id) !=
3819711890bcSjc156560 			    OBJ_TYPE_ARRAY) {
3820711890bcSjc156560 				free(hsp_relation);
3821711890bcSjc156560 				return (ERR_DEVICE_TYPE);
3822711890bcSjc156560 			}
3823711890bcSjc156560 
3824711890bcSjc156560 			/* Get array attributes */
3825711890bcSjc156560 			ret = obj_get_attr(raid_tab, array_obj_id,
3826711890bcSjc156560 			    (void **)(&array_attr));
3827711890bcSjc156560 
3828711890bcSjc156560 			/* If It's belong to another controller */
3829711890bcSjc156560 			if (controller_obj_id != obj_get_controller(raid_tab,
3830711890bcSjc156560 			    array_obj_id)) {
3831711890bcSjc156560 				free(hsp_relation);
3832711890bcSjc156560 				return (ERR_DRIVER_ACROSS);
3833711890bcSjc156560 			}
3834711890bcSjc156560 
3835711890bcSjc156560 			/* If want to remove an array from a global hsp */
3836711890bcSjc156560 			if (hsp_attr->type == HSP_TYPE_GLOBAL) {
3837711890bcSjc156560 				free(hsp_relation);
3838711890bcSjc156560 				return (ERR_OP_ILLEGAL);
3839711890bcSjc156560 			}
3840711890bcSjc156560 
3841711890bcSjc156560 			do {
3842711890bcSjc156560 				(void) obj_get_attr(raid_tab, obj_id,
3843711890bcSjc156560 				    (void **)(&hsp_attr));
3844711890bcSjc156560 
3845711890bcSjc156560 				if (hsp_attr->associated_id ==
3846711890bcSjc156560 				    array_attr->array_id ||
3847711890bcSjc156560 				    hsp_attr->type == HSP_TYPE_GLOBAL)
3848711890bcSjc156560 					break;
3849711890bcSjc156560 
3850711890bcSjc156560 				obj_id = obj_get_sibling(raid_tab, obj_id);
3851711890bcSjc156560 			} while (obj_id > OBJ_NONE);
3852711890bcSjc156560 		} else if (hsp_attr->type != HSP_TYPE_GLOBAL) {
3853711890bcSjc156560 			/* if global hsp is supported */
3854711890bcSjc156560 			free(hsp_relation);
3855711890bcSjc156560 			return (ERR_OP_ILLEGAL);
3856711890bcSjc156560 		}
3857711890bcSjc156560 
3858711890bcSjc156560 		/*
3859711890bcSjc156560 		 * If array is associated with a local hsp, or remove a
3860711890bcSjc156560 		 * global hsp disk
3861711890bcSjc156560 		 */
3862711890bcSjc156560 		if ((obj_id && (array_obj_id != OBJ_ATTR_NONE)) ||
3863711890bcSjc156560 		    (array_obj_id == OBJ_ATTR_NONE)) {
3864711890bcSjc156560 			if (array_obj_id != OBJ_ATTR_NONE)
3865711890bcSjc156560 				hsp_relation[j].array_id = array_attr->array_id;
3866711890bcSjc156560 			else
3867711890bcSjc156560 				hsp_relation[j].array_id =
3868711890bcSjc156560 				    (uint32_t)OBJ_ATTR_NONE;
3869711890bcSjc156560 			hsp_relation[j].disk_id = disk_attr->disk_id;
3870711890bcSjc156560 			++ j;
3871711890bcSjc156560 		} else {
3872711890bcSjc156560 			free(hsp_relation);
3873711890bcSjc156560 			return (ERR_OP_ILLEGAL);
3874711890bcSjc156560 		}
3875711890bcSjc156560 	}
3876711890bcSjc156560 
3877711890bcSjc156560 
3878711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3879711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3880711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3881711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3882711890bcSjc156560 
3883711890bcSjc156560 	if (raid_lib->hsp_unbind == NULL) {
3884711890bcSjc156560 		free(hsp_relation);
3885711890bcSjc156560 		return (ERR_OP_NO_IMPL);
3886711890bcSjc156560 	}
3887711890bcSjc156560 
3888711890bcSjc156560 	ret = raid_lib->hsp_unbind(controller_attr->controller_id,
3889711890bcSjc156560 	    j, hsp_relation, plugin_err_str);
3890711890bcSjc156560 
3891711890bcSjc156560 	free(hsp_relation);
3892711890bcSjc156560 	return (ret);
3893711890bcSjc156560 }
3894711890bcSjc156560 
3895711890bcSjc156560 /*
3896711890bcSjc156560  * Object maintennance routines
3897711890bcSjc156560  */
3898711890bcSjc156560 static int
3899711890bcSjc156560 raid_obj_create_system_obj(raid_obj_tab_t *raid_tab)
3900711890bcSjc156560 {
3901711890bcSjc156560 	raid_obj_t *raid_obj;
3902711890bcSjc156560 	int ret;
3903711890bcSjc156560 
3904711890bcSjc156560 	raid_obj = calloc(1, sizeof (raid_obj_t));
3905711890bcSjc156560 	if (raid_obj == NULL)
3906711890bcSjc156560 		return (ERR_NOMEM);
3907711890bcSjc156560 
3908711890bcSjc156560 	raid_obj->obj_id = OBJ_SYSTEM;
3909711890bcSjc156560 	raid_obj->obj_type_id = OBJ_TYPE_SYSTEM;
3910711890bcSjc156560 	raid_obj->data = NULL;
3911711890bcSjc156560 
3912711890bcSjc156560 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3913711890bcSjc156560 	if (ret == ERR_DEVICE_DUP) {
3914711890bcSjc156560 		free(raid_obj);
3915711890bcSjc156560 		return (ERR_DEVICE_UNCLEAN);
3916711890bcSjc156560 	}
3917711890bcSjc156560 
3918711890bcSjc156560 	return (SUCCESS);
3919711890bcSjc156560 }
3920711890bcSjc156560 
3921711890bcSjc156560 static raid_obj_id_t
3922711890bcSjc156560 raid_obj_id_new(raid_obj_tab_t *raid_tab)
3923711890bcSjc156560 {
3924711890bcSjc156560 	++ raid_tab->obj_id_cnt;
3925711890bcSjc156560 	if (raid_tab->obj_id_cnt <= 0)
3926711890bcSjc156560 		return (ERR_DEVICE_OVERFLOW);
3927711890bcSjc156560 
3928711890bcSjc156560 	return (raid_tab->obj_id_cnt);
3929711890bcSjc156560 }
3930711890bcSjc156560 
3931711890bcSjc156560 static void *
3932711890bcSjc156560 raid_obj_attr_new(raid_obj_type_id_t obj_type)
3933711890bcSjc156560 {
3934711890bcSjc156560 	void *obj_attr = NULL;
3935711890bcSjc156560 
3936711890bcSjc156560 	switch (obj_type) {
3937711890bcSjc156560 	case	OBJ_TYPE_CONTROLLER:
3938711890bcSjc156560 		obj_attr = calloc(1, sizeof (controller_attr_t));
3939711890bcSjc156560 		break;
3940711890bcSjc156560 	case	OBJ_TYPE_ARRAY:
3941711890bcSjc156560 		obj_attr = calloc(1, sizeof (array_attr_t));
3942711890bcSjc156560 		break;
3943711890bcSjc156560 	case	OBJ_TYPE_DISK:
3944711890bcSjc156560 		obj_attr = calloc(1, sizeof (disk_attr_t));
3945711890bcSjc156560 		break;
3946711890bcSjc156560 	case	OBJ_TYPE_HSP:
3947711890bcSjc156560 		obj_attr = calloc(1, sizeof (hsp_attr_t));
3948711890bcSjc156560 		break;
3949711890bcSjc156560 	case	OBJ_TYPE_ARRAY_PART:
3950711890bcSjc156560 		obj_attr = calloc(1, sizeof (arraypart_attr_t));
3951711890bcSjc156560 		break;
3952711890bcSjc156560 	case	OBJ_TYPE_DISK_SEG:
3953711890bcSjc156560 		obj_attr = calloc(1, sizeof (diskseg_attr_t));
3954711890bcSjc156560 		break;
3955711890bcSjc156560 	case	OBJ_TYPE_TASK:
3956711890bcSjc156560 		obj_attr = calloc(1, sizeof (task_attr_t));
3957711890bcSjc156560 		break;
3958711890bcSjc156560 	default:
3959711890bcSjc156560 		break;
3960711890bcSjc156560 	}
3961711890bcSjc156560 
3962711890bcSjc156560 	return (obj_attr);
3963711890bcSjc156560 }
3964711890bcSjc156560 
3965711890bcSjc156560 static raid_obj_id_t
3966711890bcSjc156560 raid_obj_create(raid_obj_tab_t *raid_tab, raid_obj_type_id_t obj_type)
3967711890bcSjc156560 {
3968711890bcSjc156560 	raid_obj_t *raid_obj;
3969711890bcSjc156560 	int ret;
3970711890bcSjc156560 	void *data_ptr;
3971711890bcSjc156560 
3972711890bcSjc156560 	raid_obj = calloc(1, sizeof (raid_obj_t));
3973711890bcSjc156560 	if (raid_obj == NULL)
3974711890bcSjc156560 		return (ERR_NOMEM);
3975711890bcSjc156560 
3976711890bcSjc156560 	raid_obj->obj_id = raid_obj_id_new(raid_tab);
3977711890bcSjc156560 	if (raid_obj->obj_id < OBJ_NONE)
3978711890bcSjc156560 		return (ERR_DEVICE_OVERFLOW);
3979711890bcSjc156560 
3980711890bcSjc156560 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3981711890bcSjc156560 	if (ret == ERR_DEVICE_DUP) {
3982711890bcSjc156560 		free(raid_obj);
3983711890bcSjc156560 		return (ERR_DEVICE_DUP);
3984711890bcSjc156560 	}
3985711890bcSjc156560 
3986711890bcSjc156560 	data_ptr = raid_obj_attr_new(obj_type);
3987711890bcSjc156560 	if (data_ptr == NULL) {
3988711890bcSjc156560 		(void) raid_obj_delete(raid_tab, raid_obj->obj_id);
3989711890bcSjc156560 		return (ERR_NOMEM);
3990711890bcSjc156560 	}
3991711890bcSjc156560 
3992711890bcSjc156560 	(void) raid_obj_set_data_ptr(raid_tab, raid_obj->obj_id, data_ptr);
3993711890bcSjc156560 
3994711890bcSjc156560 	(void) raid_obj_set_type(raid_tab, raid_obj->obj_id, obj_type);
3995711890bcSjc156560 	return (raid_obj->obj_id);
3996711890bcSjc156560 }
3997711890bcSjc156560 
3998711890bcSjc156560 static int
3999711890bcSjc156560 raid_obj_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t raid_obj_id)
4000711890bcSjc156560 {
4001711890bcSjc156560 	raid_obj_t *obj;
4002711890bcSjc156560 
4003711890bcSjc156560 	obj = raid_obj_tab_remove(raid_tab, raid_obj_id);
4004711890bcSjc156560 	if (obj != NULL) {
4005711890bcSjc156560 		free(obj->data);
4006711890bcSjc156560 		free(obj);
4007711890bcSjc156560 		return (SUCCESS);
4008711890bcSjc156560 	}
4009711890bcSjc156560 
4010711890bcSjc156560 	return (ERR_DEVICE_NOENT);
4011711890bcSjc156560 }
4012711890bcSjc156560 
4013711890bcSjc156560 static int
4014711890bcSjc156560 raid_obj_add_org(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4015711890bcSjc156560 	raid_obj_id_t container_id)
4016711890bcSjc156560 {
4017711890bcSjc156560 	raid_obj_id_t tmp, tmp1;
4018711890bcSjc156560 
4019711890bcSjc156560 	tmp = raid_obj_get_comp(raid_tab, container_id);
4020711890bcSjc156560 	if (tmp < OBJ_NONE)
4021711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4022711890bcSjc156560 
4023711890bcSjc156560 	if (tmp == OBJ_NONE) {
4024711890bcSjc156560 		(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4025711890bcSjc156560 		(void) raid_obj_set_comp(raid_tab, container_id, obj_id);
4026711890bcSjc156560 		return (SUCCESS);
4027711890bcSjc156560 	}
4028711890bcSjc156560 
4029711890bcSjc156560 	while ((tmp1 = raid_obj_get_sibling(raid_tab, tmp)) != OBJ_NONE)
4030711890bcSjc156560 		tmp = tmp1;
4031711890bcSjc156560 
4032711890bcSjc156560 	if (raid_obj_set_sibling(raid_tab, tmp, obj_id) < SUCCESS)
4033711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4034711890bcSjc156560 	(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4035711890bcSjc156560 
4036711890bcSjc156560 	return (SUCCESS);
4037711890bcSjc156560 }
4038711890bcSjc156560 
4039711890bcSjc156560 static raid_obj_type_id_t
4040711890bcSjc156560 raid_obj_get_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4041711890bcSjc156560 {
4042711890bcSjc156560 	raid_obj_t *obj;
4043711890bcSjc156560 
4044711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4045711890bcSjc156560 	if (obj == NULL)
4046711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4047711890bcSjc156560 
4048711890bcSjc156560 	if ((obj->obj_type_id < OBJ_TYPE_SYSTEM) ||
4049711890bcSjc156560 	    (obj->obj_type_id >= OBJ_TYPE_ALL))
4050711890bcSjc156560 		return (ERR_DEVICE_INVALID);
4051711890bcSjc156560 
4052711890bcSjc156560 	return (obj->obj_type_id);
4053711890bcSjc156560 }
4054711890bcSjc156560 
4055711890bcSjc156560 static int
4056711890bcSjc156560 raid_obj_set_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4057711890bcSjc156560 	raid_obj_type_id_t type)
4058711890bcSjc156560 {
4059711890bcSjc156560 	raid_obj_t *obj;
4060711890bcSjc156560 
4061711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4062711890bcSjc156560 	if (obj == NULL)
4063711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4064711890bcSjc156560 
4065711890bcSjc156560 	if ((type < OBJ_TYPE_SYSTEM) || (type >= OBJ_TYPE_ALL))
4066711890bcSjc156560 		return (ERR_DEVICE_TYPE);
4067711890bcSjc156560 
4068711890bcSjc156560 	obj->obj_type_id = type;
4069711890bcSjc156560 	return (SUCCESS);
4070711890bcSjc156560 }
4071711890bcSjc156560 
4072711890bcSjc156560 static raid_obj_status_t
4073711890bcSjc156560 raid_obj_get_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4074711890bcSjc156560 {
4075711890bcSjc156560 	raid_obj_t *obj;
4076711890bcSjc156560 
4077711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4078711890bcSjc156560 	if (obj == NULL)
4079711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4080711890bcSjc156560 
4081711890bcSjc156560 	return (obj->status);
4082711890bcSjc156560 }
4083711890bcSjc156560 
4084711890bcSjc156560 static int
4085711890bcSjc156560 raid_obj_set_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4086711890bcSjc156560 	raid_obj_status_t status)
4087711890bcSjc156560 {
4088711890bcSjc156560 	raid_obj_t *obj;
4089711890bcSjc156560 
4090711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4091711890bcSjc156560 	if (obj == NULL)
4092711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4093711890bcSjc156560 
4094711890bcSjc156560 	obj->status = obj->status | status;
4095711890bcSjc156560 
4096711890bcSjc156560 	return (SUCCESS);
4097711890bcSjc156560 }
4098711890bcSjc156560 
4099711890bcSjc156560 static int
4100711890bcSjc156560 raid_obj_clear_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4101711890bcSjc156560 	raid_obj_status_t status)
4102711890bcSjc156560 {
4103711890bcSjc156560 	raid_obj_t *obj;
4104711890bcSjc156560 
4105711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4106711890bcSjc156560 	if (obj == NULL)
4107711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4108711890bcSjc156560 
4109711890bcSjc156560 	obj->status = obj->status & ~status;
4110711890bcSjc156560 
4111711890bcSjc156560 	return (SUCCESS);
4112711890bcSjc156560 }
4113711890bcSjc156560 
4114711890bcSjc156560 static raid_obj_id_t
4115711890bcSjc156560 raid_obj_get_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4116711890bcSjc156560 {
4117711890bcSjc156560 	raid_obj_t *obj;
4118711890bcSjc156560 
4119711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4120711890bcSjc156560 	if (obj == NULL)
4121711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4122711890bcSjc156560 
4123711890bcSjc156560 	return (obj->container);
4124711890bcSjc156560 }
4125711890bcSjc156560 
4126711890bcSjc156560 static int
4127711890bcSjc156560 raid_obj_set_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4128711890bcSjc156560 	raid_obj_id_t container_id)
4129711890bcSjc156560 {
4130711890bcSjc156560 	raid_obj_t *obj;
4131711890bcSjc156560 
4132711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4133711890bcSjc156560 	if (obj == NULL)
4134711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4135711890bcSjc156560 
4136711890bcSjc156560 	obj->container = container_id;
4137711890bcSjc156560 	return (SUCCESS);
4138711890bcSjc156560 }
4139711890bcSjc156560 
4140711890bcSjc156560 static raid_obj_id_t
4141711890bcSjc156560 raid_obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4142711890bcSjc156560 {
4143711890bcSjc156560 	raid_obj_t *obj;
4144711890bcSjc156560 
4145711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4146711890bcSjc156560 	if (obj == NULL)
4147711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4148711890bcSjc156560 
4149711890bcSjc156560 	return (obj->component);
4150711890bcSjc156560 }
4151711890bcSjc156560 
4152711890bcSjc156560 static int
4153711890bcSjc156560 raid_obj_set_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4154711890bcSjc156560 	raid_obj_id_t comp)
4155711890bcSjc156560 {
4156711890bcSjc156560 	raid_obj_t *obj;
4157711890bcSjc156560 
4158711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4159711890bcSjc156560 	if (obj == NULL)
4160711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4161711890bcSjc156560 
4162711890bcSjc156560 	obj->component = comp;
4163711890bcSjc156560 	return (SUCCESS);
4164711890bcSjc156560 }
4165711890bcSjc156560 
4166711890bcSjc156560 static raid_obj_id_t
4167711890bcSjc156560 raid_obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4168711890bcSjc156560 {
4169711890bcSjc156560 	raid_obj_t *obj;
4170711890bcSjc156560 
4171711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4172711890bcSjc156560 	if (obj == NULL)
4173711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4174711890bcSjc156560 
4175711890bcSjc156560 	return (obj->sibling);
4176711890bcSjc156560 }
4177711890bcSjc156560 
4178711890bcSjc156560 static int
4179711890bcSjc156560 raid_obj_set_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4180711890bcSjc156560 	raid_obj_id_t sibling)
4181711890bcSjc156560 {
4182711890bcSjc156560 	raid_obj_t *obj;
4183711890bcSjc156560 
4184711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4185711890bcSjc156560 	if (obj == NULL)
4186711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4187711890bcSjc156560 
4188711890bcSjc156560 	obj->sibling = sibling;
4189711890bcSjc156560 
4190711890bcSjc156560 	return (SUCCESS);
4191711890bcSjc156560 }
4192711890bcSjc156560 
4193711890bcSjc156560 static void *
4194711890bcSjc156560 raid_obj_get_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4195711890bcSjc156560 {
4196711890bcSjc156560 	raid_obj_t *obj;
4197711890bcSjc156560 
4198711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4199711890bcSjc156560 	if (obj == NULL)
4200711890bcSjc156560 		return (NULL);
4201711890bcSjc156560 
4202711890bcSjc156560 	return (obj->data);
4203711890bcSjc156560 }
4204711890bcSjc156560 
4205711890bcSjc156560 static int
4206711890bcSjc156560 raid_obj_set_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4207711890bcSjc156560 	void *data)
4208711890bcSjc156560 {
4209711890bcSjc156560 	raid_obj_t *obj;
4210711890bcSjc156560 
4211711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4212711890bcSjc156560 	if (obj == NULL)
4213711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4214711890bcSjc156560 
4215711890bcSjc156560 	obj->data = data;
4216711890bcSjc156560 
4217711890bcSjc156560 	return (SUCCESS);
4218711890bcSjc156560 }
4219711890bcSjc156560 
4220711890bcSjc156560 static raid_obj_handle_t
4221711890bcSjc156560 raid_obj_get_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4222711890bcSjc156560 {
4223711890bcSjc156560 	raid_obj_t *obj;
4224711890bcSjc156560 
4225711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4226711890bcSjc156560 	if (obj == NULL)
4227711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4228711890bcSjc156560 
4229711890bcSjc156560 	return (obj->handle);
4230711890bcSjc156560 }
4231711890bcSjc156560 
4232711890bcSjc156560 static int
4233711890bcSjc156560 raid_obj_set_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4234711890bcSjc156560 	raid_obj_handle_t handle)
4235711890bcSjc156560 {
4236711890bcSjc156560 	raid_obj_t *obj;
4237711890bcSjc156560 
4238711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4239711890bcSjc156560 	if (obj == NULL)
4240711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4241711890bcSjc156560 
4242711890bcSjc156560 	obj->handle = handle;
4243711890bcSjc156560 	return (SUCCESS);
4244711890bcSjc156560 }
4245711890bcSjc156560 /*
4246711890bcSjc156560  * Object list maintennance routines
4247711890bcSjc156560  */
4248711890bcSjc156560 static void
4249711890bcSjc156560 raid_list_create(raid_list_t *list, size_t offset)
4250711890bcSjc156560 {
4251711890bcSjc156560 	list->head = NULL;
4252711890bcSjc156560 	list->tail = NULL;
4253711890bcSjc156560 	list->offset = offset;
4254711890bcSjc156560 }
4255711890bcSjc156560 
4256711890bcSjc156560 static void *
4257711890bcSjc156560 raid_list_head(raid_list_t *list)
4258711890bcSjc156560 {
4259711890bcSjc156560 	return (list->head);
4260711890bcSjc156560 }
4261711890bcSjc156560 
4262711890bcSjc156560 static void *
4263711890bcSjc156560 raid_list_next(raid_list_t *list, void *obj)
4264711890bcSjc156560 {
4265711890bcSjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj);
4266711890bcSjc156560 
4267711890bcSjc156560 	return (el->next);
4268711890bcSjc156560 }
4269711890bcSjc156560 
4270711890bcSjc156560 static void
4271711890bcSjc156560 raid_list_insert_tail(raid_list_t *list, void *obj)
4272711890bcSjc156560 {
4273711890bcSjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4274711890bcSjc156560 
4275711890bcSjc156560 	el->prev = list->tail;
4276711890bcSjc156560 	list->tail = obj;
4277711890bcSjc156560 
4278711890bcSjc156560 	el->next = NULL;
4279711890bcSjc156560 
4280711890bcSjc156560 	if (list->head == NULL)
4281711890bcSjc156560 		list->head = obj;
4282711890bcSjc156560 
4283711890bcSjc156560 	if (el->prev != NULL) {
4284711890bcSjc156560 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4285711890bcSjc156560 		el1->next = obj;
4286711890bcSjc156560 	}
4287711890bcSjc156560 }
4288711890bcSjc156560 
4289711890bcSjc156560 static void
4290711890bcSjc156560 raid_list_remove(raid_list_t *list, void *obj)
4291711890bcSjc156560 {
4292711890bcSjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4293711890bcSjc156560 
4294711890bcSjc156560 	if (list->head == obj)
4295711890bcSjc156560 		list->head = el->next;
4296711890bcSjc156560 
4297711890bcSjc156560 	if (list->tail == obj)
4298711890bcSjc156560 		list->tail = el->prev;
4299711890bcSjc156560 
4300711890bcSjc156560 	if (el->next != NULL) {
4301711890bcSjc156560 		el1 = LIST_OBJ_TO_EL(list, el->next);
4302711890bcSjc156560 		el1->prev = el->prev;
4303711890bcSjc156560 	}
4304711890bcSjc156560 
4305711890bcSjc156560 	if (el->prev != NULL) {
4306711890bcSjc156560 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4307711890bcSjc156560 		el1->next = el->next;
4308711890bcSjc156560 	}
4309711890bcSjc156560 
4310711890bcSjc156560 	el->prev = el->next = NULL;
4311711890bcSjc156560 }
4312711890bcSjc156560 
4313711890bcSjc156560 static void *
4314711890bcSjc156560 raid_list_remove_head(raid_list_t *list)
4315711890bcSjc156560 {
4316711890bcSjc156560 	void *obj = list->head;
4317711890bcSjc156560 
4318711890bcSjc156560 	if (obj != NULL)
4319711890bcSjc156560 		raid_list_remove(list, obj);
4320711890bcSjc156560 
4321711890bcSjc156560 	return (obj);
4322711890bcSjc156560 }
4323711890bcSjc156560 
4324711890bcSjc156560 static void *
4325711890bcSjc156560 raid_list_find(raid_list_t *list, raid_obj_id_t obj_id)
4326711890bcSjc156560 {
4327711890bcSjc156560 	raid_obj_t *obj;
4328711890bcSjc156560 
4329711890bcSjc156560 	for (obj = raid_list_head(list); obj != NULL;
4330711890bcSjc156560 	    obj = raid_list_next(list, obj))
4331711890bcSjc156560 			if (obj->obj_id == obj_id)
4332711890bcSjc156560 				break;
4333711890bcSjc156560 
4334711890bcSjc156560 	return (obj);
4335711890bcSjc156560 }
4336711890bcSjc156560 
4337711890bcSjc156560 static int
4338711890bcSjc156560 raid_obj_tab_create(raid_obj_tab_t *tab, size_t hash_slots)
4339711890bcSjc156560 {
4340711890bcSjc156560 	unsigned i;
4341711890bcSjc156560 
4342711890bcSjc156560 	if (hash_slots == 0)
4343711890bcSjc156560 		return (ERR_OP_ILLEGAL);
4344711890bcSjc156560 
4345711890bcSjc156560 	tab->slots = hash_slots;
4346711890bcSjc156560 
4347711890bcSjc156560 	if ((tab->table = calloc(hash_slots, sizeof (raid_list_t))) == NULL)
4348711890bcSjc156560 		return (ERR_NOMEM);
4349711890bcSjc156560 
4350711890bcSjc156560 	for (i = 0; i < hash_slots; i++)
4351711890bcSjc156560 		raid_list_create(&tab->table[i], offsetof(raid_obj_t, el));
4352711890bcSjc156560 
4353711890bcSjc156560 	return (SUCCESS);
4354711890bcSjc156560 }
4355711890bcSjc156560 
4356711890bcSjc156560 static void
4357711890bcSjc156560 raid_obj_tab_destroy(raid_obj_tab_t *tab)
4358711890bcSjc156560 {
4359711890bcSjc156560 	unsigned i;
4360711890bcSjc156560 
4361711890bcSjc156560 	for (i = 0; i < tab->slots; i++) {
4362711890bcSjc156560 		struct raid_obj_t *obj;
4363711890bcSjc156560 
4364711890bcSjc156560 		while ((obj = raid_list_remove_head(&tab->table[i])) != NULL)
4365711890bcSjc156560 			free(obj);
4366711890bcSjc156560 
4367711890bcSjc156560 		raid_list_destroy(&tab->table[i]);
4368711890bcSjc156560 	}
4369711890bcSjc156560 
4370711890bcSjc156560 	if (tab->table)
4371711890bcSjc156560 		free(tab->table);
4372711890bcSjc156560 
4373711890bcSjc156560 	tab->table = NULL;
4374711890bcSjc156560 	tab->slots = 0;
4375711890bcSjc156560 	tab->obj_id_cnt = 0;
4376711890bcSjc156560 }
4377711890bcSjc156560 
4378711890bcSjc156560 static int
4379711890bcSjc156560 raid_obj_tab_insert(raid_obj_tab_t *tab, raid_obj_id_t id, void *obj)
4380711890bcSjc156560 {
4381711890bcSjc156560 	raid_list_t *list;
4382711890bcSjc156560 
4383711890bcSjc156560 	list = OBJ_TAB_SLOT(tab, id);
4384711890bcSjc156560 
4385711890bcSjc156560 	if (raid_list_find(list, id) != NULL)
4386711890bcSjc156560 		return (ERR_DEVICE_DUP);
4387711890bcSjc156560 
4388711890bcSjc156560 	raid_list_insert_tail(list, obj);
4389711890bcSjc156560 
4390711890bcSjc156560 	return (SUCCESS);
4391711890bcSjc156560 }
4392711890bcSjc156560 
4393711890bcSjc156560 static void *
4394711890bcSjc156560 raid_obj_tab_remove(raid_obj_tab_t *tab, raid_obj_id_t id)
4395711890bcSjc156560 {
4396711890bcSjc156560 	raid_list_t *list;
4397711890bcSjc156560 	raid_obj_t *obj;
4398711890bcSjc156560 
4399711890bcSjc156560 	list = OBJ_TAB_SLOT(tab, id);
4400711890bcSjc156560 
4401711890bcSjc156560 	if ((obj = raid_list_find(list, id)) != NULL)
4402711890bcSjc156560 		raid_list_remove(list, obj);
4403711890bcSjc156560 
4404711890bcSjc156560 	return (obj);
4405711890bcSjc156560 }
4406711890bcSjc156560 
4407711890bcSjc156560 static void *
4408711890bcSjc156560 raid_obj_tab_find(raid_obj_tab_t *tab, raid_obj_id_t id)
4409711890bcSjc156560 {
4410711890bcSjc156560 	raid_list_t *list;
4411711890bcSjc156560 	raid_obj_t *obj;
4412711890bcSjc156560 
4413711890bcSjc156560 	list = OBJ_TAB_SLOT(tab, id);
4414711890bcSjc156560 	obj = raid_list_find(list, id);
4415711890bcSjc156560 
4416711890bcSjc156560 	return (obj);
4417711890bcSjc156560 }
4418711890bcSjc156560 
4419711890bcSjc156560 static void
4420711890bcSjc156560 raid_list_destroy(raid_list_t *list)
4421711890bcSjc156560 {
4422711890bcSjc156560 	list->head = NULL;
4423711890bcSjc156560 	list->tail = NULL;
4424711890bcSjc156560 	list->offset = 0;
4425711890bcSjc156560 }
4426711890bcSjc156560 
4427711890bcSjc156560 /*
4428711890bcSjc156560  * Plug-in maintennance routines
4429711890bcSjc156560  */
4430711890bcSjc156560 static int
4431711890bcSjc156560 controller_id_to_path(uint32_t controller_id, char *path)
4432711890bcSjc156560 {
4433711890bcSjc156560 	char buf[MAX_PATH_LEN] = {0}, buf1[MAX_PATH_LEN] = {0}, *colon;
4434711890bcSjc156560 
4435711890bcSjc156560 	(void) snprintf(buf, MAX_PATH_LEN, "%s/c%d", CFGDIR, controller_id);
4436711890bcSjc156560 	if (readlink(buf, buf1, sizeof (buf1)) < 0)
4437711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
4438711890bcSjc156560 
4439711890bcSjc156560 	if (buf1[0] != '/')
4440711890bcSjc156560 		(void) snprintf(buf, sizeof (buf), "%s/", CFGDIR);
4441711890bcSjc156560 	else
4442711890bcSjc156560 		buf[0] = 0;
4443711890bcSjc156560 	(void) strlcat(buf, buf1, MAX_PATH_LEN);
4444711890bcSjc156560 
4445711890bcSjc156560 	colon = strrchr(buf, ':');
4446711890bcSjc156560 	if (colon == NULL)
4447711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
4448711890bcSjc156560 	else
4449711890bcSjc156560 		*colon = 0;
4450711890bcSjc156560 
4451711890bcSjc156560 	(void) snprintf(path, MAX_PATH_LEN, "%s:devctl", buf);
4452711890bcSjc156560 
4453711890bcSjc156560 	if (access(path, F_OK) < 0)
4454711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
4455711890bcSjc156560 
4456711890bcSjc156560 	return (SUCCESS);
4457711890bcSjc156560 }
4458711890bcSjc156560 
4459711890bcSjc156560 static char *
4460711890bcSjc156560 controller_id_to_driver_name(uint32_t controller_id)
4461711890bcSjc156560 {
4462711890bcSjc156560 	char buf[MAX_PATH_LEN];
4463711890bcSjc156560 	di_node_t di_node;
4464711890bcSjc156560 	char *name, *tmp;
4465711890bcSjc156560 	int ret;
4466711890bcSjc156560 
4467711890bcSjc156560 	ret = controller_id_to_path(controller_id, buf);
4468711890bcSjc156560 	if (ret < SUCCESS)
4469711890bcSjc156560 		return (NULL);
4470711890bcSjc156560 
4471711890bcSjc156560 	tmp = strrchr(buf, ':');
4472711890bcSjc156560 	if (tmp != NULL)
4473711890bcSjc156560 		*tmp = 0;
4474711890bcSjc156560 
4475711890bcSjc156560 	tmp = strstr(buf, "pci");
4476711890bcSjc156560 	if (tmp == NULL)
4477711890bcSjc156560 		return (NULL);
4478711890bcSjc156560 
4479711890bcSjc156560 	di_node = di_init(tmp, DINFOPROP);
4480711890bcSjc156560 	if (di_node == DI_NODE_NIL)
4481711890bcSjc156560 		return (NULL);
4482711890bcSjc156560 
4483711890bcSjc156560 	name = di_driver_name(di_node);
4484711890bcSjc156560 
4485711890bcSjc156560 	return (name);
4486711890bcSjc156560 }
4487711890bcSjc156560 
4488711890bcSjc156560 static void
4489711890bcSjc156560 raid_plugin_init()
4490711890bcSjc156560 {
4491711890bcSjc156560 	raid_lib_t *raid_lib = raid_lib_sys;
4492711890bcSjc156560 
4493711890bcSjc156560 	while (raid_lib) {
4494711890bcSjc156560 		raid_lib_sys = raid_lib->next;
4495711890bcSjc156560 		(void) dlclose(raid_lib->lib_handle);
4496711890bcSjc156560 		free(raid_lib);
4497711890bcSjc156560 		raid_lib = raid_lib_sys;
4498711890bcSjc156560 	}
4499711890bcSjc156560 }
4500711890bcSjc156560 
4501711890bcSjc156560 static raid_lib_t *
4502711890bcSjc156560 raid_plugin_load(char *driver_name)
4503711890bcSjc156560 {
4504711890bcSjc156560 	char buf[MAX_PATH_LEN] = {0};
4505711890bcSjc156560 	raid_lib_t *supplib;
4506711890bcSjc156560 	void *sym;
4507711890bcSjc156560 
4508711890bcSjc156560 	supplib = calloc(1, sizeof (raid_lib_t));
4509711890bcSjc156560 	if (supplib == NULL)
4510711890bcSjc156560 		return (NULL);
4511711890bcSjc156560 
4512711890bcSjc156560 	(void) snprintf(buf, MAX_PATH_LEN, "%s/%s.so.1",
4513711890bcSjc156560 	    SUPP_PLUGIN_DIR, driver_name);
4514711890bcSjc156560 
4515711890bcSjc156560 	supplib->lib_handle = dlopen(buf, RTLD_LAZY);
4516711890bcSjc156560 	if (supplib->lib_handle == NULL) {
4517711890bcSjc156560 		free(supplib);
4518711890bcSjc156560 		return (NULL);
4519711890bcSjc156560 	}
4520711890bcSjc156560 
4521711890bcSjc156560 	supplib->name = driver_name;
4522711890bcSjc156560 
4523711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_version")) == NULL)
4524711890bcSjc156560 		supplib->version = RDCFG_PLUGIN_V1;
4525711890bcSjc156560 	else {
4526711890bcSjc156560 		supplib->version = *((uint32_t *)sym);
4527711890bcSjc156560 		if (supplib->version != RDCFG_PLUGIN_V1) {
4528711890bcSjc156560 			(void) dlclose(supplib->lib_handle);
4529711890bcSjc156560 			free(supplib);
4530711890bcSjc156560 			return (NULL);
4531711890bcSjc156560 		}
4532711890bcSjc156560 	}
4533711890bcSjc156560 
4534711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_open_controller")) ==
4535711890bcSjc156560 	    NULL) {
4536711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4537711890bcSjc156560 		free(supplib);
4538711890bcSjc156560 		return (NULL);
4539711890bcSjc156560 	} else
4540711890bcSjc156560 		supplib->open_controller = (int(*)(uint32_t, char **))sym;
4541711890bcSjc156560 
4542711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_close_controller")) ==
4543711890bcSjc156560 	    NULL) {
4544711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4545711890bcSjc156560 		free(supplib);
4546711890bcSjc156560 		return (NULL);
4547711890bcSjc156560 	} else
4548711890bcSjc156560 		supplib->close_controller = (int (*)(uint32_t, char **))sym;
4549711890bcSjc156560 
4550711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_compnum")) == NULL) {
4551711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4552711890bcSjc156560 		free(supplib);
4553711890bcSjc156560 		return (NULL);
4554711890bcSjc156560 	} else
4555711890bcSjc156560 		supplib->compnum = (int (*)(uint32_t, uint32_t,
4556711890bcSjc156560 		    raid_obj_type_id_t, raid_obj_type_id_t))sym;
4557711890bcSjc156560 
4558711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_complist")) == NULL) {
4559711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4560711890bcSjc156560 		free(supplib);
4561711890bcSjc156560 		return (NULL);
4562711890bcSjc156560 	} else
4563711890bcSjc156560 		supplib->complist = (int (*)(uint32_t, uint32_t,
4564711890bcSjc156560 		    raid_obj_type_id_t, raid_obj_type_id_t, int, void *))sym;
4565711890bcSjc156560 
4566711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_get_attr")) == NULL) {
4567711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4568711890bcSjc156560 		free(supplib);
4569711890bcSjc156560 		return (NULL);
4570711890bcSjc156560 	} else
4571711890bcSjc156560 		supplib->get_attr = (int (*)(uint32_t, uint32_t, uint32_t,
4572711890bcSjc156560 		    raid_obj_type_id_t, void*))sym;
4573711890bcSjc156560 
4574711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_create")) == NULL) {
4575711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4576711890bcSjc156560 		free(supplib);
4577711890bcSjc156560 		return (NULL);
4578711890bcSjc156560 	} else
4579711890bcSjc156560 		supplib->array_create = (int (*)(uint32_t, array_attr_t *, int,
4580711890bcSjc156560 		    arraypart_attr_t *, char **))sym;
4581711890bcSjc156560 
4582711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_delete")) == NULL) {
4583711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4584711890bcSjc156560 		free(supplib);
4585711890bcSjc156560 		return (NULL);
4586711890bcSjc156560 	} else
4587711890bcSjc156560 		supplib->array_delete =
4588711890bcSjc156560 		    (int (*)(uint32_t, uint32_t, char **))sym;
4589711890bcSjc156560 
4590711890bcSjc156560 	supplib->hsp_bind = (int (*)(uint32_t, uint32_t, hsp_relation_t *,
4591711890bcSjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_bind");
4592711890bcSjc156560 	supplib->hsp_unbind = (int (*)(uint32_t, uint32_t, hsp_relation_t *,
4593711890bcSjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_unbind");
4594711890bcSjc156560 	supplib->set_attr = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t *,
4595711890bcSjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_set_attr");
4596711890bcSjc156560 	supplib->flash_fw = (int (*)(uint32_t, char *, uint32_t, char **))
4597711890bcSjc156560 	    dlsym(supplib->lib_handle, "rdcfg_flash_fw");
4598711890bcSjc156560 
4599711890bcSjc156560 	supplib->next = raid_lib_sys;
4600711890bcSjc156560 	raid_lib_sys = supplib;
4601711890bcSjc156560 	return (supplib);
4602711890bcSjc156560 }
4603711890bcSjc156560 
4604711890bcSjc156560 static raid_lib_t *
4605711890bcSjc156560 raid_find_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t controller_obj_id)
4606711890bcSjc156560 {
4607711890bcSjc156560 	controller_attr_t *controller_attr;
4608711890bcSjc156560 	raid_lib_t *raid_lib;
4609711890bcSjc156560 	char *driver_name;
4610711890bcSjc156560 	raid_obj_handle_t handle;
4611711890bcSjc156560 
4612711890bcSjc156560 	/* Check if it's mapped to handle structure */
4613711890bcSjc156560 	handle = raid_obj_to_handle(raid_tab, controller_obj_id);
4614711890bcSjc156560 	if (raid_handle_sys.handles[handle].raid_lib != NULL)
4615711890bcSjc156560 		return (raid_handle_sys.handles[handle].raid_lib);
4616711890bcSjc156560 
4617711890bcSjc156560 	(void) obj_get_attr(raid_tab, controller_obj_id,
4618711890bcSjc156560 	    (void **)(&controller_attr));
4619711890bcSjc156560 
4620711890bcSjc156560 	/* Check if the plugin module is already loaded */
4621711890bcSjc156560 	driver_name = controller_id_to_driver_name(
4622711890bcSjc156560 	    controller_attr->controller_id);
4623711890bcSjc156560 	if (driver_name == NULL)
4624711890bcSjc156560 		return (NULL);
4625711890bcSjc156560 
4626711890bcSjc156560 	raid_lib = raid_lib_sys;
4627711890bcSjc156560 	while (raid_lib != NULL) {
4628711890bcSjc156560 		if (raid_lib->name != NULL &&
4629711890bcSjc156560 		    strcmp(driver_name, raid_lib->name) == 0)
4630711890bcSjc156560 			return (raid_lib);
4631711890bcSjc156560 
4632711890bcSjc156560 		raid_lib = raid_lib->next;
4633711890bcSjc156560 	}
4634711890bcSjc156560 
4635711890bcSjc156560 	/* Loading the plugin module */
4636711890bcSjc156560 	raid_lib = raid_plugin_load(driver_name);
4637711890bcSjc156560 
4638711890bcSjc156560 	return (raid_lib);
4639711890bcSjc156560 }
4640