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