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 20*711890bcSjc156560 * 21*711890bcSjc156560 * 22*711890bcSjc156560 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24*711890bcSjc156560 * 25*711890bcSjc156560 * raidctl.c is the entry file of RAID configuration utility. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <ctype.h> 31*711890bcSjc156560 #include <sys/types.h> 32*711890bcSjc156560 #include <sys/stat.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <langinfo.h> 35*711890bcSjc156560 #include <regex.h> 367c478bd9Sstevel@tonic-gate #include <locale.h> 37*711890bcSjc156560 #include <libintl.h> 387c478bd9Sstevel@tonic-gate #include <stdio.h> 397c478bd9Sstevel@tonic-gate #include <stdlib.h> 407c478bd9Sstevel@tonic-gate #include <string.h> 417c478bd9Sstevel@tonic-gate #include <strings.h> 427c478bd9Sstevel@tonic-gate #include <unistd.h> 43*711890bcSjc156560 #include <errno.h> 44*711890bcSjc156560 #include <libgen.h> 45*711890bcSjc156560 #include <raidcfg.h> 46*711890bcSjc156560 47*711890bcSjc156560 48*711890bcSjc156560 #define TRUE 1 49*711890bcSjc156560 #define FALSE 0 50*711890bcSjc156560 51*711890bcSjc156560 #ifndef TEXT_DOMAIN 52*711890bcSjc156560 #define TEXT_DOMAIN "SYS_TEST" 53*711890bcSjc156560 #endif 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* 56*711890bcSjc156560 * Return value of command 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate #define SUCCESS 0 597c478bd9Sstevel@tonic-gate #define INVALID_ARG 1 607c478bd9Sstevel@tonic-gate #define FAILURE 2 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 63*711890bcSjc156560 * Initial value of variables 647c478bd9Sstevel@tonic-gate */ 65*711890bcSjc156560 #define INIT_HANDLE_VALUE -3 66*711890bcSjc156560 #define MAX64BIT 0xffffffffffffffffull 67*711890bcSjc156560 #define MAX32BIT 0xfffffffful 687c478bd9Sstevel@tonic-gate 69*711890bcSjc156560 /* 70*711890bcSjc156560 * Flag of set or unset HSP 71*711890bcSjc156560 */ 72*711890bcSjc156560 #define HSP_SET 1 73*711890bcSjc156560 #define HSP_UNSET 0 747c478bd9Sstevel@tonic-gate 75*711890bcSjc156560 /* 76*711890bcSjc156560 * Operate codes of command 77*711890bcSjc156560 */ 78*711890bcSjc156560 #define DO_HW_RAID_NOP -1 79*711890bcSjc156560 #define DO_HW_RAID_HELP 0 80*711890bcSjc156560 #define DO_HW_RAID_CREATEO 1 81*711890bcSjc156560 #define DO_HW_RAID_CREATEN 2 82*711890bcSjc156560 #define DO_HW_RAID_DELETE 3 83*711890bcSjc156560 #define DO_HW_RAID_LIST 4 84*711890bcSjc156560 #define DO_HW_RAID_FLASH 5 85*711890bcSjc156560 #define DO_HW_RAID_HSP 6 86*711890bcSjc156560 #define DO_HW_RAID_SET_ATTR 7 87*711890bcSjc156560 #define DO_HW_RAID_SNAPSHOT 8 887c478bd9Sstevel@tonic-gate 89*711890bcSjc156560 #define LOWER_H (1 << 0) 90*711890bcSjc156560 #define LOWER_C (1 << 1) 91*711890bcSjc156560 #define LOWER_D (1 << 2) 92*711890bcSjc156560 #define LOWER_L (1 << 3) 93*711890bcSjc156560 #define LOWER_R (1 << 4) 94*711890bcSjc156560 #define LOWER_Z (1 << 5) 95*711890bcSjc156560 #define LOWER_G (1 << 6) 96*711890bcSjc156560 #define LOWER_A (1 << 7) 97*711890bcSjc156560 #define LOWER_S (1 << 8) 98*711890bcSjc156560 #define LOWER_P (1 << 9) 99*711890bcSjc156560 #define LOWER_F (1 << 10) 100*711890bcSjc156560 #define UPPER_S (1 << 11) 101*711890bcSjc156560 #define UPPER_C (1 << 12) 102*711890bcSjc156560 #define UPPER_F (1 << 13) 1037c478bd9Sstevel@tonic-gate 104*711890bcSjc156560 /* Add a ARRAY state (temporary) */ 105*711890bcSjc156560 #define ARRAY_STATE_SYNC 100 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * Function and strings to properly localize our prompt. 109*711890bcSjc156560 * So for example in German it would ask (ja/nein) or (yes/no) in 1107c478bd9Sstevel@tonic-gate * english. 1117c478bd9Sstevel@tonic-gate */ 112*711890bcSjc156560 #ifndef SCHAR_MAX 113*711890bcSjc156560 #define SCHAR_MAX 10 114*711890bcSjc156560 #endif 115*711890bcSjc156560 116*711890bcSjc156560 #define RAIDCTL_LOCKF "/var/run/lockf_raidctl" 117*711890bcSjc156560 118*711890bcSjc156560 /* Locale setting */ 1196fec3791Sjesseb static int yes(void); 120*711890bcSjc156560 static int rpmatch(char *s); 121*711890bcSjc156560 static char *yesstr = NULL; 122*711890bcSjc156560 static char *nostr = NULL; 123*711890bcSjc156560 static char *yesexpr = NULL; 1247c478bd9Sstevel@tonic-gate 125*711890bcSjc156560 static char *default_yesexpr = "^[yY]"; 126*711890bcSjc156560 static char *default_yesstr = "yes"; 127*711890bcSjc156560 static char *default_nostr = "no"; 1287c478bd9Sstevel@tonic-gate 129*711890bcSjc156560 static regex_t re; 130*711890bcSjc156560 131*711890bcSjc156560 #define SET_DEFAULT_STRS \ 132*711890bcSjc156560 regfree(&re); \ 133*711890bcSjc156560 free(yesexpr); \ 134*711890bcSjc156560 free(yesstr); \ 135*711890bcSjc156560 free(nostr); \ 136*711890bcSjc156560 yesexpr = default_yesexpr; \ 137*711890bcSjc156560 yesstr = default_yesstr; \ 138*711890bcSjc156560 nostr = default_nostr; 139*711890bcSjc156560 140*711890bcSjc156560 #define FREE_STRS \ 141*711890bcSjc156560 if (yesexpr != default_yesexpr) \ 142*711890bcSjc156560 free(yesexpr); \ 143*711890bcSjc156560 if (yesstr != default_yesstr) \ 144*711890bcSjc156560 free(yesstr); \ 145*711890bcSjc156560 if (nostr != default_nostr) \ 146*711890bcSjc156560 free(nostr); 147*711890bcSjc156560 148*711890bcSjc156560 /* program name */ 149*711890bcSjc156560 static char *prog_namep; 150*711890bcSjc156560 1517c478bd9Sstevel@tonic-gate 1526fec3791Sjesseb /* 153*711890bcSjc156560 * Functions declaration 1546fec3791Sjesseb */ 155*711890bcSjc156560 static void helpinfo(char *prog_namep); 156*711890bcSjc156560 static int do_create_cidl(char *raid_levelp, char *capacityp, char *disk_argp, 157*711890bcSjc156560 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind); 158*711890bcSjc156560 static int do_create_ctd(char *raid_levelp, char **disks_argpp, 159*711890bcSjc156560 uint32_t disks_num, uint32_t argindex, uint32_t f_flag); 160*711890bcSjc156560 static int do_list(char *disk_argp, char **argv, uint32_t optind, 161*711890bcSjc156560 uint8_t is_snapshot); 162*711890bcSjc156560 static int do_delete(uint32_t f_flag, char **argv, uint32_t optind); 163*711890bcSjc156560 static int do_flash(uint8_t f_flag, char *filep, char **ctls_argpp, 164*711890bcSjc156560 uint32_t index, uint32_t ctl_num); 165*711890bcSjc156560 static int do_set_hsp(char *a_argp, char *disk_argp, char **argv, 166*711890bcSjc156560 uint32_t optind); 167*711890bcSjc156560 static int do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, 168*711890bcSjc156560 uint32_t optind); 169*711890bcSjc156560 static int snapshot_raidsystem(uint8_t recursive, uint8_t indent, 170*711890bcSjc156560 uint8_t is_snapshot); 171*711890bcSjc156560 static int snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, 172*711890bcSjc156560 uint8_t indent, uint8_t is_snapshot); 173*711890bcSjc156560 static int snapshot_array(raid_obj_handle_t array_handle, 174*711890bcSjc156560 uint8_t indent, uint8_t is_sub, uint8_t is_snapshot); 175*711890bcSjc156560 static int snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, 176*711890bcSjc156560 uint8_t indent, uint8_t is_snapshot); 177*711890bcSjc156560 static int print_ctl_table(raid_obj_handle_t ctl_handle); 178*711890bcSjc156560 static int print_array_table(raid_obj_handle_t ctl_handle, 179*711890bcSjc156560 raid_obj_handle_t array_handle); 180*711890bcSjc156560 static int print_disk_table(raid_obj_handle_t ctl_handle, 181*711890bcSjc156560 raid_obj_handle_t disk_handle); 182*711890bcSjc156560 static int print_ctl_attr(raidcfg_controller_t *attrp); 183*711890bcSjc156560 static int print_array_attr(raidcfg_array_t *attrp); 184*711890bcSjc156560 static int print_arraypart_attr(raidcfg_arraypart_t *attrp); 185*711890bcSjc156560 static int print_disk_attr(raid_obj_handle_t ctl_handle, 186*711890bcSjc156560 raid_obj_handle_t disk_handle, raidcfg_disk_t *attrp); 187*711890bcSjc156560 static void print_indent(uint8_t indent); 188*711890bcSjc156560 static int get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, 189*711890bcSjc156560 int *comps_nump, raid_obj_handle_t **handlespp); 190*711890bcSjc156560 static int get_disk_handle_ctd(int disks_num, char **disks_argpp, 191*711890bcSjc156560 uint32_t *ctl_tagp, raid_obj_handle_t *disks_handlep); 192*711890bcSjc156560 static int get_ctl_tag(char *argp, uint32_t *ctl_tagp); 193*711890bcSjc156560 static int get_array_tag(char *argp, uint32_t *ctl_tagp, 194*711890bcSjc156560 array_tag_t *array_tagp); 195*711890bcSjc156560 static int get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, 196*711890bcSjc156560 uint32_t *controller_id); 197*711890bcSjc156560 static int get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp); 198*711890bcSjc156560 static int calc_size(char *sizep, uint64_t *valp); 199*711890bcSjc156560 static int is_fully_numeric(char *strp); 200*711890bcSjc156560 static int size_to_string(uint64_t size, char *string, int len); 201*711890bcSjc156560 static int enter_raidctl_lock(int *fd); 202*711890bcSjc156560 static void exit_raidctl_lock(int fd); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 205*711890bcSjc156560 * Entry function of raidctl command 2067c478bd9Sstevel@tonic-gate */ 207*711890bcSjc156560 int 208*711890bcSjc156560 main(int argc, char **argv) 2097c478bd9Sstevel@tonic-gate { 210*711890bcSjc156560 /* operation index */ 211*711890bcSjc156560 int8_t findex = DO_HW_RAID_NOP; 2127c478bd9Sstevel@tonic-gate 213*711890bcSjc156560 /* argument pointers */ 214*711890bcSjc156560 char *r_argp = NULL; 215*711890bcSjc156560 char *z_argp = NULL; 216*711890bcSjc156560 char *g_argp = NULL; 217*711890bcSjc156560 char *a_argp = NULL; 218*711890bcSjc156560 char *s_argp = NULL; 219*711890bcSjc156560 char *p_argp = NULL; 220*711890bcSjc156560 char *F_argp = NULL; 221*711890bcSjc156560 char *C_argp = NULL; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 224*711890bcSjc156560 * operation flags. 2257c478bd9Sstevel@tonic-gate */ 226*711890bcSjc156560 uint8_t r_flag = FALSE; 227*711890bcSjc156560 uint8_t f_flag = FALSE; 228*711890bcSjc156560 uint8_t action = FALSE; 229*711890bcSjc156560 uint64_t options = 0; 2307c478bd9Sstevel@tonic-gate 231*711890bcSjc156560 /* index and temporary variables */ 232*711890bcSjc156560 int ret; 233*711890bcSjc156560 int status; 234*711890bcSjc156560 char c = '\0'; 2357c478bd9Sstevel@tonic-gate 236*711890bcSjc156560 /* fd for the filelock */ 2377c478bd9Sstevel@tonic-gate int fd; 2387c478bd9Sstevel@tonic-gate 239*711890bcSjc156560 if (enter_raidctl_lock(&fd) != SUCCESS) { 2407c478bd9Sstevel@tonic-gate return (FAILURE); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 243*711890bcSjc156560 (void) setlocale(LC_ALL, ""); 244*711890bcSjc156560 (void) textdomain(TEXT_DOMAIN); 2457c478bd9Sstevel@tonic-gate 246*711890bcSjc156560 /* parse command line, and get program name */ 247*711890bcSjc156560 if ((prog_namep = strrchr(argv[0], '/')) == NULL) { 248*711890bcSjc156560 prog_namep = argv[0]; 2496fec3791Sjesseb } else { 250*711890bcSjc156560 prog_namep++; 2516fec3791Sjesseb } 2526fec3791Sjesseb 253*711890bcSjc156560 /* close error option messages from getopt */ 254*711890bcSjc156560 opterr = 0; 2556fec3791Sjesseb 256*711890bcSjc156560 /* get yes expression according to current locale */ 257*711890bcSjc156560 yesexpr = strdup(nl_langinfo(YESEXPR)); 258*711890bcSjc156560 yesstr = strdup(nl_langinfo(YESSTR)); 259*711890bcSjc156560 nostr = strdup(nl_langinfo(NOSTR)); 260*711890bcSjc156560 if (yesexpr == NULL || yesstr == NULL || nostr == NULL) { 2617c478bd9Sstevel@tonic-gate return (FAILURE); 262*711890bcSjc156560 } 263*711890bcSjc156560 264*711890bcSjc156560 /* 265*711890bcSjc156560 * If the was no expression or if there is a compile error 266*711890bcSjc156560 * use default yes expression. 267*711890bcSjc156560 */ 268*711890bcSjc156560 status = regcomp(&re, yesexpr, REG_EXTENDED | REG_NOSUB); 269*711890bcSjc156560 if ((*yesexpr == (char)NULL) || 270*711890bcSjc156560 (*yesstr == (char)NULL) || 271*711890bcSjc156560 (*nostr == (char)NULL) || 272*711890bcSjc156560 (status != 0)) { 273*711890bcSjc156560 SET_DEFAULT_STRS; 274*711890bcSjc156560 if (regcomp(&re, default_yesexpr, 275*711890bcSjc156560 REG_EXTENDED | REG_NOSUB) != 0) { 276*711890bcSjc156560 return (FALSE); 277*711890bcSjc156560 } 278*711890bcSjc156560 } 279*711890bcSjc156560 280*711890bcSjc156560 while ((c = getopt(argc, argv, 281*711890bcSjc156560 "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) { 282*711890bcSjc156560 switch (c) { 283*711890bcSjc156560 case 'h': 284*711890bcSjc156560 case '?': 285*711890bcSjc156560 if (action == FALSE) { 286*711890bcSjc156560 findex = DO_HW_RAID_HELP; 287*711890bcSjc156560 action = TRUE; 288*711890bcSjc156560 options |= LOWER_H; 289*711890bcSjc156560 } else { 290*711890bcSjc156560 findex = DO_HW_RAID_NOP; 291*711890bcSjc156560 } 292*711890bcSjc156560 break; 293*711890bcSjc156560 case 'C': 294*711890bcSjc156560 if (action == FALSE) { 295*711890bcSjc156560 findex = DO_HW_RAID_CREATEN; 296*711890bcSjc156560 C_argp = optarg; 297*711890bcSjc156560 action = TRUE; 298*711890bcSjc156560 options |= UPPER_C; 299*711890bcSjc156560 } else { 300*711890bcSjc156560 findex = DO_HW_RAID_NOP; 301*711890bcSjc156560 } 302*711890bcSjc156560 break; 303*711890bcSjc156560 case 'c': 304*711890bcSjc156560 if (action == FALSE) { 305*711890bcSjc156560 findex = DO_HW_RAID_CREATEO; 306*711890bcSjc156560 action = TRUE; 307*711890bcSjc156560 options |= LOWER_C; 308*711890bcSjc156560 } else { 309*711890bcSjc156560 findex = DO_HW_RAID_NOP; 310*711890bcSjc156560 } 311*711890bcSjc156560 break; 312*711890bcSjc156560 case 'd': 313*711890bcSjc156560 if (action == FALSE) { 314*711890bcSjc156560 findex = DO_HW_RAID_DELETE; 315*711890bcSjc156560 action = TRUE; 316*711890bcSjc156560 options |= LOWER_D; 317*711890bcSjc156560 } else { 318*711890bcSjc156560 findex = DO_HW_RAID_NOP; 319*711890bcSjc156560 } 320*711890bcSjc156560 break; 321*711890bcSjc156560 case 'l': 322*711890bcSjc156560 if (action == FALSE) { 323*711890bcSjc156560 findex = DO_HW_RAID_LIST; 324*711890bcSjc156560 action = TRUE; 325*711890bcSjc156560 options |= LOWER_L; 326*711890bcSjc156560 } else { 327*711890bcSjc156560 findex = DO_HW_RAID_NOP; 328*711890bcSjc156560 } 329*711890bcSjc156560 break; 330*711890bcSjc156560 case 'F': 331*711890bcSjc156560 if (action == FALSE) { 332*711890bcSjc156560 findex = DO_HW_RAID_FLASH; 333*711890bcSjc156560 F_argp = optarg; 334*711890bcSjc156560 action = TRUE; 335*711890bcSjc156560 options |= UPPER_F; 336*711890bcSjc156560 } else { 337*711890bcSjc156560 findex = DO_HW_RAID_NOP; 338*711890bcSjc156560 } 339*711890bcSjc156560 break; 340*711890bcSjc156560 case 'a': 341*711890bcSjc156560 if (action == FALSE) { 342*711890bcSjc156560 findex = DO_HW_RAID_HSP; 343*711890bcSjc156560 a_argp = optarg; 344*711890bcSjc156560 action = TRUE; 345*711890bcSjc156560 options |= LOWER_A; 346*711890bcSjc156560 } else { 347*711890bcSjc156560 findex = DO_HW_RAID_NOP; 348*711890bcSjc156560 } 349*711890bcSjc156560 break; 350*711890bcSjc156560 case 'p': 351*711890bcSjc156560 if (action == FALSE) { 352*711890bcSjc156560 findex = DO_HW_RAID_SET_ATTR; 353*711890bcSjc156560 p_argp = optarg; 354*711890bcSjc156560 action = TRUE; 355*711890bcSjc156560 options |= LOWER_P; 356*711890bcSjc156560 } else { 357*711890bcSjc156560 findex = DO_HW_RAID_NOP; 358*711890bcSjc156560 } 359*711890bcSjc156560 break; 360*711890bcSjc156560 case 'r': 361*711890bcSjc156560 r_argp = optarg; 362*711890bcSjc156560 r_flag = TRUE; 363*711890bcSjc156560 options |= LOWER_R; 364*711890bcSjc156560 break; 365*711890bcSjc156560 case 'z': 366*711890bcSjc156560 z_argp = optarg; 367*711890bcSjc156560 options |= LOWER_Z; 368*711890bcSjc156560 break; 369*711890bcSjc156560 case 'g': 370*711890bcSjc156560 g_argp = optarg; 371*711890bcSjc156560 options |= LOWER_G; 372*711890bcSjc156560 break; 373*711890bcSjc156560 case 's': 374*711890bcSjc156560 s_argp = optarg; 375*711890bcSjc156560 options |= LOWER_S; 376*711890bcSjc156560 break; 377*711890bcSjc156560 case 'f': 378*711890bcSjc156560 f_flag = TRUE; 379*711890bcSjc156560 options |= LOWER_F; 380*711890bcSjc156560 break; 381*711890bcSjc156560 case 'S': 382*711890bcSjc156560 if (action == FALSE) { 383*711890bcSjc156560 findex = DO_HW_RAID_SNAPSHOT; 384*711890bcSjc156560 action = TRUE; 385*711890bcSjc156560 options |= UPPER_S; 386*711890bcSjc156560 } else { 387*711890bcSjc156560 findex = DO_HW_RAID_NOP; 388*711890bcSjc156560 } 389*711890bcSjc156560 break; 390*711890bcSjc156560 default: 391*711890bcSjc156560 (void) fprintf(stderr, 392*711890bcSjc156560 gettext("Invalid argument(s).\n")); 393*711890bcSjc156560 exit_raidctl_lock(fd); 394*711890bcSjc156560 FREE_STRS; 395*711890bcSjc156560 regfree(&re); 396*711890bcSjc156560 return (INVALID_ARG); 397*711890bcSjc156560 } 398*711890bcSjc156560 } 399*711890bcSjc156560 400*711890bcSjc156560 /* parse options */ 401*711890bcSjc156560 switch (findex) { 402*711890bcSjc156560 case DO_HW_RAID_HELP: 403*711890bcSjc156560 if ((options & ~(LOWER_H)) != 0) { 404*711890bcSjc156560 ret = INVALID_ARG; 405*711890bcSjc156560 } else { 406*711890bcSjc156560 helpinfo(prog_namep); 407*711890bcSjc156560 ret = SUCCESS; 408*711890bcSjc156560 } 409*711890bcSjc156560 break; 410*711890bcSjc156560 case DO_HW_RAID_CREATEO: 411*711890bcSjc156560 if ((options & ~(LOWER_F | LOWER_C | LOWER_R)) != 0) { 412*711890bcSjc156560 ret = INVALID_ARG; 413*711890bcSjc156560 } else { 414*711890bcSjc156560 if (r_flag != FALSE && f_flag == FALSE) { 415*711890bcSjc156560 ret = do_create_ctd(r_argp, argv, argc - 4, 416*711890bcSjc156560 optind, f_flag); 417*711890bcSjc156560 } else if (r_flag == FALSE && f_flag == FALSE) { 418*711890bcSjc156560 ret = do_create_ctd(NULL, argv, argc - 2, 419*711890bcSjc156560 optind, f_flag); 420*711890bcSjc156560 } else if (r_flag != FALSE && f_flag != FALSE) { 421*711890bcSjc156560 ret = do_create_ctd(r_argp, argv, argc - 5, 422*711890bcSjc156560 optind, f_flag); 423*711890bcSjc156560 } else { 424*711890bcSjc156560 ret = do_create_ctd(NULL, argv, argc - 3, 425*711890bcSjc156560 optind, f_flag); 426*711890bcSjc156560 } 427*711890bcSjc156560 } 428*711890bcSjc156560 break; 429*711890bcSjc156560 case DO_HW_RAID_CREATEN: 430*711890bcSjc156560 if ((options & ~(LOWER_F | UPPER_C | LOWER_R | LOWER_Z | 431*711890bcSjc156560 LOWER_S)) != 0) { 432*711890bcSjc156560 ret = INVALID_ARG; 433*711890bcSjc156560 } else { 434*711890bcSjc156560 ret = do_create_cidl(r_argp, z_argp, C_argp, s_argp, 435*711890bcSjc156560 f_flag, argv, optind); 436*711890bcSjc156560 } 437*711890bcSjc156560 break; 438*711890bcSjc156560 case DO_HW_RAID_DELETE: 439*711890bcSjc156560 if ((options & ~(LOWER_F | LOWER_D)) != 0) { 440*711890bcSjc156560 ret = INVALID_ARG; 441*711890bcSjc156560 } else { 442*711890bcSjc156560 ret = do_delete(f_flag, argv, optind); 443*711890bcSjc156560 } 444*711890bcSjc156560 break; 445*711890bcSjc156560 case DO_HW_RAID_LIST: 446*711890bcSjc156560 if ((options & ~(LOWER_L | LOWER_G)) != 0) { 447*711890bcSjc156560 ret = INVALID_ARG; 448*711890bcSjc156560 } else { 449*711890bcSjc156560 ret = do_list(g_argp, argv, optind, FALSE); 450*711890bcSjc156560 } 451*711890bcSjc156560 break; 452*711890bcSjc156560 case DO_HW_RAID_SNAPSHOT: 453*711890bcSjc156560 if ((options & ~(UPPER_S | LOWER_G)) != 0) { 454*711890bcSjc156560 ret = INVALID_ARG; 455*711890bcSjc156560 } else { 456*711890bcSjc156560 ret = do_list(g_argp, argv, optind, TRUE); 457*711890bcSjc156560 } 458*711890bcSjc156560 break; 459*711890bcSjc156560 case DO_HW_RAID_FLASH: 460*711890bcSjc156560 if ((options & ~(LOWER_F | UPPER_F)) != 0) { 461*711890bcSjc156560 ret = INVALID_ARG; 462*711890bcSjc156560 } else { 463*711890bcSjc156560 if (f_flag == FALSE) { 464*711890bcSjc156560 ret = do_flash(f_flag, F_argp, argv, optind, 465*711890bcSjc156560 argc - 3); 466*711890bcSjc156560 } else { 467*711890bcSjc156560 ret = do_flash(f_flag, F_argp, argv, optind, 468*711890bcSjc156560 argc - 4); 469*711890bcSjc156560 } 470*711890bcSjc156560 } 471*711890bcSjc156560 break; 472*711890bcSjc156560 case DO_HW_RAID_HSP: 473*711890bcSjc156560 if ((options & ~(LOWER_A | LOWER_G)) != 0) { 474*711890bcSjc156560 ret = INVALID_ARG; 475*711890bcSjc156560 } else { 476*711890bcSjc156560 ret = do_set_hsp(a_argp, g_argp, argv, optind); 477*711890bcSjc156560 } 478*711890bcSjc156560 break; 479*711890bcSjc156560 case DO_HW_RAID_SET_ATTR: 480*711890bcSjc156560 if ((options & ~(LOWER_F | LOWER_P)) != 0) { 481*711890bcSjc156560 ret = INVALID_ARG; 482*711890bcSjc156560 } else { 483*711890bcSjc156560 ret = do_set_array_attr(f_flag, p_argp, argv, optind); 484*711890bcSjc156560 } 485*711890bcSjc156560 break; 486*711890bcSjc156560 case DO_HW_RAID_NOP: 487*711890bcSjc156560 if (argc == 1) { 488*711890bcSjc156560 ret = do_list(g_argp, argv, optind, FALSE); 489*711890bcSjc156560 } else { 490*711890bcSjc156560 ret = INVALID_ARG; 491*711890bcSjc156560 } 492*711890bcSjc156560 break; 493*711890bcSjc156560 default: 494*711890bcSjc156560 ret = INVALID_ARG; 495*711890bcSjc156560 break; 496*711890bcSjc156560 } 497*711890bcSjc156560 498*711890bcSjc156560 if (ret == INVALID_ARG) { 499*711890bcSjc156560 (void) fprintf(stderr, 500*711890bcSjc156560 gettext("Invalid argument(s).\n")); 501*711890bcSjc156560 } 502*711890bcSjc156560 exit_raidctl_lock(fd); 503*711890bcSjc156560 504*711890bcSjc156560 FREE_STRS; 505*711890bcSjc156560 regfree(&re); 506*711890bcSjc156560 return (ret); 507*711890bcSjc156560 } 508*711890bcSjc156560 509*711890bcSjc156560 /* 510*711890bcSjc156560 * helpinfo(prog_namep) 511*711890bcSjc156560 * This function prints help informations for usrs. 512*711890bcSjc156560 */ 513*711890bcSjc156560 static void 514*711890bcSjc156560 helpinfo(char *prog_namep) 515*711890bcSjc156560 { 516*711890bcSjc156560 char quote = '"'; 517*711890bcSjc156560 518*711890bcSjc156560 (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] " 519*711890bcSjc156560 "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep, 520*711890bcSjc156560 quote, quote); 521*711890bcSjc156560 522*711890bcSjc156560 (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep); 523*711890bcSjc156560 524*711890bcSjc156560 (void) printf(gettext("%s [-f] -F <filename> <controller1> " 525*711890bcSjc156560 "[<controller2> ...]\n"), prog_namep); 526*711890bcSjc156560 527*711890bcSjc156560 (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"), 528*711890bcSjc156560 prog_namep, quote, quote); 529*711890bcSjc156560 530*711890bcSjc156560 (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> " 531*711890bcSjc156560 "[<disk3> ...]\n"), prog_namep); 532*711890bcSjc156560 533*711890bcSjc156560 (void) printf(gettext("%s [-l]\n"), prog_namep); 534*711890bcSjc156560 535*711890bcSjc156560 (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep); 536*711890bcSjc156560 537*711890bcSjc156560 (void) printf(gettext("%s -l <volume>\n"), prog_namep); 538*711890bcSjc156560 539*711890bcSjc156560 (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"), 540*711890bcSjc156560 prog_namep); 541*711890bcSjc156560 542*711890bcSjc156560 (void) printf(gettext("%s -a {set | unset} -g <disk> " 543*711890bcSjc156560 "{<volume> | <controller>}\n"), prog_namep); 544*711890bcSjc156560 545*711890bcSjc156560 (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep); 546*711890bcSjc156560 547*711890bcSjc156560 (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep); 548*711890bcSjc156560 549*711890bcSjc156560 (void) printf(gettext("%s -h\n"), prog_namep); 550*711890bcSjc156560 } 551*711890bcSjc156560 552*711890bcSjc156560 /* 553*711890bcSjc156560 * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep, 554*711890bcSjc156560 * f_flag, argv, optind) 555*711890bcSjc156560 * This function creates a new RAID volume with specified arguments, 556*711890bcSjc156560 * and returns result as SUCCESS, INVALID_ARG or FAILURE. 557*711890bcSjc156560 * The "c.id.l" is used to express single physical disk. 'c' expresses 558*711890bcSjc156560 * bus number, 'id' expresses target number, and 'l' expresses lun. 559*711890bcSjc156560 * The physical disks represented by c.id.l may be invisible to OS, which 560*711890bcSjc156560 * means physical disks attached to controllers are not accessible by 561*711890bcSjc156560 * OS directly. The disks should be organized as a logical volume, and 562*711890bcSjc156560 * the logical volume is exported to OS as a single unit. Some hardware 563*711890bcSjc156560 * RAID controllers also support physical disks accessed by OS directly, 564*711890bcSjc156560 * for example LSI1068. In this case, it's both OK to express physical 565*711890bcSjc156560 * disk by c.id.l format or canonical ctd format. 566*711890bcSjc156560 */ 567*711890bcSjc156560 static int 568*711890bcSjc156560 do_create_cidl(char *raid_levelp, char *capacityp, char *disks_argp, 569*711890bcSjc156560 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind) 570*711890bcSjc156560 { 571*711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 572*711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 573*711890bcSjc156560 uint32_t raid_level = RAID_LEVEL_1; 574*711890bcSjc156560 uint64_t capacity = 0; 575*711890bcSjc156560 uint64_t stripe_size = (uint64_t)OBJ_ATTR_NONE; 576*711890bcSjc156560 raid_obj_handle_t *disk_handlesp = NULL; 577*711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 578*711890bcSjc156560 raidcfg_controller_t ctl_attr; 579*711890bcSjc156560 int comps_num = 0; 580*711890bcSjc156560 int ret = 0; 581*711890bcSjc156560 582*711890bcSjc156560 raidcfg_array_t array_attr; 583*711890bcSjc156560 584*711890bcSjc156560 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 585*711890bcSjc156560 return (INVALID_ARG); 586*711890bcSjc156560 } 587*711890bcSjc156560 588*711890bcSjc156560 if (disks_argp == NULL) { 589*711890bcSjc156560 return (INVALID_ARG); 590*711890bcSjc156560 } 591*711890bcSjc156560 592*711890bcSjc156560 /* Check controller tag */ 593*711890bcSjc156560 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 594*711890bcSjc156560 return (INVALID_ARG); 595*711890bcSjc156560 } 596*711890bcSjc156560 597*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 598*711890bcSjc156560 if (ctl_handle <= 0) { 599*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 600*711890bcSjc156560 return (FAILURE); 601*711890bcSjc156560 } 602*711890bcSjc156560 603*711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 604*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 605*711890bcSjc156560 return (FAILURE); 606*711890bcSjc156560 } 607*711890bcSjc156560 608*711890bcSjc156560 /* Get raid level */ 609*711890bcSjc156560 if (raid_levelp != NULL) { 610*711890bcSjc156560 if (*raid_levelp == '1' && 611*711890bcSjc156560 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) { 612*711890bcSjc156560 raid_level = RAID_LEVEL_1E; 613*711890bcSjc156560 } else { 614*711890bcSjc156560 if (is_fully_numeric(raid_levelp) == FALSE) { 615*711890bcSjc156560 return (INVALID_ARG); 616*711890bcSjc156560 } 617*711890bcSjc156560 618*711890bcSjc156560 switch (atoi(raid_levelp)) { 619*711890bcSjc156560 case 0: 620*711890bcSjc156560 raid_level = RAID_LEVEL_0; 621*711890bcSjc156560 break; 6227c478bd9Sstevel@tonic-gate case 1: 623*711890bcSjc156560 raid_level = RAID_LEVEL_1; 6247c478bd9Sstevel@tonic-gate break; 625*711890bcSjc156560 case 5: 626*711890bcSjc156560 raid_level = RAID_LEVEL_5; 627*711890bcSjc156560 break; 628*711890bcSjc156560 case 10: 629*711890bcSjc156560 raid_level = RAID_LEVEL_10; 630*711890bcSjc156560 break; 631*711890bcSjc156560 case 50: 632*711890bcSjc156560 raid_level = RAID_LEVEL_50; 633*711890bcSjc156560 break; 634*711890bcSjc156560 default: 6357c478bd9Sstevel@tonic-gate return (INVALID_ARG); 6367c478bd9Sstevel@tonic-gate } 637*711890bcSjc156560 } 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate 6406fec3791Sjesseb /* 641*711890bcSjc156560 * The rang check of capacity and stripe size is performed in library, 642*711890bcSjc156560 * and it relates to hardware feature. 6436fec3791Sjesseb */ 6446fec3791Sjesseb 645*711890bcSjc156560 /* Capacity in bytes. Capacity 0 means max available space. */ 646*711890bcSjc156560 if (capacityp != NULL) { 647*711890bcSjc156560 if (*capacityp == '-' || 648*711890bcSjc156560 calc_size(capacityp, &capacity) != SUCCESS) { 6496fec3791Sjesseb return (INVALID_ARG); 6506fec3791Sjesseb } 6516fec3791Sjesseb } 6526fec3791Sjesseb 653*711890bcSjc156560 /* Stripe size in bytes */ 654*711890bcSjc156560 if (stripe_sizep != NULL) { 655*711890bcSjc156560 if (calc_size(stripe_sizep, &stripe_size) != SUCCESS || 656*711890bcSjc156560 *stripe_sizep == '-') { 657*711890bcSjc156560 return (INVALID_ARG); 658*711890bcSjc156560 } 659*711890bcSjc156560 } 660*711890bcSjc156560 661*711890bcSjc156560 /* Open controller before accessing its object */ 662*711890bcSjc156560 if ((ret = raidcfg_open_controller(ctl_handle, NULL)) < 0) { 663*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 664*711890bcSjc156560 return (FAILURE); 665*711890bcSjc156560 } 666*711890bcSjc156560 667*711890bcSjc156560 /* Get disks' handles */ 668*711890bcSjc156560 if ((ret = get_disk_handle_cidl(ctl_tag, disks_argp, &comps_num, 669*711890bcSjc156560 &disk_handlesp)) != SUCCESS) { 670*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 671*711890bcSjc156560 return (ret); 672*711890bcSjc156560 } 673*711890bcSjc156560 674*711890bcSjc156560 if (f_flag == FALSE) { 675*711890bcSjc156560 (void) fprintf(stdout, gettext("Creating RAID volume " 676*711890bcSjc156560 "will destroy all data on spare space of member disks, " 677*711890bcSjc156560 "proceed (%s/%s)? "), yesstr, nostr); 6786fec3791Sjesseb if (!yes()) { 679*711890bcSjc156560 (void) fprintf(stdout, gettext("RAID volume " 680*711890bcSjc156560 "not created.\n\n")); 681*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 682*711890bcSjc156560 free(disk_handlesp); 6836fec3791Sjesseb return (SUCCESS); 6846fec3791Sjesseb } 6856fec3791Sjesseb } 6866fec3791Sjesseb 687*711890bcSjc156560 /* Create array */ 688*711890bcSjc156560 array_handle = raidcfg_create_array(comps_num, 689*711890bcSjc156560 disk_handlesp, raid_level, capacity, stripe_size, NULL); 6906fec3791Sjesseb 691*711890bcSjc156560 if (array_handle <= 0) { 692*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 693*711890bcSjc156560 free(disk_handlesp); 694*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 6957c478bd9Sstevel@tonic-gate return (FAILURE); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 698*711890bcSjc156560 /* Get attribute of the new created array */ 699*711890bcSjc156560 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 700*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 701*711890bcSjc156560 free(disk_handlesp); 702*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 703*711890bcSjc156560 return (FAILURE); 704*711890bcSjc156560 } 705*711890bcSjc156560 706*711890bcSjc156560 (void) fprintf(stdout, gettext("Volume c%ut%llud%llu is created " 707*711890bcSjc156560 "successfully!\n"), ctl_tag, array_attr.tag.idl.target_id, 708*711890bcSjc156560 array_attr.tag.idl.lun); 709*711890bcSjc156560 710*711890bcSjc156560 /* Print attribute of array */ 711*711890bcSjc156560 (void) print_array_table(ctl_handle, array_handle); 712*711890bcSjc156560 713*711890bcSjc156560 /* Close controller */ 714*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 715*711890bcSjc156560 716*711890bcSjc156560 free(disk_handlesp); 717*711890bcSjc156560 return (SUCCESS); 718*711890bcSjc156560 } 719*711890bcSjc156560 720*711890bcSjc156560 /* 721*711890bcSjc156560 * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag) 722*711890bcSjc156560 * This function creates array with specified arguments, and return result 723*711890bcSjc156560 * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller 724*711890bcSjc156560 * to be compatible with old raidctl. The capacity and stripe size can't 725*711890bcSjc156560 * be specified for LSI MPT controller, and they use zero and default value. 726*711890bcSjc156560 * The "ctd" is the canonical expression of physical disks which are 727*711890bcSjc156560 * accessible by OS. 728*711890bcSjc156560 */ 7297c478bd9Sstevel@tonic-gate static int 730*711890bcSjc156560 do_create_ctd(char *raid_levelp, char **disks_argpp, uint32_t disks_num, 731*711890bcSjc156560 uint32_t argindex, uint32_t f_flag) 7327c478bd9Sstevel@tonic-gate { 733*711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 734*711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 735*711890bcSjc156560 uint32_t raid_level = RAID_LEVEL_1; 736*711890bcSjc156560 uint64_t capacity = 0; 737*711890bcSjc156560 uint32_t stripe_size = (uint32_t)OBJ_ATTR_NONE; 738*711890bcSjc156560 raid_obj_handle_t *disk_handlesp = NULL; 739*711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 740*711890bcSjc156560 raidcfg_controller_t ctl_attr; 741*711890bcSjc156560 int ret; 742*711890bcSjc156560 743*711890bcSjc156560 raidcfg_array_t array_attr; 7446fec3791Sjesseb int i, j; 7457c478bd9Sstevel@tonic-gate 746*711890bcSjc156560 /* Check disks parameter */ 747*711890bcSjc156560 if (disks_argpp == NULL || disks_num < 2) { 7487c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 751*711890bcSjc156560 for (i = 0, j = argindex; i < disks_num; i++, j++) { 752*711890bcSjc156560 if (disks_argpp[j] == NULL) { 753*711890bcSjc156560 return (INVALID_ARG); 754*711890bcSjc156560 } 755*711890bcSjc156560 } 7567c478bd9Sstevel@tonic-gate 757*711890bcSjc156560 /* 758*711890bcSjc156560 * We need check if the raid_level string is fully numeric. If user 759*711890bcSjc156560 * input string with unsupported letters, such as "s10", atoi() will 760*711890bcSjc156560 * return zero because it is an illegal string, but it doesn't mean 761*711890bcSjc156560 * RAID_LEVEL_0. 762*711890bcSjc156560 */ 763*711890bcSjc156560 if (raid_levelp != NULL) { 764*711890bcSjc156560 if (*raid_levelp == '1' && 765*711890bcSjc156560 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) { 766*711890bcSjc156560 raid_level = RAID_LEVEL_1E; 767*711890bcSjc156560 } else { 768*711890bcSjc156560 if (is_fully_numeric(raid_levelp) == FALSE) { 769*711890bcSjc156560 return (INVALID_ARG); 770*711890bcSjc156560 } 771*711890bcSjc156560 772*711890bcSjc156560 switch (atoi(raid_levelp)) { 773*711890bcSjc156560 case 0: 774*711890bcSjc156560 raid_level = RAID_LEVEL_0; 775*711890bcSjc156560 break; 776*711890bcSjc156560 case 1: 777*711890bcSjc156560 raid_level = RAID_LEVEL_1; 778*711890bcSjc156560 break; 779*711890bcSjc156560 case 5: 780*711890bcSjc156560 raid_level = RAID_LEVEL_5; 781*711890bcSjc156560 break; 782*711890bcSjc156560 default: 783*711890bcSjc156560 return (INVALID_ARG); 784*711890bcSjc156560 } 785*711890bcSjc156560 } 786*711890bcSjc156560 } 787*711890bcSjc156560 788*711890bcSjc156560 /* Get disks tag and controller tag */ 789*711890bcSjc156560 disk_handlesp = (raid_obj_handle_t *)calloc(disks_num + 2, 790*711890bcSjc156560 sizeof (raid_obj_handle_t)); 791*711890bcSjc156560 if (disk_handlesp == NULL) { 7927c478bd9Sstevel@tonic-gate return (FAILURE); 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 795*711890bcSjc156560 disk_handlesp[0] = OBJ_SEPARATOR_BEGIN; 796*711890bcSjc156560 disk_handlesp[disks_num + 1] = OBJ_SEPARATOR_END; 797*711890bcSjc156560 798*711890bcSjc156560 if ((ret = get_disk_handle_ctd(disks_num, &disks_argpp[argindex], 799*711890bcSjc156560 &ctl_tag, &disk_handlesp[1])) != SUCCESS) { 800*711890bcSjc156560 free(disk_handlesp); 801*711890bcSjc156560 return (ret); 802*711890bcSjc156560 } 803*711890bcSjc156560 804*711890bcSjc156560 /* LIB API should check whether all disks here belong to one ctl. */ 805*711890bcSjc156560 /* get_disk_handle_ctd has opened controller. */ 806*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 807*711890bcSjc156560 808*711890bcSjc156560 if (ctl_handle <= 0) { 809*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 810*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 811*711890bcSjc156560 free(disk_handlesp); 8127c478bd9Sstevel@tonic-gate return (FAILURE); 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate 815*711890bcSjc156560 /* Check if the controller is host raid type */ 816*711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 817*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 818*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 819*711890bcSjc156560 free(disk_handlesp); 820*711890bcSjc156560 return (FAILURE); 8216fec3791Sjesseb } 8226fec3791Sjesseb 823*711890bcSjc156560 if ((ctl_attr.capability & RAID_CAP_DISK_TRANS) == 0) { 824*711890bcSjc156560 /* -c only support host raid controller, return failure here */ 825*711890bcSjc156560 (void) fprintf(stderr, 826*711890bcSjc156560 gettext("Option -c only supports host raid controller.\n")); 827*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 828*711890bcSjc156560 free(disk_handlesp); 829*711890bcSjc156560 return (FAILURE); 8307c478bd9Sstevel@tonic-gate } 831*711890bcSjc156560 832*711890bcSjc156560 if (f_flag == FALSE) { 833*711890bcSjc156560 (void) fprintf(stdout, gettext("Creating RAID volume " 834*711890bcSjc156560 "will destroy all data on spare space of member disks, " 835*711890bcSjc156560 "proceed (%s/%s)? "), yesstr, nostr); 836*711890bcSjc156560 if (!yes()) { 837*711890bcSjc156560 (void) fprintf(stdout, gettext("RAID volume " 838*711890bcSjc156560 "not created.\n\n")); 839*711890bcSjc156560 free(disk_handlesp); 840*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 841*711890bcSjc156560 return (SUCCESS); 842*711890bcSjc156560 } 843*711890bcSjc156560 } 844*711890bcSjc156560 845*711890bcSjc156560 /* 846*711890bcSjc156560 * For old raidctl, capacity is 0, which means to creates 847*711890bcSjc156560 * max possible capacity of array. 848*711890bcSjc156560 */ 849*711890bcSjc156560 850*711890bcSjc156560 array_handle = raidcfg_create_array(disks_num + 2, 851*711890bcSjc156560 disk_handlesp, raid_level, capacity, stripe_size, NULL); 852*711890bcSjc156560 853*711890bcSjc156560 if (array_handle <= 0) { 854*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 855*711890bcSjc156560 free(disk_handlesp); 856*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 857*711890bcSjc156560 return (FAILURE); 858*711890bcSjc156560 } 859*711890bcSjc156560 860*711890bcSjc156560 /* Get attribute of array */ 861*711890bcSjc156560 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 862*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 863*711890bcSjc156560 free(disk_handlesp); 864*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 865*711890bcSjc156560 return (FAILURE); 866*711890bcSjc156560 } 867*711890bcSjc156560 868*711890bcSjc156560 /* Close controller */ 869*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 870*711890bcSjc156560 871*711890bcSjc156560 /* Print feedback for user */ 872*711890bcSjc156560 (void) fprintf(stdout, 873*711890bcSjc156560 gettext("Volume c%ut%llud%llu is created successfully!\n"), 874*711890bcSjc156560 ctl_tag, array_attr.tag.idl.target_id, 875*711890bcSjc156560 array_attr.tag.idl.lun); 876*711890bcSjc156560 free(disk_handlesp); 877*711890bcSjc156560 return (SUCCESS); 878*711890bcSjc156560 } 879*711890bcSjc156560 880*711890bcSjc156560 /* 881*711890bcSjc156560 * do_list(disk_arg, argv, optind, is_snapshot) 882*711890bcSjc156560 * This function lists RAID's system configuration. It supports various RAID 883*711890bcSjc156560 * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG. 884*711890bcSjc156560 */ 885*711890bcSjc156560 static int 886*711890bcSjc156560 do_list(char *disk_argp, char **argv, uint32_t optind, uint8_t is_snapshot) 887*711890bcSjc156560 { 888*711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 889*711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 890*711890bcSjc156560 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 891*711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 892*711890bcSjc156560 disk_tag_t disk_tag; 893*711890bcSjc156560 array_tag_t array_tag; 894*711890bcSjc156560 895*711890bcSjc156560 int ret; 896*711890bcSjc156560 897*711890bcSjc156560 /* print RAID system */ 898*711890bcSjc156560 if (disk_argp == NULL) { 899*711890bcSjc156560 if (argv[optind] == NULL) { 900*711890bcSjc156560 ret = snapshot_raidsystem(TRUE, 0, is_snapshot); 901*711890bcSjc156560 return (ret); 902*711890bcSjc156560 } else { 903*711890bcSjc156560 if (is_fully_numeric(argv[optind]) == TRUE) { 904*711890bcSjc156560 while (argv[optind] != NULL) { 905*711890bcSjc156560 if (get_ctl_tag(argv[optind], &ctl_tag) 906*711890bcSjc156560 != SUCCESS) { 907*711890bcSjc156560 ret = INVALID_ARG; 908*711890bcSjc156560 optind++; 9096fec3791Sjesseb continue; 9106fec3791Sjesseb } 911*711890bcSjc156560 ctl_handle = 912*711890bcSjc156560 raidcfg_get_controller(ctl_tag); 913*711890bcSjc156560 if (ctl_handle <= 0) { 914*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 915*711890bcSjc156560 raidcfg_errstr(ctl_handle)); 916*711890bcSjc156560 ret = FAILURE; 917*711890bcSjc156560 optind++; 918*711890bcSjc156560 continue; 9196fec3791Sjesseb } 920*711890bcSjc156560 ret = 921*711890bcSjc156560 raidcfg_open_controller(ctl_handle, 922*711890bcSjc156560 NULL); 923*711890bcSjc156560 if (ret < 0) { 924*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 925*711890bcSjc156560 raidcfg_errstr(ret)); 926*711890bcSjc156560 ret = FAILURE; 927*711890bcSjc156560 optind++; 928*711890bcSjc156560 continue; 9296fec3791Sjesseb } 930*711890bcSjc156560 if (is_snapshot == FALSE) { 931*711890bcSjc156560 ret = 932*711890bcSjc156560 print_ctl_table(ctl_handle); 933*711890bcSjc156560 } else { 934*711890bcSjc156560 ret = 935*711890bcSjc156560 snapshot_ctl(ctl_handle, 936*711890bcSjc156560 FALSE, 0, is_snapshot); 9377c478bd9Sstevel@tonic-gate } 938*711890bcSjc156560 (void) raidcfg_close_controller( 939*711890bcSjc156560 ctl_handle, NULL); 940*711890bcSjc156560 optind++; 9417c478bd9Sstevel@tonic-gate } 942*711890bcSjc156560 } else { 943*711890bcSjc156560 if (get_array_tag(argv[optind], 944*711890bcSjc156560 &ctl_tag, &array_tag) != SUCCESS) { 9456fec3791Sjesseb return (INVALID_ARG); 9466fec3791Sjesseb } 947*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 948*711890bcSjc156560 if (ctl_handle <= 0) { 949*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 950*711890bcSjc156560 raidcfg_errstr(ctl_handle)); 9517c478bd9Sstevel@tonic-gate return (FAILURE); 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate 954*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 955*711890bcSjc156560 if (ret < 0) { 956*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 957*711890bcSjc156560 raidcfg_errstr(ret)); 958*711890bcSjc156560 return (FAILURE); 959*711890bcSjc156560 } 960*711890bcSjc156560 961*711890bcSjc156560 array_handle = raidcfg_get_array(ctl_handle, 962*711890bcSjc156560 array_tag.idl.target_id, array_tag.idl.lun); 963*711890bcSjc156560 if (array_handle <= 0) { 964*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 965*711890bcSjc156560 raidcfg_errstr(array_handle)); 966*711890bcSjc156560 (void) raidcfg_close_controller( 967*711890bcSjc156560 ctl_handle, NULL); 968*711890bcSjc156560 return (FAILURE); 969*711890bcSjc156560 } 970*711890bcSjc156560 if (is_snapshot == FALSE) { 971*711890bcSjc156560 ret = print_array_table(ctl_handle, 972*711890bcSjc156560 array_handle); 973*711890bcSjc156560 } else { 974*711890bcSjc156560 ret = snapshot_array(array_handle, 0, 975*711890bcSjc156560 FALSE, is_snapshot); 976*711890bcSjc156560 } 977*711890bcSjc156560 (void) raidcfg_close_controller( 978*711890bcSjc156560 ctl_handle, NULL); 979*711890bcSjc156560 } 980*711890bcSjc156560 } 981*711890bcSjc156560 } else { 982*711890bcSjc156560 if (argv[optind + 1] != NULL) { 983*711890bcSjc156560 return (INVALID_ARG); 984*711890bcSjc156560 } 985*711890bcSjc156560 986*711890bcSjc156560 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 987*711890bcSjc156560 return (INVALID_ARG); 988*711890bcSjc156560 } 989*711890bcSjc156560 990*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 991*711890bcSjc156560 if (ctl_handle <= 0) { 992*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 993*711890bcSjc156560 raidcfg_errstr(ctl_handle)); 994*711890bcSjc156560 return (FAILURE); 995*711890bcSjc156560 } 996*711890bcSjc156560 997*711890bcSjc156560 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 998*711890bcSjc156560 return (INVALID_ARG); 999*711890bcSjc156560 } 1000*711890bcSjc156560 1001*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1002*711890bcSjc156560 if (ret < 0) { 1003*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1004*711890bcSjc156560 raidcfg_errstr(ret)); 1005*711890bcSjc156560 return (FAILURE); 1006*711890bcSjc156560 } 1007*711890bcSjc156560 1008*711890bcSjc156560 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1009*711890bcSjc156560 if (disk_handle <= 0) { 1010*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1011*711890bcSjc156560 raidcfg_errstr(disk_handle)); 1012*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1013*711890bcSjc156560 return (FAILURE); 1014*711890bcSjc156560 } 1015*711890bcSjc156560 1016*711890bcSjc156560 if (is_snapshot == FALSE) { 1017*711890bcSjc156560 ret = print_disk_table(ctl_handle, disk_handle); 1018*711890bcSjc156560 } else { 1019*711890bcSjc156560 ret = snapshot_disk(ctl_tag, disk_handle, 0, 1020*711890bcSjc156560 is_snapshot); 1021*711890bcSjc156560 } 1022*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1023*711890bcSjc156560 } 1024*711890bcSjc156560 return (ret); 1025*711890bcSjc156560 } 1026*711890bcSjc156560 1027*711890bcSjc156560 /* 1028*711890bcSjc156560 * do_delete(f_flag, argv, optind) 1029*711890bcSjc156560 * This function deletes a specified array, and return result as SUCCESS, 1030*711890bcSjc156560 * FAILURE or INVALID_ARG. 1031*711890bcSjc156560 */ 1032*711890bcSjc156560 static int 1033*711890bcSjc156560 do_delete(uint32_t f_flag, char **argv, uint32_t optind) 1034*711890bcSjc156560 { 1035*711890bcSjc156560 uint32_t ctl_tag; 1036*711890bcSjc156560 char *array_argp; 1037*711890bcSjc156560 array_tag_t array_tag; 1038*711890bcSjc156560 raid_obj_handle_t ctl_handle; 1039*711890bcSjc156560 raid_obj_handle_t array_handle; 1040*711890bcSjc156560 int ret; 1041*711890bcSjc156560 1042*711890bcSjc156560 array_argp = argv[optind]; 1043*711890bcSjc156560 if (array_argp == NULL || argv[optind + 1] != NULL) { 1044*711890bcSjc156560 return (INVALID_ARG); 1045*711890bcSjc156560 } 1046*711890bcSjc156560 1047*711890bcSjc156560 if (get_array_tag(array_argp, &ctl_tag, &array_tag) != SUCCESS) { 1048*711890bcSjc156560 return (INVALID_ARG); 1049*711890bcSjc156560 } 1050*711890bcSjc156560 1051*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1052*711890bcSjc156560 if (ctl_handle <= 0) { 1053*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 1054*711890bcSjc156560 return (INVALID_ARG); 1055*711890bcSjc156560 } 1056*711890bcSjc156560 1057*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1058*711890bcSjc156560 if (ret < 0) { 1059*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1060*711890bcSjc156560 return (FAILURE); 1061*711890bcSjc156560 } 1062*711890bcSjc156560 1063*711890bcSjc156560 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id, 1064*711890bcSjc156560 array_tag.idl.lun); 1065*711890bcSjc156560 if (array_handle <= 0) { 1066*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 1067*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1068*711890bcSjc156560 return (FAILURE); 1069*711890bcSjc156560 } 1070*711890bcSjc156560 1071*711890bcSjc156560 if (f_flag == FALSE) { 1072*711890bcSjc156560 (void) fprintf(stdout, gettext("Deleting RAID volume " 1073*711890bcSjc156560 "%s will destroy all data it contains, " 1074*711890bcSjc156560 "proceed (%s/%s)? "), array_argp, yesstr, nostr); 1075*711890bcSjc156560 if (!yes()) { 1076*711890bcSjc156560 (void) fprintf(stdout, gettext("RAID Volume " 1077*711890bcSjc156560 "%s not deleted.\n\n"), array_argp); 1078*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1079*711890bcSjc156560 return (SUCCESS); 1080*711890bcSjc156560 } 1081*711890bcSjc156560 } 1082*711890bcSjc156560 1083*711890bcSjc156560 1084*711890bcSjc156560 if ((ret = raidcfg_delete_array(array_handle, NULL)) < 0) { 1085*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1086*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1087*711890bcSjc156560 return (FAILURE); 1088*711890bcSjc156560 } 1089*711890bcSjc156560 1090*711890bcSjc156560 (void) fprintf(stdout, gettext("Volume %s is deleted successfully!\n"), 1091*711890bcSjc156560 array_argp); 1092*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1093*711890bcSjc156560 1094*711890bcSjc156560 return (SUCCESS); 1095*711890bcSjc156560 } 1096*711890bcSjc156560 1097*711890bcSjc156560 /* 1098*711890bcSjc156560 * do_flash(f_flag, filep, ctls_argpp, index, ctl_num) 1099*711890bcSjc156560 * This function downloads and updates firmware for specified controller, and 1100*711890bcSjc156560 * return result as SUCCESS, FAILURE or INVALID_ARG. 1101*711890bcSjc156560 */ 1102*711890bcSjc156560 static int 1103*711890bcSjc156560 do_flash(uint8_t f_flag, char *filep, char **ctls_argpp, 1104*711890bcSjc156560 uint32_t index, uint32_t ctl_num) 1105*711890bcSjc156560 { 1106*711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 1107*711890bcSjc156560 char *ctl_argp = NULL; 1108*711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1109*711890bcSjc156560 int ret; 1110*711890bcSjc156560 int i, j; 1111*711890bcSjc156560 1112*711890bcSjc156560 if (ctl_num == 0) 1113*711890bcSjc156560 return (INVALID_ARG); 1114*711890bcSjc156560 1115*711890bcSjc156560 for (i = 0, j = index; i < ctl_num; i++, j++) { 1116*711890bcSjc156560 ctl_argp = ctls_argpp[j]; 1117*711890bcSjc156560 if (get_ctl_tag(ctl_argp, &ctl_tag) != SUCCESS) { 1118*711890bcSjc156560 return (INVALID_ARG); 1119*711890bcSjc156560 } 1120*711890bcSjc156560 1121*711890bcSjc156560 /* Ask user to confirm operation. */ 1122*711890bcSjc156560 if (f_flag == FALSE) { 1123*711890bcSjc156560 (void) fprintf(stdout, gettext("Update flash image on " 1124*711890bcSjc156560 "controller %d (%s/%s)? "), ctl_tag, yesstr, nostr); 1125*711890bcSjc156560 if (!yes()) { 1126*711890bcSjc156560 (void) fprintf(stdout, 1127*711890bcSjc156560 gettext("Controller %d not " 1128*711890bcSjc156560 "flashed.\n\n"), ctl_tag); 1129*711890bcSjc156560 return (SUCCESS); 1130*711890bcSjc156560 } 1131*711890bcSjc156560 } 1132*711890bcSjc156560 1133*711890bcSjc156560 if ((ctl_handle = raidcfg_get_controller(ctl_tag)) < 0) { 1134*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1135*711890bcSjc156560 raidcfg_errstr(ctl_handle)); 1136*711890bcSjc156560 return (FAILURE); 1137*711890bcSjc156560 } 1138*711890bcSjc156560 1139*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1140*711890bcSjc156560 if (ret < 0) { 1141*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1142*711890bcSjc156560 return (FAILURE); 1143*711890bcSjc156560 } 1144*711890bcSjc156560 1145*711890bcSjc156560 (void) fprintf(stdout, gettext("Start updating controller " 1146*711890bcSjc156560 "c%u firmware....\n"), ctl_tag); 1147*711890bcSjc156560 1148*711890bcSjc156560 if ((ret = raidcfg_update_fw(ctl_handle, filep, NULL)) < 0) { 1149*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1150*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1151*711890bcSjc156560 return (FAILURE); 1152*711890bcSjc156560 } 1153*711890bcSjc156560 1154*711890bcSjc156560 (void) fprintf(stdout, gettext("Update controller " 1155*711890bcSjc156560 "c%u firmware successfully.\n"), ctl_tag); 1156*711890bcSjc156560 1157*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1158*711890bcSjc156560 } 1159*711890bcSjc156560 1160*711890bcSjc156560 return (SUCCESS); 1161*711890bcSjc156560 } 1162*711890bcSjc156560 1163*711890bcSjc156560 /* 1164*711890bcSjc156560 * do_set_hsp(a_argp, disk_argp, argv, optind) 1165*711890bcSjc156560 * This function set or unset HSP relationship between disk and controller/ 1166*711890bcSjc156560 * array, and return result as SUCCESS, FAILURE or INVALID_ARG. 1167*711890bcSjc156560 */ 1168*711890bcSjc156560 static int 1169*711890bcSjc156560 do_set_hsp(char *a_argp, char *disk_argp, char **argv, uint32_t optind) 1170*711890bcSjc156560 { 1171*711890bcSjc156560 uint32_t flag = MAX32BIT; 1172*711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 1173*711890bcSjc156560 array_tag_t array_tag; 1174*711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1175*711890bcSjc156560 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 1176*711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1177*711890bcSjc156560 raidcfg_controller_t ctl_attr; 1178*711890bcSjc156560 disk_tag_t disk_tag; 1179*711890bcSjc156560 1180*711890bcSjc156560 int ret; 1181*711890bcSjc156560 int hsp_type; 1182*711890bcSjc156560 raidcfg_hsp_relation_t hsp_relation; 1183*711890bcSjc156560 1184*711890bcSjc156560 (void) memset(&hsp_relation, 0, sizeof (raidcfg_hsp_relation_t)); 1185*711890bcSjc156560 1186*711890bcSjc156560 if (a_argp == NULL) { 1187*711890bcSjc156560 return (INVALID_ARG); 1188*711890bcSjc156560 } 1189*711890bcSjc156560 1190*711890bcSjc156560 if (strcmp(a_argp, "set") == 0) { 1191*711890bcSjc156560 flag = HSP_SET; 1192*711890bcSjc156560 } else if (strcmp(a_argp, "unset") == 0) { 1193*711890bcSjc156560 flag = HSP_UNSET; 1194*711890bcSjc156560 } else { 1195*711890bcSjc156560 return (INVALID_ARG); 1196*711890bcSjc156560 } 1197*711890bcSjc156560 1198*711890bcSjc156560 if (disk_argp == NULL) { 1199*711890bcSjc156560 return (INVALID_ARG); 1200*711890bcSjc156560 } 1201*711890bcSjc156560 1202*711890bcSjc156560 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 1203*711890bcSjc156560 return (INVALID_ARG); 1204*711890bcSjc156560 } else if (is_fully_numeric(argv[optind]) == TRUE) { 1205*711890bcSjc156560 /* Global HSP */ 1206*711890bcSjc156560 hsp_type = 0; 1207*711890bcSjc156560 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 1208*711890bcSjc156560 return (INVALID_ARG); 1209*711890bcSjc156560 } 1210*711890bcSjc156560 1211*711890bcSjc156560 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 1212*711890bcSjc156560 return (INVALID_ARG); 1213*711890bcSjc156560 } 1214*711890bcSjc156560 1215*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1216*711890bcSjc156560 if (ctl_handle <= 0) { 1217*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1218*711890bcSjc156560 raidcfg_errstr(ctl_handle)); 1219*711890bcSjc156560 return (FAILURE); 1220*711890bcSjc156560 } 1221*711890bcSjc156560 1222*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1223*711890bcSjc156560 if (ret < 0) { 1224*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1225*711890bcSjc156560 return (FAILURE); 1226*711890bcSjc156560 } 1227*711890bcSjc156560 1228*711890bcSjc156560 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1229*711890bcSjc156560 if (disk_handle <= 0) { 1230*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1231*711890bcSjc156560 raidcfg_errstr(disk_handle)); 1232*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1233*711890bcSjc156560 return (FAILURE); 1234*711890bcSjc156560 } 1235*711890bcSjc156560 } else { 1236*711890bcSjc156560 /* Local HSP */ 1237*711890bcSjc156560 hsp_type = 1; 1238*711890bcSjc156560 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != 1239*711890bcSjc156560 SUCCESS) { 1240*711890bcSjc156560 return (INVALID_ARG); 1241*711890bcSjc156560 } 1242*711890bcSjc156560 1243*711890bcSjc156560 /* Open controller */ 1244*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1245*711890bcSjc156560 if (ctl_handle <= 0) { 1246*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1247*711890bcSjc156560 raidcfg_errstr(ctl_handle)); 1248*711890bcSjc156560 return (FAILURE); 1249*711890bcSjc156560 } 1250*711890bcSjc156560 1251*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1252*711890bcSjc156560 if (ret < 0) { 1253*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1254*711890bcSjc156560 return (FAILURE); 1255*711890bcSjc156560 } 1256*711890bcSjc156560 1257*711890bcSjc156560 /* Get controller's attribute */ 1258*711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1259*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1260*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1261*711890bcSjc156560 return (FAILURE); 1262*711890bcSjc156560 } 1263*711890bcSjc156560 1264*711890bcSjc156560 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 1265*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1266*711890bcSjc156560 return (INVALID_ARG); 1267*711890bcSjc156560 } 1268*711890bcSjc156560 1269*711890bcSjc156560 /* Get disk handle */ 1270*711890bcSjc156560 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1271*711890bcSjc156560 if (disk_handle <= 0) { 1272*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1273*711890bcSjc156560 raidcfg_errstr(disk_handle)); 1274*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1275*711890bcSjc156560 return (FAILURE); 1276*711890bcSjc156560 } 1277*711890bcSjc156560 1278*711890bcSjc156560 /* Get array handle */ 1279*711890bcSjc156560 array_handle = raidcfg_get_array(ctl_handle, 1280*711890bcSjc156560 array_tag.idl.target_id, array_tag.idl.lun); 1281*711890bcSjc156560 if (array_handle <= 0) { 1282*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1283*711890bcSjc156560 raidcfg_errstr(array_handle)); 1284*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1285*711890bcSjc156560 return (FAILURE); 1286*711890bcSjc156560 } 1287*711890bcSjc156560 } 1288*711890bcSjc156560 1289*711890bcSjc156560 hsp_relation.disk_handle = disk_handle; 1290*711890bcSjc156560 if (hsp_type) { 1291*711890bcSjc156560 /* Set or unset local HSP */ 1292*711890bcSjc156560 hsp_relation.array_handle = array_handle; 1293*711890bcSjc156560 } else { 1294*711890bcSjc156560 /* Set or unset global HSP */ 1295*711890bcSjc156560 hsp_relation.array_handle = OBJ_ATTR_NONE; 1296*711890bcSjc156560 } 1297*711890bcSjc156560 1298*711890bcSjc156560 /* Perform operation of set or unset */ 1299*711890bcSjc156560 if (flag == HSP_SET) { 1300*711890bcSjc156560 if ((ret = raidcfg_set_hsp(1, &hsp_relation, NULL)) < 0) { 1301*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1302*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1303*711890bcSjc156560 return (FAILURE); 1304*711890bcSjc156560 } 1305*711890bcSjc156560 1306*711890bcSjc156560 if (hsp_type) { 1307*711890bcSjc156560 (void) printf(gettext("Set local HSP between disk %s " 1308*711890bcSjc156560 "and RAID volume %s successfully.\n"), 1309*711890bcSjc156560 disk_argp, argv[optind]); 1310*711890bcSjc156560 } else { 1311*711890bcSjc156560 (void) printf(gettext("Set global HSP between disk %s " 1312*711890bcSjc156560 "and controller %s successfully.\n"), 1313*711890bcSjc156560 disk_argp, argv[optind]); 1314*711890bcSjc156560 } 1315*711890bcSjc156560 } else { 1316*711890bcSjc156560 if ((ret = raidcfg_unset_hsp(1, &hsp_relation, NULL)) < 0) { 1317*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1318*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1319*711890bcSjc156560 return (FAILURE); 1320*711890bcSjc156560 } 1321*711890bcSjc156560 1322*711890bcSjc156560 if (hsp_type) { 1323*711890bcSjc156560 (void) printf(gettext("Unset local HSP between " 1324*711890bcSjc156560 "disk %s and RAID volume %s successfully.\n"), 1325*711890bcSjc156560 disk_argp, argv[optind]); 1326*711890bcSjc156560 } else { 1327*711890bcSjc156560 (void) printf(gettext("Unset global HSP between " 1328*711890bcSjc156560 "disk %s and controller %s successfully.\n"), 1329*711890bcSjc156560 disk_argp, argv[optind]); 1330*711890bcSjc156560 } 1331*711890bcSjc156560 } 1332*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1333*711890bcSjc156560 return (SUCCESS); 1334*711890bcSjc156560 } 1335*711890bcSjc156560 1336*711890bcSjc156560 /* 1337*711890bcSjc156560 * do_set_array_attr(f_flag, p_argp, argv, optind) 1338*711890bcSjc156560 * This function changes array's attribute when array is running. 1339*711890bcSjc156560 * The changeable attribute is up to controller's feature. 1340*711890bcSjc156560 * The return value can be SUCCESS, FAILURE or INVALID_ARG. 1341*711890bcSjc156560 */ 1342*711890bcSjc156560 static int 1343*711890bcSjc156560 do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, uint32_t optind) 1344*711890bcSjc156560 { 1345*711890bcSjc156560 uint32_t ctl_tag = MAX32BIT; 1346*711890bcSjc156560 array_tag_t array_tag; 1347*711890bcSjc156560 uint32_t type = MAX32BIT; 1348*711890bcSjc156560 uint32_t value = MAX32BIT; 1349*711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1350*711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1351*711890bcSjc156560 1352*711890bcSjc156560 char *param, *op = "="; 1353*711890bcSjc156560 1354*711890bcSjc156560 int ret; 1355*711890bcSjc156560 1356*711890bcSjc156560 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 1357*711890bcSjc156560 return (INVALID_ARG); 1358*711890bcSjc156560 } 1359*711890bcSjc156560 1360*711890bcSjc156560 if (p_argp != NULL) { 1361*711890bcSjc156560 param = strtok(p_argp, op); 1362*711890bcSjc156560 if (strcmp(param, "wp") == 0) { 1363*711890bcSjc156560 type = SET_CACHE_WR_PLY; 1364*711890bcSjc156560 } else { 1365*711890bcSjc156560 return (INVALID_ARG); 1366*711890bcSjc156560 } 1367*711890bcSjc156560 1368*711890bcSjc156560 param = strtok(NULL, op); 1369*711890bcSjc156560 if (strcmp(param, "on") == 0) { 1370*711890bcSjc156560 value = CACHE_WR_ON; 1371*711890bcSjc156560 } else if (strcmp(param, "off") == 0) { 1372*711890bcSjc156560 value = CACHE_WR_OFF; 1373*711890bcSjc156560 } else { 1374*711890bcSjc156560 return (INVALID_ARG); 1375*711890bcSjc156560 } 1376*711890bcSjc156560 1377*711890bcSjc156560 } else { 1378*711890bcSjc156560 return (INVALID_ARG); 1379*711890bcSjc156560 } 1380*711890bcSjc156560 1381*711890bcSjc156560 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != SUCCESS) { 1382*711890bcSjc156560 return (INVALID_ARG); 1383*711890bcSjc156560 } 1384*711890bcSjc156560 1385*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1386*711890bcSjc156560 if (ctl_handle <= 0) { 1387*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 1388*711890bcSjc156560 return (FAILURE); 1389*711890bcSjc156560 } 1390*711890bcSjc156560 1391*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1392*711890bcSjc156560 if (ret < 0) { 1393*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1394*711890bcSjc156560 return (FAILURE); 1395*711890bcSjc156560 } 1396*711890bcSjc156560 1397*711890bcSjc156560 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id, 1398*711890bcSjc156560 array_tag.idl.lun); 1399*711890bcSjc156560 if (array_handle <= 0) { 1400*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 1401*711890bcSjc156560 return (FAILURE); 1402*711890bcSjc156560 } 1403*711890bcSjc156560 1404*711890bcSjc156560 /* Ask user to confirm operation. */ 1405*711890bcSjc156560 if (f_flag == FALSE) { 1406*711890bcSjc156560 (void) fprintf(stdout, gettext("Update attribute of " 1407*711890bcSjc156560 "array %s (%s/%s)? "), argv[optind], yesstr, nostr); 1408*711890bcSjc156560 if (!yes()) { 1409*711890bcSjc156560 (void) fprintf(stdout, 1410*711890bcSjc156560 gettext("Array %s not " 1411*711890bcSjc156560 "changed.\n\n"), argv[optind]); 1412*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1413*711890bcSjc156560 return (SUCCESS); 1414*711890bcSjc156560 } 1415*711890bcSjc156560 } 1416*711890bcSjc156560 1417*711890bcSjc156560 if ((ret = raidcfg_set_attr(array_handle, type, &value, NULL)) < 0) { 1418*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1419*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1420*711890bcSjc156560 return (FAILURE); 1421*711890bcSjc156560 } 1422*711890bcSjc156560 1423*711890bcSjc156560 (void) printf(gettext("Set attribute of RAID volume %s " 1424*711890bcSjc156560 "successfully.\n"), argv[optind]); 1425*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 1426*711890bcSjc156560 1427*711890bcSjc156560 return (SUCCESS); 1428*711890bcSjc156560 } 1429*711890bcSjc156560 1430*711890bcSjc156560 /* 1431*711890bcSjc156560 * snapshot_raidsystem(recursive, indent, is_snapshot) 1432*711890bcSjc156560 * This function prints the snapshot of whole RAID's system configuration, 1433*711890bcSjc156560 * and return result as SUCCESS or FAILURE. 1434*711890bcSjc156560 */ 1435*711890bcSjc156560 static int 1436*711890bcSjc156560 snapshot_raidsystem(uint8_t recursive, uint8_t indent, uint8_t is_snapshot) 1437*711890bcSjc156560 { 1438*711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1439*711890bcSjc156560 int ret; 1440*711890bcSjc156560 1441*711890bcSjc156560 ctl_handle = raidcfg_list_head(OBJ_SYSTEM, OBJ_TYPE_CONTROLLER); 1442*711890bcSjc156560 while (ctl_handle > 0) { 1443*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 1444*711890bcSjc156560 if (ret == 0) { 1445*711890bcSjc156560 if (snapshot_ctl(ctl_handle, recursive, indent, 1446*711890bcSjc156560 is_snapshot) == FAILURE) { 1447*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, 1448*711890bcSjc156560 NULL); 1449*711890bcSjc156560 } 1450*711890bcSjc156560 } 1451*711890bcSjc156560 ctl_handle = raidcfg_list_next(ctl_handle); 1452*711890bcSjc156560 } 1453*711890bcSjc156560 return (SUCCESS); 1454*711890bcSjc156560 } 1455*711890bcSjc156560 1456*711890bcSjc156560 /* 1457*711890bcSjc156560 * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot) 1458*711890bcSjc156560 * This function prints snapshot of specified controller's configuration, 1459*711890bcSjc156560 * and return result as SUCCESS or FAILURE. 1460*711890bcSjc156560 */ 1461*711890bcSjc156560 static int 1462*711890bcSjc156560 snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, uint8_t indent, 1463*711890bcSjc156560 uint8_t is_snapshot) 1464*711890bcSjc156560 { 1465*711890bcSjc156560 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1466*711890bcSjc156560 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 1467*711890bcSjc156560 raidcfg_controller_t ctl_attr; 1468*711890bcSjc156560 uint32_t ctl_tag; 1469*711890bcSjc156560 char ctlbuf[256]; 1470*711890bcSjc156560 int ret; 1471*711890bcSjc156560 1472*711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1473*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1474*711890bcSjc156560 return (FAILURE); 1475*711890bcSjc156560 } 1476*711890bcSjc156560 1477*711890bcSjc156560 ctl_tag = ctl_attr.controller_id; 1478*711890bcSjc156560 if (is_snapshot == FALSE) { 1479*711890bcSjc156560 print_indent(indent); 1480*711890bcSjc156560 (void) fprintf(stdout, gettext("Controller: %u\n"), ctl_tag); 1481*711890bcSjc156560 } else { 1482*711890bcSjc156560 (void) snprintf(ctlbuf, sizeof (ctlbuf), "%u \"%s\"", 1483*711890bcSjc156560 ctl_tag, ctl_attr.controller_type); 1484*711890bcSjc156560 (void) fprintf(stdout, "%s", ctlbuf); 1485*711890bcSjc156560 1486*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1487*711890bcSjc156560 } 1488*711890bcSjc156560 1489*711890bcSjc156560 if (recursive == TRUE) { 1490*711890bcSjc156560 array_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_ARRAY); 1491*711890bcSjc156560 while (array_handle > 0) { 1492*711890bcSjc156560 if (snapshot_array(array_handle, 1493*711890bcSjc156560 indent + 1, FALSE, is_snapshot) == FAILURE) { 1494*711890bcSjc156560 return (FAILURE); 1495*711890bcSjc156560 } 1496*711890bcSjc156560 1497*711890bcSjc156560 array_handle = raidcfg_list_next(array_handle); 1498*711890bcSjc156560 } 1499*711890bcSjc156560 1500*711890bcSjc156560 disk_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_DISK); 1501*711890bcSjc156560 while (disk_handle > 0) { 1502*711890bcSjc156560 if (snapshot_disk(ctl_tag, disk_handle, 1503*711890bcSjc156560 indent + 1, is_snapshot) == FAILURE) { 1504*711890bcSjc156560 return (FAILURE); 1505*711890bcSjc156560 } 1506*711890bcSjc156560 1507*711890bcSjc156560 disk_handle = raidcfg_list_next(disk_handle); 1508*711890bcSjc156560 } 1509*711890bcSjc156560 } 1510*711890bcSjc156560 return (SUCCESS); 1511*711890bcSjc156560 } 1512*711890bcSjc156560 1513*711890bcSjc156560 1514*711890bcSjc156560 /* 1515*711890bcSjc156560 * snapshot_array(array_handle, indent, is_sub, is_snapshot) 1516*711890bcSjc156560 * This function prints snapshot of specified array's configuration, 1517*711890bcSjc156560 * and return result as SUCCESS or FAILURE. 1518*711890bcSjc156560 */ 1519*711890bcSjc156560 static int 1520*711890bcSjc156560 snapshot_array(raid_obj_handle_t array_handle, uint8_t indent, uint8_t is_sub, 1521*711890bcSjc156560 uint8_t is_snapshot) 1522*711890bcSjc156560 { 1523*711890bcSjc156560 raid_obj_handle_t ctl_handle; 1524*711890bcSjc156560 raid_obj_handle_t subarray_handle; 1525*711890bcSjc156560 raid_obj_handle_t arraypart_handle; 1526*711890bcSjc156560 raid_obj_handle_t task_handle; 1527*711890bcSjc156560 1528*711890bcSjc156560 raidcfg_controller_t ctl_attr; 1529*711890bcSjc156560 raidcfg_array_t array_attr; 1530*711890bcSjc156560 raidcfg_arraypart_t arraypart_attr; 1531*711890bcSjc156560 raidcfg_task_t task_attr; 1532*711890bcSjc156560 1533*711890bcSjc156560 char arraybuf[256] = "\0"; 1534*711890bcSjc156560 char diskbuf[256] = "\0"; 1535*711890bcSjc156560 char tempbuf[256] = "\0"; 1536*711890bcSjc156560 int disknum = 0; 1537*711890bcSjc156560 1538*711890bcSjc156560 uint32_t ctl_tag; 1539*711890bcSjc156560 int ret; 1540*711890bcSjc156560 1541*711890bcSjc156560 ctl_handle = raidcfg_get_container(array_handle); 1542*711890bcSjc156560 ret = raidcfg_get_attr(ctl_handle, &ctl_attr); 1543*711890bcSjc156560 if (ret < 0) { 1544*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1545*711890bcSjc156560 return (FAILURE); 1546*711890bcSjc156560 } 1547*711890bcSjc156560 ctl_tag = ctl_attr.controller_id; 1548*711890bcSjc156560 1549*711890bcSjc156560 /* Print array attribute */ 1550*711890bcSjc156560 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 1551*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1552*711890bcSjc156560 return (FAILURE); 1553*711890bcSjc156560 } 1554*711890bcSjc156560 1555*711890bcSjc156560 if (is_snapshot == FALSE) { 1556*711890bcSjc156560 print_indent(indent); 1557*711890bcSjc156560 if (is_sub == FALSE) { 1558*711890bcSjc156560 (void) fprintf(stdout, gettext("Volume:" 1559*711890bcSjc156560 "c%ut%llud%llu\n"), 1560*711890bcSjc156560 ctl_tag, array_attr.tag.idl.target_id, 1561*711890bcSjc156560 array_attr.tag.idl.lun); 1562*711890bcSjc156560 } else { 1563*711890bcSjc156560 (void) fprintf(stdout, gettext("Sub-Volume\n")); 1564*711890bcSjc156560 } 1565*711890bcSjc156560 } else { 1566*711890bcSjc156560 (void) snprintf(arraybuf, sizeof (arraybuf), "c%ut%llud%llu ", 1567*711890bcSjc156560 ctl_tag, array_attr.tag.idl.target_id, 1568*711890bcSjc156560 array_attr.tag.idl.lun); 1569*711890bcSjc156560 1570*711890bcSjc156560 /* Check if array is in sync state */ 1571*711890bcSjc156560 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK); 1572*711890bcSjc156560 if (task_handle > 0) { 1573*711890bcSjc156560 (void) raidcfg_get_attr(task_handle, &task_attr); 1574*711890bcSjc156560 if (task_attr.task_func == TASK_FUNC_BUILD) { 1575*711890bcSjc156560 array_attr.state = ARRAY_STATE_SYNC; 1576*711890bcSjc156560 } 1577*711890bcSjc156560 } else { 1578*711890bcSjc156560 subarray_handle = raidcfg_list_head(array_handle, 1579*711890bcSjc156560 OBJ_TYPE_ARRAY); 1580*711890bcSjc156560 while (subarray_handle > 0) { 1581*711890bcSjc156560 task_handle = raidcfg_list_head(subarray_handle, 1582*711890bcSjc156560 OBJ_TYPE_TASK); 1583*711890bcSjc156560 if (task_handle > 0) { 1584*711890bcSjc156560 (void) raidcfg_get_attr(task_handle, 1585*711890bcSjc156560 &task_attr); 1586*711890bcSjc156560 if (task_attr.task_func == 1587*711890bcSjc156560 TASK_FUNC_BUILD) { 1588*711890bcSjc156560 array_attr.state = 1589*711890bcSjc156560 ARRAY_STATE_SYNC; 1590*711890bcSjc156560 } 1591*711890bcSjc156560 break; 1592*711890bcSjc156560 } 1593*711890bcSjc156560 subarray_handle = 1594*711890bcSjc156560 raidcfg_list_next(subarray_handle); 1595*711890bcSjc156560 } 1596*711890bcSjc156560 } 1597*711890bcSjc156560 1598*711890bcSjc156560 /* Print sub array */ 1599*711890bcSjc156560 subarray_handle = raidcfg_list_head(array_handle, 1600*711890bcSjc156560 OBJ_TYPE_ARRAY); 1601*711890bcSjc156560 while (subarray_handle > 0) { 1602*711890bcSjc156560 /* print subarraypart */ 1603*711890bcSjc156560 arraypart_handle = raidcfg_list_head(subarray_handle, 1604*711890bcSjc156560 OBJ_TYPE_ARRAY_PART); 1605*711890bcSjc156560 while (arraypart_handle > 0) { 1606*711890bcSjc156560 if ((ret = raidcfg_get_attr(arraypart_handle, 1607*711890bcSjc156560 &arraypart_attr)) < 0) { 1608*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1609*711890bcSjc156560 raidcfg_errstr(ret)); 1610*711890bcSjc156560 return (FAILURE); 1611*711890bcSjc156560 } 1612*711890bcSjc156560 1613*711890bcSjc156560 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1614*711890bcSjc156560 (void) snprintf(tempbuf, 1615*711890bcSjc156560 sizeof (tempbuf), 1616*711890bcSjc156560 gettext("N/A")); 1617*711890bcSjc156560 } else { 1618*711890bcSjc156560 (void) snprintf(tempbuf, 1619*711890bcSjc156560 sizeof (tempbuf), 1620*711890bcSjc156560 "%llu.%llu.%llu", 1621*711890bcSjc156560 arraypart_attr.tag.cidl.bus, 1622*711890bcSjc156560 arraypart_attr.tag.cidl.target_id, 1623*711890bcSjc156560 arraypart_attr.tag.cidl.lun); 1624*711890bcSjc156560 } 1625*711890bcSjc156560 (void) strcat(diskbuf, tempbuf); 1626*711890bcSjc156560 (void) strcat(diskbuf, " "); 1627*711890bcSjc156560 disknum++; 1628*711890bcSjc156560 arraypart_handle = 1629*711890bcSjc156560 raidcfg_list_next(arraypart_handle); 1630*711890bcSjc156560 } 1631*711890bcSjc156560 subarray_handle = raidcfg_list_next(subarray_handle); 1632*711890bcSjc156560 } 1633*711890bcSjc156560 1634*711890bcSjc156560 /* Print arraypart */ 1635*711890bcSjc156560 arraypart_handle = raidcfg_list_head(array_handle, 1636*711890bcSjc156560 OBJ_TYPE_ARRAY_PART); 1637*711890bcSjc156560 while (arraypart_handle > 0) { 1638*711890bcSjc156560 if ((ret = raidcfg_get_attr(arraypart_handle, 1639*711890bcSjc156560 &arraypart_attr)) < 0) { 1640*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1641*711890bcSjc156560 raidcfg_errstr(ret)); 1642*711890bcSjc156560 return (FAILURE); 1643*711890bcSjc156560 } 1644*711890bcSjc156560 1645*711890bcSjc156560 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1646*711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1647*711890bcSjc156560 gettext("N/A")); 1648*711890bcSjc156560 } else { 1649*711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1650*711890bcSjc156560 "%llu.%llu.%llu", 1651*711890bcSjc156560 arraypart_attr.tag.cidl.bus, 1652*711890bcSjc156560 arraypart_attr.tag.cidl.target_id, 1653*711890bcSjc156560 arraypart_attr.tag.cidl.lun); 1654*711890bcSjc156560 } 1655*711890bcSjc156560 (void) strcat(diskbuf, tempbuf); 1656*711890bcSjc156560 (void) strcat(diskbuf, " "); 1657*711890bcSjc156560 disknum++; 1658*711890bcSjc156560 arraypart_handle = raidcfg_list_next(arraypart_handle); 1659*711890bcSjc156560 } 1660*711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), "%u ", disknum); 1661*711890bcSjc156560 (void) strcat(arraybuf, tempbuf); 1662*711890bcSjc156560 (void) strcat(arraybuf, diskbuf); 1663*711890bcSjc156560 1664*711890bcSjc156560 switch (array_attr.raid_level) { 1665*711890bcSjc156560 case RAID_LEVEL_0: 1666*711890bcSjc156560 (void) sprintf(tempbuf, "0"); 1667*711890bcSjc156560 break; 1668*711890bcSjc156560 case RAID_LEVEL_1: 1669*711890bcSjc156560 (void) sprintf(tempbuf, "1"); 1670*711890bcSjc156560 break; 1671*711890bcSjc156560 case RAID_LEVEL_1E: 1672*711890bcSjc156560 (void) sprintf(tempbuf, "1E"); 1673*711890bcSjc156560 break; 1674*711890bcSjc156560 case RAID_LEVEL_5: 1675*711890bcSjc156560 (void) sprintf(tempbuf, "5"); 1676*711890bcSjc156560 break; 1677*711890bcSjc156560 case RAID_LEVEL_10: 1678*711890bcSjc156560 (void) sprintf(tempbuf, "10"); 1679*711890bcSjc156560 break; 1680*711890bcSjc156560 case RAID_LEVEL_50: 1681*711890bcSjc156560 (void) sprintf(tempbuf, "50"); 1682*711890bcSjc156560 break; 1683*711890bcSjc156560 default: 1684*711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1685*711890bcSjc156560 gettext("N/A")); 1686*711890bcSjc156560 break; 1687*711890bcSjc156560 } 1688*711890bcSjc156560 (void) strcat(arraybuf, tempbuf); 1689*711890bcSjc156560 (void) fprintf(stdout, "%s ", arraybuf); 1690*711890bcSjc156560 1691*711890bcSjc156560 switch (array_attr.state) { 1692*711890bcSjc156560 case ARRAY_STATE_OPTIMAL: 1693*711890bcSjc156560 (void) fprintf(stdout, gettext("OPTIMAL")); 1694*711890bcSjc156560 break; 1695*711890bcSjc156560 case ARRAY_STATE_DEGRADED: 1696*711890bcSjc156560 (void) fprintf(stdout, gettext("DEGRADED")); 1697*711890bcSjc156560 break; 1698*711890bcSjc156560 case ARRAY_STATE_FAILED: 1699*711890bcSjc156560 (void) fprintf(stdout, gettext("FAILED")); 1700*711890bcSjc156560 break; 1701*711890bcSjc156560 case ARRAY_STATE_SYNC: 1702*711890bcSjc156560 (void) fprintf(stdout, gettext("SYNC")); 1703*711890bcSjc156560 break; 1704*711890bcSjc156560 default: 1705*711890bcSjc156560 (void) fprintf(stdout, gettext("N/A")); 1706*711890bcSjc156560 break; 1707*711890bcSjc156560 } 1708*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1709*711890bcSjc156560 } 1710*711890bcSjc156560 1711*711890bcSjc156560 return (SUCCESS); 1712*711890bcSjc156560 } 1713*711890bcSjc156560 1714*711890bcSjc156560 /* 1715*711890bcSjc156560 * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot) 1716*711890bcSjc156560 * This function prints snapshot of specified disk's configuration, and return 1717*711890bcSjc156560 * result as SUCCESS or FAILURE. 1718*711890bcSjc156560 */ 1719*711890bcSjc156560 static int 1720*711890bcSjc156560 snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, uint8_t indent, 1721*711890bcSjc156560 uint8_t is_snapshot) 1722*711890bcSjc156560 { 1723*711890bcSjc156560 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1724*711890bcSjc156560 raid_obj_handle_t hsp_handle; 1725*711890bcSjc156560 1726*711890bcSjc156560 raidcfg_controller_t ctl_attr; 1727*711890bcSjc156560 raidcfg_disk_t disk_attr; 1728*711890bcSjc156560 char diskbuf[256] = ""; 1729*711890bcSjc156560 char tempbuf[256] = ""; 1730*711890bcSjc156560 1731*711890bcSjc156560 int ret; 1732*711890bcSjc156560 1733*711890bcSjc156560 ctl_handle = raidcfg_get_controller(ctl_tag); 1734*711890bcSjc156560 ret = raidcfg_get_attr(ctl_handle, &ctl_attr); 1735*711890bcSjc156560 if (ret < 0) { 1736*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1737*711890bcSjc156560 return (FAILURE); 1738*711890bcSjc156560 } 1739*711890bcSjc156560 1740*711890bcSjc156560 /* Print attribute of disk */ 1741*711890bcSjc156560 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) { 1742*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1743*711890bcSjc156560 return (FAILURE); 1744*711890bcSjc156560 } 1745*711890bcSjc156560 1746*711890bcSjc156560 if (is_snapshot == FALSE) { 1747*711890bcSjc156560 print_indent(indent); 1748*711890bcSjc156560 1749*711890bcSjc156560 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); 1750*711890bcSjc156560 1751*711890bcSjc156560 if (disk_attr.tag.cidl.bus == MAX64BIT) { 1752*711890bcSjc156560 (void) fprintf(stdout, gettext("Disk: N/A")); 1753*711890bcSjc156560 } else { 1754*711890bcSjc156560 (void) fprintf(stdout, gettext("Disk: %llu.%llu.%llu"), 1755*711890bcSjc156560 disk_attr.tag.cidl.bus, 1756*711890bcSjc156560 disk_attr.tag.cidl.target_id, 1757*711890bcSjc156560 disk_attr.tag.cidl.lun); 1758*711890bcSjc156560 } 1759*711890bcSjc156560 if (hsp_handle > 0) { 1760*711890bcSjc156560 (void) fprintf(stdout, "(HSP)"); 1761*711890bcSjc156560 } 1762*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1763*711890bcSjc156560 } else { 1764*711890bcSjc156560 if (disk_attr.tag.cidl.bus == MAX64BIT) { 1765*711890bcSjc156560 (void) fprintf(stdout, gettext("N/A")); 1766*711890bcSjc156560 } else { 1767*711890bcSjc156560 (void) snprintf(diskbuf, sizeof (diskbuf), 1768*711890bcSjc156560 "%llu.%llu.%llu ", 1769*711890bcSjc156560 disk_attr.tag.cidl.bus, 1770*711890bcSjc156560 disk_attr.tag.cidl.target_id, 1771*711890bcSjc156560 disk_attr.tag.cidl.lun); 1772*711890bcSjc156560 } 1773*711890bcSjc156560 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); 1774*711890bcSjc156560 if (hsp_handle > 0) { 1775*711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1776*711890bcSjc156560 gettext("HSP")); 1777*711890bcSjc156560 } else if (disk_attr.state == DISK_STATE_GOOD) { 1778*711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1779*711890bcSjc156560 gettext("GOOD")); 1780*711890bcSjc156560 } else if (disk_attr.state == DISK_STATE_FAILED) { 1781*711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1782*711890bcSjc156560 gettext("FAILED")); 1783*711890bcSjc156560 } else { 1784*711890bcSjc156560 (void) snprintf(tempbuf, sizeof (tempbuf), 1785*711890bcSjc156560 gettext("N/A")); 1786*711890bcSjc156560 } 1787*711890bcSjc156560 1788*711890bcSjc156560 (void) strcat(diskbuf, tempbuf); 1789*711890bcSjc156560 (void) fprintf(stdout, "%s\n", diskbuf); 1790*711890bcSjc156560 } 1791*711890bcSjc156560 1792*711890bcSjc156560 return (SUCCESS); 1793*711890bcSjc156560 } 1794*711890bcSjc156560 1795*711890bcSjc156560 static int 1796*711890bcSjc156560 print_ctl_table(raid_obj_handle_t ctl_handle) 1797*711890bcSjc156560 { 1798*711890bcSjc156560 raidcfg_controller_t ctl_attr; 1799*711890bcSjc156560 char controller[8]; 1800*711890bcSjc156560 int ret; 1801*711890bcSjc156560 1802*711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1803*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1804*711890bcSjc156560 return (FAILURE); 1805*711890bcSjc156560 } 1806*711890bcSjc156560 1807*711890bcSjc156560 (void) fprintf(stdout, gettext("Controller\tType\t\tVersion")); 1808*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1809*711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 1810*711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 1811*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1812*711890bcSjc156560 1813*711890bcSjc156560 (void) snprintf(controller, sizeof (controller), "%u", 1814*711890bcSjc156560 ctl_attr.controller_id); 1815*711890bcSjc156560 (void) printf("c%s\t\t", controller); 1816*711890bcSjc156560 1817*711890bcSjc156560 (void) print_ctl_attr(&ctl_attr); 1818*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1819*711890bcSjc156560 1820*711890bcSjc156560 return (SUCCESS); 1821*711890bcSjc156560 } 1822*711890bcSjc156560 1823*711890bcSjc156560 static int 1824*711890bcSjc156560 print_array_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t array_handle) 1825*711890bcSjc156560 { 1826*711890bcSjc156560 raidcfg_controller_t ctl_attr; 1827*711890bcSjc156560 raidcfg_array_t array_attr; 1828*711890bcSjc156560 raidcfg_array_t subarray_attr; 1829*711890bcSjc156560 raidcfg_arraypart_t arraypart_attr; 1830*711890bcSjc156560 raidcfg_task_t task_attr; 1831*711890bcSjc156560 1832*711890bcSjc156560 raid_obj_handle_t subarray_handle; 1833*711890bcSjc156560 raid_obj_handle_t arraypart_handle; 1834*711890bcSjc156560 raid_obj_handle_t task_handle; 1835*711890bcSjc156560 1836*711890bcSjc156560 char array[8]; 1837*711890bcSjc156560 char arraypart[8]; 1838*711890bcSjc156560 int ret; 1839*711890bcSjc156560 int i; 1840*711890bcSjc156560 1841*711890bcSjc156560 /* Controller attribute */ 1842*711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1843*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1844*711890bcSjc156560 return (FAILURE); 1845*711890bcSjc156560 } 1846*711890bcSjc156560 1847*711890bcSjc156560 /* Array attribute */ 1848*711890bcSjc156560 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 1849*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1850*711890bcSjc156560 return (FAILURE); 1851*711890bcSjc156560 } 1852*711890bcSjc156560 1853*711890bcSjc156560 /* print header */ 1854*711890bcSjc156560 (void) fprintf(stdout, gettext("Volume\t\t\tSize\tStripe\tStatus\t" 1855*711890bcSjc156560 " Cache\tRAID")); 1856*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1857*711890bcSjc156560 (void) fprintf(stdout, gettext("\tSub\t\t\tSize\t\t\tLevel")); 1858*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1859*711890bcSjc156560 (void) fprintf(stdout, gettext("\t\tDisk\t\t\t\t\t")); 1860*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1861*711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 1862*711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 1863*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1864*711890bcSjc156560 1865*711890bcSjc156560 /* print array */ 1866*711890bcSjc156560 (void) snprintf(array, sizeof (array), "c%ut%llud%llu", 1867*711890bcSjc156560 ctl_attr.controller_id, array_attr.tag.idl.target_id, 1868*711890bcSjc156560 array_attr.tag.idl.lun); 1869*711890bcSjc156560 (void) fprintf(stdout, "%s\t\t\t", array); 1870*711890bcSjc156560 1871*711890bcSjc156560 /* check if array is in sync state */ 1872*711890bcSjc156560 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK); 1873*711890bcSjc156560 if (task_handle > 0) { 1874*711890bcSjc156560 (void) raidcfg_get_attr(task_handle, &task_attr); 1875*711890bcSjc156560 if (task_attr.task_func == TASK_FUNC_BUILD) { 1876*711890bcSjc156560 array_attr.state = ARRAY_STATE_SYNC; 1877*711890bcSjc156560 } 1878*711890bcSjc156560 } else { 1879*711890bcSjc156560 subarray_handle = raidcfg_list_head(array_handle, 1880*711890bcSjc156560 OBJ_TYPE_ARRAY); 1881*711890bcSjc156560 while (subarray_handle > 0) { 1882*711890bcSjc156560 task_handle = raidcfg_list_head(subarray_handle, 1883*711890bcSjc156560 OBJ_TYPE_TASK); 1884*711890bcSjc156560 if (task_handle > 0) { 1885*711890bcSjc156560 (void) raidcfg_get_attr(task_handle, 1886*711890bcSjc156560 &task_attr); 1887*711890bcSjc156560 if (task_attr.task_func == TASK_FUNC_BUILD) { 1888*711890bcSjc156560 array_attr.state = ARRAY_STATE_SYNC; 1889*711890bcSjc156560 } 1890*711890bcSjc156560 break; 1891*711890bcSjc156560 } 1892*711890bcSjc156560 subarray_handle = raidcfg_list_next(subarray_handle); 1893*711890bcSjc156560 } 1894*711890bcSjc156560 } 1895*711890bcSjc156560 1896*711890bcSjc156560 (void) print_array_attr(&array_attr); 1897*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1898*711890bcSjc156560 1899*711890bcSjc156560 /* Print sub array */ 1900*711890bcSjc156560 i = 0; /* Count sub array number */ 1901*711890bcSjc156560 subarray_handle = raidcfg_list_head(array_handle, OBJ_TYPE_ARRAY); 1902*711890bcSjc156560 while (subarray_handle > 0) { 1903*711890bcSjc156560 if ((ret = raidcfg_get_attr(subarray_handle, 1904*711890bcSjc156560 &subarray_attr)) < 0) { 1905*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1906*711890bcSjc156560 return (FAILURE); 1907*711890bcSjc156560 } 1908*711890bcSjc156560 1909*711890bcSjc156560 /* Use sub0/sub1 here, not cxtxd0 for subarray */ 1910*711890bcSjc156560 (void) snprintf(array, sizeof (array), "sub%u", i++); 1911*711890bcSjc156560 (void) fprintf(stdout, "\t%s\t\t", array); 1912*711890bcSjc156560 1913*711890bcSjc156560 /* Check if array is in sync */ 1914*711890bcSjc156560 task_handle = raidcfg_list_head(subarray_handle, OBJ_TYPE_TASK); 1915*711890bcSjc156560 if (task_handle > 0) { 1916*711890bcSjc156560 (void) raidcfg_get_attr(task_handle, &task_attr); 1917*711890bcSjc156560 if (task_attr.task_func == TASK_FUNC_BUILD) { 1918*711890bcSjc156560 subarray_attr.state = ARRAY_STATE_SYNC; 1919*711890bcSjc156560 } 1920*711890bcSjc156560 } 1921*711890bcSjc156560 1922*711890bcSjc156560 (void) print_array_attr(&subarray_attr); 1923*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1924*711890bcSjc156560 1925*711890bcSjc156560 /* Print subarraypart */ 1926*711890bcSjc156560 arraypart_handle = raidcfg_list_head(subarray_handle, 1927*711890bcSjc156560 OBJ_TYPE_ARRAY_PART); 1928*711890bcSjc156560 while (arraypart_handle > 0) { 1929*711890bcSjc156560 if ((ret = raidcfg_get_attr(arraypart_handle, 1930*711890bcSjc156560 &arraypart_attr)) < 0) { 1931*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 1932*711890bcSjc156560 raidcfg_errstr(ret)); 1933*711890bcSjc156560 return (FAILURE); 1934*711890bcSjc156560 } 1935*711890bcSjc156560 1936*711890bcSjc156560 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1937*711890bcSjc156560 (void) snprintf(arraypart, sizeof (arraypart), 1938*711890bcSjc156560 gettext("N/A")); 1939*711890bcSjc156560 } else { 1940*711890bcSjc156560 (void) snprintf(arraypart, sizeof (arraypart), 1941*711890bcSjc156560 "%llu.%llu.%llu", 1942*711890bcSjc156560 arraypart_attr.tag.cidl.bus, 1943*711890bcSjc156560 arraypart_attr.tag.cidl.target_id, 1944*711890bcSjc156560 arraypart_attr.tag.cidl.lun); 1945*711890bcSjc156560 } 1946*711890bcSjc156560 1947*711890bcSjc156560 (void) fprintf(stdout, "\t\t%s\t", arraypart); 1948*711890bcSjc156560 (void) print_arraypart_attr(&arraypart_attr); 1949*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1950*711890bcSjc156560 arraypart_handle = raidcfg_list_next(arraypart_handle); 1951*711890bcSjc156560 } 1952*711890bcSjc156560 subarray_handle = raidcfg_list_next(subarray_handle); 1953*711890bcSjc156560 } 1954*711890bcSjc156560 1955*711890bcSjc156560 /* Print arraypart */ 1956*711890bcSjc156560 arraypart_handle = raidcfg_list_head(array_handle, 1957*711890bcSjc156560 OBJ_TYPE_ARRAY_PART); 1958*711890bcSjc156560 while (arraypart_handle > 0) { 1959*711890bcSjc156560 if ((ret = raidcfg_get_attr(arraypart_handle, 1960*711890bcSjc156560 &arraypart_attr)) < 0) { 1961*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1962*711890bcSjc156560 return (FAILURE); 1963*711890bcSjc156560 } 1964*711890bcSjc156560 1965*711890bcSjc156560 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1966*711890bcSjc156560 (void) snprintf(arraypart, sizeof (arraypart), 1967*711890bcSjc156560 gettext("N/A")); 1968*711890bcSjc156560 } else { 1969*711890bcSjc156560 (void) snprintf(arraypart, sizeof (arraypart), 1970*711890bcSjc156560 "%llu.%llu.%llu", 1971*711890bcSjc156560 arraypart_attr.tag.cidl.bus, 1972*711890bcSjc156560 arraypart_attr.tag.cidl.target_id, 1973*711890bcSjc156560 arraypart_attr.tag.cidl.lun); 1974*711890bcSjc156560 } 1975*711890bcSjc156560 1976*711890bcSjc156560 (void) fprintf(stdout, "\t\t%s\t", arraypart); 1977*711890bcSjc156560 (void) print_arraypart_attr(&arraypart_attr); 1978*711890bcSjc156560 (void) fprintf(stdout, "\n"); 1979*711890bcSjc156560 arraypart_handle = raidcfg_list_next(arraypart_handle); 1980*711890bcSjc156560 } 1981*711890bcSjc156560 1982*711890bcSjc156560 return (SUCCESS); 1983*711890bcSjc156560 } 1984*711890bcSjc156560 1985*711890bcSjc156560 static int 1986*711890bcSjc156560 print_disk_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle) 1987*711890bcSjc156560 { 1988*711890bcSjc156560 raidcfg_controller_t ctl_attr; 1989*711890bcSjc156560 raidcfg_disk_t disk_attr; 1990*711890bcSjc156560 char disk[8]; 1991*711890bcSjc156560 int ret; 1992*711890bcSjc156560 1993*711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1994*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1995*711890bcSjc156560 return (FAILURE); 1996*711890bcSjc156560 } 1997*711890bcSjc156560 1998*711890bcSjc156560 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) { 1999*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2000*711890bcSjc156560 return (FAILURE); 2001*711890bcSjc156560 } 2002*711890bcSjc156560 2003*711890bcSjc156560 /* Print header */ 2004*711890bcSjc156560 (void) fprintf(stdout, gettext("Disk\tVendor\tProduct\t\tCapacity\t" 2005*711890bcSjc156560 "Status\tHSP")); 2006*711890bcSjc156560 (void) fprintf(stdout, "\n"); 2007*711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 2008*711890bcSjc156560 (void) fprintf(stdout, "--------------------------------"); 2009*711890bcSjc156560 (void) fprintf(stdout, "\n"); 2010*711890bcSjc156560 2011*711890bcSjc156560 2012*711890bcSjc156560 (void) snprintf(disk, sizeof (disk), "%llu.%llu.%llu", 2013*711890bcSjc156560 disk_attr.tag.cidl.bus, 2014*711890bcSjc156560 disk_attr.tag.cidl.target_id, 2015*711890bcSjc156560 disk_attr.tag.cidl.lun); 2016*711890bcSjc156560 2017*711890bcSjc156560 (void) fprintf(stdout, "%s\t", disk); 2018*711890bcSjc156560 2019*711890bcSjc156560 (void) print_disk_attr(ctl_handle, disk_handle, &disk_attr); 2020*711890bcSjc156560 (void) fprintf(stdout, "\n"); 2021*711890bcSjc156560 2022*711890bcSjc156560 return (SUCCESS); 2023*711890bcSjc156560 } 2024*711890bcSjc156560 2025*711890bcSjc156560 /* 2026*711890bcSjc156560 * print_ctl_attr(attrp) 2027*711890bcSjc156560 * This function prints attribute of specified controller, and return 2028*711890bcSjc156560 * result as SUCCESS or FAILURE. 2029*711890bcSjc156560 */ 2030*711890bcSjc156560 static int 2031*711890bcSjc156560 print_ctl_attr(raidcfg_controller_t *attrp) 2032*711890bcSjc156560 { 2033*711890bcSjc156560 char type[CONTROLLER_TYPE_LEN]; 2034*711890bcSjc156560 char version[CONTROLLER_FW_LEN]; 2035*711890bcSjc156560 2036*711890bcSjc156560 if (attrp == NULL) { 2037*711890bcSjc156560 return (FAILURE); 2038*711890bcSjc156560 } 2039*711890bcSjc156560 2040*711890bcSjc156560 (void) snprintf(type, sizeof (type), "%s", attrp->controller_type); 2041*711890bcSjc156560 (void) fprintf(stdout, "%-16s", type); 2042*711890bcSjc156560 2043*711890bcSjc156560 (void) snprintf(version, sizeof (version), "%s", attrp->fw_version); 2044*711890bcSjc156560 (void) fprintf(stdout, "%s", version); 2045*711890bcSjc156560 2046*711890bcSjc156560 return (SUCCESS); 2047*711890bcSjc156560 } 2048*711890bcSjc156560 2049*711890bcSjc156560 /* 2050*711890bcSjc156560 * print_array_attr(attrp) 2051*711890bcSjc156560 * This function prints attribute of specified array, and return 2052*711890bcSjc156560 * result as SUCCESS or FAILURE. 2053*711890bcSjc156560 */ 2054*711890bcSjc156560 static int 2055*711890bcSjc156560 print_array_attr(raidcfg_array_t *attrp) 2056*711890bcSjc156560 { 2057*711890bcSjc156560 char capacity[8]; 2058*711890bcSjc156560 char stripe_size[8]; 2059*711890bcSjc156560 char raid_level[8]; 2060*711890bcSjc156560 2061*711890bcSjc156560 if (attrp == NULL) { 2062*711890bcSjc156560 return (FAILURE); 2063*711890bcSjc156560 } 2064*711890bcSjc156560 2065*711890bcSjc156560 if (attrp->capacity != MAX64BIT) { 2066*711890bcSjc156560 if (size_to_string(attrp->capacity, capacity, 8) != SUCCESS) { 2067*711890bcSjc156560 return (FAILURE); 2068*711890bcSjc156560 } 2069*711890bcSjc156560 (void) printf("%s\t", capacity); 2070*711890bcSjc156560 } else { 2071*711890bcSjc156560 (void) printf(gettext("N/A\t")); 2072*711890bcSjc156560 } 2073*711890bcSjc156560 2074*711890bcSjc156560 if (attrp->stripe_size != MAX32BIT) { 2075*711890bcSjc156560 (void) snprintf(stripe_size, sizeof (stripe_size), "%uK", 2076*711890bcSjc156560 attrp->stripe_size / 1024); 2077*711890bcSjc156560 (void) printf("%s\t", stripe_size); 2078*711890bcSjc156560 } else { 2079*711890bcSjc156560 (void) printf(gettext("N/A\t")); 2080*711890bcSjc156560 } 2081*711890bcSjc156560 2082*711890bcSjc156560 switch (attrp->state) { 2083*711890bcSjc156560 case ARRAY_STATE_OPTIMAL: 2084*711890bcSjc156560 (void) printf("%-8s", gettext("OPTIMAL")); 2085*711890bcSjc156560 break; 2086*711890bcSjc156560 case ARRAY_STATE_DEGRADED: 2087*711890bcSjc156560 (void) printf("%-8s", gettext("DEGRADED")); 2088*711890bcSjc156560 break; 2089*711890bcSjc156560 case ARRAY_STATE_FAILED: 2090*711890bcSjc156560 (void) printf("%-8s", gettext("FAILED")); 2091*711890bcSjc156560 break; 2092*711890bcSjc156560 case ARRAY_STATE_SYNC: 2093*711890bcSjc156560 (void) printf("%-8s", gettext("SYNC")); 2094*711890bcSjc156560 break; 2095*711890bcSjc156560 default: 2096*711890bcSjc156560 (void) printf("%-8s", gettext("N/A")); 2097*711890bcSjc156560 break; 2098*711890bcSjc156560 } 2099*711890bcSjc156560 (void) printf(" "); 2100*711890bcSjc156560 2101*711890bcSjc156560 if (attrp->write_policy == CACHE_WR_OFF) { 2102*711890bcSjc156560 (void) printf(gettext("OFF")); 2103*711890bcSjc156560 } else if (attrp->write_policy == CACHE_WR_ON) { 2104*711890bcSjc156560 (void) printf(gettext("ON")); 2105*711890bcSjc156560 } else { 2106*711890bcSjc156560 (void) printf(gettext("N/A")); 2107*711890bcSjc156560 } 2108*711890bcSjc156560 (void) printf("\t"); 2109*711890bcSjc156560 2110*711890bcSjc156560 switch (attrp->raid_level) { 2111*711890bcSjc156560 case RAID_LEVEL_0: 2112*711890bcSjc156560 (void) sprintf(raid_level, "RAID0"); 2113*711890bcSjc156560 break; 2114*711890bcSjc156560 case RAID_LEVEL_1: 2115*711890bcSjc156560 (void) sprintf(raid_level, "RAID1"); 2116*711890bcSjc156560 break; 2117*711890bcSjc156560 case RAID_LEVEL_1E: 2118*711890bcSjc156560 (void) sprintf(raid_level, "RAID1E"); 2119*711890bcSjc156560 break; 2120*711890bcSjc156560 case RAID_LEVEL_5: 2121*711890bcSjc156560 (void) sprintf(raid_level, "RAID5"); 2122*711890bcSjc156560 break; 2123*711890bcSjc156560 case RAID_LEVEL_10: 2124*711890bcSjc156560 (void) sprintf(raid_level, "RAID10"); 2125*711890bcSjc156560 break; 2126*711890bcSjc156560 case RAID_LEVEL_50: 2127*711890bcSjc156560 (void) sprintf(raid_level, "RAID50"); 2128*711890bcSjc156560 break; 2129*711890bcSjc156560 default: 2130*711890bcSjc156560 (void) snprintf(raid_level, sizeof (raid_level), 2131*711890bcSjc156560 gettext("N/A")); 2132*711890bcSjc156560 break; 2133*711890bcSjc156560 } 2134*711890bcSjc156560 (void) printf("%s", raid_level); 2135*711890bcSjc156560 2136*711890bcSjc156560 return (SUCCESS); 2137*711890bcSjc156560 } 2138*711890bcSjc156560 2139*711890bcSjc156560 /* 2140*711890bcSjc156560 * print_arraypart_attr(attrp) 2141*711890bcSjc156560 * This function print attribute of specified arraypart, and return 2142*711890bcSjc156560 * result as SUCCESS or FAILURE. 2143*711890bcSjc156560 */ 2144*711890bcSjc156560 static int 2145*711890bcSjc156560 print_arraypart_attr(raidcfg_arraypart_t *attrp) 2146*711890bcSjc156560 { 2147*711890bcSjc156560 char size[8]; 2148*711890bcSjc156560 2149*711890bcSjc156560 if (attrp == NULL) { 2150*711890bcSjc156560 return (FAILURE); 2151*711890bcSjc156560 } 2152*711890bcSjc156560 2153*711890bcSjc156560 if (attrp->size != MAX64BIT) { 2154*711890bcSjc156560 if (size_to_string(attrp->size, size, 8) != SUCCESS) { 2155*711890bcSjc156560 return (FAILURE); 2156*711890bcSjc156560 } 2157*711890bcSjc156560 (void) printf("%s\t", size); 2158*711890bcSjc156560 } else { 2159*711890bcSjc156560 (void) printf(gettext("N/A\t")); 2160*711890bcSjc156560 } 2161*711890bcSjc156560 2162*711890bcSjc156560 (void) printf("\t"); 2163*711890bcSjc156560 2164*711890bcSjc156560 if (attrp->state == DISK_STATE_GOOD) { 2165*711890bcSjc156560 (void) printf(gettext("GOOD")); 2166*711890bcSjc156560 } else if (attrp->state == DISK_STATE_FAILED) { 2167*711890bcSjc156560 (void) printf(gettext("FAILED")); 2168*711890bcSjc156560 } else { 2169*711890bcSjc156560 (void) printf(gettext("N/A")); 2170*711890bcSjc156560 } 2171*711890bcSjc156560 (void) printf("\t"); 2172*711890bcSjc156560 2173*711890bcSjc156560 return (SUCCESS); 2174*711890bcSjc156560 } 2175*711890bcSjc156560 2176*711890bcSjc156560 /* 2177*711890bcSjc156560 * print_disk_attr(ctl_handle, disk_handle, attrp) 2178*711890bcSjc156560 * This function prints attribute of specified disk, and return 2179*711890bcSjc156560 * result as SUCCESS or FAILURE. 2180*711890bcSjc156560 */ 2181*711890bcSjc156560 static int 2182*711890bcSjc156560 print_disk_attr(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle, 2183*711890bcSjc156560 raidcfg_disk_t *attrp) 2184*711890bcSjc156560 { 2185*711890bcSjc156560 char vendor[DISK_VENDER_LEN]; 2186*711890bcSjc156560 char product[DISK_PRODUCT_LEN]; 2187*711890bcSjc156560 char capacity[16]; 2188*711890bcSjc156560 char hsp[16]; 2189*711890bcSjc156560 2190*711890bcSjc156560 raid_obj_handle_t hsp_handle; 2191*711890bcSjc156560 raidcfg_hsp_t hsp_attr; 2192*711890bcSjc156560 raidcfg_controller_t ctl_attr; 2193*711890bcSjc156560 int ret; 2194*711890bcSjc156560 char is_indent; 2195*711890bcSjc156560 2196*711890bcSjc156560 if (attrp == NULL) { 2197*711890bcSjc156560 return (FAILURE); 2198*711890bcSjc156560 } 2199*711890bcSjc156560 2200*711890bcSjc156560 (void) snprintf(vendor, sizeof (vendor), "%s", attrp->vendorid); 2201*711890bcSjc156560 (void) printf("%s\t", vendor); 2202*711890bcSjc156560 2203*711890bcSjc156560 (void) snprintf(product, sizeof (product), "%s", attrp->productid); 2204*711890bcSjc156560 (void) printf("%s\t", product); 2205*711890bcSjc156560 2206*711890bcSjc156560 if (attrp->capacity != MAX64BIT) { 2207*711890bcSjc156560 if (size_to_string(attrp->capacity, capacity, 16) != SUCCESS) { 2208*711890bcSjc156560 return (FAILURE); 2209*711890bcSjc156560 } 2210*711890bcSjc156560 (void) printf("%s\t\t", capacity); 2211*711890bcSjc156560 } else { 2212*711890bcSjc156560 (void) printf(gettext("N/A")); 2213*711890bcSjc156560 } 2214*711890bcSjc156560 2215*711890bcSjc156560 if (attrp->state == DISK_STATE_GOOD) { 2216*711890bcSjc156560 (void) printf(gettext("GOOD")); 2217*711890bcSjc156560 } else if (attrp->state == DISK_STATE_FAILED) { 2218*711890bcSjc156560 (void) printf(gettext("FAILED")); 2219*711890bcSjc156560 } else { 2220*711890bcSjc156560 (void) printf(gettext("N/A")); 2221*711890bcSjc156560 } 2222*711890bcSjc156560 (void) printf("\t"); 2223*711890bcSjc156560 2224*711890bcSjc156560 /* Controller attribute */ 2225*711890bcSjc156560 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 2226*711890bcSjc156560 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2227*711890bcSjc156560 return (FAILURE); 2228*711890bcSjc156560 } 2229*711890bcSjc156560 2230*711890bcSjc156560 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); 2231*711890bcSjc156560 if (hsp_handle == 0) { 2232*711890bcSjc156560 (void) printf(gettext("N/A\n")); 2233*711890bcSjc156560 } else { 2234*711890bcSjc156560 is_indent = FALSE; 2235*711890bcSjc156560 while (hsp_handle > 0) { 2236*711890bcSjc156560 if ((ret = raidcfg_get_attr(hsp_handle, 2237*711890bcSjc156560 &hsp_attr)) < 0) { 2238*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2239*711890bcSjc156560 raidcfg_errstr(ret)); 2240*711890bcSjc156560 return (FAILURE); 2241*711890bcSjc156560 } 2242*711890bcSjc156560 2243*711890bcSjc156560 if (is_indent == TRUE) { 2244*711890bcSjc156560 (void) printf("\t\t\t\t\t\t\t"); 2245*711890bcSjc156560 } else { 2246*711890bcSjc156560 is_indent = TRUE; 2247*711890bcSjc156560 } 2248*711890bcSjc156560 2249*711890bcSjc156560 if (hsp_attr.type == HSP_TYPE_LOCAL) { 2250*711890bcSjc156560 (void) snprintf(hsp, sizeof (hsp), 2251*711890bcSjc156560 "c%ut%llud%llu", 2252*711890bcSjc156560 ctl_attr.controller_id, 2253*711890bcSjc156560 hsp_attr.tag.idl.target_id, 2254*711890bcSjc156560 hsp_attr.tag.idl.lun); 2255*711890bcSjc156560 (void) printf("%s\n", hsp); 2256*711890bcSjc156560 } else if (hsp_attr.type == HSP_TYPE_GLOBAL) { 2257*711890bcSjc156560 (void) printf(gettext("Global\n")); 2258*711890bcSjc156560 } else { 2259*711890bcSjc156560 return (FAILURE); 2260*711890bcSjc156560 } 2261*711890bcSjc156560 2262*711890bcSjc156560 hsp_handle = raidcfg_list_next(hsp_handle); 2263*711890bcSjc156560 } 2264*711890bcSjc156560 } 2265*711890bcSjc156560 return (SUCCESS); 2266*711890bcSjc156560 } 2267*711890bcSjc156560 2268*711890bcSjc156560 2269*711890bcSjc156560 /* 2270*711890bcSjc156560 * print_indent(indent) 2271*711890bcSjc156560 * This function prints specified number of tab characters. It's used to 2272*711890bcSjc156560 * format layout. 2273*711890bcSjc156560 */ 22747f000930Syw161884 static void 2275*711890bcSjc156560 print_indent(uint8_t indent) 22767f000930Syw161884 { 2277*711890bcSjc156560 uint32_t i; 2278*711890bcSjc156560 for (i = 0; i < indent; i++) { 2279*711890bcSjc156560 (void) fprintf(stdout, "\t"); 22807f000930Syw161884 } 22817f000930Syw161884 } 22827f000930Syw161884 2283*711890bcSjc156560 /* 2284*711890bcSjc156560 * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp) 2285*711890bcSjc156560 * This function parses the string of disk argument, and gets the disks tag 2286*711890bcSjc156560 * and separators from the string. Then it translates the tag to handle, and 2287*711890bcSjc156560 * stores handles and separators to new buffer pointed by parameter handlespp. 2288*711890bcSjc156560 * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first 2289*711890bcSjc156560 * "0" is channel number, and the second "1" is target number, and the third 2290*711890bcSjc156560 * "0" is LUN number. The disk tags are separated by comma and parenthesis. 2291*711890bcSjc156560 * Function returns SUCCESS or FAILURE. 2292*711890bcSjc156560 */ 22937c478bd9Sstevel@tonic-gate static int 2294*711890bcSjc156560 get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, int *comps_nump, 2295*711890bcSjc156560 raid_obj_handle_t **handlespp) 22967c478bd9Sstevel@tonic-gate { 2297*711890bcSjc156560 int len = 0; 2298*711890bcSjc156560 int i = 0, j = 0; 2299*711890bcSjc156560 char *p, *t; 2300*711890bcSjc156560 char *delimit = " "; 2301*711890bcSjc156560 char *disks_str; 2302*711890bcSjc156560 disk_tag_t disk_tag; 23037c478bd9Sstevel@tonic-gate 2304*711890bcSjc156560 if (disks_argp == NULL || comps_nump == NULL) { 2305*711890bcSjc156560 return (FAILURE); 2306*711890bcSjc156560 } 2307*711890bcSjc156560 2308*711890bcSjc156560 p = disks_argp; 2309*711890bcSjc156560 len = strlen(disks_argp); 2310*711890bcSjc156560 2311*711890bcSjc156560 if ((disks_str = (char *)malloc(3 * len + 4)) == NULL) { 2312*711890bcSjc156560 return (FAILURE); 2313*711890bcSjc156560 } 2314*711890bcSjc156560 2315*711890bcSjc156560 /* Insert whitespace between disk tags, '(' , and ')' */ 2316*711890bcSjc156560 disks_str[j ++] = '('; 2317*711890bcSjc156560 disks_str[j ++] = ' '; 2318*711890bcSjc156560 2319*711890bcSjc156560 while (p[i] != '\0') { 2320*711890bcSjc156560 if (p[i] == ')' || p[i] == '(') { 2321*711890bcSjc156560 disks_str[j ++] = ' '; 2322*711890bcSjc156560 disks_str[j ++] = p[i]; 2323*711890bcSjc156560 disks_str[j ++] = ' '; 2324*711890bcSjc156560 } else 2325*711890bcSjc156560 disks_str[j ++] = p[i]; 2326*711890bcSjc156560 i ++; 2327*711890bcSjc156560 } 2328*711890bcSjc156560 disks_str[j ++] = ' '; 2329*711890bcSjc156560 disks_str[j ++] = ')'; 2330*711890bcSjc156560 disks_str[j] = '\0'; 2331*711890bcSjc156560 2332*711890bcSjc156560 len = strlen(disks_str) + 1; 2333*711890bcSjc156560 2334*711890bcSjc156560 if ((t = (char *)malloc(len)) == NULL) { 2335*711890bcSjc156560 return (FAILURE); 2336*711890bcSjc156560 } 2337*711890bcSjc156560 (void) memcpy(t, disks_str, len); 2338*711890bcSjc156560 p = strtok(t, delimit); 2339*711890bcSjc156560 while (p != NULL) { 2340*711890bcSjc156560 (*comps_nump)++; 2341*711890bcSjc156560 p = strtok(NULL, delimit); 2342*711890bcSjc156560 } 2343*711890bcSjc156560 free(t); 2344*711890bcSjc156560 2345*711890bcSjc156560 *handlespp = calloc(*comps_nump, sizeof (raid_obj_handle_t)); 2346*711890bcSjc156560 if (*handlespp == NULL) { 2347*711890bcSjc156560 return (FAILURE); 2348*711890bcSjc156560 } 2349*711890bcSjc156560 2350*711890bcSjc156560 for (i = 0; i < *comps_nump; i++) 2351*711890bcSjc156560 (*handlespp)[i] = INIT_HANDLE_VALUE; 2352*711890bcSjc156560 2353*711890bcSjc156560 i = 0; 2354*711890bcSjc156560 p = strtok(disks_str, delimit); 2355*711890bcSjc156560 while (p != NULL) { 2356*711890bcSjc156560 if (*p == '(') { 2357*711890bcSjc156560 (*handlespp)[i] = OBJ_SEPARATOR_BEGIN; 2358*711890bcSjc156560 } else if (*p == ')') { 2359*711890bcSjc156560 (*handlespp)[i] = OBJ_SEPARATOR_END; 2360*711890bcSjc156560 } else { 2361*711890bcSjc156560 if (get_disk_tag_cidl(p, &disk_tag) != SUCCESS) { 2362*711890bcSjc156560 free(*handlespp); 2363*711890bcSjc156560 free(disks_str); 2364*711890bcSjc156560 return (INVALID_ARG); 2365*711890bcSjc156560 } 2366*711890bcSjc156560 (*handlespp)[i] = 2367*711890bcSjc156560 raidcfg_get_disk(raidcfg_get_controller(ctl_tag), 2368*711890bcSjc156560 disk_tag); 2369*711890bcSjc156560 if ((*handlespp)[i] <= 0) { 2370*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2371*711890bcSjc156560 raidcfg_errstr((*handlespp)[i])); 2372*711890bcSjc156560 free(*handlespp); 2373*711890bcSjc156560 free(disks_str); 2374*711890bcSjc156560 return (FAILURE); 2375*711890bcSjc156560 } 2376*711890bcSjc156560 } 2377*711890bcSjc156560 p = strtok(NULL, delimit); 2378*711890bcSjc156560 i++; 2379*711890bcSjc156560 } 2380*711890bcSjc156560 2381*711890bcSjc156560 free(disks_str); 2382*711890bcSjc156560 return (SUCCESS); 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate /* 2386*711890bcSjc156560 * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep) 2387*711890bcSjc156560 * This function parses string of single disk with "ctd" format, for example, 2388*711890bcSjc156560 * c0t0d0, and translates it to controller tag and disk tag. 2389*711890bcSjc156560 * Then it calls lib api and get disk handle. The controller tag and disk 2390*711890bcSjc156560 * handle are both returned by out parameters. 2391*711890bcSjc156560 * The return value is SUCCESS or FAILURE. 23927c478bd9Sstevel@tonic-gate */ 2393*711890bcSjc156560 static int 2394*711890bcSjc156560 get_disk_handle_ctd(int disks_num, char **disks_argpp, uint32_t *ctl_tagp, 2395*711890bcSjc156560 raid_obj_handle_t *disks_handlep) 2396*711890bcSjc156560 { 2397*711890bcSjc156560 raid_obj_handle_t ctl_handle; 2398*711890bcSjc156560 disk_tag_t disk_tag; 2399*711890bcSjc156560 uint32_t ctl_id; 2400*711890bcSjc156560 int i; 2401*711890bcSjc156560 int ret; 2402*711890bcSjc156560 2403*711890bcSjc156560 if (disks_handlep == NULL) { 2404*711890bcSjc156560 return (FAILURE); 2405*711890bcSjc156560 } 2406*711890bcSjc156560 2407*711890bcSjc156560 for (i = 0; i < disks_num; i++) { 2408*711890bcSjc156560 if (get_disk_tag_ctd(disks_argpp[i], &disk_tag, &ctl_id) != 2409*711890bcSjc156560 SUCCESS) { 2410*711890bcSjc156560 return (INVALID_ARG); 2411*711890bcSjc156560 } 2412*711890bcSjc156560 2413*711890bcSjc156560 *ctl_tagp = ctl_id; 2414*711890bcSjc156560 2415*711890bcSjc156560 if (i == 0) { 2416*711890bcSjc156560 ctl_handle = raidcfg_get_controller(*ctl_tagp); 2417*711890bcSjc156560 if (ctl_handle <= 0) { 2418*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2419*711890bcSjc156560 raidcfg_errstr(ctl_handle)); 2420*711890bcSjc156560 return (FAILURE); 2421*711890bcSjc156560 } 2422*711890bcSjc156560 ret = raidcfg_open_controller(ctl_handle, NULL); 2423*711890bcSjc156560 if (ret < 0) { 2424*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2425*711890bcSjc156560 raidcfg_errstr(ret)); 2426*711890bcSjc156560 return (FAILURE); 2427*711890bcSjc156560 } 2428*711890bcSjc156560 } 2429*711890bcSjc156560 2430*711890bcSjc156560 if ((disks_handlep[i] = 2431*711890bcSjc156560 raidcfg_get_disk(ctl_handle, disk_tag)) < 0) { 2432*711890bcSjc156560 (void) fprintf(stderr, "%s\n", 2433*711890bcSjc156560 raidcfg_errstr(disks_handlep[i])); 2434*711890bcSjc156560 (void) raidcfg_close_controller(ctl_handle, NULL); 2435*711890bcSjc156560 return (FAILURE); 2436*711890bcSjc156560 } 2437*711890bcSjc156560 } 2438*711890bcSjc156560 2439*711890bcSjc156560 return (SUCCESS); 24407c478bd9Sstevel@tonic-gate } 24417c478bd9Sstevel@tonic-gate 24427c478bd9Sstevel@tonic-gate /* 2443*711890bcSjc156560 * get_ctl_tag(argp) 2444*711890bcSjc156560 * This function translates controller string to tag. The return value is 2445*711890bcSjc156560 * SUCCESS if the string has legal format and is parsed successfully, 2446*711890bcSjc156560 * or FAILURE if it fails. 24477c478bd9Sstevel@tonic-gate */ 2448*711890bcSjc156560 static int 2449*711890bcSjc156560 get_ctl_tag(char *argp, uint32_t *ctl_tagp) 2450*711890bcSjc156560 { 2451*711890bcSjc156560 if (argp == NULL || is_fully_numeric(argp) == FALSE || 2452*711890bcSjc156560 ctl_tagp == NULL) { 2453*711890bcSjc156560 return (FAILURE); 24547c478bd9Sstevel@tonic-gate } 2455*711890bcSjc156560 *ctl_tagp = (atoi(argp)); 2456*711890bcSjc156560 return (SUCCESS); 24577c478bd9Sstevel@tonic-gate } 24587c478bd9Sstevel@tonic-gate 24597c478bd9Sstevel@tonic-gate /* 2460*711890bcSjc156560 * get_array_tag(argp, ctl_tagp, array_tagp) 2461*711890bcSjc156560 * This function parses array string to get array tag and controller tag. 2462*711890bcSjc156560 * The return value is SUCCESS if the string has legal format, or 2463*711890bcSjc156560 * FAILURE if it fails. 24647c478bd9Sstevel@tonic-gate */ 2465*711890bcSjc156560 static int 2466*711890bcSjc156560 get_array_tag(char *argp, uint32_t *ctl_tagp, array_tag_t *array_tagp) 2467*711890bcSjc156560 { 2468*711890bcSjc156560 char *t = NULL; 2469*711890bcSjc156560 char *cp = NULL; 2470*711890bcSjc156560 char *tp = NULL; 2471*711890bcSjc156560 char *dp = NULL; 2472*711890bcSjc156560 2473*711890bcSjc156560 uint32_t value_c = MAX32BIT; 2474*711890bcSjc156560 uint32_t value_t = MAX32BIT; 2475*711890bcSjc156560 uint32_t value_d = MAX32BIT; 2476*711890bcSjc156560 2477*711890bcSjc156560 int len = 0; 2478*711890bcSjc156560 2479*711890bcSjc156560 if (argp == NULL || (len = strlen(argp)) == 0 || 2480*711890bcSjc156560 array_tagp == NULL) { 2481*711890bcSjc156560 return (FAILURE); 2482*711890bcSjc156560 } 2483*711890bcSjc156560 2484*711890bcSjc156560 t = (char *)malloc(len + 1); 2485*711890bcSjc156560 if (t == NULL) { 2486*711890bcSjc156560 return (FAILURE); 2487*711890bcSjc156560 } 2488*711890bcSjc156560 2489*711890bcSjc156560 (void) memcpy(t, argp, len + 1); 2490*711890bcSjc156560 2491*711890bcSjc156560 /* Now remmber to release t memory if exception occurs */ 2492*711890bcSjc156560 if (((dp = strchr(t, 'd')) == NULL) || 2493*711890bcSjc156560 ((tp = strchr(t, 't')) == NULL) || 2494*711890bcSjc156560 ((cp = strchr(t, 'c')) == NULL)) { 2495*711890bcSjc156560 free(t); 2496*711890bcSjc156560 return (FAILURE); 2497*711890bcSjc156560 } 2498*711890bcSjc156560 cp = t; 2499*711890bcSjc156560 2500*711890bcSjc156560 *dp = '\0'; 2501*711890bcSjc156560 dp++; 2502*711890bcSjc156560 *tp = '\0'; 2503*711890bcSjc156560 tp++; 2504*711890bcSjc156560 cp++; 2505*711890bcSjc156560 2506*711890bcSjc156560 if (is_fully_numeric(dp) == FALSE || 2507*711890bcSjc156560 is_fully_numeric(tp) == FALSE || 2508*711890bcSjc156560 is_fully_numeric(cp) == FALSE) { 2509*711890bcSjc156560 free(t); 2510*711890bcSjc156560 return (FAILURE); 2511*711890bcSjc156560 } 2512*711890bcSjc156560 2513*711890bcSjc156560 value_c = atoi(cp); 2514*711890bcSjc156560 value_t = atoi(tp); 2515*711890bcSjc156560 value_d = atoi(dp); 2516*711890bcSjc156560 2517*711890bcSjc156560 array_tagp->idl.target_id = value_t; 2518*711890bcSjc156560 array_tagp->idl.lun = value_d; 2519*711890bcSjc156560 2520*711890bcSjc156560 if (ctl_tagp != NULL) { 2521*711890bcSjc156560 *ctl_tagp = value_c; 2522*711890bcSjc156560 } 2523*711890bcSjc156560 2524*711890bcSjc156560 free(t); 2525*711890bcSjc156560 return (SUCCESS); 2526*711890bcSjc156560 } 2527*711890bcSjc156560 2528*711890bcSjc156560 /* 2529*711890bcSjc156560 * get_disk_tag_ctd(argp, disk_tagp) 2530*711890bcSjc156560 * This function parses disk string of ctd format, and translates it to 2531*711890bcSjc156560 * disk tag and controller tag. The tags is returned by out parameters. 2532*711890bcSjc156560 * The return value is SUCCESS if the string has legal format, or FAILURE 2533*711890bcSjc156560 * if it fails. 2534*711890bcSjc156560 */ 2535*711890bcSjc156560 static int 2536*711890bcSjc156560 get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, uint32_t *ctl_tag) 2537*711890bcSjc156560 { 2538*711890bcSjc156560 char *t = NULL; 2539*711890bcSjc156560 char *cp = NULL; 2540*711890bcSjc156560 char *tp = NULL; 2541*711890bcSjc156560 char *dp = NULL; 2542*711890bcSjc156560 2543*711890bcSjc156560 uint32_t value_c = MAX32BIT; 2544*711890bcSjc156560 uint32_t value_t = MAX32BIT; 2545*711890bcSjc156560 uint32_t value_d = MAX32BIT; 2546*711890bcSjc156560 2547*711890bcSjc156560 int len = 0; 2548*711890bcSjc156560 2549*711890bcSjc156560 if (argp == NULL || (len = strlen(argp)) == 0 || 2550*711890bcSjc156560 disk_tagp == NULL) { 2551*711890bcSjc156560 return (FAILURE); 2552*711890bcSjc156560 } 2553*711890bcSjc156560 2554*711890bcSjc156560 t = (char *)malloc(len + 1); 2555*711890bcSjc156560 if (t == NULL) { 2556*711890bcSjc156560 return (FAILURE); 2557*711890bcSjc156560 } 2558*711890bcSjc156560 2559*711890bcSjc156560 (void) memcpy(t, argp, len + 1); 2560*711890bcSjc156560 2561*711890bcSjc156560 /* Now remmber to release t memory if exception occurs */ 2562*711890bcSjc156560 if (((dp = strchr(t, 'd')) == NULL) || 2563*711890bcSjc156560 ((tp = strchr(t, 't')) == NULL) || 2564*711890bcSjc156560 ((cp = strchr(t, 'c')) == NULL)) { 2565*711890bcSjc156560 free(t); 2566*711890bcSjc156560 return (FAILURE); 2567*711890bcSjc156560 } 2568*711890bcSjc156560 cp = t; 2569*711890bcSjc156560 2570*711890bcSjc156560 *dp = '\0'; 2571*711890bcSjc156560 dp++; 2572*711890bcSjc156560 *tp = '\0'; 2573*711890bcSjc156560 tp++; 2574*711890bcSjc156560 cp++; 2575*711890bcSjc156560 2576*711890bcSjc156560 if (is_fully_numeric(dp) == FALSE || 2577*711890bcSjc156560 is_fully_numeric(tp) == FALSE || 2578*711890bcSjc156560 is_fully_numeric(cp) == FALSE) { 2579*711890bcSjc156560 free(t); 2580*711890bcSjc156560 return (FAILURE); 2581*711890bcSjc156560 } 2582*711890bcSjc156560 2583*711890bcSjc156560 value_c = atoi(cp); 2584*711890bcSjc156560 value_t = atoi(tp); 2585*711890bcSjc156560 value_d = atoi(dp); 2586*711890bcSjc156560 2587*711890bcSjc156560 disk_tagp->cidl.bus = 0; 2588*711890bcSjc156560 disk_tagp->cidl.target_id = value_t; 2589*711890bcSjc156560 disk_tagp->cidl.lun = value_d; 2590*711890bcSjc156560 *ctl_tag = value_c; 2591*711890bcSjc156560 2592*711890bcSjc156560 free(t); 2593*711890bcSjc156560 return (SUCCESS); 2594*711890bcSjc156560 } 2595*711890bcSjc156560 2596*711890bcSjc156560 /* 2597*711890bcSjc156560 * get_disk_tag_cidl(argp, disk_tagp) 2598*711890bcSjc156560 * This function parses disk string of cidl format and translates it to tag. 2599*711890bcSjc156560 * The return value is disk tag if the string has legal format, or FAILURE 2600*711890bcSjc156560 * if it fails. 2601*711890bcSjc156560 */ 2602*711890bcSjc156560 static int 2603*711890bcSjc156560 get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp) 2604*711890bcSjc156560 { 2605*711890bcSjc156560 int len = 0; 2606*711890bcSjc156560 char *p = NULL; 2607*711890bcSjc156560 char *t = NULL; 2608*711890bcSjc156560 char *dot1p = NULL; 2609*711890bcSjc156560 char *dot2p = NULL; 2610*711890bcSjc156560 2611*711890bcSjc156560 if (argp == NULL || (len = strlen(argp)) == 0) { 2612*711890bcSjc156560 return (FAILURE); 2613*711890bcSjc156560 } 2614*711890bcSjc156560 2615*711890bcSjc156560 if (disk_tagp == NULL) { 2616*711890bcSjc156560 return (FAILURE); 2617*711890bcSjc156560 } 2618*711890bcSjc156560 2619*711890bcSjc156560 t = (char *)malloc(len + 1); 2620*711890bcSjc156560 if (t == NULL) { 2621*711890bcSjc156560 return (FAILURE); 2622*711890bcSjc156560 } 2623*711890bcSjc156560 2624*711890bcSjc156560 (void) memcpy(t, argp, len + 1); 2625*711890bcSjc156560 p = t; 2626*711890bcSjc156560 2627*711890bcSjc156560 dot2p = strrchr(p, '.'); 2628*711890bcSjc156560 if (dot2p == NULL) { 2629*711890bcSjc156560 free(t); 2630*711890bcSjc156560 return (FAILURE); 2631*711890bcSjc156560 } 2632*711890bcSjc156560 *dot2p = '\0'; 2633*711890bcSjc156560 dot2p++; 2634*711890bcSjc156560 2635*711890bcSjc156560 dot1p = strrchr(p, '.'); 2636*711890bcSjc156560 if (dot1p == NULL) { 2637*711890bcSjc156560 free(t); 2638*711890bcSjc156560 return (FAILURE); 2639*711890bcSjc156560 } 2640*711890bcSjc156560 *dot1p = '\0'; 2641*711890bcSjc156560 dot1p++; 2642*711890bcSjc156560 2643*711890bcSjc156560 /* Assert only 2 dots in this string */ 2644*711890bcSjc156560 if (strrchr(p, '.') != NULL) { 2645*711890bcSjc156560 free(t); 2646*711890bcSjc156560 return (FAILURE); 2647*711890bcSjc156560 } 2648*711890bcSjc156560 2649*711890bcSjc156560 while (*p == ' ') 2650*711890bcSjc156560 p++; 2651*711890bcSjc156560 2652*711890bcSjc156560 if (is_fully_numeric(p) == FALSE || 2653*711890bcSjc156560 is_fully_numeric(dot1p) == FALSE || 2654*711890bcSjc156560 is_fully_numeric(dot2p) == FALSE) { 2655*711890bcSjc156560 free(t); 2656*711890bcSjc156560 return (FAILURE); 2657*711890bcSjc156560 } 2658*711890bcSjc156560 2659*711890bcSjc156560 disk_tagp->cidl.bus = atoi(p); 2660*711890bcSjc156560 disk_tagp->cidl.target_id = atoi(dot1p); 2661*711890bcSjc156560 disk_tagp->cidl.lun = atoi(dot2p); 2662*711890bcSjc156560 2663*711890bcSjc156560 free(t); 2664*711890bcSjc156560 return (SUCCESS); 2665*711890bcSjc156560 } 2666*711890bcSjc156560 2667*711890bcSjc156560 /* 2668*711890bcSjc156560 * calc_size(sizep, valp) 2669*711890bcSjc156560 * This function calculates the value represented by string sizep. 2670*711890bcSjc156560 * The string sizep can be decomposed into three parts: an initial, 2671*711890bcSjc156560 * possibly empty, sequence of white-space characters; a subject digital 2672*711890bcSjc156560 * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a 2673*711890bcSjc156560 * final string of one or more unrecognized characters or white-sapce 2674*711890bcSjc156560 * characters, including the terminating null. If unrecognized character 2675*711890bcSjc156560 * exists or overflow happens, the conversion must fail and return 2676*711890bcSjc156560 * INVALID_ARG. If the conversion is performed successfully, result will 2677*711890bcSjc156560 * be saved into valp and function returns SUCCESS. It returns FAILURE 2678*711890bcSjc156560 * when memory allocation fails. 2679*711890bcSjc156560 */ 2680*711890bcSjc156560 static int 2681*711890bcSjc156560 calc_size(char *sizep, uint64_t *valp) 2682*711890bcSjc156560 { 2683*711890bcSjc156560 int len; 2684*711890bcSjc156560 uint64_t size; 2685*711890bcSjc156560 uint64_t unit; 2686*711890bcSjc156560 char *t = NULL; 2687*711890bcSjc156560 char *tailp = NULL; 2688*711890bcSjc156560 2689*711890bcSjc156560 if (sizep == NULL || valp == NULL) { 2690*711890bcSjc156560 return (INVALID_ARG); 2691*711890bcSjc156560 } 2692*711890bcSjc156560 2693*711890bcSjc156560 len = strlen(sizep); 2694*711890bcSjc156560 if (len == 0) { 2695*711890bcSjc156560 return (INVALID_ARG); 2696*711890bcSjc156560 } 2697*711890bcSjc156560 2698*711890bcSjc156560 t = (char *)malloc(len + 1); 2699*711890bcSjc156560 if (t == NULL) { 2700*711890bcSjc156560 return (FAILURE); 2701*711890bcSjc156560 } 2702*711890bcSjc156560 2703*711890bcSjc156560 (void) memcpy(t, sizep, len + 1); 2704*711890bcSjc156560 2705*711890bcSjc156560 switch (*(t + len - 1)) { 2706*711890bcSjc156560 case 'k': 2707*711890bcSjc156560 case 'K': 2708*711890bcSjc156560 unit = 1024ull; 2709*711890bcSjc156560 errno = 0; 2710*711890bcSjc156560 size = strtoll(t, &tailp, 0); 2711*711890bcSjc156560 break; 2712*711890bcSjc156560 case 'm': 2713*711890bcSjc156560 case 'M': 2714*711890bcSjc156560 unit = 1024ull * 1024ull; 2715*711890bcSjc156560 errno = 0; 2716*711890bcSjc156560 size = strtoll(t, &tailp, 0); 2717*711890bcSjc156560 break; 2718*711890bcSjc156560 case 'g': 2719*711890bcSjc156560 case 'G': 2720*711890bcSjc156560 unit = 1024ull * 1024ull * 1024ull; 2721*711890bcSjc156560 errno = 0; 2722*711890bcSjc156560 size = strtoll(t, &tailp, 0); 2723*711890bcSjc156560 break; 2724*711890bcSjc156560 case 't': 2725*711890bcSjc156560 case 'T': 2726*711890bcSjc156560 unit = 1024ull * 1024ull * 1024ull * 1024ull; 2727*711890bcSjc156560 errno = 0; 2728*711890bcSjc156560 size = strtoll(t, &tailp, 0); 2729*711890bcSjc156560 break; 2730*711890bcSjc156560 default: 2731*711890bcSjc156560 /* The unit must be kilobyte at least. */ 2732*711890bcSjc156560 free(t); 2733*711890bcSjc156560 return (INVALID_ARG); 2734*711890bcSjc156560 } 2735*711890bcSjc156560 2736*711890bcSjc156560 *(t + len - 1) = '\0'; 2737*711890bcSjc156560 if (is_fully_numeric(t) != TRUE) { 2738*711890bcSjc156560 free(t); 2739*711890bcSjc156560 return (INVALID_ARG); 2740*711890bcSjc156560 } 2741*711890bcSjc156560 2742*711890bcSjc156560 errno = 0; 2743*711890bcSjc156560 size = strtoll(t, &tailp, 0); 2744*711890bcSjc156560 2745*711890bcSjc156560 /* Check overflow condition */ 2746*711890bcSjc156560 if (errno == ERANGE || (size > (MAX64BIT / unit))) { 2747*711890bcSjc156560 free(t); 2748*711890bcSjc156560 return (INVALID_ARG); 2749*711890bcSjc156560 } 2750*711890bcSjc156560 2751*711890bcSjc156560 *valp = size * unit; 2752*711890bcSjc156560 free(t); 2753*711890bcSjc156560 return (SUCCESS); 2754*711890bcSjc156560 } 2755*711890bcSjc156560 2756*711890bcSjc156560 /* 2757*711890bcSjc156560 * is_fully_numeric(str) 2758*711890bcSjc156560 * This function checks if the string are legal numeric string. The beginning 2759*711890bcSjc156560 * or ending characters can be white spaces. 2760*711890bcSjc156560 * Return value is TRUE if the string are legal numeric string, or FALSE 2761*711890bcSjc156560 * otherwise. 2762*711890bcSjc156560 */ 2763*711890bcSjc156560 static int 2764*711890bcSjc156560 is_fully_numeric(char *strp) 2765*711890bcSjc156560 { 2766*711890bcSjc156560 uint32_t len; 2767*711890bcSjc156560 uint32_t i; 2768*711890bcSjc156560 2769*711890bcSjc156560 if (strp == NULL) { 2770*711890bcSjc156560 return (FALSE); 2771*711890bcSjc156560 } 2772*711890bcSjc156560 2773*711890bcSjc156560 len = strlen(strp); 2774*711890bcSjc156560 if (len == 0) { 2775*711890bcSjc156560 return (FALSE); 2776*711890bcSjc156560 } 2777*711890bcSjc156560 2778*711890bcSjc156560 /* Skip whitespace characters */ 2779*711890bcSjc156560 for (i = 0; i < len; i++) { 2780*711890bcSjc156560 if (strp[i] != ' ') { 27817c478bd9Sstevel@tonic-gate break; 27827c478bd9Sstevel@tonic-gate } 27837c478bd9Sstevel@tonic-gate } 27847c478bd9Sstevel@tonic-gate 2785*711890bcSjc156560 /* if strp points all space characters */ 2786*711890bcSjc156560 if (i == len) { 2787*711890bcSjc156560 return (FALSE); 27887c478bd9Sstevel@tonic-gate } 27897c478bd9Sstevel@tonic-gate 2790*711890bcSjc156560 /* Check the digitals in string */ 2791*711890bcSjc156560 for (; i < len; i++) { 2792*711890bcSjc156560 if (!isdigit(strp[i])) { 27937c478bd9Sstevel@tonic-gate break; 27947c478bd9Sstevel@tonic-gate } 27957c478bd9Sstevel@tonic-gate } 27967c478bd9Sstevel@tonic-gate 2797*711890bcSjc156560 /* Check the ending string */ 2798*711890bcSjc156560 for (; i < len; i++) { 2799*711890bcSjc156560 if (strp[i] != ' ') { 2800*711890bcSjc156560 return (FALSE); 28017c478bd9Sstevel@tonic-gate } 28027c478bd9Sstevel@tonic-gate } 28037c478bd9Sstevel@tonic-gate 2804*711890bcSjc156560 return (TRUE); 28057c478bd9Sstevel@tonic-gate } 28067c478bd9Sstevel@tonic-gate 28077c478bd9Sstevel@tonic-gate static int 28086fec3791Sjesseb yes(void) 28097c478bd9Sstevel@tonic-gate { 28107c478bd9Sstevel@tonic-gate int i, b; 28117c478bd9Sstevel@tonic-gate char ans[SCHAR_MAX + 1]; 28127c478bd9Sstevel@tonic-gate 28137c478bd9Sstevel@tonic-gate for (i = 0; ; i++) { 28147c478bd9Sstevel@tonic-gate b = getchar(); 28157c478bd9Sstevel@tonic-gate if (b == '\n' || b == '\0' || b == EOF) { 28167c478bd9Sstevel@tonic-gate ans[i] = 0; 28177c478bd9Sstevel@tonic-gate break; 28187c478bd9Sstevel@tonic-gate } 2819*711890bcSjc156560 if (i < SCHAR_MAX) { 28207c478bd9Sstevel@tonic-gate ans[i] = b; 28217c478bd9Sstevel@tonic-gate } 2822*711890bcSjc156560 } 28237c478bd9Sstevel@tonic-gate if (i >= SCHAR_MAX) { 28247c478bd9Sstevel@tonic-gate i = SCHAR_MAX; 28257c478bd9Sstevel@tonic-gate ans[SCHAR_MAX] = 0; 28267c478bd9Sstevel@tonic-gate } 28276fec3791Sjesseb 2828*711890bcSjc156560 return (rpmatch(ans)); 2829*711890bcSjc156560 } 2830*711890bcSjc156560 2831*711890bcSjc156560 /* 2832*711890bcSjc156560 * Function: int rpmatch(char *) 2833*711890bcSjc156560 * 2834*711890bcSjc156560 * Description: 2835*711890bcSjc156560 * 2836*711890bcSjc156560 * Internationalized get yes / no answer. 2837*711890bcSjc156560 * 2838*711890bcSjc156560 * Inputs: 2839*711890bcSjc156560 * s -> Pointer to answer to compare against. 2840*711890bcSjc156560 * 2841*711890bcSjc156560 * Returns: 2842*711890bcSjc156560 * TRUE -> Answer was affirmative 2843*711890bcSjc156560 * FALSE -> Answer was negative 2844*711890bcSjc156560 */ 2845*711890bcSjc156560 2846*711890bcSjc156560 static int 2847*711890bcSjc156560 rpmatch(char *s) 2848*711890bcSjc156560 { 2849*711890bcSjc156560 int status; 2850*711890bcSjc156560 2851*711890bcSjc156560 /* match yesexpr */ 2852*711890bcSjc156560 status = regexec(&re, s, (size_t)0, NULL, 0); 2853*711890bcSjc156560 if (status != 0) { 2854*711890bcSjc156560 return (FALSE); 2855*711890bcSjc156560 } 2856*711890bcSjc156560 return (TRUE); 28577c478bd9Sstevel@tonic-gate } 28587c478bd9Sstevel@tonic-gate 28597c478bd9Sstevel@tonic-gate static int 2860*711890bcSjc156560 size_to_string(uint64_t size, char *string, int len) 28617c478bd9Sstevel@tonic-gate { 2862*711890bcSjc156560 int i = 0; 2863*711890bcSjc156560 uint32_t remainder; 2864*711890bcSjc156560 char unit[][2] = {" ", "K", "M", "G", "T"}; 28657c478bd9Sstevel@tonic-gate 2866*711890bcSjc156560 if (string == NULL) { 2867*711890bcSjc156560 return (FAILURE); 2868*711890bcSjc156560 } 2869*711890bcSjc156560 while (size > 1023) { 2870*711890bcSjc156560 remainder = size % 1024; 2871*711890bcSjc156560 size /= 1024; 2872*711890bcSjc156560 i++; 2873*711890bcSjc156560 } 2874*711890bcSjc156560 2875*711890bcSjc156560 if (i > 4) { 28767c478bd9Sstevel@tonic-gate return (FAILURE); 28777c478bd9Sstevel@tonic-gate } 28787c478bd9Sstevel@tonic-gate 2879*711890bcSjc156560 remainder /= 103; 2880*711890bcSjc156560 if (remainder == 0) { 2881*711890bcSjc156560 (void) snprintf(string, len, "%llu", size); 2882*711890bcSjc156560 } else { 2883*711890bcSjc156560 (void) snprintf(string, len, "%llu.%1u", size, 2884*711890bcSjc156560 remainder); 28857c478bd9Sstevel@tonic-gate } 28867c478bd9Sstevel@tonic-gate 2887*711890bcSjc156560 /* make sure there is one byte for unit */ 2888*711890bcSjc156560 if ((strlen(string) + 1) >= len) { 28897c478bd9Sstevel@tonic-gate return (FAILURE); 28907c478bd9Sstevel@tonic-gate } 2891*711890bcSjc156560 (void) strcat(string, unit[i]); 28927c478bd9Sstevel@tonic-gate 28937c478bd9Sstevel@tonic-gate return (SUCCESS); 28947c478bd9Sstevel@tonic-gate } 28957c478bd9Sstevel@tonic-gate 28967c478bd9Sstevel@tonic-gate /* 2897*711890bcSjc156560 * Only one raidctl is running at one time. 28987c478bd9Sstevel@tonic-gate */ 28997c478bd9Sstevel@tonic-gate static int 2900*711890bcSjc156560 enter_raidctl_lock(int *fd) 29017c478bd9Sstevel@tonic-gate { 2902*711890bcSjc156560 int fd0 = -1; 2903*711890bcSjc156560 struct flock lock; 29047c478bd9Sstevel@tonic-gate 2905*711890bcSjc156560 fd0 = open(RAIDCTL_LOCKF, O_CREAT|O_WRONLY, 0600); 2906*711890bcSjc156560 if (fd0 < 0) { 2907*711890bcSjc156560 (void) fprintf(stderr, gettext("raidctl:failed to open lockfile" 2908*711890bcSjc156560 " '"RAIDCTL_LOCKF"': %s\n"), strerror(errno)); 29097c478bd9Sstevel@tonic-gate return (FAILURE); 29107c478bd9Sstevel@tonic-gate } 29117c478bd9Sstevel@tonic-gate 2912*711890bcSjc156560 *fd = fd0; 2913*711890bcSjc156560 lock.l_type = F_WRLCK; 2914*711890bcSjc156560 lock.l_whence = SEEK_SET; 2915*711890bcSjc156560 lock.l_start = 0; 2916*711890bcSjc156560 lock.l_len = 0; 2917*711890bcSjc156560 2918*711890bcSjc156560 if ((fcntl(fd0, F_SETLK, &lock) == -1) && 2919*711890bcSjc156560 (errno == EAGAIN || errno == EDEADLK)) { 2920*711890bcSjc156560 if (fcntl(fd0, F_GETLK, &lock) == -1) { 2921*711890bcSjc156560 (void) fprintf(stderr, 2922*711890bcSjc156560 gettext("raidctl:enter_filelock error\n")); 29237c478bd9Sstevel@tonic-gate return (FAILURE); 29247c478bd9Sstevel@tonic-gate } 2925*711890bcSjc156560 (void) fprintf(stderr, gettext("raidctl:" 2926*711890bcSjc156560 "enter_filelock:filelock is owned " 2927*711890bcSjc156560 "by 'process %d'\n"), lock.l_pid); 2928*711890bcSjc156560 return (FAILURE); 29297c478bd9Sstevel@tonic-gate } 29307c478bd9Sstevel@tonic-gate 2931*711890bcSjc156560 return (SUCCESS); 29327c478bd9Sstevel@tonic-gate } 29336fec3791Sjesseb 2934*711890bcSjc156560 static void 2935*711890bcSjc156560 exit_raidctl_lock(int fd) 2936*711890bcSjc156560 { 2937*711890bcSjc156560 struct flock lock; 29387c478bd9Sstevel@tonic-gate 2939*711890bcSjc156560 lock.l_type = F_UNLCK; 2940*711890bcSjc156560 lock.l_whence = SEEK_SET; 2941*711890bcSjc156560 lock.l_start = 0; 2942*711890bcSjc156560 lock.l_len = 0; 2943*711890bcSjc156560 if (fcntl(fd, F_SETLK, &lock) == -1) { 2944*711890bcSjc156560 (void) fprintf(stderr, gettext("raidctl: failed to" 2945*711890bcSjc156560 " exit_filelock: %s\n"), 2946*711890bcSjc156560 strerror(errno)); 29477c478bd9Sstevel@tonic-gate } 2948*711890bcSjc156560 (void) close(fd); 29497c478bd9Sstevel@tonic-gate } 2950