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