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