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