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