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}