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