xref: /titanic_50/usr/src/lib/libraidcfg/common/raidcfg.c (revision 711890bc9379ceea66272dc8d4981812224ea86e)
1*711890bcSjc156560 /*
2*711890bcSjc156560  * CDDL HEADER START
3*711890bcSjc156560  *
4*711890bcSjc156560  * The contents of this file are subject to the terms of the
5*711890bcSjc156560  * Common Development and Distribution License (the "License").
6*711890bcSjc156560  * You may not use this file except in compliance with the License.
7*711890bcSjc156560  *
8*711890bcSjc156560  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*711890bcSjc156560  * or http://www.opensolaris.org/os/licensing.
10*711890bcSjc156560  * See the License for the specific language governing permissions
11*711890bcSjc156560  * and limitations under the License.
12*711890bcSjc156560  *
13*711890bcSjc156560  * When distributing Covered Code, include this CDDL HEADER in each
14*711890bcSjc156560  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*711890bcSjc156560  * If applicable, add the following below this CDDL HEADER, with the
16*711890bcSjc156560  * fields enclosed by brackets "[]" replaced with your own identifying
17*711890bcSjc156560  * information: Portions Copyright [yyyy] [name of copyright owner]
18*711890bcSjc156560  *
19*711890bcSjc156560  * CDDL HEADER END
20*711890bcSjc156560  */
21*711890bcSjc156560 
22*711890bcSjc156560 /*
23*711890bcSjc156560  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*711890bcSjc156560  * Use is subject to license terms.
25*711890bcSjc156560  */
26*711890bcSjc156560 
27*711890bcSjc156560 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*711890bcSjc156560 
29*711890bcSjc156560 #include <fcntl.h>
30*711890bcSjc156560 #include <sys/types.h>
31*711890bcSjc156560 #include <sys/stat.h>
32*711890bcSjc156560 #include <stddef.h>
33*711890bcSjc156560 #include <stdlib.h>
34*711890bcSjc156560 #include <dirent.h>
35*711890bcSjc156560 #include <dlfcn.h>
36*711890bcSjc156560 #include <link.h>
37*711890bcSjc156560 #include <strings.h>
38*711890bcSjc156560 #include <stdio.h>
39*711890bcSjc156560 #include <unistd.h>
40*711890bcSjc156560 #include <sys/mnttab.h>
41*711890bcSjc156560 #include <config_admin.h>
42*711890bcSjc156560 #include <sys/param.h>
43*711890bcSjc156560 #include <libintl.h>
44*711890bcSjc156560 #include <libdevinfo.h>
45*711890bcSjc156560 #include <raidcfg.h>
46*711890bcSjc156560 #include <thread.h>
47*711890bcSjc156560 #include <synch.h>
48*711890bcSjc156560 
49*711890bcSjc156560 #ifndef TEXT_DOMAIN
50*711890bcSjc156560 #define	TEXT_DOMAIN	"SYS_TEST"
51*711890bcSjc156560 #endif
52*711890bcSjc156560 
53*711890bcSjc156560 #define	HASH_SLOTS	16
54*711890bcSjc156560 #define	HANDLER_SLOTS	256
55*711890bcSjc156560 
56*711890bcSjc156560 /*
57*711890bcSjc156560  * Raid object status;
58*711890bcSjc156560  */
59*711890bcSjc156560 #define	OBJ_STATUS_CMD_CLEAN	-1
60*711890bcSjc156560 #define	OBJ_STATUS_OPENED	1
61*711890bcSjc156560 #define	OBJ_STATUS_SCANCOMP	1 << 1
62*711890bcSjc156560 
63*711890bcSjc156560 #if defined(__sparcv9)
64*711890bcSjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg/sparcv9"
65*711890bcSjc156560 #elif defined(__amd64)
66*711890bcSjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg/amd64"
67*711890bcSjc156560 #else
68*711890bcSjc156560 #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg"
69*711890bcSjc156560 #endif
70*711890bcSjc156560 
71*711890bcSjc156560 /*
72*711890bcSjc156560  * Basic types
73*711890bcSjc156560  */
74*711890bcSjc156560 typedef	int raid_obj_id_t;
75*711890bcSjc156560 typedef	int raid_obj_status_t;
76*711890bcSjc156560 
77*711890bcSjc156560 /*
78*711890bcSjc156560  * Data structures used for object maintennance
79*711890bcSjc156560  */
80*711890bcSjc156560 typedef	struct {
81*711890bcSjc156560 	void *head;
82*711890bcSjc156560 	void *tail;
83*711890bcSjc156560 	size_t offset;	/* offset of double-linked element (raid_list_el_t) */
84*711890bcSjc156560 			/* in the linked data structures (objects) */
85*711890bcSjc156560 } raid_list_t;
86*711890bcSjc156560 
87*711890bcSjc156560 typedef	struct {
88*711890bcSjc156560 	void *prev;
89*711890bcSjc156560 	void *next;
90*711890bcSjc156560 } raid_list_el_t;
91*711890bcSjc156560 
92*711890bcSjc156560 typedef	struct {
93*711890bcSjc156560 	raid_obj_id_t obj_id_cnt;	/* id 0 is reserved */
94*711890bcSjc156560 	size_t slots;			/* How many lists linked by *table */
95*711890bcSjc156560 	raid_list_t *table;
96*711890bcSjc156560 } raid_obj_tab_t;
97*711890bcSjc156560 
98*711890bcSjc156560 /*
99*711890bcSjc156560  * Object type structure containing function pointers;
100*711890bcSjc156560  */
101*711890bcSjc156560 typedef	struct {
102*711890bcSjc156560 	int (*compnum)(raid_obj_tab_t *, raid_obj_id_t, raid_obj_type_id_t);
103*711890bcSjc156560 	int (*complist)(raid_obj_tab_t *, raid_obj_id_t, int, raid_obj_id_t *,
104*711890bcSjc156560 		raid_obj_type_id_t);
105*711890bcSjc156560 	int (*get_attr)(raid_obj_tab_t *, raid_obj_id_t);
106*711890bcSjc156560 	int (*set_attr)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, uint32_t *,
107*711890bcSjc156560 		char **);
108*711890bcSjc156560 	int (*act)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, void *, char **);
109*711890bcSjc156560 	int (*create_obj)(raid_obj_tab_t *, raid_obj_id_t, int,
110*711890bcSjc156560 		raid_obj_id_t *, char **);
111*711890bcSjc156560 	int (*delete_obj)(raid_obj_tab_t *, raid_obj_id_t, char **);
112*711890bcSjc156560 	int (*bind_obj)(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
113*711890bcSjc156560 	int (*unbind_obj)(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
114*711890bcSjc156560 } raid_obj_op_t;
115*711890bcSjc156560 
116*711890bcSjc156560 /*
117*711890bcSjc156560  * Common object data structure
118*711890bcSjc156560  */
119*711890bcSjc156560 typedef	struct {
120*711890bcSjc156560 	raid_list_el_t		el;	/* double-links */
121*711890bcSjc156560 
122*711890bcSjc156560 	raid_obj_type_id_t	obj_type_id;
123*711890bcSjc156560 	raid_obj_id_t		obj_id;
124*711890bcSjc156560 	raid_obj_status_t	status;
125*711890bcSjc156560 
126*711890bcSjc156560 	raid_obj_id_t		container;
127*711890bcSjc156560 	raid_obj_id_t		sibling;
128*711890bcSjc156560 	raid_obj_id_t		component;
129*711890bcSjc156560 
130*711890bcSjc156560 	void			*data;	/* Pointer to attribute structure */
131*711890bcSjc156560 	raid_obj_handle_t	handle;
132*711890bcSjc156560 } raid_obj_t;
133*711890bcSjc156560 
134*711890bcSjc156560 /*
135*711890bcSjc156560  * Definition about handle
136*711890bcSjc156560  */
137*711890bcSjc156560 typedef	struct {
138*711890bcSjc156560 	uint32_t	next;
139*711890bcSjc156560 	uint32_t	type;
140*711890bcSjc156560 	uint32_t	controller_id;
141*711890bcSjc156560 	uint32_t	array_id;
142*711890bcSjc156560 	uint32_t	disk_id;
143*711890bcSjc156560 	uint64_t	seq_id;
144*711890bcSjc156560 	uint32_t	task_id;
145*711890bcSjc156560 	uint32_t	fd;		/* Only for controller */
146*711890bcSjc156560 	raid_lib_t	*raid_lib;	/* Only for controller */
147*711890bcSjc156560 } handle_attr_t;
148*711890bcSjc156560 
149*711890bcSjc156560 #define	LIST_OBJ_TO_EL(list, obj)	\
150*711890bcSjc156560 	((void *)((char *)(obj) + (list)->offset))
151*711890bcSjc156560 #define	OBJ_TAB_SLOT(tab, id)	\
152*711890bcSjc156560 	((tab)->table + ((id)%(tab)->slots))
153*711890bcSjc156560 
154*711890bcSjc156560 #pragma init(raidcfg_init)
155*711890bcSjc156560 #pragma fini(raidcfg_fini)
156*711890bcSjc156560 
157*711890bcSjc156560 /*
158*711890bcSjc156560  * Function prototypes
159*711890bcSjc156560  */
160*711890bcSjc156560 static int intcompare(const void *p1, const void *p2);
161*711890bcSjc156560 static uint64_t raid_space_noalign(raid_obj_tab_t *, uint32_t, int,
162*711890bcSjc156560 	raid_obj_id_t *, arraypart_attr_t *);
163*711890bcSjc156560 static int raid_dev_config(cfga_cmd_t, uint32_t, uint32_t, uint8_t);
164*711890bcSjc156560 static int raid_dev_unmounted(uint32_t, uint32_t);
165*711890bcSjc156560 static int raid_handle_init();
166*711890bcSjc156560 static void raid_handle_fini();
167*711890bcSjc156560 static raid_obj_handle_t raid_handle_new(raid_obj_type_id_t);
168*711890bcSjc156560 static void raid_handle_delete(raid_obj_handle_t);
169*711890bcSjc156560 static void raid_handle_delete_controller_comp(uint32_t);
170*711890bcSjc156560 static raid_obj_id_t raid_handle_to_obj(raid_obj_tab_t *,
171*711890bcSjc156560 	raid_obj_handle_t);
172*711890bcSjc156560 static raid_obj_handle_t raid_obj_to_handle(raid_obj_tab_t *,
173*711890bcSjc156560 	raid_obj_id_t);
174*711890bcSjc156560 static raid_lib_t *raid_obj_get_lib(raid_obj_tab_t *, raid_obj_id_t);
175*711890bcSjc156560 static int raid_obj_set_lib(raid_obj_tab_t *, raid_obj_id_t, raid_lib_t *);
176*711890bcSjc156560 static int raid_obj_get_fd(raid_obj_tab_t *, raid_obj_id_t);
177*711890bcSjc156560 static int raid_obj_set_fd(raid_obj_tab_t *, raid_obj_id_t, int);
178*711890bcSjc156560 static int obj_scan_comp(raid_obj_tab_t *, raid_obj_id_t);
179*711890bcSjc156560 static int obj_rescan(raid_obj_tab_t *);
180*711890bcSjc156560 static raid_obj_id_t obj_get_comp(raid_obj_tab_t *, raid_obj_id_t,
181*711890bcSjc156560 	raid_obj_type_id_t);
182*711890bcSjc156560 static raid_obj_id_t obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
183*711890bcSjc156560 static int obj_get_attr(raid_obj_tab_t *, raid_obj_id_t, void **);
184*711890bcSjc156560 static raid_obj_id_t obj_locate_controller(raid_obj_tab_t *, uint32_t);
185*711890bcSjc156560 static raid_obj_id_t obj_locate_array(raid_obj_tab_t *, uint32_t, uint32_t);
186*711890bcSjc156560 static raid_obj_id_t obj_locate_array_recur(raid_obj_tab_t *, raid_obj_id_t,
187*711890bcSjc156560 	uint32_t);
188*711890bcSjc156560 static raid_obj_id_t obj_locate_hsp(raid_obj_tab_t *, uint32_t,
189*711890bcSjc156560 	uint32_t, uint32_t);
190*711890bcSjc156560 static raid_obj_id_t obj_locate_disk(raid_obj_tab_t *, uint32_t, uint32_t);
191*711890bcSjc156560 static raid_obj_id_t obj_locate_arraypart(raid_obj_tab_t *, uint32_t,
192*711890bcSjc156560 	uint32_t, uint32_t);
193*711890bcSjc156560 static raid_obj_id_t obj_locate_diskseg(raid_obj_tab_t *, uint32_t,
194*711890bcSjc156560 	uint32_t, uint32_t);
195*711890bcSjc156560 static raid_obj_id_t obj_locate_task(raid_obj_tab_t *, uint32_t, uint32_t);
196*711890bcSjc156560 static raid_obj_id_t obj_get_controller(raid_obj_tab_t *, raid_obj_id_t);
197*711890bcSjc156560 
198*711890bcSjc156560 static int obj_sys_compnum(raid_obj_tab_t *, raid_obj_id_t,
199*711890bcSjc156560 	raid_obj_type_id_t);
200*711890bcSjc156560 static int obj_sys_complist(raid_obj_tab_t *, raid_obj_id_t, int,
201*711890bcSjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
202*711890bcSjc156560 static int obj_controller_compnum(raid_obj_tab_t *, raid_obj_id_t,
203*711890bcSjc156560 	raid_obj_type_id_t);
204*711890bcSjc156560 static int obj_controller_complist(raid_obj_tab_t *, raid_obj_id_t, int,
205*711890bcSjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
206*711890bcSjc156560 static int obj_controller_get_attr(raid_obj_tab_t *, raid_obj_id_t);
207*711890bcSjc156560 static int obj_controller_act(raid_obj_tab_t *, raid_obj_id_t,
208*711890bcSjc156560 	uint32_t, void *, char **);
209*711890bcSjc156560 static int obj_array_compnum(raid_obj_tab_t *, raid_obj_id_t,
210*711890bcSjc156560 	raid_obj_type_id_t);
211*711890bcSjc156560 static int obj_array_complist(raid_obj_tab_t *, raid_obj_id_t, int,
212*711890bcSjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
213*711890bcSjc156560 static int obj_array_get_attr(raid_obj_tab_t *, raid_obj_id_t);
214*711890bcSjc156560 static int obj_array_set_attr(raid_obj_tab_t *, raid_obj_id_t,
215*711890bcSjc156560 	uint32_t, uint32_t *, char **);
216*711890bcSjc156560 static int obj_disk_compnum(raid_obj_tab_t *, raid_obj_id_t,
217*711890bcSjc156560 	raid_obj_type_id_t);
218*711890bcSjc156560 static int obj_disk_complist(raid_obj_tab_t *, raid_obj_id_t, int,
219*711890bcSjc156560 	raid_obj_id_t *, raid_obj_type_id_t);
220*711890bcSjc156560 static int obj_disk_get_attr(raid_obj_tab_t *, raid_obj_id_t);
221*711890bcSjc156560 static int obj_hsp_get_attr(raid_obj_tab_t *, raid_obj_id_t);
222*711890bcSjc156560 static int obj_arraypart_get_attr(raid_obj_tab_t *, raid_obj_id_t);
223*711890bcSjc156560 static int obj_diskseg_get_attr(raid_obj_tab_t *, raid_obj_id_t);
224*711890bcSjc156560 static int obj_task_get_attr(raid_obj_tab_t *, raid_obj_id_t);
225*711890bcSjc156560 static int obj_array_create(raid_obj_tab_t *, raid_obj_id_t, int,
226*711890bcSjc156560 	raid_obj_id_t *, char **);
227*711890bcSjc156560 static int obj_array_delete(raid_obj_tab_t *, raid_obj_id_t, char **);
228*711890bcSjc156560 static int obj_hsp_bind(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
229*711890bcSjc156560 static int obj_hsp_unbind(raid_obj_tab_t *, int, raid_obj_id_t *, char **);
230*711890bcSjc156560 
231*711890bcSjc156560 static int raid_obj_create_system_obj(raid_obj_tab_t *);
232*711890bcSjc156560 static raid_obj_id_t raid_obj_id_new(raid_obj_tab_t *);
233*711890bcSjc156560 static void *raid_obj_attr_new(raid_obj_type_id_t);
234*711890bcSjc156560 static raid_obj_id_t raid_obj_create(raid_obj_tab_t *, raid_obj_type_id_t);
235*711890bcSjc156560 static int raid_obj_delete(raid_obj_tab_t *, raid_obj_id_t);
236*711890bcSjc156560 static int raid_obj_add_org(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
237*711890bcSjc156560 static raid_obj_type_id_t raid_obj_get_type(raid_obj_tab_t *, raid_obj_id_t);
238*711890bcSjc156560 static int raid_obj_set_type(raid_obj_tab_t *, raid_obj_id_t,
239*711890bcSjc156560 	raid_obj_type_id_t);
240*711890bcSjc156560 static raid_obj_status_t raid_obj_get_status(raid_obj_tab_t *, raid_obj_id_t);
241*711890bcSjc156560 static int raid_obj_set_status(raid_obj_tab_t *, raid_obj_id_t,
242*711890bcSjc156560 	raid_obj_status_t);
243*711890bcSjc156560 static int raid_obj_clear_status(raid_obj_tab_t *, raid_obj_id_t,
244*711890bcSjc156560 	raid_obj_status_t);
245*711890bcSjc156560 static raid_obj_id_t raid_obj_get_container(raid_obj_tab_t *, raid_obj_id_t);
246*711890bcSjc156560 static int raid_obj_set_container(raid_obj_tab_t *, raid_obj_id_t,
247*711890bcSjc156560 	raid_obj_id_t);
248*711890bcSjc156560 static raid_obj_id_t raid_obj_get_comp(raid_obj_tab_t *, raid_obj_id_t);
249*711890bcSjc156560 static int raid_obj_set_comp(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
250*711890bcSjc156560 static raid_obj_id_t raid_obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
251*711890bcSjc156560 static int raid_obj_set_sibling(raid_obj_tab_t *, raid_obj_id_t,
252*711890bcSjc156560 	raid_obj_id_t);
253*711890bcSjc156560 static void *raid_obj_get_data_ptr(raid_obj_tab_t *, raid_obj_id_t);
254*711890bcSjc156560 static int raid_obj_set_data_ptr(raid_obj_tab_t *, raid_obj_id_t, void *);
255*711890bcSjc156560 static raid_obj_handle_t raid_obj_get_handle(raid_obj_tab_t *,
256*711890bcSjc156560 	raid_obj_id_t);
257*711890bcSjc156560 static int raid_obj_set_handle(raid_obj_tab_t *, raid_obj_id_t,
258*711890bcSjc156560 	raid_obj_handle_t);
259*711890bcSjc156560 
260*711890bcSjc156560 static void raid_list_create(raid_list_t *, size_t);
261*711890bcSjc156560 static void *raid_list_head(raid_list_t *);
262*711890bcSjc156560 static void *raid_list_next(raid_list_t *, void *);
263*711890bcSjc156560 static void raid_list_insert_tail(raid_list_t *, void *);
264*711890bcSjc156560 static void raid_list_remove(raid_list_t *, void *);
265*711890bcSjc156560 static void *raid_list_remove_head(raid_list_t *);
266*711890bcSjc156560 static void *raid_list_find(raid_list_t *, raid_obj_id_t);
267*711890bcSjc156560 static int raid_obj_tab_create(raid_obj_tab_t *, size_t);
268*711890bcSjc156560 static void raid_obj_tab_destroy(raid_obj_tab_t *);
269*711890bcSjc156560 static int raid_obj_tab_insert(raid_obj_tab_t *, raid_obj_id_t, void *);
270*711890bcSjc156560 static void *raid_obj_tab_remove(raid_obj_tab_t *, raid_obj_id_t);
271*711890bcSjc156560 static void *raid_obj_tab_find(raid_obj_tab_t *, raid_obj_id_t);
272*711890bcSjc156560 static void raid_list_destroy(raid_list_t *);
273*711890bcSjc156560 
274*711890bcSjc156560 static int controller_id_to_path(uint32_t, char *);
275*711890bcSjc156560 static char *controller_id_to_driver_name(uint32_t);
276*711890bcSjc156560 static void raid_plugin_init();
277*711890bcSjc156560 static raid_lib_t *raid_plugin_load(char *);
278*711890bcSjc156560 static raid_lib_t *raid_find_lib(raid_obj_tab_t *, raid_obj_id_t);
279*711890bcSjc156560 
280*711890bcSjc156560 /* Global object table */
281*711890bcSjc156560 static raid_obj_tab_t raid_tab_sys = {0, 0, NULL};
282*711890bcSjc156560 
283*711890bcSjc156560 /* Plug-in modules maintenance data structures */
284*711890bcSjc156560 static raid_lib_t *raid_lib_sys = NULL;
285*711890bcSjc156560 
286*711890bcSjc156560 /* Handle table definition */
287*711890bcSjc156560 static struct {
288*711890bcSjc156560 	int		handle_num;
289*711890bcSjc156560 	int		used;
290*711890bcSjc156560 	int		unused;
291*711890bcSjc156560 	handle_attr_t	*handles;
292*711890bcSjc156560 } raid_handle_sys = {0, 0, 0, NULL};
293*711890bcSjc156560 
294*711890bcSjc156560 /*
295*711890bcSjc156560  * RAID object method table definition
296*711890bcSjc156560  */
297*711890bcSjc156560 static raid_obj_op_t raid_obj_op_sys[OBJ_TYPE_ALL] = {
298*711890bcSjc156560 	{obj_sys_compnum, obj_sys_complist, NULL, NULL, NULL,
299*711890bcSjc156560 		NULL, NULL, NULL, NULL},	/* system object methods */
300*711890bcSjc156560 	{obj_controller_compnum, obj_controller_complist,
301*711890bcSjc156560 		obj_controller_get_attr, NULL, obj_controller_act,
302*711890bcSjc156560 		NULL, NULL, NULL, NULL},	/* controller object methods */
303*711890bcSjc156560 	{obj_array_compnum, obj_array_complist, obj_array_get_attr,
304*711890bcSjc156560 		obj_array_set_attr, NULL, obj_array_create,
305*711890bcSjc156560 		obj_array_delete, NULL, NULL},	/* array object methods */
306*711890bcSjc156560 	{obj_disk_compnum, obj_disk_complist, obj_disk_get_attr, NULL,
307*711890bcSjc156560 		NULL, NULL, NULL, NULL, NULL},	/* disk object methods */
308*711890bcSjc156560 	{NULL, NULL, obj_hsp_get_attr, NULL, NULL, NULL, NULL, obj_hsp_bind,
309*711890bcSjc156560 		obj_hsp_unbind},		/* hsp object methods */
310*711890bcSjc156560 	{NULL, NULL, obj_arraypart_get_attr, NULL, NULL, NULL, NULL,
311*711890bcSjc156560 		NULL, NULL},			/* array part object methods */
312*711890bcSjc156560 	{NULL, NULL, obj_diskseg_get_attr, NULL, NULL, NULL, NULL, NULL, NULL},
313*711890bcSjc156560 	{NULL, NULL, obj_task_get_attr, NULL, NULL, NULL, NULL,
314*711890bcSjc156560 		NULL, NULL}			/* disk seg object methods */
315*711890bcSjc156560 };
316*711890bcSjc156560 
317*711890bcSjc156560 /*
318*711890bcSjc156560  * Mutex for multithread safe
319*711890bcSjc156560  */
320*711890bcSjc156560 static mutex_t raidcfg_mp;
321*711890bcSjc156560 
322*711890bcSjc156560 /*
323*711890bcSjc156560  * RaidCfg library APIs
324*711890bcSjc156560  */
325*711890bcSjc156560 const char *
326*711890bcSjc156560 raidcfg_errstr(int err_code)
327*711890bcSjc156560 {
328*711890bcSjc156560 	char *ret_val;
329*711890bcSjc156560 
330*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
331*711890bcSjc156560 	switch (err_code) {
332*711890bcSjc156560 	case	SUCCESS:
333*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Operation succeeded.\n");
334*711890bcSjc156560 		break;
335*711890bcSjc156560 	case	STD_IOCTL:
336*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
337*711890bcSjc156560 			"Request standard IOCTL service.\n");
338*711890bcSjc156560 		break;
339*711890bcSjc156560 	case	ERR_DRIVER_NOT_FOUND:
340*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
341*711890bcSjc156560 			"Controller device can not be found.\n");
342*711890bcSjc156560 		break;
343*711890bcSjc156560 	case	ERR_DRIVER_OPEN:
344*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Can not open controller.\n");
345*711890bcSjc156560 		break;
346*711890bcSjc156560 	case	ERR_DRIVER_LOCK:
347*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Controller is locked.\n");
348*711890bcSjc156560 		break;
349*711890bcSjc156560 	case	ERR_DRIVER_CLOSED:
350*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Controller is not opened.\n");
351*711890bcSjc156560 		break;
352*711890bcSjc156560 	case	ERR_DRIVER_ACROSS:
353*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
354*711890bcSjc156560 			"Operation across multiple controllers.\n");
355*711890bcSjc156560 		break;
356*711890bcSjc156560 	case	ERR_ARRAY_LEVEL:
357*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
358*711890bcSjc156560 			"Operation not support with volume of this level.\n");
359*711890bcSjc156560 		break;
360*711890bcSjc156560 	case	ERR_ARRAY_SIZE:
361*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
362*711890bcSjc156560 			"Capacity of array out of range.\n");
363*711890bcSjc156560 		break;
364*711890bcSjc156560 	case	ERR_ARRAY_STRIPE_SIZE:
365*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal stripe size.\n");
366*711890bcSjc156560 		break;
367*711890bcSjc156560 	case	ERR_ARRAY_CACHE_POLICY:
368*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
369*711890bcSjc156560 			"Illegal cache-write policy.\n");
370*711890bcSjc156560 		break;
371*711890bcSjc156560 	case	ERR_ARRAY_IN_USE:
372*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Array in use.\n");
373*711890bcSjc156560 		break;
374*711890bcSjc156560 	case	ERR_ARRAY_TASK:
375*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Array has background task.\n");
376*711890bcSjc156560 		break;
377*711890bcSjc156560 	case	ERR_ARRAY_CONFIG:
378*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
379*711890bcSjc156560 			"Configuration over device node failed.\n");
380*711890bcSjc156560 		break;
381*711890bcSjc156560 	case	ERR_ARRAY_DISKNUM:
382*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Incorrect number of disks.\n");
383*711890bcSjc156560 		break;
384*711890bcSjc156560 	case	ERR_ARRAY_LAYOUT:
385*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal array layout.\n");
386*711890bcSjc156560 		break;
387*711890bcSjc156560 	case	ERR_ARRAY_AMOUNT:
388*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many arrays.\n");
389*711890bcSjc156560 		break;
390*711890bcSjc156560 	case	ERR_DISK_STATE:
391*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
392*711890bcSjc156560 			"Incorrect disk status for current operation.\n");
393*711890bcSjc156560 		break;
394*711890bcSjc156560 	case	ERR_DISK_SPACE:
395*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "No enough disk space.\n");
396*711890bcSjc156560 		break;
397*711890bcSjc156560 	case	ERR_DISK_SEG_AMOUNT:
398*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many disk segments.\n");
399*711890bcSjc156560 		break;
400*711890bcSjc156560 	case	ERR_DISK_NOT_EMPTY:
401*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Disk has occupied space.\n");
402*711890bcSjc156560 		break;
403*711890bcSjc156560 	case	ERR_DISK_TASK:
404*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Disk has background task.\n");
405*711890bcSjc156560 		break;
406*711890bcSjc156560 	case	ERR_TASK_STATE:
407*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
408*711890bcSjc156560 			"Incorrect task state for current operation.\n");
409*711890bcSjc156560 		break;
410*711890bcSjc156560 	case	ERR_OP_ILLEGAL:
411*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal operation.\n");
412*711890bcSjc156560 		break;
413*711890bcSjc156560 	case	ERR_OP_NO_IMPL:
414*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
415*711890bcSjc156560 			"Operation is not implemented.\n");
416*711890bcSjc156560 		break;
417*711890bcSjc156560 	case	ERR_OP_FAILED:
418*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
419*711890bcSjc156560 			"Operation in plugin failed.\n");
420*711890bcSjc156560 		break;
421*711890bcSjc156560 	case	ERR_DEVICE_NOENT:
422*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device not found.\n");
423*711890bcSjc156560 		break;
424*711890bcSjc156560 	case	ERR_DEVICE_TYPE:
425*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Illegal type of device.\n");
426*711890bcSjc156560 		break;
427*711890bcSjc156560 	case	ERR_DEVICE_DUP:
428*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device record duplicated.\n");
429*711890bcSjc156560 		break;
430*711890bcSjc156560 	case	ERR_DEVICE_OVERFLOW:
431*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Too many devices.\n");
432*711890bcSjc156560 		break;
433*711890bcSjc156560 	case	ERR_DEVICE_UNCLEAN:
434*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device pool is not clean.\n");
435*711890bcSjc156560 		break;
436*711890bcSjc156560 	case	ERR_DEVICE_INVALID:
437*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Device record is invalid.\n");
438*711890bcSjc156560 		break;
439*711890bcSjc156560 	case	ERR_NOMEM:
440*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN,
441*711890bcSjc156560 			"Can not allocate more memory space.\n");
442*711890bcSjc156560 		break;
443*711890bcSjc156560 	case	ERR_PRIV:
444*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "No privilege.\n");
445*711890bcSjc156560 		break;
446*711890bcSjc156560 	default:
447*711890bcSjc156560 		ret_val = dgettext(TEXT_DOMAIN, "Undefined error.\n");
448*711890bcSjc156560 	}
449*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
450*711890bcSjc156560 
451*711890bcSjc156560 	return (ret_val);
452*711890bcSjc156560 }
453*711890bcSjc156560 
454*711890bcSjc156560 int
455*711890bcSjc156560 raidcfg_get_controller(uint32_t controller_id)
456*711890bcSjc156560 {
457*711890bcSjc156560 	raid_obj_id_t obj_id;
458*711890bcSjc156560 	int ret_val;
459*711890bcSjc156560 
460*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
461*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
462*711890bcSjc156560 	obj_id = obj_locate_controller(&raid_tab_sys, controller_id);
463*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
464*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
465*711890bcSjc156560 		return (obj_id);
466*711890bcSjc156560 	}
467*711890bcSjc156560 
468*711890bcSjc156560 	if (obj_id == OBJ_NONE) {
469*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
470*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
471*711890bcSjc156560 	}
472*711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
473*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
474*711890bcSjc156560 
475*711890bcSjc156560 	return (ret_val);
476*711890bcSjc156560 }
477*711890bcSjc156560 
478*711890bcSjc156560 int
479*711890bcSjc156560 raidcfg_get_array(int controller_handle, uint64_t target_id, uint64_t lun)
480*711890bcSjc156560 {
481*711890bcSjc156560 	raid_obj_id_t obj_id;
482*711890bcSjc156560 	raidcfg_array_t *attr;
483*711890bcSjc156560 	int ret_val;
484*711890bcSjc156560 
485*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
486*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
487*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
488*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
489*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
490*711890bcSjc156560 		return (obj_id);
491*711890bcSjc156560 	}
492*711890bcSjc156560 
493*711890bcSjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_ARRAY);
494*711890bcSjc156560 
495*711890bcSjc156560 	while (obj_id > OBJ_NONE) {
496*711890bcSjc156560 		(void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
497*711890bcSjc156560 		if (attr->tag.idl.target_id == target_id &&
498*711890bcSjc156560 			attr->tag.idl.lun == lun)
499*711890bcSjc156560 			break;
500*711890bcSjc156560 
501*711890bcSjc156560 		obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
502*711890bcSjc156560 	}
503*711890bcSjc156560 
504*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
505*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
506*711890bcSjc156560 		return (obj_id);
507*711890bcSjc156560 	}
508*711890bcSjc156560 	if (obj_id == OBJ_NONE) {
509*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
510*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
511*711890bcSjc156560 	}
512*711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
513*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
514*711890bcSjc156560 
515*711890bcSjc156560 	return (ret_val);
516*711890bcSjc156560 }
517*711890bcSjc156560 
518*711890bcSjc156560 int
519*711890bcSjc156560 raidcfg_get_disk(int controller_handle, disk_tag_t tag)
520*711890bcSjc156560 {
521*711890bcSjc156560 	raid_obj_id_t obj_id;
522*711890bcSjc156560 	raidcfg_disk_t *attr;
523*711890bcSjc156560 	int ret_val;
524*711890bcSjc156560 
525*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
526*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
527*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
528*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
529*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
530*711890bcSjc156560 		return (obj_id);
531*711890bcSjc156560 	}
532*711890bcSjc156560 
533*711890bcSjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_DISK);
534*711890bcSjc156560 
535*711890bcSjc156560 	while (obj_id > OBJ_NONE) {
536*711890bcSjc156560 		(void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
537*711890bcSjc156560 		if (attr->tag.cidl.bus == tag.cidl.bus &&
538*711890bcSjc156560 		    attr->tag.cidl.target_id == tag.cidl.target_id &&
539*711890bcSjc156560 		    attr->tag.cidl.lun == tag.cidl.lun)
540*711890bcSjc156560 			break;
541*711890bcSjc156560 
542*711890bcSjc156560 		obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
543*711890bcSjc156560 	}
544*711890bcSjc156560 
545*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
546*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
547*711890bcSjc156560 		return (obj_id);
548*711890bcSjc156560 	}
549*711890bcSjc156560 	if (obj_id == OBJ_NONE) {
550*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
551*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
552*711890bcSjc156560 	}
553*711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
554*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
555*711890bcSjc156560 
556*711890bcSjc156560 	return (ret_val);
557*711890bcSjc156560 }
558*711890bcSjc156560 
559*711890bcSjc156560 int
560*711890bcSjc156560 raidcfg_open_controller(int handle, char **plugin_err_str)
561*711890bcSjc156560 {
562*711890bcSjc156560 	raid_obj_id_t obj_id;
563*711890bcSjc156560 	int ret;
564*711890bcSjc156560 
565*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
566*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
567*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
568*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
569*711890bcSjc156560 		raid_handle_delete(handle);
570*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
571*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
572*711890bcSjc156560 	}
573*711890bcSjc156560 
574*711890bcSjc156560 	ret = obj_controller_act(&raid_tab_sys, obj_id,
575*711890bcSjc156560 		ACT_CONTROLLER_OPEN, NULL, plugin_err_str);
576*711890bcSjc156560 	if (ret < SUCCESS) {
577*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
578*711890bcSjc156560 		return (ret);
579*711890bcSjc156560 	}
580*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
581*711890bcSjc156560 
582*711890bcSjc156560 	return (SUCCESS);
583*711890bcSjc156560 }
584*711890bcSjc156560 
585*711890bcSjc156560 int
586*711890bcSjc156560 raidcfg_close_controller(int handle, char **plugin_err_str)
587*711890bcSjc156560 {
588*711890bcSjc156560 	raid_obj_id_t obj_id;
589*711890bcSjc156560 	int ret;
590*711890bcSjc156560 
591*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
592*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
593*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
594*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
595*711890bcSjc156560 		raid_handle_delete(handle);
596*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
597*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
598*711890bcSjc156560 	}
599*711890bcSjc156560 
600*711890bcSjc156560 	ret = obj_controller_act(&raid_tab_sys, obj_id,
601*711890bcSjc156560 		ACT_CONTROLLER_CLOSE, NULL, plugin_err_str);
602*711890bcSjc156560 	if (ret < SUCCESS) {
603*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
604*711890bcSjc156560 		return (ret);
605*711890bcSjc156560 	}
606*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
607*711890bcSjc156560 
608*711890bcSjc156560 	return (SUCCESS);
609*711890bcSjc156560 }
610*711890bcSjc156560 
611*711890bcSjc156560 int
612*711890bcSjc156560 raidcfg_get_type(int handle)
613*711890bcSjc156560 {
614*711890bcSjc156560 	raid_obj_id_t obj_id;
615*711890bcSjc156560 	int ret_val;
616*711890bcSjc156560 
617*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
618*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
619*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
620*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
621*711890bcSjc156560 		raid_handle_delete(handle);
622*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
623*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
624*711890bcSjc156560 	}
625*711890bcSjc156560 	ret_val = raid_obj_get_type(&raid_tab_sys, obj_id);
626*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
627*711890bcSjc156560 
628*711890bcSjc156560 	return (ret_val);
629*711890bcSjc156560 }
630*711890bcSjc156560 
631*711890bcSjc156560 int
632*711890bcSjc156560 raidcfg_get_attr(int handle, void *attr)
633*711890bcSjc156560 {
634*711890bcSjc156560 	raid_obj_id_t obj_id;
635*711890bcSjc156560 	raid_obj_type_id_t type;
636*711890bcSjc156560 	void *data;
637*711890bcSjc156560 	int ret, size;
638*711890bcSjc156560 
639*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
640*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
641*711890bcSjc156560 	if (attr == NULL) {
642*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
643*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
644*711890bcSjc156560 	}
645*711890bcSjc156560 
646*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
647*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
648*711890bcSjc156560 		raid_handle_delete(handle);
649*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
650*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
651*711890bcSjc156560 	}
652*711890bcSjc156560 
653*711890bcSjc156560 	type = raid_obj_get_type(&raid_tab_sys, obj_id);
654*711890bcSjc156560 	ret = obj_get_attr(&raid_tab_sys, obj_id, &data);
655*711890bcSjc156560 	if (ret < SUCCESS) {
656*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
657*711890bcSjc156560 		return (ret);
658*711890bcSjc156560 	}
659*711890bcSjc156560 
660*711890bcSjc156560 	switch (type) {
661*711890bcSjc156560 	case	OBJ_TYPE_CONTROLLER:
662*711890bcSjc156560 		size = sizeof (controller_attr_t);
663*711890bcSjc156560 		break;
664*711890bcSjc156560 	case	OBJ_TYPE_ARRAY:
665*711890bcSjc156560 		size = sizeof (array_attr_t);
666*711890bcSjc156560 		break;
667*711890bcSjc156560 	case	OBJ_TYPE_HSP:
668*711890bcSjc156560 		{
669*711890bcSjc156560 			raidcfg_hsp_t *dst = attr;
670*711890bcSjc156560 			hsp_attr_t *src = data;
671*711890bcSjc156560 			controller_attr_t *ctlr_attr;
672*711890bcSjc156560 			array_attr_t *array_attr;
673*711890bcSjc156560 
674*711890bcSjc156560 			dst->associated_id = src->associated_id;
675*711890bcSjc156560 			dst->type = src->type;
676*711890bcSjc156560 
677*711890bcSjc156560 			obj_id = obj_get_controller(&raid_tab_sys, obj_id);
678*711890bcSjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
679*711890bcSjc156560 				(void **)(&ctlr_attr));
680*711890bcSjc156560 			if (ret < SUCCESS) {
681*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
682*711890bcSjc156560 				return (ret);
683*711890bcSjc156560 			}
684*711890bcSjc156560 
685*711890bcSjc156560 			if (src->type == HSP_TYPE_LOCAL) {
686*711890bcSjc156560 				obj_id = obj_locate_array(&raid_tab_sys,
687*711890bcSjc156560 					ctlr_attr->controller_id,
688*711890bcSjc156560 					src->associated_id);
689*711890bcSjc156560 				ret = obj_get_attr(&raid_tab_sys, obj_id,
690*711890bcSjc156560 					(void **)(&array_attr));
691*711890bcSjc156560 				if (ret < SUCCESS) {
692*711890bcSjc156560 					(void) mutex_unlock(&raidcfg_mp);
693*711890bcSjc156560 					return (ret);
694*711890bcSjc156560 				}
695*711890bcSjc156560 
696*711890bcSjc156560 				dst->tag.idl.target_id =
697*711890bcSjc156560 					array_attr->tag.idl.target_id;
698*711890bcSjc156560 				dst->tag.idl.lun = array_attr->tag.idl.lun;
699*711890bcSjc156560 			}
700*711890bcSjc156560 		}
701*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
702*711890bcSjc156560 		return (SUCCESS);
703*711890bcSjc156560 	case	OBJ_TYPE_DISK:
704*711890bcSjc156560 		size = sizeof (disk_attr_t);
705*711890bcSjc156560 		break;
706*711890bcSjc156560 	case	OBJ_TYPE_ARRAY_PART:
707*711890bcSjc156560 		{
708*711890bcSjc156560 			raidcfg_arraypart_t *dst = attr;
709*711890bcSjc156560 			arraypart_attr_t *src = data;
710*711890bcSjc156560 			controller_attr_t *ctlr_attr;
711*711890bcSjc156560 			disk_attr_t *disk_attr;
712*711890bcSjc156560 
713*711890bcSjc156560 			dst->disk_id = src->disk_id;
714*711890bcSjc156560 			dst->offset = src->offset;
715*711890bcSjc156560 			dst->size = src->size;
716*711890bcSjc156560 			dst->state = src->state;
717*711890bcSjc156560 
718*711890bcSjc156560 			obj_id = obj_get_controller(&raid_tab_sys, obj_id);
719*711890bcSjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
720*711890bcSjc156560 				(void **)(&ctlr_attr));
721*711890bcSjc156560 			if (ret < SUCCESS) {
722*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
723*711890bcSjc156560 				return (ret);
724*711890bcSjc156560 			}
725*711890bcSjc156560 
726*711890bcSjc156560 			obj_id = obj_locate_disk(&raid_tab_sys,
727*711890bcSjc156560 				ctlr_attr->controller_id, src->disk_id);
728*711890bcSjc156560 			if (obj_id <= OBJ_NONE) {
729*711890bcSjc156560 				dst->tag.cidl.bus = (uint64_t)OBJ_ATTR_NONE;
730*711890bcSjc156560 				dst->tag.cidl.target_id =
731*711890bcSjc156560 				    (uint64_t)OBJ_ATTR_NONE;
732*711890bcSjc156560 				dst->tag.cidl.lun = (uint64_t)OBJ_ATTR_NONE;
733*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
734*711890bcSjc156560 				return (SUCCESS);
735*711890bcSjc156560 			}
736*711890bcSjc156560 
737*711890bcSjc156560 			ret = obj_get_attr(&raid_tab_sys, obj_id,
738*711890bcSjc156560 				(void **)(&disk_attr));
739*711890bcSjc156560 			if (ret < SUCCESS) {
740*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
741*711890bcSjc156560 				return (ret);
742*711890bcSjc156560 			}
743*711890bcSjc156560 
744*711890bcSjc156560 			dst->tag.cidl.bus = disk_attr->tag.cidl.bus;
745*711890bcSjc156560 			dst->tag.cidl.target_id = disk_attr->tag.cidl.target_id;
746*711890bcSjc156560 			dst->tag.cidl.lun = disk_attr->tag.cidl.lun;
747*711890bcSjc156560 		}
748*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
749*711890bcSjc156560 		return (SUCCESS);
750*711890bcSjc156560 	case	OBJ_TYPE_DISK_SEG:
751*711890bcSjc156560 		size = sizeof (diskseg_attr_t);
752*711890bcSjc156560 		break;
753*711890bcSjc156560 	case	OBJ_TYPE_TASK:
754*711890bcSjc156560 		size = sizeof (task_attr_t);
755*711890bcSjc156560 		break;
756*711890bcSjc156560 	default:
757*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
758*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
759*711890bcSjc156560 	}
760*711890bcSjc156560 
761*711890bcSjc156560 	(void) memcpy(attr, data, size);
762*711890bcSjc156560 
763*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
764*711890bcSjc156560 	return (ret);
765*711890bcSjc156560 }
766*711890bcSjc156560 
767*711890bcSjc156560 int
768*711890bcSjc156560 raidcfg_get_container(int handle)
769*711890bcSjc156560 {
770*711890bcSjc156560 	raid_obj_id_t obj_id;
771*711890bcSjc156560 	int ret_val;
772*711890bcSjc156560 
773*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
774*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
775*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
776*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
777*711890bcSjc156560 		raid_handle_delete(handle);
778*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
779*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
780*711890bcSjc156560 	}
781*711890bcSjc156560 
782*711890bcSjc156560 	obj_id = raid_obj_get_container(&raid_tab_sys, obj_id);
783*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
784*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
785*711890bcSjc156560 		return (obj_id);
786*711890bcSjc156560 	}
787*711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
788*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
789*711890bcSjc156560 
790*711890bcSjc156560 	return (ret_val);
791*711890bcSjc156560 }
792*711890bcSjc156560 
793*711890bcSjc156560 int
794*711890bcSjc156560 raidcfg_list_head(int handle, raid_obj_type_id_t type)
795*711890bcSjc156560 {
796*711890bcSjc156560 	raid_obj_id_t obj_id;
797*711890bcSjc156560 	int ret_val;
798*711890bcSjc156560 
799*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
800*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
801*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
802*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
803*711890bcSjc156560 		raid_handle_delete(handle);
804*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
805*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
806*711890bcSjc156560 	}
807*711890bcSjc156560 
808*711890bcSjc156560 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, type);
809*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
810*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
811*711890bcSjc156560 		return (obj_id);
812*711890bcSjc156560 	}
813*711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
814*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
815*711890bcSjc156560 
816*711890bcSjc156560 	return (ret_val);
817*711890bcSjc156560 }
818*711890bcSjc156560 
819*711890bcSjc156560 int
820*711890bcSjc156560 raidcfg_list_next(int handle)
821*711890bcSjc156560 {
822*711890bcSjc156560 	raid_obj_id_t obj_id;
823*711890bcSjc156560 	int ret_val;
824*711890bcSjc156560 
825*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
826*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
827*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
828*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
829*711890bcSjc156560 		raid_handle_delete(handle);
830*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
831*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
832*711890bcSjc156560 	}
833*711890bcSjc156560 
834*711890bcSjc156560 	obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
835*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
836*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
837*711890bcSjc156560 		return (obj_id);
838*711890bcSjc156560 	}
839*711890bcSjc156560 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
840*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
841*711890bcSjc156560 
842*711890bcSjc156560 	return (ret_val);
843*711890bcSjc156560 }
844*711890bcSjc156560 
845*711890bcSjc156560 int
846*711890bcSjc156560 raidcfg_set_attr(int handle, uint32_t set_cmd, void *value,
847*711890bcSjc156560 	char **plugin_err_str)
848*711890bcSjc156560 {
849*711890bcSjc156560 	raid_obj_id_t obj_id;
850*711890bcSjc156560 	raid_obj_type_id_t type;
851*711890bcSjc156560 	int ret;
852*711890bcSjc156560 
853*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
854*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
855*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
856*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
857*711890bcSjc156560 		raid_handle_delete(handle);
858*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
859*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
860*711890bcSjc156560 	}
861*711890bcSjc156560 
862*711890bcSjc156560 	type = raid_obj_get_type(&raid_tab_sys, obj_id);
863*711890bcSjc156560 	if (raid_obj_op_sys[type].set_attr == NULL) {
864*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
865*711890bcSjc156560 		return (ERR_OP_NO_IMPL);
866*711890bcSjc156560 	}
867*711890bcSjc156560 
868*711890bcSjc156560 	ret = raid_obj_op_sys[type].set_attr(&raid_tab_sys,
869*711890bcSjc156560 		obj_id, set_cmd, value, plugin_err_str);
870*711890bcSjc156560 
871*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
872*711890bcSjc156560 	return (ret);
873*711890bcSjc156560 }
874*711890bcSjc156560 
875*711890bcSjc156560 int
876*711890bcSjc156560 raidcfg_update_fw(int handle, char *file, char **plugin_err_str)
877*711890bcSjc156560 {
878*711890bcSjc156560 	raid_obj_id_t obj_id;
879*711890bcSjc156560 	int ret;
880*711890bcSjc156560 
881*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
882*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
883*711890bcSjc156560 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
884*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
885*711890bcSjc156560 		raid_handle_delete(handle);
886*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
887*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
888*711890bcSjc156560 	}
889*711890bcSjc156560 
890*711890bcSjc156560 	if (raid_obj_get_type(&raid_tab_sys, obj_id) != OBJ_TYPE_CONTROLLER) {
891*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
892*711890bcSjc156560 		return (ERR_OP_NO_IMPL);
893*711890bcSjc156560 	}
894*711890bcSjc156560 
895*711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_CONTROLLER].act(&raid_tab_sys,
896*711890bcSjc156560 		obj_id, ACT_CONTROLLER_FLASH_FW, file, plugin_err_str);
897*711890bcSjc156560 
898*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
899*711890bcSjc156560 	return (ret);
900*711890bcSjc156560 }
901*711890bcSjc156560 
902*711890bcSjc156560 int
903*711890bcSjc156560 raidcfg_create_array(int num_of_comps, int *disk_handles,
904*711890bcSjc156560 	uint32_t raid_level, uint64_t size, uint32_t stripe_size,
905*711890bcSjc156560 	char **plugin_err_str)
906*711890bcSjc156560 {
907*711890bcSjc156560 	raid_obj_id_t *disk_obj_ids, obj_id;
908*711890bcSjc156560 	array_attr_t *array_attr;
909*711890bcSjc156560 	raid_obj_handle_t array_handle;
910*711890bcSjc156560 	int i, ret;
911*711890bcSjc156560 
912*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
913*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
914*711890bcSjc156560 
915*711890bcSjc156560 	disk_obj_ids = calloc(num_of_comps, sizeof (raid_obj_id_t));
916*711890bcSjc156560 	if (disk_obj_ids == NULL) {
917*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
918*711890bcSjc156560 		return (ERR_NOMEM);
919*711890bcSjc156560 	}
920*711890bcSjc156560 
921*711890bcSjc156560 	/* convert disk handles into disk object ids; */
922*711890bcSjc156560 	for (i = 0; i < num_of_comps; ++i) {
923*711890bcSjc156560 		if (*(disk_handles + i) == OBJ_SEPARATOR_BEGIN ||
924*711890bcSjc156560 			*(disk_handles + i) == OBJ_SEPARATOR_END) {
925*711890bcSjc156560 			*(disk_obj_ids + i) = *(disk_handles + i);
926*711890bcSjc156560 			continue;
927*711890bcSjc156560 		}
928*711890bcSjc156560 
929*711890bcSjc156560 		*(disk_obj_ids + i) = raid_handle_to_obj(&raid_tab_sys,
930*711890bcSjc156560 			*(disk_handles + i));
931*711890bcSjc156560 		if (raid_obj_get_type(&raid_tab_sys, *(disk_obj_ids + i)) !=
932*711890bcSjc156560 			OBJ_TYPE_DISK) {
933*711890bcSjc156560 			free(disk_obj_ids);
934*711890bcSjc156560 			(void) obj_rescan(&raid_tab_sys);
935*711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
936*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
937*711890bcSjc156560 		}
938*711890bcSjc156560 	}
939*711890bcSjc156560 
940*711890bcSjc156560 	/* Create an empty array object */
941*711890bcSjc156560 	obj_id = raid_obj_create(&raid_tab_sys, OBJ_TYPE_ARRAY);
942*711890bcSjc156560 	if (obj_id < OBJ_NONE) {
943*711890bcSjc156560 		free(disk_obj_ids);
944*711890bcSjc156560 		(void) obj_rescan(&raid_tab_sys);
945*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
946*711890bcSjc156560 		return (obj_id);
947*711890bcSjc156560 	}
948*711890bcSjc156560 	(void) raid_obj_clear_status(&raid_tab_sys, obj_id,
949*711890bcSjc156560 		OBJ_STATUS_CMD_CLEAN);
950*711890bcSjc156560 
951*711890bcSjc156560 	array_attr = raid_obj_get_data_ptr(&raid_tab_sys, obj_id);
952*711890bcSjc156560 	array_attr->array_id = (uint32_t)OBJ_ATTR_NONE;
953*711890bcSjc156560 	array_attr->raid_level = raid_level;
954*711890bcSjc156560 	array_attr->capacity = size;
955*711890bcSjc156560 	array_attr->stripe_size = stripe_size;
956*711890bcSjc156560 	array_attr->write_policy = CACHE_WR_ON;
957*711890bcSjc156560 	array_attr->read_policy = CACHE_RD_ON;
958*711890bcSjc156560 
959*711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].create_obj(&raid_tab_sys, obj_id,
960*711890bcSjc156560 		num_of_comps, disk_obj_ids, plugin_err_str);
961*711890bcSjc156560 	free(disk_obj_ids);
962*711890bcSjc156560 
963*711890bcSjc156560 	if (ret < SUCCESS) {
964*711890bcSjc156560 		(void) obj_rescan(&raid_tab_sys);
965*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
966*711890bcSjc156560 		return (ret);
967*711890bcSjc156560 	}
968*711890bcSjc156560 
969*711890bcSjc156560 	/* create_obj() method should put the array object in the device tree */
970*711890bcSjc156560 	array_handle = raid_obj_to_handle(&raid_tab_sys, obj_id);
971*711890bcSjc156560 
972*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
973*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
974*711890bcSjc156560 	return (array_handle);
975*711890bcSjc156560 }
976*711890bcSjc156560 
977*711890bcSjc156560 int
978*711890bcSjc156560 raidcfg_delete_array(int array_handle, char **plugin_err_str)
979*711890bcSjc156560 {
980*711890bcSjc156560 	raid_obj_id_t array_obj_id;
981*711890bcSjc156560 	int ret;
982*711890bcSjc156560 
983*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
984*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
985*711890bcSjc156560 
986*711890bcSjc156560 	if (raidcfg_get_type(array_handle) != OBJ_TYPE_ARRAY) {
987*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
988*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
989*711890bcSjc156560 	}
990*711890bcSjc156560 
991*711890bcSjc156560 	array_obj_id = raid_handle_to_obj(&raid_tab_sys, array_handle);
992*711890bcSjc156560 	if (array_obj_id < OBJ_NONE) {
993*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
994*711890bcSjc156560 		return (array_obj_id);
995*711890bcSjc156560 	}
996*711890bcSjc156560 	if (array_obj_id == OBJ_NONE) {
997*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
998*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
999*711890bcSjc156560 	}
1000*711890bcSjc156560 
1001*711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].delete_obj(&raid_tab_sys,
1002*711890bcSjc156560 		array_obj_id, plugin_err_str);
1003*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1004*711890bcSjc156560 
1005*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
1006*711890bcSjc156560 	return (ret);
1007*711890bcSjc156560 }
1008*711890bcSjc156560 
1009*711890bcSjc156560 int
1010*711890bcSjc156560 raidcfg_set_hsp(int num, raidcfg_hsp_relation_t *hsp_relations,
1011*711890bcSjc156560 	char **plugin_err_str)
1012*711890bcSjc156560 {
1013*711890bcSjc156560 	raid_obj_id_t disk_obj_id, array_obj_id;
1014*711890bcSjc156560 	raid_obj_id_t *hsp_relation_objs;
1015*711890bcSjc156560 	int ret, i;
1016*711890bcSjc156560 
1017*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
1018*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1019*711890bcSjc156560 	if ((num == 0) || (hsp_relations == NULL)) {
1020*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
1021*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
1022*711890bcSjc156560 	}
1023*711890bcSjc156560 
1024*711890bcSjc156560 	hsp_relation_objs = malloc(2 * num * sizeof (raid_obj_id_t));
1025*711890bcSjc156560 	if (hsp_relation_objs == NULL) {
1026*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
1027*711890bcSjc156560 		return (ERR_NOMEM);
1028*711890bcSjc156560 	}
1029*711890bcSjc156560 
1030*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1031*711890bcSjc156560 
1032*711890bcSjc156560 	for (i = 0; i < num; ++ i) {
1033*711890bcSjc156560 		if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
1034*711890bcSjc156560 			array_obj_id = raid_handle_to_obj(&raid_tab_sys,
1035*711890bcSjc156560 				hsp_relations[i].array_handle);
1036*711890bcSjc156560 			if (array_obj_id < OBJ_NONE) {
1037*711890bcSjc156560 				free(hsp_relation_objs);
1038*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1039*711890bcSjc156560 				return (array_obj_id);
1040*711890bcSjc156560 			}
1041*711890bcSjc156560 			if (array_obj_id == OBJ_NONE) {
1042*711890bcSjc156560 				(void) free(hsp_relation_objs);
1043*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1044*711890bcSjc156560 				return (ERR_DEVICE_NOENT);
1045*711890bcSjc156560 			}
1046*711890bcSjc156560 			if (raidcfg_get_type(hsp_relations[i].array_handle) !=
1047*711890bcSjc156560 				OBJ_TYPE_ARRAY) {
1048*711890bcSjc156560 				free(hsp_relation_objs);
1049*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1050*711890bcSjc156560 				return (ERR_DEVICE_TYPE);
1051*711890bcSjc156560 			}
1052*711890bcSjc156560 		} else
1053*711890bcSjc156560 			array_obj_id = OBJ_ATTR_NONE;
1054*711890bcSjc156560 
1055*711890bcSjc156560 		disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
1056*711890bcSjc156560 			hsp_relations[i].disk_handle);
1057*711890bcSjc156560 		if (disk_obj_id < OBJ_NONE) {
1058*711890bcSjc156560 			free(hsp_relation_objs);
1059*711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1060*711890bcSjc156560 			return (disk_obj_id);
1061*711890bcSjc156560 		}
1062*711890bcSjc156560 		if (disk_obj_id == OBJ_NONE) {
1063*711890bcSjc156560 			free(hsp_relation_objs);
1064*711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1065*711890bcSjc156560 			return (ERR_DEVICE_NOENT);
1066*711890bcSjc156560 		}
1067*711890bcSjc156560 		if (raidcfg_get_type(hsp_relations[i].disk_handle) !=
1068*711890bcSjc156560 			OBJ_TYPE_DISK) {
1069*711890bcSjc156560 			free(hsp_relation_objs);
1070*711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1071*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
1072*711890bcSjc156560 		}
1073*711890bcSjc156560 
1074*711890bcSjc156560 		hsp_relation_objs[2 * i] = array_obj_id;
1075*711890bcSjc156560 		hsp_relation_objs[2 * i + 1] = disk_obj_id;
1076*711890bcSjc156560 	}
1077*711890bcSjc156560 
1078*711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].bind_obj(&raid_tab_sys, num,
1079*711890bcSjc156560 		hsp_relation_objs, plugin_err_str);
1080*711890bcSjc156560 
1081*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1082*711890bcSjc156560 	free(hsp_relation_objs);
1083*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
1084*711890bcSjc156560 
1085*711890bcSjc156560 	return (ret);
1086*711890bcSjc156560 }
1087*711890bcSjc156560 
1088*711890bcSjc156560 int
1089*711890bcSjc156560 raidcfg_unset_hsp(int num, raidcfg_hsp_relation_t *hsp_relations,
1090*711890bcSjc156560 	char **plugin_err_str)
1091*711890bcSjc156560 {
1092*711890bcSjc156560 	raid_obj_id_t disk_obj_id, array_obj_id;
1093*711890bcSjc156560 	raid_obj_id_t *hsp_relation_objs;
1094*711890bcSjc156560 	int ret, i;
1095*711890bcSjc156560 
1096*711890bcSjc156560 	(void) mutex_lock(&raidcfg_mp);
1097*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1098*711890bcSjc156560 	if ((num == 0) || (hsp_relations == NULL)) {
1099*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
1100*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
1101*711890bcSjc156560 	}
1102*711890bcSjc156560 
1103*711890bcSjc156560 	hsp_relation_objs = malloc(2 * num * sizeof (raid_obj_id_t));
1104*711890bcSjc156560 	if (hsp_relation_objs == NULL) {
1105*711890bcSjc156560 		(void) mutex_unlock(&raidcfg_mp);
1106*711890bcSjc156560 		return (ERR_NOMEM);
1107*711890bcSjc156560 	}
1108*711890bcSjc156560 
1109*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1110*711890bcSjc156560 
1111*711890bcSjc156560 	for (i = 0; i < num; ++ i) {
1112*711890bcSjc156560 		if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
1113*711890bcSjc156560 			array_obj_id = raid_handle_to_obj(&raid_tab_sys,
1114*711890bcSjc156560 				hsp_relations[i].array_handle);
1115*711890bcSjc156560 			if (array_obj_id < OBJ_NONE) {
1116*711890bcSjc156560 				free(hsp_relation_objs);
1117*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1118*711890bcSjc156560 				return (array_obj_id);
1119*711890bcSjc156560 			}
1120*711890bcSjc156560 			if (array_obj_id == OBJ_NONE) {
1121*711890bcSjc156560 				free(hsp_relation_objs);
1122*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1123*711890bcSjc156560 				return (ERR_DEVICE_NOENT);
1124*711890bcSjc156560 			}
1125*711890bcSjc156560 			if (raidcfg_get_type(hsp_relations[i].array_handle) !=
1126*711890bcSjc156560 				OBJ_TYPE_ARRAY) {
1127*711890bcSjc156560 				free(hsp_relation_objs);
1128*711890bcSjc156560 				(void) mutex_unlock(&raidcfg_mp);
1129*711890bcSjc156560 				return (ERR_DEVICE_TYPE);
1130*711890bcSjc156560 			}
1131*711890bcSjc156560 		} else
1132*711890bcSjc156560 			array_obj_id = OBJ_ATTR_NONE;
1133*711890bcSjc156560 
1134*711890bcSjc156560 		disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
1135*711890bcSjc156560 			hsp_relations[i].disk_handle);
1136*711890bcSjc156560 		if (disk_obj_id < OBJ_NONE) {
1137*711890bcSjc156560 			free(hsp_relation_objs);
1138*711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1139*711890bcSjc156560 			return (disk_obj_id);
1140*711890bcSjc156560 		}
1141*711890bcSjc156560 		if (disk_obj_id == OBJ_NONE) {
1142*711890bcSjc156560 			free(hsp_relation_objs);
1143*711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1144*711890bcSjc156560 			return (ERR_DEVICE_NOENT);
1145*711890bcSjc156560 		}
1146*711890bcSjc156560 		if (raidcfg_get_type(hsp_relations[i].disk_handle) !=
1147*711890bcSjc156560 			OBJ_TYPE_DISK) {
1148*711890bcSjc156560 			free(hsp_relation_objs);
1149*711890bcSjc156560 			(void) mutex_unlock(&raidcfg_mp);
1150*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
1151*711890bcSjc156560 		}
1152*711890bcSjc156560 
1153*711890bcSjc156560 		hsp_relation_objs[2 * i] = array_obj_id;
1154*711890bcSjc156560 		hsp_relation_objs[2 * i + 1] = disk_obj_id;
1155*711890bcSjc156560 	}
1156*711890bcSjc156560 
1157*711890bcSjc156560 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].unbind_obj(&raid_tab_sys,
1158*711890bcSjc156560 		num, hsp_relation_objs, plugin_err_str);
1159*711890bcSjc156560 
1160*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1161*711890bcSjc156560 	free(hsp_relation_objs);
1162*711890bcSjc156560 	(void) mutex_unlock(&raidcfg_mp);
1163*711890bcSjc156560 
1164*711890bcSjc156560 	return (ret);
1165*711890bcSjc156560 }
1166*711890bcSjc156560 
1167*711890bcSjc156560 /*
1168*711890bcSjc156560  * RaidCfg lib routines
1169*711890bcSjc156560  */
1170*711890bcSjc156560 void
1171*711890bcSjc156560 raidcfg_init(void)
1172*711890bcSjc156560 {
1173*711890bcSjc156560 	(void) mutex_init(&raidcfg_mp, NULL, NULL);
1174*711890bcSjc156560 	raid_plugin_init();
1175*711890bcSjc156560 	(void) raid_handle_init();
1176*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1177*711890bcSjc156560 }
1178*711890bcSjc156560 
1179*711890bcSjc156560 void
1180*711890bcSjc156560 raidcfg_fini(void)
1181*711890bcSjc156560 {
1182*711890bcSjc156560 	/*
1183*711890bcSjc156560 	 * Need to close all opened controllers before destroying object table
1184*711890bcSjc156560 	 */
1185*711890bcSjc156560 	(void) obj_rescan(&raid_tab_sys);
1186*711890bcSjc156560 	raid_handle_fini();
1187*711890bcSjc156560 	raid_obj_tab_destroy(&raid_tab_sys);
1188*711890bcSjc156560 	raid_plugin_init();
1189*711890bcSjc156560 	(void) mutex_destroy(&raidcfg_mp);
1190*711890bcSjc156560 }
1191*711890bcSjc156560 
1192*711890bcSjc156560 /*
1193*711890bcSjc156560  * Support routines
1194*711890bcSjc156560  */
1195*711890bcSjc156560 static int
1196*711890bcSjc156560 intcompare(const void *p1, const void *p2)
1197*711890bcSjc156560 {
1198*711890bcSjc156560 	int i, j;
1199*711890bcSjc156560 	i = *((int *)p1);
1200*711890bcSjc156560 	j = *((int *)p2);
1201*711890bcSjc156560 	return (i - j);
1202*711890bcSjc156560 }
1203*711890bcSjc156560 
1204*711890bcSjc156560 static uint64_t
1205*711890bcSjc156560 raid_space_noalign(raid_obj_tab_t *raid_tab, uint32_t raid_level, int num,
1206*711890bcSjc156560 	raid_obj_id_t *disk_objs, arraypart_attr_t *arraypart_attrs)
1207*711890bcSjc156560 {
1208*711890bcSjc156560 	disk_attr_t *disk_attr;
1209*711890bcSjc156560 	diskseg_attr_t *diskseg_attr;
1210*711890bcSjc156560 	raid_obj_id_t obj_id;
1211*711890bcSjc156560 	uint64_t offset, capacity;
1212*711890bcSjc156560 	int i, disk_num, sub_array_num, disk_layer;
1213*711890bcSjc156560 
1214*711890bcSjc156560 	/* Find out the maximum available space for all disks */
1215*711890bcSjc156560 	for (i = 0; i < num; ++i) {
1216*711890bcSjc156560 		if ((disk_objs[i] == OBJ_SEPARATOR_BEGIN) ||
1217*711890bcSjc156560 			(disk_objs[i] == OBJ_SEPARATOR_END))
1218*711890bcSjc156560 			continue;
1219*711890bcSjc156560 
1220*711890bcSjc156560 		(void) obj_get_attr(raid_tab, disk_objs[i],
1221*711890bcSjc156560 			(void **)(&disk_attr));
1222*711890bcSjc156560 		obj_id = obj_get_comp(raid_tab, disk_objs[i],
1223*711890bcSjc156560 			OBJ_TYPE_DISK_SEG);
1224*711890bcSjc156560 		if (obj_id == OBJ_NONE) {
1225*711890bcSjc156560 			arraypart_attrs[i].offset = 0;
1226*711890bcSjc156560 			arraypart_attrs[i].size = disk_attr->capacity;
1227*711890bcSjc156560 			continue;
1228*711890bcSjc156560 		}
1229*711890bcSjc156560 
1230*711890bcSjc156560 		(void) obj_get_attr(raid_tab, obj_id, (void **)
1231*711890bcSjc156560 			(&diskseg_attr));
1232*711890bcSjc156560 		arraypart_attrs[i].offset = 0;
1233*711890bcSjc156560 		arraypart_attrs[i].size = diskseg_attr->offset;
1234*711890bcSjc156560 		offset = diskseg_attr->offset + diskseg_attr->size;
1235*711890bcSjc156560 
1236*711890bcSjc156560 		while ((obj_id = obj_get_sibling(raid_tab, obj_id)) !=
1237*711890bcSjc156560 		    OBJ_NONE) {
1238*711890bcSjc156560 			(void) obj_get_attr(raid_tab, obj_id,
1239*711890bcSjc156560 				(void **)(&diskseg_attr));
1240*711890bcSjc156560 			if ((diskseg_attr->offset - offset) >
1241*711890bcSjc156560 				arraypart_attrs[i].size) {
1242*711890bcSjc156560 				arraypart_attrs[i].offset = offset;
1243*711890bcSjc156560 				arraypart_attrs[i].size = diskseg_attr->offset
1244*711890bcSjc156560 					- offset;
1245*711890bcSjc156560 			}
1246*711890bcSjc156560 
1247*711890bcSjc156560 			offset = diskseg_attr->offset + diskseg_attr->size;
1248*711890bcSjc156560 		}
1249*711890bcSjc156560 
1250*711890bcSjc156560 		if ((disk_attr->capacity - offset) > arraypart_attrs[i].size) {
1251*711890bcSjc156560 			arraypart_attrs[i].offset = offset;
1252*711890bcSjc156560 			arraypart_attrs[i].size = disk_attr->capacity
1253*711890bcSjc156560 				- offset;
1254*711890bcSjc156560 		}
1255*711890bcSjc156560 	}
1256*711890bcSjc156560 
1257*711890bcSjc156560 	capacity = OBJ_ATTR_NONE;
1258*711890bcSjc156560 	disk_num = 0;
1259*711890bcSjc156560 	disk_layer = 0;
1260*711890bcSjc156560 	sub_array_num = 0;
1261*711890bcSjc156560 	for (i = 0; i < num; ++i) {
1262*711890bcSjc156560 		if (disk_objs[i] == OBJ_SEPARATOR_BEGIN) {
1263*711890bcSjc156560 			++ disk_layer;
1264*711890bcSjc156560 			continue;
1265*711890bcSjc156560 		}
1266*711890bcSjc156560 		if (disk_objs[i] == OBJ_SEPARATOR_END) {
1267*711890bcSjc156560 			-- disk_layer;
1268*711890bcSjc156560 			if (disk_layer != 0)
1269*711890bcSjc156560 				++ sub_array_num;
1270*711890bcSjc156560 			continue;
1271*711890bcSjc156560 		}
1272*711890bcSjc156560 
1273*711890bcSjc156560 		if (capacity > arraypart_attrs[i].size)
1274*711890bcSjc156560 			capacity = arraypart_attrs[i].size;
1275*711890bcSjc156560 		++disk_num;
1276*711890bcSjc156560 	}
1277*711890bcSjc156560 
1278*711890bcSjc156560 	switch (raid_level) {
1279*711890bcSjc156560 	case	RAID_LEVEL_0:
1280*711890bcSjc156560 		capacity = capacity * disk_num;
1281*711890bcSjc156560 		break;
1282*711890bcSjc156560 	case	RAID_LEVEL_1:
1283*711890bcSjc156560 		capacity = capacity * disk_num / 2;
1284*711890bcSjc156560 		break;
1285*711890bcSjc156560 	case	RAID_LEVEL_1E:
1286*711890bcSjc156560 		capacity = capacity * disk_num / 2;
1287*711890bcSjc156560 		break;
1288*711890bcSjc156560 	case	RAID_LEVEL_5:
1289*711890bcSjc156560 		capacity = capacity * (disk_num - 1);
1290*711890bcSjc156560 		break;
1291*711890bcSjc156560 	case	RAID_LEVEL_10:
1292*711890bcSjc156560 		capacity = capacity * disk_num / 2;
1293*711890bcSjc156560 		break;
1294*711890bcSjc156560 	case	RAID_LEVEL_50:
1295*711890bcSjc156560 		capacity = capacity * (disk_num - sub_array_num);
1296*711890bcSjc156560 		break;
1297*711890bcSjc156560 	default:
1298*711890bcSjc156560 		return (ERR_ARRAY_LEVEL);
1299*711890bcSjc156560 		break;
1300*711890bcSjc156560 	}
1301*711890bcSjc156560 
1302*711890bcSjc156560 	return (capacity);
1303*711890bcSjc156560 }
1304*711890bcSjc156560 
1305*711890bcSjc156560 static int
1306*711890bcSjc156560 raid_dev_config(cfga_cmd_t cmd, uint32_t controller_id, uint32_t target_id,
1307*711890bcSjc156560 	uint8_t type)
1308*711890bcSjc156560 {
1309*711890bcSjc156560 	cfga_err_t cfga_err;
1310*711890bcSjc156560 	char *ap_id;
1311*711890bcSjc156560 	int count = 0;
1312*711890bcSjc156560 
1313*711890bcSjc156560 	ap_id = (char *)malloc(MAX_PATH_LEN);
1314*711890bcSjc156560 	if (ap_id == NULL)
1315*711890bcSjc156560 		return (ERR_NOMEM);
1316*711890bcSjc156560 
1317*711890bcSjc156560 	if (type == 0) {
1318*711890bcSjc156560 		(void) snprintf(ap_id, MAX_PATH_LEN, "c%d::dsk/c%dt%dd0",
1319*711890bcSjc156560 		    controller_id, controller_id, target_id);
1320*711890bcSjc156560 	} else
1321*711890bcSjc156560 		(void) snprintf(ap_id, MAX_PATH_LEN, "c%d", controller_id);
1322*711890bcSjc156560 
1323*711890bcSjc156560 	do {
1324*711890bcSjc156560 		cfga_err = config_change_state(cmd, 1, &ap_id, "disable_rcm",
1325*711890bcSjc156560 			NULL, NULL, NULL, 0);
1326*711890bcSjc156560 		count++;
1327*711890bcSjc156560 	} while (cfga_err != CFGA_OK && count < 2);
1328*711890bcSjc156560 
1329*711890bcSjc156560 	if (cfga_err != CFGA_OK) {
1330*711890bcSjc156560 		free(ap_id);
1331*711890bcSjc156560 		return (ERR_ARRAY_CONFIG);
1332*711890bcSjc156560 	}
1333*711890bcSjc156560 
1334*711890bcSjc156560 	free(ap_id);
1335*711890bcSjc156560 	return (SUCCESS);
1336*711890bcSjc156560 }
1337*711890bcSjc156560 
1338*711890bcSjc156560 static int
1339*711890bcSjc156560 raid_dev_unmounted(uint32_t controller_id, uint32_t target_id)
1340*711890bcSjc156560 {
1341*711890bcSjc156560 	struct mnttab mt;
1342*711890bcSjc156560 	FILE *f;
1343*711890bcSjc156560 	char path[MAX_PATH_LEN];
1344*711890bcSjc156560 
1345*711890bcSjc156560 	(void) snprintf(path, MAX_PATH_LEN, "c%dt%dd0",
1346*711890bcSjc156560 		controller_id, target_id);
1347*711890bcSjc156560 
1348*711890bcSjc156560 	f = fopen(MNTTAB, "r");
1349*711890bcSjc156560 
1350*711890bcSjc156560 	while (getmntent(f, &mt) != EOF)
1351*711890bcSjc156560 		if (strstr(mt.mnt_special, path) != NULL) {
1352*711890bcSjc156560 			(void) fclose(f);
1353*711890bcSjc156560 			return (ERR_ARRAY_IN_USE);
1354*711890bcSjc156560 		}
1355*711890bcSjc156560 
1356*711890bcSjc156560 	(void) fclose(f);
1357*711890bcSjc156560 	return (SUCCESS);
1358*711890bcSjc156560 }
1359*711890bcSjc156560 
1360*711890bcSjc156560 /*
1361*711890bcSjc156560  * Raid handle maintenance routines
1362*711890bcSjc156560  */
1363*711890bcSjc156560 static int
1364*711890bcSjc156560 raid_handle_init()
1365*711890bcSjc156560 {
1366*711890bcSjc156560 	int i;
1367*711890bcSjc156560 	void *ptr;
1368*711890bcSjc156560 
1369*711890bcSjc156560 	raid_handle_sys.handle_num += HANDLER_SLOTS;
1370*711890bcSjc156560 	ptr = realloc(raid_handle_sys.handles,
1371*711890bcSjc156560 		raid_handle_sys.handle_num * sizeof (handle_attr_t));
1372*711890bcSjc156560 	if (ptr == NULL)
1373*711890bcSjc156560 		return (ERR_NOMEM);
1374*711890bcSjc156560 	raid_handle_sys.handles = ptr;
1375*711890bcSjc156560 
1376*711890bcSjc156560 	/* Clean up the new allocated handles */
1377*711890bcSjc156560 	for (i = raid_handle_sys.handle_num - HANDLER_SLOTS;
1378*711890bcSjc156560 		i < raid_handle_sys.handle_num; ++i) {
1379*711890bcSjc156560 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1380*711890bcSjc156560 		raid_handle_sys.handles[i].next = i + 1;
1381*711890bcSjc156560 	}
1382*711890bcSjc156560 
1383*711890bcSjc156560 	/* For the first time of allocation, set up the system object handle */
1384*711890bcSjc156560 	if (raid_handle_sys.handle_num == HANDLER_SLOTS) {
1385*711890bcSjc156560 		raid_handle_sys.handles[0].type = OBJ_TYPE_SYSTEM;
1386*711890bcSjc156560 		raid_handle_sys.handles[0].next = 0;
1387*711890bcSjc156560 		raid_handle_sys.unused = 1;
1388*711890bcSjc156560 		raid_handle_sys.used = 0;
1389*711890bcSjc156560 	}
1390*711890bcSjc156560 	return (SUCCESS);
1391*711890bcSjc156560 }
1392*711890bcSjc156560 
1393*711890bcSjc156560 static void
1394*711890bcSjc156560 raid_handle_fini()
1395*711890bcSjc156560 {
1396*711890bcSjc156560 	raid_obj_handle_t i;
1397*711890bcSjc156560 
1398*711890bcSjc156560 	i = raid_handle_sys.used;
1399*711890bcSjc156560 
1400*711890bcSjc156560 	/* Close all opened controllers */
1401*711890bcSjc156560 	while (i != 0) {
1402*711890bcSjc156560 		if ((raid_handle_sys.handles[i].type == OBJ_TYPE_CONTROLLER) &&
1403*711890bcSjc156560 			(raid_handle_sys.handles[i].fd != 0) &&
1404*711890bcSjc156560 			(raid_handle_sys.handles[i].raid_lib != NULL))
1405*711890bcSjc156560 			raid_handle_sys.handles[i].raid_lib->close_controller(
1406*711890bcSjc156560 				raid_handle_sys.handles[i].controller_id, NULL);
1407*711890bcSjc156560 		i = raid_handle_sys.handles[i].next;
1408*711890bcSjc156560 	}
1409*711890bcSjc156560 
1410*711890bcSjc156560 	/* Clean up handle space */
1411*711890bcSjc156560 	raid_handle_sys.handle_num = 0;
1412*711890bcSjc156560 	raid_handle_sys.unused = 0;
1413*711890bcSjc156560 	raid_handle_sys.used = 0;
1414*711890bcSjc156560 	free(raid_handle_sys.handles);
1415*711890bcSjc156560 	raid_handle_sys.handles = NULL;
1416*711890bcSjc156560 }
1417*711890bcSjc156560 
1418*711890bcSjc156560 static raid_obj_handle_t
1419*711890bcSjc156560 raid_handle_new(raid_obj_type_id_t type)
1420*711890bcSjc156560 {
1421*711890bcSjc156560 	int ret;
1422*711890bcSjc156560 
1423*711890bcSjc156560 	if (raid_handle_sys.unused == raid_handle_sys.handle_num - 1) {
1424*711890bcSjc156560 		ret = raid_handle_init();
1425*711890bcSjc156560 		if (ret < SUCCESS)
1426*711890bcSjc156560 			return (ret);
1427*711890bcSjc156560 	}
1428*711890bcSjc156560 
1429*711890bcSjc156560 	ret = raid_handle_sys.unused;
1430*711890bcSjc156560 	raid_handle_sys.unused = raid_handle_sys.handles[ret].next;
1431*711890bcSjc156560 
1432*711890bcSjc156560 	raid_handle_sys.handles[ret].next = raid_handle_sys.used;
1433*711890bcSjc156560 	raid_handle_sys.used = ret;
1434*711890bcSjc156560 	raid_handle_sys.handles[ret].type = type;
1435*711890bcSjc156560 
1436*711890bcSjc156560 	return (ret);
1437*711890bcSjc156560 }
1438*711890bcSjc156560 
1439*711890bcSjc156560 static void
1440*711890bcSjc156560 raid_handle_delete(raid_obj_handle_t handle)
1441*711890bcSjc156560 {
1442*711890bcSjc156560 	int i = raid_handle_sys.used, j = 0;
1443*711890bcSjc156560 
1444*711890bcSjc156560 	if (handle == 0)
1445*711890bcSjc156560 		return;
1446*711890bcSjc156560 
1447*711890bcSjc156560 	while (i != 0 && i != handle) {
1448*711890bcSjc156560 		j = i;
1449*711890bcSjc156560 		i = raid_handle_sys.handles[i].next;
1450*711890bcSjc156560 	}
1451*711890bcSjc156560 
1452*711890bcSjc156560 	if (i == handle) {
1453*711890bcSjc156560 		if (j != 0)
1454*711890bcSjc156560 			raid_handle_sys.handles[j].next =
1455*711890bcSjc156560 				raid_handle_sys.handles[i].next;
1456*711890bcSjc156560 		else
1457*711890bcSjc156560 			raid_handle_sys.used =
1458*711890bcSjc156560 				raid_handle_sys.handles[i].next;
1459*711890bcSjc156560 
1460*711890bcSjc156560 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1461*711890bcSjc156560 		raid_handle_sys.handles[i].next =
1462*711890bcSjc156560 			raid_handle_sys.unused;
1463*711890bcSjc156560 		raid_handle_sys.unused = i;
1464*711890bcSjc156560 	}
1465*711890bcSjc156560 }
1466*711890bcSjc156560 
1467*711890bcSjc156560 static void
1468*711890bcSjc156560 raid_handle_delete_controller_comp(uint32_t controller_id)
1469*711890bcSjc156560 {
1470*711890bcSjc156560 	int i = raid_handle_sys.used, j;
1471*711890bcSjc156560 
1472*711890bcSjc156560 	while (i != 0) {
1473*711890bcSjc156560 	    j = i;
1474*711890bcSjc156560 	    i = raid_handle_sys.handles[i].next;
1475*711890bcSjc156560 	    if ((raid_handle_sys.handles[j].controller_id == controller_id) &&
1476*711890bcSjc156560 		(raid_handle_sys.handles[j].type != OBJ_TYPE_CONTROLLER))
1477*711890bcSjc156560 		raid_handle_delete(j);
1478*711890bcSjc156560 	}
1479*711890bcSjc156560 }
1480*711890bcSjc156560 
1481*711890bcSjc156560 static raid_obj_id_t
1482*711890bcSjc156560 raid_handle_to_obj(raid_obj_tab_t *raid_tab, raid_obj_handle_t handle)
1483*711890bcSjc156560 {
1484*711890bcSjc156560 	handle_attr_t *handle_attr;
1485*711890bcSjc156560 	raid_obj_id_t obj_id;
1486*711890bcSjc156560 
1487*711890bcSjc156560 	if (handle == OBJ_SYSTEM)
1488*711890bcSjc156560 		return (OBJ_SYSTEM);
1489*711890bcSjc156560 
1490*711890bcSjc156560 	handle_attr = raid_handle_sys.handles + handle;
1491*711890bcSjc156560 
1492*711890bcSjc156560 	switch (handle_attr->type) {
1493*711890bcSjc156560 	case	OBJ_TYPE_SYSTEM:
1494*711890bcSjc156560 		return (OBJ_SYSTEM);
1495*711890bcSjc156560 	case	OBJ_TYPE_CONTROLLER:
1496*711890bcSjc156560 		obj_id = obj_locate_controller(raid_tab,
1497*711890bcSjc156560 			handle_attr->controller_id);
1498*711890bcSjc156560 		break;
1499*711890bcSjc156560 	case	OBJ_TYPE_ARRAY:
1500*711890bcSjc156560 		obj_id = obj_locate_array(raid_tab,
1501*711890bcSjc156560 			handle_attr->controller_id, handle_attr->array_id);
1502*711890bcSjc156560 		break;
1503*711890bcSjc156560 	case	OBJ_TYPE_HSP:
1504*711890bcSjc156560 		obj_id = obj_locate_hsp(raid_tab,
1505*711890bcSjc156560 			handle_attr->controller_id, handle_attr->disk_id,
1506*711890bcSjc156560 			handle_attr->array_id);
1507*711890bcSjc156560 		break;
1508*711890bcSjc156560 	case	OBJ_TYPE_DISK:
1509*711890bcSjc156560 		obj_id = obj_locate_disk(raid_tab,
1510*711890bcSjc156560 			handle_attr->controller_id, handle_attr->disk_id);
1511*711890bcSjc156560 		break;
1512*711890bcSjc156560 	case	OBJ_TYPE_ARRAY_PART:
1513*711890bcSjc156560 		obj_id = obj_locate_arraypart(raid_tab,
1514*711890bcSjc156560 			handle_attr->controller_id, handle_attr->array_id,
1515*711890bcSjc156560 			handle_attr->disk_id);
1516*711890bcSjc156560 		break;
1517*711890bcSjc156560 	case	OBJ_TYPE_DISK_SEG:
1518*711890bcSjc156560 		obj_id = obj_locate_diskseg(raid_tab,
1519*711890bcSjc156560 			handle_attr->controller_id,
1520*711890bcSjc156560 			handle_attr->disk_id, handle_attr->seq_id);
1521*711890bcSjc156560 		break;
1522*711890bcSjc156560 	case	OBJ_TYPE_TASK:
1523*711890bcSjc156560 		obj_id = obj_locate_task(raid_tab,
1524*711890bcSjc156560 			handle_attr->controller_id, handle_attr->task_id);
1525*711890bcSjc156560 		break;
1526*711890bcSjc156560 	default:
1527*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
1528*711890bcSjc156560 	}
1529*711890bcSjc156560 
1530*711890bcSjc156560 	if (obj_id < OBJ_NONE)
1531*711890bcSjc156560 		return (obj_id);
1532*711890bcSjc156560 	if (obj_id == OBJ_NONE)
1533*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
1534*711890bcSjc156560 
1535*711890bcSjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
1536*711890bcSjc156560 	return (obj_id);
1537*711890bcSjc156560 }
1538*711890bcSjc156560 
1539*711890bcSjc156560 static raid_obj_handle_t
1540*711890bcSjc156560 raid_obj_to_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1541*711890bcSjc156560 {
1542*711890bcSjc156560 	raid_obj_id_t obj_id_backup = obj_id;
1543*711890bcSjc156560 	raid_obj_type_id_t type;
1544*711890bcSjc156560 	raid_obj_handle_t handle;
1545*711890bcSjc156560 	controller_attr_t *controller_attr;
1546*711890bcSjc156560 	array_attr_t *array_attr;
1547*711890bcSjc156560 	hsp_attr_t *hsp_attr;
1548*711890bcSjc156560 	disk_attr_t *disk_attr;
1549*711890bcSjc156560 	arraypart_attr_t *arraypart_attr;
1550*711890bcSjc156560 	diskseg_attr_t *diskseg_attr;
1551*711890bcSjc156560 	task_attr_t *task_attr;
1552*711890bcSjc156560 
1553*711890bcSjc156560 	if (obj_id == OBJ_SYSTEM)
1554*711890bcSjc156560 		return (OBJ_SYSTEM);
1555*711890bcSjc156560 
1556*711890bcSjc156560 	/* If the object mapped by a handle */
1557*711890bcSjc156560 	handle = raid_obj_get_handle(raid_tab, obj_id);
1558*711890bcSjc156560 	if (handle != 0)
1559*711890bcSjc156560 		return (handle);
1560*711890bcSjc156560 
1561*711890bcSjc156560 	/* Search for existing handles */
1562*711890bcSjc156560 	for (handle = raid_handle_sys.used; handle != 0;
1563*711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next)
1564*711890bcSjc156560 		if (raid_handle_to_obj(raid_tab, handle) == obj_id)
1565*711890bcSjc156560 			break;
1566*711890bcSjc156560 
1567*711890bcSjc156560 	if (handle != 0)
1568*711890bcSjc156560 		return (handle);
1569*711890bcSjc156560 
1570*711890bcSjc156560 	/* Allocate new handle for this object */
1571*711890bcSjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
1572*711890bcSjc156560 	handle = raid_handle_new(type);
1573*711890bcSjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
1574*711890bcSjc156560 	raid_handle_sys.handles[handle].type = type;
1575*711890bcSjc156560 
1576*711890bcSjc156560 	switch (type) {
1577*711890bcSjc156560 	case OBJ_TYPE_SYSTEM:
1578*711890bcSjc156560 		break;
1579*711890bcSjc156560 	case OBJ_TYPE_CONTROLLER:
1580*711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1581*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1582*711890bcSjc156560 			controller_attr->controller_id;
1583*711890bcSjc156560 		break;
1584*711890bcSjc156560 	case OBJ_TYPE_ARRAY:
1585*711890bcSjc156560 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1586*711890bcSjc156560 		raid_handle_sys.handles[handle].array_id = array_attr->array_id;
1587*711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1588*711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1589*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1590*711890bcSjc156560 			controller_attr->controller_id;
1591*711890bcSjc156560 		break;
1592*711890bcSjc156560 	case OBJ_TYPE_HSP:
1593*711890bcSjc156560 		hsp_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1594*711890bcSjc156560 		raid_handle_sys.handles[handle].array_id =
1595*711890bcSjc156560 			hsp_attr->associated_id;
1596*711890bcSjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1597*711890bcSjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1598*711890bcSjc156560 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1599*711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1600*711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1601*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1602*711890bcSjc156560 			controller_attr->controller_id;
1603*711890bcSjc156560 		break;
1604*711890bcSjc156560 	case OBJ_TYPE_DISK:
1605*711890bcSjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1606*711890bcSjc156560 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1607*711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1608*711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1609*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1610*711890bcSjc156560 			controller_attr->controller_id;
1611*711890bcSjc156560 		break;
1612*711890bcSjc156560 	case OBJ_TYPE_ARRAY_PART:
1613*711890bcSjc156560 		arraypart_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1614*711890bcSjc156560 		raid_handle_sys.handles[handle].disk_id =
1615*711890bcSjc156560 			arraypart_attr->disk_id;
1616*711890bcSjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1617*711890bcSjc156560 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1618*711890bcSjc156560 		raid_handle_sys.handles[handle].array_id =
1619*711890bcSjc156560 			array_attr->array_id;
1620*711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1621*711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1622*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1623*711890bcSjc156560 			controller_attr->controller_id;
1624*711890bcSjc156560 		break;
1625*711890bcSjc156560 	case OBJ_TYPE_DISK_SEG:
1626*711890bcSjc156560 		diskseg_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1627*711890bcSjc156560 		raid_handle_sys.handles[handle].seq_id = diskseg_attr->seq_no;
1628*711890bcSjc156560 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1629*711890bcSjc156560 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1630*711890bcSjc156560 		raid_handle_sys.handles[handle].disk_id =
1631*711890bcSjc156560 				disk_attr->disk_id;
1632*711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1633*711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1634*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1635*711890bcSjc156560 			controller_attr->controller_id;
1636*711890bcSjc156560 		break;
1637*711890bcSjc156560 	case OBJ_TYPE_TASK:
1638*711890bcSjc156560 		task_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1639*711890bcSjc156560 		raid_handle_sys.handles[handle].task_id = task_attr->task_id;
1640*711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, obj_id);
1641*711890bcSjc156560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1642*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id =
1643*711890bcSjc156560 			controller_attr->controller_id;
1644*711890bcSjc156560 		break;
1645*711890bcSjc156560 	default:
1646*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
1647*711890bcSjc156560 	}
1648*711890bcSjc156560 
1649*711890bcSjc156560 	(void) raid_obj_set_handle(raid_tab, obj_id_backup, handle);
1650*711890bcSjc156560 	return (handle);
1651*711890bcSjc156560 }
1652*711890bcSjc156560 
1653*711890bcSjc156560 static raid_lib_t *
1654*711890bcSjc156560 raid_obj_get_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1655*711890bcSjc156560 {
1656*711890bcSjc156560 	raid_obj_handle_t handle;
1657*711890bcSjc156560 	controller_attr_t *attr;
1658*711890bcSjc156560 
1659*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1660*711890bcSjc156560 		return (NULL);
1661*711890bcSjc156560 
1662*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1663*711890bcSjc156560 	handle = raid_handle_sys.used;
1664*711890bcSjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1665*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id !=
1666*711890bcSjc156560 		attr->controller_id)
1667*711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next;
1668*711890bcSjc156560 
1669*711890bcSjc156560 	if (handle == 0)
1670*711890bcSjc156560 		return (NULL);
1671*711890bcSjc156560 
1672*711890bcSjc156560 	return (raid_handle_sys.handles[handle].raid_lib);
1673*711890bcSjc156560 }
1674*711890bcSjc156560 
1675*711890bcSjc156560 static int
1676*711890bcSjc156560 raid_obj_set_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1677*711890bcSjc156560 	raid_lib_t *raid_lib)
1678*711890bcSjc156560 {
1679*711890bcSjc156560 	raid_obj_handle_t handle;
1680*711890bcSjc156560 	controller_attr_t *attr;
1681*711890bcSjc156560 
1682*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1683*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
1684*711890bcSjc156560 
1685*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1686*711890bcSjc156560 	handle = raid_handle_sys.used;
1687*711890bcSjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1688*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id !=
1689*711890bcSjc156560 		attr->controller_id)
1690*711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next;
1691*711890bcSjc156560 
1692*711890bcSjc156560 	if (handle == 0)
1693*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
1694*711890bcSjc156560 
1695*711890bcSjc156560 	raid_handle_sys.handles[handle].raid_lib = raid_lib;
1696*711890bcSjc156560 	return (SUCCESS);
1697*711890bcSjc156560 }
1698*711890bcSjc156560 
1699*711890bcSjc156560 static int
1700*711890bcSjc156560 raid_obj_get_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1701*711890bcSjc156560 {
1702*711890bcSjc156560 	raid_obj_handle_t handle;
1703*711890bcSjc156560 	controller_attr_t *attr;
1704*711890bcSjc156560 
1705*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1706*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
1707*711890bcSjc156560 
1708*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1709*711890bcSjc156560 	handle = raid_handle_sys.used;
1710*711890bcSjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1711*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id !=
1712*711890bcSjc156560 		attr->controller_id)
1713*711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next;
1714*711890bcSjc156560 
1715*711890bcSjc156560 	if (handle == 0)
1716*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
1717*711890bcSjc156560 
1718*711890bcSjc156560 	return (raid_handle_sys.handles[handle].fd);
1719*711890bcSjc156560 }
1720*711890bcSjc156560 
1721*711890bcSjc156560 static int
1722*711890bcSjc156560 raid_obj_set_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, int fd)
1723*711890bcSjc156560 {
1724*711890bcSjc156560 	raid_obj_handle_t handle;
1725*711890bcSjc156560 	controller_attr_t *attr;
1726*711890bcSjc156560 
1727*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1728*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
1729*711890bcSjc156560 
1730*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1731*711890bcSjc156560 	handle = raid_handle_sys.used;
1732*711890bcSjc156560 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1733*711890bcSjc156560 		raid_handle_sys.handles[handle].controller_id !=
1734*711890bcSjc156560 		attr->controller_id)
1735*711890bcSjc156560 		handle = raid_handle_sys.handles[handle].next;
1736*711890bcSjc156560 
1737*711890bcSjc156560 	if (handle == 0)
1738*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
1739*711890bcSjc156560 
1740*711890bcSjc156560 	raid_handle_sys.handles[handle].fd = fd;
1741*711890bcSjc156560 	return (SUCCESS);
1742*711890bcSjc156560 }
1743*711890bcSjc156560 
1744*711890bcSjc156560 /*
1745*711890bcSjc156560  * Raid object maintenance routines
1746*711890bcSjc156560  */
1747*711890bcSjc156560 static int
1748*711890bcSjc156560 obj_scan_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1749*711890bcSjc156560 {
1750*711890bcSjc156560 	raid_obj_status_t status;
1751*711890bcSjc156560 	raid_obj_type_id_t type;
1752*711890bcSjc156560 	int ret, i, obj_type_cnt, comp_num;
1753*711890bcSjc156560 	raid_obj_id_t *comp_list;
1754*711890bcSjc156560 
1755*711890bcSjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
1756*711890bcSjc156560 	if (status < SUCCESS)
1757*711890bcSjc156560 		return (status);
1758*711890bcSjc156560 
1759*711890bcSjc156560 	if (status & OBJ_STATUS_SCANCOMP)
1760*711890bcSjc156560 		return (SUCCESS);
1761*711890bcSjc156560 
1762*711890bcSjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
1763*711890bcSjc156560 	if (type < OBJ_TYPE_SYSTEM || type > OBJ_TYPE_ALL)
1764*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
1765*711890bcSjc156560 
1766*711890bcSjc156560 	for (obj_type_cnt = OBJ_SYSTEM; obj_type_cnt < OBJ_TYPE_ALL;
1767*711890bcSjc156560 		++obj_type_cnt) {
1768*711890bcSjc156560 		if (raid_obj_op_sys[type].compnum != NULL)
1769*711890bcSjc156560 			comp_num = raid_obj_op_sys[type].compnum(
1770*711890bcSjc156560 				raid_tab, obj_id, obj_type_cnt);
1771*711890bcSjc156560 		else
1772*711890bcSjc156560 			comp_num = 0;
1773*711890bcSjc156560 
1774*711890bcSjc156560 		if (comp_num < SUCCESS)
1775*711890bcSjc156560 			return (comp_num);
1776*711890bcSjc156560 		if (comp_num == 0)
1777*711890bcSjc156560 			continue;
1778*711890bcSjc156560 
1779*711890bcSjc156560 		comp_list = calloc(comp_num, sizeof (raid_obj_id_t));
1780*711890bcSjc156560 		if (comp_list == NULL)
1781*711890bcSjc156560 			return (ERR_NOMEM);
1782*711890bcSjc156560 
1783*711890bcSjc156560 		for (i = 0; i < comp_num; ++i) {
1784*711890bcSjc156560 			*(comp_list + i) = raid_obj_create(raid_tab,
1785*711890bcSjc156560 				obj_type_cnt);
1786*711890bcSjc156560 			if (*(comp_list + i) < SUCCESS) {
1787*711890bcSjc156560 				ret = *(comp_list + i);
1788*711890bcSjc156560 				free(comp_list);
1789*711890bcSjc156560 				return (ret);
1790*711890bcSjc156560 			}
1791*711890bcSjc156560 
1792*711890bcSjc156560 			(void) raid_obj_clear_status(raid_tab,
1793*711890bcSjc156560 				*(comp_list + i), OBJ_STATUS_CMD_CLEAN);
1794*711890bcSjc156560 			(void) raid_obj_add_org(raid_tab, *(comp_list + i),
1795*711890bcSjc156560 				obj_id);
1796*711890bcSjc156560 		}
1797*711890bcSjc156560 
1798*711890bcSjc156560 		if (raid_obj_op_sys[type].complist != NULL)
1799*711890bcSjc156560 			raid_obj_op_sys[type].complist(raid_tab,
1800*711890bcSjc156560 				obj_id, comp_num, comp_list, obj_type_cnt);
1801*711890bcSjc156560 		free(comp_list);
1802*711890bcSjc156560 	}
1803*711890bcSjc156560 
1804*711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_SCANCOMP);
1805*711890bcSjc156560 	return (SUCCESS);
1806*711890bcSjc156560 }
1807*711890bcSjc156560 
1808*711890bcSjc156560 static int
1809*711890bcSjc156560 obj_rescan(raid_obj_tab_t *raid_tab)
1810*711890bcSjc156560 {
1811*711890bcSjc156560 	int ret;
1812*711890bcSjc156560 
1813*711890bcSjc156560 	raid_obj_tab_destroy(raid_tab);
1814*711890bcSjc156560 
1815*711890bcSjc156560 	if (raid_obj_tab_create(raid_tab, HASH_SLOTS) != SUCCESS)
1816*711890bcSjc156560 		return (ERR_NOMEM);
1817*711890bcSjc156560 
1818*711890bcSjc156560 	if ((ret = raid_obj_create_system_obj(raid_tab)) != SUCCESS) {
1819*711890bcSjc156560 		raid_obj_tab_destroy(raid_tab);
1820*711890bcSjc156560 		return (ret);
1821*711890bcSjc156560 	}
1822*711890bcSjc156560 
1823*711890bcSjc156560 	return (SUCCESS);
1824*711890bcSjc156560 }
1825*711890bcSjc156560 
1826*711890bcSjc156560 static raid_obj_id_t
1827*711890bcSjc156560 obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1828*711890bcSjc156560 	raid_obj_type_id_t obj_type)
1829*711890bcSjc156560 {
1830*711890bcSjc156560 	raid_obj_id_t id;
1831*711890bcSjc156560 	raid_obj_type_id_t type;
1832*711890bcSjc156560 	raid_obj_status_t status;
1833*711890bcSjc156560 	int ret;
1834*711890bcSjc156560 
1835*711890bcSjc156560 	if ((obj_type < OBJ_TYPE_SYSTEM) || (obj_type > OBJ_TYPE_ALL))
1836*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
1837*711890bcSjc156560 
1838*711890bcSjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
1839*711890bcSjc156560 	if (status < SUCCESS)
1840*711890bcSjc156560 		return (status);
1841*711890bcSjc156560 
1842*711890bcSjc156560 	if (!(status & OBJ_STATUS_SCANCOMP)) {
1843*711890bcSjc156560 		ret = obj_scan_comp(raid_tab, obj_id);
1844*711890bcSjc156560 		if (ret < SUCCESS)
1845*711890bcSjc156560 			return (ret);
1846*711890bcSjc156560 	}
1847*711890bcSjc156560 
1848*711890bcSjc156560 	id = raid_obj_get_comp(raid_tab, obj_id);
1849*711890bcSjc156560 	if (id <= OBJ_NONE)
1850*711890bcSjc156560 		return (id);
1851*711890bcSjc156560 
1852*711890bcSjc156560 	type = raid_obj_get_type(raid_tab, id);
1853*711890bcSjc156560 	if (type < OBJ_TYPE_SYSTEM)
1854*711890bcSjc156560 		return (type);
1855*711890bcSjc156560 
1856*711890bcSjc156560 	if (type == obj_type)
1857*711890bcSjc156560 		return (id);
1858*711890bcSjc156560 
1859*711890bcSjc156560 	while (id > OBJ_NONE) {
1860*711890bcSjc156560 		id = raid_obj_get_sibling(raid_tab, id);
1861*711890bcSjc156560 		if (id <= OBJ_NONE)
1862*711890bcSjc156560 			return (id);
1863*711890bcSjc156560 
1864*711890bcSjc156560 		type = raid_obj_get_type(raid_tab, id);
1865*711890bcSjc156560 		if (type < OBJ_TYPE_SYSTEM)
1866*711890bcSjc156560 			return (type);
1867*711890bcSjc156560 
1868*711890bcSjc156560 		if (type == obj_type)
1869*711890bcSjc156560 			break;
1870*711890bcSjc156560 	};
1871*711890bcSjc156560 
1872*711890bcSjc156560 	return (id);
1873*711890bcSjc156560 }
1874*711890bcSjc156560 
1875*711890bcSjc156560 static raid_obj_id_t
1876*711890bcSjc156560 obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1877*711890bcSjc156560 {
1878*711890bcSjc156560 	raid_obj_id_t id;
1879*711890bcSjc156560 	raid_obj_type_id_t type, obj_type;
1880*711890bcSjc156560 
1881*711890bcSjc156560 	id = obj_id;
1882*711890bcSjc156560 	obj_type = raid_obj_get_type(raid_tab, id);
1883*711890bcSjc156560 	if (obj_type < OBJ_TYPE_SYSTEM)
1884*711890bcSjc156560 		return (obj_type);
1885*711890bcSjc156560 
1886*711890bcSjc156560 	do {
1887*711890bcSjc156560 		id = raid_obj_get_sibling(raid_tab, id);
1888*711890bcSjc156560 		if (id < OBJ_NONE)
1889*711890bcSjc156560 			return (id);
1890*711890bcSjc156560 
1891*711890bcSjc156560 		type = raid_obj_get_type(raid_tab, id);
1892*711890bcSjc156560 		if (type < OBJ_TYPE_SYSTEM)
1893*711890bcSjc156560 			return (type);
1894*711890bcSjc156560 	} while ((type != obj_type) && (id != OBJ_NONE));
1895*711890bcSjc156560 
1896*711890bcSjc156560 	return (id);
1897*711890bcSjc156560 }
1898*711890bcSjc156560 
1899*711890bcSjc156560 static int
1900*711890bcSjc156560 obj_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, void **data)
1901*711890bcSjc156560 {
1902*711890bcSjc156560 	raid_obj_type_id_t type;
1903*711890bcSjc156560 	raid_obj_status_t status;
1904*711890bcSjc156560 	void *attr;
1905*711890bcSjc156560 	int ret = SUCCESS;
1906*711890bcSjc156560 
1907*711890bcSjc156560 	status = raid_obj_get_status(raid_tab, obj_id);
1908*711890bcSjc156560 	if (status < SUCCESS)
1909*711890bcSjc156560 		return (status);
1910*711890bcSjc156560 
1911*711890bcSjc156560 	type = raid_obj_get_type(raid_tab, obj_id);
1912*711890bcSjc156560 	if (type < OBJ_TYPE_SYSTEM)
1913*711890bcSjc156560 		return (type);
1914*711890bcSjc156560 
1915*711890bcSjc156560 	if (!(status & OBJ_STATUS_OPENED)) {
1916*711890bcSjc156560 		if (raid_obj_op_sys[type].get_attr == NULL)
1917*711890bcSjc156560 			(void) raid_obj_set_status(raid_tab, obj_id,
1918*711890bcSjc156560 				OBJ_STATUS_OPENED);
1919*711890bcSjc156560 		else
1920*711890bcSjc156560 			ret = raid_obj_op_sys[type].get_attr(raid_tab, obj_id);
1921*711890bcSjc156560 	}
1922*711890bcSjc156560 	if (ret < SUCCESS)
1923*711890bcSjc156560 		return (ret);
1924*711890bcSjc156560 
1925*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1926*711890bcSjc156560 	if (attr == NULL && type != OBJ_TYPE_SYSTEM)
1927*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
1928*711890bcSjc156560 
1929*711890bcSjc156560 	*data = attr;
1930*711890bcSjc156560 	return (SUCCESS);
1931*711890bcSjc156560 }
1932*711890bcSjc156560 
1933*711890bcSjc156560 static raid_obj_id_t
1934*711890bcSjc156560 obj_locate_controller(raid_obj_tab_t *raid_tab, uint32_t controller_id)
1935*711890bcSjc156560 {
1936*711890bcSjc156560 	raid_obj_id_t obj_id;
1937*711890bcSjc156560 	controller_attr_t *attr;
1938*711890bcSjc156560 
1939*711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
1940*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
1941*711890bcSjc156560 		return (obj_id);
1942*711890bcSjc156560 
1943*711890bcSjc156560 	do {
1944*711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1945*711890bcSjc156560 		if (attr == NULL)
1946*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
1947*711890bcSjc156560 
1948*711890bcSjc156560 		if (attr->controller_id == controller_id)
1949*711890bcSjc156560 			break;
1950*711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) != OBJ_NONE);
1951*711890bcSjc156560 
1952*711890bcSjc156560 	return (obj_id);
1953*711890bcSjc156560 }
1954*711890bcSjc156560 
1955*711890bcSjc156560 static raid_obj_id_t
1956*711890bcSjc156560 obj_locate_array(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1957*711890bcSjc156560 	uint32_t array_id)
1958*711890bcSjc156560 {
1959*711890bcSjc156560 	raid_obj_id_t obj_id;
1960*711890bcSjc156560 
1961*711890bcSjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
1962*711890bcSjc156560 	if (obj_id < OBJ_NONE)
1963*711890bcSjc156560 		return (obj_id);
1964*711890bcSjc156560 
1965*711890bcSjc156560 	obj_id = obj_locate_array_recur(raid_tab, obj_id, array_id);
1966*711890bcSjc156560 
1967*711890bcSjc156560 	return (obj_id);
1968*711890bcSjc156560 }
1969*711890bcSjc156560 
1970*711890bcSjc156560 static raid_obj_id_t
1971*711890bcSjc156560 obj_locate_array_recur(raid_obj_tab_t *raid_tab,
1972*711890bcSjc156560 	raid_obj_id_t container_obj_id, uint32_t array_id)
1973*711890bcSjc156560 {
1974*711890bcSjc156560 	raid_obj_id_t obj_id, ret;
1975*711890bcSjc156560 	array_attr_t *attr;
1976*711890bcSjc156560 
1977*711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, container_obj_id, OBJ_TYPE_ARRAY);
1978*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
1979*711890bcSjc156560 		return (obj_id);
1980*711890bcSjc156560 
1981*711890bcSjc156560 	do {
1982*711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1983*711890bcSjc156560 		if (attr == NULL)
1984*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
1985*711890bcSjc156560 
1986*711890bcSjc156560 		if (attr->array_id == array_id)
1987*711890bcSjc156560 			break;
1988*711890bcSjc156560 
1989*711890bcSjc156560 		ret = obj_locate_array_recur(raid_tab, obj_id, array_id);
1990*711890bcSjc156560 		if (ret != OBJ_NONE)
1991*711890bcSjc156560 			return (ret);
1992*711890bcSjc156560 
1993*711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
1994*711890bcSjc156560 
1995*711890bcSjc156560 	return (obj_id);
1996*711890bcSjc156560 }
1997*711890bcSjc156560 
1998*711890bcSjc156560 static raid_obj_id_t
1999*711890bcSjc156560 obj_locate_hsp(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2000*711890bcSjc156560 	uint32_t disk_id, uint32_t array_id)
2001*711890bcSjc156560 {
2002*711890bcSjc156560 	raid_obj_id_t obj_id;
2003*711890bcSjc156560 	hsp_attr_t *hsp_attr;
2004*711890bcSjc156560 
2005*711890bcSjc156560 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2006*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2007*711890bcSjc156560 		return (obj_id);
2008*711890bcSjc156560 
2009*711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_HSP);
2010*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2011*711890bcSjc156560 		return (obj_id);
2012*711890bcSjc156560 
2013*711890bcSjc156560 	do {
2014*711890bcSjc156560 		(void) obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
2015*711890bcSjc156560 		if (hsp_attr->associated_id == array_id)
2016*711890bcSjc156560 			break;
2017*711890bcSjc156560 
2018*711890bcSjc156560 		obj_id = obj_get_sibling(raid_tab, obj_id);
2019*711890bcSjc156560 		if (obj_id < OBJ_NONE)
2020*711890bcSjc156560 			return (obj_id);
2021*711890bcSjc156560 	} while (obj_id > OBJ_NONE);
2022*711890bcSjc156560 
2023*711890bcSjc156560 	return (obj_id);
2024*711890bcSjc156560 }
2025*711890bcSjc156560 
2026*711890bcSjc156560 static raid_obj_id_t
2027*711890bcSjc156560 obj_locate_disk(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2028*711890bcSjc156560 	uint32_t disk_id)
2029*711890bcSjc156560 {
2030*711890bcSjc156560 	raid_obj_id_t obj_id;
2031*711890bcSjc156560 	disk_attr_t *attr;
2032*711890bcSjc156560 
2033*711890bcSjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
2034*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2035*711890bcSjc156560 		return (obj_id);
2036*711890bcSjc156560 
2037*711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2038*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2039*711890bcSjc156560 		return (obj_id);
2040*711890bcSjc156560 
2041*711890bcSjc156560 	do {
2042*711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2043*711890bcSjc156560 		if (attr == NULL)
2044*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2045*711890bcSjc156560 
2046*711890bcSjc156560 		if (attr->disk_id == disk_id)
2047*711890bcSjc156560 			break;
2048*711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2049*711890bcSjc156560 
2050*711890bcSjc156560 	return (obj_id);
2051*711890bcSjc156560 }
2052*711890bcSjc156560 
2053*711890bcSjc156560 static raid_obj_id_t
2054*711890bcSjc156560 obj_locate_arraypart(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2055*711890bcSjc156560 	uint32_t array_id, uint32_t disk_id)
2056*711890bcSjc156560 {
2057*711890bcSjc156560 	raid_obj_id_t obj_id;
2058*711890bcSjc156560 
2059*711890bcSjc156560 	arraypart_attr_t *attr;
2060*711890bcSjc156560 
2061*711890bcSjc156560 	obj_id = obj_locate_array(raid_tab, controller_id, array_id);
2062*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2063*711890bcSjc156560 		return (obj_id);
2064*711890bcSjc156560 
2065*711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY_PART);
2066*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2067*711890bcSjc156560 		return (obj_id);
2068*711890bcSjc156560 
2069*711890bcSjc156560 	do {
2070*711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2071*711890bcSjc156560 		if (attr == NULL)
2072*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2073*711890bcSjc156560 
2074*711890bcSjc156560 		if (attr->disk_id == disk_id)
2075*711890bcSjc156560 			break;
2076*711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) >
2077*711890bcSjc156560 		OBJ_NONE);
2078*711890bcSjc156560 
2079*711890bcSjc156560 	return (obj_id);
2080*711890bcSjc156560 }
2081*711890bcSjc156560 
2082*711890bcSjc156560 static raid_obj_id_t
2083*711890bcSjc156560 obj_locate_diskseg(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2084*711890bcSjc156560 	uint32_t disk_id, uint32_t seq_no)
2085*711890bcSjc156560 {
2086*711890bcSjc156560 	raid_obj_id_t obj_id;
2087*711890bcSjc156560 	diskseg_attr_t *attr;
2088*711890bcSjc156560 
2089*711890bcSjc156560 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2090*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2091*711890bcSjc156560 		return (obj_id);
2092*711890bcSjc156560 
2093*711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK_SEG);
2094*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2095*711890bcSjc156560 		return (obj_id);
2096*711890bcSjc156560 
2097*711890bcSjc156560 	do {
2098*711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2099*711890bcSjc156560 		if (attr == NULL)
2100*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2101*711890bcSjc156560 
2102*711890bcSjc156560 		if (attr->seq_no == seq_no)
2103*711890bcSjc156560 			break;
2104*711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2105*711890bcSjc156560 
2106*711890bcSjc156560 	return (obj_id);
2107*711890bcSjc156560 }
2108*711890bcSjc156560 
2109*711890bcSjc156560 static raid_obj_id_t
2110*711890bcSjc156560 obj_locate_task(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2111*711890bcSjc156560 	uint32_t task_id)
2112*711890bcSjc156560 {
2113*711890bcSjc156560 	raid_obj_id_t obj_id, obj_id2, task_obj_id;
2114*711890bcSjc156560 	task_attr_t *attr;
2115*711890bcSjc156560 
2116*711890bcSjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
2117*711890bcSjc156560 	if (obj_id <= OBJ_NONE)
2118*711890bcSjc156560 		return (obj_id);
2119*711890bcSjc156560 
2120*711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2121*711890bcSjc156560 	if (obj_id < OBJ_NONE)
2122*711890bcSjc156560 		return (obj_id);
2123*711890bcSjc156560 
2124*711890bcSjc156560 	do {
2125*711890bcSjc156560 		obj_id2 = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2126*711890bcSjc156560 		while (obj_id2 != OBJ_NONE) {
2127*711890bcSjc156560 			task_obj_id = obj_get_comp(raid_tab, obj_id2,
2128*711890bcSjc156560 				OBJ_TYPE_TASK);
2129*711890bcSjc156560 
2130*711890bcSjc156560 			if (task_obj_id < OBJ_NONE)
2131*711890bcSjc156560 				return (task_obj_id);
2132*711890bcSjc156560 
2133*711890bcSjc156560 			if (task_obj_id == OBJ_NONE) {
2134*711890bcSjc156560 				obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2135*711890bcSjc156560 				continue;
2136*711890bcSjc156560 			}
2137*711890bcSjc156560 
2138*711890bcSjc156560 			attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2139*711890bcSjc156560 			if (attr == NULL)
2140*711890bcSjc156560 				return (ERR_DEVICE_INVALID);
2141*711890bcSjc156560 
2142*711890bcSjc156560 			if (attr->task_id == task_id)
2143*711890bcSjc156560 				return (task_obj_id);
2144*711890bcSjc156560 
2145*711890bcSjc156560 			obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2146*711890bcSjc156560 		}
2147*711890bcSjc156560 
2148*711890bcSjc156560 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2149*711890bcSjc156560 		if (task_obj_id < OBJ_NONE)
2150*711890bcSjc156560 			return (task_obj_id);
2151*711890bcSjc156560 
2152*711890bcSjc156560 		if (task_obj_id == OBJ_NONE)
2153*711890bcSjc156560 			continue;
2154*711890bcSjc156560 
2155*711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2156*711890bcSjc156560 		if (attr == NULL)
2157*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2158*711890bcSjc156560 
2159*711890bcSjc156560 		if (attr->task_id == task_id)
2160*711890bcSjc156560 			return (task_obj_id);
2161*711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2162*711890bcSjc156560 
2163*711890bcSjc156560 	if (obj_id < OBJ_NONE)
2164*711890bcSjc156560 		return (obj_id);
2165*711890bcSjc156560 
2166*711890bcSjc156560 	obj_id = obj_locate_controller(raid_tab, controller_id);
2167*711890bcSjc156560 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2168*711890bcSjc156560 	if (obj_id < OBJ_NONE)
2169*711890bcSjc156560 		return (obj_id);
2170*711890bcSjc156560 
2171*711890bcSjc156560 	do {
2172*711890bcSjc156560 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2173*711890bcSjc156560 		if (task_obj_id < OBJ_NONE)
2174*711890bcSjc156560 			return (task_obj_id);
2175*711890bcSjc156560 
2176*711890bcSjc156560 		if (task_obj_id == OBJ_NONE)
2177*711890bcSjc156560 			continue;
2178*711890bcSjc156560 
2179*711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2180*711890bcSjc156560 		if (attr == NULL)
2181*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2182*711890bcSjc156560 
2183*711890bcSjc156560 		if (attr->task_id == task_id)
2184*711890bcSjc156560 			return (task_obj_id);
2185*711890bcSjc156560 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2186*711890bcSjc156560 
2187*711890bcSjc156560 	return (obj_id);
2188*711890bcSjc156560 
2189*711890bcSjc156560 }
2190*711890bcSjc156560 
2191*711890bcSjc156560 static raid_obj_id_t
2192*711890bcSjc156560 obj_get_controller(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2193*711890bcSjc156560 {
2194*711890bcSjc156560 	raid_obj_id_t id = obj_id;
2195*711890bcSjc156560 
2196*711890bcSjc156560 	while (raid_obj_get_type(raid_tab, id) != OBJ_TYPE_CONTROLLER) {
2197*711890bcSjc156560 		id = raid_obj_get_container(raid_tab, id);
2198*711890bcSjc156560 		if ((id == OBJ_SYSTEM) || (id < OBJ_NONE))
2199*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2200*711890bcSjc156560 	}
2201*711890bcSjc156560 
2202*711890bcSjc156560 	return (id);
2203*711890bcSjc156560 }
2204*711890bcSjc156560 
2205*711890bcSjc156560 /*
2206*711890bcSjc156560  * Raid object operation routines
2207*711890bcSjc156560  */
2208*711890bcSjc156560 static int
2209*711890bcSjc156560 obj_sys_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2210*711890bcSjc156560 	raid_obj_type_id_t comp_type)
2211*711890bcSjc156560 {
2212*711890bcSjc156560 	DIR *dir;
2213*711890bcSjc156560 	struct dirent *dp;
2214*711890bcSjc156560 	int num = 0;
2215*711890bcSjc156560 
2216*711890bcSjc156560 	if ((raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM))
2217*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2218*711890bcSjc156560 
2219*711890bcSjc156560 	if (comp_type != OBJ_TYPE_CONTROLLER)
2220*711890bcSjc156560 		return (0);
2221*711890bcSjc156560 
2222*711890bcSjc156560 	if ((dir = opendir(CFGDIR)) == NULL)
2223*711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
2224*711890bcSjc156560 
2225*711890bcSjc156560 	while ((dp = readdir(dir)) != NULL) {
2226*711890bcSjc156560 		uint32_t controller_id;
2227*711890bcSjc156560 		char path[MAX_PATH_LEN];
2228*711890bcSjc156560 
2229*711890bcSjc156560 		if (strcmp(dp->d_name, ".") == 0 ||
2230*711890bcSjc156560 			strcmp(dp->d_name, "..") == 0)
2231*711890bcSjc156560 			continue;
2232*711890bcSjc156560 
2233*711890bcSjc156560 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2234*711890bcSjc156560 			continue;
2235*711890bcSjc156560 
2236*711890bcSjc156560 		if (controller_id_to_path(controller_id, path) == SUCCESS)
2237*711890bcSjc156560 			++ num;
2238*711890bcSjc156560 	}
2239*711890bcSjc156560 
2240*711890bcSjc156560 	(void) closedir(dir);
2241*711890bcSjc156560 	return (num);
2242*711890bcSjc156560 }
2243*711890bcSjc156560 
2244*711890bcSjc156560 static int
2245*711890bcSjc156560 obj_sys_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2246*711890bcSjc156560 	int num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2247*711890bcSjc156560 {
2248*711890bcSjc156560 	DIR *dir;
2249*711890bcSjc156560 	struct dirent *dp;
2250*711890bcSjc156560 	controller_attr_t *attr;
2251*711890bcSjc156560 	uint32_t controller_id;
2252*711890bcSjc156560 	uint32_t *tmplist;
2253*711890bcSjc156560 	char path[MAX_PATH_LEN];
2254*711890bcSjc156560 	int i = 0;
2255*711890bcSjc156560 
2256*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM)
2257*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2258*711890bcSjc156560 	if ((num <= 0) || (comp_list == NULL))
2259*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2260*711890bcSjc156560 
2261*711890bcSjc156560 	if (comp_type != OBJ_TYPE_CONTROLLER)
2262*711890bcSjc156560 		return (0);
2263*711890bcSjc156560 
2264*711890bcSjc156560 	if ((dir = opendir(CFGDIR)) == NULL)
2265*711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
2266*711890bcSjc156560 	tmplist = calloc(num, sizeof (uint32_t));
2267*711890bcSjc156560 	if (tmplist == NULL) {
2268*711890bcSjc156560 		return (ERR_NOMEM);
2269*711890bcSjc156560 	}
2270*711890bcSjc156560 	while ((dp = readdir(dir)) != NULL) {
2271*711890bcSjc156560 		if (strcmp(dp->d_name, ".") == 0 ||
2272*711890bcSjc156560 			strcmp(dp->d_name, "..") == 0)
2273*711890bcSjc156560 			continue;
2274*711890bcSjc156560 
2275*711890bcSjc156560 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2276*711890bcSjc156560 			continue;
2277*711890bcSjc156560 
2278*711890bcSjc156560 		if (controller_id_to_path(controller_id, path) == SUCCESS) {
2279*711890bcSjc156560 			tmplist[i] = controller_id;
2280*711890bcSjc156560 			++ i;
2281*711890bcSjc156560 		}
2282*711890bcSjc156560 	}
2283*711890bcSjc156560 	qsort((void *)tmplist, num, sizeof (uint32_t), intcompare);
2284*711890bcSjc156560 	for (i = 0; i < num; i++) {
2285*711890bcSjc156560 		attr = raid_obj_get_data_ptr(raid_tab,
2286*711890bcSjc156560 			*(comp_list + i));
2287*711890bcSjc156560 
2288*711890bcSjc156560 		if (attr == NULL) {
2289*711890bcSjc156560 			free(tmplist);
2290*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2291*711890bcSjc156560 		}
2292*711890bcSjc156560 
2293*711890bcSjc156560 		attr->controller_id = tmplist[i];
2294*711890bcSjc156560 	}
2295*711890bcSjc156560 	free(tmplist);
2296*711890bcSjc156560 	(void) closedir(dir);
2297*711890bcSjc156560 	return (SUCCESS);
2298*711890bcSjc156560 }
2299*711890bcSjc156560 
2300*711890bcSjc156560 static int
2301*711890bcSjc156560 obj_controller_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2302*711890bcSjc156560 	raid_obj_type_id_t comp_type)
2303*711890bcSjc156560 {
2304*711890bcSjc156560 	raid_lib_t *raid_lib;
2305*711890bcSjc156560 	int ret = SUCCESS, fd;
2306*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2307*711890bcSjc156560 
2308*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2309*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2310*711890bcSjc156560 
2311*711890bcSjc156560 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2312*711890bcSjc156560 		return (0);
2313*711890bcSjc156560 
2314*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2315*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
2316*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2317*711890bcSjc156560 	if ((raid_lib == NULL) || (ctl_attrp == NULL) || (fd == 0))
2318*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2319*711890bcSjc156560 
2320*711890bcSjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id, 0,
2321*711890bcSjc156560 				OBJ_TYPE_CONTROLLER, comp_type);
2322*711890bcSjc156560 
2323*711890bcSjc156560 	return (ret);
2324*711890bcSjc156560 }
2325*711890bcSjc156560 
2326*711890bcSjc156560 static int
2327*711890bcSjc156560 obj_controller_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2328*711890bcSjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2329*711890bcSjc156560 {
2330*711890bcSjc156560 	raid_lib_t *raid_lib;
2331*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2332*711890bcSjc156560 	int ret, i, fd;
2333*711890bcSjc156560 	uint32_t *ids;
2334*711890bcSjc156560 
2335*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2336*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2337*711890bcSjc156560 
2338*711890bcSjc156560 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2339*711890bcSjc156560 		return (0);
2340*711890bcSjc156560 
2341*711890bcSjc156560 	if ((comp_num <= 0) || (comp_list == NULL))
2342*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2343*711890bcSjc156560 
2344*711890bcSjc156560 	for (i = 0; i < comp_num; ++i)
2345*711890bcSjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2346*711890bcSjc156560 			comp_type)
2347*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
2348*711890bcSjc156560 
2349*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2350*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2351*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
2352*711890bcSjc156560 	if ((raid_lib == NULL) || (ctl_attrp == NULL)|| (fd == 0))
2353*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2354*711890bcSjc156560 
2355*711890bcSjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
2356*711890bcSjc156560 	if (ids == NULL)
2357*711890bcSjc156560 		return (ERR_NOMEM);
2358*711890bcSjc156560 
2359*711890bcSjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id, 0,
2360*711890bcSjc156560 		OBJ_TYPE_CONTROLLER, comp_type, comp_num, ids);
2361*711890bcSjc156560 	if (ret < SUCCESS) {
2362*711890bcSjc156560 		free(ids);
2363*711890bcSjc156560 		return (ret);
2364*711890bcSjc156560 	}
2365*711890bcSjc156560 	qsort((void *)ids, comp_num, sizeof (uint32_t), intcompare);
2366*711890bcSjc156560 	for (i = 0; i < comp_num; ++ i) {
2367*711890bcSjc156560 		array_attr_t *array_attr;
2368*711890bcSjc156560 		disk_attr_t *disk_attr;
2369*711890bcSjc156560 		void *attr_buf;
2370*711890bcSjc156560 
2371*711890bcSjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2372*711890bcSjc156560 		if (attr_buf == NULL) {
2373*711890bcSjc156560 			free(ids);
2374*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2375*711890bcSjc156560 		}
2376*711890bcSjc156560 
2377*711890bcSjc156560 		switch (comp_type) {
2378*711890bcSjc156560 		case OBJ_TYPE_ARRAY:
2379*711890bcSjc156560 			array_attr = attr_buf;
2380*711890bcSjc156560 			array_attr->array_id = *(ids + i);
2381*711890bcSjc156560 			break;
2382*711890bcSjc156560 		case OBJ_TYPE_DISK:
2383*711890bcSjc156560 			disk_attr = attr_buf;
2384*711890bcSjc156560 			disk_attr->disk_id = *(ids + i);
2385*711890bcSjc156560 			break;
2386*711890bcSjc156560 		default:
2387*711890bcSjc156560 			free(ids);
2388*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2389*711890bcSjc156560 		}
2390*711890bcSjc156560 	}
2391*711890bcSjc156560 
2392*711890bcSjc156560 	free(ids);
2393*711890bcSjc156560 	return (SUCCESS);
2394*711890bcSjc156560 }
2395*711890bcSjc156560 
2396*711890bcSjc156560 static int
2397*711890bcSjc156560 obj_controller_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2398*711890bcSjc156560 {
2399*711890bcSjc156560 	controller_attr_t *attr;
2400*711890bcSjc156560 	raid_lib_t *raid_lib;
2401*711890bcSjc156560 	int ret = SUCCESS, fd;
2402*711890bcSjc156560 
2403*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2404*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2405*711890bcSjc156560 
2406*711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2407*711890bcSjc156560 		return (SUCCESS);
2408*711890bcSjc156560 
2409*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2410*711890bcSjc156560 	if (attr == NULL)
2411*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2412*711890bcSjc156560 
2413*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2414*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
2415*711890bcSjc156560 
2416*711890bcSjc156560 	/*
2417*711890bcSjc156560 	 * For a controller, even it's not opened, we can still
2418*711890bcSjc156560 	 * get the driver name
2419*711890bcSjc156560 	 */
2420*711890bcSjc156560 
2421*711890bcSjc156560 	if (fd == 0)
2422*711890bcSjc156560 		return (SUCCESS);
2423*711890bcSjc156560 
2424*711890bcSjc156560 	if (raid_lib == NULL) {
2425*711890bcSjc156560 		return (SUCCESS);
2426*711890bcSjc156560 	}
2427*711890bcSjc156560 
2428*711890bcSjc156560 	ret = raid_lib->get_attr(attr->controller_id, OBJ_ATTR_NONE,
2429*711890bcSjc156560 		OBJ_ATTR_NONE, OBJ_TYPE_CONTROLLER, attr);
2430*711890bcSjc156560 	if (ret < SUCCESS)
2431*711890bcSjc156560 		return (ret);
2432*711890bcSjc156560 
2433*711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2434*711890bcSjc156560 
2435*711890bcSjc156560 	return (ret);
2436*711890bcSjc156560 }
2437*711890bcSjc156560 
2438*711890bcSjc156560 static int
2439*711890bcSjc156560 obj_controller_act(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2440*711890bcSjc156560 	uint32_t sub_cmd, void *prop_list, char **plugin_err_str)
2441*711890bcSjc156560 {
2442*711890bcSjc156560 	controller_attr_t *attr;
2443*711890bcSjc156560 	raid_lib_t *raid_lib;
2444*711890bcSjc156560 	int ret, fd;
2445*711890bcSjc156560 
2446*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2447*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2448*711890bcSjc156560 
2449*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2450*711890bcSjc156560 
2451*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2452*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, obj_id);
2453*711890bcSjc156560 
2454*711890bcSjc156560 	switch (sub_cmd) {
2455*711890bcSjc156560 	case ACT_CONTROLLER_OPEN:
2456*711890bcSjc156560 		/* Check if already opened */
2457*711890bcSjc156560 
2458*711890bcSjc156560 		if (fd > 0)
2459*711890bcSjc156560 			return (SUCCESS);
2460*711890bcSjc156560 
2461*711890bcSjc156560 		/* Check if plugin is already attached */
2462*711890bcSjc156560 		if (raid_lib == NULL) {
2463*711890bcSjc156560 			raid_lib = raid_find_lib(raid_tab, obj_id);
2464*711890bcSjc156560 			if (raid_lib == NULL)
2465*711890bcSjc156560 				return (ERR_DRIVER_NOT_FOUND);
2466*711890bcSjc156560 		}
2467*711890bcSjc156560 
2468*711890bcSjc156560 		ret = raid_lib->open_controller(attr->controller_id,
2469*711890bcSjc156560 			plugin_err_str);
2470*711890bcSjc156560 		if (ret == SUCCESS) {
2471*711890bcSjc156560 			(void) raid_obj_set_lib(raid_tab, obj_id, raid_lib);
2472*711890bcSjc156560 			(void) raid_obj_set_fd(raid_tab, obj_id, 1);
2473*711890bcSjc156560 		}
2474*711890bcSjc156560 		break;
2475*711890bcSjc156560 	case ACT_CONTROLLER_CLOSE:
2476*711890bcSjc156560 
2477*711890bcSjc156560 		if (fd <= 0)
2478*711890bcSjc156560 			return (SUCCESS);
2479*711890bcSjc156560 
2480*711890bcSjc156560 		if (raid_lib == NULL) {
2481*711890bcSjc156560 			return (SUCCESS);
2482*711890bcSjc156560 		}
2483*711890bcSjc156560 		ret = raid_lib->close_controller(attr->controller_id,
2484*711890bcSjc156560 			plugin_err_str);
2485*711890bcSjc156560 		if (ret == SUCCESS) {
2486*711890bcSjc156560 			(void) raid_obj_set_fd(raid_tab, obj_id, 0);
2487*711890bcSjc156560 			(void) raid_obj_set_lib(raid_tab, obj_id, NULL);
2488*711890bcSjc156560 			raid_handle_delete_controller_comp(attr->controller_id);
2489*711890bcSjc156560 		}
2490*711890bcSjc156560 		break;
2491*711890bcSjc156560 	case ACT_CONTROLLER_FLASH_FW:
2492*711890bcSjc156560 		{
2493*711890bcSjc156560 			char		*filebuf;
2494*711890bcSjc156560 			int		image_fd;
2495*711890bcSjc156560 			uint32_t	size;
2496*711890bcSjc156560 			struct stat	statbuf;
2497*711890bcSjc156560 
2498*711890bcSjc156560 			if (prop_list == NULL)
2499*711890bcSjc156560 				return (ERR_OP_ILLEGAL);
2500*711890bcSjc156560 
2501*711890bcSjc156560 			/* Open firmware image file */
2502*711890bcSjc156560 			image_fd = open((const char *)prop_list,
2503*711890bcSjc156560 				O_RDONLY | O_NDELAY);
2504*711890bcSjc156560 			if (image_fd == -1)
2505*711890bcSjc156560 				return (ERR_OP_FAILED);
2506*711890bcSjc156560 
2507*711890bcSjc156560 			if (fstat(image_fd, &statbuf) != 0) {
2508*711890bcSjc156560 				(void) close(image_fd);
2509*711890bcSjc156560 				return (ERR_OP_FAILED);
2510*711890bcSjc156560 			}
2511*711890bcSjc156560 
2512*711890bcSjc156560 			filebuf = malloc(statbuf.st_size);
2513*711890bcSjc156560 			if (filebuf == NULL) {
2514*711890bcSjc156560 				(void) close(image_fd);
2515*711890bcSjc156560 				return (ERR_NOMEM);
2516*711890bcSjc156560 			}
2517*711890bcSjc156560 
2518*711890bcSjc156560 			size = read(image_fd, filebuf, statbuf.st_size);
2519*711890bcSjc156560 			if (size != statbuf.st_size) {
2520*711890bcSjc156560 				(void) close(image_fd);
2521*711890bcSjc156560 				free(filebuf);
2522*711890bcSjc156560 				return (ERR_OP_FAILED);
2523*711890bcSjc156560 			}
2524*711890bcSjc156560 
2525*711890bcSjc156560 			if (fd <= 0) {
2526*711890bcSjc156560 				(void) close(image_fd);
2527*711890bcSjc156560 				free(filebuf);
2528*711890bcSjc156560 				return (ERR_DRIVER_CLOSED);
2529*711890bcSjc156560 			}
2530*711890bcSjc156560 
2531*711890bcSjc156560 			if (raid_lib == NULL) {
2532*711890bcSjc156560 				(void) close(image_fd);
2533*711890bcSjc156560 				free(filebuf);
2534*711890bcSjc156560 				return (ERR_DRIVER_CLOSED);
2535*711890bcSjc156560 			}
2536*711890bcSjc156560 			if (raid_lib->flash_fw == NULL) {
2537*711890bcSjc156560 				(void) close(image_fd);
2538*711890bcSjc156560 				free(filebuf);
2539*711890bcSjc156560 				return (ERR_OP_NO_IMPL);
2540*711890bcSjc156560 			}
2541*711890bcSjc156560 
2542*711890bcSjc156560 			ret = raid_lib->flash_fw(attr->controller_id,
2543*711890bcSjc156560 				filebuf, size, plugin_err_str);
2544*711890bcSjc156560 		}
2545*711890bcSjc156560 		break;
2546*711890bcSjc156560 	default:
2547*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2548*711890bcSjc156560 	}
2549*711890bcSjc156560 
2550*711890bcSjc156560 	return (ret);
2551*711890bcSjc156560 }
2552*711890bcSjc156560 
2553*711890bcSjc156560 static int
2554*711890bcSjc156560 obj_array_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2555*711890bcSjc156560 	raid_obj_type_id_t comp_type)
2556*711890bcSjc156560 {
2557*711890bcSjc156560 	array_attr_t *attr;
2558*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2559*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2560*711890bcSjc156560 	raid_lib_t *raid_lib;
2561*711890bcSjc156560 	int ret = SUCCESS, fd;
2562*711890bcSjc156560 
2563*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2564*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2565*711890bcSjc156560 
2566*711890bcSjc156560 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
2567*711890bcSjc156560 		comp_type != OBJ_TYPE_ARRAY &&
2568*711890bcSjc156560 		comp_type != OBJ_TYPE_TASK)
2569*711890bcSjc156560 		return (0);
2570*711890bcSjc156560 
2571*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2572*711890bcSjc156560 	if (attr == NULL)
2573*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2574*711890bcSjc156560 
2575*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2576*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2577*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2578*711890bcSjc156560 
2579*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2580*711890bcSjc156560 	if (ctl_attrp == NULL) {
2581*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2582*711890bcSjc156560 	}
2583*711890bcSjc156560 
2584*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2585*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2586*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2587*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2588*711890bcSjc156560 
2589*711890bcSjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id, attr->array_id,
2590*711890bcSjc156560 		OBJ_TYPE_ARRAY, comp_type);
2591*711890bcSjc156560 
2592*711890bcSjc156560 	return (ret);
2593*711890bcSjc156560 }
2594*711890bcSjc156560 
2595*711890bcSjc156560 static int
2596*711890bcSjc156560 obj_array_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2597*711890bcSjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2598*711890bcSjc156560 {
2599*711890bcSjc156560 	array_attr_t *attr;
2600*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2601*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2602*711890bcSjc156560 	raid_lib_t *raid_lib;
2603*711890bcSjc156560 	int ret, i, fd;
2604*711890bcSjc156560 	uint32_t *ids;
2605*711890bcSjc156560 
2606*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2607*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2608*711890bcSjc156560 
2609*711890bcSjc156560 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
2610*711890bcSjc156560 		comp_type != OBJ_TYPE_ARRAY &&
2611*711890bcSjc156560 		comp_type != OBJ_TYPE_TASK)
2612*711890bcSjc156560 		return (0);
2613*711890bcSjc156560 
2614*711890bcSjc156560 	if (comp_num <= 0 || comp_list == NULL)
2615*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2616*711890bcSjc156560 
2617*711890bcSjc156560 	for (i = 0; i < comp_num; ++i)
2618*711890bcSjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2619*711890bcSjc156560 			comp_type)
2620*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
2621*711890bcSjc156560 
2622*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2623*711890bcSjc156560 	if (attr == NULL)
2624*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2625*711890bcSjc156560 
2626*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2627*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2628*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2629*711890bcSjc156560 
2630*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2631*711890bcSjc156560 	if (ctl_attrp == NULL) {
2632*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2633*711890bcSjc156560 	}
2634*711890bcSjc156560 
2635*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2636*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2637*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2638*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2639*711890bcSjc156560 
2640*711890bcSjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
2641*711890bcSjc156560 	if (ids == NULL)
2642*711890bcSjc156560 		return (ERR_NOMEM);
2643*711890bcSjc156560 
2644*711890bcSjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id,
2645*711890bcSjc156560 		attr->array_id, OBJ_TYPE_ARRAY, comp_type, comp_num, ids);
2646*711890bcSjc156560 
2647*711890bcSjc156560 	if (ret < SUCCESS) {
2648*711890bcSjc156560 		free(ids);
2649*711890bcSjc156560 		return (ret);
2650*711890bcSjc156560 	}
2651*711890bcSjc156560 
2652*711890bcSjc156560 	for (i = 0; i < comp_num; ++ i) {
2653*711890bcSjc156560 		array_attr_t *array_attr;
2654*711890bcSjc156560 		arraypart_attr_t *arraypart_attr;
2655*711890bcSjc156560 		task_attr_t *task_attr;
2656*711890bcSjc156560 		void *attr_buf;
2657*711890bcSjc156560 
2658*711890bcSjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2659*711890bcSjc156560 		if (attr_buf == NULL) {
2660*711890bcSjc156560 			free(ids);
2661*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2662*711890bcSjc156560 		}
2663*711890bcSjc156560 
2664*711890bcSjc156560 		switch (comp_type) {
2665*711890bcSjc156560 		case OBJ_TYPE_ARRAY:
2666*711890bcSjc156560 			array_attr = attr_buf;
2667*711890bcSjc156560 			array_attr->array_id = *(ids + i);
2668*711890bcSjc156560 			break;
2669*711890bcSjc156560 		case OBJ_TYPE_ARRAY_PART:
2670*711890bcSjc156560 			arraypart_attr = attr_buf;
2671*711890bcSjc156560 			arraypart_attr->disk_id = *(ids + i);
2672*711890bcSjc156560 			break;
2673*711890bcSjc156560 		case OBJ_TYPE_TASK:
2674*711890bcSjc156560 			task_attr = attr_buf;
2675*711890bcSjc156560 			task_attr->task_id = *(ids + i);
2676*711890bcSjc156560 			break;
2677*711890bcSjc156560 		default:
2678*711890bcSjc156560 			free(ids);
2679*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2680*711890bcSjc156560 		}
2681*711890bcSjc156560 	}
2682*711890bcSjc156560 
2683*711890bcSjc156560 
2684*711890bcSjc156560 	free(ids);
2685*711890bcSjc156560 	return (ret);
2686*711890bcSjc156560 }
2687*711890bcSjc156560 
2688*711890bcSjc156560 static int
2689*711890bcSjc156560 obj_array_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2690*711890bcSjc156560 {
2691*711890bcSjc156560 	array_attr_t *attr;
2692*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2693*711890bcSjc156560 	raid_lib_t *raid_lib;
2694*711890bcSjc156560 	int ret = SUCCESS, fd;
2695*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2696*711890bcSjc156560 
2697*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2698*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2699*711890bcSjc156560 
2700*711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2701*711890bcSjc156560 		return (SUCCESS);
2702*711890bcSjc156560 
2703*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2704*711890bcSjc156560 	if (attr == NULL)
2705*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2706*711890bcSjc156560 
2707*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2708*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2709*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2710*711890bcSjc156560 
2711*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2712*711890bcSjc156560 	if (ctl_attrp == NULL) {
2713*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2714*711890bcSjc156560 	}
2715*711890bcSjc156560 
2716*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2717*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2718*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2719*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2720*711890bcSjc156560 
2721*711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
2722*711890bcSjc156560 		attr->array_id, 0, OBJ_TYPE_ARRAY, attr);
2723*711890bcSjc156560 
2724*711890bcSjc156560 	if (ret < SUCCESS)
2725*711890bcSjc156560 		return (ret);
2726*711890bcSjc156560 
2727*711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2728*711890bcSjc156560 
2729*711890bcSjc156560 	return (ret);
2730*711890bcSjc156560 }
2731*711890bcSjc156560 
2732*711890bcSjc156560 static int
2733*711890bcSjc156560 obj_array_set_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2734*711890bcSjc156560 	uint32_t sub_cmd, uint32_t *value, char **plugin_err_str)
2735*711890bcSjc156560 {
2736*711890bcSjc156560 	array_attr_t *attr;
2737*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2738*711890bcSjc156560 	raid_lib_t *raid_lib;
2739*711890bcSjc156560 	int ret = SUCCESS, fd;
2740*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2741*711890bcSjc156560 
2742*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2743*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2744*711890bcSjc156560 
2745*711890bcSjc156560 	switch (sub_cmd) {
2746*711890bcSjc156560 	case SET_CACHE_WR_PLY:
2747*711890bcSjc156560 		if (*value != CACHE_WR_OFF &&
2748*711890bcSjc156560 			*value != CACHE_WR_ON)
2749*711890bcSjc156560 			return (ERR_OP_ILLEGAL);
2750*711890bcSjc156560 		break;
2751*711890bcSjc156560 	case SET_CACHE_RD_PLY:
2752*711890bcSjc156560 		if (*value != CACHE_RD_OFF &&
2753*711890bcSjc156560 			*value != CACHE_RD_ON)
2754*711890bcSjc156560 			return (ERR_OP_ILLEGAL);
2755*711890bcSjc156560 		break;
2756*711890bcSjc156560 	default:
2757*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2758*711890bcSjc156560 	}
2759*711890bcSjc156560 
2760*711890bcSjc156560 	(void) obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2761*711890bcSjc156560 
2762*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2763*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2764*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2765*711890bcSjc156560 
2766*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2767*711890bcSjc156560 	if (ctl_attrp == NULL) {
2768*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2769*711890bcSjc156560 	}
2770*711890bcSjc156560 
2771*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2772*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2773*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2774*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2775*711890bcSjc156560 
2776*711890bcSjc156560 	if (raid_lib->set_attr == NULL)
2777*711890bcSjc156560 		return (ERR_OP_NO_IMPL);
2778*711890bcSjc156560 
2779*711890bcSjc156560 	ret = raid_lib->set_attr(ctl_attrp->controller_id,
2780*711890bcSjc156560 		attr->array_id, sub_cmd, value, plugin_err_str);
2781*711890bcSjc156560 
2782*711890bcSjc156560 	return (ret);
2783*711890bcSjc156560 }
2784*711890bcSjc156560 
2785*711890bcSjc156560 static int
2786*711890bcSjc156560 obj_disk_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2787*711890bcSjc156560 	raid_obj_type_id_t comp_type)
2788*711890bcSjc156560 {
2789*711890bcSjc156560 	disk_attr_t *attr;
2790*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2791*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2792*711890bcSjc156560 	raid_lib_t *raid_lib;
2793*711890bcSjc156560 	int ret = SUCCESS, fd;
2794*711890bcSjc156560 
2795*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2796*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2797*711890bcSjc156560 
2798*711890bcSjc156560 	if (comp_type != OBJ_TYPE_DISK_SEG &&
2799*711890bcSjc156560 		comp_type != OBJ_TYPE_HSP &&
2800*711890bcSjc156560 		comp_type != OBJ_TYPE_TASK)
2801*711890bcSjc156560 		return (0);
2802*711890bcSjc156560 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2803*711890bcSjc156560 	if ((ret != SUCCESS) || (attr == NULL)) {
2804*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2805*711890bcSjc156560 	}
2806*711890bcSjc156560 	if (attr->state == DISK_STATE_FAILED) {
2807*711890bcSjc156560 		return (SUCCESS);
2808*711890bcSjc156560 	}
2809*711890bcSjc156560 
2810*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2811*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2812*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2813*711890bcSjc156560 
2814*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2815*711890bcSjc156560 	if (ctl_attrp == NULL) {
2816*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2817*711890bcSjc156560 	}
2818*711890bcSjc156560 
2819*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2820*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2821*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2822*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2823*711890bcSjc156560 
2824*711890bcSjc156560 	ret = raid_lib->compnum(ctl_attrp->controller_id,
2825*711890bcSjc156560 		attr->disk_id, OBJ_TYPE_DISK, comp_type);
2826*711890bcSjc156560 
2827*711890bcSjc156560 	return (ret);
2828*711890bcSjc156560 }
2829*711890bcSjc156560 
2830*711890bcSjc156560 static int
2831*711890bcSjc156560 obj_disk_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2832*711890bcSjc156560 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2833*711890bcSjc156560 {
2834*711890bcSjc156560 	disk_attr_t *attr;
2835*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2836*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2837*711890bcSjc156560 	raid_lib_t *raid_lib;
2838*711890bcSjc156560 	int ret, i, fd;
2839*711890bcSjc156560 	uint32_t *ids;
2840*711890bcSjc156560 
2841*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2842*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2843*711890bcSjc156560 
2844*711890bcSjc156560 	if (comp_type != OBJ_TYPE_DISK_SEG &&
2845*711890bcSjc156560 		comp_type != OBJ_TYPE_HSP &&
2846*711890bcSjc156560 		comp_type != OBJ_TYPE_TASK)
2847*711890bcSjc156560 		return (0);
2848*711890bcSjc156560 
2849*711890bcSjc156560 	if (comp_num <= 0 || comp_list == NULL)
2850*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
2851*711890bcSjc156560 
2852*711890bcSjc156560 	for (i = 0; i < comp_num; ++i)
2853*711890bcSjc156560 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2854*711890bcSjc156560 			comp_type)
2855*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
2856*711890bcSjc156560 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2857*711890bcSjc156560 	if ((ret != SUCCESS) || (attr == NULL)) {
2858*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2859*711890bcSjc156560 	}
2860*711890bcSjc156560 	if (attr->state == DISK_STATE_FAILED) {
2861*711890bcSjc156560 		return (SUCCESS);
2862*711890bcSjc156560 	}
2863*711890bcSjc156560 
2864*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2865*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2866*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2867*711890bcSjc156560 
2868*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2869*711890bcSjc156560 	if (ctl_attrp == NULL) {
2870*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2871*711890bcSjc156560 	}
2872*711890bcSjc156560 
2873*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2874*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2875*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2876*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2877*711890bcSjc156560 
2878*711890bcSjc156560 	ids = malloc(comp_num * sizeof (uint32_t));
2879*711890bcSjc156560 	if (ids == NULL)
2880*711890bcSjc156560 		return (ERR_NOMEM);
2881*711890bcSjc156560 
2882*711890bcSjc156560 	ret = raid_lib->complist(ctl_attrp->controller_id,
2883*711890bcSjc156560 		attr->disk_id, OBJ_TYPE_DISK, comp_type, comp_num, ids);
2884*711890bcSjc156560 
2885*711890bcSjc156560 	if (ret < SUCCESS) {
2886*711890bcSjc156560 		free(ids);
2887*711890bcSjc156560 		return (ret);
2888*711890bcSjc156560 	}
2889*711890bcSjc156560 
2890*711890bcSjc156560 	for (i = 0; i < comp_num; ++ i) {
2891*711890bcSjc156560 		diskseg_attr_t *diskseg_attr;
2892*711890bcSjc156560 		hsp_attr_t *hsp_attr;
2893*711890bcSjc156560 		task_attr_t *task_attr;
2894*711890bcSjc156560 		void *attr_buf;
2895*711890bcSjc156560 
2896*711890bcSjc156560 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2897*711890bcSjc156560 		if (attr_buf == NULL) {
2898*711890bcSjc156560 			free(ids);
2899*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2900*711890bcSjc156560 		}
2901*711890bcSjc156560 
2902*711890bcSjc156560 		switch (comp_type) {
2903*711890bcSjc156560 		case OBJ_TYPE_DISK_SEG:
2904*711890bcSjc156560 			diskseg_attr = attr_buf;
2905*711890bcSjc156560 			diskseg_attr->seq_no = *(ids + i);
2906*711890bcSjc156560 			break;
2907*711890bcSjc156560 		case OBJ_TYPE_HSP:
2908*711890bcSjc156560 			hsp_attr = attr_buf;
2909*711890bcSjc156560 			hsp_attr->associated_id = *(ids + i);
2910*711890bcSjc156560 			break;
2911*711890bcSjc156560 		case OBJ_TYPE_TASK:
2912*711890bcSjc156560 			task_attr = attr_buf;
2913*711890bcSjc156560 			task_attr->task_id = *(ids + i);
2914*711890bcSjc156560 			break;
2915*711890bcSjc156560 		default:
2916*711890bcSjc156560 			free(ids);
2917*711890bcSjc156560 			return (ERR_DEVICE_INVALID);
2918*711890bcSjc156560 		}
2919*711890bcSjc156560 	}
2920*711890bcSjc156560 
2921*711890bcSjc156560 
2922*711890bcSjc156560 	free(ids);
2923*711890bcSjc156560 	return (ret);
2924*711890bcSjc156560 }
2925*711890bcSjc156560 
2926*711890bcSjc156560 static int
2927*711890bcSjc156560 obj_disk_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2928*711890bcSjc156560 {
2929*711890bcSjc156560 	disk_attr_t *attr;
2930*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2931*711890bcSjc156560 	raid_lib_t *raid_lib;
2932*711890bcSjc156560 	int ret = SUCCESS, fd;
2933*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
2934*711890bcSjc156560 
2935*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2936*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2937*711890bcSjc156560 
2938*711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2939*711890bcSjc156560 		return (SUCCESS);
2940*711890bcSjc156560 
2941*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2942*711890bcSjc156560 	if (attr == NULL)
2943*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2944*711890bcSjc156560 
2945*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2946*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
2947*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2948*711890bcSjc156560 
2949*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2950*711890bcSjc156560 	if (ctl_attrp == NULL) {
2951*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2952*711890bcSjc156560 	}
2953*711890bcSjc156560 
2954*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2955*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2956*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
2957*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
2958*711890bcSjc156560 
2959*711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
2960*711890bcSjc156560 		attr->disk_id, 0, OBJ_TYPE_DISK, attr);
2961*711890bcSjc156560 
2962*711890bcSjc156560 	if (ret < SUCCESS)
2963*711890bcSjc156560 		return (ret);
2964*711890bcSjc156560 
2965*711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2966*711890bcSjc156560 
2967*711890bcSjc156560 	return (ret);
2968*711890bcSjc156560 }
2969*711890bcSjc156560 
2970*711890bcSjc156560 static int
2971*711890bcSjc156560 obj_hsp_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2972*711890bcSjc156560 {
2973*711890bcSjc156560 	hsp_attr_t *attr;
2974*711890bcSjc156560 
2975*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_HSP)
2976*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
2977*711890bcSjc156560 
2978*711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2979*711890bcSjc156560 		return (SUCCESS);
2980*711890bcSjc156560 
2981*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2982*711890bcSjc156560 	if (attr == NULL)
2983*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
2984*711890bcSjc156560 
2985*711890bcSjc156560 	if (attr->associated_id == (uint32_t)OBJ_ATTR_NONE)
2986*711890bcSjc156560 		attr->type = HSP_TYPE_GLOBAL;
2987*711890bcSjc156560 	else
2988*711890bcSjc156560 		attr->type = HSP_TYPE_LOCAL;
2989*711890bcSjc156560 
2990*711890bcSjc156560 	return (SUCCESS);
2991*711890bcSjc156560 }
2992*711890bcSjc156560 
2993*711890bcSjc156560 static int
2994*711890bcSjc156560 obj_arraypart_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2995*711890bcSjc156560 {
2996*711890bcSjc156560 	arraypart_attr_t *attr;
2997*711890bcSjc156560 	array_attr_t *array_attr;
2998*711890bcSjc156560 	controller_attr_t *ctl_attrp;
2999*711890bcSjc156560 	raid_lib_t *raid_lib;
3000*711890bcSjc156560 	int ret = SUCCESS, fd;
3001*711890bcSjc156560 	raid_obj_id_t controller_obj_id, array_obj_id;
3002*711890bcSjc156560 
3003*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY_PART)
3004*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
3005*711890bcSjc156560 
3006*711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3007*711890bcSjc156560 		return (SUCCESS);
3008*711890bcSjc156560 
3009*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3010*711890bcSjc156560 	if (attr == NULL)
3011*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3012*711890bcSjc156560 
3013*711890bcSjc156560 	array_obj_id = raid_obj_get_container(raid_tab, obj_id);
3014*711890bcSjc156560 	if (array_obj_id < OBJ_NONE)
3015*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3016*711890bcSjc156560 
3017*711890bcSjc156560 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3018*711890bcSjc156560 	if (array_attr == NULL)
3019*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3020*711890bcSjc156560 
3021*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3022*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
3023*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3024*711890bcSjc156560 
3025*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3026*711890bcSjc156560 	if (ctl_attrp == NULL) {
3027*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3028*711890bcSjc156560 	}
3029*711890bcSjc156560 
3030*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3031*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3032*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3033*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3034*711890bcSjc156560 
3035*711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3036*711890bcSjc156560 		array_attr->array_id, attr->disk_id,
3037*711890bcSjc156560 		OBJ_TYPE_ARRAY_PART, attr);
3038*711890bcSjc156560 
3039*711890bcSjc156560 	if (ret < SUCCESS)
3040*711890bcSjc156560 		return (ret);
3041*711890bcSjc156560 
3042*711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3043*711890bcSjc156560 
3044*711890bcSjc156560 	return (ret);
3045*711890bcSjc156560 }
3046*711890bcSjc156560 
3047*711890bcSjc156560 static int
3048*711890bcSjc156560 obj_diskseg_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3049*711890bcSjc156560 {
3050*711890bcSjc156560 	diskseg_attr_t *attr;
3051*711890bcSjc156560 	disk_attr_t *disk_attr;
3052*711890bcSjc156560 	controller_attr_t *ctl_attrp;
3053*711890bcSjc156560 	raid_lib_t *raid_lib;
3054*711890bcSjc156560 	int ret = SUCCESS, fd;
3055*711890bcSjc156560 	raid_obj_id_t controller_obj_id, disk_obj_id;
3056*711890bcSjc156560 
3057*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK_SEG)
3058*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
3059*711890bcSjc156560 
3060*711890bcSjc156560 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3061*711890bcSjc156560 		return (SUCCESS);
3062*711890bcSjc156560 
3063*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3064*711890bcSjc156560 	if (attr == NULL)
3065*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3066*711890bcSjc156560 
3067*711890bcSjc156560 	disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
3068*711890bcSjc156560 	if (disk_obj_id < OBJ_NONE)
3069*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3070*711890bcSjc156560 
3071*711890bcSjc156560 	disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
3072*711890bcSjc156560 	if (disk_attr == NULL)
3073*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3074*711890bcSjc156560 
3075*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3076*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
3077*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3078*711890bcSjc156560 
3079*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3080*711890bcSjc156560 	if (ctl_attrp == NULL) {
3081*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3082*711890bcSjc156560 	}
3083*711890bcSjc156560 
3084*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3085*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3086*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3087*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3088*711890bcSjc156560 
3089*711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3090*711890bcSjc156560 		disk_attr->disk_id, attr->seq_no, OBJ_TYPE_DISK_SEG, attr);
3091*711890bcSjc156560 
3092*711890bcSjc156560 	if (ret < SUCCESS)
3093*711890bcSjc156560 		return (ret);
3094*711890bcSjc156560 
3095*711890bcSjc156560 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3096*711890bcSjc156560 
3097*711890bcSjc156560 	return (ret);
3098*711890bcSjc156560 }
3099*711890bcSjc156560 
3100*711890bcSjc156560 static int
3101*711890bcSjc156560 obj_task_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3102*711890bcSjc156560 {
3103*711890bcSjc156560 	task_attr_t *attr;
3104*711890bcSjc156560 	controller_attr_t *ctl_attrp;
3105*711890bcSjc156560 	raid_lib_t *raid_lib;
3106*711890bcSjc156560 	int ret = SUCCESS, fd;
3107*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
3108*711890bcSjc156560 
3109*711890bcSjc156560 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_TASK)
3110*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
3111*711890bcSjc156560 
3112*711890bcSjc156560 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3113*711890bcSjc156560 	if (attr == NULL)
3114*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3115*711890bcSjc156560 
3116*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3117*711890bcSjc156560 	if (controller_obj_id < OBJ_NONE)
3118*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3119*711890bcSjc156560 
3120*711890bcSjc156560 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3121*711890bcSjc156560 	if (ctl_attrp == NULL) {
3122*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3123*711890bcSjc156560 	}
3124*711890bcSjc156560 
3125*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3126*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3127*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3128*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3129*711890bcSjc156560 
3130*711890bcSjc156560 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3131*711890bcSjc156560 		attr->task_id, OBJ_ATTR_NONE, OBJ_TYPE_TASK, attr);
3132*711890bcSjc156560 
3133*711890bcSjc156560 	return (ret);
3134*711890bcSjc156560 }
3135*711890bcSjc156560 
3136*711890bcSjc156560 static int
3137*711890bcSjc156560 obj_array_create(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3138*711890bcSjc156560 	int num_of_comp, raid_obj_id_t *disk_list, char **plugin_err_str)
3139*711890bcSjc156560 {
3140*711890bcSjc156560 	controller_attr_t *controller_attr;
3141*711890bcSjc156560 	array_attr_t *array_attr, array_attr2;
3142*711890bcSjc156560 	disk_attr_t *disk_attr;
3143*711890bcSjc156560 	arraypart_attr_t *arraypart_attrs;
3144*711890bcSjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3145*711890bcSjc156560 	raid_lib_t *raid_lib;
3146*711890bcSjc156560 	int i, j, ret, fd;
3147*711890bcSjc156560 	int disk_cnt = 0, disk_set_num = 0, set_num = 0, layer_cnt = 0;
3148*711890bcSjc156560 	uint64_t min_disk_capacity = 0;
3149*711890bcSjc156560 	uint32_t *diskid_list;
3150*711890bcSjc156560 
3151*711890bcSjc156560 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3152*711890bcSjc156560 	if (array_attr == NULL)
3153*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
3154*711890bcSjc156560 
3155*711890bcSjc156560 	/* Check the disk layout expression */
3156*711890bcSjc156560 	if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
3157*711890bcSjc156560 		disk_list[num_of_comp - 1] != OBJ_SEPARATOR_END)
3158*711890bcSjc156560 		return (ERR_ARRAY_LAYOUT);
3159*711890bcSjc156560 	for (i = 0; i < num_of_comp; ++i) {
3160*711890bcSjc156560 		if (disk_list[i] == OBJ_SEPARATOR_BEGIN) {
3161*711890bcSjc156560 			if (disk_cnt != 0)
3162*711890bcSjc156560 				return (ERR_ARRAY_LAYOUT);
3163*711890bcSjc156560 			++layer_cnt;
3164*711890bcSjc156560 			continue;
3165*711890bcSjc156560 		}
3166*711890bcSjc156560 		if (disk_list[i] == OBJ_SEPARATOR_END) {
3167*711890bcSjc156560 			if (disk_set_num == 0)
3168*711890bcSjc156560 				disk_set_num = disk_cnt;
3169*711890bcSjc156560 			else if (disk_set_num != disk_cnt && disk_cnt != 0)
3170*711890bcSjc156560 				return (ERR_ARRAY_LAYOUT);
3171*711890bcSjc156560 			disk_cnt = 0;
3172*711890bcSjc156560 			++set_num;
3173*711890bcSjc156560 			--layer_cnt;
3174*711890bcSjc156560 			continue;
3175*711890bcSjc156560 		}
3176*711890bcSjc156560 		switch (array_attr->raid_level) {
3177*711890bcSjc156560 		case RAID_LEVEL_0:
3178*711890bcSjc156560 		case RAID_LEVEL_1:
3179*711890bcSjc156560 		case RAID_LEVEL_1E:
3180*711890bcSjc156560 		case RAID_LEVEL_5:
3181*711890bcSjc156560 			if (layer_cnt != 1)
3182*711890bcSjc156560 				return (ERR_ARRAY_LAYOUT);
3183*711890bcSjc156560 			break;
3184*711890bcSjc156560 		case RAID_LEVEL_10:
3185*711890bcSjc156560 		case RAID_LEVEL_50:
3186*711890bcSjc156560 			if (layer_cnt != 2)
3187*711890bcSjc156560 				return (ERR_ARRAY_LAYOUT);
3188*711890bcSjc156560 			break;
3189*711890bcSjc156560 		default:
3190*711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3191*711890bcSjc156560 		}
3192*711890bcSjc156560 		++disk_cnt;
3193*711890bcSjc156560 	}
3194*711890bcSjc156560 
3195*711890bcSjc156560 	if (layer_cnt != 0)
3196*711890bcSjc156560 		return (ERR_ARRAY_LAYOUT);
3197*711890bcSjc156560 
3198*711890bcSjc156560 	switch (array_attr->raid_level) {
3199*711890bcSjc156560 	case RAID_LEVEL_0:
3200*711890bcSjc156560 		if (disk_set_num < 2 || set_num != 1)
3201*711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3202*711890bcSjc156560 		break;
3203*711890bcSjc156560 	case RAID_LEVEL_1:
3204*711890bcSjc156560 		if (disk_set_num != 2 || set_num != 1)
3205*711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3206*711890bcSjc156560 		break;
3207*711890bcSjc156560 	case RAID_LEVEL_1E:
3208*711890bcSjc156560 	case RAID_LEVEL_5:
3209*711890bcSjc156560 		if (disk_set_num < 3 || set_num != 1)
3210*711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3211*711890bcSjc156560 		break;
3212*711890bcSjc156560 	case RAID_LEVEL_10:
3213*711890bcSjc156560 		if (disk_set_num != 2 || set_num < 2)
3214*711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3215*711890bcSjc156560 		break;
3216*711890bcSjc156560 	case RAID_LEVEL_50:
3217*711890bcSjc156560 		if (disk_set_num < 3 || set_num < 2)
3218*711890bcSjc156560 			return (ERR_ARRAY_LAYOUT);
3219*711890bcSjc156560 		break;
3220*711890bcSjc156560 	default:
3221*711890bcSjc156560 		return (ERR_ARRAY_LEVEL);
3222*711890bcSjc156560 	}
3223*711890bcSjc156560 
3224*711890bcSjc156560 	arraypart_attrs = calloc(num_of_comp, sizeof (arraypart_attr_t));
3225*711890bcSjc156560 	if (arraypart_attrs == NULL)
3226*711890bcSjc156560 		return (ERR_NOMEM);
3227*711890bcSjc156560 
3228*711890bcSjc156560 	for (i = 0; i < num_of_comp; ++i) {
3229*711890bcSjc156560 		/* Keep seperators */
3230*711890bcSjc156560 		if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3231*711890bcSjc156560 			arraypart_attrs[i].disk_id =
3232*711890bcSjc156560 				(uint32_t)OBJ_SEPARATOR_BEGIN;
3233*711890bcSjc156560 			continue;
3234*711890bcSjc156560 		}
3235*711890bcSjc156560 
3236*711890bcSjc156560 		if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3237*711890bcSjc156560 			arraypart_attrs[i].disk_id =
3238*711890bcSjc156560 				(uint32_t)OBJ_SEPARATOR_END;
3239*711890bcSjc156560 			continue;
3240*711890bcSjc156560 		}
3241*711890bcSjc156560 
3242*711890bcSjc156560 		disk_cnt++;
3243*711890bcSjc156560 		/* Check if it's a disk */
3244*711890bcSjc156560 		if (raid_obj_get_type(raid_tab, *(disk_list + i)) !=
3245*711890bcSjc156560 			OBJ_TYPE_DISK)
3246*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
3247*711890bcSjc156560 
3248*711890bcSjc156560 		/* Check if it's duplicated with other disks */
3249*711890bcSjc156560 		for (j = 0; j < i; ++j)
3250*711890bcSjc156560 			if (*(disk_list + j) == *(disk_list + i)) {
3251*711890bcSjc156560 				free(arraypart_attrs);
3252*711890bcSjc156560 				return (ERR_DEVICE_DUP);
3253*711890bcSjc156560 			}
3254*711890bcSjc156560 
3255*711890bcSjc156560 		/* Check disk status */
3256*711890bcSjc156560 		ret = obj_get_attr(raid_tab, *(disk_list + i),
3257*711890bcSjc156560 			(void **)(&disk_attr));
3258*711890bcSjc156560 		if (ret != SUCCESS)
3259*711890bcSjc156560 			return (ret);
3260*711890bcSjc156560 
3261*711890bcSjc156560 		if (disk_attr->state != DISK_STATE_GOOD) {
3262*711890bcSjc156560 			free(arraypart_attrs);
3263*711890bcSjc156560 			return (ERR_DISK_STATE);
3264*711890bcSjc156560 		}
3265*711890bcSjc156560 
3266*711890bcSjc156560 		/* All disks must belong to the same controller */
3267*711890bcSjc156560 		obj_id = obj_get_controller(raid_tab, *(disk_list + i));
3268*711890bcSjc156560 		if (obj_id <= OBJ_NONE)
3269*711890bcSjc156560 			return (obj_id);
3270*711890bcSjc156560 		if (controller_obj_id == OBJ_NONE) {
3271*711890bcSjc156560 			controller_obj_id = obj_id;
3272*711890bcSjc156560 			ret = obj_get_attr(raid_tab, controller_obj_id,
3273*711890bcSjc156560 				(void **)(&controller_attr));
3274*711890bcSjc156560 		} else if (obj_id != controller_obj_id) {
3275*711890bcSjc156560 			free(arraypart_attrs);
3276*711890bcSjc156560 			return (ERR_DRIVER_ACROSS);
3277*711890bcSjc156560 		}
3278*711890bcSjc156560 
3279*711890bcSjc156560 		/* Check if the disk contains too many segments */
3280*711890bcSjc156560 		obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3281*711890bcSjc156560 				OBJ_TYPE_DISK_SEG);
3282*711890bcSjc156560 		j = 0;
3283*711890bcSjc156560 		while (obj_id > OBJ_NONE) {
3284*711890bcSjc156560 			++j;
3285*711890bcSjc156560 			obj_id = obj_get_sibling(raid_tab, obj_id);
3286*711890bcSjc156560 		}
3287*711890bcSjc156560 		if (j > controller_attr->max_seg_per_disk) {
3288*711890bcSjc156560 			free(arraypart_attrs);
3289*711890bcSjc156560 			return (ERR_DISK_SEG_AMOUNT);
3290*711890bcSjc156560 		}
3291*711890bcSjc156560 
3292*711890bcSjc156560 		/* Each disk should be un-used */
3293*711890bcSjc156560 		if ((ret = raid_dev_unmounted(controller_attr->controller_id,
3294*711890bcSjc156560 		    disk_attr->disk_id)) != SUCCESS) {
3295*711890bcSjc156560 			free(arraypart_attrs);
3296*711890bcSjc156560 			return (ret);
3297*711890bcSjc156560 		}
3298*711890bcSjc156560 
3299*711890bcSjc156560 		/* Check if controller is a hostraid controller */
3300*711890bcSjc156560 		if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3301*711890bcSjc156560 			/*
3302*711890bcSjc156560 			 * For hostraid, the first disk should
3303*711890bcSjc156560 			 * be with of minimum capacity
3304*711890bcSjc156560 			 */
3305*711890bcSjc156560 			if (min_disk_capacity == 0) {
3306*711890bcSjc156560 				min_disk_capacity = disk_attr->capacity;
3307*711890bcSjc156560 
3308*711890bcSjc156560 				/* Can not specify capacity for hostraid */
3309*711890bcSjc156560 				if (array_attr->capacity != 0) {
3310*711890bcSjc156560 					free(arraypart_attrs);
3311*711890bcSjc156560 					return (ERR_DISK_SPACE);
3312*711890bcSjc156560 				}
3313*711890bcSjc156560 			} else if (min_disk_capacity > disk_attr->capacity) {
3314*711890bcSjc156560 				free(arraypart_attrs);
3315*711890bcSjc156560 				return (ERR_DISK_SPACE);
3316*711890bcSjc156560 			}
3317*711890bcSjc156560 
3318*711890bcSjc156560 			/* Disk should not be used for hostraid */
3319*711890bcSjc156560 			obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3320*711890bcSjc156560 				OBJ_TYPE_DISK_SEG);
3321*711890bcSjc156560 			if (obj_id < OBJ_NONE) {
3322*711890bcSjc156560 				free(arraypart_attrs);
3323*711890bcSjc156560 				return (obj_id);
3324*711890bcSjc156560 			} else if (obj_id > OBJ_NONE) {
3325*711890bcSjc156560 				free(arraypart_attrs);
3326*711890bcSjc156560 				return (ERR_DISK_NOT_EMPTY);
3327*711890bcSjc156560 			}
3328*711890bcSjc156560 		}
3329*711890bcSjc156560 
3330*711890bcSjc156560 		arraypart_attrs[i].disk_id = disk_attr->disk_id;
3331*711890bcSjc156560 		arraypart_attrs[i].offset = OBJ_ATTR_NONE;
3332*711890bcSjc156560 		arraypart_attrs[i].size = OBJ_ATTR_NONE;
3333*711890bcSjc156560 	}
3334*711890bcSjc156560 
3335*711890bcSjc156560 	/* Check if array amount exceeds limit */
3336*711890bcSjc156560 	if (controller_attr->max_array_num <=
3337*711890bcSjc156560 		obj_controller_compnum(raid_tab, controller_obj_id,
3338*711890bcSjc156560 		OBJ_TYPE_ARRAY))
3339*711890bcSjc156560 		return (ERR_ARRAY_AMOUNT);
3340*711890bcSjc156560 
3341*711890bcSjc156560 
3342*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3343*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3344*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3345*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3346*711890bcSjc156560 
3347*711890bcSjc156560 	/* Check if the controller can support the array RAID level */
3348*711890bcSjc156560 	switch (array_attr->raid_level) {
3349*711890bcSjc156560 	case	RAID_LEVEL_0:
3350*711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID0)) {
3351*711890bcSjc156560 			free(arraypart_attrs);
3352*711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3353*711890bcSjc156560 		}
3354*711890bcSjc156560 		break;
3355*711890bcSjc156560 	case	RAID_LEVEL_1:
3356*711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID1)) {
3357*711890bcSjc156560 			free(arraypart_attrs);
3358*711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3359*711890bcSjc156560 		}
3360*711890bcSjc156560 		break;
3361*711890bcSjc156560 	case	RAID_LEVEL_1E:
3362*711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID1E)) {
3363*711890bcSjc156560 			free(arraypart_attrs);
3364*711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3365*711890bcSjc156560 		}
3366*711890bcSjc156560 		break;
3367*711890bcSjc156560 	case	RAID_LEVEL_5:
3368*711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID5)) {
3369*711890bcSjc156560 			free(arraypart_attrs);
3370*711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3371*711890bcSjc156560 		}
3372*711890bcSjc156560 		break;
3373*711890bcSjc156560 	case	RAID_LEVEL_10:
3374*711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID10)) {
3375*711890bcSjc156560 			free(arraypart_attrs);
3376*711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3377*711890bcSjc156560 		}
3378*711890bcSjc156560 		break;
3379*711890bcSjc156560 	case	RAID_LEVEL_50:
3380*711890bcSjc156560 		if (!(controller_attr->capability & RAID_CAP_RAID50)) {
3381*711890bcSjc156560 			free(arraypart_attrs);
3382*711890bcSjc156560 			return (ERR_ARRAY_LEVEL);
3383*711890bcSjc156560 		}
3384*711890bcSjc156560 		break;
3385*711890bcSjc156560 	default:
3386*711890bcSjc156560 		free(arraypart_attrs);
3387*711890bcSjc156560 		return (ERR_ARRAY_LEVEL);
3388*711890bcSjc156560 	}
3389*711890bcSjc156560 
3390*711890bcSjc156560 	/* Check if plug in can calculate the maximum size */
3391*711890bcSjc156560 	(void) memcpy(&array_attr2, array_attr, sizeof (array_attr_t));
3392*711890bcSjc156560 	array_attr2.capacity = OBJ_ATTR_NONE;
3393*711890bcSjc156560 	ret = raid_lib->array_create(controller_attr->controller_id,
3394*711890bcSjc156560 		&array_attr2, num_of_comp, arraypart_attrs, plugin_err_str);
3395*711890bcSjc156560 
3396*711890bcSjc156560 	/* If plugin/driver will not calculate space */
3397*711890bcSjc156560 	if (ret == ERR_OP_NO_IMPL) {
3398*711890bcSjc156560 		/* Calculate the maximum capacity */
3399*711890bcSjc156560 		array_attr2.capacity = raid_space_noalign(raid_tab,
3400*711890bcSjc156560 			array_attr2.raid_level, num_of_comp, disk_list,
3401*711890bcSjc156560 			arraypart_attrs);
3402*711890bcSjc156560 
3403*711890bcSjc156560 		/*
3404*711890bcSjc156560 		 * If controller is capable to allocate space,
3405*711890bcSjc156560 		 * set offset and size attributes to OBJ_ATTR_NONE
3406*711890bcSjc156560 		 * and let the controller to determine these value
3407*711890bcSjc156560 		 */
3408*711890bcSjc156560 		if (controller_attr->capability & RAID_CAP_SMART_ALLOC)
3409*711890bcSjc156560 			for (i = 0; i < num_of_comp; ++i) {
3410*711890bcSjc156560 				arraypart_attrs[i].offset =
3411*711890bcSjc156560 					OBJ_ATTR_NONE;
3412*711890bcSjc156560 				arraypart_attrs[i].size =
3413*711890bcSjc156560 					OBJ_ATTR_NONE;
3414*711890bcSjc156560 			}
3415*711890bcSjc156560 
3416*711890bcSjc156560 		/* There's no enough space for specified capacity */
3417*711890bcSjc156560 		if (array_attr->capacity > array_attr2.capacity) {
3418*711890bcSjc156560 			free(arraypart_attrs);
3419*711890bcSjc156560 			return (ERR_ARRAY_SIZE);
3420*711890bcSjc156560 		}
3421*711890bcSjc156560 
3422*711890bcSjc156560 		/* capacity == 0, allocate maximum space */
3423*711890bcSjc156560 		if (array_attr->capacity == 0)
3424*711890bcSjc156560 			array_attr->capacity = array_attr2.capacity;
3425*711890bcSjc156560 	} else if (ret < SUCCESS) {
3426*711890bcSjc156560 		free(arraypart_attrs);
3427*711890bcSjc156560 		return (ret);
3428*711890bcSjc156560 	} else if (array_attr2.capacity < array_attr->capacity) {
3429*711890bcSjc156560 		/* Return the maximum size */
3430*711890bcSjc156560 		array_attr->capacity = array_attr2.capacity;
3431*711890bcSjc156560 		free(arraypart_attrs);
3432*711890bcSjc156560 		return (ERR_ARRAY_SIZE);
3433*711890bcSjc156560 	}
3434*711890bcSjc156560 
3435*711890bcSjc156560 	if (array_attr->capacity < ARRAYPART_MIN_SIZE * disk_cnt) {
3436*711890bcSjc156560 		free(arraypart_attrs);
3437*711890bcSjc156560 		return (ERR_ARRAY_SIZE);
3438*711890bcSjc156560 	}
3439*711890bcSjc156560 
3440*711890bcSjc156560 
3441*711890bcSjc156560 	ret = raid_lib->array_create(controller_attr->controller_id,
3442*711890bcSjc156560 		array_attr, num_of_comp, arraypart_attrs, plugin_err_str);
3443*711890bcSjc156560 	free(arraypart_attrs);
3444*711890bcSjc156560 
3445*711890bcSjc156560 	if (ret != SUCCESS)
3446*711890bcSjc156560 		return (ret);
3447*711890bcSjc156560 
3448*711890bcSjc156560 	/* Add array object into device tree so that we can map the handle */
3449*711890bcSjc156560 	(void) raid_obj_add_org(raid_tab, array_obj_id, controller_obj_id);
3450*711890bcSjc156560 
3451*711890bcSjc156560 	/* unconfig disk minor nodes if it's hostraid */
3452*711890bcSjc156560 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3453*711890bcSjc156560 		diskid_list = (uint32_t *)calloc(num_of_comp,
3454*711890bcSjc156560 			sizeof (uint32_t));
3455*711890bcSjc156560 		if (diskid_list == NULL) {
3456*711890bcSjc156560 			return (ERR_NOMEM);
3457*711890bcSjc156560 		}
3458*711890bcSjc156560 
3459*711890bcSjc156560 		for (i = 0; i < num_of_comp; ++i) {
3460*711890bcSjc156560 			if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3461*711890bcSjc156560 				diskid_list[i] = (uint32_t)OBJ_SEPARATOR_BEGIN;
3462*711890bcSjc156560 			} else if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3463*711890bcSjc156560 				diskid_list[i] = (uint32_t)OBJ_SEPARATOR_END;
3464*711890bcSjc156560 			} else {
3465*711890bcSjc156560 				ret = obj_get_attr(raid_tab, *(disk_list + i),
3466*711890bcSjc156560 				    (void **)(&disk_attr));
3467*711890bcSjc156560 				if (ret != SUCCESS) {
3468*711890bcSjc156560 					free(diskid_list);
3469*711890bcSjc156560 					return (ret);
3470*711890bcSjc156560 				}
3471*711890bcSjc156560 				diskid_list[i] = disk_attr->disk_id;
3472*711890bcSjc156560 			}
3473*711890bcSjc156560 		}
3474*711890bcSjc156560 
3475*711890bcSjc156560 		for (i = 0; i < num_of_comp; ++i) {
3476*711890bcSjc156560 			if (diskid_list[i] == (uint32_t)OBJ_SEPARATOR_BEGIN ||
3477*711890bcSjc156560 			    diskid_list[i] == (uint32_t)OBJ_SEPARATOR_END) {
3478*711890bcSjc156560 				continue;
3479*711890bcSjc156560 			}
3480*711890bcSjc156560 
3481*711890bcSjc156560 			if (TARGET(diskid_list[i]) ==
3482*711890bcSjc156560 			    ARRAY_TARGET(array_attr->array_id) &&
3483*711890bcSjc156560 			    LUN(diskid_list[i]) ==
3484*711890bcSjc156560 			    ARRAY_LUN(array_attr->array_id))
3485*711890bcSjc156560 				continue;
3486*711890bcSjc156560 
3487*711890bcSjc156560 			ret = raid_dev_config(CFGA_CMD_UNCONFIGURE,
3488*711890bcSjc156560 			    controller_attr->controller_id, diskid_list[i], 0);
3489*711890bcSjc156560 			if (ret != SUCCESS) {
3490*711890bcSjc156560 				free(diskid_list);
3491*711890bcSjc156560 				return (ret);
3492*711890bcSjc156560 			}
3493*711890bcSjc156560 		}
3494*711890bcSjc156560 		free(diskid_list);
3495*711890bcSjc156560 	} else {
3496*711890bcSjc156560 		/* for HW raid */
3497*711890bcSjc156560 		ret = raid_dev_config(CFGA_CMD_CONFIGURE,
3498*711890bcSjc156560 		    controller_attr->controller_id, array_attr->array_id, 1);
3499*711890bcSjc156560 	}
3500*711890bcSjc156560 
3501*711890bcSjc156560 	return (ret);
3502*711890bcSjc156560 }
3503*711890bcSjc156560 
3504*711890bcSjc156560 static int
3505*711890bcSjc156560 obj_array_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3506*711890bcSjc156560 	char **plugin_err_str)
3507*711890bcSjc156560 {
3508*711890bcSjc156560 	raid_obj_id_t controller_obj_id;
3509*711890bcSjc156560 	controller_attr_t *controller_attr;
3510*711890bcSjc156560 	array_attr_t *array_attr;
3511*711890bcSjc156560 	arraypart_attr_t *arraypart_attr;
3512*711890bcSjc156560 	raid_obj_id_t arraypart_obj_id;
3513*711890bcSjc156560 	raid_lib_t *raid_lib;
3514*711890bcSjc156560 	int i = 0, j = 0, ret, fd;
3515*711890bcSjc156560 	uint32_t *disk_ids = NULL;
3516*711890bcSjc156560 
3517*711890bcSjc156560 	controller_obj_id = obj_get_controller(raid_tab, array_obj_id);
3518*711890bcSjc156560 	if (controller_obj_id <= OBJ_NONE)
3519*711890bcSjc156560 		return (controller_obj_id);
3520*711890bcSjc156560 
3521*711890bcSjc156560 	ret = obj_get_attr(raid_tab, controller_obj_id,
3522*711890bcSjc156560 		(void **)(&controller_attr));
3523*711890bcSjc156560 	if (ret < SUCCESS) {
3524*711890bcSjc156560 		return (ret);
3525*711890bcSjc156560 	}
3526*711890bcSjc156560 	ret = obj_get_attr(raid_tab, array_obj_id, (void **)(&array_attr));
3527*711890bcSjc156560 	if (ret < SUCCESS)
3528*711890bcSjc156560 		return (ret);
3529*711890bcSjc156560 
3530*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3531*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3532*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3533*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3534*711890bcSjc156560 
3535*711890bcSjc156560 	if ((ret = raid_dev_unmounted(controller_attr->controller_id,
3536*711890bcSjc156560 		array_attr->array_id)) != SUCCESS)
3537*711890bcSjc156560 		return (ret);
3538*711890bcSjc156560 
3539*711890bcSjc156560 	/* change minor nodes state for disks */
3540*711890bcSjc156560 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3541*711890bcSjc156560 		arraypart_obj_id = obj_get_comp(raid_tab, array_obj_id,
3542*711890bcSjc156560 		    OBJ_TYPE_ARRAY_PART);
3543*711890bcSjc156560 		if (arraypart_obj_id < OBJ_NONE) {
3544*711890bcSjc156560 			return (arraypart_obj_id);
3545*711890bcSjc156560 		}
3546*711890bcSjc156560 
3547*711890bcSjc156560 		/*
3548*711890bcSjc156560 		 * Check how many disks in volume and malloc space for
3549*711890bcSjc156560 		 * disk_ids; note that the number should be the disk
3550*711890bcSjc156560 		 * number minors 1 since the primary disk should not
3551*711890bcSjc156560 		 * be counted in.
3552*711890bcSjc156560 		 */
3553*711890bcSjc156560 		while (arraypart_obj_id = obj_get_sibling(raid_tab,
3554*711890bcSjc156560 		    arraypart_obj_id)) {
3555*711890bcSjc156560 			if (arraypart_obj_id < OBJ_NONE)
3556*711890bcSjc156560 				return (arraypart_obj_id);
3557*711890bcSjc156560 			++i;
3558*711890bcSjc156560 		}
3559*711890bcSjc156560 		disk_ids = calloc(i, sizeof (uint32_t));
3560*711890bcSjc156560 		if (disk_ids == NULL)
3561*711890bcSjc156560 			return (ERR_NOMEM);
3562*711890bcSjc156560 
3563*711890bcSjc156560 		/* Stor all member disk ids into disk_ids */
3564*711890bcSjc156560 		arraypart_obj_id = obj_get_comp(raid_tab, array_obj_id,
3565*711890bcSjc156560 		    OBJ_TYPE_ARRAY_PART);
3566*711890bcSjc156560 
3567*711890bcSjc156560 		while (arraypart_obj_id > OBJ_NONE) {
3568*711890bcSjc156560 			ret = obj_get_attr(raid_tab, arraypart_obj_id,
3569*711890bcSjc156560 			    (void **)(&arraypart_attr));
3570*711890bcSjc156560 			if (ret != SUCCESS) {
3571*711890bcSjc156560 				return (ret);
3572*711890bcSjc156560 			}
3573*711890bcSjc156560 			if (TARGET(arraypart_attr->disk_id) ==
3574*711890bcSjc156560 			    ARRAY_TARGET(array_attr->array_id) &&
3575*711890bcSjc156560 			    LUN(arraypart_attr->disk_id) ==
3576*711890bcSjc156560 			    ARRAY_LUN(array_attr->array_id)) {
3577*711890bcSjc156560 				arraypart_obj_id = obj_get_sibling(raid_tab,
3578*711890bcSjc156560 					arraypart_obj_id);
3579*711890bcSjc156560 				continue;
3580*711890bcSjc156560 			}
3581*711890bcSjc156560 
3582*711890bcSjc156560 			disk_ids[j] = arraypart_attr->disk_id;
3583*711890bcSjc156560 			++j;
3584*711890bcSjc156560 			arraypart_obj_id = obj_get_sibling(raid_tab,
3585*711890bcSjc156560 			    arraypart_obj_id);
3586*711890bcSjc156560 		}
3587*711890bcSjc156560 	} else {
3588*711890bcSjc156560 		ret = raid_dev_config(CFGA_CMD_UNCONFIGURE,
3589*711890bcSjc156560 		    controller_attr->controller_id, array_attr->array_id, 1);
3590*711890bcSjc156560 		if (ret != SUCCESS)
3591*711890bcSjc156560 			return (ret);
3592*711890bcSjc156560 	}
3593*711890bcSjc156560 
3594*711890bcSjc156560 	ret = raid_lib->array_delete(controller_attr->controller_id,
3595*711890bcSjc156560 		array_attr->array_id, plugin_err_str);
3596*711890bcSjc156560 	if (ret < SUCCESS) {
3597*711890bcSjc156560 		if (disk_ids)
3598*711890bcSjc156560 			free(disk_ids);
3599*711890bcSjc156560 		return (ret);
3600*711890bcSjc156560 	}
3601*711890bcSjc156560 
3602*711890bcSjc156560 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3603*711890bcSjc156560 		for (i = 0; i < j; ++i)
3604*711890bcSjc156560 			ret = raid_dev_config(CFGA_CMD_CONFIGURE,
3605*711890bcSjc156560 			    controller_attr->controller_id,
3606*711890bcSjc156560 			    disk_ids[i], 0);
3607*711890bcSjc156560 			if (ret < SUCCESS) {
3608*711890bcSjc156560 				free(disk_ids);
3609*711890bcSjc156560 				return (ret);
3610*711890bcSjc156560 			}
3611*711890bcSjc156560 	}
3612*711890bcSjc156560 
3613*711890bcSjc156560 	if (disk_ids)
3614*711890bcSjc156560 		free(disk_ids);
3615*711890bcSjc156560 	return (ret);
3616*711890bcSjc156560 }
3617*711890bcSjc156560 
3618*711890bcSjc156560 static int
3619*711890bcSjc156560 obj_hsp_bind(raid_obj_tab_t *raid_tab, int num, raid_obj_id_t *obj_ids,
3620*711890bcSjc156560 	char **plugin_err_str)
3621*711890bcSjc156560 {
3622*711890bcSjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3623*711890bcSjc156560 	raid_obj_id_t array_obj_id, disk_obj_id;
3624*711890bcSjc156560 	hsp_relation_t *hsp_relation;
3625*711890bcSjc156560 	controller_attr_t *controller_attr;
3626*711890bcSjc156560 	array_attr_t *array_attr;
3627*711890bcSjc156560 	arraypart_attr_t *arraypart_attr;
3628*711890bcSjc156560 	disk_attr_t *disk_attr;
3629*711890bcSjc156560 	diskseg_attr_t *diskseg_attr;
3630*711890bcSjc156560 	hsp_attr_t *hsp_attr;
3631*711890bcSjc156560 	raid_lib_t *raid_lib;
3632*711890bcSjc156560 	int ret, fd, i, j = 0;
3633*711890bcSjc156560 
3634*711890bcSjc156560 	hsp_relation = malloc(sizeof (hsp_relation_t) * num);
3635*711890bcSjc156560 	if (hsp_relation == NULL)
3636*711890bcSjc156560 		return (ERR_NOMEM);
3637*711890bcSjc156560 
3638*711890bcSjc156560 	for (i = 0; i < num; ++i) {
3639*711890bcSjc156560 		array_obj_id = *(obj_ids + i * 2);
3640*711890bcSjc156560 		disk_obj_id = *(obj_ids + i * 2 + 1);
3641*711890bcSjc156560 
3642*711890bcSjc156560 		if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK ||
3643*711890bcSjc156560 			(array_obj_id != OBJ_ATTR_NONE &&
3644*711890bcSjc156560 			raid_obj_get_type(raid_tab, array_obj_id) !=
3645*711890bcSjc156560 			OBJ_TYPE_ARRAY)) {
3646*711890bcSjc156560 			free(hsp_relation);
3647*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
3648*711890bcSjc156560 		}
3649*711890bcSjc156560 
3650*711890bcSjc156560 		/* Get controller attributes */
3651*711890bcSjc156560 		if (controller_obj_id == OBJ_NONE)
3652*711890bcSjc156560 			controller_obj_id = obj_get_controller(raid_tab,
3653*711890bcSjc156560 				disk_obj_id);
3654*711890bcSjc156560 		else if (controller_obj_id != obj_get_controller(raid_tab,
3655*711890bcSjc156560 			disk_obj_id)) {
3656*711890bcSjc156560 			free(hsp_relation);
3657*711890bcSjc156560 			return (ERR_DRIVER_ACROSS);
3658*711890bcSjc156560 		}
3659*711890bcSjc156560 
3660*711890bcSjc156560 		ret = obj_get_attr(raid_tab, controller_obj_id,
3661*711890bcSjc156560 			(void **)(&controller_attr));
3662*711890bcSjc156560 
3663*711890bcSjc156560 		/* Get disk attributes */
3664*711890bcSjc156560 		ret = obj_get_attr(raid_tab,  disk_obj_id,
3665*711890bcSjc156560 			(void **)(&disk_attr));
3666*711890bcSjc156560 		if (disk_attr->state == DISK_STATE_FAILED) {
3667*711890bcSjc156560 			free(hsp_relation);
3668*711890bcSjc156560 			return (ERR_DISK_STATE);
3669*711890bcSjc156560 		}
3670*711890bcSjc156560 
3671*711890bcSjc156560 		/* If it's not a hsp disk, check if there's occupied space */
3672*711890bcSjc156560 		if (obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP) ==
3673*711890bcSjc156560 		    OBJ_NONE) {
3674*711890bcSjc156560 			obj_id = obj_get_comp(raid_tab, disk_obj_id,
3675*711890bcSjc156560 				OBJ_TYPE_DISK_SEG);
3676*711890bcSjc156560 			while (obj_id != OBJ_NONE) {
3677*711890bcSjc156560 				ret = obj_get_attr(raid_tab, obj_id,
3678*711890bcSjc156560 					(void **)(&diskseg_attr));
3679*711890bcSjc156560 				if (!(diskseg_attr->state &
3680*711890bcSjc156560 					DISKSEG_STATE_RESERVED)) {
3681*711890bcSjc156560 					free(hsp_relation);
3682*711890bcSjc156560 					return (ERR_DISK_NOT_EMPTY);
3683*711890bcSjc156560 				}
3684*711890bcSjc156560 				obj_id = obj_get_sibling(raid_tab, obj_id);
3685*711890bcSjc156560 			}
3686*711890bcSjc156560 		}
3687*711890bcSjc156560 
3688*711890bcSjc156560 		if (array_obj_id != OBJ_ATTR_NONE) {
3689*711890bcSjc156560 			/* If local hsp is supported */
3690*711890bcSjc156560 			if (!(controller_attr->capability & RAID_CAP_L_HSP)) {
3691*711890bcSjc156560 				free(hsp_relation);
3692*711890bcSjc156560 				return (ERR_OP_ILLEGAL);
3693*711890bcSjc156560 			}
3694*711890bcSjc156560 
3695*711890bcSjc156560 			if (raid_obj_get_type(raid_tab, array_obj_id) !=
3696*711890bcSjc156560 				OBJ_TYPE_ARRAY) {
3697*711890bcSjc156560 				free(hsp_relation);
3698*711890bcSjc156560 				return (ERR_DEVICE_TYPE);
3699*711890bcSjc156560 			}
3700*711890bcSjc156560 
3701*711890bcSjc156560 			/* Get array attributes */
3702*711890bcSjc156560 			ret = obj_get_attr(raid_tab, array_obj_id,
3703*711890bcSjc156560 				(void **)(&array_attr));
3704*711890bcSjc156560 			/* RAID 0 array can not use hsp */
3705*711890bcSjc156560 			if (array_attr->raid_level == RAID_LEVEL_0) {
3706*711890bcSjc156560 				free(hsp_relation);
3707*711890bcSjc156560 				return (ERR_ARRAY_LEVEL);
3708*711890bcSjc156560 			}
3709*711890bcSjc156560 
3710*711890bcSjc156560 			/* If It's belong to another controller */
3711*711890bcSjc156560 			if (controller_obj_id != obj_get_controller(raid_tab,
3712*711890bcSjc156560 				array_obj_id)) {
3713*711890bcSjc156560 				free(hsp_relation);
3714*711890bcSjc156560 				return (ERR_DRIVER_ACROSS);
3715*711890bcSjc156560 			}
3716*711890bcSjc156560 
3717*711890bcSjc156560 			/* Get an array part attributes */
3718*711890bcSjc156560 			if ((array_attr->raid_level == RAID_LEVEL_10) ||
3719*711890bcSjc156560 				(array_attr->raid_level == RAID_LEVEL_50))
3720*711890bcSjc156560 				obj_id = obj_get_comp(raid_tab, array_obj_id,
3721*711890bcSjc156560 					OBJ_TYPE_ARRAY);
3722*711890bcSjc156560 			else
3723*711890bcSjc156560 				obj_id = array_obj_id;
3724*711890bcSjc156560 			obj_id = obj_get_comp(raid_tab, obj_id,
3725*711890bcSjc156560 				OBJ_TYPE_ARRAY_PART);
3726*711890bcSjc156560 			ret = obj_get_attr(raid_tab, obj_id,
3727*711890bcSjc156560 				(void **)(&arraypart_attr));
3728*711890bcSjc156560 
3729*711890bcSjc156560 			/* Check if disk space is enough for array */
3730*711890bcSjc156560 			if (arraypart_attr->size > disk_attr->capacity) {
3731*711890bcSjc156560 				free(hsp_relation);
3732*711890bcSjc156560 				return (ERR_DISK_SPACE);
3733*711890bcSjc156560 			}
3734*711890bcSjc156560 			if (controller_attr->capability & RAID_CAP_ARRAY_ALIGN)
3735*711890bcSjc156560 				if ((arraypart_attr->size +
3736*711890bcSjc156560 					arraypart_attr->offset) >
3737*711890bcSjc156560 					disk_attr->capacity) {
3738*711890bcSjc156560 				free(hsp_relation);
3739*711890bcSjc156560 				return (ERR_DISK_SPACE);
3740*711890bcSjc156560 				}
3741*711890bcSjc156560 		} else if (!(controller_attr->capability & RAID_CAP_G_HSP)) {
3742*711890bcSjc156560 			/* if global hsp is supported */
3743*711890bcSjc156560 			free(hsp_relation);
3744*711890bcSjc156560 			return (ERR_OP_ILLEGAL);
3745*711890bcSjc156560 		}
3746*711890bcSjc156560 
3747*711890bcSjc156560 		/*
3748*711890bcSjc156560 		 * If the array is already associated with the
3749*711890bcSjc156560 		 * local hsp, or it's a global hsp, ignore it
3750*711890bcSjc156560 		 */
3751*711890bcSjc156560 		obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3752*711890bcSjc156560 		if (obj_id > OBJ_NONE) {
3753*711890bcSjc156560 			if (obj_get_attr(raid_tab, obj_id,
3754*711890bcSjc156560 			    (void **)&hsp_attr) >= SUCCESS) {
3755*711890bcSjc156560 				if (((hsp_attr->type == HSP_TYPE_GLOBAL) &&
3756*711890bcSjc156560 				    (array_obj_id != OBJ_ATTR_NONE)) ||
3757*711890bcSjc156560 				    ((hsp_attr->type == HSP_TYPE_LOCAL) &&
3758*711890bcSjc156560 				    (array_obj_id == OBJ_ATTR_NONE))) {
3759*711890bcSjc156560 				    free(hsp_relation);
3760*711890bcSjc156560 				    return (ERR_OP_ILLEGAL);
3761*711890bcSjc156560 				}
3762*711890bcSjc156560 			}
3763*711890bcSjc156560 		}
3764*711890bcSjc156560 
3765*711890bcSjc156560 		if (array_obj_id != OBJ_ATTR_NONE)
3766*711890bcSjc156560 			hsp_relation[j].array_id = array_attr->array_id;
3767*711890bcSjc156560 		else
3768*711890bcSjc156560 			hsp_relation[j].array_id = (uint32_t)OBJ_ATTR_NONE;
3769*711890bcSjc156560 		hsp_relation[j].disk_id = disk_attr->disk_id;
3770*711890bcSjc156560 		++ j;
3771*711890bcSjc156560 	}
3772*711890bcSjc156560 
3773*711890bcSjc156560 
3774*711890bcSjc156560 	if (j == 0)
3775*711890bcSjc156560 		return (SUCCESS);
3776*711890bcSjc156560 
3777*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3778*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3779*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3780*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3781*711890bcSjc156560 
3782*711890bcSjc156560 	if (raid_lib->hsp_bind == NULL) {
3783*711890bcSjc156560 		free(hsp_relation);
3784*711890bcSjc156560 		return (ERR_OP_NO_IMPL);
3785*711890bcSjc156560 	}
3786*711890bcSjc156560 
3787*711890bcSjc156560 	ret = raid_lib->hsp_bind(controller_attr->controller_id,
3788*711890bcSjc156560 		j, hsp_relation, plugin_err_str);
3789*711890bcSjc156560 
3790*711890bcSjc156560 	free(hsp_relation);
3791*711890bcSjc156560 	return (ret);
3792*711890bcSjc156560 }
3793*711890bcSjc156560 
3794*711890bcSjc156560 static int
3795*711890bcSjc156560 obj_hsp_unbind(raid_obj_tab_t *raid_tab, int num, raid_obj_id_t *obj_ids,
3796*711890bcSjc156560 	char **plugin_err_str)
3797*711890bcSjc156560 {
3798*711890bcSjc156560 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3799*711890bcSjc156560 	raid_obj_id_t array_obj_id, disk_obj_id;
3800*711890bcSjc156560 	hsp_relation_t *hsp_relation;
3801*711890bcSjc156560 	controller_attr_t *controller_attr;
3802*711890bcSjc156560 	array_attr_t *array_attr;
3803*711890bcSjc156560 	disk_attr_t *disk_attr;
3804*711890bcSjc156560 	hsp_attr_t *hsp_attr;
3805*711890bcSjc156560 	raid_lib_t *raid_lib;
3806*711890bcSjc156560 	int ret, fd, i, j = 0;
3807*711890bcSjc156560 
3808*711890bcSjc156560 	hsp_relation = malloc(sizeof (hsp_relation_t) * num);
3809*711890bcSjc156560 	if (hsp_relation == NULL)
3810*711890bcSjc156560 		return (ERR_NOMEM);
3811*711890bcSjc156560 
3812*711890bcSjc156560 	for (i = 0; i < num; ++i) {
3813*711890bcSjc156560 		array_obj_id = *(obj_ids + i * 2);
3814*711890bcSjc156560 		disk_obj_id = *(obj_ids + i * 2 + 1);
3815*711890bcSjc156560 
3816*711890bcSjc156560 		if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK) {
3817*711890bcSjc156560 			free(hsp_relation);
3818*711890bcSjc156560 			return (ERR_DEVICE_TYPE);
3819*711890bcSjc156560 		}
3820*711890bcSjc156560 
3821*711890bcSjc156560 		/* Get controller attributes */
3822*711890bcSjc156560 		if (controller_obj_id == OBJ_NONE)
3823*711890bcSjc156560 			controller_obj_id = obj_get_controller(raid_tab,
3824*711890bcSjc156560 				disk_obj_id);
3825*711890bcSjc156560 		else if (controller_obj_id != obj_get_controller(raid_tab,
3826*711890bcSjc156560 			disk_obj_id)) {
3827*711890bcSjc156560 			free(hsp_relation);
3828*711890bcSjc156560 			return (ERR_DRIVER_ACROSS);
3829*711890bcSjc156560 		}
3830*711890bcSjc156560 
3831*711890bcSjc156560 		ret = obj_get_attr(raid_tab, controller_obj_id,
3832*711890bcSjc156560 			(void **)(&controller_attr));
3833*711890bcSjc156560 
3834*711890bcSjc156560 		/* Get disk attributes */
3835*711890bcSjc156560 		ret = obj_get_attr(raid_tab,  disk_obj_id,
3836*711890bcSjc156560 			(void **)(&disk_attr));
3837*711890bcSjc156560 		if (disk_attr->state == DISK_STATE_FAILED) {
3838*711890bcSjc156560 			free(hsp_relation);
3839*711890bcSjc156560 			return (ERR_DISK_STATE);
3840*711890bcSjc156560 		}
3841*711890bcSjc156560 
3842*711890bcSjc156560 		/* If it's not a hsp disk */
3843*711890bcSjc156560 		obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3844*711890bcSjc156560 		if (obj_id == OBJ_NONE) {
3845*711890bcSjc156560 			free(hsp_relation);
3846*711890bcSjc156560 			return (ERR_DISK_STATE);
3847*711890bcSjc156560 		}
3848*711890bcSjc156560 		ret = obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
3849*711890bcSjc156560 
3850*711890bcSjc156560 		if (array_obj_id != OBJ_ATTR_NONE) {
3851*711890bcSjc156560 			if (raid_obj_get_type(raid_tab, array_obj_id) !=
3852*711890bcSjc156560 				OBJ_TYPE_ARRAY) {
3853*711890bcSjc156560 				free(hsp_relation);
3854*711890bcSjc156560 				return (ERR_DEVICE_TYPE);
3855*711890bcSjc156560 				}
3856*711890bcSjc156560 
3857*711890bcSjc156560 			/* Get array attributes */
3858*711890bcSjc156560 			ret = obj_get_attr(raid_tab, array_obj_id,
3859*711890bcSjc156560 				(void **)(&array_attr));
3860*711890bcSjc156560 
3861*711890bcSjc156560 			/* If It's belong to another controller */
3862*711890bcSjc156560 			if (controller_obj_id != obj_get_controller(raid_tab,
3863*711890bcSjc156560 				array_obj_id)) {
3864*711890bcSjc156560 				free(hsp_relation);
3865*711890bcSjc156560 				return (ERR_DRIVER_ACROSS);
3866*711890bcSjc156560 			}
3867*711890bcSjc156560 
3868*711890bcSjc156560 			/* If want to remove an array from a global hsp */
3869*711890bcSjc156560 			if (hsp_attr->type == HSP_TYPE_GLOBAL) {
3870*711890bcSjc156560 				free(hsp_relation);
3871*711890bcSjc156560 				return (ERR_OP_ILLEGAL);
3872*711890bcSjc156560 			}
3873*711890bcSjc156560 
3874*711890bcSjc156560 			do {
3875*711890bcSjc156560 				(void) obj_get_attr(raid_tab, obj_id,
3876*711890bcSjc156560 					(void **)(&hsp_attr));
3877*711890bcSjc156560 
3878*711890bcSjc156560 				if (hsp_attr->associated_id ==
3879*711890bcSjc156560 					array_attr->array_id ||
3880*711890bcSjc156560 					hsp_attr->type == HSP_TYPE_GLOBAL)
3881*711890bcSjc156560 					break;
3882*711890bcSjc156560 
3883*711890bcSjc156560 				obj_id = obj_get_sibling(raid_tab, obj_id);
3884*711890bcSjc156560 			} while (obj_id > OBJ_NONE);
3885*711890bcSjc156560 		} else if (hsp_attr->type != HSP_TYPE_GLOBAL) {
3886*711890bcSjc156560 			/* if global hsp is supported */
3887*711890bcSjc156560 			free(hsp_relation);
3888*711890bcSjc156560 			return (ERR_OP_ILLEGAL);
3889*711890bcSjc156560 		}
3890*711890bcSjc156560 
3891*711890bcSjc156560 		/*
3892*711890bcSjc156560 		 * If array is associated with a local hsp, or remove a
3893*711890bcSjc156560 		 * global hsp disk
3894*711890bcSjc156560 		 */
3895*711890bcSjc156560 		if ((obj_id && (array_obj_id != OBJ_ATTR_NONE)) ||
3896*711890bcSjc156560 			(array_obj_id == OBJ_ATTR_NONE)) {
3897*711890bcSjc156560 			if (array_obj_id != OBJ_ATTR_NONE)
3898*711890bcSjc156560 				hsp_relation[j].array_id = array_attr->array_id;
3899*711890bcSjc156560 			else
3900*711890bcSjc156560 				hsp_relation[j].array_id =
3901*711890bcSjc156560 					(uint32_t)OBJ_ATTR_NONE;
3902*711890bcSjc156560 			hsp_relation[j].disk_id = disk_attr->disk_id;
3903*711890bcSjc156560 			++ j;
3904*711890bcSjc156560 		} else {
3905*711890bcSjc156560 			free(hsp_relation);
3906*711890bcSjc156560 			return (ERR_OP_ILLEGAL);
3907*711890bcSjc156560 		}
3908*711890bcSjc156560 	}
3909*711890bcSjc156560 
3910*711890bcSjc156560 
3911*711890bcSjc156560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3912*711890bcSjc156560 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3913*711890bcSjc156560 	if ((raid_lib == NULL) || (fd == 0))
3914*711890bcSjc156560 		return (ERR_DRIVER_CLOSED);
3915*711890bcSjc156560 
3916*711890bcSjc156560 	if (raid_lib->hsp_unbind == NULL) {
3917*711890bcSjc156560 		free(hsp_relation);
3918*711890bcSjc156560 		return (ERR_OP_NO_IMPL);
3919*711890bcSjc156560 	}
3920*711890bcSjc156560 
3921*711890bcSjc156560 	ret = raid_lib->hsp_unbind(controller_attr->controller_id,
3922*711890bcSjc156560 		j, hsp_relation, plugin_err_str);
3923*711890bcSjc156560 
3924*711890bcSjc156560 	free(hsp_relation);
3925*711890bcSjc156560 	return (ret);
3926*711890bcSjc156560 }
3927*711890bcSjc156560 
3928*711890bcSjc156560 /*
3929*711890bcSjc156560  * Object maintennance routines
3930*711890bcSjc156560  */
3931*711890bcSjc156560 static int
3932*711890bcSjc156560 raid_obj_create_system_obj(raid_obj_tab_t *raid_tab)
3933*711890bcSjc156560 {
3934*711890bcSjc156560 	raid_obj_t *raid_obj;
3935*711890bcSjc156560 	int ret;
3936*711890bcSjc156560 
3937*711890bcSjc156560 	raid_obj = calloc(1, sizeof (raid_obj_t));
3938*711890bcSjc156560 	if (raid_obj == NULL)
3939*711890bcSjc156560 		return (ERR_NOMEM);
3940*711890bcSjc156560 
3941*711890bcSjc156560 	raid_obj->obj_id = OBJ_SYSTEM;
3942*711890bcSjc156560 	raid_obj->obj_type_id = OBJ_TYPE_SYSTEM;
3943*711890bcSjc156560 	raid_obj->data = NULL;
3944*711890bcSjc156560 
3945*711890bcSjc156560 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3946*711890bcSjc156560 	if (ret == ERR_DEVICE_DUP) {
3947*711890bcSjc156560 		free(raid_obj);
3948*711890bcSjc156560 		return (ERR_DEVICE_UNCLEAN);
3949*711890bcSjc156560 	}
3950*711890bcSjc156560 
3951*711890bcSjc156560 	return (SUCCESS);
3952*711890bcSjc156560 }
3953*711890bcSjc156560 
3954*711890bcSjc156560 static raid_obj_id_t
3955*711890bcSjc156560 raid_obj_id_new(raid_obj_tab_t *raid_tab)
3956*711890bcSjc156560 {
3957*711890bcSjc156560 	++ raid_tab->obj_id_cnt;
3958*711890bcSjc156560 	if (raid_tab->obj_id_cnt <= 0)
3959*711890bcSjc156560 		return (ERR_DEVICE_OVERFLOW);
3960*711890bcSjc156560 
3961*711890bcSjc156560 	return (raid_tab->obj_id_cnt);
3962*711890bcSjc156560 }
3963*711890bcSjc156560 
3964*711890bcSjc156560 static void *
3965*711890bcSjc156560 raid_obj_attr_new(raid_obj_type_id_t obj_type)
3966*711890bcSjc156560 {
3967*711890bcSjc156560 	void *obj_attr = NULL;
3968*711890bcSjc156560 
3969*711890bcSjc156560 	switch (obj_type) {
3970*711890bcSjc156560 	case	OBJ_TYPE_CONTROLLER:
3971*711890bcSjc156560 		obj_attr = calloc(1, sizeof (controller_attr_t));
3972*711890bcSjc156560 		break;
3973*711890bcSjc156560 	case	OBJ_TYPE_ARRAY:
3974*711890bcSjc156560 		obj_attr = calloc(1, sizeof (array_attr_t));
3975*711890bcSjc156560 		break;
3976*711890bcSjc156560 	case	OBJ_TYPE_DISK:
3977*711890bcSjc156560 		obj_attr = calloc(1, sizeof (disk_attr_t));
3978*711890bcSjc156560 		break;
3979*711890bcSjc156560 	case	OBJ_TYPE_HSP:
3980*711890bcSjc156560 		obj_attr = calloc(1, sizeof (hsp_attr_t));
3981*711890bcSjc156560 		break;
3982*711890bcSjc156560 	case	OBJ_TYPE_ARRAY_PART:
3983*711890bcSjc156560 		obj_attr = calloc(1, sizeof (arraypart_attr_t));
3984*711890bcSjc156560 		break;
3985*711890bcSjc156560 	case	OBJ_TYPE_DISK_SEG:
3986*711890bcSjc156560 		obj_attr = calloc(1, sizeof (diskseg_attr_t));
3987*711890bcSjc156560 		break;
3988*711890bcSjc156560 	case	OBJ_TYPE_TASK:
3989*711890bcSjc156560 		obj_attr = calloc(1, sizeof (task_attr_t));
3990*711890bcSjc156560 		break;
3991*711890bcSjc156560 	default:
3992*711890bcSjc156560 		break;
3993*711890bcSjc156560 	}
3994*711890bcSjc156560 
3995*711890bcSjc156560 	return (obj_attr);
3996*711890bcSjc156560 }
3997*711890bcSjc156560 
3998*711890bcSjc156560 static raid_obj_id_t
3999*711890bcSjc156560 raid_obj_create(raid_obj_tab_t *raid_tab, raid_obj_type_id_t obj_type)
4000*711890bcSjc156560 {
4001*711890bcSjc156560 	raid_obj_t *raid_obj;
4002*711890bcSjc156560 	int ret;
4003*711890bcSjc156560 	void *data_ptr;
4004*711890bcSjc156560 
4005*711890bcSjc156560 	raid_obj = calloc(1, sizeof (raid_obj_t));
4006*711890bcSjc156560 	if (raid_obj == NULL)
4007*711890bcSjc156560 		return (ERR_NOMEM);
4008*711890bcSjc156560 
4009*711890bcSjc156560 	raid_obj->obj_id = raid_obj_id_new(raid_tab);
4010*711890bcSjc156560 	if (raid_obj->obj_id < OBJ_NONE)
4011*711890bcSjc156560 		return (ERR_DEVICE_OVERFLOW);
4012*711890bcSjc156560 
4013*711890bcSjc156560 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
4014*711890bcSjc156560 	if (ret == ERR_DEVICE_DUP) {
4015*711890bcSjc156560 		free(raid_obj);
4016*711890bcSjc156560 		return (ERR_DEVICE_DUP);
4017*711890bcSjc156560 	}
4018*711890bcSjc156560 
4019*711890bcSjc156560 	data_ptr = raid_obj_attr_new(obj_type);
4020*711890bcSjc156560 	if (data_ptr == NULL) {
4021*711890bcSjc156560 		(void) raid_obj_delete(raid_tab, raid_obj->obj_id);
4022*711890bcSjc156560 		return (ERR_NOMEM);
4023*711890bcSjc156560 	}
4024*711890bcSjc156560 
4025*711890bcSjc156560 	(void) raid_obj_set_data_ptr(raid_tab, raid_obj->obj_id, data_ptr);
4026*711890bcSjc156560 
4027*711890bcSjc156560 	(void) raid_obj_set_type(raid_tab, raid_obj->obj_id, obj_type);
4028*711890bcSjc156560 	return (raid_obj->obj_id);
4029*711890bcSjc156560 }
4030*711890bcSjc156560 
4031*711890bcSjc156560 static int
4032*711890bcSjc156560 raid_obj_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t raid_obj_id)
4033*711890bcSjc156560 {
4034*711890bcSjc156560 	raid_obj_t *obj;
4035*711890bcSjc156560 
4036*711890bcSjc156560 	obj = raid_obj_tab_remove(raid_tab, raid_obj_id);
4037*711890bcSjc156560 	if (obj != NULL) {
4038*711890bcSjc156560 		free(obj->data);
4039*711890bcSjc156560 		free(obj);
4040*711890bcSjc156560 		return (SUCCESS);
4041*711890bcSjc156560 	}
4042*711890bcSjc156560 
4043*711890bcSjc156560 	return (ERR_DEVICE_NOENT);
4044*711890bcSjc156560 }
4045*711890bcSjc156560 
4046*711890bcSjc156560 static int
4047*711890bcSjc156560 raid_obj_add_org(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4048*711890bcSjc156560 	raid_obj_id_t container_id)
4049*711890bcSjc156560 {
4050*711890bcSjc156560 	raid_obj_id_t tmp, tmp1;
4051*711890bcSjc156560 
4052*711890bcSjc156560 	tmp = raid_obj_get_comp(raid_tab, container_id);
4053*711890bcSjc156560 	if (tmp < OBJ_NONE)
4054*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4055*711890bcSjc156560 
4056*711890bcSjc156560 	if (tmp == OBJ_NONE) {
4057*711890bcSjc156560 		(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4058*711890bcSjc156560 		(void) raid_obj_set_comp(raid_tab, container_id, obj_id);
4059*711890bcSjc156560 		return (SUCCESS);
4060*711890bcSjc156560 	}
4061*711890bcSjc156560 
4062*711890bcSjc156560 	while ((tmp1 = raid_obj_get_sibling(raid_tab, tmp)) != OBJ_NONE)
4063*711890bcSjc156560 		tmp = tmp1;
4064*711890bcSjc156560 
4065*711890bcSjc156560 	if (raid_obj_set_sibling(raid_tab, tmp, obj_id) < SUCCESS)
4066*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4067*711890bcSjc156560 	(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4068*711890bcSjc156560 
4069*711890bcSjc156560 	return (SUCCESS);
4070*711890bcSjc156560 }
4071*711890bcSjc156560 
4072*711890bcSjc156560 static raid_obj_type_id_t
4073*711890bcSjc156560 raid_obj_get_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4074*711890bcSjc156560 {
4075*711890bcSjc156560 	raid_obj_t *obj;
4076*711890bcSjc156560 
4077*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4078*711890bcSjc156560 	if (obj == NULL)
4079*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4080*711890bcSjc156560 
4081*711890bcSjc156560 	if ((obj->obj_type_id < OBJ_TYPE_SYSTEM) ||
4082*711890bcSjc156560 		(obj->obj_type_id >= OBJ_TYPE_ALL))
4083*711890bcSjc156560 		return (ERR_DEVICE_INVALID);
4084*711890bcSjc156560 
4085*711890bcSjc156560 	return (obj->obj_type_id);
4086*711890bcSjc156560 }
4087*711890bcSjc156560 
4088*711890bcSjc156560 static int
4089*711890bcSjc156560 raid_obj_set_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4090*711890bcSjc156560 	raid_obj_type_id_t type)
4091*711890bcSjc156560 {
4092*711890bcSjc156560 	raid_obj_t *obj;
4093*711890bcSjc156560 
4094*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4095*711890bcSjc156560 	if (obj == NULL)
4096*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4097*711890bcSjc156560 
4098*711890bcSjc156560 	if ((type < OBJ_TYPE_SYSTEM) || (type >= OBJ_TYPE_ALL))
4099*711890bcSjc156560 		return (ERR_DEVICE_TYPE);
4100*711890bcSjc156560 
4101*711890bcSjc156560 	obj->obj_type_id = type;
4102*711890bcSjc156560 	return (SUCCESS);
4103*711890bcSjc156560 }
4104*711890bcSjc156560 
4105*711890bcSjc156560 static raid_obj_status_t
4106*711890bcSjc156560 raid_obj_get_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4107*711890bcSjc156560 {
4108*711890bcSjc156560 	raid_obj_t *obj;
4109*711890bcSjc156560 
4110*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4111*711890bcSjc156560 	if (obj == NULL)
4112*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4113*711890bcSjc156560 
4114*711890bcSjc156560 	return (obj->status);
4115*711890bcSjc156560 }
4116*711890bcSjc156560 
4117*711890bcSjc156560 static int
4118*711890bcSjc156560 raid_obj_set_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4119*711890bcSjc156560 	raid_obj_status_t status)
4120*711890bcSjc156560 {
4121*711890bcSjc156560 	raid_obj_t *obj;
4122*711890bcSjc156560 
4123*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4124*711890bcSjc156560 	if (obj == NULL)
4125*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4126*711890bcSjc156560 
4127*711890bcSjc156560 	obj->status = obj->status | status;
4128*711890bcSjc156560 
4129*711890bcSjc156560 	return (SUCCESS);
4130*711890bcSjc156560 }
4131*711890bcSjc156560 
4132*711890bcSjc156560 static int
4133*711890bcSjc156560 raid_obj_clear_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4134*711890bcSjc156560 	raid_obj_status_t status)
4135*711890bcSjc156560 {
4136*711890bcSjc156560 	raid_obj_t *obj;
4137*711890bcSjc156560 
4138*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4139*711890bcSjc156560 	if (obj == NULL)
4140*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4141*711890bcSjc156560 
4142*711890bcSjc156560 	obj->status = obj->status & ~status;
4143*711890bcSjc156560 
4144*711890bcSjc156560 	return (SUCCESS);
4145*711890bcSjc156560 }
4146*711890bcSjc156560 
4147*711890bcSjc156560 static raid_obj_id_t
4148*711890bcSjc156560 raid_obj_get_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4149*711890bcSjc156560 {
4150*711890bcSjc156560 	raid_obj_t *obj;
4151*711890bcSjc156560 
4152*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4153*711890bcSjc156560 	if (obj == NULL)
4154*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4155*711890bcSjc156560 
4156*711890bcSjc156560 	return (obj->container);
4157*711890bcSjc156560 }
4158*711890bcSjc156560 
4159*711890bcSjc156560 static int
4160*711890bcSjc156560 raid_obj_set_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4161*711890bcSjc156560 	raid_obj_id_t container_id)
4162*711890bcSjc156560 {
4163*711890bcSjc156560 	raid_obj_t *obj;
4164*711890bcSjc156560 
4165*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4166*711890bcSjc156560 	if (obj == NULL)
4167*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4168*711890bcSjc156560 
4169*711890bcSjc156560 	obj->container = container_id;
4170*711890bcSjc156560 	return (SUCCESS);
4171*711890bcSjc156560 }
4172*711890bcSjc156560 
4173*711890bcSjc156560 static raid_obj_id_t
4174*711890bcSjc156560 raid_obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4175*711890bcSjc156560 {
4176*711890bcSjc156560 	raid_obj_t *obj;
4177*711890bcSjc156560 
4178*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4179*711890bcSjc156560 	if (obj == NULL)
4180*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4181*711890bcSjc156560 
4182*711890bcSjc156560 	return (obj->component);
4183*711890bcSjc156560 }
4184*711890bcSjc156560 
4185*711890bcSjc156560 static int
4186*711890bcSjc156560 raid_obj_set_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4187*711890bcSjc156560 	raid_obj_id_t comp)
4188*711890bcSjc156560 {
4189*711890bcSjc156560 	raid_obj_t *obj;
4190*711890bcSjc156560 
4191*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4192*711890bcSjc156560 	if (obj == NULL)
4193*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4194*711890bcSjc156560 
4195*711890bcSjc156560 	obj->component = comp;
4196*711890bcSjc156560 	return (SUCCESS);
4197*711890bcSjc156560 }
4198*711890bcSjc156560 
4199*711890bcSjc156560 static raid_obj_id_t
4200*711890bcSjc156560 raid_obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4201*711890bcSjc156560 {
4202*711890bcSjc156560 	raid_obj_t *obj;
4203*711890bcSjc156560 
4204*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4205*711890bcSjc156560 	if (obj == NULL)
4206*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4207*711890bcSjc156560 
4208*711890bcSjc156560 	return (obj->sibling);
4209*711890bcSjc156560 }
4210*711890bcSjc156560 
4211*711890bcSjc156560 static int
4212*711890bcSjc156560 raid_obj_set_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4213*711890bcSjc156560 	raid_obj_id_t sibling)
4214*711890bcSjc156560 {
4215*711890bcSjc156560 	raid_obj_t *obj;
4216*711890bcSjc156560 
4217*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4218*711890bcSjc156560 	if (obj == NULL)
4219*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4220*711890bcSjc156560 
4221*711890bcSjc156560 	obj->sibling = sibling;
4222*711890bcSjc156560 
4223*711890bcSjc156560 	return (SUCCESS);
4224*711890bcSjc156560 }
4225*711890bcSjc156560 
4226*711890bcSjc156560 static void *
4227*711890bcSjc156560 raid_obj_get_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4228*711890bcSjc156560 {
4229*711890bcSjc156560 	raid_obj_t *obj;
4230*711890bcSjc156560 
4231*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4232*711890bcSjc156560 	if (obj == NULL)
4233*711890bcSjc156560 		return (NULL);
4234*711890bcSjc156560 
4235*711890bcSjc156560 	return (obj->data);
4236*711890bcSjc156560 }
4237*711890bcSjc156560 
4238*711890bcSjc156560 static int
4239*711890bcSjc156560 raid_obj_set_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4240*711890bcSjc156560 	void *data)
4241*711890bcSjc156560 {
4242*711890bcSjc156560 	raid_obj_t *obj;
4243*711890bcSjc156560 
4244*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4245*711890bcSjc156560 	if (obj == NULL)
4246*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4247*711890bcSjc156560 
4248*711890bcSjc156560 	obj->data = data;
4249*711890bcSjc156560 
4250*711890bcSjc156560 	return (SUCCESS);
4251*711890bcSjc156560 }
4252*711890bcSjc156560 
4253*711890bcSjc156560 static raid_obj_handle_t
4254*711890bcSjc156560 raid_obj_get_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4255*711890bcSjc156560 {
4256*711890bcSjc156560 	raid_obj_t *obj;
4257*711890bcSjc156560 
4258*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4259*711890bcSjc156560 	if (obj == NULL)
4260*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4261*711890bcSjc156560 
4262*711890bcSjc156560 	return (obj->handle);
4263*711890bcSjc156560 }
4264*711890bcSjc156560 
4265*711890bcSjc156560 static int
4266*711890bcSjc156560 raid_obj_set_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4267*711890bcSjc156560 	raid_obj_handle_t handle)
4268*711890bcSjc156560 {
4269*711890bcSjc156560 	raid_obj_t *obj;
4270*711890bcSjc156560 
4271*711890bcSjc156560 	obj = raid_obj_tab_find(raid_tab, obj_id);
4272*711890bcSjc156560 	if (obj == NULL)
4273*711890bcSjc156560 		return (ERR_DEVICE_NOENT);
4274*711890bcSjc156560 
4275*711890bcSjc156560 	obj->handle = handle;
4276*711890bcSjc156560 	return (SUCCESS);
4277*711890bcSjc156560 }
4278*711890bcSjc156560 /*
4279*711890bcSjc156560  * Object list maintennance routines
4280*711890bcSjc156560  */
4281*711890bcSjc156560 static void
4282*711890bcSjc156560 raid_list_create(raid_list_t *list, size_t offset)
4283*711890bcSjc156560 {
4284*711890bcSjc156560 	list->head = NULL;
4285*711890bcSjc156560 	list->tail = NULL;
4286*711890bcSjc156560 	list->offset = offset;
4287*711890bcSjc156560 }
4288*711890bcSjc156560 
4289*711890bcSjc156560 static void *
4290*711890bcSjc156560 raid_list_head(raid_list_t *list)
4291*711890bcSjc156560 {
4292*711890bcSjc156560 	return (list->head);
4293*711890bcSjc156560 }
4294*711890bcSjc156560 
4295*711890bcSjc156560 static void *
4296*711890bcSjc156560 raid_list_next(raid_list_t *list, void *obj)
4297*711890bcSjc156560 {
4298*711890bcSjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj);
4299*711890bcSjc156560 
4300*711890bcSjc156560 	return (el->next);
4301*711890bcSjc156560 }
4302*711890bcSjc156560 
4303*711890bcSjc156560 static void
4304*711890bcSjc156560 raid_list_insert_tail(raid_list_t *list, void *obj)
4305*711890bcSjc156560 {
4306*711890bcSjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4307*711890bcSjc156560 
4308*711890bcSjc156560 	el->prev = list->tail;
4309*711890bcSjc156560 	list->tail = obj;
4310*711890bcSjc156560 
4311*711890bcSjc156560 	el->next = NULL;
4312*711890bcSjc156560 
4313*711890bcSjc156560 	if (list->head == NULL)
4314*711890bcSjc156560 		list->head = obj;
4315*711890bcSjc156560 
4316*711890bcSjc156560 	if (el->prev != NULL) {
4317*711890bcSjc156560 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4318*711890bcSjc156560 		el1->next = obj;
4319*711890bcSjc156560 	}
4320*711890bcSjc156560 }
4321*711890bcSjc156560 
4322*711890bcSjc156560 static void
4323*711890bcSjc156560 raid_list_remove(raid_list_t *list, void *obj)
4324*711890bcSjc156560 {
4325*711890bcSjc156560 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4326*711890bcSjc156560 
4327*711890bcSjc156560 	if (list->head == obj)
4328*711890bcSjc156560 		list->head = el->next;
4329*711890bcSjc156560 
4330*711890bcSjc156560 	if (list->tail == obj)
4331*711890bcSjc156560 		list->tail = el->prev;
4332*711890bcSjc156560 
4333*711890bcSjc156560 	if (el->next != NULL) {
4334*711890bcSjc156560 		el1 = LIST_OBJ_TO_EL(list, el->next);
4335*711890bcSjc156560 		el1->prev = el->prev;
4336*711890bcSjc156560 	}
4337*711890bcSjc156560 
4338*711890bcSjc156560 	if (el->prev != NULL) {
4339*711890bcSjc156560 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4340*711890bcSjc156560 		el1->next = el->next;
4341*711890bcSjc156560 	}
4342*711890bcSjc156560 
4343*711890bcSjc156560 	el->prev = el->next = NULL;
4344*711890bcSjc156560 }
4345*711890bcSjc156560 
4346*711890bcSjc156560 static void *
4347*711890bcSjc156560 raid_list_remove_head(raid_list_t *list)
4348*711890bcSjc156560 {
4349*711890bcSjc156560 	void *obj = list->head;
4350*711890bcSjc156560 
4351*711890bcSjc156560 	if (obj != NULL)
4352*711890bcSjc156560 		raid_list_remove(list, obj);
4353*711890bcSjc156560 
4354*711890bcSjc156560 	return (obj);
4355*711890bcSjc156560 }
4356*711890bcSjc156560 
4357*711890bcSjc156560 static void *
4358*711890bcSjc156560 raid_list_find(raid_list_t *list, raid_obj_id_t obj_id)
4359*711890bcSjc156560 {
4360*711890bcSjc156560 	raid_obj_t *obj;
4361*711890bcSjc156560 
4362*711890bcSjc156560 	for (obj = raid_list_head(list); obj != NULL;
4363*711890bcSjc156560 		obj = raid_list_next(list, obj))
4364*711890bcSjc156560 			if (obj->obj_id == obj_id)
4365*711890bcSjc156560 				break;
4366*711890bcSjc156560 
4367*711890bcSjc156560 	return (obj);
4368*711890bcSjc156560 }
4369*711890bcSjc156560 
4370*711890bcSjc156560 static int
4371*711890bcSjc156560 raid_obj_tab_create(raid_obj_tab_t *tab, size_t hash_slots)
4372*711890bcSjc156560 {
4373*711890bcSjc156560 	unsigned i;
4374*711890bcSjc156560 
4375*711890bcSjc156560 	if (hash_slots == 0)
4376*711890bcSjc156560 		return (ERR_OP_ILLEGAL);
4377*711890bcSjc156560 
4378*711890bcSjc156560 	tab->slots = hash_slots;
4379*711890bcSjc156560 
4380*711890bcSjc156560 	if ((tab->table = calloc(hash_slots, sizeof (raid_list_t))) == NULL)
4381*711890bcSjc156560 		return (ERR_NOMEM);
4382*711890bcSjc156560 
4383*711890bcSjc156560 	for (i = 0; i < hash_slots; i++)
4384*711890bcSjc156560 		raid_list_create(&tab->table[i], offsetof(raid_obj_t, el));
4385*711890bcSjc156560 
4386*711890bcSjc156560 	return (SUCCESS);
4387*711890bcSjc156560 }
4388*711890bcSjc156560 
4389*711890bcSjc156560 static void
4390*711890bcSjc156560 raid_obj_tab_destroy(raid_obj_tab_t *tab)
4391*711890bcSjc156560 {
4392*711890bcSjc156560 	unsigned i;
4393*711890bcSjc156560 
4394*711890bcSjc156560 	for (i = 0; i < tab->slots; i++) {
4395*711890bcSjc156560 		struct raid_obj_t *obj;
4396*711890bcSjc156560 
4397*711890bcSjc156560 		while ((obj = raid_list_remove_head(&tab->table[i])) != NULL)
4398*711890bcSjc156560 			free(obj);
4399*711890bcSjc156560 
4400*711890bcSjc156560 		raid_list_destroy(&tab->table[i]);
4401*711890bcSjc156560 	}
4402*711890bcSjc156560 
4403*711890bcSjc156560 	if (tab->table)
4404*711890bcSjc156560 		free(tab->table);
4405*711890bcSjc156560 
4406*711890bcSjc156560 	tab->table = NULL;
4407*711890bcSjc156560 	tab->slots = 0;
4408*711890bcSjc156560 	tab->obj_id_cnt = 0;
4409*711890bcSjc156560 }
4410*711890bcSjc156560 
4411*711890bcSjc156560 static int
4412*711890bcSjc156560 raid_obj_tab_insert(raid_obj_tab_t *tab, raid_obj_id_t id, void *obj)
4413*711890bcSjc156560 {
4414*711890bcSjc156560 	raid_list_t *list;
4415*711890bcSjc156560 
4416*711890bcSjc156560 	list = OBJ_TAB_SLOT(tab, id);
4417*711890bcSjc156560 
4418*711890bcSjc156560 	if (raid_list_find(list, id) != NULL)
4419*711890bcSjc156560 		return (ERR_DEVICE_DUP);
4420*711890bcSjc156560 
4421*711890bcSjc156560 	raid_list_insert_tail(list, obj);
4422*711890bcSjc156560 
4423*711890bcSjc156560 	return (SUCCESS);
4424*711890bcSjc156560 }
4425*711890bcSjc156560 
4426*711890bcSjc156560 static void *
4427*711890bcSjc156560 raid_obj_tab_remove(raid_obj_tab_t *tab, raid_obj_id_t id)
4428*711890bcSjc156560 {
4429*711890bcSjc156560 	raid_list_t *list;
4430*711890bcSjc156560 	raid_obj_t *obj;
4431*711890bcSjc156560 
4432*711890bcSjc156560 	list = OBJ_TAB_SLOT(tab, id);
4433*711890bcSjc156560 
4434*711890bcSjc156560 	if ((obj = raid_list_find(list, id)) != NULL)
4435*711890bcSjc156560 		raid_list_remove(list, obj);
4436*711890bcSjc156560 
4437*711890bcSjc156560 	return (obj);
4438*711890bcSjc156560 }
4439*711890bcSjc156560 
4440*711890bcSjc156560 static void *
4441*711890bcSjc156560 raid_obj_tab_find(raid_obj_tab_t *tab, raid_obj_id_t id)
4442*711890bcSjc156560 {
4443*711890bcSjc156560 	raid_list_t *list;
4444*711890bcSjc156560 	raid_obj_t *obj;
4445*711890bcSjc156560 
4446*711890bcSjc156560 	list = OBJ_TAB_SLOT(tab, id);
4447*711890bcSjc156560 	obj = raid_list_find(list, id);
4448*711890bcSjc156560 
4449*711890bcSjc156560 	return (obj);
4450*711890bcSjc156560 }
4451*711890bcSjc156560 
4452*711890bcSjc156560 static void
4453*711890bcSjc156560 raid_list_destroy(raid_list_t *list)
4454*711890bcSjc156560 {
4455*711890bcSjc156560 	list->head = NULL;
4456*711890bcSjc156560 	list->tail = NULL;
4457*711890bcSjc156560 	list->offset = 0;
4458*711890bcSjc156560 }
4459*711890bcSjc156560 
4460*711890bcSjc156560 /*
4461*711890bcSjc156560  * Plug-in maintennance routines
4462*711890bcSjc156560  */
4463*711890bcSjc156560 static int
4464*711890bcSjc156560 controller_id_to_path(uint32_t controller_id, char *path)
4465*711890bcSjc156560 {
4466*711890bcSjc156560 	char buf[MAX_PATH_LEN] = {0}, buf1[MAX_PATH_LEN] = {0}, *colon;
4467*711890bcSjc156560 
4468*711890bcSjc156560 	(void) snprintf(buf, MAX_PATH_LEN, "%s/c%d", CFGDIR, controller_id);
4469*711890bcSjc156560 	if (readlink(buf, buf1, sizeof (buf1)) < 0)
4470*711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
4471*711890bcSjc156560 
4472*711890bcSjc156560 	if (buf1[0] != '/')
4473*711890bcSjc156560 		(void) snprintf(buf, sizeof (buf), "%s/", CFGDIR);
4474*711890bcSjc156560 	else
4475*711890bcSjc156560 		buf[0] = 0;
4476*711890bcSjc156560 	(void) strlcat(buf, buf1, MAX_PATH_LEN);
4477*711890bcSjc156560 
4478*711890bcSjc156560 	colon = strrchr(buf, ':');
4479*711890bcSjc156560 	if (colon == NULL)
4480*711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
4481*711890bcSjc156560 	else
4482*711890bcSjc156560 		*colon = 0;
4483*711890bcSjc156560 
4484*711890bcSjc156560 	(void) snprintf(path, MAX_PATH_LEN, "%s:devctl", buf);
4485*711890bcSjc156560 
4486*711890bcSjc156560 	if (access(path, F_OK) < 0)
4487*711890bcSjc156560 		return (ERR_DRIVER_NOT_FOUND);
4488*711890bcSjc156560 
4489*711890bcSjc156560 	return (SUCCESS);
4490*711890bcSjc156560 }
4491*711890bcSjc156560 
4492*711890bcSjc156560 static char *
4493*711890bcSjc156560 controller_id_to_driver_name(uint32_t controller_id)
4494*711890bcSjc156560 {
4495*711890bcSjc156560 	char buf[MAX_PATH_LEN];
4496*711890bcSjc156560 	di_node_t di_node;
4497*711890bcSjc156560 	char *name, *tmp;
4498*711890bcSjc156560 	int ret;
4499*711890bcSjc156560 
4500*711890bcSjc156560 	ret = controller_id_to_path(controller_id, buf);
4501*711890bcSjc156560 	if (ret < SUCCESS)
4502*711890bcSjc156560 		return (NULL);
4503*711890bcSjc156560 
4504*711890bcSjc156560 	tmp = strrchr(buf, ':');
4505*711890bcSjc156560 	if (tmp != NULL)
4506*711890bcSjc156560 		*tmp = 0;
4507*711890bcSjc156560 
4508*711890bcSjc156560 	tmp = strstr(buf, "pci");
4509*711890bcSjc156560 	if (tmp == NULL)
4510*711890bcSjc156560 		return (NULL);
4511*711890bcSjc156560 
4512*711890bcSjc156560 	di_node = di_init(tmp, DINFOPROP);
4513*711890bcSjc156560 	if (di_node == DI_NODE_NIL)
4514*711890bcSjc156560 		return (NULL);
4515*711890bcSjc156560 
4516*711890bcSjc156560 	name = di_driver_name(di_node);
4517*711890bcSjc156560 
4518*711890bcSjc156560 	return (name);
4519*711890bcSjc156560 }
4520*711890bcSjc156560 
4521*711890bcSjc156560 static void
4522*711890bcSjc156560 raid_plugin_init()
4523*711890bcSjc156560 {
4524*711890bcSjc156560 	raid_lib_t *raid_lib = raid_lib_sys;
4525*711890bcSjc156560 
4526*711890bcSjc156560 	while (raid_lib) {
4527*711890bcSjc156560 		raid_lib_sys = raid_lib->next;
4528*711890bcSjc156560 		(void) dlclose(raid_lib->lib_handle);
4529*711890bcSjc156560 		free(raid_lib);
4530*711890bcSjc156560 		raid_lib = raid_lib_sys;
4531*711890bcSjc156560 	}
4532*711890bcSjc156560 }
4533*711890bcSjc156560 
4534*711890bcSjc156560 static raid_lib_t *
4535*711890bcSjc156560 raid_plugin_load(char *driver_name)
4536*711890bcSjc156560 {
4537*711890bcSjc156560 	char buf[MAX_PATH_LEN] = {0};
4538*711890bcSjc156560 	raid_lib_t *supplib;
4539*711890bcSjc156560 	void *sym;
4540*711890bcSjc156560 
4541*711890bcSjc156560 	supplib = calloc(1, sizeof (raid_lib_t));
4542*711890bcSjc156560 	if (supplib == NULL)
4543*711890bcSjc156560 		return (NULL);
4544*711890bcSjc156560 
4545*711890bcSjc156560 	(void) snprintf(buf, MAX_PATH_LEN, "%s/%s.so.1",
4546*711890bcSjc156560 		SUPP_PLUGIN_DIR, driver_name);
4547*711890bcSjc156560 
4548*711890bcSjc156560 	supplib->lib_handle = dlopen(buf, RTLD_LAZY);
4549*711890bcSjc156560 	if (supplib->lib_handle == NULL) {
4550*711890bcSjc156560 		free(supplib);
4551*711890bcSjc156560 		return (NULL);
4552*711890bcSjc156560 	}
4553*711890bcSjc156560 
4554*711890bcSjc156560 	supplib->name = driver_name;
4555*711890bcSjc156560 
4556*711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_version")) == NULL)
4557*711890bcSjc156560 		supplib->version = RDCFG_PLUGIN_V1;
4558*711890bcSjc156560 	else {
4559*711890bcSjc156560 		supplib->version = *((uint32_t *)sym);
4560*711890bcSjc156560 		if (supplib->version != RDCFG_PLUGIN_V1) {
4561*711890bcSjc156560 			(void) dlclose(supplib->lib_handle);
4562*711890bcSjc156560 			free(supplib);
4563*711890bcSjc156560 			return (NULL);
4564*711890bcSjc156560 		}
4565*711890bcSjc156560 	}
4566*711890bcSjc156560 
4567*711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_open_controller")) ==
4568*711890bcSjc156560 		NULL) {
4569*711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4570*711890bcSjc156560 		free(supplib);
4571*711890bcSjc156560 		return (NULL);
4572*711890bcSjc156560 	} else
4573*711890bcSjc156560 		supplib->open_controller = (int(*)(uint32_t, char **))sym;
4574*711890bcSjc156560 
4575*711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_close_controller")) ==
4576*711890bcSjc156560 		NULL) {
4577*711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4578*711890bcSjc156560 		free(supplib);
4579*711890bcSjc156560 		return (NULL);
4580*711890bcSjc156560 	} else
4581*711890bcSjc156560 		supplib->close_controller = (int (*)(uint32_t, char **))sym;
4582*711890bcSjc156560 
4583*711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_compnum")) == NULL) {
4584*711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4585*711890bcSjc156560 		free(supplib);
4586*711890bcSjc156560 		return (NULL);
4587*711890bcSjc156560 	} else
4588*711890bcSjc156560 		supplib->compnum = (int (*)(uint32_t, uint32_t,
4589*711890bcSjc156560 		    raid_obj_type_id_t, raid_obj_type_id_t))sym;
4590*711890bcSjc156560 
4591*711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_complist")) == NULL) {
4592*711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4593*711890bcSjc156560 		free(supplib);
4594*711890bcSjc156560 		return (NULL);
4595*711890bcSjc156560 	} else
4596*711890bcSjc156560 		supplib->complist = (int (*)(uint32_t, uint32_t,
4597*711890bcSjc156560 		    raid_obj_type_id_t, raid_obj_type_id_t, int, void *))sym;
4598*711890bcSjc156560 
4599*711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_get_attr")) == NULL) {
4600*711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4601*711890bcSjc156560 		free(supplib);
4602*711890bcSjc156560 		return (NULL);
4603*711890bcSjc156560 	} else
4604*711890bcSjc156560 		supplib->get_attr = (int (*)(uint32_t, uint32_t, uint32_t,
4605*711890bcSjc156560 		    raid_obj_type_id_t, void*))sym;
4606*711890bcSjc156560 
4607*711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_create")) == NULL) {
4608*711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4609*711890bcSjc156560 		free(supplib);
4610*711890bcSjc156560 		return (NULL);
4611*711890bcSjc156560 	} else
4612*711890bcSjc156560 		supplib->array_create = (int (*)(uint32_t, array_attr_t *, int,
4613*711890bcSjc156560 		    arraypart_attr_t *, char **))sym;
4614*711890bcSjc156560 
4615*711890bcSjc156560 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_delete")) == NULL) {
4616*711890bcSjc156560 		(void) dlclose(supplib->lib_handle);
4617*711890bcSjc156560 		free(supplib);
4618*711890bcSjc156560 		return (NULL);
4619*711890bcSjc156560 	} else
4620*711890bcSjc156560 		supplib->array_delete =
4621*711890bcSjc156560 		    (int (*)(uint32_t, uint32_t, char **))sym;
4622*711890bcSjc156560 
4623*711890bcSjc156560 	supplib->hsp_bind = (int (*)(uint32_t, uint32_t, hsp_relation_t *,
4624*711890bcSjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_bind");
4625*711890bcSjc156560 	supplib->hsp_unbind = (int (*)(uint32_t, uint32_t, hsp_relation_t *,
4626*711890bcSjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_unbind");
4627*711890bcSjc156560 	supplib->set_attr = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t *,
4628*711890bcSjc156560 	    char **))dlsym(supplib->lib_handle, "rdcfg_set_attr");
4629*711890bcSjc156560 	supplib->flash_fw = (int (*)(uint32_t, char *, uint32_t, char **))
4630*711890bcSjc156560 	    dlsym(supplib->lib_handle, "rdcfg_flash_fw");
4631*711890bcSjc156560 
4632*711890bcSjc156560 	supplib->next = raid_lib_sys;
4633*711890bcSjc156560 	raid_lib_sys = supplib;
4634*711890bcSjc156560 	return (supplib);
4635*711890bcSjc156560 }
4636*711890bcSjc156560 
4637*711890bcSjc156560 static raid_lib_t *
4638*711890bcSjc156560 raid_find_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t controller_obj_id)
4639*711890bcSjc156560 {
4640*711890bcSjc156560 	controller_attr_t *controller_attr;
4641*711890bcSjc156560 	raid_lib_t *raid_lib;
4642*711890bcSjc156560 	char *driver_name;
4643*711890bcSjc156560 	raid_obj_handle_t handle;
4644*711890bcSjc156560 
4645*711890bcSjc156560 	/* Check if it's mapped to handle structure */
4646*711890bcSjc156560 	handle = raid_obj_to_handle(raid_tab, controller_obj_id);
4647*711890bcSjc156560 	if (raid_handle_sys.handles[handle].raid_lib != NULL)
4648*711890bcSjc156560 		return (raid_handle_sys.handles[handle].raid_lib);
4649*711890bcSjc156560 
4650*711890bcSjc156560 	(void) obj_get_attr(raid_tab, controller_obj_id,
4651*711890bcSjc156560 		(void **)(&controller_attr));
4652*711890bcSjc156560 
4653*711890bcSjc156560 	/* Check if the plugin module is already loaded */
4654*711890bcSjc156560 	driver_name = controller_id_to_driver_name(
4655*711890bcSjc156560 		controller_attr->controller_id);
4656*711890bcSjc156560 	if (driver_name == NULL)
4657*711890bcSjc156560 		return (NULL);
4658*711890bcSjc156560 
4659*711890bcSjc156560 	raid_lib = raid_lib_sys;
4660*711890bcSjc156560 	while (raid_lib != NULL) {
4661*711890bcSjc156560 		if (raid_lib->name != NULL &&
4662*711890bcSjc156560 			strcmp(driver_name, raid_lib->name) == 0)
4663*711890bcSjc156560 			return (raid_lib);
4664*711890bcSjc156560 
4665*711890bcSjc156560 		raid_lib = raid_lib->next;
4666*711890bcSjc156560 	}
4667*711890bcSjc156560 
4668*711890bcSjc156560 	/* Loading the plugin module */
4669*711890bcSjc156560 	raid_lib = raid_plugin_load(driver_name);
4670*711890bcSjc156560 
4671*711890bcSjc156560 	return (raid_lib);
4672*711890bcSjc156560 }
4673