1711890bcSjc /*
2711890bcSjc  * CDDL HEADER START
3711890bcSjc  *
4711890bcSjc  * The contents of this file are subject to the terms of the
5711890bcSjc  * Common Development and Distribution License (the "License").
6711890bcSjc  * You may not use this file except in compliance with the License.
7711890bcSjc  *
8711890bcSjc  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9711890bcSjc  * or http://www.opensolaris.org/os/licensing.
10711890bcSjc  * See the License for the specific language governing permissions
11711890bcSjc  * and limitations under the License.
12711890bcSjc  *
13711890bcSjc  * When distributing Covered Code, include this CDDL HEADER in each
14711890bcSjc  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15711890bcSjc  * If applicable, add the following below this CDDL HEADER, with the
16711890bcSjc  * fields enclosed by brackets "[]" replaced with your own identifying
17711890bcSjc  * information: Portions Copyright [yyyy] [name of copyright owner]
18711890bcSjc  *
19711890bcSjc  * CDDL HEADER END
20711890bcSjc  */
21711890bcSjc 
22711890bcSjc /*
23edabaf6fSMilan Jurik  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24711890bcSjc  * Use is subject to license terms.
2533f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
26711890bcSjc  */
27711890bcSjc 
28711890bcSjc #include <fcntl.h>
29711890bcSjc #include <sys/types.h>
30711890bcSjc #include <sys/stat.h>
31711890bcSjc #include <stddef.h>
32711890bcSjc #include <stdlib.h>
33711890bcSjc #include <dirent.h>
34711890bcSjc #include <dlfcn.h>
35711890bcSjc #include <link.h>
36711890bcSjc #include <strings.h>
37711890bcSjc #include <stdio.h>
38711890bcSjc #include <unistd.h>
39711890bcSjc #include <sys/mnttab.h>
40711890bcSjc #include <config_admin.h>
41711890bcSjc #include <sys/param.h>
42711890bcSjc #include <libintl.h>
43711890bcSjc #include <libdevinfo.h>
44711890bcSjc #include <raidcfg.h>
45711890bcSjc #include <thread.h>
46711890bcSjc #include <synch.h>
47711890bcSjc 
48711890bcSjc #ifndef TEXT_DOMAIN
49711890bcSjc #define	TEXT_DOMAIN	"SYS_TEST"
50711890bcSjc #endif
51711890bcSjc 
52711890bcSjc #define	HASH_SLOTS	16
53711890bcSjc #define	HANDLER_SLOTS	256
54711890bcSjc 
55711890bcSjc /*
56711890bcSjc  * Raid object status;
57711890bcSjc  */
58711890bcSjc #define	OBJ_STATUS_CMD_CLEAN	-1
59711890bcSjc #define	OBJ_STATUS_OPENED	1
60711890bcSjc #define	OBJ_STATUS_SCANCOMP	1 << 1
61711890bcSjc 
62711890bcSjc #if defined(__sparcv9)
63711890bcSjc #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg/sparcv9"
64711890bcSjc #elif defined(__amd64)
65711890bcSjc #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg/amd64"
66711890bcSjc #else
67711890bcSjc #define	SUPP_PLUGIN_DIR	"/usr/lib/raidcfg"
68711890bcSjc #endif
69711890bcSjc 
70711890bcSjc /*
71711890bcSjc  * Basic types
72711890bcSjc  */
73711890bcSjc typedef	int raid_obj_id_t;
74711890bcSjc typedef	int raid_obj_status_t;
75711890bcSjc 
76711890bcSjc /*
77711890bcSjc  * Data structures used for object maintennance
78711890bcSjc  */
79711890bcSjc typedef	struct {
80711890bcSjc 	void *head;
81711890bcSjc 	void *tail;
82711890bcSjc 	size_t offset;	/* offset of double-linked element (raid_list_el_t) */
83711890bcSjc 			/* in the linked data structures (objects) */
84711890bcSjc } raid_list_t;
85711890bcSjc 
86711890bcSjc typedef	struct {
87711890bcSjc 	void *prev;
88711890bcSjc 	void *next;
89711890bcSjc } raid_list_el_t;
90711890bcSjc 
91711890bcSjc typedef	struct {
92711890bcSjc 	raid_obj_id_t obj_id_cnt;	/* id 0 is reserved */
93711890bcSjc 	size_t slots;			/* How many lists linked by *table */
94711890bcSjc 	raid_list_t *table;
95711890bcSjc } raid_obj_tab_t;
96711890bcSjc 
97711890bcSjc /*
98711890bcSjc  * Object type structure containing function pointers;
99711890bcSjc  */
100711890bcSjc typedef	struct {
101711890bcSjc 	int (*compnum)(raid_obj_tab_t *, raid_obj_id_t, raid_obj_type_id_t);
102711890bcSjc 	int (*complist)(raid_obj_tab_t *, raid_obj_id_t, int, raid_obj_id_t *,
103711890bcSjc 		raid_obj_type_id_t);
104711890bcSjc 	int (*get_attr)(raid_obj_tab_t *, raid_obj_id_t);
105711890bcSjc 	int (*set_attr)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, uint32_t *,
106711890bcSjc 		char **);
107711890bcSjc 	int (*act)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, void *, char **);
108711890bcSjc 	int (*create_obj)(raid_obj_tab_t *, raid_obj_id_t, int,
109711890bcSjc 		raid_obj_id_t *, char **);
110711890bcSjc 	int (*delete_obj)(raid_obj_tab_t *, raid_obj_id_t, char **);
1115c9d25d2SYu-Bo Ryan Wang 	int (*bind_obj)(raid_obj_tab_t *, raid_obj_id_t *, char **);
1125c9d25d2SYu-Bo Ryan Wang 	int (*unbind_obj)(raid_obj_tab_t *, raid_obj_id_t *, char **);
113711890bcSjc } raid_obj_op_t;
114711890bcSjc 
115711890bcSjc /*
116711890bcSjc  * Common object data structure
117711890bcSjc  */
118711890bcSjc typedef	struct {
119711890bcSjc 	raid_list_el_t		el;	/* double-links */
120711890bcSjc 
121711890bcSjc 	raid_obj_type_id_t	obj_type_id;
122711890bcSjc 	raid_obj_id_t		obj_id;
123711890bcSjc 	raid_obj_status_t	status;
124711890bcSjc 
125711890bcSjc 	raid_obj_id_t		container;
126711890bcSjc 	raid_obj_id_t		sibling;
127711890bcSjc 	raid_obj_id_t		component;
128711890bcSjc 
129711890bcSjc 	void			*data;	/* Pointer to attribute structure */
130711890bcSjc 	raid_obj_handle_t	handle;
131711890bcSjc } raid_obj_t;
132711890bcSjc 
133711890bcSjc /*
134711890bcSjc  * Definition about handle
135711890bcSjc  */
136711890bcSjc typedef	struct {
137711890bcSjc 	uint32_t	next;
138711890bcSjc 	uint32_t	type;
139711890bcSjc 	uint32_t	controller_id;
140711890bcSjc 	uint32_t	array_id;
141711890bcSjc 	uint32_t	disk_id;
142711890bcSjc 	uint64_t	seq_id;
143711890bcSjc 	uint32_t	task_id;
144b449fa8aSyw 	uint32_t	prop_id;
145711890bcSjc 	uint32_t	fd;		/* Only for controller */
146711890bcSjc 	raid_lib_t	*raid_lib;	/* Only for controller */
147711890bcSjc } handle_attr_t;
148711890bcSjc 
149711890bcSjc #define	LIST_OBJ_TO_EL(list, obj)	\
150711890bcSjc 	((void *)((char *)(obj) + (list)->offset))
151711890bcSjc #define	OBJ_TAB_SLOT(tab, id)	\
152711890bcSjc 	((tab)->table + ((id)%(tab)->slots))
153711890bcSjc 
154711890bcSjc #pragma init(raidcfg_init)
155711890bcSjc #pragma fini(raidcfg_fini)
156711890bcSjc 
157711890bcSjc /*
158711890bcSjc  * Function prototypes
159711890bcSjc  */
160711890bcSjc static int intcompare(const void *p1, const void *p2);
161711890bcSjc static uint64_t raid_space_noalign(raid_obj_tab_t *, uint32_t, int,
162711890bcSjc 	raid_obj_id_t *, arraypart_attr_t *);
163711890bcSjc static int raid_handle_init();
164711890bcSjc static void raid_handle_fini();
165711890bcSjc static raid_obj_handle_t raid_handle_new(raid_obj_type_id_t);
166711890bcSjc static void raid_handle_delete(raid_obj_handle_t);
167711890bcSjc static void raid_handle_delete_controller_comp(uint32_t);
168711890bcSjc static raid_obj_id_t raid_handle_to_obj(raid_obj_tab_t *,
169711890bcSjc 	raid_obj_handle_t);
170711890bcSjc static raid_obj_handle_t raid_obj_to_handle(raid_obj_tab_t *,
171711890bcSjc 	raid_obj_id_t);
172711890bcSjc static raid_lib_t *raid_obj_get_lib(raid_obj_tab_t *, raid_obj_id_t);
173711890bcSjc static int raid_obj_set_lib(raid_obj_tab_t *, raid_obj_id_t, raid_lib_t *);
174711890bcSjc static int raid_obj_get_fd(raid_obj_tab_t *, raid_obj_id_t);
175711890bcSjc static int raid_obj_set_fd(raid_obj_tab_t *, raid_obj_id_t, int);
176711890bcSjc static int obj_scan_comp(raid_obj_tab_t *, raid_obj_id_t);
177711890bcSjc static int obj_rescan(raid_obj_tab_t *);
178711890bcSjc static raid_obj_id_t obj_get_comp(raid_obj_tab_t *, raid_obj_id_t,
179711890bcSjc 	raid_obj_type_id_t);
180711890bcSjc static raid_obj_id_t obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
181711890bcSjc static int obj_get_attr(raid_obj_tab_t *, raid_obj_id_t, void **);
182711890bcSjc static raid_obj_id_t obj_locate_controller(raid_obj_tab_t *, uint32_t);
183711890bcSjc static raid_obj_id_t obj_locate_array(raid_obj_tab_t *, uint32_t, uint32_t);
184711890bcSjc static raid_obj_id_t obj_locate_array_recur(raid_obj_tab_t *, raid_obj_id_t,
185711890bcSjc 	uint32_t);
186711890bcSjc static raid_obj_id_t obj_locate_hsp(raid_obj_tab_t *, uint32_t,
187711890bcSjc 	uint32_t, uint32_t);
188711890bcSjc static raid_obj_id_t obj_locate_disk(raid_obj_tab_t *, uint32_t, uint32_t);
189711890bcSjc static raid_obj_id_t obj_locate_arraypart(raid_obj_tab_t *, uint32_t,
190711890bcSjc 	uint32_t, uint32_t);
191711890bcSjc static raid_obj_id_t obj_locate_diskseg(raid_obj_tab_t *, uint32_t,
192711890bcSjc 	uint32_t, uint32_t);
193711890bcSjc static raid_obj_id_t obj_locate_task(raid_obj_tab_t *, uint32_t, uint32_t);
194b449fa8aSyw static raid_obj_id_t obj_locate_prop(raid_obj_tab_t *, uint32_t, uint32_t,
195b449fa8aSyw 	uint32_t);
196711890bcSjc static raid_obj_id_t obj_get_controller(raid_obj_tab_t *, raid_obj_id_t);
197711890bcSjc 
198711890bcSjc static int obj_sys_compnum(raid_obj_tab_t *, raid_obj_id_t,
199711890bcSjc 	raid_obj_type_id_t);
200711890bcSjc static int obj_sys_complist(raid_obj_tab_t *, raid_obj_id_t, int,
201711890bcSjc 	raid_obj_id_t *, raid_obj_type_id_t);
202711890bcSjc static int obj_controller_compnum(raid_obj_tab_t *, raid_obj_id_t,
203711890bcSjc 	raid_obj_type_id_t);
204711890bcSjc static int obj_controller_complist(raid_obj_tab_t *, raid_obj_id_t, int,
205711890bcSjc 	raid_obj_id_t *, raid_obj_type_id_t);
206711890bcSjc static int obj_controller_get_attr(raid_obj_tab_t *, raid_obj_id_t);
207711890bcSjc static int obj_controller_act(raid_obj_tab_t *, raid_obj_id_t,
208711890bcSjc 	uint32_t, void *, char **);
209711890bcSjc static int obj_array_compnum(raid_obj_tab_t *, raid_obj_id_t,
210711890bcSjc 	raid_obj_type_id_t);
211711890bcSjc static int obj_array_complist(raid_obj_tab_t *, raid_obj_id_t, int,
212711890bcSjc 	raid_obj_id_t *, raid_obj_type_id_t);
213711890bcSjc static int obj_array_get_attr(raid_obj_tab_t *, raid_obj_id_t);
214711890bcSjc static int obj_array_set_attr(raid_obj_tab_t *, raid_obj_id_t,
215711890bcSjc 	uint32_t, uint32_t *, char **);
216711890bcSjc static int obj_disk_compnum(raid_obj_tab_t *, raid_obj_id_t,
217711890bcSjc 	raid_obj_type_id_t);
218711890bcSjc static int obj_disk_complist(raid_obj_tab_t *, raid_obj_id_t, int,
219711890bcSjc 	raid_obj_id_t *, raid_obj_type_id_t);
220711890bcSjc static int obj_disk_get_attr(raid_obj_tab_t *, raid_obj_id_t);
221711890bcSjc static int obj_hsp_get_attr(raid_obj_tab_t *, raid_obj_id_t);
222711890bcSjc static int obj_arraypart_get_attr(raid_obj_tab_t *, raid_obj_id_t);
223711890bcSjc static int obj_diskseg_get_attr(raid_obj_tab_t *, raid_obj_id_t);
224711890bcSjc static int obj_task_get_attr(raid_obj_tab_t *, raid_obj_id_t);
225b449fa8aSyw static int obj_prop_get_attr(raid_obj_tab_t *, raid_obj_id_t);
226711890bcSjc static int obj_array_create(raid_obj_tab_t *, raid_obj_id_t, int,
227711890bcSjc 	raid_obj_id_t *, char **);
228711890bcSjc static int obj_array_delete(raid_obj_tab_t *, raid_obj_id_t, char **);
2295c9d25d2SYu-Bo Ryan Wang static int obj_hsp_bind(raid_obj_tab_t *, raid_obj_id_t *, char **);
2305c9d25d2SYu-Bo Ryan Wang static int obj_hsp_unbind(raid_obj_tab_t *, raid_obj_id_t *, char **);
231711890bcSjc 
232711890bcSjc static int raid_obj_create_system_obj(raid_obj_tab_t *);
233711890bcSjc static raid_obj_id_t raid_obj_id_new(raid_obj_tab_t *);
234711890bcSjc static void *raid_obj_attr_new(raid_obj_type_id_t);
235711890bcSjc static raid_obj_id_t raid_obj_create(raid_obj_tab_t *, raid_obj_type_id_t);
236711890bcSjc static int raid_obj_delete(raid_obj_tab_t *, raid_obj_id_t);
237711890bcSjc static int raid_obj_add_org(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
238711890bcSjc static raid_obj_type_id_t raid_obj_get_type(raid_obj_tab_t *, raid_obj_id_t);
239711890bcSjc static int raid_obj_set_type(raid_obj_tab_t *, raid_obj_id_t,
240711890bcSjc 	raid_obj_type_id_t);
241711890bcSjc static raid_obj_status_t raid_obj_get_status(raid_obj_tab_t *, raid_obj_id_t);
242711890bcSjc static int raid_obj_set_status(raid_obj_tab_t *, raid_obj_id_t,
243711890bcSjc 	raid_obj_status_t);
244711890bcSjc static int raid_obj_clear_status(raid_obj_tab_t *, raid_obj_id_t,
245711890bcSjc 	raid_obj_status_t);
246711890bcSjc static raid_obj_id_t raid_obj_get_container(raid_obj_tab_t *, raid_obj_id_t);
247711890bcSjc static int raid_obj_set_container(raid_obj_tab_t *, raid_obj_id_t,
248711890bcSjc 	raid_obj_id_t);
249711890bcSjc static raid_obj_id_t raid_obj_get_comp(raid_obj_tab_t *, raid_obj_id_t);
250711890bcSjc static int raid_obj_set_comp(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
251711890bcSjc static raid_obj_id_t raid_obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
252711890bcSjc static int raid_obj_set_sibling(raid_obj_tab_t *, raid_obj_id_t,
253711890bcSjc 	raid_obj_id_t);
254711890bcSjc static void *raid_obj_get_data_ptr(raid_obj_tab_t *, raid_obj_id_t);
255711890bcSjc static int raid_obj_set_data_ptr(raid_obj_tab_t *, raid_obj_id_t, void *);
256711890bcSjc static raid_obj_handle_t raid_obj_get_handle(raid_obj_tab_t *,
257711890bcSjc 	raid_obj_id_t);
258711890bcSjc static int raid_obj_set_handle(raid_obj_tab_t *, raid_obj_id_t,
259711890bcSjc 	raid_obj_handle_t);
260711890bcSjc 
261711890bcSjc static void raid_list_create(raid_list_t *, size_t);
262711890bcSjc static void *raid_list_head(raid_list_t *);
263711890bcSjc static void *raid_list_next(raid_list_t *, void *);
264711890bcSjc static void raid_list_insert_tail(raid_list_t *, void *);
265711890bcSjc static void raid_list_remove(raid_list_t *, void *);
266711890bcSjc static void *raid_list_remove_head(raid_list_t *);
267711890bcSjc static void *raid_list_find(raid_list_t *, raid_obj_id_t);
268711890bcSjc static int raid_obj_tab_create(raid_obj_tab_t *, size_t);
269711890bcSjc static void raid_obj_tab_destroy(raid_obj_tab_t *);
270711890bcSjc static int raid_obj_tab_insert(raid_obj_tab_t *, raid_obj_id_t, void *);
271711890bcSjc static void *raid_obj_tab_remove(raid_obj_tab_t *, raid_obj_id_t);
272711890bcSjc static void *raid_obj_tab_find(raid_obj_tab_t *, raid_obj_id_t);
273711890bcSjc static void raid_list_destroy(raid_list_t *);
274711890bcSjc 
275711890bcSjc static int controller_id_to_path(uint32_t, char *);
276711890bcSjc static char *controller_id_to_driver_name(uint32_t);
277711890bcSjc static void raid_plugin_init();
278711890bcSjc static raid_lib_t *raid_plugin_load(char *);
279711890bcSjc static raid_lib_t *raid_find_lib(raid_obj_tab_t *, raid_obj_id_t);
280711890bcSjc 
281711890bcSjc /* Global object table */
282711890bcSjc static raid_obj_tab_t raid_tab_sys = {0, 0, NULL};
283711890bcSjc 
284711890bcSjc /* Plug-in modules maintenance data structures */
285711890bcSjc static raid_lib_t *raid_lib_sys = NULL;
286711890bcSjc 
287711890bcSjc /* Handle table definition */
288711890bcSjc static struct {
289711890bcSjc 	int		handle_num;
290711890bcSjc 	int		used;
291711890bcSjc 	int		unused;
292711890bcSjc 	handle_attr_t	*handles;
293711890bcSjc } raid_handle_sys = {0, 0, 0, NULL};
294711890bcSjc 
295711890bcSjc /*
296711890bcSjc  * RAID object method table definition
297711890bcSjc  */
298711890bcSjc static raid_obj_op_t raid_obj_op_sys[OBJ_TYPE_ALL] = {
299711890bcSjc 	{obj_sys_compnum, obj_sys_complist, NULL, NULL, NULL,
300711890bcSjc 		NULL, NULL, NULL, NULL},	/* system object methods */
301711890bcSjc 	{obj_controller_compnum, obj_controller_complist,
302711890bcSjc 		obj_controller_get_attr, NULL, obj_controller_act,
303711890bcSjc 		NULL, NULL, NULL, NULL},	/* controller object methods */
304711890bcSjc 	{obj_array_compnum, obj_array_complist, obj_array_get_attr,
305711890bcSjc 		obj_array_set_attr, NULL, obj_array_create,
306711890bcSjc 		obj_array_delete, NULL, NULL},	/* array object methods */
307711890bcSjc 	{obj_disk_compnum, obj_disk_complist, obj_disk_get_attr, NULL,
308711890bcSjc 		NULL, NULL, NULL, NULL, NULL},	/* disk object methods */
309711890bcSjc 	{NULL, NULL, obj_hsp_get_attr, NULL, NULL, NULL, NULL, obj_hsp_bind,
310711890bcSjc 		obj_hsp_unbind},		/* hsp object methods */
311711890bcSjc 	{NULL, NULL, obj_arraypart_get_attr, NULL, NULL, NULL, NULL,
312711890bcSjc 		NULL, NULL},			/* array part object methods */
313711890bcSjc 	{NULL, NULL, obj_diskseg_get_attr, NULL, NULL, NULL, NULL, NULL, NULL},
314711890bcSjc 	{NULL, NULL, obj_task_get_attr, NULL, NULL, NULL, NULL,
315b449fa8aSyw 		NULL, NULL},			/* disk seg object methods */
316b449fa8aSyw 	{NULL, NULL, obj_prop_get_attr, NULL, NULL, NULL, NULL,
317b449fa8aSyw 		NULL, NULL}			/* property object methods */
318711890bcSjc };
319711890bcSjc 
320711890bcSjc /*
321711890bcSjc  * Mutex for multithread safe
322711890bcSjc  */
323711890bcSjc static mutex_t raidcfg_mp;
324711890bcSjc 
325711890bcSjc /*
326711890bcSjc  * RaidCfg library APIs
327711890bcSjc  */
328711890bcSjc const char *
raidcfg_errstr(int err_code)329711890bcSjc raidcfg_errstr(int err_code)
330711890bcSjc {
331711890bcSjc 	char *ret_val;
332711890bcSjc 
333711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
334711890bcSjc 	switch (err_code) {
335711890bcSjc 	case	SUCCESS:
336711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Operation succeeded.\n");
337711890bcSjc 		break;
338711890bcSjc 	case	STD_IOCTL:
339711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
340700682b8Syw 		    "Request standard IOCTL service.\n");
341711890bcSjc 		break;
342711890bcSjc 	case	ERR_DRIVER_NOT_FOUND:
343711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
344700682b8Syw 		    "Controller device can not be found.\n");
345711890bcSjc 		break;
346711890bcSjc 	case	ERR_DRIVER_OPEN:
347711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Can not open controller.\n");
348711890bcSjc 		break;
349711890bcSjc 	case	ERR_DRIVER_LOCK:
350711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Controller is locked.\n");
351711890bcSjc 		break;
352711890bcSjc 	case	ERR_DRIVER_CLOSED:
353711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Controller is not opened.\n");
354711890bcSjc 		break;
355711890bcSjc 	case	ERR_DRIVER_ACROSS:
356711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
357700682b8Syw 		    "Operation across multiple controllers.\n");
358711890bcSjc 		break;
359711890bcSjc 	case	ERR_ARRAY_LEVEL:
360711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
361700682b8Syw 		    "Operation not support with volume of this level.\n");
362711890bcSjc 		break;
363711890bcSjc 	case	ERR_ARRAY_SIZE:
364711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
365700682b8Syw 		    "Capacity of array out of range.\n");
366711890bcSjc 		break;
367711890bcSjc 	case	ERR_ARRAY_STRIPE_SIZE:
368711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Illegal stripe size.\n");
369711890bcSjc 		break;
370711890bcSjc 	case	ERR_ARRAY_CACHE_POLICY:
371711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
372700682b8Syw 		    "Illegal cache-write policy.\n");
373711890bcSjc 		break;
374711890bcSjc 	case	ERR_ARRAY_IN_USE:
375474adcbbSyw 		ret_val = dgettext(TEXT_DOMAIN, "Array or disk in use.\n");
376711890bcSjc 		break;
377711890bcSjc 	case	ERR_ARRAY_TASK:
378711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Array has background task.\n");
379711890bcSjc 		break;
380711890bcSjc 	case	ERR_ARRAY_CONFIG:
381711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
382700682b8Syw 		    "Configuration over device node failed.\n");
383711890bcSjc 		break;
384711890bcSjc 	case	ERR_ARRAY_DISKNUM:
385711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Incorrect number of disks.\n");
386711890bcSjc 		break;
387711890bcSjc 	case	ERR_ARRAY_LAYOUT:
388711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Illegal array layout.\n");
389711890bcSjc 		break;
390711890bcSjc 	case	ERR_ARRAY_AMOUNT:
391711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Too many arrays.\n");
392711890bcSjc 		break;
393711890bcSjc 	case	ERR_DISK_STATE:
394711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
395700682b8Syw 		    "Incorrect disk status for current operation.\n");
396711890bcSjc 		break;
397711890bcSjc 	case	ERR_DISK_SPACE:
398711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "No enough disk space.\n");
399711890bcSjc 		break;
400711890bcSjc 	case	ERR_DISK_SEG_AMOUNT:
401711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Too many disk segments.\n");
402711890bcSjc 		break;
403711890bcSjc 	case	ERR_DISK_NOT_EMPTY:
404711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Disk has occupied space.\n");
405711890bcSjc 		break;
406711890bcSjc 	case	ERR_DISK_TASK:
407711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Disk has background task.\n");
408711890bcSjc 		break;
409711890bcSjc 	case	ERR_TASK_STATE:
410711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
411700682b8Syw 		    "Incorrect task state for current operation.\n");
412711890bcSjc 		break;
413711890bcSjc 	case	ERR_OP_ILLEGAL:
414711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Illegal operation.\n");
415711890bcSjc 		break;
416711890bcSjc 	case	ERR_OP_NO_IMPL:
417711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
418700682b8Syw 		    "Operation is not implemented.\n");
419711890bcSjc 		break;
420711890bcSjc 	case	ERR_OP_FAILED:
421474adcbbSyw 		ret_val = dgettext(TEXT_DOMAIN, "Operation failed.\n");
422711890bcSjc 		break;
423711890bcSjc 	case	ERR_DEVICE_NOENT:
424711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Device not found.\n");
425711890bcSjc 		break;
426711890bcSjc 	case	ERR_DEVICE_TYPE:
427711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Illegal type of device.\n");
428711890bcSjc 		break;
429711890bcSjc 	case	ERR_DEVICE_DUP:
430711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Device record duplicated.\n");
431711890bcSjc 		break;
432711890bcSjc 	case	ERR_DEVICE_OVERFLOW:
433711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Too many devices.\n");
434711890bcSjc 		break;
435711890bcSjc 	case	ERR_DEVICE_UNCLEAN:
436711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Device pool is not clean.\n");
437711890bcSjc 		break;
438711890bcSjc 	case	ERR_DEVICE_INVALID:
439711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Device record is invalid.\n");
440711890bcSjc 		break;
441711890bcSjc 	case	ERR_NOMEM:
442711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN,
443700682b8Syw 		    "Can not allocate more memory space.\n");
444711890bcSjc 		break;
445711890bcSjc 	case	ERR_PRIV:
446711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "No privilege.\n");
447711890bcSjc 		break;
448711890bcSjc 	default:
449711890bcSjc 		ret_val = dgettext(TEXT_DOMAIN, "Undefined error.\n");
450711890bcSjc 	}
451711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
452711890bcSjc 
453711890bcSjc 	return (ret_val);
454711890bcSjc }
455711890bcSjc 
456711890bcSjc int
raidcfg_get_controller(uint32_t controller_id)457711890bcSjc raidcfg_get_controller(uint32_t controller_id)
458711890bcSjc {
459711890bcSjc 	raid_obj_id_t obj_id;
460711890bcSjc 	int ret_val;
461711890bcSjc 
462711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
463711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
464711890bcSjc 	obj_id = obj_locate_controller(&raid_tab_sys, controller_id);
465711890bcSjc 	if (obj_id < OBJ_NONE) {
466711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
467711890bcSjc 		return (obj_id);
468711890bcSjc 	}
469711890bcSjc 
470711890bcSjc 	if (obj_id == OBJ_NONE) {
471711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
472711890bcSjc 		return (ERR_DEVICE_NOENT);
473711890bcSjc 	}
474711890bcSjc 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
475711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
476711890bcSjc 
477711890bcSjc 	return (ret_val);
478711890bcSjc }
479711890bcSjc 
480711890bcSjc int
raidcfg_get_array(int controller_handle,uint64_t target_id,uint64_t lun)481711890bcSjc raidcfg_get_array(int controller_handle, uint64_t target_id, uint64_t lun)
482711890bcSjc {
483711890bcSjc 	raid_obj_id_t obj_id;
484711890bcSjc 	raidcfg_array_t *attr;
485711890bcSjc 	int ret_val;
486711890bcSjc 
487711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
488711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
489711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
490711890bcSjc 	if (obj_id < OBJ_NONE) {
491711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
492711890bcSjc 		return (obj_id);
493711890bcSjc 	}
494711890bcSjc 
495711890bcSjc 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_ARRAY);
496711890bcSjc 
497711890bcSjc 	while (obj_id > OBJ_NONE) {
498711890bcSjc 		(void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
499711890bcSjc 		if (attr->tag.idl.target_id == target_id &&
500700682b8Syw 		    attr->tag.idl.lun == lun)
501711890bcSjc 			break;
502711890bcSjc 
503711890bcSjc 		obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
504711890bcSjc 	}
505711890bcSjc 
506711890bcSjc 	if (obj_id < OBJ_NONE) {
507711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
508711890bcSjc 		return (obj_id);
509711890bcSjc 	}
510711890bcSjc 	if (obj_id == OBJ_NONE) {
511711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
512711890bcSjc 		return (ERR_DEVICE_NOENT);
513711890bcSjc 	}
514711890bcSjc 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
515711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
516711890bcSjc 
517711890bcSjc 	return (ret_val);
518711890bcSjc }
519711890bcSjc 
520711890bcSjc int
raidcfg_get_disk(int controller_handle,disk_tag_t tag)521711890bcSjc raidcfg_get_disk(int controller_handle, disk_tag_t tag)
522711890bcSjc {
523711890bcSjc 	raid_obj_id_t obj_id;
524711890bcSjc 	raidcfg_disk_t *attr;
525711890bcSjc 	int ret_val;
526711890bcSjc 
527711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
528711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
529711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
530711890bcSjc 	if (obj_id < OBJ_NONE) {
531711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
532711890bcSjc 		return (obj_id);
533711890bcSjc 	}
534711890bcSjc 
535711890bcSjc 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_DISK);
536711890bcSjc 
537711890bcSjc 	while (obj_id > OBJ_NONE) {
538711890bcSjc 		(void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
539711890bcSjc 		if (attr->tag.cidl.bus == tag.cidl.bus &&
540711890bcSjc 		    attr->tag.cidl.target_id == tag.cidl.target_id &&
541711890bcSjc 		    attr->tag.cidl.lun == tag.cidl.lun)
542711890bcSjc 			break;
543711890bcSjc 
544711890bcSjc 		obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
545711890bcSjc 	}
546711890bcSjc 
547711890bcSjc 	if (obj_id < OBJ_NONE) {
548711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
549711890bcSjc 		return (obj_id);
550711890bcSjc 	}
551711890bcSjc 	if (obj_id == OBJ_NONE) {
552711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
553711890bcSjc 		return (ERR_DEVICE_NOENT);
554711890bcSjc 	}
555711890bcSjc 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
556711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
557711890bcSjc 
558711890bcSjc 	return (ret_val);
559711890bcSjc }
560711890bcSjc 
561711890bcSjc int
raidcfg_open_controller(int handle,char ** plugin_err_str)562711890bcSjc raidcfg_open_controller(int handle, char **plugin_err_str)
563711890bcSjc {
564711890bcSjc 	raid_obj_id_t obj_id;
565711890bcSjc 	int ret;
566711890bcSjc 
567711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
568711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
569711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
570711890bcSjc 	if (obj_id < OBJ_NONE) {
571711890bcSjc 		raid_handle_delete(handle);
572711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
573711890bcSjc 		return (ERR_DEVICE_NOENT);
574711890bcSjc 	}
575711890bcSjc 
576711890bcSjc 	ret = obj_controller_act(&raid_tab_sys, obj_id,
577700682b8Syw 	    ACT_CONTROLLER_OPEN, NULL, plugin_err_str);
578711890bcSjc 	if (ret < SUCCESS) {
579711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
580711890bcSjc 		return (ret);
581711890bcSjc 	}
582711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
583711890bcSjc 
584711890bcSjc 	return (SUCCESS);
585711890bcSjc }
586711890bcSjc 
587711890bcSjc int
raidcfg_close_controller(int handle,char ** plugin_err_str)588711890bcSjc raidcfg_close_controller(int handle, char **plugin_err_str)
589711890bcSjc {
590711890bcSjc 	raid_obj_id_t obj_id;
591711890bcSjc 	int ret;
592711890bcSjc 
593711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
594711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
595711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
596711890bcSjc 	if (obj_id < OBJ_NONE) {
597711890bcSjc 		raid_handle_delete(handle);
598711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
599711890bcSjc 		return (ERR_DEVICE_NOENT);
600711890bcSjc 	}
601711890bcSjc 
602711890bcSjc 	ret = obj_controller_act(&raid_tab_sys, obj_id,
603700682b8Syw 	    ACT_CONTROLLER_CLOSE, NULL, plugin_err_str);
604711890bcSjc 	if (ret < SUCCESS) {
605711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
606711890bcSjc 		return (ret);
607711890bcSjc 	}
608711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
609711890bcSjc 
610711890bcSjc 	return (SUCCESS);
611711890bcSjc }
612711890bcSjc 
613711890bcSjc int
raidcfg_get_type(int handle)614711890bcSjc raidcfg_get_type(int handle)
615711890bcSjc {
616711890bcSjc 	raid_obj_id_t obj_id;
617711890bcSjc 	int ret_val;
618711890bcSjc 
619711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
620711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
621711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
622711890bcSjc 	if (obj_id < OBJ_NONE) {
623711890bcSjc 		raid_handle_delete(handle);
624711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
625711890bcSjc 		return (ERR_DEVICE_NOENT);
626711890bcSjc 	}
627711890bcSjc 	ret_val = raid_obj_get_type(&raid_tab_sys, obj_id);
628711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
629711890bcSjc 
630711890bcSjc 	return (ret_val);
631711890bcSjc }
632711890bcSjc 
633711890bcSjc int
raidcfg_get_attr(int handle,void * attr)634711890bcSjc raidcfg_get_attr(int handle, void *attr)
635711890bcSjc {
636711890bcSjc 	raid_obj_id_t obj_id;
637711890bcSjc 	raid_obj_type_id_t type;
638711890bcSjc 	void *data;
639711890bcSjc 	int ret, size;
640711890bcSjc 
641711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
642711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
643711890bcSjc 	if (attr == NULL) {
644711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
645711890bcSjc 		return (ERR_DEVICE_INVALID);
646711890bcSjc 	}
647711890bcSjc 
648711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
649711890bcSjc 	if (obj_id < OBJ_NONE) {
650711890bcSjc 		raid_handle_delete(handle);
651711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
652711890bcSjc 		return (ERR_DEVICE_NOENT);
653711890bcSjc 	}
654711890bcSjc 
655711890bcSjc 	type = raid_obj_get_type(&raid_tab_sys, obj_id);
656711890bcSjc 	ret = obj_get_attr(&raid_tab_sys, obj_id, &data);
657711890bcSjc 	if (ret < SUCCESS) {
658711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
659711890bcSjc 		return (ret);
660711890bcSjc 	}
661711890bcSjc 
662711890bcSjc 	switch (type) {
663711890bcSjc 	case	OBJ_TYPE_CONTROLLER:
664711890bcSjc 		size = sizeof (controller_attr_t);
665711890bcSjc 		break;
666711890bcSjc 	case	OBJ_TYPE_ARRAY:
667711890bcSjc 		size = sizeof (array_attr_t);
668711890bcSjc 		break;
669711890bcSjc 	case	OBJ_TYPE_HSP:
670711890bcSjc 		{
671711890bcSjc 			raidcfg_hsp_t *dst = attr;
672711890bcSjc 			hsp_attr_t *src = data;
673711890bcSjc 			controller_attr_t *ctlr_attr;
674711890bcSjc 			array_attr_t *array_attr;
675711890bcSjc 
676711890bcSjc 			dst->associated_id = src->associated_id;
677711890bcSjc 			dst->type = src->type;
678711890bcSjc 
679711890bcSjc 			obj_id = obj_get_controller(&raid_tab_sys, obj_id);
680711890bcSjc 			ret = obj_get_attr(&raid_tab_sys, obj_id,
681700682b8Syw 			    (void **)(&ctlr_attr));
682711890bcSjc 			if (ret < SUCCESS) {
683711890bcSjc 				(void) mutex_unlock(&raidcfg_mp);
684711890bcSjc 				return (ret);
685711890bcSjc 			}
686711890bcSjc 
687711890bcSjc 			if (src->type == HSP_TYPE_LOCAL) {
688711890bcSjc 				obj_id = obj_locate_array(&raid_tab_sys,
689700682b8Syw 				    ctlr_attr->controller_id,
690700682b8Syw 				    src->associated_id);
691711890bcSjc 				ret = obj_get_attr(&raid_tab_sys, obj_id,
692700682b8Syw 				    (void **)(&array_attr));
693711890bcSjc 				if (ret < SUCCESS) {
694711890bcSjc 					(void) mutex_unlock(&raidcfg_mp);
695711890bcSjc 					return (ret);
696711890bcSjc 				}
697711890bcSjc 
698711890bcSjc 				dst->tag.idl.target_id =
699700682b8Syw 				    array_attr->tag.idl.target_id;
700711890bcSjc 				dst->tag.idl.lun = array_attr->tag.idl.lun;
701711890bcSjc 			}
702711890bcSjc 		}
703711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
704711890bcSjc 		return (SUCCESS);
705711890bcSjc 	case	OBJ_TYPE_DISK:
706711890bcSjc 		size = sizeof (disk_attr_t);
707711890bcSjc 		break;
708711890bcSjc 	case	OBJ_TYPE_ARRAY_PART:
709711890bcSjc 		{
710711890bcSjc 			raidcfg_arraypart_t *dst = attr;
711711890bcSjc 			arraypart_attr_t *src = data;
712711890bcSjc 			controller_attr_t *ctlr_attr;
713711890bcSjc 			disk_attr_t *disk_attr;
714711890bcSjc 
715711890bcSjc 			dst->disk_id = src->disk_id;
716711890bcSjc 			dst->offset = src->offset;
717711890bcSjc 			dst->size = src->size;
718711890bcSjc 			dst->state = src->state;
719711890bcSjc 
720711890bcSjc 			obj_id = obj_get_controller(&raid_tab_sys, obj_id);
721711890bcSjc 			ret = obj_get_attr(&raid_tab_sys, obj_id,
722700682b8Syw 			    (void **)(&ctlr_attr));
723711890bcSjc 			if (ret < SUCCESS) {
724711890bcSjc 				(void) mutex_unlock(&raidcfg_mp);
725711890bcSjc 				return (ret);
726711890bcSjc 			}
727711890bcSjc 
728711890bcSjc 			obj_id = obj_locate_disk(&raid_tab_sys,
729700682b8Syw 			    ctlr_attr->controller_id, src->disk_id);
730711890bcSjc 			if (obj_id <= OBJ_NONE) {
731711890bcSjc 				dst->tag.cidl.bus = (uint64_t)OBJ_ATTR_NONE;
732711890bcSjc 				dst->tag.cidl.target_id =
733711890bcSjc 				    (uint64_t)OBJ_ATTR_NONE;
734711890bcSjc 				dst->tag.cidl.lun = (uint64_t)OBJ_ATTR_NONE;
735711890bcSjc 				(void) mutex_unlock(&raidcfg_mp);
736711890bcSjc 				return (SUCCESS);
737711890bcSjc 			}
738711890bcSjc 
739711890bcSjc 			ret = obj_get_attr(&raid_tab_sys, obj_id,
740700682b8Syw 			    (void **)(&disk_attr));
741711890bcSjc 			if (ret < SUCCESS) {
742711890bcSjc 				(void) mutex_unlock(&raidcfg_mp);
743711890bcSjc 				return (ret);
744711890bcSjc 			}
745711890bcSjc 
746711890bcSjc 			dst->tag.cidl.bus = disk_attr->tag.cidl.bus;
747711890bcSjc 			dst->tag.cidl.target_id = disk_attr->tag.cidl.target_id;
748711890bcSjc 			dst->tag.cidl.lun = disk_attr->tag.cidl.lun;
749711890bcSjc 		}
750711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
751711890bcSjc 		return (SUCCESS);
752711890bcSjc 	case	OBJ_TYPE_DISK_SEG:
753711890bcSjc 		size = sizeof (diskseg_attr_t);
754711890bcSjc 		break;
755711890bcSjc 	case	OBJ_TYPE_TASK:
756711890bcSjc 		size = sizeof (task_attr_t);
757711890bcSjc 		break;
758b449fa8aSyw 	case	OBJ_TYPE_PROP:
759b449fa8aSyw 		{
760b449fa8aSyw 			property_attr_t *src = data, *dst = attr;
761b449fa8aSyw 
762b449fa8aSyw 			dst->prop_id = src->prop_id;
763b449fa8aSyw 			dst->prop_type = src->prop_type;
764b449fa8aSyw 			if (dst->prop_size == 0) {
765b449fa8aSyw 				dst->prop_size = src->prop_size;
766b449fa8aSyw 				(void) mutex_unlock(&raidcfg_mp);
767b449fa8aSyw 				return (SUCCESS);
768b449fa8aSyw 			}
769b449fa8aSyw 
770b449fa8aSyw 			if (dst->prop_size < src->prop_size)
771b449fa8aSyw 				size = dst->prop_size;
772b449fa8aSyw 			else
773b449fa8aSyw 				size = src->prop_size;
774b449fa8aSyw 
775b449fa8aSyw 			(void) memcpy(dst->prop, src->prop, size);
776b449fa8aSyw 			(void) mutex_unlock(&raidcfg_mp);
777b449fa8aSyw 			return (SUCCESS);
778b449fa8aSyw 		}
779711890bcSjc 	default:
780711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
781711890bcSjc 		return (ERR_DEVICE_TYPE);
782711890bcSjc 	}
783711890bcSjc 
784711890bcSjc 	(void) memcpy(attr, data, size);
785711890bcSjc 
786711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
787711890bcSjc 	return (ret);
788711890bcSjc }
789711890bcSjc 
790711890bcSjc int
raidcfg_get_container(int handle)791711890bcSjc raidcfg_get_container(int handle)
792711890bcSjc {
793711890bcSjc 	raid_obj_id_t obj_id;
794711890bcSjc 	int ret_val;
795711890bcSjc 
796711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
797711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
798711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
799711890bcSjc 	if (obj_id < OBJ_NONE) {
800711890bcSjc 		raid_handle_delete(handle);
801711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
802711890bcSjc 		return (ERR_DEVICE_NOENT);
803711890bcSjc 	}
804711890bcSjc 
805711890bcSjc 	obj_id = raid_obj_get_container(&raid_tab_sys, obj_id);
806711890bcSjc 	if (obj_id < OBJ_NONE) {
807711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
808711890bcSjc 		return (obj_id);
809711890bcSjc 	}
810711890bcSjc 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
811711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
812711890bcSjc 
813711890bcSjc 	return (ret_val);
814711890bcSjc }
815711890bcSjc 
816711890bcSjc int
raidcfg_list_head(int handle,raid_obj_type_id_t type)817711890bcSjc raidcfg_list_head(int handle, raid_obj_type_id_t type)
818711890bcSjc {
819711890bcSjc 	raid_obj_id_t obj_id;
820711890bcSjc 	int ret_val;
821711890bcSjc 
822711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
823711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
824711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
825711890bcSjc 	if (obj_id < OBJ_NONE) {
826711890bcSjc 		raid_handle_delete(handle);
827711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
828711890bcSjc 		return (ERR_DEVICE_NOENT);
829711890bcSjc 	}
830711890bcSjc 
831711890bcSjc 	obj_id = obj_get_comp(&raid_tab_sys, obj_id, type);
832711890bcSjc 	if (obj_id < OBJ_NONE) {
833711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
834711890bcSjc 		return (obj_id);
835711890bcSjc 	}
836711890bcSjc 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
837711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
838711890bcSjc 
839711890bcSjc 	return (ret_val);
840711890bcSjc }
841711890bcSjc 
842711890bcSjc int
raidcfg_list_next(int handle)843711890bcSjc raidcfg_list_next(int handle)
844711890bcSjc {
845711890bcSjc 	raid_obj_id_t obj_id;
846711890bcSjc 	int ret_val;
847711890bcSjc 
848711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
849711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
850711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
851711890bcSjc 	if (obj_id < OBJ_NONE) {
852711890bcSjc 		raid_handle_delete(handle);
853711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
854711890bcSjc 		return (ERR_DEVICE_NOENT);
855711890bcSjc 	}
856711890bcSjc 
857711890bcSjc 	obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
858711890bcSjc 	if (obj_id < OBJ_NONE) {
859711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
860711890bcSjc 		return (obj_id);
861711890bcSjc 	}
862711890bcSjc 	ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
863711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
864711890bcSjc 
865711890bcSjc 	return (ret_val);
866711890bcSjc }
867711890bcSjc 
868711890bcSjc int
raidcfg_set_attr(int handle,uint32_t set_cmd,void * value,char ** plugin_err_str)869711890bcSjc raidcfg_set_attr(int handle, uint32_t set_cmd, void *value,
870*8bc1b774SToomas Soome     char **plugin_err_str)
871711890bcSjc {
872711890bcSjc 	raid_obj_id_t obj_id;
873711890bcSjc 	raid_obj_type_id_t type;
874711890bcSjc 	int ret;
875711890bcSjc 
876711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
877711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
878711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
879711890bcSjc 	if (obj_id < OBJ_NONE) {
880711890bcSjc 		raid_handle_delete(handle);
881711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
882711890bcSjc 		return (ERR_DEVICE_NOENT);
883711890bcSjc 	}
884711890bcSjc 
885711890bcSjc 	type = raid_obj_get_type(&raid_tab_sys, obj_id);
886711890bcSjc 	if (raid_obj_op_sys[type].set_attr == NULL) {
887711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
888711890bcSjc 		return (ERR_OP_NO_IMPL);
889711890bcSjc 	}
890711890bcSjc 
891711890bcSjc 	ret = raid_obj_op_sys[type].set_attr(&raid_tab_sys,
892700682b8Syw 	    obj_id, set_cmd, value, plugin_err_str);
893711890bcSjc 
894711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
895711890bcSjc 	return (ret);
896711890bcSjc }
897711890bcSjc 
898711890bcSjc int
raidcfg_update_fw(int handle,char * file,char ** plugin_err_str)899711890bcSjc raidcfg_update_fw(int handle, char *file, char **plugin_err_str)
900711890bcSjc {
901711890bcSjc 	raid_obj_id_t obj_id;
902711890bcSjc 	int ret;
903711890bcSjc 
904711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
905711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
906711890bcSjc 	obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
907711890bcSjc 	if (obj_id < OBJ_NONE) {
908711890bcSjc 		raid_handle_delete(handle);
909711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
910711890bcSjc 		return (ERR_DEVICE_NOENT);
911711890bcSjc 	}
912711890bcSjc 
913711890bcSjc 	if (raid_obj_get_type(&raid_tab_sys, obj_id) != OBJ_TYPE_CONTROLLER) {
914711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
915711890bcSjc 		return (ERR_OP_NO_IMPL);
916711890bcSjc 	}
917711890bcSjc 
918711890bcSjc 	ret = raid_obj_op_sys[OBJ_TYPE_CONTROLLER].act(&raid_tab_sys,
919700682b8Syw 	    obj_id, ACT_CONTROLLER_FLASH_FW, file, plugin_err_str);
920711890bcSjc 
921711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
922711890bcSjc 	return (ret);
923711890bcSjc }
924711890bcSjc 
925711890bcSjc int
raidcfg_create_array(int num_of_comps,int * disk_handles,uint32_t raid_level,uint64_t size,uint32_t stripe_size,char ** plugin_err_str)926711890bcSjc raidcfg_create_array(int num_of_comps, int *disk_handles,
927*8bc1b774SToomas Soome     uint32_t raid_level, uint64_t size, uint32_t stripe_size,
928*8bc1b774SToomas Soome     char **plugin_err_str)
929711890bcSjc {
930711890bcSjc 	raid_obj_id_t *disk_obj_ids, obj_id;
931711890bcSjc 	array_attr_t *array_attr;
932711890bcSjc 	raid_obj_handle_t array_handle;
933711890bcSjc 	int i, ret;
934711890bcSjc 
935711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
936711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
937711890bcSjc 
938711890bcSjc 	disk_obj_ids = calloc(num_of_comps, sizeof (raid_obj_id_t));
939711890bcSjc 	if (disk_obj_ids == NULL) {
940711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
941711890bcSjc 		return (ERR_NOMEM);
942711890bcSjc 	}
943711890bcSjc 
944711890bcSjc 	/* convert disk handles into disk object ids; */
945711890bcSjc 	for (i = 0; i < num_of_comps; ++i) {
946711890bcSjc 		if (*(disk_handles + i) == OBJ_SEPARATOR_BEGIN ||
947700682b8Syw 		    *(disk_handles + i) == OBJ_SEPARATOR_END) {
948711890bcSjc 			*(disk_obj_ids + i) = *(disk_handles + i);
949711890bcSjc 			continue;
950711890bcSjc 		}
951711890bcSjc 
952711890bcSjc 		*(disk_obj_ids + i) = raid_handle_to_obj(&raid_tab_sys,
953700682b8Syw 		    *(disk_handles + i));
954711890bcSjc 		if (raid_obj_get_type(&raid_tab_sys, *(disk_obj_ids + i)) !=
955700682b8Syw 		    OBJ_TYPE_DISK) {
956711890bcSjc 			free(disk_obj_ids);
957711890bcSjc 			(void) obj_rescan(&raid_tab_sys);
958711890bcSjc 			(void) mutex_unlock(&raidcfg_mp);
959711890bcSjc 			return (ERR_DEVICE_TYPE);
960711890bcSjc 		}
961711890bcSjc 	}
962711890bcSjc 
963711890bcSjc 	/* Create an empty array object */
964711890bcSjc 	obj_id = raid_obj_create(&raid_tab_sys, OBJ_TYPE_ARRAY);
965711890bcSjc 	if (obj_id < OBJ_NONE) {
966711890bcSjc 		free(disk_obj_ids);
967711890bcSjc 		(void) obj_rescan(&raid_tab_sys);
968711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
969711890bcSjc 		return (obj_id);
970711890bcSjc 	}
971711890bcSjc 	(void) raid_obj_clear_status(&raid_tab_sys, obj_id,
972700682b8Syw 	    OBJ_STATUS_CMD_CLEAN);
973711890bcSjc 
974711890bcSjc 	array_attr = raid_obj_get_data_ptr(&raid_tab_sys, obj_id);
975711890bcSjc 	array_attr->array_id = (uint32_t)OBJ_ATTR_NONE;
976711890bcSjc 	array_attr->raid_level = raid_level;
977711890bcSjc 	array_attr->capacity = size;
978711890bcSjc 	array_attr->stripe_size = stripe_size;
979711890bcSjc 	array_attr->write_policy = CACHE_WR_ON;
980711890bcSjc 	array_attr->read_policy = CACHE_RD_ON;
981711890bcSjc 
982711890bcSjc 	ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].create_obj(&raid_tab_sys, obj_id,
983700682b8Syw 	    num_of_comps, disk_obj_ids, plugin_err_str);
984711890bcSjc 	free(disk_obj_ids);
985711890bcSjc 
986711890bcSjc 	if (ret < SUCCESS) {
987711890bcSjc 		(void) obj_rescan(&raid_tab_sys);
988711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
989711890bcSjc 		return (ret);
990711890bcSjc 	}
991711890bcSjc 
992711890bcSjc 	/* create_obj() method should put the array object in the device tree */
993711890bcSjc 	array_handle = raid_obj_to_handle(&raid_tab_sys, obj_id);
994711890bcSjc 
995711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
996711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
997711890bcSjc 	return (array_handle);
998711890bcSjc }
999711890bcSjc 
1000711890bcSjc int
raidcfg_delete_array(int array_handle,char ** plugin_err_str)1001711890bcSjc raidcfg_delete_array(int array_handle, char **plugin_err_str)
1002711890bcSjc {
1003711890bcSjc 	raid_obj_id_t array_obj_id;
1004711890bcSjc 	int ret;
1005711890bcSjc 
1006711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
1007711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
1008711890bcSjc 
1009711890bcSjc 	if (raidcfg_get_type(array_handle) != OBJ_TYPE_ARRAY) {
1010711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
1011711890bcSjc 		return (ERR_DEVICE_TYPE);
1012711890bcSjc 	}
1013711890bcSjc 
1014711890bcSjc 	array_obj_id = raid_handle_to_obj(&raid_tab_sys, array_handle);
1015711890bcSjc 	if (array_obj_id < OBJ_NONE) {
1016711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
1017711890bcSjc 		return (array_obj_id);
1018711890bcSjc 	}
1019711890bcSjc 	if (array_obj_id == OBJ_NONE) {
1020711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
1021711890bcSjc 		return (ERR_DEVICE_INVALID);
1022711890bcSjc 	}
1023711890bcSjc 
1024711890bcSjc 	ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].delete_obj(&raid_tab_sys,
1025700682b8Syw 	    array_obj_id, plugin_err_str);
1026711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
1027711890bcSjc 
1028711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
1029711890bcSjc 	return (ret);
1030711890bcSjc }
1031711890bcSjc 
1032711890bcSjc int
raidcfg_set_hsp(raidcfg_hsp_relation_t * hsp_relations,char ** plugin_err_str)10335c9d25d2SYu-Bo Ryan Wang raidcfg_set_hsp(raidcfg_hsp_relation_t *hsp_relations,
1034*8bc1b774SToomas Soome     char **plugin_err_str)
1035711890bcSjc {
1036711890bcSjc 	raid_obj_id_t disk_obj_id, array_obj_id;
1037711890bcSjc 	raid_obj_id_t *hsp_relation_objs;
10385c9d25d2SYu-Bo Ryan Wang 	int ret;
1039711890bcSjc 
1040711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
1041711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
10425c9d25d2SYu-Bo Ryan Wang 	if (hsp_relations == NULL) {
1043711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
1044711890bcSjc 		return (ERR_OP_ILLEGAL);
1045711890bcSjc 	}
1046711890bcSjc 
10475c9d25d2SYu-Bo Ryan Wang 	hsp_relation_objs = malloc(2 * sizeof (raid_obj_id_t));
1048711890bcSjc 	if (hsp_relation_objs == NULL) {
1049711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
1050711890bcSjc 		return (ERR_NOMEM);
1051711890bcSjc 	}
1052711890bcSjc 
1053711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
1054711890bcSjc 
10555c9d25d2SYu-Bo Ryan Wang 	if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
10565c9d25d2SYu-Bo Ryan Wang 		array_obj_id = raid_handle_to_obj(&raid_tab_sys,
10575c9d25d2SYu-Bo Ryan Wang 		    hsp_relations->array_handle);
10585c9d25d2SYu-Bo Ryan Wang 		if (array_obj_id < OBJ_NONE) {
1059711890bcSjc 			free(hsp_relation_objs);
1060711890bcSjc 			(void) mutex_unlock(&raidcfg_mp);
10615c9d25d2SYu-Bo Ryan Wang 			return (array_obj_id);
1062711890bcSjc 		}
10635c9d25d2SYu-Bo Ryan Wang 		if (array_obj_id == OBJ_NONE) {
10645c9d25d2SYu-Bo Ryan Wang 			(void) free(hsp_relation_objs);
1065711890bcSjc 			(void) mutex_unlock(&raidcfg_mp);
1066711890bcSjc 			return (ERR_DEVICE_NOENT);
1067711890bcSjc 		}
10685c9d25d2SYu-Bo Ryan Wang 		if (raidcfg_get_type(hsp_relations->array_handle) !=
10695c9d25d2SYu-Bo Ryan Wang 		    OBJ_TYPE_ARRAY) {
1070711890bcSjc 			free(hsp_relation_objs);
1071711890bcSjc 			(void) mutex_unlock(&raidcfg_mp);
1072711890bcSjc 			return (ERR_DEVICE_TYPE);
1073711890bcSjc 		}
10745c9d25d2SYu-Bo Ryan Wang 	} else
10755c9d25d2SYu-Bo Ryan Wang 		array_obj_id = OBJ_ATTR_NONE;
1076711890bcSjc 
10775c9d25d2SYu-Bo Ryan Wang 	disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
10785c9d25d2SYu-Bo Ryan Wang 	    hsp_relations->disk_handle);
10795c9d25d2SYu-Bo Ryan Wang 	if (disk_obj_id < OBJ_NONE) {
10805c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation_objs);
10815c9d25d2SYu-Bo Ryan Wang 		(void) mutex_unlock(&raidcfg_mp);
10825c9d25d2SYu-Bo Ryan Wang 		return (disk_obj_id);
10835c9d25d2SYu-Bo Ryan Wang 	}
10845c9d25d2SYu-Bo Ryan Wang 	if (disk_obj_id == OBJ_NONE) {
10855c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation_objs);
10865c9d25d2SYu-Bo Ryan Wang 		(void) mutex_unlock(&raidcfg_mp);
10875c9d25d2SYu-Bo Ryan Wang 		return (ERR_DEVICE_NOENT);
10885c9d25d2SYu-Bo Ryan Wang 	}
10895c9d25d2SYu-Bo Ryan Wang 	if (raidcfg_get_type(hsp_relations->disk_handle) !=
10905c9d25d2SYu-Bo Ryan Wang 	    OBJ_TYPE_DISK) {
10915c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation_objs);
10925c9d25d2SYu-Bo Ryan Wang 		(void) mutex_unlock(&raidcfg_mp);
10935c9d25d2SYu-Bo Ryan Wang 		return (ERR_DEVICE_TYPE);
1094711890bcSjc 	}
1095711890bcSjc 
10965c9d25d2SYu-Bo Ryan Wang 	hsp_relation_objs[0] = array_obj_id;
10975c9d25d2SYu-Bo Ryan Wang 	hsp_relation_objs[1] = disk_obj_id;
10985c9d25d2SYu-Bo Ryan Wang 
10995c9d25d2SYu-Bo Ryan Wang 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].bind_obj(&raid_tab_sys,
1100700682b8Syw 	    hsp_relation_objs, plugin_err_str);
1101711890bcSjc 
1102711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
1103711890bcSjc 	free(hsp_relation_objs);
1104711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
1105711890bcSjc 
1106711890bcSjc 	return (ret);
1107711890bcSjc }
1108711890bcSjc 
1109711890bcSjc int
raidcfg_unset_hsp(raidcfg_hsp_relation_t * hsp_relations,char ** plugin_err_str)11105c9d25d2SYu-Bo Ryan Wang raidcfg_unset_hsp(raidcfg_hsp_relation_t *hsp_relations,
1111*8bc1b774SToomas Soome     char **plugin_err_str)
1112711890bcSjc {
1113711890bcSjc 	raid_obj_id_t disk_obj_id, array_obj_id;
1114711890bcSjc 	raid_obj_id_t *hsp_relation_objs;
11155c9d25d2SYu-Bo Ryan Wang 	int ret;
1116711890bcSjc 
1117711890bcSjc 	(void) mutex_lock(&raidcfg_mp);
1118711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
11195c9d25d2SYu-Bo Ryan Wang 	if (hsp_relations == NULL) {
1120711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
1121711890bcSjc 		return (ERR_OP_ILLEGAL);
1122711890bcSjc 	}
1123711890bcSjc 
11245c9d25d2SYu-Bo Ryan Wang 	hsp_relation_objs = malloc(2 * sizeof (raid_obj_id_t));
1125711890bcSjc 	if (hsp_relation_objs == NULL) {
1126711890bcSjc 		(void) mutex_unlock(&raidcfg_mp);
1127711890bcSjc 		return (ERR_NOMEM);
1128711890bcSjc 	}
1129711890bcSjc 
1130711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
1131711890bcSjc 
11325c9d25d2SYu-Bo Ryan Wang 	if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
11335c9d25d2SYu-Bo Ryan Wang 		array_obj_id = raid_handle_to_obj(&raid_tab_sys,
11345c9d25d2SYu-Bo Ryan Wang 		    hsp_relations->array_handle);
11355c9d25d2SYu-Bo Ryan Wang 		if (array_obj_id < OBJ_NONE) {
1136711890bcSjc 			free(hsp_relation_objs);
1137711890bcSjc 			(void) mutex_unlock(&raidcfg_mp);
11385c9d25d2SYu-Bo Ryan Wang 			return (array_obj_id);
1139711890bcSjc 		}
11405c9d25d2SYu-Bo Ryan Wang 		if (array_obj_id == OBJ_NONE) {
1141711890bcSjc 			free(hsp_relation_objs);
1142711890bcSjc 			(void) mutex_unlock(&raidcfg_mp);
1143711890bcSjc 			return (ERR_DEVICE_NOENT);
1144711890bcSjc 		}
11455c9d25d2SYu-Bo Ryan Wang 		if (raidcfg_get_type(hsp_relations->array_handle) !=
11465c9d25d2SYu-Bo Ryan Wang 		    OBJ_TYPE_ARRAY) {
1147711890bcSjc 			free(hsp_relation_objs);
1148711890bcSjc 			(void) mutex_unlock(&raidcfg_mp);
1149711890bcSjc 			return (ERR_DEVICE_TYPE);
1150711890bcSjc 		}
11515c9d25d2SYu-Bo Ryan Wang 	} else
11525c9d25d2SYu-Bo Ryan Wang 		array_obj_id = OBJ_ATTR_NONE;
1153711890bcSjc 
11545c9d25d2SYu-Bo Ryan Wang 	disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
11555c9d25d2SYu-Bo Ryan Wang 	    hsp_relations->disk_handle);
11565c9d25d2SYu-Bo Ryan Wang 	if (disk_obj_id < OBJ_NONE) {
11575c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation_objs);
11585c9d25d2SYu-Bo Ryan Wang 		(void) mutex_unlock(&raidcfg_mp);
11595c9d25d2SYu-Bo Ryan Wang 		return (disk_obj_id);
11605c9d25d2SYu-Bo Ryan Wang 	}
11615c9d25d2SYu-Bo Ryan Wang 	if (disk_obj_id == OBJ_NONE) {
11625c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation_objs);
11635c9d25d2SYu-Bo Ryan Wang 		(void) mutex_unlock(&raidcfg_mp);
11645c9d25d2SYu-Bo Ryan Wang 		return (ERR_DEVICE_NOENT);
11655c9d25d2SYu-Bo Ryan Wang 	}
11665c9d25d2SYu-Bo Ryan Wang 	if (raidcfg_get_type(hsp_relations->disk_handle) !=
11675c9d25d2SYu-Bo Ryan Wang 	    OBJ_TYPE_DISK) {
11685c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation_objs);
11695c9d25d2SYu-Bo Ryan Wang 		(void) mutex_unlock(&raidcfg_mp);
11705c9d25d2SYu-Bo Ryan Wang 		return (ERR_DEVICE_TYPE);
1171711890bcSjc 	}
1172711890bcSjc 
11735c9d25d2SYu-Bo Ryan Wang 	hsp_relation_objs[0] = array_obj_id;
11745c9d25d2SYu-Bo Ryan Wang 	hsp_relation_objs[1] = disk_obj_id;
11755c9d25d2SYu-Bo Ryan Wang 
1176711890bcSjc 	ret = raid_obj_op_sys[OBJ_TYPE_HSP].unbind_obj(&raid_tab_sys,
11775c9d25d2SYu-Bo Ryan Wang 	    hsp_relation_objs, plugin_err_str);
1178711890bcSjc 
1179711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
1180711890bcSjc 	free(hsp_relation_objs);
1181711890bcSjc 	(void) mutex_unlock(&raidcfg_mp);
1182711890bcSjc 
1183711890bcSjc 	return (ret);
1184711890bcSjc }
1185711890bcSjc 
1186711890bcSjc /*
1187711890bcSjc  * RaidCfg lib routines
1188711890bcSjc  */
1189711890bcSjc void
raidcfg_init(void)1190711890bcSjc raidcfg_init(void)
1191711890bcSjc {
1192*8bc1b774SToomas Soome 	(void) mutex_init(&raidcfg_mp, USYNC_THREAD, NULL);
1193711890bcSjc 	raid_plugin_init();
1194711890bcSjc 	(void) raid_handle_init();
1195711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
1196711890bcSjc }
1197711890bcSjc 
1198711890bcSjc void
raidcfg_fini(void)1199711890bcSjc raidcfg_fini(void)
1200711890bcSjc {
1201711890bcSjc 	/*
1202711890bcSjc 	 * Need to close all opened controllers before destroying object table
1203711890bcSjc 	 */
1204711890bcSjc 	(void) obj_rescan(&raid_tab_sys);
1205711890bcSjc 	raid_handle_fini();
1206711890bcSjc 	raid_obj_tab_destroy(&raid_tab_sys);
1207711890bcSjc 	raid_plugin_init();
1208711890bcSjc 	(void) mutex_destroy(&raidcfg_mp);
1209711890bcSjc }
1210711890bcSjc 
1211711890bcSjc /*
1212711890bcSjc  * Support routines
1213711890bcSjc  */
1214711890bcSjc static int
intcompare(const void * p1,const void * p2)1215711890bcSjc intcompare(const void *p1, const void *p2)
1216711890bcSjc {
1217711890bcSjc 	int i, j;
1218711890bcSjc 	i = *((int *)p1);
1219711890bcSjc 	j = *((int *)p2);
1220711890bcSjc 	return (i - j);
1221711890bcSjc }
1222711890bcSjc 
1223711890bcSjc static uint64_t
raid_space_noalign(raid_obj_tab_t * raid_tab,uint32_t raid_level,int num,raid_obj_id_t * disk_objs,arraypart_attr_t * arraypart_attrs)1224711890bcSjc raid_space_noalign(raid_obj_tab_t *raid_tab, uint32_t raid_level, int num,
1225*8bc1b774SToomas Soome     raid_obj_id_t *disk_objs, arraypart_attr_t *arraypart_attrs)
1226711890bcSjc {
1227711890bcSjc 	disk_attr_t *disk_attr;
1228711890bcSjc 	diskseg_attr_t *diskseg_attr;
1229711890bcSjc 	raid_obj_id_t obj_id;
1230711890bcSjc 	uint64_t offset, capacity;
1231711890bcSjc 	int i, disk_num, sub_array_num, disk_layer;
1232711890bcSjc 
1233711890bcSjc 	/* Find out the maximum available space for all disks */
1234711890bcSjc 	for (i = 0; i < num; ++i) {
1235711890bcSjc 		if ((disk_objs[i] == OBJ_SEPARATOR_BEGIN) ||
1236700682b8Syw 		    (disk_objs[i] == OBJ_SEPARATOR_END))
1237711890bcSjc 			continue;
1238711890bcSjc 
1239711890bcSjc 		(void) obj_get_attr(raid_tab, disk_objs[i],
1240700682b8Syw 		    (void **)(&disk_attr));
1241711890bcSjc 		obj_id = obj_get_comp(raid_tab, disk_objs[i],
1242700682b8Syw 		    OBJ_TYPE_DISK_SEG);
1243711890bcSjc 		if (obj_id == OBJ_NONE) {
1244711890bcSjc 			arraypart_attrs[i].offset = 0;
1245711890bcSjc 			arraypart_attrs[i].size = disk_attr->capacity;
1246711890bcSjc 			continue;
1247711890bcSjc 		}
1248711890bcSjc 
1249711890bcSjc 		(void) obj_get_attr(raid_tab, obj_id, (void **)
1250700682b8Syw 		    (&diskseg_attr));
1251711890bcSjc 		arraypart_attrs[i].offset = 0;
1252711890bcSjc 		arraypart_attrs[i].size = diskseg_attr->offset;
1253711890bcSjc 		offset = diskseg_attr->offset + diskseg_attr->size;
1254711890bcSjc 
1255711890bcSjc 		while ((obj_id = obj_get_sibling(raid_tab, obj_id)) !=
1256711890bcSjc 		    OBJ_NONE) {
1257711890bcSjc 			(void) obj_get_attr(raid_tab, obj_id,
1258700682b8Syw 			    (void **)(&diskseg_attr));
1259711890bcSjc 			if ((diskseg_attr->offset - offset) >
1260700682b8Syw 			    arraypart_attrs[i].size) {
1261711890bcSjc 				arraypart_attrs[i].offset = offset;
1262700682b8Syw 				arraypart_attrs[i].size = diskseg_attr->offset -
1263700682b8Syw 				    offset;
1264711890bcSjc 			}
1265711890bcSjc 
1266711890bcSjc 			offset = diskseg_attr->offset + diskseg_attr->size;
1267711890bcSjc 		}
1268711890bcSjc 
1269711890bcSjc 		if ((disk_attr->capacity - offset) > arraypart_attrs[i].size) {
1270711890bcSjc 			arraypart_attrs[i].offset = offset;
1271700682b8Syw 			arraypart_attrs[i].size = disk_attr->capacity -
1272700682b8Syw 			    offset;
1273711890bcSjc 		}
1274711890bcSjc 	}
1275711890bcSjc 
1276711890bcSjc 	capacity = OBJ_ATTR_NONE;
1277711890bcSjc 	disk_num = 0;
1278711890bcSjc 	disk_layer = 0;
1279711890bcSjc 	sub_array_num = 0;
1280711890bcSjc 	for (i = 0; i < num; ++i) {
1281711890bcSjc 		if (disk_objs[i] == OBJ_SEPARATOR_BEGIN) {
1282711890bcSjc 			++ disk_layer;
1283711890bcSjc 			continue;
1284711890bcSjc 		}
1285711890bcSjc 		if (disk_objs[i] == OBJ_SEPARATOR_END) {
1286711890bcSjc 			-- disk_layer;
1287711890bcSjc 			if (disk_layer != 0)
1288711890bcSjc 				++ sub_array_num;
1289711890bcSjc 			continue;
1290711890bcSjc 		}
1291711890bcSjc 
1292711890bcSjc 		if (capacity > arraypart_attrs[i].size)
1293711890bcSjc 			capacity = arraypart_attrs[i].size;
1294711890bcSjc 		++disk_num;
1295711890bcSjc 	}
1296711890bcSjc 
1297711890bcSjc 	switch (raid_level) {
1298711890bcSjc 	case	RAID_LEVEL_0:
1299711890bcSjc 		capacity = capacity * disk_num;
1300711890bcSjc 		break;
1301711890bcSjc 	case	RAID_LEVEL_1:
1302711890bcSjc 		capacity = capacity * disk_num / 2;
1303711890bcSjc 		break;
1304711890bcSjc 	case	RAID_LEVEL_1E:
1305711890bcSjc 		capacity = capacity * disk_num / 2;
1306711890bcSjc 		break;
1307711890bcSjc 	case	RAID_LEVEL_5:
1308711890bcSjc 		capacity = capacity * (disk_num - 1);
1309711890bcSjc 		break;
1310711890bcSjc 	case	RAID_LEVEL_10:
1311711890bcSjc 		capacity = capacity * disk_num / 2;
1312711890bcSjc 		break;
1313711890bcSjc 	case	RAID_LEVEL_50:
1314711890bcSjc 		capacity = capacity * (disk_num - sub_array_num);
1315711890bcSjc 		break;
1316711890bcSjc 	default:
1317711890bcSjc 		return (ERR_ARRAY_LEVEL);
1318711890bcSjc 	}
1319711890bcSjc 
1320711890bcSjc 	return (capacity);
1321711890bcSjc }
1322711890bcSjc 
1323711890bcSjc /*
1324711890bcSjc  * Raid handle maintenance routines
1325711890bcSjc  */
1326711890bcSjc static int
raid_handle_init()1327711890bcSjc raid_handle_init()
1328711890bcSjc {
1329711890bcSjc 	int i;
1330711890bcSjc 	void *ptr;
1331711890bcSjc 
1332711890bcSjc 	raid_handle_sys.handle_num += HANDLER_SLOTS;
1333711890bcSjc 	ptr = realloc(raid_handle_sys.handles,
1334700682b8Syw 	    raid_handle_sys.handle_num * sizeof (handle_attr_t));
1335711890bcSjc 	if (ptr == NULL)
1336711890bcSjc 		return (ERR_NOMEM);
1337711890bcSjc 	raid_handle_sys.handles = ptr;
1338711890bcSjc 
1339711890bcSjc 	/* Clean up the new allocated handles */
1340711890bcSjc 	for (i = raid_handle_sys.handle_num - HANDLER_SLOTS;
1341700682b8Syw 	    i < raid_handle_sys.handle_num; ++i) {
1342ee992693SZach Kissel 		bzero(&raid_handle_sys.handles[i], sizeof (handle_attr_t));
1343711890bcSjc 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1344711890bcSjc 		raid_handle_sys.handles[i].next = i + 1;
1345711890bcSjc 	}
1346711890bcSjc 
1347711890bcSjc 	/* For the first time of allocation, set up the system object handle */
1348711890bcSjc 	if (raid_handle_sys.handle_num == HANDLER_SLOTS) {
1349711890bcSjc 		raid_handle_sys.handles[0].type = OBJ_TYPE_SYSTEM;
1350711890bcSjc 		raid_handle_sys.handles[0].next = 0;
1351711890bcSjc 		raid_handle_sys.unused = 1;
1352711890bcSjc 		raid_handle_sys.used = 0;
1353711890bcSjc 	}
1354711890bcSjc 	return (SUCCESS);
1355711890bcSjc }
1356711890bcSjc 
1357711890bcSjc static void
raid_handle_fini()1358711890bcSjc raid_handle_fini()
1359711890bcSjc {
1360711890bcSjc 	raid_obj_handle_t i;
1361711890bcSjc 
1362711890bcSjc 	i = raid_handle_sys.used;
1363711890bcSjc 
1364711890bcSjc 	/* Close all opened controllers */
1365711890bcSjc 	while (i != 0) {
1366711890bcSjc 		if ((raid_handle_sys.handles[i].type == OBJ_TYPE_CONTROLLER) &&
1367700682b8Syw 		    (raid_handle_sys.handles[i].fd != 0) &&
1368700682b8Syw 		    (raid_handle_sys.handles[i].raid_lib != NULL))
1369711890bcSjc 			raid_handle_sys.handles[i].raid_lib->close_controller(
1370700682b8Syw 			    raid_handle_sys.handles[i].controller_id, NULL);
1371711890bcSjc 		i = raid_handle_sys.handles[i].next;
1372711890bcSjc 	}
1373711890bcSjc 
1374711890bcSjc 	/* Clean up handle space */
1375711890bcSjc 	raid_handle_sys.handle_num = 0;
1376711890bcSjc 	raid_handle_sys.unused = 0;
1377711890bcSjc 	raid_handle_sys.used = 0;
1378711890bcSjc 	free(raid_handle_sys.handles);
1379711890bcSjc 	raid_handle_sys.handles = NULL;
1380711890bcSjc }
1381711890bcSjc 
1382711890bcSjc static raid_obj_handle_t
raid_handle_new(raid_obj_type_id_t type)1383711890bcSjc raid_handle_new(raid_obj_type_id_t type)
1384711890bcSjc {
1385711890bcSjc 	int ret;
1386711890bcSjc 
1387711890bcSjc 	if (raid_handle_sys.unused == raid_handle_sys.handle_num - 1) {
1388711890bcSjc 		ret = raid_handle_init();
1389711890bcSjc 		if (ret < SUCCESS)
1390711890bcSjc 			return (ret);
1391711890bcSjc 	}
1392711890bcSjc 
1393711890bcSjc 	ret = raid_handle_sys.unused;
1394711890bcSjc 	raid_handle_sys.unused = raid_handle_sys.handles[ret].next;
1395711890bcSjc 
1396711890bcSjc 	raid_handle_sys.handles[ret].next = raid_handle_sys.used;
1397711890bcSjc 	raid_handle_sys.used = ret;
1398711890bcSjc 	raid_handle_sys.handles[ret].type = type;
1399711890bcSjc 
1400711890bcSjc 	return (ret);
1401711890bcSjc }
1402711890bcSjc 
1403711890bcSjc static void
raid_handle_delete(raid_obj_handle_t handle)1404711890bcSjc raid_handle_delete(raid_obj_handle_t handle)
1405711890bcSjc {
1406711890bcSjc 	int i = raid_handle_sys.used, j = 0;
1407711890bcSjc 
1408711890bcSjc 	if (handle == 0)
1409711890bcSjc 		return;
1410711890bcSjc 
1411711890bcSjc 	while (i != 0 && i != handle) {
1412711890bcSjc 		j = i;
1413711890bcSjc 		i = raid_handle_sys.handles[i].next;
1414711890bcSjc 	}
1415711890bcSjc 
1416711890bcSjc 	if (i == handle) {
1417711890bcSjc 		if (j != 0)
1418711890bcSjc 			raid_handle_sys.handles[j].next =
1419700682b8Syw 			    raid_handle_sys.handles[i].next;
1420711890bcSjc 		else
1421711890bcSjc 			raid_handle_sys.used =
1422700682b8Syw 			    raid_handle_sys.handles[i].next;
1423711890bcSjc 
1424711890bcSjc 		raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1425711890bcSjc 		raid_handle_sys.handles[i].next =
1426700682b8Syw 		    raid_handle_sys.unused;
1427711890bcSjc 		raid_handle_sys.unused = i;
1428711890bcSjc 	}
1429711890bcSjc }
1430711890bcSjc 
1431711890bcSjc static void
raid_handle_delete_controller_comp(uint32_t controller_id)1432711890bcSjc raid_handle_delete_controller_comp(uint32_t controller_id)
1433711890bcSjc {
1434711890bcSjc 	int i = raid_handle_sys.used, j;
1435711890bcSjc 
1436711890bcSjc 	while (i != 0) {
1437700682b8Syw 		j = i;
1438700682b8Syw 		i = raid_handle_sys.handles[i].next;
1439700682b8Syw 		if ((raid_handle_sys.handles[j].controller_id ==
1440700682b8Syw 		    controller_id) &&
1441700682b8Syw 		    (raid_handle_sys.handles[j].type !=
1442700682b8Syw 		    OBJ_TYPE_CONTROLLER))
1443711890bcSjc 		raid_handle_delete(j);
1444711890bcSjc 	}
1445711890bcSjc }
1446711890bcSjc 
1447711890bcSjc static raid_obj_id_t
raid_handle_to_obj(raid_obj_tab_t * raid_tab,raid_obj_handle_t handle)1448711890bcSjc raid_handle_to_obj(raid_obj_tab_t *raid_tab, raid_obj_handle_t handle)
1449711890bcSjc {
1450711890bcSjc 	handle_attr_t *handle_attr;
1451711890bcSjc 	raid_obj_id_t obj_id;
1452711890bcSjc 
1453711890bcSjc 	if (handle == OBJ_SYSTEM)
1454711890bcSjc 		return (OBJ_SYSTEM);
1455711890bcSjc 
1456711890bcSjc 	handle_attr = raid_handle_sys.handles + handle;
1457711890bcSjc 
1458711890bcSjc 	switch (handle_attr->type) {
1459711890bcSjc 	case	OBJ_TYPE_SYSTEM:
1460711890bcSjc 		return (OBJ_SYSTEM);
1461711890bcSjc 	case	OBJ_TYPE_CONTROLLER:
1462711890bcSjc 		obj_id = obj_locate_controller(raid_tab,
1463700682b8Syw 		    handle_attr->controller_id);
1464711890bcSjc 		break;
1465711890bcSjc 	case	OBJ_TYPE_ARRAY:
1466711890bcSjc 		obj_id = obj_locate_array(raid_tab,
1467700682b8Syw 		    handle_attr->controller_id, handle_attr->array_id);
1468711890bcSjc 		break;
1469711890bcSjc 	case	OBJ_TYPE_HSP:
1470711890bcSjc 		obj_id = obj_locate_hsp(raid_tab,
1471700682b8Syw 		    handle_attr->controller_id, handle_attr->disk_id,
1472700682b8Syw 		    handle_attr->array_id);
1473711890bcSjc 		break;
1474711890bcSjc 	case	OBJ_TYPE_DISK:
1475711890bcSjc 		obj_id = obj_locate_disk(raid_tab,
1476700682b8Syw 		    handle_attr->controller_id, handle_attr->disk_id);
1477711890bcSjc 		break;
1478711890bcSjc 	case	OBJ_TYPE_ARRAY_PART:
1479711890bcSjc 		obj_id = obj_locate_arraypart(raid_tab,
1480700682b8Syw 		    handle_attr->controller_id, handle_attr->array_id,
1481700682b8Syw 		    handle_attr->disk_id);
1482711890bcSjc 		break;
1483711890bcSjc 	case	OBJ_TYPE_DISK_SEG:
1484711890bcSjc 		obj_id = obj_locate_diskseg(raid_tab,
1485700682b8Syw 		    handle_attr->controller_id,
1486700682b8Syw 		    handle_attr->disk_id, handle_attr->seq_id);
1487711890bcSjc 		break;
1488711890bcSjc 	case	OBJ_TYPE_TASK:
1489711890bcSjc 		obj_id = obj_locate_task(raid_tab,
1490700682b8Syw 		    handle_attr->controller_id, handle_attr->task_id);
1491711890bcSjc 		break;
1492b449fa8aSyw 	case	OBJ_TYPE_PROP:
1493b449fa8aSyw 		obj_id = obj_locate_prop(raid_tab,
1494b449fa8aSyw 		    handle_attr->controller_id, handle_attr->disk_id,
1495b449fa8aSyw 		    handle_attr->prop_id);
1496b449fa8aSyw 		break;
1497711890bcSjc 	default:
1498711890bcSjc 		return (ERR_DEVICE_INVALID);
1499711890bcSjc 	}
1500711890bcSjc 
1501711890bcSjc 	if (obj_id < OBJ_NONE)
1502711890bcSjc 		return (obj_id);
1503711890bcSjc 	if (obj_id == OBJ_NONE)
1504711890bcSjc 		return (ERR_DEVICE_NOENT);
1505711890bcSjc 
1506711890bcSjc 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
1507711890bcSjc 	return (obj_id);
1508711890bcSjc }
1509711890bcSjc 
1510711890bcSjc static raid_obj_handle_t
raid_obj_to_handle(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)1511711890bcSjc raid_obj_to_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1512711890bcSjc {
1513711890bcSjc 	raid_obj_id_t obj_id_backup = obj_id;
1514711890bcSjc 	raid_obj_type_id_t type;
1515711890bcSjc 	raid_obj_handle_t handle;
1516711890bcSjc 	controller_attr_t *controller_attr;
1517711890bcSjc 	array_attr_t *array_attr;
1518711890bcSjc 	hsp_attr_t *hsp_attr;
1519711890bcSjc 	disk_attr_t *disk_attr;
1520711890bcSjc 	arraypart_attr_t *arraypart_attr;
1521711890bcSjc 	diskseg_attr_t *diskseg_attr;
1522711890bcSjc 	task_attr_t *task_attr;
1523b449fa8aSyw 	property_attr_t *prop_attr;
1524711890bcSjc 
1525711890bcSjc 	if (obj_id == OBJ_SYSTEM)
1526711890bcSjc 		return (OBJ_SYSTEM);
1527711890bcSjc 
1528711890bcSjc 	/* If the object mapped by a handle */
1529711890bcSjc 	handle = raid_obj_get_handle(raid_tab, obj_id);
1530711890bcSjc 	if (handle != 0)
1531711890bcSjc 		return (handle);
1532711890bcSjc 
1533711890bcSjc 	/* Search for existing handles */
1534711890bcSjc 	for (handle = raid_handle_sys.used; handle != 0;
1535700682b8Syw 	    handle = raid_handle_sys.handles[handle].next)
1536711890bcSjc 		if (raid_handle_to_obj(raid_tab, handle) == obj_id)
1537711890bcSjc 			break;
1538711890bcSjc 
1539711890bcSjc 	if (handle != 0)
1540711890bcSjc 		return (handle);
1541711890bcSjc 
1542711890bcSjc 	/* Allocate new handle for this object */
1543711890bcSjc 	type = raid_obj_get_type(raid_tab, obj_id);
1544711890bcSjc 	handle = raid_handle_new(type);
1545711890bcSjc 	(void) raid_obj_set_handle(raid_tab, obj_id, handle);
1546711890bcSjc 	raid_handle_sys.handles[handle].type = type;
1547711890bcSjc 
1548711890bcSjc 	switch (type) {
1549711890bcSjc 	case OBJ_TYPE_SYSTEM:
1550711890bcSjc 		break;
1551711890bcSjc 	case OBJ_TYPE_CONTROLLER:
1552711890bcSjc 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1553711890bcSjc 		raid_handle_sys.handles[handle].controller_id =
1554700682b8Syw 		    controller_attr->controller_id;
1555711890bcSjc 		break;
1556711890bcSjc 	case OBJ_TYPE_ARRAY:
1557711890bcSjc 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1558711890bcSjc 		raid_handle_sys.handles[handle].array_id = array_attr->array_id;
1559711890bcSjc 		obj_id = obj_get_controller(raid_tab, obj_id);
1560711890bcSjc 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1561711890bcSjc 		raid_handle_sys.handles[handle].controller_id =
1562700682b8Syw 		    controller_attr->controller_id;
1563711890bcSjc 		break;
1564711890bcSjc 	case OBJ_TYPE_HSP:
1565711890bcSjc 		hsp_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1566711890bcSjc 		raid_handle_sys.handles[handle].array_id =
1567700682b8Syw 		    hsp_attr->associated_id;
1568711890bcSjc 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1569711890bcSjc 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1570711890bcSjc 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1571711890bcSjc 		obj_id = obj_get_controller(raid_tab, obj_id);
1572711890bcSjc 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1573711890bcSjc 		raid_handle_sys.handles[handle].controller_id =
1574700682b8Syw 		    controller_attr->controller_id;
1575711890bcSjc 		break;
1576711890bcSjc 	case OBJ_TYPE_DISK:
1577711890bcSjc 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1578711890bcSjc 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1579711890bcSjc 		obj_id = obj_get_controller(raid_tab, obj_id);
1580711890bcSjc 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1581711890bcSjc 		raid_handle_sys.handles[handle].controller_id =
1582700682b8Syw 		    controller_attr->controller_id;
1583711890bcSjc 		break;
1584711890bcSjc 	case OBJ_TYPE_ARRAY_PART:
1585711890bcSjc 		arraypart_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1586711890bcSjc 		raid_handle_sys.handles[handle].disk_id =
1587700682b8Syw 		    arraypart_attr->disk_id;
1588711890bcSjc 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1589711890bcSjc 		array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1590711890bcSjc 		raid_handle_sys.handles[handle].array_id =
1591700682b8Syw 		    array_attr->array_id;
1592711890bcSjc 		obj_id = obj_get_controller(raid_tab, obj_id);
1593711890bcSjc 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1594711890bcSjc 		raid_handle_sys.handles[handle].controller_id =
1595700682b8Syw 		    controller_attr->controller_id;
1596711890bcSjc 		break;
1597711890bcSjc 	case OBJ_TYPE_DISK_SEG:
1598711890bcSjc 		diskseg_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1599711890bcSjc 		raid_handle_sys.handles[handle].seq_id = diskseg_attr->seq_no;
1600711890bcSjc 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1601711890bcSjc 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1602711890bcSjc 		raid_handle_sys.handles[handle].disk_id =
1603700682b8Syw 		    disk_attr->disk_id;
1604711890bcSjc 		obj_id = obj_get_controller(raid_tab, obj_id);
1605711890bcSjc 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1606711890bcSjc 		raid_handle_sys.handles[handle].controller_id =
1607700682b8Syw 		    controller_attr->controller_id;
1608711890bcSjc 		break;
1609711890bcSjc 	case OBJ_TYPE_TASK:
1610711890bcSjc 		task_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1611711890bcSjc 		raid_handle_sys.handles[handle].task_id = task_attr->task_id;
1612711890bcSjc 		obj_id = obj_get_controller(raid_tab, obj_id);
1613711890bcSjc 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1614711890bcSjc 		raid_handle_sys.handles[handle].controller_id =
1615700682b8Syw 		    controller_attr->controller_id;
1616711890bcSjc 		break;
1617b449fa8aSyw 	case OBJ_TYPE_PROP:
1618b449fa8aSyw 		prop_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1619b449fa8aSyw 		raid_handle_sys.handles[handle].prop_id =
1620b449fa8aSyw 		    prop_attr->prop_id;
1621b449fa8aSyw 		obj_id = raid_obj_get_container(raid_tab, obj_id);
1622b449fa8aSyw 		disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1623b449fa8aSyw 		raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1624b449fa8aSyw 		obj_id = obj_get_controller(raid_tab, obj_id);
1625b449fa8aSyw 		controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1626b449fa8aSyw 		raid_handle_sys.handles[handle].controller_id =
1627b449fa8aSyw 		    controller_attr->controller_id;
1628b449fa8aSyw 		break;
1629711890bcSjc 	default:
1630711890bcSjc 		return (ERR_DEVICE_INVALID);
1631711890bcSjc 	}
1632711890bcSjc 
1633711890bcSjc 	(void) raid_obj_set_handle(raid_tab, obj_id_backup, handle);
1634711890bcSjc 	return (handle);
1635711890bcSjc }
1636711890bcSjc 
1637711890bcSjc static raid_lib_t *
raid_obj_get_lib(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)1638711890bcSjc raid_obj_get_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1639711890bcSjc {
1640711890bcSjc 	raid_obj_handle_t handle;
1641711890bcSjc 	controller_attr_t *attr;
1642711890bcSjc 
1643711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1644711890bcSjc 		return (NULL);
1645711890bcSjc 
1646711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1647711890bcSjc 	handle = raid_handle_sys.used;
1648711890bcSjc 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1649700682b8Syw 	    raid_handle_sys.handles[handle].controller_id !=
1650700682b8Syw 	    attr->controller_id)
1651711890bcSjc 		handle = raid_handle_sys.handles[handle].next;
1652711890bcSjc 
1653711890bcSjc 	if (handle == 0)
1654711890bcSjc 		return (NULL);
1655711890bcSjc 
1656711890bcSjc 	return (raid_handle_sys.handles[handle].raid_lib);
1657711890bcSjc }
1658711890bcSjc 
1659711890bcSjc static int
raid_obj_set_lib(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_lib_t * raid_lib)1660711890bcSjc raid_obj_set_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1661*8bc1b774SToomas Soome     raid_lib_t *raid_lib)
1662711890bcSjc {
1663711890bcSjc 	raid_obj_handle_t handle;
1664711890bcSjc 	controller_attr_t *attr;
1665711890bcSjc 
1666711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1667711890bcSjc 		return (ERR_DEVICE_TYPE);
1668711890bcSjc 
1669711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1670711890bcSjc 	handle = raid_handle_sys.used;
1671711890bcSjc 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1672700682b8Syw 	    raid_handle_sys.handles[handle].controller_id !=
1673700682b8Syw 	    attr->controller_id)
1674711890bcSjc 		handle = raid_handle_sys.handles[handle].next;
1675711890bcSjc 
1676711890bcSjc 	if (handle == 0)
1677711890bcSjc 		return (ERR_DEVICE_NOENT);
1678711890bcSjc 
1679711890bcSjc 	raid_handle_sys.handles[handle].raid_lib = raid_lib;
1680711890bcSjc 	return (SUCCESS);
1681711890bcSjc }
1682711890bcSjc 
1683711890bcSjc static int
raid_obj_get_fd(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)1684711890bcSjc raid_obj_get_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1685711890bcSjc {
1686711890bcSjc 	raid_obj_handle_t handle;
1687711890bcSjc 	controller_attr_t *attr;
1688711890bcSjc 
1689711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1690711890bcSjc 		return (ERR_DEVICE_TYPE);
1691711890bcSjc 
1692711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1693711890bcSjc 	handle = raid_handle_sys.used;
1694711890bcSjc 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1695700682b8Syw 	    raid_handle_sys.handles[handle].controller_id !=
1696700682b8Syw 	    attr->controller_id)
1697711890bcSjc 		handle = raid_handle_sys.handles[handle].next;
1698711890bcSjc 
1699711890bcSjc 	if (handle == 0)
1700711890bcSjc 		return (ERR_DEVICE_NOENT);
1701711890bcSjc 
1702711890bcSjc 	return (raid_handle_sys.handles[handle].fd);
1703711890bcSjc }
1704711890bcSjc 
1705711890bcSjc static int
raid_obj_set_fd(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int fd)1706711890bcSjc raid_obj_set_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, int fd)
1707711890bcSjc {
1708711890bcSjc 	raid_obj_handle_t handle;
1709711890bcSjc 	controller_attr_t *attr;
1710711890bcSjc 
1711711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1712711890bcSjc 		return (ERR_DEVICE_TYPE);
1713711890bcSjc 
1714711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1715711890bcSjc 	handle = raid_handle_sys.used;
1716711890bcSjc 	while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1717700682b8Syw 	    raid_handle_sys.handles[handle].controller_id !=
1718700682b8Syw 	    attr->controller_id)
1719711890bcSjc 		handle = raid_handle_sys.handles[handle].next;
1720711890bcSjc 
1721711890bcSjc 	if (handle == 0)
1722711890bcSjc 		return (ERR_DEVICE_NOENT);
1723711890bcSjc 
1724711890bcSjc 	raid_handle_sys.handles[handle].fd = fd;
1725711890bcSjc 	return (SUCCESS);
1726711890bcSjc }
1727711890bcSjc 
1728711890bcSjc /*
1729711890bcSjc  * Raid object maintenance routines
1730711890bcSjc  */
1731711890bcSjc static int
obj_scan_comp(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)1732711890bcSjc obj_scan_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1733711890bcSjc {
1734711890bcSjc 	raid_obj_status_t status;
1735711890bcSjc 	raid_obj_type_id_t type;
1736711890bcSjc 	int ret, i, obj_type_cnt, comp_num;
1737711890bcSjc 	raid_obj_id_t *comp_list;
1738711890bcSjc 
1739711890bcSjc 	status = raid_obj_get_status(raid_tab, obj_id);
1740711890bcSjc 	if (status < SUCCESS)
1741711890bcSjc 		return (status);
1742711890bcSjc 
1743711890bcSjc 	if (status & OBJ_STATUS_SCANCOMP)
1744711890bcSjc 		return (SUCCESS);
1745711890bcSjc 
1746711890bcSjc 	type = raid_obj_get_type(raid_tab, obj_id);
1747edabaf6fSMilan Jurik 	/* type less than OBJ_TYPE_SYSTEM means error */
1748edabaf6fSMilan Jurik 	if (type < OBJ_TYPE_SYSTEM)
1749711890bcSjc 		return (ERR_DEVICE_INVALID);
1750711890bcSjc 
1751711890bcSjc 	for (obj_type_cnt = OBJ_SYSTEM; obj_type_cnt < OBJ_TYPE_ALL;
1752700682b8Syw 	    ++obj_type_cnt) {
1753711890bcSjc 		if (raid_obj_op_sys[type].compnum != NULL)
1754711890bcSjc 			comp_num = raid_obj_op_sys[type].compnum(
1755700682b8Syw 			    raid_tab, obj_id, obj_type_cnt);
1756711890bcSjc 		else
1757711890bcSjc 			comp_num = 0;
1758711890bcSjc 
1759711890bcSjc 		if (comp_num < SUCCESS)
1760711890bcSjc 			return (comp_num);
1761711890bcSjc 		if (comp_num == 0)
1762711890bcSjc 			continue;
1763711890bcSjc 
1764711890bcSjc 		comp_list = calloc(comp_num, sizeof (raid_obj_id_t));
1765711890bcSjc 		if (comp_list == NULL)
1766711890bcSjc 			return (ERR_NOMEM);
1767711890bcSjc 
1768711890bcSjc 		for (i = 0; i < comp_num; ++i) {
1769711890bcSjc 			*(comp_list + i) = raid_obj_create(raid_tab,
1770700682b8Syw 			    obj_type_cnt);
1771711890bcSjc 			if (*(comp_list + i) < SUCCESS) {
1772711890bcSjc 				ret = *(comp_list + i);
1773711890bcSjc 				free(comp_list);
1774711890bcSjc 				return (ret);
1775711890bcSjc 			}
1776711890bcSjc 
1777711890bcSjc 			(void) raid_obj_clear_status(raid_tab,
1778700682b8Syw 			    *(comp_list + i), OBJ_STATUS_CMD_CLEAN);
1779711890bcSjc 			(void) raid_obj_add_org(raid_tab, *(comp_list + i),
1780700682b8Syw 			    obj_id);
1781711890bcSjc 		}
1782711890bcSjc 
1783711890bcSjc 		if (raid_obj_op_sys[type].complist != NULL)
1784711890bcSjc 			raid_obj_op_sys[type].complist(raid_tab,
1785700682b8Syw 			    obj_id, comp_num, comp_list, obj_type_cnt);
1786711890bcSjc 		free(comp_list);
1787711890bcSjc 	}
1788711890bcSjc 
1789711890bcSjc 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_SCANCOMP);
1790711890bcSjc 	return (SUCCESS);
1791711890bcSjc }
1792711890bcSjc 
1793711890bcSjc static int
obj_rescan(raid_obj_tab_t * raid_tab)1794711890bcSjc obj_rescan(raid_obj_tab_t *raid_tab)
1795711890bcSjc {
1796711890bcSjc 	int ret;
1797711890bcSjc 
1798711890bcSjc 	raid_obj_tab_destroy(raid_tab);
1799711890bcSjc 
1800711890bcSjc 	if (raid_obj_tab_create(raid_tab, HASH_SLOTS) != SUCCESS)
1801711890bcSjc 		return (ERR_NOMEM);
1802711890bcSjc 
1803711890bcSjc 	if ((ret = raid_obj_create_system_obj(raid_tab)) != SUCCESS) {
1804711890bcSjc 		raid_obj_tab_destroy(raid_tab);
1805711890bcSjc 		return (ret);
1806711890bcSjc 	}
1807711890bcSjc 
1808711890bcSjc 	return (SUCCESS);
1809711890bcSjc }
1810711890bcSjc 
1811711890bcSjc static raid_obj_id_t
obj_get_comp(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t obj_type)1812711890bcSjc obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1813*8bc1b774SToomas Soome     raid_obj_type_id_t obj_type)
1814711890bcSjc {
1815711890bcSjc 	raid_obj_id_t id;
1816711890bcSjc 	raid_obj_type_id_t type;
1817711890bcSjc 	raid_obj_status_t status;
1818711890bcSjc 	int ret;
1819711890bcSjc 
1820711890bcSjc 	if ((obj_type < OBJ_TYPE_SYSTEM) || (obj_type > OBJ_TYPE_ALL))
1821711890bcSjc 		return (ERR_DEVICE_TYPE);
1822711890bcSjc 
1823711890bcSjc 	status = raid_obj_get_status(raid_tab, obj_id);
1824711890bcSjc 	if (status < SUCCESS)
1825711890bcSjc 		return (status);
1826711890bcSjc 
1827711890bcSjc 	if (!(status & OBJ_STATUS_SCANCOMP)) {
1828711890bcSjc 		ret = obj_scan_comp(raid_tab, obj_id);
1829711890bcSjc 		if (ret < SUCCESS)
1830711890bcSjc 			return (ret);
1831711890bcSjc 	}
1832711890bcSjc 
1833711890bcSjc 	id = raid_obj_get_comp(raid_tab, obj_id);
1834711890bcSjc 	if (id <= OBJ_NONE)
1835711890bcSjc 		return (id);
1836711890bcSjc 
1837711890bcSjc 	type = raid_obj_get_type(raid_tab, id);
1838711890bcSjc 	if (type < OBJ_TYPE_SYSTEM)
1839711890bcSjc 		return (type);
1840711890bcSjc 
1841711890bcSjc 	if (type == obj_type)
1842711890bcSjc 		return (id);
1843711890bcSjc 
1844711890bcSjc 	while (id > OBJ_NONE) {
1845711890bcSjc 		id = raid_obj_get_sibling(raid_tab, id);
1846711890bcSjc 		if (id <= OBJ_NONE)
1847711890bcSjc 			return (id);
1848711890bcSjc 
1849711890bcSjc 		type = raid_obj_get_type(raid_tab, id);
1850711890bcSjc 		if (type < OBJ_TYPE_SYSTEM)
1851711890bcSjc 			return (type);
1852711890bcSjc 
1853711890bcSjc 		if (type == obj_type)
1854711890bcSjc 			break;
1855711890bcSjc 	};
1856711890bcSjc 
1857711890bcSjc 	return (id);
1858711890bcSjc }
1859711890bcSjc 
1860711890bcSjc static raid_obj_id_t
obj_get_sibling(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)1861711890bcSjc obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1862711890bcSjc {
1863711890bcSjc 	raid_obj_id_t id;
1864711890bcSjc 	raid_obj_type_id_t type, obj_type;
1865711890bcSjc 
1866711890bcSjc 	id = obj_id;
1867711890bcSjc 	obj_type = raid_obj_get_type(raid_tab, id);
1868711890bcSjc 	if (obj_type < OBJ_TYPE_SYSTEM)
1869711890bcSjc 		return (obj_type);
1870711890bcSjc 
1871711890bcSjc 	do {
1872711890bcSjc 		id = raid_obj_get_sibling(raid_tab, id);
1873711890bcSjc 		if (id < OBJ_NONE)
1874711890bcSjc 			return (id);
1875711890bcSjc 
1876711890bcSjc 		type = raid_obj_get_type(raid_tab, id);
1877711890bcSjc 		if (type < OBJ_TYPE_SYSTEM)
1878711890bcSjc 			return (type);
1879711890bcSjc 	} while ((type != obj_type) && (id != OBJ_NONE));
1880711890bcSjc 
1881711890bcSjc 	return (id);
1882711890bcSjc }
1883711890bcSjc 
1884711890bcSjc static int
obj_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,void ** data)1885711890bcSjc obj_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, void **data)
1886711890bcSjc {
1887711890bcSjc 	raid_obj_type_id_t type;
1888711890bcSjc 	raid_obj_status_t status;
1889711890bcSjc 	void *attr;
1890711890bcSjc 	int ret = SUCCESS;
1891711890bcSjc 
1892711890bcSjc 	status = raid_obj_get_status(raid_tab, obj_id);
1893711890bcSjc 	if (status < SUCCESS)
1894711890bcSjc 		return (status);
1895711890bcSjc 
1896711890bcSjc 	type = raid_obj_get_type(raid_tab, obj_id);
1897711890bcSjc 	if (type < OBJ_TYPE_SYSTEM)
1898711890bcSjc 		return (type);
1899711890bcSjc 
1900711890bcSjc 	if (!(status & OBJ_STATUS_OPENED)) {
1901711890bcSjc 		if (raid_obj_op_sys[type].get_attr == NULL)
1902711890bcSjc 			(void) raid_obj_set_status(raid_tab, obj_id,
1903700682b8Syw 			    OBJ_STATUS_OPENED);
1904711890bcSjc 		else
1905711890bcSjc 			ret = raid_obj_op_sys[type].get_attr(raid_tab, obj_id);
1906711890bcSjc 	}
1907711890bcSjc 	if (ret < SUCCESS)
1908711890bcSjc 		return (ret);
1909711890bcSjc 
1910711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1911711890bcSjc 	if (attr == NULL && type != OBJ_TYPE_SYSTEM)
1912711890bcSjc 		return (ERR_DEVICE_INVALID);
1913711890bcSjc 
1914711890bcSjc 	*data = attr;
1915711890bcSjc 	return (SUCCESS);
1916711890bcSjc }
1917711890bcSjc 
1918711890bcSjc static raid_obj_id_t
obj_locate_controller(raid_obj_tab_t * raid_tab,uint32_t controller_id)1919711890bcSjc obj_locate_controller(raid_obj_tab_t *raid_tab, uint32_t controller_id)
1920711890bcSjc {
1921711890bcSjc 	raid_obj_id_t obj_id;
1922711890bcSjc 	controller_attr_t *attr;
1923711890bcSjc 
1924711890bcSjc 	obj_id = obj_get_comp(raid_tab, OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
1925711890bcSjc 	if (obj_id <= OBJ_NONE)
1926711890bcSjc 		return (obj_id);
1927711890bcSjc 
1928711890bcSjc 	do {
1929711890bcSjc 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1930711890bcSjc 		if (attr == NULL)
1931711890bcSjc 			return (ERR_DEVICE_INVALID);
1932711890bcSjc 
1933711890bcSjc 		if (attr->controller_id == controller_id)
1934711890bcSjc 			break;
1935711890bcSjc 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) != OBJ_NONE);
1936711890bcSjc 
1937711890bcSjc 	return (obj_id);
1938711890bcSjc }
1939711890bcSjc 
1940711890bcSjc static raid_obj_id_t
obj_locate_array(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t array_id)1941711890bcSjc obj_locate_array(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1942*8bc1b774SToomas Soome     uint32_t array_id)
1943711890bcSjc {
1944711890bcSjc 	raid_obj_id_t obj_id;
1945711890bcSjc 
1946711890bcSjc 	obj_id = obj_locate_controller(raid_tab, controller_id);
1947711890bcSjc 	if (obj_id < OBJ_NONE)
1948711890bcSjc 		return (obj_id);
1949711890bcSjc 
1950711890bcSjc 	obj_id = obj_locate_array_recur(raid_tab, obj_id, array_id);
1951711890bcSjc 
1952711890bcSjc 	return (obj_id);
1953711890bcSjc }
1954711890bcSjc 
1955711890bcSjc static raid_obj_id_t
obj_locate_array_recur(raid_obj_tab_t * raid_tab,raid_obj_id_t container_obj_id,uint32_t array_id)1956711890bcSjc obj_locate_array_recur(raid_obj_tab_t *raid_tab,
1957*8bc1b774SToomas Soome     raid_obj_id_t container_obj_id, uint32_t array_id)
1958711890bcSjc {
1959711890bcSjc 	raid_obj_id_t obj_id, ret;
1960711890bcSjc 	array_attr_t *attr;
1961711890bcSjc 
1962711890bcSjc 	obj_id = obj_get_comp(raid_tab, container_obj_id, OBJ_TYPE_ARRAY);
1963711890bcSjc 	if (obj_id <= OBJ_NONE)
1964711890bcSjc 		return (obj_id);
1965711890bcSjc 
1966711890bcSjc 	do {
1967711890bcSjc 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1968711890bcSjc 		if (attr == NULL)
1969711890bcSjc 			return (ERR_DEVICE_INVALID);
1970711890bcSjc 
1971711890bcSjc 		if (attr->array_id == array_id)
1972711890bcSjc 			break;
1973711890bcSjc 
1974711890bcSjc 		ret = obj_locate_array_recur(raid_tab, obj_id, array_id);
1975711890bcSjc 		if (ret != OBJ_NONE)
1976711890bcSjc 			return (ret);
1977711890bcSjc 
1978711890bcSjc 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
1979711890bcSjc 
1980711890bcSjc 	return (obj_id);
1981711890bcSjc }
1982711890bcSjc 
1983711890bcSjc static raid_obj_id_t
obj_locate_hsp(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t disk_id,uint32_t array_id)1984711890bcSjc obj_locate_hsp(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1985*8bc1b774SToomas Soome     uint32_t disk_id, uint32_t array_id)
1986711890bcSjc {
1987711890bcSjc 	raid_obj_id_t obj_id;
1988711890bcSjc 	hsp_attr_t *hsp_attr;
1989711890bcSjc 
1990711890bcSjc 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
1991711890bcSjc 	if (obj_id <= OBJ_NONE)
1992711890bcSjc 		return (obj_id);
1993711890bcSjc 
1994711890bcSjc 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_HSP);
1995711890bcSjc 	if (obj_id <= OBJ_NONE)
1996711890bcSjc 		return (obj_id);
1997711890bcSjc 
1998711890bcSjc 	do {
1999711890bcSjc 		(void) obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
2000711890bcSjc 		if (hsp_attr->associated_id == array_id)
2001711890bcSjc 			break;
2002711890bcSjc 
2003711890bcSjc 		obj_id = obj_get_sibling(raid_tab, obj_id);
2004711890bcSjc 		if (obj_id < OBJ_NONE)
2005711890bcSjc 			return (obj_id);
2006711890bcSjc 	} while (obj_id > OBJ_NONE);
2007711890bcSjc 
2008711890bcSjc 	return (obj_id);
2009711890bcSjc }
2010711890bcSjc 
2011711890bcSjc static raid_obj_id_t
obj_locate_disk(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t disk_id)2012711890bcSjc obj_locate_disk(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2013*8bc1b774SToomas Soome     uint32_t disk_id)
2014711890bcSjc {
2015711890bcSjc 	raid_obj_id_t obj_id;
2016711890bcSjc 	disk_attr_t *attr;
2017711890bcSjc 
2018711890bcSjc 	obj_id = obj_locate_controller(raid_tab, controller_id);
2019711890bcSjc 	if (obj_id <= OBJ_NONE)
2020711890bcSjc 		return (obj_id);
2021711890bcSjc 
2022711890bcSjc 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2023711890bcSjc 	if (obj_id <= OBJ_NONE)
2024711890bcSjc 		return (obj_id);
2025711890bcSjc 
2026711890bcSjc 	do {
2027711890bcSjc 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2028711890bcSjc 		if (attr == NULL)
2029711890bcSjc 			return (ERR_DEVICE_INVALID);
2030711890bcSjc 
2031711890bcSjc 		if (attr->disk_id == disk_id)
2032711890bcSjc 			break;
2033711890bcSjc 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2034711890bcSjc 
2035711890bcSjc 	return (obj_id);
2036711890bcSjc }
2037711890bcSjc 
2038711890bcSjc static raid_obj_id_t
obj_locate_arraypart(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t array_id,uint32_t disk_id)2039711890bcSjc obj_locate_arraypart(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2040*8bc1b774SToomas Soome     uint32_t array_id, uint32_t disk_id)
2041711890bcSjc {
2042711890bcSjc 	raid_obj_id_t obj_id;
2043711890bcSjc 
2044711890bcSjc 	arraypart_attr_t *attr;
2045711890bcSjc 
2046711890bcSjc 	obj_id = obj_locate_array(raid_tab, controller_id, array_id);
2047711890bcSjc 	if (obj_id <= OBJ_NONE)
2048711890bcSjc 		return (obj_id);
2049711890bcSjc 
2050711890bcSjc 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY_PART);
2051711890bcSjc 	if (obj_id <= OBJ_NONE)
2052711890bcSjc 		return (obj_id);
2053711890bcSjc 
2054711890bcSjc 	do {
2055711890bcSjc 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2056711890bcSjc 		if (attr == NULL)
2057711890bcSjc 			return (ERR_DEVICE_INVALID);
2058711890bcSjc 
2059711890bcSjc 		if (attr->disk_id == disk_id)
2060711890bcSjc 			break;
2061711890bcSjc 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) >
2062700682b8Syw 	    OBJ_NONE);
2063711890bcSjc 
2064711890bcSjc 	return (obj_id);
2065711890bcSjc }
2066711890bcSjc 
2067711890bcSjc static raid_obj_id_t
obj_locate_diskseg(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t disk_id,uint32_t seq_no)2068711890bcSjc obj_locate_diskseg(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2069*8bc1b774SToomas Soome     uint32_t disk_id, uint32_t seq_no)
2070711890bcSjc {
2071711890bcSjc 	raid_obj_id_t obj_id;
2072711890bcSjc 	diskseg_attr_t *attr;
2073711890bcSjc 
2074711890bcSjc 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2075711890bcSjc 	if (obj_id <= OBJ_NONE)
2076711890bcSjc 		return (obj_id);
2077711890bcSjc 
2078711890bcSjc 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK_SEG);
2079711890bcSjc 	if (obj_id <= OBJ_NONE)
2080711890bcSjc 		return (obj_id);
2081711890bcSjc 
2082711890bcSjc 	do {
2083711890bcSjc 		attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2084711890bcSjc 		if (attr == NULL)
2085711890bcSjc 			return (ERR_DEVICE_INVALID);
2086711890bcSjc 
2087711890bcSjc 		if (attr->seq_no == seq_no)
2088711890bcSjc 			break;
2089711890bcSjc 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2090711890bcSjc 
2091711890bcSjc 	return (obj_id);
2092711890bcSjc }
2093711890bcSjc 
2094711890bcSjc static raid_obj_id_t
obj_locate_task(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t task_id)2095711890bcSjc obj_locate_task(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2096*8bc1b774SToomas Soome     uint32_t task_id)
2097711890bcSjc {
2098711890bcSjc 	raid_obj_id_t obj_id, obj_id2, task_obj_id;
2099711890bcSjc 	task_attr_t *attr;
2100711890bcSjc 
2101711890bcSjc 	obj_id = obj_locate_controller(raid_tab, controller_id);
2102711890bcSjc 	if (obj_id <= OBJ_NONE)
2103711890bcSjc 		return (obj_id);
2104711890bcSjc 
2105711890bcSjc 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2106711890bcSjc 	if (obj_id < OBJ_NONE)
2107711890bcSjc 		return (obj_id);
2108711890bcSjc 
2109711890bcSjc 	do {
2110711890bcSjc 		obj_id2 = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2111711890bcSjc 		while (obj_id2 != OBJ_NONE) {
2112711890bcSjc 			task_obj_id = obj_get_comp(raid_tab, obj_id2,
2113700682b8Syw 			    OBJ_TYPE_TASK);
2114711890bcSjc 
2115711890bcSjc 			if (task_obj_id < OBJ_NONE)
2116711890bcSjc 				return (task_obj_id);
2117711890bcSjc 
2118711890bcSjc 			if (task_obj_id == OBJ_NONE) {
2119711890bcSjc 				obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2120711890bcSjc 				continue;
2121711890bcSjc 			}
2122711890bcSjc 
2123711890bcSjc 			attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2124711890bcSjc 			if (attr == NULL)
2125711890bcSjc 				return (ERR_DEVICE_INVALID);
2126711890bcSjc 
2127711890bcSjc 			if (attr->task_id == task_id)
2128711890bcSjc 				return (task_obj_id);
2129711890bcSjc 
2130711890bcSjc 			obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2131711890bcSjc 		}
2132711890bcSjc 
2133711890bcSjc 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2134711890bcSjc 		if (task_obj_id < OBJ_NONE)
2135711890bcSjc 			return (task_obj_id);
2136711890bcSjc 
2137711890bcSjc 		if (task_obj_id == OBJ_NONE)
2138711890bcSjc 			continue;
2139711890bcSjc 
2140711890bcSjc 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2141711890bcSjc 		if (attr == NULL)
2142711890bcSjc 			return (ERR_DEVICE_INVALID);
2143711890bcSjc 
2144711890bcSjc 		if (attr->task_id == task_id)
2145711890bcSjc 			return (task_obj_id);
2146711890bcSjc 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2147711890bcSjc 
2148711890bcSjc 	if (obj_id < OBJ_NONE)
2149711890bcSjc 		return (obj_id);
2150711890bcSjc 
2151711890bcSjc 	obj_id = obj_locate_controller(raid_tab, controller_id);
2152711890bcSjc 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2153711890bcSjc 	if (obj_id < OBJ_NONE)
2154711890bcSjc 		return (obj_id);
2155711890bcSjc 
2156711890bcSjc 	do {
2157711890bcSjc 		task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2158711890bcSjc 		if (task_obj_id < OBJ_NONE)
2159711890bcSjc 			return (task_obj_id);
2160711890bcSjc 
2161711890bcSjc 		if (task_obj_id == OBJ_NONE)
2162711890bcSjc 			continue;
2163711890bcSjc 
2164711890bcSjc 		attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2165711890bcSjc 		if (attr == NULL)
2166711890bcSjc 			return (ERR_DEVICE_INVALID);
2167711890bcSjc 
2168711890bcSjc 		if (attr->task_id == task_id)
2169711890bcSjc 			return (task_obj_id);
2170711890bcSjc 	} while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2171711890bcSjc 
2172711890bcSjc 	return (obj_id);
2173b449fa8aSyw }
2174b449fa8aSyw 
2175b449fa8aSyw static raid_obj_id_t
obj_locate_prop(raid_obj_tab_t * raid_tab,uint32_t controller_id,uint32_t disk_id,uint32_t prop_id)2176b449fa8aSyw obj_locate_prop(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2177*8bc1b774SToomas Soome     uint32_t disk_id, uint32_t prop_id)
2178b449fa8aSyw {
2179b449fa8aSyw 	raid_obj_id_t obj_id;
2180b449fa8aSyw 	property_attr_t *prop_attr;
2181b449fa8aSyw 
2182b449fa8aSyw 	obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2183b449fa8aSyw 	if (obj_id < OBJ_NONE)
2184b449fa8aSyw 		return (obj_id);
2185b449fa8aSyw 
2186b449fa8aSyw 	obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_PROP);
2187b449fa8aSyw 	if (obj_id <= OBJ_NONE)
2188b449fa8aSyw 		return (obj_id);
2189b449fa8aSyw 
2190b449fa8aSyw 	do {
2191b449fa8aSyw 		(void) obj_get_attr(raid_tab, obj_id, (void **)(&prop_attr));
2192b449fa8aSyw 		if (prop_attr->prop_id == prop_id)
2193b449fa8aSyw 			break;
2194711890bcSjc 
2195b449fa8aSyw 		obj_id = obj_get_sibling(raid_tab, obj_id);
2196b449fa8aSyw 		if (obj_id < OBJ_NONE)
2197b449fa8aSyw 			return (obj_id);
2198b449fa8aSyw 	} while (obj_id > OBJ_NONE);
2199b449fa8aSyw 
2200b449fa8aSyw 	return (obj_id);
2201711890bcSjc }
2202711890bcSjc 
2203711890bcSjc static raid_obj_id_t
obj_get_controller(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)2204711890bcSjc obj_get_controller(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2205711890bcSjc {
2206711890bcSjc 	raid_obj_id_t id = obj_id;
2207711890bcSjc 
2208711890bcSjc 	while (raid_obj_get_type(raid_tab, id) != OBJ_TYPE_CONTROLLER) {
2209711890bcSjc 		id = raid_obj_get_container(raid_tab, id);
2210711890bcSjc 		if ((id == OBJ_SYSTEM) || (id < OBJ_NONE))
2211711890bcSjc 			return (ERR_DEVICE_INVALID);
2212711890bcSjc 	}
2213711890bcSjc 
2214711890bcSjc 	return (id);
2215711890bcSjc }
2216711890bcSjc 
2217711890bcSjc /*
2218711890bcSjc  * Raid object operation routines
2219711890bcSjc  */
2220711890bcSjc static int
obj_sys_compnum(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t comp_type)2221711890bcSjc obj_sys_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2222*8bc1b774SToomas Soome     raid_obj_type_id_t comp_type)
2223711890bcSjc {
2224711890bcSjc 	DIR *dir;
2225711890bcSjc 	struct dirent *dp;
2226711890bcSjc 	int num = 0;
2227711890bcSjc 
2228711890bcSjc 	if ((raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM))
2229711890bcSjc 		return (ERR_DEVICE_TYPE);
2230711890bcSjc 
2231711890bcSjc 	if (comp_type != OBJ_TYPE_CONTROLLER)
2232711890bcSjc 		return (0);
2233711890bcSjc 
2234711890bcSjc 	if ((dir = opendir(CFGDIR)) == NULL)
2235711890bcSjc 		return (ERR_DRIVER_NOT_FOUND);
2236711890bcSjc 
2237711890bcSjc 	while ((dp = readdir(dir)) != NULL) {
2238711890bcSjc 		uint32_t controller_id;
2239711890bcSjc 		char path[MAX_PATH_LEN];
2240711890bcSjc 
2241711890bcSjc 		if (strcmp(dp->d_name, ".") == 0 ||
2242700682b8Syw 		    strcmp(dp->d_name, "..") == 0)
2243711890bcSjc 			continue;
2244711890bcSjc 
2245711890bcSjc 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2246711890bcSjc 			continue;
2247711890bcSjc 
2248711890bcSjc 		if (controller_id_to_path(controller_id, path) == SUCCESS)
2249711890bcSjc 			++ num;
2250711890bcSjc 	}
2251711890bcSjc 
2252711890bcSjc 	(void) closedir(dir);
2253711890bcSjc 	return (num);
2254711890bcSjc }
2255711890bcSjc 
2256711890bcSjc static int
obj_sys_complist(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int num,raid_obj_id_t * comp_list,raid_obj_type_id_t comp_type)2257711890bcSjc obj_sys_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2258*8bc1b774SToomas Soome     int num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2259711890bcSjc {
2260711890bcSjc 	DIR *dir;
2261711890bcSjc 	struct dirent *dp;
2262711890bcSjc 	controller_attr_t *attr;
2263711890bcSjc 	uint32_t controller_id;
2264711890bcSjc 	uint32_t *tmplist;
2265711890bcSjc 	char path[MAX_PATH_LEN];
2266711890bcSjc 	int i = 0;
2267711890bcSjc 
2268711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM)
2269711890bcSjc 		return (ERR_DEVICE_TYPE);
2270711890bcSjc 	if ((num <= 0) || (comp_list == NULL))
2271711890bcSjc 		return (ERR_OP_ILLEGAL);
2272711890bcSjc 
2273711890bcSjc 	if (comp_type != OBJ_TYPE_CONTROLLER)
2274711890bcSjc 		return (0);
2275711890bcSjc 
2276711890bcSjc 	if ((dir = opendir(CFGDIR)) == NULL)
2277711890bcSjc 		return (ERR_DRIVER_NOT_FOUND);
2278711890bcSjc 	tmplist = calloc(num, sizeof (uint32_t));
2279711890bcSjc 	if (tmplist == NULL) {
2280711890bcSjc 		return (ERR_NOMEM);
2281711890bcSjc 	}
2282711890bcSjc 	while ((dp = readdir(dir)) != NULL) {
2283711890bcSjc 		if (strcmp(dp->d_name, ".") == 0 ||
2284700682b8Syw 		    strcmp(dp->d_name, "..") == 0)
2285711890bcSjc 			continue;
2286711890bcSjc 
2287711890bcSjc 		if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2288711890bcSjc 			continue;
2289711890bcSjc 
2290711890bcSjc 		if (controller_id_to_path(controller_id, path) == SUCCESS) {
2291711890bcSjc 			tmplist[i] = controller_id;
2292711890bcSjc 			++ i;
2293711890bcSjc 		}
2294711890bcSjc 	}
2295711890bcSjc 	qsort((void *)tmplist, num, sizeof (uint32_t), intcompare);
2296711890bcSjc 	for (i = 0; i < num; i++) {
2297711890bcSjc 		attr = raid_obj_get_data_ptr(raid_tab,
2298700682b8Syw 		    *(comp_list + i));
2299711890bcSjc 
2300711890bcSjc 		if (attr == NULL) {
2301711890bcSjc 			free(tmplist);
2302711890bcSjc 			return (ERR_DEVICE_INVALID);
2303711890bcSjc 		}
2304711890bcSjc 
2305711890bcSjc 		attr->controller_id = tmplist[i];
2306711890bcSjc 	}
2307711890bcSjc 	free(tmplist);
2308711890bcSjc 	(void) closedir(dir);
2309711890bcSjc 	return (SUCCESS);
2310711890bcSjc }
2311711890bcSjc 
2312711890bcSjc static int
obj_controller_compnum(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t comp_type)2313711890bcSjc obj_controller_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2314*8bc1b774SToomas Soome     raid_obj_type_id_t comp_type)
2315711890bcSjc {
2316711890bcSjc 	raid_lib_t *raid_lib;
2317711890bcSjc 	int ret = SUCCESS, fd;
2318711890bcSjc 	controller_attr_t *ctl_attrp;
2319711890bcSjc 
2320711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2321711890bcSjc 		return (ERR_DEVICE_TYPE);
2322711890bcSjc 
2323711890bcSjc 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2324711890bcSjc 		return (0);
2325711890bcSjc 
2326711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2327711890bcSjc 	fd = raid_obj_get_fd(raid_tab, obj_id);
2328711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2329711890bcSjc 	if ((raid_lib == NULL) || (ctl_attrp == NULL) || (fd == 0))
2330711890bcSjc 		return (ERR_DRIVER_CLOSED);
2331711890bcSjc 
2332711890bcSjc 	ret = raid_lib->compnum(ctl_attrp->controller_id, 0,
2333700682b8Syw 	    OBJ_TYPE_CONTROLLER, comp_type);
2334711890bcSjc 
2335711890bcSjc 	return (ret);
2336711890bcSjc }
2337711890bcSjc 
2338711890bcSjc static int
obj_controller_complist(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int comp_num,raid_obj_id_t * comp_list,raid_obj_type_id_t comp_type)2339711890bcSjc obj_controller_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2340*8bc1b774SToomas Soome     int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2341711890bcSjc {
2342711890bcSjc 	raid_lib_t *raid_lib;
2343711890bcSjc 	controller_attr_t *ctl_attrp;
2344711890bcSjc 	int ret, i, fd;
2345711890bcSjc 	uint32_t *ids;
2346711890bcSjc 
2347711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2348711890bcSjc 		return (ERR_DEVICE_TYPE);
2349711890bcSjc 
2350711890bcSjc 	if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2351711890bcSjc 		return (0);
2352711890bcSjc 
2353711890bcSjc 	if ((comp_num <= 0) || (comp_list == NULL))
2354711890bcSjc 		return (ERR_OP_ILLEGAL);
2355711890bcSjc 
2356711890bcSjc 	for (i = 0; i < comp_num; ++i)
2357711890bcSjc 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2358700682b8Syw 		    comp_type)
2359711890bcSjc 			return (ERR_DEVICE_TYPE);
2360711890bcSjc 
2361711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2362711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2363711890bcSjc 	fd = raid_obj_get_fd(raid_tab, obj_id);
2364711890bcSjc 	if ((raid_lib == NULL) || (ctl_attrp == NULL)|| (fd == 0))
2365711890bcSjc 		return (ERR_DRIVER_CLOSED);
2366711890bcSjc 
2367711890bcSjc 	ids = malloc(comp_num * sizeof (uint32_t));
2368711890bcSjc 	if (ids == NULL)
2369711890bcSjc 		return (ERR_NOMEM);
2370711890bcSjc 
2371711890bcSjc 	ret = raid_lib->complist(ctl_attrp->controller_id, 0,
2372700682b8Syw 	    OBJ_TYPE_CONTROLLER, comp_type, comp_num, ids);
2373711890bcSjc 	if (ret < SUCCESS) {
2374711890bcSjc 		free(ids);
2375711890bcSjc 		return (ret);
2376711890bcSjc 	}
2377711890bcSjc 	qsort((void *)ids, comp_num, sizeof (uint32_t), intcompare);
2378711890bcSjc 	for (i = 0; i < comp_num; ++ i) {
2379711890bcSjc 		array_attr_t *array_attr;
2380711890bcSjc 		disk_attr_t *disk_attr;
2381711890bcSjc 		void *attr_buf;
2382711890bcSjc 
2383711890bcSjc 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2384711890bcSjc 		if (attr_buf == NULL) {
2385711890bcSjc 			free(ids);
2386711890bcSjc 			return (ERR_DEVICE_INVALID);
2387711890bcSjc 		}
2388711890bcSjc 
2389711890bcSjc 		switch (comp_type) {
2390711890bcSjc 		case OBJ_TYPE_ARRAY:
2391711890bcSjc 			array_attr = attr_buf;
2392711890bcSjc 			array_attr->array_id = *(ids + i);
2393711890bcSjc 			break;
2394711890bcSjc 		case OBJ_TYPE_DISK:
2395711890bcSjc 			disk_attr = attr_buf;
2396711890bcSjc 			disk_attr->disk_id = *(ids + i);
2397711890bcSjc 			break;
2398711890bcSjc 		default:
2399711890bcSjc 			free(ids);
2400711890bcSjc 			return (ERR_DEVICE_INVALID);
2401711890bcSjc 		}
2402711890bcSjc 	}
2403711890bcSjc 
2404711890bcSjc 	free(ids);
2405711890bcSjc 	return (SUCCESS);
2406711890bcSjc }
2407711890bcSjc 
2408711890bcSjc static int
obj_controller_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)2409711890bcSjc obj_controller_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2410711890bcSjc {
2411711890bcSjc 	controller_attr_t *attr;
2412711890bcSjc 	raid_lib_t *raid_lib;
2413711890bcSjc 	int ret = SUCCESS, fd;
2414711890bcSjc 
2415711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2416711890bcSjc 		return (ERR_DEVICE_TYPE);
2417711890bcSjc 
2418711890bcSjc 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2419711890bcSjc 		return (SUCCESS);
2420711890bcSjc 
2421711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2422711890bcSjc 	if (attr == NULL)
2423711890bcSjc 		return (ERR_DEVICE_INVALID);
2424711890bcSjc 
2425711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2426711890bcSjc 	fd = raid_obj_get_fd(raid_tab, obj_id);
2427711890bcSjc 
2428711890bcSjc 	/*
2429711890bcSjc 	 * For a controller, even it's not opened, we can still
2430711890bcSjc 	 * get the driver name
2431711890bcSjc 	 */
2432711890bcSjc 
2433711890bcSjc 	if (fd == 0)
2434711890bcSjc 		return (SUCCESS);
2435711890bcSjc 
2436711890bcSjc 	if (raid_lib == NULL) {
2437711890bcSjc 		return (SUCCESS);
2438711890bcSjc 	}
2439711890bcSjc 
2440711890bcSjc 	ret = raid_lib->get_attr(attr->controller_id, OBJ_ATTR_NONE,
2441700682b8Syw 	    OBJ_ATTR_NONE, OBJ_TYPE_CONTROLLER, attr);
2442711890bcSjc 	if (ret < SUCCESS)
2443711890bcSjc 		return (ret);
2444711890bcSjc 
2445711890bcSjc 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2446711890bcSjc 
2447711890bcSjc 	return (ret);
2448711890bcSjc }
2449711890bcSjc 
2450711890bcSjc static int
obj_controller_act(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,uint32_t sub_cmd,void * prop_list,char ** plugin_err_str)2451711890bcSjc obj_controller_act(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2452*8bc1b774SToomas Soome     uint32_t sub_cmd, void *prop_list, char **plugin_err_str)
2453711890bcSjc {
2454711890bcSjc 	controller_attr_t *attr;
2455711890bcSjc 	raid_lib_t *raid_lib;
2456711890bcSjc 	int ret, fd;
2457711890bcSjc 
2458711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2459711890bcSjc 		return (ERR_DEVICE_TYPE);
2460711890bcSjc 
2461711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2462711890bcSjc 
2463711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2464711890bcSjc 	fd = raid_obj_get_fd(raid_tab, obj_id);
2465711890bcSjc 
2466711890bcSjc 	switch (sub_cmd) {
2467711890bcSjc 	case ACT_CONTROLLER_OPEN:
2468711890bcSjc 		/* Check if already opened */
2469711890bcSjc 
2470711890bcSjc 		if (fd > 0)
2471711890bcSjc 			return (SUCCESS);
2472711890bcSjc 
2473711890bcSjc 		/* Check if plugin is already attached */
2474711890bcSjc 		if (raid_lib == NULL) {
2475711890bcSjc 			raid_lib = raid_find_lib(raid_tab, obj_id);
2476711890bcSjc 			if (raid_lib == NULL)
2477711890bcSjc 				return (ERR_DRIVER_NOT_FOUND);
2478711890bcSjc 		}
2479711890bcSjc 
2480711890bcSjc 		ret = raid_lib->open_controller(attr->controller_id,
2481700682b8Syw 		    plugin_err_str);
2482711890bcSjc 		if (ret == SUCCESS) {
2483711890bcSjc 			(void) raid_obj_set_lib(raid_tab, obj_id, raid_lib);
2484711890bcSjc 			(void) raid_obj_set_fd(raid_tab, obj_id, 1);
2485711890bcSjc 		}
2486711890bcSjc 		break;
2487711890bcSjc 	case ACT_CONTROLLER_CLOSE:
2488711890bcSjc 
2489711890bcSjc 		if (fd <= 0)
2490711890bcSjc 			return (SUCCESS);
2491711890bcSjc 
2492711890bcSjc 		if (raid_lib == NULL) {
2493711890bcSjc 			return (SUCCESS);
2494711890bcSjc 		}
2495711890bcSjc 		ret = raid_lib->close_controller(attr->controller_id,
2496700682b8Syw 		    plugin_err_str);
2497711890bcSjc 		if (ret == SUCCESS) {
2498711890bcSjc 			(void) raid_obj_set_fd(raid_tab, obj_id, 0);
2499711890bcSjc 			(void) raid_obj_set_lib(raid_tab, obj_id, NULL);
2500711890bcSjc 			raid_handle_delete_controller_comp(attr->controller_id);
2501711890bcSjc 		}
2502711890bcSjc 		break;
2503711890bcSjc 	case ACT_CONTROLLER_FLASH_FW:
2504711890bcSjc 		{
2505711890bcSjc 			char		*filebuf;
2506711890bcSjc 			int		image_fd;
2507711890bcSjc 			uint32_t	size;
2508711890bcSjc 			struct stat	statbuf;
2509711890bcSjc 
2510711890bcSjc 			if (prop_list == NULL)
2511711890bcSjc 				return (ERR_OP_ILLEGAL);
2512711890bcSjc 
2513711890bcSjc 			/* Open firmware image file */
2514711890bcSjc 			image_fd = open((const char *)prop_list,
2515700682b8Syw 			    O_RDONLY | O_NDELAY);
2516711890bcSjc 			if (image_fd == -1)
2517711890bcSjc 				return (ERR_OP_FAILED);
2518711890bcSjc 
2519711890bcSjc 			if (fstat(image_fd, &statbuf) != 0) {
2520711890bcSjc 				(void) close(image_fd);
2521711890bcSjc 				return (ERR_OP_FAILED);
2522711890bcSjc 			}
2523711890bcSjc 
2524711890bcSjc 			filebuf = malloc(statbuf.st_size);
2525711890bcSjc 			if (filebuf == NULL) {
2526711890bcSjc 				(void) close(image_fd);
2527711890bcSjc 				return (ERR_NOMEM);
2528711890bcSjc 			}
2529711890bcSjc 
2530711890bcSjc 			size = read(image_fd, filebuf, statbuf.st_size);
2531711890bcSjc 			if (size != statbuf.st_size) {
2532711890bcSjc 				(void) close(image_fd);
2533711890bcSjc 				free(filebuf);
2534711890bcSjc 				return (ERR_OP_FAILED);
2535711890bcSjc 			}
2536711890bcSjc 
2537711890bcSjc 			if (fd <= 0) {
2538711890bcSjc 				(void) close(image_fd);
2539711890bcSjc 				free(filebuf);
2540711890bcSjc 				return (ERR_DRIVER_CLOSED);
2541711890bcSjc 			}
2542711890bcSjc 
2543711890bcSjc 			if (raid_lib == NULL) {
2544711890bcSjc 				(void) close(image_fd);
2545711890bcSjc 				free(filebuf);
2546711890bcSjc 				return (ERR_DRIVER_CLOSED);
2547711890bcSjc 			}
2548711890bcSjc 			if (raid_lib->flash_fw == NULL) {
2549711890bcSjc 				(void) close(image_fd);
2550711890bcSjc 				free(filebuf);
2551711890bcSjc 				return (ERR_OP_NO_IMPL);
2552711890bcSjc 			}
2553711890bcSjc 
2554711890bcSjc 			ret = raid_lib->flash_fw(attr->controller_id,
2555700682b8Syw 			    filebuf, size, plugin_err_str);
2556711890bcSjc 		}
2557711890bcSjc 		break;
2558711890bcSjc 	default:
2559711890bcSjc 		return (ERR_OP_ILLEGAL);
2560711890bcSjc 	}
2561711890bcSjc 
2562711890bcSjc 	return (ret);
2563711890bcSjc }
2564711890bcSjc 
2565711890bcSjc static int
obj_array_compnum(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t comp_type)2566711890bcSjc obj_array_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2567*8bc1b774SToomas Soome     raid_obj_type_id_t comp_type)
2568711890bcSjc {
2569711890bcSjc 	array_attr_t *attr;
2570711890bcSjc 	controller_attr_t *ctl_attrp;
2571711890bcSjc 	raid_obj_id_t controller_obj_id;
2572711890bcSjc 	raid_lib_t *raid_lib;
2573711890bcSjc 	int ret = SUCCESS, fd;
2574711890bcSjc 
2575711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2576711890bcSjc 		return (ERR_DEVICE_TYPE);
2577711890bcSjc 
2578711890bcSjc 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
2579700682b8Syw 	    comp_type != OBJ_TYPE_ARRAY &&
2580700682b8Syw 	    comp_type != OBJ_TYPE_TASK)
2581711890bcSjc 		return (0);
2582711890bcSjc 
2583711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2584711890bcSjc 	if (attr == NULL)
2585711890bcSjc 		return (ERR_DEVICE_INVALID);
2586711890bcSjc 
2587711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2588711890bcSjc 	if (controller_obj_id < OBJ_NONE)
2589711890bcSjc 		return (ERR_DEVICE_INVALID);
2590711890bcSjc 
2591711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2592711890bcSjc 	if (ctl_attrp == NULL) {
2593711890bcSjc 		return (ERR_DEVICE_INVALID);
2594711890bcSjc 	}
2595711890bcSjc 
2596711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2597711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2598711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
2599711890bcSjc 		return (ERR_DRIVER_CLOSED);
2600711890bcSjc 
2601711890bcSjc 	ret = raid_lib->compnum(ctl_attrp->controller_id, attr->array_id,
2602700682b8Syw 	    OBJ_TYPE_ARRAY, comp_type);
2603711890bcSjc 
2604711890bcSjc 	return (ret);
2605711890bcSjc }
2606711890bcSjc 
2607711890bcSjc static int
obj_array_complist(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int comp_num,raid_obj_id_t * comp_list,raid_obj_type_id_t comp_type)2608711890bcSjc obj_array_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2609*8bc1b774SToomas Soome     int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2610711890bcSjc {
2611711890bcSjc 	array_attr_t *attr;
2612711890bcSjc 	controller_attr_t *ctl_attrp;
2613711890bcSjc 	raid_obj_id_t controller_obj_id;
2614711890bcSjc 	raid_lib_t *raid_lib;
2615711890bcSjc 	int ret, i, fd;
2616711890bcSjc 	uint32_t *ids;
2617711890bcSjc 
2618711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2619711890bcSjc 		return (ERR_DEVICE_TYPE);
2620711890bcSjc 
2621711890bcSjc 	if (comp_type != OBJ_TYPE_ARRAY_PART &&
2622700682b8Syw 	    comp_type != OBJ_TYPE_ARRAY &&
2623700682b8Syw 	    comp_type != OBJ_TYPE_TASK)
2624711890bcSjc 		return (0);
2625711890bcSjc 
2626711890bcSjc 	if (comp_num <= 0 || comp_list == NULL)
2627711890bcSjc 		return (ERR_OP_ILLEGAL);
2628711890bcSjc 
2629711890bcSjc 	for (i = 0; i < comp_num; ++i)
2630711890bcSjc 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2631700682b8Syw 		    comp_type)
2632711890bcSjc 			return (ERR_DEVICE_TYPE);
2633711890bcSjc 
2634711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2635711890bcSjc 	if (attr == NULL)
2636711890bcSjc 		return (ERR_DEVICE_INVALID);
2637711890bcSjc 
2638711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2639711890bcSjc 	if (controller_obj_id < OBJ_NONE)
2640711890bcSjc 		return (ERR_DEVICE_INVALID);
2641711890bcSjc 
2642711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2643711890bcSjc 	if (ctl_attrp == NULL) {
2644711890bcSjc 		return (ERR_DEVICE_INVALID);
2645711890bcSjc 	}
2646711890bcSjc 
2647711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2648711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2649711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
2650711890bcSjc 		return (ERR_DRIVER_CLOSED);
2651711890bcSjc 
2652711890bcSjc 	ids = malloc(comp_num * sizeof (uint32_t));
2653711890bcSjc 	if (ids == NULL)
2654711890bcSjc 		return (ERR_NOMEM);
2655711890bcSjc 
2656711890bcSjc 	ret = raid_lib->complist(ctl_attrp->controller_id,
2657700682b8Syw 	    attr->array_id, OBJ_TYPE_ARRAY, comp_type, comp_num, ids);
2658711890bcSjc 
2659711890bcSjc 	if (ret < SUCCESS) {
2660711890bcSjc 		free(ids);
2661711890bcSjc 		return (ret);
2662711890bcSjc 	}
2663711890bcSjc 
2664711890bcSjc 	for (i = 0; i < comp_num; ++ i) {
2665711890bcSjc 		array_attr_t *array_attr;
2666711890bcSjc 		arraypart_attr_t *arraypart_attr;
2667711890bcSjc 		task_attr_t *task_attr;
2668711890bcSjc 		void *attr_buf;
2669711890bcSjc 
2670711890bcSjc 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2671711890bcSjc 		if (attr_buf == NULL) {
2672711890bcSjc 			free(ids);
2673711890bcSjc 			return (ERR_DEVICE_INVALID);
2674711890bcSjc 		}
2675711890bcSjc 
2676711890bcSjc 		switch (comp_type) {
2677711890bcSjc 		case OBJ_TYPE_ARRAY:
2678711890bcSjc 			array_attr = attr_buf;
2679711890bcSjc 			array_attr->array_id = *(ids + i);
2680711890bcSjc 			break;
2681711890bcSjc 		case OBJ_TYPE_ARRAY_PART:
2682711890bcSjc 			arraypart_attr = attr_buf;
2683711890bcSjc 			arraypart_attr->disk_id = *(ids + i);
2684711890bcSjc 			break;
2685711890bcSjc 		case OBJ_TYPE_TASK:
2686711890bcSjc 			task_attr = attr_buf;
2687711890bcSjc 			task_attr->task_id = *(ids + i);
2688711890bcSjc 			break;
2689711890bcSjc 		default:
2690711890bcSjc 			free(ids);
2691711890bcSjc 			return (ERR_DEVICE_INVALID);
2692711890bcSjc 		}
2693711890bcSjc 	}
2694711890bcSjc 
2695711890bcSjc 
2696711890bcSjc 	free(ids);
2697711890bcSjc 	return (ret);
2698711890bcSjc }
2699711890bcSjc 
2700711890bcSjc static int
obj_array_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)2701711890bcSjc obj_array_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2702711890bcSjc {
2703711890bcSjc 	array_attr_t *attr;
2704711890bcSjc 	controller_attr_t *ctl_attrp;
2705711890bcSjc 	raid_lib_t *raid_lib;
2706711890bcSjc 	int ret = SUCCESS, fd;
2707711890bcSjc 	raid_obj_id_t controller_obj_id;
2708711890bcSjc 
2709711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2710711890bcSjc 		return (ERR_DEVICE_TYPE);
2711711890bcSjc 
2712711890bcSjc 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2713711890bcSjc 		return (SUCCESS);
2714711890bcSjc 
2715711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2716711890bcSjc 	if (attr == NULL)
2717711890bcSjc 		return (ERR_DEVICE_INVALID);
2718711890bcSjc 
2719711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2720711890bcSjc 	if (controller_obj_id < OBJ_NONE)
2721711890bcSjc 		return (ERR_DEVICE_INVALID);
2722711890bcSjc 
2723711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2724711890bcSjc 	if (ctl_attrp == NULL) {
2725711890bcSjc 		return (ERR_DEVICE_INVALID);
2726711890bcSjc 	}
2727711890bcSjc 
2728711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2729711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2730711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
2731711890bcSjc 		return (ERR_DRIVER_CLOSED);
2732711890bcSjc 
2733711890bcSjc 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
2734700682b8Syw 	    attr->array_id, 0, OBJ_TYPE_ARRAY, attr);
2735711890bcSjc 
2736711890bcSjc 	if (ret < SUCCESS)
2737711890bcSjc 		return (ret);
2738711890bcSjc 
2739711890bcSjc 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2740711890bcSjc 
2741711890bcSjc 	return (ret);
2742711890bcSjc }
2743711890bcSjc 
2744711890bcSjc static int
obj_array_set_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,uint32_t sub_cmd,uint32_t * value,char ** plugin_err_str)2745711890bcSjc obj_array_set_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2746*8bc1b774SToomas Soome     uint32_t sub_cmd, uint32_t *value, char **plugin_err_str)
2747711890bcSjc {
2748711890bcSjc 	array_attr_t *attr;
2749711890bcSjc 	controller_attr_t *ctl_attrp;
2750711890bcSjc 	raid_lib_t *raid_lib;
2751711890bcSjc 	int ret = SUCCESS, fd;
2752711890bcSjc 	raid_obj_id_t controller_obj_id;
2753711890bcSjc 
2754711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2755711890bcSjc 		return (ERR_DEVICE_TYPE);
2756711890bcSjc 
2757711890bcSjc 	switch (sub_cmd) {
2758711890bcSjc 	case SET_CACHE_WR_PLY:
2759711890bcSjc 		if (*value != CACHE_WR_OFF &&
2760700682b8Syw 		    *value != CACHE_WR_ON)
2761711890bcSjc 			return (ERR_OP_ILLEGAL);
2762711890bcSjc 		break;
2763711890bcSjc 	case SET_CACHE_RD_PLY:
2764711890bcSjc 		if (*value != CACHE_RD_OFF &&
2765700682b8Syw 		    *value != CACHE_RD_ON)
2766711890bcSjc 			return (ERR_OP_ILLEGAL);
2767711890bcSjc 		break;
2768b449fa8aSyw 	case SET_ACTIVATION_PLY:
2769b449fa8aSyw 		if (*value != ARRAY_ACT_ACTIVATE)
2770b449fa8aSyw 			return (ERR_OP_ILLEGAL);
2771b449fa8aSyw 		break;
2772711890bcSjc 	default:
2773711890bcSjc 		return (ERR_OP_ILLEGAL);
2774711890bcSjc 	}
2775711890bcSjc 
2776711890bcSjc 	(void) obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2777711890bcSjc 
2778711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2779711890bcSjc 	if (controller_obj_id < OBJ_NONE)
2780711890bcSjc 		return (ERR_DEVICE_INVALID);
2781711890bcSjc 
2782711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2783711890bcSjc 	if (ctl_attrp == NULL) {
2784711890bcSjc 		return (ERR_DEVICE_INVALID);
2785711890bcSjc 	}
2786711890bcSjc 
2787711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2788711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2789711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
2790711890bcSjc 		return (ERR_DRIVER_CLOSED);
2791711890bcSjc 
2792711890bcSjc 	if (raid_lib->set_attr == NULL)
2793711890bcSjc 		return (ERR_OP_NO_IMPL);
2794711890bcSjc 
2795711890bcSjc 	ret = raid_lib->set_attr(ctl_attrp->controller_id,
2796700682b8Syw 	    attr->array_id, sub_cmd, value, plugin_err_str);
2797711890bcSjc 
2798711890bcSjc 	return (ret);
2799711890bcSjc }
2800711890bcSjc 
2801711890bcSjc static int
obj_disk_compnum(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t comp_type)2802711890bcSjc obj_disk_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2803*8bc1b774SToomas Soome     raid_obj_type_id_t comp_type)
2804711890bcSjc {
2805711890bcSjc 	disk_attr_t *attr;
2806711890bcSjc 	controller_attr_t *ctl_attrp;
2807711890bcSjc 	raid_obj_id_t controller_obj_id;
2808711890bcSjc 	raid_lib_t *raid_lib;
2809711890bcSjc 	int ret = SUCCESS, fd;
2810711890bcSjc 
2811711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2812711890bcSjc 		return (ERR_DEVICE_TYPE);
2813711890bcSjc 
2814711890bcSjc 	if (comp_type != OBJ_TYPE_DISK_SEG &&
2815700682b8Syw 	    comp_type != OBJ_TYPE_HSP &&
2816b449fa8aSyw 	    comp_type != OBJ_TYPE_TASK &&
2817b449fa8aSyw 	    comp_type != OBJ_TYPE_PROP)
2818711890bcSjc 		return (0);
2819711890bcSjc 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2820711890bcSjc 	if ((ret != SUCCESS) || (attr == NULL)) {
2821711890bcSjc 		return (ERR_DEVICE_INVALID);
2822711890bcSjc 	}
2823711890bcSjc 	if (attr->state == DISK_STATE_FAILED) {
2824711890bcSjc 		return (SUCCESS);
2825711890bcSjc 	}
2826711890bcSjc 
2827711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2828711890bcSjc 	if (controller_obj_id < OBJ_NONE)
2829711890bcSjc 		return (ERR_DEVICE_INVALID);
2830711890bcSjc 
2831711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2832711890bcSjc 	if (ctl_attrp == NULL) {
2833711890bcSjc 		return (ERR_DEVICE_INVALID);
2834711890bcSjc 	}
2835711890bcSjc 
2836711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2837711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2838711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
2839711890bcSjc 		return (ERR_DRIVER_CLOSED);
2840711890bcSjc 
2841711890bcSjc 	ret = raid_lib->compnum(ctl_attrp->controller_id,
2842700682b8Syw 	    attr->disk_id, OBJ_TYPE_DISK, comp_type);
2843711890bcSjc 
2844711890bcSjc 	return (ret);
2845711890bcSjc }
2846711890bcSjc 
2847711890bcSjc static int
obj_disk_complist(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,int comp_num,raid_obj_id_t * comp_list,raid_obj_type_id_t comp_type)2848711890bcSjc obj_disk_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2849*8bc1b774SToomas Soome     int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2850711890bcSjc {
2851711890bcSjc 	disk_attr_t *attr;
2852711890bcSjc 	controller_attr_t *ctl_attrp;
2853711890bcSjc 	raid_obj_id_t controller_obj_id;
2854711890bcSjc 	raid_lib_t *raid_lib;
2855711890bcSjc 	int ret, i, fd;
2856711890bcSjc 	uint32_t *ids;
2857711890bcSjc 
2858711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2859711890bcSjc 		return (ERR_DEVICE_TYPE);
2860711890bcSjc 
2861711890bcSjc 	if (comp_type != OBJ_TYPE_DISK_SEG &&
2862700682b8Syw 	    comp_type != OBJ_TYPE_HSP &&
2863b449fa8aSyw 	    comp_type != OBJ_TYPE_TASK &&
2864b449fa8aSyw 	    comp_type != OBJ_TYPE_PROP)
2865711890bcSjc 		return (0);
2866711890bcSjc 
2867711890bcSjc 	if (comp_num <= 0 || comp_list == NULL)
2868711890bcSjc 		return (ERR_OP_ILLEGAL);
2869711890bcSjc 
2870711890bcSjc 	for (i = 0; i < comp_num; ++i)
2871711890bcSjc 		if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2872700682b8Syw 		    comp_type)
2873711890bcSjc 			return (ERR_DEVICE_TYPE);
2874711890bcSjc 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2875711890bcSjc 	if ((ret != SUCCESS) || (attr == NULL)) {
2876711890bcSjc 		return (ERR_DEVICE_INVALID);
2877711890bcSjc 	}
2878711890bcSjc 	if (attr->state == DISK_STATE_FAILED) {
2879711890bcSjc 		return (SUCCESS);
2880711890bcSjc 	}
2881711890bcSjc 
2882711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2883711890bcSjc 	if (controller_obj_id < OBJ_NONE)
2884711890bcSjc 		return (ERR_DEVICE_INVALID);
2885711890bcSjc 
2886711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2887711890bcSjc 	if (ctl_attrp == NULL) {
2888711890bcSjc 		return (ERR_DEVICE_INVALID);
2889711890bcSjc 	}
2890711890bcSjc 
2891711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2892711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2893711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
2894711890bcSjc 		return (ERR_DRIVER_CLOSED);
2895711890bcSjc 
2896711890bcSjc 	ids = malloc(comp_num * sizeof (uint32_t));
2897711890bcSjc 	if (ids == NULL)
2898711890bcSjc 		return (ERR_NOMEM);
2899711890bcSjc 
2900711890bcSjc 	ret = raid_lib->complist(ctl_attrp->controller_id,
2901700682b8Syw 	    attr->disk_id, OBJ_TYPE_DISK, comp_type, comp_num, ids);
2902711890bcSjc 
2903711890bcSjc 	if (ret < SUCCESS) {
2904711890bcSjc 		free(ids);
2905711890bcSjc 		return (ret);
2906711890bcSjc 	}
2907711890bcSjc 
2908711890bcSjc 	for (i = 0; i < comp_num; ++ i) {
2909711890bcSjc 		diskseg_attr_t *diskseg_attr;
2910711890bcSjc 		hsp_attr_t *hsp_attr;
2911711890bcSjc 		task_attr_t *task_attr;
2912b449fa8aSyw 		property_attr_t *prop_attr;
2913711890bcSjc 		void *attr_buf;
2914711890bcSjc 
2915711890bcSjc 		attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2916711890bcSjc 		if (attr_buf == NULL) {
2917711890bcSjc 			free(ids);
2918711890bcSjc 			return (ERR_DEVICE_INVALID);
2919711890bcSjc 		}
2920711890bcSjc 
2921711890bcSjc 		switch (comp_type) {
2922711890bcSjc 		case OBJ_TYPE_DISK_SEG:
2923711890bcSjc 			diskseg_attr = attr_buf;
2924711890bcSjc 			diskseg_attr->seq_no = *(ids + i);
2925711890bcSjc 			break;
2926711890bcSjc 		case OBJ_TYPE_HSP:
2927711890bcSjc 			hsp_attr = attr_buf;
2928711890bcSjc 			hsp_attr->associated_id = *(ids + i);
2929711890bcSjc 			break;
2930711890bcSjc 		case OBJ_TYPE_TASK:
2931711890bcSjc 			task_attr = attr_buf;
2932711890bcSjc 			task_attr->task_id = *(ids + i);
2933711890bcSjc 			break;
2934b449fa8aSyw 		case OBJ_TYPE_PROP:
2935b449fa8aSyw 			prop_attr = attr_buf;
2936b449fa8aSyw 			prop_attr->prop_id = *(ids + i);
2937b449fa8aSyw 			break;
2938711890bcSjc 		default:
2939711890bcSjc 			free(ids);
2940711890bcSjc 			return (ERR_DEVICE_INVALID);
2941711890bcSjc 		}
2942711890bcSjc 	}
2943711890bcSjc 
2944711890bcSjc 
2945711890bcSjc 	free(ids);
2946711890bcSjc 	return (ret);
2947711890bcSjc }
2948711890bcSjc 
2949711890bcSjc static int
obj_disk_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)2950711890bcSjc obj_disk_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2951711890bcSjc {
2952711890bcSjc 	disk_attr_t *attr;
2953711890bcSjc 	controller_attr_t *ctl_attrp;
2954711890bcSjc 	raid_lib_t *raid_lib;
2955711890bcSjc 	int ret = SUCCESS, fd;
2956711890bcSjc 	raid_obj_id_t controller_obj_id;
2957711890bcSjc 
2958711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2959711890bcSjc 		return (ERR_DEVICE_TYPE);
2960711890bcSjc 
2961711890bcSjc 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2962711890bcSjc 		return (SUCCESS);
2963711890bcSjc 
2964711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2965711890bcSjc 	if (attr == NULL)
2966711890bcSjc 		return (ERR_DEVICE_INVALID);
2967711890bcSjc 
2968711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
2969711890bcSjc 	if (controller_obj_id < OBJ_NONE)
2970711890bcSjc 		return (ERR_DEVICE_INVALID);
2971711890bcSjc 
2972711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2973711890bcSjc 	if (ctl_attrp == NULL) {
2974711890bcSjc 		return (ERR_DEVICE_INVALID);
2975711890bcSjc 	}
2976711890bcSjc 
2977711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2978711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2979711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
2980711890bcSjc 		return (ERR_DRIVER_CLOSED);
2981711890bcSjc 
2982711890bcSjc 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
2983700682b8Syw 	    attr->disk_id, 0, OBJ_TYPE_DISK, attr);
2984711890bcSjc 
2985711890bcSjc 	if (ret < SUCCESS)
2986711890bcSjc 		return (ret);
2987711890bcSjc 
2988711890bcSjc 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2989711890bcSjc 
2990711890bcSjc 	return (ret);
2991711890bcSjc }
2992711890bcSjc 
2993711890bcSjc static int
obj_hsp_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)2994711890bcSjc obj_hsp_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2995711890bcSjc {
2996711890bcSjc 	hsp_attr_t *attr;
2997711890bcSjc 
2998711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_HSP)
2999711890bcSjc 		return (ERR_DEVICE_TYPE);
3000711890bcSjc 
3001711890bcSjc 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3002711890bcSjc 		return (SUCCESS);
3003711890bcSjc 
3004711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3005711890bcSjc 	if (attr == NULL)
3006711890bcSjc 		return (ERR_DEVICE_INVALID);
3007711890bcSjc 
3008711890bcSjc 	if (attr->associated_id == (uint32_t)OBJ_ATTR_NONE)
3009711890bcSjc 		attr->type = HSP_TYPE_GLOBAL;
3010711890bcSjc 	else
3011711890bcSjc 		attr->type = HSP_TYPE_LOCAL;
3012711890bcSjc 
3013711890bcSjc 	return (SUCCESS);
3014711890bcSjc }
3015711890bcSjc 
3016711890bcSjc static int
obj_arraypart_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)3017711890bcSjc obj_arraypart_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3018711890bcSjc {
3019711890bcSjc 	arraypart_attr_t *attr;
3020711890bcSjc 	array_attr_t *array_attr;
3021711890bcSjc 	controller_attr_t *ctl_attrp;
3022711890bcSjc 	raid_lib_t *raid_lib;
3023711890bcSjc 	int ret = SUCCESS, fd;
3024711890bcSjc 	raid_obj_id_t controller_obj_id, array_obj_id;
3025711890bcSjc 
3026711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY_PART)
3027711890bcSjc 		return (ERR_DEVICE_TYPE);
3028711890bcSjc 
3029711890bcSjc 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3030711890bcSjc 		return (SUCCESS);
3031711890bcSjc 
3032711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3033711890bcSjc 	if (attr == NULL)
3034711890bcSjc 		return (ERR_DEVICE_INVALID);
3035711890bcSjc 
3036711890bcSjc 	array_obj_id = raid_obj_get_container(raid_tab, obj_id);
3037711890bcSjc 	if (array_obj_id < OBJ_NONE)
3038711890bcSjc 		return (ERR_DEVICE_INVALID);
3039711890bcSjc 
3040711890bcSjc 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3041711890bcSjc 	if (array_attr == NULL)
3042711890bcSjc 		return (ERR_DEVICE_INVALID);
3043711890bcSjc 
3044711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3045711890bcSjc 	if (controller_obj_id < OBJ_NONE)
3046711890bcSjc 		return (ERR_DEVICE_INVALID);
3047711890bcSjc 
3048711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3049711890bcSjc 	if (ctl_attrp == NULL) {
3050711890bcSjc 		return (ERR_DEVICE_INVALID);
3051711890bcSjc 	}
3052711890bcSjc 
3053711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3054711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3055711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
3056711890bcSjc 		return (ERR_DRIVER_CLOSED);
3057711890bcSjc 
3058711890bcSjc 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3059700682b8Syw 	    array_attr->array_id, attr->disk_id,
3060700682b8Syw 	    OBJ_TYPE_ARRAY_PART, attr);
3061711890bcSjc 
3062711890bcSjc 	if (ret < SUCCESS)
3063711890bcSjc 		return (ret);
3064711890bcSjc 
3065711890bcSjc 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3066711890bcSjc 
3067711890bcSjc 	return (ret);
3068711890bcSjc }
3069711890bcSjc 
3070711890bcSjc static int
obj_diskseg_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)3071711890bcSjc obj_diskseg_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3072711890bcSjc {
3073711890bcSjc 	diskseg_attr_t *attr;
3074711890bcSjc 	disk_attr_t *disk_attr;
3075711890bcSjc 	controller_attr_t *ctl_attrp;
3076711890bcSjc 	raid_lib_t *raid_lib;
3077711890bcSjc 	int ret = SUCCESS, fd;
3078711890bcSjc 	raid_obj_id_t controller_obj_id, disk_obj_id;
3079711890bcSjc 
3080711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK_SEG)
3081711890bcSjc 		return (ERR_DEVICE_TYPE);
3082711890bcSjc 
3083711890bcSjc 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3084711890bcSjc 		return (SUCCESS);
3085711890bcSjc 
3086711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3087711890bcSjc 	if (attr == NULL)
3088711890bcSjc 		return (ERR_DEVICE_INVALID);
3089711890bcSjc 
3090711890bcSjc 	disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
3091711890bcSjc 	if (disk_obj_id < OBJ_NONE)
3092711890bcSjc 		return (ERR_DEVICE_INVALID);
3093711890bcSjc 
3094711890bcSjc 	disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
3095711890bcSjc 	if (disk_attr == NULL)
3096711890bcSjc 		return (ERR_DEVICE_INVALID);
3097711890bcSjc 
3098711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3099711890bcSjc 	if (controller_obj_id < OBJ_NONE)
3100711890bcSjc 		return (ERR_DEVICE_INVALID);
3101711890bcSjc 
3102711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3103711890bcSjc 	if (ctl_attrp == NULL) {
3104711890bcSjc 		return (ERR_DEVICE_INVALID);
3105711890bcSjc 	}
3106711890bcSjc 
3107711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3108711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3109711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
3110711890bcSjc 		return (ERR_DRIVER_CLOSED);
3111711890bcSjc 
3112711890bcSjc 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3113700682b8Syw 	    disk_attr->disk_id, attr->seq_no, OBJ_TYPE_DISK_SEG, attr);
3114711890bcSjc 
3115711890bcSjc 	if (ret < SUCCESS)
3116711890bcSjc 		return (ret);
3117711890bcSjc 
3118711890bcSjc 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3119711890bcSjc 
3120711890bcSjc 	return (ret);
3121711890bcSjc }
3122711890bcSjc 
3123711890bcSjc static int
obj_task_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)3124711890bcSjc obj_task_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3125711890bcSjc {
3126711890bcSjc 	task_attr_t *attr;
3127711890bcSjc 	controller_attr_t *ctl_attrp;
3128711890bcSjc 	raid_lib_t *raid_lib;
3129711890bcSjc 	int ret = SUCCESS, fd;
3130711890bcSjc 	raid_obj_id_t controller_obj_id;
3131711890bcSjc 
3132711890bcSjc 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_TASK)
3133711890bcSjc 		return (ERR_DEVICE_TYPE);
3134711890bcSjc 
3135711890bcSjc 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3136711890bcSjc 	if (attr == NULL)
3137711890bcSjc 		return (ERR_DEVICE_INVALID);
3138711890bcSjc 
3139711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3140711890bcSjc 	if (controller_obj_id < OBJ_NONE)
3141711890bcSjc 		return (ERR_DEVICE_INVALID);
3142711890bcSjc 
3143711890bcSjc 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3144711890bcSjc 	if (ctl_attrp == NULL) {
3145711890bcSjc 		return (ERR_DEVICE_INVALID);
3146711890bcSjc 	}
3147711890bcSjc 
3148711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3149711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3150711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
3151711890bcSjc 		return (ERR_DRIVER_CLOSED);
3152711890bcSjc 
3153711890bcSjc 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3154700682b8Syw 	    attr->task_id, OBJ_ATTR_NONE, OBJ_TYPE_TASK, attr);
3155711890bcSjc 
3156711890bcSjc 	return (ret);
3157711890bcSjc }
3158711890bcSjc 
3159b449fa8aSyw static int
obj_prop_get_attr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)3160b449fa8aSyw obj_prop_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3161b449fa8aSyw {
3162b449fa8aSyw 	property_attr_t *attr, *attr_new;
3163b449fa8aSyw 	disk_attr_t *disk_attr;
3164b449fa8aSyw 	controller_attr_t *ctl_attrp;
3165b449fa8aSyw 	raid_lib_t *raid_lib;
3166b449fa8aSyw 	int ret = SUCCESS, fd;
3167b449fa8aSyw 	raid_obj_id_t controller_obj_id, disk_obj_id;
3168b449fa8aSyw 
3169b449fa8aSyw 	if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_PROP)
3170b449fa8aSyw 		return (ERR_DEVICE_TYPE);
3171b449fa8aSyw 
3172b449fa8aSyw 	if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3173b449fa8aSyw 		return (SUCCESS);
3174b449fa8aSyw 
3175b449fa8aSyw 	attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3176b449fa8aSyw 	if (attr == NULL)
3177b449fa8aSyw 		return (ERR_DEVICE_INVALID);
3178b449fa8aSyw 
3179b449fa8aSyw 	disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
3180b449fa8aSyw 	if (disk_obj_id < OBJ_NONE)
3181b449fa8aSyw 		return (ERR_DEVICE_INVALID);
3182b449fa8aSyw 
3183b449fa8aSyw 	disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
3184b449fa8aSyw 	if (disk_attr == NULL)
3185b449fa8aSyw 		return (ERR_DEVICE_INVALID);
3186b449fa8aSyw 
3187b449fa8aSyw 	controller_obj_id = obj_get_controller(raid_tab, obj_id);
3188b449fa8aSyw 	if (controller_obj_id < OBJ_NONE)
3189b449fa8aSyw 		return (ERR_DEVICE_INVALID);
3190b449fa8aSyw 
3191b449fa8aSyw 	ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3192b449fa8aSyw 	if (ctl_attrp == NULL) {
3193b449fa8aSyw 		return (ERR_DEVICE_INVALID);
3194b449fa8aSyw 	}
3195b449fa8aSyw 
3196b449fa8aSyw 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3197b449fa8aSyw 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3198b449fa8aSyw 	if ((raid_lib == NULL) || (fd == 0))
3199b449fa8aSyw 		return (ERR_DRIVER_CLOSED);
3200b449fa8aSyw 
3201b449fa8aSyw 	/* Get the property size at first */
3202b449fa8aSyw 	attr->prop_size = 0;
3203b449fa8aSyw 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3204b449fa8aSyw 	    disk_attr->disk_id, OBJ_ATTR_NONE, OBJ_TYPE_PROP, attr);
3205b449fa8aSyw 
3206b449fa8aSyw 	if (ret < SUCCESS)
3207b449fa8aSyw 		return (ret);
3208b449fa8aSyw 
3209b449fa8aSyw 	/* Allocate memory for property and fill the buffer */
3210b449fa8aSyw 	attr_new = realloc(attr, sizeof (property_attr_t) + attr->prop_size);
3211b449fa8aSyw 	if (attr_new == NULL)
3212b449fa8aSyw 		return (ERR_NOMEM);
3213b449fa8aSyw 
3214b449fa8aSyw 	(void) raid_obj_set_data_ptr(raid_tab, obj_id, attr_new);
3215b449fa8aSyw 
3216b449fa8aSyw 	ret = raid_lib->get_attr(ctl_attrp->controller_id,
3217b449fa8aSyw 	    disk_attr->disk_id, OBJ_ATTR_NONE, OBJ_TYPE_PROP, attr_new);
3218b449fa8aSyw 
3219b449fa8aSyw 	if (ret < SUCCESS)
3220b449fa8aSyw 		return (ret);
3221b449fa8aSyw 
3222b449fa8aSyw 	(void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3223b449fa8aSyw 
3224b449fa8aSyw 	return (ret);
3225b449fa8aSyw }
3226b449fa8aSyw 
3227711890bcSjc static int
obj_array_create(raid_obj_tab_t * raid_tab,raid_obj_id_t array_obj_id,int num_of_comp,raid_obj_id_t * disk_list,char ** plugin_err_str)3228711890bcSjc obj_array_create(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3229*8bc1b774SToomas Soome     int num_of_comp, raid_obj_id_t *disk_list, char **plugin_err_str)
3230711890bcSjc {
3231711890bcSjc 	controller_attr_t *controller_attr;
3232711890bcSjc 	array_attr_t *array_attr, array_attr2;
3233711890bcSjc 	disk_attr_t *disk_attr;
3234711890bcSjc 	arraypart_attr_t *arraypart_attrs;
3235711890bcSjc 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3236711890bcSjc 	raid_lib_t *raid_lib;
3237711890bcSjc 	int i, j, ret, fd;
3238711890bcSjc 	int disk_cnt = 0, disk_set_num = 0, set_num = 0, layer_cnt = 0;
3239711890bcSjc 	uint64_t min_disk_capacity = 0;
3240711890bcSjc 
3241711890bcSjc 	array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3242711890bcSjc 	if (array_attr == NULL)
3243711890bcSjc 		return (ERR_DEVICE_INVALID);
3244711890bcSjc 
3245711890bcSjc 	/* Check the disk layout expression */
3246711890bcSjc 	if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
3247700682b8Syw 	    disk_list[num_of_comp - 1] != OBJ_SEPARATOR_END)
3248711890bcSjc 		return (ERR_ARRAY_LAYOUT);
3249711890bcSjc 	for (i = 0; i < num_of_comp; ++i) {
3250711890bcSjc 		if (disk_list[i] == OBJ_SEPARATOR_BEGIN) {
3251711890bcSjc 			if (disk_cnt != 0)
3252711890bcSjc 				return (ERR_ARRAY_LAYOUT);
3253711890bcSjc 			++layer_cnt;
3254711890bcSjc 			continue;
3255711890bcSjc 		}
3256711890bcSjc 		if (disk_list[i] == OBJ_SEPARATOR_END) {
3257711890bcSjc 			if (disk_set_num == 0)
3258711890bcSjc 				disk_set_num = disk_cnt;
3259711890bcSjc 			else if (disk_set_num != disk_cnt && disk_cnt != 0)
3260711890bcSjc 				return (ERR_ARRAY_LAYOUT);
3261711890bcSjc 			disk_cnt = 0;
3262711890bcSjc 			++set_num;
3263711890bcSjc 			--layer_cnt;
3264711890bcSjc 			continue;
3265711890bcSjc 		}
3266711890bcSjc 		switch (array_attr->raid_level) {
3267711890bcSjc 		case RAID_LEVEL_0:
3268711890bcSjc 		case RAID_LEVEL_1:
3269711890bcSjc 		case RAID_LEVEL_1E:
3270711890bcSjc 		case RAID_LEVEL_5:
3271711890bcSjc 			if (layer_cnt != 1)
3272711890bcSjc 				return (ERR_ARRAY_LAYOUT);
3273711890bcSjc 			break;
3274711890bcSjc 		case RAID_LEVEL_10:
3275711890bcSjc 		case RAID_LEVEL_50:
3276711890bcSjc 			if (layer_cnt != 2)
3277711890bcSjc 				return (ERR_ARRAY_LAYOUT);
3278711890bcSjc 			break;
3279711890bcSjc 		default:
3280711890bcSjc 			return (ERR_ARRAY_LEVEL);
3281711890bcSjc 		}
3282711890bcSjc 		++disk_cnt;
3283711890bcSjc 	}
3284711890bcSjc 
3285711890bcSjc 	if (layer_cnt != 0)
3286711890bcSjc 		return (ERR_ARRAY_LAYOUT);
3287711890bcSjc 
3288711890bcSjc 	switch (array_attr->raid_level) {
3289711890bcSjc 	case RAID_LEVEL_0:
3290711890bcSjc 		if (disk_set_num < 2 || set_num != 1)
3291711890bcSjc 			return (ERR_ARRAY_LAYOUT);
3292711890bcSjc 		break;
3293711890bcSjc 	case RAID_LEVEL_1:
3294711890bcSjc 		if (disk_set_num != 2 || set_num != 1)
3295711890bcSjc 			return (ERR_ARRAY_LAYOUT);
3296711890bcSjc 		break;
3297711890bcSjc 	case RAID_LEVEL_1E:
3298711890bcSjc 	case RAID_LEVEL_5:
3299711890bcSjc 		if (disk_set_num < 3 || set_num != 1)
3300711890bcSjc 			return (ERR_ARRAY_LAYOUT);
3301711890bcSjc 		break;
3302711890bcSjc 	case RAID_LEVEL_10:
3303711890bcSjc 		if (disk_set_num != 2 || set_num < 2)
3304711890bcSjc 			return (ERR_ARRAY_LAYOUT);
3305711890bcSjc 		break;
3306711890bcSjc 	case RAID_LEVEL_50:
3307711890bcSjc 		if (disk_set_num < 3 || set_num < 2)
3308711890bcSjc 			return (ERR_ARRAY_LAYOUT);
3309711890bcSjc 		break;
3310711890bcSjc 	default:
3311711890bcSjc 		return (ERR_ARRAY_LEVEL);
3312711890bcSjc 	}
3313711890bcSjc 
3314711890bcSjc 	arraypart_attrs = calloc(num_of_comp, sizeof (arraypart_attr_t));
3315711890bcSjc 	if (arraypart_attrs == NULL)
3316711890bcSjc 		return (ERR_NOMEM);
3317711890bcSjc 
3318711890bcSjc 	for (i = 0; i < num_of_comp; ++i) {
3319711890bcSjc 		/* Keep seperators */
3320711890bcSjc 		if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3321711890bcSjc 			arraypart_attrs[i].disk_id =
3322700682b8Syw 			    (uint32_t)OBJ_SEPARATOR_BEGIN;
3323711890bcSjc 			continue;
3324711890bcSjc 		}
3325711890bcSjc 
3326711890bcSjc 		if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3327711890bcSjc 			arraypart_attrs[i].disk_id =
3328700682b8Syw 			    (uint32_t)OBJ_SEPARATOR_END;
3329711890bcSjc 			continue;
3330711890bcSjc 		}
3331711890bcSjc 
3332711890bcSjc 		disk_cnt++;
3333711890bcSjc 		/* Check if it's a disk */
3334711890bcSjc 		if (raid_obj_get_type(raid_tab, *(disk_list + i)) !=
3335700682b8Syw 		    OBJ_TYPE_DISK)
3336711890bcSjc 			return (ERR_DEVICE_TYPE);
3337711890bcSjc 
3338711890bcSjc 		/* Check if it's duplicated with other disks */
3339711890bcSjc 		for (j = 0; j < i; ++j)
3340711890bcSjc 			if (*(disk_list + j) == *(disk_list + i)) {
3341711890bcSjc 				free(arraypart_attrs);
3342711890bcSjc 				return (ERR_DEVICE_DUP);
3343711890bcSjc 			}
3344711890bcSjc 
3345711890bcSjc 		/* Check disk status */
3346711890bcSjc 		ret = obj_get_attr(raid_tab, *(disk_list + i),
3347700682b8Syw 		    (void **)(&disk_attr));
3348711890bcSjc 		if (ret != SUCCESS)
3349711890bcSjc 			return (ret);
3350711890bcSjc 
3351711890bcSjc 		if (disk_attr->state != DISK_STATE_GOOD) {
3352711890bcSjc 			free(arraypart_attrs);
3353711890bcSjc 			return (ERR_DISK_STATE);
3354711890bcSjc 		}
3355711890bcSjc 
3356711890bcSjc 		/* All disks must belong to the same controller */
3357711890bcSjc 		obj_id = obj_get_controller(raid_tab, *(disk_list + i));
3358711890bcSjc 		if (obj_id <= OBJ_NONE)
3359711890bcSjc 			return (obj_id);
3360711890bcSjc 		if (controller_obj_id == OBJ_NONE) {
3361711890bcSjc 			controller_obj_id = obj_id;
3362711890bcSjc 			ret = obj_get_attr(raid_tab, controller_obj_id,
3363700682b8Syw 			    (void **)(&controller_attr));
3364711890bcSjc 		} else if (obj_id != controller_obj_id) {
3365711890bcSjc 			free(arraypart_attrs);
3366711890bcSjc 			return (ERR_DRIVER_ACROSS);
3367711890bcSjc 		}
3368711890bcSjc 
3369711890bcSjc 		/* Check if the disk contains too many segments */
3370711890bcSjc 		obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3371700682b8Syw 		    OBJ_TYPE_DISK_SEG);
3372711890bcSjc 		j = 0;
3373711890bcSjc 		while (obj_id > OBJ_NONE) {
3374711890bcSjc 			++j;
3375711890bcSjc 			obj_id = obj_get_sibling(raid_tab, obj_id);
3376711890bcSjc 		}
3377711890bcSjc 		if (j > controller_attr->max_seg_per_disk) {
3378711890bcSjc 			free(arraypart_attrs);
3379711890bcSjc 			return (ERR_DISK_SEG_AMOUNT);
3380711890bcSjc 		}
3381711890bcSjc 
3382711890bcSjc 		/* Check if controller is a hostraid controller */
3383711890bcSjc 		if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3384711890bcSjc 			/*
3385711890bcSjc 			 * For hostraid, the first disk should
3386711890bcSjc 			 * be with of minimum capacity
3387711890bcSjc 			 */
3388711890bcSjc 			if (min_disk_capacity == 0) {
3389711890bcSjc 				min_disk_capacity = disk_attr->capacity;
3390711890bcSjc 
3391711890bcSjc 				/* Can not specify capacity for hostraid */
3392711890bcSjc 				if (array_attr->capacity != 0) {
3393711890bcSjc 					free(arraypart_attrs);
3394700682b8Syw 					return (ERR_OP_ILLEGAL);
3395711890bcSjc 				}
3396711890bcSjc 			} else if (min_disk_capacity > disk_attr->capacity) {
3397711890bcSjc 				free(arraypart_attrs);
3398711890bcSjc 				return (ERR_DISK_SPACE);
3399711890bcSjc 			}
3400711890bcSjc 
3401711890bcSjc 			/* Disk should not be used for hostraid */
3402711890bcSjc 			obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3403700682b8Syw 			    OBJ_TYPE_DISK_SEG);
3404711890bcSjc 			if (obj_id < OBJ_NONE) {
3405711890bcSjc 				free(arraypart_attrs);
3406711890bcSjc 				return (obj_id);
3407711890bcSjc 			} else if (obj_id > OBJ_NONE) {
3408711890bcSjc 				free(arraypart_attrs);
3409711890bcSjc 				return (ERR_DISK_NOT_EMPTY);
3410711890bcSjc 			}
3411711890bcSjc 		}
3412711890bcSjc 
3413711890bcSjc 		arraypart_attrs[i].disk_id = disk_attr->disk_id;
3414711890bcSjc 		arraypart_attrs[i].offset = OBJ_ATTR_NONE;
3415711890bcSjc 		arraypart_attrs[i].size = OBJ_ATTR_NONE;
3416711890bcSjc 	}
3417711890bcSjc 
3418711890bcSjc 	/* Check if array amount exceeds limit */
3419711890bcSjc 	if (controller_attr->max_array_num <=
3420700682b8Syw 	    obj_controller_compnum(raid_tab, controller_obj_id,
3421700682b8Syw 	    OBJ_TYPE_ARRAY))
3422711890bcSjc 		return (ERR_ARRAY_AMOUNT);
3423711890bcSjc 
3424711890bcSjc 
3425711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3426711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3427711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
3428711890bcSjc 		return (ERR_DRIVER_CLOSED);
3429711890bcSjc 
3430711890bcSjc 	/* Check if the controller can support the array RAID level */
3431711890bcSjc 	switch (array_attr->raid_level) {
3432711890bcSjc 	case	RAID_LEVEL_0:
3433711890bcSjc 		if (!(controller_attr->capability & RAID_CAP_RAID0)) {
3434711890bcSjc 			free(arraypart_attrs);
3435711890bcSjc 			return (ERR_ARRAY_LEVEL);
3436711890bcSjc 		}
3437711890bcSjc 		break;
3438711890bcSjc 	case	RAID_LEVEL_1:
3439711890bcSjc 		if (!(controller_attr->capability & RAID_CAP_RAID1)) {
3440711890bcSjc 			free(arraypart_attrs);
3441711890bcSjc 			return (ERR_ARRAY_LEVEL);
3442711890bcSjc 		}
3443711890bcSjc 		break;
3444711890bcSjc 	case	RAID_LEVEL_1E:
3445711890bcSjc 		if (!(controller_attr->capability & RAID_CAP_RAID1E)) {
3446711890bcSjc 			free(arraypart_attrs);
3447711890bcSjc 			return (ERR_ARRAY_LEVEL);
3448711890bcSjc 		}
3449711890bcSjc 		break;
3450711890bcSjc 	case	RAID_LEVEL_5:
3451711890bcSjc 		if (!(controller_attr->capability & RAID_CAP_RAID5)) {
3452711890bcSjc 			free(arraypart_attrs);
3453711890bcSjc 			return (ERR_ARRAY_LEVEL);
3454711890bcSjc 		}
3455711890bcSjc 		break;
3456711890bcSjc 	case	RAID_LEVEL_10:
3457711890bcSjc 		if (!(controller_attr->capability & RAID_CAP_RAID10)) {
3458711890bcSjc 			free(arraypart_attrs);
3459711890bcSjc 			return (ERR_ARRAY_LEVEL);
3460711890bcSjc 		}
3461711890bcSjc 		break;
3462711890bcSjc 	case	RAID_LEVEL_50:
3463711890bcSjc 		if (!(controller_attr->capability & RAID_CAP_RAID50)) {
3464711890bcSjc 			free(arraypart_attrs);
3465711890bcSjc 			return (ERR_ARRAY_LEVEL);
3466711890bcSjc 		}
3467711890bcSjc 		break;
3468711890bcSjc 	default:
3469711890bcSjc 		free(arraypart_attrs);
3470711890bcSjc 		return (ERR_ARRAY_LEVEL);
3471711890bcSjc 	}
3472711890bcSjc 
3473711890bcSjc 	/* Check if plug in can calculate the maximum size */
3474711890bcSjc 	(void) memcpy(&array_attr2, array_attr, sizeof (array_attr_t));
3475711890bcSjc 	array_attr2.capacity = OBJ_ATTR_NONE;
3476711890bcSjc 	ret = raid_lib->array_create(controller_attr->controller_id,
3477700682b8Syw 	    &array_attr2, num_of_comp, arraypart_attrs, plugin_err_str);
3478711890bcSjc 
3479711890bcSjc 	/* If plugin/driver will not calculate space */
3480711890bcSjc 	if (ret == ERR_OP_NO_IMPL) {
3481711890bcSjc 		/* Calculate the maximum capacity */
3482711890bcSjc 		array_attr2.capacity = raid_space_noalign(raid_tab,
3483700682b8Syw 		    array_attr2.raid_level, num_of_comp, disk_list,
3484700682b8Syw 		    arraypart_attrs);
3485711890bcSjc 
3486711890bcSjc 		/*
3487711890bcSjc 		 * If controller is capable to allocate space,
3488711890bcSjc 		 * set offset and size attributes to OBJ_ATTR_NONE
3489711890bcSjc 		 * and let the controller to determine these value
3490711890bcSjc 		 */
3491711890bcSjc 		if (controller_attr->capability & RAID_CAP_SMART_ALLOC)
3492711890bcSjc 			for (i = 0; i < num_of_comp; ++i) {
3493711890bcSjc 				arraypart_attrs[i].offset =
3494700682b8Syw 				    OBJ_ATTR_NONE;
3495711890bcSjc 				arraypart_attrs[i].size =
3496700682b8Syw 				    OBJ_ATTR_NONE;
3497711890bcSjc 			}
3498711890bcSjc 
3499711890bcSjc 		/* There's no enough space for specified capacity */
3500711890bcSjc 		if (array_attr->capacity > array_attr2.capacity) {
3501711890bcSjc 			free(arraypart_attrs);
3502711890bcSjc 			return (ERR_ARRAY_SIZE);
3503711890bcSjc 		}
3504711890bcSjc 
3505711890bcSjc 		/* capacity == 0, allocate maximum space */
3506711890bcSjc 		if (array_attr->capacity == 0)
3507711890bcSjc 			array_attr->capacity = array_attr2.capacity;
3508711890bcSjc 	} else if (ret < SUCCESS) {
3509711890bcSjc 		free(arraypart_attrs);
3510711890bcSjc 		return (ret);
3511711890bcSjc 	} else if (array_attr2.capacity < array_attr->capacity) {
3512711890bcSjc 		/* Return the maximum size */
3513711890bcSjc 		array_attr->capacity = array_attr2.capacity;
3514711890bcSjc 		free(arraypart_attrs);
3515711890bcSjc 		return (ERR_ARRAY_SIZE);
3516711890bcSjc 	}
3517711890bcSjc 
3518711890bcSjc 	if (array_attr->capacity < ARRAYPART_MIN_SIZE * disk_cnt) {
3519711890bcSjc 		free(arraypart_attrs);
3520711890bcSjc 		return (ERR_ARRAY_SIZE);
3521711890bcSjc 	}
3522711890bcSjc 
3523711890bcSjc 
3524711890bcSjc 	ret = raid_lib->array_create(controller_attr->controller_id,
3525700682b8Syw 	    array_attr, num_of_comp, arraypart_attrs, plugin_err_str);
3526711890bcSjc 	free(arraypart_attrs);
3527711890bcSjc 
3528711890bcSjc 	if (ret != SUCCESS)
3529711890bcSjc 		return (ret);
3530711890bcSjc 
3531711890bcSjc 	/* Add array object into device tree so that we can map the handle */
3532711890bcSjc 	(void) raid_obj_add_org(raid_tab, array_obj_id, controller_obj_id);
3533711890bcSjc 
3534711890bcSjc 	return (ret);
3535711890bcSjc }
3536711890bcSjc 
3537711890bcSjc static int
obj_array_delete(raid_obj_tab_t * raid_tab,raid_obj_id_t array_obj_id,char ** plugin_err_str)3538711890bcSjc obj_array_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3539*8bc1b774SToomas Soome     char **plugin_err_str)
3540711890bcSjc {
3541711890bcSjc 	raid_obj_id_t controller_obj_id;
3542711890bcSjc 	controller_attr_t *controller_attr;
3543711890bcSjc 	array_attr_t *array_attr;
3544711890bcSjc 	raid_lib_t *raid_lib;
354572e1c055Sjc 	int ret, fd;
3546711890bcSjc 	uint32_t *disk_ids = NULL;
3547711890bcSjc 
3548711890bcSjc 	controller_obj_id = obj_get_controller(raid_tab, array_obj_id);
3549711890bcSjc 	if (controller_obj_id <= OBJ_NONE)
3550711890bcSjc 		return (controller_obj_id);
3551711890bcSjc 
3552711890bcSjc 	ret = obj_get_attr(raid_tab, controller_obj_id,
3553700682b8Syw 	    (void **)(&controller_attr));
3554711890bcSjc 	if (ret < SUCCESS) {
3555711890bcSjc 		return (ret);
3556711890bcSjc 	}
3557711890bcSjc 	ret = obj_get_attr(raid_tab, array_obj_id, (void **)(&array_attr));
3558711890bcSjc 	if (ret < SUCCESS)
3559711890bcSjc 		return (ret);
3560711890bcSjc 
3561711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3562711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3563711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
3564711890bcSjc 		return (ERR_DRIVER_CLOSED);
3565711890bcSjc 
3566711890bcSjc 	ret = raid_lib->array_delete(controller_attr->controller_id,
3567700682b8Syw 	    array_attr->array_id, plugin_err_str);
3568711890bcSjc 	if (ret < SUCCESS) {
3569711890bcSjc 		if (disk_ids)
3570711890bcSjc 			free(disk_ids);
3571711890bcSjc 		return (ret);
3572711890bcSjc 	}
3573711890bcSjc 
3574711890bcSjc 	if (disk_ids)
3575711890bcSjc 		free(disk_ids);
3576711890bcSjc 	return (ret);
3577711890bcSjc }
3578711890bcSjc 
3579711890bcSjc static int
obj_hsp_bind(raid_obj_tab_t * raid_tab,raid_obj_id_t * obj_ids,char ** plugin_err_str)35805c9d25d2SYu-Bo Ryan Wang obj_hsp_bind(raid_obj_tab_t *raid_tab, raid_obj_id_t *obj_ids,
3581*8bc1b774SToomas Soome     char **plugin_err_str)
3582711890bcSjc {
3583711890bcSjc 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3584711890bcSjc 	raid_obj_id_t array_obj_id, disk_obj_id;
3585711890bcSjc 	hsp_relation_t *hsp_relation;
3586711890bcSjc 	controller_attr_t *controller_attr;
3587711890bcSjc 	array_attr_t *array_attr;
3588711890bcSjc 	arraypart_attr_t *arraypart_attr;
3589711890bcSjc 	disk_attr_t *disk_attr;
3590711890bcSjc 	diskseg_attr_t *diskseg_attr;
3591711890bcSjc 	hsp_attr_t *hsp_attr;
3592711890bcSjc 	raid_lib_t *raid_lib;
35935c9d25d2SYu-Bo Ryan Wang 	int ret, fd;
3594711890bcSjc 
35955c9d25d2SYu-Bo Ryan Wang 	hsp_relation = malloc(sizeof (hsp_relation_t));
3596711890bcSjc 	if (hsp_relation == NULL)
3597711890bcSjc 		return (ERR_NOMEM);
3598711890bcSjc 
35995c9d25d2SYu-Bo Ryan Wang 	array_obj_id = *(obj_ids);
36005c9d25d2SYu-Bo Ryan Wang 	disk_obj_id = *(obj_ids + 1);
3601711890bcSjc 
36025c9d25d2SYu-Bo Ryan Wang 	if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK ||
36035c9d25d2SYu-Bo Ryan Wang 	    (array_obj_id != OBJ_ATTR_NONE &&
36045c9d25d2SYu-Bo Ryan Wang 	    raid_obj_get_type(raid_tab, array_obj_id) !=
36055c9d25d2SYu-Bo Ryan Wang 	    OBJ_TYPE_ARRAY)) {
36065c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
36075c9d25d2SYu-Bo Ryan Wang 		return (ERR_DEVICE_TYPE);
36085c9d25d2SYu-Bo Ryan Wang 	}
3609711890bcSjc 
36105c9d25d2SYu-Bo Ryan Wang 	/* Get controller attributes */
36115c9d25d2SYu-Bo Ryan Wang 	if (controller_obj_id == OBJ_NONE)
36125c9d25d2SYu-Bo Ryan Wang 		controller_obj_id = obj_get_controller(raid_tab,
36135c9d25d2SYu-Bo Ryan Wang 		    disk_obj_id);
36145c9d25d2SYu-Bo Ryan Wang 	else if (controller_obj_id != obj_get_controller(raid_tab,
36155c9d25d2SYu-Bo Ryan Wang 	    disk_obj_id)) {
36165c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
36175c9d25d2SYu-Bo Ryan Wang 		return (ERR_DRIVER_ACROSS);
36185c9d25d2SYu-Bo Ryan Wang 	}
3619711890bcSjc 
36205c9d25d2SYu-Bo Ryan Wang 	ret = obj_get_attr(raid_tab, controller_obj_id,
36215c9d25d2SYu-Bo Ryan Wang 	    (void **)(&controller_attr));
3622711890bcSjc 
36235c9d25d2SYu-Bo Ryan Wang 	/* Get disk attributes */
36245c9d25d2SYu-Bo Ryan Wang 	ret = obj_get_attr(raid_tab,  disk_obj_id,
36255c9d25d2SYu-Bo Ryan Wang 	    (void **)(&disk_attr));
36265c9d25d2SYu-Bo Ryan Wang 	if (disk_attr->state == DISK_STATE_FAILED) {
36275c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
36285c9d25d2SYu-Bo Ryan Wang 		return (ERR_DISK_STATE);
36295c9d25d2SYu-Bo Ryan Wang 	}
3630711890bcSjc 
36315c9d25d2SYu-Bo Ryan Wang 	/* If it's not a hsp disk, check if there's occupied space */
36325c9d25d2SYu-Bo Ryan Wang 	if (obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP) ==
36335c9d25d2SYu-Bo Ryan Wang 	    OBJ_NONE) {
36345c9d25d2SYu-Bo Ryan Wang 		obj_id = obj_get_comp(raid_tab, disk_obj_id,
36355c9d25d2SYu-Bo Ryan Wang 		    OBJ_TYPE_DISK_SEG);
36365c9d25d2SYu-Bo Ryan Wang 		while (obj_id != OBJ_NONE) {
36375c9d25d2SYu-Bo Ryan Wang 			ret = obj_get_attr(raid_tab, obj_id,
36385c9d25d2SYu-Bo Ryan Wang 			    (void **)(&diskseg_attr));
36395c9d25d2SYu-Bo Ryan Wang 			if (!(diskseg_attr->state &
36405c9d25d2SYu-Bo Ryan Wang 			    DISKSEG_STATE_RESERVED)) {
3641711890bcSjc 				free(hsp_relation);
36425c9d25d2SYu-Bo Ryan Wang 				return (ERR_DISK_NOT_EMPTY);
3643711890bcSjc 			}
36445c9d25d2SYu-Bo Ryan Wang 			obj_id = obj_get_sibling(raid_tab, obj_id);
36455c9d25d2SYu-Bo Ryan Wang 		}
36465c9d25d2SYu-Bo Ryan Wang 	}
3647711890bcSjc 
36485c9d25d2SYu-Bo Ryan Wang 	if (array_obj_id != OBJ_ATTR_NONE) {
36495c9d25d2SYu-Bo Ryan Wang 		/* If local hsp is supported */
36505c9d25d2SYu-Bo Ryan Wang 		if (!(controller_attr->capability & RAID_CAP_L_HSP)) {
36515c9d25d2SYu-Bo Ryan Wang 			free(hsp_relation);
36525c9d25d2SYu-Bo Ryan Wang 			return (ERR_OP_ILLEGAL);
36535c9d25d2SYu-Bo Ryan Wang 		}
3654711890bcSjc 
36555c9d25d2SYu-Bo Ryan Wang 		if (raid_obj_get_type(raid_tab, array_obj_id) !=
36565c9d25d2SYu-Bo Ryan Wang 		    OBJ_TYPE_ARRAY) {
36575c9d25d2SYu-Bo Ryan Wang 			free(hsp_relation);
36585c9d25d2SYu-Bo Ryan Wang 			return (ERR_DEVICE_TYPE);
36595c9d25d2SYu-Bo Ryan Wang 		}
3660711890bcSjc 
36615c9d25d2SYu-Bo Ryan Wang 		/* Get array attributes */
36625c9d25d2SYu-Bo Ryan Wang 		ret = obj_get_attr(raid_tab, array_obj_id,
36635c9d25d2SYu-Bo Ryan Wang 		    (void **)(&array_attr));
36645c9d25d2SYu-Bo Ryan Wang 		/* RAID 0 array can not use hsp */
36655c9d25d2SYu-Bo Ryan Wang 		if (array_attr->raid_level == RAID_LEVEL_0) {
3666711890bcSjc 			free(hsp_relation);
36675c9d25d2SYu-Bo Ryan Wang 			return (ERR_ARRAY_LEVEL);
3668711890bcSjc 		}
3669711890bcSjc 
36705c9d25d2SYu-Bo Ryan Wang 		/* If It's belong to another controller */
36715c9d25d2SYu-Bo Ryan Wang 		if (controller_obj_id != obj_get_controller(raid_tab,
36725c9d25d2SYu-Bo Ryan Wang 		    array_obj_id)) {
36735c9d25d2SYu-Bo Ryan Wang 			free(hsp_relation);
36745c9d25d2SYu-Bo Ryan Wang 			return (ERR_DRIVER_ACROSS);
3675711890bcSjc 		}
3676711890bcSjc 
36775c9d25d2SYu-Bo Ryan Wang 		/* Get an array part attributes */
36785c9d25d2SYu-Bo Ryan Wang 		if ((array_attr->raid_level == RAID_LEVEL_10) ||
36795c9d25d2SYu-Bo Ryan Wang 		    (array_attr->raid_level == RAID_LEVEL_50))
36805c9d25d2SYu-Bo Ryan Wang 			obj_id = obj_get_comp(raid_tab, array_obj_id,
36815c9d25d2SYu-Bo Ryan Wang 			    OBJ_TYPE_ARRAY);
3682711890bcSjc 		else
36835c9d25d2SYu-Bo Ryan Wang 			obj_id = array_obj_id;
36845c9d25d2SYu-Bo Ryan Wang 		obj_id = obj_get_comp(raid_tab, obj_id,
36855c9d25d2SYu-Bo Ryan Wang 		    OBJ_TYPE_ARRAY_PART);
36865c9d25d2SYu-Bo Ryan Wang 		ret = obj_get_attr(raid_tab, obj_id,
36875c9d25d2SYu-Bo Ryan Wang 		    (void **)(&arraypart_attr));
36885c9d25d2SYu-Bo Ryan Wang 
36895c9d25d2SYu-Bo Ryan Wang 		/* Check if disk space is enough for array */
36905c9d25d2SYu-Bo Ryan Wang 		if (arraypart_attr->size > disk_attr->capacity) {
36915c9d25d2SYu-Bo Ryan Wang 			free(hsp_relation);
36925c9d25d2SYu-Bo Ryan Wang 			return (ERR_DISK_SPACE);
36935c9d25d2SYu-Bo Ryan Wang 		}
36945c9d25d2SYu-Bo Ryan Wang 		if (controller_attr->capability & RAID_CAP_ARRAY_ALIGN)
36955c9d25d2SYu-Bo Ryan Wang 			if ((arraypart_attr->size +
36965c9d25d2SYu-Bo Ryan Wang 			    arraypart_attr->offset) >
36975c9d25d2SYu-Bo Ryan Wang 			    disk_attr->capacity) {
36985c9d25d2SYu-Bo Ryan Wang 			free(hsp_relation);
36995c9d25d2SYu-Bo Ryan Wang 			return (ERR_DISK_SPACE);
37005c9d25d2SYu-Bo Ryan Wang 			}
37015c9d25d2SYu-Bo Ryan Wang 	} else if (!(controller_attr->capability & RAID_CAP_G_HSP)) {
37025c9d25d2SYu-Bo Ryan Wang 		/* if global hsp is supported */
37035c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
37045c9d25d2SYu-Bo Ryan Wang 		return (ERR_OP_ILLEGAL);
3705711890bcSjc 	}
3706711890bcSjc 
37075c9d25d2SYu-Bo Ryan Wang 	/*
37085c9d25d2SYu-Bo Ryan Wang 	 * If the array is already associated with the
37095c9d25d2SYu-Bo Ryan Wang 	 * local hsp, or it's a global hsp, ignore it
37105c9d25d2SYu-Bo Ryan Wang 	 */
37115c9d25d2SYu-Bo Ryan Wang 	obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
37125c9d25d2SYu-Bo Ryan Wang 	if (obj_id > OBJ_NONE) {
37135c9d25d2SYu-Bo Ryan Wang 		if (obj_get_attr(raid_tab, obj_id,
37145c9d25d2SYu-Bo Ryan Wang 		    (void **)&hsp_attr) >= SUCCESS) {
37155c9d25d2SYu-Bo Ryan Wang 			if (((hsp_attr->type == HSP_TYPE_GLOBAL) &&
37165c9d25d2SYu-Bo Ryan Wang 			    (array_obj_id != OBJ_ATTR_NONE)) ||
37175c9d25d2SYu-Bo Ryan Wang 			    ((hsp_attr->type == HSP_TYPE_LOCAL) &&
37185c9d25d2SYu-Bo Ryan Wang 			    (array_obj_id == OBJ_ATTR_NONE))) {
37195c9d25d2SYu-Bo Ryan Wang 				free(hsp_relation);
37205c9d25d2SYu-Bo Ryan Wang 				return (ERR_OP_ILLEGAL);
37215c9d25d2SYu-Bo Ryan Wang 			}
37225c9d25d2SYu-Bo Ryan Wang 		}
37235c9d25d2SYu-Bo Ryan Wang 	}
3724711890bcSjc 
37255c9d25d2SYu-Bo Ryan Wang 	if (array_obj_id != OBJ_ATTR_NONE)
37265c9d25d2SYu-Bo Ryan Wang 		hsp_relation->array_id = array_attr->array_id;
37275c9d25d2SYu-Bo Ryan Wang 	else
37285c9d25d2SYu-Bo Ryan Wang 		hsp_relation->array_id = (uint32_t)OBJ_ATTR_NONE;
37295c9d25d2SYu-Bo Ryan Wang 	hsp_relation->disk_id = disk_attr->disk_id;
3730711890bcSjc 
3731711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3732711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3733711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
3734711890bcSjc 		return (ERR_DRIVER_CLOSED);
3735711890bcSjc 
3736711890bcSjc 	if (raid_lib->hsp_bind == NULL) {
3737711890bcSjc 		free(hsp_relation);
3738711890bcSjc 		return (ERR_OP_NO_IMPL);
3739711890bcSjc 	}
3740711890bcSjc 
3741711890bcSjc 	ret = raid_lib->hsp_bind(controller_attr->controller_id,
37425c9d25d2SYu-Bo Ryan Wang 	    hsp_relation, plugin_err_str);
3743711890bcSjc 
3744711890bcSjc 	free(hsp_relation);
3745711890bcSjc 	return (ret);
3746711890bcSjc }
3747711890bcSjc 
3748711890bcSjc static int
obj_hsp_unbind(raid_obj_tab_t * raid_tab,raid_obj_id_t * obj_ids,char ** plugin_err_str)37495c9d25d2SYu-Bo Ryan Wang obj_hsp_unbind(raid_obj_tab_t *raid_tab, raid_obj_id_t *obj_ids,
3750*8bc1b774SToomas Soome     char **plugin_err_str)
3751711890bcSjc {
3752711890bcSjc 	raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3753711890bcSjc 	raid_obj_id_t array_obj_id, disk_obj_id;
3754711890bcSjc 	hsp_relation_t *hsp_relation;
3755711890bcSjc 	controller_attr_t *controller_attr;
3756711890bcSjc 	array_attr_t *array_attr;
3757711890bcSjc 	disk_attr_t *disk_attr;
3758711890bcSjc 	hsp_attr_t *hsp_attr;
3759711890bcSjc 	raid_lib_t *raid_lib;
37605c9d25d2SYu-Bo Ryan Wang 	int ret, fd;
3761711890bcSjc 
37625c9d25d2SYu-Bo Ryan Wang 	hsp_relation = malloc(sizeof (hsp_relation_t));
3763711890bcSjc 	if (hsp_relation == NULL)
3764711890bcSjc 		return (ERR_NOMEM);
3765711890bcSjc 
37665c9d25d2SYu-Bo Ryan Wang 	array_obj_id = *(obj_ids);
37675c9d25d2SYu-Bo Ryan Wang 	disk_obj_id = *(obj_ids + 1);
3768711890bcSjc 
37695c9d25d2SYu-Bo Ryan Wang 	if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK) {
37705c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
37715c9d25d2SYu-Bo Ryan Wang 		return (ERR_DEVICE_TYPE);
37725c9d25d2SYu-Bo Ryan Wang 	}
3773711890bcSjc 
37745c9d25d2SYu-Bo Ryan Wang 	/* Get controller attributes */
37755c9d25d2SYu-Bo Ryan Wang 	if (controller_obj_id == OBJ_NONE)
37765c9d25d2SYu-Bo Ryan Wang 		controller_obj_id = obj_get_controller(raid_tab,
37775c9d25d2SYu-Bo Ryan Wang 		    disk_obj_id);
37785c9d25d2SYu-Bo Ryan Wang 	else if (controller_obj_id != obj_get_controller(raid_tab,
37795c9d25d2SYu-Bo Ryan Wang 	    disk_obj_id)) {
37805c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
37815c9d25d2SYu-Bo Ryan Wang 		return (ERR_DRIVER_ACROSS);
37825c9d25d2SYu-Bo Ryan Wang 	}
37835c9d25d2SYu-Bo Ryan Wang 
37845c9d25d2SYu-Bo Ryan Wang 	ret = obj_get_attr(raid_tab, controller_obj_id,
37855c9d25d2SYu-Bo Ryan Wang 	    (void **)(&controller_attr));
3786711890bcSjc 
37875c9d25d2SYu-Bo Ryan Wang 	/* Get disk attributes */
37885c9d25d2SYu-Bo Ryan Wang 	ret = obj_get_attr(raid_tab,  disk_obj_id,
37895c9d25d2SYu-Bo Ryan Wang 	    (void **)(&disk_attr));
37905c9d25d2SYu-Bo Ryan Wang 	if (disk_attr->state == DISK_STATE_FAILED) {
37915c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
37925c9d25d2SYu-Bo Ryan Wang 		return (ERR_DISK_STATE);
37935c9d25d2SYu-Bo Ryan Wang 	}
3794711890bcSjc 
37955c9d25d2SYu-Bo Ryan Wang 	/* If it's not a hsp disk */
37965c9d25d2SYu-Bo Ryan Wang 	obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
37975c9d25d2SYu-Bo Ryan Wang 	if (obj_id == OBJ_NONE) {
37985c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
37995c9d25d2SYu-Bo Ryan Wang 		return (ERR_DISK_STATE);
38005c9d25d2SYu-Bo Ryan Wang 	}
38015c9d25d2SYu-Bo Ryan Wang 	ret = obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
3802711890bcSjc 
38035c9d25d2SYu-Bo Ryan Wang 	if (array_obj_id != OBJ_ATTR_NONE) {
38045c9d25d2SYu-Bo Ryan Wang 		if (raid_obj_get_type(raid_tab, array_obj_id) !=
38055c9d25d2SYu-Bo Ryan Wang 		    OBJ_TYPE_ARRAY) {
3806711890bcSjc 			free(hsp_relation);
38075c9d25d2SYu-Bo Ryan Wang 			return (ERR_DEVICE_TYPE);
3808711890bcSjc 		}
3809711890bcSjc 
38105c9d25d2SYu-Bo Ryan Wang 		/* Get array attributes */
38115c9d25d2SYu-Bo Ryan Wang 		ret = obj_get_attr(raid_tab, array_obj_id,
38125c9d25d2SYu-Bo Ryan Wang 		    (void **)(&array_attr));
3813711890bcSjc 
38145c9d25d2SYu-Bo Ryan Wang 		/* If It's belong to another controller */
38155c9d25d2SYu-Bo Ryan Wang 		if (controller_obj_id != obj_get_controller(raid_tab,
38165c9d25d2SYu-Bo Ryan Wang 		    array_obj_id)) {
3817711890bcSjc 			free(hsp_relation);
38185c9d25d2SYu-Bo Ryan Wang 			return (ERR_DRIVER_ACROSS);
3819711890bcSjc 		}
3820711890bcSjc 
38215c9d25d2SYu-Bo Ryan Wang 		/* If want to remove an array from a global hsp */
38225c9d25d2SYu-Bo Ryan Wang 		if (hsp_attr->type == HSP_TYPE_GLOBAL) {
3823711890bcSjc 			free(hsp_relation);
3824711890bcSjc 			return (ERR_OP_ILLEGAL);
3825711890bcSjc 		}
38265c9d25d2SYu-Bo Ryan Wang 
38275c9d25d2SYu-Bo Ryan Wang 		do {
38285c9d25d2SYu-Bo Ryan Wang 			(void) obj_get_attr(raid_tab, obj_id,
38295c9d25d2SYu-Bo Ryan Wang 			    (void **)(&hsp_attr));
38305c9d25d2SYu-Bo Ryan Wang 
38315c9d25d2SYu-Bo Ryan Wang 			if (hsp_attr->associated_id ==
38325c9d25d2SYu-Bo Ryan Wang 			    array_attr->array_id ||
38335c9d25d2SYu-Bo Ryan Wang 			    hsp_attr->type == HSP_TYPE_GLOBAL)
38345c9d25d2SYu-Bo Ryan Wang 				break;
38355c9d25d2SYu-Bo Ryan Wang 
38365c9d25d2SYu-Bo Ryan Wang 			obj_id = obj_get_sibling(raid_tab, obj_id);
38375c9d25d2SYu-Bo Ryan Wang 		} while (obj_id > OBJ_NONE);
38385c9d25d2SYu-Bo Ryan Wang 	} else if (hsp_attr->type != HSP_TYPE_GLOBAL) {
38395c9d25d2SYu-Bo Ryan Wang 		/* if global hsp is supported */
38405c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
38415c9d25d2SYu-Bo Ryan Wang 		return (ERR_OP_ILLEGAL);
3842711890bcSjc 	}
3843711890bcSjc 
38445c9d25d2SYu-Bo Ryan Wang 	/*
38455c9d25d2SYu-Bo Ryan Wang 	 * If array is associated with a local hsp, or remove a
38465c9d25d2SYu-Bo Ryan Wang 	 * global hsp disk
38475c9d25d2SYu-Bo Ryan Wang 	 */
38485c9d25d2SYu-Bo Ryan Wang 	if ((obj_id && (array_obj_id != OBJ_ATTR_NONE)) ||
38495c9d25d2SYu-Bo Ryan Wang 	    (array_obj_id == OBJ_ATTR_NONE)) {
38505c9d25d2SYu-Bo Ryan Wang 		if (array_obj_id != OBJ_ATTR_NONE)
38515c9d25d2SYu-Bo Ryan Wang 			hsp_relation->array_id = array_attr->array_id;
38525c9d25d2SYu-Bo Ryan Wang 		else
38535c9d25d2SYu-Bo Ryan Wang 			hsp_relation->array_id =
38545c9d25d2SYu-Bo Ryan Wang 			    (uint32_t)OBJ_ATTR_NONE;
38555c9d25d2SYu-Bo Ryan Wang 		hsp_relation->disk_id = disk_attr->disk_id;
38565c9d25d2SYu-Bo Ryan Wang 	} else {
38575c9d25d2SYu-Bo Ryan Wang 		free(hsp_relation);
38585c9d25d2SYu-Bo Ryan Wang 		return (ERR_OP_ILLEGAL);
38595c9d25d2SYu-Bo Ryan Wang 	}
3860711890bcSjc 
3861711890bcSjc 	raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3862711890bcSjc 	fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3863711890bcSjc 	if ((raid_lib == NULL) || (fd == 0))
3864711890bcSjc 		return (ERR_DRIVER_CLOSED);
3865711890bcSjc 
3866711890bcSjc 	if (raid_lib->hsp_unbind == NULL) {
3867711890bcSjc 		free(hsp_relation);
3868711890bcSjc 		return (ERR_OP_NO_IMPL);
3869711890bcSjc 	}
3870711890bcSjc 
3871711890bcSjc 	ret = raid_lib->hsp_unbind(controller_attr->controller_id,
38725c9d25d2SYu-Bo Ryan Wang 	    hsp_relation, plugin_err_str);
3873711890bcSjc 
3874711890bcSjc 	free(hsp_relation);
3875711890bcSjc 	return (ret);
3876711890bcSjc }
3877711890bcSjc 
3878711890bcSjc /*
3879711890bcSjc  * Object maintennance routines
3880711890bcSjc  */
3881711890bcSjc static int
raid_obj_create_system_obj(raid_obj_tab_t * raid_tab)3882711890bcSjc raid_obj_create_system_obj(raid_obj_tab_t *raid_tab)
3883711890bcSjc {
3884711890bcSjc 	raid_obj_t *raid_obj;
3885711890bcSjc 	int ret;
3886711890bcSjc 
3887711890bcSjc 	raid_obj = calloc(1, sizeof (raid_obj_t));
3888711890bcSjc 	if (raid_obj == NULL)
3889711890bcSjc 		return (ERR_NOMEM);
3890711890bcSjc 
3891711890bcSjc 	raid_obj->obj_id = OBJ_SYSTEM;
3892711890bcSjc 	raid_obj->obj_type_id = OBJ_TYPE_SYSTEM;
3893711890bcSjc 	raid_obj->data = NULL;
3894711890bcSjc 
3895711890bcSjc 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3896711890bcSjc 	if (ret == ERR_DEVICE_DUP) {
3897711890bcSjc 		free(raid_obj);
3898711890bcSjc 		return (ERR_DEVICE_UNCLEAN);
3899711890bcSjc 	}
3900711890bcSjc 
3901711890bcSjc 	return (SUCCESS);
3902711890bcSjc }
3903711890bcSjc 
3904711890bcSjc static raid_obj_id_t
raid_obj_id_new(raid_obj_tab_t * raid_tab)3905711890bcSjc raid_obj_id_new(raid_obj_tab_t *raid_tab)
3906711890bcSjc {
3907711890bcSjc 	++ raid_tab->obj_id_cnt;
3908711890bcSjc 	if (raid_tab->obj_id_cnt <= 0)
3909711890bcSjc 		return (ERR_DEVICE_OVERFLOW);
3910711890bcSjc 
3911711890bcSjc 	return (raid_tab->obj_id_cnt);
3912711890bcSjc }
3913711890bcSjc 
3914711890bcSjc static void *
raid_obj_attr_new(raid_obj_type_id_t obj_type)3915711890bcSjc raid_obj_attr_new(raid_obj_type_id_t obj_type)
3916711890bcSjc {
3917711890bcSjc 	void *obj_attr = NULL;
3918711890bcSjc 
3919711890bcSjc 	switch (obj_type) {
3920711890bcSjc 	case	OBJ_TYPE_CONTROLLER:
3921711890bcSjc 		obj_attr = calloc(1, sizeof (controller_attr_t));
3922711890bcSjc 		break;
3923711890bcSjc 	case	OBJ_TYPE_ARRAY:
3924711890bcSjc 		obj_attr = calloc(1, sizeof (array_attr_t));
3925711890bcSjc 		break;
3926711890bcSjc 	case	OBJ_TYPE_DISK:
3927711890bcSjc 		obj_attr = calloc(1, sizeof (disk_attr_t));
3928711890bcSjc 		break;
3929711890bcSjc 	case	OBJ_TYPE_HSP:
3930711890bcSjc 		obj_attr = calloc(1, sizeof (hsp_attr_t));
3931711890bcSjc 		break;
3932711890bcSjc 	case	OBJ_TYPE_ARRAY_PART:
3933711890bcSjc 		obj_attr = calloc(1, sizeof (arraypart_attr_t));
3934711890bcSjc 		break;
3935711890bcSjc 	case	OBJ_TYPE_DISK_SEG:
3936711890bcSjc 		obj_attr = calloc(1, sizeof (diskseg_attr_t));
3937711890bcSjc 		break;
3938711890bcSjc 	case	OBJ_TYPE_TASK:
3939711890bcSjc 		obj_attr = calloc(1, sizeof (task_attr_t));
3940711890bcSjc 		break;
3941b449fa8aSyw 	case	OBJ_TYPE_PROP:
3942b449fa8aSyw 		obj_attr = calloc(1, sizeof (property_attr_t));
3943b449fa8aSyw 		break;
3944711890bcSjc 	default:
3945711890bcSjc 		break;
3946711890bcSjc 	}
3947711890bcSjc 
3948711890bcSjc 	return (obj_attr);
3949711890bcSjc }
3950711890bcSjc 
3951711890bcSjc static raid_obj_id_t
raid_obj_create(raid_obj_tab_t * raid_tab,raid_obj_type_id_t obj_type)3952711890bcSjc raid_obj_create(raid_obj_tab_t *raid_tab, raid_obj_type_id_t obj_type)
3953711890bcSjc {
3954711890bcSjc 	raid_obj_t *raid_obj;
3955711890bcSjc 	int ret;
3956711890bcSjc 	void *data_ptr;
3957711890bcSjc 
3958711890bcSjc 	raid_obj = calloc(1, sizeof (raid_obj_t));
3959711890bcSjc 	if (raid_obj == NULL)
3960711890bcSjc 		return (ERR_NOMEM);
3961711890bcSjc 
3962711890bcSjc 	raid_obj->obj_id = raid_obj_id_new(raid_tab);
3963711890bcSjc 	if (raid_obj->obj_id < OBJ_NONE)
3964711890bcSjc 		return (ERR_DEVICE_OVERFLOW);
3965711890bcSjc 
3966711890bcSjc 	ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3967711890bcSjc 	if (ret == ERR_DEVICE_DUP) {
3968711890bcSjc 		free(raid_obj);
3969711890bcSjc 		return (ERR_DEVICE_DUP);
3970711890bcSjc 	}
3971711890bcSjc 
3972711890bcSjc 	data_ptr = raid_obj_attr_new(obj_type);
3973711890bcSjc 	if (data_ptr == NULL) {
3974711890bcSjc 		(void) raid_obj_delete(raid_tab, raid_obj->obj_id);
3975711890bcSjc 		return (ERR_NOMEM);
3976711890bcSjc 	}
3977711890bcSjc 
3978711890bcSjc 	(void) raid_obj_set_data_ptr(raid_tab, raid_obj->obj_id, data_ptr);
3979711890bcSjc 
3980711890bcSjc 	(void) raid_obj_set_type(raid_tab, raid_obj->obj_id, obj_type);
3981711890bcSjc 	return (raid_obj->obj_id);
3982711890bcSjc }
3983711890bcSjc 
3984711890bcSjc static int
raid_obj_delete(raid_obj_tab_t * raid_tab,raid_obj_id_t raid_obj_id)3985711890bcSjc raid_obj_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t raid_obj_id)
3986711890bcSjc {
3987711890bcSjc 	raid_obj_t *obj;
3988711890bcSjc 
3989711890bcSjc 	obj = raid_obj_tab_remove(raid_tab, raid_obj_id);
3990711890bcSjc 	if (obj != NULL) {
3991711890bcSjc 		free(obj->data);
3992711890bcSjc 		free(obj);
3993711890bcSjc 		return (SUCCESS);
3994711890bcSjc 	}
3995711890bcSjc 
3996711890bcSjc 	return (ERR_DEVICE_NOENT);
3997711890bcSjc }
3998711890bcSjc 
3999711890bcSjc static int
raid_obj_add_org(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_id_t container_id)4000711890bcSjc raid_obj_add_org(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4001*8bc1b774SToomas Soome     raid_obj_id_t container_id)
4002711890bcSjc {
4003711890bcSjc 	raid_obj_id_t tmp, tmp1;
4004711890bcSjc 
4005711890bcSjc 	tmp = raid_obj_get_comp(raid_tab, container_id);
4006711890bcSjc 	if (tmp < OBJ_NONE)
4007711890bcSjc 		return (ERR_DEVICE_NOENT);
4008711890bcSjc 
4009711890bcSjc 	if (tmp == OBJ_NONE) {
4010711890bcSjc 		(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4011711890bcSjc 		(void) raid_obj_set_comp(raid_tab, container_id, obj_id);
4012711890bcSjc 		return (SUCCESS);
4013711890bcSjc 	}
4014711890bcSjc 
4015711890bcSjc 	while ((tmp1 = raid_obj_get_sibling(raid_tab, tmp)) != OBJ_NONE)
4016711890bcSjc 		tmp = tmp1;
4017711890bcSjc 
4018711890bcSjc 	if (raid_obj_set_sibling(raid_tab, tmp, obj_id) < SUCCESS)
4019711890bcSjc 		return (ERR_DEVICE_NOENT);
4020711890bcSjc 	(void) raid_obj_set_container(raid_tab, obj_id, container_id);
4021711890bcSjc 
4022711890bcSjc 	return (SUCCESS);
4023711890bcSjc }
4024711890bcSjc 
4025711890bcSjc static raid_obj_type_id_t
raid_obj_get_type(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)4026711890bcSjc raid_obj_get_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4027711890bcSjc {
4028711890bcSjc 	raid_obj_t *obj;
4029711890bcSjc 
4030711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4031711890bcSjc 	if (obj == NULL)
4032711890bcSjc 		return (ERR_DEVICE_NOENT);
4033711890bcSjc 
4034711890bcSjc 	if ((obj->obj_type_id < OBJ_TYPE_SYSTEM) ||
4035700682b8Syw 	    (obj->obj_type_id >= OBJ_TYPE_ALL))
4036711890bcSjc 		return (ERR_DEVICE_INVALID);
4037711890bcSjc 
4038711890bcSjc 	return (obj->obj_type_id);
4039711890bcSjc }
4040711890bcSjc 
4041711890bcSjc static int
raid_obj_set_type(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_type_id_t type)4042711890bcSjc raid_obj_set_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4043*8bc1b774SToomas Soome     raid_obj_type_id_t type)
4044711890bcSjc {
4045711890bcSjc 	raid_obj_t *obj;
4046711890bcSjc 
4047711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4048711890bcSjc 	if (obj == NULL)
4049711890bcSjc 		return (ERR_DEVICE_NOENT);
4050711890bcSjc 
4051711890bcSjc 	if ((type < OBJ_TYPE_SYSTEM) || (type >= OBJ_TYPE_ALL))
4052711890bcSjc 		return (ERR_DEVICE_TYPE);
4053711890bcSjc 
4054711890bcSjc 	obj->obj_type_id = type;
4055711890bcSjc 	return (SUCCESS);
4056711890bcSjc }
4057711890bcSjc 
4058711890bcSjc static raid_obj_status_t
raid_obj_get_status(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)4059711890bcSjc raid_obj_get_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4060711890bcSjc {
4061711890bcSjc 	raid_obj_t *obj;
4062711890bcSjc 
4063711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4064711890bcSjc 	if (obj == NULL)
4065711890bcSjc 		return (ERR_DEVICE_NOENT);
4066711890bcSjc 
4067711890bcSjc 	return (obj->status);
4068711890bcSjc }
4069711890bcSjc 
4070711890bcSjc static int
raid_obj_set_status(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_status_t status)4071711890bcSjc raid_obj_set_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4072*8bc1b774SToomas Soome     raid_obj_status_t status)
4073711890bcSjc {
4074711890bcSjc 	raid_obj_t *obj;
4075711890bcSjc 
4076711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4077711890bcSjc 	if (obj == NULL)
4078711890bcSjc 		return (ERR_DEVICE_NOENT);
4079711890bcSjc 
4080711890bcSjc 	obj->status = obj->status | status;
4081711890bcSjc 
4082711890bcSjc 	return (SUCCESS);
4083711890bcSjc }
4084711890bcSjc 
4085711890bcSjc static int
raid_obj_clear_status(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_status_t status)4086711890bcSjc raid_obj_clear_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4087*8bc1b774SToomas Soome     raid_obj_status_t status)
4088711890bcSjc {
4089711890bcSjc 	raid_obj_t *obj;
4090711890bcSjc 
4091711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4092711890bcSjc 	if (obj == NULL)
4093711890bcSjc 		return (ERR_DEVICE_NOENT);
4094711890bcSjc 
4095711890bcSjc 	obj->status = obj->status & ~status;
4096711890bcSjc 
4097711890bcSjc 	return (SUCCESS);
4098711890bcSjc }
4099711890bcSjc 
4100711890bcSjc static raid_obj_id_t
raid_obj_get_container(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)4101711890bcSjc raid_obj_get_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4102711890bcSjc {
4103711890bcSjc 	raid_obj_t *obj;
4104711890bcSjc 
4105711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4106711890bcSjc 	if (obj == NULL)
4107711890bcSjc 		return (ERR_DEVICE_NOENT);
4108711890bcSjc 
4109711890bcSjc 	return (obj->container);
4110711890bcSjc }
4111711890bcSjc 
4112711890bcSjc static int
raid_obj_set_container(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_id_t container_id)4113711890bcSjc raid_obj_set_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4114*8bc1b774SToomas Soome     raid_obj_id_t container_id)
4115711890bcSjc {
4116711890bcSjc 	raid_obj_t *obj;
4117711890bcSjc 
4118711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4119711890bcSjc 	if (obj == NULL)
4120711890bcSjc 		return (ERR_DEVICE_NOENT);
4121711890bcSjc 
4122711890bcSjc 	obj->container = container_id;
4123711890bcSjc 	return (SUCCESS);
4124711890bcSjc }
4125711890bcSjc 
4126711890bcSjc static raid_obj_id_t
raid_obj_get_comp(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)4127711890bcSjc raid_obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4128711890bcSjc {
4129711890bcSjc 	raid_obj_t *obj;
4130711890bcSjc 
4131711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4132711890bcSjc 	if (obj == NULL)
4133711890bcSjc 		return (ERR_DEVICE_NOENT);
4134711890bcSjc 
4135711890bcSjc 	return (obj->component);
4136711890bcSjc }
4137711890bcSjc 
4138711890bcSjc static int
raid_obj_set_comp(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_id_t comp)4139711890bcSjc raid_obj_set_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4140*8bc1b774SToomas Soome     raid_obj_id_t comp)
4141711890bcSjc {
4142711890bcSjc 	raid_obj_t *obj;
4143711890bcSjc 
4144711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4145711890bcSjc 	if (obj == NULL)
4146711890bcSjc 		return (ERR_DEVICE_NOENT);
4147711890bcSjc 
4148711890bcSjc 	obj->component = comp;
4149711890bcSjc 	return (SUCCESS);
4150711890bcSjc }
4151711890bcSjc 
4152711890bcSjc static raid_obj_id_t
raid_obj_get_sibling(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)4153711890bcSjc raid_obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4154711890bcSjc {
4155711890bcSjc 	raid_obj_t *obj;
4156711890bcSjc 
4157711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4158711890bcSjc 	if (obj == NULL)
4159711890bcSjc 		return (ERR_DEVICE_NOENT);
4160711890bcSjc 
4161711890bcSjc 	return (obj->sibling);
4162711890bcSjc }
4163711890bcSjc 
4164711890bcSjc static int
raid_obj_set_sibling(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_id_t sibling)4165711890bcSjc raid_obj_set_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4166*8bc1b774SToomas Soome     raid_obj_id_t sibling)
4167711890bcSjc {
4168711890bcSjc 	raid_obj_t *obj;
4169711890bcSjc 
4170711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4171711890bcSjc 	if (obj == NULL)
4172711890bcSjc 		return (ERR_DEVICE_NOENT);
4173711890bcSjc 
4174711890bcSjc 	obj->sibling = sibling;
4175711890bcSjc 
4176711890bcSjc 	return (SUCCESS);
4177711890bcSjc }
4178711890bcSjc 
4179711890bcSjc static void *
raid_obj_get_data_ptr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)4180711890bcSjc raid_obj_get_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4181711890bcSjc {
4182711890bcSjc 	raid_obj_t *obj;
4183711890bcSjc 
4184711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4185711890bcSjc 	if (obj == NULL)
4186711890bcSjc 		return (NULL);
4187711890bcSjc 
4188711890bcSjc 	return (obj->data);
4189711890bcSjc }
4190711890bcSjc 
4191711890bcSjc static int
raid_obj_set_data_ptr(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,void * data)4192711890bcSjc raid_obj_set_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4193*8bc1b774SToomas Soome     void *data)
4194711890bcSjc {
4195711890bcSjc 	raid_obj_t *obj;
4196711890bcSjc 
4197711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4198711890bcSjc 	if (obj == NULL)
4199711890bcSjc 		return (ERR_DEVICE_NOENT);
4200711890bcSjc 
4201711890bcSjc 	obj->data = data;
4202711890bcSjc 
4203711890bcSjc 	return (SUCCESS);
4204711890bcSjc }
4205711890bcSjc 
4206711890bcSjc static raid_obj_handle_t
raid_obj_get_handle(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id)4207711890bcSjc raid_obj_get_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4208711890bcSjc {
4209711890bcSjc 	raid_obj_t *obj;
4210711890bcSjc 
4211711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4212711890bcSjc 	if (obj == NULL)
4213711890bcSjc 		return (ERR_DEVICE_NOENT);
4214711890bcSjc 
4215711890bcSjc 	return (obj->handle);
4216711890bcSjc }
4217711890bcSjc 
4218711890bcSjc static int
raid_obj_set_handle(raid_obj_tab_t * raid_tab,raid_obj_id_t obj_id,raid_obj_handle_t handle)4219711890bcSjc raid_obj_set_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4220*8bc1b774SToomas Soome     raid_obj_handle_t handle)
4221711890bcSjc {
4222711890bcSjc 	raid_obj_t *obj;
4223711890bcSjc 
4224711890bcSjc 	obj = raid_obj_tab_find(raid_tab, obj_id);
4225711890bcSjc 	if (obj == NULL)
4226711890bcSjc 		return (ERR_DEVICE_NOENT);
4227711890bcSjc 
4228711890bcSjc 	obj->handle = handle;
4229711890bcSjc 	return (SUCCESS);
4230711890bcSjc }
4231711890bcSjc /*
4232711890bcSjc  * Object list maintennance routines
4233711890bcSjc  */
4234711890bcSjc static void
raid_list_create(raid_list_t * list,size_t offset)4235711890bcSjc raid_list_create(raid_list_t *list, size_t offset)
4236711890bcSjc {
4237711890bcSjc 	list->head = NULL;
4238711890bcSjc 	list->tail = NULL;
4239711890bcSjc 	list->offset = offset;
4240711890bcSjc }
4241711890bcSjc 
4242711890bcSjc static void *
raid_list_head(raid_list_t * list)4243711890bcSjc raid_list_head(raid_list_t *list)
4244711890bcSjc {
4245711890bcSjc 	return (list->head);
4246711890bcSjc }
4247711890bcSjc 
4248711890bcSjc static void *
raid_list_next(raid_list_t * list,void * obj)4249711890bcSjc raid_list_next(raid_list_t *list, void *obj)
4250711890bcSjc {
4251711890bcSjc 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj);
4252711890bcSjc 
4253711890bcSjc 	return (el->next);
4254711890bcSjc }
4255711890bcSjc 
4256711890bcSjc static void
raid_list_insert_tail(raid_list_t * list,void * obj)4257711890bcSjc raid_list_insert_tail(raid_list_t *list, void *obj)
4258711890bcSjc {
4259711890bcSjc 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4260711890bcSjc 
4261711890bcSjc 	el->prev = list->tail;
4262711890bcSjc 	list->tail = obj;
4263711890bcSjc 
4264711890bcSjc 	el->next = NULL;
4265711890bcSjc 
4266711890bcSjc 	if (list->head == NULL)
4267711890bcSjc 		list->head = obj;
4268711890bcSjc 
4269711890bcSjc 	if (el->prev != NULL) {
4270711890bcSjc 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4271711890bcSjc 		el1->next = obj;
4272711890bcSjc 	}
4273711890bcSjc }
4274711890bcSjc 
4275711890bcSjc static void
raid_list_remove(raid_list_t * list,void * obj)4276711890bcSjc raid_list_remove(raid_list_t *list, void *obj)
4277711890bcSjc {
4278711890bcSjc 	raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4279711890bcSjc 
4280711890bcSjc 	if (list->head == obj)
4281711890bcSjc 		list->head = el->next;
4282711890bcSjc 
4283711890bcSjc 	if (list->tail == obj)
4284711890bcSjc 		list->tail = el->prev;
4285711890bcSjc 
4286711890bcSjc 	if (el->next != NULL) {
4287711890bcSjc 		el1 = LIST_OBJ_TO_EL(list, el->next);
4288711890bcSjc 		el1->prev = el->prev;
4289711890bcSjc 	}
4290711890bcSjc 
4291711890bcSjc 	if (el->prev != NULL) {
4292711890bcSjc 		el1 = LIST_OBJ_TO_EL(list, el->prev);
4293711890bcSjc 		el1->next = el->next;
4294711890bcSjc 	}
4295711890bcSjc 
4296711890bcSjc 	el->prev = el->next = NULL;
4297711890bcSjc }
4298711890bcSjc 
4299711890bcSjc static void *
raid_list_remove_head(raid_list_t * list)4300711890bcSjc raid_list_remove_head(raid_list_t *list)
4301711890bcSjc {
4302711890bcSjc 	void *obj = list->head;
4303711890bcSjc 
4304711890bcSjc 	if (obj != NULL)
4305711890bcSjc 		raid_list_remove(list, obj);
4306711890bcSjc 
4307711890bcSjc 	return (obj);
4308711890bcSjc }
4309711890bcSjc 
4310711890bcSjc static void *
raid_list_find(raid_list_t * list,raid_obj_id_t obj_id)4311711890bcSjc raid_list_find(raid_list_t *list, raid_obj_id_t obj_id)
4312711890bcSjc {
4313711890bcSjc 	raid_obj_t *obj;
4314711890bcSjc 
4315711890bcSjc 	for (obj = raid_list_head(list); obj != NULL;
4316700682b8Syw 	    obj = raid_list_next(list, obj))
4317711890bcSjc 			if (obj->obj_id == obj_id)
4318711890bcSjc 				break;
4319711890bcSjc 
4320711890bcSjc 	return (obj);
4321711890bcSjc }
4322711890bcSjc 
4323711890bcSjc static int
raid_obj_tab_create(raid_obj_tab_t * tab,size_t hash_slots)4324711890bcSjc raid_obj_tab_create(raid_obj_tab_t *tab, size_t hash_slots)
4325711890bcSjc {
4326711890bcSjc 	unsigned i;
4327711890bcSjc 
4328711890bcSjc 	if (hash_slots == 0)
4329711890bcSjc 		return (ERR_OP_ILLEGAL);
4330711890bcSjc 
4331711890bcSjc 	tab->slots = hash_slots;
4332711890bcSjc 
4333711890bcSjc 	if ((tab->table = calloc(hash_slots, sizeof (raid_list_t))) == NULL)
4334711890bcSjc 		return (ERR_NOMEM);
4335711890bcSjc 
4336711890bcSjc 	for (i = 0; i < hash_slots; i++)
4337711890bcSjc 		raid_list_create(&tab->table[i], offsetof(raid_obj_t, el));
4338711890bcSjc 
4339711890bcSjc 	return (SUCCESS);
4340711890bcSjc }
4341711890bcSjc 
4342711890bcSjc static void
raid_obj_tab_destroy(raid_obj_tab_t * tab)4343711890bcSjc raid_obj_tab_destroy(raid_obj_tab_t *tab)
4344711890bcSjc {
4345711890bcSjc 	unsigned i;
4346711890bcSjc 
4347711890bcSjc 	for (i = 0; i < tab->slots; i++) {
4348711890bcSjc 		struct raid_obj_t *obj;
4349711890bcSjc 
4350711890bcSjc 		while ((obj = raid_list_remove_head(&tab->table[i])) != NULL)
4351711890bcSjc 			free(obj);
4352711890bcSjc 
4353711890bcSjc 		raid_list_destroy(&tab->table[i]);
4354711890bcSjc 	}
4355711890bcSjc 
4356711890bcSjc 	if (tab->table)
4357711890bcSjc 		free(tab->table);
4358711890bcSjc 
4359711890bcSjc 	tab->table = NULL;
4360711890bcSjc 	tab->slots = 0;
4361711890bcSjc 	tab->obj_id_cnt = 0;
4362711890bcSjc }
4363711890bcSjc 
4364711890bcSjc static int
raid_obj_tab_insert(raid_obj_tab_t * tab,raid_obj_id_t id,void * obj)4365711890bcSjc raid_obj_tab_insert(raid_obj_tab_t *tab, raid_obj_id_t id, void *obj)
4366711890bcSjc {
4367711890bcSjc 	raid_list_t *list;
4368711890bcSjc 
4369711890bcSjc 	list = OBJ_TAB_SLOT(tab, id);
4370711890bcSjc 
4371711890bcSjc 	if (raid_list_find(list, id) != NULL)
4372711890bcSjc 		return (ERR_DEVICE_DUP);
4373711890bcSjc 
4374711890bcSjc 	raid_list_insert_tail(list, obj);
4375711890bcSjc 
4376711890bcSjc 	return (SUCCESS);
4377711890bcSjc }
4378711890bcSjc 
4379711890bcSjc static void *
raid_obj_tab_remove(raid_obj_tab_t * tab,raid_obj_id_t id)4380711890bcSjc raid_obj_tab_remove(raid_obj_tab_t *tab, raid_obj_id_t id)
4381711890bcSjc {
4382711890bcSjc 	raid_list_t *list;
4383711890bcSjc 	raid_obj_t *obj;
4384711890bcSjc 
4385711890bcSjc 	list = OBJ_TAB_SLOT(tab, id);
4386711890bcSjc 
4387711890bcSjc 	if ((obj = raid_list_find(list, id)) != NULL)
4388711890bcSjc 		raid_list_remove(list, obj);
4389711890bcSjc 
4390711890bcSjc 	return (obj);
4391711890bcSjc }
4392711890bcSjc 
4393711890bcSjc static void *
raid_obj_tab_find(raid_obj_tab_t * tab,raid_obj_id_t id)4394711890bcSjc raid_obj_tab_find(raid_obj_tab_t *tab, raid_obj_id_t id)
4395711890bcSjc {
4396711890bcSjc 	raid_list_t *list;
4397711890bcSjc 	raid_obj_t *obj;
4398711890bcSjc 
4399711890bcSjc 	list = OBJ_TAB_SLOT(tab, id);
4400711890bcSjc 	obj = raid_list_find(list, id);
4401711890bcSjc 
4402711890bcSjc 	return (obj);
4403711890bcSjc }
4404711890bcSjc 
4405711890bcSjc static void
raid_list_destroy(raid_list_t * list)4406711890bcSjc raid_list_destroy(raid_list_t *list)
4407711890bcSjc {
4408711890bcSjc 	list->head = NULL;
4409711890bcSjc 	list->tail = NULL;
4410711890bcSjc 	list->offset = 0;
4411711890bcSjc }
4412711890bcSjc 
4413711890bcSjc /*
4414711890bcSjc  * Plug-in maintennance routines
4415711890bcSjc  */
4416711890bcSjc static int
controller_id_to_path(uint32_t controller_id,char * path)4417711890bcSjc controller_id_to_path(uint32_t controller_id, char *path)
4418711890bcSjc {
4419317fb4acSYu-Bo Ryan Wang 	int fd;
4420711890bcSjc 	char buf[MAX_PATH_LEN] = {0}, buf1[MAX_PATH_LEN] = {0}, *colon;
4421711890bcSjc 
4422711890bcSjc 	(void) snprintf(buf, MAX_PATH_LEN, "%s/c%d", CFGDIR, controller_id);
4423711890bcSjc 	if (readlink(buf, buf1, sizeof (buf1)) < 0)
4424711890bcSjc 		return (ERR_DRIVER_NOT_FOUND);
4425711890bcSjc 
4426711890bcSjc 	if (buf1[0] != '/')
4427711890bcSjc 		(void) snprintf(buf, sizeof (buf), "%s/", CFGDIR);
4428711890bcSjc 	else
4429711890bcSjc 		buf[0] = 0;
4430711890bcSjc 	(void) strlcat(buf, buf1, MAX_PATH_LEN);
4431711890bcSjc 
4432711890bcSjc 	colon = strrchr(buf, ':');
4433711890bcSjc 	if (colon == NULL)
4434711890bcSjc 		return (ERR_DRIVER_NOT_FOUND);
4435711890bcSjc 	else
4436711890bcSjc 		*colon = 0;
4437711890bcSjc 
4438711890bcSjc 	(void) snprintf(path, MAX_PATH_LEN, "%s:devctl", buf);
4439711890bcSjc 
4440317fb4acSYu-Bo Ryan Wang 	fd = open(path, O_RDONLY | O_NDELAY);
4441317fb4acSYu-Bo Ryan Wang 
4442317fb4acSYu-Bo Ryan Wang 	if (fd < 0)
4443711890bcSjc 		return (ERR_DRIVER_NOT_FOUND);
4444711890bcSjc 
4445317fb4acSYu-Bo Ryan Wang 	(void) close(fd);
4446317fb4acSYu-Bo Ryan Wang 
4447711890bcSjc 	return (SUCCESS);
4448711890bcSjc }
4449711890bcSjc 
4450711890bcSjc static char *
controller_id_to_driver_name(uint32_t controller_id)4451711890bcSjc controller_id_to_driver_name(uint32_t controller_id)
4452711890bcSjc {
4453711890bcSjc 	char buf[MAX_PATH_LEN];
4454711890bcSjc 	di_node_t di_node;
4455711890bcSjc 	char *name, *tmp;
4456711890bcSjc 	int ret;
4457711890bcSjc 
4458711890bcSjc 	ret = controller_id_to_path(controller_id, buf);
4459711890bcSjc 	if (ret < SUCCESS)
4460711890bcSjc 		return (NULL);
4461711890bcSjc 
4462711890bcSjc 	tmp = strrchr(buf, ':');
4463711890bcSjc 	if (tmp != NULL)
4464711890bcSjc 		*tmp = 0;
4465711890bcSjc 
4466711890bcSjc 	tmp = strstr(buf, "pci");
4467711890bcSjc 	if (tmp == NULL)
4468711890bcSjc 		return (NULL);
4469711890bcSjc 
4470711890bcSjc 	di_node = di_init(tmp, DINFOPROP);
4471711890bcSjc 	if (di_node == DI_NODE_NIL)
4472711890bcSjc 		return (NULL);
4473711890bcSjc 
4474711890bcSjc 	name = di_driver_name(di_node);
4475711890bcSjc 
4476711890bcSjc 	return (name);
4477711890bcSjc }
4478711890bcSjc 
4479711890bcSjc static void
raid_plugin_init()4480711890bcSjc raid_plugin_init()
4481711890bcSjc {
4482711890bcSjc 	raid_lib_t *raid_lib = raid_lib_sys;
4483711890bcSjc 
4484711890bcSjc 	while (raid_lib) {
4485711890bcSjc 		raid_lib_sys = raid_lib->next;
4486711890bcSjc 		(void) dlclose(raid_lib->lib_handle);
4487711890bcSjc 		free(raid_lib);
4488711890bcSjc 		raid_lib = raid_lib_sys;
4489711890bcSjc 	}
4490711890bcSjc }
4491711890bcSjc 
4492711890bcSjc static raid_lib_t *
raid_plugin_load(char * driver_name)4493711890bcSjc raid_plugin_load(char *driver_name)
4494711890bcSjc {
4495711890bcSjc 	char buf[MAX_PATH_LEN] = {0};
4496711890bcSjc 	raid_lib_t *supplib;
4497711890bcSjc 	void *sym;
4498711890bcSjc 
4499711890bcSjc 	supplib = calloc(1, sizeof (raid_lib_t));
4500711890bcSjc 	if (supplib == NULL)
4501711890bcSjc 		return (NULL);
4502711890bcSjc 
4503711890bcSjc 	(void) snprintf(buf, MAX_PATH_LEN, "%s/%s.so.1",
4504700682b8Syw 	    SUPP_PLUGIN_DIR, driver_name);
4505711890bcSjc 
4506711890bcSjc 	supplib->lib_handle = dlopen(buf, RTLD_LAZY);
4507711890bcSjc 	if (supplib->lib_handle == NULL) {
4508711890bcSjc 		free(supplib);
4509711890bcSjc 		return (NULL);
4510711890bcSjc 	}
4511711890bcSjc 
4512711890bcSjc 	supplib->name = driver_name;
4513711890bcSjc 
4514711890bcSjc 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_version")) == NULL)
4515711890bcSjc 		supplib->version = RDCFG_PLUGIN_V1;
4516711890bcSjc 	else {
4517711890bcSjc 		supplib->version = *((uint32_t *)sym);
4518711890bcSjc 		if (supplib->version != RDCFG_PLUGIN_V1) {
4519711890bcSjc 			(void) dlclose(supplib->lib_handle);
4520711890bcSjc 			free(supplib);
4521711890bcSjc 			return (NULL);
4522711890bcSjc 		}
4523711890bcSjc 	}
4524711890bcSjc 
4525711890bcSjc 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_open_controller")) ==
4526700682b8Syw 	    NULL) {
4527711890bcSjc 		(void) dlclose(supplib->lib_handle);
4528711890bcSjc 		free(supplib);
4529711890bcSjc 		return (NULL);
4530711890bcSjc 	} else
4531711890bcSjc 		supplib->open_controller = (int(*)(uint32_t, char **))sym;
4532711890bcSjc 
4533711890bcSjc 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_close_controller")) ==
4534700682b8Syw 	    NULL) {
4535711890bcSjc 		(void) dlclose(supplib->lib_handle);
4536711890bcSjc 		free(supplib);
4537711890bcSjc 		return (NULL);
4538711890bcSjc 	} else
4539711890bcSjc 		supplib->close_controller = (int (*)(uint32_t, char **))sym;
4540711890bcSjc 
4541711890bcSjc 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_compnum")) == NULL) {
4542711890bcSjc 		(void) dlclose(supplib->lib_handle);
4543711890bcSjc 		free(supplib);
4544711890bcSjc 		return (NULL);
4545711890bcSjc 	} else
4546711890bcSjc 		supplib->compnum = (int (*)(uint32_t, uint32_t,
4547711890bcSjc 		    raid_obj_type_id_t, raid_obj_type_id_t))sym;
4548711890bcSjc 
4549711890bcSjc 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_complist")) == NULL) {
4550711890bcSjc 		(void) dlclose(supplib->lib_handle);
4551711890bcSjc 		free(supplib);
4552711890bcSjc 		return (NULL);
4553711890bcSjc 	} else
4554711890bcSjc 		supplib->complist = (int (*)(uint32_t, uint32_t,
4555711890bcSjc 		    raid_obj_type_id_t, raid_obj_type_id_t, int, void *))sym;
4556711890bcSjc 
4557711890bcSjc 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_get_attr")) == NULL) {
4558711890bcSjc 		(void) dlclose(supplib->lib_handle);
4559711890bcSjc 		free(supplib);
4560711890bcSjc 		return (NULL);
4561711890bcSjc 	} else
4562711890bcSjc 		supplib->get_attr = (int (*)(uint32_t, uint32_t, uint32_t,
4563711890bcSjc 		    raid_obj_type_id_t, void*))sym;
4564711890bcSjc 
4565711890bcSjc 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_create")) == NULL) {
4566711890bcSjc 		(void) dlclose(supplib->lib_handle);
4567711890bcSjc 		free(supplib);
4568711890bcSjc 		return (NULL);
4569711890bcSjc 	} else
4570711890bcSjc 		supplib->array_create = (int (*)(uint32_t, array_attr_t *, int,
4571711890bcSjc 		    arraypart_attr_t *, char **))sym;
4572711890bcSjc 
4573711890bcSjc 	if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_delete")) == NULL) {
4574711890bcSjc 		(void) dlclose(supplib->lib_handle);
4575711890bcSjc 		free(supplib);
4576711890bcSjc 		return (NULL);
4577711890bcSjc 	} else
4578711890bcSjc 		supplib->array_delete =
4579711890bcSjc 		    (int (*)(uint32_t, uint32_t, char **))sym;
4580711890bcSjc 
45815c9d25d2SYu-Bo Ryan Wang 	supplib->hsp_bind = (int (*)(uint32_t, hsp_relation_t *,
4582711890bcSjc 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_bind");
45835c9d25d2SYu-Bo Ryan Wang 	supplib->hsp_unbind = (int (*)(uint32_t, hsp_relation_t *,
4584711890bcSjc 	    char **))dlsym(supplib->lib_handle, "rdcfg_hsp_unbind");
4585711890bcSjc 	supplib->set_attr = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t *,
4586711890bcSjc 	    char **))dlsym(supplib->lib_handle, "rdcfg_set_attr");
4587711890bcSjc 	supplib->flash_fw = (int (*)(uint32_t, char *, uint32_t, char **))
4588711890bcSjc 	    dlsym(supplib->lib_handle, "rdcfg_flash_fw");
4589711890bcSjc 
4590711890bcSjc 	supplib->next = raid_lib_sys;
4591711890bcSjc 	raid_lib_sys = supplib;
4592711890bcSjc 	return (supplib);
4593711890bcSjc }
4594711890bcSjc 
4595711890bcSjc static raid_lib_t *
raid_find_lib(raid_obj_tab_t * raid_tab,raid_obj_id_t controller_obj_id)4596711890bcSjc raid_find_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t controller_obj_id)
4597711890bcSjc {
4598711890bcSjc 	controller_attr_t *controller_attr;
4599711890bcSjc 	raid_lib_t *raid_lib;
4600711890bcSjc 	char *driver_name;
4601711890bcSjc 	raid_obj_handle_t handle;
4602711890bcSjc 
4603711890bcSjc 	/* Check if it's mapped to handle structure */
4604711890bcSjc 	handle = raid_obj_to_handle(raid_tab, controller_obj_id);
4605711890bcSjc 	if (raid_handle_sys.handles[handle].raid_lib != NULL)
4606711890bcSjc 		return (raid_handle_sys.handles[handle].raid_lib);
4607711890bcSjc 
4608711890bcSjc 	(void) obj_get_attr(raid_tab, controller_obj_id,
4609700682b8Syw 	    (void **)(&controller_attr));
4610711890bcSjc 
4611711890bcSjc 	/* Check if the plugin module is already loaded */
4612711890bcSjc 	driver_name = controller_id_to_driver_name(
4613700682b8Syw 	    controller_attr->controller_id);
4614711890bcSjc 	if (driver_name == NULL)
4615711890bcSjc 		return (NULL);
4616711890bcSjc 
4617711890bcSjc 	raid_lib = raid_lib_sys;
4618711890bcSjc 	while (raid_lib != NULL) {
4619711890bcSjc 		if (raid_lib->name != NULL &&
4620700682b8Syw 		    strcmp(driver_name, raid_lib->name) == 0)
4621711890bcSjc 			return (raid_lib);
4622711890bcSjc 
4623711890bcSjc 		raid_lib = raid_lib->next;
4624711890bcSjc 	}
4625711890bcSjc 
4626711890bcSjc 	/* Loading the plugin module */
4627711890bcSjc 	raid_lib = raid_plugin_load(driver_name);
4628711890bcSjc 
4629711890bcSjc 	return (raid_lib);
4630711890bcSjc }
4631