17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57f000930Syw161884 * Common Development and Distribution License (the "License"). 67f000930Syw161884 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 20711890bcSjc156560 * 21711890bcSjc156560 * 22*f3f093f5SMilan Jurik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24711890bcSjc156560 * 25711890bcSjc156560 * raidctl.c is the entry file of RAID configuration utility. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <ctype.h> 29711890bcSjc156560 #include <sys/types.h> 30711890bcSjc156560 #include <sys/stat.h> 317c478bd9Sstevel@tonic-gate #include <fcntl.h> 327c478bd9Sstevel@tonic-gate #include <langinfo.h> 33711890bcSjc156560 #include <regex.h> 347c478bd9Sstevel@tonic-gate #include <locale.h> 35711890bcSjc156560 #include <libintl.h> 367c478bd9Sstevel@tonic-gate #include <stdio.h> 377c478bd9Sstevel@tonic-gate #include <stdlib.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <strings.h> 407c478bd9Sstevel@tonic-gate #include <unistd.h> 41711890bcSjc156560 #include <errno.h> 42711890bcSjc156560 #include <libgen.h> 43711890bcSjc156560 #include <raidcfg.h> 44711890bcSjc156560 45711890bcSjc156560 46711890bcSjc156560 #define TRUE 1 47711890bcSjc156560 #define FALSE 0 48711890bcSjc156560 49711890bcSjc156560 #ifndef TEXT_DOMAIN 50711890bcSjc156560 #define TEXT_DOMAIN "SYS_TEST" 51711890bcSjc156560 #endif 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* 54711890bcSjc156560 * Return value of command 557c478bd9Sstevel@tonic-gate */ 567c478bd9Sstevel@tonic-gate #define SUCCESS 0 577c478bd9Sstevel@tonic-gate #define INVALID_ARG 1 587c478bd9Sstevel@tonic-gate #define FAILURE 2 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* 61711890bcSjc156560 * Initial value of variables 627c478bd9Sstevel@tonic-gate */ 63711890bcSjc156560 #define INIT_HANDLE_VALUE -3 64711890bcSjc156560 #define MAX64BIT 0xffffffffffffffffull 65711890bcSjc156560 #define MAX32BIT 0xfffffffful 667c478bd9Sstevel@tonic-gate 67711890bcSjc156560 /* 68711890bcSjc156560 * Flag of set or unset HSP 69711890bcSjc156560 */ 70711890bcSjc156560 #define HSP_SET 1 71711890bcSjc156560 #define HSP_UNSET 0 727c478bd9Sstevel@tonic-gate 73711890bcSjc156560 /* 74711890bcSjc156560 * Operate codes of command 75711890bcSjc156560 */ 76711890bcSjc156560 #define DO_HW_RAID_NOP -1 77711890bcSjc156560 #define DO_HW_RAID_HELP 0 78711890bcSjc156560 #define DO_HW_RAID_CREATEO 1 79711890bcSjc156560 #define DO_HW_RAID_CREATEN 2 80711890bcSjc156560 #define DO_HW_RAID_DELETE 3 81711890bcSjc156560 #define DO_HW_RAID_LIST 4 82711890bcSjc156560 #define DO_HW_RAID_FLASH 5 83711890bcSjc156560 #define DO_HW_RAID_HSP 6 84711890bcSjc156560 #define DO_HW_RAID_SET_ATTR 7 85711890bcSjc156560 #define DO_HW_RAID_SNAPSHOT 8 867c478bd9Sstevel@tonic-gate 87711890bcSjc156560 #define LOWER_H (1 << 0) 88711890bcSjc156560 #define LOWER_C (1 << 1) 89711890bcSjc156560 #define LOWER_D (1 << 2) 90711890bcSjc156560 #define LOWER_L (1 << 3) 91711890bcSjc156560 #define LOWER_R (1 << 4) 92711890bcSjc156560 #define LOWER_Z (1 << 5) 93711890bcSjc156560 #define LOWER_G (1 << 6) 94711890bcSjc156560 #define LOWER_A (1 << 7) 95711890bcSjc156560 #define LOWER_S (1 << 8) 96711890bcSjc156560 #define LOWER_P (1 << 9) 97711890bcSjc156560 #define LOWER_F (1 << 10) 98711890bcSjc156560 #define UPPER_S (1 << 11) 99711890bcSjc156560 #define UPPER_C (1 << 12) 100711890bcSjc156560 #define UPPER_F (1 << 13) 1017c478bd9Sstevel@tonic-gate 102711890bcSjc156560 /* Add a ARRAY state (temporary) */ 103711890bcSjc156560 #define ARRAY_STATE_SYNC 100 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Function and strings to properly localize our prompt. 107711890bcSjc156560 * So for example in German it would ask (ja/nein) or (yes/no) in 1087c478bd9Sstevel@tonic-gate * english. 1097c478bd9Sstevel@tonic-gate */ 110711890bcSjc156560 #ifndef SCHAR_MAX 111711890bcSjc156560 #define SCHAR_MAX 10 112711890bcSjc156560 #endif 113711890bcSjc156560 114711890bcSjc156560 #define RAIDCTL_LOCKF "/var/run/lockf_raidctl" 115711890bcSjc156560 116711890bcSjc156560 /* Locale setting */ 1176fec3791Sjesseb static int yes(void); 118711890bcSjc156560 static int rpmatch(char *s); 119711890bcSjc156560 static char *yesstr = NULL; 120711890bcSjc156560 static char *nostr = NULL; 121711890bcSjc156560 static char *yesexpr = NULL; 1227c478bd9Sstevel@tonic-gate 123711890bcSjc156560 static char *default_yesexpr = "^[yY]"; 124711890bcSjc156560 static char *default_yesstr = "yes"; 125711890bcSjc156560 static char *default_nostr = "no"; 1267c478bd9Sstevel@tonic-gate 127711890bcSjc156560 static regex_t re; 128711890bcSjc156560 129711890bcSjc156560 #define SET_DEFAULT_STRS \ 130711890bcSjc156560 regfree(&re); \ 131711890bcSjc156560 free(yesexpr); \ 132711890bcSjc156560 free(yesstr); \ 133711890bcSjc156560 free(nostr); \ 134711890bcSjc156560 yesexpr = default_yesexpr; \ 135711890bcSjc156560 yesstr = default_yesstr; \ 136711890bcSjc156560 nostr = default_nostr; 137711890bcSjc156560 138711890bcSjc156560 #define FREE_STRS \ 139711890bcSjc156560 if (yesexpr != default_yesexpr) \ 140711890bcSjc156560 free(yesexpr); \ 141711890bcSjc156560 if (yesstr != default_yesstr) \ 142711890bcSjc156560 free(yesstr); \ 143711890bcSjc156560 if (nostr != default_nostr) \ 144711890bcSjc156560 free(nostr); 145711890bcSjc156560 146711890bcSjc156560 /* program name */ 147711890bcSjc156560 static char *prog_namep; 148711890bcSjc156560 1497c478bd9Sstevel@tonic-gate 1506fec3791Sjesseb /* 151711890bcSjc156560 * Functions declaration 1526fec3791Sjesseb */ 153711890bcSjc156560 static void helpinfo(char *prog_namep); 154711890bcSjc156560 static int do_create_cidl(char *raid_levelp, char *capacityp, char *disk_argp, 155711890bcSjc156560 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind); 156711890bcSjc156560 static int do_create_ctd(char *raid_levelp, char **disks_argpp, 157711890bcSjc156560 uint32_t disks_num, uint32_t argindex, uint32_t f_flag); 158711890bcSjc156560 static int do_list(char *disk_argp, char **argv, uint32_t optind, 159711890bcSjc156560 uint8_t is_snapshot); 160711890bcSjc156560 static int do_delete(uint32_t f_flag, char **argv, uint32_t optind); 161711890bcSjc156560 static int do_flash(uint8_t f_flag, char *filep, char **ctls_argpp, 162711890bcSjc156560 uint32_t index, uint32_t ctl_num); 163711890bcSjc156560 static int do_set_hsp(char *a_argp, char *disk_argp, char **argv, 164711890bcSjc156560 uint32_t optind); 165711890bcSjc156560 static int do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, 166711890bcSjc156560 uint32_t optind); 167711890bcSjc156560 static int snapshot_raidsystem(uint8_t recursive, uint8_t indent, 168711890bcSjc156560 uint8_t is_snapshot); 169711890bcSjc156560 static int snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, 170711890bcSjc156560 uint8_t indent, uint8_t is_snapshot); 171711890bcSjc156560 static int snapshot_array(raid_obj_handle_t array_handle, 172711890bcSjc156560 uint8_t indent, uint8_t is_sub, uint8_t is_snapshot); 173711890bcSjc156560 static int snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, 174711890bcSjc156560 uint8_t indent, uint8_t is_snapshot); 175711890bcSjc156560 static int print_ctl_table(raid_obj_handle_t ctl_handle); 176711890bcSjc156560 static int print_array_table(raid_obj_handle_t ctl_handle, 177711890bcSjc156560 raid_obj_handle_t array_handle); 178711890bcSjc156560 static int print_disk_table(raid_obj_handle_t ctl_handle, 179711890bcSjc156560 raid_obj_handle_t disk_handle); 180711890bcSjc156560 static int print_ctl_attr(raidcfg_controller_t *attrp); 181711890bcSjc156560 static int print_array_attr(raidcfg_array_t *attrp); 182711890bcSjc156560 static int print_arraypart_attr(raidcfg_arraypart_t *attrp); 183711890bcSjc156560 static int print_disk_attr(raid_obj_handle_t ctl_handle, 184711890bcSjc156560 raid_obj_handle_t disk_handle, raidcfg_disk_t *attrp); 185711890bcSjc156560 static void print_indent(uint8_t indent); 186711890bcSjc156560 static int get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, 187711890bcSjc156560 int *comps_nump, raid_obj_handle_t **handlespp); 188711890bcSjc156560 static int get_disk_handle_ctd(int disks_num, char **disks_argpp, 189711890bcSjc156560 uint32_t *ctl_tagp, raid_obj_handle_t *disks_handlep); 190711890bcSjc156560 static int get_ctl_tag(char *argp, uint32_t *ctl_tagp); 191711890bcSjc156560 static int get_array_tag(char *argp, uint32_t *ctl_tagp, 192711890bcSjc156560 array_tag_t *array_tagp); 193711890bcSjc156560 static int get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, 194711890bcSjc156560 uint32_t *controller_id); 195711890bcSjc156560 static int get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp); 196711890bcSjc156560 static int calc_size(char *sizep, uint64_t *valp); 197711890bcSjc156560 static int is_fully_numeric(char *strp); 198711890bcSjc156560 static int size_to_string(uint64_t size, char *string, int len); 199711890bcSjc156560 static int enter_raidctl_lock(int *fd); 200711890bcSjc156560 static void exit_raidctl_lock(int fd); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 203711890bcSjc156560 * Entry function of raidctl command 2047c478bd9Sstevel@tonic-gate */ 205711890bcSjc156560 int 206711890bcSjc156560 main(int argc, char **argv) 2077c478bd9Sstevel@tonic-gate { 208711890bcSjc156560 /* operation index */ 209711890bcSjc156560 int8_t findex = DO_HW_RAID_NOP; 2107c478bd9Sstevel@tonic-gate 211711890bcSjc156560 /* argument pointers */ 212711890bcSjc156560 char *r_argp = NULL; 213711890bcSjc156560 char *z_argp = NULL; 214711890bcSjc156560 char *g_argp = NULL; 215711890bcSjc156560 char *a_argp = NULL; 216711890bcSjc156560 char *s_argp = NULL; 217711890bcSjc156560 char *p_argp = NULL; 218711890bcSjc156560 char *F_argp = NULL; 219711890bcSjc156560 char *C_argp = NULL; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate /* 222711890bcSjc156560 * operation flags. 2237c478bd9Sstevel@tonic-gate */ 224711890bcSjc156560 uint8_t r_flag = FALSE; 225711890bcSjc156560 uint8_t f_flag = FALSE; 226711890bcSjc156560 uint8_t action = FALSE; 227711890bcSjc156560 uint64_t options = 0; 2287c478bd9Sstevel@tonic-gate 229711890bcSjc156560 /* index and temporary variables */ 230711890bcSjc156560 int ret; 231711890bcSjc156560 int status; 232711890bcSjc156560 char c = '\0'; 2337c478bd9Sstevel@tonic-gate 234711890bcSjc156560 /* fd for the filelock */ 2357c478bd9Sstevel@tonic-gate int fd; 2367c478bd9Sstevel@tonic-gate 237711890bcSjc156560 if (enter_raidctl_lock(&fd) != SUCCESS) { 2387c478bd9Sstevel@tonic-gate return (FAILURE); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 241711890bcSjc156560 (void) setlocale(LC_ALL, ""); 242711890bcSjc156560 (void) textdomain(TEXT_DOMAIN); 2437c478bd9Sstevel@tonic-gate 244711890bcSjc156560 /* parse command line, and get program name */ 245711890bcSjc156560 if ((prog_namep = strrchr(argv[0], '/')) == NULL) { 246711890bcSjc156560 prog_namep = argv[0]; 2476fec3791Sjesseb } else { 248711890bcSjc156560 prog_namep++; 2496fec3791Sjesseb } 2506fec3791Sjesseb 251711890bcSjc156560 /* close error option messages from getopt */ 252711890bcSjc156560 opterr = 0; 2536fec3791Sjesseb 254711890bcSjc156560 /* get yes expression according to current locale */ 255711890bcSjc156560 yesexpr = strdup(nl_langinfo(YESEXPR)); 256711890bcSjc156560 yesstr = strdup(nl_langinfo(YESSTR)); 257711890bcSjc156560 nostr = strdup(nl_langinfo(NOSTR)); 258711890bcSjc156560 if (yesexpr == NULL || yesstr == NULL || nostr == NULL) { 2597c478bd9Sstevel@tonic-gate return (FAILURE); 260711890bcSjc156560 } 261711890bcSjc156560 262711890bcSjc156560 /* 263711890bcSjc156560 * If the was no expression or if there is a compile error 264711890bcSjc156560 * use default yes expression. 265711890bcSjc156560 */ 266711890bcSjc156560 status = regcomp(&re, yesexpr, REG_EXTENDED | REG_NOSUB); 267711890bcSjc156560 if ((*yesexpr == (char)NULL) || 268711890bcSjc156560 (*yesstr == (char)NULL) || 269711890bcSjc156560 (*nostr == (char)NULL) || 270711890bcSjc156560 (status != 0)) { 271711890bcSjc156560 SET_DEFAULT_STRS; 272711890bcSjc156560 if (regcomp(&re, default_yesexpr, 273711890bcSjc156560 REG_EXTENDED | REG_NOSUB) != 0) { 274711890bcSjc156560 return (FALSE); 275711890bcSjc156560 } 276711890bcSjc156560 } 277711890bcSjc156560 278711890bcSjc156560 while ((c = getopt(argc, argv, 279711890bcSjc156560 "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) { 280711890bcSjc156560 switch (c) { 281711890bcSjc156560 case 'h': 282711890bcSjc156560 case '?': 283711890bcSjc156560 if (action == FALSE) { 284711890bcSjc156560 findex = DO_HW_RAID_HELP; 285711890bcSjc156560 action = TRUE; 286711890bcSjc156560 options |= LOWER_H; 287711890bcSjc156560 } else { 288711890bcSjc156560 findex = DO_HW_RAID_NOP; 289711890bcSjc156560 } 290711890bcSjc156560 break; 291711890bcSjc156560 case 'C': 292711890bcSjc156560 if (action == FALSE) { 293711890bcSjc156560 findex = DO_HW_RAID_CREATEN; 294711890bcSjc156560 C_argp = optarg; 295711890bcSjc156560 action = TRUE; 296711890bcSjc156560 options |= UPPER_C; 297711890bcSjc156560 } else { 298711890bcSjc156560 findex = DO_HW_RAID_NOP; 299711890bcSjc156560 } 300711890bcSjc156560 break; 301711890bcSjc156560 case 'c': 302711890bcSjc156560 if (action == FALSE) { 303711890bcSjc156560 findex = DO_HW_RAID_CREATEO; 304711890bcSjc156560 action = TRUE; 305711890bcSjc156560 options |= LOWER_C; 306711890bcSjc156560 } else { 307711890bcSjc156560 findex = DO_HW_RAID_NOP; 308711890bcSjc156560 } 309711890bcSjc156560 break; 310711890bcSjc156560 case 'd': 311711890bcSjc156560 if (action == FALSE) { 312711890bcSjc156560 findex = DO_HW_RAID_DELETE; 313711890bcSjc156560 action = TRUE; 314711890bcSjc156560 options |= LOWER_D; 315711890bcSjc156560 } else { 316711890bcSjc156560 findex = DO_HW_RAID_NOP; 317711890bcSjc156560 } 318711890bcSjc156560 break; 319711890bcSjc156560 case 'l': 320711890bcSjc156560 if (action == FALSE) { 321711890bcSjc156560 findex = DO_HW_RAID_LIST; 322711890bcSjc156560 action = TRUE; 323711890bcSjc156560 options |= LOWER_L; 324711890bcSjc156560 } else { 325711890bcSjc156560 findex = DO_HW_RAID_NOP; 326711890bcSjc156560 } 327711890bcSjc156560 break; 328711890bcSjc156560 case 'F': 329711890bcSjc156560 if (action == FALSE) { 330711890bcSjc156560 findex = DO_HW_RAID_FLASH; 331711890bcSjc156560 F_argp = optarg; 332711890bcSjc156560 action = TRUE; 333711890bcSjc156560 options |= UPPER_F; 334711890bcSjc156560 } else { 335711890bcSjc156560 findex = DO_HW_RAID_NOP; 336711890bcSjc156560 } 337711890bcSjc156560 break; 338711890bcSjc156560 case 'a': 339711890bcSjc156560 if (action == FALSE) { 340711890bcSjc156560 findex = DO_HW_RAID_HSP; 341711890bcSjc156560 a_argp = optarg; 342711890bcSjc156560 action = TRUE; 343711890bcSjc156560 options |= LOWER_A; 344711890bcSjc156560 } else { 345711890bcSjc156560 findex = DO_HW_RAID_NOP; 346711890bcSjc156560 } 347711890bcSjc156560 break; 348711890bcSjc156560 case 'p': 349711890bcSjc156560 if (action == FALSE) { 350711890bcSjc156560 findex = DO_HW_RAID_SET_ATTR; 351711890bcSjc156560 p_argp = optarg; 352711890bcSjc156560 action = TRUE; 353711890bcSjc156560 options |= LOWER_P; 354711890bcSjc156560 } else { 355711890bcSjc156560 findex = DO_HW_RAID_NOP; 356711890bcSjc156560 } 357711890bcSjc156560 break; 358711890bcSjc156560 case 'r': 359711890bcSjc156560 r_argp = optarg; 360711890bcSjc156560 r_flag = TRUE; 361711890bcSjc156560 options |= LOWER_R; 362711890bcSjc156560 break; 363711890bcSjc156560 case 'z': 364711890bcSjc156560 z_argp = optarg; 365711890bcSjc156560 options |= LOWER_Z; 366711890bcSjc156560 break; 367711890bcSjc156560 case 'g': 368711890bcSjc156560 g_argp = optarg; 369711890bcSjc156560 options |= LOWER_G; 370711890bcSjc156560 break; 371711890bcSjc156560 case 's': 372711890bcSjc156560 s_argp = optarg; 373711890bcSjc156560 options |= LOWER_S; 374711890bcSjc156560 break; 375711890bcSjc156560 case 'f': 376711890bcSjc156560 f_flag = TRUE; 377711890bcSjc156560 options |= LOWER_F; 378711890bcSjc156560 break; 379711890bcSjc156560 case 'S': 380711890bcSjc156560 if (action == FALSE) { 381711890bcSjc156560 findex = DO_HW_RAID_SNAPSHOT; 382711890bcSjc156560 action = TRUE; 383711890bcSjc156560 options |= UPPER_S; 384711890bcSjc156560 } else { 385711890bcSjc156560 findex = DO_HW_RAID_NOP; 386711890bcSjc156560 } 387711890bcSjc156560 break; 388711890bcSjc156560 default: 389711890bcSjc156560 (void) fprintf(stderr, 390711890bcSjc156560 gettext("Invalid argument(s).\n")); 391711890bcSjc156560 exit_raidctl_lock(fd); 392711890bcSjc156560 FREE_STRS; 393711890bcSjc156560 regfree(&re); 394711890bcSjc156560 return (INVALID_ARG); 395711890bcSjc156560 } 396711890bcSjc156560 } 397711890bcSjc156560 398711890bcSjc156560 /* parse options */ 399711890bcSjc156560 switch (findex) { 400711890bcSjc156560 case DO_HW_RAID_HELP: 401711890bcSjc156560 if ((options & ~(LOWER_H)) != 0) { 402711890bcSjc156560 ret = INVALID_ARG; 403711890bcSjc156560 } else { 404711890bcSjc156560 helpinfo(prog_namep); 405711890bcSjc156560 ret = SUCCESS; 406711890bcSjc156560 } 407711890bcSjc156560 break; 408711890bcSjc156560 case DO_HW_RAID_CREATEO: 409711890bcSjc156560 if ((options & ~(LOWER_F | LOWER_C | LOWER_R)) != 0) { 410711890bcSjc156560 ret = INVALID_ARG; 411711890bcSjc156560 } else { 412711890bcSjc156560 if (r_flag != FALSE && f_flag == FALSE) { 413711890bcSjc156560 ret = do_create_ctd(r_argp, argv, argc - 4, 414711890bcSjc156560 optind, f_flag); 415711890bcSjc156560 } else if (r_flag == FALSE && f_flag == FALSE) { 416711890bcSjc156560 ret = do_create_ctd(NULL, argv, argc - 2, 417711890bcSjc156560 optind, f_flag); 418711890bcSjc156560 } else if (r_flag != FALSE && f_flag != FALSE) { 419711890bcSjc156560 ret = do_create_ctd(r_argp, argv, argc - 5, 420711890bcSjc156560 optind, f_flag); 421711890bcSjc156560 } else { 422711890bcSjc156560 ret = do_create_ctd(NULL, argv, argc - 3, 423711890bcSjc156560 optind, f_flag); 424711890bcSjc156560 } 425711890bcSjc156560 } 426711890bcSjc156560 break; 427711890bcSjc156560 case DO_HW_RAID_CREATEN: 428711890bcSjc156560 if ((options & ~(LOWER_F | UPPER_C | LOWER_R | LOWER_Z | 429711890bcSjc156560 LOWER_S)) != 0) { 430711890bcSjc156560 ret = INVALID_ARG; 431711890bcSjc156560 } else { 432711890bcSjc156560 ret = do_create_cidl(r_argp, z_argp, C_argp, s_argp, 433711890bcSjc156560 f_flag, argv, optind); 434711890bcSjc156560 } 435711890bcSjc156560 break; 436711890bcSjc156560 case DO_HW_RAID_DELETE: 437711890bcSjc156560 if ((options & ~(LOWER_F | LOWER_D)) != 0) { 438711890bcSjc156560 ret = INVALID_ARG; 439711890bcSjc156560 } else { 440711890bcSjc156560 ret = do_delete(f_flag, argv, optind); 441711890bcSjc156560 } 442711890bcSjc156560 break; 443711890bcSjc156560 case DO_HW_RAID_LIST: 444711890bcSjc156560 if ((options & ~(LOWER_L | LOWER_G)) != 0) { 445711890bcSjc156560 ret = INVALID_ARG; 446711890bcSjc156560 } else { 447711890bcSjc156560 ret = do_list(g_argp, argv, optind, FALSE); 448711890bcSjc156560 } 449711890bcSjc156560 break; 450711890bcSjc156560 case DO_HW_RAID_SNAPSHOT: 451711890bcSjc156560 if ((options & ~(UPPER_S | LOWER_G)) != 0) { 452711890bcSjc156560 ret = INVALID_ARG; 453711890bcSjc156560 } else { 454711890bcSjc156560 ret = do_list(g_argp, argv, optind, TRUE); 455711890bcSjc156560 } 456711890bcSjc156560 break; 457711890bcSjc156560 case DO_HW_RAID_FLASH: 458711890bcSjc156560 if ((options & ~(LOWER_F | UPPER_F)) != 0) { 459711890bcSjc156560 ret = INVALID_ARG; 460711890bcSjc156560 } else { 461711890bcSjc156560 if (f_flag == FALSE) { 462711890bcSjc156560 ret = do_flash(f_flag, F_argp, argv, optind, 463711890bcSjc156560 argc - 3); 464711890bcSjc156560 } else { 465711890bcSjc156560 ret = do_flash(f_flag, F_argp, argv, optind, 466711890bcSjc156560 argc - 4); 467711890bcSjc156560 } 468711890bcSjc156560 } 469711890bcSjc156560 break; 470711890bcSjc156560 case DO_HW_RAID_HSP: 471711890bcSjc156560 if ((options & ~(LOWER_A | LOWER_G)) != 0) { 472711890bcSjc156560 ret = INVALID_ARG; 473711890bcSjc156560 } else { 474711890bcSjc156560 ret = do_set_hsp(a_argp, g_argp, argv, optind); 475711890bcSjc156560 } 476711890bcSjc156560 break; 477711890bcSjc156560 case DO_HW_RAID_SET_ATTR: 478711890bcSjc156560 if ((options & ~(LOWER_F | LOWER_P)) != 0) { 479711890bcSjc156560 ret = INVALID_ARG; 480711890bcSjc156560 } else { 481711890bcSjc156560 ret = do_set_array_attr(f_flag, p_argp, argv, optind); 482711890bcSjc156560 } 483711890bcSjc156560 break; 484711890bcSjc156560 case DO_HW_RAID_NOP: 485711890bcSjc156560 if (argc == 1) { 486711890bcSjc156560 ret = do_list(g_argp, argv, optind, FALSE); 487711890bcSjc156560 } else { 488711890bcSjc156560 ret = INVALID_ARG; 489711890bcSjc156560 } 490711890bcSjc156560 break; 491711890bcSjc156560 default: 492711890bcSjc156560 ret = INVALID_ARG; 493711890bcSjc156560 break; 494711890bcSjc156560 } 495711890bcSjc156560 496711890bcSjc156560 if (ret == INVALID_ARG) { 497711890bcSjc156560 (void) fprintf(stderr, 498711890bcSjc156560 gettext("Invalid argument(s).\n")); 499711890bcSjc156560 } 500711890bcSjc156560 exit_raidctl_lock(fd); 501711890bcSjc156560 502711890bcSjc156560 FREE_STRS; 503711890bcSjc156560 regfree(&re); 504711890bcSjc156560 return (ret); 505711890bcSjc156560 } 506711890bcSjc156560 507711890bcSjc156560 /* 508711890bcSjc156560 * helpinfo(prog_namep) 509711890bcSjc156560 * This function prints help informations for usrs. 510711890bcSjc156560 */ 511711890bcSjc156560 static void 512711890bcSjc156560 helpinfo(char *prog_namep) 513711890bcSjc156560 { 514711890bcSjc156560 char quote = '"'; 515711890bcSjc156560 516711890bcSjc156560 (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] " 517711890bcSjc156560 "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep, 518711890bcSjc156560 quote, quote); 519711890bcSjc156560 520711890bcSjc156560 (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep); 521711890bcSjc156560 522711890bcSjc156560 (void) printf(gettext("%s [-f] -F <filename> <controller1> " 523711890bcSjc156560 "[<controller2> ...]\n"), prog_namep); 524711890bcSjc156560 525711890bcSjc156560 (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"), 526711890bcSjc156560 prog_namep, quote, quote); 527711890bcSjc156560 528711890bcSjc156560 (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> " 529711890bcSjc156560 "[<disk3> ...]\n"), prog_namep); 530711890bcSjc156560 531711890bcSjc156560 (void) printf(gettext("%s [-l]\n"), prog_namep); 532711890bcSjc156560 533711890bcSjc156560 (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep); 534711890bcSjc156560 535711890bcSjc156560 (void) printf(gettext("%s -l <volume>\n"), prog_namep); 536711890bcSjc156560 537711890bcSjc156560 (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"), 538711890bcSjc156560 prog_namep); 539711890bcSjc156560 540711890bcSjc156560 (void) printf(gettext("%s -a {set | unset} -g <disk> " 541711890bcSjc156560 "{<volume> | <controller>}\n"), prog_namep); 542711890bcSjc156560 543711890bcSjc156560 (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep); 544711890bcSjc156560 545711890bcSjc156560 (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep); 546711890bcSjc156560 547711890bcSjc156560 (void) printf(gettext("%s -h\n"), prog_namep); 548711890bcSjc156560 } 549711890bcSjc156560 550711890bcSjc156560 /* 551711890bcSjc156560 * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep, 552711890bcSjc156560 * f_flag, argv, optind) 553711890bcSjc156560 * This function creates a new RAID volume with specified arguments, 554711890bcSjc156560 * and returns result as SUCCESS, INVALID_ARG or FAILURE. 555711890bcSjc156560 * The "c.id.l" is used to express single physical disk. 'c' expresses 556711890bcSjc156560 * bus number, 'id' expresses target number, and 'l' expresses lun. 557711890bcSjc156560 * The physical disks represented by c.id.l may be invisible to OS, which 558711890bcSjc156560 * means physical disks attached to controllers are not accessible by 559711890bcSjc156560 * OS directly. The disks should be organized as a logical volume, and 560711890bcSjc156560 * the logical volume is exported to OS as a single unit. Some hardware 561711890bcSjc156560 * RAID controllers also support physical disks accessed by OS directly, 562711890bcSjc156560 * for example LSI1068. In this case, it's both OK to express physical 563711890bcSjc156560 * disk by c.id.l format or canonical ctd format. 564711890bcSjc156560 */ 565711890bcSjc156560 static int 566711890bcSjc156560 do_create_cidl(char *raid_levelp, char *capacityp, char *disks_argp, 567711890bcSjc156560 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind) 568711890bcSjc156560 { 569711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 570711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 571711890bcSjc156560 uint32_t raid_level = RAID_LEVEL_1; 572711890bcSjc156560 uint64_t capacity = 0; 573711890bcSjc156560 uint64_t stripe_size = (uint64_t)OBJ_ATTR_NONE; 574711890bcSjc156560 raid_obj_handle_t *disk_handlesp = NULL; 575711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 576711890bcSjc156560 raidcfg_controller_t ctl_attr; 577711890bcSjc156560 int comps_num = 0; 578711890bcSjc156560 int ret = 0; 579711890bcSjc156560 580711890bcSjc156560 raidcfg_array_t array_attr; 581711890bcSjc156560 582711890bcSjc156560 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 583711890bcSjc156560 return (INVALID_ARG); 584711890bcSjc156560 } 585711890bcSjc156560 586711890bcSjc156560 if (disks_argp == NULL) { 587711890bcSjc156560 return (INVALID_ARG); 588711890bcSjc156560 } 589711890bcSjc156560 590711890bcSjc156560 /* Check controller tag */ 591711890bcSjc156560 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 592711890bcSjc156560 return (INVALID_ARG); 593711890bcSjc156560 } 594711890bcSjc156560 595711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 596711890bcSjc156560 if (ctl_handle <= 0) { 597711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 598711890bcSjc156560 return (FAILURE); 599711890bcSjc156560 } 600711890bcSjc156560 601711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 602711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 603711890bcSjc156560 return (FAILURE); 604711890bcSjc156560 } 605711890bcSjc156560 606711890bcSjc156560 /* Get raid level */ 607711890bcSjc156560 if (raid_levelp != NULL) { 608711890bcSjc156560 if (*raid_levelp == '1' && 609711890bcSjc156560 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) { 610711890bcSjc156560 raid_level = RAID_LEVEL_1E; 611711890bcSjc156560 } else { 612711890bcSjc156560 if (is_fully_numeric(raid_levelp) == FALSE) { 613711890bcSjc156560 return (INVALID_ARG); 614711890bcSjc156560 } 615711890bcSjc156560 616711890bcSjc156560 switch (atoi(raid_levelp)) { 617711890bcSjc156560 case 0: 618711890bcSjc156560 raid_level = RAID_LEVEL_0; 619711890bcSjc156560 break; 6207c478bd9Sstevel@tonic-gate case 1: 621711890bcSjc156560 raid_level = RAID_LEVEL_1; 6227c478bd9Sstevel@tonic-gate break; 623711890bcSjc156560 case 5: 624711890bcSjc156560 raid_level = RAID_LEVEL_5; 625711890bcSjc156560 break; 626711890bcSjc156560 case 10: 627711890bcSjc156560 raid_level = RAID_LEVEL_10; 628711890bcSjc156560 break; 629711890bcSjc156560 case 50: 630711890bcSjc156560 raid_level = RAID_LEVEL_50; 631711890bcSjc156560 break; 632711890bcSjc156560 default: 6337c478bd9Sstevel@tonic-gate return (INVALID_ARG); 6347c478bd9Sstevel@tonic-gate } 635711890bcSjc156560 } 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6386fec3791Sjesseb /* 639711890bcSjc156560 * The rang check of capacity and stripe size is performed in library, 640711890bcSjc156560 * and it relates to hardware feature. 6416fec3791Sjesseb */ 6426fec3791Sjesseb 643711890bcSjc156560 /* Capacity in bytes. Capacity 0 means max available space. */ 644711890bcSjc156560 if (capacityp != NULL) { 645711890bcSjc156560 if (*capacityp == '-' || 646711890bcSjc156560 calc_size(capacityp, &capacity) != SUCCESS) { 6476fec3791Sjesseb return (INVALID_ARG); 6486fec3791Sjesseb } 6496fec3791Sjesseb } 6506fec3791Sjesseb 651711890bcSjc156560 /* Stripe size in bytes */ 652711890bcSjc156560 if (stripe_sizep != NULL) { 653711890bcSjc156560 if (calc_size(stripe_sizep, &stripe_size) != SUCCESS || 654711890bcSjc156560 *stripe_sizep == '-') { 655711890bcSjc156560 return (INVALID_ARG); 656711890bcSjc156560 } 657711890bcSjc156560 } 658711890bcSjc156560 659711890bcSjc156560 /* Open controller before accessing its object */ 660711890bcSjc156560 if ((ret = raidcfg_open_controller(ctl_handle, NULL)) < 0) { 661711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 662711890bcSjc156560 return (FAILURE); 663711890bcSjc156560 } 664711890bcSjc156560 665711890bcSjc156560 /* Get disks' handles */ 666711890bcSjc156560 if ((ret = get_disk_handle_cidl(ctl_tag, disks_argp, &comps_num, 667711890bcSjc156560 &disk_handlesp)) != SUCCESS) { 668711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 669711890bcSjc156560 return (ret); 670711890bcSjc156560 } 671711890bcSjc156560 672711890bcSjc156560 if (f_flag == FALSE) { 673711890bcSjc156560 (void) fprintf(stdout, gettext("Creating RAID volume " 674711890bcSjc156560 "will destroy all data on spare space of member disks, " 675711890bcSjc156560 "proceed (%s/%s)? "), yesstr, nostr); 6766fec3791Sjesseb if (!yes()) { 677711890bcSjc156560 (void) fprintf(stdout, gettext("RAID volume " 678711890bcSjc156560 "not created.\n\n")); 679711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 680711890bcSjc156560 free(disk_handlesp); 6816fec3791Sjesseb return (SUCCESS); 6826fec3791Sjesseb } 6836fec3791Sjesseb } 6846fec3791Sjesseb 685711890bcSjc156560 /* Create array */ 686711890bcSjc156560 array_handle = raidcfg_create_array(comps_num, 687711890bcSjc156560 disk_handlesp, raid_level, capacity, stripe_size, NULL); 6886fec3791Sjesseb 689711890bcSjc156560 if (array_handle <= 0) { 690711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 691711890bcSjc156560 free(disk_handlesp); 692711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 6937c478bd9Sstevel@tonic-gate return (FAILURE); 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate 696711890bcSjc156560 /* Get attribute of the new created array */ 697711890bcSjc156560 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 698711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 699711890bcSjc156560 free(disk_handlesp); 700711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 701711890bcSjc156560 return (FAILURE); 702711890bcSjc156560 } 703711890bcSjc156560 704711890bcSjc156560 (void) fprintf(stdout, gettext("Volume c%ut%llud%llu is created " 705711890bcSjc156560 "successfully!\n"), ctl_tag, array_attr.tag.idl.target_id, 706711890bcSjc156560 array_attr.tag.idl.lun); 707711890bcSjc156560 708711890bcSjc156560 /* Print attribute of array */ 709711890bcSjc156560 (void) print_array_table(ctl_handle, array_handle); 710711890bcSjc156560 711711890bcSjc156560 /* Close controller */ 712711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 713711890bcSjc156560 714711890bcSjc156560 free(disk_handlesp); 715711890bcSjc156560 return (SUCCESS); 716711890bcSjc156560 } 717711890bcSjc156560 718711890bcSjc156560 /* 719711890bcSjc156560 * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag) 720711890bcSjc156560 * This function creates array with specified arguments, and return result 721711890bcSjc156560 * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller 722711890bcSjc156560 * to be compatible with old raidctl. The capacity and stripe size can't 723711890bcSjc156560 * be specified for LSI MPT controller, and they use zero and default value. 724711890bcSjc156560 * The "ctd" is the canonical expression of physical disks which are 725711890bcSjc156560 * accessible by OS. 726711890bcSjc156560 */ 7277c478bd9Sstevel@tonic-gate static int 728711890bcSjc156560 do_create_ctd(char *raid_levelp, char **disks_argpp, uint32_t disks_num, 729711890bcSjc156560 uint32_t argindex, uint32_t f_flag) 7307c478bd9Sstevel@tonic-gate { 731711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 732711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 733711890bcSjc156560 uint32_t raid_level = RAID_LEVEL_1; 734711890bcSjc156560 uint64_t capacity = 0; 735711890bcSjc156560 uint32_t stripe_size = (uint32_t)OBJ_ATTR_NONE; 736711890bcSjc156560 raid_obj_handle_t *disk_handlesp = NULL; 737711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 738711890bcSjc156560 raidcfg_controller_t ctl_attr; 739711890bcSjc156560 int ret; 740711890bcSjc156560 741711890bcSjc156560 raidcfg_array_t array_attr; 7426fec3791Sjesseb int i, j; 7437c478bd9Sstevel@tonic-gate 744711890bcSjc156560 /* Check disks parameter */ 745711890bcSjc156560 if (disks_argpp == NULL || disks_num < 2) { 7467c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate 749711890bcSjc156560 for (i = 0, j = argindex; i < disks_num; i++, j++) { 750711890bcSjc156560 if (disks_argpp[j] == NULL) { 751711890bcSjc156560 return (INVALID_ARG); 752711890bcSjc156560 } 753711890bcSjc156560 } 7547c478bd9Sstevel@tonic-gate 755711890bcSjc156560 /* 756711890bcSjc156560 * We need check if the raid_level string is fully numeric. If user 757711890bcSjc156560 * input string with unsupported letters, such as "s10", atoi() will 758711890bcSjc156560 * return zero because it is an illegal string, but it doesn't mean 759711890bcSjc156560 * RAID_LEVEL_0. 760711890bcSjc156560 */ 761711890bcSjc156560 if (raid_levelp != NULL) { 762711890bcSjc156560 if (*raid_levelp == '1' && 763711890bcSjc156560 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) { 764711890bcSjc156560 raid_level = RAID_LEVEL_1E; 765711890bcSjc156560 } else { 766711890bcSjc156560 if (is_fully_numeric(raid_levelp) == FALSE) { 767711890bcSjc156560 return (INVALID_ARG); 768711890bcSjc156560 } 769711890bcSjc156560 770711890bcSjc156560 switch (atoi(raid_levelp)) { 771711890bcSjc156560 case 0: 772711890bcSjc156560 raid_level = RAID_LEVEL_0; 773711890bcSjc156560 break; 774711890bcSjc156560 case 1: 775711890bcSjc156560 raid_level = RAID_LEVEL_1; 776711890bcSjc156560 break; 777711890bcSjc156560 case 5: 778711890bcSjc156560 raid_level = RAID_LEVEL_5; 779711890bcSjc156560 break; 780711890bcSjc156560 default: 781711890bcSjc156560 return (INVALID_ARG); 782711890bcSjc156560 } 783711890bcSjc156560 } 784711890bcSjc156560 } 785711890bcSjc156560 786711890bcSjc156560 /* Get disks tag and controller tag */ 787711890bcSjc156560 disk_handlesp = (raid_obj_handle_t *)calloc(disks_num + 2, 788711890bcSjc156560 sizeof (raid_obj_handle_t)); 789711890bcSjc156560 if (disk_handlesp == NULL) { 7907c478bd9Sstevel@tonic-gate return (FAILURE); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 793711890bcSjc156560 disk_handlesp[0] = OBJ_SEPARATOR_BEGIN; 794711890bcSjc156560 disk_handlesp[disks_num + 1] = OBJ_SEPARATOR_END; 795711890bcSjc156560 796711890bcSjc156560 if ((ret = get_disk_handle_ctd(disks_num, &disks_argpp[argindex], 797711890bcSjc156560 &ctl_tag, &disk_handlesp[1])) != SUCCESS) { 798711890bcSjc156560 free(disk_handlesp); 799711890bcSjc156560 return (ret); 800711890bcSjc156560 } 801711890bcSjc156560 802711890bcSjc156560 /* LIB API should check whether all disks here belong to one ctl. */ 803711890bcSjc156560 /* get_disk_handle_ctd has opened controller. */ 804711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 805711890bcSjc156560 806711890bcSjc156560 if (ctl_handle <= 0) { 807711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 808711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 809711890bcSjc156560 free(disk_handlesp); 8107c478bd9Sstevel@tonic-gate return (FAILURE); 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 813711890bcSjc156560 /* Check if the controller is host raid type */ 814711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 815711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 816711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 817711890bcSjc156560 free(disk_handlesp); 818711890bcSjc156560 return (FAILURE); 8196fec3791Sjesseb } 8206fec3791Sjesseb 821711890bcSjc156560 if ((ctl_attr.capability & RAID_CAP_DISK_TRANS) == 0) { 822711890bcSjc156560 /* -c only support host raid controller, return failure here */ 823711890bcSjc156560 (void) fprintf(stderr, 824711890bcSjc156560 gettext("Option -c only supports host raid controller.\n")); 825711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 826711890bcSjc156560 free(disk_handlesp); 827711890bcSjc156560 return (FAILURE); 8287c478bd9Sstevel@tonic-gate } 829711890bcSjc156560 830711890bcSjc156560 if (f_flag == FALSE) { 831711890bcSjc156560 (void) fprintf(stdout, gettext("Creating RAID volume " 832711890bcSjc156560 "will destroy all data on spare space of member disks, " 833711890bcSjc156560 "proceed (%s/%s)? "), yesstr, nostr); 834711890bcSjc156560 if (!yes()) { 835711890bcSjc156560 (void) fprintf(stdout, gettext("RAID volume " 836711890bcSjc156560 "not created.\n\n")); 837711890bcSjc156560 free(disk_handlesp); 838711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 839711890bcSjc156560 return (SUCCESS); 840711890bcSjc156560 } 841711890bcSjc156560 } 842711890bcSjc156560 843711890bcSjc156560 /* 844711890bcSjc156560 * For old raidctl, capacity is 0, which means to creates 845711890bcSjc156560 * max possible capacity of array. 846711890bcSjc156560 */ 847711890bcSjc156560 848711890bcSjc156560 array_handle = raidcfg_create_array(disks_num + 2, 849711890bcSjc156560 disk_handlesp, raid_level, capacity, stripe_size, NULL); 850711890bcSjc156560 851711890bcSjc156560 if (array_handle <= 0) { 852711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 853711890bcSjc156560 free(disk_handlesp); 854711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 855711890bcSjc156560 return (FAILURE); 856711890bcSjc156560 } 857711890bcSjc156560 858711890bcSjc156560 /* Get attribute of array */ 859711890bcSjc156560 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 860711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 861711890bcSjc156560 free(disk_handlesp); 862711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 863711890bcSjc156560 return (FAILURE); 864711890bcSjc156560 } 865711890bcSjc156560 866711890bcSjc156560 /* Close controller */ 867711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 868711890bcSjc156560 869711890bcSjc156560 /* Print feedback for user */ 870711890bcSjc156560 (void) fprintf(stdout, 871711890bcSjc156560 gettext("Volume c%ut%llud%llu is created successfully!\n"), 872711890bcSjc156560 ctl_tag, array_attr.tag.idl.target_id, 873711890bcSjc156560 array_attr.tag.idl.lun); 874711890bcSjc156560 free(disk_handlesp); 875711890bcSjc156560 return (SUCCESS); 876711890bcSjc156560 } 877711890bcSjc156560 878711890bcSjc156560 /* 879711890bcSjc156560 * do_list(disk_arg, argv, optind, is_snapshot) 880711890bcSjc156560 * This function lists RAID's system configuration. It supports various RAID 881711890bcSjc156560 * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG. 882711890bcSjc156560 */ 883711890bcSjc156560 static int 884711890bcSjc156560 do_list(char *disk_argp, char **argv, uint32_t optind, uint8_t is_snapshot) 885711890bcSjc156560 { 886711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 887711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 888711890bcSjc156560 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 889711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 890711890bcSjc156560 disk_tag_t disk_tag; 891711890bcSjc156560 array_tag_t array_tag; 892711890bcSjc156560 893711890bcSjc156560 int ret; 894711890bcSjc156560 895711890bcSjc156560 /* print RAID system */ 896711890bcSjc156560 if (disk_argp == NULL) { 897711890bcSjc156560 if (argv[optind] == NULL) { 898711890bcSjc156560 ret = snapshot_raidsystem(TRUE, 0, is_snapshot); 899711890bcSjc156560 return (ret); 900711890bcSjc156560 } else { 901711890bcSjc156560 if (is_fully_numeric(argv[optind]) == TRUE) { 902711890bcSjc156560 while (argv[optind] != NULL) { 903711890bcSjc156560 if (get_ctl_tag(argv[optind], &ctl_tag) 904711890bcSjc156560 != SUCCESS) { 905711890bcSjc156560 ret = INVALID_ARG; 906711890bcSjc156560 optind++; 9076fec3791Sjesseb continue; 9086fec3791Sjesseb } 909711890bcSjc156560 ctl_handle = 910711890bcSjc156560 raidcfg_get_controller(ctl_tag); 911711890bcSjc156560 if (ctl_handle <= 0) { 912711890bcSjc156560 (void) fprintf(stderr, "%s\n", 913711890bcSjc156560 raidcfg_errstr(ctl_handle)); 914711890bcSjc156560 ret = FAILURE; 915711890bcSjc156560 optind++; 916711890bcSjc156560 continue; 9176fec3791Sjesseb } 918711890bcSjc156560 ret = 919711890bcSjc156560 raidcfg_open_controller(ctl_handle, 920711890bcSjc156560 NULL); 921711890bcSjc156560 if (ret < 0) { 922711890bcSjc156560 (void) fprintf(stderr, "%s\n", 923711890bcSjc156560 raidcfg_errstr(ret)); 924711890bcSjc156560 ret = FAILURE; 925711890bcSjc156560 optind++; 926711890bcSjc156560 continue; 9276fec3791Sjesseb } 928711890bcSjc156560 if (is_snapshot == FALSE) { 929711890bcSjc156560 ret = 930711890bcSjc156560 print_ctl_table(ctl_handle); 931711890bcSjc156560 } else { 932711890bcSjc156560 ret = 933711890bcSjc156560 snapshot_ctl(ctl_handle, 934711890bcSjc156560 FALSE, 0, is_snapshot); 9357c478bd9Sstevel@tonic-gate } 936711890bcSjc156560 (void) raidcfg_close_controller( 937711890bcSjc156560 ctl_handle, NULL); 938711890bcSjc156560 optind++; 9397c478bd9Sstevel@tonic-gate } 940711890bcSjc156560 } else { 941711890bcSjc156560 if (get_array_tag(argv[optind], 942711890bcSjc156560 &ctl_tag, &array_tag) != SUCCESS) { 9436fec3791Sjesseb return (INVALID_ARG); 9446fec3791Sjesseb } 945711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 946711890bcSjc156560 if (ctl_handle <= 0) { 947711890bcSjc156560 (void) fprintf(stderr, "%s\n", 948711890bcSjc156560 raidcfg_errstr(ctl_handle)); 9497c478bd9Sstevel@tonic-gate return (FAILURE); 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 952711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 953711890bcSjc156560 if (ret < 0) { 954711890bcSjc156560 (void) fprintf(stderr, "%s\n", 955711890bcSjc156560 raidcfg_errstr(ret)); 956711890bcSjc156560 return (FAILURE); 957711890bcSjc156560 } 958711890bcSjc156560 959711890bcSjc156560 array_handle = raidcfg_get_array(ctl_handle, 960711890bcSjc156560 array_tag.idl.target_id, array_tag.idl.lun); 961711890bcSjc156560 if (array_handle <= 0) { 962711890bcSjc156560 (void) fprintf(stderr, "%s\n", 963711890bcSjc156560 raidcfg_errstr(array_handle)); 964711890bcSjc156560 (void) raidcfg_close_controller( 965711890bcSjc156560 ctl_handle, NULL); 966711890bcSjc156560 return (FAILURE); 967711890bcSjc156560 } 968711890bcSjc156560 if (is_snapshot == FALSE) { 969711890bcSjc156560 ret = print_array_table(ctl_handle, 970711890bcSjc156560 array_handle); 971711890bcSjc156560 } else { 972711890bcSjc156560 ret = snapshot_array(array_handle, 0, 973711890bcSjc156560 FALSE, is_snapshot); 974711890bcSjc156560 } 975711890bcSjc156560 (void) raidcfg_close_controller( 976711890bcSjc156560 ctl_handle, NULL); 977711890bcSjc156560 } 978711890bcSjc156560 } 979711890bcSjc156560 } else { 980711890bcSjc156560 if (argv[optind + 1] != NULL) { 981711890bcSjc156560 return (INVALID_ARG); 982711890bcSjc156560 } 983711890bcSjc156560 984711890bcSjc156560 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 985711890bcSjc156560 return (INVALID_ARG); 986711890bcSjc156560 } 987711890bcSjc156560 988711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 989711890bcSjc156560 if (ctl_handle <= 0) { 990711890bcSjc156560 (void) fprintf(stderr, "%s\n", 991711890bcSjc156560 raidcfg_errstr(ctl_handle)); 992711890bcSjc156560 return (FAILURE); 993711890bcSjc156560 } 994711890bcSjc156560 995711890bcSjc156560 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 996711890bcSjc156560 return (INVALID_ARG); 997711890bcSjc156560 } 998711890bcSjc156560 999711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1000711890bcSjc156560 if (ret < 0) { 1001711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1002711890bcSjc156560 raidcfg_errstr(ret)); 1003711890bcSjc156560 return (FAILURE); 1004711890bcSjc156560 } 1005711890bcSjc156560 1006711890bcSjc156560 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1007711890bcSjc156560 if (disk_handle <= 0) { 1008711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1009711890bcSjc156560 raidcfg_errstr(disk_handle)); 1010711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1011711890bcSjc156560 return (FAILURE); 1012711890bcSjc156560 } 1013711890bcSjc156560 1014711890bcSjc156560 if (is_snapshot == FALSE) { 1015711890bcSjc156560 ret = print_disk_table(ctl_handle, disk_handle); 1016711890bcSjc156560 } else { 1017711890bcSjc156560 ret = snapshot_disk(ctl_tag, disk_handle, 0, 1018711890bcSjc156560 is_snapshot); 1019711890bcSjc156560 } 1020711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1021711890bcSjc156560 } 1022711890bcSjc156560 return (ret); 1023711890bcSjc156560 } 1024711890bcSjc156560 1025711890bcSjc156560 /* 1026711890bcSjc156560 * do_delete(f_flag, argv, optind) 1027711890bcSjc156560 * This function deletes a specified array, and return result as SUCCESS, 1028711890bcSjc156560 * FAILURE or INVALID_ARG. 1029711890bcSjc156560 */ 1030711890bcSjc156560 static int 1031711890bcSjc156560 do_delete(uint32_t f_flag, char **argv, uint32_t optind) 1032711890bcSjc156560 { 1033711890bcSjc156560 uint32_t ctl_tag; 1034711890bcSjc156560 char *array_argp; 1035711890bcSjc156560 array_tag_t array_tag; 1036711890bcSjc156560 raid_obj_handle_t ctl_handle; 1037711890bcSjc156560 raid_obj_handle_t array_handle; 1038711890bcSjc156560 int ret; 1039711890bcSjc156560 1040711890bcSjc156560 array_argp = argv[optind]; 1041711890bcSjc156560 if (array_argp == NULL || argv[optind + 1] != NULL) { 1042711890bcSjc156560 return (INVALID_ARG); 1043711890bcSjc156560 } 1044711890bcSjc156560 1045711890bcSjc156560 if (get_array_tag(array_argp, &ctl_tag, &array_tag) != SUCCESS) { 1046711890bcSjc156560 return (INVALID_ARG); 1047711890bcSjc156560 } 1048711890bcSjc156560 1049711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1050711890bcSjc156560 if (ctl_handle <= 0) { 1051711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 1052711890bcSjc156560 return (INVALID_ARG); 1053711890bcSjc156560 } 1054711890bcSjc156560 1055711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1056711890bcSjc156560 if (ret < 0) { 1057711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1058711890bcSjc156560 return (FAILURE); 1059711890bcSjc156560 } 1060711890bcSjc156560 1061711890bcSjc156560 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id, 1062711890bcSjc156560 array_tag.idl.lun); 1063711890bcSjc156560 if (array_handle <= 0) { 1064711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 1065711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1066711890bcSjc156560 return (FAILURE); 1067711890bcSjc156560 } 1068711890bcSjc156560 1069711890bcSjc156560 if (f_flag == FALSE) { 1070711890bcSjc156560 (void) fprintf(stdout, gettext("Deleting RAID volume " 1071711890bcSjc156560 "%s will destroy all data it contains, " 1072711890bcSjc156560 "proceed (%s/%s)? "), array_argp, yesstr, nostr); 1073711890bcSjc156560 if (!yes()) { 1074711890bcSjc156560 (void) fprintf(stdout, gettext("RAID Volume " 1075711890bcSjc156560 "%s not deleted.\n\n"), array_argp); 1076711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1077711890bcSjc156560 return (SUCCESS); 1078711890bcSjc156560 } 1079711890bcSjc156560 } 1080711890bcSjc156560 1081711890bcSjc156560 1082711890bcSjc156560 if ((ret = raidcfg_delete_array(array_handle, NULL)) < 0) { 1083711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1084711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1085711890bcSjc156560 return (FAILURE); 1086711890bcSjc156560 } 1087711890bcSjc156560 1088711890bcSjc156560 (void) fprintf(stdout, gettext("Volume %s is deleted successfully!\n"), 1089711890bcSjc156560 array_argp); 1090711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1091711890bcSjc156560 1092711890bcSjc156560 return (SUCCESS); 1093711890bcSjc156560 } 1094711890bcSjc156560 1095711890bcSjc156560 /* 1096711890bcSjc156560 * do_flash(f_flag, filep, ctls_argpp, index, ctl_num) 1097711890bcSjc156560 * This function downloads and updates firmware for specified controller, and 1098711890bcSjc156560 * return result as SUCCESS, FAILURE or INVALID_ARG. 1099711890bcSjc156560 */ 1100711890bcSjc156560 static int 1101711890bcSjc156560 do_flash(uint8_t f_flag, char *filep, char **ctls_argpp, 1102711890bcSjc156560 uint32_t index, uint32_t ctl_num) 1103711890bcSjc156560 { 1104711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 1105711890bcSjc156560 char *ctl_argp = NULL; 1106711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1107711890bcSjc156560 int ret; 1108711890bcSjc156560 int i, j; 1109711890bcSjc156560 1110711890bcSjc156560 if (ctl_num == 0) 1111711890bcSjc156560 return (INVALID_ARG); 1112711890bcSjc156560 1113711890bcSjc156560 for (i = 0, j = index; i < ctl_num; i++, j++) { 1114711890bcSjc156560 ctl_argp = ctls_argpp[j]; 1115711890bcSjc156560 if (get_ctl_tag(ctl_argp, &ctl_tag) != SUCCESS) { 1116711890bcSjc156560 return (INVALID_ARG); 1117711890bcSjc156560 } 1118711890bcSjc156560 1119711890bcSjc156560 /* Ask user to confirm operation. */ 1120711890bcSjc156560 if (f_flag == FALSE) { 1121711890bcSjc156560 (void) fprintf(stdout, gettext("Update flash image on " 1122711890bcSjc156560 "controller %d (%s/%s)? "), ctl_tag, yesstr, nostr); 1123711890bcSjc156560 if (!yes()) { 1124711890bcSjc156560 (void) fprintf(stdout, 1125711890bcSjc156560 gettext("Controller %d not " 1126711890bcSjc156560 "flashed.\n\n"), ctl_tag); 1127711890bcSjc156560 return (SUCCESS); 1128711890bcSjc156560 } 1129711890bcSjc156560 } 1130711890bcSjc156560 1131711890bcSjc156560 if ((ctl_handle = raidcfg_get_controller(ctl_tag)) < 0) { 1132711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1133711890bcSjc156560 raidcfg_errstr(ctl_handle)); 1134711890bcSjc156560 return (FAILURE); 1135711890bcSjc156560 } 1136711890bcSjc156560 1137711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1138711890bcSjc156560 if (ret < 0) { 1139711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1140711890bcSjc156560 return (FAILURE); 1141711890bcSjc156560 } 1142711890bcSjc156560 1143711890bcSjc156560 (void) fprintf(stdout, gettext("Start updating controller " 1144711890bcSjc156560 "c%u firmware....\n"), ctl_tag); 1145711890bcSjc156560 1146711890bcSjc156560 if ((ret = raidcfg_update_fw(ctl_handle, filep, NULL)) < 0) { 1147711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1148711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1149711890bcSjc156560 return (FAILURE); 1150711890bcSjc156560 } 1151711890bcSjc156560 1152711890bcSjc156560 (void) fprintf(stdout, gettext("Update controller " 1153711890bcSjc156560 "c%u firmware successfully.\n"), ctl_tag); 1154711890bcSjc156560 1155711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1156711890bcSjc156560 } 1157711890bcSjc156560 1158711890bcSjc156560 return (SUCCESS); 1159711890bcSjc156560 } 1160711890bcSjc156560 1161711890bcSjc156560 /* 1162711890bcSjc156560 * do_set_hsp(a_argp, disk_argp, argv, optind) 1163711890bcSjc156560 * This function set or unset HSP relationship between disk and controller/ 1164711890bcSjc156560 * array, and return result as SUCCESS, FAILURE or INVALID_ARG. 1165711890bcSjc156560 */ 1166711890bcSjc156560 static int 1167711890bcSjc156560 do_set_hsp(char *a_argp, char *disk_argp, char **argv, uint32_t optind) 1168711890bcSjc156560 { 1169711890bcSjc156560 uint32_t flag = MAX32BIT; 1170711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 1171711890bcSjc156560 array_tag_t array_tag; 1172711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1173711890bcSjc156560 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 1174711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1175711890bcSjc156560 raidcfg_controller_t ctl_attr; 1176711890bcSjc156560 disk_tag_t disk_tag; 1177711890bcSjc156560 1178711890bcSjc156560 int ret; 1179711890bcSjc156560 int hsp_type; 1180711890bcSjc156560 raidcfg_hsp_relation_t hsp_relation; 1181711890bcSjc156560 1182711890bcSjc156560 (void) memset(&hsp_relation, 0, sizeof (raidcfg_hsp_relation_t)); 1183711890bcSjc156560 1184711890bcSjc156560 if (a_argp == NULL) { 1185711890bcSjc156560 return (INVALID_ARG); 1186711890bcSjc156560 } 1187711890bcSjc156560 1188711890bcSjc156560 if (strcmp(a_argp, "set") == 0) { 1189711890bcSjc156560 flag = HSP_SET; 1190711890bcSjc156560 } else if (strcmp(a_argp, "unset") == 0) { 1191711890bcSjc156560 flag = HSP_UNSET; 1192711890bcSjc156560 } else { 1193711890bcSjc156560 return (INVALID_ARG); 1194711890bcSjc156560 } 1195711890bcSjc156560 1196711890bcSjc156560 if (disk_argp == NULL) { 1197711890bcSjc156560 return (INVALID_ARG); 1198711890bcSjc156560 } 1199711890bcSjc156560 1200711890bcSjc156560 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 1201711890bcSjc156560 return (INVALID_ARG); 1202711890bcSjc156560 } else if (is_fully_numeric(argv[optind]) == TRUE) { 1203711890bcSjc156560 /* Global HSP */ 1204711890bcSjc156560 hsp_type = 0; 1205711890bcSjc156560 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 1206711890bcSjc156560 return (INVALID_ARG); 1207711890bcSjc156560 } 1208711890bcSjc156560 1209711890bcSjc156560 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 1210711890bcSjc156560 return (INVALID_ARG); 1211711890bcSjc156560 } 1212711890bcSjc156560 1213711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1214711890bcSjc156560 if (ctl_handle <= 0) { 1215711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1216711890bcSjc156560 raidcfg_errstr(ctl_handle)); 1217711890bcSjc156560 return (FAILURE); 1218711890bcSjc156560 } 1219711890bcSjc156560 1220711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1221711890bcSjc156560 if (ret < 0) { 1222711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1223711890bcSjc156560 return (FAILURE); 1224711890bcSjc156560 } 1225711890bcSjc156560 1226711890bcSjc156560 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1227711890bcSjc156560 if (disk_handle <= 0) { 1228711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1229711890bcSjc156560 raidcfg_errstr(disk_handle)); 1230711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1231711890bcSjc156560 return (FAILURE); 1232711890bcSjc156560 } 1233711890bcSjc156560 } else { 1234711890bcSjc156560 /* Local HSP */ 1235711890bcSjc156560 hsp_type = 1; 1236711890bcSjc156560 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != 1237711890bcSjc156560 SUCCESS) { 1238711890bcSjc156560 return (INVALID_ARG); 1239711890bcSjc156560 } 1240711890bcSjc156560 1241711890bcSjc156560 /* Open controller */ 1242711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1243711890bcSjc156560 if (ctl_handle <= 0) { 1244711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1245711890bcSjc156560 raidcfg_errstr(ctl_handle)); 1246711890bcSjc156560 return (FAILURE); 1247711890bcSjc156560 } 1248711890bcSjc156560 1249711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1250711890bcSjc156560 if (ret < 0) { 1251711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1252711890bcSjc156560 return (FAILURE); 1253711890bcSjc156560 } 1254711890bcSjc156560 1255711890bcSjc156560 /* Get controller's attribute */ 1256711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1257711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1258711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1259711890bcSjc156560 return (FAILURE); 1260711890bcSjc156560 } 1261711890bcSjc156560 1262711890bcSjc156560 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 1263711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1264711890bcSjc156560 return (INVALID_ARG); 1265711890bcSjc156560 } 1266711890bcSjc156560 1267711890bcSjc156560 /* Get disk handle */ 1268711890bcSjc156560 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1269711890bcSjc156560 if (disk_handle <= 0) { 1270711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1271711890bcSjc156560 raidcfg_errstr(disk_handle)); 1272711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1273711890bcSjc156560 return (FAILURE); 1274711890bcSjc156560 } 1275711890bcSjc156560 1276711890bcSjc156560 /* Get array handle */ 1277711890bcSjc156560 array_handle = raidcfg_get_array(ctl_handle, 1278711890bcSjc156560 array_tag.idl.target_id, array_tag.idl.lun); 1279711890bcSjc156560 if (array_handle <= 0) { 1280711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1281711890bcSjc156560 raidcfg_errstr(array_handle)); 1282711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1283711890bcSjc156560 return (FAILURE); 1284711890bcSjc156560 } 1285711890bcSjc156560 } 1286711890bcSjc156560 1287711890bcSjc156560 hsp_relation.disk_handle = disk_handle; 1288711890bcSjc156560 if (hsp_type) { 1289711890bcSjc156560 /* Set or unset local HSP */ 1290711890bcSjc156560 hsp_relation.array_handle = array_handle; 1291711890bcSjc156560 } else { 1292711890bcSjc156560 /* Set or unset global HSP */ 1293711890bcSjc156560 hsp_relation.array_handle = OBJ_ATTR_NONE; 1294711890bcSjc156560 } 1295711890bcSjc156560 1296711890bcSjc156560 /* Perform operation of set or unset */ 1297711890bcSjc156560 if (flag == HSP_SET) { 12985c9d25d2SYu-Bo Ryan Wang if ((ret = raidcfg_set_hsp(&hsp_relation, NULL)) < 0) { 1299711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1300711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1301711890bcSjc156560 return (FAILURE); 1302711890bcSjc156560 } 1303711890bcSjc156560 1304711890bcSjc156560 if (hsp_type) { 1305711890bcSjc156560 (void) printf(gettext("Set local HSP between disk %s " 1306711890bcSjc156560 "and RAID volume %s successfully.\n"), 1307711890bcSjc156560 disk_argp, argv[optind]); 1308711890bcSjc156560 } else { 1309711890bcSjc156560 (void) printf(gettext("Set global HSP between disk %s " 1310711890bcSjc156560 "and controller %s successfully.\n"), 1311711890bcSjc156560 disk_argp, argv[optind]); 1312711890bcSjc156560 } 1313711890bcSjc156560 } else { 13145c9d25d2SYu-Bo Ryan Wang if ((ret = raidcfg_unset_hsp(&hsp_relation, NULL)) < 0) { 1315711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1316711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1317711890bcSjc156560 return (FAILURE); 1318711890bcSjc156560 } 1319711890bcSjc156560 1320711890bcSjc156560 if (hsp_type) { 1321711890bcSjc156560 (void) printf(gettext("Unset local HSP between " 1322711890bcSjc156560 "disk %s and RAID volume %s successfully.\n"), 1323711890bcSjc156560 disk_argp, argv[optind]); 1324711890bcSjc156560 } else { 1325711890bcSjc156560 (void) printf(gettext("Unset global HSP between " 1326711890bcSjc156560 "disk %s and controller %s successfully.\n"), 1327711890bcSjc156560 disk_argp, argv[optind]); 1328711890bcSjc156560 } 1329711890bcSjc156560 } 1330711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1331711890bcSjc156560 return (SUCCESS); 1332711890bcSjc156560 } 1333711890bcSjc156560 1334711890bcSjc156560 /* 1335711890bcSjc156560 * do_set_array_attr(f_flag, p_argp, argv, optind) 1336711890bcSjc156560 * This function changes array's attribute when array is running. 1337711890bcSjc156560 * The changeable attribute is up to controller's feature. 1338711890bcSjc156560 * The return value can be SUCCESS, FAILURE or INVALID_ARG. 1339711890bcSjc156560 */ 1340711890bcSjc156560 static int 1341711890bcSjc156560 do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, uint32_t optind) 1342711890bcSjc156560 { 1343711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 1344711890bcSjc156560 array_tag_t array_tag; 1345711890bcSjc156560 uint32_t type = MAX32BIT; 1346711890bcSjc156560 uint32_t value = MAX32BIT; 1347711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1348711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1349711890bcSjc156560 1350711890bcSjc156560 char *param, *op = "="; 1351711890bcSjc156560 1352711890bcSjc156560 int ret; 1353711890bcSjc156560 1354711890bcSjc156560 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 1355711890bcSjc156560 return (INVALID_ARG); 1356711890bcSjc156560 } 1357711890bcSjc156560 1358711890bcSjc156560 if (p_argp != NULL) { 1359711890bcSjc156560 param = strtok(p_argp, op); 1360711890bcSjc156560 if (strcmp(param, "wp") == 0) { 1361711890bcSjc156560 type = SET_CACHE_WR_PLY; 1362711890bcSjc156560 param = strtok(NULL, op); 1363711890bcSjc156560 if (strcmp(param, "on") == 0) { 1364711890bcSjc156560 value = CACHE_WR_ON; 1365711890bcSjc156560 } else if (strcmp(param, "off") == 0) { 1366711890bcSjc156560 value = CACHE_WR_OFF; 1367711890bcSjc156560 } else { 1368711890bcSjc156560 return (INVALID_ARG); 1369711890bcSjc156560 } 1370b449fa8aSyw161884 } else if (strcmp(param, "state") == 0) { 1371b449fa8aSyw161884 type = SET_ACTIVATION_PLY; 1372b449fa8aSyw161884 param = strtok(NULL, op); 1373b449fa8aSyw161884 if (strcmp(param, "activate") == 0) { 1374b449fa8aSyw161884 value = ARRAY_ACT_ACTIVATE; 1375b449fa8aSyw161884 } else { 1376b449fa8aSyw161884 return (INVALID_ARG); 1377b449fa8aSyw161884 } 1378b449fa8aSyw161884 } else { 1379b449fa8aSyw161884 return (INVALID_ARG); 1380b449fa8aSyw161884 } 1381711890bcSjc156560 } else { 1382711890bcSjc156560 return (INVALID_ARG); 1383711890bcSjc156560 } 1384711890bcSjc156560 1385711890bcSjc156560 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != SUCCESS) { 1386711890bcSjc156560 return (INVALID_ARG); 1387711890bcSjc156560 } 1388711890bcSjc156560 1389711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1390711890bcSjc156560 if (ctl_handle <= 0) { 1391711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 1392711890bcSjc156560 return (FAILURE); 1393711890bcSjc156560 } 1394711890bcSjc156560 1395711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1396711890bcSjc156560 if (ret < 0) { 1397711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1398711890bcSjc156560 return (FAILURE); 1399711890bcSjc156560 } 1400711890bcSjc156560 1401711890bcSjc156560 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id, 1402711890bcSjc156560 array_tag.idl.lun); 1403711890bcSjc156560 if (array_handle <= 0) { 1404711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 1405711890bcSjc156560 return (FAILURE); 1406711890bcSjc156560 } 1407711890bcSjc156560 1408711890bcSjc156560 /* Ask user to confirm operation. */ 1409711890bcSjc156560 if (f_flag == FALSE) { 1410711890bcSjc156560 (void) fprintf(stdout, gettext("Update attribute of " 1411711890bcSjc156560 "array %s (%s/%s)? "), argv[optind], yesstr, nostr); 1412711890bcSjc156560 if (!yes()) { 1413711890bcSjc156560 (void) fprintf(stdout, 1414711890bcSjc156560 gettext("Array %s not " 1415711890bcSjc156560 "changed.\n\n"), argv[optind]); 1416711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1417711890bcSjc156560 return (SUCCESS); 1418711890bcSjc156560 } 1419711890bcSjc156560 } 1420711890bcSjc156560 1421711890bcSjc156560 if ((ret = raidcfg_set_attr(array_handle, type, &value, NULL)) < 0) { 1422711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1423711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1424711890bcSjc156560 return (FAILURE); 1425711890bcSjc156560 } 1426711890bcSjc156560 1427711890bcSjc156560 (void) printf(gettext("Set attribute of RAID volume %s " 1428711890bcSjc156560 "successfully.\n"), argv[optind]); 1429711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1430711890bcSjc156560 1431711890bcSjc156560 return (SUCCESS); 1432711890bcSjc156560 } 1433711890bcSjc156560 1434711890bcSjc156560 /* 1435711890bcSjc156560 * snapshot_raidsystem(recursive, indent, is_snapshot) 1436711890bcSjc156560 * This function prints the snapshot of whole RAID's system configuration, 1437711890bcSjc156560 * and return result as SUCCESS or FAILURE. 1438711890bcSjc156560 */ 1439711890bcSjc156560 static int 1440711890bcSjc156560 snapshot_raidsystem(uint8_t recursive, uint8_t indent, uint8_t is_snapshot) 1441711890bcSjc156560 { 1442711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1443711890bcSjc156560 int ret; 1444711890bcSjc156560 1445711890bcSjc156560 ctl_handle = raidcfg_list_head(OBJ_SYSTEM, OBJ_TYPE_CONTROLLER); 1446711890bcSjc156560 while (ctl_handle > 0) { 1447711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1448711890bcSjc156560 if (ret == 0) { 1449711890bcSjc156560 if (snapshot_ctl(ctl_handle, recursive, indent, 1450711890bcSjc156560 is_snapshot) == FAILURE) { 1451711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, 1452711890bcSjc156560 NULL); 1453711890bcSjc156560 } 1454711890bcSjc156560 } 1455711890bcSjc156560 ctl_handle = raidcfg_list_next(ctl_handle); 1456711890bcSjc156560 } 1457711890bcSjc156560 return (SUCCESS); 1458711890bcSjc156560 } 1459711890bcSjc156560 1460711890bcSjc156560 /* 1461711890bcSjc156560 * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot) 1462711890bcSjc156560 * This function prints snapshot of specified controller's configuration, 1463711890bcSjc156560 * and return result as SUCCESS or FAILURE. 1464711890bcSjc156560 */ 1465711890bcSjc156560 static int 1466711890bcSjc156560 snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, uint8_t indent, 1467711890bcSjc156560 uint8_t is_snapshot) 1468711890bcSjc156560 { 1469711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1470711890bcSjc156560 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 1471711890bcSjc156560 raidcfg_controller_t ctl_attr; 1472711890bcSjc156560 uint32_t ctl_tag; 1473711890bcSjc156560 char ctlbuf[256]; 1474711890bcSjc156560 int ret; 1475711890bcSjc156560 1476711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1477711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1478711890bcSjc156560 return (FAILURE); 1479711890bcSjc156560 } 1480711890bcSjc156560 1481711890bcSjc156560 ctl_tag = ctl_attr.controller_id; 1482711890bcSjc156560 if (is_snapshot == FALSE) { 1483711890bcSjc156560 print_indent(indent); 1484711890bcSjc156560 (void) fprintf(stdout, gettext("Controller: %u\n"), ctl_tag); 1485711890bcSjc156560 } else { 1486711890bcSjc156560 (void) snprintf(ctlbuf, sizeof (ctlbuf), "%u \"%s\"", 1487711890bcSjc156560 ctl_tag, ctl_attr.controller_type); 1488711890bcSjc156560 (void) fprintf(stdout, "%s", ctlbuf); 1489711890bcSjc156560 1490711890bcSjc156560 (void) fprintf(stdout, "\n"); 1491711890bcSjc156560 } 1492711890bcSjc156560 1493711890bcSjc156560 if (recursive == TRUE) { 1494711890bcSjc156560 array_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_ARRAY); 1495711890bcSjc156560 while (array_handle > 0) { 1496711890bcSjc156560 if (snapshot_array(array_handle, 1497711890bcSjc156560 indent + 1, FALSE, is_snapshot) == FAILURE) { 1498711890bcSjc156560 return (FAILURE); 1499711890bcSjc156560 } 1500711890bcSjc156560 1501711890bcSjc156560 array_handle = raidcfg_list_next(array_handle); 1502711890bcSjc156560 } 1503711890bcSjc156560 1504711890bcSjc156560 disk_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_DISK); 1505711890bcSjc156560 while (disk_handle > 0) { 1506711890bcSjc156560 if (snapshot_disk(ctl_tag, disk_handle, 1507711890bcSjc156560 indent + 1, is_snapshot) == FAILURE) { 1508711890bcSjc156560 return (FAILURE); 1509711890bcSjc156560 } 1510711890bcSjc156560 1511711890bcSjc156560 disk_handle = raidcfg_list_next(disk_handle); 1512711890bcSjc156560 } 1513711890bcSjc156560 } 1514711890bcSjc156560 return (SUCCESS); 1515711890bcSjc156560 } 1516711890bcSjc156560 1517711890bcSjc156560 1518711890bcSjc156560 /* 1519711890bcSjc156560 * snapshot_array(array_handle, indent, is_sub, is_snapshot) 1520711890bcSjc156560 * This function prints snapshot of specified array's configuration, 1521711890bcSjc156560 * and return result as SUCCESS or FAILURE. 1522711890bcSjc156560 */ 1523711890bcSjc156560 static int 1524711890bcSjc156560 snapshot_array(raid_obj_handle_t array_handle, uint8_t indent, uint8_t is_sub, 1525711890bcSjc156560 uint8_t is_snapshot) 1526711890bcSjc156560 { 1527711890bcSjc156560 raid_obj_handle_t ctl_handle; 1528711890bcSjc156560 raid_obj_handle_t subarray_handle; 1529711890bcSjc156560 raid_obj_handle_t arraypart_handle; 1530711890bcSjc156560 raid_obj_handle_t task_handle; 1531711890bcSjc156560 1532711890bcSjc156560 raidcfg_controller_t ctl_attr; 1533711890bcSjc156560 raidcfg_array_t array_attr; 1534711890bcSjc156560 raidcfg_arraypart_t arraypart_attr; 1535711890bcSjc156560 raidcfg_task_t task_attr; 1536711890bcSjc156560 1537711890bcSjc156560 char arraybuf[256] = "\0"; 1538711890bcSjc156560 char diskbuf[256] = "\0"; 1539711890bcSjc156560 char tempbuf[256] = "\0"; 1540711890bcSjc156560 int disknum = 0; 1541711890bcSjc156560 1542711890bcSjc156560 uint32_t ctl_tag; 1543711890bcSjc156560 int ret; 1544711890bcSjc156560 1545711890bcSjc156560 ctl_handle = raidcfg_get_container(array_handle); 1546711890bcSjc156560 ret = raidcfg_get_attr(ctl_handle, &ctl_attr); 1547711890bcSjc156560 if (ret < 0) { 1548711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1549711890bcSjc156560 return (FAILURE); 1550711890bcSjc156560 } 1551711890bcSjc156560 ctl_tag = ctl_attr.controller_id; 1552711890bcSjc156560 1553711890bcSjc156560 /* Print array attribute */ 1554711890bcSjc156560 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 1555711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1556711890bcSjc156560 return (FAILURE); 1557711890bcSjc156560 } 1558711890bcSjc156560 1559711890bcSjc156560 if (is_snapshot == FALSE) { 1560711890bcSjc156560 print_indent(indent); 1561711890bcSjc156560 if (is_sub == FALSE) { 1562711890bcSjc156560 (void) fprintf(stdout, gettext("Volume:" 1563711890bcSjc156560 "c%ut%llud%llu\n"), 1564711890bcSjc156560 ctl_tag, array_attr.tag.idl.target_id, 1565711890bcSjc156560 array_attr.tag.idl.lun); 1566711890bcSjc156560 } else { 1567711890bcSjc156560 (void) fprintf(stdout, gettext("Sub-Volume\n")); 1568711890bcSjc156560 } 1569711890bcSjc156560 } else { 1570711890bcSjc156560 (void) snprintf(arraybuf, sizeof (arraybuf), "c%ut%llud%llu ", 1571711890bcSjc156560 ctl_tag, array_attr.tag.idl.target_id, 1572711890bcSjc156560 array_attr.tag.idl.lun); 1573711890bcSjc156560 1574711890bcSjc156560 /* Check if array is in sync state */ 1575711890bcSjc156560 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK); 1576711890bcSjc156560 if (task_handle > 0) { 1577711890bcSjc156560 (void) raidcfg_get_attr(task_handle, &task_attr); 1578711890bcSjc156560 if (task_attr.task_func == TASK_FUNC_BUILD) { 1579711890bcSjc156560 array_attr.state = ARRAY_STATE_SYNC; 1580711890bcSjc156560 } 1581711890bcSjc156560 } else { 1582711890bcSjc156560 subarray_handle = raidcfg_list_head(array_handle, 1583711890bcSjc156560 OBJ_TYPE_ARRAY); 1584711890bcSjc156560 while (subarray_handle > 0) { 1585711890bcSjc156560 task_handle = raidcfg_list_head(subarray_handle, 1586711890bcSjc156560 OBJ_TYPE_TASK); 1587711890bcSjc156560 if (task_handle > 0) { 1588711890bcSjc156560 (void) raidcfg_get_attr(task_handle, 1589711890bcSjc156560 &task_attr); 1590711890bcSjc156560 if (task_attr.task_func == 1591711890bcSjc156560 TASK_FUNC_BUILD) { 1592711890bcSjc156560 array_attr.state = 1593711890bcSjc156560 ARRAY_STATE_SYNC; 1594711890bcSjc156560 } 1595711890bcSjc156560 break; 1596711890bcSjc156560 } 1597711890bcSjc156560 subarray_handle = 1598711890bcSjc156560 raidcfg_list_next(subarray_handle); 1599711890bcSjc156560 } 1600711890bcSjc156560 } 1601711890bcSjc156560 1602711890bcSjc156560 /* Print sub array */ 1603711890bcSjc156560 subarray_handle = raidcfg_list_head(array_handle, 1604711890bcSjc156560 OBJ_TYPE_ARRAY); 1605711890bcSjc156560 while (subarray_handle > 0) { 1606711890bcSjc156560 /* print subarraypart */ 1607711890bcSjc156560 arraypart_handle = raidcfg_list_head(subarray_handle, 1608711890bcSjc156560 OBJ_TYPE_ARRAY_PART); 1609711890bcSjc156560 while (arraypart_handle > 0) { 1610711890bcSjc156560 if ((ret = raidcfg_get_attr(arraypart_handle, 1611711890bcSjc156560 &arraypart_attr)) < 0) { 1612711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1613711890bcSjc156560 raidcfg_errstr(ret)); 1614711890bcSjc156560 return (FAILURE); 1615711890bcSjc156560 } 1616711890bcSjc156560 1617711890bcSjc156560 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1618711890bcSjc156560 (void) snprintf(tempbuf, 1619711890bcSjc156560 sizeof (tempbuf), 1620711890bcSjc156560 gettext("N/A")); 1621711890bcSjc156560 } else { 1622711890bcSjc156560 (void) snprintf(tempbuf, 1623711890bcSjc156560 sizeof (tempbuf), 1624711890bcSjc156560 "%llu.%llu.%llu", 1625711890bcSjc156560 arraypart_attr.tag.cidl.bus, 1626711890bcSjc156560 arraypart_attr.tag.cidl.target_id, 1627711890bcSjc156560 arraypart_attr.tag.cidl.lun); 1628711890bcSjc156560 } 1629317fb4acSYu-Bo Ryan Wang (void) strlcat(diskbuf, tempbuf, 1630317fb4acSYu-Bo Ryan Wang sizeof (diskbuf)); 1631711890bcSjc156560 (void) strcat(diskbuf, " "); 1632711890bcSjc156560 disknum++; 1633711890bcSjc156560 arraypart_handle = 1634711890bcSjc156560 raidcfg_list_next(arraypart_handle); 1635711890bcSjc156560 } 1636711890bcSjc156560 subarray_handle = raidcfg_list_next(subarray_handle); 1637711890bcSjc156560 } 1638711890bcSjc156560 1639711890bcSjc156560 /* Print arraypart */ 1640711890bcSjc156560 arraypart_handle = raidcfg_list_head(array_handle, 1641711890bcSjc156560 OBJ_TYPE_ARRAY_PART); 1642711890bcSjc156560 while (arraypart_handle > 0) { 1643711890bcSjc156560 if ((ret = raidcfg_get_attr(arraypart_handle, 1644711890bcSjc156560 &arraypart_attr)) < 0) { 1645711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1646711890bcSjc156560 raidcfg_errstr(ret)); 1647711890bcSjc156560 return (FAILURE); 1648711890bcSjc156560 } 1649711890bcSjc156560 1650711890bcSjc156560 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1651711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1652711890bcSjc156560 gettext("N/A")); 1653711890bcSjc156560 } else { 1654711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1655711890bcSjc156560 "%llu.%llu.%llu", 1656711890bcSjc156560 arraypart_attr.tag.cidl.bus, 1657711890bcSjc156560 arraypart_attr.tag.cidl.target_id, 1658711890bcSjc156560 arraypart_attr.tag.cidl.lun); 1659711890bcSjc156560 } 1660317fb4acSYu-Bo Ryan Wang (void) strlcat(diskbuf, tempbuf, sizeof (diskbuf)); 1661711890bcSjc156560 (void) strcat(diskbuf, " "); 1662711890bcSjc156560 disknum++; 1663711890bcSjc156560 arraypart_handle = raidcfg_list_next(arraypart_handle); 1664711890bcSjc156560 } 1665711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), "%u ", disknum); 1666317fb4acSYu-Bo Ryan Wang (void) strlcat(arraybuf, tempbuf, sizeof (arraybuf)); 1667317fb4acSYu-Bo Ryan Wang (void) strlcat(arraybuf, diskbuf, sizeof (arraybuf)); 1668711890bcSjc156560 1669711890bcSjc156560 switch (array_attr.raid_level) { 1670711890bcSjc156560 case RAID_LEVEL_0: 1671711890bcSjc156560 (void) sprintf(tempbuf, "0"); 1672711890bcSjc156560 break; 1673711890bcSjc156560 case RAID_LEVEL_1: 1674711890bcSjc156560 (void) sprintf(tempbuf, "1"); 1675711890bcSjc156560 break; 1676711890bcSjc156560 case RAID_LEVEL_1E: 1677711890bcSjc156560 (void) sprintf(tempbuf, "1E"); 1678711890bcSjc156560 break; 1679711890bcSjc156560 case RAID_LEVEL_5: 1680711890bcSjc156560 (void) sprintf(tempbuf, "5"); 1681711890bcSjc156560 break; 1682711890bcSjc156560 case RAID_LEVEL_10: 1683711890bcSjc156560 (void) sprintf(tempbuf, "10"); 1684711890bcSjc156560 break; 1685711890bcSjc156560 case RAID_LEVEL_50: 1686711890bcSjc156560 (void) sprintf(tempbuf, "50"); 1687711890bcSjc156560 break; 1688711890bcSjc156560 default: 1689711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1690711890bcSjc156560 gettext("N/A")); 1691711890bcSjc156560 break; 1692711890bcSjc156560 } 1693317fb4acSYu-Bo Ryan Wang (void) strlcat(arraybuf, tempbuf, sizeof (arraybuf)); 1694711890bcSjc156560 (void) fprintf(stdout, "%s ", arraybuf); 1695711890bcSjc156560 1696711890bcSjc156560 switch (array_attr.state) { 1697711890bcSjc156560 case ARRAY_STATE_OPTIMAL: 1698711890bcSjc156560 (void) fprintf(stdout, gettext("OPTIMAL")); 1699711890bcSjc156560 break; 1700711890bcSjc156560 case ARRAY_STATE_DEGRADED: 1701711890bcSjc156560 (void) fprintf(stdout, gettext("DEGRADED")); 1702711890bcSjc156560 break; 1703711890bcSjc156560 case ARRAY_STATE_FAILED: 1704711890bcSjc156560 (void) fprintf(stdout, gettext("FAILED")); 1705711890bcSjc156560 break; 1706711890bcSjc156560 case ARRAY_STATE_SYNC: 1707711890bcSjc156560 (void) fprintf(stdout, gettext("SYNC")); 1708711890bcSjc156560 break; 1709a6e966d7Szk194757 case ARRAY_STATE_MISSING: 1710a6e966d7Szk194757 (void) fprintf(stdout, gettext("MISSING")); 1711a6e966d7Szk194757 break; 1712711890bcSjc156560 default: 1713711890bcSjc156560 (void) fprintf(stdout, gettext("N/A")); 1714711890bcSjc156560 break; 1715711890bcSjc156560 } 1716711890bcSjc156560 (void) fprintf(stdout, "\n"); 1717711890bcSjc156560 } 1718711890bcSjc156560 1719711890bcSjc156560 return (SUCCESS); 1720711890bcSjc156560 } 1721711890bcSjc156560 1722711890bcSjc156560 /* 1723711890bcSjc156560 * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot) 1724711890bcSjc156560 * This function prints snapshot of specified disk's configuration, and return 1725711890bcSjc156560 * result as SUCCESS or FAILURE. 1726711890bcSjc156560 */ 1727711890bcSjc156560 static int 1728711890bcSjc156560 snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, uint8_t indent, 1729711890bcSjc156560 uint8_t is_snapshot) 1730711890bcSjc156560 { 1731711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1732711890bcSjc156560 raid_obj_handle_t hsp_handle; 1733711890bcSjc156560 1734711890bcSjc156560 raidcfg_controller_t ctl_attr; 1735711890bcSjc156560 raidcfg_disk_t disk_attr; 1736711890bcSjc156560 char diskbuf[256] = ""; 1737711890bcSjc156560 char tempbuf[256] = ""; 1738711890bcSjc156560 1739711890bcSjc156560 int ret; 1740711890bcSjc156560 1741711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1742711890bcSjc156560 ret = raidcfg_get_attr(ctl_handle, &ctl_attr); 1743711890bcSjc156560 if (ret < 0) { 1744711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1745711890bcSjc156560 return (FAILURE); 1746711890bcSjc156560 } 1747711890bcSjc156560 1748711890bcSjc156560 /* Print attribute of disk */ 1749711890bcSjc156560 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) { 1750711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1751711890bcSjc156560 return (FAILURE); 1752711890bcSjc156560 } 1753711890bcSjc156560 1754711890bcSjc156560 if (is_snapshot == FALSE) { 1755711890bcSjc156560 print_indent(indent); 1756711890bcSjc156560 1757711890bcSjc156560 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); 1758711890bcSjc156560 1759711890bcSjc156560 if (disk_attr.tag.cidl.bus == MAX64BIT) { 1760711890bcSjc156560 (void) fprintf(stdout, gettext("Disk: N/A")); 1761711890bcSjc156560 } else { 1762711890bcSjc156560 (void) fprintf(stdout, gettext("Disk: %llu.%llu.%llu"), 1763711890bcSjc156560 disk_attr.tag.cidl.bus, 1764711890bcSjc156560 disk_attr.tag.cidl.target_id, 1765711890bcSjc156560 disk_attr.tag.cidl.lun); 1766711890bcSjc156560 } 1767711890bcSjc156560 if (hsp_handle > 0) { 1768711890bcSjc156560 (void) fprintf(stdout, "(HSP)"); 1769711890bcSjc156560 } 1770711890bcSjc156560 (void) fprintf(stdout, "\n"); 1771711890bcSjc156560 } else { 1772711890bcSjc156560 if (disk_attr.tag.cidl.bus == MAX64BIT) { 1773711890bcSjc156560 (void) fprintf(stdout, gettext("N/A")); 1774711890bcSjc156560 } else { 1775711890bcSjc156560 (void) snprintf(diskbuf, sizeof (diskbuf), 1776711890bcSjc156560 "%llu.%llu.%llu ", 1777711890bcSjc156560 disk_attr.tag.cidl.bus, 1778711890bcSjc156560 disk_attr.tag.cidl.target_id, 1779711890bcSjc156560 disk_attr.tag.cidl.lun); 1780711890bcSjc156560 } 1781711890bcSjc156560 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); 1782711890bcSjc156560 if (hsp_handle > 0) { 1783711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1784711890bcSjc156560 gettext("HSP")); 1785711890bcSjc156560 } else if (disk_attr.state == DISK_STATE_GOOD) { 1786711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1787711890bcSjc156560 gettext("GOOD")); 1788711890bcSjc156560 } else if (disk_attr.state == DISK_STATE_FAILED) { 1789711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1790711890bcSjc156560 gettext("FAILED")); 1791711890bcSjc156560 } else { 1792711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1793711890bcSjc156560 gettext("N/A")); 1794711890bcSjc156560 } 1795711890bcSjc156560 1796317fb4acSYu-Bo Ryan Wang (void) strlcat(diskbuf, tempbuf, sizeof (diskbuf)); 1797711890bcSjc156560 (void) fprintf(stdout, "%s\n", diskbuf); 1798711890bcSjc156560 } 1799711890bcSjc156560 1800711890bcSjc156560 return (SUCCESS); 1801711890bcSjc156560 } 1802711890bcSjc156560 1803711890bcSjc156560 static int 1804711890bcSjc156560 print_ctl_table(raid_obj_handle_t ctl_handle) 1805711890bcSjc156560 { 1806711890bcSjc156560 raidcfg_controller_t ctl_attr; 1807711890bcSjc156560 char controller[8]; 1808711890bcSjc156560 int ret; 1809711890bcSjc156560 1810711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1811711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1812711890bcSjc156560 return (FAILURE); 1813711890bcSjc156560 } 1814711890bcSjc156560 1815711890bcSjc156560 (void) fprintf(stdout, gettext("Controller\tType\t\tVersion")); 1816711890bcSjc156560 (void) fprintf(stdout, "\n"); 1817711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 1818711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 1819711890bcSjc156560 (void) fprintf(stdout, "\n"); 1820711890bcSjc156560 1821711890bcSjc156560 (void) snprintf(controller, sizeof (controller), "%u", 1822711890bcSjc156560 ctl_attr.controller_id); 1823711890bcSjc156560 (void) printf("c%s\t\t", controller); 1824711890bcSjc156560 1825711890bcSjc156560 (void) print_ctl_attr(&ctl_attr); 1826711890bcSjc156560 (void) fprintf(stdout, "\n"); 1827711890bcSjc156560 1828711890bcSjc156560 return (SUCCESS); 1829711890bcSjc156560 } 1830711890bcSjc156560 1831711890bcSjc156560 static int 1832711890bcSjc156560 print_array_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t array_handle) 1833711890bcSjc156560 { 1834711890bcSjc156560 raidcfg_controller_t ctl_attr; 1835711890bcSjc156560 raidcfg_array_t array_attr; 1836711890bcSjc156560 raidcfg_array_t subarray_attr; 1837711890bcSjc156560 raidcfg_arraypart_t arraypart_attr; 1838711890bcSjc156560 raidcfg_task_t task_attr; 1839711890bcSjc156560 1840711890bcSjc156560 raid_obj_handle_t subarray_handle; 1841711890bcSjc156560 raid_obj_handle_t arraypart_handle; 1842711890bcSjc156560 raid_obj_handle_t task_handle; 1843711890bcSjc156560 1844b449fa8aSyw161884 char array[16]; 1845711890bcSjc156560 char arraypart[8]; 1846711890bcSjc156560 int ret; 1847711890bcSjc156560 int i; 1848711890bcSjc156560 1849711890bcSjc156560 /* Controller attribute */ 1850711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1851711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1852711890bcSjc156560 return (FAILURE); 1853711890bcSjc156560 } 1854711890bcSjc156560 1855711890bcSjc156560 /* Array attribute */ 1856711890bcSjc156560 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 1857711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1858711890bcSjc156560 return (FAILURE); 1859711890bcSjc156560 } 1860711890bcSjc156560 1861711890bcSjc156560 /* print header */ 1862711890bcSjc156560 (void) fprintf(stdout, gettext("Volume\t\t\tSize\tStripe\tStatus\t" 1863711890bcSjc156560 " Cache\tRAID")); 1864711890bcSjc156560 (void) fprintf(stdout, "\n"); 1865711890bcSjc156560 (void) fprintf(stdout, gettext("\tSub\t\t\tSize\t\t\tLevel")); 1866711890bcSjc156560 (void) fprintf(stdout, "\n"); 1867711890bcSjc156560 (void) fprintf(stdout, gettext("\t\tDisk\t\t\t\t\t")); 1868711890bcSjc156560 (void) fprintf(stdout, "\n"); 1869711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 1870711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 1871711890bcSjc156560 (void) fprintf(stdout, "\n"); 1872711890bcSjc156560 1873711890bcSjc156560 /* print array */ 1874711890bcSjc156560 (void) snprintf(array, sizeof (array), "c%ut%llud%llu", 1875711890bcSjc156560 ctl_attr.controller_id, array_attr.tag.idl.target_id, 1876711890bcSjc156560 array_attr.tag.idl.lun); 1877b449fa8aSyw161884 (void) fprintf(stdout, "%s\t\t", array); 1878b449fa8aSyw161884 if (strlen(array) < 8) 1879b449fa8aSyw161884 (void) fprintf(stdout, "\t"); 1880b449fa8aSyw161884 1881711890bcSjc156560 1882711890bcSjc156560 /* check if array is in sync state */ 1883711890bcSjc156560 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK); 1884711890bcSjc156560 if (task_handle > 0) { 1885711890bcSjc156560 (void) raidcfg_get_attr(task_handle, &task_attr); 1886711890bcSjc156560 if (task_attr.task_func == TASK_FUNC_BUILD) { 1887711890bcSjc156560 array_attr.state = ARRAY_STATE_SYNC; 1888711890bcSjc156560 } 1889711890bcSjc156560 } else { 1890711890bcSjc156560 subarray_handle = raidcfg_list_head(array_handle, 1891711890bcSjc156560 OBJ_TYPE_ARRAY); 1892711890bcSjc156560 while (subarray_handle > 0) { 1893711890bcSjc156560 task_handle = raidcfg_list_head(subarray_handle, 1894711890bcSjc156560 OBJ_TYPE_TASK); 1895711890bcSjc156560 if (task_handle > 0) { 1896711890bcSjc156560 (void) raidcfg_get_attr(task_handle, 1897711890bcSjc156560 &task_attr); 1898711890bcSjc156560 if (task_attr.task_func == TASK_FUNC_BUILD) { 1899711890bcSjc156560 array_attr.state = ARRAY_STATE_SYNC; 1900711890bcSjc156560 } 1901711890bcSjc156560 break; 1902711890bcSjc156560 } 1903711890bcSjc156560 subarray_handle = raidcfg_list_next(subarray_handle); 1904711890bcSjc156560 } 1905711890bcSjc156560 } 1906711890bcSjc156560 1907711890bcSjc156560 (void) print_array_attr(&array_attr); 1908711890bcSjc156560 (void) fprintf(stdout, "\n"); 1909711890bcSjc156560 1910711890bcSjc156560 /* Print sub array */ 1911711890bcSjc156560 i = 0; /* Count sub array number */ 1912711890bcSjc156560 subarray_handle = raidcfg_list_head(array_handle, OBJ_TYPE_ARRAY); 1913711890bcSjc156560 while (subarray_handle > 0) { 1914711890bcSjc156560 if ((ret = raidcfg_get_attr(subarray_handle, 1915711890bcSjc156560 &subarray_attr)) < 0) { 1916711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1917711890bcSjc156560 return (FAILURE); 1918711890bcSjc156560 } 1919711890bcSjc156560 1920711890bcSjc156560 /* Use sub0/sub1 here, not cxtxd0 for subarray */ 1921711890bcSjc156560 (void) snprintf(array, sizeof (array), "sub%u", i++); 1922711890bcSjc156560 (void) fprintf(stdout, "\t%s\t\t", array); 1923711890bcSjc156560 1924711890bcSjc156560 /* Check if array is in sync */ 1925711890bcSjc156560 task_handle = raidcfg_list_head(subarray_handle, OBJ_TYPE_TASK); 1926711890bcSjc156560 if (task_handle > 0) { 1927711890bcSjc156560 (void) raidcfg_get_attr(task_handle, &task_attr); 1928711890bcSjc156560 if (task_attr.task_func == TASK_FUNC_BUILD) { 1929711890bcSjc156560 subarray_attr.state = ARRAY_STATE_SYNC; 1930711890bcSjc156560 } 1931711890bcSjc156560 } 1932711890bcSjc156560 1933711890bcSjc156560 (void) print_array_attr(&subarray_attr); 1934711890bcSjc156560 (void) fprintf(stdout, "\n"); 1935711890bcSjc156560 1936711890bcSjc156560 /* Print subarraypart */ 1937711890bcSjc156560 arraypart_handle = raidcfg_list_head(subarray_handle, 1938711890bcSjc156560 OBJ_TYPE_ARRAY_PART); 1939711890bcSjc156560 while (arraypart_handle > 0) { 1940711890bcSjc156560 if ((ret = raidcfg_get_attr(arraypart_handle, 1941711890bcSjc156560 &arraypart_attr)) < 0) { 1942711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1943711890bcSjc156560 raidcfg_errstr(ret)); 1944711890bcSjc156560 return (FAILURE); 1945711890bcSjc156560 } 1946711890bcSjc156560 1947711890bcSjc156560 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1948711890bcSjc156560 (void) snprintf(arraypart, sizeof (arraypart), 1949711890bcSjc156560 gettext("N/A")); 1950711890bcSjc156560 } else { 1951711890bcSjc156560 (void) snprintf(arraypart, sizeof (arraypart), 1952711890bcSjc156560 "%llu.%llu.%llu", 1953711890bcSjc156560 arraypart_attr.tag.cidl.bus, 1954711890bcSjc156560 arraypart_attr.tag.cidl.target_id, 1955711890bcSjc156560 arraypart_attr.tag.cidl.lun); 1956711890bcSjc156560 } 1957711890bcSjc156560 1958711890bcSjc156560 (void) fprintf(stdout, "\t\t%s\t", arraypart); 1959711890bcSjc156560 (void) print_arraypart_attr(&arraypart_attr); 1960711890bcSjc156560 (void) fprintf(stdout, "\n"); 1961711890bcSjc156560 arraypart_handle = raidcfg_list_next(arraypart_handle); 1962711890bcSjc156560 } 1963711890bcSjc156560 subarray_handle = raidcfg_list_next(subarray_handle); 1964711890bcSjc156560 } 1965711890bcSjc156560 1966711890bcSjc156560 /* Print arraypart */ 1967711890bcSjc156560 arraypart_handle = raidcfg_list_head(array_handle, 1968711890bcSjc156560 OBJ_TYPE_ARRAY_PART); 1969711890bcSjc156560 while (arraypart_handle > 0) { 1970711890bcSjc156560 if ((ret = raidcfg_get_attr(arraypart_handle, 1971711890bcSjc156560 &arraypart_attr)) < 0) { 1972711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1973711890bcSjc156560 return (FAILURE); 1974711890bcSjc156560 } 1975711890bcSjc156560 1976711890bcSjc156560 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1977711890bcSjc156560 (void) snprintf(arraypart, sizeof (arraypart), 1978711890bcSjc156560 gettext("N/A")); 1979711890bcSjc156560 } else { 1980711890bcSjc156560 (void) snprintf(arraypart, sizeof (arraypart), 1981711890bcSjc156560 "%llu.%llu.%llu", 1982711890bcSjc156560 arraypart_attr.tag.cidl.bus, 1983711890bcSjc156560 arraypart_attr.tag.cidl.target_id, 1984711890bcSjc156560 arraypart_attr.tag.cidl.lun); 1985711890bcSjc156560 } 1986711890bcSjc156560 1987711890bcSjc156560 (void) fprintf(stdout, "\t\t%s\t", arraypart); 1988711890bcSjc156560 (void) print_arraypart_attr(&arraypart_attr); 1989711890bcSjc156560 (void) fprintf(stdout, "\n"); 1990711890bcSjc156560 arraypart_handle = raidcfg_list_next(arraypart_handle); 1991711890bcSjc156560 } 1992711890bcSjc156560 1993711890bcSjc156560 return (SUCCESS); 1994711890bcSjc156560 } 1995711890bcSjc156560 1996711890bcSjc156560 static int 1997711890bcSjc156560 print_disk_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle) 1998711890bcSjc156560 { 1999711890bcSjc156560 raidcfg_controller_t ctl_attr; 2000711890bcSjc156560 raidcfg_disk_t disk_attr; 2001b449fa8aSyw161884 raidcfg_prop_t *prop_attr, *prop_attr2; 2002b449fa8aSyw161884 raid_obj_handle_t prop_handle; 2003711890bcSjc156560 char disk[8]; 2004711890bcSjc156560 int ret; 2005711890bcSjc156560 2006711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 2007711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2008711890bcSjc156560 return (FAILURE); 2009711890bcSjc156560 } 2010711890bcSjc156560 2011711890bcSjc156560 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) { 2012711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2013711890bcSjc156560 return (FAILURE); 2014711890bcSjc156560 } 2015711890bcSjc156560 2016711890bcSjc156560 /* Print header */ 2017*f3f093f5SMilan Jurik (void) fprintf(stdout, gettext("Disk\tVendor Product " 2018*f3f093f5SMilan Jurik "Firmware\tCapacity\tStatus\tHSP")); 2019711890bcSjc156560 (void) fprintf(stdout, "\n"); 20209415b234Szk194757 (void) fprintf(stdout, "--------------------------------------"); 20219415b234Szk194757 (void) fprintf(stdout, "--------------------------------------"); 2022711890bcSjc156560 (void) fprintf(stdout, "\n"); 2023711890bcSjc156560 2024711890bcSjc156560 2025711890bcSjc156560 (void) snprintf(disk, sizeof (disk), "%llu.%llu.%llu", 2026711890bcSjc156560 disk_attr.tag.cidl.bus, 2027711890bcSjc156560 disk_attr.tag.cidl.target_id, 2028711890bcSjc156560 disk_attr.tag.cidl.lun); 2029711890bcSjc156560 2030711890bcSjc156560 (void) fprintf(stdout, "%s\t", disk); 2031711890bcSjc156560 2032711890bcSjc156560 (void) print_disk_attr(ctl_handle, disk_handle, &disk_attr); 2033711890bcSjc156560 2034b449fa8aSyw161884 prop_attr = calloc(1, sizeof (raidcfg_prop_t)); 2035b449fa8aSyw161884 if (prop_attr == NULL) { 2036b449fa8aSyw161884 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM)); 2037b449fa8aSyw161884 return (FAILURE); 2038b449fa8aSyw161884 } 2039b449fa8aSyw161884 2040b449fa8aSyw161884 prop_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_PROP); 2041b449fa8aSyw161884 if (prop_handle == 0) { 2042b449fa8aSyw161884 free(prop_attr); 2043b449fa8aSyw161884 return (SUCCESS); 2044b449fa8aSyw161884 } 2045b449fa8aSyw161884 2046b449fa8aSyw161884 do { 2047b449fa8aSyw161884 prop_attr->prop_size = 0; 2048b449fa8aSyw161884 if ((ret = raidcfg_get_attr(prop_handle, prop_attr)) < 0) { 2049b449fa8aSyw161884 free(prop_attr); 2050b449fa8aSyw161884 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2051b449fa8aSyw161884 return (FAILURE); 2052b449fa8aSyw161884 } 2053b449fa8aSyw161884 if (prop_attr->prop_type == PROP_GUID) 2054b449fa8aSyw161884 break; 2055b449fa8aSyw161884 } while (prop_handle != 0); 2056b449fa8aSyw161884 2057b449fa8aSyw161884 prop_attr2 = realloc(prop_attr, 2058b449fa8aSyw161884 sizeof (raidcfg_prop_t) + prop_attr->prop_size); 2059b449fa8aSyw161884 free(prop_attr); 2060b449fa8aSyw161884 if (prop_attr2 == NULL) { 2061b449fa8aSyw161884 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM)); 2062b449fa8aSyw161884 return (FAILURE); 2063b449fa8aSyw161884 } 2064b449fa8aSyw161884 2065b449fa8aSyw161884 if ((ret = raidcfg_get_attr(prop_handle, prop_attr2)) < 0) { 2066b449fa8aSyw161884 free(prop_attr2); 2067b449fa8aSyw161884 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2068b449fa8aSyw161884 return (FAILURE); 2069b449fa8aSyw161884 } 2070b449fa8aSyw161884 2071b449fa8aSyw161884 (void) fprintf(stdout, "GUID:%s\n", prop_attr2->prop); 2072b449fa8aSyw161884 2073b449fa8aSyw161884 free(prop_attr2); 2074711890bcSjc156560 return (SUCCESS); 2075711890bcSjc156560 } 2076711890bcSjc156560 2077711890bcSjc156560 /* 2078711890bcSjc156560 * print_ctl_attr(attrp) 2079711890bcSjc156560 * This function prints attribute of specified controller, and return 2080711890bcSjc156560 * result as SUCCESS or FAILURE. 2081711890bcSjc156560 */ 2082711890bcSjc156560 static int 2083711890bcSjc156560 print_ctl_attr(raidcfg_controller_t *attrp) 2084711890bcSjc156560 { 2085711890bcSjc156560 char type[CONTROLLER_TYPE_LEN]; 2086711890bcSjc156560 char version[CONTROLLER_FW_LEN]; 2087711890bcSjc156560 2088711890bcSjc156560 if (attrp == NULL) { 2089711890bcSjc156560 return (FAILURE); 2090711890bcSjc156560 } 2091711890bcSjc156560 2092711890bcSjc156560 (void) snprintf(type, sizeof (type), "%s", attrp->controller_type); 2093711890bcSjc156560 (void) fprintf(stdout, "%-16s", type); 2094711890bcSjc156560 2095711890bcSjc156560 (void) snprintf(version, sizeof (version), "%s", attrp->fw_version); 2096711890bcSjc156560 (void) fprintf(stdout, "%s", version); 2097711890bcSjc156560 2098711890bcSjc156560 return (SUCCESS); 2099711890bcSjc156560 } 2100711890bcSjc156560 2101711890bcSjc156560 /* 2102711890bcSjc156560 * print_array_attr(attrp) 2103711890bcSjc156560 * This function prints attribute of specified array, and return 2104711890bcSjc156560 * result as SUCCESS or FAILURE. 2105711890bcSjc156560 */ 2106711890bcSjc156560 static int 2107711890bcSjc156560 print_array_attr(raidcfg_array_t *attrp) 2108711890bcSjc156560 { 2109711890bcSjc156560 char capacity[8]; 2110711890bcSjc156560 char stripe_size[8]; 2111711890bcSjc156560 char raid_level[8]; 2112711890bcSjc156560 2113711890bcSjc156560 if (attrp == NULL) { 2114711890bcSjc156560 return (FAILURE); 2115711890bcSjc156560 } 2116711890bcSjc156560 2117711890bcSjc156560 if (attrp->capacity != MAX64BIT) { 2118711890bcSjc156560 if (size_to_string(attrp->capacity, capacity, 8) != SUCCESS) { 2119711890bcSjc156560 return (FAILURE); 2120711890bcSjc156560 } 2121711890bcSjc156560 (void) printf("%s\t", capacity); 2122711890bcSjc156560 } else { 2123711890bcSjc156560 (void) printf(gettext("N/A\t")); 2124711890bcSjc156560 } 2125711890bcSjc156560 2126711890bcSjc156560 if (attrp->stripe_size != MAX32BIT) { 2127711890bcSjc156560 (void) snprintf(stripe_size, sizeof (stripe_size), "%uK", 2128711890bcSjc156560 attrp->stripe_size / 1024); 2129711890bcSjc156560 (void) printf("%s\t", stripe_size); 2130711890bcSjc156560 } else { 2131711890bcSjc156560 (void) printf(gettext("N/A\t")); 2132711890bcSjc156560 } 2133711890bcSjc156560 2134b449fa8aSyw161884 if (attrp->state & ARRAY_STATE_INACTIVATE) 2135b449fa8aSyw161884 (void) printf("%-8s", gettext("INACTIVE")); 2136b449fa8aSyw161884 else { 2137711890bcSjc156560 switch (attrp->state) { 2138711890bcSjc156560 case ARRAY_STATE_OPTIMAL: 2139711890bcSjc156560 (void) printf("%-8s", gettext("OPTIMAL")); 2140711890bcSjc156560 break; 2141711890bcSjc156560 case ARRAY_STATE_DEGRADED: 2142711890bcSjc156560 (void) printf("%-8s", gettext("DEGRADED")); 2143711890bcSjc156560 break; 2144711890bcSjc156560 case ARRAY_STATE_FAILED: 2145711890bcSjc156560 (void) printf("%-8s", gettext("FAILED")); 2146711890bcSjc156560 break; 2147711890bcSjc156560 case ARRAY_STATE_SYNC: 2148711890bcSjc156560 (void) printf("%-8s", gettext("SYNC")); 2149711890bcSjc156560 break; 2150a6e966d7Szk194757 case ARRAY_STATE_MISSING: 2151a6e966d7Szk194757 (void) printf("%-8s", gettext("MISSING")); 2152a6e966d7Szk194757 break; 2153711890bcSjc156560 default: 2154711890bcSjc156560 (void) printf("%-8s", gettext("N/A")); 2155711890bcSjc156560 break; 2156711890bcSjc156560 } 2157b449fa8aSyw161884 } 2158711890bcSjc156560 (void) printf(" "); 2159711890bcSjc156560 2160711890bcSjc156560 if (attrp->write_policy == CACHE_WR_OFF) { 2161711890bcSjc156560 (void) printf(gettext("OFF")); 2162711890bcSjc156560 } else if (attrp->write_policy == CACHE_WR_ON) { 2163711890bcSjc156560 (void) printf(gettext("ON")); 2164711890bcSjc156560 } else { 2165711890bcSjc156560 (void) printf(gettext("N/A")); 2166711890bcSjc156560 } 2167711890bcSjc156560 (void) printf("\t"); 2168711890bcSjc156560 2169711890bcSjc156560 switch (attrp->raid_level) { 2170711890bcSjc156560 case RAID_LEVEL_0: 2171711890bcSjc156560 (void) sprintf(raid_level, "RAID0"); 2172711890bcSjc156560 break; 2173711890bcSjc156560 case RAID_LEVEL_1: 2174711890bcSjc156560 (void) sprintf(raid_level, "RAID1"); 2175711890bcSjc156560 break; 2176711890bcSjc156560 case RAID_LEVEL_1E: 2177711890bcSjc156560 (void) sprintf(raid_level, "RAID1E"); 2178711890bcSjc156560 break; 2179711890bcSjc156560 case RAID_LEVEL_5: 2180711890bcSjc156560 (void) sprintf(raid_level, "RAID5"); 2181711890bcSjc156560 break; 2182711890bcSjc156560 case RAID_LEVEL_10: 2183711890bcSjc156560 (void) sprintf(raid_level, "RAID10"); 2184711890bcSjc156560 break; 2185711890bcSjc156560 case RAID_LEVEL_50: 2186711890bcSjc156560 (void) sprintf(raid_level, "RAID50"); 2187711890bcSjc156560 break; 2188711890bcSjc156560 default: 2189711890bcSjc156560 (void) snprintf(raid_level, sizeof (raid_level), 2190711890bcSjc156560 gettext("N/A")); 2191711890bcSjc156560 break; 2192711890bcSjc156560 } 2193711890bcSjc156560 (void) printf("%s", raid_level); 2194711890bcSjc156560 2195711890bcSjc156560 return (SUCCESS); 2196711890bcSjc156560 } 2197711890bcSjc156560 2198711890bcSjc156560 /* 2199711890bcSjc156560 * print_arraypart_attr(attrp) 2200711890bcSjc156560 * This function print attribute of specified arraypart, and return 2201711890bcSjc156560 * result as SUCCESS or FAILURE. 2202711890bcSjc156560 */ 2203711890bcSjc156560 static int 2204711890bcSjc156560 print_arraypart_attr(raidcfg_arraypart_t *attrp) 2205711890bcSjc156560 { 2206711890bcSjc156560 char size[8]; 2207711890bcSjc156560 2208711890bcSjc156560 if (attrp == NULL) { 2209711890bcSjc156560 return (FAILURE); 2210711890bcSjc156560 } 2211711890bcSjc156560 2212711890bcSjc156560 if (attrp->size != MAX64BIT) { 2213711890bcSjc156560 if (size_to_string(attrp->size, size, 8) != SUCCESS) { 2214711890bcSjc156560 return (FAILURE); 2215711890bcSjc156560 } 2216711890bcSjc156560 (void) printf("%s\t", size); 2217711890bcSjc156560 } else { 2218711890bcSjc156560 (void) printf(gettext("N/A\t")); 2219711890bcSjc156560 } 2220711890bcSjc156560 2221711890bcSjc156560 (void) printf("\t"); 2222711890bcSjc156560 2223711890bcSjc156560 if (attrp->state == DISK_STATE_GOOD) { 2224711890bcSjc156560 (void) printf(gettext("GOOD")); 2225711890bcSjc156560 } else if (attrp->state == DISK_STATE_FAILED) { 2226711890bcSjc156560 (void) printf(gettext("FAILED")); 2227711890bcSjc156560 } else { 2228711890bcSjc156560 (void) printf(gettext("N/A")); 2229711890bcSjc156560 } 2230711890bcSjc156560 (void) printf("\t"); 2231711890bcSjc156560 2232711890bcSjc156560 return (SUCCESS); 2233711890bcSjc156560 } 2234711890bcSjc156560 2235711890bcSjc156560 /* 2236711890bcSjc156560 * print_disk_attr(ctl_handle, disk_handle, attrp) 2237711890bcSjc156560 * This function prints attribute of specified disk, and return 2238711890bcSjc156560 * result as SUCCESS or FAILURE. 2239711890bcSjc156560 */ 2240711890bcSjc156560 static int 2241711890bcSjc156560 print_disk_attr(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle, 2242711890bcSjc156560 raidcfg_disk_t *attrp) 2243711890bcSjc156560 { 2244*f3f093f5SMilan Jurik char vendor[DISK_VENDER_LEN + 1]; 2245*f3f093f5SMilan Jurik char product[DISK_PRODUCT_LEN + 1]; 22469415b234Szk194757 char revision[DISK_REV_LEN + 1]; 2247711890bcSjc156560 char capacity[16]; 2248711890bcSjc156560 char hsp[16]; 2249711890bcSjc156560 2250711890bcSjc156560 raid_obj_handle_t hsp_handle; 2251711890bcSjc156560 raidcfg_hsp_t hsp_attr; 2252711890bcSjc156560 raidcfg_controller_t ctl_attr; 2253711890bcSjc156560 int ret; 2254711890bcSjc156560 char is_indent; 2255711890bcSjc156560 2256711890bcSjc156560 if (attrp == NULL) { 2257711890bcSjc156560 return (FAILURE); 2258711890bcSjc156560 } 2259711890bcSjc156560 2260*f3f093f5SMilan Jurik (void) memccpy(vendor, attrp->vendorid, '\0', DISK_VENDER_LEN); 2261*f3f093f5SMilan Jurik vendor[DISK_VENDER_LEN] = '\0'; 2262*f3f093f5SMilan Jurik (void) printf("%-9s", vendor); 2263711890bcSjc156560 2264*f3f093f5SMilan Jurik (void) memccpy(product, attrp->productid, '\0', DISK_PRODUCT_LEN); 2265*f3f093f5SMilan Jurik product[DISK_PRODUCT_LEN] = '\0'; 2266*f3f093f5SMilan Jurik (void) printf("%-17s", product); 2267711890bcSjc156560 2268*f3f093f5SMilan Jurik (void) memccpy(revision, attrp->revision, '\0', DISK_REV_LEN); 2269*f3f093f5SMilan Jurik revision[DISK_REV_LEN] = '\0'; 22709415b234Szk194757 (void) printf("%s\t\t", revision); 22719415b234Szk194757 2272711890bcSjc156560 if (attrp->capacity != MAX64BIT) { 2273711890bcSjc156560 if (size_to_string(attrp->capacity, capacity, 16) != SUCCESS) { 2274711890bcSjc156560 return (FAILURE); 2275711890bcSjc156560 } 2276711890bcSjc156560 (void) printf("%s\t\t", capacity); 2277711890bcSjc156560 } else { 2278711890bcSjc156560 (void) printf(gettext("N/A")); 2279711890bcSjc156560 } 2280711890bcSjc156560 2281711890bcSjc156560 if (attrp->state == DISK_STATE_GOOD) { 2282711890bcSjc156560 (void) printf(gettext("GOOD")); 2283711890bcSjc156560 } else if (attrp->state == DISK_STATE_FAILED) { 2284711890bcSjc156560 (void) printf(gettext("FAILED")); 2285711890bcSjc156560 } else { 2286711890bcSjc156560 (void) printf(gettext("N/A")); 2287711890bcSjc156560 } 2288711890bcSjc156560 (void) printf("\t"); 2289711890bcSjc156560 2290711890bcSjc156560 /* Controller attribute */ 2291711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 2292711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2293711890bcSjc156560 return (FAILURE); 2294711890bcSjc156560 } 2295711890bcSjc156560 2296711890bcSjc156560 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); 2297711890bcSjc156560 if (hsp_handle == 0) { 2298711890bcSjc156560 (void) printf(gettext("N/A\n")); 2299711890bcSjc156560 } else { 2300711890bcSjc156560 is_indent = FALSE; 2301711890bcSjc156560 while (hsp_handle > 0) { 2302711890bcSjc156560 if ((ret = raidcfg_get_attr(hsp_handle, 2303711890bcSjc156560 &hsp_attr)) < 0) { 2304711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2305711890bcSjc156560 raidcfg_errstr(ret)); 2306711890bcSjc156560 return (FAILURE); 2307711890bcSjc156560 } 2308711890bcSjc156560 2309711890bcSjc156560 if (is_indent == TRUE) { 2310711890bcSjc156560 (void) printf("\t\t\t\t\t\t\t"); 2311711890bcSjc156560 } else { 2312711890bcSjc156560 is_indent = TRUE; 2313711890bcSjc156560 } 2314711890bcSjc156560 2315711890bcSjc156560 if (hsp_attr.type == HSP_TYPE_LOCAL) { 2316711890bcSjc156560 (void) snprintf(hsp, sizeof (hsp), 2317711890bcSjc156560 "c%ut%llud%llu", 2318711890bcSjc156560 ctl_attr.controller_id, 2319711890bcSjc156560 hsp_attr.tag.idl.target_id, 2320711890bcSjc156560 hsp_attr.tag.idl.lun); 2321711890bcSjc156560 (void) printf("%s\n", hsp); 2322711890bcSjc156560 } else if (hsp_attr.type == HSP_TYPE_GLOBAL) { 2323711890bcSjc156560 (void) printf(gettext("Global\n")); 2324711890bcSjc156560 } else { 2325711890bcSjc156560 return (FAILURE); 2326711890bcSjc156560 } 2327711890bcSjc156560 2328711890bcSjc156560 hsp_handle = raidcfg_list_next(hsp_handle); 2329711890bcSjc156560 } 2330711890bcSjc156560 } 2331711890bcSjc156560 return (SUCCESS); 2332711890bcSjc156560 } 2333711890bcSjc156560 2334711890bcSjc156560 2335711890bcSjc156560 /* 2336711890bcSjc156560 * print_indent(indent) 2337711890bcSjc156560 * This function prints specified number of tab characters. It's used to 2338711890bcSjc156560 * format layout. 2339711890bcSjc156560 */ 23407f000930Syw161884 static void 2341711890bcSjc156560 print_indent(uint8_t indent) 23427f000930Syw161884 { 2343711890bcSjc156560 uint32_t i; 2344711890bcSjc156560 for (i = 0; i < indent; i++) { 2345711890bcSjc156560 (void) fprintf(stdout, "\t"); 23467f000930Syw161884 } 23477f000930Syw161884 } 23487f000930Syw161884 2349711890bcSjc156560 /* 2350711890bcSjc156560 * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp) 2351711890bcSjc156560 * This function parses the string of disk argument, and gets the disks tag 2352711890bcSjc156560 * and separators from the string. Then it translates the tag to handle, and 2353711890bcSjc156560 * stores handles and separators to new buffer pointed by parameter handlespp. 2354711890bcSjc156560 * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first 2355711890bcSjc156560 * "0" is channel number, and the second "1" is target number, and the third 2356711890bcSjc156560 * "0" is LUN number. The disk tags are separated by comma and parenthesis. 2357711890bcSjc156560 * Function returns SUCCESS or FAILURE. 2358711890bcSjc156560 */ 23597c478bd9Sstevel@tonic-gate static int 2360711890bcSjc156560 get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, int *comps_nump, 2361711890bcSjc156560 raid_obj_handle_t **handlespp) 23627c478bd9Sstevel@tonic-gate { 2363711890bcSjc156560 int len = 0; 2364711890bcSjc156560 int i = 0, j = 0; 2365711890bcSjc156560 char *p, *t; 2366711890bcSjc156560 char *delimit = " "; 2367711890bcSjc156560 char *disks_str; 2368711890bcSjc156560 disk_tag_t disk_tag; 23697c478bd9Sstevel@tonic-gate 2370711890bcSjc156560 if (disks_argp == NULL || comps_nump == NULL) { 2371711890bcSjc156560 return (FAILURE); 2372711890bcSjc156560 } 2373711890bcSjc156560 2374711890bcSjc156560 p = disks_argp; 2375711890bcSjc156560 len = strlen(disks_argp); 2376711890bcSjc156560 2377711890bcSjc156560 if ((disks_str = (char *)malloc(3 * len + 4)) == NULL) { 2378711890bcSjc156560 return (FAILURE); 2379711890bcSjc156560 } 2380711890bcSjc156560 2381711890bcSjc156560 /* Insert whitespace between disk tags, '(' , and ')' */ 2382711890bcSjc156560 disks_str[j ++] = '('; 2383711890bcSjc156560 disks_str[j ++] = ' '; 2384711890bcSjc156560 2385711890bcSjc156560 while (p[i] != '\0') { 2386711890bcSjc156560 if (p[i] == ')' || p[i] == '(') { 2387711890bcSjc156560 disks_str[j ++] = ' '; 2388711890bcSjc156560 disks_str[j ++] = p[i]; 2389711890bcSjc156560 disks_str[j ++] = ' '; 2390711890bcSjc156560 } else 2391711890bcSjc156560 disks_str[j ++] = p[i]; 2392711890bcSjc156560 i ++; 2393711890bcSjc156560 } 2394711890bcSjc156560 disks_str[j ++] = ' '; 2395711890bcSjc156560 disks_str[j ++] = ')'; 2396711890bcSjc156560 disks_str[j] = '\0'; 2397711890bcSjc156560 2398711890bcSjc156560 len = strlen(disks_str) + 1; 2399711890bcSjc156560 2400711890bcSjc156560 if ((t = (char *)malloc(len)) == NULL) { 2401711890bcSjc156560 return (FAILURE); 2402711890bcSjc156560 } 2403711890bcSjc156560 (void) memcpy(t, disks_str, len); 2404711890bcSjc156560 p = strtok(t, delimit); 2405711890bcSjc156560 while (p != NULL) { 2406711890bcSjc156560 (*comps_nump)++; 2407711890bcSjc156560 p = strtok(NULL, delimit); 2408711890bcSjc156560 } 2409711890bcSjc156560 free(t); 2410711890bcSjc156560 2411711890bcSjc156560 *handlespp = calloc(*comps_nump, sizeof (raid_obj_handle_t)); 2412711890bcSjc156560 if (*handlespp == NULL) { 2413711890bcSjc156560 return (FAILURE); 2414711890bcSjc156560 } 2415711890bcSjc156560 2416711890bcSjc156560 for (i = 0; i < *comps_nump; i++) 2417711890bcSjc156560 (*handlespp)[i] = INIT_HANDLE_VALUE; 2418711890bcSjc156560 2419711890bcSjc156560 i = 0; 2420711890bcSjc156560 p = strtok(disks_str, delimit); 2421711890bcSjc156560 while (p != NULL) { 2422711890bcSjc156560 if (*p == '(') { 2423711890bcSjc156560 (*handlespp)[i] = OBJ_SEPARATOR_BEGIN; 2424711890bcSjc156560 } else if (*p == ')') { 2425711890bcSjc156560 (*handlespp)[i] = OBJ_SEPARATOR_END; 2426711890bcSjc156560 } else { 2427711890bcSjc156560 if (get_disk_tag_cidl(p, &disk_tag) != SUCCESS) { 2428711890bcSjc156560 free(*handlespp); 2429711890bcSjc156560 free(disks_str); 2430711890bcSjc156560 return (INVALID_ARG); 2431711890bcSjc156560 } 2432711890bcSjc156560 (*handlespp)[i] = 2433711890bcSjc156560 raidcfg_get_disk(raidcfg_get_controller(ctl_tag), 2434711890bcSjc156560 disk_tag); 2435711890bcSjc156560 if ((*handlespp)[i] <= 0) { 2436711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2437711890bcSjc156560 raidcfg_errstr((*handlespp)[i])); 2438711890bcSjc156560 free(*handlespp); 2439711890bcSjc156560 free(disks_str); 2440711890bcSjc156560 return (FAILURE); 2441711890bcSjc156560 } 2442711890bcSjc156560 } 2443711890bcSjc156560 p = strtok(NULL, delimit); 2444711890bcSjc156560 i++; 2445711890bcSjc156560 } 2446711890bcSjc156560 2447711890bcSjc156560 free(disks_str); 2448711890bcSjc156560 return (SUCCESS); 24497c478bd9Sstevel@tonic-gate } 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate /* 2452711890bcSjc156560 * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep) 2453711890bcSjc156560 * This function parses string of single disk with "ctd" format, for example, 2454711890bcSjc156560 * c0t0d0, and translates it to controller tag and disk tag. 2455711890bcSjc156560 * Then it calls lib api and get disk handle. The controller tag and disk 2456711890bcSjc156560 * handle are both returned by out parameters. 2457711890bcSjc156560 * The return value is SUCCESS or FAILURE. 24587c478bd9Sstevel@tonic-gate */ 2459711890bcSjc156560 static int 2460711890bcSjc156560 get_disk_handle_ctd(int disks_num, char **disks_argpp, uint32_t *ctl_tagp, 2461711890bcSjc156560 raid_obj_handle_t *disks_handlep) 2462711890bcSjc156560 { 2463711890bcSjc156560 raid_obj_handle_t ctl_handle; 2464711890bcSjc156560 disk_tag_t disk_tag; 2465711890bcSjc156560 uint32_t ctl_id; 2466711890bcSjc156560 int i; 2467711890bcSjc156560 int ret; 2468711890bcSjc156560 2469711890bcSjc156560 if (disks_handlep == NULL) { 2470711890bcSjc156560 return (FAILURE); 2471711890bcSjc156560 } 2472711890bcSjc156560 2473711890bcSjc156560 for (i = 0; i < disks_num; i++) { 2474711890bcSjc156560 if (get_disk_tag_ctd(disks_argpp[i], &disk_tag, &ctl_id) != 2475711890bcSjc156560 SUCCESS) { 2476711890bcSjc156560 return (INVALID_ARG); 2477711890bcSjc156560 } 2478711890bcSjc156560 2479711890bcSjc156560 *ctl_tagp = ctl_id; 2480711890bcSjc156560 2481711890bcSjc156560 if (i == 0) { 2482711890bcSjc156560 ctl_handle = raidcfg_get_controller(*ctl_tagp); 2483711890bcSjc156560 if (ctl_handle <= 0) { 2484711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2485711890bcSjc156560 raidcfg_errstr(ctl_handle)); 2486711890bcSjc156560 return (FAILURE); 2487711890bcSjc156560 } 2488711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 2489711890bcSjc156560 if (ret < 0) { 2490711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2491711890bcSjc156560 raidcfg_errstr(ret)); 2492711890bcSjc156560 return (FAILURE); 2493711890bcSjc156560 } 2494711890bcSjc156560 } 2495711890bcSjc156560 2496711890bcSjc156560 if ((disks_handlep[i] = 2497711890bcSjc156560 raidcfg_get_disk(ctl_handle, disk_tag)) < 0) { 2498711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2499711890bcSjc156560 raidcfg_errstr(disks_handlep[i])); 2500711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 2501711890bcSjc156560 return (FAILURE); 2502711890bcSjc156560 } 2503711890bcSjc156560 } 2504711890bcSjc156560 2505711890bcSjc156560 return (SUCCESS); 25067c478bd9Sstevel@tonic-gate } 25077c478bd9Sstevel@tonic-gate 25087c478bd9Sstevel@tonic-gate /* 2509711890bcSjc156560 * get_ctl_tag(argp) 2510711890bcSjc156560 * This function translates controller string to tag. The return value is 2511711890bcSjc156560 * SUCCESS if the string has legal format and is parsed successfully, 2512711890bcSjc156560 * or FAILURE if it fails. 25137c478bd9Sstevel@tonic-gate */ 2514711890bcSjc156560 static int 2515711890bcSjc156560 get_ctl_tag(char *argp, uint32_t *ctl_tagp) 2516711890bcSjc156560 { 2517711890bcSjc156560 if (argp == NULL || is_fully_numeric(argp) == FALSE || 2518711890bcSjc156560 ctl_tagp == NULL) { 2519711890bcSjc156560 return (FAILURE); 25207c478bd9Sstevel@tonic-gate } 2521711890bcSjc156560 *ctl_tagp = (atoi(argp)); 2522711890bcSjc156560 return (SUCCESS); 25237c478bd9Sstevel@tonic-gate } 25247c478bd9Sstevel@tonic-gate 25257c478bd9Sstevel@tonic-gate /* 2526711890bcSjc156560 * get_array_tag(argp, ctl_tagp, array_tagp) 2527711890bcSjc156560 * This function parses array string to get array tag and controller tag. 2528711890bcSjc156560 * The return value is SUCCESS if the string has legal format, or 2529711890bcSjc156560 * FAILURE if it fails. 25307c478bd9Sstevel@tonic-gate */ 2531711890bcSjc156560 static int 2532711890bcSjc156560 get_array_tag(char *argp, uint32_t *ctl_tagp, array_tag_t *array_tagp) 2533711890bcSjc156560 { 2534711890bcSjc156560 char *t = NULL; 2535711890bcSjc156560 char *cp = NULL; 2536711890bcSjc156560 char *tp = NULL; 2537711890bcSjc156560 char *dp = NULL; 2538711890bcSjc156560 2539711890bcSjc156560 uint32_t value_c = MAX32BIT; 2540711890bcSjc156560 uint32_t value_t = MAX32BIT; 2541711890bcSjc156560 uint32_t value_d = MAX32BIT; 2542711890bcSjc156560 2543711890bcSjc156560 int len = 0; 2544711890bcSjc156560 2545711890bcSjc156560 if (argp == NULL || (len = strlen(argp)) == 0 || 2546711890bcSjc156560 array_tagp == NULL) { 2547711890bcSjc156560 return (FAILURE); 2548711890bcSjc156560 } 2549711890bcSjc156560 2550711890bcSjc156560 t = (char *)malloc(len + 1); 2551711890bcSjc156560 if (t == NULL) { 2552711890bcSjc156560 return (FAILURE); 2553711890bcSjc156560 } 2554711890bcSjc156560 2555711890bcSjc156560 (void) memcpy(t, argp, len + 1); 2556711890bcSjc156560 2557711890bcSjc156560 /* Now remmber to release t memory if exception occurs */ 2558711890bcSjc156560 if (((dp = strchr(t, 'd')) == NULL) || 2559711890bcSjc156560 ((tp = strchr(t, 't')) == NULL) || 2560711890bcSjc156560 ((cp = strchr(t, 'c')) == NULL)) { 2561711890bcSjc156560 free(t); 2562711890bcSjc156560 return (FAILURE); 2563711890bcSjc156560 } 2564711890bcSjc156560 cp = t; 2565711890bcSjc156560 2566711890bcSjc156560 *dp = '\0'; 2567711890bcSjc156560 dp++; 2568711890bcSjc156560 *tp = '\0'; 2569711890bcSjc156560 tp++; 2570711890bcSjc156560 cp++; 2571711890bcSjc156560 2572711890bcSjc156560 if (is_fully_numeric(dp) == FALSE || 2573711890bcSjc156560 is_fully_numeric(tp) == FALSE || 2574711890bcSjc156560 is_fully_numeric(cp) == FALSE) { 2575711890bcSjc156560 free(t); 2576711890bcSjc156560 return (FAILURE); 2577711890bcSjc156560 } 2578711890bcSjc156560 2579711890bcSjc156560 value_c = atoi(cp); 2580711890bcSjc156560 value_t = atoi(tp); 2581711890bcSjc156560 value_d = atoi(dp); 2582711890bcSjc156560 2583711890bcSjc156560 array_tagp->idl.target_id = value_t; 2584711890bcSjc156560 array_tagp->idl.lun = value_d; 2585711890bcSjc156560 2586711890bcSjc156560 if (ctl_tagp != NULL) { 2587711890bcSjc156560 *ctl_tagp = value_c; 2588711890bcSjc156560 } 2589711890bcSjc156560 2590711890bcSjc156560 free(t); 2591711890bcSjc156560 return (SUCCESS); 2592711890bcSjc156560 } 2593711890bcSjc156560 2594711890bcSjc156560 /* 2595711890bcSjc156560 * get_disk_tag_ctd(argp, disk_tagp) 2596711890bcSjc156560 * This function parses disk string of ctd format, and translates it to 2597711890bcSjc156560 * disk tag and controller tag. The tags is returned by out parameters. 2598711890bcSjc156560 * The return value is SUCCESS if the string has legal format, or FAILURE 2599711890bcSjc156560 * if it fails. 2600711890bcSjc156560 */ 2601711890bcSjc156560 static int 2602711890bcSjc156560 get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, uint32_t *ctl_tag) 2603711890bcSjc156560 { 2604711890bcSjc156560 char *t = NULL; 2605711890bcSjc156560 char *cp = NULL; 2606711890bcSjc156560 char *tp = NULL; 2607711890bcSjc156560 char *dp = NULL; 2608711890bcSjc156560 2609711890bcSjc156560 uint32_t value_c = MAX32BIT; 2610711890bcSjc156560 uint32_t value_t = MAX32BIT; 2611711890bcSjc156560 uint32_t value_d = MAX32BIT; 2612711890bcSjc156560 2613711890bcSjc156560 int len = 0; 2614711890bcSjc156560 2615711890bcSjc156560 if (argp == NULL || (len = strlen(argp)) == 0 || 2616711890bcSjc156560 disk_tagp == NULL) { 2617711890bcSjc156560 return (FAILURE); 2618711890bcSjc156560 } 2619711890bcSjc156560 2620711890bcSjc156560 t = (char *)malloc(len + 1); 2621711890bcSjc156560 if (t == NULL) { 2622711890bcSjc156560 return (FAILURE); 2623711890bcSjc156560 } 2624711890bcSjc156560 2625711890bcSjc156560 (void) memcpy(t, argp, len + 1); 2626711890bcSjc156560 2627711890bcSjc156560 /* Now remmber to release t memory if exception occurs */ 2628711890bcSjc156560 if (((dp = strchr(t, 'd')) == NULL) || 2629711890bcSjc156560 ((tp = strchr(t, 't')) == NULL) || 2630711890bcSjc156560 ((cp = strchr(t, 'c')) == NULL)) { 2631711890bcSjc156560 free(t); 2632711890bcSjc156560 return (FAILURE); 2633711890bcSjc156560 } 2634711890bcSjc156560 cp = t; 2635711890bcSjc156560 2636711890bcSjc156560 *dp = '\0'; 2637711890bcSjc156560 dp++; 2638711890bcSjc156560 *tp = '\0'; 2639711890bcSjc156560 tp++; 2640711890bcSjc156560 cp++; 2641711890bcSjc156560 2642711890bcSjc156560 if (is_fully_numeric(dp) == FALSE || 2643711890bcSjc156560 is_fully_numeric(tp) == FALSE || 2644711890bcSjc156560 is_fully_numeric(cp) == FALSE) { 2645711890bcSjc156560 free(t); 2646711890bcSjc156560 return (FAILURE); 2647711890bcSjc156560 } 2648711890bcSjc156560 2649711890bcSjc156560 value_c = atoi(cp); 2650711890bcSjc156560 value_t = atoi(tp); 2651711890bcSjc156560 value_d = atoi(dp); 2652711890bcSjc156560 2653711890bcSjc156560 disk_tagp->cidl.bus = 0; 2654711890bcSjc156560 disk_tagp->cidl.target_id = value_t; 2655711890bcSjc156560 disk_tagp->cidl.lun = value_d; 2656711890bcSjc156560 *ctl_tag = value_c; 2657711890bcSjc156560 2658711890bcSjc156560 free(t); 2659711890bcSjc156560 return (SUCCESS); 2660711890bcSjc156560 } 2661711890bcSjc156560 2662711890bcSjc156560 /* 2663711890bcSjc156560 * get_disk_tag_cidl(argp, disk_tagp) 2664711890bcSjc156560 * This function parses disk string of cidl format and translates it to tag. 2665711890bcSjc156560 * The return value is disk tag if the string has legal format, or FAILURE 2666711890bcSjc156560 * if it fails. 2667711890bcSjc156560 */ 2668711890bcSjc156560 static int 2669711890bcSjc156560 get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp) 2670711890bcSjc156560 { 2671711890bcSjc156560 int len = 0; 2672711890bcSjc156560 char *p = NULL; 2673711890bcSjc156560 char *t = NULL; 2674711890bcSjc156560 char *dot1p = NULL; 2675711890bcSjc156560 char *dot2p = NULL; 2676711890bcSjc156560 2677711890bcSjc156560 if (argp == NULL || (len = strlen(argp)) == 0) { 2678711890bcSjc156560 return (FAILURE); 2679711890bcSjc156560 } 2680711890bcSjc156560 2681711890bcSjc156560 if (disk_tagp == NULL) { 2682711890bcSjc156560 return (FAILURE); 2683711890bcSjc156560 } 2684711890bcSjc156560 2685711890bcSjc156560 t = (char *)malloc(len + 1); 2686711890bcSjc156560 if (t == NULL) { 2687711890bcSjc156560 return (FAILURE); 2688711890bcSjc156560 } 2689711890bcSjc156560 2690711890bcSjc156560 (void) memcpy(t, argp, len + 1); 2691711890bcSjc156560 p = t; 2692711890bcSjc156560 2693711890bcSjc156560 dot2p = strrchr(p, '.'); 2694711890bcSjc156560 if (dot2p == NULL) { 2695711890bcSjc156560 free(t); 2696711890bcSjc156560 return (FAILURE); 2697711890bcSjc156560 } 2698711890bcSjc156560 *dot2p = '\0'; 2699711890bcSjc156560 dot2p++; 2700711890bcSjc156560 2701711890bcSjc156560 dot1p = strrchr(p, '.'); 2702711890bcSjc156560 if (dot1p == NULL) { 2703711890bcSjc156560 free(t); 2704711890bcSjc156560 return (FAILURE); 2705711890bcSjc156560 } 2706711890bcSjc156560 *dot1p = '\0'; 2707711890bcSjc156560 dot1p++; 2708711890bcSjc156560 2709711890bcSjc156560 /* Assert only 2 dots in this string */ 2710711890bcSjc156560 if (strrchr(p, '.') != NULL) { 2711711890bcSjc156560 free(t); 2712711890bcSjc156560 return (FAILURE); 2713711890bcSjc156560 } 2714711890bcSjc156560 2715711890bcSjc156560 while (*p == ' ') 2716711890bcSjc156560 p++; 2717711890bcSjc156560 2718711890bcSjc156560 if (is_fully_numeric(p) == FALSE || 2719711890bcSjc156560 is_fully_numeric(dot1p) == FALSE || 2720711890bcSjc156560 is_fully_numeric(dot2p) == FALSE) { 2721711890bcSjc156560 free(t); 2722711890bcSjc156560 return (FAILURE); 2723711890bcSjc156560 } 2724711890bcSjc156560 2725711890bcSjc156560 disk_tagp->cidl.bus = atoi(p); 2726711890bcSjc156560 disk_tagp->cidl.target_id = atoi(dot1p); 2727711890bcSjc156560 disk_tagp->cidl.lun = atoi(dot2p); 2728711890bcSjc156560 2729711890bcSjc156560 free(t); 2730711890bcSjc156560 return (SUCCESS); 2731711890bcSjc156560 } 2732711890bcSjc156560 2733711890bcSjc156560 /* 2734711890bcSjc156560 * calc_size(sizep, valp) 2735711890bcSjc156560 * This function calculates the value represented by string sizep. 2736711890bcSjc156560 * The string sizep can be decomposed into three parts: an initial, 2737711890bcSjc156560 * possibly empty, sequence of white-space characters; a subject digital 2738711890bcSjc156560 * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a 2739711890bcSjc156560 * final string of one or more unrecognized characters or white-sapce 2740711890bcSjc156560 * characters, including the terminating null. If unrecognized character 2741711890bcSjc156560 * exists or overflow happens, the conversion must fail and return 2742711890bcSjc156560 * INVALID_ARG. If the conversion is performed successfully, result will 2743711890bcSjc156560 * be saved into valp and function returns SUCCESS. It returns FAILURE 2744711890bcSjc156560 * when memory allocation fails. 2745711890bcSjc156560 */ 2746711890bcSjc156560 static int 2747711890bcSjc156560 calc_size(char *sizep, uint64_t *valp) 2748711890bcSjc156560 { 2749711890bcSjc156560 int len; 2750711890bcSjc156560 uint64_t size; 2751711890bcSjc156560 uint64_t unit; 2752711890bcSjc156560 char *t = NULL; 2753711890bcSjc156560 char *tailp = NULL; 2754711890bcSjc156560 2755711890bcSjc156560 if (sizep == NULL || valp == NULL) { 2756711890bcSjc156560 return (INVALID_ARG); 2757700682b8Syw161884 } 2758700682b8Syw161884 2759700682b8Syw161884 if (is_fully_numeric(sizep) == TRUE) { 2760700682b8Syw161884 *valp = atoi(sizep); 2761700682b8Syw161884 return (SUCCESS); 2762711890bcSjc156560 } 2763711890bcSjc156560 2764711890bcSjc156560 len = strlen(sizep); 2765711890bcSjc156560 if (len == 0) { 2766711890bcSjc156560 return (INVALID_ARG); 2767711890bcSjc156560 } 2768711890bcSjc156560 2769711890bcSjc156560 t = (char *)malloc(len + 1); 2770711890bcSjc156560 if (t == NULL) { 2771711890bcSjc156560 return (FAILURE); 2772711890bcSjc156560 } 2773711890bcSjc156560 2774711890bcSjc156560 (void) memcpy(t, sizep, len + 1); 2775711890bcSjc156560 2776711890bcSjc156560 switch (*(t + len - 1)) { 2777711890bcSjc156560 case 'k': 2778711890bcSjc156560 case 'K': 2779711890bcSjc156560 unit = 1024ull; 2780711890bcSjc156560 errno = 0; 2781711890bcSjc156560 size = strtoll(t, &tailp, 0); 2782711890bcSjc156560 break; 2783711890bcSjc156560 case 'm': 2784711890bcSjc156560 case 'M': 2785711890bcSjc156560 unit = 1024ull * 1024ull; 2786711890bcSjc156560 errno = 0; 2787711890bcSjc156560 size = strtoll(t, &tailp, 0); 2788711890bcSjc156560 break; 2789711890bcSjc156560 case 'g': 2790711890bcSjc156560 case 'G': 2791711890bcSjc156560 unit = 1024ull * 1024ull * 1024ull; 2792711890bcSjc156560 errno = 0; 2793711890bcSjc156560 size = strtoll(t, &tailp, 0); 2794711890bcSjc156560 break; 2795711890bcSjc156560 case 't': 2796711890bcSjc156560 case 'T': 2797711890bcSjc156560 unit = 1024ull * 1024ull * 1024ull * 1024ull; 2798711890bcSjc156560 errno = 0; 2799711890bcSjc156560 size = strtoll(t, &tailp, 0); 2800711890bcSjc156560 break; 2801711890bcSjc156560 default: 2802711890bcSjc156560 /* The unit must be kilobyte at least. */ 2803711890bcSjc156560 free(t); 2804711890bcSjc156560 return (INVALID_ARG); 2805711890bcSjc156560 } 2806711890bcSjc156560 2807711890bcSjc156560 *(t + len - 1) = '\0'; 2808711890bcSjc156560 if (is_fully_numeric(t) != TRUE) { 2809711890bcSjc156560 free(t); 2810711890bcSjc156560 return (INVALID_ARG); 2811711890bcSjc156560 } 2812711890bcSjc156560 2813711890bcSjc156560 errno = 0; 2814711890bcSjc156560 size = strtoll(t, &tailp, 0); 2815711890bcSjc156560 2816711890bcSjc156560 /* Check overflow condition */ 2817711890bcSjc156560 if (errno == ERANGE || (size > (MAX64BIT / unit))) { 2818711890bcSjc156560 free(t); 2819711890bcSjc156560 return (INVALID_ARG); 2820711890bcSjc156560 } 2821711890bcSjc156560 2822711890bcSjc156560 *valp = size * unit; 2823711890bcSjc156560 free(t); 2824711890bcSjc156560 return (SUCCESS); 2825711890bcSjc156560 } 2826711890bcSjc156560 2827711890bcSjc156560 /* 2828711890bcSjc156560 * is_fully_numeric(str) 2829711890bcSjc156560 * This function checks if the string are legal numeric string. The beginning 2830711890bcSjc156560 * or ending characters can be white spaces. 2831711890bcSjc156560 * Return value is TRUE if the string are legal numeric string, or FALSE 2832711890bcSjc156560 * otherwise. 2833711890bcSjc156560 */ 2834711890bcSjc156560 static int 2835711890bcSjc156560 is_fully_numeric(char *strp) 2836711890bcSjc156560 { 2837711890bcSjc156560 uint32_t len; 2838711890bcSjc156560 uint32_t i; 2839711890bcSjc156560 2840711890bcSjc156560 if (strp == NULL) { 2841711890bcSjc156560 return (FALSE); 2842711890bcSjc156560 } 2843711890bcSjc156560 2844711890bcSjc156560 len = strlen(strp); 2845711890bcSjc156560 if (len == 0) { 2846711890bcSjc156560 return (FALSE); 2847711890bcSjc156560 } 2848711890bcSjc156560 2849711890bcSjc156560 /* Skip whitespace characters */ 2850711890bcSjc156560 for (i = 0; i < len; i++) { 2851711890bcSjc156560 if (strp[i] != ' ') { 28527c478bd9Sstevel@tonic-gate break; 28537c478bd9Sstevel@tonic-gate } 28547c478bd9Sstevel@tonic-gate } 28557c478bd9Sstevel@tonic-gate 2856711890bcSjc156560 /* if strp points all space characters */ 2857711890bcSjc156560 if (i == len) { 2858711890bcSjc156560 return (FALSE); 28597c478bd9Sstevel@tonic-gate } 28607c478bd9Sstevel@tonic-gate 2861711890bcSjc156560 /* Check the digitals in string */ 2862711890bcSjc156560 for (; i < len; i++) { 2863711890bcSjc156560 if (!isdigit(strp[i])) { 28647c478bd9Sstevel@tonic-gate break; 28657c478bd9Sstevel@tonic-gate } 28667c478bd9Sstevel@tonic-gate } 28677c478bd9Sstevel@tonic-gate 2868711890bcSjc156560 /* Check the ending string */ 2869711890bcSjc156560 for (; i < len; i++) { 2870711890bcSjc156560 if (strp[i] != ' ') { 2871711890bcSjc156560 return (FALSE); 28727c478bd9Sstevel@tonic-gate } 28737c478bd9Sstevel@tonic-gate } 28747c478bd9Sstevel@tonic-gate 2875711890bcSjc156560 return (TRUE); 28767c478bd9Sstevel@tonic-gate } 28777c478bd9Sstevel@tonic-gate 28787c478bd9Sstevel@tonic-gate static int 28796fec3791Sjesseb yes(void) 28807c478bd9Sstevel@tonic-gate { 28817c478bd9Sstevel@tonic-gate int i, b; 28827c478bd9Sstevel@tonic-gate char ans[SCHAR_MAX + 1]; 28837c478bd9Sstevel@tonic-gate 28847c478bd9Sstevel@tonic-gate for (i = 0; ; i++) { 28857c478bd9Sstevel@tonic-gate b = getchar(); 28867c478bd9Sstevel@tonic-gate if (b == '\n' || b == '\0' || b == EOF) { 28877c478bd9Sstevel@tonic-gate ans[i] = 0; 28887c478bd9Sstevel@tonic-gate break; 28897c478bd9Sstevel@tonic-gate } 2890711890bcSjc156560 if (i < SCHAR_MAX) { 28917c478bd9Sstevel@tonic-gate ans[i] = b; 28927c478bd9Sstevel@tonic-gate } 2893711890bcSjc156560 } 28947c478bd9Sstevel@tonic-gate if (i >= SCHAR_MAX) { 28957c478bd9Sstevel@tonic-gate i = SCHAR_MAX; 28967c478bd9Sstevel@tonic-gate ans[SCHAR_MAX] = 0; 28977c478bd9Sstevel@tonic-gate } 28986fec3791Sjesseb 2899711890bcSjc156560 return (rpmatch(ans)); 2900711890bcSjc156560 } 2901711890bcSjc156560 2902711890bcSjc156560 /* 2903711890bcSjc156560 * Function: int rpmatch(char *) 2904711890bcSjc156560 * 2905711890bcSjc156560 * Description: 2906711890bcSjc156560 * 2907711890bcSjc156560 * Internationalized get yes / no answer. 2908711890bcSjc156560 * 2909711890bcSjc156560 * Inputs: 2910711890bcSjc156560 * s -> Pointer to answer to compare against. 2911711890bcSjc156560 * 2912711890bcSjc156560 * Returns: 2913711890bcSjc156560 * TRUE -> Answer was affirmative 2914711890bcSjc156560 * FALSE -> Answer was negative 2915711890bcSjc156560 */ 2916711890bcSjc156560 2917711890bcSjc156560 static int 2918711890bcSjc156560 rpmatch(char *s) 2919711890bcSjc156560 { 2920711890bcSjc156560 int status; 2921711890bcSjc156560 2922711890bcSjc156560 /* match yesexpr */ 2923711890bcSjc156560 status = regexec(&re, s, (size_t)0, NULL, 0); 2924711890bcSjc156560 if (status != 0) { 2925711890bcSjc156560 return (FALSE); 2926711890bcSjc156560 } 2927711890bcSjc156560 return (TRUE); 29287c478bd9Sstevel@tonic-gate } 29297c478bd9Sstevel@tonic-gate 29307c478bd9Sstevel@tonic-gate static int 2931711890bcSjc156560 size_to_string(uint64_t size, char *string, int len) 29327c478bd9Sstevel@tonic-gate { 2933711890bcSjc156560 int i = 0; 2934711890bcSjc156560 uint32_t remainder; 2935711890bcSjc156560 char unit[][2] = {" ", "K", "M", "G", "T"}; 29367c478bd9Sstevel@tonic-gate 2937711890bcSjc156560 if (string == NULL) { 2938711890bcSjc156560 return (FAILURE); 2939711890bcSjc156560 } 2940711890bcSjc156560 while (size > 1023) { 2941711890bcSjc156560 remainder = size % 1024; 2942711890bcSjc156560 size /= 1024; 2943711890bcSjc156560 i++; 2944711890bcSjc156560 } 2945711890bcSjc156560 2946711890bcSjc156560 if (i > 4) { 29477c478bd9Sstevel@tonic-gate return (FAILURE); 29487c478bd9Sstevel@tonic-gate } 29497c478bd9Sstevel@tonic-gate 2950711890bcSjc156560 remainder /= 103; 2951711890bcSjc156560 if (remainder == 0) { 2952711890bcSjc156560 (void) snprintf(string, len, "%llu", size); 2953711890bcSjc156560 } else { 2954711890bcSjc156560 (void) snprintf(string, len, "%llu.%1u", size, 2955711890bcSjc156560 remainder); 29567c478bd9Sstevel@tonic-gate } 29577c478bd9Sstevel@tonic-gate 2958711890bcSjc156560 /* make sure there is one byte for unit */ 2959711890bcSjc156560 if ((strlen(string) + 1) >= len) { 29607c478bd9Sstevel@tonic-gate return (FAILURE); 29617c478bd9Sstevel@tonic-gate } 2962317fb4acSYu-Bo Ryan Wang (void) strlcat(string, unit[i], len); 29637c478bd9Sstevel@tonic-gate 29647c478bd9Sstevel@tonic-gate return (SUCCESS); 29657c478bd9Sstevel@tonic-gate } 29667c478bd9Sstevel@tonic-gate 29677c478bd9Sstevel@tonic-gate /* 2968711890bcSjc156560 * Only one raidctl is running at one time. 29697c478bd9Sstevel@tonic-gate */ 29707c478bd9Sstevel@tonic-gate static int 2971711890bcSjc156560 enter_raidctl_lock(int *fd) 29727c478bd9Sstevel@tonic-gate { 2973711890bcSjc156560 int fd0 = -1; 2974711890bcSjc156560 struct flock lock; 29757c478bd9Sstevel@tonic-gate 2976711890bcSjc156560 fd0 = open(RAIDCTL_LOCKF, O_CREAT|O_WRONLY, 0600); 2977711890bcSjc156560 if (fd0 < 0) { 29787978b887Sanbui if (errno == EACCES) { 29797978b887Sanbui (void) fprintf(stderr, 29807978b887Sanbui gettext("raidctl:must be root to run raidctl" 29817978b887Sanbui ": %s\n"), strerror(errno)); 29827978b887Sanbui } else { 29837978b887Sanbui (void) fprintf(stderr, 29847978b887Sanbui gettext("raidctl:failed to open lockfile" 2985711890bcSjc156560 " '"RAIDCTL_LOCKF"': %s\n"), strerror(errno)); 29867978b887Sanbui } 29877c478bd9Sstevel@tonic-gate return (FAILURE); 29887c478bd9Sstevel@tonic-gate } 29897c478bd9Sstevel@tonic-gate 2990711890bcSjc156560 *fd = fd0; 2991711890bcSjc156560 lock.l_type = F_WRLCK; 2992711890bcSjc156560 lock.l_whence = SEEK_SET; 2993711890bcSjc156560 lock.l_start = 0; 2994711890bcSjc156560 lock.l_len = 0; 2995711890bcSjc156560 2996711890bcSjc156560 if ((fcntl(fd0, F_SETLK, &lock) == -1) && 2997711890bcSjc156560 (errno == EAGAIN || errno == EDEADLK)) { 2998711890bcSjc156560 if (fcntl(fd0, F_GETLK, &lock) == -1) { 2999711890bcSjc156560 (void) fprintf(stderr, 3000711890bcSjc156560 gettext("raidctl:enter_filelock error\n")); 30017c478bd9Sstevel@tonic-gate return (FAILURE); 30027c478bd9Sstevel@tonic-gate } 3003711890bcSjc156560 (void) fprintf(stderr, gettext("raidctl:" 3004711890bcSjc156560 "enter_filelock:filelock is owned " 3005711890bcSjc156560 "by 'process %d'\n"), lock.l_pid); 3006711890bcSjc156560 return (FAILURE); 30077c478bd9Sstevel@tonic-gate } 30087c478bd9Sstevel@tonic-gate 3009711890bcSjc156560 return (SUCCESS); 30107c478bd9Sstevel@tonic-gate } 30116fec3791Sjesseb 3012711890bcSjc156560 static void 3013711890bcSjc156560 exit_raidctl_lock(int fd) 3014711890bcSjc156560 { 3015711890bcSjc156560 struct flock lock; 30167c478bd9Sstevel@tonic-gate 3017711890bcSjc156560 lock.l_type = F_UNLCK; 3018711890bcSjc156560 lock.l_whence = SEEK_SET; 3019711890bcSjc156560 lock.l_start = 0; 3020711890bcSjc156560 lock.l_len = 0; 3021711890bcSjc156560 if (fcntl(fd, F_SETLK, &lock) == -1) { 3022711890bcSjc156560 (void) fprintf(stderr, gettext("raidctl: failed to" 3023711890bcSjc156560 " exit_filelock: %s\n"), 3024711890bcSjc156560 strerror(errno)); 30257c478bd9Sstevel@tonic-gate } 3026711890bcSjc156560 (void) close(fd); 30277c478bd9Sstevel@tonic-gate } 3028