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