1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 *
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * raidctl.c is the entry file of RAID configuration utility.
26 */
27
28 #include <ctype.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <langinfo.h>
33 #include <regex.h>
34 #include <locale.h>
35 #include <libintl.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <errno.h>
42 #include <libgen.h>
43 #include <raidcfg.h>
44
45
46 #define TRUE 1
47 #define FALSE 0
48
49 #ifndef TEXT_DOMAIN
50 #define TEXT_DOMAIN "SYS_TEST"
51 #endif
52
53 /*
54 * Return value of command
55 */
56 #define SUCCESS 0
57 #define INVALID_ARG 1
58 #define FAILURE 2
59
60 /*
61 * Initial value of variables
62 */
63 #define INIT_HANDLE_VALUE -3
64 #define MAX64BIT 0xffffffffffffffffull
65 #define MAX32BIT 0xfffffffful
66
67 /*
68 * Flag of set or unset HSP
69 */
70 #define HSP_SET 1
71 #define HSP_UNSET 0
72
73 /*
74 * Operate codes of command
75 */
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
86
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)
101
102 /* Add a ARRAY state (temporary) */
103 #define ARRAY_STATE_SYNC 100
104
105 /*
106 * Function and strings to properly localize our prompt.
107 * So for example in German it would ask (ja/nein) or (yes/no) in
108 * english.
109 */
110 #ifndef SCHAR_MAX
111 #define SCHAR_MAX 10
112 #endif
113
114 #define RAIDCTL_LOCKF "/var/run/lockf_raidctl"
115
116 /* Locale setting */
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;
122
123 static char *default_yesexpr = "^[yY]";
124 static char *default_yesstr = "yes";
125 static char *default_nostr = "no";
126
127 static regex_t re;
128
129 #define SET_DEFAULT_STRS \
130 regfree(&re); \
131 free(yesexpr); \
132 free(yesstr); \
133 free(nostr); \
134 yesexpr = default_yesexpr; \
135 yesstr = default_yesstr; \
136 nostr = default_nostr;
137
138 #define FREE_STRS \
139 if (yesexpr != default_yesexpr) \
140 free(yesexpr); \
141 if (yesstr != default_yesstr) \
142 free(yesstr); \
143 if (nostr != default_nostr) \
144 free(nostr);
145
146 /* program name */
147 static char *prog_namep;
148
149
150 /*
151 * Functions declaration
152 */
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,
164 uint32_t optind);
165 static int do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv,
166 uint32_t optind);
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);
201
202 /*
203 * Entry function of raidctl command
204 */
205 int
main(int argc,char ** argv)206 main(int argc, char **argv)
207 {
208 /* operation index */
209 int8_t findex = DO_HW_RAID_NOP;
210
211 /* argument pointers */
212 char *r_argp = NULL;
213 char *z_argp = NULL;
214 char *g_argp = NULL;
215 char *a_argp = NULL;
216 char *s_argp = NULL;
217 char *p_argp = NULL;
218 char *F_argp = NULL;
219 char *C_argp = NULL;
220
221 /*
222 * operation flags.
223 */
224 uint8_t r_flag = FALSE;
225 uint8_t f_flag = FALSE;
226 uint8_t action = FALSE;
227 uint64_t options = 0;
228
229 /* index and temporary variables */
230 int ret;
231 int status;
232 int c;
233
234 /* fd for the filelock */
235 int fd;
236
237 if (enter_raidctl_lock(&fd) != SUCCESS) {
238 return (FAILURE);
239 }
240
241 (void) setlocale(LC_ALL, "");
242 (void) textdomain(TEXT_DOMAIN);
243
244 /* parse command line, and get program name */
245 if ((prog_namep = strrchr(argv[0], '/')) == NULL) {
246 prog_namep = argv[0];
247 } else {
248 prog_namep++;
249 }
250
251 /* close error option messages from getopt */
252 opterr = 0;
253
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) {
259 return (FAILURE);
260 }
261
262 /*
263 * If the was no expression or if there is a compile error
264 * use default yes expression.
265 */
266 status = regcomp(&re, yesexpr, REG_EXTENDED | REG_NOSUB);
267 if ((*yesexpr == '\0') ||
268 (*yesstr == '\0') ||
269 (*nostr == '\0') ||
270 (status != 0)) {
271 SET_DEFAULT_STRS;
272 if (regcomp(&re, default_yesexpr,
273 REG_EXTENDED | REG_NOSUB) != 0) {
274 return (FALSE);
275 }
276 }
277
278 while ((c = getopt(argc, argv,
279 "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) {
280 switch (c) {
281 case 'h':
282 case '?':
283 if (action == FALSE) {
284 findex = DO_HW_RAID_HELP;
285 action = TRUE;
286 options |= LOWER_H;
287 } else {
288 findex = DO_HW_RAID_NOP;
289 }
290 break;
291 case 'C':
292 if (action == FALSE) {
293 findex = DO_HW_RAID_CREATEN;
294 C_argp = optarg;
295 action = TRUE;
296 options |= UPPER_C;
297 } else {
298 findex = DO_HW_RAID_NOP;
299 }
300 break;
301 case 'c':
302 if (action == FALSE) {
303 findex = DO_HW_RAID_CREATEO;
304 action = TRUE;
305 options |= LOWER_C;
306 } else {
307 findex = DO_HW_RAID_NOP;
308 }
309 break;
310 case 'd':
311 if (action == FALSE) {
312 findex = DO_HW_RAID_DELETE;
313 action = TRUE;
314 options |= LOWER_D;
315 } else {
316 findex = DO_HW_RAID_NOP;
317 }
318 break;
319 case 'l':
320 if (action == FALSE) {
321 findex = DO_HW_RAID_LIST;
322 action = TRUE;
323 options |= LOWER_L;
324 } else {
325 findex = DO_HW_RAID_NOP;
326 }
327 break;
328 case 'F':
329 if (action == FALSE) {
330 findex = DO_HW_RAID_FLASH;
331 F_argp = optarg;
332 action = TRUE;
333 options |= UPPER_F;
334 } else {
335 findex = DO_HW_RAID_NOP;
336 }
337 break;
338 case 'a':
339 if (action == FALSE) {
340 findex = DO_HW_RAID_HSP;
341 a_argp = optarg;
342 action = TRUE;
343 options |= LOWER_A;
344 } else {
345 findex = DO_HW_RAID_NOP;
346 }
347 break;
348 case 'p':
349 if (action == FALSE) {
350 findex = DO_HW_RAID_SET_ATTR;
351 p_argp = optarg;
352 action = TRUE;
353 options |= LOWER_P;
354 } else {
355 findex = DO_HW_RAID_NOP;
356 }
357 break;
358 case 'r':
359 r_argp = optarg;
360 r_flag = TRUE;
361 options |= LOWER_R;
362 break;
363 case 'z':
364 z_argp = optarg;
365 options |= LOWER_Z;
366 break;
367 case 'g':
368 g_argp = optarg;
369 options |= LOWER_G;
370 break;
371 case 's':
372 s_argp = optarg;
373 options |= LOWER_S;
374 break;
375 case 'f':
376 f_flag = TRUE;
377 options |= LOWER_F;
378 break;
379 case 'S':
380 if (action == FALSE) {
381 findex = DO_HW_RAID_SNAPSHOT;
382 action = TRUE;
383 options |= UPPER_S;
384 } else {
385 findex = DO_HW_RAID_NOP;
386 }
387 break;
388 default:
389 (void) fprintf(stderr,
390 gettext("Invalid argument(s).\n"));
391 exit_raidctl_lock(fd);
392 FREE_STRS;
393 regfree(&re);
394 return (INVALID_ARG);
395 }
396 }
397
398 /* parse options */
399 switch (findex) {
400 case DO_HW_RAID_HELP:
401 if ((options & ~(LOWER_H)) != 0) {
402 ret = INVALID_ARG;
403 } else {
404 helpinfo(prog_namep);
405 ret = SUCCESS;
406 }
407 break;
408 case DO_HW_RAID_CREATEO:
409 if ((options & ~(LOWER_F | LOWER_C | LOWER_R)) != 0) {
410 ret = INVALID_ARG;
411 } else {
412 if (r_flag != FALSE && f_flag == FALSE) {
413 ret = do_create_ctd(r_argp, argv, argc - 4,
414 optind, f_flag);
415 } else if (r_flag == FALSE && f_flag == FALSE) {
416 ret = do_create_ctd(NULL, argv, argc - 2,
417 optind, f_flag);
418 } else if (r_flag != FALSE && f_flag != FALSE) {
419 ret = do_create_ctd(r_argp, argv, argc - 5,
420 optind, f_flag);
421 } else {
422 ret = do_create_ctd(NULL, argv, argc - 3,
423 optind, f_flag);
424 }
425 }
426 break;
427 case DO_HW_RAID_CREATEN:
428 if ((options & ~(LOWER_F | UPPER_C | LOWER_R | LOWER_Z |
429 LOWER_S)) != 0) {
430 ret = INVALID_ARG;
431 } else {
432 ret = do_create_cidl(r_argp, z_argp, C_argp, s_argp,
433 f_flag, argv, optind);
434 }
435 break;
436 case DO_HW_RAID_DELETE:
437 if ((options & ~(LOWER_F | LOWER_D)) != 0) {
438 ret = INVALID_ARG;
439 } else {
440 ret = do_delete(f_flag, argv, optind);
441 }
442 break;
443 case DO_HW_RAID_LIST:
444 if ((options & ~(LOWER_L | LOWER_G)) != 0) {
445 ret = INVALID_ARG;
446 } else {
447 ret = do_list(g_argp, argv, optind, FALSE);
448 }
449 break;
450 case DO_HW_RAID_SNAPSHOT:
451 if ((options & ~(UPPER_S | LOWER_G)) != 0) {
452 ret = INVALID_ARG;
453 } else {
454 ret = do_list(g_argp, argv, optind, TRUE);
455 }
456 break;
457 case DO_HW_RAID_FLASH:
458 if ((options & ~(LOWER_F | UPPER_F)) != 0) {
459 ret = INVALID_ARG;
460 } else {
461 if (f_flag == FALSE) {
462 ret = do_flash(f_flag, F_argp, argv, optind,
463 argc - 3);
464 } else {
465 ret = do_flash(f_flag, F_argp, argv, optind,
466 argc - 4);
467 }
468 }
469 break;
470 case DO_HW_RAID_HSP:
471 if ((options & ~(LOWER_A | LOWER_G)) != 0) {
472 ret = INVALID_ARG;
473 } else {
474 ret = do_set_hsp(a_argp, g_argp, argv, optind);
475 }
476 break;
477 case DO_HW_RAID_SET_ATTR:
478 if ((options & ~(LOWER_F | LOWER_P)) != 0) {
479 ret = INVALID_ARG;
480 } else {
481 ret = do_set_array_attr(f_flag, p_argp, argv, optind);
482 }
483 break;
484 case DO_HW_RAID_NOP:
485 if (argc == 1) {
486 ret = do_list(g_argp, argv, optind, FALSE);
487 } else {
488 ret = INVALID_ARG;
489 }
490 break;
491 default:
492 ret = INVALID_ARG;
493 break;
494 }
495
496 if (ret == INVALID_ARG) {
497 (void) fprintf(stderr,
498 gettext("Invalid argument(s).\n"));
499 }
500 exit_raidctl_lock(fd);
501
502 FREE_STRS;
503 regfree(&re);
504 return (ret);
505 }
506
507 /*
508 * helpinfo(prog_namep)
509 * This function prints help informations for usrs.
510 */
511 static void
helpinfo(char * prog_namep)512 helpinfo(char *prog_namep)
513 {
514 char quote = '"';
515
516 (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] "
517 "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep,
518 quote, quote);
519
520 (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep);
521
522 (void) printf(gettext("%s [-f] -F <filename> <controller1> "
523 "[<controller2> ...]\n"), prog_namep);
524
525 (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"),
526 prog_namep, quote, quote);
527
528 (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> "
529 "[<disk3> ...]\n"), prog_namep);
530
531 (void) printf(gettext("%s [-l]\n"), prog_namep);
532
533 (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep);
534
535 (void) printf(gettext("%s -l <volume>\n"), prog_namep);
536
537 (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"),
538 prog_namep);
539
540 (void) printf(gettext("%s -a {set | unset} -g <disk> "
541 "{<volume> | <controller>}\n"), prog_namep);
542
543 (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep);
544
545 (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep);
546
547 (void) printf(gettext("%s -h\n"), prog_namep);
548 }
549
550 /*
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.
564 */
565 static int
do_create_cidl(char * raid_levelp,char * capacityp,char * disks_argp,char * stripe_sizep,uint32_t f_flag,char ** argv,uint32_t optind)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)
568 {
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;
577 int comps_num = 0;
578 int ret = 0;
579
580 raidcfg_array_t array_attr;
581
582 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
583 return (INVALID_ARG);
584 }
585
586 if (disks_argp == NULL) {
587 return (INVALID_ARG);
588 }
589
590 /* Check controller tag */
591 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
592 return (INVALID_ARG);
593 }
594
595 ctl_handle = raidcfg_get_controller(ctl_tag);
596 if (ctl_handle <= 0) {
597 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
598 return (FAILURE);
599 }
600
601 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
602 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
603 return (FAILURE);
604 }
605
606 /* Get raid level */
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;
611 } else {
612 if (is_fully_numeric(raid_levelp) == FALSE) {
613 return (INVALID_ARG);
614 }
615
616 switch (atoi(raid_levelp)) {
617 case 0:
618 raid_level = RAID_LEVEL_0;
619 break;
620 case 1:
621 raid_level = RAID_LEVEL_1;
622 break;
623 case 5:
624 raid_level = RAID_LEVEL_5;
625 break;
626 case 10:
627 raid_level = RAID_LEVEL_10;
628 break;
629 case 50:
630 raid_level = RAID_LEVEL_50;
631 break;
632 default:
633 return (INVALID_ARG);
634 }
635 }
636 }
637
638 /*
639 * The rang check of capacity and stripe size is performed in library,
640 * and it relates to hardware feature.
641 */
642
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);
648 }
649 }
650
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);
656 }
657 }
658
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));
662 return (FAILURE);
663 }
664
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);
669 return (ret);
670 }
671
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);
676 if (!yes()) {
677 (void) fprintf(stdout, gettext("RAID volume "
678 "not created.\n\n"));
679 (void) raidcfg_close_controller(ctl_handle, NULL);
680 free(disk_handlesp);
681 return (SUCCESS);
682 }
683 }
684
685 /* Create array */
686 array_handle = raidcfg_create_array(comps_num,
687 disk_handlesp, raid_level, capacity, stripe_size, NULL);
688
689 if (array_handle <= 0) {
690 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
691 free(disk_handlesp);
692 (void) raidcfg_close_controller(ctl_handle, NULL);
693 return (FAILURE);
694 }
695
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));
699 free(disk_handlesp);
700 (void) raidcfg_close_controller(ctl_handle, NULL);
701 return (FAILURE);
702 }
703
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);
707
708 /* Print attribute of array */
709 (void) print_array_table(ctl_handle, array_handle);
710
711 /* Close controller */
712 (void) raidcfg_close_controller(ctl_handle, NULL);
713
714 free(disk_handlesp);
715 return (SUCCESS);
716 }
717
718 /*
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
725 * accessible by OS.
726 */
727 static int
do_create_ctd(char * raid_levelp,char ** disks_argpp,uint32_t disks_num,uint32_t argindex,uint32_t f_flag)728 do_create_ctd(char *raid_levelp, char **disks_argpp, uint32_t disks_num,
729 uint32_t argindex, uint32_t f_flag)
730 {
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;
739 int ret;
740
741 raidcfg_array_t array_attr;
742 int i, j;
743
744 /* Check disks parameter */
745 if (disks_argpp == NULL || disks_num < 2) {
746 return (INVALID_ARG);
747 }
748
749 for (i = 0, j = argindex; i < disks_num; i++, j++) {
750 if (disks_argpp[j] == NULL) {
751 return (INVALID_ARG);
752 }
753 }
754
755 /*
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
759 * RAID_LEVEL_0.
760 */
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;
765 } else {
766 if (is_fully_numeric(raid_levelp) == FALSE) {
767 return (INVALID_ARG);
768 }
769
770 switch (atoi(raid_levelp)) {
771 case 0:
772 raid_level = RAID_LEVEL_0;
773 break;
774 case 1:
775 raid_level = RAID_LEVEL_1;
776 break;
777 case 5:
778 raid_level = RAID_LEVEL_5;
779 break;
780 default:
781 return (INVALID_ARG);
782 }
783 }
784 }
785
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) {
790 return (FAILURE);
791 }
792
793 disk_handlesp[0] = OBJ_SEPARATOR_BEGIN;
794 disk_handlesp[disks_num + 1] = OBJ_SEPARATOR_END;
795
796 if ((ret = get_disk_handle_ctd(disks_num, &disks_argpp[argindex],
797 &ctl_tag, &disk_handlesp[1])) != SUCCESS) {
798 free(disk_handlesp);
799 return (ret);
800 }
801
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);
805
806 if (ctl_handle <= 0) {
807 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
808 (void) raidcfg_close_controller(ctl_handle, NULL);
809 free(disk_handlesp);
810 return (FAILURE);
811 }
812
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);
817 free(disk_handlesp);
818 return (FAILURE);
819 }
820
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);
826 free(disk_handlesp);
827 return (FAILURE);
828 }
829
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);
834 if (!yes()) {
835 (void) fprintf(stdout, gettext("RAID volume "
836 "not created.\n\n"));
837 free(disk_handlesp);
838 (void) raidcfg_close_controller(ctl_handle, NULL);
839 return (SUCCESS);
840 }
841 }
842
843 /*
844 * For old raidctl, capacity is 0, which means to creates
845 * max possible capacity of array.
846 */
847
848 array_handle = raidcfg_create_array(disks_num + 2,
849 disk_handlesp, raid_level, capacity, stripe_size, NULL);
850
851 if (array_handle <= 0) {
852 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
853 free(disk_handlesp);
854 (void) raidcfg_close_controller(ctl_handle, NULL);
855 return (FAILURE);
856 }
857
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));
861 free(disk_handlesp);
862 (void) raidcfg_close_controller(ctl_handle, NULL);
863 return (FAILURE);
864 }
865
866 /* Close controller */
867 (void) raidcfg_close_controller(ctl_handle, NULL);
868
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);
874 free(disk_handlesp);
875 return (SUCCESS);
876 }
877
878 /*
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.
882 */
883 static int
do_list(char * disk_argp,char ** argv,uint32_t optind,uint8_t is_snapshot)884 do_list(char *disk_argp, char **argv, uint32_t optind, uint8_t is_snapshot)
885 {
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;
890 disk_tag_t disk_tag;
891 array_tag_t array_tag;
892
893 int ret;
894
895 /* print RAID system */
896 if (disk_argp == NULL) {
897 if (argv[optind] == NULL) {
898 ret = snapshot_raidsystem(TRUE, 0, is_snapshot);
899 return (ret);
900 } else {
901 if (is_fully_numeric(argv[optind]) == TRUE) {
902 while (argv[optind] != NULL) {
903 if (get_ctl_tag(argv[optind], &ctl_tag)
904 != SUCCESS) {
905 ret = INVALID_ARG;
906 optind++;
907 continue;
908 }
909 ctl_handle =
910 raidcfg_get_controller(ctl_tag);
911 if (ctl_handle <= 0) {
912 (void) fprintf(stderr, "%s\n",
913 raidcfg_errstr(ctl_handle));
914 ret = FAILURE;
915 optind++;
916 continue;
917 }
918 ret =
919 raidcfg_open_controller(ctl_handle,
920 NULL);
921 if (ret < 0) {
922 (void) fprintf(stderr, "%s\n",
923 raidcfg_errstr(ret));
924 ret = FAILURE;
925 optind++;
926 continue;
927 }
928 if (is_snapshot == FALSE) {
929 ret =
930 print_ctl_table(ctl_handle);
931 } else {
932 ret =
933 snapshot_ctl(ctl_handle,
934 FALSE, 0, is_snapshot);
935 }
936 (void) raidcfg_close_controller(
937 ctl_handle, NULL);
938 optind++;
939 }
940 } else {
941 if (get_array_tag(argv[optind],
942 &ctl_tag, &array_tag) != SUCCESS) {
943 return (INVALID_ARG);
944 }
945 ctl_handle = raidcfg_get_controller(ctl_tag);
946 if (ctl_handle <= 0) {
947 (void) fprintf(stderr, "%s\n",
948 raidcfg_errstr(ctl_handle));
949 return (FAILURE);
950 }
951
952 ret = raidcfg_open_controller(ctl_handle, NULL);
953 if (ret < 0) {
954 (void) fprintf(stderr, "%s\n",
955 raidcfg_errstr(ret));
956 return (FAILURE);
957 }
958
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(
965 ctl_handle, NULL);
966 return (FAILURE);
967 }
968 if (is_snapshot == FALSE) {
969 ret = print_array_table(ctl_handle,
970 array_handle);
971 } else {
972 ret = snapshot_array(array_handle, 0,
973 FALSE, is_snapshot);
974 }
975 (void) raidcfg_close_controller(
976 ctl_handle, NULL);
977 }
978 }
979 } else {
980 if (argv[optind + 1] != NULL) {
981 return (INVALID_ARG);
982 }
983
984 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
985 return (INVALID_ARG);
986 }
987
988 ctl_handle = raidcfg_get_controller(ctl_tag);
989 if (ctl_handle <= 0) {
990 (void) fprintf(stderr, "%s\n",
991 raidcfg_errstr(ctl_handle));
992 return (FAILURE);
993 }
994
995 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
996 return (INVALID_ARG);
997 }
998
999 ret = raidcfg_open_controller(ctl_handle, NULL);
1000 if (ret < 0) {
1001 (void) fprintf(stderr, "%s\n",
1002 raidcfg_errstr(ret));
1003 return (FAILURE);
1004 }
1005
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);
1011 return (FAILURE);
1012 }
1013
1014 if (is_snapshot == FALSE) {
1015 ret = print_disk_table(ctl_handle, disk_handle);
1016 } else {
1017 ret = snapshot_disk(ctl_tag, disk_handle, 0,
1018 is_snapshot);
1019 }
1020 (void) raidcfg_close_controller(ctl_handle, NULL);
1021 }
1022 return (ret);
1023 }
1024
1025 /*
1026 * do_delete(f_flag, argv, optind)
1027 * This function deletes a specified array, and return result as SUCCESS,
1028 * FAILURE or INVALID_ARG.
1029 */
1030 static int
do_delete(uint32_t f_flag,char ** argv,uint32_t optind)1031 do_delete(uint32_t f_flag, char **argv, uint32_t optind)
1032 {
1033 uint32_t ctl_tag;
1034 char *array_argp;
1035 array_tag_t array_tag;
1036 raid_obj_handle_t ctl_handle;
1037 raid_obj_handle_t array_handle;
1038 int ret;
1039
1040 array_argp = argv[optind];
1041 if (array_argp == NULL || argv[optind + 1] != NULL) {
1042 return (INVALID_ARG);
1043 }
1044
1045 if (get_array_tag(array_argp, &ctl_tag, &array_tag) != SUCCESS) {
1046 return (INVALID_ARG);
1047 }
1048
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);
1053 }
1054
1055 ret = raidcfg_open_controller(ctl_handle, NULL);
1056 if (ret < 0) {
1057 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1058 return (FAILURE);
1059 }
1060
1061 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
1062 array_tag.idl.lun);
1063 if (array_handle <= 0) {
1064 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
1065 (void) raidcfg_close_controller(ctl_handle, NULL);
1066 return (FAILURE);
1067 }
1068
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);
1073 if (!yes()) {
1074 (void) fprintf(stdout, gettext("RAID Volume "
1075 "%s not deleted.\n\n"), array_argp);
1076 (void) raidcfg_close_controller(ctl_handle, NULL);
1077 return (SUCCESS);
1078 }
1079 }
1080
1081
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);
1085 return (FAILURE);
1086 }
1087
1088 (void) fprintf(stdout, gettext("Volume %s is deleted successfully!\n"),
1089 array_argp);
1090 (void) raidcfg_close_controller(ctl_handle, NULL);
1091
1092 return (SUCCESS);
1093 }
1094
1095 /*
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.
1099 */
1100 static int
do_flash(uint8_t f_flag,char * filep,char ** ctls_argpp,uint32_t index,uint32_t ctl_num)1101 do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
1102 uint32_t index, uint32_t ctl_num)
1103 {
1104 uint32_t ctl_tag = MAX32BIT;
1105 char *ctl_argp = NULL;
1106 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1107 int ret;
1108 int i, j;
1109
1110 if (ctl_num == 0)
1111 return (INVALID_ARG);
1112
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);
1117 }
1118
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);
1123 if (!yes()) {
1124 (void) fprintf(stdout,
1125 gettext("Controller %d not "
1126 "flashed.\n\n"), ctl_tag);
1127 return (SUCCESS);
1128 }
1129 }
1130
1131 if ((ctl_handle = raidcfg_get_controller(ctl_tag)) < 0) {
1132 (void) fprintf(stderr, "%s\n",
1133 raidcfg_errstr(ctl_handle));
1134 return (FAILURE);
1135 }
1136
1137 ret = raidcfg_open_controller(ctl_handle, NULL);
1138 if (ret < 0) {
1139 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1140 return (FAILURE);
1141 }
1142
1143 (void) fprintf(stdout, gettext("Start updating controller "
1144 "c%u firmware....\n"), ctl_tag);
1145
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);
1149 return (FAILURE);
1150 }
1151
1152 (void) fprintf(stdout, gettext("Update controller "
1153 "c%u firmware successfully.\n"), ctl_tag);
1154
1155 (void) raidcfg_close_controller(ctl_handle, NULL);
1156 }
1157
1158 return (SUCCESS);
1159 }
1160
1161 /*
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.
1165 */
1166 static int
do_set_hsp(char * a_argp,char * disk_argp,char ** argv,uint32_t optind)1167 do_set_hsp(char *a_argp, char *disk_argp, char **argv, uint32_t optind)
1168 {
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;
1177
1178 int ret;
1179 int hsp_type;
1180 raidcfg_hsp_relation_t hsp_relation;
1181
1182 (void) memset(&hsp_relation, 0, sizeof (raidcfg_hsp_relation_t));
1183
1184 if (a_argp == NULL) {
1185 return (INVALID_ARG);
1186 }
1187
1188 if (strcmp(a_argp, "set") == 0) {
1189 flag = HSP_SET;
1190 } else if (strcmp(a_argp, "unset") == 0) {
1191 flag = HSP_UNSET;
1192 } else {
1193 return (INVALID_ARG);
1194 }
1195
1196 if (disk_argp == NULL) {
1197 return (INVALID_ARG);
1198 }
1199
1200 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
1201 return (INVALID_ARG);
1202 } else if (is_fully_numeric(argv[optind]) == TRUE) {
1203 /* Global HSP */
1204 hsp_type = 0;
1205 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
1206 return (INVALID_ARG);
1207 }
1208
1209 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
1210 return (INVALID_ARG);
1211 }
1212
1213 ctl_handle = raidcfg_get_controller(ctl_tag);
1214 if (ctl_handle <= 0) {
1215 (void) fprintf(stderr, "%s\n",
1216 raidcfg_errstr(ctl_handle));
1217 return (FAILURE);
1218 }
1219
1220 ret = raidcfg_open_controller(ctl_handle, NULL);
1221 if (ret < 0) {
1222 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1223 return (FAILURE);
1224 }
1225
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);
1231 return (FAILURE);
1232 }
1233 } else {
1234 /* Local HSP */
1235 hsp_type = 1;
1236 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) !=
1237 SUCCESS) {
1238 return (INVALID_ARG);
1239 }
1240
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));
1246 return (FAILURE);
1247 }
1248
1249 ret = raidcfg_open_controller(ctl_handle, NULL);
1250 if (ret < 0) {
1251 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1252 return (FAILURE);
1253 }
1254
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);
1259 return (FAILURE);
1260 }
1261
1262 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
1263 (void) raidcfg_close_controller(ctl_handle, NULL);
1264 return (INVALID_ARG);
1265 }
1266
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);
1273 return (FAILURE);
1274 }
1275
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);
1283 return (FAILURE);
1284 }
1285 }
1286
1287 hsp_relation.disk_handle = disk_handle;
1288 if (hsp_type) {
1289 /* Set or unset local HSP */
1290 hsp_relation.array_handle = array_handle;
1291 } else {
1292 /* Set or unset global HSP */
1293 hsp_relation.array_handle = OBJ_ATTR_NONE;
1294 }
1295
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);
1301 return (FAILURE);
1302 }
1303
1304 if (hsp_type) {
1305 (void) printf(gettext("Set local HSP between disk %s "
1306 "and RAID volume %s successfully.\n"),
1307 disk_argp, argv[optind]);
1308 } else {
1309 (void) printf(gettext("Set global HSP between disk %s "
1310 "and controller %s successfully.\n"),
1311 disk_argp, argv[optind]);
1312 }
1313 } else {
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);
1317 return (FAILURE);
1318 }
1319
1320 if (hsp_type) {
1321 (void) printf(gettext("Unset local HSP between "
1322 "disk %s and RAID volume %s successfully.\n"),
1323 disk_argp, argv[optind]);
1324 } else {
1325 (void) printf(gettext("Unset global HSP between "
1326 "disk %s and controller %s successfully.\n"),
1327 disk_argp, argv[optind]);
1328 }
1329 }
1330 (void) raidcfg_close_controller(ctl_handle, NULL);
1331 return (SUCCESS);
1332 }
1333
1334 /*
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.
1339 */
1340 static int
do_set_array_attr(uint32_t f_flag,char * p_argp,char ** argv,uint32_t optind)1341 do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, uint32_t optind)
1342 {
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;
1349
1350 char *param, *op = "=";
1351
1352 int ret;
1353
1354 if (argv[optind] == NULL || argv[optind + 1] != NULL) {
1355 return (INVALID_ARG);
1356 }
1357
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;
1367 } else {
1368 return (INVALID_ARG);
1369 }
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;
1375 } else {
1376 return (INVALID_ARG);
1377 }
1378 } else {
1379 return (INVALID_ARG);
1380 }
1381 } else {
1382 return (INVALID_ARG);
1383 }
1384
1385 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != SUCCESS) {
1386 return (INVALID_ARG);
1387 }
1388
1389 ctl_handle = raidcfg_get_controller(ctl_tag);
1390 if (ctl_handle <= 0) {
1391 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
1392 return (FAILURE);
1393 }
1394
1395 ret = raidcfg_open_controller(ctl_handle, NULL);
1396 if (ret < 0) {
1397 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1398 return (FAILURE);
1399 }
1400
1401 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
1402 array_tag.idl.lun);
1403 if (array_handle <= 0) {
1404 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
1405 return (FAILURE);
1406 }
1407
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);
1412 if (!yes()) {
1413 (void) fprintf(stdout,
1414 gettext("Array %s not "
1415 "changed.\n\n"), argv[optind]);
1416 (void) raidcfg_close_controller(ctl_handle, NULL);
1417 return (SUCCESS);
1418 }
1419 }
1420
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);
1424 return (FAILURE);
1425 }
1426
1427 (void) printf(gettext("Set attribute of RAID volume %s "
1428 "successfully.\n"), argv[optind]);
1429 (void) raidcfg_close_controller(ctl_handle, NULL);
1430
1431 return (SUCCESS);
1432 }
1433
1434 /*
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.
1438 */
1439 static int
snapshot_raidsystem(uint8_t recursive,uint8_t indent,uint8_t is_snapshot)1440 snapshot_raidsystem(uint8_t recursive, uint8_t indent, uint8_t is_snapshot)
1441 {
1442 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1443 int ret;
1444
1445 ctl_handle = raidcfg_list_head(OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
1446 while (ctl_handle > 0) {
1447 ret = raidcfg_open_controller(ctl_handle, NULL);
1448 if (ret == 0) {
1449 if (snapshot_ctl(ctl_handle, recursive, indent,
1450 is_snapshot) == FAILURE) {
1451 (void) raidcfg_close_controller(ctl_handle,
1452 NULL);
1453 }
1454 }
1455 ctl_handle = raidcfg_list_next(ctl_handle);
1456 }
1457 return (SUCCESS);
1458 }
1459
1460 /*
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.
1464 */
1465 static int
snapshot_ctl(raid_obj_handle_t ctl_handle,uint8_t recursive,uint8_t indent,uint8_t is_snapshot)1466 snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, uint8_t indent,
1467 uint8_t is_snapshot)
1468 {
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;
1472 uint32_t ctl_tag;
1473 char ctlbuf[256];
1474 int ret;
1475
1476 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1477 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1478 return (FAILURE);
1479 }
1480
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);
1485 } else {
1486 (void) snprintf(ctlbuf, sizeof (ctlbuf), "%u \"%s\"",
1487 ctl_tag, ctl_attr.controller_type);
1488 (void) fprintf(stdout, "%s", ctlbuf);
1489
1490 (void) fprintf(stdout, "\n");
1491 }
1492
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) {
1498 return (FAILURE);
1499 }
1500
1501 array_handle = raidcfg_list_next(array_handle);
1502 }
1503
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) {
1508 return (FAILURE);
1509 }
1510
1511 disk_handle = raidcfg_list_next(disk_handle);
1512 }
1513 }
1514 return (SUCCESS);
1515 }
1516
1517
1518 /*
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.
1522 */
1523 static int
snapshot_array(raid_obj_handle_t array_handle,uint8_t indent,uint8_t is_sub,uint8_t is_snapshot)1524 snapshot_array(raid_obj_handle_t array_handle, uint8_t indent, uint8_t is_sub,
1525 uint8_t is_snapshot)
1526 {
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;
1531
1532 raidcfg_controller_t ctl_attr;
1533 raidcfg_array_t array_attr;
1534 raidcfg_arraypart_t arraypart_attr;
1535 raidcfg_task_t task_attr;
1536
1537 char arraybuf[256] = "\0";
1538 char diskbuf[256] = "\0";
1539 char tempbuf[256] = "\0";
1540 int disknum = 0;
1541
1542 uint32_t ctl_tag;
1543 int ret;
1544
1545 ctl_handle = raidcfg_get_container(array_handle);
1546 ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
1547 if (ret < 0) {
1548 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1549 return (FAILURE);
1550 }
1551 ctl_tag = ctl_attr.controller_id;
1552
1553 /* Print array attribute */
1554 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
1555 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1556 return (FAILURE);
1557 }
1558
1559 if (is_snapshot == FALSE) {
1560 print_indent(indent);
1561 if (is_sub == FALSE) {
1562 (void) fprintf(stdout, gettext("Volume:"
1563 "c%ut%llud%llu\n"),
1564 ctl_tag, array_attr.tag.idl.target_id,
1565 array_attr.tag.idl.lun);
1566 } else {
1567 (void) fprintf(stdout, gettext("Sub-Volume\n"));
1568 }
1569 } else {
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);
1573
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;
1580 }
1581 } else {
1582 subarray_handle = raidcfg_list_head(array_handle,
1583 OBJ_TYPE_ARRAY);
1584 while (subarray_handle > 0) {
1585 task_handle = raidcfg_list_head(subarray_handle,
1586 OBJ_TYPE_TASK);
1587 if (task_handle > 0) {
1588 (void) raidcfg_get_attr(task_handle,
1589 &task_attr);
1590 if (task_attr.task_func ==
1591 TASK_FUNC_BUILD) {
1592 array_attr.state =
1593 ARRAY_STATE_SYNC;
1594 }
1595 break;
1596 }
1597 subarray_handle =
1598 raidcfg_list_next(subarray_handle);
1599 }
1600 }
1601
1602 /* Print sub array */
1603 subarray_handle = raidcfg_list_head(array_handle,
1604 OBJ_TYPE_ARRAY);
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));
1614 return (FAILURE);
1615 }
1616
1617 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1618 (void) snprintf(tempbuf,
1619 sizeof (tempbuf),
1620 gettext("N/A"));
1621 } else {
1622 (void) snprintf(tempbuf,
1623 sizeof (tempbuf),
1624 "%llu.%llu.%llu",
1625 arraypart_attr.tag.cidl.bus,
1626 arraypart_attr.tag.cidl.target_id,
1627 arraypart_attr.tag.cidl.lun);
1628 }
1629 (void) strlcat(diskbuf, tempbuf,
1630 sizeof (diskbuf));
1631 (void) strcat(diskbuf, " ");
1632 disknum++;
1633 arraypart_handle =
1634 raidcfg_list_next(arraypart_handle);
1635 }
1636 subarray_handle = raidcfg_list_next(subarray_handle);
1637 }
1638
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));
1647 return (FAILURE);
1648 }
1649
1650 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1651 (void) snprintf(tempbuf, sizeof (tempbuf),
1652 gettext("N/A"));
1653 } else {
1654 (void) snprintf(tempbuf, sizeof (tempbuf),
1655 "%llu.%llu.%llu",
1656 arraypart_attr.tag.cidl.bus,
1657 arraypart_attr.tag.cidl.target_id,
1658 arraypart_attr.tag.cidl.lun);
1659 }
1660 (void) strlcat(diskbuf, tempbuf, sizeof (diskbuf));
1661 (void) strcat(diskbuf, " ");
1662 disknum++;
1663 arraypart_handle = raidcfg_list_next(arraypart_handle);
1664 }
1665 (void) snprintf(tempbuf, sizeof (tempbuf), "%u ", disknum);
1666 (void) strlcat(arraybuf, tempbuf, sizeof (arraybuf));
1667 (void) strlcat(arraybuf, diskbuf, sizeof (arraybuf));
1668
1669 switch (array_attr.raid_level) {
1670 case RAID_LEVEL_0:
1671 (void) sprintf(tempbuf, "0");
1672 break;
1673 case RAID_LEVEL_1:
1674 (void) sprintf(tempbuf, "1");
1675 break;
1676 case RAID_LEVEL_1E:
1677 (void) sprintf(tempbuf, "1E");
1678 break;
1679 case RAID_LEVEL_5:
1680 (void) sprintf(tempbuf, "5");
1681 break;
1682 case RAID_LEVEL_10:
1683 (void) sprintf(tempbuf, "10");
1684 break;
1685 case RAID_LEVEL_50:
1686 (void) sprintf(tempbuf, "50");
1687 break;
1688 default:
1689 (void) snprintf(tempbuf, sizeof (tempbuf),
1690 gettext("N/A"));
1691 break;
1692 }
1693 (void) strlcat(arraybuf, tempbuf, sizeof (arraybuf));
1694 (void) fprintf(stdout, "%s ", arraybuf);
1695
1696 switch (array_attr.state) {
1697 case ARRAY_STATE_OPTIMAL:
1698 (void) fprintf(stdout, gettext("OPTIMAL"));
1699 break;
1700 case ARRAY_STATE_DEGRADED:
1701 (void) fprintf(stdout, gettext("DEGRADED"));
1702 break;
1703 case ARRAY_STATE_FAILED:
1704 (void) fprintf(stdout, gettext("FAILED"));
1705 break;
1706 case ARRAY_STATE_SYNC:
1707 (void) fprintf(stdout, gettext("SYNC"));
1708 break;
1709 case ARRAY_STATE_MISSING:
1710 (void) fprintf(stdout, gettext("MISSING"));
1711 break;
1712 default:
1713 (void) fprintf(stdout, gettext("N/A"));
1714 break;
1715 }
1716 (void) fprintf(stdout, "\n");
1717 }
1718
1719 return (SUCCESS);
1720 }
1721
1722 /*
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.
1726 */
1727 static int
snapshot_disk(uint32_t ctl_tag,raid_obj_handle_t disk_handle,uint8_t indent,uint8_t is_snapshot)1728 snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, uint8_t indent,
1729 uint8_t is_snapshot)
1730 {
1731 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
1732 raid_obj_handle_t hsp_handle;
1733
1734 raidcfg_controller_t ctl_attr;
1735 raidcfg_disk_t disk_attr;
1736 char diskbuf[256] = "";
1737 char tempbuf[256] = "";
1738
1739 int ret;
1740
1741 ctl_handle = raidcfg_get_controller(ctl_tag);
1742 ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
1743 if (ret < 0) {
1744 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1745 return (FAILURE);
1746 }
1747
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));
1751 return (FAILURE);
1752 }
1753
1754 if (is_snapshot == FALSE) {
1755 print_indent(indent);
1756
1757 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
1758
1759 if (disk_attr.tag.cidl.bus == MAX64BIT) {
1760 (void) fprintf(stdout, gettext("Disk: N/A"));
1761 } else {
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);
1766 }
1767 if (hsp_handle > 0) {
1768 (void) fprintf(stdout, "(HSP)");
1769 }
1770 (void) fprintf(stdout, "\n");
1771 } else {
1772 if (disk_attr.tag.cidl.bus == MAX64BIT) {
1773 (void) fprintf(stdout, gettext("N/A"));
1774 } else {
1775 (void) snprintf(diskbuf, sizeof (diskbuf),
1776 "%llu.%llu.%llu ",
1777 disk_attr.tag.cidl.bus,
1778 disk_attr.tag.cidl.target_id,
1779 disk_attr.tag.cidl.lun);
1780 }
1781 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
1782 if (hsp_handle > 0) {
1783 (void) snprintf(tempbuf, sizeof (tempbuf),
1784 gettext("HSP"));
1785 } else if (disk_attr.state == DISK_STATE_GOOD) {
1786 (void) snprintf(tempbuf, sizeof (tempbuf),
1787 gettext("GOOD"));
1788 } else if (disk_attr.state == DISK_STATE_FAILED) {
1789 (void) snprintf(tempbuf, sizeof (tempbuf),
1790 gettext("FAILED"));
1791 } else {
1792 (void) snprintf(tempbuf, sizeof (tempbuf),
1793 gettext("N/A"));
1794 }
1795
1796 (void) strlcat(diskbuf, tempbuf, sizeof (diskbuf));
1797 (void) fprintf(stdout, "%s\n", diskbuf);
1798 }
1799
1800 return (SUCCESS);
1801 }
1802
1803 static int
print_ctl_table(raid_obj_handle_t ctl_handle)1804 print_ctl_table(raid_obj_handle_t ctl_handle)
1805 {
1806 raidcfg_controller_t ctl_attr;
1807 char controller[8];
1808 int ret;
1809
1810 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1811 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1812 return (FAILURE);
1813 }
1814
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");
1820
1821 (void) snprintf(controller, sizeof (controller), "%u",
1822 ctl_attr.controller_id);
1823 (void) printf("c%s\t\t", controller);
1824
1825 (void) print_ctl_attr(&ctl_attr);
1826 (void) fprintf(stdout, "\n");
1827
1828 return (SUCCESS);
1829 }
1830
1831 static int
print_array_table(raid_obj_handle_t ctl_handle,raid_obj_handle_t array_handle)1832 print_array_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t array_handle)
1833 {
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;
1839
1840 raid_obj_handle_t subarray_handle;
1841 raid_obj_handle_t arraypart_handle;
1842 raid_obj_handle_t task_handle;
1843
1844 char array[16];
1845 char arraypart[8];
1846 int ret;
1847 int i;
1848
1849 /* Controller attribute */
1850 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
1851 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1852 return (FAILURE);
1853 }
1854
1855 /* Array attribute */
1856 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
1857 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
1858 return (FAILURE);
1859 }
1860
1861 /* print header */
1862 (void) fprintf(stdout, gettext("Volume\t\t\tSize\tStripe\tStatus\t"
1863 " Cache\tRAID"));
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");
1872
1873 /* print array */
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");
1880
1881
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;
1888 }
1889 } else {
1890 subarray_handle = raidcfg_list_head(array_handle,
1891 OBJ_TYPE_ARRAY);
1892 while (subarray_handle > 0) {
1893 task_handle = raidcfg_list_head(subarray_handle,
1894 OBJ_TYPE_TASK);
1895 if (task_handle > 0) {
1896 (void) raidcfg_get_attr(task_handle,
1897 &task_attr);
1898 if (task_attr.task_func == TASK_FUNC_BUILD) {
1899 array_attr.state = ARRAY_STATE_SYNC;
1900 }
1901 break;
1902 }
1903 subarray_handle = raidcfg_list_next(subarray_handle);
1904 }
1905 }
1906
1907 (void) print_array_attr(&array_attr);
1908 (void) fprintf(stdout, "\n");
1909
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));
1917 return (FAILURE);
1918 }
1919
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);
1923
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;
1930 }
1931 }
1932
1933 (void) print_array_attr(&subarray_attr);
1934 (void) fprintf(stdout, "\n");
1935
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));
1944 return (FAILURE);
1945 }
1946
1947 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1948 (void) snprintf(arraypart, sizeof (arraypart),
1949 gettext("N/A"));
1950 } else {
1951 (void) snprintf(arraypart, sizeof (arraypart),
1952 "%llu.%llu.%llu",
1953 arraypart_attr.tag.cidl.bus,
1954 arraypart_attr.tag.cidl.target_id,
1955 arraypart_attr.tag.cidl.lun);
1956 }
1957
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);
1962 }
1963 subarray_handle = raidcfg_list_next(subarray_handle);
1964 }
1965
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));
1973 return (FAILURE);
1974 }
1975
1976 if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
1977 (void) snprintf(arraypart, sizeof (arraypart),
1978 gettext("N/A"));
1979 } else {
1980 (void) snprintf(arraypart, sizeof (arraypart),
1981 "%llu.%llu.%llu",
1982 arraypart_attr.tag.cidl.bus,
1983 arraypart_attr.tag.cidl.target_id,
1984 arraypart_attr.tag.cidl.lun);
1985 }
1986
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);
1991 }
1992
1993 return (SUCCESS);
1994 }
1995
1996 static int
print_disk_table(raid_obj_handle_t ctl_handle,raid_obj_handle_t disk_handle)1997 print_disk_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle)
1998 {
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;
2003 char disk[8];
2004 int ret;
2005
2006 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
2007 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2008 return (FAILURE);
2009 }
2010
2011 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
2012 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2013 return (FAILURE);
2014 }
2015
2016 /* Print header */
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");
2023
2024
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);
2029
2030 (void) fprintf(stdout, "%s\t", disk);
2031
2032 (void) print_disk_attr(ctl_handle, disk_handle, &disk_attr);
2033
2034 prop_attr = calloc(1, sizeof (raidcfg_prop_t));
2035 if (prop_attr == NULL) {
2036 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM));
2037 return (FAILURE);
2038 }
2039
2040 prop_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_PROP);
2041 if (prop_handle == 0) {
2042 free(prop_attr);
2043 return (SUCCESS);
2044 }
2045
2046 do {
2047 prop_attr->prop_size = 0;
2048 if ((ret = raidcfg_get_attr(prop_handle, prop_attr)) < 0) {
2049 free(prop_attr);
2050 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2051 return (FAILURE);
2052 }
2053 if (prop_attr->prop_type == PROP_GUID)
2054 break;
2055 } while (prop_handle != 0);
2056
2057 prop_attr2 = realloc(prop_attr,
2058 sizeof (raidcfg_prop_t) + prop_attr->prop_size);
2059 free(prop_attr);
2060 if (prop_attr2 == NULL) {
2061 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM));
2062 return (FAILURE);
2063 }
2064
2065 if ((ret = raidcfg_get_attr(prop_handle, prop_attr2)) < 0) {
2066 free(prop_attr2);
2067 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2068 return (FAILURE);
2069 }
2070
2071 (void) fprintf(stdout, "GUID:%s\n", prop_attr2->prop);
2072
2073 free(prop_attr2);
2074 return (SUCCESS);
2075 }
2076
2077 /*
2078 * print_ctl_attr(attrp)
2079 * This function prints attribute of specified controller, and return
2080 * result as SUCCESS or FAILURE.
2081 */
2082 static int
print_ctl_attr(raidcfg_controller_t * attrp)2083 print_ctl_attr(raidcfg_controller_t *attrp)
2084 {
2085 char type[CONTROLLER_TYPE_LEN];
2086 char version[CONTROLLER_FW_LEN];
2087
2088 if (attrp == NULL) {
2089 return (FAILURE);
2090 }
2091
2092 (void) snprintf(type, sizeof (type), "%s", attrp->controller_type);
2093 (void) fprintf(stdout, "%-16s", type);
2094
2095 (void) snprintf(version, sizeof (version), "%s", attrp->fw_version);
2096 (void) fprintf(stdout, "%s", version);
2097
2098 return (SUCCESS);
2099 }
2100
2101 /*
2102 * print_array_attr(attrp)
2103 * This function prints attribute of specified array, and return
2104 * result as SUCCESS or FAILURE.
2105 */
2106 static int
print_array_attr(raidcfg_array_t * attrp)2107 print_array_attr(raidcfg_array_t *attrp)
2108 {
2109 char capacity[8];
2110 char stripe_size[8];
2111 char raid_level[8];
2112
2113 if (attrp == NULL) {
2114 return (FAILURE);
2115 }
2116
2117 if (attrp->capacity != MAX64BIT) {
2118 if (size_to_string(attrp->capacity, capacity, 8) != SUCCESS) {
2119 return (FAILURE);
2120 }
2121 (void) printf("%s\t", capacity);
2122 } else {
2123 (void) printf(gettext("N/A\t"));
2124 }
2125
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);
2130 } else {
2131 (void) printf(gettext("N/A\t"));
2132 }
2133
2134 if (attrp->state & ARRAY_STATE_INACTIVATE)
2135 (void) printf("%-8s", gettext("INACTIVE"));
2136 else {
2137 switch (attrp->state) {
2138 case ARRAY_STATE_OPTIMAL:
2139 (void) printf("%-8s", gettext("OPTIMAL"));
2140 break;
2141 case ARRAY_STATE_DEGRADED:
2142 (void) printf("%-8s", gettext("DEGRADED"));
2143 break;
2144 case ARRAY_STATE_FAILED:
2145 (void) printf("%-8s", gettext("FAILED"));
2146 break;
2147 case ARRAY_STATE_SYNC:
2148 (void) printf("%-8s", gettext("SYNC"));
2149 break;
2150 case ARRAY_STATE_MISSING:
2151 (void) printf("%-8s", gettext("MISSING"));
2152 break;
2153 default:
2154 (void) printf("%-8s", gettext("N/A"));
2155 break;
2156 }
2157 }
2158 (void) printf(" ");
2159
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"));
2164 } else {
2165 (void) printf(gettext("N/A"));
2166 }
2167 (void) printf("\t");
2168
2169 switch (attrp->raid_level) {
2170 case RAID_LEVEL_0:
2171 (void) sprintf(raid_level, "RAID0");
2172 break;
2173 case RAID_LEVEL_1:
2174 (void) sprintf(raid_level, "RAID1");
2175 break;
2176 case RAID_LEVEL_1E:
2177 (void) sprintf(raid_level, "RAID1E");
2178 break;
2179 case RAID_LEVEL_5:
2180 (void) sprintf(raid_level, "RAID5");
2181 break;
2182 case RAID_LEVEL_10:
2183 (void) sprintf(raid_level, "RAID10");
2184 break;
2185 case RAID_LEVEL_50:
2186 (void) sprintf(raid_level, "RAID50");
2187 break;
2188 default:
2189 (void) snprintf(raid_level, sizeof (raid_level),
2190 gettext("N/A"));
2191 break;
2192 }
2193 (void) printf("%s", raid_level);
2194
2195 return (SUCCESS);
2196 }
2197
2198 /*
2199 * print_arraypart_attr(attrp)
2200 * This function print attribute of specified arraypart, and return
2201 * result as SUCCESS or FAILURE.
2202 */
2203 static int
print_arraypart_attr(raidcfg_arraypart_t * attrp)2204 print_arraypart_attr(raidcfg_arraypart_t *attrp)
2205 {
2206 char size[8];
2207
2208 if (attrp == NULL) {
2209 return (FAILURE);
2210 }
2211
2212 if (attrp->size != MAX64BIT) {
2213 if (size_to_string(attrp->size, size, 8) != SUCCESS) {
2214 return (FAILURE);
2215 }
2216 (void) printf("%s\t", size);
2217 } else {
2218 (void) printf(gettext("N/A\t"));
2219 }
2220
2221 (void) printf("\t");
2222
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"));
2227 } else {
2228 (void) printf(gettext("N/A"));
2229 }
2230 (void) printf("\t");
2231
2232 return (SUCCESS);
2233 }
2234
2235 /*
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.
2239 */
2240 static int
print_disk_attr(raid_obj_handle_t ctl_handle,raid_obj_handle_t disk_handle,raidcfg_disk_t * attrp)2241 print_disk_attr(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle,
2242 raidcfg_disk_t *attrp)
2243 {
2244 char vendor[DISK_VENDER_LEN + 1];
2245 char product[DISK_PRODUCT_LEN + 1];
2246 char revision[DISK_REV_LEN + 1];
2247 char capacity[16];
2248 char hsp[16];
2249
2250 raid_obj_handle_t hsp_handle;
2251 raidcfg_hsp_t hsp_attr;
2252 raidcfg_controller_t ctl_attr;
2253 int ret;
2254 char is_indent;
2255
2256 if (attrp == NULL) {
2257 return (FAILURE);
2258 }
2259
2260 (void) memccpy(vendor, attrp->vendorid, '\0', DISK_VENDER_LEN);
2261 vendor[DISK_VENDER_LEN] = '\0';
2262 (void) printf("%-9s", vendor);
2263
2264 (void) memccpy(product, attrp->productid, '\0', DISK_PRODUCT_LEN);
2265 product[DISK_PRODUCT_LEN] = '\0';
2266 (void) printf("%-17s", product);
2267
2268 (void) memccpy(revision, attrp->revision, '\0', DISK_REV_LEN);
2269 revision[DISK_REV_LEN] = '\0';
2270 (void) printf("%s\t\t", revision);
2271
2272 if (attrp->capacity != MAX64BIT) {
2273 if (size_to_string(attrp->capacity, capacity, 16) != SUCCESS) {
2274 return (FAILURE);
2275 }
2276 (void) printf("%s\t\t", capacity);
2277 } else {
2278 (void) printf(gettext("N/A"));
2279 }
2280
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"));
2285 } else {
2286 (void) printf(gettext("N/A"));
2287 }
2288 (void) printf("\t");
2289
2290 /* Controller attribute */
2291 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
2292 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
2293 return (FAILURE);
2294 }
2295
2296 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
2297 if (hsp_handle == 0) {
2298 (void) printf(gettext("N/A\n"));
2299 } else {
2300 is_indent = FALSE;
2301 while (hsp_handle > 0) {
2302 if ((ret = raidcfg_get_attr(hsp_handle,
2303 &hsp_attr)) < 0) {
2304 (void) fprintf(stderr, "%s\n",
2305 raidcfg_errstr(ret));
2306 return (FAILURE);
2307 }
2308
2309 if (is_indent == TRUE) {
2310 (void) printf("\t\t\t\t\t\t\t");
2311 } else {
2312 is_indent = TRUE;
2313 }
2314
2315 if (hsp_attr.type == HSP_TYPE_LOCAL) {
2316 (void) snprintf(hsp, sizeof (hsp),
2317 "c%ut%llud%llu",
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"));
2324 } else {
2325 return (FAILURE);
2326 }
2327
2328 hsp_handle = raidcfg_list_next(hsp_handle);
2329 }
2330 }
2331 return (SUCCESS);
2332 }
2333
2334
2335 /*
2336 * print_indent(indent)
2337 * This function prints specified number of tab characters. It's used to
2338 * format layout.
2339 */
2340 static void
print_indent(uint8_t indent)2341 print_indent(uint8_t indent)
2342 {
2343 uint32_t i;
2344 for (i = 0; i < indent; i++) {
2345 (void) fprintf(stdout, "\t");
2346 }
2347 }
2348
2349 /*
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.
2358 */
2359 static int
get_disk_handle_cidl(uint32_t ctl_tag,char * disks_argp,int * comps_nump,raid_obj_handle_t ** handlespp)2360 get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, int *comps_nump,
2361 raid_obj_handle_t **handlespp)
2362 {
2363 int len = 0;
2364 int i = 0, j = 0;
2365 char *p, *t;
2366 char *delimit = " ";
2367 char *disks_str;
2368 disk_tag_t disk_tag;
2369
2370 if (disks_argp == NULL || comps_nump == NULL) {
2371 return (FAILURE);
2372 }
2373
2374 p = disks_argp;
2375 len = strlen(disks_argp);
2376
2377 if ((disks_str = (char *)malloc(3 * len + 4)) == NULL) {
2378 return (FAILURE);
2379 }
2380
2381 /* Insert whitespace between disk tags, '(' , and ')' */
2382 disks_str[j ++] = '(';
2383 disks_str[j ++] = ' ';
2384
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 ++] = ' ';
2390 } else
2391 disks_str[j ++] = p[i];
2392 i ++;
2393 }
2394 disks_str[j ++] = ' ';
2395 disks_str[j ++] = ')';
2396 disks_str[j] = '\0';
2397
2398 len = strlen(disks_str) + 1;
2399
2400 if ((t = (char *)malloc(len)) == NULL) {
2401 return (FAILURE);
2402 }
2403 (void) memcpy(t, disks_str, len);
2404 p = strtok(t, delimit);
2405 while (p != NULL) {
2406 (*comps_nump)++;
2407 p = strtok(NULL, delimit);
2408 }
2409 free(t);
2410
2411 *handlespp = calloc(*comps_nump, sizeof (raid_obj_handle_t));
2412 if (*handlespp == NULL) {
2413 return (FAILURE);
2414 }
2415
2416 for (i = 0; i < *comps_nump; i++)
2417 (*handlespp)[i] = INIT_HANDLE_VALUE;
2418
2419 i = 0;
2420 p = strtok(disks_str, delimit);
2421 while (p != NULL) {
2422 if (*p == '(') {
2423 (*handlespp)[i] = OBJ_SEPARATOR_BEGIN;
2424 } else if (*p == ')') {
2425 (*handlespp)[i] = OBJ_SEPARATOR_END;
2426 } else {
2427 if (get_disk_tag_cidl(p, &disk_tag) != SUCCESS) {
2428 free(*handlespp);
2429 free(disks_str);
2430 return (INVALID_ARG);
2431 }
2432 (*handlespp)[i] =
2433 raidcfg_get_disk(raidcfg_get_controller(ctl_tag),
2434 disk_tag);
2435 if ((*handlespp)[i] <= 0) {
2436 (void) fprintf(stderr, "%s\n",
2437 raidcfg_errstr((*handlespp)[i]));
2438 free(*handlespp);
2439 free(disks_str);
2440 return (FAILURE);
2441 }
2442 }
2443 p = strtok(NULL, delimit);
2444 i++;
2445 }
2446
2447 free(disks_str);
2448 return (SUCCESS);
2449 }
2450
2451 /*
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.
2458 */
2459 static int
get_disk_handle_ctd(int disks_num,char ** disks_argpp,uint32_t * ctl_tagp,raid_obj_handle_t * disks_handlep)2460 get_disk_handle_ctd(int disks_num, char **disks_argpp, uint32_t *ctl_tagp,
2461 raid_obj_handle_t *disks_handlep)
2462 {
2463 raid_obj_handle_t ctl_handle;
2464 disk_tag_t disk_tag;
2465 uint32_t ctl_id;
2466 int i;
2467 int ret;
2468
2469 if (disks_handlep == NULL) {
2470 return (FAILURE);
2471 }
2472
2473 for (i = 0; i < disks_num; i++) {
2474 if (get_disk_tag_ctd(disks_argpp[i], &disk_tag, &ctl_id) !=
2475 SUCCESS) {
2476 return (INVALID_ARG);
2477 }
2478
2479 *ctl_tagp = ctl_id;
2480
2481 if (i == 0) {
2482 ctl_handle = raidcfg_get_controller(*ctl_tagp);
2483 if (ctl_handle <= 0) {
2484 (void) fprintf(stderr, "%s\n",
2485 raidcfg_errstr(ctl_handle));
2486 return (FAILURE);
2487 }
2488 ret = raidcfg_open_controller(ctl_handle, NULL);
2489 if (ret < 0) {
2490 (void) fprintf(stderr, "%s\n",
2491 raidcfg_errstr(ret));
2492 return (FAILURE);
2493 }
2494 }
2495
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);
2501 return (FAILURE);
2502 }
2503 }
2504
2505 return (SUCCESS);
2506 }
2507
2508 /*
2509 * get_ctl_tag(argp)
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.
2513 */
2514 static int
get_ctl_tag(char * argp,uint32_t * ctl_tagp)2515 get_ctl_tag(char *argp, uint32_t *ctl_tagp)
2516 {
2517 if (argp == NULL || is_fully_numeric(argp) == FALSE ||
2518 ctl_tagp == NULL) {
2519 return (FAILURE);
2520 }
2521 *ctl_tagp = (atoi(argp));
2522 return (SUCCESS);
2523 }
2524
2525 /*
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.
2530 */
2531 static int
get_array_tag(char * argp,uint32_t * ctl_tagp,array_tag_t * array_tagp)2532 get_array_tag(char *argp, uint32_t *ctl_tagp, array_tag_t *array_tagp)
2533 {
2534 char *t = NULL;
2535 char *cp = NULL;
2536 char *tp = NULL;
2537 char *dp = NULL;
2538
2539 uint32_t value_c = MAX32BIT;
2540 uint32_t value_t = MAX32BIT;
2541 uint32_t value_d = MAX32BIT;
2542
2543 int len = 0;
2544
2545 if (argp == NULL || (len = strlen(argp)) == 0 ||
2546 array_tagp == NULL) {
2547 return (FAILURE);
2548 }
2549
2550 t = (char *)malloc(len + 1);
2551 if (t == NULL) {
2552 return (FAILURE);
2553 }
2554
2555 (void) memcpy(t, argp, len + 1);
2556
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)) {
2561 free(t);
2562 return (FAILURE);
2563 }
2564 cp = t;
2565
2566 *dp = '\0';
2567 dp++;
2568 *tp = '\0';
2569 tp++;
2570 cp++;
2571
2572 if (is_fully_numeric(dp) == FALSE ||
2573 is_fully_numeric(tp) == FALSE ||
2574 is_fully_numeric(cp) == FALSE) {
2575 free(t);
2576 return (FAILURE);
2577 }
2578
2579 value_c = atoi(cp);
2580 value_t = atoi(tp);
2581 value_d = atoi(dp);
2582
2583 array_tagp->idl.target_id = value_t;
2584 array_tagp->idl.lun = value_d;
2585
2586 if (ctl_tagp != NULL) {
2587 *ctl_tagp = value_c;
2588 }
2589
2590 free(t);
2591 return (SUCCESS);
2592 }
2593
2594 /*
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
2599 * if it fails.
2600 */
2601 static int
get_disk_tag_ctd(char * argp,disk_tag_t * disk_tagp,uint32_t * ctl_tag)2602 get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, uint32_t *ctl_tag)
2603 {
2604 char *t = NULL;
2605 char *cp = NULL;
2606 char *tp = NULL;
2607 char *dp = NULL;
2608
2609 uint32_t value_c = MAX32BIT;
2610 uint32_t value_t = MAX32BIT;
2611 uint32_t value_d = MAX32BIT;
2612
2613 int len = 0;
2614
2615 if (argp == NULL || (len = strlen(argp)) == 0 ||
2616 disk_tagp == NULL) {
2617 return (FAILURE);
2618 }
2619
2620 t = (char *)malloc(len + 1);
2621 if (t == NULL) {
2622 return (FAILURE);
2623 }
2624
2625 (void) memcpy(t, argp, len + 1);
2626
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)) {
2631 free(t);
2632 return (FAILURE);
2633 }
2634 cp = t;
2635
2636 *dp = '\0';
2637 dp++;
2638 *tp = '\0';
2639 tp++;
2640 cp++;
2641
2642 if (is_fully_numeric(dp) == FALSE ||
2643 is_fully_numeric(tp) == FALSE ||
2644 is_fully_numeric(cp) == FALSE) {
2645 free(t);
2646 return (FAILURE);
2647 }
2648
2649 value_c = atoi(cp);
2650 value_t = atoi(tp);
2651 value_d = atoi(dp);
2652
2653 disk_tagp->cidl.bus = 0;
2654 disk_tagp->cidl.target_id = value_t;
2655 disk_tagp->cidl.lun = value_d;
2656 *ctl_tag = value_c;
2657
2658 free(t);
2659 return (SUCCESS);
2660 }
2661
2662 /*
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
2666 * if it fails.
2667 */
2668 static int
get_disk_tag_cidl(char * argp,disk_tag_t * disk_tagp)2669 get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp)
2670 {
2671 int len = 0;
2672 char *p = NULL;
2673 char *t = NULL;
2674 char *dot1p = NULL;
2675 char *dot2p = NULL;
2676
2677 if (argp == NULL || (len = strlen(argp)) == 0) {
2678 return (FAILURE);
2679 }
2680
2681 if (disk_tagp == NULL) {
2682 return (FAILURE);
2683 }
2684
2685 t = (char *)malloc(len + 1);
2686 if (t == NULL) {
2687 return (FAILURE);
2688 }
2689
2690 (void) memcpy(t, argp, len + 1);
2691 p = t;
2692
2693 dot2p = strrchr(p, '.');
2694 if (dot2p == NULL) {
2695 free(t);
2696 return (FAILURE);
2697 }
2698 *dot2p = '\0';
2699 dot2p++;
2700
2701 dot1p = strrchr(p, '.');
2702 if (dot1p == NULL) {
2703 free(t);
2704 return (FAILURE);
2705 }
2706 *dot1p = '\0';
2707 dot1p++;
2708
2709 /* Assert only 2 dots in this string */
2710 if (strrchr(p, '.') != NULL) {
2711 free(t);
2712 return (FAILURE);
2713 }
2714
2715 while (*p == ' ')
2716 p++;
2717
2718 if (is_fully_numeric(p) == FALSE ||
2719 is_fully_numeric(dot1p) == FALSE ||
2720 is_fully_numeric(dot2p) == FALSE) {
2721 free(t);
2722 return (FAILURE);
2723 }
2724
2725 disk_tagp->cidl.bus = atoi(p);
2726 disk_tagp->cidl.target_id = atoi(dot1p);
2727 disk_tagp->cidl.lun = atoi(dot2p);
2728
2729 free(t);
2730 return (SUCCESS);
2731 }
2732
2733 /*
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.
2745 */
2746 static int
calc_size(char * sizep,uint64_t * valp)2747 calc_size(char *sizep, uint64_t *valp)
2748 {
2749 int len;
2750 uint64_t size;
2751 uint64_t unit;
2752 char *t = NULL;
2753 char *tailp = NULL;
2754
2755 if (sizep == NULL || valp == NULL) {
2756 return (INVALID_ARG);
2757 }
2758
2759 if (is_fully_numeric(sizep) == TRUE) {
2760 *valp = atoi(sizep);
2761 return (SUCCESS);
2762 }
2763
2764 len = strlen(sizep);
2765 if (len == 0) {
2766 return (INVALID_ARG);
2767 }
2768
2769 t = (char *)malloc(len + 1);
2770 if (t == NULL) {
2771 return (FAILURE);
2772 }
2773
2774 (void) memcpy(t, sizep, len + 1);
2775
2776 switch (*(t + len - 1)) {
2777 case 'k':
2778 case 'K':
2779 unit = 1024ull;
2780 errno = 0;
2781 size = strtoll(t, &tailp, 0);
2782 break;
2783 case 'm':
2784 case 'M':
2785 unit = 1024ull * 1024ull;
2786 errno = 0;
2787 size = strtoll(t, &tailp, 0);
2788 break;
2789 case 'g':
2790 case 'G':
2791 unit = 1024ull * 1024ull * 1024ull;
2792 errno = 0;
2793 size = strtoll(t, &tailp, 0);
2794 break;
2795 case 't':
2796 case 'T':
2797 unit = 1024ull * 1024ull * 1024ull * 1024ull;
2798 errno = 0;
2799 size = strtoll(t, &tailp, 0);
2800 break;
2801 default:
2802 /* The unit must be kilobyte at least. */
2803 free(t);
2804 return (INVALID_ARG);
2805 }
2806
2807 *(t + len - 1) = '\0';
2808 if (is_fully_numeric(t) != TRUE) {
2809 free(t);
2810 return (INVALID_ARG);
2811 }
2812
2813 errno = 0;
2814 size = strtoll(t, &tailp, 0);
2815
2816 /* Check overflow condition */
2817 if (errno == ERANGE || (size > (MAX64BIT / unit))) {
2818 free(t);
2819 return (INVALID_ARG);
2820 }
2821
2822 *valp = size * unit;
2823 free(t);
2824 return (SUCCESS);
2825 }
2826
2827 /*
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
2832 * otherwise.
2833 */
2834 static int
is_fully_numeric(char * strp)2835 is_fully_numeric(char *strp)
2836 {
2837 uint32_t len;
2838 uint32_t i;
2839
2840 if (strp == NULL) {
2841 return (FALSE);
2842 }
2843
2844 len = strlen(strp);
2845 if (len == 0) {
2846 return (FALSE);
2847 }
2848
2849 /* Skip whitespace characters */
2850 for (i = 0; i < len; i++) {
2851 if (strp[i] != ' ') {
2852 break;
2853 }
2854 }
2855
2856 /* if strp points all space characters */
2857 if (i == len) {
2858 return (FALSE);
2859 }
2860
2861 /* Check the digitals in string */
2862 for (; i < len; i++) {
2863 if (!isdigit(strp[i])) {
2864 break;
2865 }
2866 }
2867
2868 /* Check the ending string */
2869 for (; i < len; i++) {
2870 if (strp[i] != ' ') {
2871 return (FALSE);
2872 }
2873 }
2874
2875 return (TRUE);
2876 }
2877
2878 static int
yes(void)2879 yes(void)
2880 {
2881 int i, b;
2882 char ans[SCHAR_MAX + 1];
2883
2884 for (i = 0; ; i++) {
2885 b = getchar();
2886 if (b == '\n' || b == '\0' || b == EOF) {
2887 ans[i] = 0;
2888 break;
2889 }
2890 if (i < SCHAR_MAX) {
2891 ans[i] = b;
2892 }
2893 }
2894 if (i >= SCHAR_MAX) {
2895 i = SCHAR_MAX;
2896 ans[SCHAR_MAX] = 0;
2897 }
2898
2899 return (rpmatch(ans));
2900 }
2901
2902 /*
2903 * Function: int rpmatch(char *)
2904 *
2905 * Description:
2906 *
2907 * Internationalized get yes / no answer.
2908 *
2909 * Inputs:
2910 * s -> Pointer to answer to compare against.
2911 *
2912 * Returns:
2913 * TRUE -> Answer was affirmative
2914 * FALSE -> Answer was negative
2915 */
2916
2917 static int
rpmatch(char * s)2918 rpmatch(char *s)
2919 {
2920 int status;
2921
2922 /* match yesexpr */
2923 status = regexec(&re, s, (size_t)0, NULL, 0);
2924 if (status != 0) {
2925 return (FALSE);
2926 }
2927 return (TRUE);
2928 }
2929
2930 static int
size_to_string(uint64_t size,char * string,int len)2931 size_to_string(uint64_t size, char *string, int len)
2932 {
2933 int i = 0;
2934 uint32_t remainder;
2935 char unit[][2] = {" ", "K", "M", "G", "T"};
2936
2937 if (string == NULL) {
2938 return (FAILURE);
2939 }
2940 while (size > 1023) {
2941 remainder = size % 1024;
2942 size /= 1024;
2943 i++;
2944 }
2945
2946 if (i > 4) {
2947 return (FAILURE);
2948 }
2949
2950 remainder /= 103;
2951 if (remainder == 0) {
2952 (void) snprintf(string, len, "%llu", size);
2953 } else {
2954 (void) snprintf(string, len, "%llu.%1u", size,
2955 remainder);
2956 }
2957
2958 /* make sure there is one byte for unit */
2959 if ((strlen(string) + 1) >= len) {
2960 return (FAILURE);
2961 }
2962 (void) strlcat(string, unit[i], len);
2963
2964 return (SUCCESS);
2965 }
2966
2967 /*
2968 * Only one raidctl is running at one time.
2969 */
2970 static int
enter_raidctl_lock(int * fd)2971 enter_raidctl_lock(int *fd)
2972 {
2973 int fd0 = -1;
2974 struct flock lock;
2975
2976 fd0 = open(RAIDCTL_LOCKF, O_CREAT|O_WRONLY, 0600);
2977 if (fd0 < 0) {
2978 if (errno == EACCES) {
2979 (void) fprintf(stderr,
2980 gettext("raidctl:must be root to run raidctl"
2981 ": %s\n"), strerror(errno));
2982 } else {
2983 (void) fprintf(stderr,
2984 gettext("raidctl:failed to open lockfile"
2985 " '"RAIDCTL_LOCKF"': %s\n"), strerror(errno));
2986 }
2987 return (FAILURE);
2988 }
2989
2990 *fd = fd0;
2991 lock.l_type = F_WRLCK;
2992 lock.l_whence = SEEK_SET;
2993 lock.l_start = 0;
2994 lock.l_len = 0;
2995
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"));
3001 return (FAILURE);
3002 }
3003 (void) fprintf(stderr, gettext("raidctl:"
3004 "enter_filelock:filelock is owned "
3005 "by 'process %d'\n"), lock.l_pid);
3006 return (FAILURE);
3007 }
3008
3009 return (SUCCESS);
3010 }
3011
3012 static void
exit_raidctl_lock(int fd)3013 exit_raidctl_lock(int fd)
3014 {
3015 struct flock lock;
3016
3017 lock.l_type = F_UNLCK;
3018 lock.l_whence = SEEK_SET;
3019 lock.l_start = 0;
3020 lock.l_len = 0;
3021 if (fcntl(fd, F_SETLK, &lock) == -1) {
3022 (void) fprintf(stderr, gettext("raidctl: failed to"
3023 " exit_filelock: %s\n"),
3024 strerror(errno));
3025 }
3026 (void) close(fd);
3027 }
3028