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