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