raidctl.c (bdf93bc2b769af60b8d1a5403151836935a722b6) | raidctl.c (711890bc9379ceea66272dc8d4981812224ea86e) |
---|---|
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END | 1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END |
20 */ 21/* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. | 20 * 21 * 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. |
23 * Use is subject to license terms. | 23 * Use is subject to license terms. |
24 * 25 * raidctl.c is the entry file of RAID configuration utility. |
|
24 */ 25 26#pragma ident "%Z%%M% %I% %E% SMI" 27 28#include <ctype.h> | 26 */ 27 28#pragma ident "%Z%%M% %I% %E% SMI" 29 30#include <ctype.h> |
29#include <dirent.h> 30#include <errno.h> | 31#include <sys/types.h> 32#include <sys/stat.h> |
31#include <fcntl.h> 32#include <langinfo.h> | 33#include <fcntl.h> 34#include <langinfo.h> |
33#include <libintl.h> 34#include <limits.h> | 35#include <regex.h> |
35#include <locale.h> | 36#include <locale.h> |
36#include <stdarg.h> | 37#include <libintl.h> |
37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <strings.h> | 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41#include <strings.h> |
41#include <sys/ddi.h> 42#include <sys/mpt/mpi.h> 43#include <sys/mpt/mpi_ioc.h> 44#include <sys/stat.h> 45#include <sys/types.h> 46#include <sys/pci.h> | |
47#include <unistd.h> | 42#include <unistd.h> |
48#include <sys/mnttab.h> 49#include <sys/dkio.h> 50#include <config_admin.h> 51#include <sys/param.h> 52#include <sys/raidioctl.h> | 43#include <errno.h> 44#include <libgen.h> 45#include <raidcfg.h> |
53 | 46 |
54/* 55 * list of controllers to list 56 * setup like this: 57 * [ctrl_num] [status] 58 * 59 * where status is: 60 * RAID Found, 61 * No RAID Found 62 * RAID not supported on this controller 63 * Invalid Controller 64 */ | |
65 | 47 |
66typedef enum { 67 RAID_FOUND = 0x0, 68 RAID_NOT_FOUND, 69 RAID_NOT_SUPPORTED, 70 RAID_INVALID_CTRL, 71 RAID_DONT_USE 72} raidctl_errno_t; | 48#define TRUE 1 49#define FALSE 0 |
73 | 50 |
74/* For no-mixup indexing of info_ctrl */ 75#define INFO_CTRL 0 76#define INFO_STATUS 1 | 51#ifndef TEXT_DOMAIN 52#define TEXT_DOMAIN "SYS_TEST" 53#endif |
77 | 54 |
78static int **info_ctrl = NULL; 79/* Length of conrollers list */ 80static int ctrl_nums = 0; | 55/* 56 * Return value of command 57 */ 58#define SUCCESS 0 59#define INVALID_ARG 1 60#define FAILURE 2 |
81 | 61 |
62/* 63 * Initial value of variables 64 */ 65#define INIT_HANDLE_VALUE -3 66#define MAX64BIT 0xffffffffffffffffull 67#define MAX32BIT 0xfffffffful |
|
82 | 68 |
83#define DEVDIR "/dev/rdsk" | 69/* 70 * Flag of set or unset HSP 71 */ 72#define HSP_SET 1 73#define HSP_UNSET 0 |
84 | 74 |
75/* 76 * Operate codes of command 77 */ |
|
85#define DO_HW_RAID_NOP -1 | 78#define DO_HW_RAID_NOP -1 |
86#define DO_HW_RAID_INFO 0 87#define DO_HW_RAID_CREATE 1 88#define DO_HW_RAID_DELETE 2 89#define DO_HW_RAID_FLASH 3 | 79#define DO_HW_RAID_HELP 0 80#define DO_HW_RAID_CREATEO 1 81#define DO_HW_RAID_CREATEN 2 82#define DO_HW_RAID_DELETE 3 83#define DO_HW_RAID_LIST 4 84#define DO_HW_RAID_FLASH 5 85#define DO_HW_RAID_HSP 6 86#define DO_HW_RAID_SET_ATTR 7 87#define DO_HW_RAID_SNAPSHOT 8 |
90 | 88 |
91/* values to use for raid level in raidctl */ 92#define RAID_STRIPE 0 93#define RAID_MIRROR 1 | 89#define LOWER_H (1 << 0) 90#define LOWER_C (1 << 1) 91#define LOWER_D (1 << 2) 92#define LOWER_L (1 << 3) 93#define LOWER_R (1 << 4) 94#define LOWER_Z (1 << 5) 95#define LOWER_G (1 << 6) 96#define LOWER_A (1 << 7) 97#define LOWER_S (1 << 8) 98#define LOWER_P (1 << 9) 99#define LOWER_F (1 << 10) 100#define UPPER_S (1 << 11) 101#define UPPER_C (1 << 12) 102#define UPPER_F (1 << 13) |
94 | 103 |
95/* 96 * Error return codes 97 */ 98#define SUCCESS 0 99#define INVALID_ARG 1 100#define FAILURE 2 | 104/* Add a ARRAY state (temporary) */ 105#define ARRAY_STATE_SYNC 100 |
101 102/* | 106 107/* |
103 * FW Update Stuff | 108 * Function and strings to properly localize our prompt. 109 * So for example in German it would ask (ja/nein) or (yes/no) in 110 * english. |
104 */ | 111 */ |
112#ifndef SCHAR_MAX 113#define SCHAR_MAX 10 114#endif |
|
105 | 115 |
106/* signature and initial offset for PCI expansion rom images */ 107#define PCIROM_SIG 0xaa55 /* offset 0h, length 2 bytes */ 108#define PCIR_OFF 0x18 /* Pointer to PCI Data Structure */ | 116#define RAIDCTL_LOCKF "/var/run/lockf_raidctl" |
109 | 117 |
110/* offsets in PCI data structure header */ 111#define PCIR_DEVID 0x6 /* PCI device id */ 112#define PCIR_CODETYPE 0x14 /* type of code (intel/fcode) */ 113#define PCIR_INDICATOR 0x15 /* "last image" indicator */ | 118/* Locale setting */ 119static int yes(void); 120static int rpmatch(char *s); 121static char *yesstr = NULL; 122static char *nostr = NULL; 123static char *yesexpr = NULL; |
114 | 124 |
115/* flags for image types */ 116#define BIOS_IMAGE 0x1 117#define FCODE_IMAGE 0x2 118#define UNKNOWN_IMAGE 0x3 119#define LAST_IMAGE 0x80 120#define NOT_LAST_IMAGE 0 121#define PCI_IMAGE_UNIT_SIZE 512 | 125static char *default_yesexpr = "^[yY]"; 126static char *default_yesstr = "yes"; 127static char *default_nostr = "no"; |
122 | 128 |
123/* ID's and offsets for MPT Firmware images */ 124#define FW_ROM_ID 0x5aea /* bytes 4 & 5 of file */ 125#define FW_ROM_OFFSET_CHIP_TYPE 0x22 /* (U16) */ 126#define FW_ROM_OFFSET_VERSION 0x24 /* (U16) */ 127#define FW_ROM_OFFSET_VERSION_NAME 0x44 /* (32 U8) */ | 129static regex_t re; |
128 | 130 |
129/* ID's for supported chips */ 130#define LSI_1030 0x30 131#define LSI_1064 0x50 132#define LSI_1068 0x54 133#define LSI_1064E 0x56 134#define LSI_1068E 0x58 | 131#define SET_DEFAULT_STRS \ 132 regfree(&re); \ 133 free(yesexpr); \ 134 free(yesstr); \ 135 free(nostr); \ 136 yesexpr = default_yesexpr; \ 137 yesstr = default_yesstr; \ 138 nostr = default_nostr; |
135 | 139 |
136/* Key to search for when looking for fcode version */ 137#define FCODE_VERS_KEY1 0x12 138#define FCODE_VERS_KEY2 0x7 139#define BIOS_STR "LSI SCSI Host Adapter BIOS Driver: " | 140#define FREE_STRS \ 141 if (yesexpr != default_yesexpr) \ 142 free(yesexpr); \ 143 if (yesstr != default_yesstr) \ 144 free(yesstr); \ 145 if (nostr != default_nostr) \ 146 free(nostr); |
140 | 147 |
141/* get a word from a buffer (works with non-word aligned offsets) */ 142#define gw(x) (((x)[0]) + (((x)[1]) << 8)) | 148/* program name */ 149static char *prog_namep; |
143 | 150 |
144/* Number of disks currently supported, per RAID volume */ 145#define N_DISKS 8 | |
146 | 151 |
147/* Maximum number of RAID volumes currently supported per HBA */ 148#define N_RAIDVOLS 2 149 | |
150/* | 152/* |
151 * Function and strings to properly localize our prompt. 152 * So for example in german it would ask (ja/nein) or (yes/no) in 153 * english. | 153 * Functions declaration |
154 */ | 154 */ |
155static int yes(void); 156static char yeschr[SCHAR_MAX + 2]; 157static char nochr[SCHAR_MAX +2]; | 155static void helpinfo(char *prog_namep); 156static int do_create_cidl(char *raid_levelp, char *capacityp, char *disk_argp, 157 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind); 158static int do_create_ctd(char *raid_levelp, char **disks_argpp, 159 uint32_t disks_num, uint32_t argindex, uint32_t f_flag); 160static int do_list(char *disk_argp, char **argv, uint32_t optind, 161 uint8_t is_snapshot); 162static int do_delete(uint32_t f_flag, char **argv, uint32_t optind); 163static int do_flash(uint8_t f_flag, char *filep, char **ctls_argpp, 164 uint32_t index, uint32_t ctl_num); 165static int do_set_hsp(char *a_argp, char *disk_argp, char **argv, 166 uint32_t optind); 167static int do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, 168 uint32_t optind); 169static int snapshot_raidsystem(uint8_t recursive, uint8_t indent, 170 uint8_t is_snapshot); 171static int snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, 172 uint8_t indent, uint8_t is_snapshot); 173static int snapshot_array(raid_obj_handle_t array_handle, 174 uint8_t indent, uint8_t is_sub, uint8_t is_snapshot); 175static int snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, 176 uint8_t indent, uint8_t is_snapshot); 177static int print_ctl_table(raid_obj_handle_t ctl_handle); 178static int print_array_table(raid_obj_handle_t ctl_handle, 179 raid_obj_handle_t array_handle); 180static int print_disk_table(raid_obj_handle_t ctl_handle, 181 raid_obj_handle_t disk_handle); 182static int print_ctl_attr(raidcfg_controller_t *attrp); 183static int print_array_attr(raidcfg_array_t *attrp); 184static int print_arraypart_attr(raidcfg_arraypart_t *attrp); 185static int print_disk_attr(raid_obj_handle_t ctl_handle, 186 raid_obj_handle_t disk_handle, raidcfg_disk_t *attrp); 187static void print_indent(uint8_t indent); 188static int get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, 189 int *comps_nump, raid_obj_handle_t **handlespp); 190static int get_disk_handle_ctd(int disks_num, char **disks_argpp, 191 uint32_t *ctl_tagp, raid_obj_handle_t *disks_handlep); 192static int get_ctl_tag(char *argp, uint32_t *ctl_tagp); 193static int get_array_tag(char *argp, uint32_t *ctl_tagp, 194 array_tag_t *array_tagp); 195static int get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, 196 uint32_t *controller_id); 197static int get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp); 198static int calc_size(char *sizep, uint64_t *valp); 199static int is_fully_numeric(char *strp); 200static int size_to_string(uint64_t size, char *string, int len); 201static int enter_raidctl_lock(int *fd); 202static void exit_raidctl_lock(int fd); |
158 | 203 |
159typedef struct raidlist { 160 raid_config_t raid_config[N_RAIDVOLS]; 161 int controller; 162 char devctl[MAXPATHLEN]; 163 struct raidlist *next; 164} raidlist_t; 165 166static raidlist_t *raids; 167 | |
168/* | 204/* |
169 * usage: raidctl 170 * usage: raidctl [-f] -c primary secondary 171 * usage: raidctl [-f] -c -r 1 primary secondary 172 * usage: raidctl [-f] -c -r 0 disk1 disk2 [disk3] ... 173 * usage: raidctl [-f] -d volume 174 * usage: raidctl [-f] -F image_file controller 175 * usage: raidctl -l [controller...] 176 * example: 177 * raidctl -c c1t1d0 c1t2d0 178 * raidctl -c -r 0 c1t1d0 c1t2d0 c1t3d0 c1t4d0 179 * raidctl -d c1t1d0 180 * raidctl -F image 1 | 205 * Entry function of raidctl command |
181 */ | 206 */ |
182static void 183usage(char *prog_name) | 207int 208main(int argc, char **argv) |
184{ | 209{ |
185 (void) fprintf(stderr, gettext("usage: %s\n"), prog_name); | 210 /* operation index */ 211 int8_t findex = DO_HW_RAID_NOP; |
186 | 212 |
187 (void) fprintf(stderr, gettext("usage: %s [-f] -c primary secondary\n"), 188 prog_name); | 213 /* argument pointers */ 214 char *r_argp = NULL; 215 char *z_argp = NULL; 216 char *g_argp = NULL; 217 char *a_argp = NULL; 218 char *s_argp = NULL; 219 char *p_argp = NULL; 220 char *F_argp = NULL; 221 char *C_argp = NULL; |
189 | 222 |
190 (void) fprintf(stderr, gettext("usage: %s [-f] -c -r 1 primary " 191 "secondary\n"), prog_name); | 223 /* 224 * operation flags. 225 */ 226 uint8_t r_flag = FALSE; 227 uint8_t f_flag = FALSE; 228 uint8_t action = FALSE; 229 uint64_t options = 0; |
192 | 230 |
193 (void) fprintf(stderr, gettext("usage: %s [-f] -c -r 0 disk1 disk2 " 194 "[disk3] ...\n"), prog_name); | 231 /* index and temporary variables */ 232 int ret; 233 int status; 234 char c = '\0'; |
195 | 235 |
196 (void) fprintf(stderr, gettext("usage: %s [-f] -d volume\n"), 197 prog_name); | 236 /* fd for the filelock */ 237 int fd; |
198 | 238 |
199 (void) fprintf(stderr, 200 gettext("usage: %s [-f] -F image_file controller \n"), 201 prog_name); | 239 if (enter_raidctl_lock(&fd) != SUCCESS) { 240 return (FAILURE); 241 } |
202 | 242 |
203 (void) fprintf(stderr, gettext("usage: %s -l [controller...]\n"), 204 prog_name); | 243 (void) setlocale(LC_ALL, ""); 244 (void) textdomain(TEXT_DOMAIN); |
205 | 245 |
206 (void) fprintf(stderr, gettext("example:\n")); 207 (void) fprintf(stderr, "%s -c c1t1d0 c1t2d0\n", prog_name); 208 (void) fprintf(stderr, "%s -c -r 0 c1t1d0 c1t2d0 " 209 "c1t3d0 c1t4d0\n", prog_name); 210 (void) fprintf(stderr, "%s -d c1t1d0\n", prog_name); 211 (void) fprintf(stderr, "%s -F image 1\n", prog_name); | 246 /* parse command line, and get program name */ 247 if ((prog_namep = strrchr(argv[0], '/')) == NULL) { 248 prog_namep = argv[0]; 249 } else { 250 prog_namep++; 251 } |
212 | 252 |
213 exit(1); 214} | 253 /* close error option messages from getopt */ 254 opterr = 0; |
215 | 255 |
216/* Make errno message more "user friendly" */ 217static void 218raidctl_error(char *str) 219{ 220 switch (errno) { 221 case EINVAL: 222 (void) fprintf(stderr, gettext("Error: " 223 "invalid argument would be returned\n")); | 256 /* get yes expression according to current locale */ 257 yesexpr = strdup(nl_langinfo(YESEXPR)); 258 yesstr = strdup(nl_langinfo(YESSTR)); 259 nostr = strdup(nl_langinfo(NOSTR)); 260 if (yesexpr == NULL || yesstr == NULL || nostr == NULL) { 261 return (FAILURE); 262 } 263 264 /* 265 * If the was no expression or if there is a compile error 266 * use default yes expression. 267 */ 268 status = regcomp(&re, yesexpr, REG_EXTENDED | REG_NOSUB); 269 if ((*yesexpr == (char)NULL) || 270 (*yesstr == (char)NULL) || 271 (*nostr == (char)NULL) || 272 (status != 0)) { 273 SET_DEFAULT_STRS; 274 if (regcomp(&re, default_yesexpr, 275 REG_EXTENDED | REG_NOSUB) != 0) { 276 return (FALSE); 277 } 278 } 279 280 while ((c = getopt(argc, argv, 281 "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) { 282 switch (c) { 283 case 'h': 284 case '?': 285 if (action == FALSE) { 286 findex = DO_HW_RAID_HELP; 287 action = TRUE; 288 options |= LOWER_H; 289 } else { 290 findex = DO_HW_RAID_NOP; 291 } 292 break; 293 case 'C': 294 if (action == FALSE) { 295 findex = DO_HW_RAID_CREATEN; 296 C_argp = optarg; 297 action = TRUE; 298 options |= UPPER_C; 299 } else { 300 findex = DO_HW_RAID_NOP; 301 } 302 break; 303 case 'c': 304 if (action == FALSE) { 305 findex = DO_HW_RAID_CREATEO; 306 action = TRUE; 307 options |= LOWER_C; 308 } else { 309 findex = DO_HW_RAID_NOP; 310 } 311 break; 312 case 'd': 313 if (action == FALSE) { 314 findex = DO_HW_RAID_DELETE; 315 action = TRUE; 316 options |= LOWER_D; 317 } else { 318 findex = DO_HW_RAID_NOP; 319 } 320 break; 321 case 'l': 322 if (action == FALSE) { 323 findex = DO_HW_RAID_LIST; 324 action = TRUE; 325 options |= LOWER_L; 326 } else { 327 findex = DO_HW_RAID_NOP; 328 } 329 break; 330 case 'F': 331 if (action == FALSE) { 332 findex = DO_HW_RAID_FLASH; 333 F_argp = optarg; 334 action = TRUE; 335 options |= UPPER_F; 336 } else { 337 findex = DO_HW_RAID_NOP; 338 } 339 break; 340 case 'a': 341 if (action == FALSE) { 342 findex = DO_HW_RAID_HSP; 343 a_argp = optarg; 344 action = TRUE; 345 options |= LOWER_A; 346 } else { 347 findex = DO_HW_RAID_NOP; 348 } 349 break; 350 case 'p': 351 if (action == FALSE) { 352 findex = DO_HW_RAID_SET_ATTR; 353 p_argp = optarg; 354 action = TRUE; 355 options |= LOWER_P; 356 } else { 357 findex = DO_HW_RAID_NOP; 358 } 359 break; 360 case 'r': 361 r_argp = optarg; 362 r_flag = TRUE; 363 options |= LOWER_R; 364 break; 365 case 'z': 366 z_argp = optarg; 367 options |= LOWER_Z; 368 break; 369 case 'g': 370 g_argp = optarg; 371 options |= LOWER_G; 372 break; 373 case 's': 374 s_argp = optarg; 375 options |= LOWER_S; 376 break; 377 case 'f': 378 f_flag = TRUE; 379 options |= LOWER_F; 380 break; 381 case 'S': 382 if (action == FALSE) { 383 findex = DO_HW_RAID_SNAPSHOT; 384 action = TRUE; 385 options |= UPPER_S; 386 } else { 387 findex = DO_HW_RAID_NOP; 388 } 389 break; 390 default: 391 (void) fprintf(stderr, 392 gettext("Invalid argument(s).\n")); 393 exit_raidctl_lock(fd); 394 FREE_STRS; 395 regfree(&re); 396 return (INVALID_ARG); 397 } 398 } 399 400 /* parse options */ 401 switch (findex) { 402 case DO_HW_RAID_HELP: 403 if ((options & ~(LOWER_H)) != 0) { 404 ret = INVALID_ARG; 405 } else { 406 helpinfo(prog_namep); 407 ret = SUCCESS; 408 } |
224 break; | 409 break; |
225 case EIO: 226 case EFAULT: 227 (void) fprintf(stderr, 228 gettext("Error: Device inaccessible.\n")); | 410 case DO_HW_RAID_CREATEO: 411 if ((options & ~(LOWER_F | LOWER_C | LOWER_R)) != 0) { 412 ret = INVALID_ARG; 413 } else { 414 if (r_flag != FALSE && f_flag == FALSE) { 415 ret = do_create_ctd(r_argp, argv, argc - 4, 416 optind, f_flag); 417 } else if (r_flag == FALSE && f_flag == FALSE) { 418 ret = do_create_ctd(NULL, argv, argc - 2, 419 optind, f_flag); 420 } else if (r_flag != FALSE && f_flag != FALSE) { 421 ret = do_create_ctd(r_argp, argv, argc - 5, 422 optind, f_flag); 423 } else { 424 ret = do_create_ctd(NULL, argv, argc - 3, 425 optind, f_flag); 426 } 427 } |
229 break; | 428 break; |
230 case ENOTTY: 231 (void) fprintf(stderr, gettext("Error: " 232 "Device does not support requested action.\n")); | 429 case DO_HW_RAID_CREATEN: 430 if ((options & ~(LOWER_F | UPPER_C | LOWER_R | LOWER_Z | 431 LOWER_S)) != 0) { 432 ret = INVALID_ARG; 433 } else { 434 ret = do_create_cidl(r_argp, z_argp, C_argp, s_argp, 435 f_flag, argv, optind); 436 } |
233 break; | 437 break; |
438 case DO_HW_RAID_DELETE: 439 if ((options & ~(LOWER_F | LOWER_D)) != 0) { 440 ret = INVALID_ARG; 441 } else { 442 ret = do_delete(f_flag, argv, optind); 443 } 444 break; 445 case DO_HW_RAID_LIST: 446 if ((options & ~(LOWER_L | LOWER_G)) != 0) { 447 ret = INVALID_ARG; 448 } else { 449 ret = do_list(g_argp, argv, optind, FALSE); 450 } 451 break; 452 case DO_HW_RAID_SNAPSHOT: 453 if ((options & ~(UPPER_S | LOWER_G)) != 0) { 454 ret = INVALID_ARG; 455 } else { 456 ret = do_list(g_argp, argv, optind, TRUE); 457 } 458 break; 459 case DO_HW_RAID_FLASH: 460 if ((options & ~(LOWER_F | UPPER_F)) != 0) { 461 ret = INVALID_ARG; 462 } else { 463 if (f_flag == FALSE) { 464 ret = do_flash(f_flag, F_argp, argv, optind, 465 argc - 3); 466 } else { 467 ret = do_flash(f_flag, F_argp, argv, optind, 468 argc - 4); 469 } 470 } 471 break; 472 case DO_HW_RAID_HSP: 473 if ((options & ~(LOWER_A | LOWER_G)) != 0) { 474 ret = INVALID_ARG; 475 } else { 476 ret = do_set_hsp(a_argp, g_argp, argv, optind); 477 } 478 break; 479 case DO_HW_RAID_SET_ATTR: 480 if ((options & ~(LOWER_F | LOWER_P)) != 0) { 481 ret = INVALID_ARG; 482 } else { 483 ret = do_set_array_attr(f_flag, p_argp, argv, optind); 484 } 485 break; 486 case DO_HW_RAID_NOP: 487 if (argc == 1) { 488 ret = do_list(g_argp, argv, optind, FALSE); 489 } else { 490 ret = INVALID_ARG; 491 } 492 break; |
|
234 default: | 493 default: |
235 perror(str); | 494 ret = INVALID_ARG; 495 break; |
236 } | 496 } |
237} | |
238 | 497 |
239static int 240get_link_path(const char *thing, char *buf) 241{ 242 if (readlink(thing, buf, MAXPATHLEN) < 0) 243 return (1); 244 return (0); | 498 if (ret == INVALID_ARG) { 499 (void) fprintf(stderr, 500 gettext("Invalid argument(s).\n")); 501 } 502 exit_raidctl_lock(fd); 503 504 FREE_STRS; 505 regfree(&re); 506 return (ret); |
245} 246 | 507} 508 |
247static int 248get_ctrl_devctl(char *ctrl, char *b) | 509/* 510 * helpinfo(prog_namep) 511 * This function prints help informations for usrs. 512 */ 513static void 514helpinfo(char *prog_namep) |
249{ | 515{ |
250 char devctl_buf[MAXPATHLEN]; 251 char *colon; | 516 char quote = '"'; |
252 | 517 |
253 (void) strlcpy(devctl_buf, ctrl, MAXPATHLEN); | 518 (void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] " 519 "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep, 520 quote, quote); |
254 | 521 |
255 colon = strrchr(devctl_buf, ':'); 256 if (colon == NULL) 257 return (1); | 522 (void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep); |
258 | 523 |
259 *colon = 0; 260 (void) snprintf(devctl_buf, MAXPATHLEN, "%s:devctl", devctl_buf); 261 (void) strlcpy(b, devctl_buf, MAXPATHLEN); 262 return (0); 263} | 524 (void) printf(gettext("%s [-f] -F <filename> <controller1> " 525 "[<controller2> ...]\n"), prog_namep); |
264 | 526 |
265static int 266get_devctl(char *disk, char *b) 267{ 268 char buf1[MAXPATHLEN] = {0}; 269 char devctl_buf[MAXPATHLEN]; 270 char *slash; 271 char devname[32]; | 527 (void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"), 528 prog_namep, quote, quote); |
272 | 529 |
273 if (get_link_path(disk, buf1)) 274 return (1); | 530 (void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> " 531 "[<disk3> ...]\n"), prog_namep); |
275 | 532 |
276 (void) strlcpy(devctl_buf, buf1, MAXPATHLEN); | 533 (void) printf(gettext("%s [-l]\n"), prog_namep); |
277 | 534 |
278 slash = strrchr(devctl_buf, '/'); 279 if (slash == NULL) 280 return (1); | 535 (void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep); |
281 | 536 |
282 *slash = 0; 283 slash = strrchr(devctl_buf, '/'); 284 (void) strlcpy(devname, slash, 32); 285 *slash = 0; | 537 (void) printf(gettext("%s -l <volume>\n"), prog_namep); |
286 | 538 |
287 (void) snprintf(devctl_buf, MAXPATHLEN, "%s%s:devctl", 288 devctl_buf, devname); | 539 (void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"), 540 prog_namep); |
289 | 541 |
290 (void) strlcpy(b, devctl_buf, MAXPATHLEN); | 542 (void) printf(gettext("%s -a {set | unset} -g <disk> " 543 "{<volume> | <controller>}\n"), prog_namep); |
291 | 544 |
292 return (0); 293} | 545 (void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep); |
294 | 546 |
295raidlist_t * 296already_there(int controller) 297{ 298 raidlist_t *curr = raids; | 547 (void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep); |
299 | 548 |
300 while (curr != NULL) { 301 if (curr->controller == controller) 302 return (curr); 303 304 curr = curr->next; 305 } 306 307 return (NULL); | 549 (void) printf(gettext("%s -h\n"), prog_namep); |
308} 309 310/* | 550} 551 552/* |
311 * Display those controllers where RAID volumes were not found | 553 * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep, 554 * f_flag, argv, optind) 555 * This function creates a new RAID volume with specified arguments, 556 * and returns result as SUCCESS, INVALID_ARG or FAILURE. 557 * The "c.id.l" is used to express single physical disk. 'c' expresses 558 * bus number, 'id' expresses target number, and 'l' expresses lun. 559 * The physical disks represented by c.id.l may be invisible to OS, which 560 * means physical disks attached to controllers are not accessible by 561 * OS directly. The disks should be organized as a logical volume, and 562 * the logical volume is exported to OS as a single unit. Some hardware 563 * RAID controllers also support physical disks accessed by OS directly, 564 * for example LSI1068. In this case, it's both OK to express physical 565 * disk by c.id.l format or canonical ctd format. |
312 */ | 566 */ |
313static void 314print_no_raids() | 567static int 568do_create_cidl(char *raid_levelp, char *capacityp, char *disks_argp, 569 char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind) |
315{ | 570{ |
316 int i, space = 0; | 571 uint32_t ctl_tag = MAX32BIT; 572 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 573 uint32_t raid_level = RAID_LEVEL_1; 574 uint64_t capacity = 0; 575 uint64_t stripe_size = (uint64_t)OBJ_ATTR_NONE; 576 raid_obj_handle_t *disk_handlesp = NULL; 577 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 578 raidcfg_controller_t ctl_attr; 579 int comps_num = 0; 580 int ret = 0; |
317 | 581 |
318 if (info_ctrl == NULL) 319 return; | 582 raidcfg_array_t array_attr; |
320 | 583 |
321 for (i = 0; i < ctrl_nums; i++) { 322 /* Status of '0' means RAID exists at that controller */ 323 if (info_ctrl[i][INFO_STATUS] == RAID_FOUND || 324 info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 325 continue; | 584 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 585 return (INVALID_ARG); 586 } |
326 | 587 |
327 if (!space && raids != NULL) { 328 (void) printf("\n"); 329 space = 1; 330 } | 588 if (disks_argp == NULL) { 589 return (INVALID_ARG); 590 } |
331 | 591 |
332 /* switch statement used to enable gettext()'ing of text */ 333 switch (info_ctrl[i][INFO_STATUS]) { 334 case RAID_INVALID_CTRL: 335 (void) printf(gettext("Invalid controller '%d'\n"), 336 info_ctrl[i][INFO_CTRL]); 337 break; 338 case RAID_NOT_SUPPORTED: 339 (void) printf(gettext("No RAID supported " 340 "on controller '%d'\n"), 341 info_ctrl[i][INFO_CTRL]); | 592 /* Check controller tag */ 593 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 594 return (INVALID_ARG); 595 } |
342 | 596 |
343 break; 344 default: 345 (void) printf(gettext("No RAID volumes found on " 346 "controller '%d'\n"), info_ctrl[i][INFO_CTRL]); 347 } | 597 ctl_handle = raidcfg_get_controller(ctl_tag); 598 if (ctl_handle <= 0) { 599 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 600 return (FAILURE); |
348 } | 601 } |
349} | |
350 | 602 |
351static void 352add_raid_to_raidlist(char *ctrl_name, int controller) 353{ 354 raidlist_t *curr; 355 char buf[MAXPATHLEN] = {0}; 356 char buf1[MAXPATHLEN] = {0}; 357 int nvols; 358 int fd; 359 int i; 360 int n; | 603 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 604 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 605 return (FAILURE); 606 } |
361 | 607 |
362 if (readlink(ctrl_name, buf, sizeof (buf)) < 0) 363 return; | 608 /* Get raid level */ 609 if (raid_levelp != NULL) { 610 if (*raid_levelp == '1' && 611 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) { 612 raid_level = RAID_LEVEL_1E; 613 } else { 614 if (is_fully_numeric(raid_levelp) == FALSE) { 615 return (INVALID_ARG); 616 } |
364 | 617 |
365 if (get_ctrl_devctl(buf, buf1)) 366 return; | 618 switch (atoi(raid_levelp)) { 619 case 0: 620 raid_level = RAID_LEVEL_0; 621 break; 622 case 1: 623 raid_level = RAID_LEVEL_1; 624 break; 625 case 5: 626 raid_level = RAID_LEVEL_5; 627 break; 628 case 10: 629 raid_level = RAID_LEVEL_10; 630 break; 631 case 50: 632 raid_level = RAID_LEVEL_50; 633 break; 634 default: 635 return (INVALID_ARG); 636 } 637 } 638 } |
367 368 /* | 639 640 /* |
369 * If "-l" was specified, then only look at those controllers 370 * listed as part of the command line input. | 641 * The rang check of capacity and stripe size is performed in library, 642 * and it relates to hardware feature. |
371 */ | 643 */ |
372 if (info_ctrl != NULL) { 373 for (i = 0; i < ctrl_nums; i++) { 374 if (info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 375 continue; 376 if (controller == info_ctrl[i][INFO_CTRL]) 377 break; | 644 645 /* Capacity in bytes. Capacity 0 means max available space. */ 646 if (capacityp != NULL) { 647 if (*capacityp == '-' || 648 calc_size(capacityp, &capacity) != SUCCESS) { 649 return (INVALID_ARG); |
378 } | 650 } |
379 /* return if we didn't find a controller */ 380 if (i == ctrl_nums) 381 return; | |
382 } 383 | 651 } 652 |
384 fd = open(buf1, O_RDONLY); 385 if (fd == -1) { 386 if (info_ctrl != NULL) 387 info_ctrl[i][INFO_STATUS] = RAID_INVALID_CTRL; 388 return; | 653 /* Stripe size in bytes */ 654 if (stripe_sizep != NULL) { 655 if (calc_size(stripe_sizep, &stripe_size) != SUCCESS || 656 *stripe_sizep == '-') { 657 return (INVALID_ARG); 658 } |
389 } 390 | 659 } 660 |
391 /* 392 * query the HBA driver for volume capacity 393 */ 394 if (ioctl(fd, RAID_NUMVOLUMES, &nvols) < 0) { 395 if (info_ctrl != NULL) 396 info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED; 397 (void) close(fd); 398 return; | 661 /* Open controller before accessing its object */ 662 if ((ret = raidcfg_open_controller(ctl_handle, NULL)) < 0) { 663 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 664 return (FAILURE); |
399 } 400 | 665 } 666 |
401 /* 402 * now iterate through nvols configurations 403 */ 404 for (n = 0; n < nvols; n++) { 405 raid_config_t config; | 667 /* Get disks' handles */ 668 if ((ret = get_disk_handle_cidl(ctl_tag, disks_argp, &comps_num, 669 &disk_handlesp)) != SUCCESS) { 670 (void) raidcfg_close_controller(ctl_handle, NULL); 671 return (ret); 672 } |
406 | 673 |
407 /* use unitid to retrieve this volume */ 408 config.unitid = n; 409 if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 410 if (info_ctrl != NULL) 411 info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED; 412 (void) close(fd); 413 return; | 674 if (f_flag == FALSE) { 675 (void) fprintf(stdout, gettext("Creating RAID volume " 676 "will destroy all data on spare space of member disks, " 677 "proceed (%s/%s)? "), yesstr, nostr); 678 if (!yes()) { 679 (void) fprintf(stdout, gettext("RAID volume " 680 "not created.\n\n")); 681 (void) raidcfg_close_controller(ctl_handle, NULL); 682 free(disk_handlesp); 683 return (SUCCESS); |
414 } | 684 } |
685 } |
|
415 | 686 |
416 /* if ndisks is 0, this volume is not configured */ 417 if (config.ndisks == 0) 418 continue; | 687 /* Create array */ 688 array_handle = raidcfg_create_array(comps_num, 689 disk_handlesp, raid_level, capacity, stripe_size, NULL); |
419 | 690 |
420 /* otherwise, we have a raid volume */ 421 if (info_ctrl != NULL) 422 info_ctrl[i][INFO_STATUS] = RAID_FOUND; | 691 if (array_handle <= 0) { 692 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 693 free(disk_handlesp); 694 (void) raidcfg_close_controller(ctl_handle, NULL); 695 return (FAILURE); 696 } |
423 | 697 |
424 /* 425 * if raids has not been initialized, then do so. 426 * otherwise, see if this controller is in raids. 427 * if it is not, add it. then, add this volume to 428 * the raidlist 429 */ 430 if (raids == NULL) { 431 raids = (raidlist_t *)malloc(sizeof (raidlist_t)); 432 curr = raids; 433 } else { 434 if ((curr = already_there(controller)) != NULL) 435 goto already_there; | 698 /* Get attribute of the new created array */ 699 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 700 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 701 free(disk_handlesp); 702 (void) raidcfg_close_controller(ctl_handle, NULL); 703 return (FAILURE); 704 } |
436 | 705 |
437 curr = raids; | 706 (void) fprintf(stdout, gettext("Volume c%ut%llud%llu is created " 707 "successfully!\n"), ctl_tag, array_attr.tag.idl.target_id, 708 array_attr.tag.idl.lun); |
438 | 709 |
439 /* add this controller to raids */ 440 while (curr->next != NULL) 441 curr = curr->next; | 710 /* Print attribute of array */ 711 (void) print_array_table(ctl_handle, array_handle); |
442 | 712 |
443 curr->next = (raidlist_t *)malloc(sizeof (raidlist_t)); 444 curr = curr->next; 445 } | 713 /* Close controller */ 714 (void) raidcfg_close_controller(ctl_handle, NULL); |
446 | 715 |
447already_there: 448 /* 449 * curr is now pointing to this controller. since we are 450 * adding controllers one at a time from do_search(), set 451 * curr->next to NULL so that we know where the end of our 452 * currently added controllers lies. 453 */ 454 curr->next = NULL; 455 curr->controller = controller; 456 (void) strlcpy(curr->devctl, buf1, sizeof (curr->devctl)); 457 (void) fflush(stdout); 458 (void) memcpy(&curr->raid_config[n], &config, 459 (sizeof (raid_config_t))); 460 } 461 462 if (info_ctrl != NULL && info_ctrl[i][INFO_STATUS] != RAID_FOUND) 463 info_ctrl[i][INFO_STATUS] = RAID_NOT_FOUND; | 716 free(disk_handlesp); 717 return (SUCCESS); |
464} 465 | 718} 719 |
466static void 467print_header() | 720/* 721 * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag) 722 * This function creates array with specified arguments, and return result 723 * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller 724 * to be compatible with old raidctl. The capacity and stripe size can't 725 * be specified for LSI MPT controller, and they use zero and default value. 726 * The "ctd" is the canonical expression of physical disks which are 727 * accessible by OS. 728 */ 729static int 730do_create_ctd(char *raid_levelp, char **disks_argpp, uint32_t disks_num, 731 uint32_t argindex, uint32_t f_flag) |
468{ | 732{ |
469 (void) printf(gettext("RAID\tVolume\tRAID\t\tRAID\t\tDisk")); 470 (void) printf("\n"); 471 (void) printf(gettext("Volume\tType\tStatus\t\tDisk\t\tStatus")); 472 (void) printf("\n"); 473 (void) printf("------------------------------------------------------"); 474 (void) printf("\n"); 475} | 733 uint32_t ctl_tag = MAX32BIT; 734 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 735 uint32_t raid_level = RAID_LEVEL_1; 736 uint64_t capacity = 0; 737 uint32_t stripe_size = (uint32_t)OBJ_ATTR_NONE; 738 raid_obj_handle_t *disk_handlesp = NULL; 739 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 740 raidcfg_controller_t ctl_attr; 741 int ret; |
476 | 742 |
477static void 478print_raidconfig(int c, raid_config_t config) 479{ 480 int i; 481 char voltype[8]; | 743 raidcfg_array_t array_attr; 744 int i, j; |
482 | 745 |
483 /* print RAID volume target ID and volume type */ 484 if (config.raid_level == RAID_STRIPE) { 485 (void) snprintf(voltype, sizeof (voltype), "IS"); 486 } else if (config.raid_level == RAID_MIRROR) { 487 (void) snprintf(voltype, sizeof (voltype), "IM"); | 746 /* Check disks parameter */ 747 if (disks_argpp == NULL || disks_num < 2) { 748 return (INVALID_ARG); |
488 } 489 | 749 } 750 |
490 (void) printf("c%dt%dd0\t%s\t", c, config.targetid, voltype); 491 492 /* Get RAID Info */ 493 if (config.flags & RAID_FLAG_RESYNCING && 494 config.state == RAID_STATE_DEGRADED) { 495 (void) printf(gettext("RESYNCING\t")); 496 } else if (config.state == RAID_STATE_DEGRADED) { 497 (void) printf(gettext("DEGRADED\t")); 498 } else if (config.state == RAID_STATE_OPTIMAL) { 499 (void) printf(gettext("OK\t\t")); 500 } else if (config.state == RAID_STATE_FAILED) { 501 (void) printf(gettext("FAILED\t\t")); 502 } else { 503 (void) printf(gettext("ERROR\t\t")); | 751 for (i = 0, j = argindex; i < disks_num; i++, j++) { 752 if (disks_argpp[j] == NULL) { 753 return (INVALID_ARG); 754 } |
504 } 505 | 755 } 756 |
506 /* Get RAID Disks */ 507 if (config.disk[0] != 0xff) 508 (void) printf("c%dt%dd0\t\t", c, config.disk[0]); 509 else 510 (void) printf("-\t\t"); | 757 /* 758 * We need check if the raid_level string is fully numeric. If user 759 * input string with unsupported letters, such as "s10", atoi() will 760 * return zero because it is an illegal string, but it doesn't mean 761 * RAID_LEVEL_0. 762 */ 763 if (raid_levelp != NULL) { 764 if (*raid_levelp == '1' && 765 (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) { 766 raid_level = RAID_LEVEL_1E; 767 } else { 768 if (is_fully_numeric(raid_levelp) == FALSE) { 769 return (INVALID_ARG); 770 } |
511 | 771 |
512 /* Get RAID Disk's Status */ 513 if (config.diskstatus[0] & RAID_DISKSTATUS_FAILED) { 514 (void) printf(gettext("FAILED\n")); 515 } else if (config.diskstatus[0] & RAID_DISKSTATUS_MISSING) { 516 (void) printf(gettext("MISSING\n")); 517 } else { 518 (void) printf(gettext("OK\n")); | 772 switch (atoi(raid_levelp)) { 773 case 0: 774 raid_level = RAID_LEVEL_0; 775 break; 776 case 1: 777 raid_level = RAID_LEVEL_1; 778 break; 779 case 5: 780 raid_level = RAID_LEVEL_5; 781 break; 782 default: 783 return (INVALID_ARG); 784 } 785 } |
519 } 520 | 786 } 787 |
521 for (i = 1; i < config.ndisks; i++) { 522 if (config.disk[i] != 0xff) 523 (void) printf("\t\t\t\tc%dt%dd0\t\t", c, 524 config.disk[i]); 525 else 526 (void) printf("\t\t\t\t-\t\t"); 527 528 if (config.diskstatus[i] & RAID_DISKSTATUS_FAILED) { 529 (void) printf(gettext("FAILED\n")); 530 } else if (config.diskstatus[i] & RAID_DISKSTATUS_MISSING) { 531 (void) printf(gettext("MISSING\n")); 532 } else { 533 (void) printf(gettext("OK\n")); 534 } | 788 /* Get disks tag and controller tag */ 789 disk_handlesp = (raid_obj_handle_t *)calloc(disks_num + 2, 790 sizeof (raid_obj_handle_t)); 791 if (disk_handlesp == NULL) { 792 return (FAILURE); |
535 } | 793 } |
536} | |
537 | 794 |
538static void 539print_disklist() 540{ 541 raidlist_t *curr = raids; 542 int i; | 795 disk_handlesp[0] = OBJ_SEPARATOR_BEGIN; 796 disk_handlesp[disks_num + 1] = OBJ_SEPARATOR_END; |
543 | 797 |
544 while (curr != NULL) { 545 for (i = 0; i < N_RAIDVOLS; i++) { 546 if (curr->raid_config[i].ndisks != 0) { 547 print_raidconfig(curr->controller, 548 curr->raid_config[i]); 549 } 550 } 551 curr = curr->next; | 798 if ((ret = get_disk_handle_ctd(disks_num, &disks_argpp[argindex], 799 &ctl_tag, &disk_handlesp[1])) != SUCCESS) { 800 free(disk_handlesp); 801 return (ret); |
552 } | 802 } |
553} | |
554 | 803 |
555static void 556free_disklist() 557{ 558 raidlist_t *curr = raids; | 804 /* LIB API should check whether all disks here belong to one ctl. */ 805 /* get_disk_handle_ctd has opened controller. */ 806 ctl_handle = raidcfg_get_controller(ctl_tag); |
559 | 807 |
560 while (curr != NULL) { 561 raidlist_t *temp; 562 temp = curr; 563 curr = curr->next; 564 free(temp); | 808 if (ctl_handle <= 0) { 809 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 810 (void) raidcfg_close_controller(ctl_handle, NULL); 811 free(disk_handlesp); 812 return (FAILURE); |
565 } | 813 } |
566} | |
567 | 814 |
568static void 569do_search() 570{ 571 DIR *dir; 572 struct dirent *dp; 573 char buf[MAXPATHLEN]; 574 int c; 575 int i, j; 576 577 /* 578 * In case repeated numbers were found, assign the repititions as 579 * RAID_DONT_USE 580 */ 581 for (i = 0; i < ctrl_nums; i++) { 582 int first_one = 1; 583 for (j = 0; j < ctrl_nums; j++) { 584 if (info_ctrl[i][INFO_CTRL] == 585 info_ctrl[j][INFO_CTRL]) { 586 if (info_ctrl[j][INFO_STATUS] == RAID_DONT_USE) 587 continue; 588 if (first_one) { 589 first_one = 0; 590 } else { 591 info_ctrl[j][INFO_STATUS] = 592 RAID_DONT_USE; 593 } 594 } 595 } | 815 /* Check if the controller is host raid type */ 816 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 817 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 818 (void) raidcfg_close_controller(ctl_handle, NULL); 819 free(disk_handlesp); 820 return (FAILURE); |
596 } 597 | 821 } 822 |
598 if ((dir = opendir("/dev/cfg")) == NULL) { | 823 if ((ctl_attr.capability & RAID_CAP_DISK_TRANS) == 0) { 824 /* -c only support host raid controller, return failure here */ |
599 (void) fprintf(stderr, | 825 (void) fprintf(stderr, |
600 gettext("Cannot open /dev/cfg: %s\n"), strerror(errno)); 601 return; | 826 gettext("Option -c only supports host raid controller.\n")); 827 (void) raidcfg_close_controller(ctl_handle, NULL); 828 free(disk_handlesp); 829 return (FAILURE); |
602 } | 830 } |
831 832 if (f_flag == FALSE) { 833 (void) fprintf(stdout, gettext("Creating RAID volume " 834 "will destroy all data on spare space of member disks, " 835 "proceed (%s/%s)? "), yesstr, nostr); 836 if (!yes()) { 837 (void) fprintf(stdout, gettext("RAID volume " 838 "not created.\n\n")); 839 free(disk_handlesp); 840 (void) raidcfg_close_controller(ctl_handle, NULL); 841 return (SUCCESS); 842 } 843 } 844 |
|
603 /* | 845 /* |
604 * iterate over the controllers and add any 605 * controllers with RAID volumes to the raids 606 * list, one at a time | 846 * For old raidctl, capacity is 0, which means to creates 847 * max possible capacity of array. |
607 */ | 848 */ |
608 while ((dp = readdir(dir)) != NULL) { 609 if (strcmp(dp->d_name, ".") == 0 || 610 strcmp(dp->d_name, "..") == 0) 611 continue; 612 if (sscanf(dp->d_name, "c%d", &c) != 1) 613 continue; 614 (void) snprintf(buf, sizeof (buf), "/dev/cfg/%s", dp->d_name); 615 add_raid_to_raidlist(buf, c); 616 } 617 (void) closedir(dir); 618} | |
619 | 849 |
620/* 621 * do_info() will do the following: 622 * - create a list of disks' devctls 623 * - try to talk to each of the devctls found 624 * - if raid configuration is found, display it. 625 */ 626static void 627do_info() 628{ 629 int i; 630 (void) chdir(DEVDIR); | 850 array_handle = raidcfg_create_array(disks_num + 2, 851 disk_handlesp, raid_level, capacity, stripe_size, NULL); |
631 | 852 |
632 do_search(); 633 634 if (raids == NULL) { 635 if (info_ctrl != NULL) { 636 print_no_raids(); 637 for (i = 0; i < ctrl_nums; i++) 638 free(info_ctrl[i]); 639 free(info_ctrl); 640 } else { 641 (void) printf(gettext("No RAID volumes found\n")); 642 } 643 return; | 853 if (array_handle <= 0) { 854 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 855 free(disk_handlesp); 856 (void) raidcfg_close_controller(ctl_handle, NULL); 857 return (FAILURE); |
644 } 645 | 858 } 859 |
646 print_header(); 647 print_disklist(); 648 print_no_raids(); 649 free_disklist(); 650 if (info_ctrl) { 651 for (i = 0; i < ctrl_nums; i++) 652 free(info_ctrl[i]); 653 free(info_ctrl); | 860 /* Get attribute of array */ 861 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 862 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 863 free(disk_handlesp); 864 (void) raidcfg_close_controller(ctl_handle, NULL); 865 return (FAILURE); |
654 } | 866 } |
867 868 /* Close controller */ 869 (void) raidcfg_close_controller(ctl_handle, NULL); 870 871 /* Print feedback for user */ 872 (void) fprintf(stdout, 873 gettext("Volume c%ut%llud%llu is created successfully!\n"), 874 ctl_tag, array_attr.tag.idl.target_id, 875 array_attr.tag.idl.lun); 876 free(disk_handlesp); 877 return (SUCCESS); |
|
655} 656 | 878} 879 |
880/* 881 * do_list(disk_arg, argv, optind, is_snapshot) 882 * This function lists RAID's system configuration. It supports various RAID 883 * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG. 884 */ |
|
657static int | 885static int |
658disk_in_raid(int c, int t) | 886do_list(char *disk_argp, char **argv, uint32_t optind, uint8_t is_snapshot) |
659{ | 887{ |
660 raidlist_t *curr; 661 raid_config_t raid; 662 int i, j, n; | 888 uint32_t ctl_tag = MAX32BIT; 889 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 890 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 891 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 892 disk_tag_t disk_tag; 893 array_tag_t array_tag; |
663 | 894 |
664 do_search(); 665 curr = raids; | 895 int ret; |
666 | 896 |
667 while (curr != NULL) { 668 if (curr->controller == c) { 669 for (i = 0; i < N_RAIDVOLS; i++) { 670 raid = curr->raid_config[i]; 671 if ((n = raid.ndisks) != 0) { 672 for (j = 0; j < n; j++) { 673 if (raid.disk[j] == t) { 674 return (1); 675 } | 897 /* print RAID system */ 898 if (disk_argp == NULL) { 899 if (argv[optind] == NULL) { 900 ret = snapshot_raidsystem(TRUE, 0, is_snapshot); 901 return (ret); 902 } else { 903 if (is_fully_numeric(argv[optind]) == TRUE) { 904 while (argv[optind] != NULL) { 905 if (get_ctl_tag(argv[optind], &ctl_tag) 906 != SUCCESS) { 907 ret = INVALID_ARG; 908 optind++; 909 continue; |
676 } | 910 } |
911 ctl_handle = 912 raidcfg_get_controller(ctl_tag); 913 if (ctl_handle <= 0) { 914 (void) fprintf(stderr, "%s\n", 915 raidcfg_errstr(ctl_handle)); 916 ret = FAILURE; 917 optind++; 918 continue; 919 } 920 ret = 921 raidcfg_open_controller(ctl_handle, 922 NULL); 923 if (ret < 0) { 924 (void) fprintf(stderr, "%s\n", 925 raidcfg_errstr(ret)); 926 ret = FAILURE; 927 optind++; 928 continue; 929 } 930 if (is_snapshot == FALSE) { 931 ret = 932 print_ctl_table(ctl_handle); 933 } else { 934 ret = 935 snapshot_ctl(ctl_handle, 936 FALSE, 0, is_snapshot); 937 } 938 (void) raidcfg_close_controller( 939 ctl_handle, NULL); 940 optind++; |
|
677 } | 941 } |
942 } else { 943 if (get_array_tag(argv[optind], 944 &ctl_tag, &array_tag) != SUCCESS) { 945 return (INVALID_ARG); 946 } 947 ctl_handle = raidcfg_get_controller(ctl_tag); 948 if (ctl_handle <= 0) { 949 (void) fprintf(stderr, "%s\n", 950 raidcfg_errstr(ctl_handle)); 951 return (FAILURE); 952 } 953 954 ret = raidcfg_open_controller(ctl_handle, NULL); 955 if (ret < 0) { 956 (void) fprintf(stderr, "%s\n", 957 raidcfg_errstr(ret)); 958 return (FAILURE); 959 } 960 961 array_handle = raidcfg_get_array(ctl_handle, 962 array_tag.idl.target_id, array_tag.idl.lun); 963 if (array_handle <= 0) { 964 (void) fprintf(stderr, "%s\n", 965 raidcfg_errstr(array_handle)); 966 (void) raidcfg_close_controller( 967 ctl_handle, NULL); 968 return (FAILURE); 969 } 970 if (is_snapshot == FALSE) { 971 ret = print_array_table(ctl_handle, 972 array_handle); 973 } else { 974 ret = snapshot_array(array_handle, 0, 975 FALSE, is_snapshot); 976 } 977 (void) raidcfg_close_controller( 978 ctl_handle, NULL); |
|
678 } 679 } | 979 } 980 } |
680 curr = curr->next; | 981 } else { 982 if (argv[optind + 1] != NULL) { 983 return (INVALID_ARG); 984 } 985 986 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 987 return (INVALID_ARG); 988 } 989 990 ctl_handle = raidcfg_get_controller(ctl_tag); 991 if (ctl_handle <= 0) { 992 (void) fprintf(stderr, "%s\n", 993 raidcfg_errstr(ctl_handle)); 994 return (FAILURE); 995 } 996 997 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 998 return (INVALID_ARG); 999 } 1000 1001 ret = raidcfg_open_controller(ctl_handle, NULL); 1002 if (ret < 0) { 1003 (void) fprintf(stderr, "%s\n", 1004 raidcfg_errstr(ret)); 1005 return (FAILURE); 1006 } 1007 1008 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1009 if (disk_handle <= 0) { 1010 (void) fprintf(stderr, "%s\n", 1011 raidcfg_errstr(disk_handle)); 1012 (void) raidcfg_close_controller(ctl_handle, NULL); 1013 return (FAILURE); 1014 } 1015 1016 if (is_snapshot == FALSE) { 1017 ret = print_disk_table(ctl_handle, disk_handle); 1018 } else { 1019 ret = snapshot_disk(ctl_tag, disk_handle, 0, 1020 is_snapshot); 1021 } 1022 (void) raidcfg_close_controller(ctl_handle, NULL); |
681 } | 1023 } |
682 return (0); | 1024 return (ret); |
683} 684 | 1025} 1026 |
1027/* 1028 * do_delete(f_flag, argv, optind) 1029 * This function deletes a specified array, and return result as SUCCESS, 1030 * FAILURE or INVALID_ARG. 1031 */ |
|
685static int | 1032static int |
686disk_there(int c, int t) | 1033do_delete(uint32_t f_flag, char **argv, uint32_t optind) |
687{ | 1034{ |
688 char disk[100]; 689 int fd; | 1035 uint32_t ctl_tag; 1036 char *array_argp; 1037 array_tag_t array_tag; 1038 raid_obj_handle_t ctl_handle; 1039 raid_obj_handle_t array_handle; 1040 int ret; |
690 | 1041 |
691 (void) snprintf(disk, sizeof (disk), "c%dt%dd0s2", c, t); | 1042 array_argp = argv[optind]; 1043 if (array_argp == NULL || argv[optind + 1] != NULL) { 1044 return (INVALID_ARG); 1045 } |
692 | 1046 |
693 fd = open(disk, O_RDWR | O_NDELAY); 694 if (fd == -1) { 695 return (-1); | 1047 if (get_array_tag(array_argp, &ctl_tag, &array_tag) != SUCCESS) { 1048 return (INVALID_ARG); |
696 } 697 | 1049 } 1050 |
698 (void) close(fd); 699 return (0); 700} | 1051 ctl_handle = raidcfg_get_controller(ctl_tag); 1052 if (ctl_handle <= 0) { 1053 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); 1054 return (INVALID_ARG); 1055 } |
701 | 1056 |
702static int 703get_controller(char *dev) 704{ 705 raidlist_t *curr; 706 int c; 707 do_search(); 708 curr = raids; 709 while (curr != NULL) { 710 if (strcmp(curr->devctl, dev) == 0) { 711 c = curr->controller; 712 break; | 1057 ret = raidcfg_open_controller(ctl_handle, NULL); 1058 if (ret < 0) { 1059 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1060 return (FAILURE); 1061 } 1062 1063 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id, 1064 array_tag.idl.lun); 1065 if (array_handle <= 0) { 1066 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); 1067 (void) raidcfg_close_controller(ctl_handle, NULL); 1068 return (FAILURE); 1069 } 1070 1071 if (f_flag == FALSE) { 1072 (void) fprintf(stdout, gettext("Deleting RAID volume " 1073 "%s will destroy all data it contains, " 1074 "proceed (%s/%s)? "), array_argp, yesstr, nostr); 1075 if (!yes()) { 1076 (void) fprintf(stdout, gettext("RAID Volume " 1077 "%s not deleted.\n\n"), array_argp); 1078 (void) raidcfg_close_controller(ctl_handle, NULL); 1079 return (SUCCESS); |
713 } | 1080 } |
714 curr = curr->next; | |
715 } 716 | 1081 } 1082 |
717 free_disklist(); 718 return (c); 719} | |
720 | 1083 |
721static int 722disk_mounted(char *d) 723{ 724 struct mnttab mt; 725 FILE *f = fopen("/etc/mnttab", "r"); | 1084 if ((ret = raidcfg_delete_array(array_handle, NULL)) < 0) { 1085 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1086 (void) raidcfg_close_controller(ctl_handle, NULL); 1087 return (FAILURE); 1088 } |
726 | 1089 |
727 while (getmntent(f, &mt) != EOF) 728 if (strstr(mt.mnt_special, d) != NULL) 729 return (1); | 1090 (void) fprintf(stdout, gettext("Volume %s is deleted successfully!\n"), 1091 array_argp); 1092 (void) raidcfg_close_controller(ctl_handle, NULL); |
730 | 1093 |
731 return (0); | 1094 return (SUCCESS); |
732} 733 | 1095} 1096 |
1097/* 1098 * do_flash(f_flag, filep, ctls_argpp, index, ctl_num) 1099 * This function downloads and updates firmware for specified controller, and 1100 * return result as SUCCESS, FAILURE or INVALID_ARG. 1101 */ |
|
734static int | 1102static int |
735disk_big_enough(char **d, diskaddr_t *cap, int *errcond) | 1103do_flash(uint8_t f_flag, char *filep, char **ctls_argpp, 1104 uint32_t index, uint32_t ctl_num) |
736{ | 1105{ |
737 struct dk_minfo minfo; 738 char disk[N_DISKS][MAXPATHLEN]; 739 uint_t disk_lbsize[N_DISKS]; 740 diskaddr_t disk_capacity[N_DISKS]; 741 int i, fd; | 1106 uint32_t ctl_tag = MAX32BIT; 1107 char *ctl_argp = NULL; 1108 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1109 int ret; 1110 int i, j; |
742 | 1111 |
743 for (i = 0; i < N_DISKS; i++) { 744 if (d[i] == NULL) 745 break; | 1112 if (ctl_num == 0) 1113 return (INVALID_ARG); |
746 | 1114 |
747 (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 748 fd = open(disk[i], O_RDWR | O_NDELAY); 749 if (fd == -1) | 1115 for (i = 0, j = index; i < ctl_num; i++, j++) { 1116 ctl_argp = ctls_argpp[j]; 1117 if (get_ctl_tag(ctl_argp, &ctl_tag) != SUCCESS) { 1118 return (INVALID_ARG); 1119 } 1120 1121 /* Ask user to confirm operation. */ 1122 if (f_flag == FALSE) { 1123 (void) fprintf(stdout, gettext("Update flash image on " 1124 "controller %d (%s/%s)? "), ctl_tag, yesstr, nostr); 1125 if (!yes()) { 1126 (void) fprintf(stdout, 1127 gettext("Controller %d not " 1128 "flashed.\n\n"), ctl_tag); 1129 return (SUCCESS); 1130 } 1131 } 1132 1133 if ((ctl_handle = raidcfg_get_controller(ctl_tag)) < 0) { 1134 (void) fprintf(stderr, "%s\n", 1135 raidcfg_errstr(ctl_handle)); |
750 return (FAILURE); | 1136 return (FAILURE); |
751 if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == -1) { 752 (void) close(fd); | 1137 } 1138 1139 ret = raidcfg_open_controller(ctl_handle, NULL); 1140 if (ret < 0) { 1141 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); |
753 return (FAILURE); 754 } 755 | 1142 return (FAILURE); 1143 } 1144 |
756 disk_lbsize[i] = minfo.dki_lbsize; 757 disk_capacity[i] = minfo.dki_capacity; | 1145 (void) fprintf(stdout, gettext("Start updating controller " 1146 "c%u firmware....\n"), ctl_tag); |
758 | 1147 |
759 /* lbsize must be the same on all disks */ 760 if (disk_lbsize[0] != disk_lbsize[i]) { 761 *errcond = 2; 762 return (INVALID_ARG); | 1148 if ((ret = raidcfg_update_fw(ctl_handle, filep, NULL)) < 0) { 1149 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1150 (void) raidcfg_close_controller(ctl_handle, NULL); 1151 return (FAILURE); |
763 } 764 | 1152 } 1153 |
765 /* ensure drive capacity is greater than or equal to first */ 766 if (disk_capacity[0] > disk_capacity[i]) { 767 *errcond = 1; 768 return (INVALID_ARG); 769 } 770 (void) close(fd); | 1154 (void) fprintf(stdout, gettext("Update controller " 1155 "c%u firmware successfully.\n"), ctl_tag); 1156 1157 (void) raidcfg_close_controller(ctl_handle, NULL); |
771 } 772 | 1158 } 1159 |
773 /* 774 * setting capacity as the dk_minfo.dki_capacity of d[0] 775 * this is the number of dki_lbsize blocks on disk 776 */ 777 *cap = disk_capacity[0]; | |
778 return (SUCCESS); 779} 780 | 1160 return (SUCCESS); 1161} 1162 |
1163/* 1164 * do_set_hsp(a_argp, disk_argp, argv, optind) 1165 * This function set or unset HSP relationship between disk and controller/ 1166 * array, and return result as SUCCESS, FAILURE or INVALID_ARG. 1167 */ |
|
781static int | 1168static int |
782do_config_change_state(cfga_cmd_t cmd, int d, int c) | 1169do_set_hsp(char *a_argp, char *disk_argp, char **argv, uint32_t optind) |
783{ | 1170{ |
784 cfga_err_t cfga_err; 785 char *ap_id; 786 int rv = SUCCESS; 787 int count = 0; | 1171 uint32_t flag = MAX32BIT; 1172 uint32_t ctl_tag = MAX32BIT; 1173 array_tag_t array_tag; 1174 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1175 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 1176 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1177 raidcfg_controller_t ctl_attr; 1178 disk_tag_t disk_tag; |
788 | 1179 |
789 ap_id = (char *)malloc(100); 790 if (ap_id == NULL) 791 return (FAILURE); | 1180 int ret; 1181 int hsp_type; 1182 raidcfg_hsp_relation_t hsp_relation; |
792 | 1183 |
793 (void) snprintf(ap_id, 100, "c%d::dsk/c%dt%dd0", c, c, d); | 1184 (void) memset(&hsp_relation, 0, sizeof (raidcfg_hsp_relation_t)); |
794 | 1185 |
795 /* 796 * If the config_change_state() funcation fails, we want to 797 * retry. If the retry fails, then we return failure to fail. 798 * 799 * If we fail: 800 * 801 * If we were called from create, then we fail the raid 802 * creation. 803 * 804 * If we were called from delete, then the disk will not 805 * be re-configured by raidctl. 806 */ 807 do { 808 cfga_err = config_change_state(cmd, 1, &ap_id, NULL, 809 NULL, NULL, NULL, 0); 810 count++; 811 } while (cfga_err != CFGA_OK && count < 2); | 1186 if (a_argp == NULL) { 1187 return (INVALID_ARG); 1188 } |
812 | 1189 |
813 if (cfga_err != CFGA_OK) 814 rv = FAILURE; | 1190 if (strcmp(a_argp, "set") == 0) { 1191 flag = HSP_SET; 1192 } else if (strcmp(a_argp, "unset") == 0) { 1193 flag = HSP_UNSET; 1194 } else { 1195 return (INVALID_ARG); 1196 } |
815 | 1197 |
816 free(ap_id); 817 return (rv); 818} | 1198 if (disk_argp == NULL) { 1199 return (INVALID_ARG); 1200 } |
819 | 1201 |
820static int 821do_create(char **d, int rlevel, int force) 822{ 823 raid_config_t config; 824 raid_config_t newvol; 825 char disk[N_DISKS][MAXPATHLEN] = {0}; 826 int map[N_DISKS]; 827 char channel1[MAXPATHLEN]; 828 char channel2[MAXPATHLEN]; 829 diskaddr_t capacity; 830 int fd, fd2, size, errcond; 831 int c[N_DISKS]; 832 int t[N_DISKS]; 833 char *tmp; 834 int loc, i, devid, n, ndisks = 0; | 1202 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 1203 return (INVALID_ARG); 1204 } else if (is_fully_numeric(argv[optind]) == TRUE) { 1205 /* Global HSP */ 1206 hsp_type = 0; 1207 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 1208 return (INVALID_ARG); 1209 } |
835 | 1210 |
836 (void) chdir(DEVDIR); | 1211 if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) { 1212 return (INVALID_ARG); 1213 } |
837 | 1214 |
838 /* initialize target map */ 839 for (i = 0; i < N_DISKS; i++) 840 map[i] = -1; | 1215 ctl_handle = raidcfg_get_controller(ctl_tag); 1216 if (ctl_handle <= 0) { 1217 (void) fprintf(stderr, "%s\n", 1218 raidcfg_errstr(ctl_handle)); 1219 return (FAILURE); 1220 } |
841 | 1221 |
842 for (i = 0; i < N_DISKS; i++) { 843 if (d[i] == NULL) 844 break; | 1222 ret = raidcfg_open_controller(ctl_handle, NULL); 1223 if (ret < 0) { 1224 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1225 return (FAILURE); 1226 } |
845 | 1227 |
846 if ((sscanf(d[i], "c%dt%dd0", &c[i], &t[i])) != 2 || 847 t[i] < 0) { 848 (void) fprintf(stderr, 849 gettext("Invalid disk format.\n")); | 1228 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1229 if (disk_handle <= 0) { 1230 (void) fprintf(stderr, "%s\n", 1231 raidcfg_errstr(disk_handle)); 1232 (void) raidcfg_close_controller(ctl_handle, NULL); 1233 return (FAILURE); 1234 } 1235 } else { 1236 /* Local HSP */ 1237 hsp_type = 1; 1238 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != 1239 SUCCESS) { |
850 return (INVALID_ARG); 851 } 852 | 1240 return (INVALID_ARG); 1241 } 1242 |
853 /* ensure that all disks are on the same controller, */ 854 if (c[i] != c[0]) { 855 (void) fprintf(stderr, gettext("Disks must be " 856 "on the same controller.\n")); 857 return (INVALID_ARG); | 1243 /* Open controller */ 1244 ctl_handle = raidcfg_get_controller(ctl_tag); 1245 if (ctl_handle <= 0) { 1246 (void) fprintf(stderr, "%s\n", 1247 raidcfg_errstr(ctl_handle)); 1248 return (FAILURE); |
858 } 859 | 1249 } 1250 |
860 /* that all disks are online, */ 861 if (disk_there(c[0], t[i])) { 862 (void) printf(gettext("Disk 'c%dt%dd0' is not " 863 "present.\n"), c[0], t[i]); 864 (void) printf(gettext("Cannot create RAID volume.\n")); | 1251 ret = raidcfg_open_controller(ctl_handle, NULL); 1252 if (ret < 0) { 1253 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1254 return (FAILURE); 1255 } 1256 1257 /* Get controller's attribute */ 1258 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1259 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1260 (void) raidcfg_close_controller(ctl_handle, NULL); 1261 return (FAILURE); 1262 } 1263 1264 if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) { 1265 (void) raidcfg_close_controller(ctl_handle, NULL); |
865 return (INVALID_ARG); 866 } 867 | 1266 return (INVALID_ARG); 1267 } 1268 |
868 /* that there are no duplicate disks, */ 869 loc = t[i]; 870 if (map[loc] == -1) { 871 map[loc] = t[i]; | 1269 /* Get disk handle */ 1270 disk_handle = raidcfg_get_disk(ctl_handle, disk_tag); 1271 if (disk_handle <= 0) { 1272 (void) fprintf(stderr, "%s\n", 1273 raidcfg_errstr(disk_handle)); 1274 (void) raidcfg_close_controller(ctl_handle, NULL); 1275 return (FAILURE); 1276 } 1277 1278 /* Get array handle */ 1279 array_handle = raidcfg_get_array(ctl_handle, 1280 array_tag.idl.target_id, array_tag.idl.lun); 1281 if (array_handle <= 0) { 1282 (void) fprintf(stderr, "%s\n", 1283 raidcfg_errstr(array_handle)); 1284 (void) raidcfg_close_controller(ctl_handle, NULL); 1285 return (FAILURE); 1286 } 1287 } 1288 1289 hsp_relation.disk_handle = disk_handle; 1290 if (hsp_type) { 1291 /* Set or unset local HSP */ 1292 hsp_relation.array_handle = array_handle; 1293 } else { 1294 /* Set or unset global HSP */ 1295 hsp_relation.array_handle = OBJ_ATTR_NONE; 1296 } 1297 1298 /* Perform operation of set or unset */ 1299 if (flag == HSP_SET) { 1300 if ((ret = raidcfg_set_hsp(1, &hsp_relation, NULL)) < 0) { 1301 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1302 (void) raidcfg_close_controller(ctl_handle, NULL); 1303 return (FAILURE); 1304 } 1305 1306 if (hsp_type) { 1307 (void) printf(gettext("Set local HSP between disk %s " 1308 "and RAID volume %s successfully.\n"), 1309 disk_argp, argv[optind]); |
872 } else { | 1310 } else { |
873 (void) fprintf(stderr, 874 gettext("Disks must be different.\n")); 875 return (INVALID_ARG); | 1311 (void) printf(gettext("Set global HSP between disk %s " 1312 "and controller %s successfully.\n"), 1313 disk_argp, argv[optind]); |
876 } | 1314 } |
1315 } else { 1316 if ((ret = raidcfg_unset_hsp(1, &hsp_relation, NULL)) < 0) { 1317 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1318 (void) raidcfg_close_controller(ctl_handle, NULL); 1319 return (FAILURE); 1320 } |
|
877 | 1321 |
878 /* that no disk is already in use by another volume, */ 879 if (disk_in_raid(c[0], t[i])) { 880 (void) fprintf(stderr, gettext("Disk %s is already in " 881 "a RAID volume.\n"), d[i]); | 1322 if (hsp_type) { 1323 (void) printf(gettext("Unset local HSP between " 1324 "disk %s and RAID volume %s successfully.\n"), 1325 disk_argp, argv[optind]); 1326 } else { 1327 (void) printf(gettext("Unset global HSP between " 1328 "disk %s and controller %s successfully.\n"), 1329 disk_argp, argv[optind]); 1330 } 1331 } 1332 (void) raidcfg_close_controller(ctl_handle, NULL); 1333 return (SUCCESS); 1334} 1335 1336/* 1337 * do_set_array_attr(f_flag, p_argp, argv, optind) 1338 * This function changes array's attribute when array is running. 1339 * The changeable attribute is up to controller's feature. 1340 * The return value can be SUCCESS, FAILURE or INVALID_ARG. 1341 */ 1342static int 1343do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, uint32_t optind) 1344{ 1345 uint32_t ctl_tag = MAX32BIT; 1346 array_tag_t array_tag; 1347 uint32_t type = MAX32BIT; 1348 uint32_t value = MAX32BIT; 1349 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1350 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1351 1352 char *param, *op = "="; 1353 1354 int ret; 1355 1356 if (argv[optind] == NULL || argv[optind + 1] != NULL) { 1357 return (INVALID_ARG); 1358 } 1359 1360 if (p_argp != NULL) { 1361 param = strtok(p_argp, op); 1362 if (strcmp(param, "wp") == 0) { 1363 type = SET_CACHE_WR_PLY; 1364 } else { |
882 return (INVALID_ARG); 883 } 884 | 1365 return (INVALID_ARG); 1366 } 1367 |
885 /* that no target's id is lower than the raidtarg, */ 886 if (t[0] > t[i]) { 887 (void) fprintf(stderr, gettext("First target ID must " 888 "be less than other member target IDs.\n")); | 1368 param = strtok(NULL, op); 1369 if (strcmp(param, "on") == 0) { 1370 value = CACHE_WR_ON; 1371 } else if (strcmp(param, "off") == 0) { 1372 value = CACHE_WR_OFF; 1373 } else { |
889 return (INVALID_ARG); 890 } 891 | 1374 return (INVALID_ARG); 1375 } 1376 |
892 (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 893 ndisks++; | 1377 } else { 1378 return (INVALID_ARG); |
894 } 895 | 1379 } 1380 |
896 /* confirm minimum number of disks */ 897 if (ndisks < 2) { 898 (void) fprintf(stderr, gettext("At least two disks are required" 899 " for RAID creation.\n")); | 1381 if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != SUCCESS) { |
900 return (INVALID_ARG); 901 } 902 | 1382 return (INVALID_ARG); 1383 } 1384 |
903 /* validate the drive capacities */ 904 switch (disk_big_enough(d, &capacity, &errcond)) { 905 case FAILURE: | 1385 ctl_handle = raidcfg_get_controller(ctl_tag); 1386 if (ctl_handle <= 0) { 1387 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle)); |
906 return (FAILURE); | 1388 return (FAILURE); |
907 case INVALID_ARG: 908 switch (errcond) { 909 case 1: 910 (void) fprintf(stderr, gettext("Cannot create RAID volume when " 911 "primary disk is larger than secondary disk.\n")); 912 break; 913 case 2: 914 (void) fprintf(stderr, gettext("Cannot create RAID volume when " 915 "disk block sizes differ.\n")); 916 } 917 return (INVALID_ARG); | |
918 } 919 | 1389 } 1390 |
920 /* 921 * capacity is now set to the number of blocks on a disk, which is 922 * the total capacity of a mirror. the capacity of a stripe is the 923 * cumulative amount of blocks on all disks 924 */ 925 if (rlevel == RAID_STRIPE) 926 capacity *= ndisks; | 1391 ret = raidcfg_open_controller(ctl_handle, NULL); 1392 if (ret < 0) { 1393 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1394 return (FAILURE); 1395 } |
927 | 1396 |
928 if (get_devctl(disk[0], channel1)) | 1397 array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id, 1398 array_tag.idl.lun); 1399 if (array_handle <= 0) { 1400 (void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle)); |
929 return (FAILURE); | 1401 return (FAILURE); |
1402 } |
|
930 | 1403 |
931 fd = open(channel1, O_RDONLY); 932 if (fd == -1) { 933 perror(channel1); | 1404 /* Ask user to confirm operation. */ 1405 if (f_flag == FALSE) { 1406 (void) fprintf(stdout, gettext("Update attribute of " 1407 "array %s (%s/%s)? "), argv[optind], yesstr, nostr); 1408 if (!yes()) { 1409 (void) fprintf(stdout, 1410 gettext("Array %s not " 1411 "changed.\n\n"), argv[optind]); 1412 (void) raidcfg_close_controller(ctl_handle, NULL); 1413 return (SUCCESS); 1414 } 1415 } 1416 1417 if ((ret = raidcfg_set_attr(array_handle, type, &value, NULL)) < 0) { 1418 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1419 (void) raidcfg_close_controller(ctl_handle, NULL); |
934 return (FAILURE); 935 } 936 | 1420 return (FAILURE); 1421 } 1422 |
937 /* 938 * query the HBA driver for volume capacity 939 */ 940 if (ioctl(fd, RAID_NUMVOLUMES, &n) < 0) { 941 raidctl_error("RAID_NUMVOLUMES"); 942 goto fail; | 1423 (void) printf(gettext("Set attribute of RAID volume %s " 1424 "successfully.\n"), argv[optind]); 1425 (void) raidcfg_close_controller(ctl_handle, NULL); 1426 1427 return (SUCCESS); 1428} 1429 1430/* 1431 * snapshot_raidsystem(recursive, indent, is_snapshot) 1432 * This function prints the snapshot of whole RAID's system configuration, 1433 * and return result as SUCCESS or FAILURE. 1434 */ 1435static int 1436snapshot_raidsystem(uint8_t recursive, uint8_t indent, uint8_t is_snapshot) 1437{ 1438 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1439 int ret; 1440 1441 ctl_handle = raidcfg_list_head(OBJ_SYSTEM, OBJ_TYPE_CONTROLLER); 1442 while (ctl_handle > 0) { 1443 ret = raidcfg_open_controller(ctl_handle, NULL); 1444 if (ret == 0) { 1445 if (snapshot_ctl(ctl_handle, recursive, indent, 1446 is_snapshot) == FAILURE) { 1447 (void) raidcfg_close_controller(ctl_handle, 1448 NULL); 1449 } 1450 } 1451 ctl_handle = raidcfg_list_next(ctl_handle); |
943 } | 1452 } |
1453 return (SUCCESS); 1454} |
|
944 | 1455 |
945 /* 946 * current support for both LSI1030 and LSI1064/1068 HBAs 947 */ 948 if (ioctl(fd, RAID_GETDEVID, &devid) < 0) { 949 raidctl_error("RAID_GETDEVID"); 950 goto fail; | 1456/* 1457 * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot) 1458 * This function prints snapshot of specified controller's configuration, 1459 * and return result as SUCCESS or FAILURE. 1460 */ 1461static int 1462snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, uint8_t indent, 1463 uint8_t is_snapshot) 1464{ 1465 raid_obj_handle_t array_handle = INIT_HANDLE_VALUE; 1466 raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE; 1467 raidcfg_controller_t ctl_attr; 1468 uint32_t ctl_tag; 1469 char ctlbuf[256]; 1470 int ret; 1471 1472 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1473 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1474 return (FAILURE); |
951 } 952 | 1475 } 1476 |
953 if ((devid == LSI_1064) || (devid == LSI_1064E) || 954 (devid == LSI_1068) || (devid == LSI_1068E)) { 955 /* 956 * no secondary channel, just check to make 957 * sure we can fit a new volume 958 */ 959 for (i = 0; i < n; i++) { 960 config.unitid = i; 961 if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 962 raidctl_error("RAID_GETCONFIG"); 963 goto fail; | 1477 ctl_tag = ctl_attr.controller_id; 1478 if (is_snapshot == FALSE) { 1479 print_indent(indent); 1480 (void) fprintf(stdout, gettext("Controller: %u\n"), ctl_tag); 1481 } else { 1482 (void) snprintf(ctlbuf, sizeof (ctlbuf), "%u \"%s\"", 1483 ctl_tag, ctl_attr.controller_type); 1484 (void) fprintf(stdout, "%s", ctlbuf); 1485 1486 (void) fprintf(stdout, "\n"); 1487 } 1488 1489 if (recursive == TRUE) { 1490 array_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_ARRAY); 1491 while (array_handle > 0) { 1492 if (snapshot_array(array_handle, 1493 indent + 1, FALSE, is_snapshot) == FAILURE) { 1494 return (FAILURE); |
964 } 965 | 1495 } 1496 |
966 if (config.ndisks == 0) 967 break; | 1497 array_handle = raidcfg_list_next(array_handle); |
968 } 969 | 1498 } 1499 |
970 if (i == n) { 971 (void) printf(gettext("HBA supports a maximum of %d " 972 "RAID Volumes, HBA is full\n"), n); 973 goto fail; | 1500 disk_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_DISK); 1501 while (disk_handle > 0) { 1502 if (snapshot_disk(ctl_tag, disk_handle, 1503 indent + 1, is_snapshot) == FAILURE) { 1504 return (FAILURE); 1505 } 1506 1507 disk_handle = raidcfg_list_next(disk_handle); |
974 } | 1508 } |
1509 } 1510 return (SUCCESS); 1511} |
|
975 | 1512 |
976 /* 977 * we have the capacity to add a volume, now confirm the 978 * creation. the 1064/1068 uses a much larger metadata region 979 * than the 1030 (64MB, as opposed to 16KB). this larger 980 * reservation is enough to alter the disk label. therefore, 981 * once the volume is created, it must be relabeled. 982 * first, confirm that no file systems are mounted, as 983 * we will be pulling the disk out from under them 984 */ 985 for (i = 0; i < ndisks; i++) { 986 if (disk_mounted(d[i])) { 987 (void) fprintf(stderr, gettext("Cannot create " 988 "RAID volume, disk \"%s\" is mounted " 989 ".\n"), d[i]); 990 return (INVALID_ARG); | 1513 1514/* 1515 * snapshot_array(array_handle, indent, is_sub, is_snapshot) 1516 * This function prints snapshot of specified array's configuration, 1517 * and return result as SUCCESS or FAILURE. 1518 */ 1519static int 1520snapshot_array(raid_obj_handle_t array_handle, uint8_t indent, uint8_t is_sub, 1521 uint8_t is_snapshot) 1522{ 1523 raid_obj_handle_t ctl_handle; 1524 raid_obj_handle_t subarray_handle; 1525 raid_obj_handle_t arraypart_handle; 1526 raid_obj_handle_t task_handle; 1527 1528 raidcfg_controller_t ctl_attr; 1529 raidcfg_array_t array_attr; 1530 raidcfg_arraypart_t arraypart_attr; 1531 raidcfg_task_t task_attr; 1532 1533 char arraybuf[256] = "\0"; 1534 char diskbuf[256] = "\0"; 1535 char tempbuf[256] = "\0"; 1536 int disknum = 0; 1537 1538 uint32_t ctl_tag; 1539 int ret; 1540 1541 ctl_handle = raidcfg_get_container(array_handle); 1542 ret = raidcfg_get_attr(ctl_handle, &ctl_attr); 1543 if (ret < 0) { 1544 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1545 return (FAILURE); 1546 } 1547 ctl_tag = ctl_attr.controller_id; 1548 1549 /* Print array attribute */ 1550 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 1551 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1552 return (FAILURE); 1553 } 1554 1555 if (is_snapshot == FALSE) { 1556 print_indent(indent); 1557 if (is_sub == FALSE) { 1558 (void) fprintf(stdout, gettext("Volume:" 1559 "c%ut%llud%llu\n"), 1560 ctl_tag, array_attr.tag.idl.target_id, 1561 array_attr.tag.idl.lun); 1562 } else { 1563 (void) fprintf(stdout, gettext("Sub-Volume\n")); 1564 } 1565 } else { 1566 (void) snprintf(arraybuf, sizeof (arraybuf), "c%ut%llud%llu ", 1567 ctl_tag, array_attr.tag.idl.target_id, 1568 array_attr.tag.idl.lun); 1569 1570 /* Check if array is in sync state */ 1571 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK); 1572 if (task_handle > 0) { 1573 (void) raidcfg_get_attr(task_handle, &task_attr); 1574 if (task_attr.task_func == TASK_FUNC_BUILD) { 1575 array_attr.state = ARRAY_STATE_SYNC; |
991 } | 1576 } |
1577 } else { 1578 subarray_handle = raidcfg_list_head(array_handle, 1579 OBJ_TYPE_ARRAY); 1580 while (subarray_handle > 0) { 1581 task_handle = raidcfg_list_head(subarray_handle, 1582 OBJ_TYPE_TASK); 1583 if (task_handle > 0) { 1584 (void) raidcfg_get_attr(task_handle, 1585 &task_attr); 1586 if (task_attr.task_func == 1587 TASK_FUNC_BUILD) { 1588 array_attr.state = 1589 ARRAY_STATE_SYNC; 1590 } 1591 break; 1592 } 1593 subarray_handle = 1594 raidcfg_list_next(subarray_handle); 1595 } |
|
992 } 993 | 1596 } 1597 |
994 /* 995 * will not support data migration or disk relabeling with 996 * this utility, and so next we must confirm the creation as 997 * all data on member disks will be lost. 998 */ 999 if (!force) { 1000 (void) fprintf(stderr, gettext("Creating RAID volume " 1001 "c%dt%dd0 will destroy all data on member disks, " 1002 "proceed (%s/%s)? "), c[0], t[0], yeschr, nochr); 1003 if (!yes()) { 1004 (void) fprintf(stderr, gettext("RAID volume " 1005 "c%dt%dd0 not created.\n\n"), c[0], t[0]); 1006 (void) close(fd); 1007 return (SUCCESS); | 1598 /* Print sub array */ 1599 subarray_handle = raidcfg_list_head(array_handle, 1600 OBJ_TYPE_ARRAY); 1601 while (subarray_handle > 0) { 1602 /* print subarraypart */ 1603 arraypart_handle = raidcfg_list_head(subarray_handle, 1604 OBJ_TYPE_ARRAY_PART); 1605 while (arraypart_handle > 0) { 1606 if ((ret = raidcfg_get_attr(arraypart_handle, 1607 &arraypart_attr)) < 0) { 1608 (void) fprintf(stderr, "%s\n", 1609 raidcfg_errstr(ret)); 1610 return (FAILURE); 1611 } 1612 1613 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1614 (void) snprintf(tempbuf, 1615 sizeof (tempbuf), 1616 gettext("N/A")); 1617 } else { 1618 (void) snprintf(tempbuf, 1619 sizeof (tempbuf), 1620 "%llu.%llu.%llu", 1621 arraypart_attr.tag.cidl.bus, 1622 arraypart_attr.tag.cidl.target_id, 1623 arraypart_attr.tag.cidl.lun); 1624 } 1625 (void) strcat(diskbuf, tempbuf); 1626 (void) strcat(diskbuf, " "); 1627 disknum++; 1628 arraypart_handle = 1629 raidcfg_list_next(arraypart_handle); |
1008 } | 1630 } |
1631 subarray_handle = raidcfg_list_next(subarray_handle); |
|
1009 } 1010 | 1632 } 1633 |
1011 /* 1012 * we are ready to move onto the creation 1013 */ 1014 goto no_secondary_channel; 1015 } | 1634 /* Print arraypart */ 1635 arraypart_handle = raidcfg_list_head(array_handle, 1636 OBJ_TYPE_ARRAY_PART); 1637 while (arraypart_handle > 0) { 1638 if ((ret = raidcfg_get_attr(arraypart_handle, 1639 &arraypart_attr)) < 0) { 1640 (void) fprintf(stderr, "%s\n", 1641 raidcfg_errstr(ret)); 1642 return (FAILURE); 1643 } |
1016 | 1644 |
1017 /* 1018 * LSI1030, support for single IM volume 1019 */ 1020 if (rlevel != RAID_MIRROR) { 1021 (void) printf(gettext("HBA only supports RAID " 1022 "level 1 (mirrored) volumes\n")); 1023 goto fail; 1024 } 1025 /* 1026 * look up the volume configuration 1027 */ 1028 config.unitid = n; 1029 if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 1030 raidctl_error("RAID_GETCONFIG"); 1031 goto fail; 1032 } | 1645 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1646 (void) snprintf(tempbuf, sizeof (tempbuf), 1647 gettext("N/A")); 1648 } else { 1649 (void) snprintf(tempbuf, sizeof (tempbuf), 1650 "%llu.%llu.%llu", 1651 arraypart_attr.tag.cidl.bus, 1652 arraypart_attr.tag.cidl.target_id, 1653 arraypart_attr.tag.cidl.lun); 1654 } 1655 (void) strcat(diskbuf, tempbuf); 1656 (void) strcat(diskbuf, " "); 1657 disknum++; 1658 arraypart_handle = raidcfg_list_next(arraypart_handle); 1659 } 1660 (void) snprintf(tempbuf, sizeof (tempbuf), "%u ", disknum); 1661 (void) strcat(arraybuf, tempbuf); 1662 (void) strcat(arraybuf, diskbuf); |
1033 | 1663 |
1034 if (config.ndisks != 0) { 1035 (void) printf(gettext("RAID Volume already exists " 1036 "on this controller 'c%dt%dd0'\n"), 1037 c[0], config.targetid); 1038 goto fail; | 1664 switch (array_attr.raid_level) { 1665 case RAID_LEVEL_0: 1666 (void) sprintf(tempbuf, "0"); 1667 break; 1668 case RAID_LEVEL_1: 1669 (void) sprintf(tempbuf, "1"); 1670 break; 1671 case RAID_LEVEL_1E: 1672 (void) sprintf(tempbuf, "1E"); 1673 break; 1674 case RAID_LEVEL_5: 1675 (void) sprintf(tempbuf, "5"); 1676 break; 1677 case RAID_LEVEL_10: 1678 (void) sprintf(tempbuf, "10"); 1679 break; 1680 case RAID_LEVEL_50: 1681 (void) sprintf(tempbuf, "50"); 1682 break; 1683 default: 1684 (void) snprintf(tempbuf, sizeof (tempbuf), 1685 gettext("N/A")); 1686 break; 1687 } 1688 (void) strcat(arraybuf, tempbuf); 1689 (void) fprintf(stdout, "%s ", arraybuf); 1690 1691 switch (array_attr.state) { 1692 case ARRAY_STATE_OPTIMAL: 1693 (void) fprintf(stdout, gettext("OPTIMAL")); 1694 break; 1695 case ARRAY_STATE_DEGRADED: 1696 (void) fprintf(stdout, gettext("DEGRADED")); 1697 break; 1698 case ARRAY_STATE_FAILED: 1699 (void) fprintf(stdout, gettext("FAILED")); 1700 break; 1701 case ARRAY_STATE_SYNC: 1702 (void) fprintf(stdout, gettext("SYNC")); 1703 break; 1704 default: 1705 (void) fprintf(stdout, gettext("N/A")); 1706 break; 1707 } 1708 (void) fprintf(stdout, "\n"); |
1039 } 1040 | 1709 } 1710 |
1041 /* 1042 * Make sure there isn't a raid created on this controller's 1043 * other channel, if it has multiple channels 1044 */ 1045 (void) strlcpy(channel2, channel1, sizeof (channel2)); 1046 tmp = strrchr(channel2, ':'); 1047 tmp[0] = 0; 1048 size = strlen(channel2); | 1711 return (SUCCESS); 1712} |
1049 | 1713 |
1050 /* 1051 * Make sure that the secondary disk is not mounted 1052 */ 1053 if (disk_mounted(disk[1])) { 1054 (void) fprintf(stderr, gettext("Cannot create RAID volume when " 1055 "secondary disk \"%s\" is mounted.\n"), disk[1]); 1056 return (INVALID_ARG); 1057 } | 1714/* 1715 * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot) 1716 * This function prints snapshot of specified disk's configuration, and return 1717 * result as SUCCESS or FAILURE. 1718 */ 1719static int 1720snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, uint8_t indent, 1721 uint8_t is_snapshot) 1722{ 1723 raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE; 1724 raid_obj_handle_t hsp_handle; |
1058 | 1725 |
1059 /* 1060 * Format the channel string for the other channel so we can 1061 * see if a raid exists on it. In this case if we are being 1062 * asked to create a raid on channel 2 (indicated by the 1,1 1063 * at the end of the string) we want to check channel 1), 1064 * otherwise we will check channel 2. 1065 */ 1066 if (channel2[size - 2] == ',') { 1067 channel2[size - 1] = 0; 1068 channel2[size - 2] = 0; 1069 (void) snprintf(channel2, sizeof (channel2), 1070 "%s:devctl", channel2); 1071 } else { 1072 (void) snprintf(channel2, sizeof (channel2), 1073 "%s,1:devctl", channel2); 1074 } | 1726 raidcfg_controller_t ctl_attr; 1727 raidcfg_disk_t disk_attr; 1728 char diskbuf[256] = ""; 1729 char tempbuf[256] = ""; |
1075 | 1730 |
1076 fd2 = open(channel2, O_RDONLY); 1077 if (fd2 == -1) { 1078 if (errno == ENOENT) 1079 goto no_secondary_channel; 1080 perror(channel2); 1081 goto fail; 1082 } | 1731 int ret; |
1083 | 1732 |
1084 if (ioctl(fd2, RAID_GETCONFIG, &config) < 0) { 1085 goto fail; | 1733 ctl_handle = raidcfg_get_controller(ctl_tag); 1734 ret = raidcfg_get_attr(ctl_handle, &ctl_attr); 1735 if (ret < 0) { 1736 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1737 return (FAILURE); |
1086 } 1087 | 1738 } 1739 |
1088 if (config.ndisks != 0) { 1089 int cx; 1090 cx = get_controller(channel2); 1091 (void) printf(gettext("RAID Volume already exists " 1092 "on this controller 'c%dt%dd0'\n"), cx, 1093 config.targetid); 1094 goto fail; | 1740 /* Print attribute of disk */ 1741 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) { 1742 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1743 return (FAILURE); |
1095 } 1096 | 1744 } 1745 |
1097no_secondary_channel: | 1746 if (is_snapshot == FALSE) { 1747 print_indent(indent); |
1098 | 1748 |
1099 /* all checks complete, fill in the config */ 1100 newvol.targetid = t[0]; 1101 newvol.disk[0] = t[0]; 1102 newvol.raid_level = rlevel; 1103 newvol.ndisks = ndisks; 1104 newvol.raid_capacity = capacity; | 1749 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); |
1105 | 1750 |
1106 /* populate config.disk, and unconfigure all disks, except targetid */ 1107 for (i = 1; i < ndisks; i++) { 1108 if (do_config_change_state(CFGA_CMD_UNCONFIGURE, 1109 t[i], c[0])) { 1110 perror("config_change_state"); 1111 goto fail; | 1751 if (disk_attr.tag.cidl.bus == MAX64BIT) { 1752 (void) fprintf(stdout, gettext("Disk: N/A")); 1753 } else { 1754 (void) fprintf(stdout, gettext("Disk: %llu.%llu.%llu"), 1755 disk_attr.tag.cidl.bus, 1756 disk_attr.tag.cidl.target_id, 1757 disk_attr.tag.cidl.lun); |
1112 } | 1758 } |
1113 newvol.disk[i] = t[i]; 1114 } 1115 1116 if (ioctl(fd, RAID_CREATE, &newvol)) { 1117 /* reconfigure all disks, except targetid */ 1118 for (i = 1; i < ndisks; i++) { 1119 (void) do_config_change_state(CFGA_CMD_CONFIGURE, 1120 newvol.disk[i], c[0]); | 1759 if (hsp_handle > 0) { 1760 (void) fprintf(stdout, "(HSP)"); |
1121 } | 1761 } |
1122 raidctl_error("RAID_CREATE"); 1123 goto fail; | 1762 (void) fprintf(stdout, "\n"); 1763 } else { 1764 if (disk_attr.tag.cidl.bus == MAX64BIT) { 1765 (void) fprintf(stdout, gettext("N/A")); 1766 } else { 1767 (void) snprintf(diskbuf, sizeof (diskbuf), 1768 "%llu.%llu.%llu ", 1769 disk_attr.tag.cidl.bus, 1770 disk_attr.tag.cidl.target_id, 1771 disk_attr.tag.cidl.lun); 1772 } 1773 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); 1774 if (hsp_handle > 0) { 1775 (void) snprintf(tempbuf, sizeof (tempbuf), 1776 gettext("HSP")); 1777 } else if (disk_attr.state == DISK_STATE_GOOD) { 1778 (void) snprintf(tempbuf, sizeof (tempbuf), 1779 gettext("GOOD")); 1780 } else if (disk_attr.state == DISK_STATE_FAILED) { 1781 (void) snprintf(tempbuf, sizeof (tempbuf), 1782 gettext("FAILED")); 1783 } else { 1784 (void) snprintf(tempbuf, sizeof (tempbuf), 1785 gettext("N/A")); 1786 } 1787 1788 (void) strcat(diskbuf, tempbuf); 1789 (void) fprintf(stdout, "%s\n", diskbuf); |
1124 } 1125 | 1790 } 1791 |
1126 (void) printf(gettext("Volume 'c%dt%dd0' created\n"), c[0], t[0]); 1127 (void) close(fd); 1128 (void) close(fd2); | |
1129 return (SUCCESS); | 1792 return (SUCCESS); |
1130 1131fail: 1132 (void) close(fd); 1133 (void) close(fd2); 1134 return (FAILURE); | |
1135} 1136 1137static int | 1793} 1794 1795static int |
1138do_delete(char *d, int force) | 1796print_ctl_table(raid_obj_handle_t ctl_handle) |
1139{ | 1797{ |
1140 raid_config_t config; 1141 char disk1[MAXPATHLEN]; 1142 char buf[MAXPATHLEN]; 1143 int fd; 1144 int target; 1145 int ctrl; 1146 int i, j; 1147 int wrong_targ = 0; 1148 int nvols; 1149 uint8_t t; | 1798 raidcfg_controller_t ctl_attr; 1799 char controller[8]; 1800 int ret; |
1150 | 1801 |
1151 (void) chdir(DEVDIR); 1152 1153 if ((sscanf(d, "c%dt%dd0", &ctrl, &target)) != 2) { 1154 (void) fprintf(stderr, gettext("Invalid disk format.\n")); 1155 return (INVALID_ARG); | 1802 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1803 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1804 return (FAILURE); |
1156 } | 1805 } |
1157 t = (uint8_t)target; | |
1158 | 1806 |
1159 (void) snprintf(disk1, sizeof (disk1), DEVDIR"/%ss2", d); | 1807 (void) fprintf(stdout, gettext("Controller\tType\t\tVersion")); 1808 (void) fprintf(stdout, "\n"); 1809 (void) fprintf(stdout, "--------------------------------"); 1810 (void) fprintf(stdout, "--------------------------------"); 1811 (void) fprintf(stdout, "\n"); |
1160 | 1812 |
1161 if (get_devctl(disk1, buf) != 0) { 1162 (void) fprintf(stderr, gettext("Not a volume '%s'\n"), d); | 1813 (void) snprintf(controller, sizeof (controller), "%u", 1814 ctl_attr.controller_id); 1815 (void) printf("c%s\t\t", controller); 1816 1817 (void) print_ctl_attr(&ctl_attr); 1818 (void) fprintf(stdout, "\n"); 1819 1820 return (SUCCESS); 1821} 1822 1823static int 1824print_array_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t array_handle) 1825{ 1826 raidcfg_controller_t ctl_attr; 1827 raidcfg_array_t array_attr; 1828 raidcfg_array_t subarray_attr; 1829 raidcfg_arraypart_t arraypart_attr; 1830 raidcfg_task_t task_attr; 1831 1832 raid_obj_handle_t subarray_handle; 1833 raid_obj_handle_t arraypart_handle; 1834 raid_obj_handle_t task_handle; 1835 1836 char array[8]; 1837 char arraypart[8]; 1838 int ret; 1839 int i; 1840 1841 /* Controller attribute */ 1842 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1843 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); |
1163 return (FAILURE); 1164 } 1165 | 1844 return (FAILURE); 1845 } 1846 |
1166 fd = open(buf, O_RDONLY); 1167 if (fd == -1) { 1168 perror(buf); | 1847 /* Array attribute */ 1848 if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) { 1849 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); |
1169 return (FAILURE); 1170 } 1171 | 1850 return (FAILURE); 1851 } 1852 |
1172 if (ioctl(fd, RAID_NUMVOLUMES, &nvols)) { 1173 raidctl_error("RAID_NUMVOLUMES"); 1174 goto fail; 1175 } | 1853 /* print header */ 1854 (void) fprintf(stdout, gettext("Volume\t\t\tSize\tStripe\tStatus\t" 1855 " Cache\tRAID")); 1856 (void) fprintf(stdout, "\n"); 1857 (void) fprintf(stdout, gettext("\tSub\t\t\tSize\t\t\tLevel")); 1858 (void) fprintf(stdout, "\n"); 1859 (void) fprintf(stdout, gettext("\t\tDisk\t\t\t\t\t")); 1860 (void) fprintf(stdout, "\n"); 1861 (void) fprintf(stdout, "--------------------------------"); 1862 (void) fprintf(stdout, "--------------------------------"); 1863 (void) fprintf(stdout, "\n"); |
1176 | 1864 |
1177 for (i = 0; i < nvols; i++) { 1178 config.unitid = i; 1179 if (ioctl(fd, RAID_GETCONFIG, &config)) { 1180 raidctl_error("RAID_GETCONFIG"); 1181 goto fail; | 1865 /* print array */ 1866 (void) snprintf(array, sizeof (array), "c%ut%llud%llu", 1867 ctl_attr.controller_id, array_attr.tag.idl.target_id, 1868 array_attr.tag.idl.lun); 1869 (void) fprintf(stdout, "%s\t\t\t", array); 1870 1871 /* check if array is in sync state */ 1872 task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK); 1873 if (task_handle > 0) { 1874 (void) raidcfg_get_attr(task_handle, &task_attr); 1875 if (task_attr.task_func == TASK_FUNC_BUILD) { 1876 array_attr.state = ARRAY_STATE_SYNC; |
1182 } | 1877 } |
1183 if (config.ndisks != 0) { 1184 /* there is a RAID volume in this slot */ 1185 if (config.targetid != t) { 1186 wrong_targ++; 1187 continue; | 1878 } else { 1879 subarray_handle = raidcfg_list_head(array_handle, 1880 OBJ_TYPE_ARRAY); 1881 while (subarray_handle > 0) { 1882 task_handle = raidcfg_list_head(subarray_handle, 1883 OBJ_TYPE_TASK); 1884 if (task_handle > 0) { 1885 (void) raidcfg_get_attr(task_handle, 1886 &task_attr); 1887 if (task_attr.task_func == TASK_FUNC_BUILD) { 1888 array_attr.state = ARRAY_STATE_SYNC; 1889 } 1890 break; |
1188 } | 1891 } |
1189 /* and it's our target */ 1190 break; | 1892 subarray_handle = raidcfg_list_next(subarray_handle); |
1191 } 1192 } 1193 | 1893 } 1894 } 1895 |
1194 if (i == nvols) { 1195 /* we found no RAID volumes */ 1196 (void) fprintf(stderr, gettext("No RAID volumes exist on " 1197 "controller '%d'\n"), ctrl); 1198 goto fail; 1199 } | 1896 (void) print_array_attr(&array_attr); 1897 (void) fprintf(stdout, "\n"); |
1200 | 1898 |
1201 if (wrong_targ == nvols) { 1202 /* we found RAID volumes, but none matched */ 1203 (void) fprintf(stderr, 1204 gettext("RAID volume 'c%dt%dd0' does not exist\n"), 1205 ctrl, t); 1206 goto fail; 1207 } | 1899 /* Print sub array */ 1900 i = 0; /* Count sub array number */ 1901 subarray_handle = raidcfg_list_head(array_handle, OBJ_TYPE_ARRAY); 1902 while (subarray_handle > 0) { 1903 if ((ret = raidcfg_get_attr(subarray_handle, 1904 &subarray_attr)) < 0) { 1905 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1906 return (FAILURE); 1907 } |
1208 | 1908 |
1209 /* if this volume is a stripe, all data will be lost */ 1210 if (config.raid_level == RAID_STRIPE) { 1211 if (disk_mounted(d)) { 1212 (void) fprintf(stderr, gettext("Cannot delete " 1213 "RAID0 volume, \"%s\" is mounted.\n"), d); 1214 return (INVALID_ARG); | 1909 /* Use sub0/sub1 here, not cxtxd0 for subarray */ 1910 (void) snprintf(array, sizeof (array), "sub%u", i++); 1911 (void) fprintf(stdout, "\t%s\t\t", array); 1912 1913 /* Check if array is in sync */ 1914 task_handle = raidcfg_list_head(subarray_handle, OBJ_TYPE_TASK); 1915 if (task_handle > 0) { 1916 (void) raidcfg_get_attr(task_handle, &task_attr); 1917 if (task_attr.task_func == TASK_FUNC_BUILD) { 1918 subarray_attr.state = ARRAY_STATE_SYNC; 1919 } |
1215 } | 1920 } |
1216 if (!force) { 1217 (void) fprintf(stderr, gettext("Deleting volume " 1218 "c%dt%dd0 will destroy all data it contains, " 1219 "proceed (%s/%s)? "), ctrl, t, yeschr, nochr); 1220 if (!yes()) { 1221 (void) fprintf(stderr, gettext("RAID volume " 1222 "c%dt%dd0 not deleted.\n\n"), ctrl, t); 1223 (void) close(fd); 1224 return (SUCCESS); | 1921 1922 (void) print_array_attr(&subarray_attr); 1923 (void) fprintf(stdout, "\n"); 1924 1925 /* Print subarraypart */ 1926 arraypart_handle = raidcfg_list_head(subarray_handle, 1927 OBJ_TYPE_ARRAY_PART); 1928 while (arraypart_handle > 0) { 1929 if ((ret = raidcfg_get_attr(arraypart_handle, 1930 &arraypart_attr)) < 0) { 1931 (void) fprintf(stderr, "%s\n", 1932 raidcfg_errstr(ret)); 1933 return (FAILURE); |
1225 } | 1934 } |
1935 1936 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1937 (void) snprintf(arraypart, sizeof (arraypart), 1938 gettext("N/A")); 1939 } else { 1940 (void) snprintf(arraypart, sizeof (arraypart), 1941 "%llu.%llu.%llu", 1942 arraypart_attr.tag.cidl.bus, 1943 arraypart_attr.tag.cidl.target_id, 1944 arraypart_attr.tag.cidl.lun); 1945 } 1946 1947 (void) fprintf(stdout, "\t\t%s\t", arraypart); 1948 (void) print_arraypart_attr(&arraypart_attr); 1949 (void) fprintf(stdout, "\n"); 1950 arraypart_handle = raidcfg_list_next(arraypart_handle); |
|
1226 } | 1951 } |
1952 subarray_handle = raidcfg_list_next(subarray_handle); |
|
1227 } | 1953 } |
1228 /* if this volume is a mirror, prompt user to verify the operation */ 1229 else if (config.raid_level == RAID_MIRROR && !force) { 1230 (void) fprintf(stderr, gettext("Are you sure you want to " 1231 "delete RAID-1 Volume c%dt%dd0(%s/%s)? "), 1232 ctrl, t, yeschr, nochr); 1233 if (!yes()) { 1234 (void) fprintf(stderr, gettext("RAID volume " 1235 "c%dt%dd0 not deleted.\n\n"), ctrl, t); 1236 (void) close(fd); 1237 return (SUCCESS); | 1954 1955 /* Print arraypart */ 1956 arraypart_handle = raidcfg_list_head(array_handle, 1957 OBJ_TYPE_ARRAY_PART); 1958 while (arraypart_handle > 0) { 1959 if ((ret = raidcfg_get_attr(arraypart_handle, 1960 &arraypart_attr)) < 0) { 1961 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1962 return (FAILURE); |
1238 } | 1963 } |
1964 1965 if (arraypart_attr.tag.cidl.bus == MAX64BIT) { 1966 (void) snprintf(arraypart, sizeof (arraypart), 1967 gettext("N/A")); 1968 } else { 1969 (void) snprintf(arraypart, sizeof (arraypart), 1970 "%llu.%llu.%llu", 1971 arraypart_attr.tag.cidl.bus, 1972 arraypart_attr.tag.cidl.target_id, 1973 arraypart_attr.tag.cidl.lun); 1974 } 1975 1976 (void) fprintf(stdout, "\t\t%s\t", arraypart); 1977 (void) print_arraypart_attr(&arraypart_attr); 1978 (void) fprintf(stdout, "\n"); 1979 arraypart_handle = raidcfg_list_next(arraypart_handle); |
|
1239 } 1240 | 1980 } 1981 |
1241 if (ioctl(fd, RAID_DELETE, &t)) { 1242 perror("RAID_DELETE"); 1243 goto fail; | 1982 return (SUCCESS); 1983} 1984 1985static int 1986print_disk_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle) 1987{ 1988 raidcfg_controller_t ctl_attr; 1989 raidcfg_disk_t disk_attr; 1990 char disk[8]; 1991 int ret; 1992 1993 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 1994 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 1995 return (FAILURE); |
1244 } 1245 | 1996 } 1997 |
1246 /* reconfigure all disks, except targetid */ 1247 for (j = 1; j < config.ndisks; j++) { 1248 (void) do_config_change_state(CFGA_CMD_CONFIGURE, 1249 config.disk[j], ctrl); | 1998 if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) { 1999 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2000 return (FAILURE); |
1250 } 1251 | 2001 } 2002 |
1252 (void) fprintf(stderr, gettext("Volume 'c%dt%dd0' deleted.\n"), 1253 ctrl, target); 1254 (void) close(fd); | 2003 /* Print header */ 2004 (void) fprintf(stdout, gettext("Disk\tVendor\tProduct\t\tCapacity\t" 2005 "Status\tHSP")); 2006 (void) fprintf(stdout, "\n"); 2007 (void) fprintf(stdout, "--------------------------------"); 2008 (void) fprintf(stdout, "--------------------------------"); 2009 (void) fprintf(stdout, "\n"); 2010 2011 2012 (void) snprintf(disk, sizeof (disk), "%llu.%llu.%llu", 2013 disk_attr.tag.cidl.bus, 2014 disk_attr.tag.cidl.target_id, 2015 disk_attr.tag.cidl.lun); 2016 2017 (void) fprintf(stdout, "%s\t", disk); 2018 2019 (void) print_disk_attr(ctl_handle, disk_handle, &disk_attr); 2020 (void) fprintf(stdout, "\n"); 2021 |
1255 return (SUCCESS); | 2022 return (SUCCESS); |
2023} |
|
1256 | 2024 |
1257fail: 1258 (void) close(fd); 1259 return (FAILURE); | 2025/* 2026 * print_ctl_attr(attrp) 2027 * This function prints attribute of specified controller, and return 2028 * result as SUCCESS or FAILURE. 2029 */ 2030static int 2031print_ctl_attr(raidcfg_controller_t *attrp) 2032{ 2033 char type[CONTROLLER_TYPE_LEN]; 2034 char version[CONTROLLER_FW_LEN]; 2035 2036 if (attrp == NULL) { 2037 return (FAILURE); 2038 } 2039 2040 (void) snprintf(type, sizeof (type), "%s", attrp->controller_type); 2041 (void) fprintf(stdout, "%-16s", type); 2042 2043 (void) snprintf(version, sizeof (version), "%s", attrp->fw_version); 2044 (void) fprintf(stdout, "%s", version); 2045 2046 return (SUCCESS); |
1260} 1261 | 2047} 2048 |
1262static void 1263getimagetype(uint8_t *rombuf, int *imagetype) | 2049/* 2050 * print_array_attr(attrp) 2051 * This function prints attribute of specified array, and return 2052 * result as SUCCESS or FAILURE. 2053 */ 2054static int 2055print_array_attr(raidcfg_array_t *attrp) |
1264{ | 2056{ |
1265 uint8_t type = rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE]; 1266 if (type == 0) { 1267 *imagetype = BIOS_IMAGE; 1268 return; | 2057 char capacity[8]; 2058 char stripe_size[8]; 2059 char raid_level[8]; 2060 2061 if (attrp == NULL) { 2062 return (FAILURE); |
1269 } | 2063 } |
1270 if (type == 1) { 1271 *imagetype = FCODE_IMAGE; 1272 return; | 2064 2065 if (attrp->capacity != MAX64BIT) { 2066 if (size_to_string(attrp->capacity, capacity, 8) != SUCCESS) { 2067 return (FAILURE); 2068 } 2069 (void) printf("%s\t", capacity); 2070 } else { 2071 (void) printf(gettext("N/A\t")); |
1273 } | 2072 } |
2073 2074 if (attrp->stripe_size != MAX32BIT) { 2075 (void) snprintf(stripe_size, sizeof (stripe_size), "%uK", 2076 attrp->stripe_size / 1024); 2077 (void) printf("%s\t", stripe_size); 2078 } else { 2079 (void) printf(gettext("N/A\t")); 2080 } 2081 2082 switch (attrp->state) { 2083 case ARRAY_STATE_OPTIMAL: 2084 (void) printf("%-8s", gettext("OPTIMAL")); 2085 break; 2086 case ARRAY_STATE_DEGRADED: 2087 (void) printf("%-8s", gettext("DEGRADED")); 2088 break; 2089 case ARRAY_STATE_FAILED: 2090 (void) printf("%-8s", gettext("FAILED")); 2091 break; 2092 case ARRAY_STATE_SYNC: 2093 (void) printf("%-8s", gettext("SYNC")); 2094 break; 2095 default: 2096 (void) printf("%-8s", gettext("N/A")); 2097 break; 2098 } 2099 (void) printf(" "); 2100 2101 if (attrp->write_policy == CACHE_WR_OFF) { 2102 (void) printf(gettext("OFF")); 2103 } else if (attrp->write_policy == CACHE_WR_ON) { 2104 (void) printf(gettext("ON")); 2105 } else { 2106 (void) printf(gettext("N/A")); 2107 } 2108 (void) printf("\t"); 2109 2110 switch (attrp->raid_level) { 2111 case RAID_LEVEL_0: 2112 (void) sprintf(raid_level, "RAID0"); 2113 break; 2114 case RAID_LEVEL_1: 2115 (void) sprintf(raid_level, "RAID1"); 2116 break; 2117 case RAID_LEVEL_1E: 2118 (void) sprintf(raid_level, "RAID1E"); 2119 break; 2120 case RAID_LEVEL_5: 2121 (void) sprintf(raid_level, "RAID5"); 2122 break; 2123 case RAID_LEVEL_10: 2124 (void) sprintf(raid_level, "RAID10"); 2125 break; 2126 case RAID_LEVEL_50: 2127 (void) sprintf(raid_level, "RAID50"); 2128 break; 2129 default: 2130 (void) snprintf(raid_level, sizeof (raid_level), 2131 gettext("N/A")); 2132 break; 2133 } 2134 (void) printf("%s", raid_level); 2135 2136 return (SUCCESS); |
|
1274} 1275 | 2137} 2138 |
2139/* 2140 * print_arraypart_attr(attrp) 2141 * This function print attribute of specified arraypart, and return 2142 * result as SUCCESS or FAILURE. 2143 */ |
|
1276static int | 2144static int |
1277getfcodever(uint8_t *rombuf, uint32_t nbytes, char **fcodeversion) | 2145print_arraypart_attr(raidcfg_arraypart_t *attrp) |
1278{ | 2146{ |
1279 int x, y, size; 1280 int found_1 = 0, found_2 = 0; 1281 int image_length = 0; 1282 int no_of_images = 0; 1283 uint8_t *rombuf_1 = NULL; 1284 uint16_t image_units = 0; | 2147 char size[8]; |
1285 | 2148 |
1286 /* 1287 * Single Image - Open firmware image 1288 */ 1289 if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] == 1) { 1290 rombuf_1 = rombuf + gw(rombuf + PCIR_OFF) + PCI_PDS_INDICATOR; 1291 no_of_images = 1; 1292 goto process_image; | 2149 if (attrp == NULL) { 2150 return (FAILURE); |
1293 } 1294 | 2151 } 2152 |
1295 /* 1296 * Combined Image - First Image - x86/PC-AT Bios image 1297 */ 1298 if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] != 0) { 1299 (void) fprintf(stderr, gettext("This is neither open image" 1300 " nor Bios/Fcode combined image\n")); 1301 return (1); | 2153 if (attrp->size != MAX64BIT) { 2154 if (size_to_string(attrp->size, size, 8) != SUCCESS) { 2155 return (FAILURE); 2156 } 2157 (void) printf("%s\t", size); 2158 } else { 2159 (void) printf(gettext("N/A\t")); |
1302 } 1303 | 2160 } 2161 |
1304 /* 1305 * Seek to 2nd Image 1306 */ 1307 rombuf_1 = rombuf + gw(rombuf + PCI_ROM_PCI_DATA_STRUCT_PTR); 1308 image_units = gw(rombuf_1 + PCI_PDS_IMAGE_LENGTH); 1309 image_length = image_units * PCI_IMAGE_UNIT_SIZE; 1310 rombuf_1 += image_length; | 2162 (void) printf("\t"); |
1311 | 2163 |
1312 /* 1313 * Combined Image - Second Image - Open Firmware image 1314 */ 1315 if (rombuf_1[PCI_PDS_CODE_TYPE] != 1) { 1316 (void) fprintf(stderr, gettext("This is neither open image" 1317 " nor Bios/Fcode combined image\n")); 1318 return (1); | 2164 if (attrp->state == DISK_STATE_GOOD) { 2165 (void) printf(gettext("GOOD")); 2166 } else if (attrp->state == DISK_STATE_FAILED) { 2167 (void) printf(gettext("FAILED")); 2168 } else { 2169 (void) printf(gettext("N/A")); |
1319 } | 2170 } |
1320 rombuf_1 += PCI_PDS_INDICATOR; 1321 no_of_images = 2; | 2171 (void) printf("\t"); |
1322 | 2172 |
1323process_image: 1324 /* 1325 * This should be the last image 1326 */ 1327 if (*rombuf_1 != LAST_IMAGE) { 1328 (void) fprintf(stderr, gettext("This is not a valid " 1329 "Bios/Fcode image file\n")); 1330 return (1); | 2173 return (SUCCESS); 2174} 2175 2176/* 2177 * print_disk_attr(ctl_handle, disk_handle, attrp) 2178 * This function prints attribute of specified disk, and return 2179 * result as SUCCESS or FAILURE. 2180 */ 2181static int 2182print_disk_attr(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle, 2183 raidcfg_disk_t *attrp) 2184{ 2185 char vendor[DISK_VENDER_LEN]; 2186 char product[DISK_PRODUCT_LEN]; 2187 char capacity[16]; 2188 char hsp[16]; 2189 2190 raid_obj_handle_t hsp_handle; 2191 raidcfg_hsp_t hsp_attr; 2192 raidcfg_controller_t ctl_attr; 2193 int ret; 2194 char is_indent; 2195 2196 if (attrp == NULL) { 2197 return (FAILURE); |
1331 } 1332 | 2198 } 2199 |
1333 /* 1334 * Scan through the bios/fcode file to get the fcode version 1335 * 0x12 and 0x7 indicate the start of the fcode version string 1336 */ 1337 for (x = 0; x < (nbytes - 8); x++) { 1338 if ((rombuf[x] == FCODE_VERS_KEY1) && 1339 (rombuf[x+1] == FCODE_VERS_KEY2) && 1340 (rombuf[x+2] == 'v') && (rombuf[x+3] == 'e') && 1341 (rombuf[x+4] == 'r') && (rombuf[x+5] == 's') && 1342 (rombuf[x+6] == 'i') && (rombuf[x+7] == 'o') && 1343 (rombuf[x+8] == 'n')) { 1344 found_1 = 1; 1345 break; | 2200 (void) snprintf(vendor, sizeof (vendor), "%s", attrp->vendorid); 2201 (void) printf("%s\t", vendor); 2202 2203 (void) snprintf(product, sizeof (product), "%s", attrp->productid); 2204 (void) printf("%s\t", product); 2205 2206 if (attrp->capacity != MAX64BIT) { 2207 if (size_to_string(attrp->capacity, capacity, 16) != SUCCESS) { 2208 return (FAILURE); |
1346 } | 2209 } |
2210 (void) printf("%s\t\t", capacity); 2211 } else { 2212 (void) printf(gettext("N/A")); |
|
1347 } 1348 | 2213 } 2214 |
1349 /* 1350 * Store the version string if we have found the beginning of it 1351 */ 1352 if (found_1) { 1353 while (x > 0) { 1354 if (rombuf[--x] == FCODE_VERS_KEY1) { 1355 if (rombuf[x-1] != FCODE_VERS_KEY1) { 1356 x++; 1357 } 1358 break; | 2215 if (attrp->state == DISK_STATE_GOOD) { 2216 (void) printf(gettext("GOOD")); 2217 } else if (attrp->state == DISK_STATE_FAILED) { 2218 (void) printf(gettext("FAILED")); 2219 } else { 2220 (void) printf(gettext("N/A")); 2221 } 2222 (void) printf("\t"); 2223 2224 /* Controller attribute */ 2225 if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) { 2226 (void) fprintf(stderr, "%s\n", raidcfg_errstr(ret)); 2227 return (FAILURE); 2228 } 2229 2230 hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP); 2231 if (hsp_handle == 0) { 2232 (void) printf(gettext("N/A\n")); 2233 } else { 2234 is_indent = FALSE; 2235 while (hsp_handle > 0) { 2236 if ((ret = raidcfg_get_attr(hsp_handle, 2237 &hsp_attr)) < 0) { 2238 (void) fprintf(stderr, "%s\n", 2239 raidcfg_errstr(ret)); 2240 return (FAILURE); |
1359 } | 2241 } |
1360 } 1361 if (x > 0) { 1362 *fcodeversion = (char *)malloc(rombuf[x] + 1); 1363 for (y = 0; y < rombuf[x]; y++) { 1364 (*fcodeversion)[y] = rombuf[x+y+1]; | 2242 2243 if (is_indent == TRUE) { 2244 (void) printf("\t\t\t\t\t\t\t"); 2245 } else { 2246 is_indent = TRUE; |
1365 } | 2247 } |
1366 (*fcodeversion)[y] = '\0'; 1367 } else { 1368 found_1 = 0; 1369 } 1370 } | |
1371 | 2248 |
1372 /* 1373 * Scan through the bios/fcode file to get the Bios version 1374 * "@(#)" string indicates the start of the Bios version string 1375 * Append this version string, after already existing fcode version. 1376 */ 1377 if (no_of_images == 2) { 1378 for (x = 0; x < (nbytes - 4); x++) { 1379 if ((rombuf[x] == '@') && (rombuf[x+1] == '(') && 1380 (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) { 1381 found_2 = 1; 1382 break; | 2249 if (hsp_attr.type == HSP_TYPE_LOCAL) { 2250 (void) snprintf(hsp, sizeof (hsp), 2251 "c%ut%llud%llu", 2252 ctl_attr.controller_id, 2253 hsp_attr.tag.idl.target_id, 2254 hsp_attr.tag.idl.lun); 2255 (void) printf("%s\n", hsp); 2256 } else if (hsp_attr.type == HSP_TYPE_GLOBAL) { 2257 (void) printf(gettext("Global\n")); 2258 } else { 2259 return (FAILURE); |
1383 } | 2260 } |
1384 } | |
1385 | 2261 |
1386 if (found_2) { 1387 x += 4; 1388 (*fcodeversion)[y] = '\n'; 1389 size = y + strlen((char *)(rombuf + x)) + 1390 strlen(BIOS_STR) + 2; 1391 *fcodeversion = (char *)realloc((*fcodeversion), size); 1392 y++; 1393 (*fcodeversion)[y] = '\0'; 1394 (void) strlcat(*fcodeversion, BIOS_STR, size); 1395 (void) strlcat(*fcodeversion, (char *)(rombuf + x), 1396 size); | 2262 hsp_handle = raidcfg_list_next(hsp_handle); |
1397 } 1398 } | 2263 } 2264 } |
1399 1400 return ((found_1 || found_2) ? 0 : 1); | 2265 return (SUCCESS); |
1401} 1402 | 2266} 2267 |
2268 2269/* 2270 * print_indent(indent) 2271 * This function prints specified number of tab characters. It's used to 2272 * format layout. 2273 */ |
|
1403static void | 2274static void |
1404getfwver(uint8_t *rombuf, char *fwversion) | 2275print_indent(uint8_t indent) |
1405{ | 2276{ |
1406 (void) snprintf(fwversion, 8, "%d.%.2d.%.2d.%.2d", 1407 rombuf[FW_ROM_OFFSET_VERSION + 3], 1408 rombuf[FW_ROM_OFFSET_VERSION + 2], 1409 rombuf[FW_ROM_OFFSET_VERSION + 1], 1410 rombuf[FW_ROM_OFFSET_VERSION + 0]); | 2277 uint32_t i; 2278 for (i = 0; i < indent; i++) { 2279 (void) fprintf(stdout, "\t"); 2280 } |
1411} 1412 | 2281} 2282 |
2283/* 2284 * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp) 2285 * This function parses the string of disk argument, and gets the disks tag 2286 * and separators from the string. Then it translates the tag to handle, and 2287 * stores handles and separators to new buffer pointed by parameter handlespp. 2288 * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first 2289 * "0" is channel number, and the second "1" is target number, and the third 2290 * "0" is LUN number. The disk tags are separated by comma and parenthesis. 2291 * Function returns SUCCESS or FAILURE. 2292 */ |
|
1413static int | 2293static int |
1414getbioscodever(uint8_t *rombuf, uint32_t nbytes, char **biosversion) | 2294get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, int *comps_nump, 2295 raid_obj_handle_t **handlespp) |
1415{ | 2296{ |
1416 int x, size; 1417 int found = 0; | 2297 int len = 0; 2298 int i = 0, j = 0; 2299 char *p, *t; 2300 char *delimit = " "; 2301 char *disks_str; 2302 disk_tag_t disk_tag; |
1418 | 2303 |
1419 for (x = 0; x < (nbytes - 4); x++) { 1420 if ((rombuf[x] == '@') && (rombuf[x+1] == '(') && 1421 (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) { 1422 found = 1; 1423 break; 1424 } | 2304 if (disks_argp == NULL || comps_nump == NULL) { 2305 return (FAILURE); |
1425 } 1426 | 2306 } 2307 |
1427 if (found) { 1428 x += 4; 1429 size = strlen((char *)(rombuf + x)) + strlen(BIOS_STR) + 1; 1430 *biosversion = (char *)realloc((*biosversion), size); 1431 bcopy((char *)(rombuf + x), *biosversion, size - 1); 1432 (*biosversion)[size - 1] = '\0'; | 2308 p = disks_argp; 2309 len = strlen(disks_argp); 2310 2311 if ((disks_str = (char *)malloc(3 * len + 4)) == NULL) { 2312 return (FAILURE); |
1433 } 1434 | 2313 } 2314 |
1435 return (found); | 2315 /* Insert whitespace between disk tags, '(' , and ')' */ 2316 disks_str[j ++] = '('; 2317 disks_str[j ++] = ' '; |
1436 | 2318 |
2319 while (p[i] != '\0') { 2320 if (p[i] == ')' || p[i] == '(') { 2321 disks_str[j ++] = ' '; 2322 disks_str[j ++] = p[i]; 2323 disks_str[j ++] = ' '; 2324 } else 2325 disks_str[j ++] = p[i]; 2326 i ++; 2327 } 2328 disks_str[j ++] = ' '; 2329 disks_str[j ++] = ')'; 2330 disks_str[j] = '\0'; 2331 2332 len = strlen(disks_str) + 1; 2333 2334 if ((t = (char *)malloc(len)) == NULL) { 2335 return (FAILURE); 2336 } 2337 (void) memcpy(t, disks_str, len); 2338 p = strtok(t, delimit); 2339 while (p != NULL) { 2340 (*comps_nump)++; 2341 p = strtok(NULL, delimit); 2342 } 2343 free(t); 2344 2345 *handlespp = calloc(*comps_nump, sizeof (raid_obj_handle_t)); 2346 if (*handlespp == NULL) { 2347 return (FAILURE); 2348 } 2349 2350 for (i = 0; i < *comps_nump; i++) 2351 (*handlespp)[i] = INIT_HANDLE_VALUE; 2352 2353 i = 0; 2354 p = strtok(disks_str, delimit); 2355 while (p != NULL) { 2356 if (*p == '(') { 2357 (*handlespp)[i] = OBJ_SEPARATOR_BEGIN; 2358 } else if (*p == ')') { 2359 (*handlespp)[i] = OBJ_SEPARATOR_END; 2360 } else { 2361 if (get_disk_tag_cidl(p, &disk_tag) != SUCCESS) { 2362 free(*handlespp); 2363 free(disks_str); 2364 return (INVALID_ARG); 2365 } 2366 (*handlespp)[i] = 2367 raidcfg_get_disk(raidcfg_get_controller(ctl_tag), 2368 disk_tag); 2369 if ((*handlespp)[i] <= 0) { 2370 (void) fprintf(stderr, "%s\n", 2371 raidcfg_errstr((*handlespp)[i])); 2372 free(*handlespp); 2373 free(disks_str); 2374 return (FAILURE); 2375 } 2376 } 2377 p = strtok(NULL, delimit); 2378 i++; 2379 } 2380 2381 free(disks_str); 2382 return (SUCCESS); |
|
1437} 1438 | 2383} 2384 |
2385/* 2386 * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep) 2387 * This function parses string of single disk with "ctd" format, for example, 2388 * c0t0d0, and translates it to controller tag and disk tag. 2389 * Then it calls lib api and get disk handle. The controller tag and disk 2390 * handle are both returned by out parameters. 2391 * The return value is SUCCESS or FAILURE. 2392 */ |
|
1439static int | 2393static int |
1440checkfile(uint8_t *rombuf, uint32_t nbytes, uint32_t chksum, int *imagetype) | 2394get_disk_handle_ctd(int disks_num, char **disks_argpp, uint32_t *ctl_tagp, 2395 raid_obj_handle_t *disks_handlep) |
1441{ | 2396{ |
1442 char *imageversion = NULL; 1443 char *biosversion = NULL; 1444 char *fwversion; | 2397 raid_obj_handle_t ctl_handle; 2398 disk_tag_t disk_tag; 2399 uint32_t ctl_id; 2400 int i; 2401 int ret; |
1445 | 2402 |
1446 fwversion = (char *)malloc(8); | 2403 if (disks_handlep == NULL) { 2404 return (FAILURE); 2405 } |
1447 | 2406 |
1448 if (gw(&rombuf[0]) == PCIROM_SIG) { | 2407 for (i = 0; i < disks_num; i++) { 2408 if (get_disk_tag_ctd(disks_argpp[i], &disk_tag, &ctl_id) != 2409 SUCCESS) { 2410 return (INVALID_ARG); 2411 } |
1449 | 2412 |
1450 *imagetype = UNKNOWN_IMAGE; 1451 getimagetype(rombuf, imagetype); | 2413 *ctl_tagp = ctl_id; |
1452 | 2414 |
1453 if (*imagetype == FCODE_IMAGE) { 1454 if (getfcodever(rombuf, nbytes, &imageversion) == 0 && 1455 imageversion != NULL) { 1456 (void) printf(gettext("Image file contains " 1457 "fcode version \t%s\n"), imageversion); 1458 free(imageversion); | 2415 if (i == 0) { 2416 ctl_handle = raidcfg_get_controller(*ctl_tagp); 2417 if (ctl_handle <= 0) { 2418 (void) fprintf(stderr, "%s\n", 2419 raidcfg_errstr(ctl_handle)); 2420 return (FAILURE); |
1459 } | 2421 } |
1460 } else if (*imagetype == BIOS_IMAGE) { 1461 if (getbioscodever(rombuf, nbytes, &biosversion) == 1 && 1462 biosversion != NULL) { 1463 (void) printf(gettext("Image file contains " 1464 "BIOS version \t%s\n"), biosversion); 1465 free(biosversion); | 2422 ret = raidcfg_open_controller(ctl_handle, NULL); 2423 if (ret < 0) { 2424 (void) fprintf(stderr, "%s\n", 2425 raidcfg_errstr(ret)); 2426 return (FAILURE); |
1466 } | 2427 } |
1467 } else { 1468 /* When imagetype equals to UNKNOWN_IMAGE */ 1469 return (-1); | |
1470 } 1471 | 2428 } 2429 |
1472 } else if (gw(&rombuf[3]) == FW_ROM_ID) { 1473 if (chksum != 0) { 1474 (void) fprintf(stderr, 1475 gettext("The ROM checksum appears bad " 1476 "(%d)\n"), chksum); 1477 return (-1); 1478 } 1479 getfwver(rombuf, fwversion); | 2430 if ((disks_handlep[i] = 2431 raidcfg_get_disk(ctl_handle, disk_tag)) < 0) { 2432 (void) fprintf(stderr, "%s\n", 2433 raidcfg_errstr(disks_handlep[i])); 2434 (void) raidcfg_close_controller(ctl_handle, NULL); 2435 return (FAILURE); 2436 } 2437 } |
1480 | 2438 |
1481 if ((gw(&rombuf[FW_ROM_OFFSET_CHIP_TYPE]) & 1482 MPI_FW_HEADER_PID_PROD_MASK) == 1483 MPI_FW_HEADER_PID_PROD_IM_SCSI) { 1484 (void) printf(gettext("ROM image contains " 1485 "MPT firmware version %s " 1486 "(w/Integrated Mirroring)\n"), 1487 fwversion); 1488 } else { 1489 (void) printf(gettext("ROM image contains " 1490 "MPT firmware ""version %s\n"), 1491 fwversion); 1492 } 1493 free(fwversion); 1494 } else { | 2439 return (SUCCESS); 2440} |
1495 | 2441 |
1496#ifdef DEBUG 1497 (void) fprintf(stderr, "Not valid FCODE image %x\n", gw(&rombuf[0])); 1498#else 1499 (void) fprintf(stderr, gettext("Not valid FCODE image\n")); 1500#endif 1501 return (-1); | 2442/* 2443 * get_ctl_tag(argp) 2444 * This function translates controller string to tag. The return value is 2445 * SUCCESS if the string has legal format and is parsed successfully, 2446 * or FAILURE if it fails. 2447 */ 2448static int 2449get_ctl_tag(char *argp, uint32_t *ctl_tagp) 2450{ 2451 if (argp == NULL || is_fully_numeric(argp) == FALSE || 2452 ctl_tagp == NULL) { 2453 return (FAILURE); |
1502 } | 2454 } |
1503 return (0); | 2455 *ctl_tagp = (atoi(argp)); 2456 return (SUCCESS); |
1504} 1505 | 2457} 2458 |
2459/* 2460 * get_array_tag(argp, ctl_tagp, array_tagp) 2461 * This function parses array string to get array tag and controller tag. 2462 * The return value is SUCCESS if the string has legal format, or 2463 * FAILURE if it fails. 2464 */ |
|
1506static int | 2465static int |
1507updateflash(uint8_t *rombuf, uint32_t nbytes, char *devctl) | 2466get_array_tag(char *argp, uint32_t *ctl_tagp, array_tag_t *array_tagp) |
1508{ | 2467{ |
1509 int fd = 0; 1510 update_flash_t flashdata; | 2468 char *t = NULL; 2469 char *cp = NULL; 2470 char *tp = NULL; 2471 char *dp = NULL; |
1511 | 2472 |
1512 fd = open(devctl, O_RDONLY); 1513 if (fd == -1) { 1514 perror(devctl); 1515 return (-1); | 2473 uint32_t value_c = MAX32BIT; 2474 uint32_t value_t = MAX32BIT; 2475 uint32_t value_d = MAX32BIT; 2476 2477 int len = 0; 2478 2479 if (argp == NULL || (len = strlen(argp)) == 0 || 2480 array_tagp == NULL) { 2481 return (FAILURE); |
1516 } | 2482 } |
1517 (void) memset(&flashdata, 0, sizeof (flashdata)); 1518 flashdata.ptrbuffer = (caddr_t)rombuf; 1519 flashdata.size = nbytes; 1520 if ((rombuf[0] == 0x55) && (rombuf[1] == 0xaa)) { 1521 flashdata.type = FW_TYPE_FCODE; 1522 } else { 1523 flashdata.type = FW_TYPE_UCODE; | 2483 2484 t = (char *)malloc(len + 1); 2485 if (t == NULL) { 2486 return (FAILURE); |
1524 } 1525 | 2487 } 2488 |
1526 if (ioctl(fd, RAID_UPDATEFW, &flashdata)) { 1527 raidctl_error("RAID_UPDATEFW"); 1528 (void) close(fd); 1529 return (-1); | 2489 (void) memcpy(t, argp, len + 1); 2490 2491 /* Now remmber to release t memory if exception occurs */ 2492 if (((dp = strchr(t, 'd')) == NULL) || 2493 ((tp = strchr(t, 't')) == NULL) || 2494 ((cp = strchr(t, 'c')) == NULL)) { 2495 free(t); 2496 return (FAILURE); |
1530 } | 2497 } |
2498 cp = t; |
|
1531 | 2499 |
1532 (void) close(fd); 1533 return (0); | 2500 *dp = '\0'; 2501 dp++; 2502 *tp = '\0'; 2503 tp++; 2504 cp++; 2505 2506 if (is_fully_numeric(dp) == FALSE || 2507 is_fully_numeric(tp) == FALSE || 2508 is_fully_numeric(cp) == FALSE) { 2509 free(t); 2510 return (FAILURE); 2511 } 2512 2513 value_c = atoi(cp); 2514 value_t = atoi(tp); 2515 value_d = atoi(dp); 2516 2517 array_tagp->idl.target_id = value_t; 2518 array_tagp->idl.lun = value_d; 2519 2520 if (ctl_tagp != NULL) { 2521 *ctl_tagp = value_c; 2522 } 2523 2524 free(t); 2525 return (SUCCESS); |
1534} 1535 | 2526} 2527 |
2528/* 2529 * get_disk_tag_ctd(argp, disk_tagp) 2530 * This function parses disk string of ctd format, and translates it to 2531 * disk tag and controller tag. The tags is returned by out parameters. 2532 * The return value is SUCCESS if the string has legal format, or FAILURE 2533 * if it fails. 2534 */ |
|
1536static int | 2535static int |
1537readfile(char *filespec, uint8_t **rombuf, uint32_t *nbytes, uint32_t *chksum) | 2536get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, uint32_t *ctl_tag) |
1538{ | 2537{ |
1539 struct stat statbuf; 1540 uint32_t count; 1541 uint32_t checksum = 0; 1542 int fd, i; 1543 uint8_t *filebuf; | 2538 char *t = NULL; 2539 char *cp = NULL; 2540 char *tp = NULL; 2541 char *dp = NULL; |
1544 | 2542 |
2543 uint32_t value_c = MAX32BIT; 2544 uint32_t value_t = MAX32BIT; 2545 uint32_t value_d = MAX32BIT; |
|
1545 | 2546 |
1546 if ((fd = open((const char *)filespec, O_RDONLY | O_NDELAY)) == -1) { 1547 perror(filespec); 1548 return (-1); | 2547 int len = 0; 2548 2549 if (argp == NULL || (len = strlen(argp)) == 0 || 2550 disk_tagp == NULL) { 2551 return (FAILURE); |
1549 } 1550 | 2552 } 2553 |
1551 if (fstat(fd, &statbuf) != 0) { 1552 perror("fstat"); 1553 (void) fprintf(stderr, 1554 gettext("Error getting stats on file\n")); 1555 (void) close(fd); 1556 return (-1); | 2554 t = (char *)malloc(len + 1); 2555 if (t == NULL) { 2556 return (FAILURE); |
1557 } 1558 | 2557 } 2558 |
1559#ifdef DEBUG 1560 (void) printf("Filesize = %ld\n", statbuf.st_size); 1561#endif | 2559 (void) memcpy(t, argp, len + 1); |
1562 | 2560 |
1563 filebuf = (uint8_t *)realloc(*rombuf, statbuf.st_size + *nbytes); | 2561 /* Now remmber to release t memory if exception occurs */ 2562 if (((dp = strchr(t, 'd')) == NULL) || 2563 ((tp = strchr(t, 't')) == NULL) || 2564 ((cp = strchr(t, 'c')) == NULL)) { 2565 free(t); 2566 return (FAILURE); 2567 } 2568 cp = t; |
1564 | 2569 |
1565 count = read(fd, filebuf + *nbytes, statbuf.st_size); 1566 (void) close(fd); 1567 if (count != statbuf.st_size) { 1568 perror("size check"); 1569 (void) fprintf(stderr, gettext("File is corrupt\n")); 1570 return (-1); | 2570 *dp = '\0'; 2571 dp++; 2572 *tp = '\0'; 2573 tp++; 2574 cp++; 2575 2576 if (is_fully_numeric(dp) == FALSE || 2577 is_fully_numeric(tp) == FALSE || 2578 is_fully_numeric(cp) == FALSE) { 2579 free(t); 2580 return (FAILURE); |
1571 } 1572 | 2581 } 2582 |
1573 for (i = 0; i < *nbytes; i++) 1574 checksum += filebuf[i] << (8 * (i & 3)); | 2583 value_c = atoi(cp); 2584 value_t = atoi(tp); 2585 value_d = atoi(dp); |
1575 | 2586 |
1576 *rombuf = filebuf; 1577 *nbytes = *nbytes + count; 1578 *chksum = checksum; | 2587 disk_tagp->cidl.bus = 0; 2588 disk_tagp->cidl.target_id = value_t; 2589 disk_tagp->cidl.lun = value_d; 2590 *ctl_tag = value_c; |
1579 | 2591 |
1580 return (0); | 2592 free(t); 2593 return (SUCCESS); |
1581} 1582 | 2594} 2595 |
2596/* 2597 * get_disk_tag_cidl(argp, disk_tagp) 2598 * This function parses disk string of cidl format and translates it to tag. 2599 * The return value is disk tag if the string has legal format, or FAILURE 2600 * if it fails. 2601 */ |
|
1583static int | 2602static int |
1584yes(void) | 2603get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp) |
1585{ | 2604{ |
1586 int i, b; 1587 char ans[SCHAR_MAX + 1]; | 2605 int len = 0; 2606 char *p = NULL; 2607 char *t = NULL; 2608 char *dot1p = NULL; 2609 char *dot2p = NULL; |
1588 | 2610 |
1589 for (i = 0; ; i++) { 1590 b = getchar(); 1591 if (b == '\n' || b == '\0' || b == EOF) { 1592 ans[i] = 0; 1593 break; 1594 } 1595 if (i < SCHAR_MAX) 1596 ans[i] = b; | 2611 if (argp == NULL || (len = strlen(argp)) == 0) { 2612 return (FAILURE); |
1597 } | 2613 } |
1598 if (i >= SCHAR_MAX) { 1599 i = SCHAR_MAX; 1600 ans[SCHAR_MAX] = 0; | 2614 2615 if (disk_tagp == NULL) { 2616 return (FAILURE); |
1601 } | 2617 } |
1602 if ((i != 0) && ((strncmp(yeschr, ans, i)) == 0)) 1603 return (1); | |
1604 | 2618 |
1605 return (0); 1606} | 2619 t = (char *)malloc(len + 1); 2620 if (t == NULL) { 2621 return (FAILURE); 2622 } |
1607 | 2623 |
1608static int 1609do_flash(int c, char *fpath, int force) 1610{ 1611 char devctl[MAXPATHLEN] = {0}; 1612 char buf[MAXPATHLEN] = {0}; 1613 int rv = 0; 1614 int imagetype; 1615 uint32_t nbytes = 0; 1616 uint32_t chksum; 1617 uint8_t *rombuf = NULL; 1618 char cwd[MAXPATHLEN]; | 2624 (void) memcpy(t, argp, len + 1); 2625 p = t; |
1619 | 2626 |
1620 /* 1621 * Read fw file 1622 */ 1623 rv = readfile(fpath, &rombuf, &nbytes, &chksum); 1624 if (rv != 0) { | 2627 dot2p = strrchr(p, '.'); 2628 if (dot2p == NULL) { 2629 free(t); |
1625 return (FAILURE); 1626 } | 2630 return (FAILURE); 2631 } |
2632 *dot2p = '\0'; 2633 dot2p++; |
|
1627 | 2634 |
1628 (void) getcwd(cwd, sizeof (cwd)); | 2635 dot1p = strrchr(p, '.'); 2636 if (dot1p == NULL) { 2637 free(t); 2638 return (FAILURE); 2639 } 2640 *dot1p = '\0'; 2641 dot1p++; |
1629 | 2642 |
1630 (void) chdir(DEVDIR); | 2643 /* Assert only 2 dots in this string */ 2644 if (strrchr(p, '.') != NULL) { 2645 free(t); 2646 return (FAILURE); 2647 } |
1631 | 2648 |
1632 /* Get link from "/dev/cfg" */ 1633 (void) snprintf(buf, sizeof (buf), "/dev/cfg/c%d", c); 1634 if (get_link_path(buf, devctl) != 0) { 1635 (void) fprintf(stderr, 1636 gettext("Invalid controller '%d'\n"), c); | 2649 while (*p == ' ') 2650 p++; 2651 2652 if (is_fully_numeric(p) == FALSE || 2653 is_fully_numeric(dot1p) == FALSE || 2654 is_fully_numeric(dot2p) == FALSE) { 2655 free(t); 2656 return (FAILURE); 2657 } 2658 2659 disk_tagp->cidl.bus = atoi(p); 2660 disk_tagp->cidl.target_id = atoi(dot1p); 2661 disk_tagp->cidl.lun = atoi(dot2p); 2662 2663 free(t); 2664 return (SUCCESS); 2665} 2666 2667/* 2668 * calc_size(sizep, valp) 2669 * This function calculates the value represented by string sizep. 2670 * The string sizep can be decomposed into three parts: an initial, 2671 * possibly empty, sequence of white-space characters; a subject digital 2672 * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a 2673 * final string of one or more unrecognized characters or white-sapce 2674 * characters, including the terminating null. If unrecognized character 2675 * exists or overflow happens, the conversion must fail and return 2676 * INVALID_ARG. If the conversion is performed successfully, result will 2677 * be saved into valp and function returns SUCCESS. It returns FAILURE 2678 * when memory allocation fails. 2679 */ 2680static int 2681calc_size(char *sizep, uint64_t *valp) 2682{ 2683 int len; 2684 uint64_t size; 2685 uint64_t unit; 2686 char *t = NULL; 2687 char *tailp = NULL; 2688 2689 if (sizep == NULL || valp == NULL) { |
1637 return (INVALID_ARG); 1638 } 1639 | 2690 return (INVALID_ARG); 2691 } 2692 |
1640 /* Check File */ 1641 rv = checkfile(rombuf, nbytes, chksum, &imagetype); 1642 if (rv != 0) { | 2693 len = strlen(sizep); 2694 if (len == 0) { 2695 return (INVALID_ARG); 2696 } 2697 2698 t = (char *)malloc(len + 1); 2699 if (t == NULL) { |
1643 return (FAILURE); 1644 } 1645 | 2700 return (FAILURE); 2701 } 2702 |
1646 /* Confirm */ 1647 if (!force) { 1648 (void) fprintf(stderr, gettext("Update flash image on " 1649 "controller %d (%s/%s)? "), c, yeschr, nochr); 1650 if (!yes()) { 1651 (void) fprintf(stderr, gettext("Controller %d not " 1652 "flashed.\n\n"), c); 1653 return (SUCCESS); 1654 } | 2703 (void) memcpy(t, sizep, len + 1); 2704 2705 switch (*(t + len - 1)) { 2706 case 'k': 2707 case 'K': 2708 unit = 1024ull; 2709 errno = 0; 2710 size = strtoll(t, &tailp, 0); 2711 break; 2712 case 'm': 2713 case 'M': 2714 unit = 1024ull * 1024ull; 2715 errno = 0; 2716 size = strtoll(t, &tailp, 0); 2717 break; 2718 case 'g': 2719 case 'G': 2720 unit = 1024ull * 1024ull * 1024ull; 2721 errno = 0; 2722 size = strtoll(t, &tailp, 0); 2723 break; 2724 case 't': 2725 case 'T': 2726 unit = 1024ull * 1024ull * 1024ull * 1024ull; 2727 errno = 0; 2728 size = strtoll(t, &tailp, 0); 2729 break; 2730 default: 2731 /* The unit must be kilobyte at least. */ 2732 free(t); 2733 return (INVALID_ARG); |
1655 } 1656 | 2734 } 2735 |
1657 /* Do Flash */ 1658 if (updateflash(rombuf, nbytes, devctl)) { 1659 (void) fprintf(stderr, gettext("Flash not updated on " 1660 "Controller %d.\n\n"), c); | 2736 *(t + len - 1) = '\0'; 2737 if (is_fully_numeric(t) != TRUE) { 2738 free(t); |
1661 return (INVALID_ARG); 1662 } | 2739 return (INVALID_ARG); 2740 } |
1663 (void) printf(gettext("Flash updated successfully.\n\n")); 1664 return (SUCCESS); 1665} | |
1666 | 2741 |
1667static int 1668fully_numeric(char *str) 1669{ 1670 int size = strlen(str); 1671 int i; | 2742 errno = 0; 2743 size = strtoll(t, &tailp, 0); |
1672 | 2744 |
1673 for (i = 0; i < size; i++) { 1674 if (i == 0 && str[i] == '-' && size != 1) 1675 continue; 1676 if (!isdigit(str[i])) 1677 return (0); | 2745 /* Check overflow condition */ 2746 if (errno == ERANGE || (size > (MAX64BIT / unit))) { 2747 free(t); 2748 return (INVALID_ARG); |
1678 } | 2749 } |
1679 return (1); | 2750 2751 *valp = size * unit; 2752 free(t); 2753 return (SUCCESS); |
1680} 1681 1682/* | 2754} 2755 2756/* |
1683 * Useful parsing macros | 2757 * is_fully_numeric(str) 2758 * This function checks if the string are legal numeric string. The beginning 2759 * or ending characters can be white spaces. 2760 * Return value is TRUE if the string are legal numeric string, or FALSE 2761 * otherwise. |
1684 */ | 2762 */ |
1685#define must_be(s, c) if (*s++ != c) return (0) 1686#define skip_digits(s) while (isdigit(*s)) s++ 1687 1688/* 1689 * Return true if a name is in the internal canonical form 1690 */ | |
1691static int | 2763static int |
1692canonical_name(char *name) | 2764is_fully_numeric(char *strp) |
1693{ | 2765{ |
1694 must_be(name, 'c'); 1695 skip_digits(name); 1696 if (*name == 't') { 1697 name++; 1698 skip_digits(name); | 2766 uint32_t len; 2767 uint32_t i; 2768 2769 if (strp == NULL) { 2770 return (FALSE); |
1699 } | 2771 } |
1700 must_be(name, 'd'); 1701 skip_digits(name); 1702 return (*name == 0); 1703} | |
1704 | 2772 |
1705int 1706main(int argc, char **argv) 1707{ 1708 int rv = SUCCESS; 1709 int i, c; 1710 int findex = DO_HW_RAID_INFO; 1711 int controller; 1712 char *disks[N_DISKS] = {0}; 1713 char *darg; 1714 char *farg; 1715 char *rarg; 1716 char *progname; | 2773 len = strlen(strp); 2774 if (len == 0) { 2775 return (FALSE); 2776 } |
1717 | 2777 |
1718 int l_flag = 0; 1719 int c_flag = 0; 1720 int d_flag = 0; 1721 int f_flag = 0; 1722 int F_flag = 0; 1723 int r_flag = 0; 1724 int no_flags = 1; 1725 int r = RAID_MIRROR; /* default raid level is 1 */ 1726 char *current_dir; | 2778 /* Skip whitespace characters */ 2779 for (i = 0; i < len; i++) { 2780 if (strp[i] != ' ') { 2781 break; 2782 } 2783 } |
1727 | 2784 |
1728 (void) setlocale(LC_ALL, ""); 1729 (void) textdomain(TEXT_DOMAIN); | 2785 /* if strp points all space characters */ 2786 if (i == len) { 2787 return (FALSE); 2788 } |
1730 | 2789 |
1731 if (geteuid() != 0) { 1732 (void) fprintf(stderr, gettext("Must be root.\n")); 1733 exit(1); | 2790 /* Check the digitals in string */ 2791 for (; i < len; i++) { 2792 if (!isdigit(strp[i])) { 2793 break; 2794 } |
1734 } 1735 | 2795 } 2796 |
1736 if ((progname = strrchr(argv[0], '/')) == NULL) 1737 progname = argv[0]; 1738 else 1739 progname++; | 2797 /* Check the ending string */ 2798 for (; i < len; i++) { 2799 if (strp[i] != ' ') { 2800 return (FALSE); 2801 } 2802 } |
1740 | 2803 |
1741 raids = NULL; | 2804 return (TRUE); 2805} |
1742 | 2806 |
1743 (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1); 1744 (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1); | 2807static int 2808yes(void) 2809{ 2810 int i, b; 2811 char ans[SCHAR_MAX + 1]; |
1745 | 2812 |
1746 while ((c = getopt(argc, argv, "cr:lfd:F:")) != EOF) { 1747 switch (c) { 1748 case 'c': 1749 if (argc < 4) 1750 usage(progname); 1751 findex = DO_HW_RAID_CREATE; 1752 c_flag = 1; 1753 no_flags = 0; | 2813 for (i = 0; ; i++) { 2814 b = getchar(); 2815 if (b == '\n' || b == '\0' || b == EOF) { 2816 ans[i] = 0; |
1754 break; | 2817 break; |
1755 case 'r': 1756 rarg = optarg; 1757 r = atoi(rarg); 1758 if ((r != RAID_STRIPE) && (r != RAID_MIRROR)) 1759 usage(progname); 1760 r_flag = 1; 1761 break; 1762 case 'd': 1763 darg = optarg; 1764 d_flag = 1; 1765 findex = DO_HW_RAID_DELETE; 1766 no_flags = 0; 1767 break; 1768 case 'l': 1769 findex = DO_HW_RAID_INFO; 1770 l_flag = 1; 1771 no_flags = 0; 1772 break; 1773 case 'F': 1774 findex = DO_HW_RAID_FLASH; 1775 farg = optarg; 1776 F_flag = 1; 1777 no_flags = 0; 1778 break; 1779 case 'f': 1780 f_flag = 1; 1781 no_flags = 0; 1782 break; 1783 case '?': 1784 default: 1785 usage(progname); | |
1786 } | 2818 } |
2819 if (i < SCHAR_MAX) { 2820 ans[i] = b; 2821 } |
|
1787 } | 2822 } |
2823 if (i >= SCHAR_MAX) { 2824 i = SCHAR_MAX; 2825 ans[SCHAR_MAX] = 0; 2826 } |
|
1788 | 2827 |
1789 if (no_flags && argc > 1) 1790 usage(progname); | 2828 return (rpmatch(ans)); 2829} |
1791 | 2830 |
1792 /* compatibility rules */ 1793 if (c_flag && d_flag) 1794 usage(progname); 1795 if (l_flag && (d_flag || c_flag || f_flag || F_flag || r_flag)) 1796 usage(progname); 1797 if (F_flag && (d_flag || c_flag || l_flag || r_flag)) 1798 usage(progname); | 2831/* 2832 * Function: int rpmatch(char *) 2833 * 2834 * Description: 2835 * 2836 * Internationalized get yes / no answer. 2837 * 2838 * Inputs: 2839 * s -> Pointer to answer to compare against. 2840 * 2841 * Returns: 2842 * TRUE -> Answer was affirmative 2843 * FALSE -> Answer was negative 2844 */ |
1799 | 2845 |
1800 switch (findex) { 1801 case DO_HW_RAID_INFO: 1802 if (l_flag) { 1803 /* 1804 * "raidctl" makes argc == 1 1805 * "-l" makes argc == 2 1806 */ 1807 ctrl_nums = argc - 2; 1808 if (ctrl_nums != 0) { 1809 info_ctrl = (int **) 1810 malloc(ctrl_nums * sizeof (int)); 1811 if (info_ctrl == NULL) 1812 return (FAILURE); 1813 } 1814 for (i = 0; i < ctrl_nums; i++) { 1815 char *tmp = argv[i + 2]; | 2846static int 2847rpmatch(char *s) 2848{ 2849 int status; |
1816 | 2850 |
1817 info_ctrl[i] = (int *)malloc(2 * sizeof (int)); 1818 if (info_ctrl[i] == NULL) { 1819 free(info_ctrl); 1820 return (FAILURE); 1821 } 1822 if (fully_numeric(tmp)) { 1823 (void) sscanf(tmp, "%d", 1824 &info_ctrl[i][INFO_CTRL]); 1825 info_ctrl[i][INFO_STATUS] = 1826 RAID_INVALID_CTRL; 1827 } else { 1828 (void) fprintf(stderr, 1829 gettext("Invalid controller '%s'\n"), 1830 tmp); 1831 info_ctrl[i][INFO_STATUS] = 1832 RAID_DONT_USE; 1833 } 1834 } 1835 } else if (argc > 1) { 1836 usage(progname); 1837 } | 2851 /* match yesexpr */ 2852 status = regexec(&re, s, (size_t)0, NULL, 0); 2853 if (status != 0) { 2854 return (FALSE); 2855 } 2856 return (TRUE); 2857} |
1838 | 2858 |
1839 do_info(); 1840 break; 1841 case DO_HW_RAID_CREATE: 1842 for (i = 0; i < N_DISKS; i++) { 1843 int p = 2 + (r_flag * 2) + f_flag + i; | 2859static int 2860size_to_string(uint64_t size, char *string, int len) 2861{ 2862 int i = 0; 2863 uint32_t remainder; 2864 char unit[][2] = {" ", "K", "M", "G", "T"}; |
1844 | 2865 |
1845 if (p == argc) 1846 break; | 2866 if (string == NULL) { 2867 return (FAILURE); 2868 } 2869 while (size > 1023) { 2870 remainder = size % 1024; 2871 size /= 1024; 2872 i++; 2873 } |
1847 | 2874 |
1848 disks[i] = argv[p]; | 2875 if (i > 4) { 2876 return (FAILURE); 2877 } |
1849 | 2878 |
1850 if (!canonical_name(disks[i])) 1851 usage(progname); | 2879 remainder /= 103; 2880 if (remainder == 0) { 2881 (void) snprintf(string, len, "%llu", size); 2882 } else { 2883 (void) snprintf(string, len, "%llu.%1u", size, 2884 remainder); 2885 } |
1852 | 2886 |
1853 /* no more than 2 disks for raid level 1 */ 1854 if ((r == RAID_MIRROR) && (i > 1)) 1855 usage(progname); 1856 } | 2887 /* make sure there is one byte for unit */ 2888 if ((strlen(string) + 1) >= len) { 2889 return (FAILURE); 2890 } 2891 (void) strcat(string, unit[i]); |
1857 | 2892 |
1858 rv = do_create(disks, r, f_flag); 1859 break; 1860 case DO_HW_RAID_DELETE: 1861 if (!canonical_name(darg)) 1862 usage(progname); | 2893 return (SUCCESS); 2894} |
1863 | 2895 |
1864 rv = do_delete(darg, f_flag); 1865 break; 1866 case DO_HW_RAID_FLASH: 1867 ctrl_nums = argc - f_flag - 3; 1868 if (ctrl_nums == 0) 1869 usage(progname); | 2896/* 2897 * Only one raidctl is running at one time. 2898 */ 2899static int 2900enter_raidctl_lock(int *fd) 2901{ 2902 int fd0 = -1; 2903 struct flock lock; |
1870 | 2904 |
1871 current_dir = getcwd(NULL, MAXPATHLEN); | 2905 fd0 = open(RAIDCTL_LOCKF, O_CREAT|O_WRONLY, 0600); 2906 if (fd0 < 0) { 2907 (void) fprintf(stderr, gettext("raidctl:failed to open lockfile" 2908 " '"RAIDCTL_LOCKF"': %s\n"), strerror(errno)); 2909 return (FAILURE); 2910 } |
1872 | 2911 |
1873 for (i = 0; i < ctrl_nums; i++) { 1874 char *tmp = argv[i + 3 + f_flag]; 1875 (void) chdir(current_dir); 1876 if (fully_numeric(tmp)) { 1877 (void) sscanf(tmp, "%d", &controller); 1878 rv = do_flash(controller, farg, f_flag); 1879 if (rv == FAILURE) 1880 break; 1881 } else { 1882 (void) fprintf(stderr, 1883 gettext("Invalid controller '%s'\n"), 1884 tmp); 1885 } | 2912 *fd = fd0; 2913 lock.l_type = F_WRLCK; 2914 lock.l_whence = SEEK_SET; 2915 lock.l_start = 0; 2916 lock.l_len = 0; 2917 2918 if ((fcntl(fd0, F_SETLK, &lock) == -1) && 2919 (errno == EAGAIN || errno == EDEADLK)) { 2920 if (fcntl(fd0, F_GETLK, &lock) == -1) { 2921 (void) fprintf(stderr, 2922 gettext("raidctl:enter_filelock error\n")); 2923 return (FAILURE); |
1886 } | 2924 } |
1887 free(current_dir); 1888 break; 1889 default: 1890 usage(progname); | 2925 (void) fprintf(stderr, gettext("raidctl:" 2926 "enter_filelock:filelock is owned " 2927 "by 'process %d'\n"), lock.l_pid); 2928 return (FAILURE); |
1891 } | 2929 } |
1892 return (rv); | 2930 2931 return (SUCCESS); |
1893} | 2932} |
2933 2934static void 2935exit_raidctl_lock(int fd) 2936{ 2937 struct flock lock; 2938 2939 lock.l_type = F_UNLCK; 2940 lock.l_whence = SEEK_SET; 2941 lock.l_start = 0; 2942 lock.l_len = 0; 2943 if (fcntl(fd, F_SETLK, &lock) == -1) { 2944 (void) fprintf(stderr, gettext("raidctl: failed to" 2945 " exit_filelock: %s\n"), 2946 strerror(errno)); 2947 } 2948 (void) close(fd); 2949} |
|