xref: /illumos-gate/usr/src/lib/libraidcfg/common/raidcfg.c (revision d62bc4badc1c1f1549c961cfb8b420e650e1272b)
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 	disk_tag_t *disk_tags;
3123 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3124 	raid_lib_t *raid_lib;
3125 	int i, j, ret, fd;
3126 	int disk_cnt = 0, disk_set_num = 0, set_num = 0, layer_cnt = 0;
3127 	uint64_t min_disk_capacity = 0;
3128 	uint32_t *diskid_list;
3129 
3130 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3131 	if (array_attr == NULL)
3132 		return (ERR_DEVICE_INVALID);
3133 
3134 	/* Check the disk layout expression */
3135 	if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
3136 	    disk_list[num_of_comp - 1] != OBJ_SEPARATOR_END)
3137 		return (ERR_ARRAY_LAYOUT);
3138 	for (i = 0; i < num_of_comp; ++i) {
3139 		if (disk_list[i] == OBJ_SEPARATOR_BEGIN) {
3140 			if (disk_cnt != 0)
3141 				return (ERR_ARRAY_LAYOUT);
3142 			++layer_cnt;
3143 			continue;
3144 		}
3145 		if (disk_list[i] == OBJ_SEPARATOR_END) {
3146 			if (disk_set_num == 0)
3147 				disk_set_num = disk_cnt;
3148 			else if (disk_set_num != disk_cnt && disk_cnt != 0)
3149 				return (ERR_ARRAY_LAYOUT);
3150 			disk_cnt = 0;
3151 			++set_num;
3152 			--layer_cnt;
3153 			continue;
3154 		}
3155 		switch (array_attr->raid_level) {
3156 		case RAID_LEVEL_0:
3157 		case RAID_LEVEL_1:
3158 		case RAID_LEVEL_1E:
3159 		case RAID_LEVEL_5:
3160 			if (layer_cnt != 1)
3161 				return (ERR_ARRAY_LAYOUT);
3162 			break;
3163 		case RAID_LEVEL_10:
3164 		case RAID_LEVEL_50:
3165 			if (layer_cnt != 2)
3166 				return (ERR_ARRAY_LAYOUT);
3167 			break;
3168 		default:
3169 			return (ERR_ARRAY_LEVEL);
3170 		}
3171 		++disk_cnt;
3172 	}
3173 
3174 	if (layer_cnt != 0)
3175 		return (ERR_ARRAY_LAYOUT);
3176 
3177 	switch (array_attr->raid_level) {
3178 	case RAID_LEVEL_0:
3179 		if (disk_set_num < 2 || set_num != 1)
3180 			return (ERR_ARRAY_LAYOUT);
3181 		break;
3182 	case RAID_LEVEL_1:
3183 		if (disk_set_num != 2 || set_num != 1)
3184 			return (ERR_ARRAY_LAYOUT);
3185 		break;
3186 	case RAID_LEVEL_1E:
3187 	case RAID_LEVEL_5:
3188 		if (disk_set_num < 3 || set_num != 1)
3189 			return (ERR_ARRAY_LAYOUT);
3190 		break;
3191 	case RAID_LEVEL_10:
3192 		if (disk_set_num != 2 || set_num < 2)
3193 			return (ERR_ARRAY_LAYOUT);
3194 		break;
3195 	case RAID_LEVEL_50:
3196 		if (disk_set_num < 3 || set_num < 2)
3197 			return (ERR_ARRAY_LAYOUT);
3198 		break;
3199 	default:
3200 		return (ERR_ARRAY_LEVEL);
3201 	}
3202 
3203 	arraypart_attrs = calloc(num_of_comp, sizeof (arraypart_attr_t));
3204 	if (arraypart_attrs == NULL)
3205 		return (ERR_NOMEM);
3206 
3207 	for (i = 0; i < num_of_comp; ++i) {
3208 		/* Keep seperators */
3209 		if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3210 			arraypart_attrs[i].disk_id =
3211 			    (uint32_t)OBJ_SEPARATOR_BEGIN;
3212 			continue;
3213 		}
3214 
3215 		if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3216 			arraypart_attrs[i].disk_id =
3217 			    (uint32_t)OBJ_SEPARATOR_END;
3218 			continue;
3219 		}
3220 
3221 		disk_cnt++;
3222 		/* Check if it's a disk */
3223 		if (raid_obj_get_type(raid_tab, *(disk_list + i)) !=
3224 		    OBJ_TYPE_DISK)
3225 			return (ERR_DEVICE_TYPE);
3226 
3227 		/* Check if it's duplicated with other disks */
3228 		for (j = 0; j < i; ++j)
3229 			if (*(disk_list + j) == *(disk_list + i)) {
3230 				free(arraypart_attrs);
3231 				return (ERR_DEVICE_DUP);
3232 			}
3233 
3234 		/* Check disk status */
3235 		ret = obj_get_attr(raid_tab, *(disk_list + i),
3236 		    (void **)(&disk_attr));
3237 		if (ret != SUCCESS)
3238 			return (ret);
3239 
3240 		if (disk_attr->state != DISK_STATE_GOOD) {
3241 			free(arraypart_attrs);
3242 			return (ERR_DISK_STATE);
3243 		}
3244 
3245 		/* All disks must belong to the same controller */
3246 		obj_id = obj_get_controller(raid_tab, *(disk_list + i));
3247 		if (obj_id <= OBJ_NONE)
3248 			return (obj_id);
3249 		if (controller_obj_id == OBJ_NONE) {
3250 			controller_obj_id = obj_id;
3251 			ret = obj_get_attr(raid_tab, controller_obj_id,
3252 			    (void **)(&controller_attr));
3253 		} else if (obj_id != controller_obj_id) {
3254 			free(arraypart_attrs);
3255 			return (ERR_DRIVER_ACROSS);
3256 		}
3257 
3258 		/* Check if the disk contains too many segments */
3259 		obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3260 		    OBJ_TYPE_DISK_SEG);
3261 		j = 0;
3262 		while (obj_id > OBJ_NONE) {
3263 			++j;
3264 			obj_id = obj_get_sibling(raid_tab, obj_id);
3265 		}
3266 		if (j > controller_attr->max_seg_per_disk) {
3267 			free(arraypart_attrs);
3268 			return (ERR_DISK_SEG_AMOUNT);
3269 		}
3270 
3271 		/* Check if controller is a hostraid controller */
3272 		if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3273 			/*
3274 			 * For hostraid, the first disk should
3275 			 * be with of minimum capacity
3276 			 */
3277 			if (min_disk_capacity == 0) {
3278 				min_disk_capacity = disk_attr->capacity;
3279 
3280 				/* Can not specify capacity for hostraid */
3281 				if (array_attr->capacity != 0) {
3282 					free(arraypart_attrs);
3283 					return (ERR_OP_ILLEGAL);
3284 				}
3285 			} else if (min_disk_capacity > disk_attr->capacity) {
3286 				free(arraypart_attrs);
3287 				return (ERR_DISK_SPACE);
3288 			}
3289 
3290 			/* Disk should not be used for hostraid */
3291 			obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3292 			    OBJ_TYPE_DISK_SEG);
3293 			if (obj_id < OBJ_NONE) {
3294 				free(arraypart_attrs);
3295 				return (obj_id);
3296 			} else if (obj_id > OBJ_NONE) {
3297 				free(arraypart_attrs);
3298 				return (ERR_DISK_NOT_EMPTY);
3299 			}
3300 		}
3301 
3302 		arraypart_attrs[i].disk_id = disk_attr->disk_id;
3303 		arraypart_attrs[i].offset = OBJ_ATTR_NONE;
3304 		arraypart_attrs[i].size = OBJ_ATTR_NONE;
3305 	}
3306 
3307 	/* Check if array amount exceeds limit */
3308 	if (controller_attr->max_array_num <=
3309 	    obj_controller_compnum(raid_tab, controller_obj_id,
3310 	    OBJ_TYPE_ARRAY))
3311 		return (ERR_ARRAY_AMOUNT);
3312 
3313 
3314 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3315 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3316 	if ((raid_lib == NULL) || (fd == 0))
3317 		return (ERR_DRIVER_CLOSED);
3318 
3319 	/* Check if the controller can support the array RAID level */
3320 	switch (array_attr->raid_level) {
3321 	case	RAID_LEVEL_0:
3322 		if (!(controller_attr->capability & RAID_CAP_RAID0)) {
3323 			free(arraypart_attrs);
3324 			return (ERR_ARRAY_LEVEL);
3325 		}
3326 		break;
3327 	case	RAID_LEVEL_1:
3328 		if (!(controller_attr->capability & RAID_CAP_RAID1)) {
3329 			free(arraypart_attrs);
3330 			return (ERR_ARRAY_LEVEL);
3331 		}
3332 		break;
3333 	case	RAID_LEVEL_1E:
3334 		if (!(controller_attr->capability & RAID_CAP_RAID1E)) {
3335 			free(arraypart_attrs);
3336 			return (ERR_ARRAY_LEVEL);
3337 		}
3338 		break;
3339 	case	RAID_LEVEL_5:
3340 		if (!(controller_attr->capability & RAID_CAP_RAID5)) {
3341 			free(arraypart_attrs);
3342 			return (ERR_ARRAY_LEVEL);
3343 		}
3344 		break;
3345 	case	RAID_LEVEL_10:
3346 		if (!(controller_attr->capability & RAID_CAP_RAID10)) {
3347 			free(arraypart_attrs);
3348 			return (ERR_ARRAY_LEVEL);
3349 		}
3350 		break;
3351 	case	RAID_LEVEL_50:
3352 		if (!(controller_attr->capability & RAID_CAP_RAID50)) {
3353 			free(arraypart_attrs);
3354 			return (ERR_ARRAY_LEVEL);
3355 		}
3356 		break;
3357 	default:
3358 		free(arraypart_attrs);
3359 		return (ERR_ARRAY_LEVEL);
3360 	}
3361 
3362 	/* Check if plug in can calculate the maximum size */
3363 	(void) memcpy(&array_attr2, array_attr, sizeof (array_attr_t));
3364 	array_attr2.capacity = OBJ_ATTR_NONE;
3365 	ret = raid_lib->array_create(controller_attr->controller_id,
3366 	    &array_attr2, num_of_comp, arraypart_attrs, plugin_err_str);
3367 
3368 	/* If plugin/driver will not calculate space */
3369 	if (ret == ERR_OP_NO_IMPL) {
3370 		/* Calculate the maximum capacity */
3371 		array_attr2.capacity = raid_space_noalign(raid_tab,
3372 		    array_attr2.raid_level, num_of_comp, disk_list,
3373 		    arraypart_attrs);
3374 
3375 		/*
3376 		 * If controller is capable to allocate space,
3377 		 * set offset and size attributes to OBJ_ATTR_NONE
3378 		 * and let the controller to determine these value
3379 		 */
3380 		if (controller_attr->capability & RAID_CAP_SMART_ALLOC)
3381 			for (i = 0; i < num_of_comp; ++i) {
3382 				arraypart_attrs[i].offset =
3383 				    OBJ_ATTR_NONE;
3384 				arraypart_attrs[i].size =
3385 				    OBJ_ATTR_NONE;
3386 			}
3387 
3388 		/* There's no enough space for specified capacity */
3389 		if (array_attr->capacity > array_attr2.capacity) {
3390 			free(arraypart_attrs);
3391 			return (ERR_ARRAY_SIZE);
3392 		}
3393 
3394 		/* capacity == 0, allocate maximum space */
3395 		if (array_attr->capacity == 0)
3396 			array_attr->capacity = array_attr2.capacity;
3397 	} else if (ret < SUCCESS) {
3398 		free(arraypart_attrs);
3399 		return (ret);
3400 	} else if (array_attr2.capacity < array_attr->capacity) {
3401 		/* Return the maximum size */
3402 		array_attr->capacity = array_attr2.capacity;
3403 		free(arraypart_attrs);
3404 		return (ERR_ARRAY_SIZE);
3405 	}
3406 
3407 	if (array_attr->capacity < ARRAYPART_MIN_SIZE * disk_cnt) {
3408 		free(arraypart_attrs);
3409 		return (ERR_ARRAY_SIZE);
3410 	}
3411 
3412 
3413 	ret = raid_lib->array_create(controller_attr->controller_id,
3414 	    array_attr, num_of_comp, arraypart_attrs, plugin_err_str);
3415 	free(arraypart_attrs);
3416 
3417 	if (ret != SUCCESS)
3418 		return (ret);
3419 
3420 	/* Add array object into device tree so that we can map the handle */
3421 	(void) raid_obj_add_org(raid_tab, array_obj_id, controller_obj_id);
3422 
3423 	/* unconfig disk minor nodes if it's hostraid */
3424 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3425 		diskid_list = (uint32_t *)calloc(num_of_comp,
3426 		    sizeof (uint32_t));
3427 		if (diskid_list == NULL) {
3428 			return (ERR_NOMEM);
3429 		}
3430 		disk_tags = (disk_tag_t *)calloc(num_of_comp,
3431 		    sizeof (disk_tag_t));
3432 		if (disk_tags == NULL) {
3433 			return (ERR_NOMEM);
3434 		}
3435 
3436 		for (i = 0; i < num_of_comp; ++i) {
3437 			if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3438 				diskid_list[i] = (uint32_t)OBJ_SEPARATOR_BEGIN;
3439 			} else if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3440 				diskid_list[i] = (uint32_t)OBJ_SEPARATOR_END;
3441 			} else {
3442 				ret = obj_get_attr(raid_tab, *(disk_list + i),
3443 				    (void **)(&disk_attr));
3444 				if (ret != SUCCESS) {
3445 					free(diskid_list);
3446 					return (ret);
3447 				}
3448 				diskid_list[i] = disk_attr->disk_id;
3449 				disk_tags[i] = disk_attr->tag;
3450 			}
3451 		}
3452 
3453 		for (i = 0; i < num_of_comp; ++i) {
3454 			if (diskid_list[i] == (uint32_t)OBJ_SEPARATOR_BEGIN ||
3455 			    diskid_list[i] == (uint32_t)OBJ_SEPARATOR_END) {
3456 				continue;
3457 			}
3458 
3459 			if ((disk_tags[i].cidl.target_id ==
3460 			    array_attr->tag.idl.target_id) &&
3461 			    (disk_tags[i].cidl.lun ==
3462 			    array_attr->tag.idl.lun))
3463 				continue;
3464 
3465 			ret = raid_dev_config(CFGA_CMD_UNCONFIGURE,
3466 			    controller_attr->controller_id, diskid_list[i], 0);
3467 			if (ret != SUCCESS) {
3468 				free(diskid_list);
3469 				free(disk_tags);
3470 				return (ret);
3471 			}
3472 		}
3473 		free(diskid_list);
3474 		free(disk_tags);
3475 	} else {
3476 		/* for HW raid */
3477 		ret = raid_dev_config(CFGA_CMD_CONFIGURE,
3478 		    controller_attr->controller_id, array_attr->array_id, 1);
3479 	}
3480 
3481 	return (ret);
3482 }
3483 
3484 static int
3485 obj_array_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3486 	char **plugin_err_str)
3487 {
3488 	raid_obj_id_t controller_obj_id;
3489 	controller_attr_t *controller_attr;
3490 	array_attr_t *array_attr;
3491 	arraypart_attr_t *arraypart_attr;
3492 	disk_attr_t *disk_attr;
3493 	raid_obj_id_t arraypart_obj_id;
3494 	raid_lib_t *raid_lib;
3495 	int i = 0, j = 0, ret, fd;
3496 	uint32_t *disk_ids = NULL;
3497 
3498 	controller_obj_id = obj_get_controller(raid_tab, array_obj_id);
3499 	if (controller_obj_id <= OBJ_NONE)
3500 		return (controller_obj_id);
3501 
3502 	ret = obj_get_attr(raid_tab, controller_obj_id,
3503 	    (void **)(&controller_attr));
3504 	if (ret < SUCCESS) {
3505 		return (ret);
3506 	}
3507 	ret = obj_get_attr(raid_tab, array_obj_id, (void **)(&array_attr));
3508 	if (ret < SUCCESS)
3509 		return (ret);
3510 
3511 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3512 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3513 	if ((raid_lib == NULL) || (fd == 0))
3514 		return (ERR_DRIVER_CLOSED);
3515 
3516 	/* change minor nodes state for disks */
3517 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3518 		arraypart_obj_id = obj_get_comp(raid_tab, array_obj_id,
3519 		    OBJ_TYPE_ARRAY_PART);
3520 		if (arraypart_obj_id < OBJ_NONE) {
3521 			return (arraypart_obj_id);
3522 		}
3523 
3524 		/*
3525 		 * Check how many disks in volume and malloc space for
3526 		 * disk_ids; note that the number should be the disk
3527 		 * number minors 1 since the primary disk should not
3528 		 * be counted in.
3529 		 */
3530 		while (arraypart_obj_id = obj_get_sibling(raid_tab,
3531 		    arraypart_obj_id)) {
3532 			if (arraypart_obj_id < OBJ_NONE)
3533 				return (arraypart_obj_id);
3534 			++i;
3535 		}
3536 		disk_ids = calloc(i, sizeof (uint32_t));
3537 		if (disk_ids == NULL)
3538 			return (ERR_NOMEM);
3539 
3540 		/* Stor all member disk ids into disk_ids */
3541 		arraypart_obj_id = obj_get_comp(raid_tab, array_obj_id,
3542 		    OBJ_TYPE_ARRAY_PART);
3543 
3544 		while (arraypart_obj_id > OBJ_NONE) {
3545 			ret = obj_get_attr(raid_tab, arraypart_obj_id,
3546 			    (void **)(&arraypart_attr));
3547 			if (ret != SUCCESS) {
3548 				return (ret);
3549 			}
3550 
3551 			ret = obj_get_attr(raid_tab, arraypart_obj_id,
3552 			    (void **)(&disk_attr));
3553 			if (ret != SUCCESS) {
3554 				return (ret);
3555 			}
3556 
3557 			if (array_attr->tag.idl.target_id ==
3558 			    disk_attr->tag.cidl.target_id &&
3559 			    array_attr->tag.idl.lun ==
3560 			    disk_attr->tag.cidl.target_id) {
3561 				arraypart_obj_id = obj_get_sibling(raid_tab,
3562 				    arraypart_obj_id);
3563 				continue;
3564 			}
3565 
3566 			disk_ids[j] = arraypart_attr->disk_id;
3567 			++j;
3568 			arraypart_obj_id = obj_get_sibling(raid_tab,
3569 			    arraypart_obj_id);
3570 		}
3571 	} else {
3572 		ret = raid_dev_config(CFGA_CMD_UNCONFIGURE,
3573 		    controller_attr->controller_id, array_attr->array_id, 1);
3574 		if (ret != SUCCESS)
3575 			return (ret);
3576 	}
3577 
3578 	ret = raid_lib->array_delete(controller_attr->controller_id,
3579 	    array_attr->array_id, plugin_err_str);
3580 	if (ret < SUCCESS) {
3581 		if (disk_ids)
3582 			free(disk_ids);
3583 		return (ret);
3584 	}
3585 
3586 	if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3587 		for (i = 0; i < j; ++i)
3588 			ret = raid_dev_config(CFGA_CMD_CONFIGURE,
3589 			    controller_attr->controller_id,
3590 			    disk_ids[i], 0);
3591 			if (ret == ERR_ARRAY_CONFIG)
3592 				ret = SUCCESS;
3593 			else if (ret < SUCCESS) {
3594 				free(disk_ids);
3595 				return (ret);
3596 			}
3597 	}
3598 
3599 	if (disk_ids)
3600 		free(disk_ids);
3601 	return (ret);
3602 }
3603 
3604 static int
3605 obj_hsp_bind(raid_obj_tab_t *raid_tab, int num, raid_obj_id_t *obj_ids,
3606 	char **plugin_err_str)
3607 {
3608 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3609 	raid_obj_id_t array_obj_id, disk_obj_id;
3610 	hsp_relation_t *hsp_relation;
3611 	controller_attr_t *controller_attr;
3612 	array_attr_t *array_attr;
3613 	arraypart_attr_t *arraypart_attr;
3614 	disk_attr_t *disk_attr;
3615 	diskseg_attr_t *diskseg_attr;
3616 	hsp_attr_t *hsp_attr;
3617 	raid_lib_t *raid_lib;
3618 	int ret, fd, i, j = 0;
3619 
3620 	hsp_relation = malloc(sizeof (hsp_relation_t) * num);
3621 	if (hsp_relation == NULL)
3622 		return (ERR_NOMEM);
3623 
3624 	for (i = 0; i < num; ++i) {
3625 		array_obj_id = *(obj_ids + i * 2);
3626 		disk_obj_id = *(obj_ids + i * 2 + 1);
3627 
3628 		if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK ||
3629 		    (array_obj_id != OBJ_ATTR_NONE &&
3630 		    raid_obj_get_type(raid_tab, array_obj_id) !=
3631 		    OBJ_TYPE_ARRAY)) {
3632 			free(hsp_relation);
3633 			return (ERR_DEVICE_TYPE);
3634 		}
3635 
3636 		/* Get controller attributes */
3637 		if (controller_obj_id == OBJ_NONE)
3638 			controller_obj_id = obj_get_controller(raid_tab,
3639 			    disk_obj_id);
3640 		else if (controller_obj_id != obj_get_controller(raid_tab,
3641 		    disk_obj_id)) {
3642 			free(hsp_relation);
3643 			return (ERR_DRIVER_ACROSS);
3644 		}
3645 
3646 		ret = obj_get_attr(raid_tab, controller_obj_id,
3647 		    (void **)(&controller_attr));
3648 
3649 		/* Get disk attributes */
3650 		ret = obj_get_attr(raid_tab,  disk_obj_id,
3651 		    (void **)(&disk_attr));
3652 		if (disk_attr->state == DISK_STATE_FAILED) {
3653 			free(hsp_relation);
3654 			return (ERR_DISK_STATE);
3655 		}
3656 
3657 		/* If it's not a hsp disk, check if there's occupied space */
3658 		if (obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP) ==
3659 		    OBJ_NONE) {
3660 			obj_id = obj_get_comp(raid_tab, disk_obj_id,
3661 			    OBJ_TYPE_DISK_SEG);
3662 			while (obj_id != OBJ_NONE) {
3663 				ret = obj_get_attr(raid_tab, obj_id,
3664 				    (void **)(&diskseg_attr));
3665 				if (!(diskseg_attr->state &
3666 				    DISKSEG_STATE_RESERVED)) {
3667 					free(hsp_relation);
3668 					return (ERR_DISK_NOT_EMPTY);
3669 				}
3670 				obj_id = obj_get_sibling(raid_tab, obj_id);
3671 			}
3672 		}
3673 
3674 		if (array_obj_id != OBJ_ATTR_NONE) {
3675 			/* If local hsp is supported */
3676 			if (!(controller_attr->capability & RAID_CAP_L_HSP)) {
3677 				free(hsp_relation);
3678 				return (ERR_OP_ILLEGAL);
3679 			}
3680 
3681 			if (raid_obj_get_type(raid_tab, array_obj_id) !=
3682 			    OBJ_TYPE_ARRAY) {
3683 				free(hsp_relation);
3684 				return (ERR_DEVICE_TYPE);
3685 			}
3686 
3687 			/* Get array attributes */
3688 			ret = obj_get_attr(raid_tab, array_obj_id,
3689 			    (void **)(&array_attr));
3690 			/* RAID 0 array can not use hsp */
3691 			if (array_attr->raid_level == RAID_LEVEL_0) {
3692 				free(hsp_relation);
3693 				return (ERR_ARRAY_LEVEL);
3694 			}
3695 
3696 			/* If It's belong to another controller */
3697 			if (controller_obj_id != obj_get_controller(raid_tab,
3698 			    array_obj_id)) {
3699 				free(hsp_relation);
3700 				return (ERR_DRIVER_ACROSS);
3701 			}
3702 
3703 			/* Get an array part attributes */
3704 			if ((array_attr->raid_level == RAID_LEVEL_10) ||
3705 			    (array_attr->raid_level == RAID_LEVEL_50))
3706 				obj_id = obj_get_comp(raid_tab, array_obj_id,
3707 				    OBJ_TYPE_ARRAY);
3708 			else
3709 				obj_id = array_obj_id;
3710 			obj_id = obj_get_comp(raid_tab, obj_id,
3711 			    OBJ_TYPE_ARRAY_PART);
3712 			ret = obj_get_attr(raid_tab, obj_id,
3713 			    (void **)(&arraypart_attr));
3714 
3715 			/* Check if disk space is enough for array */
3716 			if (arraypart_attr->size > disk_attr->capacity) {
3717 				free(hsp_relation);
3718 				return (ERR_DISK_SPACE);
3719 			}
3720 			if (controller_attr->capability & RAID_CAP_ARRAY_ALIGN)
3721 				if ((arraypart_attr->size +
3722 				    arraypart_attr->offset) >
3723 				    disk_attr->capacity) {
3724 				free(hsp_relation);
3725 				return (ERR_DISK_SPACE);
3726 				}
3727 		} else if (!(controller_attr->capability & RAID_CAP_G_HSP)) {
3728 			/* if global hsp is supported */
3729 			free(hsp_relation);
3730 			return (ERR_OP_ILLEGAL);
3731 		}
3732 
3733 		/*
3734 		 * If the array is already associated with the
3735 		 * local hsp, or it's a global hsp, ignore it
3736 		 */
3737 		obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3738 		if (obj_id > OBJ_NONE) {
3739 			if (obj_get_attr(raid_tab, obj_id,
3740 			    (void **)&hsp_attr) >= SUCCESS) {
3741 				if (((hsp_attr->type == HSP_TYPE_GLOBAL) &&
3742 				    (array_obj_id != OBJ_ATTR_NONE)) ||
3743 				    ((hsp_attr->type == HSP_TYPE_LOCAL) &&
3744 				    (array_obj_id == OBJ_ATTR_NONE))) {
3745 					free(hsp_relation);
3746 					return (ERR_OP_ILLEGAL);
3747 				}
3748 			}
3749 		}
3750 
3751 		if (array_obj_id != OBJ_ATTR_NONE)
3752 			hsp_relation[j].array_id = array_attr->array_id;
3753 		else
3754 			hsp_relation[j].array_id = (uint32_t)OBJ_ATTR_NONE;
3755 		hsp_relation[j].disk_id = disk_attr->disk_id;
3756 		++ j;
3757 	}
3758 
3759 
3760 	if (j == 0)
3761 		return (SUCCESS);
3762 
3763 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3764 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3765 	if ((raid_lib == NULL) || (fd == 0))
3766 		return (ERR_DRIVER_CLOSED);
3767 
3768 	if (raid_lib->hsp_bind == NULL) {
3769 		free(hsp_relation);
3770 		return (ERR_OP_NO_IMPL);
3771 	}
3772 
3773 	ret = raid_lib->hsp_bind(controller_attr->controller_id,
3774 	    j, hsp_relation, plugin_err_str);
3775 
3776 	free(hsp_relation);
3777 	return (ret);
3778 }
3779 
3780 static int
3781 obj_hsp_unbind(raid_obj_tab_t *raid_tab, int num, raid_obj_id_t *obj_ids,
3782 	char **plugin_err_str)
3783 {
3784 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3785 	raid_obj_id_t array_obj_id, disk_obj_id;
3786 	hsp_relation_t *hsp_relation;
3787 	controller_attr_t *controller_attr;
3788 	array_attr_t *array_attr;
3789 	disk_attr_t *disk_attr;
3790 	hsp_attr_t *hsp_attr;
3791 	raid_lib_t *raid_lib;
3792 	int ret, fd, i, j = 0;
3793 
3794 	hsp_relation = malloc(sizeof (hsp_relation_t) * num);
3795 	if (hsp_relation == NULL)
3796 		return (ERR_NOMEM);
3797 
3798 	for (i = 0; i < num; ++i) {
3799 		array_obj_id = *(obj_ids + i * 2);
3800 		disk_obj_id = *(obj_ids + i * 2 + 1);
3801 
3802 		if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK) {
3803 			free(hsp_relation);
3804 			return (ERR_DEVICE_TYPE);
3805 		}
3806 
3807 		/* Get controller attributes */
3808 		if (controller_obj_id == OBJ_NONE)
3809 			controller_obj_id = obj_get_controller(raid_tab,
3810 			    disk_obj_id);
3811 		else if (controller_obj_id != obj_get_controller(raid_tab,
3812 		    disk_obj_id)) {
3813 			free(hsp_relation);
3814 			return (ERR_DRIVER_ACROSS);
3815 		}
3816 
3817 		ret = obj_get_attr(raid_tab, controller_obj_id,
3818 		    (void **)(&controller_attr));
3819 
3820 		/* Get disk attributes */
3821 		ret = obj_get_attr(raid_tab,  disk_obj_id,
3822 		    (void **)(&disk_attr));
3823 		if (disk_attr->state == DISK_STATE_FAILED) {
3824 			free(hsp_relation);
3825 			return (ERR_DISK_STATE);
3826 		}
3827 
3828 		/* If it's not a hsp disk */
3829 		obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3830 		if (obj_id == OBJ_NONE) {
3831 			free(hsp_relation);
3832 			return (ERR_DISK_STATE);
3833 		}
3834 		ret = obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
3835 
3836 		if (array_obj_id != OBJ_ATTR_NONE) {
3837 			if (raid_obj_get_type(raid_tab, array_obj_id) !=
3838 			    OBJ_TYPE_ARRAY) {
3839 				free(hsp_relation);
3840 				return (ERR_DEVICE_TYPE);
3841 			}
3842 
3843 			/* Get array attributes */
3844 			ret = obj_get_attr(raid_tab, array_obj_id,
3845 			    (void **)(&array_attr));
3846 
3847 			/* If It's belong to another controller */
3848 			if (controller_obj_id != obj_get_controller(raid_tab,
3849 			    array_obj_id)) {
3850 				free(hsp_relation);
3851 				return (ERR_DRIVER_ACROSS);
3852 			}
3853 
3854 			/* If want to remove an array from a global hsp */
3855 			if (hsp_attr->type == HSP_TYPE_GLOBAL) {
3856 				free(hsp_relation);
3857 				return (ERR_OP_ILLEGAL);
3858 			}
3859 
3860 			do {
3861 				(void) obj_get_attr(raid_tab, obj_id,
3862 				    (void **)(&hsp_attr));
3863 
3864 				if (hsp_attr->associated_id ==
3865 				    array_attr->array_id ||
3866 				    hsp_attr->type == HSP_TYPE_GLOBAL)
3867 					break;
3868 
3869 				obj_id = obj_get_sibling(raid_tab, obj_id);
3870 			} while (obj_id > OBJ_NONE);
3871 		} else if (hsp_attr->type != HSP_TYPE_GLOBAL) {
3872 			/* if global hsp is supported */
3873 			free(hsp_relation);
3874 			return (ERR_OP_ILLEGAL);
3875 		}
3876 
3877 		/*
3878 		 * If array is associated with a local hsp, or remove a
3879 		 * global hsp disk
3880 		 */
3881 		if ((obj_id && (array_obj_id != OBJ_ATTR_NONE)) ||
3882 		    (array_obj_id == OBJ_ATTR_NONE)) {
3883 			if (array_obj_id != OBJ_ATTR_NONE)
3884 				hsp_relation[j].array_id = array_attr->array_id;
3885 			else
3886 				hsp_relation[j].array_id =
3887 				    (uint32_t)OBJ_ATTR_NONE;
3888 			hsp_relation[j].disk_id = disk_attr->disk_id;
3889 			++ j;
3890 		} else {
3891 			free(hsp_relation);
3892 			return (ERR_OP_ILLEGAL);
3893 		}
3894 	}
3895 
3896 
3897 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3898 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3899 	if ((raid_lib == NULL) || (fd == 0))
3900 		return (ERR_DRIVER_CLOSED);
3901 
3902 	if (raid_lib->hsp_unbind == NULL) {
3903 		free(hsp_relation);
3904 		return (ERR_OP_NO_IMPL);
3905 	}
3906 
3907 	ret = raid_lib->hsp_unbind(controller_attr->controller_id,
3908 	    j, hsp_relation, plugin_err_str);
3909 
3910 	free(hsp_relation);
3911 	return (ret);
3912 }
3913 
3914 /*
3915  * Object maintennance routines
3916  */
3917 static int
3918 raid_obj_create_system_obj(raid_obj_tab_t *raid_tab)
3919 {
3920 	raid_obj_t *raid_obj;
3921 	int ret;
3922 
3923 	raid_obj = calloc(1, sizeof (raid_obj_t));
3924 	if (raid_obj == NULL)
3925 		return (ERR_NOMEM);
3926 
3927 	raid_obj->obj_id = OBJ_SYSTEM;
3928 	raid_obj->obj_type_id = OBJ_TYPE_SYSTEM;
3929 	raid_obj->data = NULL;
3930 
3931 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3932 	if (ret == ERR_DEVICE_DUP) {
3933 		free(raid_obj);
3934 		return (ERR_DEVICE_UNCLEAN);
3935 	}
3936 
3937 	return (SUCCESS);
3938 }
3939 
3940 static raid_obj_id_t
3941 raid_obj_id_new(raid_obj_tab_t *raid_tab)
3942 {
3943 	++ raid_tab->obj_id_cnt;
3944 	if (raid_tab->obj_id_cnt <= 0)
3945 		return (ERR_DEVICE_OVERFLOW);
3946 
3947 	return (raid_tab->obj_id_cnt);
3948 }
3949 
3950 static void *
3951 raid_obj_attr_new(raid_obj_type_id_t obj_type)
3952 {
3953 	void *obj_attr = NULL;
3954 
3955 	switch (obj_type) {
3956 	case	OBJ_TYPE_CONTROLLER:
3957 		obj_attr = calloc(1, sizeof (controller_attr_t));
3958 		break;
3959 	case	OBJ_TYPE_ARRAY:
3960 		obj_attr = calloc(1, sizeof (array_attr_t));
3961 		break;
3962 	case	OBJ_TYPE_DISK:
3963 		obj_attr = calloc(1, sizeof (disk_attr_t));
3964 		break;
3965 	case	OBJ_TYPE_HSP:
3966 		obj_attr = calloc(1, sizeof (hsp_attr_t));
3967 		break;
3968 	case	OBJ_TYPE_ARRAY_PART:
3969 		obj_attr = calloc(1, sizeof (arraypart_attr_t));
3970 		break;
3971 	case	OBJ_TYPE_DISK_SEG:
3972 		obj_attr = calloc(1, sizeof (diskseg_attr_t));
3973 		break;
3974 	case	OBJ_TYPE_TASK:
3975 		obj_attr = calloc(1, sizeof (task_attr_t));
3976 		break;
3977 	default:
3978 		break;
3979 	}
3980 
3981 	return (obj_attr);
3982 }
3983 
3984 static raid_obj_id_t
3985 raid_obj_create(raid_obj_tab_t *raid_tab, raid_obj_type_id_t obj_type)
3986 {
3987 	raid_obj_t *raid_obj;
3988 	int ret;
3989 	void *data_ptr;
3990 
3991 	raid_obj = calloc(1, sizeof (raid_obj_t));
3992 	if (raid_obj == NULL)
3993 		return (ERR_NOMEM);
3994 
3995 	raid_obj->obj_id = raid_obj_id_new(raid_tab);
3996 	if (raid_obj->obj_id < OBJ_NONE)
3997 		return (ERR_DEVICE_OVERFLOW);
3998 
3999 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
4000 	if (ret == ERR_DEVICE_DUP) {
4001 		free(raid_obj);
4002 		return (ERR_DEVICE_DUP);
4003 	}
4004 
4005 	data_ptr = raid_obj_attr_new(obj_type);
4006 	if (data_ptr == NULL) {
4007 		(void) raid_obj_delete(raid_tab, raid_obj->obj_id);
4008 		return (ERR_NOMEM);
4009 	}
4010 
4011 	(void) raid_obj_set_data_ptr(raid_tab, raid_obj->obj_id, data_ptr);
4012 
4013 	(void) raid_obj_set_type(raid_tab, raid_obj->obj_id, obj_type);
4014 	return (raid_obj->obj_id);
4015 }
4016 
4017 static int
4018 raid_obj_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t raid_obj_id)
4019 {
4020 	raid_obj_t *obj;
4021 
4022 	obj = raid_obj_tab_remove(raid_tab, raid_obj_id);
4023 	if (obj != NULL) {
4024 		free(obj->data);
4025 		free(obj);
4026 		return (SUCCESS);
4027 	}
4028 
4029 	return (ERR_DEVICE_NOENT);
4030 }
4031 
4032 static int
4033 raid_obj_add_org(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4034 	raid_obj_id_t container_id)
4035 {
4036 	raid_obj_id_t tmp, tmp1;
4037 
4038 	tmp = raid_obj_get_comp(raid_tab, container_id);
4039 	if (tmp < OBJ_NONE)
4040 		return (ERR_DEVICE_NOENT);
4041 
4042 	if (tmp == OBJ_NONE) {
4043 		(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4044 		(void) raid_obj_set_comp(raid_tab, container_id, obj_id);
4045 		return (SUCCESS);
4046 	}
4047 
4048 	while ((tmp1 = raid_obj_get_sibling(raid_tab, tmp)) != OBJ_NONE)
4049 		tmp = tmp1;
4050 
4051 	if (raid_obj_set_sibling(raid_tab, tmp, obj_id) < SUCCESS)
4052 		return (ERR_DEVICE_NOENT);
4053 	(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4054 
4055 	return (SUCCESS);
4056 }
4057 
4058 static raid_obj_type_id_t
4059 raid_obj_get_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
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 ((obj->obj_type_id < OBJ_TYPE_SYSTEM) ||
4068 	    (obj->obj_type_id >= OBJ_TYPE_ALL))
4069 		return (ERR_DEVICE_INVALID);
4070 
4071 	return (obj->obj_type_id);
4072 }
4073 
4074 static int
4075 raid_obj_set_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4076 	raid_obj_type_id_t type)
4077 {
4078 	raid_obj_t *obj;
4079 
4080 	obj = raid_obj_tab_find(raid_tab, obj_id);
4081 	if (obj == NULL)
4082 		return (ERR_DEVICE_NOENT);
4083 
4084 	if ((type < OBJ_TYPE_SYSTEM) || (type >= OBJ_TYPE_ALL))
4085 		return (ERR_DEVICE_TYPE);
4086 
4087 	obj->obj_type_id = type;
4088 	return (SUCCESS);
4089 }
4090 
4091 static raid_obj_status_t
4092 raid_obj_get_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4093 {
4094 	raid_obj_t *obj;
4095 
4096 	obj = raid_obj_tab_find(raid_tab, obj_id);
4097 	if (obj == NULL)
4098 		return (ERR_DEVICE_NOENT);
4099 
4100 	return (obj->status);
4101 }
4102 
4103 static int
4104 raid_obj_set_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4105 	raid_obj_status_t status)
4106 {
4107 	raid_obj_t *obj;
4108 
4109 	obj = raid_obj_tab_find(raid_tab, obj_id);
4110 	if (obj == NULL)
4111 		return (ERR_DEVICE_NOENT);
4112 
4113 	obj->status = obj->status | status;
4114 
4115 	return (SUCCESS);
4116 }
4117 
4118 static int
4119 raid_obj_clear_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4120 	raid_obj_status_t status)
4121 {
4122 	raid_obj_t *obj;
4123 
4124 	obj = raid_obj_tab_find(raid_tab, obj_id);
4125 	if (obj == NULL)
4126 		return (ERR_DEVICE_NOENT);
4127 
4128 	obj->status = obj->status & ~status;
4129 
4130 	return (SUCCESS);
4131 }
4132 
4133 static raid_obj_id_t
4134 raid_obj_get_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4135 {
4136 	raid_obj_t *obj;
4137 
4138 	obj = raid_obj_tab_find(raid_tab, obj_id);
4139 	if (obj == NULL)
4140 		return (ERR_DEVICE_NOENT);
4141 
4142 	return (obj->container);
4143 }
4144 
4145 static int
4146 raid_obj_set_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4147 	raid_obj_id_t container_id)
4148 {
4149 	raid_obj_t *obj;
4150 
4151 	obj = raid_obj_tab_find(raid_tab, obj_id);
4152 	if (obj == NULL)
4153 		return (ERR_DEVICE_NOENT);
4154 
4155 	obj->container = container_id;
4156 	return (SUCCESS);
4157 }
4158 
4159 static raid_obj_id_t
4160 raid_obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4161 {
4162 	raid_obj_t *obj;
4163 
4164 	obj = raid_obj_tab_find(raid_tab, obj_id);
4165 	if (obj == NULL)
4166 		return (ERR_DEVICE_NOENT);
4167 
4168 	return (obj->component);
4169 }
4170 
4171 static int
4172 raid_obj_set_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4173 	raid_obj_id_t comp)
4174 {
4175 	raid_obj_t *obj;
4176 
4177 	obj = raid_obj_tab_find(raid_tab, obj_id);
4178 	if (obj == NULL)
4179 		return (ERR_DEVICE_NOENT);
4180 
4181 	obj->component = comp;
4182 	return (SUCCESS);
4183 }
4184 
4185 static raid_obj_id_t
4186 raid_obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4187 {
4188 	raid_obj_t *obj;
4189 
4190 	obj = raid_obj_tab_find(raid_tab, obj_id);
4191 	if (obj == NULL)
4192 		return (ERR_DEVICE_NOENT);
4193 
4194 	return (obj->sibling);
4195 }
4196 
4197 static int
4198 raid_obj_set_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4199 	raid_obj_id_t sibling)
4200 {
4201 	raid_obj_t *obj;
4202 
4203 	obj = raid_obj_tab_find(raid_tab, obj_id);
4204 	if (obj == NULL)
4205 		return (ERR_DEVICE_NOENT);
4206 
4207 	obj->sibling = sibling;
4208 
4209 	return (SUCCESS);
4210 }
4211 
4212 static void *
4213 raid_obj_get_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4214 {
4215 	raid_obj_t *obj;
4216 
4217 	obj = raid_obj_tab_find(raid_tab, obj_id);
4218 	if (obj == NULL)
4219 		return (NULL);
4220 
4221 	return (obj->data);
4222 }
4223 
4224 static int
4225 raid_obj_set_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4226 	void *data)
4227 {
4228 	raid_obj_t *obj;
4229 
4230 	obj = raid_obj_tab_find(raid_tab, obj_id);
4231 	if (obj == NULL)
4232 		return (ERR_DEVICE_NOENT);
4233 
4234 	obj->data = data;
4235 
4236 	return (SUCCESS);
4237 }
4238 
4239 static raid_obj_handle_t
4240 raid_obj_get_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4241 {
4242 	raid_obj_t *obj;
4243 
4244 	obj = raid_obj_tab_find(raid_tab, obj_id);
4245 	if (obj == NULL)
4246 		return (ERR_DEVICE_NOENT);
4247 
4248 	return (obj->handle);
4249 }
4250 
4251 static int
4252 raid_obj_set_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4253 	raid_obj_handle_t handle)
4254 {
4255 	raid_obj_t *obj;
4256 
4257 	obj = raid_obj_tab_find(raid_tab, obj_id);
4258 	if (obj == NULL)
4259 		return (ERR_DEVICE_NOENT);
4260 
4261 	obj->handle = handle;
4262 	return (SUCCESS);
4263 }
4264 /*
4265  * Object list maintennance routines
4266  */
4267 static void
4268 raid_list_create(raid_list_t *list, size_t offset)
4269 {
4270 	list->head = NULL;
4271 	list->tail = NULL;
4272 	list->offset = offset;
4273 }
4274 
4275 static void *
4276 raid_list_head(raid_list_t *list)
4277 {
4278 	return (list->head);
4279 }
4280 
4281 static void *
4282 raid_list_next(raid_list_t *list, void *obj)
4283 {
4284 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj);
4285 
4286 	return (el->next);
4287 }
4288 
4289 static void
4290 raid_list_insert_tail(raid_list_t *list, void *obj)
4291 {
4292 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4293 
4294 	el->prev = list->tail;
4295 	list->tail = obj;
4296 
4297 	el->next = NULL;
4298 
4299 	if (list->head == NULL)
4300 		list->head = obj;
4301 
4302 	if (el->prev != NULL) {
4303 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4304 		el1->next = obj;
4305 	}
4306 }
4307 
4308 static void
4309 raid_list_remove(raid_list_t *list, void *obj)
4310 {
4311 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4312 
4313 	if (list->head == obj)
4314 		list->head = el->next;
4315 
4316 	if (list->tail == obj)
4317 		list->tail = el->prev;
4318 
4319 	if (el->next != NULL) {
4320 		el1 = LIST_OBJ_TO_EL(list, el->next);
4321 		el1->prev = el->prev;
4322 	}
4323 
4324 	if (el->prev != NULL) {
4325 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4326 		el1->next = el->next;
4327 	}
4328 
4329 	el->prev = el->next = NULL;
4330 }
4331 
4332 static void *
4333 raid_list_remove_head(raid_list_t *list)
4334 {
4335 	void *obj = list->head;
4336 
4337 	if (obj != NULL)
4338 		raid_list_remove(list, obj);
4339 
4340 	return (obj);
4341 }
4342 
4343 static void *
4344 raid_list_find(raid_list_t *list, raid_obj_id_t obj_id)
4345 {
4346 	raid_obj_t *obj;
4347 
4348 	for (obj = raid_list_head(list); obj != NULL;
4349 	    obj = raid_list_next(list, obj))
4350 			if (obj->obj_id == obj_id)
4351 				break;
4352 
4353 	return (obj);
4354 }
4355 
4356 static int
4357 raid_obj_tab_create(raid_obj_tab_t *tab, size_t hash_slots)
4358 {
4359 	unsigned i;
4360 
4361 	if (hash_slots == 0)
4362 		return (ERR_OP_ILLEGAL);
4363 
4364 	tab->slots = hash_slots;
4365 
4366 	if ((tab->table = calloc(hash_slots, sizeof (raid_list_t))) == NULL)
4367 		return (ERR_NOMEM);
4368 
4369 	for (i = 0; i < hash_slots; i++)
4370 		raid_list_create(&tab->table[i], offsetof(raid_obj_t, el));
4371 
4372 	return (SUCCESS);
4373 }
4374 
4375 static void
4376 raid_obj_tab_destroy(raid_obj_tab_t *tab)
4377 {
4378 	unsigned i;
4379 
4380 	for (i = 0; i < tab->slots; i++) {
4381 		struct raid_obj_t *obj;
4382 
4383 		while ((obj = raid_list_remove_head(&tab->table[i])) != NULL)
4384 			free(obj);
4385 
4386 		raid_list_destroy(&tab->table[i]);
4387 	}
4388 
4389 	if (tab->table)
4390 		free(tab->table);
4391 
4392 	tab->table = NULL;
4393 	tab->slots = 0;
4394 	tab->obj_id_cnt = 0;
4395 }
4396 
4397 static int
4398 raid_obj_tab_insert(raid_obj_tab_t *tab, raid_obj_id_t id, void *obj)
4399 {
4400 	raid_list_t *list;
4401 
4402 	list = OBJ_TAB_SLOT(tab, id);
4403 
4404 	if (raid_list_find(list, id) != NULL)
4405 		return (ERR_DEVICE_DUP);
4406 
4407 	raid_list_insert_tail(list, obj);
4408 
4409 	return (SUCCESS);
4410 }
4411 
4412 static void *
4413 raid_obj_tab_remove(raid_obj_tab_t *tab, raid_obj_id_t id)
4414 {
4415 	raid_list_t *list;
4416 	raid_obj_t *obj;
4417 
4418 	list = OBJ_TAB_SLOT(tab, id);
4419 
4420 	if ((obj = raid_list_find(list, id)) != NULL)
4421 		raid_list_remove(list, obj);
4422 
4423 	return (obj);
4424 }
4425 
4426 static void *
4427 raid_obj_tab_find(raid_obj_tab_t *tab, raid_obj_id_t id)
4428 {
4429 	raid_list_t *list;
4430 	raid_obj_t *obj;
4431 
4432 	list = OBJ_TAB_SLOT(tab, id);
4433 	obj = raid_list_find(list, id);
4434 
4435 	return (obj);
4436 }
4437 
4438 static void
4439 raid_list_destroy(raid_list_t *list)
4440 {
4441 	list->head = NULL;
4442 	list->tail = NULL;
4443 	list->offset = 0;
4444 }
4445 
4446 /*
4447  * Plug-in maintennance routines
4448  */
4449 static int
4450 controller_id_to_path(uint32_t controller_id, char *path)
4451 {
4452 	char buf[MAX_PATH_LEN] = {0}, buf1[MAX_PATH_LEN] = {0}, *colon;
4453 
4454 	(void) snprintf(buf, MAX_PATH_LEN, "%s/c%d", CFGDIR, controller_id);
4455 	if (readlink(buf, buf1, sizeof (buf1)) < 0)
4456 		return (ERR_DRIVER_NOT_FOUND);
4457 
4458 	if (buf1[0] != '/')
4459 		(void) snprintf(buf, sizeof (buf), "%s/", CFGDIR);
4460 	else
4461 		buf[0] = 0;
4462 	(void) strlcat(buf, buf1, MAX_PATH_LEN);
4463 
4464 	colon = strrchr(buf, ':');
4465 	if (colon == NULL)
4466 		return (ERR_DRIVER_NOT_FOUND);
4467 	else
4468 		*colon = 0;
4469 
4470 	(void) snprintf(path, MAX_PATH_LEN, "%s:devctl", buf);
4471 
4472 	if (access(path, F_OK) < 0)
4473 		return (ERR_DRIVER_NOT_FOUND);
4474 
4475 	return (SUCCESS);
4476 }
4477 
4478 static char *
4479 controller_id_to_driver_name(uint32_t controller_id)
4480 {
4481 	char buf[MAX_PATH_LEN];
4482 	di_node_t di_node;
4483 	char *name, *tmp;
4484 	int ret;
4485 
4486 	ret = controller_id_to_path(controller_id, buf);
4487 	if (ret < SUCCESS)
4488 		return (NULL);
4489 
4490 	tmp = strrchr(buf, ':');
4491 	if (tmp != NULL)
4492 		*tmp = 0;
4493 
4494 	tmp = strstr(buf, "pci");
4495 	if (tmp == NULL)
4496 		return (NULL);
4497 
4498 	di_node = di_init(tmp, DINFOPROP);
4499 	if (di_node == DI_NODE_NIL)
4500 		return (NULL);
4501 
4502 	name = di_driver_name(di_node);
4503 
4504 	return (name);
4505 }
4506 
4507 static void
4508 raid_plugin_init()
4509 {
4510 	raid_lib_t *raid_lib = raid_lib_sys;
4511 
4512 	while (raid_lib) {
4513 		raid_lib_sys = raid_lib->next;
4514 		(void) dlclose(raid_lib->lib_handle);
4515 		free(raid_lib);
4516 		raid_lib = raid_lib_sys;
4517 	}
4518 }
4519 
4520 static raid_lib_t *
4521 raid_plugin_load(char *driver_name)
4522 {
4523 	char buf[MAX_PATH_LEN] = {0};
4524 	raid_lib_t *supplib;
4525 	void *sym;
4526 
4527 	supplib = calloc(1, sizeof (raid_lib_t));
4528 	if (supplib == NULL)
4529 		return (NULL);
4530 
4531 	(void) snprintf(buf, MAX_PATH_LEN, "%s/%s.so.1",
4532 	    SUPP_PLUGIN_DIR, driver_name);
4533 
4534 	supplib->lib_handle = dlopen(buf, RTLD_LAZY);
4535 	if (supplib->lib_handle == NULL) {
4536 		free(supplib);
4537 		return (NULL);
4538 	}
4539 
4540 	supplib->name = driver_name;
4541 
4542 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_version")) == NULL)
4543 		supplib->version = RDCFG_PLUGIN_V1;
4544 	else {
4545 		supplib->version = *((uint32_t *)sym);
4546 		if (supplib->version != RDCFG_PLUGIN_V1) {
4547 			(void) dlclose(supplib->lib_handle);
4548 			free(supplib);
4549 			return (NULL);
4550 		}
4551 	}
4552 
4553 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_open_controller")) ==
4554 	    NULL) {
4555 		(void) dlclose(supplib->lib_handle);
4556 		free(supplib);
4557 		return (NULL);
4558 	} else
4559 		supplib->open_controller = (int(*)(uint32_t, char **))sym;
4560 
4561 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_close_controller")) ==
4562 	    NULL) {
4563 		(void) dlclose(supplib->lib_handle);
4564 		free(supplib);
4565 		return (NULL);
4566 	} else
4567 		supplib->close_controller = (int (*)(uint32_t, char **))sym;
4568 
4569 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_compnum")) == NULL) {
4570 		(void) dlclose(supplib->lib_handle);
4571 		free(supplib);
4572 		return (NULL);
4573 	} else
4574 		supplib->compnum = (int (*)(uint32_t, uint32_t,
4575 		    raid_obj_type_id_t, raid_obj_type_id_t))sym;
4576 
4577 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_complist")) == NULL) {
4578 		(void) dlclose(supplib->lib_handle);
4579 		free(supplib);
4580 		return (NULL);
4581 	} else
4582 		supplib->complist = (int (*)(uint32_t, uint32_t,
4583 		    raid_obj_type_id_t, raid_obj_type_id_t, int, void *))sym;
4584 
4585 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_get_attr")) == NULL) {
4586 		(void) dlclose(supplib->lib_handle);
4587 		free(supplib);
4588 		return (NULL);
4589 	} else
4590 		supplib->get_attr = (int (*)(uint32_t, uint32_t, uint32_t,
4591 		    raid_obj_type_id_t, void*))sym;
4592 
4593 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_create")) == NULL) {
4594 		(void) dlclose(supplib->lib_handle);
4595 		free(supplib);
4596 		return (NULL);
4597 	} else
4598 		supplib->array_create = (int (*)(uint32_t, array_attr_t *, int,
4599 		    arraypart_attr_t *, char **))sym;
4600 
4601 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_delete")) == NULL) {
4602 		(void) dlclose(supplib->lib_handle);
4603 		free(supplib);
4604 		return (NULL);
4605 	} else
4606 		supplib->array_delete =
4607 		    (int (*)(uint32_t, uint32_t, char **))sym;
4608 
4609 	supplib->hsp_bind = (int (*)(uint32_t, uint32_t, hsp_relation_t *,
4610 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_bind");
4611 	supplib->hsp_unbind = (int (*)(uint32_t, uint32_t, hsp_relation_t *,
4612 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_unbind");
4613 	supplib->set_attr = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t *,
4614 	    char **))dlsym(supplib->lib_handle, "rdcfg_set_attr");
4615 	supplib->flash_fw = (int (*)(uint32_t, char *, uint32_t, char **))
4616 	    dlsym(supplib->lib_handle, "rdcfg_flash_fw");
4617 
4618 	supplib->next = raid_lib_sys;
4619 	raid_lib_sys = supplib;
4620 	return (supplib);
4621 }
4622 
4623 static raid_lib_t *
4624 raid_find_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t controller_obj_id)
4625 {
4626 	controller_attr_t *controller_attr;
4627 	raid_lib_t *raid_lib;
4628 	char *driver_name;
4629 	raid_obj_handle_t handle;
4630 
4631 	/* Check if it's mapped to handle structure */
4632 	handle = raid_obj_to_handle(raid_tab, controller_obj_id);
4633 	if (raid_handle_sys.handles[handle].raid_lib != NULL)
4634 		return (raid_handle_sys.handles[handle].raid_lib);
4635 
4636 	(void) obj_get_attr(raid_tab, controller_obj_id,
4637 	    (void **)(&controller_attr));
4638 
4639 	/* Check if the plugin module is already loaded */
4640 	driver_name = controller_id_to_driver_name(
4641 	    controller_attr->controller_id);
4642 	if (driver_name == NULL)
4643 		return (NULL);
4644 
4645 	raid_lib = raid_lib_sys;
4646 	while (raid_lib != NULL) {
4647 		if (raid_lib->name != NULL &&
4648 		    strcmp(driver_name, raid_lib->name) == 0)
4649 			return (raid_lib);
4650 
4651 		raid_lib = raid_lib->next;
4652 	}
4653 
4654 	/* Loading the plugin module */
4655 	raid_lib = raid_plugin_load(driver_name);
4656 
4657 	return (raid_lib);
4658 }
4659