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 *yesstr
= NULL
;
120 static char *nostr
= NULL
;
121 static char *yesexpr
= NULL
;
123 static char *default_yesexpr
= "^[yY]";
124 static char *default_yesstr
= "yes";
125 static char *default_nostr
= "no";
129 #define SET_DEFAULT_STRS \
134 yesexpr = default_yesexpr; \
135 yesstr = default_yesstr; \
136 nostr = default_nostr;
139 if (yesexpr != default_yesexpr) \
141 if (yesstr != default_yesstr) \
143 if (nostr != default_nostr) \
147 static char *prog_namep
;
151 * Functions declaration
153 static void helpinfo(char *prog_namep
);
154 static int do_create_cidl(char *raid_levelp
, char *capacityp
, char *disk_argp
,
155 char *stripe_sizep
, uint32_t f_flag
, char **argv
, uint32_t optind
);
156 static int do_create_ctd(char *raid_levelp
, char **disks_argpp
,
157 uint32_t disks_num
, uint32_t argindex
, uint32_t f_flag
);
158 static int do_list(char *disk_argp
, char **argv
, uint32_t optind
,
159 uint8_t is_snapshot
);
160 static int do_delete(uint32_t f_flag
, char **argv
, uint32_t optind
);
161 static int do_flash(uint8_t f_flag
, char *filep
, char **ctls_argpp
,
162 uint32_t index
, uint32_t ctl_num
);
163 static int do_set_hsp(char *a_argp
, char *disk_argp
, char **argv
,
165 static int do_set_array_attr(uint32_t f_flag
, char *p_argp
, char **argv
,
167 static int snapshot_raidsystem(uint8_t recursive
, uint8_t indent
,
168 uint8_t is_snapshot
);
169 static int snapshot_ctl(raid_obj_handle_t ctl_handle
, uint8_t recursive
,
170 uint8_t indent
, uint8_t is_snapshot
);
171 static int snapshot_array(raid_obj_handle_t array_handle
,
172 uint8_t indent
, uint8_t is_sub
, uint8_t is_snapshot
);
173 static int snapshot_disk(uint32_t ctl_tag
, raid_obj_handle_t disk_handle
,
174 uint8_t indent
, uint8_t is_snapshot
);
175 static int print_ctl_table(raid_obj_handle_t ctl_handle
);
176 static int print_array_table(raid_obj_handle_t ctl_handle
,
177 raid_obj_handle_t array_handle
);
178 static int print_disk_table(raid_obj_handle_t ctl_handle
,
179 raid_obj_handle_t disk_handle
);
180 static int print_ctl_attr(raidcfg_controller_t
*attrp
);
181 static int print_array_attr(raidcfg_array_t
*attrp
);
182 static int print_arraypart_attr(raidcfg_arraypart_t
*attrp
);
183 static int print_disk_attr(raid_obj_handle_t ctl_handle
,
184 raid_obj_handle_t disk_handle
, raidcfg_disk_t
*attrp
);
185 static void print_indent(uint8_t indent
);
186 static int get_disk_handle_cidl(uint32_t ctl_tag
, char *disks_argp
,
187 int *comps_nump
, raid_obj_handle_t
**handlespp
);
188 static int get_disk_handle_ctd(int disks_num
, char **disks_argpp
,
189 uint32_t *ctl_tagp
, raid_obj_handle_t
*disks_handlep
);
190 static int get_ctl_tag(char *argp
, uint32_t *ctl_tagp
);
191 static int get_array_tag(char *argp
, uint32_t *ctl_tagp
,
192 array_tag_t
*array_tagp
);
193 static int get_disk_tag_ctd(char *argp
, disk_tag_t
*disk_tagp
,
194 uint32_t *controller_id
);
195 static int get_disk_tag_cidl(char *argp
, disk_tag_t
*disk_tagp
);
196 static int calc_size(char *sizep
, uint64_t *valp
);
197 static int is_fully_numeric(char *strp
);
198 static int size_to_string(uint64_t size
, char *string
, int len
);
199 static int enter_raidctl_lock(int *fd
);
200 static void exit_raidctl_lock(int fd
);
203 * Entry function of raidctl command
206 main(int argc
, char **argv
)
208 /* operation index */
209 int8_t findex
= DO_HW_RAID_NOP
;
211 /* argument pointers */
224 uint8_t r_flag
= FALSE
;
225 uint8_t f_flag
= FALSE
;
226 uint8_t action
= FALSE
;
227 uint64_t options
= 0;
229 /* index and temporary variables */
234 /* fd for the filelock */
237 if (enter_raidctl_lock(&fd
) != SUCCESS
) {
241 (void) setlocale(LC_ALL
, "");
242 (void) textdomain(TEXT_DOMAIN
);
244 /* parse command line, and get program name */
245 if ((prog_namep
= strrchr(argv
[0], '/')) == NULL
) {
246 prog_namep
= argv
[0];
251 /* close error option messages from getopt */
254 /* get yes expression according to current locale */
255 yesexpr
= strdup(nl_langinfo(YESEXPR
));
256 yesstr
= strdup(nl_langinfo(YESSTR
));
257 nostr
= strdup(nl_langinfo(NOSTR
));
258 if (yesexpr
== NULL
|| yesstr
== NULL
|| nostr
== NULL
) {
263 * If the was no expression or if there is a compile error
264 * use default yes expression.
266 status
= regcomp(&re
, yesexpr
, REG_EXTENDED
| REG_NOSUB
);
267 if ((*yesexpr
== (char)NULL
) ||
268 (*yesstr
== (char)NULL
) ||
269 (*nostr
== (char)NULL
) ||
272 if (regcomp(&re
, default_yesexpr
,
273 REG_EXTENDED
| REG_NOSUB
) != 0) {
278 while ((c
= getopt(argc
, argv
,
279 "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF
) {
283 if (action
== FALSE
) {
284 findex
= DO_HW_RAID_HELP
;
288 findex
= DO_HW_RAID_NOP
;
292 if (action
== FALSE
) {
293 findex
= DO_HW_RAID_CREATEN
;
298 findex
= DO_HW_RAID_NOP
;
302 if (action
== FALSE
) {
303 findex
= DO_HW_RAID_CREATEO
;
307 findex
= DO_HW_RAID_NOP
;
311 if (action
== FALSE
) {
312 findex
= DO_HW_RAID_DELETE
;
316 findex
= DO_HW_RAID_NOP
;
320 if (action
== FALSE
) {
321 findex
= DO_HW_RAID_LIST
;
325 findex
= DO_HW_RAID_NOP
;
329 if (action
== FALSE
) {
330 findex
= DO_HW_RAID_FLASH
;
335 findex
= DO_HW_RAID_NOP
;
339 if (action
== FALSE
) {
340 findex
= DO_HW_RAID_HSP
;
345 findex
= DO_HW_RAID_NOP
;
349 if (action
== FALSE
) {
350 findex
= DO_HW_RAID_SET_ATTR
;
355 findex
= DO_HW_RAID_NOP
;
380 if (action
== FALSE
) {
381 findex
= DO_HW_RAID_SNAPSHOT
;
385 findex
= DO_HW_RAID_NOP
;
389 (void) fprintf(stderr
,
390 gettext("Invalid argument(s).\n"));
391 exit_raidctl_lock(fd
);
394 return (INVALID_ARG
);
400 case DO_HW_RAID_HELP
:
401 if ((options
& ~(LOWER_H
)) != 0) {
404 helpinfo(prog_namep
);
408 case DO_HW_RAID_CREATEO
:
409 if ((options
& ~(LOWER_F
| LOWER_C
| LOWER_R
)) != 0) {
412 if (r_flag
!= FALSE
&& f_flag
== FALSE
) {
413 ret
= do_create_ctd(r_argp
, argv
, argc
- 4,
415 } else if (r_flag
== FALSE
&& f_flag
== FALSE
) {
416 ret
= do_create_ctd(NULL
, argv
, argc
- 2,
418 } else if (r_flag
!= FALSE
&& f_flag
!= FALSE
) {
419 ret
= do_create_ctd(r_argp
, argv
, argc
- 5,
422 ret
= do_create_ctd(NULL
, argv
, argc
- 3,
427 case DO_HW_RAID_CREATEN
:
428 if ((options
& ~(LOWER_F
| UPPER_C
| LOWER_R
| LOWER_Z
|
432 ret
= do_create_cidl(r_argp
, z_argp
, C_argp
, s_argp
,
433 f_flag
, argv
, optind
);
436 case DO_HW_RAID_DELETE
:
437 if ((options
& ~(LOWER_F
| LOWER_D
)) != 0) {
440 ret
= do_delete(f_flag
, argv
, optind
);
443 case DO_HW_RAID_LIST
:
444 if ((options
& ~(LOWER_L
| LOWER_G
)) != 0) {
447 ret
= do_list(g_argp
, argv
, optind
, FALSE
);
450 case DO_HW_RAID_SNAPSHOT
:
451 if ((options
& ~(UPPER_S
| LOWER_G
)) != 0) {
454 ret
= do_list(g_argp
, argv
, optind
, TRUE
);
457 case DO_HW_RAID_FLASH
:
458 if ((options
& ~(LOWER_F
| UPPER_F
)) != 0) {
461 if (f_flag
== FALSE
) {
462 ret
= do_flash(f_flag
, F_argp
, argv
, optind
,
465 ret
= do_flash(f_flag
, F_argp
, argv
, optind
,
471 if ((options
& ~(LOWER_A
| LOWER_G
)) != 0) {
474 ret
= do_set_hsp(a_argp
, g_argp
, argv
, optind
);
477 case DO_HW_RAID_SET_ATTR
:
478 if ((options
& ~(LOWER_F
| LOWER_P
)) != 0) {
481 ret
= do_set_array_attr(f_flag
, p_argp
, argv
, optind
);
486 ret
= do_list(g_argp
, argv
, optind
, FALSE
);
496 if (ret
== INVALID_ARG
) {
497 (void) fprintf(stderr
,
498 gettext("Invalid argument(s).\n"));
500 exit_raidctl_lock(fd
);
508 * helpinfo(prog_namep)
509 * This function prints help informations for usrs.
512 helpinfo(char *prog_namep
)
516 (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] "
517 "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep
,
520 (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep
);
522 (void) printf(gettext("%s [-f] -F <filename> <controller1> "
523 "[<controller2> ...]\n"), prog_namep
);
525 (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"),
526 prog_namep
, quote
, quote
);
528 (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> "
529 "[<disk3> ...]\n"), prog_namep
);
531 (void) printf(gettext("%s [-l]\n"), prog_namep
);
533 (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep
);
535 (void) printf(gettext("%s -l <volume>\n"), prog_namep
);
537 (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"),
540 (void) printf(gettext("%s -a {set | unset} -g <disk> "
541 "{<volume> | <controller>}\n"), prog_namep
);
543 (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep
);
545 (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep
);
547 (void) printf(gettext("%s -h\n"), prog_namep
);
551 * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep,
552 * f_flag, argv, optind)
553 * This function creates a new RAID volume with specified arguments,
554 * and returns result as SUCCESS, INVALID_ARG or FAILURE.
555 * The "c.id.l" is used to express single physical disk. 'c' expresses
556 * bus number, 'id' expresses target number, and 'l' expresses lun.
557 * The physical disks represented by c.id.l may be invisible to OS, which
558 * means physical disks attached to controllers are not accessible by
559 * OS directly. The disks should be organized as a logical volume, and
560 * the logical volume is exported to OS as a single unit. Some hardware
561 * RAID controllers also support physical disks accessed by OS directly,
562 * for example LSI1068. In this case, it's both OK to express physical
563 * disk by c.id.l format or canonical ctd format.
566 do_create_cidl(char *raid_levelp
, char *capacityp
, char *disks_argp
,
567 char *stripe_sizep
, uint32_t f_flag
, char **argv
, uint32_t optind
)
569 uint32_t ctl_tag
= MAX32BIT
;
570 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
571 uint32_t raid_level
= RAID_LEVEL_1
;
572 uint64_t capacity
= 0;
573 uint64_t stripe_size
= (uint64_t)OBJ_ATTR_NONE
;
574 raid_obj_handle_t
*disk_handlesp
= NULL
;
575 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
576 raidcfg_controller_t ctl_attr
;
580 raidcfg_array_t array_attr
;
582 if (argv
[optind
] == NULL
|| argv
[optind
+ 1] != NULL
) {
583 return (INVALID_ARG
);
586 if (disks_argp
== NULL
) {
587 return (INVALID_ARG
);
590 /* Check controller tag */
591 if (get_ctl_tag(argv
[optind
], &ctl_tag
) != SUCCESS
) {
592 return (INVALID_ARG
);
595 ctl_handle
= raidcfg_get_controller(ctl_tag
);
596 if (ctl_handle
<= 0) {
597 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ctl_handle
));
601 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
602 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
607 if (raid_levelp
!= NULL
) {
608 if (*raid_levelp
== '1' &&
609 (*(raid_levelp
+ 1) == 'E' || *(raid_levelp
+ 1) == 'e')) {
610 raid_level
= RAID_LEVEL_1E
;
612 if (is_fully_numeric(raid_levelp
) == FALSE
) {
613 return (INVALID_ARG
);
616 switch (atoi(raid_levelp
)) {
618 raid_level
= RAID_LEVEL_0
;
621 raid_level
= RAID_LEVEL_1
;
624 raid_level
= RAID_LEVEL_5
;
627 raid_level
= RAID_LEVEL_10
;
630 raid_level
= RAID_LEVEL_50
;
633 return (INVALID_ARG
);
639 * The rang check of capacity and stripe size is performed in library,
640 * and it relates to hardware feature.
643 /* Capacity in bytes. Capacity 0 means max available space. */
644 if (capacityp
!= NULL
) {
645 if (*capacityp
== '-' ||
646 calc_size(capacityp
, &capacity
) != SUCCESS
) {
647 return (INVALID_ARG
);
651 /* Stripe size in bytes */
652 if (stripe_sizep
!= NULL
) {
653 if (calc_size(stripe_sizep
, &stripe_size
) != SUCCESS
||
654 *stripe_sizep
== '-') {
655 return (INVALID_ARG
);
659 /* Open controller before accessing its object */
660 if ((ret
= raidcfg_open_controller(ctl_handle
, NULL
)) < 0) {
661 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
665 /* Get disks' handles */
666 if ((ret
= get_disk_handle_cidl(ctl_tag
, disks_argp
, &comps_num
,
667 &disk_handlesp
)) != SUCCESS
) {
668 (void) raidcfg_close_controller(ctl_handle
, NULL
);
672 if (f_flag
== FALSE
) {
673 (void) fprintf(stdout
, gettext("Creating RAID volume "
674 "will destroy all data on spare space of member disks, "
675 "proceed (%s/%s)? "), yesstr
, nostr
);
677 (void) fprintf(stdout
, gettext("RAID volume "
678 "not created.\n\n"));
679 (void) raidcfg_close_controller(ctl_handle
, NULL
);
686 array_handle
= raidcfg_create_array(comps_num
,
687 disk_handlesp
, raid_level
, capacity
, stripe_size
, NULL
);
689 if (array_handle
<= 0) {
690 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(array_handle
));
692 (void) raidcfg_close_controller(ctl_handle
, NULL
);
696 /* Get attribute of the new created array */
697 if ((ret
= raidcfg_get_attr(array_handle
, &array_attr
)) < 0) {
698 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
700 (void) raidcfg_close_controller(ctl_handle
, NULL
);
704 (void) fprintf(stdout
, gettext("Volume c%ut%llud%llu is created "
705 "successfully!\n"), ctl_tag
, array_attr
.tag
.idl
.target_id
,
706 array_attr
.tag
.idl
.lun
);
708 /* Print attribute of array */
709 (void) print_array_table(ctl_handle
, array_handle
);
711 /* Close controller */
712 (void) raidcfg_close_controller(ctl_handle
, NULL
);
719 * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag)
720 * This function creates array with specified arguments, and return result
721 * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller
722 * to be compatible with old raidctl. The capacity and stripe size can't
723 * be specified for LSI MPT controller, and they use zero and default value.
724 * The "ctd" is the canonical expression of physical disks which are
728 do_create_ctd(char *raid_levelp
, char **disks_argpp
, uint32_t disks_num
,
729 uint32_t argindex
, uint32_t f_flag
)
731 uint32_t ctl_tag
= MAX32BIT
;
732 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
733 uint32_t raid_level
= RAID_LEVEL_1
;
734 uint64_t capacity
= 0;
735 uint32_t stripe_size
= (uint32_t)OBJ_ATTR_NONE
;
736 raid_obj_handle_t
*disk_handlesp
= NULL
;
737 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
738 raidcfg_controller_t ctl_attr
;
741 raidcfg_array_t array_attr
;
744 /* Check disks parameter */
745 if (disks_argpp
== NULL
|| disks_num
< 2) {
746 return (INVALID_ARG
);
749 for (i
= 0, j
= argindex
; i
< disks_num
; i
++, j
++) {
750 if (disks_argpp
[j
] == NULL
) {
751 return (INVALID_ARG
);
756 * We need check if the raid_level string is fully numeric. If user
757 * input string with unsupported letters, such as "s10", atoi() will
758 * return zero because it is an illegal string, but it doesn't mean
761 if (raid_levelp
!= NULL
) {
762 if (*raid_levelp
== '1' &&
763 (*(raid_levelp
+ 1) == 'E' || *(raid_levelp
+ 1) == 'e')) {
764 raid_level
= RAID_LEVEL_1E
;
766 if (is_fully_numeric(raid_levelp
) == FALSE
) {
767 return (INVALID_ARG
);
770 switch (atoi(raid_levelp
)) {
772 raid_level
= RAID_LEVEL_0
;
775 raid_level
= RAID_LEVEL_1
;
778 raid_level
= RAID_LEVEL_5
;
781 return (INVALID_ARG
);
786 /* Get disks tag and controller tag */
787 disk_handlesp
= (raid_obj_handle_t
*)calloc(disks_num
+ 2,
788 sizeof (raid_obj_handle_t
));
789 if (disk_handlesp
== NULL
) {
793 disk_handlesp
[0] = OBJ_SEPARATOR_BEGIN
;
794 disk_handlesp
[disks_num
+ 1] = OBJ_SEPARATOR_END
;
796 if ((ret
= get_disk_handle_ctd(disks_num
, &disks_argpp
[argindex
],
797 &ctl_tag
, &disk_handlesp
[1])) != SUCCESS
) {
802 /* LIB API should check whether all disks here belong to one ctl. */
803 /* get_disk_handle_ctd has opened controller. */
804 ctl_handle
= raidcfg_get_controller(ctl_tag
);
806 if (ctl_handle
<= 0) {
807 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ctl_handle
));
808 (void) raidcfg_close_controller(ctl_handle
, NULL
);
813 /* Check if the controller is host raid type */
814 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
815 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
816 (void) raidcfg_close_controller(ctl_handle
, NULL
);
821 if ((ctl_attr
.capability
& RAID_CAP_DISK_TRANS
) == 0) {
822 /* -c only support host raid controller, return failure here */
823 (void) fprintf(stderr
,
824 gettext("Option -c only supports host raid controller.\n"));
825 (void) raidcfg_close_controller(ctl_handle
, NULL
);
830 if (f_flag
== FALSE
) {
831 (void) fprintf(stdout
, gettext("Creating RAID volume "
832 "will destroy all data on spare space of member disks, "
833 "proceed (%s/%s)? "), yesstr
, nostr
);
835 (void) fprintf(stdout
, gettext("RAID volume "
836 "not created.\n\n"));
838 (void) raidcfg_close_controller(ctl_handle
, NULL
);
844 * For old raidctl, capacity is 0, which means to creates
845 * max possible capacity of array.
848 array_handle
= raidcfg_create_array(disks_num
+ 2,
849 disk_handlesp
, raid_level
, capacity
, stripe_size
, NULL
);
851 if (array_handle
<= 0) {
852 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(array_handle
));
854 (void) raidcfg_close_controller(ctl_handle
, NULL
);
858 /* Get attribute of array */
859 if ((ret
= raidcfg_get_attr(array_handle
, &array_attr
)) < 0) {
860 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
862 (void) raidcfg_close_controller(ctl_handle
, NULL
);
866 /* Close controller */
867 (void) raidcfg_close_controller(ctl_handle
, NULL
);
869 /* Print feedback for user */
870 (void) fprintf(stdout
,
871 gettext("Volume c%ut%llud%llu is created successfully!\n"),
872 ctl_tag
, array_attr
.tag
.idl
.target_id
,
873 array_attr
.tag
.idl
.lun
);
879 * do_list(disk_arg, argv, optind, is_snapshot)
880 * This function lists RAID's system configuration. It supports various RAID
881 * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG.
884 do_list(char *disk_argp
, char **argv
, uint32_t optind
, uint8_t is_snapshot
)
886 uint32_t ctl_tag
= MAX32BIT
;
887 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
888 raid_obj_handle_t disk_handle
= INIT_HANDLE_VALUE
;
889 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
891 array_tag_t array_tag
;
895 /* print RAID system */
896 if (disk_argp
== NULL
) {
897 if (argv
[optind
] == NULL
) {
898 ret
= snapshot_raidsystem(TRUE
, 0, is_snapshot
);
901 if (is_fully_numeric(argv
[optind
]) == TRUE
) {
902 while (argv
[optind
] != NULL
) {
903 if (get_ctl_tag(argv
[optind
], &ctl_tag
)
910 raidcfg_get_controller(ctl_tag
);
911 if (ctl_handle
<= 0) {
912 (void) fprintf(stderr
, "%s\n",
913 raidcfg_errstr(ctl_handle
));
919 raidcfg_open_controller(ctl_handle
,
922 (void) fprintf(stderr
, "%s\n",
923 raidcfg_errstr(ret
));
928 if (is_snapshot
== FALSE
) {
930 print_ctl_table(ctl_handle
);
933 snapshot_ctl(ctl_handle
,
934 FALSE
, 0, is_snapshot
);
936 (void) raidcfg_close_controller(
941 if (get_array_tag(argv
[optind
],
942 &ctl_tag
, &array_tag
) != SUCCESS
) {
943 return (INVALID_ARG
);
945 ctl_handle
= raidcfg_get_controller(ctl_tag
);
946 if (ctl_handle
<= 0) {
947 (void) fprintf(stderr
, "%s\n",
948 raidcfg_errstr(ctl_handle
));
952 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
954 (void) fprintf(stderr
, "%s\n",
955 raidcfg_errstr(ret
));
959 array_handle
= raidcfg_get_array(ctl_handle
,
960 array_tag
.idl
.target_id
, array_tag
.idl
.lun
);
961 if (array_handle
<= 0) {
962 (void) fprintf(stderr
, "%s\n",
963 raidcfg_errstr(array_handle
));
964 (void) raidcfg_close_controller(
968 if (is_snapshot
== FALSE
) {
969 ret
= print_array_table(ctl_handle
,
972 ret
= snapshot_array(array_handle
, 0,
975 (void) raidcfg_close_controller(
980 if (argv
[optind
+ 1] != NULL
) {
981 return (INVALID_ARG
);
984 if (get_ctl_tag(argv
[optind
], &ctl_tag
) != SUCCESS
) {
985 return (INVALID_ARG
);
988 ctl_handle
= raidcfg_get_controller(ctl_tag
);
989 if (ctl_handle
<= 0) {
990 (void) fprintf(stderr
, "%s\n",
991 raidcfg_errstr(ctl_handle
));
995 if (get_disk_tag_cidl(disk_argp
, &disk_tag
) != SUCCESS
) {
996 return (INVALID_ARG
);
999 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1001 (void) fprintf(stderr
, "%s\n",
1002 raidcfg_errstr(ret
));
1006 disk_handle
= raidcfg_get_disk(ctl_handle
, disk_tag
);
1007 if (disk_handle
<= 0) {
1008 (void) fprintf(stderr
, "%s\n",
1009 raidcfg_errstr(disk_handle
));
1010 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1014 if (is_snapshot
== FALSE
) {
1015 ret
= print_disk_table(ctl_handle
, disk_handle
);
1017 ret
= snapshot_disk(ctl_tag
, disk_handle
, 0,
1020 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1026 * do_delete(f_flag, argv, optind)
1027 * This function deletes a specified array, and return result as SUCCESS,
1028 * FAILURE or INVALID_ARG.
1031 do_delete(uint32_t f_flag
, char **argv
, uint32_t optind
)
1035 array_tag_t array_tag
;
1036 raid_obj_handle_t ctl_handle
;
1037 raid_obj_handle_t array_handle
;
1040 array_argp
= argv
[optind
];
1041 if (array_argp
== NULL
|| argv
[optind
+ 1] != NULL
) {
1042 return (INVALID_ARG
);
1045 if (get_array_tag(array_argp
, &ctl_tag
, &array_tag
) != SUCCESS
) {
1046 return (INVALID_ARG
);
1049 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1050 if (ctl_handle
<= 0) {
1051 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ctl_handle
));
1052 return (INVALID_ARG
);
1055 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1057 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1061 array_handle
= raidcfg_get_array(ctl_handle
, array_tag
.idl
.target_id
,
1063 if (array_handle
<= 0) {
1064 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(array_handle
));
1065 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1069 if (f_flag
== FALSE
) {
1070 (void) fprintf(stdout
, gettext("Deleting RAID volume "
1071 "%s will destroy all data it contains, "
1072 "proceed (%s/%s)? "), array_argp
, yesstr
, nostr
);
1074 (void) fprintf(stdout
, gettext("RAID Volume "
1075 "%s not deleted.\n\n"), array_argp
);
1076 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1082 if ((ret
= raidcfg_delete_array(array_handle
, NULL
)) < 0) {
1083 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1084 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1088 (void) fprintf(stdout
, gettext("Volume %s is deleted successfully!\n"),
1090 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1096 * do_flash(f_flag, filep, ctls_argpp, index, ctl_num)
1097 * This function downloads and updates firmware for specified controller, and
1098 * return result as SUCCESS, FAILURE or INVALID_ARG.
1101 do_flash(uint8_t f_flag
, char *filep
, char **ctls_argpp
,
1102 uint32_t index
, uint32_t ctl_num
)
1104 uint32_t ctl_tag
= MAX32BIT
;
1105 char *ctl_argp
= NULL
;
1106 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1111 return (INVALID_ARG
);
1113 for (i
= 0, j
= index
; i
< ctl_num
; i
++, j
++) {
1114 ctl_argp
= ctls_argpp
[j
];
1115 if (get_ctl_tag(ctl_argp
, &ctl_tag
) != SUCCESS
) {
1116 return (INVALID_ARG
);
1119 /* Ask user to confirm operation. */
1120 if (f_flag
== FALSE
) {
1121 (void) fprintf(stdout
, gettext("Update flash image on "
1122 "controller %d (%s/%s)? "), ctl_tag
, yesstr
, nostr
);
1124 (void) fprintf(stdout
,
1125 gettext("Controller %d not "
1126 "flashed.\n\n"), ctl_tag
);
1131 if ((ctl_handle
= raidcfg_get_controller(ctl_tag
)) < 0) {
1132 (void) fprintf(stderr
, "%s\n",
1133 raidcfg_errstr(ctl_handle
));
1137 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1139 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1143 (void) fprintf(stdout
, gettext("Start updating controller "
1144 "c%u firmware....\n"), ctl_tag
);
1146 if ((ret
= raidcfg_update_fw(ctl_handle
, filep
, NULL
)) < 0) {
1147 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1148 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1152 (void) fprintf(stdout
, gettext("Update controller "
1153 "c%u firmware successfully.\n"), ctl_tag
);
1155 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1162 * do_set_hsp(a_argp, disk_argp, argv, optind)
1163 * This function set or unset HSP relationship between disk and controller/
1164 * array, and return result as SUCCESS, FAILURE or INVALID_ARG.
1167 do_set_hsp(char *a_argp
, char *disk_argp
, char **argv
, uint32_t optind
)
1169 uint32_t flag
= MAX32BIT
;
1170 uint32_t ctl_tag
= MAX32BIT
;
1171 array_tag_t array_tag
;
1172 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1173 raid_obj_handle_t disk_handle
= INIT_HANDLE_VALUE
;
1174 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
1175 raidcfg_controller_t ctl_attr
;
1176 disk_tag_t disk_tag
;
1180 raidcfg_hsp_relation_t hsp_relation
;
1182 (void) memset(&hsp_relation
, 0, sizeof (raidcfg_hsp_relation_t
));
1184 if (a_argp
== NULL
) {
1185 return (INVALID_ARG
);
1188 if (strcmp(a_argp
, "set") == 0) {
1190 } else if (strcmp(a_argp
, "unset") == 0) {
1193 return (INVALID_ARG
);
1196 if (disk_argp
== NULL
) {
1197 return (INVALID_ARG
);
1200 if (argv
[optind
] == NULL
|| argv
[optind
+ 1] != NULL
) {
1201 return (INVALID_ARG
);
1202 } else if (is_fully_numeric(argv
[optind
]) == TRUE
) {
1205 if (get_disk_tag_cidl(disk_argp
, &disk_tag
) != SUCCESS
) {
1206 return (INVALID_ARG
);
1209 if (get_ctl_tag(argv
[optind
], &ctl_tag
) != SUCCESS
) {
1210 return (INVALID_ARG
);
1213 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1214 if (ctl_handle
<= 0) {
1215 (void) fprintf(stderr
, "%s\n",
1216 raidcfg_errstr(ctl_handle
));
1220 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1222 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1226 disk_handle
= raidcfg_get_disk(ctl_handle
, disk_tag
);
1227 if (disk_handle
<= 0) {
1228 (void) fprintf(stderr
, "%s\n",
1229 raidcfg_errstr(disk_handle
));
1230 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1236 if (get_array_tag(argv
[optind
], &ctl_tag
, &array_tag
) !=
1238 return (INVALID_ARG
);
1241 /* Open controller */
1242 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1243 if (ctl_handle
<= 0) {
1244 (void) fprintf(stderr
, "%s\n",
1245 raidcfg_errstr(ctl_handle
));
1249 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1251 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1255 /* Get controller's attribute */
1256 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1257 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1258 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1262 if (get_disk_tag_cidl(disk_argp
, &disk_tag
) != SUCCESS
) {
1263 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1264 return (INVALID_ARG
);
1267 /* Get disk handle */
1268 disk_handle
= raidcfg_get_disk(ctl_handle
, disk_tag
);
1269 if (disk_handle
<= 0) {
1270 (void) fprintf(stderr
, "%s\n",
1271 raidcfg_errstr(disk_handle
));
1272 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1276 /* Get array handle */
1277 array_handle
= raidcfg_get_array(ctl_handle
,
1278 array_tag
.idl
.target_id
, array_tag
.idl
.lun
);
1279 if (array_handle
<= 0) {
1280 (void) fprintf(stderr
, "%s\n",
1281 raidcfg_errstr(array_handle
));
1282 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1287 hsp_relation
.disk_handle
= disk_handle
;
1289 /* Set or unset local HSP */
1290 hsp_relation
.array_handle
= array_handle
;
1292 /* Set or unset global HSP */
1293 hsp_relation
.array_handle
= OBJ_ATTR_NONE
;
1296 /* Perform operation of set or unset */
1297 if (flag
== HSP_SET
) {
1298 if ((ret
= raidcfg_set_hsp(&hsp_relation
, NULL
)) < 0) {
1299 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1300 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1305 (void) printf(gettext("Set local HSP between disk %s "
1306 "and RAID volume %s successfully.\n"),
1307 disk_argp
, argv
[optind
]);
1309 (void) printf(gettext("Set global HSP between disk %s "
1310 "and controller %s successfully.\n"),
1311 disk_argp
, argv
[optind
]);
1314 if ((ret
= raidcfg_unset_hsp(&hsp_relation
, NULL
)) < 0) {
1315 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1316 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1321 (void) printf(gettext("Unset local HSP between "
1322 "disk %s and RAID volume %s successfully.\n"),
1323 disk_argp
, argv
[optind
]);
1325 (void) printf(gettext("Unset global HSP between "
1326 "disk %s and controller %s successfully.\n"),
1327 disk_argp
, argv
[optind
]);
1330 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1335 * do_set_array_attr(f_flag, p_argp, argv, optind)
1336 * This function changes array's attribute when array is running.
1337 * The changeable attribute is up to controller's feature.
1338 * The return value can be SUCCESS, FAILURE or INVALID_ARG.
1341 do_set_array_attr(uint32_t f_flag
, char *p_argp
, char **argv
, uint32_t optind
)
1343 uint32_t ctl_tag
= MAX32BIT
;
1344 array_tag_t array_tag
;
1345 uint32_t type
= MAX32BIT
;
1346 uint32_t value
= MAX32BIT
;
1347 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1348 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
1350 char *param
, *op
= "=";
1354 if (argv
[optind
] == NULL
|| argv
[optind
+ 1] != NULL
) {
1355 return (INVALID_ARG
);
1358 if (p_argp
!= NULL
) {
1359 param
= strtok(p_argp
, op
);
1360 if (strcmp(param
, "wp") == 0) {
1361 type
= SET_CACHE_WR_PLY
;
1362 param
= strtok(NULL
, op
);
1363 if (strcmp(param
, "on") == 0) {
1364 value
= CACHE_WR_ON
;
1365 } else if (strcmp(param
, "off") == 0) {
1366 value
= CACHE_WR_OFF
;
1368 return (INVALID_ARG
);
1370 } else if (strcmp(param
, "state") == 0) {
1371 type
= SET_ACTIVATION_PLY
;
1372 param
= strtok(NULL
, op
);
1373 if (strcmp(param
, "activate") == 0) {
1374 value
= ARRAY_ACT_ACTIVATE
;
1376 return (INVALID_ARG
);
1379 return (INVALID_ARG
);
1382 return (INVALID_ARG
);
1385 if (get_array_tag(argv
[optind
], &ctl_tag
, &array_tag
) != SUCCESS
) {
1386 return (INVALID_ARG
);
1389 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1390 if (ctl_handle
<= 0) {
1391 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ctl_handle
));
1395 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1397 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1401 array_handle
= raidcfg_get_array(ctl_handle
, array_tag
.idl
.target_id
,
1403 if (array_handle
<= 0) {
1404 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(array_handle
));
1408 /* Ask user to confirm operation. */
1409 if (f_flag
== FALSE
) {
1410 (void) fprintf(stdout
, gettext("Update attribute of "
1411 "array %s (%s/%s)? "), argv
[optind
], yesstr
, nostr
);
1413 (void) fprintf(stdout
,
1414 gettext("Array %s not "
1415 "changed.\n\n"), argv
[optind
]);
1416 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1421 if ((ret
= raidcfg_set_attr(array_handle
, type
, &value
, NULL
)) < 0) {
1422 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1423 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1427 (void) printf(gettext("Set attribute of RAID volume %s "
1428 "successfully.\n"), argv
[optind
]);
1429 (void) raidcfg_close_controller(ctl_handle
, NULL
);
1435 * snapshot_raidsystem(recursive, indent, is_snapshot)
1436 * This function prints the snapshot of whole RAID's system configuration,
1437 * and return result as SUCCESS or FAILURE.
1440 snapshot_raidsystem(uint8_t recursive
, uint8_t indent
, uint8_t is_snapshot
)
1442 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1445 ctl_handle
= raidcfg_list_head(OBJ_SYSTEM
, OBJ_TYPE_CONTROLLER
);
1446 while (ctl_handle
> 0) {
1447 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
1449 if (snapshot_ctl(ctl_handle
, recursive
, indent
,
1450 is_snapshot
) == FAILURE
) {
1451 (void) raidcfg_close_controller(ctl_handle
,
1455 ctl_handle
= raidcfg_list_next(ctl_handle
);
1461 * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot)
1462 * This function prints snapshot of specified controller's configuration,
1463 * and return result as SUCCESS or FAILURE.
1466 snapshot_ctl(raid_obj_handle_t ctl_handle
, uint8_t recursive
, uint8_t indent
,
1467 uint8_t is_snapshot
)
1469 raid_obj_handle_t array_handle
= INIT_HANDLE_VALUE
;
1470 raid_obj_handle_t disk_handle
= INIT_HANDLE_VALUE
;
1471 raidcfg_controller_t ctl_attr
;
1476 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1477 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1481 ctl_tag
= ctl_attr
.controller_id
;
1482 if (is_snapshot
== FALSE
) {
1483 print_indent(indent
);
1484 (void) fprintf(stdout
, gettext("Controller: %u\n"), ctl_tag
);
1486 (void) snprintf(ctlbuf
, sizeof (ctlbuf
), "%u \"%s\"",
1487 ctl_tag
, ctl_attr
.controller_type
);
1488 (void) fprintf(stdout
, "%s", ctlbuf
);
1490 (void) fprintf(stdout
, "\n");
1493 if (recursive
== TRUE
) {
1494 array_handle
= raidcfg_list_head(ctl_handle
, OBJ_TYPE_ARRAY
);
1495 while (array_handle
> 0) {
1496 if (snapshot_array(array_handle
,
1497 indent
+ 1, FALSE
, is_snapshot
) == FAILURE
) {
1501 array_handle
= raidcfg_list_next(array_handle
);
1504 disk_handle
= raidcfg_list_head(ctl_handle
, OBJ_TYPE_DISK
);
1505 while (disk_handle
> 0) {
1506 if (snapshot_disk(ctl_tag
, disk_handle
,
1507 indent
+ 1, is_snapshot
) == FAILURE
) {
1511 disk_handle
= raidcfg_list_next(disk_handle
);
1519 * snapshot_array(array_handle, indent, is_sub, is_snapshot)
1520 * This function prints snapshot of specified array's configuration,
1521 * and return result as SUCCESS or FAILURE.
1524 snapshot_array(raid_obj_handle_t array_handle
, uint8_t indent
, uint8_t is_sub
,
1525 uint8_t is_snapshot
)
1527 raid_obj_handle_t ctl_handle
;
1528 raid_obj_handle_t subarray_handle
;
1529 raid_obj_handle_t arraypart_handle
;
1530 raid_obj_handle_t task_handle
;
1532 raidcfg_controller_t ctl_attr
;
1533 raidcfg_array_t array_attr
;
1534 raidcfg_arraypart_t arraypart_attr
;
1535 raidcfg_task_t task_attr
;
1537 char arraybuf
[256] = "\0";
1538 char diskbuf
[256] = "\0";
1539 char tempbuf
[256] = "\0";
1545 ctl_handle
= raidcfg_get_container(array_handle
);
1546 ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
);
1548 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1551 ctl_tag
= ctl_attr
.controller_id
;
1553 /* Print array attribute */
1554 if ((ret
= raidcfg_get_attr(array_handle
, &array_attr
)) < 0) {
1555 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1559 if (is_snapshot
== FALSE
) {
1560 print_indent(indent
);
1561 if (is_sub
== FALSE
) {
1562 (void) fprintf(stdout
, gettext("Volume:"
1564 ctl_tag
, array_attr
.tag
.idl
.target_id
,
1565 array_attr
.tag
.idl
.lun
);
1567 (void) fprintf(stdout
, gettext("Sub-Volume\n"));
1570 (void) snprintf(arraybuf
, sizeof (arraybuf
), "c%ut%llud%llu ",
1571 ctl_tag
, array_attr
.tag
.idl
.target_id
,
1572 array_attr
.tag
.idl
.lun
);
1574 /* Check if array is in sync state */
1575 task_handle
= raidcfg_list_head(array_handle
, OBJ_TYPE_TASK
);
1576 if (task_handle
> 0) {
1577 (void) raidcfg_get_attr(task_handle
, &task_attr
);
1578 if (task_attr
.task_func
== TASK_FUNC_BUILD
) {
1579 array_attr
.state
= ARRAY_STATE_SYNC
;
1582 subarray_handle
= raidcfg_list_head(array_handle
,
1584 while (subarray_handle
> 0) {
1585 task_handle
= raidcfg_list_head(subarray_handle
,
1587 if (task_handle
> 0) {
1588 (void) raidcfg_get_attr(task_handle
,
1590 if (task_attr
.task_func
==
1598 raidcfg_list_next(subarray_handle
);
1602 /* Print sub array */
1603 subarray_handle
= raidcfg_list_head(array_handle
,
1605 while (subarray_handle
> 0) {
1606 /* print subarraypart */
1607 arraypart_handle
= raidcfg_list_head(subarray_handle
,
1608 OBJ_TYPE_ARRAY_PART
);
1609 while (arraypart_handle
> 0) {
1610 if ((ret
= raidcfg_get_attr(arraypart_handle
,
1611 &arraypart_attr
)) < 0) {
1612 (void) fprintf(stderr
, "%s\n",
1613 raidcfg_errstr(ret
));
1617 if (arraypart_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1618 (void) snprintf(tempbuf
,
1622 (void) snprintf(tempbuf
,
1625 arraypart_attr
.tag
.cidl
.bus
,
1626 arraypart_attr
.tag
.cidl
.target_id
,
1627 arraypart_attr
.tag
.cidl
.lun
);
1629 (void) strlcat(diskbuf
, tempbuf
,
1631 (void) strcat(diskbuf
, " ");
1634 raidcfg_list_next(arraypart_handle
);
1636 subarray_handle
= raidcfg_list_next(subarray_handle
);
1639 /* Print arraypart */
1640 arraypart_handle
= raidcfg_list_head(array_handle
,
1641 OBJ_TYPE_ARRAY_PART
);
1642 while (arraypart_handle
> 0) {
1643 if ((ret
= raidcfg_get_attr(arraypart_handle
,
1644 &arraypart_attr
)) < 0) {
1645 (void) fprintf(stderr
, "%s\n",
1646 raidcfg_errstr(ret
));
1650 if (arraypart_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1651 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1654 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1656 arraypart_attr
.tag
.cidl
.bus
,
1657 arraypart_attr
.tag
.cidl
.target_id
,
1658 arraypart_attr
.tag
.cidl
.lun
);
1660 (void) strlcat(diskbuf
, tempbuf
, sizeof (diskbuf
));
1661 (void) strcat(diskbuf
, " ");
1663 arraypart_handle
= raidcfg_list_next(arraypart_handle
);
1665 (void) snprintf(tempbuf
, sizeof (tempbuf
), "%u ", disknum
);
1666 (void) strlcat(arraybuf
, tempbuf
, sizeof (arraybuf
));
1667 (void) strlcat(arraybuf
, diskbuf
, sizeof (arraybuf
));
1669 switch (array_attr
.raid_level
) {
1671 (void) sprintf(tempbuf
, "0");
1674 (void) sprintf(tempbuf
, "1");
1677 (void) sprintf(tempbuf
, "1E");
1680 (void) sprintf(tempbuf
, "5");
1683 (void) sprintf(tempbuf
, "10");
1686 (void) sprintf(tempbuf
, "50");
1689 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1693 (void) strlcat(arraybuf
, tempbuf
, sizeof (arraybuf
));
1694 (void) fprintf(stdout
, "%s ", arraybuf
);
1696 switch (array_attr
.state
) {
1697 case ARRAY_STATE_OPTIMAL
:
1698 (void) fprintf(stdout
, gettext("OPTIMAL"));
1700 case ARRAY_STATE_DEGRADED
:
1701 (void) fprintf(stdout
, gettext("DEGRADED"));
1703 case ARRAY_STATE_FAILED
:
1704 (void) fprintf(stdout
, gettext("FAILED"));
1706 case ARRAY_STATE_SYNC
:
1707 (void) fprintf(stdout
, gettext("SYNC"));
1709 case ARRAY_STATE_MISSING
:
1710 (void) fprintf(stdout
, gettext("MISSING"));
1713 (void) fprintf(stdout
, gettext("N/A"));
1716 (void) fprintf(stdout
, "\n");
1723 * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot)
1724 * This function prints snapshot of specified disk's configuration, and return
1725 * result as SUCCESS or FAILURE.
1728 snapshot_disk(uint32_t ctl_tag
, raid_obj_handle_t disk_handle
, uint8_t indent
,
1729 uint8_t is_snapshot
)
1731 raid_obj_handle_t ctl_handle
= INIT_HANDLE_VALUE
;
1732 raid_obj_handle_t hsp_handle
;
1734 raidcfg_controller_t ctl_attr
;
1735 raidcfg_disk_t disk_attr
;
1736 char diskbuf
[256] = "";
1737 char tempbuf
[256] = "";
1741 ctl_handle
= raidcfg_get_controller(ctl_tag
);
1742 ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
);
1744 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1748 /* Print attribute of disk */
1749 if ((ret
= raidcfg_get_attr(disk_handle
, &disk_attr
)) < 0) {
1750 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1754 if (is_snapshot
== FALSE
) {
1755 print_indent(indent
);
1757 hsp_handle
= raidcfg_list_head(disk_handle
, OBJ_TYPE_HSP
);
1759 if (disk_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1760 (void) fprintf(stdout
, gettext("Disk: N/A"));
1762 (void) fprintf(stdout
, gettext("Disk: %llu.%llu.%llu"),
1763 disk_attr
.tag
.cidl
.bus
,
1764 disk_attr
.tag
.cidl
.target_id
,
1765 disk_attr
.tag
.cidl
.lun
);
1767 if (hsp_handle
> 0) {
1768 (void) fprintf(stdout
, "(HSP)");
1770 (void) fprintf(stdout
, "\n");
1772 if (disk_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1773 (void) fprintf(stdout
, gettext("N/A"));
1775 (void) snprintf(diskbuf
, sizeof (diskbuf
),
1777 disk_attr
.tag
.cidl
.bus
,
1778 disk_attr
.tag
.cidl
.target_id
,
1779 disk_attr
.tag
.cidl
.lun
);
1781 hsp_handle
= raidcfg_list_head(disk_handle
, OBJ_TYPE_HSP
);
1782 if (hsp_handle
> 0) {
1783 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1785 } else if (disk_attr
.state
== DISK_STATE_GOOD
) {
1786 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1788 } else if (disk_attr
.state
== DISK_STATE_FAILED
) {
1789 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1792 (void) snprintf(tempbuf
, sizeof (tempbuf
),
1796 (void) strlcat(diskbuf
, tempbuf
, sizeof (diskbuf
));
1797 (void) fprintf(stdout
, "%s\n", diskbuf
);
1804 print_ctl_table(raid_obj_handle_t ctl_handle
)
1806 raidcfg_controller_t ctl_attr
;
1810 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1811 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1815 (void) fprintf(stdout
, gettext("Controller\tType\t\tVersion"));
1816 (void) fprintf(stdout
, "\n");
1817 (void) fprintf(stdout
, "--------------------------------");
1818 (void) fprintf(stdout
, "--------------------------------");
1819 (void) fprintf(stdout
, "\n");
1821 (void) snprintf(controller
, sizeof (controller
), "%u",
1822 ctl_attr
.controller_id
);
1823 (void) printf("c%s\t\t", controller
);
1825 (void) print_ctl_attr(&ctl_attr
);
1826 (void) fprintf(stdout
, "\n");
1832 print_array_table(raid_obj_handle_t ctl_handle
, raid_obj_handle_t array_handle
)
1834 raidcfg_controller_t ctl_attr
;
1835 raidcfg_array_t array_attr
;
1836 raidcfg_array_t subarray_attr
;
1837 raidcfg_arraypart_t arraypart_attr
;
1838 raidcfg_task_t task_attr
;
1840 raid_obj_handle_t subarray_handle
;
1841 raid_obj_handle_t arraypart_handle
;
1842 raid_obj_handle_t task_handle
;
1849 /* Controller attribute */
1850 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
1851 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1855 /* Array attribute */
1856 if ((ret
= raidcfg_get_attr(array_handle
, &array_attr
)) < 0) {
1857 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1862 (void) fprintf(stdout
, gettext("Volume\t\t\tSize\tStripe\tStatus\t"
1864 (void) fprintf(stdout
, "\n");
1865 (void) fprintf(stdout
, gettext("\tSub\t\t\tSize\t\t\tLevel"));
1866 (void) fprintf(stdout
, "\n");
1867 (void) fprintf(stdout
, gettext("\t\tDisk\t\t\t\t\t"));
1868 (void) fprintf(stdout
, "\n");
1869 (void) fprintf(stdout
, "--------------------------------");
1870 (void) fprintf(stdout
, "--------------------------------");
1871 (void) fprintf(stdout
, "\n");
1874 (void) snprintf(array
, sizeof (array
), "c%ut%llud%llu",
1875 ctl_attr
.controller_id
, array_attr
.tag
.idl
.target_id
,
1876 array_attr
.tag
.idl
.lun
);
1877 (void) fprintf(stdout
, "%s\t\t", array
);
1878 if (strlen(array
) < 8)
1879 (void) fprintf(stdout
, "\t");
1882 /* check if array is in sync state */
1883 task_handle
= raidcfg_list_head(array_handle
, OBJ_TYPE_TASK
);
1884 if (task_handle
> 0) {
1885 (void) raidcfg_get_attr(task_handle
, &task_attr
);
1886 if (task_attr
.task_func
== TASK_FUNC_BUILD
) {
1887 array_attr
.state
= ARRAY_STATE_SYNC
;
1890 subarray_handle
= raidcfg_list_head(array_handle
,
1892 while (subarray_handle
> 0) {
1893 task_handle
= raidcfg_list_head(subarray_handle
,
1895 if (task_handle
> 0) {
1896 (void) raidcfg_get_attr(task_handle
,
1898 if (task_attr
.task_func
== TASK_FUNC_BUILD
) {
1899 array_attr
.state
= ARRAY_STATE_SYNC
;
1903 subarray_handle
= raidcfg_list_next(subarray_handle
);
1907 (void) print_array_attr(&array_attr
);
1908 (void) fprintf(stdout
, "\n");
1910 /* Print sub array */
1911 i
= 0; /* Count sub array number */
1912 subarray_handle
= raidcfg_list_head(array_handle
, OBJ_TYPE_ARRAY
);
1913 while (subarray_handle
> 0) {
1914 if ((ret
= raidcfg_get_attr(subarray_handle
,
1915 &subarray_attr
)) < 0) {
1916 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1920 /* Use sub0/sub1 here, not cxtxd0 for subarray */
1921 (void) snprintf(array
, sizeof (array
), "sub%u", i
++);
1922 (void) fprintf(stdout
, "\t%s\t\t", array
);
1924 /* Check if array is in sync */
1925 task_handle
= raidcfg_list_head(subarray_handle
, OBJ_TYPE_TASK
);
1926 if (task_handle
> 0) {
1927 (void) raidcfg_get_attr(task_handle
, &task_attr
);
1928 if (task_attr
.task_func
== TASK_FUNC_BUILD
) {
1929 subarray_attr
.state
= ARRAY_STATE_SYNC
;
1933 (void) print_array_attr(&subarray_attr
);
1934 (void) fprintf(stdout
, "\n");
1936 /* Print subarraypart */
1937 arraypart_handle
= raidcfg_list_head(subarray_handle
,
1938 OBJ_TYPE_ARRAY_PART
);
1939 while (arraypart_handle
> 0) {
1940 if ((ret
= raidcfg_get_attr(arraypart_handle
,
1941 &arraypart_attr
)) < 0) {
1942 (void) fprintf(stderr
, "%s\n",
1943 raidcfg_errstr(ret
));
1947 if (arraypart_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1948 (void) snprintf(arraypart
, sizeof (arraypart
),
1951 (void) snprintf(arraypart
, sizeof (arraypart
),
1953 arraypart_attr
.tag
.cidl
.bus
,
1954 arraypart_attr
.tag
.cidl
.target_id
,
1955 arraypart_attr
.tag
.cidl
.lun
);
1958 (void) fprintf(stdout
, "\t\t%s\t", arraypart
);
1959 (void) print_arraypart_attr(&arraypart_attr
);
1960 (void) fprintf(stdout
, "\n");
1961 arraypart_handle
= raidcfg_list_next(arraypart_handle
);
1963 subarray_handle
= raidcfg_list_next(subarray_handle
);
1966 /* Print arraypart */
1967 arraypart_handle
= raidcfg_list_head(array_handle
,
1968 OBJ_TYPE_ARRAY_PART
);
1969 while (arraypart_handle
> 0) {
1970 if ((ret
= raidcfg_get_attr(arraypart_handle
,
1971 &arraypart_attr
)) < 0) {
1972 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
1976 if (arraypart_attr
.tag
.cidl
.bus
== MAX64BIT
) {
1977 (void) snprintf(arraypart
, sizeof (arraypart
),
1980 (void) snprintf(arraypart
, sizeof (arraypart
),
1982 arraypart_attr
.tag
.cidl
.bus
,
1983 arraypart_attr
.tag
.cidl
.target_id
,
1984 arraypart_attr
.tag
.cidl
.lun
);
1987 (void) fprintf(stdout
, "\t\t%s\t", arraypart
);
1988 (void) print_arraypart_attr(&arraypart_attr
);
1989 (void) fprintf(stdout
, "\n");
1990 arraypart_handle
= raidcfg_list_next(arraypart_handle
);
1997 print_disk_table(raid_obj_handle_t ctl_handle
, raid_obj_handle_t disk_handle
)
1999 raidcfg_controller_t ctl_attr
;
2000 raidcfg_disk_t disk_attr
;
2001 raidcfg_prop_t
*prop_attr
, *prop_attr2
;
2002 raid_obj_handle_t prop_handle
;
2006 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
2007 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
2011 if ((ret
= raidcfg_get_attr(disk_handle
, &disk_attr
)) < 0) {
2012 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
2017 (void) fprintf(stdout
, gettext("Disk\tVendor Product "
2018 "Firmware\tCapacity\tStatus\tHSP"));
2019 (void) fprintf(stdout
, "\n");
2020 (void) fprintf(stdout
, "--------------------------------------");
2021 (void) fprintf(stdout
, "--------------------------------------");
2022 (void) fprintf(stdout
, "\n");
2025 (void) snprintf(disk
, sizeof (disk
), "%llu.%llu.%llu",
2026 disk_attr
.tag
.cidl
.bus
,
2027 disk_attr
.tag
.cidl
.target_id
,
2028 disk_attr
.tag
.cidl
.lun
);
2030 (void) fprintf(stdout
, "%s\t", disk
);
2032 (void) print_disk_attr(ctl_handle
, disk_handle
, &disk_attr
);
2034 prop_attr
= calloc(1, sizeof (raidcfg_prop_t
));
2035 if (prop_attr
== NULL
) {
2036 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ERR_NOMEM
));
2040 prop_handle
= raidcfg_list_head(disk_handle
, OBJ_TYPE_PROP
);
2041 if (prop_handle
== 0) {
2047 prop_attr
->prop_size
= 0;
2048 if ((ret
= raidcfg_get_attr(prop_handle
, prop_attr
)) < 0) {
2050 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
2053 if (prop_attr
->prop_type
== PROP_GUID
)
2055 } while (prop_handle
!= 0);
2057 prop_attr2
= realloc(prop_attr
,
2058 sizeof (raidcfg_prop_t
) + prop_attr
->prop_size
);
2060 if (prop_attr2
== NULL
) {
2061 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ERR_NOMEM
));
2065 if ((ret
= raidcfg_get_attr(prop_handle
, prop_attr2
)) < 0) {
2067 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
2071 (void) fprintf(stdout
, "GUID:%s\n", prop_attr2
->prop
);
2078 * print_ctl_attr(attrp)
2079 * This function prints attribute of specified controller, and return
2080 * result as SUCCESS or FAILURE.
2083 print_ctl_attr(raidcfg_controller_t
*attrp
)
2085 char type
[CONTROLLER_TYPE_LEN
];
2086 char version
[CONTROLLER_FW_LEN
];
2088 if (attrp
== NULL
) {
2092 (void) snprintf(type
, sizeof (type
), "%s", attrp
->controller_type
);
2093 (void) fprintf(stdout
, "%-16s", type
);
2095 (void) snprintf(version
, sizeof (version
), "%s", attrp
->fw_version
);
2096 (void) fprintf(stdout
, "%s", version
);
2102 * print_array_attr(attrp)
2103 * This function prints attribute of specified array, and return
2104 * result as SUCCESS or FAILURE.
2107 print_array_attr(raidcfg_array_t
*attrp
)
2110 char stripe_size
[8];
2113 if (attrp
== NULL
) {
2117 if (attrp
->capacity
!= MAX64BIT
) {
2118 if (size_to_string(attrp
->capacity
, capacity
, 8) != SUCCESS
) {
2121 (void) printf("%s\t", capacity
);
2123 (void) printf(gettext("N/A\t"));
2126 if (attrp
->stripe_size
!= MAX32BIT
) {
2127 (void) snprintf(stripe_size
, sizeof (stripe_size
), "%uK",
2128 attrp
->stripe_size
/ 1024);
2129 (void) printf("%s\t", stripe_size
);
2131 (void) printf(gettext("N/A\t"));
2134 if (attrp
->state
& ARRAY_STATE_INACTIVATE
)
2135 (void) printf("%-8s", gettext("INACTIVE"));
2137 switch (attrp
->state
) {
2138 case ARRAY_STATE_OPTIMAL
:
2139 (void) printf("%-8s", gettext("OPTIMAL"));
2141 case ARRAY_STATE_DEGRADED
:
2142 (void) printf("%-8s", gettext("DEGRADED"));
2144 case ARRAY_STATE_FAILED
:
2145 (void) printf("%-8s", gettext("FAILED"));
2147 case ARRAY_STATE_SYNC
:
2148 (void) printf("%-8s", gettext("SYNC"));
2150 case ARRAY_STATE_MISSING
:
2151 (void) printf("%-8s", gettext("MISSING"));
2154 (void) printf("%-8s", gettext("N/A"));
2160 if (attrp
->write_policy
== CACHE_WR_OFF
) {
2161 (void) printf(gettext("OFF"));
2162 } else if (attrp
->write_policy
== CACHE_WR_ON
) {
2163 (void) printf(gettext("ON"));
2165 (void) printf(gettext("N/A"));
2167 (void) printf("\t");
2169 switch (attrp
->raid_level
) {
2171 (void) sprintf(raid_level
, "RAID0");
2174 (void) sprintf(raid_level
, "RAID1");
2177 (void) sprintf(raid_level
, "RAID1E");
2180 (void) sprintf(raid_level
, "RAID5");
2183 (void) sprintf(raid_level
, "RAID10");
2186 (void) sprintf(raid_level
, "RAID50");
2189 (void) snprintf(raid_level
, sizeof (raid_level
),
2193 (void) printf("%s", raid_level
);
2199 * print_arraypart_attr(attrp)
2200 * This function print attribute of specified arraypart, and return
2201 * result as SUCCESS or FAILURE.
2204 print_arraypart_attr(raidcfg_arraypart_t
*attrp
)
2208 if (attrp
== NULL
) {
2212 if (attrp
->size
!= MAX64BIT
) {
2213 if (size_to_string(attrp
->size
, size
, 8) != SUCCESS
) {
2216 (void) printf("%s\t", size
);
2218 (void) printf(gettext("N/A\t"));
2221 (void) printf("\t");
2223 if (attrp
->state
== DISK_STATE_GOOD
) {
2224 (void) printf(gettext("GOOD"));
2225 } else if (attrp
->state
== DISK_STATE_FAILED
) {
2226 (void) printf(gettext("FAILED"));
2228 (void) printf(gettext("N/A"));
2230 (void) printf("\t");
2236 * print_disk_attr(ctl_handle, disk_handle, attrp)
2237 * This function prints attribute of specified disk, and return
2238 * result as SUCCESS or FAILURE.
2241 print_disk_attr(raid_obj_handle_t ctl_handle
, raid_obj_handle_t disk_handle
,
2242 raidcfg_disk_t
*attrp
)
2244 char vendor
[DISK_VENDER_LEN
+ 1];
2245 char product
[DISK_PRODUCT_LEN
+ 1];
2246 char revision
[DISK_REV_LEN
+ 1];
2250 raid_obj_handle_t hsp_handle
;
2251 raidcfg_hsp_t hsp_attr
;
2252 raidcfg_controller_t ctl_attr
;
2256 if (attrp
== NULL
) {
2260 (void) memccpy(vendor
, attrp
->vendorid
, '\0', DISK_VENDER_LEN
);
2261 vendor
[DISK_VENDER_LEN
] = '\0';
2262 (void) printf("%-9s", vendor
);
2264 (void) memccpy(product
, attrp
->productid
, '\0', DISK_PRODUCT_LEN
);
2265 product
[DISK_PRODUCT_LEN
] = '\0';
2266 (void) printf("%-17s", product
);
2268 (void) memccpy(revision
, attrp
->revision
, '\0', DISK_REV_LEN
);
2269 revision
[DISK_REV_LEN
] = '\0';
2270 (void) printf("%s\t\t", revision
);
2272 if (attrp
->capacity
!= MAX64BIT
) {
2273 if (size_to_string(attrp
->capacity
, capacity
, 16) != SUCCESS
) {
2276 (void) printf("%s\t\t", capacity
);
2278 (void) printf(gettext("N/A"));
2281 if (attrp
->state
== DISK_STATE_GOOD
) {
2282 (void) printf(gettext("GOOD"));
2283 } else if (attrp
->state
== DISK_STATE_FAILED
) {
2284 (void) printf(gettext("FAILED"));
2286 (void) printf(gettext("N/A"));
2288 (void) printf("\t");
2290 /* Controller attribute */
2291 if ((ret
= raidcfg_get_attr(ctl_handle
, &ctl_attr
)) < 0) {
2292 (void) fprintf(stderr
, "%s\n", raidcfg_errstr(ret
));
2296 hsp_handle
= raidcfg_list_head(disk_handle
, OBJ_TYPE_HSP
);
2297 if (hsp_handle
== 0) {
2298 (void) printf(gettext("N/A\n"));
2301 while (hsp_handle
> 0) {
2302 if ((ret
= raidcfg_get_attr(hsp_handle
,
2304 (void) fprintf(stderr
, "%s\n",
2305 raidcfg_errstr(ret
));
2309 if (is_indent
== TRUE
) {
2310 (void) printf("\t\t\t\t\t\t\t");
2315 if (hsp_attr
.type
== HSP_TYPE_LOCAL
) {
2316 (void) snprintf(hsp
, sizeof (hsp
),
2318 ctl_attr
.controller_id
,
2319 hsp_attr
.tag
.idl
.target_id
,
2320 hsp_attr
.tag
.idl
.lun
);
2321 (void) printf("%s\n", hsp
);
2322 } else if (hsp_attr
.type
== HSP_TYPE_GLOBAL
) {
2323 (void) printf(gettext("Global\n"));
2328 hsp_handle
= raidcfg_list_next(hsp_handle
);
2336 * print_indent(indent)
2337 * This function prints specified number of tab characters. It's used to
2341 print_indent(uint8_t indent
)
2344 for (i
= 0; i
< indent
; i
++) {
2345 (void) fprintf(stdout
, "\t");
2350 * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp)
2351 * This function parses the string of disk argument, and gets the disks tag
2352 * and separators from the string. Then it translates the tag to handle, and
2353 * stores handles and separators to new buffer pointed by parameter handlespp.
2354 * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first
2355 * "0" is channel number, and the second "1" is target number, and the third
2356 * "0" is LUN number. The disk tags are separated by comma and parenthesis.
2357 * Function returns SUCCESS or FAILURE.
2360 get_disk_handle_cidl(uint32_t ctl_tag
, char *disks_argp
, int *comps_nump
,
2361 raid_obj_handle_t
**handlespp
)
2366 char *delimit
= " ";
2368 disk_tag_t disk_tag
;
2370 if (disks_argp
== NULL
|| comps_nump
== NULL
) {
2375 len
= strlen(disks_argp
);
2377 if ((disks_str
= (char *)malloc(3 * len
+ 4)) == NULL
) {
2381 /* Insert whitespace between disk tags, '(' , and ')' */
2382 disks_str
[j
++] = '(';
2383 disks_str
[j
++] = ' ';
2385 while (p
[i
] != '\0') {
2386 if (p
[i
] == ')' || p
[i
] == '(') {
2387 disks_str
[j
++] = ' ';
2388 disks_str
[j
++] = p
[i
];
2389 disks_str
[j
++] = ' ';
2391 disks_str
[j
++] = p
[i
];
2394 disks_str
[j
++] = ' ';
2395 disks_str
[j
++] = ')';
2396 disks_str
[j
] = '\0';
2398 len
= strlen(disks_str
) + 1;
2400 if ((t
= (char *)malloc(len
)) == NULL
) {
2403 (void) memcpy(t
, disks_str
, len
);
2404 p
= strtok(t
, delimit
);
2407 p
= strtok(NULL
, delimit
);
2411 *handlespp
= calloc(*comps_nump
, sizeof (raid_obj_handle_t
));
2412 if (*handlespp
== NULL
) {
2416 for (i
= 0; i
< *comps_nump
; i
++)
2417 (*handlespp
)[i
] = INIT_HANDLE_VALUE
;
2420 p
= strtok(disks_str
, delimit
);
2423 (*handlespp
)[i
] = OBJ_SEPARATOR_BEGIN
;
2424 } else if (*p
== ')') {
2425 (*handlespp
)[i
] = OBJ_SEPARATOR_END
;
2427 if (get_disk_tag_cidl(p
, &disk_tag
) != SUCCESS
) {
2430 return (INVALID_ARG
);
2433 raidcfg_get_disk(raidcfg_get_controller(ctl_tag
),
2435 if ((*handlespp
)[i
] <= 0) {
2436 (void) fprintf(stderr
, "%s\n",
2437 raidcfg_errstr((*handlespp
)[i
]));
2443 p
= strtok(NULL
, delimit
);
2452 * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep)
2453 * This function parses string of single disk with "ctd" format, for example,
2454 * c0t0d0, and translates it to controller tag and disk tag.
2455 * Then it calls lib api and get disk handle. The controller tag and disk
2456 * handle are both returned by out parameters.
2457 * The return value is SUCCESS or FAILURE.
2460 get_disk_handle_ctd(int disks_num
, char **disks_argpp
, uint32_t *ctl_tagp
,
2461 raid_obj_handle_t
*disks_handlep
)
2463 raid_obj_handle_t ctl_handle
;
2464 disk_tag_t disk_tag
;
2469 if (disks_handlep
== NULL
) {
2473 for (i
= 0; i
< disks_num
; i
++) {
2474 if (get_disk_tag_ctd(disks_argpp
[i
], &disk_tag
, &ctl_id
) !=
2476 return (INVALID_ARG
);
2482 ctl_handle
= raidcfg_get_controller(*ctl_tagp
);
2483 if (ctl_handle
<= 0) {
2484 (void) fprintf(stderr
, "%s\n",
2485 raidcfg_errstr(ctl_handle
));
2488 ret
= raidcfg_open_controller(ctl_handle
, NULL
);
2490 (void) fprintf(stderr
, "%s\n",
2491 raidcfg_errstr(ret
));
2496 if ((disks_handlep
[i
] =
2497 raidcfg_get_disk(ctl_handle
, disk_tag
)) < 0) {
2498 (void) fprintf(stderr
, "%s\n",
2499 raidcfg_errstr(disks_handlep
[i
]));
2500 (void) raidcfg_close_controller(ctl_handle
, NULL
);
2510 * This function translates controller string to tag. The return value is
2511 * SUCCESS if the string has legal format and is parsed successfully,
2512 * or FAILURE if it fails.
2515 get_ctl_tag(char *argp
, uint32_t *ctl_tagp
)
2517 if (argp
== NULL
|| is_fully_numeric(argp
) == FALSE
||
2521 *ctl_tagp
= (atoi(argp
));
2526 * get_array_tag(argp, ctl_tagp, array_tagp)
2527 * This function parses array string to get array tag and controller tag.
2528 * The return value is SUCCESS if the string has legal format, or
2529 * FAILURE if it fails.
2532 get_array_tag(char *argp
, uint32_t *ctl_tagp
, array_tag_t
*array_tagp
)
2539 uint32_t value_c
= MAX32BIT
;
2540 uint32_t value_t
= MAX32BIT
;
2541 uint32_t value_d
= MAX32BIT
;
2545 if (argp
== NULL
|| (len
= strlen(argp
)) == 0 ||
2546 array_tagp
== NULL
) {
2550 t
= (char *)malloc(len
+ 1);
2555 (void) memcpy(t
, argp
, len
+ 1);
2557 /* Now remmber to release t memory if exception occurs */
2558 if (((dp
= strchr(t
, 'd')) == NULL
) ||
2559 ((tp
= strchr(t
, 't')) == NULL
) ||
2560 ((cp
= strchr(t
, 'c')) == NULL
)) {
2572 if (is_fully_numeric(dp
) == FALSE
||
2573 is_fully_numeric(tp
) == FALSE
||
2574 is_fully_numeric(cp
) == FALSE
) {
2583 array_tagp
->idl
.target_id
= value_t
;
2584 array_tagp
->idl
.lun
= value_d
;
2586 if (ctl_tagp
!= NULL
) {
2587 *ctl_tagp
= value_c
;
2595 * get_disk_tag_ctd(argp, disk_tagp)
2596 * This function parses disk string of ctd format, and translates it to
2597 * disk tag and controller tag. The tags is returned by out parameters.
2598 * The return value is SUCCESS if the string has legal format, or FAILURE
2602 get_disk_tag_ctd(char *argp
, disk_tag_t
*disk_tagp
, uint32_t *ctl_tag
)
2609 uint32_t value_c
= MAX32BIT
;
2610 uint32_t value_t
= MAX32BIT
;
2611 uint32_t value_d
= MAX32BIT
;
2615 if (argp
== NULL
|| (len
= strlen(argp
)) == 0 ||
2616 disk_tagp
== NULL
) {
2620 t
= (char *)malloc(len
+ 1);
2625 (void) memcpy(t
, argp
, len
+ 1);
2627 /* Now remmber to release t memory if exception occurs */
2628 if (((dp
= strchr(t
, 'd')) == NULL
) ||
2629 ((tp
= strchr(t
, 't')) == NULL
) ||
2630 ((cp
= strchr(t
, 'c')) == NULL
)) {
2642 if (is_fully_numeric(dp
) == FALSE
||
2643 is_fully_numeric(tp
) == FALSE
||
2644 is_fully_numeric(cp
) == FALSE
) {
2653 disk_tagp
->cidl
.bus
= 0;
2654 disk_tagp
->cidl
.target_id
= value_t
;
2655 disk_tagp
->cidl
.lun
= value_d
;
2663 * get_disk_tag_cidl(argp, disk_tagp)
2664 * This function parses disk string of cidl format and translates it to tag.
2665 * The return value is disk tag if the string has legal format, or FAILURE
2669 get_disk_tag_cidl(char *argp
, disk_tag_t
*disk_tagp
)
2677 if (argp
== NULL
|| (len
= strlen(argp
)) == 0) {
2681 if (disk_tagp
== NULL
) {
2685 t
= (char *)malloc(len
+ 1);
2690 (void) memcpy(t
, argp
, len
+ 1);
2693 dot2p
= strrchr(p
, '.');
2694 if (dot2p
== NULL
) {
2701 dot1p
= strrchr(p
, '.');
2702 if (dot1p
== NULL
) {
2709 /* Assert only 2 dots in this string */
2710 if (strrchr(p
, '.') != NULL
) {
2718 if (is_fully_numeric(p
) == FALSE
||
2719 is_fully_numeric(dot1p
) == FALSE
||
2720 is_fully_numeric(dot2p
) == FALSE
) {
2725 disk_tagp
->cidl
.bus
= atoi(p
);
2726 disk_tagp
->cidl
.target_id
= atoi(dot1p
);
2727 disk_tagp
->cidl
.lun
= atoi(dot2p
);
2734 * calc_size(sizep, valp)
2735 * This function calculates the value represented by string sizep.
2736 * The string sizep can be decomposed into three parts: an initial,
2737 * possibly empty, sequence of white-space characters; a subject digital
2738 * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a
2739 * final string of one or more unrecognized characters or white-sapce
2740 * characters, including the terminating null. If unrecognized character
2741 * exists or overflow happens, the conversion must fail and return
2742 * INVALID_ARG. If the conversion is performed successfully, result will
2743 * be saved into valp and function returns SUCCESS. It returns FAILURE
2744 * when memory allocation fails.
2747 calc_size(char *sizep
, uint64_t *valp
)
2755 if (sizep
== NULL
|| valp
== NULL
) {
2756 return (INVALID_ARG
);
2759 if (is_fully_numeric(sizep
) == TRUE
) {
2760 *valp
= atoi(sizep
);
2764 len
= strlen(sizep
);
2766 return (INVALID_ARG
);
2769 t
= (char *)malloc(len
+ 1);
2774 (void) memcpy(t
, sizep
, len
+ 1);
2776 switch (*(t
+ len
- 1)) {
2781 size
= strtoll(t
, &tailp
, 0);
2785 unit
= 1024ull * 1024ull;
2787 size
= strtoll(t
, &tailp
, 0);
2791 unit
= 1024ull * 1024ull * 1024ull;
2793 size
= strtoll(t
, &tailp
, 0);
2797 unit
= 1024ull * 1024ull * 1024ull * 1024ull;
2799 size
= strtoll(t
, &tailp
, 0);
2802 /* The unit must be kilobyte at least. */
2804 return (INVALID_ARG
);
2807 *(t
+ len
- 1) = '\0';
2808 if (is_fully_numeric(t
) != TRUE
) {
2810 return (INVALID_ARG
);
2814 size
= strtoll(t
, &tailp
, 0);
2816 /* Check overflow condition */
2817 if (errno
== ERANGE
|| (size
> (MAX64BIT
/ unit
))) {
2819 return (INVALID_ARG
);
2822 *valp
= size
* unit
;
2828 * is_fully_numeric(str)
2829 * This function checks if the string are legal numeric string. The beginning
2830 * or ending characters can be white spaces.
2831 * Return value is TRUE if the string are legal numeric string, or FALSE
2835 is_fully_numeric(char *strp
)
2849 /* Skip whitespace characters */
2850 for (i
= 0; i
< len
; i
++) {
2851 if (strp
[i
] != ' ') {
2856 /* if strp points all space characters */
2861 /* Check the digitals in string */
2862 for (; i
< len
; i
++) {
2863 if (!isdigit(strp
[i
])) {
2868 /* Check the ending string */
2869 for (; i
< len
; i
++) {
2870 if (strp
[i
] != ' ') {
2882 char ans
[SCHAR_MAX
+ 1];
2884 for (i
= 0; ; i
++) {
2886 if (b
== '\n' || b
== '\0' || b
== EOF
) {
2890 if (i
< SCHAR_MAX
) {
2894 if (i
>= SCHAR_MAX
) {
2899 return (rpmatch(ans
));
2903 * Function: int rpmatch(char *)
2907 * Internationalized get yes / no answer.
2910 * s -> Pointer to answer to compare against.
2913 * TRUE -> Answer was affirmative
2914 * FALSE -> Answer was negative
2923 status
= regexec(&re
, s
, (size_t)0, NULL
, 0);
2931 size_to_string(uint64_t size
, char *string
, int len
)
2935 char unit
[][2] = {" ", "K", "M", "G", "T"};
2937 if (string
== NULL
) {
2940 while (size
> 1023) {
2941 remainder
= size
% 1024;
2951 if (remainder
== 0) {
2952 (void) snprintf(string
, len
, "%llu", size
);
2954 (void) snprintf(string
, len
, "%llu.%1u", size
,
2958 /* make sure there is one byte for unit */
2959 if ((strlen(string
) + 1) >= len
) {
2962 (void) strlcat(string
, unit
[i
], len
);
2968 * Only one raidctl is running at one time.
2971 enter_raidctl_lock(int *fd
)
2976 fd0
= open(RAIDCTL_LOCKF
, O_CREAT
|O_WRONLY
, 0600);
2978 if (errno
== EACCES
) {
2979 (void) fprintf(stderr
,
2980 gettext("raidctl:must be root to run raidctl"
2981 ": %s\n"), strerror(errno
));
2983 (void) fprintf(stderr
,
2984 gettext("raidctl:failed to open lockfile"
2985 " '"RAIDCTL_LOCKF
"': %s\n"), strerror(errno
));
2991 lock
.l_type
= F_WRLCK
;
2992 lock
.l_whence
= SEEK_SET
;
2996 if ((fcntl(fd0
, F_SETLK
, &lock
) == -1) &&
2997 (errno
== EAGAIN
|| errno
== EDEADLK
)) {
2998 if (fcntl(fd0
, F_GETLK
, &lock
) == -1) {
2999 (void) fprintf(stderr
,
3000 gettext("raidctl:enter_filelock error\n"));
3003 (void) fprintf(stderr
, gettext("raidctl:"
3004 "enter_filelock:filelock is owned "
3005 "by 'process %d'\n"), lock
.l_pid
);
3013 exit_raidctl_lock(int fd
)
3017 lock
.l_type
= F_UNLCK
;
3018 lock
.l_whence
= SEEK_SET
;
3021 if (fcntl(fd
, F_SETLK
, &lock
) == -1) {
3022 (void) fprintf(stderr
, gettext("raidctl: failed to"
3023 " exit_filelock: %s\n"),