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