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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * raidctl.c is the entry file of RAID configuration utility.
29 #include <sys/types.h>
50 #define TEXT_DOMAIN "SYS_TEST"
54 * Return value of command
61 * Initial value of variables
63 #define INIT_HANDLE_VALUE -3
64 #define MAX64BIT 0xffffffffffffffffull
65 #define MAX32BIT 0xfffffffful
68 * Flag of set or unset HSP
74 * Operate codes of command
76 #define DO_HW_RAID_NOP -1
77 #define DO_HW_RAID_HELP 0
78 #define DO_HW_RAID_CREATEO 1
79 #define DO_HW_RAID_CREATEN 2
80 #define DO_HW_RAID_DELETE 3
81 #define DO_HW_RAID_LIST 4
82 #define DO_HW_RAID_FLASH 5
83 #define DO_HW_RAID_HSP 6
84 #define DO_HW_RAID_SET_ATTR 7
85 #define DO_HW_RAID_SNAPSHOT 8
87 #define LOWER_H (1 << 0)
88 #define LOWER_C (1 << 1)
89 #define LOWER_D (1 << 2)
90 #define LOWER_L (1 << 3)
91 #define LOWER_R (1 << 4)
92 #define LOWER_Z (1 << 5)
93 #define LOWER_G (1 << 6)
94 #define LOWER_A (1 << 7)
95 #define LOWER_S (1 << 8)
96 #define LOWER_P (1 << 9)
97 #define LOWER_F (1 << 10)
98 #define UPPER_S (1 << 11)
99 #define UPPER_C (1 << 12)
100 #define UPPER_F (1 << 13)
102 /* Add a ARRAY state (temporary) */
103 #define ARRAY_STATE_SYNC 100
106 * Function and strings to properly localize our prompt.
107 * So for example in German it would ask (ja/nein) or (yes/no) in
114 #define RAIDCTL_LOCKF "/var/run/lockf_raidctl"
117 static int yes(void);
118 static int rpmatch(char *s
);
119 static char *yesexpr
= NULL
;
121 static char *default_yesexpr
= "^[yY]";
125 #define SET_DEFAULT_STRS \
128 yesexpr = default_yesexpr;
134 static char *prog_namep
;
138 * Functions declaration
140 static void helpinfo(char *prog_namep
);
141 static int do_create_cidl(char *raid_levelp
, char *capacityp
, char *disk_argp
,
142 char *stripe_sizep
, uint32_t f_flag
, char **argv
, uint32_t optind
);
143 static int do_create_ctd(char *raid_levelp
, char **disks_argpp
,
144 uint32_t disks_num
, uint32_t argindex
, uint32_t f_flag
);
145 static int do_list(char *disk_argp
, char **argv
, uint32_t optind
,
146 uint8_t is_snapshot
);
147 static int do_delete(uint32_t f_flag
, char **argv
, uint32_t optind
);
148 static int do_flash(uint8_t f_flag
, char *filep
, char **ctls_argpp
,
149 uint32_t index
, uint32_t ctl_num
);
150 static int do_set_hsp(char *a_argp
, char *disk_argp
, char **argv
,
152 static int do_set_array_attr(uint32_t f_flag
, char *p_argp
, char **argv
,
154 static int snapshot_raidsystem(uint8_t recursive
, uint8_t indent
,
155 uint8_t is_snapshot
);
156 static int snapshot_ctl(raid_obj_handle_t ctl_handle
, uint8_t recursive
,
157 uint8_t indent
, uint8_t is_snapshot
);
158 static int snapshot_array(raid_obj_handle_t array_handle
,
159 uint8_t indent
, uint8_t is_sub
, uint8_t is_snapshot
);
160 static int snapshot_disk(uint32_t ctl_tag
, raid_obj_handle_t disk_handle
,
161 uint8_t indent
, uint8_t is_snapshot
);
162 static int print_ctl_table(raid_obj_handle_t ctl_handle
);
163 static int print_array_table(raid_obj_handle_t ctl_handle
,
164 raid_obj_handle_t array_handle
);
165 static int print_disk_table(raid_obj_handle_t ctl_handle
,
166 raid_obj_handle_t disk_handle
);
167 static int print_ctl_attr(raidcfg_controller_t
*attrp
);
168 static int print_array_attr(raidcfg_array_t
*attrp
);
169 static int print_arraypart_attr(raidcfg_arraypart_t
*attrp
);
170 static int print_disk_attr(raid_obj_handle_t ctl_handle
,
171 raid_obj_handle_t disk_handle
, raidcfg_disk_t
*attrp
);
172 static void print_indent(uint8_t indent
);
173 static int get_disk_handle_cidl(uint32_t ctl_tag
, char *disks_argp
,
174 int *comps_nump
, raid_obj_handle_t
**handlespp
);
175 static int get_disk_handle_ctd(int disks_num
, char **disks_argpp
,
176 uint32_t *ctl_tagp
, raid_obj_handle_t
*disks_handlep
);
177 static int get_ctl_tag(char *argp
, uint32_t *ctl_tagp
);
178 static int get_array_tag(char *argp
, uint32_t *ctl_tagp
,
179 array_tag_t
*array_tagp
);
180 static int get_disk_tag_ctd(char *argp
, disk_tag_t
*disk_tagp
,
181 uint32_t *controller_id
);
182 static int get_disk_tag_cidl(char *argp
, disk_tag_t
*disk_tagp
);
183 static int calc_size(char *sizep
, uint64_t *valp
);
184 static int is_fully_numeric(char *strp
);
185 static int size_to_string(uint64_t size
, char *string
, int len
);
186 static int enter_raidctl_lock(int *fd
);
187 static void exit_raidctl_lock(int fd
);
190 * Entry function of raidctl command
193 main(int argc
, char **argv
)
195 /* operation index */
196 int8_t findex
= DO_HW_RAID_NOP
;
198 /* argument pointers */
211 uint8_t r_flag
= FALSE
;
212 uint8_t f_flag
= FALSE
;
213 uint8_t action
= FALSE
;
214 uint64_t options
= 0;
216 /* index and temporary variables */
221 /* fd for the filelock */
224 if (enter_raidctl_lock(&fd
) != SUCCESS
) {
228 (void) setlocale(LC_ALL
, "");
229 (void) textdomain(TEXT_DOMAIN
);
231 /* parse command line, and get program name */
232 if ((prog_namep
= strrchr(argv
[0], '/')) == NULL
) {
233 prog_namep
= argv
[0];
238 /* close error option messages from getopt */
241 /* get yes expression according to current locale */
242 yesexpr
= strdup(nl_langinfo(YESEXPR
));
247 * If the was no expression or if there is a compile error
248 * use default yes expression.
250 status
= regcomp(&re
, yesexpr
, REG_EXTENDED
| REG_NOSUB
);
251 if ((*yesexpr
== '\0') || (status
!= 0)) {
253 if (regcomp(&re
, default_yesexpr
,
254 REG_EXTENDED
| REG_NOSUB
) != 0) {
259 while ((c
= getopt(argc
, argv
,
260 "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF
) {
264 if (action
== FALSE
) {
265 findex
= DO_HW_RAID_HELP
;
269 findex
= DO_HW_RAID_NOP
;
273 if (action
== FALSE
) {
274 findex
= DO_HW_RAID_CREATEN
;
279 findex
= DO_HW_RAID_NOP
;
283 if (action
== FALSE
) {
284 findex
= DO_HW_RAID_CREATEO
;
288 findex
= DO_HW_RAID_NOP
;
292 if (action
== FALSE
) {
293 findex
= DO_HW_RAID_DELETE
;
297 findex
= DO_HW_RAID_NOP
;
301 if (action
== FALSE
) {
302 findex
= DO_HW_RAID_LIST
;
306 findex
= DO_HW_RAID_NOP
;
310 if (action
== FALSE
) {
311 findex
= DO_HW_RAID_FLASH
;
316 findex
= DO_HW_RAID_NOP
;
320 if (action
== FALSE
) {
321 findex
= DO_HW_RAID_HSP
;
326 findex
= DO_HW_RAID_NOP
;
330 if (action
== FALSE
) {
331 findex
= DO_HW_RAID_SET_ATTR
;
336 findex
= DO_HW_RAID_NOP
;
361 if (action
== FALSE
) {
362 findex
= DO_HW_RAID_SNAPSHOT
;
366 findex
= DO_HW_RAID_NOP
;
370 (void) fprintf(stderr
,
371 gettext("Invalid argument(s).\n"));
372 exit_raidctl_lock(fd
);
375 return (INVALID_ARG
);
381 case DO_HW_RAID_HELP
:
382 if ((options
& ~(LOWER_H
)) != 0) {
385 helpinfo(prog_namep
);
389 case DO_HW_RAID_CREATEO
:
390 if ((options
& ~(LOWER_F
| LOWER_C
| LOWER_R
)) != 0) {
393 if (r_flag
!= FALSE
&& f_flag
== FALSE
) {
394 ret
= do_create_ctd(r_argp
, argv
, argc
- 4,
396 } else if (r_flag
== FALSE
&& f_flag
== FALSE
) {
397 ret
= do_create_ctd(NULL
, argv
, argc
- 2,
399 } else if (r_flag
!= FALSE
&& f_flag
!= FALSE
) {
400 ret
= do_create_ctd(r_argp
, argv
, argc
- 5,
403 ret
= do_create_ctd(NULL
, argv
, argc
- 3,
408 case DO_HW_RAID_CREATEN
:
409 if ((options
& ~(LOWER_F
| UPPER_C
| LOWER_R
| LOWER_Z
|
413 ret
= do_create_cidl(r_argp
, z_argp
, C_argp
, s_argp
,
414 f_flag
, argv
, optind
);
417 case DO_HW_RAID_DELETE
:
418 if ((options
& ~(LOWER_F
| LOWER_D
)) != 0) {
421 ret
= do_delete(f_flag
, argv
, optind
);
424 case DO_HW_RAID_LIST
:
425 if ((options
& ~(LOWER_L
| LOWER_G
)) != 0) {
428 ret
= do_list(g_argp
, argv
, optind
, FALSE
);
431 case DO_HW_RAID_SNAPSHOT
:
432 if ((options
& ~(UPPER_S
| LOWER_G
)) != 0) {
435 ret
= do_list(g_argp
, argv
, optind
, TRUE
);
438 case DO_HW_RAID_FLASH
:
439 if ((options
& ~(LOWER_F
| UPPER_F
)) != 0) {
442 if (f_flag
== FALSE
) {
443 ret
= do_flash(f_flag
, F_argp
, argv
, optind
,
446 ret
= do_flash(f_flag
, F_argp
, argv
, optind
,
452 if ((options
& ~(LOWER_A
| LOWER_G
)) != 0) {
455 ret
= do_set_hsp(a_argp
, g_argp
, argv
, optind
);
458 case DO_HW_RAID_SET_ATTR
:
459 if ((options
& ~(LOWER_F
| LOWER_P
)) != 0) {
462 ret
= do_set_array_attr(f_flag
, p_argp
, argv
, optind
);
467 ret
= do_list(g_argp
, argv
, optind
, FALSE
);
477 if (ret
== INVALID_ARG
) {
478 (void) fprintf(stderr
,
479 gettext("Invalid argument(s).\n"));
481 exit_raidctl_lock(fd
);
489 * helpinfo(prog_namep)
490 * This function prints help informations for usrs.
493 helpinfo(char *prog_namep
)
497 (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] "
498 "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep
,
501 (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep
);
503 (void) printf(gettext("%s [-f] -F <filename> <controller1> "
504 "[<controller2> ...]\n"), prog_namep
);
506 (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"),
507 prog_namep
, quote
, quote
);
509 (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> "
510 "[<disk3> ...]\n"), prog_namep
);
512 (void) printf(gettext("%s [-l]\n"), prog_namep
);
514 (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep
);
516 (void) printf(gettext("%s -l <volume>\n"), prog_namep
);
518 (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"),
521 (void) printf(gettext("%s -a {set | unset} -g <disk> "
522 "{<volume> | <controller>}\n"), prog_namep
);
524 (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep
);
526 (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep
);
528 (void) printf(gettext("%s -h\n"), prog_namep
);
532 * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep,
533 * f_flag, argv, optind)
534 * This function creates a new RAID volume with specified arguments,
535 * and returns result as SUCCESS, INVALID_ARG or FAILURE.
536 * The "c.id.l" is used to express single physical disk. 'c' expresses
537 * bus number, 'id' expresses target number, and 'l' expresses lun.
538 * The physical disks represented by c.id.l may be invisible to OS, which
539 * means physical disks attached to controllers are not accessible by
540 * OS directly. The disks should be organized as a logical volume, and
541 * the logical volume is exported to OS as a single unit. Some hardware
542 * RAID controllers also support physical disks accessed by OS directly,
543 * for example LSI1068. In this case, it's both OK to express physical
544 * disk by c.id.l format or canonical ctd format.
547 do_create_cidl(char *raid_levelp
, char *capacityp
, char *disks_argp
,
548 char *stripe_sizep
, uint32_t f_flag
, char **argv
, uint32_t optind
)
550 uint32_t ctl_tag
= MAX32BIT
;
551 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
552 uint32_t raid_level
= RAID_LEVEL_1
;
553 uint64_t capacity
= 0;
554 uint64_t stripe_size
= (uint64_t)OBJ_ATTR_NONE
;
555 raid_obj_handle_t
*disk_handlesp
= NULL
;
556 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
557 raidcfg_controller_t ctl_attr
;
561 raidcfg_array_t array_attr
;
563 if (argv
[optind
] == NULL
|| argv
[optind
+ 1] != NULL
) {
564 return (INVALID_ARG
);
567 if (disks_argp
== NULL
) {
568 return (INVALID_ARG
);
571 /* Check controller tag */
572 if (get_ctl_tag(argv
[optind
], &ctl_tag
) != SUCCESS
) {
573 return (INVALID_ARG
);
576 ctl_handle
= raidcfg_get_controller(ctl_tag
);
577 if (ctl_handle
<= 0) {
578 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ctl_handle
));
582 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
583 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
588 if (raid_levelp
!= NULL
) {
589 if (*raid_levelp
== '1' &&
590 (*(raid_levelp
+ 1) == 'E' || *(raid_levelp
+ 1) == 'e')) {
591 raid_level
= RAID_LEVEL_1E
;
593 if (is_fully_numeric(raid_levelp
) == FALSE
) {
594 return (INVALID_ARG
);
597 switch (atoi(raid_levelp
)) {
599 raid_level
= RAID_LEVEL_0
;
602 raid_level
= RAID_LEVEL_1
;
605 raid_level
= RAID_LEVEL_5
;
608 raid_level
= RAID_LEVEL_10
;
611 raid_level
= RAID_LEVEL_50
;
614 return (INVALID_ARG
);
620 * The rang check of capacity and stripe size is performed in library,
621 * and it relates to hardware feature.
624 /* Capacity in bytes. Capacity 0 means max available space. */
625 if (capacityp
!= NULL
) {
626 if (*capacityp
== '-' ||
627 calc_size(capacityp
, &capacity
) != SUCCESS
) {
628 return (INVALID_ARG
);
632 /* Stripe size in bytes */
633 if (stripe_sizep
!= NULL
) {
634 if (calc_size(stripe_sizep
, &stripe_size
) != SUCCESS
||
635 *stripe_sizep
== '-') {
636 return (INVALID_ARG
);
640 /* Open controller before accessing its object */
641 if ((ret
= raidcfg_open_controller(ctl_handle
, NULL
)) < 0) {
642 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
646 /* Get disks' handles */
647 if ((ret
= get_disk_handle_cidl(ctl_tag
, disks_argp
, &comps_num
,
648 &disk_handlesp
)) != SUCCESS
) {
649 (void) raidcfg_close_controller(ctl_handle
, NULL
);
653 if (f_flag
== FALSE
) {
654 (void) fprintf(stdout
, gettext("Creating RAID volume "
655 "will destroy all data on spare space of member disks, "
658 (void) fprintf(stdout
, gettext("RAID volume "
659 "not created.\n\n"));
660 (void) raidcfg_close_controller(ctl_handle
, NULL
);
667 array_handle
= raidcfg_create_array(comps_num
,
668 disk_handlesp
, raid_level
, capacity
, stripe_size
, NULL
);
670 if (array_handle
<= 0) {
671 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(array_handle
));
673 (void) raidcfg_close_controller(ctl_handle
, NULL
);
677 /* Get attribute of the new created array */
678 if ((ret
= raidcfg_get_attr(array_handle
, &array_attr
)) < 0) {
679 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
681 (void) raidcfg_close_controller(ctl_handle
, NULL
);
685 (void) fprintf(stdout
, gettext("Volume c%ut%llud%llu is created "
686 "successfully!\n"), ctl_tag
, array_attr
.tag
.idl
.target_id
,
687 array_attr
.tag
.idl
.lun
);
689 /* Print attribute of array */
690 (void) print_array_table(ctl_handle
, array_handle
);
692 /* Close controller */
693 (void) raidcfg_close_controller(ctl_handle
, NULL
);
700 * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag)
701 * This function creates array with specified arguments, and return result
702 * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller
703 * to be compatible with old raidctl. The capacity and stripe size can't
704 * be specified for LSI MPT controller, and they use zero and default value.
705 * The "ctd" is the canonical expression of physical disks which are
709 do_create_ctd(char *raid_levelp
, char **disks_argpp
, uint32_t disks_num
,
710 uint32_t argindex
, uint32_t f_flag
)
712 uint32_t ctl_tag
= MAX32BIT
;
713 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
714 uint32_t raid_level
= RAID_LEVEL_1
;
715 uint64_t capacity
= 0;
716 uint32_t stripe_size
= (uint32_t)OBJ_ATTR_NONE
;
717 raid_obj_handle_t
*disk_handlesp
= NULL
;
718 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
719 raidcfg_controller_t ctl_attr
;
722 raidcfg_array_t array_attr
;
725 /* Check disks parameter */
726 if (disks_argpp
== NULL
|| disks_num
< 2) {
727 return (INVALID_ARG
);
730 for (i
= 0, j
= argindex
; i
< disks_num
; i
++, j
++) {
731 if (disks_argpp
[j
] == NULL
) {
732 return (INVALID_ARG
);
737 * We need check if the raid_level string is fully numeric. If user
738 * input string with unsupported letters, such as "s10", atoi() will
739 * return zero because it is an illegal string, but it doesn't mean
742 if (raid_levelp
!= NULL
) {
743 if (*raid_levelp
== '1' &&
744 (*(raid_levelp
+ 1) == 'E' || *(raid_levelp
+ 1) == 'e')) {
745 raid_level
= RAID_LEVEL_1E
;
747 if (is_fully_numeric(raid_levelp
) == FALSE
) {
748 return (INVALID_ARG
);
751 switch (atoi(raid_levelp
)) {
753 raid_level
= RAID_LEVEL_0
;
756 raid_level
= RAID_LEVEL_1
;
759 raid_level
= RAID_LEVEL_5
;
762 return (INVALID_ARG
);
767 /* Get disks tag and controller tag */
768 disk_handlesp
= (raid_obj_handle_t
*)calloc(disks_num
+ 2,
769 sizeof (raid_obj_handle_t
));
770 if (disk_handlesp
== NULL
) {
774 disk_handlesp
[0] = OBJ_SEPARATOR_BEGIN
;
775 disk_handlesp
[disks_num
+ 1] = OBJ_SEPARATOR_END
;
777 if ((ret
= get_disk_handle_ctd(disks_num
, &disks_argpp
[argindex
],
778 &ctl_tag
, &disk_handlesp
[1])) != SUCCESS
) {
783 /* LIB API should check whether all disks here belong to one ctl. */
784 /* get_disk_handle_ctd has opened controller. */
785 ctl_handle
= raidcfg_get_controller(ctl_tag
);
787 if (ctl_handle
<= 0) {
788 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ctl_handle
));
789 (void) raidcfg_close_controller(ctl_handle
, NULL
);
794 /* Check if the controller is host raid type */
795 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
796 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
797 (void) raidcfg_close_controller(ctl_handle
, NULL
);
802 if ((ctl_attr
.capability
& RAID_CAP_DISK_TRANS
) == 0) {
803 /* -c only support host raid controller, return failure here */
804 (void) fprintf(stderr
,
805 gettext("Option -c only supports host raid controller.\n"));
806 (void) raidcfg_close_controller(ctl_handle
, NULL
);
811 if (f_flag
== FALSE
) {
812 (void) fprintf(stdout
, gettext("Creating RAID volume "
813 "will destroy all data on spare space of member disks, "
816 (void) fprintf(stdout
, gettext("RAID volume "
817 "not created.\n\n"));
819 (void) raidcfg_close_controller(ctl_handle
, NULL
);
825 * For old raidctl, capacity is 0, which means to creates
826 * max possible capacity of array.
829 array_handle
= raidcfg_create_array(disks_num
+ 2,
830 disk_handlesp
, raid_level
, capacity
, stripe_size
, NULL
);
832 if (array_handle
<= 0) {
833 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(array_handle
));
835 (void) raidcfg_close_controller(ctl_handle
, NULL
);
839 /* Get attribute of array */
840 if ((ret
= raidcfg_get_attr(array_handle
, &array_attr
)) < 0) {
841 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
843 (void) raidcfg_close_controller(ctl_handle
, NULL
);
847 /* Close controller */
848 (void) raidcfg_close_controller(ctl_handle
, NULL
);
850 /* Print feedback for user */
851 (void) fprintf(stdout
,
852 gettext("Volume c%ut%llud%llu is created successfully!\n"),
853 ctl_tag
, array_attr
.tag
.idl
.target_id
,
854 array_attr
.tag
.idl
.lun
);
860 * do_list(disk_arg, argv, optind, is_snapshot)
861 * This function lists RAID's system configuration. It supports various RAID
862 * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG.
865 do_list(char *disk_argp
, char **argv
, uint32_t optind
, uint8_t is_snapshot
)
867 uint32_t ctl_tag
= MAX32BIT
;
868 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
869 raid_obj_handle_t disk_handle
= INIT_HANDLE_VALUE
;
870 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
872 array_tag_t array_tag
;
876 /* print RAID system */
877 if (disk_argp
== NULL
) {
878 if (argv
[optind
] == NULL
) {
879 ret
= snapshot_raidsystem(TRUE
, 0, is_snapshot
);
882 if (is_fully_numeric(argv
[optind
]) == TRUE
) {
883 while (argv
[optind
] != NULL
) {
884 if (get_ctl_tag(argv
[optind
], &ctl_tag
)
891 raidcfg_get_controller(ctl_tag
);
892 if (ctl_handle
<= 0) {
893 (void) fprintf(stderr
, "%s\n",
894 raidcfg_errstr(ctl_handle
));
900 raidcfg_open_controller(ctl_handle
,
903 (void) fprintf(stderr
, "%s\n",
904 raidcfg_errstr(ret
));
909 if (is_snapshot
== FALSE
) {
911 print_ctl_table(ctl_handle
);
914 snapshot_ctl(ctl_handle
,
915 FALSE
, 0, is_snapshot
);
917 (void) raidcfg_close_controller(
922 if (get_array_tag(argv
[optind
],
923 &ctl_tag
, &array_tag
) != SUCCESS
) {
924 return (INVALID_ARG
);
926 ctl_handle
= raidcfg_get_controller(ctl_tag
);
927 if (ctl_handle
<= 0) {
928 (void) fprintf(stderr
, "%s\n",
929 raidcfg_errstr(ctl_handle
));
933 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
935 (void) fprintf(stderr
, "%s\n",
936 raidcfg_errstr(ret
));
940 array_handle
= raidcfg_get_array(ctl_handle
,
941 array_tag
.idl
.target_id
, array_tag
.idl
.lun
);
942 if (array_handle
<= 0) {
943 (void) fprintf(stderr
, "%s\n",
944 raidcfg_errstr(array_handle
));
945 (void) raidcfg_close_controller(
949 if (is_snapshot
== FALSE
) {
950 ret
= print_array_table(ctl_handle
,
953 ret
= snapshot_array(array_handle
, 0,
956 (void) raidcfg_close_controller(
961 if (argv
[optind
+ 1] != NULL
) {
962 return (INVALID_ARG
);
965 if (get_ctl_tag(argv
[optind
], &ctl_tag
) != SUCCESS
) {
966 return (INVALID_ARG
);
969 ctl_handle
= raidcfg_get_controller(ctl_tag
);
970 if (ctl_handle
<= 0) {
971 (void) fprintf(stderr
, "%s\n",
972 raidcfg_errstr(ctl_handle
));
976 if (get_disk_tag_cidl(disk_argp
, &disk_tag
) != SUCCESS
) {
977 return (INVALID_ARG
);
980 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
982 (void) fprintf(stderr
, "%s\n",
983 raidcfg_errstr(ret
));
987 disk_handle
= raidcfg_get_disk(ctl_handle
, disk_tag
);
988 if (disk_handle
<= 0) {
989 (void) fprintf(stderr
, "%s\n",
990 raidcfg_errstr(disk_handle
));
991 (void) raidcfg_close_controller(ctl_handle
, NULL
);
995 if (is_snapshot
== FALSE
) {
996 ret
= print_disk_table(ctl_handle
, disk_handle
);
998 ret
= snapshot_disk(ctl_tag
, disk_handle
, 0,
1001 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1007 * do_delete(f_flag, argv, optind)
1008 * This function deletes a specified array, and return result as SUCCESS,
1009 * FAILURE or INVALID_ARG.
1012 do_delete(uint32_t f_flag
, char **argv
, uint32_t optind
)
1016 array_tag_t array_tag
;
1017 raid_obj_handle_t ctl_handle
;
1018 raid_obj_handle_t array_handle
;
1021 array_argp
= argv
[optind
];
1022 if (array_argp
== NULL
|| argv
[optind
+ 1] != NULL
) {
1023 return (INVALID_ARG
);
1026 if (get_array_tag(array_argp
, &ctl_tag
, &array_tag
) != SUCCESS
) {
1027 return (INVALID_ARG
);
1030 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1031 if (ctl_handle
<= 0) {
1032 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ctl_handle
));
1033 return (INVALID_ARG
);
1036 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1038 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1042 array_handle
= raidcfg_get_array(ctl_handle
, array_tag
.idl
.target_id
,
1044 if (array_handle
<= 0) {
1045 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(array_handle
));
1046 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1050 if (f_flag
== FALSE
) {
1051 (void) fprintf(stdout
, gettext("Deleting RAID volume "
1052 "%s will destroy all data it contains, "
1053 "proceed? "), array_argp
);
1055 (void) fprintf(stdout
, gettext("RAID Volume "
1056 "%s not deleted.\n\n"), array_argp
);
1057 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1063 if ((ret
= raidcfg_delete_array(array_handle
, NULL
)) < 0) {
1064 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1065 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1069 (void) fprintf(stdout
, gettext("Volume %s is deleted successfully!\n"),
1071 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1077 * do_flash(f_flag, filep, ctls_argpp, index, ctl_num)
1078 * This function downloads and updates firmware for specified controller, and
1079 * return result as SUCCESS, FAILURE or INVALID_ARG.
1082 do_flash(uint8_t f_flag
, char *filep
, char **ctls_argpp
,
1083 uint32_t index
, uint32_t ctl_num
)
1085 uint32_t ctl_tag
= MAX32BIT
;
1086 char *ctl_argp
= NULL
;
1087 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1092 return (INVALID_ARG
);
1094 for (i
= 0, j
= index
; i
< ctl_num
; i
++, j
++) {
1095 ctl_argp
= ctls_argpp
[j
];
1096 if (get_ctl_tag(ctl_argp
, &ctl_tag
) != SUCCESS
) {
1097 return (INVALID_ARG
);
1100 /* Ask user to confirm operation. */
1101 if (f_flag
== FALSE
) {
1102 (void) fprintf(stdout
, gettext("Update flash image on "
1103 "controller %d? "), ctl_tag
);
1105 (void) fprintf(stdout
,
1106 gettext("Controller %d not "
1107 "flashed.\n\n"), ctl_tag
);
1112 if ((ctl_handle
= raidcfg_get_controller(ctl_tag
)) < 0) {
1113 (void) fprintf(stderr
, "%s\n",
1114 raidcfg_errstr(ctl_handle
));
1118 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1120 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1124 (void) fprintf(stdout
, gettext("Start updating controller "
1125 "c%u firmware....\n"), ctl_tag
);
1127 if ((ret
= raidcfg_update_fw(ctl_handle
, filep
, NULL
)) < 0) {
1128 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1129 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1133 (void) fprintf(stdout
, gettext("Update controller "
1134 "c%u firmware successfully.\n"), ctl_tag
);
1136 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1143 * do_set_hsp(a_argp, disk_argp, argv, optind)
1144 * This function set or unset HSP relationship between disk and controller/
1145 * array, and return result as SUCCESS, FAILURE or INVALID_ARG.
1148 do_set_hsp(char *a_argp
, char *disk_argp
, char **argv
, uint32_t optind
)
1150 uint32_t flag
= MAX32BIT
;
1151 uint32_t ctl_tag
= MAX32BIT
;
1152 array_tag_t array_tag
;
1153 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1154 raid_obj_handle_t disk_handle
= INIT_HANDLE_VALUE
;
1155 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
1156 raidcfg_controller_t ctl_attr
;
1157 disk_tag_t disk_tag
;
1161 raidcfg_hsp_relation_t hsp_relation
;
1163 (void) memset(&hsp_relation
, 0, sizeof (raidcfg_hsp_relation_t
));
1165 if (a_argp
== NULL
) {
1166 return (INVALID_ARG
);
1169 if (strcmp(a_argp
, "set") == 0) {
1171 } else if (strcmp(a_argp
, "unset") == 0) {
1174 return (INVALID_ARG
);
1177 if (disk_argp
== NULL
) {
1178 return (INVALID_ARG
);
1181 if (argv
[optind
] == NULL
|| argv
[optind
+ 1] != NULL
) {
1182 return (INVALID_ARG
);
1183 } else if (is_fully_numeric(argv
[optind
]) == TRUE
) {
1186 if (get_disk_tag_cidl(disk_argp
, &disk_tag
) != SUCCESS
) {
1187 return (INVALID_ARG
);
1190 if (get_ctl_tag(argv
[optind
], &ctl_tag
) != SUCCESS
) {
1191 return (INVALID_ARG
);
1194 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1195 if (ctl_handle
<= 0) {
1196 (void) fprintf(stderr
, "%s\n",
1197 raidcfg_errstr(ctl_handle
));
1201 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1203 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1207 disk_handle
= raidcfg_get_disk(ctl_handle
, disk_tag
);
1208 if (disk_handle
<= 0) {
1209 (void) fprintf(stderr
, "%s\n",
1210 raidcfg_errstr(disk_handle
));
1211 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1217 if (get_array_tag(argv
[optind
], &ctl_tag
, &array_tag
) !=
1219 return (INVALID_ARG
);
1222 /* Open controller */
1223 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1224 if (ctl_handle
<= 0) {
1225 (void) fprintf(stderr
, "%s\n",
1226 raidcfg_errstr(ctl_handle
));
1230 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1232 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1236 /* Get controller's attribute */
1237 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1238 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1239 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1243 if (get_disk_tag_cidl(disk_argp
, &disk_tag
) != SUCCESS
) {
1244 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1245 return (INVALID_ARG
);
1248 /* Get disk handle */
1249 disk_handle
= raidcfg_get_disk(ctl_handle
, disk_tag
);
1250 if (disk_handle
<= 0) {
1251 (void) fprintf(stderr
, "%s\n",
1252 raidcfg_errstr(disk_handle
));
1253 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1257 /* Get array handle */
1258 array_handle
= raidcfg_get_array(ctl_handle
,
1259 array_tag
.idl
.target_id
, array_tag
.idl
.lun
);
1260 if (array_handle
<= 0) {
1261 (void) fprintf(stderr
, "%s\n",
1262 raidcfg_errstr(array_handle
));
1263 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1268 hsp_relation
.disk_handle
= disk_handle
;
1270 /* Set or unset local HSP */
1271 hsp_relation
.array_handle
= array_handle
;
1273 /* Set or unset global HSP */
1274 hsp_relation
.array_handle
= OBJ_ATTR_NONE
;
1277 /* Perform operation of set or unset */
1278 if (flag
== HSP_SET
) {
1279 if ((ret
= raidcfg_set_hsp(&hsp_relation
, NULL
)) < 0) {
1280 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1281 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1286 (void) printf(gettext("Set local HSP between disk %s "
1287 "and RAID volume %s successfully.\n"),
1288 disk_argp
, argv
[optind
]);
1290 (void) printf(gettext("Set global HSP between disk %s "
1291 "and controller %s successfully.\n"),
1292 disk_argp
, argv
[optind
]);
1295 if ((ret
= raidcfg_unset_hsp(&hsp_relation
, NULL
)) < 0) {
1296 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1297 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1302 (void) printf(gettext("Unset local HSP between "
1303 "disk %s and RAID volume %s successfully.\n"),
1304 disk_argp
, argv
[optind
]);
1306 (void) printf(gettext("Unset global HSP between "
1307 "disk %s and controller %s successfully.\n"),
1308 disk_argp
, argv
[optind
]);
1311 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1316 * do_set_array_attr(f_flag, p_argp, argv, optind)
1317 * This function changes array's attribute when array is running.
1318 * The changeable attribute is up to controller's feature.
1319 * The return value can be SUCCESS, FAILURE or INVALID_ARG.
1322 do_set_array_attr(uint32_t f_flag
, char *p_argp
, char **argv
, uint32_t optind
)
1324 uint32_t ctl_tag
= MAX32BIT
;
1325 array_tag_t array_tag
;
1326 uint32_t type
= MAX32BIT
;
1327 uint32_t value
= MAX32BIT
;
1328 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1329 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
1331 char *param
, *op
= "=";
1335 if (argv
[optind
] == NULL
|| argv
[optind
+ 1] != NULL
) {
1336 return (INVALID_ARG
);
1339 if (p_argp
!= NULL
) {
1340 param
= strtok(p_argp
, op
);
1341 if (strcmp(param
, "wp") == 0) {
1342 type
= SET_CACHE_WR_PLY
;
1343 param
= strtok(NULL
, op
);
1344 if (strcmp(param
, "on") == 0) {
1345 value
= CACHE_WR_ON
;
1346 } else if (strcmp(param
, "off") == 0) {
1347 value
= CACHE_WR_OFF
;
1349 return (INVALID_ARG
);
1351 } else if (strcmp(param
, "state") == 0) {
1352 type
= SET_ACTIVATION_PLY
;
1353 param
= strtok(NULL
, op
);
1354 if (strcmp(param
, "activate") == 0) {
1355 value
= ARRAY_ACT_ACTIVATE
;
1357 return (INVALID_ARG
);
1360 return (INVALID_ARG
);
1363 return (INVALID_ARG
);
1366 if (get_array_tag(argv
[optind
], &ctl_tag
, &array_tag
) != SUCCESS
) {
1367 return (INVALID_ARG
);
1370 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1371 if (ctl_handle
<= 0) {
1372 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ctl_handle
));
1376 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1378 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1382 array_handle
= raidcfg_get_array(ctl_handle
, array_tag
.idl
.target_id
,
1384 if (array_handle
<= 0) {
1385 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(array_handle
));
1389 /* Ask user to confirm operation. */
1390 if (f_flag
== FALSE
) {
1391 (void) fprintf(stdout
, gettext("Update attribute of "
1392 "array %s? "), argv
[optind
]);
1394 (void) fprintf(stdout
,
1395 gettext("Array %s not "
1396 "changed.\n\n"), argv
[optind
]);
1397 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1402 if ((ret
= raidcfg_set_attr(array_handle
, type
, &value
, NULL
)) < 0) {
1403 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1404 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1408 (void) printf(gettext("Set attribute of RAID volume %s "
1409 "successfully.\n"), argv
[optind
]);
1410 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1416 * snapshot_raidsystem(recursive, indent, is_snapshot)
1417 * This function prints the snapshot of whole RAID's system configuration,
1418 * and return result as SUCCESS or FAILURE.
1421 snapshot_raidsystem(uint8_t recursive
, uint8_t indent
, uint8_t is_snapshot
)
1423 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1426 ctl_handle
= raidcfg_list_head(OBJ_SYSTEM
, OBJ_TYPE_CONTROLLER
);
1427 while (ctl_handle
> 0) {
1428 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1430 if (snapshot_ctl(ctl_handle
, recursive
, indent
,
1431 is_snapshot
) == FAILURE
) {
1432 (void) raidcfg_close_controller(ctl_handle
,
1436 ctl_handle
= raidcfg_list_next(ctl_handle
);
1442 * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot)
1443 * This function prints snapshot of specified controller's configuration,
1444 * and return result as SUCCESS or FAILURE.
1447 snapshot_ctl(raid_obj_handle_t ctl_handle
, uint8_t recursive
, uint8_t indent
,
1448 uint8_t is_snapshot
)
1450 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
1451 raid_obj_handle_t disk_handle
= INIT_HANDLE_VALUE
;
1452 raidcfg_controller_t ctl_attr
;
1457 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1458 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1462 ctl_tag
= ctl_attr
.controller_id
;
1463 if (is_snapshot
== FALSE
) {
1464 print_indent(indent
);
1465 (void) fprintf(stdout
, gettext("Controller: %u\n"), ctl_tag
);
1467 (void) snprintf(ctlbuf
, sizeof (ctlbuf
), "%u \"%s\"",
1468 ctl_tag
, ctl_attr
.controller_type
);
1469 (void) fprintf(stdout
, "%s", ctlbuf
);
1471 (void) fprintf(stdout
, "\n");
1474 if (recursive
== TRUE
) {
1475 array_handle
= raidcfg_list_head(ctl_handle
, OBJ_TYPE_ARRAY
);
1476 while (array_handle
> 0) {
1477 if (snapshot_array(array_handle
,
1478 indent
+ 1, FALSE
, is_snapshot
) == FAILURE
) {
1482 array_handle
= raidcfg_list_next(array_handle
);
1485 disk_handle
= raidcfg_list_head(ctl_handle
, OBJ_TYPE_DISK
);
1486 while (disk_handle
> 0) {
1487 if (snapshot_disk(ctl_tag
, disk_handle
,
1488 indent
+ 1, is_snapshot
) == FAILURE
) {
1492 disk_handle
= raidcfg_list_next(disk_handle
);
1500 * snapshot_array(array_handle, indent, is_sub, is_snapshot)
1501 * This function prints snapshot of specified array's configuration,
1502 * and return result as SUCCESS or FAILURE.
1505 snapshot_array(raid_obj_handle_t array_handle
, uint8_t indent
, uint8_t is_sub
,
1506 uint8_t is_snapshot
)
1508 raid_obj_handle_t ctl_handle
;
1509 raid_obj_handle_t subarray_handle
;
1510 raid_obj_handle_t arraypart_handle
;
1511 raid_obj_handle_t task_handle
;
1513 raidcfg_controller_t ctl_attr
;
1514 raidcfg_array_t array_attr
;
1515 raidcfg_arraypart_t arraypart_attr
;
1516 raidcfg_task_t task_attr
;
1518 char arraybuf
[256] = "\0";
1519 char diskbuf
[256] = "\0";
1520 char tempbuf
[256] = "\0";
1526 ctl_handle
= raidcfg_get_container(array_handle
);
1527 ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
);
1529 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1532 ctl_tag
= ctl_attr
.controller_id
;
1534 /* Print array attribute */
1535 if ((ret
= raidcfg_get_attr(array_handle
, &array_attr
)) < 0) {
1536 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1540 if (is_snapshot
== FALSE
) {
1541 print_indent(indent
);
1542 if (is_sub
== FALSE
) {
1543 (void) fprintf(stdout
, gettext("Volume:"
1545 ctl_tag
, array_attr
.tag
.idl
.target_id
,
1546 array_attr
.tag
.idl
.lun
);
1548 (void) fprintf(stdout
, gettext("Sub-Volume\n"));
1551 (void) snprintf(arraybuf
, sizeof (arraybuf
), "c%ut%llud%llu ",
1552 ctl_tag
, array_attr
.tag
.idl
.target_id
,
1553 array_attr
.tag
.idl
.lun
);
1555 /* Check if array is in sync state */
1556 task_handle
= raidcfg_list_head(array_handle
, OBJ_TYPE_TASK
);
1557 if (task_handle
> 0) {
1558 (void) raidcfg_get_attr(task_handle
, &task_attr
);
1559 if (task_attr
.task_func
== TASK_FUNC_BUILD
) {
1560 array_attr
.state
= ARRAY_STATE_SYNC
;
1563 subarray_handle
= raidcfg_list_head(array_handle
,
1565 while (subarray_handle
> 0) {
1566 task_handle
= raidcfg_list_head(subarray_handle
,
1568 if (task_handle
> 0) {
1569 (void) raidcfg_get_attr(task_handle
,
1571 if (task_attr
.task_func
==
1579 raidcfg_list_next(subarray_handle
);
1583 /* Print sub array */
1584 subarray_handle
= raidcfg_list_head(array_handle
,
1586 while (subarray_handle
> 0) {
1587 /* print subarraypart */
1588 arraypart_handle
= raidcfg_list_head(subarray_handle
,
1589 OBJ_TYPE_ARRAY_PART
);
1590 while (arraypart_handle
> 0) {
1591 if ((ret
= raidcfg_get_attr(arraypart_handle
,
1592 &arraypart_attr
)) < 0) {
1593 (void) fprintf(stderr
, "%s\n",
1594 raidcfg_errstr(ret
));
1598 if (arraypart_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1599 (void) snprintf(tempbuf
,
1603 (void) snprintf(tempbuf
,
1606 arraypart_attr
.tag
.cidl
.bus
,
1607 arraypart_attr
.tag
.cidl
.target_id
,
1608 arraypart_attr
.tag
.cidl
.lun
);
1610 (void) strlcat(diskbuf
, tempbuf
,
1612 (void) strcat(diskbuf
, " ");
1615 raidcfg_list_next(arraypart_handle
);
1617 subarray_handle
= raidcfg_list_next(subarray_handle
);
1620 /* Print arraypart */
1621 arraypart_handle
= raidcfg_list_head(array_handle
,
1622 OBJ_TYPE_ARRAY_PART
);
1623 while (arraypart_handle
> 0) {
1624 if ((ret
= raidcfg_get_attr(arraypart_handle
,
1625 &arraypart_attr
)) < 0) {
1626 (void) fprintf(stderr
, "%s\n",
1627 raidcfg_errstr(ret
));
1631 if (arraypart_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1632 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1635 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1637 arraypart_attr
.tag
.cidl
.bus
,
1638 arraypart_attr
.tag
.cidl
.target_id
,
1639 arraypart_attr
.tag
.cidl
.lun
);
1641 (void) strlcat(diskbuf
, tempbuf
, sizeof (diskbuf
));
1642 (void) strcat(diskbuf
, " ");
1644 arraypart_handle
= raidcfg_list_next(arraypart_handle
);
1646 (void) snprintf(tempbuf
, sizeof (tempbuf
), "%u ", disknum
);
1647 (void) strlcat(arraybuf
, tempbuf
, sizeof (arraybuf
));
1648 (void) strlcat(arraybuf
, diskbuf
, sizeof (arraybuf
));
1650 switch (array_attr
.raid_level
) {
1652 (void) sprintf(tempbuf
, "0");
1655 (void) sprintf(tempbuf
, "1");
1658 (void) sprintf(tempbuf
, "1E");
1661 (void) sprintf(tempbuf
, "5");
1664 (void) sprintf(tempbuf
, "10");
1667 (void) sprintf(tempbuf
, "50");
1670 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1674 (void) strlcat(arraybuf
, tempbuf
, sizeof (arraybuf
));
1675 (void) fprintf(stdout
, "%s ", arraybuf
);
1677 switch (array_attr
.state
) {
1678 case ARRAY_STATE_OPTIMAL
:
1679 (void) fprintf(stdout
, gettext("OPTIMAL"));
1681 case ARRAY_STATE_DEGRADED
:
1682 (void) fprintf(stdout
, gettext("DEGRADED"));
1684 case ARRAY_STATE_FAILED
:
1685 (void) fprintf(stdout
, gettext("FAILED"));
1687 case ARRAY_STATE_SYNC
:
1688 (void) fprintf(stdout
, gettext("SYNC"));
1690 case ARRAY_STATE_MISSING
:
1691 (void) fprintf(stdout
, gettext("MISSING"));
1694 (void) fprintf(stdout
, gettext("N/A"));
1697 (void) fprintf(stdout
, "\n");
1704 * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot)
1705 * This function prints snapshot of specified disk's configuration, and return
1706 * result as SUCCESS or FAILURE.
1709 snapshot_disk(uint32_t ctl_tag
, raid_obj_handle_t disk_handle
, uint8_t indent
,
1710 uint8_t is_snapshot
)
1712 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1713 raid_obj_handle_t hsp_handle
;
1715 raidcfg_controller_t ctl_attr
;
1716 raidcfg_disk_t disk_attr
;
1717 char diskbuf
[256] = "";
1718 char tempbuf
[256] = "";
1722 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1723 ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
);
1725 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1729 /* Print attribute of disk */
1730 if ((ret
= raidcfg_get_attr(disk_handle
, &disk_attr
)) < 0) {
1731 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1735 if (is_snapshot
== FALSE
) {
1736 print_indent(indent
);
1738 hsp_handle
= raidcfg_list_head(disk_handle
, OBJ_TYPE_HSP
);
1740 if (disk_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1741 (void) fprintf(stdout
, gettext("Disk: N/A"));
1743 (void) fprintf(stdout
, gettext("Disk: %llu.%llu.%llu"),
1744 disk_attr
.tag
.cidl
.bus
,
1745 disk_attr
.tag
.cidl
.target_id
,
1746 disk_attr
.tag
.cidl
.lun
);
1748 if (hsp_handle
> 0) {
1749 (void) fprintf(stdout
, "(HSP)");
1751 (void) fprintf(stdout
, "\n");
1753 if (disk_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1754 (void) fprintf(stdout
, gettext("N/A"));
1756 (void) snprintf(diskbuf
, sizeof (diskbuf
),
1758 disk_attr
.tag
.cidl
.bus
,
1759 disk_attr
.tag
.cidl
.target_id
,
1760 disk_attr
.tag
.cidl
.lun
);
1762 hsp_handle
= raidcfg_list_head(disk_handle
, OBJ_TYPE_HSP
);
1763 if (hsp_handle
> 0) {
1764 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1766 } else if (disk_attr
.state
== DISK_STATE_GOOD
) {
1767 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1769 } else if (disk_attr
.state
== DISK_STATE_FAILED
) {
1770 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1773 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1777 (void) strlcat(diskbuf
, tempbuf
, sizeof (diskbuf
));
1778 (void) fprintf(stdout
, "%s\n", diskbuf
);
1785 print_ctl_table(raid_obj_handle_t ctl_handle
)
1787 raidcfg_controller_t ctl_attr
;
1791 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1792 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1796 (void) fprintf(stdout
, gettext("Controller\tType\t\tVersion"));
1797 (void) fprintf(stdout
, "\n");
1798 (void) fprintf(stdout
, "--------------------------------");
1799 (void) fprintf(stdout
, "--------------------------------");
1800 (void) fprintf(stdout
, "\n");
1802 (void) snprintf(controller
, sizeof (controller
), "%u",
1803 ctl_attr
.controller_id
);
1804 (void) printf("c%s\t\t", controller
);
1806 (void) print_ctl_attr(&ctl_attr
);
1807 (void) fprintf(stdout
, "\n");
1813 print_array_table(raid_obj_handle_t ctl_handle
, raid_obj_handle_t array_handle
)
1815 raidcfg_controller_t ctl_attr
;
1816 raidcfg_array_t array_attr
;
1817 raidcfg_array_t subarray_attr
;
1818 raidcfg_arraypart_t arraypart_attr
;
1819 raidcfg_task_t task_attr
;
1821 raid_obj_handle_t subarray_handle
;
1822 raid_obj_handle_t arraypart_handle
;
1823 raid_obj_handle_t task_handle
;
1830 /* Controller attribute */
1831 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1832 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1836 /* Array attribute */
1837 if ((ret
= raidcfg_get_attr(array_handle
, &array_attr
)) < 0) {
1838 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1843 (void) fprintf(stdout
, gettext("Volume\t\t\tSize\tStripe\tStatus\t"
1845 (void) fprintf(stdout
, "\n");
1846 (void) fprintf(stdout
, gettext("\tSub\t\t\tSize\t\t\tLevel"));
1847 (void) fprintf(stdout
, "\n");
1848 (void) fprintf(stdout
, gettext("\t\tDisk\t\t\t\t\t"));
1849 (void) fprintf(stdout
, "\n");
1850 (void) fprintf(stdout
, "--------------------------------");
1851 (void) fprintf(stdout
, "--------------------------------");
1852 (void) fprintf(stdout
, "\n");
1855 (void) snprintf(array
, sizeof (array
), "c%ut%llud%llu",
1856 ctl_attr
.controller_id
, array_attr
.tag
.idl
.target_id
,
1857 array_attr
.tag
.idl
.lun
);
1858 (void) fprintf(stdout
, "%s\t\t", array
);
1859 if (strlen(array
) < 8)
1860 (void) fprintf(stdout
, "\t");
1863 /* check if array is in sync state */
1864 task_handle
= raidcfg_list_head(array_handle
, OBJ_TYPE_TASK
);
1865 if (task_handle
> 0) {
1866 (void) raidcfg_get_attr(task_handle
, &task_attr
);
1867 if (task_attr
.task_func
== TASK_FUNC_BUILD
) {
1868 array_attr
.state
= ARRAY_STATE_SYNC
;
1871 subarray_handle
= raidcfg_list_head(array_handle
,
1873 while (subarray_handle
> 0) {
1874 task_handle
= raidcfg_list_head(subarray_handle
,
1876 if (task_handle
> 0) {
1877 (void) raidcfg_get_attr(task_handle
,
1879 if (task_attr
.task_func
== TASK_FUNC_BUILD
) {
1880 array_attr
.state
= ARRAY_STATE_SYNC
;
1884 subarray_handle
= raidcfg_list_next(subarray_handle
);
1888 (void) print_array_attr(&array_attr
);
1889 (void) fprintf(stdout
, "\n");
1891 /* Print sub array */
1892 i
= 0; /* Count sub array number */
1893 subarray_handle
= raidcfg_list_head(array_handle
, OBJ_TYPE_ARRAY
);
1894 while (subarray_handle
> 0) {
1895 if ((ret
= raidcfg_get_attr(subarray_handle
,
1896 &subarray_attr
)) < 0) {
1897 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1901 /* Use sub0/sub1 here, not cxtxd0 for subarray */
1902 (void) snprintf(array
, sizeof (array
), "sub%u", i
++);
1903 (void) fprintf(stdout
, "\t%s\t\t", array
);
1905 /* Check if array is in sync */
1906 task_handle
= raidcfg_list_head(subarray_handle
, OBJ_TYPE_TASK
);
1907 if (task_handle
> 0) {
1908 (void) raidcfg_get_attr(task_handle
, &task_attr
);
1909 if (task_attr
.task_func
== TASK_FUNC_BUILD
) {
1910 subarray_attr
.state
= ARRAY_STATE_SYNC
;
1914 (void) print_array_attr(&subarray_attr
);
1915 (void) fprintf(stdout
, "\n");
1917 /* Print subarraypart */
1918 arraypart_handle
= raidcfg_list_head(subarray_handle
,
1919 OBJ_TYPE_ARRAY_PART
);
1920 while (arraypart_handle
> 0) {
1921 if ((ret
= raidcfg_get_attr(arraypart_handle
,
1922 &arraypart_attr
)) < 0) {
1923 (void) fprintf(stderr
, "%s\n",
1924 raidcfg_errstr(ret
));
1928 if (arraypart_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1929 (void) snprintf(arraypart
, sizeof (arraypart
),
1932 (void) snprintf(arraypart
, sizeof (arraypart
),
1934 arraypart_attr
.tag
.cidl
.bus
,
1935 arraypart_attr
.tag
.cidl
.target_id
,
1936 arraypart_attr
.tag
.cidl
.lun
);
1939 (void) fprintf(stdout
, "\t\t%s\t", arraypart
);
1940 (void) print_arraypart_attr(&arraypart_attr
);
1941 (void) fprintf(stdout
, "\n");
1942 arraypart_handle
= raidcfg_list_next(arraypart_handle
);
1944 subarray_handle
= raidcfg_list_next(subarray_handle
);
1947 /* Print arraypart */
1948 arraypart_handle
= raidcfg_list_head(array_handle
,
1949 OBJ_TYPE_ARRAY_PART
);
1950 while (arraypart_handle
> 0) {
1951 if ((ret
= raidcfg_get_attr(arraypart_handle
,
1952 &arraypart_attr
)) < 0) {
1953 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1957 if (arraypart_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1958 (void) snprintf(arraypart
, sizeof (arraypart
),
1961 (void) snprintf(arraypart
, sizeof (arraypart
),
1963 arraypart_attr
.tag
.cidl
.bus
,
1964 arraypart_attr
.tag
.cidl
.target_id
,
1965 arraypart_attr
.tag
.cidl
.lun
);
1968 (void) fprintf(stdout
, "\t\t%s\t", arraypart
);
1969 (void) print_arraypart_attr(&arraypart_attr
);
1970 (void) fprintf(stdout
, "\n");
1971 arraypart_handle
= raidcfg_list_next(arraypart_handle
);
1978 print_disk_table(raid_obj_handle_t ctl_handle
, raid_obj_handle_t disk_handle
)
1980 raidcfg_controller_t ctl_attr
;
1981 raidcfg_disk_t disk_attr
;
1982 raidcfg_prop_t
*prop_attr
, *prop_attr2
;
1983 raid_obj_handle_t prop_handle
;
1987 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1988 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1992 if ((ret
= raidcfg_get_attr(disk_handle
, &disk_attr
)) < 0) {
1993 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1998 (void) fprintf(stdout
, gettext("Disk\tVendor Product "
1999 "Firmware\tCapacity\tStatus\tHSP"));
2000 (void) fprintf(stdout
, "\n");
2001 (void) fprintf(stdout
, "--------------------------------------");
2002 (void) fprintf(stdout
, "--------------------------------------");
2003 (void) fprintf(stdout
, "\n");
2006 (void) snprintf(disk
, sizeof (disk
), "%llu.%llu.%llu",
2007 disk_attr
.tag
.cidl
.bus
,
2008 disk_attr
.tag
.cidl
.target_id
,
2009 disk_attr
.tag
.cidl
.lun
);
2011 (void) fprintf(stdout
, "%s\t", disk
);
2013 (void) print_disk_attr(ctl_handle
, disk_handle
, &disk_attr
);
2015 prop_attr
= calloc(1, sizeof (raidcfg_prop_t
));
2016 if (prop_attr
== NULL
) {
2017 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ERR_NOMEM
));
2021 prop_handle
= raidcfg_list_head(disk_handle
, OBJ_TYPE_PROP
);
2022 if (prop_handle
== 0) {
2028 prop_attr
->prop_size
= 0;
2029 if ((ret
= raidcfg_get_attr(prop_handle
, prop_attr
)) < 0) {
2031 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
2034 if (prop_attr
->prop_type
== PROP_GUID
)
2036 } while (prop_handle
!= 0);
2038 prop_attr2
= realloc(prop_attr
,
2039 sizeof (raidcfg_prop_t
) + prop_attr
->prop_size
);
2041 if (prop_attr2
== NULL
) {
2042 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ERR_NOMEM
));
2046 if ((ret
= raidcfg_get_attr(prop_handle
, prop_attr2
)) < 0) {
2048 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
2052 (void) fprintf(stdout
, "GUID:%s\n", prop_attr2
->prop
);
2059 * print_ctl_attr(attrp)
2060 * This function prints attribute of specified controller, and return
2061 * result as SUCCESS or FAILURE.
2064 print_ctl_attr(raidcfg_controller_t
*attrp
)
2066 char type
[CONTROLLER_TYPE_LEN
];
2067 char version
[CONTROLLER_FW_LEN
];
2069 if (attrp
== NULL
) {
2073 (void) snprintf(type
, sizeof (type
), "%s", attrp
->controller_type
);
2074 (void) fprintf(stdout
, "%-16s", type
);
2076 (void) snprintf(version
, sizeof (version
), "%s", attrp
->fw_version
);
2077 (void) fprintf(stdout
, "%s", version
);
2083 * print_array_attr(attrp)
2084 * This function prints attribute of specified array, and return
2085 * result as SUCCESS or FAILURE.
2088 print_array_attr(raidcfg_array_t
*attrp
)
2091 char stripe_size
[8];
2094 if (attrp
== NULL
) {
2098 if (attrp
->capacity
!= MAX64BIT
) {
2099 if (size_to_string(attrp
->capacity
, capacity
, 8) != SUCCESS
) {
2102 (void) printf("%s\t", capacity
);
2104 (void) printf(gettext("N/A\t"));
2107 if (attrp
->stripe_size
!= MAX32BIT
) {
2108 (void) snprintf(stripe_size
, sizeof (stripe_size
), "%uK",
2109 attrp
->stripe_size
/ 1024);
2110 (void) printf("%s\t", stripe_size
);
2112 (void) printf(gettext("N/A\t"));
2115 if (attrp
->state
& ARRAY_STATE_INACTIVATE
)
2116 (void) printf("%-8s", gettext("INACTIVE"));
2118 switch (attrp
->state
) {
2119 case ARRAY_STATE_OPTIMAL
:
2120 (void) printf("%-8s", gettext("OPTIMAL"));
2122 case ARRAY_STATE_DEGRADED
:
2123 (void) printf("%-8s", gettext("DEGRADED"));
2125 case ARRAY_STATE_FAILED
:
2126 (void) printf("%-8s", gettext("FAILED"));
2128 case ARRAY_STATE_SYNC
:
2129 (void) printf("%-8s", gettext("SYNC"));
2131 case ARRAY_STATE_MISSING
:
2132 (void) printf("%-8s", gettext("MISSING"));
2135 (void) printf("%-8s", gettext("N/A"));
2141 if (attrp
->write_policy
== CACHE_WR_OFF
) {
2142 (void) printf(gettext("OFF"));
2143 } else if (attrp
->write_policy
== CACHE_WR_ON
) {
2144 (void) printf(gettext("ON"));
2146 (void) printf(gettext("N/A"));
2148 (void) printf("\t");
2150 switch (attrp
->raid_level
) {
2152 (void) sprintf(raid_level
, "RAID0");
2155 (void) sprintf(raid_level
, "RAID1");
2158 (void) sprintf(raid_level
, "RAID1E");
2161 (void) sprintf(raid_level
, "RAID5");
2164 (void) sprintf(raid_level
, "RAID10");
2167 (void) sprintf(raid_level
, "RAID50");
2170 (void) snprintf(raid_level
, sizeof (raid_level
),
2174 (void) printf("%s", raid_level
);
2180 * print_arraypart_attr(attrp)
2181 * This function print attribute of specified arraypart, and return
2182 * result as SUCCESS or FAILURE.
2185 print_arraypart_attr(raidcfg_arraypart_t
*attrp
)
2189 if (attrp
== NULL
) {
2193 if (attrp
->size
!= MAX64BIT
) {
2194 if (size_to_string(attrp
->size
, size
, 8) != SUCCESS
) {
2197 (void) printf("%s\t", size
);
2199 (void) printf(gettext("N/A\t"));
2202 (void) printf("\t");
2204 if (attrp
->state
== DISK_STATE_GOOD
) {
2205 (void) printf(gettext("GOOD"));
2206 } else if (attrp
->state
== DISK_STATE_FAILED
) {
2207 (void) printf(gettext("FAILED"));
2209 (void) printf(gettext("N/A"));
2211 (void) printf("\t");
2217 * print_disk_attr(ctl_handle, disk_handle, attrp)
2218 * This function prints attribute of specified disk, and return
2219 * result as SUCCESS or FAILURE.
2222 print_disk_attr(raid_obj_handle_t ctl_handle
, raid_obj_handle_t disk_handle
,
2223 raidcfg_disk_t
*attrp
)
2225 char vendor
[DISK_VENDER_LEN
+ 1];
2226 char product
[DISK_PRODUCT_LEN
+ 1];
2227 char revision
[DISK_REV_LEN
+ 1];
2231 raid_obj_handle_t hsp_handle
;
2232 raidcfg_hsp_t hsp_attr
;
2233 raidcfg_controller_t ctl_attr
;
2237 if (attrp
== NULL
) {
2241 (void) memccpy(vendor
, attrp
->vendorid
, '\0', DISK_VENDER_LEN
);
2242 vendor
[DISK_VENDER_LEN
] = '\0';
2243 (void) printf("%-9s", vendor
);
2245 (void) memccpy(product
, attrp
->productid
, '\0', DISK_PRODUCT_LEN
);
2246 product
[DISK_PRODUCT_LEN
] = '\0';
2247 (void) printf("%-17s", product
);
2249 (void) memccpy(revision
, attrp
->revision
, '\0', DISK_REV_LEN
);
2250 revision
[DISK_REV_LEN
] = '\0';
2251 (void) printf("%s\t\t", revision
);
2253 if (attrp
->capacity
!= MAX64BIT
) {
2254 if (size_to_string(attrp
->capacity
, capacity
, 16) != SUCCESS
) {
2257 (void) printf("%s\t\t", capacity
);
2259 (void) printf(gettext("N/A"));
2262 if (attrp
->state
== DISK_STATE_GOOD
) {
2263 (void) printf(gettext("GOOD"));
2264 } else if (attrp
->state
== DISK_STATE_FAILED
) {
2265 (void) printf(gettext("FAILED"));
2267 (void) printf(gettext("N/A"));
2269 (void) printf("\t");
2271 /* Controller attribute */
2272 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
2273 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
2277 hsp_handle
= raidcfg_list_head(disk_handle
, OBJ_TYPE_HSP
);
2278 if (hsp_handle
== 0) {
2279 (void) printf(gettext("N/A\n"));
2282 while (hsp_handle
> 0) {
2283 if ((ret
= raidcfg_get_attr(hsp_handle
,
2285 (void) fprintf(stderr
, "%s\n",
2286 raidcfg_errstr(ret
));
2290 if (is_indent
== TRUE
) {
2291 (void) printf("\t\t\t\t\t\t\t");
2296 if (hsp_attr
.type
== HSP_TYPE_LOCAL
) {
2297 (void) snprintf(hsp
, sizeof (hsp
),
2299 ctl_attr
.controller_id
,
2300 hsp_attr
.tag
.idl
.target_id
,
2301 hsp_attr
.tag
.idl
.lun
);
2302 (void) printf("%s\n", hsp
);
2303 } else if (hsp_attr
.type
== HSP_TYPE_GLOBAL
) {
2304 (void) printf(gettext("Global\n"));
2309 hsp_handle
= raidcfg_list_next(hsp_handle
);
2317 * print_indent(indent)
2318 * This function prints specified number of tab characters. It's used to
2322 print_indent(uint8_t indent
)
2325 for (i
= 0; i
< indent
; i
++) {
2326 (void) fprintf(stdout
, "\t");
2331 * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp)
2332 * This function parses the string of disk argument, and gets the disks tag
2333 * and separators from the string. Then it translates the tag to handle, and
2334 * stores handles and separators to new buffer pointed by parameter handlespp.
2335 * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first
2336 * "0" is channel number, and the second "1" is target number, and the third
2337 * "0" is LUN number. The disk tags are separated by comma and parenthesis.
2338 * Function returns SUCCESS or FAILURE.
2341 get_disk_handle_cidl(uint32_t ctl_tag
, char *disks_argp
, int *comps_nump
,
2342 raid_obj_handle_t
**handlespp
)
2347 char *delimit
= " ";
2349 disk_tag_t disk_tag
;
2351 if (disks_argp
== NULL
|| comps_nump
== NULL
) {
2356 len
= strlen(disks_argp
);
2358 if ((disks_str
= (char *)malloc(3 * len
+ 4)) == NULL
) {
2362 /* Insert whitespace between disk tags, '(' , and ')' */
2363 disks_str
[j
++] = '(';
2364 disks_str
[j
++] = ' ';
2366 while (p
[i
] != '\0') {
2367 if (p
[i
] == ')' || p
[i
] == '(') {
2368 disks_str
[j
++] = ' ';
2369 disks_str
[j
++] = p
[i
];
2370 disks_str
[j
++] = ' ';
2372 disks_str
[j
++] = p
[i
];
2375 disks_str
[j
++] = ' ';
2376 disks_str
[j
++] = ')';
2377 disks_str
[j
] = '\0';
2379 len
= strlen(disks_str
) + 1;
2381 if ((t
= (char *)malloc(len
)) == NULL
) {
2384 (void) memcpy(t
, disks_str
, len
);
2385 p
= strtok(t
, delimit
);
2388 p
= strtok(NULL
, delimit
);
2392 *handlespp
= calloc(*comps_nump
, sizeof (raid_obj_handle_t
));
2393 if (*handlespp
== NULL
) {
2397 for (i
= 0; i
< *comps_nump
; i
++)
2398 (*handlespp
)[i
] = INIT_HANDLE_VALUE
;
2401 p
= strtok(disks_str
, delimit
);
2404 (*handlespp
)[i
] = OBJ_SEPARATOR_BEGIN
;
2405 } else if (*p
== ')') {
2406 (*handlespp
)[i
] = OBJ_SEPARATOR_END
;
2408 if (get_disk_tag_cidl(p
, &disk_tag
) != SUCCESS
) {
2411 return (INVALID_ARG
);
2414 raidcfg_get_disk(raidcfg_get_controller(ctl_tag
),
2416 if ((*handlespp
)[i
] <= 0) {
2417 (void) fprintf(stderr
, "%s\n",
2418 raidcfg_errstr((*handlespp
)[i
]));
2424 p
= strtok(NULL
, delimit
);
2433 * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep)
2434 * This function parses string of single disk with "ctd" format, for example,
2435 * c0t0d0, and translates it to controller tag and disk tag.
2436 * Then it calls lib api and get disk handle. The controller tag and disk
2437 * handle are both returned by out parameters.
2438 * The return value is SUCCESS or FAILURE.
2441 get_disk_handle_ctd(int disks_num
, char **disks_argpp
, uint32_t *ctl_tagp
,
2442 raid_obj_handle_t
*disks_handlep
)
2444 raid_obj_handle_t ctl_handle
;
2445 disk_tag_t disk_tag
;
2450 if (disks_handlep
== NULL
) {
2454 for (i
= 0; i
< disks_num
; i
++) {
2455 if (get_disk_tag_ctd(disks_argpp
[i
], &disk_tag
, &ctl_id
) !=
2457 return (INVALID_ARG
);
2463 ctl_handle
= raidcfg_get_controller(*ctl_tagp
);
2464 if (ctl_handle
<= 0) {
2465 (void) fprintf(stderr
, "%s\n",
2466 raidcfg_errstr(ctl_handle
));
2469 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
2471 (void) fprintf(stderr
, "%s\n",
2472 raidcfg_errstr(ret
));
2477 if ((disks_handlep
[i
] =
2478 raidcfg_get_disk(ctl_handle
, disk_tag
)) < 0) {
2479 (void) fprintf(stderr
, "%s\n",
2480 raidcfg_errstr(disks_handlep
[i
]));
2481 (void) raidcfg_close_controller(ctl_handle
, NULL
);
2491 * This function translates controller string to tag. The return value is
2492 * SUCCESS if the string has legal format and is parsed successfully,
2493 * or FAILURE if it fails.
2496 get_ctl_tag(char *argp
, uint32_t *ctl_tagp
)
2498 if (argp
== NULL
|| is_fully_numeric(argp
) == FALSE
||
2502 *ctl_tagp
= (atoi(argp
));
2507 * get_array_tag(argp, ctl_tagp, array_tagp)
2508 * This function parses array string to get array tag and controller tag.
2509 * The return value is SUCCESS if the string has legal format, or
2510 * FAILURE if it fails.
2513 get_array_tag(char *argp
, uint32_t *ctl_tagp
, array_tag_t
*array_tagp
)
2520 uint32_t value_c
= MAX32BIT
;
2521 uint32_t value_t
= MAX32BIT
;
2522 uint32_t value_d
= MAX32BIT
;
2526 if (argp
== NULL
|| (len
= strlen(argp
)) == 0 ||
2527 array_tagp
== NULL
) {
2531 t
= (char *)malloc(len
+ 1);
2536 (void) memcpy(t
, argp
, len
+ 1);
2538 /* Now remmber to release t memory if exception occurs */
2539 if (((dp
= strchr(t
, 'd')) == NULL
) ||
2540 ((tp
= strchr(t
, 't')) == NULL
) ||
2541 ((cp
= strchr(t
, 'c')) == NULL
)) {
2553 if (is_fully_numeric(dp
) == FALSE
||
2554 is_fully_numeric(tp
) == FALSE
||
2555 is_fully_numeric(cp
) == FALSE
) {
2564 array_tagp
->idl
.target_id
= value_t
;
2565 array_tagp
->idl
.lun
= value_d
;
2567 if (ctl_tagp
!= NULL
) {
2568 *ctl_tagp
= value_c
;
2576 * get_disk_tag_ctd(argp, disk_tagp)
2577 * This function parses disk string of ctd format, and translates it to
2578 * disk tag and controller tag. The tags is returned by out parameters.
2579 * The return value is SUCCESS if the string has legal format, or FAILURE
2583 get_disk_tag_ctd(char *argp
, disk_tag_t
*disk_tagp
, uint32_t *ctl_tag
)
2590 uint32_t value_c
= MAX32BIT
;
2591 uint32_t value_t
= MAX32BIT
;
2592 uint32_t value_d
= MAX32BIT
;
2596 if (argp
== NULL
|| (len
= strlen(argp
)) == 0 ||
2597 disk_tagp
== NULL
) {
2601 t
= (char *)malloc(len
+ 1);
2606 (void) memcpy(t
, argp
, len
+ 1);
2608 /* Now remmber to release t memory if exception occurs */
2609 if (((dp
= strchr(t
, 'd')) == NULL
) ||
2610 ((tp
= strchr(t
, 't')) == NULL
) ||
2611 ((cp
= strchr(t
, 'c')) == NULL
)) {
2623 if (is_fully_numeric(dp
) == FALSE
||
2624 is_fully_numeric(tp
) == FALSE
||
2625 is_fully_numeric(cp
) == FALSE
) {
2634 disk_tagp
->cidl
.bus
= 0;
2635 disk_tagp
->cidl
.target_id
= value_t
;
2636 disk_tagp
->cidl
.lun
= value_d
;
2644 * get_disk_tag_cidl(argp, disk_tagp)
2645 * This function parses disk string of cidl format and translates it to tag.
2646 * The return value is disk tag if the string has legal format, or FAILURE
2650 get_disk_tag_cidl(char *argp
, disk_tag_t
*disk_tagp
)
2658 if (argp
== NULL
|| (len
= strlen(argp
)) == 0) {
2662 if (disk_tagp
== NULL
) {
2666 t
= (char *)malloc(len
+ 1);
2671 (void) memcpy(t
, argp
, len
+ 1);
2674 dot2p
= strrchr(p
, '.');
2675 if (dot2p
== NULL
) {
2682 dot1p
= strrchr(p
, '.');
2683 if (dot1p
== NULL
) {
2690 /* Assert only 2 dots in this string */
2691 if (strrchr(p
, '.') != NULL
) {
2699 if (is_fully_numeric(p
) == FALSE
||
2700 is_fully_numeric(dot1p
) == FALSE
||
2701 is_fully_numeric(dot2p
) == FALSE
) {
2706 disk_tagp
->cidl
.bus
= atoi(p
);
2707 disk_tagp
->cidl
.target_id
= atoi(dot1p
);
2708 disk_tagp
->cidl
.lun
= atoi(dot2p
);
2715 * calc_size(sizep, valp)
2716 * This function calculates the value represented by string sizep.
2717 * The string sizep can be decomposed into three parts: an initial,
2718 * possibly empty, sequence of white-space characters; a subject digital
2719 * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a
2720 * final string of one or more unrecognized characters or white-sapce
2721 * characters, including the terminating null. If unrecognized character
2722 * exists or overflow happens, the conversion must fail and return
2723 * INVALID_ARG. If the conversion is performed successfully, result will
2724 * be saved into valp and function returns SUCCESS. It returns FAILURE
2725 * when memory allocation fails.
2728 calc_size(char *sizep
, uint64_t *valp
)
2736 if (sizep
== NULL
|| valp
== NULL
) {
2737 return (INVALID_ARG
);
2740 if (is_fully_numeric(sizep
) == TRUE
) {
2741 *valp
= atoi(sizep
);
2745 len
= strlen(sizep
);
2747 return (INVALID_ARG
);
2750 t
= (char *)malloc(len
+ 1);
2755 (void) memcpy(t
, sizep
, len
+ 1);
2757 switch (*(t
+ len
- 1)) {
2762 size
= strtoll(t
, &tailp
, 0);
2766 unit
= 1024ull * 1024ull;
2768 size
= strtoll(t
, &tailp
, 0);
2772 unit
= 1024ull * 1024ull * 1024ull;
2774 size
= strtoll(t
, &tailp
, 0);
2778 unit
= 1024ull * 1024ull * 1024ull * 1024ull;
2780 size
= strtoll(t
, &tailp
, 0);
2783 /* The unit must be kilobyte at least. */
2785 return (INVALID_ARG
);
2788 *(t
+ len
- 1) = '\0';
2789 if (is_fully_numeric(t
) != TRUE
) {
2791 return (INVALID_ARG
);
2795 size
= strtoll(t
, &tailp
, 0);
2797 /* Check overflow condition */
2798 if (errno
== ERANGE
|| (size
> (MAX64BIT
/ unit
))) {
2800 return (INVALID_ARG
);
2803 *valp
= size
* unit
;
2809 * is_fully_numeric(str)
2810 * This function checks if the string are legal numeric string. The beginning
2811 * or ending characters can be white spaces.
2812 * Return value is TRUE if the string are legal numeric string, or FALSE
2816 is_fully_numeric(char *strp
)
2830 /* Skip whitespace characters */
2831 for (i
= 0; i
< len
; i
++) {
2832 if (strp
[i
] != ' ') {
2837 /* if strp points all space characters */
2842 /* Check the digitals in string */
2843 for (; i
< len
; i
++) {
2844 if (!isdigit(strp
[i
])) {
2849 /* Check the ending string */
2850 for (; i
< len
; i
++) {
2851 if (strp
[i
] != ' ') {
2863 char ans
[SCHAR_MAX
+ 1];
2865 for (i
= 0; ; i
++) {
2867 if (b
== '\n' || b
== '\0' || b
== EOF
) {
2871 if (i
< SCHAR_MAX
) {
2875 if (i
>= SCHAR_MAX
) {
2880 return (rpmatch(ans
));
2884 * Function: int rpmatch(char *)
2888 * Internationalized get yes / no answer.
2891 * s -> Pointer to answer to compare against.
2894 * TRUE -> Answer was affirmative
2895 * FALSE -> Answer was negative
2904 status
= regexec(&re
, s
, (size_t)0, NULL
, 0);
2912 size_to_string(uint64_t size
, char *string
, int len
)
2916 char unit
[][2] = {" ", "K", "M", "G", "T"};
2918 if (string
== NULL
) {
2921 while (size
> 1023) {
2922 remainder
= size
% 1024;
2932 if (remainder
== 0) {
2933 (void) snprintf(string
, len
, "%llu", size
);
2935 (void) snprintf(string
, len
, "%llu.%1u", size
,
2939 /* make sure there is one byte for unit */
2940 if ((strlen(string
) + 1) >= len
) {
2943 (void) strlcat(string
, unit
[i
], len
);
2949 * Only one raidctl is running at one time.
2952 enter_raidctl_lock(int *fd
)
2957 fd0
= open(RAIDCTL_LOCKF
, O_CREAT
|O_WRONLY
, 0600);
2959 if (errno
== EACCES
) {
2960 (void) fprintf(stderr
,
2961 gettext("raidctl:must be root to run raidctl"
2962 ": %s\n"), strerror(errno
));
2964 (void) fprintf(stderr
,
2965 gettext("raidctl:failed to open lockfile"
2966 " '"RAIDCTL_LOCKF
"': %s\n"), strerror(errno
));
2972 lock
.l_type
= F_WRLCK
;
2973 lock
.l_whence
= SEEK_SET
;
2977 if ((fcntl(fd0
, F_SETLK
, &lock
) == -1) &&
2978 (errno
== EAGAIN
|| errno
== EDEADLK
)) {
2979 if (fcntl(fd0
, F_GETLK
, &lock
) == -1) {
2980 (void) fprintf(stderr
,
2981 gettext("raidctl:enter_filelock error\n"));
2984 (void) fprintf(stderr
, gettext("raidctl:"
2985 "enter_filelock:filelock is owned "
2986 "by 'process %d'\n"), lock
.l_pid
);
2994 exit_raidctl_lock(int fd
)
2998 lock
.l_type
= F_UNLCK
;
2999 lock
.l_whence
= SEEK_SET
;
3002 if (fcntl(fd
, F_SETLK
, &lock
) == -1) {
3003 (void) fprintf(stderr
, gettext("raidctl: failed to"
3004 " exit_filelock: %s\n"),