sd: remove 'ssd' driver support
[unleashed/tickless.git] / usr / src / lib / libraidcfg / common / raidcfg.c
bloba7fa2e81e64e97ae3fc203d3457d676b33c1ce76
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Milan Jurik. All rights reserved.
28 #include <fcntl.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <stddef.h>
32 #include <stdlib.h>
33 #include <dirent.h>
34 #include <dlfcn.h>
35 #include <link.h>
36 #include <strings.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <sys/mnttab.h>
40 #include <config_admin.h>
41 #include <sys/param.h>
42 #include <libintl.h>
43 #include <libdevinfo.h>
44 #include <raidcfg.h>
45 #include <thread.h>
46 #include <synch.h>
48 #ifndef TEXT_DOMAIN
49 #define TEXT_DOMAIN "SYS_TEST"
50 #endif
52 #define HASH_SLOTS 16
53 #define HANDLER_SLOTS 256
56 * Raid object status;
58 #define OBJ_STATUS_CMD_CLEAN -1
59 #define OBJ_STATUS_OPENED 1
60 #define OBJ_STATUS_SCANCOMP 1 << 1
62 #if defined(__sparcv9)
63 #define SUPP_PLUGIN_DIR "/usr/lib/raidcfg/sparcv9"
64 #elif defined(__amd64)
65 #define SUPP_PLUGIN_DIR "/usr/lib/raidcfg/amd64"
66 #else
67 #define SUPP_PLUGIN_DIR "/usr/lib/raidcfg"
68 #endif
71 * Basic types
73 typedef int raid_obj_id_t;
74 typedef int raid_obj_status_t;
77 * Data structures used for object maintennance
79 typedef struct {
80 void *head;
81 void *tail;
82 size_t offset; /* offset of double-linked element (raid_list_el_t) */
83 /* in the linked data structures (objects) */
84 } raid_list_t;
86 typedef struct {
87 void *prev;
88 void *next;
89 } raid_list_el_t;
91 typedef struct {
92 raid_obj_id_t obj_id_cnt; /* id 0 is reserved */
93 size_t slots; /* How many lists linked by *table */
94 raid_list_t *table;
95 } raid_obj_tab_t;
98 * Object type structure containing function pointers;
100 typedef struct {
101 int (*compnum)(raid_obj_tab_t *, raid_obj_id_t, raid_obj_type_id_t);
102 int (*complist)(raid_obj_tab_t *, raid_obj_id_t, int, raid_obj_id_t *,
103 raid_obj_type_id_t);
104 int (*get_attr)(raid_obj_tab_t *, raid_obj_id_t);
105 int (*set_attr)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, uint32_t *,
106 char **);
107 int (*act)(raid_obj_tab_t *, raid_obj_id_t, uint32_t, void *, char **);
108 int (*create_obj)(raid_obj_tab_t *, raid_obj_id_t, int,
109 raid_obj_id_t *, char **);
110 int (*delete_obj)(raid_obj_tab_t *, raid_obj_id_t, char **);
111 int (*bind_obj)(raid_obj_tab_t *, raid_obj_id_t *, char **);
112 int (*unbind_obj)(raid_obj_tab_t *, raid_obj_id_t *, char **);
113 } raid_obj_op_t;
116 * Common object data structure
118 typedef struct {
119 raid_list_el_t el; /* double-links */
121 raid_obj_type_id_t obj_type_id;
122 raid_obj_id_t obj_id;
123 raid_obj_status_t status;
125 raid_obj_id_t container;
126 raid_obj_id_t sibling;
127 raid_obj_id_t component;
129 void *data; /* Pointer to attribute structure */
130 raid_obj_handle_t handle;
131 } raid_obj_t;
134 * Definition about handle
136 typedef struct {
137 uint32_t next;
138 uint32_t type;
139 uint32_t controller_id;
140 uint32_t array_id;
141 uint32_t disk_id;
142 uint64_t seq_id;
143 uint32_t task_id;
144 uint32_t prop_id;
145 uint32_t fd; /* Only for controller */
146 raid_lib_t *raid_lib; /* Only for controller */
147 } handle_attr_t;
149 #define LIST_OBJ_TO_EL(list, obj) \
150 ((void *)((char *)(obj) + (list)->offset))
151 #define OBJ_TAB_SLOT(tab, id) \
152 ((tab)->table + ((id)%(tab)->slots))
154 #pragma init(raidcfg_init)
155 #pragma fini(raidcfg_fini)
158 * Function prototypes
160 static int intcompare(const void *p1, const void *p2);
161 static uint64_t raid_space_noalign(raid_obj_tab_t *, uint32_t, int,
162 raid_obj_id_t *, arraypart_attr_t *);
163 static int raid_handle_init();
164 static void raid_handle_fini();
165 static raid_obj_handle_t raid_handle_new(raid_obj_type_id_t);
166 static void raid_handle_delete(raid_obj_handle_t);
167 static void raid_handle_delete_controller_comp(uint32_t);
168 static raid_obj_id_t raid_handle_to_obj(raid_obj_tab_t *,
169 raid_obj_handle_t);
170 static raid_obj_handle_t raid_obj_to_handle(raid_obj_tab_t *,
171 raid_obj_id_t);
172 static raid_lib_t *raid_obj_get_lib(raid_obj_tab_t *, raid_obj_id_t);
173 static int raid_obj_set_lib(raid_obj_tab_t *, raid_obj_id_t, raid_lib_t *);
174 static int raid_obj_get_fd(raid_obj_tab_t *, raid_obj_id_t);
175 static int raid_obj_set_fd(raid_obj_tab_t *, raid_obj_id_t, int);
176 static int obj_scan_comp(raid_obj_tab_t *, raid_obj_id_t);
177 static int obj_rescan(raid_obj_tab_t *);
178 static raid_obj_id_t obj_get_comp(raid_obj_tab_t *, raid_obj_id_t,
179 raid_obj_type_id_t);
180 static raid_obj_id_t obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
181 static int obj_get_attr(raid_obj_tab_t *, raid_obj_id_t, void **);
182 static raid_obj_id_t obj_locate_controller(raid_obj_tab_t *, uint32_t);
183 static raid_obj_id_t obj_locate_array(raid_obj_tab_t *, uint32_t, uint32_t);
184 static raid_obj_id_t obj_locate_array_recur(raid_obj_tab_t *, raid_obj_id_t,
185 uint32_t);
186 static raid_obj_id_t obj_locate_hsp(raid_obj_tab_t *, uint32_t,
187 uint32_t, uint32_t);
188 static raid_obj_id_t obj_locate_disk(raid_obj_tab_t *, uint32_t, uint32_t);
189 static raid_obj_id_t obj_locate_arraypart(raid_obj_tab_t *, uint32_t,
190 uint32_t, uint32_t);
191 static raid_obj_id_t obj_locate_diskseg(raid_obj_tab_t *, uint32_t,
192 uint32_t, uint32_t);
193 static raid_obj_id_t obj_locate_task(raid_obj_tab_t *, uint32_t, uint32_t);
194 static raid_obj_id_t obj_locate_prop(raid_obj_tab_t *, uint32_t, uint32_t,
195 uint32_t);
196 static raid_obj_id_t obj_get_controller(raid_obj_tab_t *, raid_obj_id_t);
198 static int obj_sys_compnum(raid_obj_tab_t *, raid_obj_id_t,
199 raid_obj_type_id_t);
200 static int obj_sys_complist(raid_obj_tab_t *, raid_obj_id_t, int,
201 raid_obj_id_t *, raid_obj_type_id_t);
202 static int obj_controller_compnum(raid_obj_tab_t *, raid_obj_id_t,
203 raid_obj_type_id_t);
204 static int obj_controller_complist(raid_obj_tab_t *, raid_obj_id_t, int,
205 raid_obj_id_t *, raid_obj_type_id_t);
206 static int obj_controller_get_attr(raid_obj_tab_t *, raid_obj_id_t);
207 static int obj_controller_act(raid_obj_tab_t *, raid_obj_id_t,
208 uint32_t, void *, char **);
209 static int obj_array_compnum(raid_obj_tab_t *, raid_obj_id_t,
210 raid_obj_type_id_t);
211 static int obj_array_complist(raid_obj_tab_t *, raid_obj_id_t, int,
212 raid_obj_id_t *, raid_obj_type_id_t);
213 static int obj_array_get_attr(raid_obj_tab_t *, raid_obj_id_t);
214 static int obj_array_set_attr(raid_obj_tab_t *, raid_obj_id_t,
215 uint32_t, uint32_t *, char **);
216 static int obj_disk_compnum(raid_obj_tab_t *, raid_obj_id_t,
217 raid_obj_type_id_t);
218 static int obj_disk_complist(raid_obj_tab_t *, raid_obj_id_t, int,
219 raid_obj_id_t *, raid_obj_type_id_t);
220 static int obj_disk_get_attr(raid_obj_tab_t *, raid_obj_id_t);
221 static int obj_hsp_get_attr(raid_obj_tab_t *, raid_obj_id_t);
222 static int obj_arraypart_get_attr(raid_obj_tab_t *, raid_obj_id_t);
223 static int obj_diskseg_get_attr(raid_obj_tab_t *, raid_obj_id_t);
224 static int obj_task_get_attr(raid_obj_tab_t *, raid_obj_id_t);
225 static int obj_prop_get_attr(raid_obj_tab_t *, raid_obj_id_t);
226 static int obj_array_create(raid_obj_tab_t *, raid_obj_id_t, int,
227 raid_obj_id_t *, char **);
228 static int obj_array_delete(raid_obj_tab_t *, raid_obj_id_t, char **);
229 static int obj_hsp_bind(raid_obj_tab_t *, raid_obj_id_t *, char **);
230 static int obj_hsp_unbind(raid_obj_tab_t *, raid_obj_id_t *, char **);
232 static int raid_obj_create_system_obj(raid_obj_tab_t *);
233 static raid_obj_id_t raid_obj_id_new(raid_obj_tab_t *);
234 static void *raid_obj_attr_new(raid_obj_type_id_t);
235 static raid_obj_id_t raid_obj_create(raid_obj_tab_t *, raid_obj_type_id_t);
236 static int raid_obj_delete(raid_obj_tab_t *, raid_obj_id_t);
237 static int raid_obj_add_org(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
238 static raid_obj_type_id_t raid_obj_get_type(raid_obj_tab_t *, raid_obj_id_t);
239 static int raid_obj_set_type(raid_obj_tab_t *, raid_obj_id_t,
240 raid_obj_type_id_t);
241 static raid_obj_status_t raid_obj_get_status(raid_obj_tab_t *, raid_obj_id_t);
242 static int raid_obj_set_status(raid_obj_tab_t *, raid_obj_id_t,
243 raid_obj_status_t);
244 static int raid_obj_clear_status(raid_obj_tab_t *, raid_obj_id_t,
245 raid_obj_status_t);
246 static raid_obj_id_t raid_obj_get_container(raid_obj_tab_t *, raid_obj_id_t);
247 static int raid_obj_set_container(raid_obj_tab_t *, raid_obj_id_t,
248 raid_obj_id_t);
249 static raid_obj_id_t raid_obj_get_comp(raid_obj_tab_t *, raid_obj_id_t);
250 static int raid_obj_set_comp(raid_obj_tab_t *, raid_obj_id_t, raid_obj_id_t);
251 static raid_obj_id_t raid_obj_get_sibling(raid_obj_tab_t *, raid_obj_id_t);
252 static int raid_obj_set_sibling(raid_obj_tab_t *, raid_obj_id_t,
253 raid_obj_id_t);
254 static void *raid_obj_get_data_ptr(raid_obj_tab_t *, raid_obj_id_t);
255 static int raid_obj_set_data_ptr(raid_obj_tab_t *, raid_obj_id_t, void *);
256 static raid_obj_handle_t raid_obj_get_handle(raid_obj_tab_t *,
257 raid_obj_id_t);
258 static int raid_obj_set_handle(raid_obj_tab_t *, raid_obj_id_t,
259 raid_obj_handle_t);
261 static void raid_list_create(raid_list_t *, size_t);
262 static void *raid_list_head(raid_list_t *);
263 static void *raid_list_next(raid_list_t *, void *);
264 static void raid_list_insert_tail(raid_list_t *, void *);
265 static void raid_list_remove(raid_list_t *, void *);
266 static void *raid_list_remove_head(raid_list_t *);
267 static void *raid_list_find(raid_list_t *, raid_obj_id_t);
268 static int raid_obj_tab_create(raid_obj_tab_t *, size_t);
269 static void raid_obj_tab_destroy(raid_obj_tab_t *);
270 static int raid_obj_tab_insert(raid_obj_tab_t *, raid_obj_id_t, void *);
271 static void *raid_obj_tab_remove(raid_obj_tab_t *, raid_obj_id_t);
272 static void *raid_obj_tab_find(raid_obj_tab_t *, raid_obj_id_t);
273 static void raid_list_destroy(raid_list_t *);
275 static int controller_id_to_path(uint32_t, char *);
276 static char *controller_id_to_driver_name(uint32_t);
277 static void raid_plugin_init();
278 static raid_lib_t *raid_plugin_load(char *);
279 static raid_lib_t *raid_find_lib(raid_obj_tab_t *, raid_obj_id_t);
281 /* Global object table */
282 static raid_obj_tab_t raid_tab_sys = {0, 0, NULL};
284 /* Plug-in modules maintenance data structures */
285 static raid_lib_t *raid_lib_sys = NULL;
287 /* Handle table definition */
288 static struct {
289 int handle_num;
290 int used;
291 int unused;
292 handle_attr_t *handles;
293 } raid_handle_sys = {0, 0, 0, NULL};
296 * RAID object method table definition
298 static raid_obj_op_t raid_obj_op_sys[OBJ_TYPE_ALL] = {
299 {obj_sys_compnum, obj_sys_complist, NULL, NULL, NULL,
300 NULL, NULL, NULL, NULL}, /* system object methods */
301 {obj_controller_compnum, obj_controller_complist,
302 obj_controller_get_attr, NULL, obj_controller_act,
303 NULL, NULL, NULL, NULL}, /* controller object methods */
304 {obj_array_compnum, obj_array_complist, obj_array_get_attr,
305 obj_array_set_attr, NULL, obj_array_create,
306 obj_array_delete, NULL, NULL}, /* array object methods */
307 {obj_disk_compnum, obj_disk_complist, obj_disk_get_attr, NULL,
308 NULL, NULL, NULL, NULL, NULL}, /* disk object methods */
309 {NULL, NULL, obj_hsp_get_attr, NULL, NULL, NULL, NULL, obj_hsp_bind,
310 obj_hsp_unbind}, /* hsp object methods */
311 {NULL, NULL, obj_arraypart_get_attr, NULL, NULL, NULL, NULL,
312 NULL, NULL}, /* array part object methods */
313 {NULL, NULL, obj_diskseg_get_attr, NULL, NULL, NULL, NULL, NULL, NULL},
314 {NULL, NULL, obj_task_get_attr, NULL, NULL, NULL, NULL,
315 NULL, NULL}, /* disk seg object methods */
316 {NULL, NULL, obj_prop_get_attr, NULL, NULL, NULL, NULL,
317 NULL, NULL} /* property object methods */
321 * Mutex for multithread safe
323 static mutex_t raidcfg_mp;
326 * RaidCfg library APIs
328 const char *
329 raidcfg_errstr(int err_code)
331 char *ret_val;
333 (void) mutex_lock(&raidcfg_mp);
334 switch (err_code) {
335 case SUCCESS:
336 ret_val = dgettext(TEXT_DOMAIN, "Operation succeeded.\n");
337 break;
338 case STD_IOCTL:
339 ret_val = dgettext(TEXT_DOMAIN,
340 "Request standard IOCTL service.\n");
341 break;
342 case ERR_DRIVER_NOT_FOUND:
343 ret_val = dgettext(TEXT_DOMAIN,
344 "Controller device can not be found.\n");
345 break;
346 case ERR_DRIVER_OPEN:
347 ret_val = dgettext(TEXT_DOMAIN, "Can not open controller.\n");
348 break;
349 case ERR_DRIVER_LOCK:
350 ret_val = dgettext(TEXT_DOMAIN, "Controller is locked.\n");
351 break;
352 case ERR_DRIVER_CLOSED:
353 ret_val = dgettext(TEXT_DOMAIN, "Controller is not opened.\n");
354 break;
355 case ERR_DRIVER_ACROSS:
356 ret_val = dgettext(TEXT_DOMAIN,
357 "Operation across multiple controllers.\n");
358 break;
359 case ERR_ARRAY_LEVEL:
360 ret_val = dgettext(TEXT_DOMAIN,
361 "Operation not support with volume of this level.\n");
362 break;
363 case ERR_ARRAY_SIZE:
364 ret_val = dgettext(TEXT_DOMAIN,
365 "Capacity of array out of range.\n");
366 break;
367 case ERR_ARRAY_STRIPE_SIZE:
368 ret_val = dgettext(TEXT_DOMAIN, "Illegal stripe size.\n");
369 break;
370 case ERR_ARRAY_CACHE_POLICY:
371 ret_val = dgettext(TEXT_DOMAIN,
372 "Illegal cache-write policy.\n");
373 break;
374 case ERR_ARRAY_IN_USE:
375 ret_val = dgettext(TEXT_DOMAIN, "Array or disk in use.\n");
376 break;
377 case ERR_ARRAY_TASK:
378 ret_val = dgettext(TEXT_DOMAIN, "Array has background task.\n");
379 break;
380 case ERR_ARRAY_CONFIG:
381 ret_val = dgettext(TEXT_DOMAIN,
382 "Configuration over device node failed.\n");
383 break;
384 case ERR_ARRAY_DISKNUM:
385 ret_val = dgettext(TEXT_DOMAIN, "Incorrect number of disks.\n");
386 break;
387 case ERR_ARRAY_LAYOUT:
388 ret_val = dgettext(TEXT_DOMAIN, "Illegal array layout.\n");
389 break;
390 case ERR_ARRAY_AMOUNT:
391 ret_val = dgettext(TEXT_DOMAIN, "Too many arrays.\n");
392 break;
393 case ERR_DISK_STATE:
394 ret_val = dgettext(TEXT_DOMAIN,
395 "Incorrect disk status for current operation.\n");
396 break;
397 case ERR_DISK_SPACE:
398 ret_val = dgettext(TEXT_DOMAIN, "No enough disk space.\n");
399 break;
400 case ERR_DISK_SEG_AMOUNT:
401 ret_val = dgettext(TEXT_DOMAIN, "Too many disk segments.\n");
402 break;
403 case ERR_DISK_NOT_EMPTY:
404 ret_val = dgettext(TEXT_DOMAIN, "Disk has occupied space.\n");
405 break;
406 case ERR_DISK_TASK:
407 ret_val = dgettext(TEXT_DOMAIN, "Disk has background task.\n");
408 break;
409 case ERR_TASK_STATE:
410 ret_val = dgettext(TEXT_DOMAIN,
411 "Incorrect task state for current operation.\n");
412 break;
413 case ERR_OP_ILLEGAL:
414 ret_val = dgettext(TEXT_DOMAIN, "Illegal operation.\n");
415 break;
416 case ERR_OP_NO_IMPL:
417 ret_val = dgettext(TEXT_DOMAIN,
418 "Operation is not implemented.\n");
419 break;
420 case ERR_OP_FAILED:
421 ret_val = dgettext(TEXT_DOMAIN, "Operation failed.\n");
422 break;
423 case ERR_DEVICE_NOENT:
424 ret_val = dgettext(TEXT_DOMAIN, "Device not found.\n");
425 break;
426 case ERR_DEVICE_TYPE:
427 ret_val = dgettext(TEXT_DOMAIN, "Illegal type of device.\n");
428 break;
429 case ERR_DEVICE_DUP:
430 ret_val = dgettext(TEXT_DOMAIN, "Device record duplicated.\n");
431 break;
432 case ERR_DEVICE_OVERFLOW:
433 ret_val = dgettext(TEXT_DOMAIN, "Too many devices.\n");
434 break;
435 case ERR_DEVICE_UNCLEAN:
436 ret_val = dgettext(TEXT_DOMAIN, "Device pool is not clean.\n");
437 break;
438 case ERR_DEVICE_INVALID:
439 ret_val = dgettext(TEXT_DOMAIN, "Device record is invalid.\n");
440 break;
441 case ERR_NOMEM:
442 ret_val = dgettext(TEXT_DOMAIN,
443 "Can not allocate more memory space.\n");
444 break;
445 case ERR_PRIV:
446 ret_val = dgettext(TEXT_DOMAIN, "No privilege.\n");
447 break;
448 default:
449 ret_val = dgettext(TEXT_DOMAIN, "Undefined error.\n");
451 (void) mutex_unlock(&raidcfg_mp);
453 return (ret_val);
457 raidcfg_get_controller(uint32_t controller_id)
459 raid_obj_id_t obj_id;
460 int ret_val;
462 (void) mutex_lock(&raidcfg_mp);
463 (void) obj_rescan(&raid_tab_sys);
464 obj_id = obj_locate_controller(&raid_tab_sys, controller_id);
465 if (obj_id < OBJ_NONE) {
466 (void) mutex_unlock(&raidcfg_mp);
467 return (obj_id);
470 if (obj_id == OBJ_NONE) {
471 (void) mutex_unlock(&raidcfg_mp);
472 return (ERR_DEVICE_NOENT);
474 ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
475 (void) mutex_unlock(&raidcfg_mp);
477 return (ret_val);
481 raidcfg_get_array(int controller_handle, uint64_t target_id, uint64_t lun)
483 raid_obj_id_t obj_id;
484 raidcfg_array_t *attr;
485 int ret_val;
487 (void) mutex_lock(&raidcfg_mp);
488 (void) obj_rescan(&raid_tab_sys);
489 obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
490 if (obj_id < OBJ_NONE) {
491 (void) mutex_unlock(&raidcfg_mp);
492 return (obj_id);
495 obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_ARRAY);
497 while (obj_id > OBJ_NONE) {
498 (void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
499 if (attr->tag.idl.target_id == target_id &&
500 attr->tag.idl.lun == lun)
501 break;
503 obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
506 if (obj_id < OBJ_NONE) {
507 (void) mutex_unlock(&raidcfg_mp);
508 return (obj_id);
510 if (obj_id == OBJ_NONE) {
511 (void) mutex_unlock(&raidcfg_mp);
512 return (ERR_DEVICE_NOENT);
514 ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
515 (void) mutex_unlock(&raidcfg_mp);
517 return (ret_val);
521 raidcfg_get_disk(int controller_handle, disk_tag_t tag)
523 raid_obj_id_t obj_id;
524 raidcfg_disk_t *attr;
525 int ret_val;
527 (void) mutex_lock(&raidcfg_mp);
528 (void) obj_rescan(&raid_tab_sys);
529 obj_id = raid_handle_to_obj(&raid_tab_sys, controller_handle);
530 if (obj_id < OBJ_NONE) {
531 (void) mutex_unlock(&raidcfg_mp);
532 return (obj_id);
535 obj_id = obj_get_comp(&raid_tab_sys, obj_id, OBJ_TYPE_DISK);
537 while (obj_id > OBJ_NONE) {
538 (void) obj_get_attr(&raid_tab_sys, obj_id, (void **)(&attr));
539 if (attr->tag.cidl.bus == tag.cidl.bus &&
540 attr->tag.cidl.target_id == tag.cidl.target_id &&
541 attr->tag.cidl.lun == tag.cidl.lun)
542 break;
544 obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
547 if (obj_id < OBJ_NONE) {
548 (void) mutex_unlock(&raidcfg_mp);
549 return (obj_id);
551 if (obj_id == OBJ_NONE) {
552 (void) mutex_unlock(&raidcfg_mp);
553 return (ERR_DEVICE_NOENT);
555 ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
556 (void) mutex_unlock(&raidcfg_mp);
558 return (ret_val);
562 raidcfg_open_controller(int handle, char **plugin_err_str)
564 raid_obj_id_t obj_id;
565 int ret;
567 (void) mutex_lock(&raidcfg_mp);
568 (void) obj_rescan(&raid_tab_sys);
569 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
570 if (obj_id < OBJ_NONE) {
571 raid_handle_delete(handle);
572 (void) mutex_unlock(&raidcfg_mp);
573 return (ERR_DEVICE_NOENT);
576 ret = obj_controller_act(&raid_tab_sys, obj_id,
577 ACT_CONTROLLER_OPEN, NULL, plugin_err_str);
578 if (ret < SUCCESS) {
579 (void) mutex_unlock(&raidcfg_mp);
580 return (ret);
582 (void) mutex_unlock(&raidcfg_mp);
584 return (SUCCESS);
588 raidcfg_close_controller(int handle, char **plugin_err_str)
590 raid_obj_id_t obj_id;
591 int ret;
593 (void) mutex_lock(&raidcfg_mp);
594 (void) obj_rescan(&raid_tab_sys);
595 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
596 if (obj_id < OBJ_NONE) {
597 raid_handle_delete(handle);
598 (void) mutex_unlock(&raidcfg_mp);
599 return (ERR_DEVICE_NOENT);
602 ret = obj_controller_act(&raid_tab_sys, obj_id,
603 ACT_CONTROLLER_CLOSE, NULL, plugin_err_str);
604 if (ret < SUCCESS) {
605 (void) mutex_unlock(&raidcfg_mp);
606 return (ret);
608 (void) mutex_unlock(&raidcfg_mp);
610 return (SUCCESS);
614 raidcfg_get_type(int handle)
616 raid_obj_id_t obj_id;
617 int ret_val;
619 (void) mutex_lock(&raidcfg_mp);
620 (void) obj_rescan(&raid_tab_sys);
621 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
622 if (obj_id < OBJ_NONE) {
623 raid_handle_delete(handle);
624 (void) mutex_unlock(&raidcfg_mp);
625 return (ERR_DEVICE_NOENT);
627 ret_val = raid_obj_get_type(&raid_tab_sys, obj_id);
628 (void) mutex_unlock(&raidcfg_mp);
630 return (ret_val);
634 raidcfg_get_attr(int handle, void *attr)
636 raid_obj_id_t obj_id;
637 raid_obj_type_id_t type;
638 void *data;
639 int ret, size;
641 (void) mutex_lock(&raidcfg_mp);
642 (void) obj_rescan(&raid_tab_sys);
643 if (attr == NULL) {
644 (void) mutex_unlock(&raidcfg_mp);
645 return (ERR_DEVICE_INVALID);
648 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
649 if (obj_id < OBJ_NONE) {
650 raid_handle_delete(handle);
651 (void) mutex_unlock(&raidcfg_mp);
652 return (ERR_DEVICE_NOENT);
655 type = raid_obj_get_type(&raid_tab_sys, obj_id);
656 ret = obj_get_attr(&raid_tab_sys, obj_id, &data);
657 if (ret < SUCCESS) {
658 (void) mutex_unlock(&raidcfg_mp);
659 return (ret);
662 switch (type) {
663 case OBJ_TYPE_CONTROLLER:
664 size = sizeof (controller_attr_t);
665 break;
666 case OBJ_TYPE_ARRAY:
667 size = sizeof (array_attr_t);
668 break;
669 case OBJ_TYPE_HSP:
671 raidcfg_hsp_t *dst = attr;
672 hsp_attr_t *src = data;
673 controller_attr_t *ctlr_attr;
674 array_attr_t *array_attr;
676 dst->associated_id = src->associated_id;
677 dst->type = src->type;
679 obj_id = obj_get_controller(&raid_tab_sys, obj_id);
680 ret = obj_get_attr(&raid_tab_sys, obj_id,
681 (void **)(&ctlr_attr));
682 if (ret < SUCCESS) {
683 (void) mutex_unlock(&raidcfg_mp);
684 return (ret);
687 if (src->type == HSP_TYPE_LOCAL) {
688 obj_id = obj_locate_array(&raid_tab_sys,
689 ctlr_attr->controller_id,
690 src->associated_id);
691 ret = obj_get_attr(&raid_tab_sys, obj_id,
692 (void **)(&array_attr));
693 if (ret < SUCCESS) {
694 (void) mutex_unlock(&raidcfg_mp);
695 return (ret);
698 dst->tag.idl.target_id =
699 array_attr->tag.idl.target_id;
700 dst->tag.idl.lun = array_attr->tag.idl.lun;
703 (void) mutex_unlock(&raidcfg_mp);
704 return (SUCCESS);
705 case OBJ_TYPE_DISK:
706 size = sizeof (disk_attr_t);
707 break;
708 case OBJ_TYPE_ARRAY_PART:
710 raidcfg_arraypart_t *dst = attr;
711 arraypart_attr_t *src = data;
712 controller_attr_t *ctlr_attr;
713 disk_attr_t *disk_attr;
715 dst->disk_id = src->disk_id;
716 dst->offset = src->offset;
717 dst->size = src->size;
718 dst->state = src->state;
720 obj_id = obj_get_controller(&raid_tab_sys, obj_id);
721 ret = obj_get_attr(&raid_tab_sys, obj_id,
722 (void **)(&ctlr_attr));
723 if (ret < SUCCESS) {
724 (void) mutex_unlock(&raidcfg_mp);
725 return (ret);
728 obj_id = obj_locate_disk(&raid_tab_sys,
729 ctlr_attr->controller_id, src->disk_id);
730 if (obj_id <= OBJ_NONE) {
731 dst->tag.cidl.bus = (uint64_t)OBJ_ATTR_NONE;
732 dst->tag.cidl.target_id =
733 (uint64_t)OBJ_ATTR_NONE;
734 dst->tag.cidl.lun = (uint64_t)OBJ_ATTR_NONE;
735 (void) mutex_unlock(&raidcfg_mp);
736 return (SUCCESS);
739 ret = obj_get_attr(&raid_tab_sys, obj_id,
740 (void **)(&disk_attr));
741 if (ret < SUCCESS) {
742 (void) mutex_unlock(&raidcfg_mp);
743 return (ret);
746 dst->tag.cidl.bus = disk_attr->tag.cidl.bus;
747 dst->tag.cidl.target_id = disk_attr->tag.cidl.target_id;
748 dst->tag.cidl.lun = disk_attr->tag.cidl.lun;
750 (void) mutex_unlock(&raidcfg_mp);
751 return (SUCCESS);
752 case OBJ_TYPE_DISK_SEG:
753 size = sizeof (diskseg_attr_t);
754 break;
755 case OBJ_TYPE_TASK:
756 size = sizeof (task_attr_t);
757 break;
758 case OBJ_TYPE_PROP:
760 property_attr_t *src = data, *dst = attr;
762 dst->prop_id = src->prop_id;
763 dst->prop_type = src->prop_type;
764 if (dst->prop_size == 0) {
765 dst->prop_size = src->prop_size;
766 (void) mutex_unlock(&raidcfg_mp);
767 return (SUCCESS);
770 if (dst->prop_size < src->prop_size)
771 size = dst->prop_size;
772 else
773 size = src->prop_size;
775 (void) memcpy(dst->prop, src->prop, size);
776 (void) mutex_unlock(&raidcfg_mp);
777 return (SUCCESS);
779 default:
780 (void) mutex_unlock(&raidcfg_mp);
781 return (ERR_DEVICE_TYPE);
784 (void) memcpy(attr, data, size);
786 (void) mutex_unlock(&raidcfg_mp);
787 return (ret);
791 raidcfg_get_container(int handle)
793 raid_obj_id_t obj_id;
794 int ret_val;
796 (void) mutex_lock(&raidcfg_mp);
797 (void) obj_rescan(&raid_tab_sys);
798 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
799 if (obj_id < OBJ_NONE) {
800 raid_handle_delete(handle);
801 (void) mutex_unlock(&raidcfg_mp);
802 return (ERR_DEVICE_NOENT);
805 obj_id = raid_obj_get_container(&raid_tab_sys, obj_id);
806 if (obj_id < OBJ_NONE) {
807 (void) mutex_unlock(&raidcfg_mp);
808 return (obj_id);
810 ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
811 (void) mutex_unlock(&raidcfg_mp);
813 return (ret_val);
817 raidcfg_list_head(int handle, raid_obj_type_id_t type)
819 raid_obj_id_t obj_id;
820 int ret_val;
822 (void) mutex_lock(&raidcfg_mp);
823 (void) obj_rescan(&raid_tab_sys);
824 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
825 if (obj_id < OBJ_NONE) {
826 raid_handle_delete(handle);
827 (void) mutex_unlock(&raidcfg_mp);
828 return (ERR_DEVICE_NOENT);
831 obj_id = obj_get_comp(&raid_tab_sys, obj_id, type);
832 if (obj_id < OBJ_NONE) {
833 (void) mutex_unlock(&raidcfg_mp);
834 return (obj_id);
836 ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
837 (void) mutex_unlock(&raidcfg_mp);
839 return (ret_val);
843 raidcfg_list_next(int handle)
845 raid_obj_id_t obj_id;
846 int ret_val;
848 (void) mutex_lock(&raidcfg_mp);
849 (void) obj_rescan(&raid_tab_sys);
850 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
851 if (obj_id < OBJ_NONE) {
852 raid_handle_delete(handle);
853 (void) mutex_unlock(&raidcfg_mp);
854 return (ERR_DEVICE_NOENT);
857 obj_id = obj_get_sibling(&raid_tab_sys, obj_id);
858 if (obj_id < OBJ_NONE) {
859 (void) mutex_unlock(&raidcfg_mp);
860 return (obj_id);
862 ret_val = raid_obj_to_handle(&raid_tab_sys, obj_id);
863 (void) mutex_unlock(&raidcfg_mp);
865 return (ret_val);
869 raidcfg_set_attr(int handle, uint32_t set_cmd, void *value,
870 char **plugin_err_str)
872 raid_obj_id_t obj_id;
873 raid_obj_type_id_t type;
874 int ret;
876 (void) mutex_lock(&raidcfg_mp);
877 (void) obj_rescan(&raid_tab_sys);
878 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
879 if (obj_id < OBJ_NONE) {
880 raid_handle_delete(handle);
881 (void) mutex_unlock(&raidcfg_mp);
882 return (ERR_DEVICE_NOENT);
885 type = raid_obj_get_type(&raid_tab_sys, obj_id);
886 if (raid_obj_op_sys[type].set_attr == NULL) {
887 (void) mutex_unlock(&raidcfg_mp);
888 return (ERR_OP_NO_IMPL);
891 ret = raid_obj_op_sys[type].set_attr(&raid_tab_sys,
892 obj_id, set_cmd, value, plugin_err_str);
894 (void) mutex_unlock(&raidcfg_mp);
895 return (ret);
899 raidcfg_update_fw(int handle, char *file, char **plugin_err_str)
901 raid_obj_id_t obj_id;
902 int ret;
904 (void) mutex_lock(&raidcfg_mp);
905 (void) obj_rescan(&raid_tab_sys);
906 obj_id = raid_handle_to_obj(&raid_tab_sys, handle);
907 if (obj_id < OBJ_NONE) {
908 raid_handle_delete(handle);
909 (void) mutex_unlock(&raidcfg_mp);
910 return (ERR_DEVICE_NOENT);
913 if (raid_obj_get_type(&raid_tab_sys, obj_id) != OBJ_TYPE_CONTROLLER) {
914 (void) mutex_unlock(&raidcfg_mp);
915 return (ERR_OP_NO_IMPL);
918 ret = raid_obj_op_sys[OBJ_TYPE_CONTROLLER].act(&raid_tab_sys,
919 obj_id, ACT_CONTROLLER_FLASH_FW, file, plugin_err_str);
921 (void) mutex_unlock(&raidcfg_mp);
922 return (ret);
926 raidcfg_create_array(int num_of_comps, int *disk_handles,
927 uint32_t raid_level, uint64_t size, uint32_t stripe_size,
928 char **plugin_err_str)
930 raid_obj_id_t *disk_obj_ids, obj_id;
931 array_attr_t *array_attr;
932 raid_obj_handle_t array_handle;
933 int i, ret;
935 (void) mutex_lock(&raidcfg_mp);
936 (void) obj_rescan(&raid_tab_sys);
938 disk_obj_ids = calloc(num_of_comps, sizeof (raid_obj_id_t));
939 if (disk_obj_ids == NULL) {
940 (void) mutex_unlock(&raidcfg_mp);
941 return (ERR_NOMEM);
944 /* convert disk handles into disk object ids; */
945 for (i = 0; i < num_of_comps; ++i) {
946 if (*(disk_handles + i) == OBJ_SEPARATOR_BEGIN ||
947 *(disk_handles + i) == OBJ_SEPARATOR_END) {
948 *(disk_obj_ids + i) = *(disk_handles + i);
949 continue;
952 *(disk_obj_ids + i) = raid_handle_to_obj(&raid_tab_sys,
953 *(disk_handles + i));
954 if (raid_obj_get_type(&raid_tab_sys, *(disk_obj_ids + i)) !=
955 OBJ_TYPE_DISK) {
956 free(disk_obj_ids);
957 (void) obj_rescan(&raid_tab_sys);
958 (void) mutex_unlock(&raidcfg_mp);
959 return (ERR_DEVICE_TYPE);
963 /* Create an empty array object */
964 obj_id = raid_obj_create(&raid_tab_sys, OBJ_TYPE_ARRAY);
965 if (obj_id < OBJ_NONE) {
966 free(disk_obj_ids);
967 (void) obj_rescan(&raid_tab_sys);
968 (void) mutex_unlock(&raidcfg_mp);
969 return (obj_id);
971 (void) raid_obj_clear_status(&raid_tab_sys, obj_id,
972 OBJ_STATUS_CMD_CLEAN);
974 array_attr = raid_obj_get_data_ptr(&raid_tab_sys, obj_id);
975 array_attr->array_id = (uint32_t)OBJ_ATTR_NONE;
976 array_attr->raid_level = raid_level;
977 array_attr->capacity = size;
978 array_attr->stripe_size = stripe_size;
979 array_attr->write_policy = CACHE_WR_ON;
980 array_attr->read_policy = CACHE_RD_ON;
982 ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].create_obj(&raid_tab_sys, obj_id,
983 num_of_comps, disk_obj_ids, plugin_err_str);
984 free(disk_obj_ids);
986 if (ret < SUCCESS) {
987 (void) obj_rescan(&raid_tab_sys);
988 (void) mutex_unlock(&raidcfg_mp);
989 return (ret);
992 /* create_obj() method should put the array object in the device tree */
993 array_handle = raid_obj_to_handle(&raid_tab_sys, obj_id);
995 (void) obj_rescan(&raid_tab_sys);
996 (void) mutex_unlock(&raidcfg_mp);
997 return (array_handle);
1001 raidcfg_delete_array(int array_handle, char **plugin_err_str)
1003 raid_obj_id_t array_obj_id;
1004 int ret;
1006 (void) mutex_lock(&raidcfg_mp);
1007 (void) obj_rescan(&raid_tab_sys);
1009 if (raidcfg_get_type(array_handle) != OBJ_TYPE_ARRAY) {
1010 (void) mutex_unlock(&raidcfg_mp);
1011 return (ERR_DEVICE_TYPE);
1014 array_obj_id = raid_handle_to_obj(&raid_tab_sys, array_handle);
1015 if (array_obj_id < OBJ_NONE) {
1016 (void) mutex_unlock(&raidcfg_mp);
1017 return (array_obj_id);
1019 if (array_obj_id == OBJ_NONE) {
1020 (void) mutex_unlock(&raidcfg_mp);
1021 return (ERR_DEVICE_INVALID);
1024 ret = raid_obj_op_sys[OBJ_TYPE_ARRAY].delete_obj(&raid_tab_sys,
1025 array_obj_id, plugin_err_str);
1026 (void) obj_rescan(&raid_tab_sys);
1028 (void) mutex_unlock(&raidcfg_mp);
1029 return (ret);
1033 raidcfg_set_hsp(raidcfg_hsp_relation_t *hsp_relations,
1034 char **plugin_err_str)
1036 raid_obj_id_t disk_obj_id, array_obj_id;
1037 raid_obj_id_t *hsp_relation_objs;
1038 int ret;
1040 (void) mutex_lock(&raidcfg_mp);
1041 (void) obj_rescan(&raid_tab_sys);
1042 if (hsp_relations == NULL) {
1043 (void) mutex_unlock(&raidcfg_mp);
1044 return (ERR_OP_ILLEGAL);
1047 hsp_relation_objs = malloc(2 * sizeof (raid_obj_id_t));
1048 if (hsp_relation_objs == NULL) {
1049 (void) mutex_unlock(&raidcfg_mp);
1050 return (ERR_NOMEM);
1053 (void) obj_rescan(&raid_tab_sys);
1055 if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
1056 array_obj_id = raid_handle_to_obj(&raid_tab_sys,
1057 hsp_relations->array_handle);
1058 if (array_obj_id < OBJ_NONE) {
1059 free(hsp_relation_objs);
1060 (void) mutex_unlock(&raidcfg_mp);
1061 return (array_obj_id);
1063 if (array_obj_id == OBJ_NONE) {
1064 (void) free(hsp_relation_objs);
1065 (void) mutex_unlock(&raidcfg_mp);
1066 return (ERR_DEVICE_NOENT);
1068 if (raidcfg_get_type(hsp_relations->array_handle) !=
1069 OBJ_TYPE_ARRAY) {
1070 free(hsp_relation_objs);
1071 (void) mutex_unlock(&raidcfg_mp);
1072 return (ERR_DEVICE_TYPE);
1074 } else
1075 array_obj_id = OBJ_ATTR_NONE;
1077 disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
1078 hsp_relations->disk_handle);
1079 if (disk_obj_id < OBJ_NONE) {
1080 free(hsp_relation_objs);
1081 (void) mutex_unlock(&raidcfg_mp);
1082 return (disk_obj_id);
1084 if (disk_obj_id == OBJ_NONE) {
1085 free(hsp_relation_objs);
1086 (void) mutex_unlock(&raidcfg_mp);
1087 return (ERR_DEVICE_NOENT);
1089 if (raidcfg_get_type(hsp_relations->disk_handle) !=
1090 OBJ_TYPE_DISK) {
1091 free(hsp_relation_objs);
1092 (void) mutex_unlock(&raidcfg_mp);
1093 return (ERR_DEVICE_TYPE);
1096 hsp_relation_objs[0] = array_obj_id;
1097 hsp_relation_objs[1] = disk_obj_id;
1099 ret = raid_obj_op_sys[OBJ_TYPE_HSP].bind_obj(&raid_tab_sys,
1100 hsp_relation_objs, plugin_err_str);
1102 (void) obj_rescan(&raid_tab_sys);
1103 free(hsp_relation_objs);
1104 (void) mutex_unlock(&raidcfg_mp);
1106 return (ret);
1110 raidcfg_unset_hsp(raidcfg_hsp_relation_t *hsp_relations,
1111 char **plugin_err_str)
1113 raid_obj_id_t disk_obj_id, array_obj_id;
1114 raid_obj_id_t *hsp_relation_objs;
1115 int ret;
1117 (void) mutex_lock(&raidcfg_mp);
1118 (void) obj_rescan(&raid_tab_sys);
1119 if (hsp_relations == NULL) {
1120 (void) mutex_unlock(&raidcfg_mp);
1121 return (ERR_OP_ILLEGAL);
1124 hsp_relation_objs = malloc(2 * sizeof (raid_obj_id_t));
1125 if (hsp_relation_objs == NULL) {
1126 (void) mutex_unlock(&raidcfg_mp);
1127 return (ERR_NOMEM);
1130 (void) obj_rescan(&raid_tab_sys);
1132 if (hsp_relations->array_handle != OBJ_ATTR_NONE) {
1133 array_obj_id = raid_handle_to_obj(&raid_tab_sys,
1134 hsp_relations->array_handle);
1135 if (array_obj_id < OBJ_NONE) {
1136 free(hsp_relation_objs);
1137 (void) mutex_unlock(&raidcfg_mp);
1138 return (array_obj_id);
1140 if (array_obj_id == OBJ_NONE) {
1141 free(hsp_relation_objs);
1142 (void) mutex_unlock(&raidcfg_mp);
1143 return (ERR_DEVICE_NOENT);
1145 if (raidcfg_get_type(hsp_relations->array_handle) !=
1146 OBJ_TYPE_ARRAY) {
1147 free(hsp_relation_objs);
1148 (void) mutex_unlock(&raidcfg_mp);
1149 return (ERR_DEVICE_TYPE);
1151 } else
1152 array_obj_id = OBJ_ATTR_NONE;
1154 disk_obj_id = raid_handle_to_obj(&raid_tab_sys,
1155 hsp_relations->disk_handle);
1156 if (disk_obj_id < OBJ_NONE) {
1157 free(hsp_relation_objs);
1158 (void) mutex_unlock(&raidcfg_mp);
1159 return (disk_obj_id);
1161 if (disk_obj_id == OBJ_NONE) {
1162 free(hsp_relation_objs);
1163 (void) mutex_unlock(&raidcfg_mp);
1164 return (ERR_DEVICE_NOENT);
1166 if (raidcfg_get_type(hsp_relations->disk_handle) !=
1167 OBJ_TYPE_DISK) {
1168 free(hsp_relation_objs);
1169 (void) mutex_unlock(&raidcfg_mp);
1170 return (ERR_DEVICE_TYPE);
1173 hsp_relation_objs[0] = array_obj_id;
1174 hsp_relation_objs[1] = disk_obj_id;
1176 ret = raid_obj_op_sys[OBJ_TYPE_HSP].unbind_obj(&raid_tab_sys,
1177 hsp_relation_objs, plugin_err_str);
1179 (void) obj_rescan(&raid_tab_sys);
1180 free(hsp_relation_objs);
1181 (void) mutex_unlock(&raidcfg_mp);
1183 return (ret);
1187 * RaidCfg lib routines
1189 void
1190 raidcfg_init(void)
1192 (void) mutex_init(&raidcfg_mp, 0, NULL);
1193 raid_plugin_init();
1194 (void) raid_handle_init();
1195 (void) obj_rescan(&raid_tab_sys);
1198 void
1199 raidcfg_fini(void)
1202 * Need to close all opened controllers before destroying object table
1204 (void) obj_rescan(&raid_tab_sys);
1205 raid_handle_fini();
1206 raid_obj_tab_destroy(&raid_tab_sys);
1207 raid_plugin_init();
1208 (void) mutex_destroy(&raidcfg_mp);
1212 * Support routines
1214 static int
1215 intcompare(const void *p1, const void *p2)
1217 int i, j;
1218 i = *((int *)p1);
1219 j = *((int *)p2);
1220 return (i - j);
1223 static uint64_t
1224 raid_space_noalign(raid_obj_tab_t *raid_tab, uint32_t raid_level, int num,
1225 raid_obj_id_t *disk_objs, arraypart_attr_t *arraypart_attrs)
1227 disk_attr_t *disk_attr;
1228 diskseg_attr_t *diskseg_attr;
1229 raid_obj_id_t obj_id;
1230 uint64_t offset, capacity;
1231 int i, disk_num, sub_array_num, disk_layer;
1233 /* Find out the maximum available space for all disks */
1234 for (i = 0; i < num; ++i) {
1235 if ((disk_objs[i] == OBJ_SEPARATOR_BEGIN) ||
1236 (disk_objs[i] == OBJ_SEPARATOR_END))
1237 continue;
1239 (void) obj_get_attr(raid_tab, disk_objs[i],
1240 (void **)(&disk_attr));
1241 obj_id = obj_get_comp(raid_tab, disk_objs[i],
1242 OBJ_TYPE_DISK_SEG);
1243 if (obj_id == OBJ_NONE) {
1244 arraypart_attrs[i].offset = 0;
1245 arraypart_attrs[i].size = disk_attr->capacity;
1246 continue;
1249 (void) obj_get_attr(raid_tab, obj_id, (void **)
1250 (&diskseg_attr));
1251 arraypart_attrs[i].offset = 0;
1252 arraypart_attrs[i].size = diskseg_attr->offset;
1253 offset = diskseg_attr->offset + diskseg_attr->size;
1255 while ((obj_id = obj_get_sibling(raid_tab, obj_id)) !=
1256 OBJ_NONE) {
1257 (void) obj_get_attr(raid_tab, obj_id,
1258 (void **)(&diskseg_attr));
1259 if ((diskseg_attr->offset - offset) >
1260 arraypart_attrs[i].size) {
1261 arraypart_attrs[i].offset = offset;
1262 arraypart_attrs[i].size = diskseg_attr->offset -
1263 offset;
1266 offset = diskseg_attr->offset + diskseg_attr->size;
1269 if ((disk_attr->capacity - offset) > arraypart_attrs[i].size) {
1270 arraypart_attrs[i].offset = offset;
1271 arraypart_attrs[i].size = disk_attr->capacity -
1272 offset;
1276 capacity = OBJ_ATTR_NONE;
1277 disk_num = 0;
1278 disk_layer = 0;
1279 sub_array_num = 0;
1280 for (i = 0; i < num; ++i) {
1281 if (disk_objs[i] == OBJ_SEPARATOR_BEGIN) {
1282 ++ disk_layer;
1283 continue;
1285 if (disk_objs[i] == OBJ_SEPARATOR_END) {
1286 -- disk_layer;
1287 if (disk_layer != 0)
1288 ++ sub_array_num;
1289 continue;
1292 if (capacity > arraypart_attrs[i].size)
1293 capacity = arraypart_attrs[i].size;
1294 ++disk_num;
1297 switch (raid_level) {
1298 case RAID_LEVEL_0:
1299 capacity = capacity * disk_num;
1300 break;
1301 case RAID_LEVEL_1:
1302 capacity = capacity * disk_num / 2;
1303 break;
1304 case RAID_LEVEL_1E:
1305 capacity = capacity * disk_num / 2;
1306 break;
1307 case RAID_LEVEL_5:
1308 capacity = capacity * (disk_num - 1);
1309 break;
1310 case RAID_LEVEL_10:
1311 capacity = capacity * disk_num / 2;
1312 break;
1313 case RAID_LEVEL_50:
1314 capacity = capacity * (disk_num - sub_array_num);
1315 break;
1316 default:
1317 return (ERR_ARRAY_LEVEL);
1320 return (capacity);
1324 * Raid handle maintenance routines
1326 static int
1327 raid_handle_init()
1329 int i;
1330 void *ptr;
1332 raid_handle_sys.handle_num += HANDLER_SLOTS;
1333 ptr = reallocarray(raid_handle_sys.handles,
1334 raid_handle_sys.handle_num, sizeof (handle_attr_t));
1335 if (ptr == NULL)
1336 return (ERR_NOMEM);
1337 raid_handle_sys.handles = ptr;
1339 /* Clean up the new allocated handles */
1340 for (i = raid_handle_sys.handle_num - HANDLER_SLOTS;
1341 i < raid_handle_sys.handle_num; ++i) {
1342 bzero(&raid_handle_sys.handles[i], sizeof (handle_attr_t));
1343 raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1344 raid_handle_sys.handles[i].next = i + 1;
1347 /* For the first time of allocation, set up the system object handle */
1348 if (raid_handle_sys.handle_num == HANDLER_SLOTS) {
1349 raid_handle_sys.handles[0].type = OBJ_TYPE_SYSTEM;
1350 raid_handle_sys.handles[0].next = 0;
1351 raid_handle_sys.unused = 1;
1352 raid_handle_sys.used = 0;
1354 return (SUCCESS);
1357 static void
1358 raid_handle_fini()
1360 raid_obj_handle_t i;
1362 i = raid_handle_sys.used;
1364 /* Close all opened controllers */
1365 while (i != 0) {
1366 if ((raid_handle_sys.handles[i].type == OBJ_TYPE_CONTROLLER) &&
1367 (raid_handle_sys.handles[i].fd != 0) &&
1368 (raid_handle_sys.handles[i].raid_lib != NULL))
1369 raid_handle_sys.handles[i].raid_lib->close_controller(
1370 raid_handle_sys.handles[i].controller_id, NULL);
1371 i = raid_handle_sys.handles[i].next;
1374 /* Clean up handle space */
1375 raid_handle_sys.handle_num = 0;
1376 raid_handle_sys.unused = 0;
1377 raid_handle_sys.used = 0;
1378 free(raid_handle_sys.handles);
1379 raid_handle_sys.handles = NULL;
1382 static raid_obj_handle_t
1383 raid_handle_new(raid_obj_type_id_t type)
1385 int ret;
1387 if (raid_handle_sys.unused == raid_handle_sys.handle_num - 1) {
1388 ret = raid_handle_init();
1389 if (ret < SUCCESS)
1390 return (ret);
1393 ret = raid_handle_sys.unused;
1394 raid_handle_sys.unused = raid_handle_sys.handles[ret].next;
1396 raid_handle_sys.handles[ret].next = raid_handle_sys.used;
1397 raid_handle_sys.used = ret;
1398 raid_handle_sys.handles[ret].type = type;
1400 return (ret);
1403 static void
1404 raid_handle_delete(raid_obj_handle_t handle)
1406 int i = raid_handle_sys.used, j = 0;
1408 if (handle == 0)
1409 return;
1411 while (i != 0 && i != handle) {
1412 j = i;
1413 i = raid_handle_sys.handles[i].next;
1416 if (i == handle) {
1417 if (j != 0)
1418 raid_handle_sys.handles[j].next =
1419 raid_handle_sys.handles[i].next;
1420 else
1421 raid_handle_sys.used =
1422 raid_handle_sys.handles[i].next;
1424 raid_handle_sys.handles[i].type = OBJ_TYPE_ALL;
1425 raid_handle_sys.handles[i].next =
1426 raid_handle_sys.unused;
1427 raid_handle_sys.unused = i;
1431 static void
1432 raid_handle_delete_controller_comp(uint32_t controller_id)
1434 int i = raid_handle_sys.used, j;
1436 while (i != 0) {
1437 j = i;
1438 i = raid_handle_sys.handles[i].next;
1439 if ((raid_handle_sys.handles[j].controller_id ==
1440 controller_id) &&
1441 (raid_handle_sys.handles[j].type !=
1442 OBJ_TYPE_CONTROLLER))
1443 raid_handle_delete(j);
1447 static raid_obj_id_t
1448 raid_handle_to_obj(raid_obj_tab_t *raid_tab, raid_obj_handle_t handle)
1450 handle_attr_t *handle_attr;
1451 raid_obj_id_t obj_id;
1453 if (handle == OBJ_SYSTEM)
1454 return (OBJ_SYSTEM);
1456 handle_attr = raid_handle_sys.handles + handle;
1458 switch (handle_attr->type) {
1459 case OBJ_TYPE_SYSTEM:
1460 return (OBJ_SYSTEM);
1461 case OBJ_TYPE_CONTROLLER:
1462 obj_id = obj_locate_controller(raid_tab,
1463 handle_attr->controller_id);
1464 break;
1465 case OBJ_TYPE_ARRAY:
1466 obj_id = obj_locate_array(raid_tab,
1467 handle_attr->controller_id, handle_attr->array_id);
1468 break;
1469 case OBJ_TYPE_HSP:
1470 obj_id = obj_locate_hsp(raid_tab,
1471 handle_attr->controller_id, handle_attr->disk_id,
1472 handle_attr->array_id);
1473 break;
1474 case OBJ_TYPE_DISK:
1475 obj_id = obj_locate_disk(raid_tab,
1476 handle_attr->controller_id, handle_attr->disk_id);
1477 break;
1478 case OBJ_TYPE_ARRAY_PART:
1479 obj_id = obj_locate_arraypart(raid_tab,
1480 handle_attr->controller_id, handle_attr->array_id,
1481 handle_attr->disk_id);
1482 break;
1483 case OBJ_TYPE_DISK_SEG:
1484 obj_id = obj_locate_diskseg(raid_tab,
1485 handle_attr->controller_id,
1486 handle_attr->disk_id, handle_attr->seq_id);
1487 break;
1488 case OBJ_TYPE_TASK:
1489 obj_id = obj_locate_task(raid_tab,
1490 handle_attr->controller_id, handle_attr->task_id);
1491 break;
1492 case OBJ_TYPE_PROP:
1493 obj_id = obj_locate_prop(raid_tab,
1494 handle_attr->controller_id, handle_attr->disk_id,
1495 handle_attr->prop_id);
1496 break;
1497 default:
1498 return (ERR_DEVICE_INVALID);
1501 if (obj_id < OBJ_NONE)
1502 return (obj_id);
1503 if (obj_id == OBJ_NONE)
1504 return (ERR_DEVICE_NOENT);
1506 (void) raid_obj_set_handle(raid_tab, obj_id, handle);
1507 return (obj_id);
1510 static raid_obj_handle_t
1511 raid_obj_to_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1513 raid_obj_id_t obj_id_backup = obj_id;
1514 raid_obj_type_id_t type;
1515 raid_obj_handle_t handle;
1516 controller_attr_t *controller_attr;
1517 array_attr_t *array_attr;
1518 hsp_attr_t *hsp_attr;
1519 disk_attr_t *disk_attr;
1520 arraypart_attr_t *arraypart_attr;
1521 diskseg_attr_t *diskseg_attr;
1522 task_attr_t *task_attr;
1523 property_attr_t *prop_attr;
1525 if (obj_id == OBJ_SYSTEM)
1526 return (OBJ_SYSTEM);
1528 /* If the object mapped by a handle */
1529 handle = raid_obj_get_handle(raid_tab, obj_id);
1530 if (handle != 0)
1531 return (handle);
1533 /* Search for existing handles */
1534 for (handle = raid_handle_sys.used; handle != 0;
1535 handle = raid_handle_sys.handles[handle].next)
1536 if (raid_handle_to_obj(raid_tab, handle) == obj_id)
1537 break;
1539 if (handle != 0)
1540 return (handle);
1542 /* Allocate new handle for this object */
1543 type = raid_obj_get_type(raid_tab, obj_id);
1544 handle = raid_handle_new(type);
1545 (void) raid_obj_set_handle(raid_tab, obj_id, handle);
1546 raid_handle_sys.handles[handle].type = type;
1548 switch (type) {
1549 case OBJ_TYPE_SYSTEM:
1550 break;
1551 case OBJ_TYPE_CONTROLLER:
1552 controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1553 raid_handle_sys.handles[handle].controller_id =
1554 controller_attr->controller_id;
1555 break;
1556 case OBJ_TYPE_ARRAY:
1557 array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1558 raid_handle_sys.handles[handle].array_id = array_attr->array_id;
1559 obj_id = obj_get_controller(raid_tab, obj_id);
1560 controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1561 raid_handle_sys.handles[handle].controller_id =
1562 controller_attr->controller_id;
1563 break;
1564 case OBJ_TYPE_HSP:
1565 hsp_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1566 raid_handle_sys.handles[handle].array_id =
1567 hsp_attr->associated_id;
1568 obj_id = raid_obj_get_container(raid_tab, obj_id);
1569 disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1570 raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1571 obj_id = obj_get_controller(raid_tab, obj_id);
1572 controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1573 raid_handle_sys.handles[handle].controller_id =
1574 controller_attr->controller_id;
1575 break;
1576 case OBJ_TYPE_DISK:
1577 disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1578 raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1579 obj_id = obj_get_controller(raid_tab, obj_id);
1580 controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1581 raid_handle_sys.handles[handle].controller_id =
1582 controller_attr->controller_id;
1583 break;
1584 case OBJ_TYPE_ARRAY_PART:
1585 arraypart_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1586 raid_handle_sys.handles[handle].disk_id =
1587 arraypart_attr->disk_id;
1588 obj_id = raid_obj_get_container(raid_tab, obj_id);
1589 array_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1590 raid_handle_sys.handles[handle].array_id =
1591 array_attr->array_id;
1592 obj_id = obj_get_controller(raid_tab, obj_id);
1593 controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1594 raid_handle_sys.handles[handle].controller_id =
1595 controller_attr->controller_id;
1596 break;
1597 case OBJ_TYPE_DISK_SEG:
1598 diskseg_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1599 raid_handle_sys.handles[handle].seq_id = diskseg_attr->seq_no;
1600 obj_id = raid_obj_get_container(raid_tab, obj_id);
1601 disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1602 raid_handle_sys.handles[handle].disk_id =
1603 disk_attr->disk_id;
1604 obj_id = obj_get_controller(raid_tab, obj_id);
1605 controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1606 raid_handle_sys.handles[handle].controller_id =
1607 controller_attr->controller_id;
1608 break;
1609 case OBJ_TYPE_TASK:
1610 task_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1611 raid_handle_sys.handles[handle].task_id = task_attr->task_id;
1612 obj_id = obj_get_controller(raid_tab, obj_id);
1613 controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1614 raid_handle_sys.handles[handle].controller_id =
1615 controller_attr->controller_id;
1616 break;
1617 case OBJ_TYPE_PROP:
1618 prop_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1619 raid_handle_sys.handles[handle].prop_id =
1620 prop_attr->prop_id;
1621 obj_id = raid_obj_get_container(raid_tab, obj_id);
1622 disk_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1623 raid_handle_sys.handles[handle].disk_id = disk_attr->disk_id;
1624 obj_id = obj_get_controller(raid_tab, obj_id);
1625 controller_attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1626 raid_handle_sys.handles[handle].controller_id =
1627 controller_attr->controller_id;
1628 break;
1629 default:
1630 return (ERR_DEVICE_INVALID);
1633 (void) raid_obj_set_handle(raid_tab, obj_id_backup, handle);
1634 return (handle);
1637 static raid_lib_t *
1638 raid_obj_get_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1640 raid_obj_handle_t handle;
1641 controller_attr_t *attr;
1643 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1644 return (NULL);
1646 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1647 handle = raid_handle_sys.used;
1648 while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1649 raid_handle_sys.handles[handle].controller_id !=
1650 attr->controller_id)
1651 handle = raid_handle_sys.handles[handle].next;
1653 if (handle == 0)
1654 return (NULL);
1656 return (raid_handle_sys.handles[handle].raid_lib);
1659 static int
1660 raid_obj_set_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1661 raid_lib_t *raid_lib)
1663 raid_obj_handle_t handle;
1664 controller_attr_t *attr;
1666 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1667 return (ERR_DEVICE_TYPE);
1669 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1670 handle = raid_handle_sys.used;
1671 while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1672 raid_handle_sys.handles[handle].controller_id !=
1673 attr->controller_id)
1674 handle = raid_handle_sys.handles[handle].next;
1676 if (handle == 0)
1677 return (ERR_DEVICE_NOENT);
1679 raid_handle_sys.handles[handle].raid_lib = raid_lib;
1680 return (SUCCESS);
1683 static int
1684 raid_obj_get_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1686 raid_obj_handle_t handle;
1687 controller_attr_t *attr;
1689 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1690 return (ERR_DEVICE_TYPE);
1692 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1693 handle = raid_handle_sys.used;
1694 while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1695 raid_handle_sys.handles[handle].controller_id !=
1696 attr->controller_id)
1697 handle = raid_handle_sys.handles[handle].next;
1699 if (handle == 0)
1700 return (ERR_DEVICE_NOENT);
1702 return (raid_handle_sys.handles[handle].fd);
1705 static int
1706 raid_obj_set_fd(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, int fd)
1708 raid_obj_handle_t handle;
1709 controller_attr_t *attr;
1711 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
1712 return (ERR_DEVICE_TYPE);
1714 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1715 handle = raid_handle_sys.used;
1716 while (raid_handle_sys.handles[handle].type != OBJ_TYPE_CONTROLLER ||
1717 raid_handle_sys.handles[handle].controller_id !=
1718 attr->controller_id)
1719 handle = raid_handle_sys.handles[handle].next;
1721 if (handle == 0)
1722 return (ERR_DEVICE_NOENT);
1724 raid_handle_sys.handles[handle].fd = fd;
1725 return (SUCCESS);
1729 * Raid object maintenance routines
1731 static int
1732 obj_scan_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1734 raid_obj_status_t status;
1735 raid_obj_type_id_t type;
1736 int ret, i, obj_type_cnt, comp_num;
1737 raid_obj_id_t *comp_list;
1739 status = raid_obj_get_status(raid_tab, obj_id);
1740 if (status < SUCCESS)
1741 return (status);
1743 if (status & OBJ_STATUS_SCANCOMP)
1744 return (SUCCESS);
1746 type = raid_obj_get_type(raid_tab, obj_id);
1747 /* type less than OBJ_TYPE_SYSTEM means error */
1748 if (type < OBJ_TYPE_SYSTEM)
1749 return (ERR_DEVICE_INVALID);
1751 for (obj_type_cnt = OBJ_SYSTEM; obj_type_cnt < OBJ_TYPE_ALL;
1752 ++obj_type_cnt) {
1753 if (raid_obj_op_sys[type].compnum != NULL)
1754 comp_num = raid_obj_op_sys[type].compnum(
1755 raid_tab, obj_id, obj_type_cnt);
1756 else
1757 comp_num = 0;
1759 if (comp_num < SUCCESS)
1760 return (comp_num);
1761 if (comp_num == 0)
1762 continue;
1764 comp_list = calloc(comp_num, sizeof (raid_obj_id_t));
1765 if (comp_list == NULL)
1766 return (ERR_NOMEM);
1768 for (i = 0; i < comp_num; ++i) {
1769 *(comp_list + i) = raid_obj_create(raid_tab,
1770 obj_type_cnt);
1771 if (*(comp_list + i) < SUCCESS) {
1772 ret = *(comp_list + i);
1773 free(comp_list);
1774 return (ret);
1777 (void) raid_obj_clear_status(raid_tab,
1778 *(comp_list + i), OBJ_STATUS_CMD_CLEAN);
1779 (void) raid_obj_add_org(raid_tab, *(comp_list + i),
1780 obj_id);
1783 if (raid_obj_op_sys[type].complist != NULL)
1784 raid_obj_op_sys[type].complist(raid_tab,
1785 obj_id, comp_num, comp_list, obj_type_cnt);
1786 free(comp_list);
1789 (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_SCANCOMP);
1790 return (SUCCESS);
1793 static int
1794 obj_rescan(raid_obj_tab_t *raid_tab)
1796 int ret;
1798 raid_obj_tab_destroy(raid_tab);
1800 if (raid_obj_tab_create(raid_tab, HASH_SLOTS) != SUCCESS)
1801 return (ERR_NOMEM);
1803 if ((ret = raid_obj_create_system_obj(raid_tab)) != SUCCESS) {
1804 raid_obj_tab_destroy(raid_tab);
1805 return (ret);
1808 return (SUCCESS);
1811 static raid_obj_id_t
1812 obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
1813 raid_obj_type_id_t obj_type)
1815 raid_obj_id_t id;
1816 raid_obj_type_id_t type;
1817 raid_obj_status_t status;
1818 int ret;
1820 if ((obj_type < OBJ_TYPE_SYSTEM) || (obj_type > OBJ_TYPE_ALL))
1821 return (ERR_DEVICE_TYPE);
1823 status = raid_obj_get_status(raid_tab, obj_id);
1824 if (status < SUCCESS)
1825 return (status);
1827 if (!(status & OBJ_STATUS_SCANCOMP)) {
1828 ret = obj_scan_comp(raid_tab, obj_id);
1829 if (ret < SUCCESS)
1830 return (ret);
1833 id = raid_obj_get_comp(raid_tab, obj_id);
1834 if (id <= OBJ_NONE)
1835 return (id);
1837 type = raid_obj_get_type(raid_tab, id);
1838 if (type < OBJ_TYPE_SYSTEM)
1839 return (type);
1841 if (type == obj_type)
1842 return (id);
1844 while (id > OBJ_NONE) {
1845 id = raid_obj_get_sibling(raid_tab, id);
1846 if (id <= OBJ_NONE)
1847 return (id);
1849 type = raid_obj_get_type(raid_tab, id);
1850 if (type < OBJ_TYPE_SYSTEM)
1851 return (type);
1853 if (type == obj_type)
1854 break;
1857 return (id);
1860 static raid_obj_id_t
1861 obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
1863 raid_obj_id_t id;
1864 raid_obj_type_id_t type, obj_type;
1866 id = obj_id;
1867 obj_type = raid_obj_get_type(raid_tab, id);
1868 if (obj_type < OBJ_TYPE_SYSTEM)
1869 return (obj_type);
1871 do {
1872 id = raid_obj_get_sibling(raid_tab, id);
1873 if (id < OBJ_NONE)
1874 return (id);
1876 type = raid_obj_get_type(raid_tab, id);
1877 if (type < OBJ_TYPE_SYSTEM)
1878 return (type);
1879 } while ((type != obj_type) && (id != OBJ_NONE));
1881 return (id);
1884 static int
1885 obj_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id, void **data)
1887 raid_obj_type_id_t type;
1888 raid_obj_status_t status;
1889 void *attr;
1890 int ret = SUCCESS;
1892 status = raid_obj_get_status(raid_tab, obj_id);
1893 if (status < SUCCESS)
1894 return (status);
1896 type = raid_obj_get_type(raid_tab, obj_id);
1897 if (type < OBJ_TYPE_SYSTEM)
1898 return (type);
1900 if (!(status & OBJ_STATUS_OPENED)) {
1901 if (raid_obj_op_sys[type].get_attr == NULL)
1902 (void) raid_obj_set_status(raid_tab, obj_id,
1903 OBJ_STATUS_OPENED);
1904 else
1905 ret = raid_obj_op_sys[type].get_attr(raid_tab, obj_id);
1907 if (ret < SUCCESS)
1908 return (ret);
1910 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1911 if (attr == NULL && type != OBJ_TYPE_SYSTEM)
1912 return (ERR_DEVICE_INVALID);
1914 *data = attr;
1915 return (SUCCESS);
1918 static raid_obj_id_t
1919 obj_locate_controller(raid_obj_tab_t *raid_tab, uint32_t controller_id)
1921 raid_obj_id_t obj_id;
1922 controller_attr_t *attr;
1924 obj_id = obj_get_comp(raid_tab, OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
1925 if (obj_id <= OBJ_NONE)
1926 return (obj_id);
1928 do {
1929 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1930 if (attr == NULL)
1931 return (ERR_DEVICE_INVALID);
1933 if (attr->controller_id == controller_id)
1934 break;
1935 } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) != OBJ_NONE);
1937 return (obj_id);
1940 static raid_obj_id_t
1941 obj_locate_array(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1942 uint32_t array_id)
1944 raid_obj_id_t obj_id;
1946 obj_id = obj_locate_controller(raid_tab, controller_id);
1947 if (obj_id < OBJ_NONE)
1948 return (obj_id);
1950 obj_id = obj_locate_array_recur(raid_tab, obj_id, array_id);
1952 return (obj_id);
1955 static raid_obj_id_t
1956 obj_locate_array_recur(raid_obj_tab_t *raid_tab,
1957 raid_obj_id_t container_obj_id, uint32_t array_id)
1959 raid_obj_id_t obj_id, ret;
1960 array_attr_t *attr;
1962 obj_id = obj_get_comp(raid_tab, container_obj_id, OBJ_TYPE_ARRAY);
1963 if (obj_id <= OBJ_NONE)
1964 return (obj_id);
1966 do {
1967 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
1968 if (attr == NULL)
1969 return (ERR_DEVICE_INVALID);
1971 if (attr->array_id == array_id)
1972 break;
1974 ret = obj_locate_array_recur(raid_tab, obj_id, array_id);
1975 if (ret != OBJ_NONE)
1976 return (ret);
1978 } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
1980 return (obj_id);
1983 static raid_obj_id_t
1984 obj_locate_hsp(raid_obj_tab_t *raid_tab, uint32_t controller_id,
1985 uint32_t disk_id, uint32_t array_id)
1987 raid_obj_id_t obj_id;
1988 hsp_attr_t *hsp_attr;
1990 obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
1991 if (obj_id <= OBJ_NONE)
1992 return (obj_id);
1994 obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_HSP);
1995 if (obj_id <= OBJ_NONE)
1996 return (obj_id);
1998 do {
1999 (void) obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
2000 if (hsp_attr->associated_id == array_id)
2001 break;
2003 obj_id = obj_get_sibling(raid_tab, obj_id);
2004 if (obj_id < OBJ_NONE)
2005 return (obj_id);
2006 } while (obj_id > OBJ_NONE);
2008 return (obj_id);
2011 static raid_obj_id_t
2012 obj_locate_disk(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2013 uint32_t disk_id)
2015 raid_obj_id_t obj_id;
2016 disk_attr_t *attr;
2018 obj_id = obj_locate_controller(raid_tab, controller_id);
2019 if (obj_id <= OBJ_NONE)
2020 return (obj_id);
2022 obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2023 if (obj_id <= OBJ_NONE)
2024 return (obj_id);
2026 do {
2027 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2028 if (attr == NULL)
2029 return (ERR_DEVICE_INVALID);
2031 if (attr->disk_id == disk_id)
2032 break;
2033 } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2035 return (obj_id);
2038 static raid_obj_id_t
2039 obj_locate_arraypart(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2040 uint32_t array_id, uint32_t disk_id)
2042 raid_obj_id_t obj_id;
2044 arraypart_attr_t *attr;
2046 obj_id = obj_locate_array(raid_tab, controller_id, array_id);
2047 if (obj_id <= OBJ_NONE)
2048 return (obj_id);
2050 obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY_PART);
2051 if (obj_id <= OBJ_NONE)
2052 return (obj_id);
2054 do {
2055 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2056 if (attr == NULL)
2057 return (ERR_DEVICE_INVALID);
2059 if (attr->disk_id == disk_id)
2060 break;
2061 } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) >
2062 OBJ_NONE);
2064 return (obj_id);
2067 static raid_obj_id_t
2068 obj_locate_diskseg(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2069 uint32_t disk_id, uint32_t seq_no)
2071 raid_obj_id_t obj_id;
2072 diskseg_attr_t *attr;
2074 obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2075 if (obj_id <= OBJ_NONE)
2076 return (obj_id);
2078 obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK_SEG);
2079 if (obj_id <= OBJ_NONE)
2080 return (obj_id);
2082 do {
2083 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2084 if (attr == NULL)
2085 return (ERR_DEVICE_INVALID);
2087 if (attr->seq_no == seq_no)
2088 break;
2089 } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2091 return (obj_id);
2094 static raid_obj_id_t
2095 obj_locate_task(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2096 uint32_t task_id)
2098 raid_obj_id_t obj_id, obj_id2, task_obj_id;
2099 task_attr_t *attr;
2101 obj_id = obj_locate_controller(raid_tab, controller_id);
2102 if (obj_id <= OBJ_NONE)
2103 return (obj_id);
2105 obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2106 if (obj_id < OBJ_NONE)
2107 return (obj_id);
2109 do {
2110 obj_id2 = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_ARRAY);
2111 while (obj_id2 != OBJ_NONE) {
2112 task_obj_id = obj_get_comp(raid_tab, obj_id2,
2113 OBJ_TYPE_TASK);
2115 if (task_obj_id < OBJ_NONE)
2116 return (task_obj_id);
2118 if (task_obj_id == OBJ_NONE) {
2119 obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2120 continue;
2123 attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2124 if (attr == NULL)
2125 return (ERR_DEVICE_INVALID);
2127 if (attr->task_id == task_id)
2128 return (task_obj_id);
2130 obj_id2 = obj_get_sibling(raid_tab, obj_id2);
2133 task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2134 if (task_obj_id < OBJ_NONE)
2135 return (task_obj_id);
2137 if (task_obj_id == OBJ_NONE)
2138 continue;
2140 attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2141 if (attr == NULL)
2142 return (ERR_DEVICE_INVALID);
2144 if (attr->task_id == task_id)
2145 return (task_obj_id);
2146 } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2148 if (obj_id < OBJ_NONE)
2149 return (obj_id);
2151 obj_id = obj_locate_controller(raid_tab, controller_id);
2152 obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_DISK);
2153 if (obj_id < OBJ_NONE)
2154 return (obj_id);
2156 do {
2157 task_obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_TASK);
2158 if (task_obj_id < OBJ_NONE)
2159 return (task_obj_id);
2161 if (task_obj_id == OBJ_NONE)
2162 continue;
2164 attr = raid_obj_get_data_ptr(raid_tab, task_obj_id);
2165 if (attr == NULL)
2166 return (ERR_DEVICE_INVALID);
2168 if (attr->task_id == task_id)
2169 return (task_obj_id);
2170 } while ((obj_id = obj_get_sibling(raid_tab, obj_id)) > OBJ_NONE);
2172 return (obj_id);
2175 static raid_obj_id_t
2176 obj_locate_prop(raid_obj_tab_t *raid_tab, uint32_t controller_id,
2177 uint32_t disk_id, uint32_t prop_id)
2179 raid_obj_id_t obj_id;
2180 property_attr_t *prop_attr;
2182 obj_id = obj_locate_disk(raid_tab, controller_id, disk_id);
2183 if (obj_id < OBJ_NONE)
2184 return (obj_id);
2186 obj_id = obj_get_comp(raid_tab, obj_id, OBJ_TYPE_PROP);
2187 if (obj_id <= OBJ_NONE)
2188 return (obj_id);
2190 do {
2191 (void) obj_get_attr(raid_tab, obj_id, (void **)(&prop_attr));
2192 if (prop_attr->prop_id == prop_id)
2193 break;
2195 obj_id = obj_get_sibling(raid_tab, obj_id);
2196 if (obj_id < OBJ_NONE)
2197 return (obj_id);
2198 } while (obj_id > OBJ_NONE);
2200 return (obj_id);
2203 static raid_obj_id_t
2204 obj_get_controller(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2206 raid_obj_id_t id = obj_id;
2208 while (raid_obj_get_type(raid_tab, id) != OBJ_TYPE_CONTROLLER) {
2209 id = raid_obj_get_container(raid_tab, id);
2210 if ((id == OBJ_SYSTEM) || (id < OBJ_NONE))
2211 return (ERR_DEVICE_INVALID);
2214 return (id);
2218 * Raid object operation routines
2220 static int
2221 obj_sys_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2222 raid_obj_type_id_t comp_type)
2224 DIR *dir;
2225 struct dirent *dp;
2226 int num = 0;
2228 if ((raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM))
2229 return (ERR_DEVICE_TYPE);
2231 if (comp_type != OBJ_TYPE_CONTROLLER)
2232 return (0);
2234 if ((dir = opendir(CFGDIR)) == NULL)
2235 return (ERR_DRIVER_NOT_FOUND);
2237 while ((dp = readdir(dir)) != NULL) {
2238 uint32_t controller_id;
2239 char path[MAX_PATH_LEN];
2241 if (strcmp(dp->d_name, ".") == 0 ||
2242 strcmp(dp->d_name, "..") == 0)
2243 continue;
2245 if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2246 continue;
2248 if (controller_id_to_path(controller_id, path) == SUCCESS)
2249 ++ num;
2252 (void) closedir(dir);
2253 return (num);
2256 static int
2257 obj_sys_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2258 int num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2260 DIR *dir;
2261 struct dirent *dp;
2262 controller_attr_t *attr;
2263 uint32_t controller_id;
2264 uint32_t *tmplist;
2265 char path[MAX_PATH_LEN];
2266 int i = 0;
2268 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_SYSTEM)
2269 return (ERR_DEVICE_TYPE);
2270 if ((num <= 0) || (comp_list == NULL))
2271 return (ERR_OP_ILLEGAL);
2273 if (comp_type != OBJ_TYPE_CONTROLLER)
2274 return (0);
2276 if ((dir = opendir(CFGDIR)) == NULL)
2277 return (ERR_DRIVER_NOT_FOUND);
2278 tmplist = calloc(num, sizeof (uint32_t));
2279 if (tmplist == NULL) {
2280 return (ERR_NOMEM);
2282 while ((dp = readdir(dir)) != NULL) {
2283 if (strcmp(dp->d_name, ".") == 0 ||
2284 strcmp(dp->d_name, "..") == 0)
2285 continue;
2287 if (sscanf(dp->d_name, "c%u", &controller_id) != 1)
2288 continue;
2290 if (controller_id_to_path(controller_id, path) == SUCCESS) {
2291 tmplist[i] = controller_id;
2292 ++ i;
2295 qsort((void *)tmplist, num, sizeof (uint32_t), intcompare);
2296 for (i = 0; i < num; i++) {
2297 attr = raid_obj_get_data_ptr(raid_tab,
2298 *(comp_list + i));
2300 if (attr == NULL) {
2301 free(tmplist);
2302 return (ERR_DEVICE_INVALID);
2305 attr->controller_id = tmplist[i];
2307 free(tmplist);
2308 (void) closedir(dir);
2309 return (SUCCESS);
2312 static int
2313 obj_controller_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2314 raid_obj_type_id_t comp_type)
2316 raid_lib_t *raid_lib;
2317 int ret = SUCCESS, fd;
2318 controller_attr_t *ctl_attrp;
2320 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2321 return (ERR_DEVICE_TYPE);
2323 if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2324 return (0);
2326 raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2327 fd = raid_obj_get_fd(raid_tab, obj_id);
2328 ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2329 if ((raid_lib == NULL) || (ctl_attrp == NULL) || (fd == 0))
2330 return (ERR_DRIVER_CLOSED);
2332 ret = raid_lib->compnum(ctl_attrp->controller_id, 0,
2333 OBJ_TYPE_CONTROLLER, comp_type);
2335 return (ret);
2338 static int
2339 obj_controller_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2340 int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2342 raid_lib_t *raid_lib;
2343 controller_attr_t *ctl_attrp;
2344 int ret, i, fd;
2345 uint32_t *ids;
2347 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2348 return (ERR_DEVICE_TYPE);
2350 if ((comp_type != OBJ_TYPE_ARRAY) && (comp_type != OBJ_TYPE_DISK))
2351 return (0);
2353 if ((comp_num <= 0) || (comp_list == NULL))
2354 return (ERR_OP_ILLEGAL);
2356 for (i = 0; i < comp_num; ++i)
2357 if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2358 comp_type)
2359 return (ERR_DEVICE_TYPE);
2361 raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2362 ctl_attrp = raid_obj_get_data_ptr(raid_tab, obj_id);
2363 fd = raid_obj_get_fd(raid_tab, obj_id);
2364 if ((raid_lib == NULL) || (ctl_attrp == NULL)|| (fd == 0))
2365 return (ERR_DRIVER_CLOSED);
2367 ids = malloc(comp_num * sizeof (uint32_t));
2368 if (ids == NULL)
2369 return (ERR_NOMEM);
2371 ret = raid_lib->complist(ctl_attrp->controller_id, 0,
2372 OBJ_TYPE_CONTROLLER, comp_type, comp_num, ids);
2373 if (ret < SUCCESS) {
2374 free(ids);
2375 return (ret);
2377 qsort((void *)ids, comp_num, sizeof (uint32_t), intcompare);
2378 for (i = 0; i < comp_num; ++ i) {
2379 array_attr_t *array_attr;
2380 disk_attr_t *disk_attr;
2381 void *attr_buf;
2383 attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2384 if (attr_buf == NULL) {
2385 free(ids);
2386 return (ERR_DEVICE_INVALID);
2389 switch (comp_type) {
2390 case OBJ_TYPE_ARRAY:
2391 array_attr = attr_buf;
2392 array_attr->array_id = *(ids + i);
2393 break;
2394 case OBJ_TYPE_DISK:
2395 disk_attr = attr_buf;
2396 disk_attr->disk_id = *(ids + i);
2397 break;
2398 default:
2399 free(ids);
2400 return (ERR_DEVICE_INVALID);
2404 free(ids);
2405 return (SUCCESS);
2408 static int
2409 obj_controller_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2411 controller_attr_t *attr;
2412 raid_lib_t *raid_lib;
2413 int ret = SUCCESS, fd;
2415 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2416 return (ERR_DEVICE_TYPE);
2418 if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2419 return (SUCCESS);
2421 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2422 if (attr == NULL)
2423 return (ERR_DEVICE_INVALID);
2425 raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2426 fd = raid_obj_get_fd(raid_tab, obj_id);
2429 * For a controller, even it's not opened, we can still
2430 * get the driver name
2433 if (fd == 0)
2434 return (SUCCESS);
2436 if (raid_lib == NULL) {
2437 return (SUCCESS);
2440 ret = raid_lib->get_attr(attr->controller_id, OBJ_ATTR_NONE,
2441 OBJ_ATTR_NONE, OBJ_TYPE_CONTROLLER, attr);
2442 if (ret < SUCCESS)
2443 return (ret);
2445 (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2447 return (ret);
2450 static int
2451 obj_controller_act(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2452 uint32_t sub_cmd, void *prop_list, char **plugin_err_str)
2454 controller_attr_t *attr;
2455 raid_lib_t *raid_lib;
2456 int ret, fd;
2458 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_CONTROLLER)
2459 return (ERR_DEVICE_TYPE);
2461 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2463 raid_lib = raid_obj_get_lib(raid_tab, obj_id);
2464 fd = raid_obj_get_fd(raid_tab, obj_id);
2466 switch (sub_cmd) {
2467 case ACT_CONTROLLER_OPEN:
2468 /* Check if already opened */
2470 if (fd > 0)
2471 return (SUCCESS);
2473 /* Check if plugin is already attached */
2474 if (raid_lib == NULL) {
2475 raid_lib = raid_find_lib(raid_tab, obj_id);
2476 if (raid_lib == NULL)
2477 return (ERR_DRIVER_NOT_FOUND);
2480 ret = raid_lib->open_controller(attr->controller_id,
2481 plugin_err_str);
2482 if (ret == SUCCESS) {
2483 (void) raid_obj_set_lib(raid_tab, obj_id, raid_lib);
2484 (void) raid_obj_set_fd(raid_tab, obj_id, 1);
2486 break;
2487 case ACT_CONTROLLER_CLOSE:
2489 if (fd <= 0)
2490 return (SUCCESS);
2492 if (raid_lib == NULL) {
2493 return (SUCCESS);
2495 ret = raid_lib->close_controller(attr->controller_id,
2496 plugin_err_str);
2497 if (ret == SUCCESS) {
2498 (void) raid_obj_set_fd(raid_tab, obj_id, 0);
2499 (void) raid_obj_set_lib(raid_tab, obj_id, NULL);
2500 raid_handle_delete_controller_comp(attr->controller_id);
2502 break;
2503 case ACT_CONTROLLER_FLASH_FW:
2505 char *filebuf;
2506 int image_fd;
2507 uint32_t size;
2508 struct stat statbuf;
2510 if (prop_list == NULL)
2511 return (ERR_OP_ILLEGAL);
2513 /* Open firmware image file */
2514 image_fd = open((const char *)prop_list,
2515 O_RDONLY | O_NDELAY);
2516 if (image_fd == -1)
2517 return (ERR_OP_FAILED);
2519 if (fstat(image_fd, &statbuf) != 0) {
2520 (void) close(image_fd);
2521 return (ERR_OP_FAILED);
2524 filebuf = malloc(statbuf.st_size);
2525 if (filebuf == NULL) {
2526 (void) close(image_fd);
2527 return (ERR_NOMEM);
2530 size = read(image_fd, filebuf, statbuf.st_size);
2531 if (size != statbuf.st_size) {
2532 (void) close(image_fd);
2533 free(filebuf);
2534 return (ERR_OP_FAILED);
2537 if (fd <= 0) {
2538 (void) close(image_fd);
2539 free(filebuf);
2540 return (ERR_DRIVER_CLOSED);
2543 if (raid_lib == NULL) {
2544 (void) close(image_fd);
2545 free(filebuf);
2546 return (ERR_DRIVER_CLOSED);
2548 if (raid_lib->flash_fw == NULL) {
2549 (void) close(image_fd);
2550 free(filebuf);
2551 return (ERR_OP_NO_IMPL);
2554 ret = raid_lib->flash_fw(attr->controller_id,
2555 filebuf, size, plugin_err_str);
2557 break;
2558 default:
2559 return (ERR_OP_ILLEGAL);
2562 return (ret);
2565 static int
2566 obj_array_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2567 raid_obj_type_id_t comp_type)
2569 array_attr_t *attr;
2570 controller_attr_t *ctl_attrp;
2571 raid_obj_id_t controller_obj_id;
2572 raid_lib_t *raid_lib;
2573 int ret = SUCCESS, fd;
2575 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2576 return (ERR_DEVICE_TYPE);
2578 if (comp_type != OBJ_TYPE_ARRAY_PART &&
2579 comp_type != OBJ_TYPE_ARRAY &&
2580 comp_type != OBJ_TYPE_TASK)
2581 return (0);
2583 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2584 if (attr == NULL)
2585 return (ERR_DEVICE_INVALID);
2587 controller_obj_id = obj_get_controller(raid_tab, obj_id);
2588 if (controller_obj_id < OBJ_NONE)
2589 return (ERR_DEVICE_INVALID);
2591 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2592 if (ctl_attrp == NULL) {
2593 return (ERR_DEVICE_INVALID);
2596 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2597 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2598 if ((raid_lib == NULL) || (fd == 0))
2599 return (ERR_DRIVER_CLOSED);
2601 ret = raid_lib->compnum(ctl_attrp->controller_id, attr->array_id,
2602 OBJ_TYPE_ARRAY, comp_type);
2604 return (ret);
2607 static int
2608 obj_array_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2609 int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2611 array_attr_t *attr;
2612 controller_attr_t *ctl_attrp;
2613 raid_obj_id_t controller_obj_id;
2614 raid_lib_t *raid_lib;
2615 int ret, i, fd;
2616 uint32_t *ids;
2618 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2619 return (ERR_DEVICE_TYPE);
2621 if (comp_type != OBJ_TYPE_ARRAY_PART &&
2622 comp_type != OBJ_TYPE_ARRAY &&
2623 comp_type != OBJ_TYPE_TASK)
2624 return (0);
2626 if (comp_num <= 0 || comp_list == NULL)
2627 return (ERR_OP_ILLEGAL);
2629 for (i = 0; i < comp_num; ++i)
2630 if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2631 comp_type)
2632 return (ERR_DEVICE_TYPE);
2634 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2635 if (attr == NULL)
2636 return (ERR_DEVICE_INVALID);
2638 controller_obj_id = obj_get_controller(raid_tab, obj_id);
2639 if (controller_obj_id < OBJ_NONE)
2640 return (ERR_DEVICE_INVALID);
2642 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2643 if (ctl_attrp == NULL) {
2644 return (ERR_DEVICE_INVALID);
2647 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2648 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2649 if ((raid_lib == NULL) || (fd == 0))
2650 return (ERR_DRIVER_CLOSED);
2652 ids = malloc(comp_num * sizeof (uint32_t));
2653 if (ids == NULL)
2654 return (ERR_NOMEM);
2656 ret = raid_lib->complist(ctl_attrp->controller_id,
2657 attr->array_id, OBJ_TYPE_ARRAY, comp_type, comp_num, ids);
2659 if (ret < SUCCESS) {
2660 free(ids);
2661 return (ret);
2664 for (i = 0; i < comp_num; ++ i) {
2665 array_attr_t *array_attr;
2666 arraypart_attr_t *arraypart_attr;
2667 task_attr_t *task_attr;
2668 void *attr_buf;
2670 attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2671 if (attr_buf == NULL) {
2672 free(ids);
2673 return (ERR_DEVICE_INVALID);
2676 switch (comp_type) {
2677 case OBJ_TYPE_ARRAY:
2678 array_attr = attr_buf;
2679 array_attr->array_id = *(ids + i);
2680 break;
2681 case OBJ_TYPE_ARRAY_PART:
2682 arraypart_attr = attr_buf;
2683 arraypart_attr->disk_id = *(ids + i);
2684 break;
2685 case OBJ_TYPE_TASK:
2686 task_attr = attr_buf;
2687 task_attr->task_id = *(ids + i);
2688 break;
2689 default:
2690 free(ids);
2691 return (ERR_DEVICE_INVALID);
2696 free(ids);
2697 return (ret);
2700 static int
2701 obj_array_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2703 array_attr_t *attr;
2704 controller_attr_t *ctl_attrp;
2705 raid_lib_t *raid_lib;
2706 int ret = SUCCESS, fd;
2707 raid_obj_id_t controller_obj_id;
2709 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2710 return (ERR_DEVICE_TYPE);
2712 if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2713 return (SUCCESS);
2715 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2716 if (attr == NULL)
2717 return (ERR_DEVICE_INVALID);
2719 controller_obj_id = obj_get_controller(raid_tab, obj_id);
2720 if (controller_obj_id < OBJ_NONE)
2721 return (ERR_DEVICE_INVALID);
2723 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2724 if (ctl_attrp == NULL) {
2725 return (ERR_DEVICE_INVALID);
2728 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2729 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2730 if ((raid_lib == NULL) || (fd == 0))
2731 return (ERR_DRIVER_CLOSED);
2733 ret = raid_lib->get_attr(ctl_attrp->controller_id,
2734 attr->array_id, 0, OBJ_TYPE_ARRAY, attr);
2736 if (ret < SUCCESS)
2737 return (ret);
2739 (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2741 return (ret);
2744 static int
2745 obj_array_set_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2746 uint32_t sub_cmd, uint32_t *value, char **plugin_err_str)
2748 array_attr_t *attr;
2749 controller_attr_t *ctl_attrp;
2750 raid_lib_t *raid_lib;
2751 int ret = SUCCESS, fd;
2752 raid_obj_id_t controller_obj_id;
2754 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY)
2755 return (ERR_DEVICE_TYPE);
2757 switch (sub_cmd) {
2758 case SET_CACHE_WR_PLY:
2759 if (*value != CACHE_WR_OFF &&
2760 *value != CACHE_WR_ON)
2761 return (ERR_OP_ILLEGAL);
2762 break;
2763 case SET_CACHE_RD_PLY:
2764 if (*value != CACHE_RD_OFF &&
2765 *value != CACHE_RD_ON)
2766 return (ERR_OP_ILLEGAL);
2767 break;
2768 case SET_ACTIVATION_PLY:
2769 if (*value != ARRAY_ACT_ACTIVATE)
2770 return (ERR_OP_ILLEGAL);
2771 break;
2772 default:
2773 return (ERR_OP_ILLEGAL);
2776 (void) obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2778 controller_obj_id = obj_get_controller(raid_tab, obj_id);
2779 if (controller_obj_id < OBJ_NONE)
2780 return (ERR_DEVICE_INVALID);
2782 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2783 if (ctl_attrp == NULL) {
2784 return (ERR_DEVICE_INVALID);
2787 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2788 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2789 if ((raid_lib == NULL) || (fd == 0))
2790 return (ERR_DRIVER_CLOSED);
2792 if (raid_lib->set_attr == NULL)
2793 return (ERR_OP_NO_IMPL);
2795 ret = raid_lib->set_attr(ctl_attrp->controller_id,
2796 attr->array_id, sub_cmd, value, plugin_err_str);
2798 return (ret);
2801 static int
2802 obj_disk_compnum(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2803 raid_obj_type_id_t comp_type)
2805 disk_attr_t *attr;
2806 controller_attr_t *ctl_attrp;
2807 raid_obj_id_t controller_obj_id;
2808 raid_lib_t *raid_lib;
2809 int ret = SUCCESS, fd;
2811 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2812 return (ERR_DEVICE_TYPE);
2814 if (comp_type != OBJ_TYPE_DISK_SEG &&
2815 comp_type != OBJ_TYPE_HSP &&
2816 comp_type != OBJ_TYPE_TASK &&
2817 comp_type != OBJ_TYPE_PROP)
2818 return (0);
2819 ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2820 if ((ret != SUCCESS) || (attr == NULL)) {
2821 return (ERR_DEVICE_INVALID);
2823 if (attr->state == DISK_STATE_FAILED) {
2824 return (SUCCESS);
2827 controller_obj_id = obj_get_controller(raid_tab, obj_id);
2828 if (controller_obj_id < OBJ_NONE)
2829 return (ERR_DEVICE_INVALID);
2831 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2832 if (ctl_attrp == NULL) {
2833 return (ERR_DEVICE_INVALID);
2836 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2837 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2838 if ((raid_lib == NULL) || (fd == 0))
2839 return (ERR_DRIVER_CLOSED);
2841 ret = raid_lib->compnum(ctl_attrp->controller_id,
2842 attr->disk_id, OBJ_TYPE_DISK, comp_type);
2844 return (ret);
2847 static int
2848 obj_disk_complist(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
2849 int comp_num, raid_obj_id_t *comp_list, raid_obj_type_id_t comp_type)
2851 disk_attr_t *attr;
2852 controller_attr_t *ctl_attrp;
2853 raid_obj_id_t controller_obj_id;
2854 raid_lib_t *raid_lib;
2855 int ret, i, fd;
2856 uint32_t *ids;
2858 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2859 return (ERR_DEVICE_TYPE);
2861 if (comp_type != OBJ_TYPE_DISK_SEG &&
2862 comp_type != OBJ_TYPE_HSP &&
2863 comp_type != OBJ_TYPE_TASK &&
2864 comp_type != OBJ_TYPE_PROP)
2865 return (0);
2867 if (comp_num <= 0 || comp_list == NULL)
2868 return (ERR_OP_ILLEGAL);
2870 for (i = 0; i < comp_num; ++i)
2871 if (raid_obj_get_type(raid_tab, *(comp_list + i)) !=
2872 comp_type)
2873 return (ERR_DEVICE_TYPE);
2874 ret = obj_get_attr(raid_tab, obj_id, (void **)(&attr));
2875 if ((ret != SUCCESS) || (attr == NULL)) {
2876 return (ERR_DEVICE_INVALID);
2878 if (attr->state == DISK_STATE_FAILED) {
2879 return (SUCCESS);
2882 controller_obj_id = obj_get_controller(raid_tab, obj_id);
2883 if (controller_obj_id < OBJ_NONE)
2884 return (ERR_DEVICE_INVALID);
2886 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2887 if (ctl_attrp == NULL) {
2888 return (ERR_DEVICE_INVALID);
2891 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2892 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2893 if ((raid_lib == NULL) || (fd == 0))
2894 return (ERR_DRIVER_CLOSED);
2896 ids = malloc(comp_num * sizeof (uint32_t));
2897 if (ids == NULL)
2898 return (ERR_NOMEM);
2900 ret = raid_lib->complist(ctl_attrp->controller_id,
2901 attr->disk_id, OBJ_TYPE_DISK, comp_type, comp_num, ids);
2903 if (ret < SUCCESS) {
2904 free(ids);
2905 return (ret);
2908 for (i = 0; i < comp_num; ++ i) {
2909 diskseg_attr_t *diskseg_attr;
2910 hsp_attr_t *hsp_attr;
2911 task_attr_t *task_attr;
2912 property_attr_t *prop_attr;
2913 void *attr_buf;
2915 attr_buf = raid_obj_get_data_ptr(raid_tab, *(comp_list + i));
2916 if (attr_buf == NULL) {
2917 free(ids);
2918 return (ERR_DEVICE_INVALID);
2921 switch (comp_type) {
2922 case OBJ_TYPE_DISK_SEG:
2923 diskseg_attr = attr_buf;
2924 diskseg_attr->seq_no = *(ids + i);
2925 break;
2926 case OBJ_TYPE_HSP:
2927 hsp_attr = attr_buf;
2928 hsp_attr->associated_id = *(ids + i);
2929 break;
2930 case OBJ_TYPE_TASK:
2931 task_attr = attr_buf;
2932 task_attr->task_id = *(ids + i);
2933 break;
2934 case OBJ_TYPE_PROP:
2935 prop_attr = attr_buf;
2936 prop_attr->prop_id = *(ids + i);
2937 break;
2938 default:
2939 free(ids);
2940 return (ERR_DEVICE_INVALID);
2945 free(ids);
2946 return (ret);
2949 static int
2950 obj_disk_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2952 disk_attr_t *attr;
2953 controller_attr_t *ctl_attrp;
2954 raid_lib_t *raid_lib;
2955 int ret = SUCCESS, fd;
2956 raid_obj_id_t controller_obj_id;
2958 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK)
2959 return (ERR_DEVICE_TYPE);
2961 if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
2962 return (SUCCESS);
2964 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
2965 if (attr == NULL)
2966 return (ERR_DEVICE_INVALID);
2968 controller_obj_id = obj_get_controller(raid_tab, obj_id);
2969 if (controller_obj_id < OBJ_NONE)
2970 return (ERR_DEVICE_INVALID);
2972 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
2973 if (ctl_attrp == NULL) {
2974 return (ERR_DEVICE_INVALID);
2977 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
2978 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
2979 if ((raid_lib == NULL) || (fd == 0))
2980 return (ERR_DRIVER_CLOSED);
2982 ret = raid_lib->get_attr(ctl_attrp->controller_id,
2983 attr->disk_id, 0, OBJ_TYPE_DISK, attr);
2985 if (ret < SUCCESS)
2986 return (ret);
2988 (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
2990 return (ret);
2993 static int
2994 obj_hsp_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
2996 hsp_attr_t *attr;
2998 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_HSP)
2999 return (ERR_DEVICE_TYPE);
3001 if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3002 return (SUCCESS);
3004 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3005 if (attr == NULL)
3006 return (ERR_DEVICE_INVALID);
3008 if (attr->associated_id == (uint32_t)OBJ_ATTR_NONE)
3009 attr->type = HSP_TYPE_GLOBAL;
3010 else
3011 attr->type = HSP_TYPE_LOCAL;
3013 return (SUCCESS);
3016 static int
3017 obj_arraypart_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3019 arraypart_attr_t *attr;
3020 array_attr_t *array_attr;
3021 controller_attr_t *ctl_attrp;
3022 raid_lib_t *raid_lib;
3023 int ret = SUCCESS, fd;
3024 raid_obj_id_t controller_obj_id, array_obj_id;
3026 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_ARRAY_PART)
3027 return (ERR_DEVICE_TYPE);
3029 if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3030 return (SUCCESS);
3032 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3033 if (attr == NULL)
3034 return (ERR_DEVICE_INVALID);
3036 array_obj_id = raid_obj_get_container(raid_tab, obj_id);
3037 if (array_obj_id < OBJ_NONE)
3038 return (ERR_DEVICE_INVALID);
3040 array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3041 if (array_attr == NULL)
3042 return (ERR_DEVICE_INVALID);
3044 controller_obj_id = obj_get_controller(raid_tab, obj_id);
3045 if (controller_obj_id < OBJ_NONE)
3046 return (ERR_DEVICE_INVALID);
3048 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3049 if (ctl_attrp == NULL) {
3050 return (ERR_DEVICE_INVALID);
3053 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3054 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3055 if ((raid_lib == NULL) || (fd == 0))
3056 return (ERR_DRIVER_CLOSED);
3058 ret = raid_lib->get_attr(ctl_attrp->controller_id,
3059 array_attr->array_id, attr->disk_id,
3060 OBJ_TYPE_ARRAY_PART, attr);
3062 if (ret < SUCCESS)
3063 return (ret);
3065 (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3067 return (ret);
3070 static int
3071 obj_diskseg_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3073 diskseg_attr_t *attr;
3074 disk_attr_t *disk_attr;
3075 controller_attr_t *ctl_attrp;
3076 raid_lib_t *raid_lib;
3077 int ret = SUCCESS, fd;
3078 raid_obj_id_t controller_obj_id, disk_obj_id;
3080 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_DISK_SEG)
3081 return (ERR_DEVICE_TYPE);
3083 if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3084 return (SUCCESS);
3086 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3087 if (attr == NULL)
3088 return (ERR_DEVICE_INVALID);
3090 disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
3091 if (disk_obj_id < OBJ_NONE)
3092 return (ERR_DEVICE_INVALID);
3094 disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
3095 if (disk_attr == NULL)
3096 return (ERR_DEVICE_INVALID);
3098 controller_obj_id = obj_get_controller(raid_tab, obj_id);
3099 if (controller_obj_id < OBJ_NONE)
3100 return (ERR_DEVICE_INVALID);
3102 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3103 if (ctl_attrp == NULL) {
3104 return (ERR_DEVICE_INVALID);
3107 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3108 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3109 if ((raid_lib == NULL) || (fd == 0))
3110 return (ERR_DRIVER_CLOSED);
3112 ret = raid_lib->get_attr(ctl_attrp->controller_id,
3113 disk_attr->disk_id, attr->seq_no, OBJ_TYPE_DISK_SEG, attr);
3115 if (ret < SUCCESS)
3116 return (ret);
3118 (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3120 return (ret);
3123 static int
3124 obj_task_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3126 task_attr_t *attr;
3127 controller_attr_t *ctl_attrp;
3128 raid_lib_t *raid_lib;
3129 int ret = SUCCESS, fd;
3130 raid_obj_id_t controller_obj_id;
3132 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_TASK)
3133 return (ERR_DEVICE_TYPE);
3135 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3136 if (attr == NULL)
3137 return (ERR_DEVICE_INVALID);
3139 controller_obj_id = obj_get_controller(raid_tab, obj_id);
3140 if (controller_obj_id < OBJ_NONE)
3141 return (ERR_DEVICE_INVALID);
3143 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3144 if (ctl_attrp == NULL) {
3145 return (ERR_DEVICE_INVALID);
3148 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3149 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3150 if ((raid_lib == NULL) || (fd == 0))
3151 return (ERR_DRIVER_CLOSED);
3153 ret = raid_lib->get_attr(ctl_attrp->controller_id,
3154 attr->task_id, OBJ_ATTR_NONE, OBJ_TYPE_TASK, attr);
3156 return (ret);
3159 static int
3160 obj_prop_get_attr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
3162 property_attr_t *attr, *attr_new;
3163 disk_attr_t *disk_attr;
3164 controller_attr_t *ctl_attrp;
3165 raid_lib_t *raid_lib;
3166 int ret = SUCCESS, fd;
3167 raid_obj_id_t controller_obj_id, disk_obj_id;
3169 if (raid_obj_get_type(raid_tab, obj_id) != OBJ_TYPE_PROP)
3170 return (ERR_DEVICE_TYPE);
3172 if (raid_obj_get_status(raid_tab, obj_id) & OBJ_STATUS_OPENED)
3173 return (SUCCESS);
3175 attr = raid_obj_get_data_ptr(raid_tab, obj_id);
3176 if (attr == NULL)
3177 return (ERR_DEVICE_INVALID);
3179 disk_obj_id = raid_obj_get_container(raid_tab, obj_id);
3180 if (disk_obj_id < OBJ_NONE)
3181 return (ERR_DEVICE_INVALID);
3183 disk_attr = raid_obj_get_data_ptr(raid_tab, disk_obj_id);
3184 if (disk_attr == NULL)
3185 return (ERR_DEVICE_INVALID);
3187 controller_obj_id = obj_get_controller(raid_tab, obj_id);
3188 if (controller_obj_id < OBJ_NONE)
3189 return (ERR_DEVICE_INVALID);
3191 ctl_attrp = raid_obj_get_data_ptr(raid_tab, controller_obj_id);
3192 if (ctl_attrp == NULL) {
3193 return (ERR_DEVICE_INVALID);
3196 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3197 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3198 if ((raid_lib == NULL) || (fd == 0))
3199 return (ERR_DRIVER_CLOSED);
3201 /* Get the property size at first */
3202 attr->prop_size = 0;
3203 ret = raid_lib->get_attr(ctl_attrp->controller_id,
3204 disk_attr->disk_id, OBJ_ATTR_NONE, OBJ_TYPE_PROP, attr);
3206 if (ret < SUCCESS)
3207 return (ret);
3209 /* Allocate memory for property and fill the buffer */
3210 attr_new = realloc(attr, sizeof (property_attr_t) + attr->prop_size);
3211 if (attr_new == NULL)
3212 return (ERR_NOMEM);
3214 (void) raid_obj_set_data_ptr(raid_tab, obj_id, attr_new);
3216 ret = raid_lib->get_attr(ctl_attrp->controller_id,
3217 disk_attr->disk_id, OBJ_ATTR_NONE, OBJ_TYPE_PROP, attr_new);
3219 if (ret < SUCCESS)
3220 return (ret);
3222 (void) raid_obj_set_status(raid_tab, obj_id, OBJ_STATUS_OPENED);
3224 return (ret);
3227 static int
3228 obj_array_create(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3229 int num_of_comp, raid_obj_id_t *disk_list, char **plugin_err_str)
3231 controller_attr_t *controller_attr;
3232 array_attr_t *array_attr, array_attr2;
3233 disk_attr_t *disk_attr;
3234 arraypart_attr_t *arraypart_attrs;
3235 raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3236 raid_lib_t *raid_lib;
3237 int i, j, ret, fd;
3238 int disk_cnt = 0, disk_set_num = 0, set_num = 0, layer_cnt = 0;
3239 uint64_t min_disk_capacity = 0;
3241 array_attr = raid_obj_get_data_ptr(raid_tab, array_obj_id);
3242 if (array_attr == NULL)
3243 return (ERR_DEVICE_INVALID);
3245 /* Check the disk layout expression */
3246 if (disk_list[0] != OBJ_SEPARATOR_BEGIN ||
3247 disk_list[num_of_comp - 1] != OBJ_SEPARATOR_END)
3248 return (ERR_ARRAY_LAYOUT);
3249 for (i = 0; i < num_of_comp; ++i) {
3250 if (disk_list[i] == OBJ_SEPARATOR_BEGIN) {
3251 if (disk_cnt != 0)
3252 return (ERR_ARRAY_LAYOUT);
3253 ++layer_cnt;
3254 continue;
3256 if (disk_list[i] == OBJ_SEPARATOR_END) {
3257 if (disk_set_num == 0)
3258 disk_set_num = disk_cnt;
3259 else if (disk_set_num != disk_cnt && disk_cnt != 0)
3260 return (ERR_ARRAY_LAYOUT);
3261 disk_cnt = 0;
3262 ++set_num;
3263 --layer_cnt;
3264 continue;
3266 switch (array_attr->raid_level) {
3267 case RAID_LEVEL_0:
3268 case RAID_LEVEL_1:
3269 case RAID_LEVEL_1E:
3270 case RAID_LEVEL_5:
3271 if (layer_cnt != 1)
3272 return (ERR_ARRAY_LAYOUT);
3273 break;
3274 case RAID_LEVEL_10:
3275 case RAID_LEVEL_50:
3276 if (layer_cnt != 2)
3277 return (ERR_ARRAY_LAYOUT);
3278 break;
3279 default:
3280 return (ERR_ARRAY_LEVEL);
3282 ++disk_cnt;
3285 if (layer_cnt != 0)
3286 return (ERR_ARRAY_LAYOUT);
3288 switch (array_attr->raid_level) {
3289 case RAID_LEVEL_0:
3290 if (disk_set_num < 2 || set_num != 1)
3291 return (ERR_ARRAY_LAYOUT);
3292 break;
3293 case RAID_LEVEL_1:
3294 if (disk_set_num != 2 || set_num != 1)
3295 return (ERR_ARRAY_LAYOUT);
3296 break;
3297 case RAID_LEVEL_1E:
3298 case RAID_LEVEL_5:
3299 if (disk_set_num < 3 || set_num != 1)
3300 return (ERR_ARRAY_LAYOUT);
3301 break;
3302 case RAID_LEVEL_10:
3303 if (disk_set_num != 2 || set_num < 2)
3304 return (ERR_ARRAY_LAYOUT);
3305 break;
3306 case RAID_LEVEL_50:
3307 if (disk_set_num < 3 || set_num < 2)
3308 return (ERR_ARRAY_LAYOUT);
3309 break;
3310 default:
3311 return (ERR_ARRAY_LEVEL);
3314 arraypart_attrs = calloc(num_of_comp, sizeof (arraypart_attr_t));
3315 if (arraypart_attrs == NULL)
3316 return (ERR_NOMEM);
3318 for (i = 0; i < num_of_comp; ++i) {
3319 /* Keep seperators */
3320 if (*(disk_list + i) == OBJ_SEPARATOR_BEGIN) {
3321 arraypart_attrs[i].disk_id =
3322 (uint32_t)OBJ_SEPARATOR_BEGIN;
3323 continue;
3326 if (*(disk_list + i) == OBJ_SEPARATOR_END) {
3327 arraypart_attrs[i].disk_id =
3328 (uint32_t)OBJ_SEPARATOR_END;
3329 continue;
3332 disk_cnt++;
3333 /* Check if it's a disk */
3334 if (raid_obj_get_type(raid_tab, *(disk_list + i)) !=
3335 OBJ_TYPE_DISK)
3336 return (ERR_DEVICE_TYPE);
3338 /* Check if it's duplicated with other disks */
3339 for (j = 0; j < i; ++j)
3340 if (*(disk_list + j) == *(disk_list + i)) {
3341 free(arraypart_attrs);
3342 return (ERR_DEVICE_DUP);
3345 /* Check disk status */
3346 ret = obj_get_attr(raid_tab, *(disk_list + i),
3347 (void **)(&disk_attr));
3348 if (ret != SUCCESS)
3349 return (ret);
3351 if (disk_attr->state != DISK_STATE_GOOD) {
3352 free(arraypart_attrs);
3353 return (ERR_DISK_STATE);
3356 /* All disks must belong to the same controller */
3357 obj_id = obj_get_controller(raid_tab, *(disk_list + i));
3358 if (obj_id <= OBJ_NONE)
3359 return (obj_id);
3360 if (controller_obj_id == OBJ_NONE) {
3361 controller_obj_id = obj_id;
3362 ret = obj_get_attr(raid_tab, controller_obj_id,
3363 (void **)(&controller_attr));
3364 } else if (obj_id != controller_obj_id) {
3365 free(arraypart_attrs);
3366 return (ERR_DRIVER_ACROSS);
3369 /* Check if the disk contains too many segments */
3370 obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3371 OBJ_TYPE_DISK_SEG);
3372 j = 0;
3373 while (obj_id > OBJ_NONE) {
3374 ++j;
3375 obj_id = obj_get_sibling(raid_tab, obj_id);
3377 if (j > controller_attr->max_seg_per_disk) {
3378 free(arraypart_attrs);
3379 return (ERR_DISK_SEG_AMOUNT);
3382 /* Check if controller is a hostraid controller */
3383 if (controller_attr->capability & RAID_CAP_DISK_TRANS) {
3385 * For hostraid, the first disk should
3386 * be with of minimum capacity
3388 if (min_disk_capacity == 0) {
3389 min_disk_capacity = disk_attr->capacity;
3391 /* Can not specify capacity for hostraid */
3392 if (array_attr->capacity != 0) {
3393 free(arraypart_attrs);
3394 return (ERR_OP_ILLEGAL);
3396 } else if (min_disk_capacity > disk_attr->capacity) {
3397 free(arraypart_attrs);
3398 return (ERR_DISK_SPACE);
3401 /* Disk should not be used for hostraid */
3402 obj_id = obj_get_comp(raid_tab, *(disk_list + i),
3403 OBJ_TYPE_DISK_SEG);
3404 if (obj_id < OBJ_NONE) {
3405 free(arraypart_attrs);
3406 return (obj_id);
3407 } else if (obj_id > OBJ_NONE) {
3408 free(arraypart_attrs);
3409 return (ERR_DISK_NOT_EMPTY);
3413 arraypart_attrs[i].disk_id = disk_attr->disk_id;
3414 arraypart_attrs[i].offset = OBJ_ATTR_NONE;
3415 arraypart_attrs[i].size = OBJ_ATTR_NONE;
3418 /* Check if array amount exceeds limit */
3419 if (controller_attr->max_array_num <=
3420 obj_controller_compnum(raid_tab, controller_obj_id,
3421 OBJ_TYPE_ARRAY))
3422 return (ERR_ARRAY_AMOUNT);
3425 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3426 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3427 if ((raid_lib == NULL) || (fd == 0))
3428 return (ERR_DRIVER_CLOSED);
3430 /* Check if the controller can support the array RAID level */
3431 switch (array_attr->raid_level) {
3432 case RAID_LEVEL_0:
3433 if (!(controller_attr->capability & RAID_CAP_RAID0)) {
3434 free(arraypart_attrs);
3435 return (ERR_ARRAY_LEVEL);
3437 break;
3438 case RAID_LEVEL_1:
3439 if (!(controller_attr->capability & RAID_CAP_RAID1)) {
3440 free(arraypart_attrs);
3441 return (ERR_ARRAY_LEVEL);
3443 break;
3444 case RAID_LEVEL_1E:
3445 if (!(controller_attr->capability & RAID_CAP_RAID1E)) {
3446 free(arraypart_attrs);
3447 return (ERR_ARRAY_LEVEL);
3449 break;
3450 case RAID_LEVEL_5:
3451 if (!(controller_attr->capability & RAID_CAP_RAID5)) {
3452 free(arraypart_attrs);
3453 return (ERR_ARRAY_LEVEL);
3455 break;
3456 case RAID_LEVEL_10:
3457 if (!(controller_attr->capability & RAID_CAP_RAID10)) {
3458 free(arraypart_attrs);
3459 return (ERR_ARRAY_LEVEL);
3461 break;
3462 case RAID_LEVEL_50:
3463 if (!(controller_attr->capability & RAID_CAP_RAID50)) {
3464 free(arraypart_attrs);
3465 return (ERR_ARRAY_LEVEL);
3467 break;
3468 default:
3469 free(arraypart_attrs);
3470 return (ERR_ARRAY_LEVEL);
3473 /* Check if plug in can calculate the maximum size */
3474 (void) memcpy(&array_attr2, array_attr, sizeof (array_attr_t));
3475 array_attr2.capacity = OBJ_ATTR_NONE;
3476 ret = raid_lib->array_create(controller_attr->controller_id,
3477 &array_attr2, num_of_comp, arraypart_attrs, plugin_err_str);
3479 /* If plugin/driver will not calculate space */
3480 if (ret == ERR_OP_NO_IMPL) {
3481 /* Calculate the maximum capacity */
3482 array_attr2.capacity = raid_space_noalign(raid_tab,
3483 array_attr2.raid_level, num_of_comp, disk_list,
3484 arraypart_attrs);
3487 * If controller is capable to allocate space,
3488 * set offset and size attributes to OBJ_ATTR_NONE
3489 * and let the controller to determine these value
3491 if (controller_attr->capability & RAID_CAP_SMART_ALLOC)
3492 for (i = 0; i < num_of_comp; ++i) {
3493 arraypart_attrs[i].offset =
3494 OBJ_ATTR_NONE;
3495 arraypart_attrs[i].size =
3496 OBJ_ATTR_NONE;
3499 /* There's no enough space for specified capacity */
3500 if (array_attr->capacity > array_attr2.capacity) {
3501 free(arraypart_attrs);
3502 return (ERR_ARRAY_SIZE);
3505 /* capacity == 0, allocate maximum space */
3506 if (array_attr->capacity == 0)
3507 array_attr->capacity = array_attr2.capacity;
3508 } else if (ret < SUCCESS) {
3509 free(arraypart_attrs);
3510 return (ret);
3511 } else if (array_attr2.capacity < array_attr->capacity) {
3512 /* Return the maximum size */
3513 array_attr->capacity = array_attr2.capacity;
3514 free(arraypart_attrs);
3515 return (ERR_ARRAY_SIZE);
3518 if (array_attr->capacity < ARRAYPART_MIN_SIZE * disk_cnt) {
3519 free(arraypart_attrs);
3520 return (ERR_ARRAY_SIZE);
3524 ret = raid_lib->array_create(controller_attr->controller_id,
3525 array_attr, num_of_comp, arraypart_attrs, plugin_err_str);
3526 free(arraypart_attrs);
3528 if (ret != SUCCESS)
3529 return (ret);
3531 /* Add array object into device tree so that we can map the handle */
3532 (void) raid_obj_add_org(raid_tab, array_obj_id, controller_obj_id);
3534 return (ret);
3537 static int
3538 obj_array_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t array_obj_id,
3539 char **plugin_err_str)
3541 raid_obj_id_t controller_obj_id;
3542 controller_attr_t *controller_attr;
3543 array_attr_t *array_attr;
3544 raid_lib_t *raid_lib;
3545 int ret, fd;
3546 uint32_t *disk_ids = NULL;
3548 controller_obj_id = obj_get_controller(raid_tab, array_obj_id);
3549 if (controller_obj_id <= OBJ_NONE)
3550 return (controller_obj_id);
3552 ret = obj_get_attr(raid_tab, controller_obj_id,
3553 (void **)(&controller_attr));
3554 if (ret < SUCCESS) {
3555 return (ret);
3557 ret = obj_get_attr(raid_tab, array_obj_id, (void **)(&array_attr));
3558 if (ret < SUCCESS)
3559 return (ret);
3561 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3562 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3563 if ((raid_lib == NULL) || (fd == 0))
3564 return (ERR_DRIVER_CLOSED);
3566 ret = raid_lib->array_delete(controller_attr->controller_id,
3567 array_attr->array_id, plugin_err_str);
3568 if (ret < SUCCESS) {
3569 free(disk_ids);
3570 return (ret);
3573 free(disk_ids);
3574 return (ret);
3577 static int
3578 obj_hsp_bind(raid_obj_tab_t *raid_tab, raid_obj_id_t *obj_ids,
3579 char **plugin_err_str)
3581 raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3582 raid_obj_id_t array_obj_id, disk_obj_id;
3583 hsp_relation_t *hsp_relation;
3584 controller_attr_t *controller_attr;
3585 array_attr_t *array_attr;
3586 arraypart_attr_t *arraypart_attr;
3587 disk_attr_t *disk_attr;
3588 diskseg_attr_t *diskseg_attr;
3589 hsp_attr_t *hsp_attr;
3590 raid_lib_t *raid_lib;
3591 int ret, fd;
3593 hsp_relation = malloc(sizeof (hsp_relation_t));
3594 if (hsp_relation == NULL)
3595 return (ERR_NOMEM);
3597 array_obj_id = *(obj_ids);
3598 disk_obj_id = *(obj_ids + 1);
3600 if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK ||
3601 (array_obj_id != OBJ_ATTR_NONE &&
3602 raid_obj_get_type(raid_tab, array_obj_id) !=
3603 OBJ_TYPE_ARRAY)) {
3604 free(hsp_relation);
3605 return (ERR_DEVICE_TYPE);
3608 /* Get controller attributes */
3609 if (controller_obj_id == OBJ_NONE)
3610 controller_obj_id = obj_get_controller(raid_tab,
3611 disk_obj_id);
3612 else if (controller_obj_id != obj_get_controller(raid_tab,
3613 disk_obj_id)) {
3614 free(hsp_relation);
3615 return (ERR_DRIVER_ACROSS);
3618 ret = obj_get_attr(raid_tab, controller_obj_id,
3619 (void **)(&controller_attr));
3621 /* Get disk attributes */
3622 ret = obj_get_attr(raid_tab, disk_obj_id,
3623 (void **)(&disk_attr));
3624 if (disk_attr->state == DISK_STATE_FAILED) {
3625 free(hsp_relation);
3626 return (ERR_DISK_STATE);
3629 /* If it's not a hsp disk, check if there's occupied space */
3630 if (obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP) ==
3631 OBJ_NONE) {
3632 obj_id = obj_get_comp(raid_tab, disk_obj_id,
3633 OBJ_TYPE_DISK_SEG);
3634 while (obj_id != OBJ_NONE) {
3635 ret = obj_get_attr(raid_tab, obj_id,
3636 (void **)(&diskseg_attr));
3637 if (!(diskseg_attr->state &
3638 DISKSEG_STATE_RESERVED)) {
3639 free(hsp_relation);
3640 return (ERR_DISK_NOT_EMPTY);
3642 obj_id = obj_get_sibling(raid_tab, obj_id);
3646 if (array_obj_id != OBJ_ATTR_NONE) {
3647 /* If local hsp is supported */
3648 if (!(controller_attr->capability & RAID_CAP_L_HSP)) {
3649 free(hsp_relation);
3650 return (ERR_OP_ILLEGAL);
3653 if (raid_obj_get_type(raid_tab, array_obj_id) !=
3654 OBJ_TYPE_ARRAY) {
3655 free(hsp_relation);
3656 return (ERR_DEVICE_TYPE);
3659 /* Get array attributes */
3660 ret = obj_get_attr(raid_tab, array_obj_id,
3661 (void **)(&array_attr));
3662 /* RAID 0 array can not use hsp */
3663 if (array_attr->raid_level == RAID_LEVEL_0) {
3664 free(hsp_relation);
3665 return (ERR_ARRAY_LEVEL);
3668 /* If It's belong to another controller */
3669 if (controller_obj_id != obj_get_controller(raid_tab,
3670 array_obj_id)) {
3671 free(hsp_relation);
3672 return (ERR_DRIVER_ACROSS);
3675 /* Get an array part attributes */
3676 if ((array_attr->raid_level == RAID_LEVEL_10) ||
3677 (array_attr->raid_level == RAID_LEVEL_50))
3678 obj_id = obj_get_comp(raid_tab, array_obj_id,
3679 OBJ_TYPE_ARRAY);
3680 else
3681 obj_id = array_obj_id;
3682 obj_id = obj_get_comp(raid_tab, obj_id,
3683 OBJ_TYPE_ARRAY_PART);
3684 ret = obj_get_attr(raid_tab, obj_id,
3685 (void **)(&arraypart_attr));
3687 /* Check if disk space is enough for array */
3688 if (arraypart_attr->size > disk_attr->capacity) {
3689 free(hsp_relation);
3690 return (ERR_DISK_SPACE);
3692 if (controller_attr->capability & RAID_CAP_ARRAY_ALIGN)
3693 if ((arraypart_attr->size +
3694 arraypart_attr->offset) >
3695 disk_attr->capacity) {
3696 free(hsp_relation);
3697 return (ERR_DISK_SPACE);
3699 } else if (!(controller_attr->capability & RAID_CAP_G_HSP)) {
3700 /* if global hsp is supported */
3701 free(hsp_relation);
3702 return (ERR_OP_ILLEGAL);
3706 * If the array is already associated with the
3707 * local hsp, or it's a global hsp, ignore it
3709 obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3710 if (obj_id > OBJ_NONE) {
3711 if (obj_get_attr(raid_tab, obj_id,
3712 (void **)&hsp_attr) >= SUCCESS) {
3713 if (((hsp_attr->type == HSP_TYPE_GLOBAL) &&
3714 (array_obj_id != OBJ_ATTR_NONE)) ||
3715 ((hsp_attr->type == HSP_TYPE_LOCAL) &&
3716 (array_obj_id == OBJ_ATTR_NONE))) {
3717 free(hsp_relation);
3718 return (ERR_OP_ILLEGAL);
3723 if (array_obj_id != OBJ_ATTR_NONE)
3724 hsp_relation->array_id = array_attr->array_id;
3725 else
3726 hsp_relation->array_id = (uint32_t)OBJ_ATTR_NONE;
3727 hsp_relation->disk_id = disk_attr->disk_id;
3729 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3730 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3731 if ((raid_lib == NULL) || (fd == 0))
3732 return (ERR_DRIVER_CLOSED);
3734 if (raid_lib->hsp_bind == NULL) {
3735 free(hsp_relation);
3736 return (ERR_OP_NO_IMPL);
3739 ret = raid_lib->hsp_bind(controller_attr->controller_id,
3740 hsp_relation, plugin_err_str);
3742 free(hsp_relation);
3743 return (ret);
3746 static int
3747 obj_hsp_unbind(raid_obj_tab_t *raid_tab, raid_obj_id_t *obj_ids,
3748 char **plugin_err_str)
3750 raid_obj_id_t obj_id, controller_obj_id = OBJ_NONE;
3751 raid_obj_id_t array_obj_id, disk_obj_id;
3752 hsp_relation_t *hsp_relation;
3753 controller_attr_t *controller_attr;
3754 array_attr_t *array_attr;
3755 disk_attr_t *disk_attr;
3756 hsp_attr_t *hsp_attr;
3757 raid_lib_t *raid_lib;
3758 int ret, fd;
3760 hsp_relation = malloc(sizeof (hsp_relation_t));
3761 if (hsp_relation == NULL)
3762 return (ERR_NOMEM);
3764 array_obj_id = *(obj_ids);
3765 disk_obj_id = *(obj_ids + 1);
3767 if (raid_obj_get_type(raid_tab, disk_obj_id) != OBJ_TYPE_DISK) {
3768 free(hsp_relation);
3769 return (ERR_DEVICE_TYPE);
3772 /* Get controller attributes */
3773 if (controller_obj_id == OBJ_NONE)
3774 controller_obj_id = obj_get_controller(raid_tab,
3775 disk_obj_id);
3776 else if (controller_obj_id != obj_get_controller(raid_tab,
3777 disk_obj_id)) {
3778 free(hsp_relation);
3779 return (ERR_DRIVER_ACROSS);
3782 ret = obj_get_attr(raid_tab, controller_obj_id,
3783 (void **)(&controller_attr));
3785 /* Get disk attributes */
3786 ret = obj_get_attr(raid_tab, disk_obj_id,
3787 (void **)(&disk_attr));
3788 if (disk_attr->state == DISK_STATE_FAILED) {
3789 free(hsp_relation);
3790 return (ERR_DISK_STATE);
3793 /* If it's not a hsp disk */
3794 obj_id = obj_get_comp(raid_tab, disk_obj_id, OBJ_TYPE_HSP);
3795 if (obj_id == OBJ_NONE) {
3796 free(hsp_relation);
3797 return (ERR_DISK_STATE);
3799 ret = obj_get_attr(raid_tab, obj_id, (void **)(&hsp_attr));
3801 if (array_obj_id != OBJ_ATTR_NONE) {
3802 if (raid_obj_get_type(raid_tab, array_obj_id) !=
3803 OBJ_TYPE_ARRAY) {
3804 free(hsp_relation);
3805 return (ERR_DEVICE_TYPE);
3808 /* Get array attributes */
3809 ret = obj_get_attr(raid_tab, array_obj_id,
3810 (void **)(&array_attr));
3812 /* If It's belong to another controller */
3813 if (controller_obj_id != obj_get_controller(raid_tab,
3814 array_obj_id)) {
3815 free(hsp_relation);
3816 return (ERR_DRIVER_ACROSS);
3819 /* If want to remove an array from a global hsp */
3820 if (hsp_attr->type == HSP_TYPE_GLOBAL) {
3821 free(hsp_relation);
3822 return (ERR_OP_ILLEGAL);
3825 do {
3826 (void) obj_get_attr(raid_tab, obj_id,
3827 (void **)(&hsp_attr));
3829 if (hsp_attr->associated_id ==
3830 array_attr->array_id ||
3831 hsp_attr->type == HSP_TYPE_GLOBAL)
3832 break;
3834 obj_id = obj_get_sibling(raid_tab, obj_id);
3835 } while (obj_id > OBJ_NONE);
3836 } else if (hsp_attr->type != HSP_TYPE_GLOBAL) {
3837 /* if global hsp is supported */
3838 free(hsp_relation);
3839 return (ERR_OP_ILLEGAL);
3843 * If array is associated with a local hsp, or remove a
3844 * global hsp disk
3846 if ((obj_id && (array_obj_id != OBJ_ATTR_NONE)) ||
3847 (array_obj_id == OBJ_ATTR_NONE)) {
3848 if (array_obj_id != OBJ_ATTR_NONE)
3849 hsp_relation->array_id = array_attr->array_id;
3850 else
3851 hsp_relation->array_id =
3852 (uint32_t)OBJ_ATTR_NONE;
3853 hsp_relation->disk_id = disk_attr->disk_id;
3854 } else {
3855 free(hsp_relation);
3856 return (ERR_OP_ILLEGAL);
3859 raid_lib = raid_obj_get_lib(raid_tab, controller_obj_id);
3860 fd = raid_obj_get_fd(raid_tab, controller_obj_id);
3861 if ((raid_lib == NULL) || (fd == 0))
3862 return (ERR_DRIVER_CLOSED);
3864 if (raid_lib->hsp_unbind == NULL) {
3865 free(hsp_relation);
3866 return (ERR_OP_NO_IMPL);
3869 ret = raid_lib->hsp_unbind(controller_attr->controller_id,
3870 hsp_relation, plugin_err_str);
3872 free(hsp_relation);
3873 return (ret);
3877 * Object maintennance routines
3879 static int
3880 raid_obj_create_system_obj(raid_obj_tab_t *raid_tab)
3882 raid_obj_t *raid_obj;
3883 int ret;
3885 raid_obj = calloc(1, sizeof (raid_obj_t));
3886 if (raid_obj == NULL)
3887 return (ERR_NOMEM);
3889 raid_obj->obj_id = OBJ_SYSTEM;
3890 raid_obj->obj_type_id = OBJ_TYPE_SYSTEM;
3891 raid_obj->data = NULL;
3893 ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3894 if (ret == ERR_DEVICE_DUP) {
3895 free(raid_obj);
3896 return (ERR_DEVICE_UNCLEAN);
3899 return (SUCCESS);
3902 static raid_obj_id_t
3903 raid_obj_id_new(raid_obj_tab_t *raid_tab)
3905 ++ raid_tab->obj_id_cnt;
3906 if (raid_tab->obj_id_cnt <= 0)
3907 return (ERR_DEVICE_OVERFLOW);
3909 return (raid_tab->obj_id_cnt);
3912 static void *
3913 raid_obj_attr_new(raid_obj_type_id_t obj_type)
3915 void *obj_attr = NULL;
3917 switch (obj_type) {
3918 case OBJ_TYPE_CONTROLLER:
3919 obj_attr = calloc(1, sizeof (controller_attr_t));
3920 break;
3921 case OBJ_TYPE_ARRAY:
3922 obj_attr = calloc(1, sizeof (array_attr_t));
3923 break;
3924 case OBJ_TYPE_DISK:
3925 obj_attr = calloc(1, sizeof (disk_attr_t));
3926 break;
3927 case OBJ_TYPE_HSP:
3928 obj_attr = calloc(1, sizeof (hsp_attr_t));
3929 break;
3930 case OBJ_TYPE_ARRAY_PART:
3931 obj_attr = calloc(1, sizeof (arraypart_attr_t));
3932 break;
3933 case OBJ_TYPE_DISK_SEG:
3934 obj_attr = calloc(1, sizeof (diskseg_attr_t));
3935 break;
3936 case OBJ_TYPE_TASK:
3937 obj_attr = calloc(1, sizeof (task_attr_t));
3938 break;
3939 case OBJ_TYPE_PROP:
3940 obj_attr = calloc(1, sizeof (property_attr_t));
3941 break;
3942 default:
3943 break;
3946 return (obj_attr);
3949 static raid_obj_id_t
3950 raid_obj_create(raid_obj_tab_t *raid_tab, raid_obj_type_id_t obj_type)
3952 raid_obj_t *raid_obj;
3953 int ret;
3954 void *data_ptr;
3956 raid_obj = calloc(1, sizeof (raid_obj_t));
3957 if (raid_obj == NULL)
3958 return (ERR_NOMEM);
3960 raid_obj->obj_id = raid_obj_id_new(raid_tab);
3961 if (raid_obj->obj_id < OBJ_NONE)
3962 return (ERR_DEVICE_OVERFLOW);
3964 ret = raid_obj_tab_insert(raid_tab, raid_obj->obj_id, raid_obj);
3965 if (ret == ERR_DEVICE_DUP) {
3966 free(raid_obj);
3967 return (ERR_DEVICE_DUP);
3970 data_ptr = raid_obj_attr_new(obj_type);
3971 if (data_ptr == NULL) {
3972 (void) raid_obj_delete(raid_tab, raid_obj->obj_id);
3973 return (ERR_NOMEM);
3976 (void) raid_obj_set_data_ptr(raid_tab, raid_obj->obj_id, data_ptr);
3978 (void) raid_obj_set_type(raid_tab, raid_obj->obj_id, obj_type);
3979 return (raid_obj->obj_id);
3982 static int
3983 raid_obj_delete(raid_obj_tab_t *raid_tab, raid_obj_id_t raid_obj_id)
3985 raid_obj_t *obj;
3987 obj = raid_obj_tab_remove(raid_tab, raid_obj_id);
3988 if (obj != NULL) {
3989 free(obj->data);
3990 free(obj);
3991 return (SUCCESS);
3994 return (ERR_DEVICE_NOENT);
3997 static int
3998 raid_obj_add_org(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
3999 raid_obj_id_t container_id)
4001 raid_obj_id_t tmp, tmp1;
4003 tmp = raid_obj_get_comp(raid_tab, container_id);
4004 if (tmp < OBJ_NONE)
4005 return (ERR_DEVICE_NOENT);
4007 if (tmp == OBJ_NONE) {
4008 (void) raid_obj_set_container(raid_tab, obj_id, container_id);
4009 (void) raid_obj_set_comp(raid_tab, container_id, obj_id);
4010 return (SUCCESS);
4013 while ((tmp1 = raid_obj_get_sibling(raid_tab, tmp)) != OBJ_NONE)
4014 tmp = tmp1;
4016 if (raid_obj_set_sibling(raid_tab, tmp, obj_id) < SUCCESS)
4017 return (ERR_DEVICE_NOENT);
4018 (void) raid_obj_set_container(raid_tab, obj_id, container_id);
4020 return (SUCCESS);
4023 static raid_obj_type_id_t
4024 raid_obj_get_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4026 raid_obj_t *obj;
4028 obj = raid_obj_tab_find(raid_tab, obj_id);
4029 if (obj == NULL)
4030 return (ERR_DEVICE_NOENT);
4032 if ((obj->obj_type_id < OBJ_TYPE_SYSTEM) ||
4033 (obj->obj_type_id >= OBJ_TYPE_ALL))
4034 return (ERR_DEVICE_INVALID);
4036 return (obj->obj_type_id);
4039 static int
4040 raid_obj_set_type(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4041 raid_obj_type_id_t type)
4043 raid_obj_t *obj;
4045 obj = raid_obj_tab_find(raid_tab, obj_id);
4046 if (obj == NULL)
4047 return (ERR_DEVICE_NOENT);
4049 if ((type < OBJ_TYPE_SYSTEM) || (type >= OBJ_TYPE_ALL))
4050 return (ERR_DEVICE_TYPE);
4052 obj->obj_type_id = type;
4053 return (SUCCESS);
4056 static raid_obj_status_t
4057 raid_obj_get_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4059 raid_obj_t *obj;
4061 obj = raid_obj_tab_find(raid_tab, obj_id);
4062 if (obj == NULL)
4063 return (ERR_DEVICE_NOENT);
4065 return (obj->status);
4068 static int
4069 raid_obj_set_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4070 raid_obj_status_t status)
4072 raid_obj_t *obj;
4074 obj = raid_obj_tab_find(raid_tab, obj_id);
4075 if (obj == NULL)
4076 return (ERR_DEVICE_NOENT);
4078 obj->status = obj->status | status;
4080 return (SUCCESS);
4083 static int
4084 raid_obj_clear_status(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4085 raid_obj_status_t status)
4087 raid_obj_t *obj;
4089 obj = raid_obj_tab_find(raid_tab, obj_id);
4090 if (obj == NULL)
4091 return (ERR_DEVICE_NOENT);
4093 obj->status = obj->status & ~status;
4095 return (SUCCESS);
4098 static raid_obj_id_t
4099 raid_obj_get_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4101 raid_obj_t *obj;
4103 obj = raid_obj_tab_find(raid_tab, obj_id);
4104 if (obj == NULL)
4105 return (ERR_DEVICE_NOENT);
4107 return (obj->container);
4110 static int
4111 raid_obj_set_container(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4112 raid_obj_id_t container_id)
4114 raid_obj_t *obj;
4116 obj = raid_obj_tab_find(raid_tab, obj_id);
4117 if (obj == NULL)
4118 return (ERR_DEVICE_NOENT);
4120 obj->container = container_id;
4121 return (SUCCESS);
4124 static raid_obj_id_t
4125 raid_obj_get_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4127 raid_obj_t *obj;
4129 obj = raid_obj_tab_find(raid_tab, obj_id);
4130 if (obj == NULL)
4131 return (ERR_DEVICE_NOENT);
4133 return (obj->component);
4136 static int
4137 raid_obj_set_comp(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4138 raid_obj_id_t comp)
4140 raid_obj_t *obj;
4142 obj = raid_obj_tab_find(raid_tab, obj_id);
4143 if (obj == NULL)
4144 return (ERR_DEVICE_NOENT);
4146 obj->component = comp;
4147 return (SUCCESS);
4150 static raid_obj_id_t
4151 raid_obj_get_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4153 raid_obj_t *obj;
4155 obj = raid_obj_tab_find(raid_tab, obj_id);
4156 if (obj == NULL)
4157 return (ERR_DEVICE_NOENT);
4159 return (obj->sibling);
4162 static int
4163 raid_obj_set_sibling(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4164 raid_obj_id_t sibling)
4166 raid_obj_t *obj;
4168 obj = raid_obj_tab_find(raid_tab, obj_id);
4169 if (obj == NULL)
4170 return (ERR_DEVICE_NOENT);
4172 obj->sibling = sibling;
4174 return (SUCCESS);
4177 static void *
4178 raid_obj_get_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4180 raid_obj_t *obj;
4182 obj = raid_obj_tab_find(raid_tab, obj_id);
4183 if (obj == NULL)
4184 return (NULL);
4186 return (obj->data);
4189 static int
4190 raid_obj_set_data_ptr(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4191 void *data)
4193 raid_obj_t *obj;
4195 obj = raid_obj_tab_find(raid_tab, obj_id);
4196 if (obj == NULL)
4197 return (ERR_DEVICE_NOENT);
4199 obj->data = data;
4201 return (SUCCESS);
4204 static raid_obj_handle_t
4205 raid_obj_get_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id)
4207 raid_obj_t *obj;
4209 obj = raid_obj_tab_find(raid_tab, obj_id);
4210 if (obj == NULL)
4211 return (ERR_DEVICE_NOENT);
4213 return (obj->handle);
4216 static int
4217 raid_obj_set_handle(raid_obj_tab_t *raid_tab, raid_obj_id_t obj_id,
4218 raid_obj_handle_t handle)
4220 raid_obj_t *obj;
4222 obj = raid_obj_tab_find(raid_tab, obj_id);
4223 if (obj == NULL)
4224 return (ERR_DEVICE_NOENT);
4226 obj->handle = handle;
4227 return (SUCCESS);
4230 * Object list maintennance routines
4232 static void
4233 raid_list_create(raid_list_t *list, size_t offset)
4235 list->head = NULL;
4236 list->tail = NULL;
4237 list->offset = offset;
4240 static void *
4241 raid_list_head(raid_list_t *list)
4243 return (list->head);
4246 static void *
4247 raid_list_next(raid_list_t *list, void *obj)
4249 raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj);
4251 return (el->next);
4254 static void
4255 raid_list_insert_tail(raid_list_t *list, void *obj)
4257 raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4259 el->prev = list->tail;
4260 list->tail = obj;
4262 el->next = NULL;
4264 if (list->head == NULL)
4265 list->head = obj;
4267 if (el->prev != NULL) {
4268 el1 = LIST_OBJ_TO_EL(list, el->prev);
4269 el1->next = obj;
4273 static void
4274 raid_list_remove(raid_list_t *list, void *obj)
4276 raid_list_el_t *el = LIST_OBJ_TO_EL(list, obj), *el1;
4278 if (list->head == obj)
4279 list->head = el->next;
4281 if (list->tail == obj)
4282 list->tail = el->prev;
4284 if (el->next != NULL) {
4285 el1 = LIST_OBJ_TO_EL(list, el->next);
4286 el1->prev = el->prev;
4289 if (el->prev != NULL) {
4290 el1 = LIST_OBJ_TO_EL(list, el->prev);
4291 el1->next = el->next;
4294 el->prev = el->next = NULL;
4297 static void *
4298 raid_list_remove_head(raid_list_t *list)
4300 void *obj = list->head;
4302 if (obj != NULL)
4303 raid_list_remove(list, obj);
4305 return (obj);
4308 static void *
4309 raid_list_find(raid_list_t *list, raid_obj_id_t obj_id)
4311 raid_obj_t *obj;
4313 for (obj = raid_list_head(list); obj != NULL;
4314 obj = raid_list_next(list, obj))
4315 if (obj->obj_id == obj_id)
4316 break;
4318 return (obj);
4321 static int
4322 raid_obj_tab_create(raid_obj_tab_t *tab, size_t hash_slots)
4324 unsigned i;
4326 if (hash_slots == 0)
4327 return (ERR_OP_ILLEGAL);
4329 tab->slots = hash_slots;
4331 if ((tab->table = calloc(hash_slots, sizeof (raid_list_t))) == NULL)
4332 return (ERR_NOMEM);
4334 for (i = 0; i < hash_slots; i++)
4335 raid_list_create(&tab->table[i], offsetof(raid_obj_t, el));
4337 return (SUCCESS);
4340 static void
4341 raid_obj_tab_destroy(raid_obj_tab_t *tab)
4343 unsigned i;
4345 for (i = 0; i < tab->slots; i++) {
4346 struct raid_obj_t *obj;
4348 while ((obj = raid_list_remove_head(&tab->table[i])) != NULL)
4349 free(obj);
4351 raid_list_destroy(&tab->table[i]);
4354 free(tab->table);
4356 tab->table = NULL;
4357 tab->slots = 0;
4358 tab->obj_id_cnt = 0;
4361 static int
4362 raid_obj_tab_insert(raid_obj_tab_t *tab, raid_obj_id_t id, void *obj)
4364 raid_list_t *list;
4366 list = OBJ_TAB_SLOT(tab, id);
4368 if (raid_list_find(list, id) != NULL)
4369 return (ERR_DEVICE_DUP);
4371 raid_list_insert_tail(list, obj);
4373 return (SUCCESS);
4376 static void *
4377 raid_obj_tab_remove(raid_obj_tab_t *tab, raid_obj_id_t id)
4379 raid_list_t *list;
4380 raid_obj_t *obj;
4382 list = OBJ_TAB_SLOT(tab, id);
4384 if ((obj = raid_list_find(list, id)) != NULL)
4385 raid_list_remove(list, obj);
4387 return (obj);
4390 static void *
4391 raid_obj_tab_find(raid_obj_tab_t *tab, raid_obj_id_t id)
4393 raid_list_t *list;
4394 raid_obj_t *obj;
4396 list = OBJ_TAB_SLOT(tab, id);
4397 obj = raid_list_find(list, id);
4399 return (obj);
4402 static void
4403 raid_list_destroy(raid_list_t *list)
4405 list->head = NULL;
4406 list->tail = NULL;
4407 list->offset = 0;
4411 * Plug-in maintennance routines
4413 static int
4414 controller_id_to_path(uint32_t controller_id, char *path)
4416 int fd;
4417 char buf[MAX_PATH_LEN] = {0}, buf1[MAX_PATH_LEN] = {0}, *colon;
4419 (void) snprintf(buf, MAX_PATH_LEN, "%s/c%d", CFGDIR, controller_id);
4420 if (readlink(buf, buf1, sizeof (buf1)) < 0)
4421 return (ERR_DRIVER_NOT_FOUND);
4423 if (buf1[0] != '/')
4424 (void) snprintf(buf, sizeof (buf), "%s/", CFGDIR);
4425 else
4426 buf[0] = 0;
4427 (void) strlcat(buf, buf1, MAX_PATH_LEN);
4429 colon = strrchr(buf, ':');
4430 if (colon == NULL)
4431 return (ERR_DRIVER_NOT_FOUND);
4432 else
4433 *colon = 0;
4435 (void) snprintf(path, MAX_PATH_LEN, "%s:devctl", buf);
4437 fd = open(path, O_RDONLY | O_NDELAY);
4439 if (fd < 0)
4440 return (ERR_DRIVER_NOT_FOUND);
4442 (void) close(fd);
4444 return (SUCCESS);
4447 static char *
4448 controller_id_to_driver_name(uint32_t controller_id)
4450 char buf[MAX_PATH_LEN];
4451 di_node_t di_node;
4452 char *name, *tmp;
4453 int ret;
4455 ret = controller_id_to_path(controller_id, buf);
4456 if (ret < SUCCESS)
4457 return (NULL);
4459 tmp = strrchr(buf, ':');
4460 if (tmp != NULL)
4461 *tmp = 0;
4463 tmp = strstr(buf, "pci");
4464 if (tmp == NULL)
4465 return (NULL);
4467 di_node = di_init(tmp, DINFOPROP);
4468 if (di_node == DI_NODE_NIL)
4469 return (NULL);
4471 name = di_driver_name(di_node);
4473 return (name);
4476 static void
4477 raid_plugin_init()
4479 raid_lib_t *raid_lib = raid_lib_sys;
4481 while (raid_lib) {
4482 raid_lib_sys = raid_lib->next;
4483 (void) dlclose(raid_lib->lib_handle);
4484 free(raid_lib);
4485 raid_lib = raid_lib_sys;
4489 static raid_lib_t *
4490 raid_plugin_load(char *driver_name)
4492 char buf[MAX_PATH_LEN] = {0};
4493 raid_lib_t *supplib;
4494 void *sym;
4496 supplib = calloc(1, sizeof (raid_lib_t));
4497 if (supplib == NULL)
4498 return (NULL);
4500 (void) snprintf(buf, MAX_PATH_LEN, "%s/%s.so.1",
4501 SUPP_PLUGIN_DIR, driver_name);
4503 supplib->lib_handle = dlopen(buf, RTLD_LAZY);
4504 if (supplib->lib_handle == NULL) {
4505 free(supplib);
4506 return (NULL);
4509 supplib->name = driver_name;
4511 if ((sym = dlsym(supplib->lib_handle, "rdcfg_version")) == NULL)
4512 supplib->version = RDCFG_PLUGIN_V1;
4513 else {
4514 supplib->version = *((uint32_t *)sym);
4515 if (supplib->version != RDCFG_PLUGIN_V1) {
4516 (void) dlclose(supplib->lib_handle);
4517 free(supplib);
4518 return (NULL);
4522 if ((sym = dlsym(supplib->lib_handle, "rdcfg_open_controller")) ==
4523 NULL) {
4524 (void) dlclose(supplib->lib_handle);
4525 free(supplib);
4526 return (NULL);
4527 } else
4528 supplib->open_controller = (int(*)(uint32_t, char **))sym;
4530 if ((sym = dlsym(supplib->lib_handle, "rdcfg_close_controller")) ==
4531 NULL) {
4532 (void) dlclose(supplib->lib_handle);
4533 free(supplib);
4534 return (NULL);
4535 } else
4536 supplib->close_controller = (int (*)(uint32_t, char **))sym;
4538 if ((sym = dlsym(supplib->lib_handle, "rdcfg_compnum")) == NULL) {
4539 (void) dlclose(supplib->lib_handle);
4540 free(supplib);
4541 return (NULL);
4542 } else
4543 supplib->compnum = (int (*)(uint32_t, uint32_t,
4544 raid_obj_type_id_t, raid_obj_type_id_t))sym;
4546 if ((sym = dlsym(supplib->lib_handle, "rdcfg_complist")) == NULL) {
4547 (void) dlclose(supplib->lib_handle);
4548 free(supplib);
4549 return (NULL);
4550 } else
4551 supplib->complist = (int (*)(uint32_t, uint32_t,
4552 raid_obj_type_id_t, raid_obj_type_id_t, int, void *))sym;
4554 if ((sym = dlsym(supplib->lib_handle, "rdcfg_get_attr")) == NULL) {
4555 (void) dlclose(supplib->lib_handle);
4556 free(supplib);
4557 return (NULL);
4558 } else
4559 supplib->get_attr = (int (*)(uint32_t, uint32_t, uint32_t,
4560 raid_obj_type_id_t, void*))sym;
4562 if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_create")) == NULL) {
4563 (void) dlclose(supplib->lib_handle);
4564 free(supplib);
4565 return (NULL);
4566 } else
4567 supplib->array_create = (int (*)(uint32_t, array_attr_t *, int,
4568 arraypart_attr_t *, char **))sym;
4570 if ((sym = dlsym(supplib->lib_handle, "rdcfg_array_delete")) == NULL) {
4571 (void) dlclose(supplib->lib_handle);
4572 free(supplib);
4573 return (NULL);
4574 } else
4575 supplib->array_delete =
4576 (int (*)(uint32_t, uint32_t, char **))sym;
4578 supplib->hsp_bind = (int (*)(uint32_t, hsp_relation_t *,
4579 char **))dlsym(supplib->lib_handle, "rdcfg_hsp_bind");
4580 supplib->hsp_unbind = (int (*)(uint32_t, hsp_relation_t *,
4581 char **))dlsym(supplib->lib_handle, "rdcfg_hsp_unbind");
4582 supplib->set_attr = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t *,
4583 char **))dlsym(supplib->lib_handle, "rdcfg_set_attr");
4584 supplib->flash_fw = (int (*)(uint32_t, char *, uint32_t, char **))
4585 dlsym(supplib->lib_handle, "rdcfg_flash_fw");
4587 supplib->next = raid_lib_sys;
4588 raid_lib_sys = supplib;
4589 return (supplib);
4592 static raid_lib_t *
4593 raid_find_lib(raid_obj_tab_t *raid_tab, raid_obj_id_t controller_obj_id)
4595 controller_attr_t *controller_attr;
4596 raid_lib_t *raid_lib;
4597 char *driver_name;
4598 raid_obj_handle_t handle;
4600 /* Check if it's mapped to handle structure */
4601 handle = raid_obj_to_handle(raid_tab, controller_obj_id);
4602 if (raid_handle_sys.handles[handle].raid_lib != NULL)
4603 return (raid_handle_sys.handles[handle].raid_lib);
4605 (void) obj_get_attr(raid_tab, controller_obj_id,
4606 (void **)(&controller_attr));
4608 /* Check if the plugin module is already loaded */
4609 driver_name = controller_id_to_driver_name(
4610 controller_attr->controller_id);
4611 if (driver_name == NULL)
4612 return (NULL);
4614 raid_lib = raid_lib_sys;
4615 while (raid_lib != NULL) {
4616 if (raid_lib->name != NULL &&
4617 strcmp(driver_name, raid_lib->name) == 0)
4618 return (raid_lib);
4620 raid_lib = raid_lib->next;
4623 /* Loading the plugin module */
4624 raid_lib = raid_plugin_load(driver_name);
4626 return (raid_lib);