xref: /titanic_51/usr/src/lib/libraidcfg/common/raidcfg.c (revision 53a7b6b6763f5865522a76e5e887390a8f4777d7)
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 *, raid_obj_id_t *, char **);
111 	int (*unbind_obj)(raid_obj_tab_t *, 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 *, raid_obj_id_t *, char **);
229 static int obj_hsp_unbind(raid_obj_tab_t *, 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(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;
1039 
1040 	(void) mutex_lock(&raidcfg_mp);
1041 	(void) obj_rescan(&raid_tab_sys);
1042 	if (hsp_relations == NULL) {
1043 		(void) mutex_unlock(&raidcfg_mp);
1044 		return (ERR_OP_ILLEGAL);
1045 	}
1046 
1047 	hsp_relation_objs = malloc(2 * 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 	if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
1056 		array_obj_id = raid_handle_to_obj(&raid_tab_sys,
1057 		    hsp_relations->array_handle);
1058 		if (array_obj_id < OBJ_NONE) {
1059 			free(hsp_relation_objs);
1060 			(void) mutex_unlock(&raidcfg_mp);
1061 			return (array_obj_id);
1062 		}
1063 		if (array_obj_id == OBJ_NONE) {
1064 			(void) free(hsp_relation_objs);
1065 			(void) mutex_unlock(&raidcfg_mp);
1066 			return (ERR_DEVICE_NOENT);
1067 		}
1068 		if (raidcfg_get_type(hsp_relations->array_handle) !=
1069 		    OBJ_TYPE_ARRAY) {
1070 			free(hsp_relation_objs);
1071 			(void) mutex_unlock(&raidcfg_mp);
1072 			return (ERR_DEVICE_TYPE);
1073 		}
1074 	} else
1075 		array_obj_id = OBJ_ATTR_NONE;
1076 
1077 	disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
1078 	    hsp_relations->disk_handle);
1079 	if (disk_obj_id < OBJ_NONE) {
1080 		free(hsp_relation_objs);
1081 		(void) mutex_unlock(&raidcfg_mp);
1082 		return (disk_obj_id);
1083 	}
1084 	if (disk_obj_id == OBJ_NONE) {
1085 		free(hsp_relation_objs);
1086 		(void) mutex_unlock(&raidcfg_mp);
1087 		return (ERR_DEVICE_NOENT);
1088 	}
1089 	if (raidcfg_get_type(hsp_relations->disk_handle) !=
1090 	    OBJ_TYPE_DISK) {
1091 		free(hsp_relation_objs);
1092 		(void) mutex_unlock(&raidcfg_mp);
1093 		return (ERR_DEVICE_TYPE);
1094 	}
1095 
1096 	hsp_relation_objs[0] = array_obj_id;
1097 	hsp_relation_objs[1] = disk_obj_id;
1098 
1099 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].bind_obj(&raid_tab_sys,
1100 	    hsp_relation_objs, plugin_err_str);
1101 
1102 	(void) obj_rescan(&raid_tab_sys);
1103 	free(hsp_relation_objs);
1104 	(void) mutex_unlock(&raidcfg_mp);
1105 
1106 	return (ret);
1107 }
1108 
1109 int
1110 raidcfg_unset_hsp(raidcfg_hsp_relation_t *hsp_relations,
1111 	char **plugin_err_str)
1112 {
1113 	raid_obj_id_t disk_obj_id, array_obj_id;
1114 	raid_obj_id_t *hsp_relation_objs;
1115 	int ret;
1116 
1117 	(void) mutex_lock(&raidcfg_mp);
1118 	(void) obj_rescan(&raid_tab_sys);
1119 	if (hsp_relations == NULL) {
1120 		(void) mutex_unlock(&raidcfg_mp);
1121 		return (ERR_OP_ILLEGAL);
1122 	}
1123 
1124 	hsp_relation_objs = malloc(2 * sizeof (raid_obj_id_t));
1125 	if (hsp_relation_objs == NULL) {
1126 		(void) mutex_unlock(&raidcfg_mp);
1127 		return (ERR_NOMEM);
1128 	}
1129 
1130 	(void) obj_rescan(&raid_tab_sys);
1131 
1132 	if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
1133 		array_obj_id = raid_handle_to_obj(&raid_tab_sys,
1134 		    hsp_relations->array_handle);
1135 		if (array_obj_id < OBJ_NONE) {
1136 			free(hsp_relation_objs);
1137 			(void) mutex_unlock(&raidcfg_mp);
1138 			return (array_obj_id);
1139 		}
1140 		if (array_obj_id == OBJ_NONE) {
1141 			free(hsp_relation_objs);
1142 			(void) mutex_unlock(&raidcfg_mp);
1143 			return (ERR_DEVICE_NOENT);
1144 		}
1145 		if (raidcfg_get_type(hsp_relations->array_handle) !=
1146 		    OBJ_TYPE_ARRAY) {
1147 			free(hsp_relation_objs);
1148 			(void) mutex_unlock(&raidcfg_mp);
1149 			return (ERR_DEVICE_TYPE);
1150 		}
1151 	} else
1152 		array_obj_id = OBJ_ATTR_NONE;
1153 
1154 	disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
1155 	    hsp_relations->disk_handle);
1156 	if (disk_obj_id < OBJ_NONE) {
1157 		free(hsp_relation_objs);
1158 		(void) mutex_unlock(&raidcfg_mp);
1159 		return (disk_obj_id);
1160 	}
1161 	if (disk_obj_id == OBJ_NONE) {
1162 		free(hsp_relation_objs);
1163 		(void) mutex_unlock(&raidcfg_mp);
1164 		return (ERR_DEVICE_NOENT);
1165 	}
1166 	if (raidcfg_get_type(hsp_relations->disk_handle) !=
1167 	    OBJ_TYPE_DISK) {
1168 		free(hsp_relation_objs);
1169 		(void) mutex_unlock(&raidcfg_mp);
1170 		return (ERR_DEVICE_TYPE);
1171 	}
1172 
1173 	hsp_relation_objs[0] = array_obj_id;
1174 	hsp_relation_objs[1] = disk_obj_id;
1175 
1176 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].unbind_obj(&raid_tab_sys,
1177 	    hsp_relation_objs, plugin_err_str);
1178 
1179 	(void) obj_rescan(&raid_tab_sys);
1180 	free(hsp_relation_objs);
1181 	(void) mutex_unlock(&raidcfg_mp);
1182 
1183 	return (ret);
1184 }
1185 
1186 /*
1187  * RaidCfg lib routines
1188  */
1189 void
1190 raidcfg_init(void)
1191 {
1192 	(void) mutex_init(&raidcfg_mp, NULL, NULL);
1193 	raid_plugin_init();
1194 	(void) raid_handle_init();
1195 	(void) obj_rescan(&raid_tab_sys);
1196 }
1197 
1198 void
1199 raidcfg_fini(void)
1200 {
1201 	/*
1202 	 * Need to close all opened controllers before destroying object table
1203 	 */
1204 	(void) obj_rescan(&raid_tab_sys);
1205 	raid_handle_fini();
1206 	raid_obj_tab_destroy(&raid_tab_sys);
1207 	raid_plugin_init();
1208 	(void) mutex_destroy(&raidcfg_mp);
1209 }
1210 
1211 /*
1212  * Support routines
1213  */
1214 static int
1215 intcompare(const void *p1, const void *p2)
1216 {
1217 	int i, j;
1218 	i = *((int *)p1);
1219 	j = *((int *)p2);
1220 	return (i - j);
1221 }
1222 
1223 static uint64_t
1224 raid_space_noalign(raid_obj_tab_t *raid_tab, uint32_t raid_level, int num,
1225 	raid_obj_id_t *disk_objs, arraypart_attr_t *arraypart_attrs)
1226 {
1227 	disk_attr_t *disk_attr;
1228 	diskseg_attr_t *diskseg_attr;
1229 	raid_obj_id_t obj_id;
1230 	uint64_t offset, capacity;
1231 	int i, disk_num, sub_array_num, disk_layer;
1232 
1233 	/* Find out the maximum available space for all disks */
1234 	for (i = 0; i < num; ++i) {
1235 		if ((disk_objs[i] == OBJ_SEPARATOR_BEGIN) ||
1236 		    (disk_objs[i] == OBJ_SEPARATOR_END))
1237 			continue;
1238 
1239 		(void) obj_get_attr(raid_tab, disk_objs[i],
1240 		    (void **)(&disk_attr));
1241 		obj_id = obj_get_comp(raid_tab, disk_objs[i],
1242 		    OBJ_TYPE_DISK_SEG);
1243 		if (obj_id == OBJ_NONE) {
1244 			arraypart_attrs[i].offset = 0;
1245 			arraypart_attrs[i].size = disk_attr->capacity;
1246 			continue;
1247 		}
1248 
1249 		(void) obj_get_attr(raid_tab, obj_id, (void **)
1250 		    (&diskseg_attr));
1251 		arraypart_attrs[i].offset = 0;
1252 		arraypart_attrs[i].size = diskseg_attr->offset;
1253 		offset = diskseg_attr->offset + diskseg_attr->size;
1254 
1255 		while ((obj_id = obj_get_sibling(raid_tab, obj_id)) !=
1256 		    OBJ_NONE) {
1257 			(void) obj_get_attr(raid_tab, obj_id,
1258 			    (void **)(&diskseg_attr));
1259 			if ((diskseg_attr->offset - offset) >
1260 			    arraypart_attrs[i].size) {
1261 				arraypart_attrs[i].offset = offset;
1262 				arraypart_attrs[i].size = diskseg_attr->offset -
1263 				    offset;
1264 			}
1265 
1266 			offset = diskseg_attr->offset + diskseg_attr->size;
1267 		}
1268 
1269 		if ((disk_attr->capacity - offset) > arraypart_attrs[i].size) {
1270 			arraypart_attrs[i].offset = offset;
1271 			arraypart_attrs[i].size = disk_attr->capacity -
1272 			    offset;
1273 		}
1274 	}
1275 
1276 	capacity = OBJ_ATTR_NONE;
1277 	disk_num = 0;
1278 	disk_layer = 0;
1279 	sub_array_num = 0;
1280 	for (i = 0; i < num; ++i) {
1281 		if (disk_objs[i] == OBJ_SEPARATOR_BEGIN) {
1282 			++ disk_layer;
1283 			continue;
1284 		}
1285 		if (disk_objs[i] == OBJ_SEPARATOR_END) {
1286 			-- disk_layer;
1287 			if (disk_layer != 0)
1288 				++ sub_array_num;
1289 			continue;
1290 		}
1291 
1292 		if (capacity > arraypart_attrs[i].size)
1293 			capacity = arraypart_attrs[i].size;
1294 		++disk_num;
1295 	}
1296 
1297 	switch (raid_level) {
1298 	case	RAID_LEVEL_0:
1299 		capacity = capacity * disk_num;
1300 		break;
1301 	case	RAID_LEVEL_1:
1302 		capacity = capacity * disk_num / 2;
1303 		break;
1304 	case	RAID_LEVEL_1E:
1305 		capacity = capacity * disk_num / 2;
1306 		break;
1307 	case	RAID_LEVEL_5:
1308 		capacity = capacity * (disk_num - 1);
1309 		break;
1310 	case	RAID_LEVEL_10:
1311 		capacity = capacity * disk_num / 2;
1312 		break;
1313 	case	RAID_LEVEL_50:
1314 		capacity = capacity * (disk_num - sub_array_num);
1315 		break;
1316 	default:
1317 		return (ERR_ARRAY_LEVEL);
1318 		break;
1319 	}
1320 
1321 	return (capacity);
1322 }
1323 
1324 /*
1325  * Raid handle maintenance routines
1326  */
1327 static int
1328 raid_handle_init()
1329 {
1330 	int i;
1331 	void *ptr;
1332 
1333 	raid_handle_sys.handle_num += HANDLER_SLOTS;
1334 	ptr = realloc(raid_handle_sys.handles,
1335 	    raid_handle_sys.handle_num * sizeof (handle_attr_t));
1336 	if (ptr == NULL)
1337 		return (ERR_NOMEM);
1338 	raid_handle_sys.handles = ptr;
1339 
1340 	/* Clean up the new allocated handles */
1341 	for (i = raid_handle_sys.handle_num - HANDLER_SLOTS;
1342 	    i < raid_handle_sys.handle_num; ++i) {
1343 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1344 		raid_handle_sys.handles[i].next = i + 1;
1345 	}
1346 
1347 	/* For the first time of allocation, set up the system object handle */
1348 	if (raid_handle_sys.handle_num == HANDLER_SLOTS) {
1349 		raid_handle_sys.handles[0].type = OBJ_TYPE_SYSTEM;
1350 		raid_handle_sys.handles[0].next = 0;
1351 		raid_handle_sys.unused = 1;
1352 		raid_handle_sys.used = 0;
1353 	}
1354 	return (SUCCESS);
1355 }
1356 
1357 static void
1358 raid_handle_fini()
1359 {
1360 	raid_obj_handle_t i;
1361 
1362 	i = raid_handle_sys.used;
1363 
1364 	/* Close all opened controllers */
1365 	while (i != 0) {
1366 		if ((raid_handle_sys.handles[i].type == OBJ_TYPE_CONTROLLER) &&
1367 		    (raid_handle_sys.handles[i].fd != 0) &&
1368 		    (raid_handle_sys.handles[i].raid_lib != NULL))
1369 			raid_handle_sys.handles[i].raid_lib->close_controller(
1370 			    raid_handle_sys.handles[i].controller_id, NULL);
1371 		i = raid_handle_sys.handles[i].next;
1372 	}
1373 
1374 	/* Clean up handle space */
1375 	raid_handle_sys.handle_num = 0;
1376 	raid_handle_sys.unused = 0;
1377 	raid_handle_sys.used = 0;
1378 	free(raid_handle_sys.handles);
1379 	raid_handle_sys.handles = NULL;
1380 }
1381 
1382 static raid_obj_handle_t
1383 raid_handle_new(raid_obj_type_id_t type)
1384 {
1385 	int ret;
1386 
1387 	if (raid_handle_sys.unused == raid_handle_sys.handle_num - 1) {
1388 		ret = raid_handle_init();
1389 		if (ret < SUCCESS)
1390 			return (ret);
1391 	}
1392 
1393 	ret = raid_handle_sys.unused;
1394 	raid_handle_sys.unused = raid_handle_sys.handles[ret].next;
1395 
1396 	raid_handle_sys.handles[ret].next = raid_handle_sys.used;
1397 	raid_handle_sys.used = ret;
1398 	raid_handle_sys.handles[ret].type = type;
1399 
1400 	return (ret);
1401 }
1402 
1403 static void
1404 raid_handle_delete(raid_obj_handle_t handle)
1405 {
1406 	int i = raid_handle_sys.used, j = 0;
1407 
1408 	if (handle == 0)
1409 		return;
1410 
1411 	while (i != 0 && i != handle) {
1412 		j = i;
1413 		i = raid_handle_sys.handles[i].next;
1414 	}
1415 
1416 	if (i == handle) {
1417 		if (j != 0)
1418 			raid_handle_sys.handles[j].next =
1419 			    raid_handle_sys.handles[i].next;
1420 		else
1421 			raid_handle_sys.used =
1422 			    raid_handle_sys.handles[i].next;
1423 
1424 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1425 		raid_handle_sys.handles[i].next =
1426 		    raid_handle_sys.unused;
1427 		raid_handle_sys.unused = i;
1428 	}
1429 }
1430 
1431 static void
1432 raid_handle_delete_controller_comp(uint32_t controller_id)
1433 {
1434 	int i = raid_handle_sys.used, j;
1435 
1436 	while (i != 0) {
1437 		j = i;
1438 		i = raid_handle_sys.handles[i].next;
1439 		if ((raid_handle_sys.handles[j].controller_id ==
1440 		    controller_id) &&
1441 		    (raid_handle_sys.handles[j].type !=
1442 		    OBJ_TYPE_CONTROLLER))
1443 		raid_handle_delete(j);
1444 	}
1445 }
1446 
1447 static raid_obj_id_t
1448 raid_handle_to_obj(raid_obj_tab_t *raid_tab, raid_obj_handle_t handle)
1449 {
1450 	handle_attr_t *handle_attr;
1451 	raid_obj_id_t obj_id;
1452 
1453 	if (handle == OBJ_SYSTEM)
1454 		return (OBJ_SYSTEM);
1455 
1456 	handle_attr = raid_handle_sys.handles + handle;
1457 
1458 	switch (handle_attr->type) {
1459 	case	OBJ_TYPE_SYSTEM:
1460 		return (OBJ_SYSTEM);
1461 	case	OBJ_TYPE_CONTROLLER:
1462 		obj_id = obj_locate_controller(raid_tab,
1463 		    handle_attr->controller_id);
1464 		break;
1465 	case	OBJ_TYPE_ARRAY:
1466 		obj_id = obj_locate_array(raid_tab,
1467 		    handle_attr->controller_id, handle_attr->array_id);
1468 		break;
1469 	case	OBJ_TYPE_HSP:
1470 		obj_id = obj_locate_hsp(raid_tab,
1471 		    handle_attr->controller_id, handle_attr->disk_id,
1472 		    handle_attr->array_id);
1473 		break;
1474 	case	OBJ_TYPE_DISK:
1475 		obj_id = obj_locate_disk(raid_tab,
1476 		    handle_attr->controller_id, handle_attr->disk_id);
1477 		break;
1478 	case	OBJ_TYPE_ARRAY_PART:
1479 		obj_id = obj_locate_arraypart(raid_tab,
1480 		    handle_attr->controller_id, handle_attr->array_id,
1481 		    handle_attr->disk_id);
1482 		break;
1483 	case	OBJ_TYPE_DISK_SEG:
1484 		obj_id = obj_locate_diskseg(raid_tab,
1485 		    handle_attr->controller_id,
1486 		    handle_attr->disk_id, handle_attr->seq_id);
1487 		break;
1488 	case	OBJ_TYPE_TASK:
1489 		obj_id = obj_locate_task(raid_tab,
1490 		    handle_attr->controller_id, handle_attr->task_id);
1491 		break;
1492 	case	OBJ_TYPE_PROP:
1493 		obj_id = obj_locate_prop(raid_tab,
1494 		    handle_attr->controller_id, handle_attr->disk_id,
1495 		    handle_attr->prop_id);
1496 		break;
1497 	default:
1498 		return (ERR_DEVICE_INVALID);
1499 	}
1500 
1501 	if (obj_id < OBJ_NONE)
1502 		return (obj_id);
1503 	if (obj_id == OBJ_NONE)
1504 		return (ERR_DEVICE_NOENT);
1505 
1506 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
1507 	return (obj_id);
1508 }
1509 
1510 static raid_obj_handle_t
1511 raid_obj_to_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1512 {
1513 	raid_obj_id_t obj_id_backup = obj_id;
1514 	raid_obj_type_id_t type;
1515 	raid_obj_handle_t handle;
1516 	controller_attr_t *controller_attr;
1517 	array_attr_t *array_attr;
1518 	hsp_attr_t *hsp_attr;
1519 	disk_attr_t *disk_attr;
1520 	arraypart_attr_t *arraypart_attr;
1521 	diskseg_attr_t *diskseg_attr;
1522 	task_attr_t *task_attr;
1523 	property_attr_t *prop_attr;
1524 
1525 	if (obj_id == OBJ_SYSTEM)
1526 		return (OBJ_SYSTEM);
1527 
1528 	/* If the object mapped by a handle */
1529 	handle = raid_obj_get_handle(raid_tab, obj_id);
1530 	if (handle != 0)
1531 		return (handle);
1532 
1533 	/* Search for existing handles */
1534 	for (handle = raid_handle_sys.used; handle != 0;
1535 	    handle = raid_handle_sys.handles[handle].next)
1536 		if (raid_handle_to_obj(raid_tab, handle) == obj_id)
1537 			break;
1538 
1539 	if (handle != 0)
1540 		return (handle);
1541 
1542 	/* Allocate new handle for this object */
1543 	type = raid_obj_get_type(raid_tab, obj_id);
1544 	handle = raid_handle_new(type);
1545 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
1546 	raid_handle_sys.handles[handle].type = type;
1547 
1548 	switch (type) {
1549 	case OBJ_TYPE_SYSTEM:
1550 		break;
1551 	case OBJ_TYPE_CONTROLLER:
1552 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1553 		raid_handle_sys.handles[handle].controller_id =
1554 		    controller_attr->controller_id;
1555 		break;
1556 	case OBJ_TYPE_ARRAY:
1557 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1558 		raid_handle_sys.handles[handle].array_id = array_attr->array_id;
1559 		obj_id = obj_get_controller(raid_tab, obj_id);
1560 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1561 		raid_handle_sys.handles[handle].controller_id =
1562 		    controller_attr->controller_id;
1563 		break;
1564 	case OBJ_TYPE_HSP:
1565 		hsp_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1566 		raid_handle_sys.handles[handle].array_id =
1567 		    hsp_attr->associated_id;
1568 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1569 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1570 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1571 		obj_id = obj_get_controller(raid_tab, obj_id);
1572 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1573 		raid_handle_sys.handles[handle].controller_id =
1574 		    controller_attr->controller_id;
1575 		break;
1576 	case OBJ_TYPE_DISK:
1577 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1578 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1579 		obj_id = obj_get_controller(raid_tab, obj_id);
1580 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1581 		raid_handle_sys.handles[handle].controller_id =
1582 		    controller_attr->controller_id;
1583 		break;
1584 	case OBJ_TYPE_ARRAY_PART:
1585 		arraypart_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1586 		raid_handle_sys.handles[handle].disk_id =
1587 		    arraypart_attr->disk_id;
1588 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1589 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1590 		raid_handle_sys.handles[handle].array_id =
1591 		    array_attr->array_id;
1592 		obj_id = obj_get_controller(raid_tab, obj_id);
1593 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1594 		raid_handle_sys.handles[handle].controller_id =
1595 		    controller_attr->controller_id;
1596 		break;
1597 	case OBJ_TYPE_DISK_SEG:
1598 		diskseg_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1599 		raid_handle_sys.handles[handle].seq_id = diskseg_attr->seq_no;
1600 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1601 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1602 		raid_handle_sys.handles[handle].disk_id =
1603 		    disk_attr->disk_id;
1604 		obj_id = obj_get_controller(raid_tab, obj_id);
1605 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1606 		raid_handle_sys.handles[handle].controller_id =
1607 		    controller_attr->controller_id;
1608 		break;
1609 	case OBJ_TYPE_TASK:
1610 		task_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1611 		raid_handle_sys.handles[handle].task_id = task_attr->task_id;
1612 		obj_id = obj_get_controller(raid_tab, obj_id);
1613 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1614 		raid_handle_sys.handles[handle].controller_id =
1615 		    controller_attr->controller_id;
1616 		break;
1617 	case OBJ_TYPE_PROP:
1618 		prop_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1619 		raid_handle_sys.handles[handle].prop_id =
1620 		    prop_attr->prop_id;
1621 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1622 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1623 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1624 		obj_id = obj_get_controller(raid_tab, obj_id);
1625 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1626 		raid_handle_sys.handles[handle].controller_id =
1627 		    controller_attr->controller_id;
1628 		break;
1629 	default:
1630 		return (ERR_DEVICE_INVALID);
1631 	}
1632 
1633 	(void) raid_obj_set_handle(raid_tab, obj_id_backup, handle);
1634 	return (handle);
1635 }
1636 
1637 static raid_lib_t *
1638 raid_obj_get_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1639 {
1640 	raid_obj_handle_t handle;
1641 	controller_attr_t *attr;
1642 
1643 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1644 		return (NULL);
1645 
1646 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1647 	handle = raid_handle_sys.used;
1648 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1649 	    raid_handle_sys.handles[handle].controller_id !=
1650 	    attr->controller_id)
1651 		handle = raid_handle_sys.handles[handle].next;
1652 
1653 	if (handle == 0)
1654 		return (NULL);
1655 
1656 	return (raid_handle_sys.handles[handle].raid_lib);
1657 }
1658 
1659 static int
1660 raid_obj_set_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1661 	raid_lib_t *raid_lib)
1662 {
1663 	raid_obj_handle_t handle;
1664 	controller_attr_t *attr;
1665 
1666 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1667 		return (ERR_DEVICE_TYPE);
1668 
1669 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1670 	handle = raid_handle_sys.used;
1671 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1672 	    raid_handle_sys.handles[handle].controller_id !=
1673 	    attr->controller_id)
1674 		handle = raid_handle_sys.handles[handle].next;
1675 
1676 	if (handle == 0)
1677 		return (ERR_DEVICE_NOENT);
1678 
1679 	raid_handle_sys.handles[handle].raid_lib = raid_lib;
1680 	return (SUCCESS);
1681 }
1682 
1683 static int
1684 raid_obj_get_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1685 {
1686 	raid_obj_handle_t handle;
1687 	controller_attr_t *attr;
1688 
1689 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1690 		return (ERR_DEVICE_TYPE);
1691 
1692 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1693 	handle = raid_handle_sys.used;
1694 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1695 	    raid_handle_sys.handles[handle].controller_id !=
1696 	    attr->controller_id)
1697 		handle = raid_handle_sys.handles[handle].next;
1698 
1699 	if (handle == 0)
1700 		return (ERR_DEVICE_NOENT);
1701 
1702 	return (raid_handle_sys.handles[handle].fd);
1703 }
1704 
1705 static int
1706 raid_obj_set_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, int fd)
1707 {
1708 	raid_obj_handle_t handle;
1709 	controller_attr_t *attr;
1710 
1711 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1712 		return (ERR_DEVICE_TYPE);
1713 
1714 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1715 	handle = raid_handle_sys.used;
1716 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1717 	    raid_handle_sys.handles[handle].controller_id !=
1718 	    attr->controller_id)
1719 		handle = raid_handle_sys.handles[handle].next;
1720 
1721 	if (handle == 0)
1722 		return (ERR_DEVICE_NOENT);
1723 
1724 	raid_handle_sys.handles[handle].fd = fd;
1725 	return (SUCCESS);
1726 }
1727 
1728 /*
1729  * Raid object maintenance routines
1730  */
1731 static int
1732 obj_scan_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1733 {
1734 	raid_obj_status_t status;
1735 	raid_obj_type_id_t type;
1736 	int ret, i, obj_type_cnt, comp_num;
1737 	raid_obj_id_t *comp_list;
1738 
1739 	status = raid_obj_get_status(raid_tab, obj_id);
1740 	if (status < SUCCESS)
1741 		return (status);
1742 
1743 	if (status & OBJ_STATUS_SCANCOMP)
1744 		return (SUCCESS);
1745 
1746 	type = raid_obj_get_type(raid_tab, obj_id);
1747 	if (type < OBJ_TYPE_SYSTEM || type > OBJ_TYPE_ALL)
1748 		return (ERR_DEVICE_INVALID);
1749 
1750 	for (obj_type_cnt = OBJ_SYSTEM; obj_type_cnt < OBJ_TYPE_ALL;
1751 	    ++obj_type_cnt) {
1752 		if (raid_obj_op_sys[type].compnum != NULL)
1753 			comp_num = raid_obj_op_sys[type].compnum(
1754 			    raid_tab, obj_id, obj_type_cnt);
1755 		else
1756 			comp_num = 0;
1757 
1758 		if (comp_num < SUCCESS)
1759 			return (comp_num);
1760 		if (comp_num == 0)
1761 			continue;
1762 
1763 		comp_list = calloc(comp_num, sizeof (raid_obj_id_t));
1764 		if (comp_list == NULL)
1765 			return (ERR_NOMEM);
1766 
1767 		for (i = 0; i < comp_num; ++i) {
1768 			*(comp_list + i) = raid_obj_create(raid_tab,
1769 			    obj_type_cnt);
1770 			if (*(comp_list + i) < SUCCESS) {
1771 				ret = *(comp_list + i);
1772 				free(comp_list);
1773 				return (ret);
1774 			}
1775 
1776 			(void) raid_obj_clear_status(raid_tab,
1777 			    *(comp_list + i), OBJ_STATUS_CMD_CLEAN);
1778 			(void) raid_obj_add_org(raid_tab, *(comp_list + i),
1779 			    obj_id);
1780 		}
1781 
1782 		if (raid_obj_op_sys[type].complist != NULL)
1783 			raid_obj_op_sys[type].complist(raid_tab,
1784 			    obj_id, comp_num, comp_list, obj_type_cnt);
1785 		free(comp_list);
1786 	}
1787 
1788 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_SCANCOMP);
1789 	return (SUCCESS);
1790 }
1791 
1792 static int
1793 obj_rescan(raid_obj_tab_t *raid_tab)
1794 {
1795 	int ret;
1796 
1797 	raid_obj_tab_destroy(raid_tab);
1798 
1799 	if (raid_obj_tab_create(raid_tab, HASH_SLOTS) != SUCCESS)
1800 		return (ERR_NOMEM);
1801 
1802 	if ((ret = raid_obj_create_system_obj(raid_tab)) != SUCCESS) {
1803 		raid_obj_tab_destroy(raid_tab);
1804 		return (ret);
1805 	}
1806 
1807 	return (SUCCESS);
1808 }
1809 
1810 static raid_obj_id_t
1811 obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1812 	raid_obj_type_id_t obj_type)
1813 {
1814 	raid_obj_id_t id;
1815 	raid_obj_type_id_t type;
1816 	raid_obj_status_t status;
1817 	int ret;
1818 
1819 	if ((obj_type < OBJ_TYPE_SYSTEM) || (obj_type > OBJ_TYPE_ALL))
1820 		return (ERR_DEVICE_TYPE);
1821 
1822 	status = raid_obj_get_status(raid_tab, obj_id);
1823 	if (status < SUCCESS)
1824 		return (status);
1825 
1826 	if (!(status & OBJ_STATUS_SCANCOMP)) {
1827 		ret = obj_scan_comp(raid_tab, obj_id);
1828 		if (ret < SUCCESS)
1829 			return (ret);
1830 	}
1831 
1832 	id = raid_obj_get_comp(raid_tab, obj_id);
1833 	if (id <= OBJ_NONE)
1834 		return (id);
1835 
1836 	type = raid_obj_get_type(raid_tab, id);
1837 	if (type < OBJ_TYPE_SYSTEM)
1838 		return (type);
1839 
1840 	if (type == obj_type)
1841 		return (id);
1842 
1843 	while (id > OBJ_NONE) {
1844 		id = raid_obj_get_sibling(raid_tab, id);
1845 		if (id <= OBJ_NONE)
1846 			return (id);
1847 
1848 		type = raid_obj_get_type(raid_tab, id);
1849 		if (type < OBJ_TYPE_SYSTEM)
1850 			return (type);
1851 
1852 		if (type == obj_type)
1853 			break;
1854 	};
1855 
1856 	return (id);
1857 }
1858 
1859 static raid_obj_id_t
1860 obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1861 {
1862 	raid_obj_id_t id;
1863 	raid_obj_type_id_t type, obj_type;
1864 
1865 	id = obj_id;
1866 	obj_type = raid_obj_get_type(raid_tab, id);
1867 	if (obj_type < OBJ_TYPE_SYSTEM)
1868 		return (obj_type);
1869 
1870 	do {
1871 		id = raid_obj_get_sibling(raid_tab, id);
1872 		if (id < OBJ_NONE)
1873 			return (id);
1874 
1875 		type = raid_obj_get_type(raid_tab, id);
1876 		if (type < OBJ_TYPE_SYSTEM)
1877 			return (type);
1878 	} while ((type != obj_type) && (id != OBJ_NONE));
1879 
1880 	return (id);
1881 }
1882 
1883 static int
1884 obj_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, void **data)
1885 {
1886 	raid_obj_type_id_t type;
1887 	raid_obj_status_t status;
1888 	void *attr;
1889 	int ret = SUCCESS;
1890 
1891 	status = raid_obj_get_status(raid_tab, obj_id);
1892 	if (status < SUCCESS)
1893 		return (status);
1894 
1895 	type = raid_obj_get_type(raid_tab, obj_id);
1896 	if (type < OBJ_TYPE_SYSTEM)
1897 		return (type);
1898 
1899 	if (!(status & OBJ_STATUS_OPENED)) {
1900 		if (raid_obj_op_sys[type].get_attr == NULL)
1901 			(void) raid_obj_set_status(raid_tab, obj_id,
1902 			    OBJ_STATUS_OPENED);
1903 		else
1904 			ret = raid_obj_op_sys[type].get_attr(raid_tab, obj_id);
1905 	}
1906 	if (ret < SUCCESS)
1907 		return (ret);
1908 
1909 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1910 	if (attr == NULL && type != OBJ_TYPE_SYSTEM)
1911 		return (ERR_DEVICE_INVALID);
1912 
1913 	*data = attr;
1914 	return (SUCCESS);
1915 }
1916 
1917 static raid_obj_id_t
1918 obj_locate_controller(raid_obj_tab_t *raid_tab, uint32_t controller_id)
1919 {
1920 	raid_obj_id_t obj_id;
1921 	controller_attr_t *attr;
1922 
1923 	obj_id = obj_get_comp(raid_tab, OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
1924 	if (obj_id <= OBJ_NONE)
1925 		return (obj_id);
1926 
1927 	do {
1928 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1929 		if (attr == NULL)
1930 			return (ERR_DEVICE_INVALID);
1931 
1932 		if (attr->controller_id == controller_id)
1933 			break;
1934 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) != OBJ_NONE);
1935 
1936 	return (obj_id);
1937 }
1938 
1939 static raid_obj_id_t
1940 obj_locate_array(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1941 	uint32_t array_id)
1942 {
1943 	raid_obj_id_t obj_id;
1944 
1945 	obj_id = obj_locate_controller(raid_tab, controller_id);
1946 	if (obj_id < OBJ_NONE)
1947 		return (obj_id);
1948 
1949 	obj_id = obj_locate_array_recur(raid_tab, obj_id, array_id);
1950 
1951 	return (obj_id);
1952 }
1953 
1954 static raid_obj_id_t
1955 obj_locate_array_recur(raid_obj_tab_t *raid_tab,
1956 	raid_obj_id_t container_obj_id, uint32_t array_id)
1957 {
1958 	raid_obj_id_t obj_id, ret;
1959 	array_attr_t *attr;
1960 
1961 	obj_id = obj_get_comp(raid_tab, container_obj_id, OBJ_TYPE_ARRAY);
1962 	if (obj_id <= OBJ_NONE)
1963 		return (obj_id);
1964 
1965 	do {
1966 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1967 		if (attr == NULL)
1968 			return (ERR_DEVICE_INVALID);
1969 
1970 		if (attr->array_id == array_id)
1971 			break;
1972 
1973 		ret = obj_locate_array_recur(raid_tab, obj_id, array_id);
1974 		if (ret != OBJ_NONE)
1975 			return (ret);
1976 
1977 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
1978 
1979 	return (obj_id);
1980 }
1981 
1982 static raid_obj_id_t
1983 obj_locate_hsp(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1984 	uint32_t disk_id, uint32_t array_id)
1985 {
1986 	raid_obj_id_t obj_id;
1987 	hsp_attr_t *hsp_attr;
1988 
1989 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
1990 	if (obj_id <= OBJ_NONE)
1991 		return (obj_id);
1992 
1993 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_HSP);
1994 	if (obj_id <= OBJ_NONE)
1995 		return (obj_id);
1996 
1997 	do {
1998 		(void) obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
1999 		if (hsp_attr->associated_id == array_id)
2000 			break;
2001 
2002 		obj_id = obj_get_sibling(raid_tab, obj_id);
2003 		if (obj_id < OBJ_NONE)
2004 			return (obj_id);
2005 	} while (obj_id > OBJ_NONE);
2006 
2007 	return (obj_id);
2008 }
2009 
2010 static raid_obj_id_t
2011 obj_locate_disk(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2012 	uint32_t disk_id)
2013 {
2014 	raid_obj_id_t obj_id;
2015 	disk_attr_t *attr;
2016 
2017 	obj_id = obj_locate_controller(raid_tab, controller_id);
2018 	if (obj_id <= OBJ_NONE)
2019 		return (obj_id);
2020 
2021 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2022 	if (obj_id <= OBJ_NONE)
2023 		return (obj_id);
2024 
2025 	do {
2026 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2027 		if (attr == NULL)
2028 			return (ERR_DEVICE_INVALID);
2029 
2030 		if (attr->disk_id == disk_id)
2031 			break;
2032 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2033 
2034 	return (obj_id);
2035 }
2036 
2037 static raid_obj_id_t
2038 obj_locate_arraypart(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2039 	uint32_t array_id, uint32_t disk_id)
2040 {
2041 	raid_obj_id_t obj_id;
2042 
2043 	arraypart_attr_t *attr;
2044 
2045 	obj_id = obj_locate_array(raid_tab, controller_id, array_id);
2046 	if (obj_id <= OBJ_NONE)
2047 		return (obj_id);
2048 
2049 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY_PART);
2050 	if (obj_id <= OBJ_NONE)
2051 		return (obj_id);
2052 
2053 	do {
2054 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2055 		if (attr == NULL)
2056 			return (ERR_DEVICE_INVALID);
2057 
2058 		if (attr->disk_id == disk_id)
2059 			break;
2060 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) >
2061 	    OBJ_NONE);
2062 
2063 	return (obj_id);
2064 }
2065 
2066 static raid_obj_id_t
2067 obj_locate_diskseg(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2068 	uint32_t disk_id, uint32_t seq_no)
2069 {
2070 	raid_obj_id_t obj_id;
2071 	diskseg_attr_t *attr;
2072 
2073 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2074 	if (obj_id <= OBJ_NONE)
2075 		return (obj_id);
2076 
2077 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK_SEG);
2078 	if (obj_id <= OBJ_NONE)
2079 		return (obj_id);
2080 
2081 	do {
2082 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2083 		if (attr == NULL)
2084 			return (ERR_DEVICE_INVALID);
2085 
2086 		if (attr->seq_no == seq_no)
2087 			break;
2088 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2089 
2090 	return (obj_id);
2091 }
2092 
2093 static raid_obj_id_t
2094 obj_locate_task(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2095 	uint32_t task_id)
2096 {
2097 	raid_obj_id_t obj_id, obj_id2, task_obj_id;
2098 	task_attr_t *attr;
2099 
2100 	obj_id = obj_locate_controller(raid_tab, controller_id);
2101 	if (obj_id <= OBJ_NONE)
2102 		return (obj_id);
2103 
2104 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2105 	if (obj_id < OBJ_NONE)
2106 		return (obj_id);
2107 
2108 	do {
2109 		obj_id2 = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2110 		while (obj_id2 != OBJ_NONE) {
2111 			task_obj_id = obj_get_comp(raid_tab, obj_id2,
2112 			    OBJ_TYPE_TASK);
2113 
2114 			if (task_obj_id < OBJ_NONE)
2115 				return (task_obj_id);
2116 
2117 			if (task_obj_id == OBJ_NONE) {
2118 				obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2119 				continue;
2120 			}
2121 
2122 			attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2123 			if (attr == NULL)
2124 				return (ERR_DEVICE_INVALID);
2125 
2126 			if (attr->task_id == task_id)
2127 				return (task_obj_id);
2128 
2129 			obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2130 		}
2131 
2132 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2133 		if (task_obj_id < OBJ_NONE)
2134 			return (task_obj_id);
2135 
2136 		if (task_obj_id == OBJ_NONE)
2137 			continue;
2138 
2139 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2140 		if (attr == NULL)
2141 			return (ERR_DEVICE_INVALID);
2142 
2143 		if (attr->task_id == task_id)
2144 			return (task_obj_id);
2145 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2146 
2147 	if (obj_id < OBJ_NONE)
2148 		return (obj_id);
2149 
2150 	obj_id = obj_locate_controller(raid_tab, controller_id);
2151 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2152 	if (obj_id < OBJ_NONE)
2153 		return (obj_id);
2154 
2155 	do {
2156 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2157 		if (task_obj_id < OBJ_NONE)
2158 			return (task_obj_id);
2159 
2160 		if (task_obj_id == OBJ_NONE)
2161 			continue;
2162 
2163 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2164 		if (attr == NULL)
2165 			return (ERR_DEVICE_INVALID);
2166 
2167 		if (attr->task_id == task_id)
2168 			return (task_obj_id);
2169 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2170 
2171 	return (obj_id);
2172 }
2173 
2174 static raid_obj_id_t
2175 obj_locate_prop(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2176 	uint32_t disk_id, uint32_t prop_id)
2177 {
2178 	raid_obj_id_t obj_id;
2179 	property_attr_t *prop_attr;
2180 
2181 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2182 	if (obj_id < OBJ_NONE)
2183 		return (obj_id);
2184 
2185 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_PROP);
2186 	if (obj_id <= OBJ_NONE)
2187 		return (obj_id);
2188 
2189 	do {
2190 		(void) obj_get_attr(raid_tab, obj_id, (void **)(&prop_attr));
2191 		if (prop_attr->prop_id == prop_id)
2192 			break;
2193 
2194 		obj_id = obj_get_sibling(raid_tab, obj_id);
2195 		if (obj_id < OBJ_NONE)
2196 			return (obj_id);
2197 	} while (obj_id > OBJ_NONE);
2198 
2199 	return (obj_id);
2200 }
2201 
2202 static raid_obj_id_t
2203 obj_get_controller(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2204 {
2205 	raid_obj_id_t id = obj_id;
2206 
2207 	while (raid_obj_get_type(raid_tab, id) != OBJ_TYPE_CONTROLLER) {
2208 		id = raid_obj_get_container(raid_tab, id);
2209 		if ((id == OBJ_SYSTEM) || (id < OBJ_NONE))
2210 			return (ERR_DEVICE_INVALID);
2211 	}
2212 
2213 	return (id);
2214 }
2215 
2216 /*
2217  * Raid object operation routines
2218  */
2219 static int
2220 obj_sys_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2221 	raid_obj_type_id_t comp_type)
2222 {
2223 	DIR *dir;
2224 	struct dirent *dp;
2225 	int num = 0;
2226 
2227 	if ((raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM))
2228 		return (ERR_DEVICE_TYPE);
2229 
2230 	if (comp_type != OBJ_TYPE_CONTROLLER)
2231 		return (0);
2232 
2233 	if ((dir = opendir(CFGDIR)) == NULL)
2234 		return (ERR_DRIVER_NOT_FOUND);
2235 
2236 	while ((dp = readdir(dir)) != NULL) {
2237 		uint32_t controller_id;
2238 		char path[MAX_PATH_LEN];
2239 
2240 		if (strcmp(dp->d_name, ".") == 0 ||
2241 		    strcmp(dp->d_name, "..") == 0)
2242 			continue;
2243 
2244 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2245 			continue;
2246 
2247 		if (controller_id_to_path(controller_id, path) == SUCCESS)
2248 			++ num;
2249 	}
2250 
2251 	(void) closedir(dir);
2252 	return (num);
2253 }
2254 
2255 static int
2256 obj_sys_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2257 	int num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2258 {
2259 	DIR *dir;
2260 	struct dirent *dp;
2261 	controller_attr_t *attr;
2262 	uint32_t controller_id;
2263 	uint32_t *tmplist;
2264 	char path[MAX_PATH_LEN];
2265 	int i = 0;
2266 
2267 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM)
2268 		return (ERR_DEVICE_TYPE);
2269 	if ((num <= 0) || (comp_list == NULL))
2270 		return (ERR_OP_ILLEGAL);
2271 
2272 	if (comp_type != OBJ_TYPE_CONTROLLER)
2273 		return (0);
2274 
2275 	if ((dir = opendir(CFGDIR)) == NULL)
2276 		return (ERR_DRIVER_NOT_FOUND);
2277 	tmplist = calloc(num, sizeof (uint32_t));
2278 	if (tmplist == NULL) {
2279 		return (ERR_NOMEM);
2280 	}
2281 	while ((dp = readdir(dir)) != NULL) {
2282 		if (strcmp(dp->d_name, ".") == 0 ||
2283 		    strcmp(dp->d_name, "..") == 0)
2284 			continue;
2285 
2286 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2287 			continue;
2288 
2289 		if (controller_id_to_path(controller_id, path) == SUCCESS) {
2290 			tmplist[i] = controller_id;
2291 			++ i;
2292 		}
2293 	}
2294 	qsort((void *)tmplist, num, sizeof (uint32_t), intcompare);
2295 	for (i = 0; i < num; i++) {
2296 		attr = raid_obj_get_data_ptr(raid_tab,
2297 		    *(comp_list + i));
2298 
2299 		if (attr == NULL) {
2300 			free(tmplist);
2301 			return (ERR_DEVICE_INVALID);
2302 		}
2303 
2304 		attr->controller_id = tmplist[i];
2305 	}
2306 	free(tmplist);
2307 	(void) closedir(dir);
2308 	return (SUCCESS);
2309 }
2310 
2311 static int
2312 obj_controller_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2313 	raid_obj_type_id_t comp_type)
2314 {
2315 	raid_lib_t *raid_lib;
2316 	int ret = SUCCESS, fd;
2317 	controller_attr_t *ctl_attrp;
2318 
2319 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2320 		return (ERR_DEVICE_TYPE);
2321 
2322 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2323 		return (0);
2324 
2325 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2326 	fd = raid_obj_get_fd(raid_tab, obj_id);
2327 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2328 	if ((raid_lib == NULL) || (ctl_attrp == NULL) || (fd == 0))
2329 		return (ERR_DRIVER_CLOSED);
2330 
2331 	ret = raid_lib->compnum(ctl_attrp->controller_id, 0,
2332 	    OBJ_TYPE_CONTROLLER, comp_type);
2333 
2334 	return (ret);
2335 }
2336 
2337 static int
2338 obj_controller_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2339 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2340 {
2341 	raid_lib_t *raid_lib;
2342 	controller_attr_t *ctl_attrp;
2343 	int ret, i, fd;
2344 	uint32_t *ids;
2345 
2346 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2347 		return (ERR_DEVICE_TYPE);
2348 
2349 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2350 		return (0);
2351 
2352 	if ((comp_num <= 0) || (comp_list == NULL))
2353 		return (ERR_OP_ILLEGAL);
2354 
2355 	for (i = 0; i < comp_num; ++i)
2356 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2357 		    comp_type)
2358 			return (ERR_DEVICE_TYPE);
2359 
2360 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2361 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2362 	fd = raid_obj_get_fd(raid_tab, obj_id);
2363 	if ((raid_lib == NULL) || (ctl_attrp == NULL)|| (fd == 0))
2364 		return (ERR_DRIVER_CLOSED);
2365 
2366 	ids = malloc(comp_num * sizeof (uint32_t));
2367 	if (ids == NULL)
2368 		return (ERR_NOMEM);
2369 
2370 	ret = raid_lib->complist(ctl_attrp->controller_id, 0,
2371 	    OBJ_TYPE_CONTROLLER, comp_type, comp_num, ids);
2372 	if (ret < SUCCESS) {
2373 		free(ids);
2374 		return (ret);
2375 	}
2376 	qsort((void *)ids, comp_num, sizeof (uint32_t), intcompare);
2377 	for (i = 0; i < comp_num; ++ i) {
2378 		array_attr_t *array_attr;
2379 		disk_attr_t *disk_attr;
2380 		void *attr_buf;
2381 
2382 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2383 		if (attr_buf == NULL) {
2384 			free(ids);
2385 			return (ERR_DEVICE_INVALID);
2386 		}
2387 
2388 		switch (comp_type) {
2389 		case OBJ_TYPE_ARRAY:
2390 			array_attr = attr_buf;
2391 			array_attr->array_id = *(ids + i);
2392 			break;
2393 		case OBJ_TYPE_DISK:
2394 			disk_attr = attr_buf;
2395 			disk_attr->disk_id = *(ids + i);
2396 			break;
2397 		default:
2398 			free(ids);
2399 			return (ERR_DEVICE_INVALID);
2400 		}
2401 	}
2402 
2403 	free(ids);
2404 	return (SUCCESS);
2405 }
2406 
2407 static int
2408 obj_controller_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2409 {
2410 	controller_attr_t *attr;
2411 	raid_lib_t *raid_lib;
2412 	int ret = SUCCESS, fd;
2413 
2414 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2415 		return (ERR_DEVICE_TYPE);
2416 
2417 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2418 		return (SUCCESS);
2419 
2420 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2421 	if (attr == NULL)
2422 		return (ERR_DEVICE_INVALID);
2423 
2424 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2425 	fd = raid_obj_get_fd(raid_tab, obj_id);
2426 
2427 	/*
2428 	 * For a controller, even it's not opened, we can still
2429 	 * get the driver name
2430 	 */
2431 
2432 	if (fd == 0)
2433 		return (SUCCESS);
2434 
2435 	if (raid_lib == NULL) {
2436 		return (SUCCESS);
2437 	}
2438 
2439 	ret = raid_lib->get_attr(attr->controller_id, OBJ_ATTR_NONE,
2440 	    OBJ_ATTR_NONE, OBJ_TYPE_CONTROLLER, attr);
2441 	if (ret < SUCCESS)
2442 		return (ret);
2443 
2444 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2445 
2446 	return (ret);
2447 }
2448 
2449 static int
2450 obj_controller_act(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2451 	uint32_t sub_cmd, void *prop_list, char **plugin_err_str)
2452 {
2453 	controller_attr_t *attr;
2454 	raid_lib_t *raid_lib;
2455 	int ret, fd;
2456 
2457 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2458 		return (ERR_DEVICE_TYPE);
2459 
2460 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2461 
2462 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2463 	fd = raid_obj_get_fd(raid_tab, obj_id);
2464 
2465 	switch (sub_cmd) {
2466 	case ACT_CONTROLLER_OPEN:
2467 		/* Check if already opened */
2468 
2469 		if (fd > 0)
2470 			return (SUCCESS);
2471 
2472 		/* Check if plugin is already attached */
2473 		if (raid_lib == NULL) {
2474 			raid_lib = raid_find_lib(raid_tab, obj_id);
2475 			if (raid_lib == NULL)
2476 				return (ERR_DRIVER_NOT_FOUND);
2477 		}
2478 
2479 		ret = raid_lib->open_controller(attr->controller_id,
2480 		    plugin_err_str);
2481 		if (ret == SUCCESS) {
2482 			(void) raid_obj_set_lib(raid_tab, obj_id, raid_lib);
2483 			(void) raid_obj_set_fd(raid_tab, obj_id, 1);
2484 		}
2485 		break;
2486 	case ACT_CONTROLLER_CLOSE:
2487 
2488 		if (fd <= 0)
2489 			return (SUCCESS);
2490 
2491 		if (raid_lib == NULL) {
2492 			return (SUCCESS);
2493 		}
2494 		ret = raid_lib->close_controller(attr->controller_id,
2495 		    plugin_err_str);
2496 		if (ret == SUCCESS) {
2497 			(void) raid_obj_set_fd(raid_tab, obj_id, 0);
2498 			(void) raid_obj_set_lib(raid_tab, obj_id, NULL);
2499 			raid_handle_delete_controller_comp(attr->controller_id);
2500 		}
2501 		break;
2502 	case ACT_CONTROLLER_FLASH_FW:
2503 		{
2504 			char		*filebuf;
2505 			int		image_fd;
2506 			uint32_t	size;
2507 			struct stat	statbuf;
2508 
2509 			if (prop_list == NULL)
2510 				return (ERR_OP_ILLEGAL);
2511 
2512 			/* Open firmware image file */
2513 			image_fd = open((const char *)prop_list,
2514 			    O_RDONLY | O_NDELAY);
2515 			if (image_fd == -1)
2516 				return (ERR_OP_FAILED);
2517 
2518 			if (fstat(image_fd, &statbuf) != 0) {
2519 				(void) close(image_fd);
2520 				return (ERR_OP_FAILED);
2521 			}
2522 
2523 			filebuf = malloc(statbuf.st_size);
2524 			if (filebuf == NULL) {
2525 				(void) close(image_fd);
2526 				return (ERR_NOMEM);
2527 			}
2528 
2529 			size = read(image_fd, filebuf, statbuf.st_size);
2530 			if (size != statbuf.st_size) {
2531 				(void) close(image_fd);
2532 				free(filebuf);
2533 				return (ERR_OP_FAILED);
2534 			}
2535 
2536 			if (fd <= 0) {
2537 				(void) close(image_fd);
2538 				free(filebuf);
2539 				return (ERR_DRIVER_CLOSED);
2540 			}
2541 
2542 			if (raid_lib == NULL) {
2543 				(void) close(image_fd);
2544 				free(filebuf);
2545 				return (ERR_DRIVER_CLOSED);
2546 			}
2547 			if (raid_lib->flash_fw == NULL) {
2548 				(void) close(image_fd);
2549 				free(filebuf);
2550 				return (ERR_OP_NO_IMPL);
2551 			}
2552 
2553 			ret = raid_lib->flash_fw(attr->controller_id,
2554 			    filebuf, size, plugin_err_str);
2555 		}
2556 		break;
2557 	default:
2558 		return (ERR_OP_ILLEGAL);
2559 	}
2560 
2561 	return (ret);
2562 }
2563 
2564 static int
2565 obj_array_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2566 	raid_obj_type_id_t comp_type)
2567 {
2568 	array_attr_t *attr;
2569 	controller_attr_t *ctl_attrp;
2570 	raid_obj_id_t controller_obj_id;
2571 	raid_lib_t *raid_lib;
2572 	int ret = SUCCESS, fd;
2573 
2574 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2575 		return (ERR_DEVICE_TYPE);
2576 
2577 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
2578 	    comp_type != OBJ_TYPE_ARRAY &&
2579 	    comp_type != OBJ_TYPE_TASK)
2580 		return (0);
2581 
2582 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2583 	if (attr == NULL)
2584 		return (ERR_DEVICE_INVALID);
2585 
2586 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2587 	if (controller_obj_id < OBJ_NONE)
2588 		return (ERR_DEVICE_INVALID);
2589 
2590 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2591 	if (ctl_attrp == NULL) {
2592 		return (ERR_DEVICE_INVALID);
2593 	}
2594 
2595 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2596 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2597 	if ((raid_lib == NULL) || (fd == 0))
2598 		return (ERR_DRIVER_CLOSED);
2599 
2600 	ret = raid_lib->compnum(ctl_attrp->controller_id, attr->array_id,
2601 	    OBJ_TYPE_ARRAY, comp_type);
2602 
2603 	return (ret);
2604 }
2605 
2606 static int
2607 obj_array_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2608 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2609 {
2610 	array_attr_t *attr;
2611 	controller_attr_t *ctl_attrp;
2612 	raid_obj_id_t controller_obj_id;
2613 	raid_lib_t *raid_lib;
2614 	int ret, i, fd;
2615 	uint32_t *ids;
2616 
2617 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2618 		return (ERR_DEVICE_TYPE);
2619 
2620 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
2621 	    comp_type != OBJ_TYPE_ARRAY &&
2622 	    comp_type != OBJ_TYPE_TASK)
2623 		return (0);
2624 
2625 	if (comp_num <= 0 || comp_list == NULL)
2626 		return (ERR_OP_ILLEGAL);
2627 
2628 	for (i = 0; i < comp_num; ++i)
2629 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2630 		    comp_type)
2631 			return (ERR_DEVICE_TYPE);
2632 
2633 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2634 	if (attr == NULL)
2635 		return (ERR_DEVICE_INVALID);
2636 
2637 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2638 	if (controller_obj_id < OBJ_NONE)
2639 		return (ERR_DEVICE_INVALID);
2640 
2641 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2642 	if (ctl_attrp == NULL) {
2643 		return (ERR_DEVICE_INVALID);
2644 	}
2645 
2646 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2647 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2648 	if ((raid_lib == NULL) || (fd == 0))
2649 		return (ERR_DRIVER_CLOSED);
2650 
2651 	ids = malloc(comp_num * sizeof (uint32_t));
2652 	if (ids == NULL)
2653 		return (ERR_NOMEM);
2654 
2655 	ret = raid_lib->complist(ctl_attrp->controller_id,
2656 	    attr->array_id, OBJ_TYPE_ARRAY, comp_type, comp_num, ids);
2657 
2658 	if (ret < SUCCESS) {
2659 		free(ids);
2660 		return (ret);
2661 	}
2662 
2663 	for (i = 0; i < comp_num; ++ i) {
2664 		array_attr_t *array_attr;
2665 		arraypart_attr_t *arraypart_attr;
2666 		task_attr_t *task_attr;
2667 		void *attr_buf;
2668 
2669 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2670 		if (attr_buf == NULL) {
2671 			free(ids);
2672 			return (ERR_DEVICE_INVALID);
2673 		}
2674 
2675 		switch (comp_type) {
2676 		case OBJ_TYPE_ARRAY:
2677 			array_attr = attr_buf;
2678 			array_attr->array_id = *(ids + i);
2679 			break;
2680 		case OBJ_TYPE_ARRAY_PART:
2681 			arraypart_attr = attr_buf;
2682 			arraypart_attr->disk_id = *(ids + i);
2683 			break;
2684 		case OBJ_TYPE_TASK:
2685 			task_attr = attr_buf;
2686 			task_attr->task_id = *(ids + i);
2687 			break;
2688 		default:
2689 			free(ids);
2690 			return (ERR_DEVICE_INVALID);
2691 		}
2692 	}
2693 
2694 
2695 	free(ids);
2696 	return (ret);
2697 }
2698 
2699 static int
2700 obj_array_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2701 {
2702 	array_attr_t *attr;
2703 	controller_attr_t *ctl_attrp;
2704 	raid_lib_t *raid_lib;
2705 	int ret = SUCCESS, fd;
2706 	raid_obj_id_t controller_obj_id;
2707 
2708 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2709 		return (ERR_DEVICE_TYPE);
2710 
2711 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2712 		return (SUCCESS);
2713 
2714 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2715 	if (attr == NULL)
2716 		return (ERR_DEVICE_INVALID);
2717 
2718 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2719 	if (controller_obj_id < OBJ_NONE)
2720 		return (ERR_DEVICE_INVALID);
2721 
2722 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2723 	if (ctl_attrp == NULL) {
2724 		return (ERR_DEVICE_INVALID);
2725 	}
2726 
2727 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2728 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2729 	if ((raid_lib == NULL) || (fd == 0))
2730 		return (ERR_DRIVER_CLOSED);
2731 
2732 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
2733 	    attr->array_id, 0, OBJ_TYPE_ARRAY, attr);
2734 
2735 	if (ret < SUCCESS)
2736 		return (ret);
2737 
2738 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2739 
2740 	return (ret);
2741 }
2742 
2743 static int
2744 obj_array_set_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2745 	uint32_t sub_cmd, uint32_t *value, char **plugin_err_str)
2746 {
2747 	array_attr_t *attr;
2748 	controller_attr_t *ctl_attrp;
2749 	raid_lib_t *raid_lib;
2750 	int ret = SUCCESS, fd;
2751 	raid_obj_id_t controller_obj_id;
2752 
2753 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2754 		return (ERR_DEVICE_TYPE);
2755 
2756 	switch (sub_cmd) {
2757 	case SET_CACHE_WR_PLY:
2758 		if (*value != CACHE_WR_OFF &&
2759 		    *value != CACHE_WR_ON)
2760 			return (ERR_OP_ILLEGAL);
2761 		break;
2762 	case SET_CACHE_RD_PLY:
2763 		if (*value != CACHE_RD_OFF &&
2764 		    *value != CACHE_RD_ON)
2765 			return (ERR_OP_ILLEGAL);
2766 		break;
2767 	case SET_ACTIVATION_PLY:
2768 		if (*value != ARRAY_ACT_ACTIVATE)
2769 			return (ERR_OP_ILLEGAL);
2770 		break;
2771 	default:
2772 		return (ERR_OP_ILLEGAL);
2773 	}
2774 
2775 	(void) obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2776 
2777 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2778 	if (controller_obj_id < OBJ_NONE)
2779 		return (ERR_DEVICE_INVALID);
2780 
2781 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2782 	if (ctl_attrp == NULL) {
2783 		return (ERR_DEVICE_INVALID);
2784 	}
2785 
2786 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2787 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2788 	if ((raid_lib == NULL) || (fd == 0))
2789 		return (ERR_DRIVER_CLOSED);
2790 
2791 	if (raid_lib->set_attr == NULL)
2792 		return (ERR_OP_NO_IMPL);
2793 
2794 	ret = raid_lib->set_attr(ctl_attrp->controller_id,
2795 	    attr->array_id, sub_cmd, value, plugin_err_str);
2796 
2797 	return (ret);
2798 }
2799 
2800 static int
2801 obj_disk_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2802 	raid_obj_type_id_t comp_type)
2803 {
2804 	disk_attr_t *attr;
2805 	controller_attr_t *ctl_attrp;
2806 	raid_obj_id_t controller_obj_id;
2807 	raid_lib_t *raid_lib;
2808 	int ret = SUCCESS, fd;
2809 
2810 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2811 		return (ERR_DEVICE_TYPE);
2812 
2813 	if (comp_type != OBJ_TYPE_DISK_SEG &&
2814 	    comp_type != OBJ_TYPE_HSP &&
2815 	    comp_type != OBJ_TYPE_TASK &&
2816 	    comp_type != OBJ_TYPE_PROP)
2817 		return (0);
2818 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2819 	if ((ret != SUCCESS) || (attr == NULL)) {
2820 		return (ERR_DEVICE_INVALID);
2821 	}
2822 	if (attr->state == DISK_STATE_FAILED) {
2823 		return (SUCCESS);
2824 	}
2825 
2826 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2827 	if (controller_obj_id < OBJ_NONE)
2828 		return (ERR_DEVICE_INVALID);
2829 
2830 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2831 	if (ctl_attrp == NULL) {
2832 		return (ERR_DEVICE_INVALID);
2833 	}
2834 
2835 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2836 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2837 	if ((raid_lib == NULL) || (fd == 0))
2838 		return (ERR_DRIVER_CLOSED);
2839 
2840 	ret = raid_lib->compnum(ctl_attrp->controller_id,
2841 	    attr->disk_id, OBJ_TYPE_DISK, comp_type);
2842 
2843 	return (ret);
2844 }
2845 
2846 static int
2847 obj_disk_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2848 	int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2849 {
2850 	disk_attr_t *attr;
2851 	controller_attr_t *ctl_attrp;
2852 	raid_obj_id_t controller_obj_id;
2853 	raid_lib_t *raid_lib;
2854 	int ret, i, fd;
2855 	uint32_t *ids;
2856 
2857 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2858 		return (ERR_DEVICE_TYPE);
2859 
2860 	if (comp_type != OBJ_TYPE_DISK_SEG &&
2861 	    comp_type != OBJ_TYPE_HSP &&
2862 	    comp_type != OBJ_TYPE_TASK &&
2863 	    comp_type != OBJ_TYPE_PROP)
2864 		return (0);
2865 
2866 	if (comp_num <= 0 || comp_list == NULL)
2867 		return (ERR_OP_ILLEGAL);
2868 
2869 	for (i = 0; i < comp_num; ++i)
2870 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2871 		    comp_type)
2872 			return (ERR_DEVICE_TYPE);
2873 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2874 	if ((ret != SUCCESS) || (attr == NULL)) {
2875 		return (ERR_DEVICE_INVALID);
2876 	}
2877 	if (attr->state == DISK_STATE_FAILED) {
2878 		return (SUCCESS);
2879 	}
2880 
2881 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2882 	if (controller_obj_id < OBJ_NONE)
2883 		return (ERR_DEVICE_INVALID);
2884 
2885 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2886 	if (ctl_attrp == NULL) {
2887 		return (ERR_DEVICE_INVALID);
2888 	}
2889 
2890 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2891 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2892 	if ((raid_lib == NULL) || (fd == 0))
2893 		return (ERR_DRIVER_CLOSED);
2894 
2895 	ids = malloc(comp_num * sizeof (uint32_t));
2896 	if (ids == NULL)
2897 		return (ERR_NOMEM);
2898 
2899 	ret = raid_lib->complist(ctl_attrp->controller_id,
2900 	    attr->disk_id, OBJ_TYPE_DISK, comp_type, comp_num, ids);
2901 
2902 	if (ret < SUCCESS) {
2903 		free(ids);
2904 		return (ret);
2905 	}
2906 
2907 	for (i = 0; i < comp_num; ++ i) {
2908 		diskseg_attr_t *diskseg_attr;
2909 		hsp_attr_t *hsp_attr;
2910 		task_attr_t *task_attr;
2911 		property_attr_t *prop_attr;
2912 		void *attr_buf;
2913 
2914 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2915 		if (attr_buf == NULL) {
2916 			free(ids);
2917 			return (ERR_DEVICE_INVALID);
2918 		}
2919 
2920 		switch (comp_type) {
2921 		case OBJ_TYPE_DISK_SEG:
2922 			diskseg_attr = attr_buf;
2923 			diskseg_attr->seq_no = *(ids + i);
2924 			break;
2925 		case OBJ_TYPE_HSP:
2926 			hsp_attr = attr_buf;
2927 			hsp_attr->associated_id = *(ids + i);
2928 			break;
2929 		case OBJ_TYPE_TASK:
2930 			task_attr = attr_buf;
2931 			task_attr->task_id = *(ids + i);
2932 			break;
2933 		case OBJ_TYPE_PROP:
2934 			prop_attr = attr_buf;
2935 			prop_attr->prop_id = *(ids + i);
2936 			break;
2937 		default:
2938 			free(ids);
2939 			return (ERR_DEVICE_INVALID);
2940 		}
2941 	}
2942 
2943 
2944 	free(ids);
2945 	return (ret);
2946 }
2947 
2948 static int
2949 obj_disk_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2950 {
2951 	disk_attr_t *attr;
2952 	controller_attr_t *ctl_attrp;
2953 	raid_lib_t *raid_lib;
2954 	int ret = SUCCESS, fd;
2955 	raid_obj_id_t controller_obj_id;
2956 
2957 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2958 		return (ERR_DEVICE_TYPE);
2959 
2960 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2961 		return (SUCCESS);
2962 
2963 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2964 	if (attr == NULL)
2965 		return (ERR_DEVICE_INVALID);
2966 
2967 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2968 	if (controller_obj_id < OBJ_NONE)
2969 		return (ERR_DEVICE_INVALID);
2970 
2971 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2972 	if (ctl_attrp == NULL) {
2973 		return (ERR_DEVICE_INVALID);
2974 	}
2975 
2976 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2977 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2978 	if ((raid_lib == NULL) || (fd == 0))
2979 		return (ERR_DRIVER_CLOSED);
2980 
2981 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
2982 	    attr->disk_id, 0, OBJ_TYPE_DISK, attr);
2983 
2984 	if (ret < SUCCESS)
2985 		return (ret);
2986 
2987 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2988 
2989 	return (ret);
2990 }
2991 
2992 static int
2993 obj_hsp_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2994 {
2995 	hsp_attr_t *attr;
2996 
2997 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_HSP)
2998 		return (ERR_DEVICE_TYPE);
2999 
3000 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3001 		return (SUCCESS);
3002 
3003 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3004 	if (attr == NULL)
3005 		return (ERR_DEVICE_INVALID);
3006 
3007 	if (attr->associated_id == (uint32_t)OBJ_ATTR_NONE)
3008 		attr->type = HSP_TYPE_GLOBAL;
3009 	else
3010 		attr->type = HSP_TYPE_LOCAL;
3011 
3012 	return (SUCCESS);
3013 }
3014 
3015 static int
3016 obj_arraypart_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3017 {
3018 	arraypart_attr_t *attr;
3019 	array_attr_t *array_attr;
3020 	controller_attr_t *ctl_attrp;
3021 	raid_lib_t *raid_lib;
3022 	int ret = SUCCESS, fd;
3023 	raid_obj_id_t controller_obj_id, array_obj_id;
3024 
3025 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY_PART)
3026 		return (ERR_DEVICE_TYPE);
3027 
3028 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3029 		return (SUCCESS);
3030 
3031 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3032 	if (attr == NULL)
3033 		return (ERR_DEVICE_INVALID);
3034 
3035 	array_obj_id = raid_obj_get_container(raid_tab, obj_id);
3036 	if (array_obj_id < OBJ_NONE)
3037 		return (ERR_DEVICE_INVALID);
3038 
3039 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3040 	if (array_attr == NULL)
3041 		return (ERR_DEVICE_INVALID);
3042 
3043 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3044 	if (controller_obj_id < OBJ_NONE)
3045 		return (ERR_DEVICE_INVALID);
3046 
3047 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3048 	if (ctl_attrp == NULL) {
3049 		return (ERR_DEVICE_INVALID);
3050 	}
3051 
3052 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3053 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3054 	if ((raid_lib == NULL) || (fd == 0))
3055 		return (ERR_DRIVER_CLOSED);
3056 
3057 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3058 	    array_attr->array_id, attr->disk_id,
3059 	    OBJ_TYPE_ARRAY_PART, attr);
3060 
3061 	if (ret < SUCCESS)
3062 		return (ret);
3063 
3064 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3065 
3066 	return (ret);
3067 }
3068 
3069 static int
3070 obj_diskseg_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3071 {
3072 	diskseg_attr_t *attr;
3073 	disk_attr_t *disk_attr;
3074 	controller_attr_t *ctl_attrp;
3075 	raid_lib_t *raid_lib;
3076 	int ret = SUCCESS, fd;
3077 	raid_obj_id_t controller_obj_id, disk_obj_id;
3078 
3079 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK_SEG)
3080 		return (ERR_DEVICE_TYPE);
3081 
3082 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3083 		return (SUCCESS);
3084 
3085 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3086 	if (attr == NULL)
3087 		return (ERR_DEVICE_INVALID);
3088 
3089 	disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
3090 	if (disk_obj_id < OBJ_NONE)
3091 		return (ERR_DEVICE_INVALID);
3092 
3093 	disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
3094 	if (disk_attr == NULL)
3095 		return (ERR_DEVICE_INVALID);
3096 
3097 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3098 	if (controller_obj_id < OBJ_NONE)
3099 		return (ERR_DEVICE_INVALID);
3100 
3101 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3102 	if (ctl_attrp == NULL) {
3103 		return (ERR_DEVICE_INVALID);
3104 	}
3105 
3106 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3107 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3108 	if ((raid_lib == NULL) || (fd == 0))
3109 		return (ERR_DRIVER_CLOSED);
3110 
3111 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3112 	    disk_attr->disk_id, attr->seq_no, OBJ_TYPE_DISK_SEG, attr);
3113 
3114 	if (ret < SUCCESS)
3115 		return (ret);
3116 
3117 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3118 
3119 	return (ret);
3120 }
3121 
3122 static int
3123 obj_task_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3124 {
3125 	task_attr_t *attr;
3126 	controller_attr_t *ctl_attrp;
3127 	raid_lib_t *raid_lib;
3128 	int ret = SUCCESS, fd;
3129 	raid_obj_id_t controller_obj_id;
3130 
3131 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_TASK)
3132 		return (ERR_DEVICE_TYPE);
3133 
3134 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3135 	if (attr == NULL)
3136 		return (ERR_DEVICE_INVALID);
3137 
3138 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3139 	if (controller_obj_id < OBJ_NONE)
3140 		return (ERR_DEVICE_INVALID);
3141 
3142 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3143 	if (ctl_attrp == NULL) {
3144 		return (ERR_DEVICE_INVALID);
3145 	}
3146 
3147 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3148 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3149 	if ((raid_lib == NULL) || (fd == 0))
3150 		return (ERR_DRIVER_CLOSED);
3151 
3152 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3153 	    attr->task_id, OBJ_ATTR_NONE, OBJ_TYPE_TASK, attr);
3154 
3155 	return (ret);
3156 }
3157 
3158 static int
3159 obj_prop_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3160 {
3161 	property_attr_t *attr, *attr_new;
3162 	disk_attr_t *disk_attr;
3163 	controller_attr_t *ctl_attrp;
3164 	raid_lib_t *raid_lib;
3165 	int ret = SUCCESS, fd;
3166 	raid_obj_id_t controller_obj_id, disk_obj_id;
3167 
3168 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_PROP)
3169 		return (ERR_DEVICE_TYPE);
3170 
3171 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3172 		return (SUCCESS);
3173 
3174 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3175 	if (attr == NULL)
3176 		return (ERR_DEVICE_INVALID);
3177 
3178 	disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
3179 	if (disk_obj_id < OBJ_NONE)
3180 		return (ERR_DEVICE_INVALID);
3181 
3182 	disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
3183 	if (disk_attr == NULL)
3184 		return (ERR_DEVICE_INVALID);
3185 
3186 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3187 	if (controller_obj_id < OBJ_NONE)
3188 		return (ERR_DEVICE_INVALID);
3189 
3190 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3191 	if (ctl_attrp == NULL) {
3192 		return (ERR_DEVICE_INVALID);
3193 	}
3194 
3195 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3196 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3197 	if ((raid_lib == NULL) || (fd == 0))
3198 		return (ERR_DRIVER_CLOSED);
3199 
3200 	/* Get the property size at first */
3201 	attr->prop_size = 0;
3202 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3203 	    disk_attr->disk_id, OBJ_ATTR_NONE, OBJ_TYPE_PROP, attr);
3204 
3205 	if (ret < SUCCESS)
3206 		return (ret);
3207 
3208 	/* Allocate memory for property and fill the buffer */
3209 	attr_new = realloc(attr, sizeof (property_attr_t) + attr->prop_size);
3210 	if (attr_new == NULL)
3211 		return (ERR_NOMEM);
3212 
3213 	(void) raid_obj_set_data_ptr(raid_tab, obj_id, attr_new);
3214 
3215 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3216 	    disk_attr->disk_id, OBJ_ATTR_NONE, OBJ_TYPE_PROP, attr_new);
3217 
3218 	if (ret < SUCCESS)
3219 		return (ret);
3220 
3221 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3222 
3223 	return (ret);
3224 }
3225 
3226 static int
3227 obj_array_create(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3228 	int num_of_comp, raid_obj_id_t *disk_list, char **plugin_err_str)
3229 {
3230 	controller_attr_t *controller_attr;
3231 	array_attr_t *array_attr, array_attr2;
3232 	disk_attr_t *disk_attr;
3233 	arraypart_attr_t *arraypart_attrs;
3234 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3235 	raid_lib_t *raid_lib;
3236 	int i, j, ret, fd;
3237 	int disk_cnt = 0, disk_set_num = 0, set_num = 0, layer_cnt = 0;
3238 	uint64_t min_disk_capacity = 0;
3239 
3240 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3241 	if (array_attr == NULL)
3242 		return (ERR_DEVICE_INVALID);
3243 
3244 	/* Check the disk layout expression */
3245 	if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
3246 	    disk_list[num_of_comp - 1] != OBJ_SEPARATOR_END)
3247 		return (ERR_ARRAY_LAYOUT);
3248 	for (i = 0; i < num_of_comp; ++i) {
3249 		if (disk_list[i] == OBJ_SEPARATOR_BEGIN) {
3250 			if (disk_cnt != 0)
3251 				return (ERR_ARRAY_LAYOUT);
3252 			++layer_cnt;
3253 			continue;
3254 		}
3255 		if (disk_list[i] == OBJ_SEPARATOR_END) {
3256 			if (disk_set_num == 0)
3257 				disk_set_num = disk_cnt;
3258 			else if (disk_set_num != disk_cnt && disk_cnt != 0)
3259 				return (ERR_ARRAY_LAYOUT);
3260 			disk_cnt = 0;
3261 			++set_num;
3262 			--layer_cnt;
3263 			continue;
3264 		}
3265 		switch (array_attr->raid_level) {
3266 		case RAID_LEVEL_0:
3267 		case RAID_LEVEL_1:
3268 		case RAID_LEVEL_1E:
3269 		case RAID_LEVEL_5:
3270 			if (layer_cnt != 1)
3271 				return (ERR_ARRAY_LAYOUT);
3272 			break;
3273 		case RAID_LEVEL_10:
3274 		case RAID_LEVEL_50:
3275 			if (layer_cnt != 2)
3276 				return (ERR_ARRAY_LAYOUT);
3277 			break;
3278 		default:
3279 			return (ERR_ARRAY_LEVEL);
3280 		}
3281 		++disk_cnt;
3282 	}
3283 
3284 	if (layer_cnt != 0)
3285 		return (ERR_ARRAY_LAYOUT);
3286 
3287 	switch (array_attr->raid_level) {
3288 	case RAID_LEVEL_0:
3289 		if (disk_set_num < 2 || set_num != 1)
3290 			return (ERR_ARRAY_LAYOUT);
3291 		break;
3292 	case RAID_LEVEL_1:
3293 		if (disk_set_num != 2 || set_num != 1)
3294 			return (ERR_ARRAY_LAYOUT);
3295 		break;
3296 	case RAID_LEVEL_1E:
3297 	case RAID_LEVEL_5:
3298 		if (disk_set_num < 3 || set_num != 1)
3299 			return (ERR_ARRAY_LAYOUT);
3300 		break;
3301 	case RAID_LEVEL_10:
3302 		if (disk_set_num != 2 || set_num < 2)
3303 			return (ERR_ARRAY_LAYOUT);
3304 		break;
3305 	case RAID_LEVEL_50:
3306 		if (disk_set_num < 3 || set_num < 2)
3307 			return (ERR_ARRAY_LAYOUT);
3308 		break;
3309 	default:
3310 		return (ERR_ARRAY_LEVEL);
3311 	}
3312 
3313 	arraypart_attrs = calloc(num_of_comp, sizeof (arraypart_attr_t));
3314 	if (arraypart_attrs == NULL)
3315 		return (ERR_NOMEM);
3316 
3317 	for (i = 0; i < num_of_comp; ++i) {
3318 		/* Keep seperators */
3319 		if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3320 			arraypart_attrs[i].disk_id =
3321 			    (uint32_t)OBJ_SEPARATOR_BEGIN;
3322 			continue;
3323 		}
3324 
3325 		if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3326 			arraypart_attrs[i].disk_id =
3327 			    (uint32_t)OBJ_SEPARATOR_END;
3328 			continue;
3329 		}
3330 
3331 		disk_cnt++;
3332 		/* Check if it's a disk */
3333 		if (raid_obj_get_type(raid_tab, *(disk_list + i)) !=
3334 		    OBJ_TYPE_DISK)
3335 			return (ERR_DEVICE_TYPE);
3336 
3337 		/* Check if it's duplicated with other disks */
3338 		for (j = 0; j < i; ++j)
3339 			if (*(disk_list + j) == *(disk_list + i)) {
3340 				free(arraypart_attrs);
3341 				return (ERR_DEVICE_DUP);
3342 			}
3343 
3344 		/* Check disk status */
3345 		ret = obj_get_attr(raid_tab, *(disk_list + i),
3346 		    (void **)(&disk_attr));
3347 		if (ret != SUCCESS)
3348 			return (ret);
3349 
3350 		if (disk_attr->state != DISK_STATE_GOOD) {
3351 			free(arraypart_attrs);
3352 			return (ERR_DISK_STATE);
3353 		}
3354 
3355 		/* All disks must belong to the same controller */
3356 		obj_id = obj_get_controller(raid_tab, *(disk_list + i));
3357 		if (obj_id <= OBJ_NONE)
3358 			return (obj_id);
3359 		if (controller_obj_id == OBJ_NONE) {
3360 			controller_obj_id = obj_id;
3361 			ret = obj_get_attr(raid_tab, controller_obj_id,
3362 			    (void **)(&controller_attr));
3363 		} else if (obj_id != controller_obj_id) {
3364 			free(arraypart_attrs);
3365 			return (ERR_DRIVER_ACROSS);
3366 		}
3367 
3368 		/* Check if the disk contains too many segments */
3369 		obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3370 		    OBJ_TYPE_DISK_SEG);
3371 		j = 0;
3372 		while (obj_id > OBJ_NONE) {
3373 			++j;
3374 			obj_id = obj_get_sibling(raid_tab, obj_id);
3375 		}
3376 		if (j > controller_attr->max_seg_per_disk) {
3377 			free(arraypart_attrs);
3378 			return (ERR_DISK_SEG_AMOUNT);
3379 		}
3380 
3381 		/* Check if controller is a hostraid controller */
3382 		if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3383 			/*
3384 			 * For hostraid, the first disk should
3385 			 * be with of minimum capacity
3386 			 */
3387 			if (min_disk_capacity == 0) {
3388 				min_disk_capacity = disk_attr->capacity;
3389 
3390 				/* Can not specify capacity for hostraid */
3391 				if (array_attr->capacity != 0) {
3392 					free(arraypart_attrs);
3393 					return (ERR_OP_ILLEGAL);
3394 				}
3395 			} else if (min_disk_capacity > disk_attr->capacity) {
3396 				free(arraypart_attrs);
3397 				return (ERR_DISK_SPACE);
3398 			}
3399 
3400 			/* Disk should not be used for hostraid */
3401 			obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3402 			    OBJ_TYPE_DISK_SEG);
3403 			if (obj_id < OBJ_NONE) {
3404 				free(arraypart_attrs);
3405 				return (obj_id);
3406 			} else if (obj_id > OBJ_NONE) {
3407 				free(arraypart_attrs);
3408 				return (ERR_DISK_NOT_EMPTY);
3409 			}
3410 		}
3411 
3412 		arraypart_attrs[i].disk_id = disk_attr->disk_id;
3413 		arraypart_attrs[i].offset = OBJ_ATTR_NONE;
3414 		arraypart_attrs[i].size = OBJ_ATTR_NONE;
3415 	}
3416 
3417 	/* Check if array amount exceeds limit */
3418 	if (controller_attr->max_array_num <=
3419 	    obj_controller_compnum(raid_tab, controller_obj_id,
3420 	    OBJ_TYPE_ARRAY))
3421 		return (ERR_ARRAY_AMOUNT);
3422 
3423 
3424 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3425 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3426 	if ((raid_lib == NULL) || (fd == 0))
3427 		return (ERR_DRIVER_CLOSED);
3428 
3429 	/* Check if the controller can support the array RAID level */
3430 	switch (array_attr->raid_level) {
3431 	case	RAID_LEVEL_0:
3432 		if (!(controller_attr->capability & RAID_CAP_RAID0)) {
3433 			free(arraypart_attrs);
3434 			return (ERR_ARRAY_LEVEL);
3435 		}
3436 		break;
3437 	case	RAID_LEVEL_1:
3438 		if (!(controller_attr->capability & RAID_CAP_RAID1)) {
3439 			free(arraypart_attrs);
3440 			return (ERR_ARRAY_LEVEL);
3441 		}
3442 		break;
3443 	case	RAID_LEVEL_1E:
3444 		if (!(controller_attr->capability & RAID_CAP_RAID1E)) {
3445 			free(arraypart_attrs);
3446 			return (ERR_ARRAY_LEVEL);
3447 		}
3448 		break;
3449 	case	RAID_LEVEL_5:
3450 		if (!(controller_attr->capability & RAID_CAP_RAID5)) {
3451 			free(arraypart_attrs);
3452 			return (ERR_ARRAY_LEVEL);
3453 		}
3454 		break;
3455 	case	RAID_LEVEL_10:
3456 		if (!(controller_attr->capability & RAID_CAP_RAID10)) {
3457 			free(arraypart_attrs);
3458 			return (ERR_ARRAY_LEVEL);
3459 		}
3460 		break;
3461 	case	RAID_LEVEL_50:
3462 		if (!(controller_attr->capability & RAID_CAP_RAID50)) {
3463 			free(arraypart_attrs);
3464 			return (ERR_ARRAY_LEVEL);
3465 		}
3466 		break;
3467 	default:
3468 		free(arraypart_attrs);
3469 		return (ERR_ARRAY_LEVEL);
3470 	}
3471 
3472 	/* Check if plug in can calculate the maximum size */
3473 	(void) memcpy(&array_attr2, array_attr, sizeof (array_attr_t));
3474 	array_attr2.capacity = OBJ_ATTR_NONE;
3475 	ret = raid_lib->array_create(controller_attr->controller_id,
3476 	    &array_attr2, num_of_comp, arraypart_attrs, plugin_err_str);
3477 
3478 	/* If plugin/driver will not calculate space */
3479 	if (ret == ERR_OP_NO_IMPL) {
3480 		/* Calculate the maximum capacity */
3481 		array_attr2.capacity = raid_space_noalign(raid_tab,
3482 		    array_attr2.raid_level, num_of_comp, disk_list,
3483 		    arraypart_attrs);
3484 
3485 		/*
3486 		 * If controller is capable to allocate space,
3487 		 * set offset and size attributes to OBJ_ATTR_NONE
3488 		 * and let the controller to determine these value
3489 		 */
3490 		if (controller_attr->capability & RAID_CAP_SMART_ALLOC)
3491 			for (i = 0; i < num_of_comp; ++i) {
3492 				arraypart_attrs[i].offset =
3493 				    OBJ_ATTR_NONE;
3494 				arraypart_attrs[i].size =
3495 				    OBJ_ATTR_NONE;
3496 			}
3497 
3498 		/* There's no enough space for specified capacity */
3499 		if (array_attr->capacity > array_attr2.capacity) {
3500 			free(arraypart_attrs);
3501 			return (ERR_ARRAY_SIZE);
3502 		}
3503 
3504 		/* capacity == 0, allocate maximum space */
3505 		if (array_attr->capacity == 0)
3506 			array_attr->capacity = array_attr2.capacity;
3507 	} else if (ret < SUCCESS) {
3508 		free(arraypart_attrs);
3509 		return (ret);
3510 	} else if (array_attr2.capacity < array_attr->capacity) {
3511 		/* Return the maximum size */
3512 		array_attr->capacity = array_attr2.capacity;
3513 		free(arraypart_attrs);
3514 		return (ERR_ARRAY_SIZE);
3515 	}
3516 
3517 	if (array_attr->capacity < ARRAYPART_MIN_SIZE * disk_cnt) {
3518 		free(arraypart_attrs);
3519 		return (ERR_ARRAY_SIZE);
3520 	}
3521 
3522 
3523 	ret = raid_lib->array_create(controller_attr->controller_id,
3524 	    array_attr, num_of_comp, arraypart_attrs, plugin_err_str);
3525 	free(arraypart_attrs);
3526 
3527 	if (ret != SUCCESS)
3528 		return (ret);
3529 
3530 	/* Add array object into device tree so that we can map the handle */
3531 	(void) raid_obj_add_org(raid_tab, array_obj_id, controller_obj_id);
3532 
3533 	return (ret);
3534 }
3535 
3536 static int
3537 obj_array_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3538 	char **plugin_err_str)
3539 {
3540 	raid_obj_id_t controller_obj_id;
3541 	controller_attr_t *controller_attr;
3542 	array_attr_t *array_attr;
3543 	raid_lib_t *raid_lib;
3544 	int ret, fd;
3545 	uint32_t *disk_ids = NULL;
3546 
3547 	controller_obj_id = obj_get_controller(raid_tab, array_obj_id);
3548 	if (controller_obj_id <= OBJ_NONE)
3549 		return (controller_obj_id);
3550 
3551 	ret = obj_get_attr(raid_tab, controller_obj_id,
3552 	    (void **)(&controller_attr));
3553 	if (ret < SUCCESS) {
3554 		return (ret);
3555 	}
3556 	ret = obj_get_attr(raid_tab, array_obj_id, (void **)(&array_attr));
3557 	if (ret < SUCCESS)
3558 		return (ret);
3559 
3560 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3561 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3562 	if ((raid_lib == NULL) || (fd == 0))
3563 		return (ERR_DRIVER_CLOSED);
3564 
3565 	ret = raid_lib->array_delete(controller_attr->controller_id,
3566 	    array_attr->array_id, plugin_err_str);
3567 	if (ret < SUCCESS) {
3568 		if (disk_ids)
3569 			free(disk_ids);
3570 		return (ret);
3571 	}
3572 
3573 	if (disk_ids)
3574 		free(disk_ids);
3575 	return (ret);
3576 }
3577 
3578 static int
3579 obj_hsp_bind(raid_obj_tab_t *raid_tab, raid_obj_id_t *obj_ids,
3580 	char **plugin_err_str)
3581 {
3582 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3583 	raid_obj_id_t array_obj_id, disk_obj_id;
3584 	hsp_relation_t *hsp_relation;
3585 	controller_attr_t *controller_attr;
3586 	array_attr_t *array_attr;
3587 	arraypart_attr_t *arraypart_attr;
3588 	disk_attr_t *disk_attr;
3589 	diskseg_attr_t *diskseg_attr;
3590 	hsp_attr_t *hsp_attr;
3591 	raid_lib_t *raid_lib;
3592 	int ret, fd;
3593 
3594 	hsp_relation = malloc(sizeof (hsp_relation_t));
3595 	if (hsp_relation == NULL)
3596 		return (ERR_NOMEM);
3597 
3598 	array_obj_id = *(obj_ids);
3599 	disk_obj_id = *(obj_ids + 1);
3600 
3601 	if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK ||
3602 	    (array_obj_id != OBJ_ATTR_NONE &&
3603 	    raid_obj_get_type(raid_tab, array_obj_id) !=
3604 	    OBJ_TYPE_ARRAY)) {
3605 		free(hsp_relation);
3606 		return (ERR_DEVICE_TYPE);
3607 	}
3608 
3609 	/* Get controller attributes */
3610 	if (controller_obj_id == OBJ_NONE)
3611 		controller_obj_id = obj_get_controller(raid_tab,
3612 		    disk_obj_id);
3613 	else if (controller_obj_id != obj_get_controller(raid_tab,
3614 	    disk_obj_id)) {
3615 		free(hsp_relation);
3616 		return (ERR_DRIVER_ACROSS);
3617 	}
3618 
3619 	ret = obj_get_attr(raid_tab, controller_obj_id,
3620 	    (void **)(&controller_attr));
3621 
3622 	/* Get disk attributes */
3623 	ret = obj_get_attr(raid_tab,  disk_obj_id,
3624 	    (void **)(&disk_attr));
3625 	if (disk_attr->state == DISK_STATE_FAILED) {
3626 		free(hsp_relation);
3627 		return (ERR_DISK_STATE);
3628 	}
3629 
3630 	/* If it's not a hsp disk, check if there's occupied space */
3631 	if (obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP) ==
3632 	    OBJ_NONE) {
3633 		obj_id = obj_get_comp(raid_tab, disk_obj_id,
3634 		    OBJ_TYPE_DISK_SEG);
3635 		while (obj_id != OBJ_NONE) {
3636 			ret = obj_get_attr(raid_tab, obj_id,
3637 			    (void **)(&diskseg_attr));
3638 			if (!(diskseg_attr->state &
3639 			    DISKSEG_STATE_RESERVED)) {
3640 				free(hsp_relation);
3641 				return (ERR_DISK_NOT_EMPTY);
3642 			}
3643 			obj_id = obj_get_sibling(raid_tab, obj_id);
3644 		}
3645 	}
3646 
3647 	if (array_obj_id != OBJ_ATTR_NONE) {
3648 		/* If local hsp is supported */
3649 		if (!(controller_attr->capability & RAID_CAP_L_HSP)) {
3650 			free(hsp_relation);
3651 			return (ERR_OP_ILLEGAL);
3652 		}
3653 
3654 		if (raid_obj_get_type(raid_tab, array_obj_id) !=
3655 		    OBJ_TYPE_ARRAY) {
3656 			free(hsp_relation);
3657 			return (ERR_DEVICE_TYPE);
3658 		}
3659 
3660 		/* Get array attributes */
3661 		ret = obj_get_attr(raid_tab, array_obj_id,
3662 		    (void **)(&array_attr));
3663 		/* RAID 0 array can not use hsp */
3664 		if (array_attr->raid_level == RAID_LEVEL_0) {
3665 			free(hsp_relation);
3666 			return (ERR_ARRAY_LEVEL);
3667 		}
3668 
3669 		/* If It's belong to another controller */
3670 		if (controller_obj_id != obj_get_controller(raid_tab,
3671 		    array_obj_id)) {
3672 			free(hsp_relation);
3673 			return (ERR_DRIVER_ACROSS);
3674 		}
3675 
3676 		/* Get an array part attributes */
3677 		if ((array_attr->raid_level == RAID_LEVEL_10) ||
3678 		    (array_attr->raid_level == RAID_LEVEL_50))
3679 			obj_id = obj_get_comp(raid_tab, array_obj_id,
3680 			    OBJ_TYPE_ARRAY);
3681 		else
3682 			obj_id = array_obj_id;
3683 		obj_id = obj_get_comp(raid_tab, obj_id,
3684 		    OBJ_TYPE_ARRAY_PART);
3685 		ret = obj_get_attr(raid_tab, obj_id,
3686 		    (void **)(&arraypart_attr));
3687 
3688 		/* Check if disk space is enough for array */
3689 		if (arraypart_attr->size > disk_attr->capacity) {
3690 			free(hsp_relation);
3691 			return (ERR_DISK_SPACE);
3692 		}
3693 		if (controller_attr->capability & RAID_CAP_ARRAY_ALIGN)
3694 			if ((arraypart_attr->size +
3695 			    arraypart_attr->offset) >
3696 			    disk_attr->capacity) {
3697 			free(hsp_relation);
3698 			return (ERR_DISK_SPACE);
3699 			}
3700 	} else if (!(controller_attr->capability & RAID_CAP_G_HSP)) {
3701 		/* if global hsp is supported */
3702 		free(hsp_relation);
3703 		return (ERR_OP_ILLEGAL);
3704 	}
3705 
3706 	/*
3707 	 * If the array is already associated with the
3708 	 * local hsp, or it's a global hsp, ignore it
3709 	 */
3710 	obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3711 	if (obj_id > OBJ_NONE) {
3712 		if (obj_get_attr(raid_tab, obj_id,
3713 		    (void **)&hsp_attr) >= SUCCESS) {
3714 			if (((hsp_attr->type == HSP_TYPE_GLOBAL) &&
3715 			    (array_obj_id != OBJ_ATTR_NONE)) ||
3716 			    ((hsp_attr->type == HSP_TYPE_LOCAL) &&
3717 			    (array_obj_id == OBJ_ATTR_NONE))) {
3718 				free(hsp_relation);
3719 				return (ERR_OP_ILLEGAL);
3720 			}
3721 		}
3722 	}
3723 
3724 	if (array_obj_id != OBJ_ATTR_NONE)
3725 		hsp_relation->array_id = array_attr->array_id;
3726 	else
3727 		hsp_relation->array_id = (uint32_t)OBJ_ATTR_NONE;
3728 	hsp_relation->disk_id = disk_attr->disk_id;
3729 
3730 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3731 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3732 	if ((raid_lib == NULL) || (fd == 0))
3733 		return (ERR_DRIVER_CLOSED);
3734 
3735 	if (raid_lib->hsp_bind == NULL) {
3736 		free(hsp_relation);
3737 		return (ERR_OP_NO_IMPL);
3738 	}
3739 
3740 	ret = raid_lib->hsp_bind(controller_attr->controller_id,
3741 	    hsp_relation, plugin_err_str);
3742 
3743 	free(hsp_relation);
3744 	return (ret);
3745 }
3746 
3747 static int
3748 obj_hsp_unbind(raid_obj_tab_t *raid_tab, raid_obj_id_t *obj_ids,
3749 	char **plugin_err_str)
3750 {
3751 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3752 	raid_obj_id_t array_obj_id, disk_obj_id;
3753 	hsp_relation_t *hsp_relation;
3754 	controller_attr_t *controller_attr;
3755 	array_attr_t *array_attr;
3756 	disk_attr_t *disk_attr;
3757 	hsp_attr_t *hsp_attr;
3758 	raid_lib_t *raid_lib;
3759 	int ret, fd;
3760 
3761 	hsp_relation = malloc(sizeof (hsp_relation_t));
3762 	if (hsp_relation == NULL)
3763 		return (ERR_NOMEM);
3764 
3765 	array_obj_id = *(obj_ids);
3766 	disk_obj_id = *(obj_ids + 1);
3767 
3768 	if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK) {
3769 		free(hsp_relation);
3770 		return (ERR_DEVICE_TYPE);
3771 	}
3772 
3773 	/* Get controller attributes */
3774 	if (controller_obj_id == OBJ_NONE)
3775 		controller_obj_id = obj_get_controller(raid_tab,
3776 		    disk_obj_id);
3777 	else if (controller_obj_id != obj_get_controller(raid_tab,
3778 	    disk_obj_id)) {
3779 		free(hsp_relation);
3780 		return (ERR_DRIVER_ACROSS);
3781 	}
3782 
3783 	ret = obj_get_attr(raid_tab, controller_obj_id,
3784 	    (void **)(&controller_attr));
3785 
3786 	/* Get disk attributes */
3787 	ret = obj_get_attr(raid_tab,  disk_obj_id,
3788 	    (void **)(&disk_attr));
3789 	if (disk_attr->state == DISK_STATE_FAILED) {
3790 		free(hsp_relation);
3791 		return (ERR_DISK_STATE);
3792 	}
3793 
3794 	/* If it's not a hsp disk */
3795 	obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3796 	if (obj_id == OBJ_NONE) {
3797 		free(hsp_relation);
3798 		return (ERR_DISK_STATE);
3799 	}
3800 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
3801 
3802 	if (array_obj_id != OBJ_ATTR_NONE) {
3803 		if (raid_obj_get_type(raid_tab, array_obj_id) !=
3804 		    OBJ_TYPE_ARRAY) {
3805 			free(hsp_relation);
3806 			return (ERR_DEVICE_TYPE);
3807 		}
3808 
3809 		/* Get array attributes */
3810 		ret = obj_get_attr(raid_tab, array_obj_id,
3811 		    (void **)(&array_attr));
3812 
3813 		/* If It's belong to another controller */
3814 		if (controller_obj_id != obj_get_controller(raid_tab,
3815 		    array_obj_id)) {
3816 			free(hsp_relation);
3817 			return (ERR_DRIVER_ACROSS);
3818 		}
3819 
3820 		/* If want to remove an array from a global hsp */
3821 		if (hsp_attr->type == HSP_TYPE_GLOBAL) {
3822 			free(hsp_relation);
3823 			return (ERR_OP_ILLEGAL);
3824 		}
3825 
3826 		do {
3827 			(void) obj_get_attr(raid_tab, obj_id,
3828 			    (void **)(&hsp_attr));
3829 
3830 			if (hsp_attr->associated_id ==
3831 			    array_attr->array_id ||
3832 			    hsp_attr->type == HSP_TYPE_GLOBAL)
3833 				break;
3834 
3835 			obj_id = obj_get_sibling(raid_tab, obj_id);
3836 		} while (obj_id > OBJ_NONE);
3837 	} else if (hsp_attr->type != HSP_TYPE_GLOBAL) {
3838 		/* if global hsp is supported */
3839 		free(hsp_relation);
3840 		return (ERR_OP_ILLEGAL);
3841 	}
3842 
3843 	/*
3844 	 * If array is associated with a local hsp, or remove a
3845 	 * global hsp disk
3846 	 */
3847 	if ((obj_id && (array_obj_id != OBJ_ATTR_NONE)) ||
3848 	    (array_obj_id == OBJ_ATTR_NONE)) {
3849 		if (array_obj_id != OBJ_ATTR_NONE)
3850 			hsp_relation->array_id = array_attr->array_id;
3851 		else
3852 			hsp_relation->array_id =
3853 			    (uint32_t)OBJ_ATTR_NONE;
3854 		hsp_relation->disk_id = disk_attr->disk_id;
3855 	} else {
3856 		free(hsp_relation);
3857 		return (ERR_OP_ILLEGAL);
3858 	}
3859 
3860 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3861 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3862 	if ((raid_lib == NULL) || (fd == 0))
3863 		return (ERR_DRIVER_CLOSED);
3864 
3865 	if (raid_lib->hsp_unbind == NULL) {
3866 		free(hsp_relation);
3867 		return (ERR_OP_NO_IMPL);
3868 	}
3869 
3870 	ret = raid_lib->hsp_unbind(controller_attr->controller_id,
3871 	    hsp_relation, plugin_err_str);
3872 
3873 	free(hsp_relation);
3874 	return (ret);
3875 }
3876 
3877 /*
3878  * Object maintennance routines
3879  */
3880 static int
3881 raid_obj_create_system_obj(raid_obj_tab_t *raid_tab)
3882 {
3883 	raid_obj_t *raid_obj;
3884 	int ret;
3885 
3886 	raid_obj = calloc(1, sizeof (raid_obj_t));
3887 	if (raid_obj == NULL)
3888 		return (ERR_NOMEM);
3889 
3890 	raid_obj->obj_id = OBJ_SYSTEM;
3891 	raid_obj->obj_type_id = OBJ_TYPE_SYSTEM;
3892 	raid_obj->data = NULL;
3893 
3894 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3895 	if (ret == ERR_DEVICE_DUP) {
3896 		free(raid_obj);
3897 		return (ERR_DEVICE_UNCLEAN);
3898 	}
3899 
3900 	return (SUCCESS);
3901 }
3902 
3903 static raid_obj_id_t
3904 raid_obj_id_new(raid_obj_tab_t *raid_tab)
3905 {
3906 	++ raid_tab->obj_id_cnt;
3907 	if (raid_tab->obj_id_cnt <= 0)
3908 		return (ERR_DEVICE_OVERFLOW);
3909 
3910 	return (raid_tab->obj_id_cnt);
3911 }
3912 
3913 static void *
3914 raid_obj_attr_new(raid_obj_type_id_t obj_type)
3915 {
3916 	void *obj_attr = NULL;
3917 
3918 	switch (obj_type) {
3919 	case	OBJ_TYPE_CONTROLLER:
3920 		obj_attr = calloc(1, sizeof (controller_attr_t));
3921 		break;
3922 	case	OBJ_TYPE_ARRAY:
3923 		obj_attr = calloc(1, sizeof (array_attr_t));
3924 		break;
3925 	case	OBJ_TYPE_DISK:
3926 		obj_attr = calloc(1, sizeof (disk_attr_t));
3927 		break;
3928 	case	OBJ_TYPE_HSP:
3929 		obj_attr = calloc(1, sizeof (hsp_attr_t));
3930 		break;
3931 	case	OBJ_TYPE_ARRAY_PART:
3932 		obj_attr = calloc(1, sizeof (arraypart_attr_t));
3933 		break;
3934 	case	OBJ_TYPE_DISK_SEG:
3935 		obj_attr = calloc(1, sizeof (diskseg_attr_t));
3936 		break;
3937 	case	OBJ_TYPE_TASK:
3938 		obj_attr = calloc(1, sizeof (task_attr_t));
3939 		break;
3940 	case	OBJ_TYPE_PROP:
3941 		obj_attr = calloc(1, sizeof (property_attr_t));
3942 		break;
3943 	default:
3944 		break;
3945 	}
3946 
3947 	return (obj_attr);
3948 }
3949 
3950 static raid_obj_id_t
3951 raid_obj_create(raid_obj_tab_t *raid_tab, raid_obj_type_id_t obj_type)
3952 {
3953 	raid_obj_t *raid_obj;
3954 	int ret;
3955 	void *data_ptr;
3956 
3957 	raid_obj = calloc(1, sizeof (raid_obj_t));
3958 	if (raid_obj == NULL)
3959 		return (ERR_NOMEM);
3960 
3961 	raid_obj->obj_id = raid_obj_id_new(raid_tab);
3962 	if (raid_obj->obj_id < OBJ_NONE)
3963 		return (ERR_DEVICE_OVERFLOW);
3964 
3965 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3966 	if (ret == ERR_DEVICE_DUP) {
3967 		free(raid_obj);
3968 		return (ERR_DEVICE_DUP);
3969 	}
3970 
3971 	data_ptr = raid_obj_attr_new(obj_type);
3972 	if (data_ptr == NULL) {
3973 		(void) raid_obj_delete(raid_tab, raid_obj->obj_id);
3974 		return (ERR_NOMEM);
3975 	}
3976 
3977 	(void) raid_obj_set_data_ptr(raid_tab, raid_obj->obj_id, data_ptr);
3978 
3979 	(void) raid_obj_set_type(raid_tab, raid_obj->obj_id, obj_type);
3980 	return (raid_obj->obj_id);
3981 }
3982 
3983 static int
3984 raid_obj_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t raid_obj_id)
3985 {
3986 	raid_obj_t *obj;
3987 
3988 	obj = raid_obj_tab_remove(raid_tab, raid_obj_id);
3989 	if (obj != NULL) {
3990 		free(obj->data);
3991 		free(obj);
3992 		return (SUCCESS);
3993 	}
3994 
3995 	return (ERR_DEVICE_NOENT);
3996 }
3997 
3998 static int
3999 raid_obj_add_org(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4000 	raid_obj_id_t container_id)
4001 {
4002 	raid_obj_id_t tmp, tmp1;
4003 
4004 	tmp = raid_obj_get_comp(raid_tab, container_id);
4005 	if (tmp < OBJ_NONE)
4006 		return (ERR_DEVICE_NOENT);
4007 
4008 	if (tmp == OBJ_NONE) {
4009 		(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4010 		(void) raid_obj_set_comp(raid_tab, container_id, obj_id);
4011 		return (SUCCESS);
4012 	}
4013 
4014 	while ((tmp1 = raid_obj_get_sibling(raid_tab, tmp)) != OBJ_NONE)
4015 		tmp = tmp1;
4016 
4017 	if (raid_obj_set_sibling(raid_tab, tmp, obj_id) < SUCCESS)
4018 		return (ERR_DEVICE_NOENT);
4019 	(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4020 
4021 	return (SUCCESS);
4022 }
4023 
4024 static raid_obj_type_id_t
4025 raid_obj_get_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4026 {
4027 	raid_obj_t *obj;
4028 
4029 	obj = raid_obj_tab_find(raid_tab, obj_id);
4030 	if (obj == NULL)
4031 		return (ERR_DEVICE_NOENT);
4032 
4033 	if ((obj->obj_type_id < OBJ_TYPE_SYSTEM) ||
4034 	    (obj->obj_type_id >= OBJ_TYPE_ALL))
4035 		return (ERR_DEVICE_INVALID);
4036 
4037 	return (obj->obj_type_id);
4038 }
4039 
4040 static int
4041 raid_obj_set_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4042 	raid_obj_type_id_t type)
4043 {
4044 	raid_obj_t *obj;
4045 
4046 	obj = raid_obj_tab_find(raid_tab, obj_id);
4047 	if (obj == NULL)
4048 		return (ERR_DEVICE_NOENT);
4049 
4050 	if ((type < OBJ_TYPE_SYSTEM) || (type >= OBJ_TYPE_ALL))
4051 		return (ERR_DEVICE_TYPE);
4052 
4053 	obj->obj_type_id = type;
4054 	return (SUCCESS);
4055 }
4056 
4057 static raid_obj_status_t
4058 raid_obj_get_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4059 {
4060 	raid_obj_t *obj;
4061 
4062 	obj = raid_obj_tab_find(raid_tab, obj_id);
4063 	if (obj == NULL)
4064 		return (ERR_DEVICE_NOENT);
4065 
4066 	return (obj->status);
4067 }
4068 
4069 static int
4070 raid_obj_set_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4071 	raid_obj_status_t status)
4072 {
4073 	raid_obj_t *obj;
4074 
4075 	obj = raid_obj_tab_find(raid_tab, obj_id);
4076 	if (obj == NULL)
4077 		return (ERR_DEVICE_NOENT);
4078 
4079 	obj->status = obj->status | status;
4080 
4081 	return (SUCCESS);
4082 }
4083 
4084 static int
4085 raid_obj_clear_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 raid_obj_id_t
4100 raid_obj_get_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4101 {
4102 	raid_obj_t *obj;
4103 
4104 	obj = raid_obj_tab_find(raid_tab, obj_id);
4105 	if (obj == NULL)
4106 		return (ERR_DEVICE_NOENT);
4107 
4108 	return (obj->container);
4109 }
4110 
4111 static int
4112 raid_obj_set_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4113 	raid_obj_id_t container_id)
4114 {
4115 	raid_obj_t *obj;
4116 
4117 	obj = raid_obj_tab_find(raid_tab, obj_id);
4118 	if (obj == NULL)
4119 		return (ERR_DEVICE_NOENT);
4120 
4121 	obj->container = container_id;
4122 	return (SUCCESS);
4123 }
4124 
4125 static raid_obj_id_t
4126 raid_obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4127 {
4128 	raid_obj_t *obj;
4129 
4130 	obj = raid_obj_tab_find(raid_tab, obj_id);
4131 	if (obj == NULL)
4132 		return (ERR_DEVICE_NOENT);
4133 
4134 	return (obj->component);
4135 }
4136 
4137 static int
4138 raid_obj_set_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4139 	raid_obj_id_t comp)
4140 {
4141 	raid_obj_t *obj;
4142 
4143 	obj = raid_obj_tab_find(raid_tab, obj_id);
4144 	if (obj == NULL)
4145 		return (ERR_DEVICE_NOENT);
4146 
4147 	obj->component = comp;
4148 	return (SUCCESS);
4149 }
4150 
4151 static raid_obj_id_t
4152 raid_obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4153 {
4154 	raid_obj_t *obj;
4155 
4156 	obj = raid_obj_tab_find(raid_tab, obj_id);
4157 	if (obj == NULL)
4158 		return (ERR_DEVICE_NOENT);
4159 
4160 	return (obj->sibling);
4161 }
4162 
4163 static int
4164 raid_obj_set_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4165 	raid_obj_id_t sibling)
4166 {
4167 	raid_obj_t *obj;
4168 
4169 	obj = raid_obj_tab_find(raid_tab, obj_id);
4170 	if (obj == NULL)
4171 		return (ERR_DEVICE_NOENT);
4172 
4173 	obj->sibling = sibling;
4174 
4175 	return (SUCCESS);
4176 }
4177 
4178 static void *
4179 raid_obj_get_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4180 {
4181 	raid_obj_t *obj;
4182 
4183 	obj = raid_obj_tab_find(raid_tab, obj_id);
4184 	if (obj == NULL)
4185 		return (NULL);
4186 
4187 	return (obj->data);
4188 }
4189 
4190 static int
4191 raid_obj_set_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4192 	void *data)
4193 {
4194 	raid_obj_t *obj;
4195 
4196 	obj = raid_obj_tab_find(raid_tab, obj_id);
4197 	if (obj == NULL)
4198 		return (ERR_DEVICE_NOENT);
4199 
4200 	obj->data = data;
4201 
4202 	return (SUCCESS);
4203 }
4204 
4205 static raid_obj_handle_t
4206 raid_obj_get_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4207 {
4208 	raid_obj_t *obj;
4209 
4210 	obj = raid_obj_tab_find(raid_tab, obj_id);
4211 	if (obj == NULL)
4212 		return (ERR_DEVICE_NOENT);
4213 
4214 	return (obj->handle);
4215 }
4216 
4217 static int
4218 raid_obj_set_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4219 	raid_obj_handle_t handle)
4220 {
4221 	raid_obj_t *obj;
4222 
4223 	obj = raid_obj_tab_find(raid_tab, obj_id);
4224 	if (obj == NULL)
4225 		return (ERR_DEVICE_NOENT);
4226 
4227 	obj->handle = handle;
4228 	return (SUCCESS);
4229 }
4230 /*
4231  * Object list maintennance routines
4232  */
4233 static void
4234 raid_list_create(raid_list_t *list, size_t offset)
4235 {
4236 	list->head = NULL;
4237 	list->tail = NULL;
4238 	list->offset = offset;
4239 }
4240 
4241 static void *
4242 raid_list_head(raid_list_t *list)
4243 {
4244 	return (list->head);
4245 }
4246 
4247 static void *
4248 raid_list_next(raid_list_t *list, void *obj)
4249 {
4250 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj);
4251 
4252 	return (el->next);
4253 }
4254 
4255 static void
4256 raid_list_insert_tail(raid_list_t *list, void *obj)
4257 {
4258 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4259 
4260 	el->prev = list->tail;
4261 	list->tail = obj;
4262 
4263 	el->next = NULL;
4264 
4265 	if (list->head == NULL)
4266 		list->head = obj;
4267 
4268 	if (el->prev != NULL) {
4269 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4270 		el1->next = obj;
4271 	}
4272 }
4273 
4274 static void
4275 raid_list_remove(raid_list_t *list, void *obj)
4276 {
4277 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4278 
4279 	if (list->head == obj)
4280 		list->head = el->next;
4281 
4282 	if (list->tail == obj)
4283 		list->tail = el->prev;
4284 
4285 	if (el->next != NULL) {
4286 		el1 = LIST_OBJ_TO_EL(list, el->next);
4287 		el1->prev = el->prev;
4288 	}
4289 
4290 	if (el->prev != NULL) {
4291 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4292 		el1->next = el->next;
4293 	}
4294 
4295 	el->prev = el->next = NULL;
4296 }
4297 
4298 static void *
4299 raid_list_remove_head(raid_list_t *list)
4300 {
4301 	void *obj = list->head;
4302 
4303 	if (obj != NULL)
4304 		raid_list_remove(list, obj);
4305 
4306 	return (obj);
4307 }
4308 
4309 static void *
4310 raid_list_find(raid_list_t *list, raid_obj_id_t obj_id)
4311 {
4312 	raid_obj_t *obj;
4313 
4314 	for (obj = raid_list_head(list); obj != NULL;
4315 	    obj = raid_list_next(list, obj))
4316 			if (obj->obj_id == obj_id)
4317 				break;
4318 
4319 	return (obj);
4320 }
4321 
4322 static int
4323 raid_obj_tab_create(raid_obj_tab_t *tab, size_t hash_slots)
4324 {
4325 	unsigned i;
4326 
4327 	if (hash_slots == 0)
4328 		return (ERR_OP_ILLEGAL);
4329 
4330 	tab->slots = hash_slots;
4331 
4332 	if ((tab->table = calloc(hash_slots, sizeof (raid_list_t))) == NULL)
4333 		return (ERR_NOMEM);
4334 
4335 	for (i = 0; i < hash_slots; i++)
4336 		raid_list_create(&tab->table[i], offsetof(raid_obj_t, el));
4337 
4338 	return (SUCCESS);
4339 }
4340 
4341 static void
4342 raid_obj_tab_destroy(raid_obj_tab_t *tab)
4343 {
4344 	unsigned i;
4345 
4346 	for (i = 0; i < tab->slots; i++) {
4347 		struct raid_obj_t *obj;
4348 
4349 		while ((obj = raid_list_remove_head(&tab->table[i])) != NULL)
4350 			free(obj);
4351 
4352 		raid_list_destroy(&tab->table[i]);
4353 	}
4354 
4355 	if (tab->table)
4356 		free(tab->table);
4357 
4358 	tab->table = NULL;
4359 	tab->slots = 0;
4360 	tab->obj_id_cnt = 0;
4361 }
4362 
4363 static int
4364 raid_obj_tab_insert(raid_obj_tab_t *tab, raid_obj_id_t id, void *obj)
4365 {
4366 	raid_list_t *list;
4367 
4368 	list = OBJ_TAB_SLOT(tab, id);
4369 
4370 	if (raid_list_find(list, id) != NULL)
4371 		return (ERR_DEVICE_DUP);
4372 
4373 	raid_list_insert_tail(list, obj);
4374 
4375 	return (SUCCESS);
4376 }
4377 
4378 static void *
4379 raid_obj_tab_remove(raid_obj_tab_t *tab, raid_obj_id_t id)
4380 {
4381 	raid_list_t *list;
4382 	raid_obj_t *obj;
4383 
4384 	list = OBJ_TAB_SLOT(tab, id);
4385 
4386 	if ((obj = raid_list_find(list, id)) != NULL)
4387 		raid_list_remove(list, obj);
4388 
4389 	return (obj);
4390 }
4391 
4392 static void *
4393 raid_obj_tab_find(raid_obj_tab_t *tab, raid_obj_id_t id)
4394 {
4395 	raid_list_t *list;
4396 	raid_obj_t *obj;
4397 
4398 	list = OBJ_TAB_SLOT(tab, id);
4399 	obj = raid_list_find(list, id);
4400 
4401 	return (obj);
4402 }
4403 
4404 static void
4405 raid_list_destroy(raid_list_t *list)
4406 {
4407 	list->head = NULL;
4408 	list->tail = NULL;
4409 	list->offset = 0;
4410 }
4411 
4412 /*
4413  * Plug-in maintennance routines
4414  */
4415 static int
4416 controller_id_to_path(uint32_t controller_id, char *path)
4417 {
4418 	int fd;
4419 	char buf[MAX_PATH_LEN] = {0}, buf1[MAX_PATH_LEN] = {0}, *colon;
4420 
4421 	(void) snprintf(buf, MAX_PATH_LEN, "%s/c%d", CFGDIR, controller_id);
4422 	if (readlink(buf, buf1, sizeof (buf1)) < 0)
4423 		return (ERR_DRIVER_NOT_FOUND);
4424 
4425 	if (buf1[0] != '/')
4426 		(void) snprintf(buf, sizeof (buf), "%s/", CFGDIR);
4427 	else
4428 		buf[0] = 0;
4429 	(void) strlcat(buf, buf1, MAX_PATH_LEN);
4430 
4431 	colon = strrchr(buf, ':');
4432 	if (colon == NULL)
4433 		return (ERR_DRIVER_NOT_FOUND);
4434 	else
4435 		*colon = 0;
4436 
4437 	(void) snprintf(path, MAX_PATH_LEN, "%s:devctl", buf);
4438 
4439 	fd = open(path, O_RDONLY | O_NDELAY);
4440 
4441 	if (fd < 0)
4442 		return (ERR_DRIVER_NOT_FOUND);
4443 
4444 	(void) close(fd);
4445 
4446 	return (SUCCESS);
4447 }
4448 
4449 static char *
4450 controller_id_to_driver_name(uint32_t controller_id)
4451 {
4452 	char buf[MAX_PATH_LEN];
4453 	di_node_t di_node;
4454 	char *name, *tmp;
4455 	int ret;
4456 
4457 	ret = controller_id_to_path(controller_id, buf);
4458 	if (ret < SUCCESS)
4459 		return (NULL);
4460 
4461 	tmp = strrchr(buf, ':');
4462 	if (tmp != NULL)
4463 		*tmp = 0;
4464 
4465 	tmp = strstr(buf, "pci");
4466 	if (tmp == NULL)
4467 		return (NULL);
4468 
4469 	di_node = di_init(tmp, DINFOPROP);
4470 	if (di_node == DI_NODE_NIL)
4471 		return (NULL);
4472 
4473 	name = di_driver_name(di_node);
4474 
4475 	return (name);
4476 }
4477 
4478 static void
4479 raid_plugin_init()
4480 {
4481 	raid_lib_t *raid_lib = raid_lib_sys;
4482 
4483 	while (raid_lib) {
4484 		raid_lib_sys = raid_lib->next;
4485 		(void) dlclose(raid_lib->lib_handle);
4486 		free(raid_lib);
4487 		raid_lib = raid_lib_sys;
4488 	}
4489 }
4490 
4491 static raid_lib_t *
4492 raid_plugin_load(char *driver_name)
4493 {
4494 	char buf[MAX_PATH_LEN] = {0};
4495 	raid_lib_t *supplib;
4496 	void *sym;
4497 
4498 	supplib = calloc(1, sizeof (raid_lib_t));
4499 	if (supplib == NULL)
4500 		return (NULL);
4501 
4502 	(void) snprintf(buf, MAX_PATH_LEN, "%s/%s.so.1",
4503 	    SUPP_PLUGIN_DIR, driver_name);
4504 
4505 	supplib->lib_handle = dlopen(buf, RTLD_LAZY);
4506 	if (supplib->lib_handle == NULL) {
4507 		free(supplib);
4508 		return (NULL);
4509 	}
4510 
4511 	supplib->name = driver_name;
4512 
4513 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_version")) == NULL)
4514 		supplib->version = RDCFG_PLUGIN_V1;
4515 	else {
4516 		supplib->version = *((uint32_t *)sym);
4517 		if (supplib->version != RDCFG_PLUGIN_V1) {
4518 			(void) dlclose(supplib->lib_handle);
4519 			free(supplib);
4520 			return (NULL);
4521 		}
4522 	}
4523 
4524 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_open_controller")) ==
4525 	    NULL) {
4526 		(void) dlclose(supplib->lib_handle);
4527 		free(supplib);
4528 		return (NULL);
4529 	} else
4530 		supplib->open_controller = (int(*)(uint32_t, char **))sym;
4531 
4532 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_close_controller")) ==
4533 	    NULL) {
4534 		(void) dlclose(supplib->lib_handle);
4535 		free(supplib);
4536 		return (NULL);
4537 	} else
4538 		supplib->close_controller = (int (*)(uint32_t, char **))sym;
4539 
4540 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_compnum")) == NULL) {
4541 		(void) dlclose(supplib->lib_handle);
4542 		free(supplib);
4543 		return (NULL);
4544 	} else
4545 		supplib->compnum = (int (*)(uint32_t, uint32_t,
4546 		    raid_obj_type_id_t, raid_obj_type_id_t))sym;
4547 
4548 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_complist")) == NULL) {
4549 		(void) dlclose(supplib->lib_handle);
4550 		free(supplib);
4551 		return (NULL);
4552 	} else
4553 		supplib->complist = (int (*)(uint32_t, uint32_t,
4554 		    raid_obj_type_id_t, raid_obj_type_id_t, int, void *))sym;
4555 
4556 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_get_attr")) == NULL) {
4557 		(void) dlclose(supplib->lib_handle);
4558 		free(supplib);
4559 		return (NULL);
4560 	} else
4561 		supplib->get_attr = (int (*)(uint32_t, uint32_t, uint32_t,
4562 		    raid_obj_type_id_t, void*))sym;
4563 
4564 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_create")) == NULL) {
4565 		(void) dlclose(supplib->lib_handle);
4566 		free(supplib);
4567 		return (NULL);
4568 	} else
4569 		supplib->array_create = (int (*)(uint32_t, array_attr_t *, int,
4570 		    arraypart_attr_t *, char **))sym;
4571 
4572 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_delete")) == NULL) {
4573 		(void) dlclose(supplib->lib_handle);
4574 		free(supplib);
4575 		return (NULL);
4576 	} else
4577 		supplib->array_delete =
4578 		    (int (*)(uint32_t, uint32_t, char **))sym;
4579 
4580 	supplib->hsp_bind = (int (*)(uint32_t, hsp_relation_t *,
4581 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_bind");
4582 	supplib->hsp_unbind = (int (*)(uint32_t, hsp_relation_t *,
4583 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_unbind");
4584 	supplib->set_attr = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t *,
4585 	    char **))dlsym(supplib->lib_handle, "rdcfg_set_attr");
4586 	supplib->flash_fw = (int (*)(uint32_t, char *, uint32_t, char **))
4587 	    dlsym(supplib->lib_handle, "rdcfg_flash_fw");
4588 
4589 	supplib->next = raid_lib_sys;
4590 	raid_lib_sys = supplib;
4591 	return (supplib);
4592 }
4593 
4594 static raid_lib_t *
4595 raid_find_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t controller_obj_id)
4596 {
4597 	controller_attr_t *controller_attr;
4598 	raid_lib_t *raid_lib;
4599 	char *driver_name;
4600 	raid_obj_handle_t handle;
4601 
4602 	/* Check if it's mapped to handle structure */
4603 	handle = raid_obj_to_handle(raid_tab, controller_obj_id);
4604 	if (raid_handle_sys.handles[handle].raid_lib != NULL)
4605 		return (raid_handle_sys.handles[handle].raid_lib);
4606 
4607 	(void) obj_get_attr(raid_tab, controller_obj_id,
4608 	    (void **)(&controller_attr));
4609 
4610 	/* Check if the plugin module is already loaded */
4611 	driver_name = controller_id_to_driver_name(
4612 	    controller_attr->controller_id);
4613 	if (driver_name == NULL)
4614 		return (NULL);
4615 
4616 	raid_lib = raid_lib_sys;
4617 	while (raid_lib != NULL) {
4618 		if (raid_lib->name != NULL &&
4619 		    strcmp(driver_name, raid_lib->name) == 0)
4620 			return (raid_lib);
4621 
4622 		raid_lib = raid_lib->next;
4623 	}
4624 
4625 	/* Loading the plugin module */
4626 	raid_lib = raid_plugin_load(driver_name);
4627 
4628 	return (raid_lib);
4629 }
4630