xref: /onnv-gate/usr/src/cmd/raidctl/raidctl.c (revision 8856:0ee7721f3e5e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5902Syw161884  * Common Development and Distribution License (the "License").
6902Syw161884  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
203457Sjc156560  *
213457Sjc156560  *
22*8856SMilan.Jurik@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
243457Sjc156560  *
253457Sjc156560  * raidctl.c is the entry file of RAID configuration utility.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <ctype.h>
293457Sjc156560 #include <sys/types.h>
303457Sjc156560 #include <sys/stat.h>
310Sstevel@tonic-gate #include <fcntl.h>
320Sstevel@tonic-gate #include <langinfo.h>
333457Sjc156560 #include <regex.h>
343457Sjc156560 #include <locale.h>
350Sstevel@tonic-gate #include <libintl.h>
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <stdlib.h>
380Sstevel@tonic-gate #include <string.h>
390Sstevel@tonic-gate #include <strings.h>
400Sstevel@tonic-gate #include <unistd.h>
413457Sjc156560 #include <errno.h>
423457Sjc156560 #include <libgen.h>
433457Sjc156560 #include <raidcfg.h>
443457Sjc156560 
453457Sjc156560 
463457Sjc156560 #define	TRUE		1
473457Sjc156560 #define	FALSE		0
483457Sjc156560 
493457Sjc156560 #ifndef TEXT_DOMAIN
503457Sjc156560 #define	TEXT_DOMAIN "SYS_TEST"
513457Sjc156560 #endif
523457Sjc156560 
533457Sjc156560 /*
543457Sjc156560  * Return value of command
553457Sjc156560  */
563457Sjc156560 #define	SUCCESS		0
573457Sjc156560 #define	INVALID_ARG	1
583457Sjc156560 #define	FAILURE		2
593457Sjc156560 
603457Sjc156560 /*
613457Sjc156560  * Initial value of variables
623457Sjc156560  */
633457Sjc156560 #define	INIT_HANDLE_VALUE	-3
643457Sjc156560 #define	MAX64BIT		0xffffffffffffffffull
653457Sjc156560 #define	MAX32BIT		0xfffffffful
660Sstevel@tonic-gate 
670Sstevel@tonic-gate /*
683457Sjc156560  * Flag of set or unset HSP
690Sstevel@tonic-gate  */
703457Sjc156560 #define	HSP_SET		1
713457Sjc156560 #define	HSP_UNSET	0
72840Sjesseb 
730Sstevel@tonic-gate /*
743457Sjc156560  * Operate codes of command
750Sstevel@tonic-gate  */
763457Sjc156560 #define	DO_HW_RAID_NOP		-1
773457Sjc156560 #define	DO_HW_RAID_HELP		0
783457Sjc156560 #define	DO_HW_RAID_CREATEO	1
793457Sjc156560 #define	DO_HW_RAID_CREATEN	2
803457Sjc156560 #define	DO_HW_RAID_DELETE	3
813457Sjc156560 #define	DO_HW_RAID_LIST		4
823457Sjc156560 #define	DO_HW_RAID_FLASH	5
833457Sjc156560 #define	DO_HW_RAID_HSP		6
843457Sjc156560 #define	DO_HW_RAID_SET_ATTR	7
853457Sjc156560 #define	DO_HW_RAID_SNAPSHOT	8
863457Sjc156560 
873457Sjc156560 #define	LOWER_H	(1 << 0)
883457Sjc156560 #define	LOWER_C	(1 << 1)
893457Sjc156560 #define	LOWER_D	(1 << 2)
903457Sjc156560 #define	LOWER_L	(1 << 3)
913457Sjc156560 #define	LOWER_R	(1 << 4)
923457Sjc156560 #define	LOWER_Z	(1 << 5)
933457Sjc156560 #define	LOWER_G	(1 << 6)
943457Sjc156560 #define	LOWER_A	(1 << 7)
953457Sjc156560 #define	LOWER_S	(1 << 8)
963457Sjc156560 #define	LOWER_P	(1 << 9)
973457Sjc156560 #define	LOWER_F	(1 << 10)
983457Sjc156560 #define	UPPER_S	(1 << 11)
993457Sjc156560 #define	UPPER_C	(1 << 12)
1003457Sjc156560 #define	UPPER_F	(1 << 13)
1013457Sjc156560 
1023457Sjc156560 /* Add a ARRAY state (temporary) */
1033457Sjc156560 #define	ARRAY_STATE_SYNC	100
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate /*
1060Sstevel@tonic-gate  * Function and strings to properly localize our prompt.
1073457Sjc156560  * So for example in German it would ask (ja/nein) or (yes/no) in
1080Sstevel@tonic-gate  * english.
1090Sstevel@tonic-gate  */
1103457Sjc156560 #ifndef SCHAR_MAX
1113457Sjc156560 #define	SCHAR_MAX	10
1123457Sjc156560 #endif
1133457Sjc156560 
1143457Sjc156560 #define	RAIDCTL_LOCKF "/var/run/lockf_raidctl"
1153457Sjc156560 
1163457Sjc156560 /* Locale setting */
117840Sjesseb static int	yes(void);
1183457Sjc156560 static int	rpmatch(char *s);
1193457Sjc156560 static char	*yesstr = NULL;
1203457Sjc156560 static char	*nostr = NULL;
1213457Sjc156560 static char	*yesexpr = NULL;
1223457Sjc156560 
1233457Sjc156560 static char	*default_yesexpr = "^[yY]";
1243457Sjc156560 static char	*default_yesstr = "yes";
1253457Sjc156560 static char	*default_nostr = "no";
1263457Sjc156560 
1273457Sjc156560 static regex_t	re;
1283457Sjc156560 
1293457Sjc156560 #define	SET_DEFAULT_STRS \
1303457Sjc156560 	regfree(&re); \
1313457Sjc156560 	free(yesexpr); \
1323457Sjc156560 	free(yesstr); \
1333457Sjc156560 	free(nostr); \
1343457Sjc156560 	yesexpr = default_yesexpr; \
1353457Sjc156560 	yesstr = default_yesstr; \
1363457Sjc156560 	nostr = default_nostr;
1373457Sjc156560 
1383457Sjc156560 #define	FREE_STRS \
1393457Sjc156560 	if (yesexpr != default_yesexpr) \
1403457Sjc156560 		free(yesexpr); \
1413457Sjc156560 	if (yesstr != default_yesstr) \
1423457Sjc156560 		free(yesstr); \
1433457Sjc156560 	if (nostr != default_nostr) \
1443457Sjc156560 		free(nostr);
1453457Sjc156560 
1463457Sjc156560 /* program name */
1473457Sjc156560 static char	*prog_namep;
1483457Sjc156560 
1493457Sjc156560 
1503457Sjc156560 /*
1513457Sjc156560  * Functions declaration
1523457Sjc156560  */
1533457Sjc156560 static void helpinfo(char *prog_namep);
1543457Sjc156560 static int do_create_cidl(char *raid_levelp, char *capacityp, char *disk_argp,
1553457Sjc156560     char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind);
1563457Sjc156560 static int do_create_ctd(char *raid_levelp, char **disks_argpp,
1573457Sjc156560     uint32_t disks_num, uint32_t argindex, uint32_t f_flag);
1583457Sjc156560 static int do_list(char *disk_argp, char **argv, uint32_t optind,
1593457Sjc156560     uint8_t is_snapshot);
1603457Sjc156560 static int do_delete(uint32_t f_flag, char **argv, uint32_t optind);
1613457Sjc156560 static int do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
1623457Sjc156560     uint32_t index, uint32_t ctl_num);
1633457Sjc156560 static int do_set_hsp(char *a_argp, char *disk_argp, char **argv,
1643457Sjc156560     uint32_t optind);
1653457Sjc156560 static int do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv,
1663457Sjc156560     uint32_t optind);
1673457Sjc156560 static int snapshot_raidsystem(uint8_t recursive, uint8_t indent,
1683457Sjc156560     uint8_t is_snapshot);
1693457Sjc156560 static int snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive,
1703457Sjc156560     uint8_t indent, uint8_t is_snapshot);
1713457Sjc156560 static int snapshot_array(raid_obj_handle_t array_handle,
1723457Sjc156560     uint8_t indent, uint8_t is_sub, uint8_t is_snapshot);
1733457Sjc156560 static int snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle,
1743457Sjc156560     uint8_t indent, uint8_t is_snapshot);
1753457Sjc156560 static int print_ctl_table(raid_obj_handle_t ctl_handle);
1763457Sjc156560 static int print_array_table(raid_obj_handle_t ctl_handle,
1773457Sjc156560     raid_obj_handle_t array_handle);
1783457Sjc156560 static int print_disk_table(raid_obj_handle_t ctl_handle,
1793457Sjc156560     raid_obj_handle_t disk_handle);
1803457Sjc156560 static int print_ctl_attr(raidcfg_controller_t *attrp);
1813457Sjc156560 static int print_array_attr(raidcfg_array_t *attrp);
1823457Sjc156560 static int print_arraypart_attr(raidcfg_arraypart_t *attrp);
1833457Sjc156560 static int print_disk_attr(raid_obj_handle_t ctl_handle,
1843457Sjc156560     raid_obj_handle_t disk_handle, raidcfg_disk_t *attrp);
1853457Sjc156560 static void print_indent(uint8_t indent);
1863457Sjc156560 static int get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp,
1873457Sjc156560     int *comps_nump, raid_obj_handle_t **handlespp);
1883457Sjc156560 static int get_disk_handle_ctd(int disks_num, char **disks_argpp,
1893457Sjc156560     uint32_t *ctl_tagp, raid_obj_handle_t *disks_handlep);
1903457Sjc156560 static int get_ctl_tag(char *argp, uint32_t *ctl_tagp);
1913457Sjc156560 static int get_array_tag(char *argp, uint32_t *ctl_tagp,
1923457Sjc156560     array_tag_t *array_tagp);
1933457Sjc156560 static int get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp,
1943457Sjc156560     uint32_t *controller_id);
1953457Sjc156560 static int get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp);
1963457Sjc156560 static int calc_size(char *sizep, uint64_t *valp);
1973457Sjc156560 static int is_fully_numeric(char *strp);
1983457Sjc156560 static int size_to_string(uint64_t size, char *string, int len);
1993457Sjc156560 static int enter_raidctl_lock(int *fd);
2003457Sjc156560 static void exit_raidctl_lock(int fd);
2010Sstevel@tonic-gate 
202840Sjesseb /*
2033457Sjc156560  * Entry function of raidctl command
204840Sjesseb  */
2053457Sjc156560 int
main(int argc,char ** argv)2063457Sjc156560 main(int argc, char **argv)
2070Sstevel@tonic-gate {
2083457Sjc156560 	/* operation index */
2093457Sjc156560 	int8_t findex = DO_HW_RAID_NOP;
2103457Sjc156560 
2113457Sjc156560 	/* argument pointers */
2123457Sjc156560 	char *r_argp = NULL;
2133457Sjc156560 	char *z_argp = NULL;
2143457Sjc156560 	char *g_argp = NULL;
2153457Sjc156560 	char *a_argp = NULL;
2163457Sjc156560 	char *s_argp = NULL;
2173457Sjc156560 	char *p_argp = NULL;
2183457Sjc156560 	char *F_argp = NULL;
2193457Sjc156560 	char *C_argp = NULL;
2203457Sjc156560 
2213457Sjc156560 	/*
2223457Sjc156560 	 * operation flags.
2233457Sjc156560 	 */
2243457Sjc156560 	uint8_t r_flag = FALSE;
2253457Sjc156560 	uint8_t f_flag = FALSE;
2263457Sjc156560 	uint8_t action = FALSE;
2273457Sjc156560 	uint64_t options = 0;
2283457Sjc156560 
2293457Sjc156560 	/* index and temporary variables */
2303457Sjc156560 	int ret;
2313457Sjc156560 	int status;
2323457Sjc156560 	char c = '\0';
2333457Sjc156560 
2343457Sjc156560 	/* fd for the filelock */
2353457Sjc156560 	int fd;
2363457Sjc156560 
2373457Sjc156560 	if (enter_raidctl_lock(&fd) != SUCCESS) {
2383457Sjc156560 		return (FAILURE);
2393457Sjc156560 	}
2403457Sjc156560 
2413457Sjc156560 	(void) setlocale(LC_ALL, "");
2423457Sjc156560 	(void) textdomain(TEXT_DOMAIN);
2433457Sjc156560 
2443457Sjc156560 	/* parse command line, and get program name */
2453457Sjc156560 	if ((prog_namep = strrchr(argv[0], '/')) == NULL) {
2463457Sjc156560 		prog_namep = argv[0];
2473457Sjc156560 	} else {
2483457Sjc156560 		prog_namep++;
2493457Sjc156560 	}
2503457Sjc156560 
2513457Sjc156560 	/* close error option messages from getopt */
2523457Sjc156560 	opterr = 0;
2533457Sjc156560 
2543457Sjc156560 	/* get yes expression according to current locale */
2553457Sjc156560 	yesexpr = strdup(nl_langinfo(YESEXPR));
2563457Sjc156560 	yesstr = strdup(nl_langinfo(YESSTR));
2573457Sjc156560 	nostr = strdup(nl_langinfo(NOSTR));
2583457Sjc156560 	if (yesexpr == NULL || yesstr == NULL || nostr == NULL) {
2593457Sjc156560 		return (FAILURE);
2603457Sjc156560 	}
2613457Sjc156560 
2623457Sjc156560 	/*
2633457Sjc156560 	 * If the was no expression or if there is a compile error
2643457Sjc156560 	 * use default yes expression.
2653457Sjc156560 	 */
2663457Sjc156560 	status = regcomp(&re, yesexpr, REG_EXTENDED | REG_NOSUB);
2673457Sjc156560 	if ((*yesexpr == (char)NULL) ||
2683457Sjc156560 	    (*yesstr == (char)NULL) ||
2693457Sjc156560 	    (*nostr == (char)NULL) ||
2703457Sjc156560 	    (status != 0)) {
2713457Sjc156560 		SET_DEFAULT_STRS;
2723457Sjc156560 		if (regcomp(&re, default_yesexpr,
2733457Sjc156560 		    REG_EXTENDED | REG_NOSUB) != 0) {
2743457Sjc156560 			return (FALSE);
2753457Sjc156560 		}
2763457Sjc156560 	}
2773457Sjc156560 
2783457Sjc156560 	while ((c = getopt(argc, argv,
2793457Sjc156560 	    "?hC:cdlF:r:z:g:a:s:p:fS")) != EOF) {
2803457Sjc156560 		switch (c) {
2813457Sjc156560 		case 'h':
2823457Sjc156560 		case '?':
2833457Sjc156560 			if (action == FALSE) {
2843457Sjc156560 				findex = DO_HW_RAID_HELP;
2853457Sjc156560 				action = TRUE;
2863457Sjc156560 				options |= LOWER_H;
2873457Sjc156560 			} else {
2883457Sjc156560 				findex = DO_HW_RAID_NOP;
2893457Sjc156560 			}
2903457Sjc156560 			break;
2913457Sjc156560 		case 'C':
2923457Sjc156560 			if (action == FALSE) {
2933457Sjc156560 				findex = DO_HW_RAID_CREATEN;
2943457Sjc156560 				C_argp = optarg;
2953457Sjc156560 				action = TRUE;
2963457Sjc156560 				options |= UPPER_C;
2973457Sjc156560 			} else {
2983457Sjc156560 				findex = DO_HW_RAID_NOP;
2993457Sjc156560 			}
3003457Sjc156560 			break;
3013457Sjc156560 		case 'c':
3023457Sjc156560 			if (action == FALSE) {
3033457Sjc156560 				findex = DO_HW_RAID_CREATEO;
3043457Sjc156560 				action = TRUE;
3053457Sjc156560 				options |= LOWER_C;
3063457Sjc156560 			} else {
3073457Sjc156560 				findex = DO_HW_RAID_NOP;
3083457Sjc156560 			}
3093457Sjc156560 			break;
3103457Sjc156560 		case 'd':
3113457Sjc156560 			if (action == FALSE) {
3123457Sjc156560 				findex = DO_HW_RAID_DELETE;
3133457Sjc156560 				action = TRUE;
3143457Sjc156560 				options |= LOWER_D;
3153457Sjc156560 			} else {
3163457Sjc156560 				findex = DO_HW_RAID_NOP;
3173457Sjc156560 			}
3183457Sjc156560 			break;
3193457Sjc156560 		case 'l':
3203457Sjc156560 			if (action == FALSE) {
3213457Sjc156560 				findex = DO_HW_RAID_LIST;
3223457Sjc156560 				action = TRUE;
3233457Sjc156560 				options |= LOWER_L;
3243457Sjc156560 			} else {
3253457Sjc156560 				findex = DO_HW_RAID_NOP;
3263457Sjc156560 			}
3273457Sjc156560 			break;
3283457Sjc156560 		case 'F':
3293457Sjc156560 			if (action == FALSE) {
3303457Sjc156560 				findex = DO_HW_RAID_FLASH;
3313457Sjc156560 				F_argp = optarg;
3323457Sjc156560 				action = TRUE;
3333457Sjc156560 				options |= UPPER_F;
3343457Sjc156560 			} else {
3353457Sjc156560 				findex = DO_HW_RAID_NOP;
3363457Sjc156560 			}
3373457Sjc156560 			break;
3383457Sjc156560 		case 'a':
3393457Sjc156560 			if (action == FALSE) {
3403457Sjc156560 				findex = DO_HW_RAID_HSP;
3413457Sjc156560 				a_argp = optarg;
3423457Sjc156560 				action = TRUE;
3433457Sjc156560 				options |= LOWER_A;
3443457Sjc156560 			} else {
3453457Sjc156560 				findex = DO_HW_RAID_NOP;
3463457Sjc156560 			}
3473457Sjc156560 			break;
3483457Sjc156560 		case 'p':
3493457Sjc156560 			if (action == FALSE) {
3503457Sjc156560 				findex = DO_HW_RAID_SET_ATTR;
3513457Sjc156560 				p_argp = optarg;
3523457Sjc156560 				action = TRUE;
3533457Sjc156560 				options |= LOWER_P;
3543457Sjc156560 			} else {
3553457Sjc156560 				findex = DO_HW_RAID_NOP;
3563457Sjc156560 			}
3573457Sjc156560 			break;
3583457Sjc156560 		case 'r':
3593457Sjc156560 			r_argp = optarg;
3603457Sjc156560 			r_flag = TRUE;
3613457Sjc156560 			options |= LOWER_R;
3623457Sjc156560 			break;
3633457Sjc156560 		case 'z':
3643457Sjc156560 			z_argp = optarg;
3653457Sjc156560 			options |= LOWER_Z;
3663457Sjc156560 			break;
3673457Sjc156560 		case 'g':
3683457Sjc156560 			g_argp = optarg;
3693457Sjc156560 			options |= LOWER_G;
3703457Sjc156560 			break;
3713457Sjc156560 		case 's':
3723457Sjc156560 			s_argp = optarg;
3733457Sjc156560 			options |= LOWER_S;
3743457Sjc156560 			break;
3753457Sjc156560 		case 'f':
3763457Sjc156560 			f_flag = TRUE;
3773457Sjc156560 			options |= LOWER_F;
3783457Sjc156560 			break;
3793457Sjc156560 		case 'S':
3803457Sjc156560 			if (action == FALSE) {
3813457Sjc156560 				findex = DO_HW_RAID_SNAPSHOT;
3823457Sjc156560 				action = TRUE;
3833457Sjc156560 				options |= UPPER_S;
3843457Sjc156560 			} else {
3853457Sjc156560 				findex = DO_HW_RAID_NOP;
3863457Sjc156560 			}
3873457Sjc156560 			break;
3883457Sjc156560 		default:
3893457Sjc156560 			(void) fprintf(stderr,
3903457Sjc156560 			    gettext("Invalid argument(s).\n"));
3913457Sjc156560 			exit_raidctl_lock(fd);
3923457Sjc156560 			FREE_STRS;
3933457Sjc156560 			regfree(&re);
3943457Sjc156560 			return (INVALID_ARG);
3953457Sjc156560 		}
3963457Sjc156560 	}
3973457Sjc156560 
3983457Sjc156560 	/* parse options */
3993457Sjc156560 	switch (findex) {
4003457Sjc156560 	case DO_HW_RAID_HELP:
4013457Sjc156560 		if ((options & ~(LOWER_H)) != 0) {
4023457Sjc156560 			ret = INVALID_ARG;
4033457Sjc156560 		} else {
4043457Sjc156560 			helpinfo(prog_namep);
4053457Sjc156560 			ret = SUCCESS;
4063457Sjc156560 		}
4074Ssafa 		break;
4083457Sjc156560 	case DO_HW_RAID_CREATEO:
4093457Sjc156560 		if ((options & ~(LOWER_F | LOWER_C | LOWER_R)) != 0) {
4103457Sjc156560 			ret = INVALID_ARG;
4113457Sjc156560 		} else {
4123457Sjc156560 			if (r_flag != FALSE && f_flag == FALSE) {
4133457Sjc156560 				ret = do_create_ctd(r_argp, argv, argc - 4,
4143457Sjc156560 				    optind, f_flag);
4153457Sjc156560 			} else if (r_flag == FALSE && f_flag == FALSE) {
4163457Sjc156560 				ret = do_create_ctd(NULL, argv, argc - 2,
4173457Sjc156560 				    optind, f_flag);
4183457Sjc156560 			} else if (r_flag != FALSE && f_flag != FALSE) {
4193457Sjc156560 				ret = do_create_ctd(r_argp, argv, argc - 5,
4203457Sjc156560 				    optind, f_flag);
4213457Sjc156560 			} else {
4223457Sjc156560 				ret = do_create_ctd(NULL, argv, argc - 3,
4233457Sjc156560 				    optind, f_flag);
4243457Sjc156560 			}
4253457Sjc156560 		}
4263457Sjc156560 		break;
4273457Sjc156560 	case DO_HW_RAID_CREATEN:
4283457Sjc156560 		if ((options & ~(LOWER_F | UPPER_C | LOWER_R | LOWER_Z |
4293457Sjc156560 		    LOWER_S)) != 0) {
4303457Sjc156560 			ret = INVALID_ARG;
4313457Sjc156560 		} else {
4323457Sjc156560 			ret = do_create_cidl(r_argp, z_argp, C_argp, s_argp,
4333457Sjc156560 			    f_flag, argv, optind);
4343457Sjc156560 		}
4353457Sjc156560 		break;
4363457Sjc156560 	case DO_HW_RAID_DELETE:
4373457Sjc156560 		if ((options & ~(LOWER_F | LOWER_D)) != 0) {
4383457Sjc156560 			ret = INVALID_ARG;
4393457Sjc156560 		} else {
4403457Sjc156560 			ret = do_delete(f_flag, argv, optind);
4413457Sjc156560 		}
4420Sstevel@tonic-gate 		break;
4433457Sjc156560 	case DO_HW_RAID_LIST:
4443457Sjc156560 		if ((options & ~(LOWER_L | LOWER_G)) != 0) {
4453457Sjc156560 			ret = INVALID_ARG;
4463457Sjc156560 		} else {
4473457Sjc156560 			ret = do_list(g_argp, argv, optind, FALSE);
4483457Sjc156560 		}
4493457Sjc156560 		break;
4503457Sjc156560 	case DO_HW_RAID_SNAPSHOT:
4513457Sjc156560 		if ((options & ~(UPPER_S | LOWER_G)) != 0) {
4523457Sjc156560 			ret = INVALID_ARG;
4533457Sjc156560 		} else {
4543457Sjc156560 			ret = do_list(g_argp, argv, optind, TRUE);
4553457Sjc156560 		}
4563457Sjc156560 		break;
4573457Sjc156560 	case DO_HW_RAID_FLASH:
4583457Sjc156560 		if ((options & ~(LOWER_F | UPPER_F)) != 0) {
4593457Sjc156560 			ret = INVALID_ARG;
4603457Sjc156560 		} else {
4613457Sjc156560 			if (f_flag == FALSE) {
4623457Sjc156560 				ret = do_flash(f_flag, F_argp, argv, optind,
4633457Sjc156560 				    argc - 3);
4643457Sjc156560 			} else {
4653457Sjc156560 				ret = do_flash(f_flag, F_argp, argv, optind,
4663457Sjc156560 				    argc - 4);
4673457Sjc156560 			}
4683457Sjc156560 		}
4693457Sjc156560 		break;
4703457Sjc156560 	case DO_HW_RAID_HSP:
4713457Sjc156560 		if ((options & ~(LOWER_A | LOWER_G)) != 0) {
4723457Sjc156560 			ret = INVALID_ARG;
4733457Sjc156560 		} else {
4743457Sjc156560 			ret = do_set_hsp(a_argp, g_argp, argv, optind);
4753457Sjc156560 		}
4763457Sjc156560 		break;
4773457Sjc156560 	case DO_HW_RAID_SET_ATTR:
4783457Sjc156560 		if ((options & ~(LOWER_F | LOWER_P)) != 0) {
4793457Sjc156560 			ret = INVALID_ARG;
4803457Sjc156560 		} else {
4813457Sjc156560 			ret = do_set_array_attr(f_flag, p_argp, argv, optind);
4823457Sjc156560 		}
4833457Sjc156560 		break;
4843457Sjc156560 	case DO_HW_RAID_NOP:
4853457Sjc156560 		if (argc == 1) {
4863457Sjc156560 			ret = do_list(g_argp, argv, optind, FALSE);
4873457Sjc156560 		} else {
4883457Sjc156560 			ret = INVALID_ARG;
4893457Sjc156560 		}
4900Sstevel@tonic-gate 		break;
4910Sstevel@tonic-gate 	default:
4923457Sjc156560 		ret = INVALID_ARG;
4933457Sjc156560 		break;
4940Sstevel@tonic-gate 	}
4953457Sjc156560 
4963457Sjc156560 	if (ret == INVALID_ARG) {
4973457Sjc156560 		(void) fprintf(stderr,
4983457Sjc156560 		    gettext("Invalid argument(s).\n"));
4990Sstevel@tonic-gate 	}
5003457Sjc156560 	exit_raidctl_lock(fd);
5013457Sjc156560 
5023457Sjc156560 	FREE_STRS;
5033457Sjc156560 	regfree(&re);
5043457Sjc156560 	return (ret);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate /*
5083457Sjc156560  * helpinfo(prog_namep)
5093457Sjc156560  * This function prints help informations for usrs.
5100Sstevel@tonic-gate  */
5110Sstevel@tonic-gate static void
helpinfo(char * prog_namep)5123457Sjc156560 helpinfo(char *prog_namep)
5130Sstevel@tonic-gate {
5143457Sjc156560 	char quote = '"';
5153457Sjc156560 
5163457Sjc156560 	(void) printf(gettext("%s [-f] -C %c<disks>%c [-r <raid_level>] "
5173457Sjc156560 	    "[-z <capacity>] [-s <stripe_size>] <controller>\n"), prog_namep,
5183457Sjc156560 	    quote, quote);
5193457Sjc156560 
5203457Sjc156560 	(void) printf(gettext("%s [-f] -d <volume>\n"), prog_namep);
5213457Sjc156560 
5223457Sjc156560 	(void) printf(gettext("%s [-f] -F <filename> <controller1> "
5233457Sjc156560 	    "[<controller2> ...]\n"), prog_namep);
5243457Sjc156560 
5253457Sjc156560 	(void) printf(gettext("%s [-f] -p %c<param>=<value>%c <volume>\n"),
5263457Sjc156560 	    prog_namep, quote, quote);
5273457Sjc156560 
5283457Sjc156560 	(void) printf(gettext("%s [-f] -c [-r <raid_level>] <disk1> <disk2> "
5293457Sjc156560 	    "[<disk3> ...]\n"), prog_namep);
5303457Sjc156560 
5313457Sjc156560 	(void) printf(gettext("%s [-l]\n"), prog_namep);
5323457Sjc156560 
5333457Sjc156560 	(void) printf(gettext("%s -l -g <disk> <controller>\n"), prog_namep);
5343457Sjc156560 
5353457Sjc156560 	(void) printf(gettext("%s -l <volume>\n"), prog_namep);
5363457Sjc156560 
5373457Sjc156560 	(void) printf(gettext("%s -l <controller1> [<controller2> ...]\n"),
5383457Sjc156560 	    prog_namep);
5393457Sjc156560 
5403457Sjc156560 	(void) printf(gettext("%s -a {set | unset} -g <disk> "
5413457Sjc156560 	    "{<volume> | <controller>}\n"), prog_namep);
5423457Sjc156560 
5433457Sjc156560 	(void) printf(gettext("%s -S [<volume> | <controller>]\n"), prog_namep);
5443457Sjc156560 
5453457Sjc156560 	(void) printf(gettext("%s -S -g <disk> <controller>\n"), prog_namep);
5463457Sjc156560 
5473457Sjc156560 	(void) printf(gettext("%s -h\n"), prog_namep);
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate 
5503457Sjc156560 /*
5513457Sjc156560  * do_create_cidl(raid_levelp, capacityp, disks_argp, stripe_sizep,
5523457Sjc156560  * f_flag, argv, optind)
5533457Sjc156560  * This function creates a new RAID volume with specified arguments,
5543457Sjc156560  * and returns result as SUCCESS, INVALID_ARG or FAILURE.
5553457Sjc156560  * The "c.id.l" is used to express single physical disk. 'c' expresses
5563457Sjc156560  * bus number, 'id' expresses target number, and 'l' expresses lun.
5573457Sjc156560  * The physical disks represented by c.id.l may be invisible to OS, which
5583457Sjc156560  * means physical disks attached to controllers are not accessible by
5593457Sjc156560  * OS directly. The disks should be organized as a logical volume, and
5603457Sjc156560  * the logical volume is exported to OS as a single unit. Some hardware
5613457Sjc156560  * RAID controllers also support physical disks accessed by OS directly,
5623457Sjc156560  * for example LSI1068. In this case, it's both OK to express physical
5633457Sjc156560  * disk by c.id.l format or canonical ctd format.
5643457Sjc156560  */
5653457Sjc156560 static int
do_create_cidl(char * raid_levelp,char * capacityp,char * disks_argp,char * stripe_sizep,uint32_t f_flag,char ** argv,uint32_t optind)5663457Sjc156560 do_create_cidl(char *raid_levelp, char *capacityp, char *disks_argp,
5673457Sjc156560 	char *stripe_sizep, uint32_t f_flag, char **argv, uint32_t optind)
5680Sstevel@tonic-gate {
5693457Sjc156560 	uint32_t ctl_tag = MAX32BIT;
5703457Sjc156560 	raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
5713457Sjc156560 	uint32_t raid_level = RAID_LEVEL_1;
5723457Sjc156560 	uint64_t capacity = 0;
5733457Sjc156560 	uint64_t stripe_size = (uint64_t)OBJ_ATTR_NONE;
5743457Sjc156560 	raid_obj_handle_t *disk_handlesp = NULL;
5753457Sjc156560 	raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
5763457Sjc156560 	raidcfg_controller_t ctl_attr;
5773457Sjc156560 	int comps_num = 0;
5783457Sjc156560 	int ret = 0;
5793457Sjc156560 
5803457Sjc156560 	raidcfg_array_t array_attr;
5813457Sjc156560 
5823457Sjc156560 	if (argv[optind] == NULL || argv[optind + 1] != NULL) {
5833457Sjc156560 		return (INVALID_ARG);
5843457Sjc156560 	}
5853457Sjc156560 
5863457Sjc156560 	if (disks_argp == NULL) {
5873457Sjc156560 		return (INVALID_ARG);
5883457Sjc156560 	}
5893457Sjc156560 
5903457Sjc156560 	/* Check controller tag */
5913457Sjc156560 	if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
5923457Sjc156560 		return (INVALID_ARG);
5933457Sjc156560 	}
5943457Sjc156560 
5953457Sjc156560 	ctl_handle = raidcfg_get_controller(ctl_tag);
5963457Sjc156560 	if (ctl_handle <= 0) {
5973457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
5983457Sjc156560 		return (FAILURE);
5993457Sjc156560 	}
6003457Sjc156560 
6013457Sjc156560 	if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
6023457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
6033457Sjc156560 		return (FAILURE);
6043457Sjc156560 	}
6053457Sjc156560 
6063457Sjc156560 	/* Get raid level */
6073457Sjc156560 	if (raid_levelp != NULL) {
6083457Sjc156560 		if (*raid_levelp == '1' &&
6093457Sjc156560 		    (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) {
6103457Sjc156560 			raid_level = RAID_LEVEL_1E;
6113457Sjc156560 		} else {
6123457Sjc156560 			if (is_fully_numeric(raid_levelp) == FALSE) {
6133457Sjc156560 				return (INVALID_ARG);
6143457Sjc156560 			}
6153457Sjc156560 
6163457Sjc156560 			switch (atoi(raid_levelp)) {
6173457Sjc156560 			case 0:
6183457Sjc156560 				raid_level = RAID_LEVEL_0;
6190Sstevel@tonic-gate 				break;
6203457Sjc156560 			case 1:
6213457Sjc156560 				raid_level = RAID_LEVEL_1;
6223457Sjc156560 				break;
6233457Sjc156560 			case 5:
6243457Sjc156560 				raid_level = RAID_LEVEL_5;
6253457Sjc156560 				break;
6263457Sjc156560 			case 10:
6273457Sjc156560 				raid_level = RAID_LEVEL_10;
6283457Sjc156560 				break;
6293457Sjc156560 			case 50:
6303457Sjc156560 				raid_level = RAID_LEVEL_50;
6313457Sjc156560 				break;
6323457Sjc156560 			default:
6333457Sjc156560 				return (INVALID_ARG);
6343457Sjc156560 			}
6350Sstevel@tonic-gate 		}
6360Sstevel@tonic-gate 	}
6370Sstevel@tonic-gate 
638840Sjesseb 	/*
6393457Sjc156560 	 * The rang check of capacity and stripe size is performed in library,
6403457Sjc156560 	 * and it relates to hardware feature.
641840Sjesseb 	 */
6423457Sjc156560 
6433457Sjc156560 	/* Capacity in bytes. Capacity 0 means max available space. */
6443457Sjc156560 	if (capacityp != NULL) {
6453457Sjc156560 		if (*capacityp == '-' ||
6463457Sjc156560 		    calc_size(capacityp, &capacity) != SUCCESS) {
6473457Sjc156560 			return (INVALID_ARG);
6483457Sjc156560 		}
6493457Sjc156560 	}
6503457Sjc156560 
6513457Sjc156560 	/* Stripe size in bytes */
6523457Sjc156560 	if (stripe_sizep != NULL) {
6533457Sjc156560 		if (calc_size(stripe_sizep, &stripe_size) != SUCCESS ||
6543457Sjc156560 		    *stripe_sizep == '-') {
6553457Sjc156560 			return (INVALID_ARG);
6563457Sjc156560 		}
6573457Sjc156560 	}
6583457Sjc156560 
6593457Sjc156560 	/* Open controller before accessing its object */
6603457Sjc156560 	if ((ret = raidcfg_open_controller(ctl_handle, NULL)) < 0) {
6613457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
6623457Sjc156560 		return (FAILURE);
6633457Sjc156560 	}
6643457Sjc156560 
6653457Sjc156560 	/* Get disks' handles */
6663457Sjc156560 	if ((ret = get_disk_handle_cidl(ctl_tag, disks_argp, &comps_num,
6673457Sjc156560 	    &disk_handlesp)) != SUCCESS) {
6683457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
6693457Sjc156560 		return (ret);
6703457Sjc156560 	}
6713457Sjc156560 
6723457Sjc156560 	if (f_flag == FALSE) {
6733457Sjc156560 		(void) fprintf(stdout, gettext("Creating RAID volume "
6743457Sjc156560 		    "will destroy all data on spare space of member disks, "
6753457Sjc156560 		    "proceed (%s/%s)? "), yesstr, nostr);
6763457Sjc156560 		if (!yes()) {
6773457Sjc156560 			(void) fprintf(stdout, gettext("RAID volume "
6783457Sjc156560 			    "not created.\n\n"));
6793457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
6803457Sjc156560 			free(disk_handlesp);
6813457Sjc156560 			return (SUCCESS);
6823457Sjc156560 		}
6833457Sjc156560 	}
6843457Sjc156560 
6853457Sjc156560 	/* Create array */
6863457Sjc156560 	array_handle = raidcfg_create_array(comps_num,
6873457Sjc156560 	    disk_handlesp, raid_level, capacity, stripe_size, NULL);
6883457Sjc156560 
6893457Sjc156560 	if (array_handle <= 0) {
6903457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
6913457Sjc156560 		free(disk_handlesp);
6923457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
6933457Sjc156560 		return (FAILURE);
6943457Sjc156560 	}
6953457Sjc156560 
6963457Sjc156560 	/* Get attribute of the new created array */
6973457Sjc156560 	if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
6983457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
6993457Sjc156560 		free(disk_handlesp);
7003457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
7013457Sjc156560 		return (FAILURE);
7023457Sjc156560 	}
7033457Sjc156560 
7043457Sjc156560 	(void) fprintf(stdout, gettext("Volume c%ut%llud%llu is created "
7053457Sjc156560 	    "successfully!\n"), ctl_tag, array_attr.tag.idl.target_id,
7063457Sjc156560 	    array_attr.tag.idl.lun);
7073457Sjc156560 
7083457Sjc156560 	/* Print attribute of array */
7093457Sjc156560 	(void) print_array_table(ctl_handle, array_handle);
7103457Sjc156560 
7113457Sjc156560 	/* Close controller */
7123457Sjc156560 	(void) raidcfg_close_controller(ctl_handle, NULL);
7133457Sjc156560 
7143457Sjc156560 	free(disk_handlesp);
7153457Sjc156560 	return (SUCCESS);
7163457Sjc156560 }
7173457Sjc156560 
7183457Sjc156560 /*
7193457Sjc156560  * do_create_ctd(raid_levelp, disks_argpp, disks_num, argindex, f_flag)
7203457Sjc156560  * This function creates array with specified arguments, and return result
7213457Sjc156560  * as SUCCESS, FAILURE, or INVALID_ARG. It only supports LSI MPT controller
7223457Sjc156560  * to be compatible with old raidctl. The capacity and stripe size can't
7233457Sjc156560  * be specified for LSI MPT controller, and they use zero and default value.
7243457Sjc156560  * The "ctd" is the canonical expression of physical disks which are
7253457Sjc156560  * accessible by OS.
7263457Sjc156560  */
7273457Sjc156560 static int
do_create_ctd(char * raid_levelp,char ** disks_argpp,uint32_t disks_num,uint32_t argindex,uint32_t f_flag)7283457Sjc156560 do_create_ctd(char *raid_levelp, char **disks_argpp, uint32_t disks_num,
7293457Sjc156560 	uint32_t argindex, uint32_t f_flag)
7303457Sjc156560 {
7313457Sjc156560 	uint32_t ctl_tag = MAX32BIT;
7323457Sjc156560 	raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
7333457Sjc156560 	uint32_t raid_level = RAID_LEVEL_1;
7343457Sjc156560 	uint64_t capacity = 0;
7353457Sjc156560 	uint32_t stripe_size = (uint32_t)OBJ_ATTR_NONE;
7363457Sjc156560 	raid_obj_handle_t *disk_handlesp = NULL;
7373457Sjc156560 	raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
7383457Sjc156560 	raidcfg_controller_t ctl_attr;
7393457Sjc156560 	int ret;
7403457Sjc156560 
7413457Sjc156560 	raidcfg_array_t array_attr;
7423457Sjc156560 	int i, j;
7433457Sjc156560 
7443457Sjc156560 	/* Check disks parameter */
7453457Sjc156560 	if (disks_argpp == NULL || disks_num < 2) {
7463457Sjc156560 		return (INVALID_ARG);
7473457Sjc156560 	}
7483457Sjc156560 
7493457Sjc156560 	for (i = 0, j = argindex; i < disks_num; i++, j++) {
7503457Sjc156560 		if (disks_argpp[j] == NULL) {
7513457Sjc156560 			return (INVALID_ARG);
7523457Sjc156560 		}
7533457Sjc156560 	}
7543457Sjc156560 
7553457Sjc156560 	/*
7563457Sjc156560 	 * We need check if the raid_level string is fully numeric. If user
7573457Sjc156560 	 * input string with unsupported letters, such as "s10", atoi() will
7583457Sjc156560 	 * return zero because it is an illegal string, but it doesn't mean
7593457Sjc156560 	 * RAID_LEVEL_0.
7603457Sjc156560 	 */
7613457Sjc156560 	if (raid_levelp != NULL) {
7623457Sjc156560 		if (*raid_levelp == '1' &&
7633457Sjc156560 		    (*(raid_levelp + 1) == 'E' || *(raid_levelp + 1) == 'e')) {
7643457Sjc156560 			raid_level = RAID_LEVEL_1E;
7653457Sjc156560 		} else {
7663457Sjc156560 			if (is_fully_numeric(raid_levelp) == FALSE) {
7673457Sjc156560 				return (INVALID_ARG);
7683457Sjc156560 			}
7693457Sjc156560 
7703457Sjc156560 			switch (atoi(raid_levelp)) {
7713457Sjc156560 			case 0:
7723457Sjc156560 				raid_level = RAID_LEVEL_0;
7733457Sjc156560 				break;
7743457Sjc156560 			case 1:
7753457Sjc156560 				raid_level = RAID_LEVEL_1;
7763457Sjc156560 				break;
7773457Sjc156560 			case 5:
7783457Sjc156560 				raid_level = RAID_LEVEL_5;
7793457Sjc156560 				break;
7803457Sjc156560 			default:
7813457Sjc156560 				return (INVALID_ARG);
7823457Sjc156560 			}
7833457Sjc156560 		}
7843457Sjc156560 	}
7853457Sjc156560 
7863457Sjc156560 	/* Get disks tag and controller tag */
7873457Sjc156560 	disk_handlesp = (raid_obj_handle_t *)calloc(disks_num + 2,
7883457Sjc156560 	    sizeof (raid_obj_handle_t));
7893457Sjc156560 	if (disk_handlesp == NULL) {
7903457Sjc156560 		return (FAILURE);
7913457Sjc156560 	}
7923457Sjc156560 
7933457Sjc156560 	disk_handlesp[0] = OBJ_SEPARATOR_BEGIN;
7943457Sjc156560 	disk_handlesp[disks_num + 1] = OBJ_SEPARATOR_END;
7953457Sjc156560 
7963457Sjc156560 	if ((ret = get_disk_handle_ctd(disks_num, &disks_argpp[argindex],
7973457Sjc156560 	    &ctl_tag, &disk_handlesp[1])) != SUCCESS) {
7983457Sjc156560 		free(disk_handlesp);
7993457Sjc156560 		return (ret);
8003457Sjc156560 	}
8013457Sjc156560 
8023457Sjc156560 	/* LIB API should check whether all disks here belong to one ctl. */
8033457Sjc156560 	/* get_disk_handle_ctd has opened controller. */
8043457Sjc156560 	ctl_handle = raidcfg_get_controller(ctl_tag);
8053457Sjc156560 
8063457Sjc156560 	if (ctl_handle <= 0) {
8073457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
8083457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
8093457Sjc156560 		free(disk_handlesp);
8103457Sjc156560 		return (FAILURE);
8113457Sjc156560 	}
8123457Sjc156560 
8133457Sjc156560 	/* Check if the controller is host raid type */
8143457Sjc156560 	if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
8153457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
8163457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
8173457Sjc156560 		free(disk_handlesp);
8183457Sjc156560 		return (FAILURE);
8193457Sjc156560 	}
8203457Sjc156560 
8213457Sjc156560 	if ((ctl_attr.capability & RAID_CAP_DISK_TRANS) == 0) {
8223457Sjc156560 		/* -c only support host raid controller, return failure here */
8233457Sjc156560 		(void) fprintf(stderr,
8243457Sjc156560 		    gettext("Option -c only supports host raid controller.\n"));
8253457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
8263457Sjc156560 		free(disk_handlesp);
8273457Sjc156560 		return (FAILURE);
8283457Sjc156560 	}
8293457Sjc156560 
8303457Sjc156560 	if (f_flag == FALSE) {
8313457Sjc156560 		(void) fprintf(stdout, gettext("Creating RAID volume "
8323457Sjc156560 		    "will destroy all data on spare space of member disks, "
8333457Sjc156560 		    "proceed (%s/%s)? "), yesstr, nostr);
8343457Sjc156560 		if (!yes()) {
8353457Sjc156560 			(void) fprintf(stdout, gettext("RAID volume "
8363457Sjc156560 			    "not created.\n\n"));
8373457Sjc156560 			free(disk_handlesp);
8383457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
8393457Sjc156560 			return (SUCCESS);
8403457Sjc156560 		}
8410Sstevel@tonic-gate 	}
8420Sstevel@tonic-gate 
843840Sjesseb 	/*
8443457Sjc156560 	 * For old raidctl, capacity is 0, which means to creates
8453457Sjc156560 	 * max possible capacity of array.
846840Sjesseb 	 */
8473457Sjc156560 
8483457Sjc156560 	array_handle = raidcfg_create_array(disks_num + 2,
8493457Sjc156560 	    disk_handlesp, raid_level, capacity, stripe_size, NULL);
8503457Sjc156560 
8513457Sjc156560 	if (array_handle <= 0) {
8523457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
8533457Sjc156560 		free(disk_handlesp);
8543457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
8553457Sjc156560 		return (FAILURE);
8560Sstevel@tonic-gate 	}
8570Sstevel@tonic-gate 
8583457Sjc156560 	/* Get attribute of array */
8593457Sjc156560 	if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
8603457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
8613457Sjc156560 		free(disk_handlesp);
8623457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
8633457Sjc156560 		return (FAILURE);
8643457Sjc156560 	}
8653457Sjc156560 
8663457Sjc156560 	/* Close controller */
8673457Sjc156560 	(void) raidcfg_close_controller(ctl_handle, NULL);
8683457Sjc156560 
8693457Sjc156560 	/* Print feedback for user */
8703457Sjc156560 	(void) fprintf(stdout,
8713457Sjc156560 	    gettext("Volume c%ut%llud%llu is created successfully!\n"),
8723457Sjc156560 	    ctl_tag, array_attr.tag.idl.target_id,
8733457Sjc156560 	    array_attr.tag.idl.lun);
8743457Sjc156560 	free(disk_handlesp);
8753457Sjc156560 	return (SUCCESS);
8760Sstevel@tonic-gate }
8770Sstevel@tonic-gate 
8783457Sjc156560 /*
8793457Sjc156560  * do_list(disk_arg, argv, optind, is_snapshot)
8803457Sjc156560  * This function lists RAID's system configuration. It supports various RAID
8813457Sjc156560  * controller. The return value can be SUCCESS, FAILURE, or INVALID_ARG.
8823457Sjc156560  */
8833457Sjc156560 static int
do_list(char * disk_argp,char ** argv,uint32_t optind,uint8_t is_snapshot)8843457Sjc156560 do_list(char *disk_argp, char **argv, uint32_t optind, uint8_t is_snapshot)
8850Sstevel@tonic-gate {
8863457Sjc156560 	uint32_t ctl_tag = MAX32BIT;
8873457Sjc156560 	raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
8883457Sjc156560 	raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
8893457Sjc156560 	raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
8903457Sjc156560 	disk_tag_t disk_tag;
8913457Sjc156560 	array_tag_t array_tag;
8923457Sjc156560 
8933457Sjc156560 	int ret;
8943457Sjc156560 
8953457Sjc156560 	/* print RAID system */
8963457Sjc156560 	if (disk_argp == NULL) {
8973457Sjc156560 		if (argv[optind] == NULL) {
8983457Sjc156560 			ret = snapshot_raidsystem(TRUE, 0, is_snapshot);
8993457Sjc156560 			return (ret);
9003457Sjc156560 		} else {
9013457Sjc156560 			if (is_fully_numeric(argv[optind]) == TRUE) {
9023457Sjc156560 				while (argv[optind] != NULL) {
9033457Sjc156560 					if (get_ctl_tag(argv[optind], &ctl_tag)
9043457Sjc156560 					    != SUCCESS) {
9053457Sjc156560 						ret = INVALID_ARG;
9063457Sjc156560 						optind++;
9073457Sjc156560 						continue;
9083457Sjc156560 					}
9093457Sjc156560 					ctl_handle =
9103457Sjc156560 					    raidcfg_get_controller(ctl_tag);
9113457Sjc156560 					if (ctl_handle <= 0) {
9123457Sjc156560 						(void) fprintf(stderr, "%s\n",
9133457Sjc156560 						    raidcfg_errstr(ctl_handle));
9143457Sjc156560 						ret = FAILURE;
9153457Sjc156560 						optind++;
9163457Sjc156560 						continue;
9173457Sjc156560 					}
9183457Sjc156560 					ret =
9193457Sjc156560 					    raidcfg_open_controller(ctl_handle,
9203457Sjc156560 					    NULL);
9213457Sjc156560 					if (ret < 0) {
9223457Sjc156560 						(void) fprintf(stderr, "%s\n",
9233457Sjc156560 						    raidcfg_errstr(ret));
9243457Sjc156560 						ret = FAILURE;
9253457Sjc156560 						optind++;
9263457Sjc156560 						continue;
9273457Sjc156560 					}
9283457Sjc156560 					if (is_snapshot == FALSE) {
9293457Sjc156560 						ret =
9303457Sjc156560 						    print_ctl_table(ctl_handle);
9313457Sjc156560 					} else {
9323457Sjc156560 						ret =
9333457Sjc156560 						    snapshot_ctl(ctl_handle,
9344563Syw161884 						    FALSE, 0, is_snapshot);
9353457Sjc156560 					}
9363457Sjc156560 					(void) raidcfg_close_controller(
9373457Sjc156560 					    ctl_handle, NULL);
9383457Sjc156560 					optind++;
9393457Sjc156560 				}
9403457Sjc156560 			} else {
9413457Sjc156560 				if (get_array_tag(argv[optind],
9423457Sjc156560 				    &ctl_tag, &array_tag) != SUCCESS) {
9433457Sjc156560 					return (INVALID_ARG);
9443457Sjc156560 				}
9453457Sjc156560 				ctl_handle = raidcfg_get_controller(ctl_tag);
9463457Sjc156560 				if (ctl_handle <= 0) {
9473457Sjc156560 					(void) fprintf(stderr, "%s\n",
9483457Sjc156560 					    raidcfg_errstr(ctl_handle));
9493457Sjc156560 					return (FAILURE);
9503457Sjc156560 				}
9513457Sjc156560 
9523457Sjc156560 				ret = raidcfg_open_controller(ctl_handle, NULL);
9533457Sjc156560 				if (ret < 0) {
9543457Sjc156560 					(void) fprintf(stderr, "%s\n",
9553457Sjc156560 					    raidcfg_errstr(ret));
9563457Sjc156560 					return (FAILURE);
9573457Sjc156560 				}
9583457Sjc156560 
9593457Sjc156560 				array_handle = raidcfg_get_array(ctl_handle,
9603457Sjc156560 				    array_tag.idl.target_id, array_tag.idl.lun);
9613457Sjc156560 				if (array_handle <= 0) {
9623457Sjc156560 					(void) fprintf(stderr, "%s\n",
9633457Sjc156560 					    raidcfg_errstr(array_handle));
9643457Sjc156560 					(void) raidcfg_close_controller(
9653457Sjc156560 					    ctl_handle, NULL);
9663457Sjc156560 					return (FAILURE);
9673457Sjc156560 				}
9683457Sjc156560 				if (is_snapshot == FALSE) {
9693457Sjc156560 					ret = print_array_table(ctl_handle,
9703457Sjc156560 					    array_handle);
9713457Sjc156560 				} else {
9723457Sjc156560 					ret = snapshot_array(array_handle, 0,
9733457Sjc156560 					    FALSE, is_snapshot);
9743457Sjc156560 				}
9753457Sjc156560 				(void) raidcfg_close_controller(
9763457Sjc156560 				    ctl_handle, NULL);
9773457Sjc156560 			}
9783457Sjc156560 		}
9793457Sjc156560 	} else {
9803457Sjc156560 		if (argv[optind + 1] != NULL) {
9813457Sjc156560 			return (INVALID_ARG);
9823457Sjc156560 		}
9833457Sjc156560 
9843457Sjc156560 		if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
9853457Sjc156560 			return (INVALID_ARG);
9863457Sjc156560 		}
9873457Sjc156560 
9883457Sjc156560 		ctl_handle = raidcfg_get_controller(ctl_tag);
9893457Sjc156560 		if (ctl_handle <= 0) {
9903457Sjc156560 			(void) fprintf(stderr, "%s\n",
9913457Sjc156560 			    raidcfg_errstr(ctl_handle));
9923457Sjc156560 			return (FAILURE);
9933457Sjc156560 		}
9943457Sjc156560 
9953457Sjc156560 		if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
9963457Sjc156560 			return (INVALID_ARG);
9973457Sjc156560 		}
9983457Sjc156560 
9993457Sjc156560 		ret = raidcfg_open_controller(ctl_handle, NULL);
10003457Sjc156560 		if (ret < 0) {
10013457Sjc156560 			(void) fprintf(stderr, "%s\n",
10023457Sjc156560 			    raidcfg_errstr(ret));
10033457Sjc156560 			return (FAILURE);
10043457Sjc156560 		}
10053457Sjc156560 
10063457Sjc156560 		disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
10073457Sjc156560 		if (disk_handle <= 0) {
10083457Sjc156560 			(void) fprintf(stderr, "%s\n",
10093457Sjc156560 			    raidcfg_errstr(disk_handle));
10103457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
10113457Sjc156560 			return (FAILURE);
10123457Sjc156560 		}
10133457Sjc156560 
10143457Sjc156560 		if (is_snapshot == FALSE) {
10153457Sjc156560 			ret = print_disk_table(ctl_handle, disk_handle);
10163457Sjc156560 		} else {
10173457Sjc156560 			ret = snapshot_disk(ctl_tag, disk_handle, 0,
10183457Sjc156560 			    is_snapshot);
10193457Sjc156560 		}
10203457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
1021840Sjesseb 	}
10223457Sjc156560 	return (ret);
10233457Sjc156560 }
10243457Sjc156560 
10253457Sjc156560 /*
10263457Sjc156560  * do_delete(f_flag, argv, optind)
10273457Sjc156560  * This function deletes a specified array, and return result as SUCCESS,
10283457Sjc156560  * FAILURE or INVALID_ARG.
10293457Sjc156560  */
10303457Sjc156560 static int
do_delete(uint32_t f_flag,char ** argv,uint32_t optind)10313457Sjc156560 do_delete(uint32_t f_flag, char **argv, uint32_t optind)
10323457Sjc156560 {
10333457Sjc156560 	uint32_t ctl_tag;
10343457Sjc156560 	char *array_argp;
10353457Sjc156560 	array_tag_t array_tag;
10363457Sjc156560 	raid_obj_handle_t ctl_handle;
10373457Sjc156560 	raid_obj_handle_t array_handle;
10383457Sjc156560 	int ret;
10393457Sjc156560 
10403457Sjc156560 	array_argp = argv[optind];
10413457Sjc156560 	if (array_argp == NULL || argv[optind + 1] != NULL) {
10423457Sjc156560 		return (INVALID_ARG);
10433457Sjc156560 	}
10443457Sjc156560 
10453457Sjc156560 	if (get_array_tag(array_argp, &ctl_tag, &array_tag) != SUCCESS) {
10463457Sjc156560 		return (INVALID_ARG);
10470Sstevel@tonic-gate 	}
10480Sstevel@tonic-gate 
10493457Sjc156560 	ctl_handle = raidcfg_get_controller(ctl_tag);
10503457Sjc156560 	if (ctl_handle <= 0) {
10513457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
10523457Sjc156560 		return (INVALID_ARG);
10533457Sjc156560 	}
10543457Sjc156560 
10553457Sjc156560 	ret = raidcfg_open_controller(ctl_handle, NULL);
10563457Sjc156560 	if (ret < 0) {
10573457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
10583457Sjc156560 		return (FAILURE);
10590Sstevel@tonic-gate 	}
10600Sstevel@tonic-gate 
10613457Sjc156560 	array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
10623457Sjc156560 	    array_tag.idl.lun);
10633457Sjc156560 	if (array_handle <= 0) {
10643457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
10653457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
10663457Sjc156560 		return (FAILURE);
10673457Sjc156560 	}
10683457Sjc156560 
10693457Sjc156560 	if (f_flag == FALSE) {
10703457Sjc156560 		(void) fprintf(stdout, gettext("Deleting RAID volume "
10713457Sjc156560 		    "%s will destroy all data it contains, "
10724563Syw161884 		    "proceed (%s/%s)? "), array_argp, yesstr, nostr);
10733457Sjc156560 		if (!yes()) {
10743457Sjc156560 			(void) fprintf(stdout, gettext("RAID Volume "
10753457Sjc156560 			    "%s not deleted.\n\n"), array_argp);
10763457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
10773457Sjc156560 			return (SUCCESS);
10780Sstevel@tonic-gate 		}
10790Sstevel@tonic-gate 	}
10803457Sjc156560 
10813457Sjc156560 
10823457Sjc156560 	if ((ret = raidcfg_delete_array(array_handle, NULL)) < 0) {
10833457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
10843457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
10853457Sjc156560 		return (FAILURE);
10863457Sjc156560 	}
10873457Sjc156560 
10883457Sjc156560 	(void) fprintf(stdout, gettext("Volume %s is deleted successfully!\n"),
10893457Sjc156560 	    array_argp);
10903457Sjc156560 	(void) raidcfg_close_controller(ctl_handle, NULL);
10913457Sjc156560 
10923457Sjc156560 	return (SUCCESS);
10930Sstevel@tonic-gate }
10940Sstevel@tonic-gate 
10953457Sjc156560 /*
10963457Sjc156560  * do_flash(f_flag, filep, ctls_argpp, index, ctl_num)
10973457Sjc156560  * This function downloads and updates firmware for specified controller, and
10983457Sjc156560  * return result as SUCCESS, FAILURE or INVALID_ARG.
10993457Sjc156560  */
11003457Sjc156560 static int
do_flash(uint8_t f_flag,char * filep,char ** ctls_argpp,uint32_t index,uint32_t ctl_num)11013457Sjc156560 do_flash(uint8_t f_flag, char *filep, char **ctls_argpp,
11023457Sjc156560 	uint32_t index, uint32_t ctl_num)
11030Sstevel@tonic-gate {
11043457Sjc156560 	uint32_t ctl_tag = MAX32BIT;
11053457Sjc156560 	char *ctl_argp = NULL;
11063457Sjc156560 	raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
11073457Sjc156560 	int ret;
11083457Sjc156560 	int i, j;
11093457Sjc156560 
11103457Sjc156560 	if (ctl_num == 0)
11113457Sjc156560 		return (INVALID_ARG);
11123457Sjc156560 
11133457Sjc156560 	for (i = 0, j = index; i < ctl_num; i++, j++) {
11143457Sjc156560 		ctl_argp = ctls_argpp[j];
11153457Sjc156560 		if (get_ctl_tag(ctl_argp, &ctl_tag) != SUCCESS) {
11163457Sjc156560 			return (INVALID_ARG);
11173457Sjc156560 		}
11183457Sjc156560 
11193457Sjc156560 		/* Ask user to confirm operation. */
11203457Sjc156560 		if (f_flag == FALSE) {
11213457Sjc156560 			(void) fprintf(stdout, gettext("Update flash image on "
11223457Sjc156560 			    "controller %d (%s/%s)? "), ctl_tag, yesstr, nostr);
11233457Sjc156560 			if (!yes()) {
11243457Sjc156560 				(void) fprintf(stdout,
11253457Sjc156560 				    gettext("Controller %d not "
11263457Sjc156560 				    "flashed.\n\n"), ctl_tag);
11273457Sjc156560 				return (SUCCESS);
1128840Sjesseb 			}
1129840Sjesseb 		}
11303457Sjc156560 
11313457Sjc156560 		if ((ctl_handle = raidcfg_get_controller(ctl_tag)) < 0) {
11323457Sjc156560 			(void) fprintf(stderr, "%s\n",
11333457Sjc156560 			    raidcfg_errstr(ctl_handle));
11343457Sjc156560 			return (FAILURE);
11353457Sjc156560 		}
11363457Sjc156560 
11373457Sjc156560 		ret = raidcfg_open_controller(ctl_handle, NULL);
11383457Sjc156560 		if (ret < 0) {
11393457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
11403457Sjc156560 			return (FAILURE);
11413457Sjc156560 		}
11423457Sjc156560 
11433457Sjc156560 		(void) fprintf(stdout, gettext("Start updating controller "
11443457Sjc156560 		    "c%u firmware....\n"), ctl_tag);
11453457Sjc156560 
11463457Sjc156560 		if ((ret = raidcfg_update_fw(ctl_handle, filep, NULL)) < 0) {
11473457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
11483457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
11493457Sjc156560 			return (FAILURE);
11503457Sjc156560 		}
11513457Sjc156560 
11523457Sjc156560 		(void) fprintf(stdout, gettext("Update controller "
11533457Sjc156560 		    "c%u firmware successfully.\n"), ctl_tag);
11543457Sjc156560 
11553457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
11560Sstevel@tonic-gate 	}
11573457Sjc156560 
11583457Sjc156560 	return (SUCCESS);
11590Sstevel@tonic-gate }
11600Sstevel@tonic-gate 
11610Sstevel@tonic-gate /*
11623457Sjc156560  * do_set_hsp(a_argp, disk_argp, argv, optind)
11633457Sjc156560  * This function set or unset HSP relationship between disk and controller/
11643457Sjc156560  * array, and return result as SUCCESS, FAILURE or INVALID_ARG.
11650Sstevel@tonic-gate  */
11663457Sjc156560 static int
do_set_hsp(char * a_argp,char * disk_argp,char ** argv,uint32_t optind)11673457Sjc156560 do_set_hsp(char *a_argp, char *disk_argp, char **argv, uint32_t optind)
11680Sstevel@tonic-gate {
11693457Sjc156560 	uint32_t flag = MAX32BIT;
11703457Sjc156560 	uint32_t ctl_tag = MAX32BIT;
11713457Sjc156560 	array_tag_t array_tag;
11723457Sjc156560 	raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
11733457Sjc156560 	raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
11743457Sjc156560 	raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
11753457Sjc156560 	raidcfg_controller_t ctl_attr;
11763457Sjc156560 	disk_tag_t disk_tag;
11773457Sjc156560 
11783457Sjc156560 	int ret;
11793457Sjc156560 	int hsp_type;
11803457Sjc156560 	raidcfg_hsp_relation_t hsp_relation;
11813457Sjc156560 
11823457Sjc156560 	(void) memset(&hsp_relation, 0, sizeof (raidcfg_hsp_relation_t));
11833457Sjc156560 
11843457Sjc156560 	if (a_argp == NULL) {
11853457Sjc156560 		return (INVALID_ARG);
11863457Sjc156560 	}
11873457Sjc156560 
11883457Sjc156560 	if (strcmp(a_argp, "set") == 0) {
11893457Sjc156560 		flag = HSP_SET;
11903457Sjc156560 	} else if (strcmp(a_argp, "unset") == 0) {
11913457Sjc156560 		flag = HSP_UNSET;
11923457Sjc156560 	} else {
11933457Sjc156560 		return (INVALID_ARG);
11943457Sjc156560 	}
11953457Sjc156560 
11963457Sjc156560 	if (disk_argp == NULL) {
11973457Sjc156560 		return (INVALID_ARG);
11983457Sjc156560 	}
11993457Sjc156560 
12003457Sjc156560 	if (argv[optind] == NULL || argv[optind + 1] != NULL) {
12013457Sjc156560 		return (INVALID_ARG);
12023457Sjc156560 	} else if (is_fully_numeric(argv[optind]) == TRUE) {
12033457Sjc156560 		/* Global HSP */
12043457Sjc156560 		hsp_type = 0;
12053457Sjc156560 		if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
12063457Sjc156560 			return (INVALID_ARG);
12073457Sjc156560 		}
12083457Sjc156560 
12093457Sjc156560 		if (get_ctl_tag(argv[optind], &ctl_tag) != SUCCESS) {
12103457Sjc156560 			return (INVALID_ARG);
12113457Sjc156560 		}
12123457Sjc156560 
12133457Sjc156560 		ctl_handle = raidcfg_get_controller(ctl_tag);
12143457Sjc156560 		if (ctl_handle <= 0) {
12153457Sjc156560 			(void) fprintf(stderr, "%s\n",
12163457Sjc156560 			    raidcfg_errstr(ctl_handle));
12173457Sjc156560 			return (FAILURE);
12183457Sjc156560 		}
12193457Sjc156560 
12203457Sjc156560 		ret = raidcfg_open_controller(ctl_handle, NULL);
12213457Sjc156560 		if (ret < 0) {
12223457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
12233457Sjc156560 			return (FAILURE);
12240Sstevel@tonic-gate 		}
12253457Sjc156560 
12263457Sjc156560 		disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
12273457Sjc156560 		if (disk_handle <= 0) {
12283457Sjc156560 			(void) fprintf(stderr, "%s\n",
12293457Sjc156560 			    raidcfg_errstr(disk_handle));
12303457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
12313457Sjc156560 			return (FAILURE);
12323457Sjc156560 		}
12333457Sjc156560 	} else {
12343457Sjc156560 		/* Local HSP */
12353457Sjc156560 		hsp_type = 1;
12363457Sjc156560 		if (get_array_tag(argv[optind], &ctl_tag, &array_tag) !=
12373457Sjc156560 		    SUCCESS) {
12383457Sjc156560 			return (INVALID_ARG);
12393457Sjc156560 		}
12403457Sjc156560 
12413457Sjc156560 		/* Open controller */
12423457Sjc156560 		ctl_handle = raidcfg_get_controller(ctl_tag);
12433457Sjc156560 		if (ctl_handle <= 0) {
12443457Sjc156560 			(void) fprintf(stderr, "%s\n",
12453457Sjc156560 			    raidcfg_errstr(ctl_handle));
12463457Sjc156560 			return (FAILURE);
12473457Sjc156560 		}
12483457Sjc156560 
12493457Sjc156560 		ret = raidcfg_open_controller(ctl_handle, NULL);
12503457Sjc156560 		if (ret < 0) {
12513457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
12523457Sjc156560 			return (FAILURE);
12533457Sjc156560 		}
12543457Sjc156560 
12553457Sjc156560 		/* Get controller's attribute */
12563457Sjc156560 		if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
12573457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
12583457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
12593457Sjc156560 			return (FAILURE);
12603457Sjc156560 		}
12613457Sjc156560 
12623457Sjc156560 		if (get_disk_tag_cidl(disk_argp, &disk_tag) != SUCCESS) {
12633457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
12643457Sjc156560 			return (INVALID_ARG);
12653457Sjc156560 		}
12663457Sjc156560 
12673457Sjc156560 		/* Get disk handle */
12683457Sjc156560 		disk_handle = raidcfg_get_disk(ctl_handle, disk_tag);
12693457Sjc156560 		if (disk_handle <= 0) {
12703457Sjc156560 			(void) fprintf(stderr, "%s\n",
12713457Sjc156560 			    raidcfg_errstr(disk_handle));
12723457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
12733457Sjc156560 			return (FAILURE);
12743457Sjc156560 		}
12753457Sjc156560 
12763457Sjc156560 		/* Get array handle */
12773457Sjc156560 		array_handle = raidcfg_get_array(ctl_handle,
12783457Sjc156560 		    array_tag.idl.target_id, array_tag.idl.lun);
12793457Sjc156560 		if (array_handle <= 0) {
12803457Sjc156560 			(void) fprintf(stderr, "%s\n",
12813457Sjc156560 			    raidcfg_errstr(array_handle));
12823457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
12833457Sjc156560 			return (FAILURE);
12843457Sjc156560 		}
12853457Sjc156560 	}
12863457Sjc156560 
12873457Sjc156560 	hsp_relation.disk_handle = disk_handle;
12883457Sjc156560 	if (hsp_type) {
12893457Sjc156560 		/* Set or unset local HSP */
12903457Sjc156560 		hsp_relation.array_handle = array_handle;
12913457Sjc156560 	} else {
12923457Sjc156560 		/* Set or unset global HSP */
12933457Sjc156560 		hsp_relation.array_handle = OBJ_ATTR_NONE;
12940Sstevel@tonic-gate 	}
12950Sstevel@tonic-gate 
12963457Sjc156560 	/* Perform operation of set or unset */
12973457Sjc156560 	if (flag == HSP_SET) {
12988263SRyan.Wang@Sun.COM 		if ((ret = raidcfg_set_hsp(&hsp_relation, NULL)) < 0) {
12993457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
13003457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
13013457Sjc156560 			return (FAILURE);
13023457Sjc156560 		}
13033457Sjc156560 
13043457Sjc156560 		if (hsp_type) {
13053457Sjc156560 			(void) printf(gettext("Set local HSP between disk %s "
13063457Sjc156560 			    "and RAID volume %s successfully.\n"),
13073457Sjc156560 			    disk_argp, argv[optind]);
13083457Sjc156560 		} else {
13093457Sjc156560 			(void) printf(gettext("Set global HSP between disk %s "
13103457Sjc156560 			    "and controller %s successfully.\n"),
13113457Sjc156560 			    disk_argp, argv[optind]);
13123457Sjc156560 		}
13133457Sjc156560 	} else {
13148263SRyan.Wang@Sun.COM 		if ((ret = raidcfg_unset_hsp(&hsp_relation, NULL)) < 0) {
13153457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
13163457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
13173457Sjc156560 			return (FAILURE);
13183457Sjc156560 		}
13193457Sjc156560 
13203457Sjc156560 		if (hsp_type) {
13213457Sjc156560 			(void) printf(gettext("Unset local HSP between "
13223457Sjc156560 			    "disk %s and RAID volume %s successfully.\n"),
13233457Sjc156560 			    disk_argp, argv[optind]);
13243457Sjc156560 		} else {
13253457Sjc156560 			(void) printf(gettext("Unset global HSP between "
13263457Sjc156560 			    "disk %s and controller %s successfully.\n"),
13273457Sjc156560 			    disk_argp, argv[optind]);
13283457Sjc156560 		}
13290Sstevel@tonic-gate 	}
13303457Sjc156560 	(void) raidcfg_close_controller(ctl_handle, NULL);
13313457Sjc156560 	return (SUCCESS);
13320Sstevel@tonic-gate }
13330Sstevel@tonic-gate 
13343457Sjc156560 /*
13353457Sjc156560  * do_set_array_attr(f_flag, p_argp, argv, optind)
13363457Sjc156560  * This function changes array's attribute when array is running.
13373457Sjc156560  * The changeable attribute is up to controller's feature.
13383457Sjc156560  * The return value can be SUCCESS, FAILURE or INVALID_ARG.
13393457Sjc156560  */
13400Sstevel@tonic-gate static int
do_set_array_attr(uint32_t f_flag,char * p_argp,char ** argv,uint32_t optind)13413457Sjc156560 do_set_array_attr(uint32_t f_flag, char *p_argp, char **argv, uint32_t optind)
1342840Sjesseb {
13433457Sjc156560 	uint32_t ctl_tag = MAX32BIT;
13443457Sjc156560 	array_tag_t array_tag;
13453457Sjc156560 	uint32_t type = MAX32BIT;
13463457Sjc156560 	uint32_t value = MAX32BIT;
13473457Sjc156560 	raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
13483457Sjc156560 	raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
13493457Sjc156560 
13503457Sjc156560 	char *param, *op = "=";
13513457Sjc156560 
13523457Sjc156560 	int ret;
13533457Sjc156560 
13543457Sjc156560 	if (argv[optind] == NULL || argv[optind + 1] != NULL) {
13553457Sjc156560 		return (INVALID_ARG);
13563457Sjc156560 	}
13573457Sjc156560 
13583457Sjc156560 	if (p_argp != NULL) {
13593457Sjc156560 		param = strtok(p_argp, op);
13603457Sjc156560 		if (strcmp(param, "wp") == 0) {
13613457Sjc156560 			type = SET_CACHE_WR_PLY;
13627233Syw161884 			param = strtok(NULL, op);
13637233Syw161884 			if (strcmp(param, "on") == 0) {
13647233Syw161884 				value = CACHE_WR_ON;
13657233Syw161884 			} else if (strcmp(param, "off") == 0) {
13667233Syw161884 				value = CACHE_WR_OFF;
13677233Syw161884 			} else {
13687233Syw161884 				return (INVALID_ARG);
13697233Syw161884 			}
13707233Syw161884 		} else if (strcmp(param, "state") == 0) {
13717233Syw161884 			type = SET_ACTIVATION_PLY;
13727233Syw161884 			param = strtok(NULL, op);
13737233Syw161884 			if (strcmp(param, "activate") == 0) {
13747233Syw161884 				value = ARRAY_ACT_ACTIVATE;
13757233Syw161884 			} else {
13767233Syw161884 				return (INVALID_ARG);
13777233Syw161884 			}
13783457Sjc156560 		} else {
13793457Sjc156560 			return (INVALID_ARG);
13803457Sjc156560 		}
13813457Sjc156560 	} else {
13823457Sjc156560 		return (INVALID_ARG);
13833457Sjc156560 	}
13843457Sjc156560 
13853457Sjc156560 	if (get_array_tag(argv[optind], &ctl_tag, &array_tag) != SUCCESS) {
13863457Sjc156560 		return (INVALID_ARG);
13873457Sjc156560 	}
13883457Sjc156560 
13893457Sjc156560 	ctl_handle = raidcfg_get_controller(ctl_tag);
13903457Sjc156560 	if (ctl_handle <= 0) {
13913457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ctl_handle));
13923457Sjc156560 		return (FAILURE);
13933457Sjc156560 	}
13943457Sjc156560 
13953457Sjc156560 	ret = raidcfg_open_controller(ctl_handle, NULL);
13963457Sjc156560 	if (ret < 0) {
13973457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
13983457Sjc156560 		return (FAILURE);
13993457Sjc156560 	}
14003457Sjc156560 
14013457Sjc156560 	array_handle = raidcfg_get_array(ctl_handle, array_tag.idl.target_id,
14023457Sjc156560 	    array_tag.idl.lun);
14033457Sjc156560 	if (array_handle <= 0) {
14043457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(array_handle));
14053457Sjc156560 		return (FAILURE);
14063457Sjc156560 	}
14073457Sjc156560 
14083457Sjc156560 	/* Ask user to confirm operation. */
14093457Sjc156560 	if (f_flag == FALSE) {
14103457Sjc156560 		(void) fprintf(stdout, gettext("Update attribute of "
14113457Sjc156560 		    "array %s (%s/%s)? "), argv[optind], yesstr, nostr);
14123457Sjc156560 		if (!yes()) {
14133457Sjc156560 			(void) fprintf(stdout,
14143457Sjc156560 			    gettext("Array %s not "
14153457Sjc156560 			    "changed.\n\n"), argv[optind]);
14163457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
14173457Sjc156560 			return (SUCCESS);
14183457Sjc156560 		}
14193457Sjc156560 	}
14203457Sjc156560 
14213457Sjc156560 	if ((ret = raidcfg_set_attr(array_handle, type, &value, NULL)) < 0) {
14223457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
14233457Sjc156560 		(void) raidcfg_close_controller(ctl_handle, NULL);
14243457Sjc156560 		return (FAILURE);
14253457Sjc156560 	}
14263457Sjc156560 
14273457Sjc156560 	(void) printf(gettext("Set attribute of RAID volume %s "
14283457Sjc156560 	    "successfully.\n"), argv[optind]);
14293457Sjc156560 	(void) raidcfg_close_controller(ctl_handle, NULL);
14303457Sjc156560 
14313457Sjc156560 	return (SUCCESS);
14323457Sjc156560 }
14333457Sjc156560 
14343457Sjc156560 /*
14353457Sjc156560  * snapshot_raidsystem(recursive, indent, is_snapshot)
14363457Sjc156560  * This function prints the snapshot of whole RAID's system configuration,
14373457Sjc156560  * and return result as SUCCESS or FAILURE.
14383457Sjc156560  */
14393457Sjc156560 static int
snapshot_raidsystem(uint8_t recursive,uint8_t indent,uint8_t is_snapshot)14403457Sjc156560 snapshot_raidsystem(uint8_t recursive, uint8_t indent, uint8_t is_snapshot)
14413457Sjc156560 {
14423457Sjc156560 	raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
14433457Sjc156560 	int ret;
14443457Sjc156560 
14453457Sjc156560 	ctl_handle = raidcfg_list_head(OBJ_SYSTEM, OBJ_TYPE_CONTROLLER);
14463457Sjc156560 	while (ctl_handle > 0) {
14473457Sjc156560 		ret = raidcfg_open_controller(ctl_handle, NULL);
14483457Sjc156560 		if (ret == 0) {
14493457Sjc156560 			if (snapshot_ctl(ctl_handle, recursive, indent,
14503457Sjc156560 			    is_snapshot) == FAILURE) {
14513457Sjc156560 				(void) raidcfg_close_controller(ctl_handle,
14523457Sjc156560 				    NULL);
1453840Sjesseb 			}
1454840Sjesseb 		}
14553457Sjc156560 		ctl_handle = raidcfg_list_next(ctl_handle);
1456840Sjesseb 	}
14573457Sjc156560 	return (SUCCESS);
1458840Sjesseb }
1459840Sjesseb 
14603457Sjc156560 /*
14613457Sjc156560  * snapshot_ctl(ctl_handle, recursive, indent, is_snapshot)
14623457Sjc156560  * This function prints snapshot of specified controller's configuration,
14633457Sjc156560  * and return result as SUCCESS or FAILURE.
14643457Sjc156560  */
1465840Sjesseb static int
snapshot_ctl(raid_obj_handle_t ctl_handle,uint8_t recursive,uint8_t indent,uint8_t is_snapshot)14663457Sjc156560 snapshot_ctl(raid_obj_handle_t ctl_handle, uint8_t recursive, uint8_t indent,
14673457Sjc156560     uint8_t is_snapshot)
14683457Sjc156560 {
14693457Sjc156560 	raid_obj_handle_t array_handle = INIT_HANDLE_VALUE;
14703457Sjc156560 	raid_obj_handle_t disk_handle = INIT_HANDLE_VALUE;
14713457Sjc156560 	raidcfg_controller_t ctl_attr;
14723457Sjc156560 	uint32_t ctl_tag;
14733457Sjc156560 	char ctlbuf[256];
14743457Sjc156560 	int ret;
14753457Sjc156560 
14763457Sjc156560 	if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
14773457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
14783457Sjc156560 		return (FAILURE);
14793457Sjc156560 	}
14803457Sjc156560 
14813457Sjc156560 	ctl_tag = ctl_attr.controller_id;
14823457Sjc156560 	if (is_snapshot == FALSE) {
14833457Sjc156560 		print_indent(indent);
14843457Sjc156560 		(void) fprintf(stdout, gettext("Controller: %u\n"), ctl_tag);
14853457Sjc156560 	} else {
14863457Sjc156560 		(void) snprintf(ctlbuf, sizeof (ctlbuf), "%u \"%s\"",
14873457Sjc156560 		    ctl_tag, ctl_attr.controller_type);
14883457Sjc156560 		(void) fprintf(stdout, "%s", ctlbuf);
14893457Sjc156560 
14903457Sjc156560 		(void) fprintf(stdout, "\n");
14913457Sjc156560 	}
14923457Sjc156560 
14933457Sjc156560 	if (recursive == TRUE) {
14943457Sjc156560 		array_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_ARRAY);
14953457Sjc156560 		while (array_handle > 0) {
14963457Sjc156560 			if (snapshot_array(array_handle,
14973457Sjc156560 			    indent + 1, FALSE, is_snapshot) == FAILURE) {
14983457Sjc156560 				return (FAILURE);
14993457Sjc156560 			}
15003457Sjc156560 
15013457Sjc156560 			array_handle = raidcfg_list_next(array_handle);
15023457Sjc156560 		}
15033457Sjc156560 
15043457Sjc156560 		disk_handle = raidcfg_list_head(ctl_handle, OBJ_TYPE_DISK);
15053457Sjc156560 		while (disk_handle > 0) {
15063457Sjc156560 			if (snapshot_disk(ctl_tag, disk_handle,
15073457Sjc156560 			    indent + 1, is_snapshot) == FAILURE) {
15083457Sjc156560 				return (FAILURE);
15093457Sjc156560 			}
15103457Sjc156560 
15113457Sjc156560 			disk_handle = raidcfg_list_next(disk_handle);
15123457Sjc156560 		}
15133457Sjc156560 	}
15143457Sjc156560 	return (SUCCESS);
15153457Sjc156560 }
15163457Sjc156560 
15173457Sjc156560 
15183457Sjc156560 /*
15193457Sjc156560  * snapshot_array(array_handle, indent, is_sub, is_snapshot)
15203457Sjc156560  * This function prints snapshot of specified array's configuration,
15213457Sjc156560  * and return result as SUCCESS or FAILURE.
15223457Sjc156560  */
15233457Sjc156560 static int
snapshot_array(raid_obj_handle_t array_handle,uint8_t indent,uint8_t is_sub,uint8_t is_snapshot)15243457Sjc156560 snapshot_array(raid_obj_handle_t array_handle, uint8_t indent, uint8_t is_sub,
15253457Sjc156560     uint8_t is_snapshot)
15260Sstevel@tonic-gate {
15273457Sjc156560 	raid_obj_handle_t ctl_handle;
15283457Sjc156560 	raid_obj_handle_t subarray_handle;
15293457Sjc156560 	raid_obj_handle_t arraypart_handle;
15303457Sjc156560 	raid_obj_handle_t task_handle;
15313457Sjc156560 
15323457Sjc156560 	raidcfg_controller_t ctl_attr;
15333457Sjc156560 	raidcfg_array_t array_attr;
15343457Sjc156560 	raidcfg_arraypart_t arraypart_attr;
15353457Sjc156560 	raidcfg_task_t task_attr;
15363457Sjc156560 
15373457Sjc156560 	char arraybuf[256] = "\0";
15383457Sjc156560 	char diskbuf[256] = "\0";
15393457Sjc156560 	char tempbuf[256] = "\0";
15403457Sjc156560 	int disknum = 0;
15413457Sjc156560 
15423457Sjc156560 	uint32_t ctl_tag;
15433457Sjc156560 	int ret;
15443457Sjc156560 
15453457Sjc156560 	ctl_handle = raidcfg_get_container(array_handle);
15463457Sjc156560 	ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
15473457Sjc156560 	if (ret < 0) {
15483457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
15493457Sjc156560 		return (FAILURE);
15503457Sjc156560 	}
15513457Sjc156560 	ctl_tag = ctl_attr.controller_id;
15523457Sjc156560 
15533457Sjc156560 	/* Print array attribute */
15543457Sjc156560 	if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
15553457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
15563457Sjc156560 		return (FAILURE);
15570Sstevel@tonic-gate 	}
15580Sstevel@tonic-gate 
15593457Sjc156560 	if (is_snapshot == FALSE) {
15603457Sjc156560 		print_indent(indent);
15613457Sjc156560 		if (is_sub == FALSE) {
15623457Sjc156560 			(void) fprintf(stdout, gettext("Volume:"
15633457Sjc156560 			    "c%ut%llud%llu\n"),
15643457Sjc156560 			    ctl_tag, array_attr.tag.idl.target_id,
15653457Sjc156560 			    array_attr.tag.idl.lun);
15663457Sjc156560 		} else {
15673457Sjc156560 			(void) fprintf(stdout, gettext("Sub-Volume\n"));
15683457Sjc156560 		}
15693457Sjc156560 	} else {
15703457Sjc156560 		(void) snprintf(arraybuf, sizeof (arraybuf), "c%ut%llud%llu ",
15713457Sjc156560 		    ctl_tag, array_attr.tag.idl.target_id,
15723457Sjc156560 		    array_attr.tag.idl.lun);
15733457Sjc156560 
15743457Sjc156560 		/* Check if array is in sync state */
15753457Sjc156560 		task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK);
15763457Sjc156560 		if (task_handle > 0) {
15773457Sjc156560 			(void) raidcfg_get_attr(task_handle, &task_attr);
15783457Sjc156560 			if (task_attr.task_func == TASK_FUNC_BUILD) {
15793457Sjc156560 				array_attr.state = ARRAY_STATE_SYNC;
15803457Sjc156560 			}
15813457Sjc156560 		} else {
15823457Sjc156560 			subarray_handle = raidcfg_list_head(array_handle,
15834563Syw161884 			    OBJ_TYPE_ARRAY);
15843457Sjc156560 			while (subarray_handle > 0) {
15853457Sjc156560 				task_handle = raidcfg_list_head(subarray_handle,
15864563Syw161884 				    OBJ_TYPE_TASK);
15873457Sjc156560 				if (task_handle > 0) {
15883457Sjc156560 					(void) raidcfg_get_attr(task_handle,
15893457Sjc156560 					    &task_attr);
15903457Sjc156560 					if (task_attr.task_func ==
15913457Sjc156560 					    TASK_FUNC_BUILD) {
15923457Sjc156560 						array_attr.state =
15933457Sjc156560 						    ARRAY_STATE_SYNC;
15943457Sjc156560 					}
15953457Sjc156560 					break;
15963457Sjc156560 				}
15973457Sjc156560 				subarray_handle =
15983457Sjc156560 				    raidcfg_list_next(subarray_handle);
15993457Sjc156560 			}
16003457Sjc156560 		}
16013457Sjc156560 
16023457Sjc156560 		/* Print sub array */
16033457Sjc156560 		subarray_handle = raidcfg_list_head(array_handle,
16043457Sjc156560 		    OBJ_TYPE_ARRAY);
16053457Sjc156560 		while (subarray_handle > 0) {
16063457Sjc156560 			/* print subarraypart */
16073457Sjc156560 			arraypart_handle = raidcfg_list_head(subarray_handle,
16083457Sjc156560 			    OBJ_TYPE_ARRAY_PART);
16093457Sjc156560 			while (arraypart_handle > 0) {
16103457Sjc156560 				if ((ret = raidcfg_get_attr(arraypart_handle,
16113457Sjc156560 				    &arraypart_attr)) < 0) {
16123457Sjc156560 					(void) fprintf(stderr, "%s\n",
16133457Sjc156560 					    raidcfg_errstr(ret));
16143457Sjc156560 					return (FAILURE);
16153457Sjc156560 				}
16163457Sjc156560 
16173457Sjc156560 				if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
16183457Sjc156560 					(void) snprintf(tempbuf,
16193457Sjc156560 					    sizeof (tempbuf),
16203457Sjc156560 					    gettext("N/A"));
16213457Sjc156560 				} else {
16223457Sjc156560 					(void) snprintf(tempbuf,
16233457Sjc156560 					    sizeof (tempbuf),
16243457Sjc156560 					    "%llu.%llu.%llu",
16253457Sjc156560 					    arraypart_attr.tag.cidl.bus,
16263457Sjc156560 					    arraypart_attr.tag.cidl.target_id,
16273457Sjc156560 					    arraypart_attr.tag.cidl.lun);
16283457Sjc156560 				}
16297336SRyan.Wang@Sun.COM 				(void) strlcat(diskbuf, tempbuf,
16307336SRyan.Wang@Sun.COM 				    sizeof (diskbuf));
16313457Sjc156560 				(void) strcat(diskbuf, " ");
16323457Sjc156560 				disknum++;
16333457Sjc156560 				arraypart_handle =
16343457Sjc156560 				    raidcfg_list_next(arraypart_handle);
16353457Sjc156560 			}
16363457Sjc156560 			subarray_handle = raidcfg_list_next(subarray_handle);
16373457Sjc156560 		}
16383457Sjc156560 
16393457Sjc156560 		/* Print arraypart */
16403457Sjc156560 		arraypart_handle = raidcfg_list_head(array_handle,
16413457Sjc156560 		    OBJ_TYPE_ARRAY_PART);
16423457Sjc156560 		while (arraypart_handle > 0) {
16433457Sjc156560 			if ((ret = raidcfg_get_attr(arraypart_handle,
16443457Sjc156560 			    &arraypart_attr)) < 0) {
16453457Sjc156560 				(void) fprintf(stderr, "%s\n",
16463457Sjc156560 				    raidcfg_errstr(ret));
16473457Sjc156560 				return (FAILURE);
16483457Sjc156560 			}
16493457Sjc156560 
16503457Sjc156560 			if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
16513457Sjc156560 				(void) snprintf(tempbuf, sizeof (tempbuf),
16523457Sjc156560 				    gettext("N/A"));
16533457Sjc156560 			} else {
16543457Sjc156560 				(void) snprintf(tempbuf, sizeof (tempbuf),
16553457Sjc156560 				    "%llu.%llu.%llu",
16563457Sjc156560 				    arraypart_attr.tag.cidl.bus,
16573457Sjc156560 				    arraypart_attr.tag.cidl.target_id,
16583457Sjc156560 				    arraypart_attr.tag.cidl.lun);
16593457Sjc156560 			}
16607336SRyan.Wang@Sun.COM 			(void) strlcat(diskbuf, tempbuf, sizeof (diskbuf));
16613457Sjc156560 			(void) strcat(diskbuf, " ");
16623457Sjc156560 			disknum++;
16633457Sjc156560 			arraypart_handle = raidcfg_list_next(arraypart_handle);
16643457Sjc156560 		}
16653457Sjc156560 		(void) snprintf(tempbuf, sizeof (tempbuf), "%u ", disknum);
16667336SRyan.Wang@Sun.COM 		(void) strlcat(arraybuf, tempbuf, sizeof (arraybuf));
16677336SRyan.Wang@Sun.COM 		(void) strlcat(arraybuf, diskbuf, sizeof (arraybuf));
16683457Sjc156560 
16693457Sjc156560 		switch (array_attr.raid_level) {
16703457Sjc156560 		case RAID_LEVEL_0:
16713457Sjc156560 			(void) sprintf(tempbuf, "0");
16723457Sjc156560 			break;
16733457Sjc156560 		case RAID_LEVEL_1:
16743457Sjc156560 			(void) sprintf(tempbuf, "1");
16753457Sjc156560 			break;
16763457Sjc156560 		case RAID_LEVEL_1E:
16773457Sjc156560 			(void) sprintf(tempbuf, "1E");
16783457Sjc156560 			break;
16793457Sjc156560 		case RAID_LEVEL_5:
16803457Sjc156560 			(void) sprintf(tempbuf, "5");
16813457Sjc156560 			break;
16823457Sjc156560 		case RAID_LEVEL_10:
16833457Sjc156560 			(void) sprintf(tempbuf, "10");
16843457Sjc156560 			break;
16853457Sjc156560 		case RAID_LEVEL_50:
16863457Sjc156560 			(void) sprintf(tempbuf, "50");
16873457Sjc156560 			break;
16883457Sjc156560 		default:
16893457Sjc156560 			(void) snprintf(tempbuf, sizeof (tempbuf),
16903457Sjc156560 			    gettext("N/A"));
16910Sstevel@tonic-gate 			break;
16920Sstevel@tonic-gate 		}
16937336SRyan.Wang@Sun.COM 		(void) strlcat(arraybuf, tempbuf, sizeof (arraybuf));
16943457Sjc156560 		(void) fprintf(stdout, "%s ", arraybuf);
16953457Sjc156560 
16963457Sjc156560 		switch (array_attr.state) {
16973457Sjc156560 		case ARRAY_STATE_OPTIMAL:
16983457Sjc156560 			(void) fprintf(stdout, gettext("OPTIMAL"));
16993457Sjc156560 			break;
17003457Sjc156560 		case ARRAY_STATE_DEGRADED:
17013457Sjc156560 			(void) fprintf(stdout, gettext("DEGRADED"));
17023457Sjc156560 			break;
17033457Sjc156560 		case ARRAY_STATE_FAILED:
17043457Sjc156560 			(void) fprintf(stdout, gettext("FAILED"));
17053457Sjc156560 			break;
17063457Sjc156560 		case ARRAY_STATE_SYNC:
17073457Sjc156560 			(void) fprintf(stdout, gettext("SYNC"));
17083457Sjc156560 			break;
17096221Szk194757 		case ARRAY_STATE_MISSING:
17106221Szk194757 			(void) fprintf(stdout, gettext("MISSING"));
17116221Szk194757 			break;
17123457Sjc156560 		default:
17133457Sjc156560 			(void) fprintf(stdout, gettext("N/A"));
1714840Sjesseb 			break;
17150Sstevel@tonic-gate 		}
17163457Sjc156560 		(void) fprintf(stdout, "\n");
17173457Sjc156560 	}
17183457Sjc156560 
17193457Sjc156560 	return (SUCCESS);
17203457Sjc156560 }
17213457Sjc156560 
17223457Sjc156560 /*
17233457Sjc156560  * snapshot_disk(ctl_tag, disk_handle, indent, is_snapshot)
17243457Sjc156560  * This function prints snapshot of specified disk's configuration, and return
17253457Sjc156560  * result as SUCCESS or FAILURE.
17263457Sjc156560  */
17273457Sjc156560 static int
snapshot_disk(uint32_t ctl_tag,raid_obj_handle_t disk_handle,uint8_t indent,uint8_t is_snapshot)17283457Sjc156560 snapshot_disk(uint32_t ctl_tag, raid_obj_handle_t disk_handle, uint8_t indent,
17293457Sjc156560     uint8_t is_snapshot)
17303457Sjc156560 {
17313457Sjc156560 	raid_obj_handle_t ctl_handle = INIT_HANDLE_VALUE;
17323457Sjc156560 	raid_obj_handle_t hsp_handle;
17333457Sjc156560 
17343457Sjc156560 	raidcfg_controller_t ctl_attr;
17353457Sjc156560 	raidcfg_disk_t disk_attr;
17363457Sjc156560 	char diskbuf[256] = "";
17373457Sjc156560 	char tempbuf[256] = "";
17383457Sjc156560 
17393457Sjc156560 	int ret;
17403457Sjc156560 
17413457Sjc156560 	ctl_handle = raidcfg_get_controller(ctl_tag);
17423457Sjc156560 	ret = raidcfg_get_attr(ctl_handle, &ctl_attr);
17433457Sjc156560 	if (ret < 0) {
17443457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
17453457Sjc156560 		return (FAILURE);
17463457Sjc156560 	}
17473457Sjc156560 
17483457Sjc156560 	/* Print attribute of disk */
17493457Sjc156560 	if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
17503457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
17513457Sjc156560 		return (FAILURE);
17523457Sjc156560 	}
17533457Sjc156560 
17543457Sjc156560 	if (is_snapshot == FALSE) {
17553457Sjc156560 		print_indent(indent);
17563457Sjc156560 
17573457Sjc156560 		hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
17583457Sjc156560 
17593457Sjc156560 		if (disk_attr.tag.cidl.bus == MAX64BIT) {
17603457Sjc156560 			(void) fprintf(stdout, gettext("Disk: N/A"));
17613457Sjc156560 		} else {
17623457Sjc156560 			(void) fprintf(stdout, gettext("Disk: %llu.%llu.%llu"),
17633457Sjc156560 			    disk_attr.tag.cidl.bus,
17643457Sjc156560 			    disk_attr.tag.cidl.target_id,
17653457Sjc156560 			    disk_attr.tag.cidl.lun);
1766840Sjesseb 		}
17673457Sjc156560 		if (hsp_handle > 0) {
17683457Sjc156560 			(void) fprintf(stdout, "(HSP)");
17693457Sjc156560 		}
17703457Sjc156560 		(void) fprintf(stdout, "\n");
17713457Sjc156560 	} else {
17723457Sjc156560 		if (disk_attr.tag.cidl.bus == MAX64BIT) {
17733457Sjc156560 			(void) fprintf(stdout, gettext("N/A"));
17743457Sjc156560 		} else {
17753457Sjc156560 			(void) snprintf(diskbuf, sizeof (diskbuf),
17763457Sjc156560 			    "%llu.%llu.%llu ",
17773457Sjc156560 			    disk_attr.tag.cidl.bus,
17783457Sjc156560 			    disk_attr.tag.cidl.target_id,
17793457Sjc156560 			    disk_attr.tag.cidl.lun);
1780840Sjesseb 		}
17813457Sjc156560 		hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
17823457Sjc156560 		if (hsp_handle > 0) {
17833457Sjc156560 			(void) snprintf(tempbuf, sizeof (tempbuf),
17843457Sjc156560 			    gettext("HSP"));
17853457Sjc156560 		} else if (disk_attr.state == DISK_STATE_GOOD) {
17863457Sjc156560 			(void) snprintf(tempbuf, sizeof (tempbuf),
17873457Sjc156560 			    gettext("GOOD"));
17883457Sjc156560 		} else if (disk_attr.state == DISK_STATE_FAILED) {
17893457Sjc156560 			(void) snprintf(tempbuf, sizeof (tempbuf),
17903457Sjc156560 			    gettext("FAILED"));
17913457Sjc156560 		} else {
17923457Sjc156560 			(void) snprintf(tempbuf, sizeof (tempbuf),
17933457Sjc156560 			    gettext("N/A"));
17943457Sjc156560 		}
17953457Sjc156560 
17967336SRyan.Wang@Sun.COM 		(void) strlcat(diskbuf, tempbuf, sizeof (diskbuf));
17973457Sjc156560 		(void) fprintf(stdout, "%s\n", diskbuf);
17980Sstevel@tonic-gate 	}
17990Sstevel@tonic-gate 
18000Sstevel@tonic-gate 	return (SUCCESS);
18010Sstevel@tonic-gate }
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate static int
print_ctl_table(raid_obj_handle_t ctl_handle)18043457Sjc156560 print_ctl_table(raid_obj_handle_t ctl_handle)
18050Sstevel@tonic-gate {
18063457Sjc156560 	raidcfg_controller_t ctl_attr;
18073457Sjc156560 	char controller[8];
18083457Sjc156560 	int ret;
18093457Sjc156560 
18103457Sjc156560 	if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
18113457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
18120Sstevel@tonic-gate 		return (FAILURE);
18133457Sjc156560 	}
18143457Sjc156560 
18153457Sjc156560 	(void) fprintf(stdout, gettext("Controller\tType\t\tVersion"));
18163457Sjc156560 	(void) fprintf(stdout, "\n");
18173457Sjc156560 	(void) fprintf(stdout, "--------------------------------");
18183457Sjc156560 	(void) fprintf(stdout, "--------------------------------");
18193457Sjc156560 	(void) fprintf(stdout, "\n");
18203457Sjc156560 
18213457Sjc156560 	(void) snprintf(controller, sizeof (controller), "%u",
18223457Sjc156560 	    ctl_attr.controller_id);
18233457Sjc156560 	(void) printf("c%s\t\t", controller);
18243457Sjc156560 
18253457Sjc156560 	(void) print_ctl_attr(&ctl_attr);
18263457Sjc156560 	(void) fprintf(stdout, "\n");
18273457Sjc156560 
18283457Sjc156560 	return (SUCCESS);
18290Sstevel@tonic-gate }
18300Sstevel@tonic-gate 
18310Sstevel@tonic-gate static int
print_array_table(raid_obj_handle_t ctl_handle,raid_obj_handle_t array_handle)18323457Sjc156560 print_array_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t array_handle)
18330Sstevel@tonic-gate {
18343457Sjc156560 	raidcfg_controller_t ctl_attr;
18353457Sjc156560 	raidcfg_array_t array_attr;
18363457Sjc156560 	raidcfg_array_t subarray_attr;
18373457Sjc156560 	raidcfg_arraypart_t arraypart_attr;
18383457Sjc156560 	raidcfg_task_t task_attr;
18393457Sjc156560 
18403457Sjc156560 	raid_obj_handle_t subarray_handle;
18413457Sjc156560 	raid_obj_handle_t arraypart_handle;
18423457Sjc156560 	raid_obj_handle_t task_handle;
18433457Sjc156560 
18447233Syw161884 	char array[16];
18453457Sjc156560 	char arraypart[8];
18463457Sjc156560 	int ret;
18473457Sjc156560 	int i;
18483457Sjc156560 
18493457Sjc156560 	/* Controller attribute */
18503457Sjc156560 	if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
18513457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
18523457Sjc156560 		return (FAILURE);
1853548Sdduvall 	}
18540Sstevel@tonic-gate 
18553457Sjc156560 	/* Array attribute */
18563457Sjc156560 	if ((ret = raidcfg_get_attr(array_handle, &array_attr)) < 0) {
18573457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
18580Sstevel@tonic-gate 		return (FAILURE);
18590Sstevel@tonic-gate 	}
18600Sstevel@tonic-gate 
18613457Sjc156560 	/* print header */
18623457Sjc156560 	(void) fprintf(stdout, gettext("Volume\t\t\tSize\tStripe\tStatus\t"
18633457Sjc156560 	    " Cache\tRAID"));
18643457Sjc156560 	(void) fprintf(stdout, "\n");
18653457Sjc156560 	(void) fprintf(stdout, gettext("\tSub\t\t\tSize\t\t\tLevel"));
18663457Sjc156560 	(void) fprintf(stdout, "\n");
18673457Sjc156560 	(void) fprintf(stdout, gettext("\t\tDisk\t\t\t\t\t"));
18683457Sjc156560 	(void) fprintf(stdout, "\n");
18693457Sjc156560 	(void) fprintf(stdout, "--------------------------------");
18703457Sjc156560 	(void) fprintf(stdout, "--------------------------------");
18713457Sjc156560 	(void) fprintf(stdout, "\n");
18723457Sjc156560 
18733457Sjc156560 	/* print array */
18743457Sjc156560 	(void) snprintf(array, sizeof (array), "c%ut%llud%llu",
18753457Sjc156560 	    ctl_attr.controller_id, array_attr.tag.idl.target_id,
18763457Sjc156560 	    array_attr.tag.idl.lun);
18777233Syw161884 	(void) fprintf(stdout, "%s\t\t", array);
18787233Syw161884 	if (strlen(array) < 8)
18797233Syw161884 		(void) fprintf(stdout, "\t");
18807233Syw161884 
18813457Sjc156560 
18823457Sjc156560 	/* check if array is in sync state */
18833457Sjc156560 	task_handle = raidcfg_list_head(array_handle, OBJ_TYPE_TASK);
18843457Sjc156560 	if (task_handle > 0) {
18853457Sjc156560 		(void) raidcfg_get_attr(task_handle, &task_attr);
18863457Sjc156560 		if (task_attr.task_func == TASK_FUNC_BUILD) {
18873457Sjc156560 			array_attr.state = ARRAY_STATE_SYNC;
1888840Sjesseb 		}
18893457Sjc156560 	} else {
18903457Sjc156560 		subarray_handle = raidcfg_list_head(array_handle,
18913457Sjc156560 		    OBJ_TYPE_ARRAY);
18923457Sjc156560 		while (subarray_handle > 0) {
18933457Sjc156560 			task_handle = raidcfg_list_head(subarray_handle,
18943457Sjc156560 			    OBJ_TYPE_TASK);
18953457Sjc156560 			if (task_handle > 0) {
18963457Sjc156560 				(void) raidcfg_get_attr(task_handle,
18973457Sjc156560 				    &task_attr);
18983457Sjc156560 				if (task_attr.task_func == TASK_FUNC_BUILD) {
18993457Sjc156560 					array_attr.state = ARRAY_STATE_SYNC;
19003457Sjc156560 				}
19013457Sjc156560 				break;
19023457Sjc156560 			}
19033457Sjc156560 			subarray_handle = raidcfg_list_next(subarray_handle);
1904840Sjesseb 		}
19053457Sjc156560 	}
19063457Sjc156560 
19073457Sjc156560 	(void) print_array_attr(&array_attr);
19083457Sjc156560 	(void) fprintf(stdout, "\n");
19093457Sjc156560 
19103457Sjc156560 	/* Print sub array */
19113457Sjc156560 	i = 0;			/* Count sub array number */
19123457Sjc156560 	subarray_handle = raidcfg_list_head(array_handle, OBJ_TYPE_ARRAY);
19133457Sjc156560 	while (subarray_handle > 0) {
19143457Sjc156560 		if ((ret = raidcfg_get_attr(subarray_handle,
19153457Sjc156560 		    &subarray_attr)) < 0) {
19163457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
19173457Sjc156560 			return (FAILURE);
1918840Sjesseb 		}
1919840Sjesseb 
19203457Sjc156560 		/* Use sub0/sub1 here, not cxtxd0 for subarray */
19213457Sjc156560 		(void) snprintf(array, sizeof (array), "sub%u", i++);
19223457Sjc156560 		(void) fprintf(stdout, "\t%s\t\t", array);
19233457Sjc156560 
19243457Sjc156560 		/* Check if array is in sync */
19253457Sjc156560 		task_handle = raidcfg_list_head(subarray_handle, OBJ_TYPE_TASK);
19263457Sjc156560 		if (task_handle > 0) {
19273457Sjc156560 			(void) raidcfg_get_attr(task_handle, &task_attr);
19283457Sjc156560 			if (task_attr.task_func == TASK_FUNC_BUILD) {
19293457Sjc156560 				subarray_attr.state = ARRAY_STATE_SYNC;
1930840Sjesseb 			}
1931840Sjesseb 		}
1932840Sjesseb 
19333457Sjc156560 		(void) print_array_attr(&subarray_attr);
19343457Sjc156560 		(void) fprintf(stdout, "\n");
19353457Sjc156560 
19363457Sjc156560 		/* Print subarraypart */
19373457Sjc156560 		arraypart_handle = raidcfg_list_head(subarray_handle,
19383457Sjc156560 		    OBJ_TYPE_ARRAY_PART);
19393457Sjc156560 		while (arraypart_handle > 0) {
19403457Sjc156560 			if ((ret = raidcfg_get_attr(arraypart_handle,
19413457Sjc156560 			    &arraypart_attr)) < 0) {
19423457Sjc156560 				(void) fprintf(stderr, "%s\n",
19433457Sjc156560 				    raidcfg_errstr(ret));
19443457Sjc156560 				return (FAILURE);
19453457Sjc156560 			}
19463457Sjc156560 
19473457Sjc156560 			if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
19483457Sjc156560 				(void) snprintf(arraypart, sizeof (arraypart),
19493457Sjc156560 				    gettext("N/A"));
19503457Sjc156560 			} else {
19513457Sjc156560 				(void) snprintf(arraypart, sizeof (arraypart),
19523457Sjc156560 				    "%llu.%llu.%llu",
19533457Sjc156560 				    arraypart_attr.tag.cidl.bus,
19543457Sjc156560 				    arraypart_attr.tag.cidl.target_id,
19553457Sjc156560 				    arraypart_attr.tag.cidl.lun);
19563457Sjc156560 			}
19573457Sjc156560 
19583457Sjc156560 			(void) fprintf(stdout, "\t\t%s\t", arraypart);
19593457Sjc156560 			(void) print_arraypart_attr(&arraypart_attr);
19603457Sjc156560 			(void) fprintf(stdout, "\n");
19613457Sjc156560 			arraypart_handle = raidcfg_list_next(arraypart_handle);
19623457Sjc156560 		}
19633457Sjc156560 		subarray_handle = raidcfg_list_next(subarray_handle);
1964840Sjesseb 	}
1965840Sjesseb 
19663457Sjc156560 	/* Print arraypart */
19673457Sjc156560 	arraypart_handle = raidcfg_list_head(array_handle,
19683457Sjc156560 	    OBJ_TYPE_ARRAY_PART);
19693457Sjc156560 	while (arraypart_handle > 0) {
19703457Sjc156560 		if ((ret = raidcfg_get_attr(arraypart_handle,
19713457Sjc156560 		    &arraypart_attr)) < 0) {
19723457Sjc156560 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
19733457Sjc156560 			return (FAILURE);
19743457Sjc156560 		}
19753457Sjc156560 
19763457Sjc156560 		if (arraypart_attr.tag.cidl.bus == MAX64BIT) {
19773457Sjc156560 			(void) snprintf(arraypart, sizeof (arraypart),
19783457Sjc156560 			    gettext("N/A"));
19793457Sjc156560 		} else {
19803457Sjc156560 			(void) snprintf(arraypart, sizeof (arraypart),
19813457Sjc156560 			    "%llu.%llu.%llu",
19823457Sjc156560 			    arraypart_attr.tag.cidl.bus,
19833457Sjc156560 			    arraypart_attr.tag.cidl.target_id,
19843457Sjc156560 			    arraypart_attr.tag.cidl.lun);
19853457Sjc156560 		}
19863457Sjc156560 
19873457Sjc156560 		(void) fprintf(stdout, "\t\t%s\t", arraypart);
19883457Sjc156560 		(void) print_arraypart_attr(&arraypart_attr);
19893457Sjc156560 		(void) fprintf(stdout, "\n");
19903457Sjc156560 		arraypart_handle = raidcfg_list_next(arraypart_handle);
19910Sstevel@tonic-gate 	}
19920Sstevel@tonic-gate 
19930Sstevel@tonic-gate 	return (SUCCESS);
19940Sstevel@tonic-gate }
19950Sstevel@tonic-gate 
19960Sstevel@tonic-gate static int
print_disk_table(raid_obj_handle_t ctl_handle,raid_obj_handle_t disk_handle)19973457Sjc156560 print_disk_table(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle)
19980Sstevel@tonic-gate {
19993457Sjc156560 	raidcfg_controller_t ctl_attr;
20003457Sjc156560 	raidcfg_disk_t disk_attr;
20017233Syw161884 	raidcfg_prop_t *prop_attr, *prop_attr2;
20027233Syw161884 	raid_obj_handle_t prop_handle;
20033457Sjc156560 	char disk[8];
20043457Sjc156560 	int ret;
20053457Sjc156560 
20063457Sjc156560 	if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
20073457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
20083457Sjc156560 		return (FAILURE);
20090Sstevel@tonic-gate 	}
20103457Sjc156560 
20113457Sjc156560 	if ((ret = raidcfg_get_attr(disk_handle, &disk_attr)) < 0) {
20123457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
20130Sstevel@tonic-gate 		return (FAILURE);
20140Sstevel@tonic-gate 	}
20150Sstevel@tonic-gate 
20163457Sjc156560 	/* Print header */
2017*8856SMilan.Jurik@Sun.COM 	(void) fprintf(stdout, gettext("Disk\tVendor   Product          "
2018*8856SMilan.Jurik@Sun.COM 	    "Firmware\tCapacity\tStatus\tHSP"));
20193457Sjc156560 	(void) fprintf(stdout, "\n");
20205683Szk194757 	(void) fprintf(stdout, "--------------------------------------");
20215683Szk194757 	(void) fprintf(stdout, "--------------------------------------");
20223457Sjc156560 	(void) fprintf(stdout, "\n");
20233457Sjc156560 
20243457Sjc156560 
20253457Sjc156560 	(void) snprintf(disk, sizeof (disk), "%llu.%llu.%llu",
20263457Sjc156560 	    disk_attr.tag.cidl.bus,
20273457Sjc156560 	    disk_attr.tag.cidl.target_id,
20283457Sjc156560 	    disk_attr.tag.cidl.lun);
20293457Sjc156560 
20303457Sjc156560 	(void) fprintf(stdout, "%s\t", disk);
20313457Sjc156560 
20323457Sjc156560 	(void) print_disk_attr(ctl_handle, disk_handle, &disk_attr);
20337233Syw161884 
20347233Syw161884 	prop_attr = calloc(1, sizeof (raidcfg_prop_t));
20357233Syw161884 	if (prop_attr == NULL) {
20367233Syw161884 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM));
20377233Syw161884 		return (FAILURE);
20387233Syw161884 	}
20397233Syw161884 
20407233Syw161884 	prop_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_PROP);
20417233Syw161884 	if (prop_handle == 0) {
20427233Syw161884 		free(prop_attr);
20437233Syw161884 		return (SUCCESS);
20447233Syw161884 	}
20457233Syw161884 
20467233Syw161884 	do {
20477233Syw161884 		prop_attr->prop_size = 0;
20487233Syw161884 		if ((ret = raidcfg_get_attr(prop_handle, prop_attr)) < 0) {
20497233Syw161884 			free(prop_attr);
20507233Syw161884 			(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
20517233Syw161884 			return (FAILURE);
20527233Syw161884 		}
20537233Syw161884 		if (prop_attr->prop_type == PROP_GUID)
20547233Syw161884 			break;
20557233Syw161884 	} while (prop_handle != 0);
20567233Syw161884 
20577233Syw161884 	prop_attr2 = realloc(prop_attr,
20587233Syw161884 	    sizeof (raidcfg_prop_t) + prop_attr->prop_size);
20597233Syw161884 	free(prop_attr);
20607233Syw161884 	if (prop_attr2 == NULL) {
20617233Syw161884 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ERR_NOMEM));
20627233Syw161884 		return (FAILURE);
20637233Syw161884 	}
20647233Syw161884 
20657233Syw161884 	if ((ret = raidcfg_get_attr(prop_handle, prop_attr2)) < 0) {
20667233Syw161884 		free(prop_attr2);
20677233Syw161884 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
20687233Syw161884 		return (FAILURE);
20697233Syw161884 	}
20707233Syw161884 
20717233Syw161884 	(void) fprintf(stdout, "GUID:%s\n", prop_attr2->prop);
20727233Syw161884 
20737233Syw161884 	free(prop_attr2);
20743457Sjc156560 	return (SUCCESS);
20753457Sjc156560 }
20763457Sjc156560 
20773457Sjc156560 /*
20783457Sjc156560  * print_ctl_attr(attrp)
20793457Sjc156560  * This function prints attribute of specified controller, and return
20803457Sjc156560  * result as SUCCESS or FAILURE.
20813457Sjc156560  */
20823457Sjc156560 static int
print_ctl_attr(raidcfg_controller_t * attrp)20833457Sjc156560 print_ctl_attr(raidcfg_controller_t *attrp)
20843457Sjc156560 {
20853457Sjc156560 	char type[CONTROLLER_TYPE_LEN];
20863457Sjc156560 	char version[CONTROLLER_FW_LEN];
20873457Sjc156560 
20883457Sjc156560 	if (attrp == NULL) {
20893457Sjc156560 		return (FAILURE);
20903457Sjc156560 	}
20913457Sjc156560 
20923457Sjc156560 	(void) snprintf(type, sizeof (type), "%s", attrp->controller_type);
20933457Sjc156560 	(void) fprintf(stdout, "%-16s", type);
20943457Sjc156560 
20953457Sjc156560 	(void) snprintf(version, sizeof (version), "%s", attrp->fw_version);
20963457Sjc156560 	(void) fprintf(stdout, "%s", version);
20973457Sjc156560 
20983457Sjc156560 	return (SUCCESS);
20993457Sjc156560 }
21003457Sjc156560 
21013457Sjc156560 /*
21023457Sjc156560  * print_array_attr(attrp)
21033457Sjc156560  * This function prints attribute of specified array, and return
21043457Sjc156560  * result as SUCCESS or FAILURE.
21053457Sjc156560  */
21063457Sjc156560 static int
print_array_attr(raidcfg_array_t * attrp)21073457Sjc156560 print_array_attr(raidcfg_array_t *attrp)
21083457Sjc156560 {
21093457Sjc156560 	char capacity[8];
21103457Sjc156560 	char stripe_size[8];
21113457Sjc156560 	char raid_level[8];
21123457Sjc156560 
21133457Sjc156560 	if (attrp == NULL) {
21140Sstevel@tonic-gate 		return (FAILURE);
21150Sstevel@tonic-gate 	}
21160Sstevel@tonic-gate 
21173457Sjc156560 	if (attrp->capacity != MAX64BIT) {
21183457Sjc156560 		if (size_to_string(attrp->capacity, capacity, 8) != SUCCESS) {
21193457Sjc156560 			return (FAILURE);
2120840Sjesseb 		}
21213457Sjc156560 		(void) printf("%s\t", capacity);
21223457Sjc156560 	} else {
21233457Sjc156560 		(void) printf(gettext("N/A\t"));
21243457Sjc156560 	}
21253457Sjc156560 
21263457Sjc156560 	if (attrp->stripe_size != MAX32BIT) {
21273457Sjc156560 		(void) snprintf(stripe_size, sizeof (stripe_size), "%uK",
21283457Sjc156560 		    attrp->stripe_size / 1024);
21293457Sjc156560 		(void) printf("%s\t", stripe_size);
21303457Sjc156560 	} else {
21313457Sjc156560 		(void) printf(gettext("N/A\t"));
21323457Sjc156560 	}
21333457Sjc156560 
21347233Syw161884 	if (attrp->state & ARRAY_STATE_INACTIVATE)
21357233Syw161884 		(void) printf("%-8s", gettext("INACTIVE"));
21367233Syw161884 	else {
21377233Syw161884 		switch (attrp->state) {
21387233Syw161884 		case ARRAY_STATE_OPTIMAL:
21397233Syw161884 			(void) printf("%-8s", gettext("OPTIMAL"));
21407233Syw161884 			break;
21417233Syw161884 		case ARRAY_STATE_DEGRADED:
21427233Syw161884 			(void) printf("%-8s", gettext("DEGRADED"));
21437233Syw161884 			break;
21447233Syw161884 		case ARRAY_STATE_FAILED:
21457233Syw161884 			(void) printf("%-8s", gettext("FAILED"));
21467233Syw161884 			break;
21477233Syw161884 		case ARRAY_STATE_SYNC:
21487233Syw161884 			(void) printf("%-8s", gettext("SYNC"));
21497233Syw161884 			break;
21507233Syw161884 		case ARRAY_STATE_MISSING:
21517233Syw161884 			(void) printf("%-8s", gettext("MISSING"));
21527233Syw161884 			break;
21537233Syw161884 		default:
21547233Syw161884 			(void) printf("%-8s", gettext("N/A"));
21557233Syw161884 			break;
21567233Syw161884 		}
21573457Sjc156560 	}
21583457Sjc156560 	(void) printf(" ");
21593457Sjc156560 
21603457Sjc156560 	if (attrp->write_policy == CACHE_WR_OFF) {
21613457Sjc156560 		(void) printf(gettext("OFF"));
21623457Sjc156560 	} else if (attrp->write_policy == CACHE_WR_ON) {
21633457Sjc156560 		(void) printf(gettext("ON"));
21643457Sjc156560 	} else {
21653457Sjc156560 		(void) printf(gettext("N/A"));
21663457Sjc156560 	}
21673457Sjc156560 	(void) printf("\t");
21683457Sjc156560 
21693457Sjc156560 	switch (attrp->raid_level) {
21703457Sjc156560 	case RAID_LEVEL_0:
21713457Sjc156560 		(void) sprintf(raid_level, "RAID0");
21723457Sjc156560 		break;
21733457Sjc156560 	case RAID_LEVEL_1:
21743457Sjc156560 		(void) sprintf(raid_level, "RAID1");
21753457Sjc156560 		break;
21763457Sjc156560 	case RAID_LEVEL_1E:
21773457Sjc156560 		(void) sprintf(raid_level, "RAID1E");
21783457Sjc156560 		break;
21793457Sjc156560 	case RAID_LEVEL_5:
21803457Sjc156560 		(void) sprintf(raid_level, "RAID5");
21813457Sjc156560 		break;
21823457Sjc156560 	case RAID_LEVEL_10:
21833457Sjc156560 		(void) sprintf(raid_level, "RAID10");
21843457Sjc156560 		break;
21853457Sjc156560 	case RAID_LEVEL_50:
21863457Sjc156560 		(void) sprintf(raid_level, "RAID50");
21873457Sjc156560 		break;
21883457Sjc156560 	default:
21893457Sjc156560 		(void) snprintf(raid_level, sizeof (raid_level),
21903457Sjc156560 		    gettext("N/A"));
21913457Sjc156560 		break;
21923457Sjc156560 	}
21933457Sjc156560 	(void) printf("%s", raid_level);
21943457Sjc156560 
21953457Sjc156560 	return (SUCCESS);
21963457Sjc156560 }
21973457Sjc156560 
21983457Sjc156560 /*
21993457Sjc156560  * print_arraypart_attr(attrp)
22003457Sjc156560  * This function print attribute of specified arraypart, and return
22013457Sjc156560  * result as SUCCESS or FAILURE.
22023457Sjc156560  */
22033457Sjc156560 static int
print_arraypart_attr(raidcfg_arraypart_t * attrp)22043457Sjc156560 print_arraypart_attr(raidcfg_arraypart_t *attrp)
22053457Sjc156560 {
22063457Sjc156560 	char size[8];
22073457Sjc156560 
22083457Sjc156560 	if (attrp == NULL) {
22093457Sjc156560 		return (FAILURE);
22103457Sjc156560 	}
22113457Sjc156560 
22123457Sjc156560 	if (attrp->size != MAX64BIT) {
22133457Sjc156560 		if (size_to_string(attrp->size, size, 8) != SUCCESS) {
22143457Sjc156560 			return (FAILURE);
2215840Sjesseb 		}
22163457Sjc156560 		(void) printf("%s\t", size);
22173457Sjc156560 	} else {
22183457Sjc156560 		(void) printf(gettext("N/A\t"));
22190Sstevel@tonic-gate 	}
22200Sstevel@tonic-gate 
22213457Sjc156560 	(void) printf("\t");
22223457Sjc156560 
22233457Sjc156560 	if (attrp->state == DISK_STATE_GOOD) {
22243457Sjc156560 		(void) printf(gettext("GOOD"));
22253457Sjc156560 	} else if (attrp->state == DISK_STATE_FAILED) {
22263457Sjc156560 		(void) printf(gettext("FAILED"));
22273457Sjc156560 	} else {
22283457Sjc156560 		(void) printf(gettext("N/A"));
22290Sstevel@tonic-gate 	}
22303457Sjc156560 	(void) printf("\t");
22313457Sjc156560 
22323457Sjc156560 	return (SUCCESS);
22333457Sjc156560 }
22343457Sjc156560 
22353457Sjc156560 /*
22363457Sjc156560  * print_disk_attr(ctl_handle, disk_handle, attrp)
22373457Sjc156560  * This function prints attribute of specified disk, and return
22383457Sjc156560  * result as SUCCESS or FAILURE.
22393457Sjc156560  */
22403457Sjc156560 static int
print_disk_attr(raid_obj_handle_t ctl_handle,raid_obj_handle_t disk_handle,raidcfg_disk_t * attrp)22413457Sjc156560 print_disk_attr(raid_obj_handle_t ctl_handle, raid_obj_handle_t disk_handle,
22423457Sjc156560 	raidcfg_disk_t *attrp)
22433457Sjc156560 {
2244*8856SMilan.Jurik@Sun.COM 	char vendor[DISK_VENDER_LEN + 1];
2245*8856SMilan.Jurik@Sun.COM 	char product[DISK_PRODUCT_LEN + 1];
22465683Szk194757 	char revision[DISK_REV_LEN + 1];
22473457Sjc156560 	char capacity[16];
22483457Sjc156560 	char hsp[16];
22493457Sjc156560 
22503457Sjc156560 	raid_obj_handle_t hsp_handle;
22513457Sjc156560 	raidcfg_hsp_t hsp_attr;
22523457Sjc156560 	raidcfg_controller_t ctl_attr;
22533457Sjc156560 	int ret;
22543457Sjc156560 	char is_indent;
22553457Sjc156560 
22563457Sjc156560 	if (attrp == NULL) {
22573457Sjc156560 		return (FAILURE);
22583457Sjc156560 	}
22593457Sjc156560 
2260*8856SMilan.Jurik@Sun.COM 	(void) memccpy(vendor, attrp->vendorid, '\0', DISK_VENDER_LEN);
2261*8856SMilan.Jurik@Sun.COM 	vendor[DISK_VENDER_LEN] = '\0';
2262*8856SMilan.Jurik@Sun.COM 	(void) printf("%-9s", vendor);
2263*8856SMilan.Jurik@Sun.COM 
2264*8856SMilan.Jurik@Sun.COM 	(void) memccpy(product, attrp->productid, '\0', DISK_PRODUCT_LEN);
2265*8856SMilan.Jurik@Sun.COM 	product[DISK_PRODUCT_LEN] = '\0';
2266*8856SMilan.Jurik@Sun.COM 	(void) printf("%-17s", product);
2267*8856SMilan.Jurik@Sun.COM 
2268*8856SMilan.Jurik@Sun.COM 	(void) memccpy(revision, attrp->revision, '\0', DISK_REV_LEN);
2269*8856SMilan.Jurik@Sun.COM 	revision[DISK_REV_LEN] = '\0';
22705683Szk194757 	(void) printf("%s\t\t", revision);
22715683Szk194757 
22723457Sjc156560 	if (attrp->capacity != MAX64BIT) {
22733457Sjc156560 		if (size_to_string(attrp->capacity, capacity, 16) != SUCCESS) {
22743457Sjc156560 			return (FAILURE);
2275840Sjesseb 		}
22763457Sjc156560 		(void) printf("%s\t\t", capacity);
22773457Sjc156560 	} else {
22783457Sjc156560 		(void) printf(gettext("N/A"));
22793457Sjc156560 	}
22803457Sjc156560 
22813457Sjc156560 	if (attrp->state == DISK_STATE_GOOD) {
22823457Sjc156560 		(void) printf(gettext("GOOD"));
22833457Sjc156560 	} else if (attrp->state == DISK_STATE_FAILED) {
22843457Sjc156560 		(void) printf(gettext("FAILED"));
22853457Sjc156560 	} else {
22863457Sjc156560 		(void) printf(gettext("N/A"));
22873457Sjc156560 	}
22883457Sjc156560 	(void) printf("\t");
22893457Sjc156560 
22903457Sjc156560 	/* Controller attribute */
22913457Sjc156560 	if ((ret = raidcfg_get_attr(ctl_handle, &ctl_attr)) < 0) {
22923457Sjc156560 		(void) fprintf(stderr, "%s\n", raidcfg_errstr(ret));
22933457Sjc156560 		return (FAILURE);
22943457Sjc156560 	}
22953457Sjc156560 
22963457Sjc156560 	hsp_handle = raidcfg_list_head(disk_handle, OBJ_TYPE_HSP);
22973457Sjc156560 	if (hsp_handle == 0) {
22983457Sjc156560 		(void) printf(gettext("N/A\n"));
22993457Sjc156560 	} else {
23003457Sjc156560 		is_indent = FALSE;
23013457Sjc156560 		while (hsp_handle > 0) {
23023457Sjc156560 			if ((ret = raidcfg_get_attr(hsp_handle,
23033457Sjc156560 			    &hsp_attr)) < 0) {
23043457Sjc156560 				(void) fprintf(stderr, "%s\n",
23053457Sjc156560 				    raidcfg_errstr(ret));
23063457Sjc156560 				return (FAILURE);
2307840Sjesseb 			}
23083457Sjc156560 
23093457Sjc156560 			if (is_indent == TRUE) {
23103457Sjc156560 				(void) printf("\t\t\t\t\t\t\t");
23113457Sjc156560 			} else {
23123457Sjc156560 				is_indent = TRUE;
23133457Sjc156560 			}
23143457Sjc156560 
23153457Sjc156560 			if (hsp_attr.type == HSP_TYPE_LOCAL) {
23163457Sjc156560 				(void) snprintf(hsp, sizeof (hsp),
23173457Sjc156560 				    "c%ut%llud%llu",
23183457Sjc156560 				    ctl_attr.controller_id,
23193457Sjc156560 				    hsp_attr.tag.idl.target_id,
23203457Sjc156560 				    hsp_attr.tag.idl.lun);
23213457Sjc156560 				(void) printf("%s\n", hsp);
23223457Sjc156560 			} else if (hsp_attr.type == HSP_TYPE_GLOBAL) {
23233457Sjc156560 				(void) printf(gettext("Global\n"));
23243457Sjc156560 			} else {
23253457Sjc156560 				return (FAILURE);
23263457Sjc156560 			}
23273457Sjc156560 
23283457Sjc156560 			hsp_handle = raidcfg_list_next(hsp_handle);
23291526Szx143588 		}
23301526Szx143588 	}
23310Sstevel@tonic-gate 	return (SUCCESS);
23320Sstevel@tonic-gate }
23330Sstevel@tonic-gate 
23343457Sjc156560 
23353457Sjc156560 /*
23363457Sjc156560  * print_indent(indent)
23373457Sjc156560  * This function prints specified number of tab characters. It's used to
23383457Sjc156560  * format layout.
23393457Sjc156560  */
2340902Syw161884 static void
print_indent(uint8_t indent)23413457Sjc156560 print_indent(uint8_t indent)
2342902Syw161884 {
23433457Sjc156560 	uint32_t i;
23443457Sjc156560 	for (i = 0; i < indent; i++) {
23453457Sjc156560 		(void) fprintf(stdout, "\t");
2346902Syw161884 	}
2347902Syw161884 }
2348902Syw161884 
23493457Sjc156560 /*
23503457Sjc156560  * get_disk_handle_cidl(ctl_tag, disks_argp, comps_num, handlespp)
23513457Sjc156560  * This function parses the string of disk argument, and gets the disks tag
23523457Sjc156560  * and separators from the string. Then it translates the tag to handle, and
23533457Sjc156560  * stores handles and separators to new buffer pointed by parameter handlespp.
23543457Sjc156560  * The format of disk_arg must be C:ID:L, for example, it is 0.1.0. The first
23553457Sjc156560  * "0" is channel number, and the second "1" is target number, and the third
23563457Sjc156560  * "0" is LUN number. The disk tags are separated by comma and parenthesis.
23573457Sjc156560  * Function returns SUCCESS or FAILURE.
23583457Sjc156560  */
23590Sstevel@tonic-gate static int
get_disk_handle_cidl(uint32_t ctl_tag,char * disks_argp,int * comps_nump,raid_obj_handle_t ** handlespp)23603457Sjc156560 get_disk_handle_cidl(uint32_t ctl_tag, char *disks_argp, int *comps_nump,
23613457Sjc156560 	raid_obj_handle_t **handlespp)
23623457Sjc156560 {
23633457Sjc156560 	int len = 0;
23643457Sjc156560 	int i = 0, j = 0;
23653457Sjc156560 	char *p, *t;
23663457Sjc156560 	char *delimit = " ";
23673457Sjc156560 	char *disks_str;
23683457Sjc156560 	disk_tag_t disk_tag;
23693457Sjc156560 
23703457Sjc156560 	if (disks_argp == NULL || comps_nump == NULL) {
23713457Sjc156560 		return (FAILURE);
23723457Sjc156560 	}
23733457Sjc156560 
23743457Sjc156560 	p = disks_argp;
23753457Sjc156560 	len = strlen(disks_argp);
23763457Sjc156560 
23773457Sjc156560 	if ((disks_str = (char *)malloc(3 * len + 4)) == NULL) {
23783457Sjc156560 		return (FAILURE);
23793457Sjc156560 	}
23803457Sjc156560 
23813457Sjc156560 	/* Insert whitespace between disk tags, '(' , and ')' */
23823457Sjc156560 	disks_str[j ++] = '(';
23833457Sjc156560 	disks_str[j ++] = ' ';
23843457Sjc156560 
23853457Sjc156560 	while (p[i] != '\0') {
23863457Sjc156560 		if (p[i] == ')' || p[i] == '(') {
23873457Sjc156560 			disks_str[j ++] = ' ';
23883457Sjc156560 			disks_str[j ++] = p[i];
23893457Sjc156560 			disks_str[j ++] = ' ';
23903457Sjc156560 		} else
23913457Sjc156560 			disks_str[j ++] = p[i];
23923457Sjc156560 		i ++;
23933457Sjc156560 	}
23943457Sjc156560 	disks_str[j ++] = ' ';
23953457Sjc156560 	disks_str[j ++] = ')';
23963457Sjc156560 	disks_str[j] = '\0';
23973457Sjc156560 
23983457Sjc156560 	len = strlen(disks_str) + 1;
23993457Sjc156560 
24003457Sjc156560 	if ((t = (char *)malloc(len)) == NULL) {
24013457Sjc156560 		return (FAILURE);
24023457Sjc156560 	}
24033457Sjc156560 	(void) memcpy(t, disks_str, len);
24043457Sjc156560 	p = strtok(t, delimit);
24053457Sjc156560 	while (p != NULL) {
24063457Sjc156560 		(*comps_nump)++;
24073457Sjc156560 		p = strtok(NULL, delimit);
24083457Sjc156560 	}
24093457Sjc156560 	free(t);
24103457Sjc156560 
24113457Sjc156560 	*handlespp = calloc(*comps_nump, sizeof (raid_obj_handle_t));
24123457Sjc156560 	if (*handlespp == NULL) {
24133457Sjc156560 		return (FAILURE);
24143457Sjc156560 	}
24153457Sjc156560 
24163457Sjc156560 	for (i = 0; i < *comps_nump; i++)
24173457Sjc156560 		(*handlespp)[i] = INIT_HANDLE_VALUE;
24183457Sjc156560 
24193457Sjc156560 	i = 0;
24203457Sjc156560 	p = strtok(disks_str, delimit);
24213457Sjc156560 	while (p != NULL) {
24223457Sjc156560 		if (*p == '(') {
24233457Sjc156560 			(*handlespp)[i] = OBJ_SEPARATOR_BEGIN;
24243457Sjc156560 		} else if (*p == ')') {
24253457Sjc156560 			(*handlespp)[i] = OBJ_SEPARATOR_END;
24263457Sjc156560 		} else {
24273457Sjc156560 			if (get_disk_tag_cidl(p, &disk_tag) != SUCCESS) {
24283457Sjc156560 				free(*handlespp);
24293457Sjc156560 				free(disks_str);
24303457Sjc156560 				return (INVALID_ARG);
24313457Sjc156560 			}
24323457Sjc156560 			(*handlespp)[i] =
24333457Sjc156560 			    raidcfg_get_disk(raidcfg_get_controller(ctl_tag),
24343457Sjc156560 			    disk_tag);
24353457Sjc156560 			if ((*handlespp)[i] <= 0) {
24363457Sjc156560 				(void) fprintf(stderr, "%s\n",
24373457Sjc156560 				    raidcfg_errstr((*handlespp)[i]));
24383457Sjc156560 				free(*handlespp);
24393457Sjc156560 				free(disks_str);
24403457Sjc156560 				return (FAILURE);
24413457Sjc156560 			}
24423457Sjc156560 		}
24433457Sjc156560 		p = strtok(NULL, delimit);
24443457Sjc156560 		i++;
24453457Sjc156560 	}
24463457Sjc156560 
24473457Sjc156560 	free(disks_str);
24483457Sjc156560 	return (SUCCESS);
24493457Sjc156560 }
24503457Sjc156560 
24513457Sjc156560 /*
24523457Sjc156560  * get_disk_handle_ctd(disks_num, disks_argpp, ctl_tagp, disks_handlep)
24533457Sjc156560  * This function parses string of single disk with "ctd" format, for example,
24543457Sjc156560  * c0t0d0, and translates it to controller tag and disk tag.
24553457Sjc156560  * Then it calls lib api and get disk handle. The controller tag and disk
24563457Sjc156560  * handle are both returned by out parameters.
24573457Sjc156560  * The return value is SUCCESS or FAILURE.
24583457Sjc156560  */
24593457Sjc156560 static int
get_disk_handle_ctd(int disks_num,char ** disks_argpp,uint32_t * ctl_tagp,raid_obj_handle_t * disks_handlep)24603457Sjc156560 get_disk_handle_ctd(int disks_num, char **disks_argpp, uint32_t *ctl_tagp,
24613457Sjc156560 	raid_obj_handle_t *disks_handlep)
24620Sstevel@tonic-gate {
24633457Sjc156560 	raid_obj_handle_t ctl_handle;
24643457Sjc156560 	disk_tag_t disk_tag;
24653457Sjc156560 	uint32_t ctl_id;
24663457Sjc156560 	int i;
24673457Sjc156560 	int ret;
24683457Sjc156560 
24693457Sjc156560 	if (disks_handlep == NULL) {
24703457Sjc156560 		return (FAILURE);
24713457Sjc156560 	}
24723457Sjc156560 
24733457Sjc156560 	for (i = 0; i < disks_num; i++) {
24743457Sjc156560 		if (get_disk_tag_ctd(disks_argpp[i], &disk_tag, &ctl_id) !=
24753457Sjc156560 		    SUCCESS) {
24763457Sjc156560 			return (INVALID_ARG);
24773457Sjc156560 		}
24783457Sjc156560 
24793457Sjc156560 		*ctl_tagp = ctl_id;
24803457Sjc156560 
24813457Sjc156560 		if (i == 0) {
24823457Sjc156560 			ctl_handle = raidcfg_get_controller(*ctl_tagp);
24833457Sjc156560 			if (ctl_handle <= 0) {
24843457Sjc156560 				(void) fprintf(stderr, "%s\n",
24853457Sjc156560 				    raidcfg_errstr(ctl_handle));
24863457Sjc156560 				return (FAILURE);
24873457Sjc156560 			}
24883457Sjc156560 			ret = raidcfg_open_controller(ctl_handle, NULL);
24893457Sjc156560 			if (ret < 0) {
24903457Sjc156560 				(void) fprintf(stderr, "%s\n",
24913457Sjc156560 				    raidcfg_errstr(ret));
24923457Sjc156560 				return (FAILURE);
24933457Sjc156560 			}
24943457Sjc156560 		}
24953457Sjc156560 
24963457Sjc156560 		if ((disks_handlep[i] =
24973457Sjc156560 		    raidcfg_get_disk(ctl_handle, disk_tag)) < 0) {
24983457Sjc156560 			(void) fprintf(stderr, "%s\n",
24993457Sjc156560 			    raidcfg_errstr(disks_handlep[i]));
25003457Sjc156560 			(void) raidcfg_close_controller(ctl_handle, NULL);
25013457Sjc156560 			return (FAILURE);
25023457Sjc156560 		}
25033457Sjc156560 	}
25043457Sjc156560 
25053457Sjc156560 	return (SUCCESS);
25063457Sjc156560 }
25073457Sjc156560 
25083457Sjc156560 /*
25093457Sjc156560  * get_ctl_tag(argp)
25103457Sjc156560  * This function translates controller string to tag. The return value is
25113457Sjc156560  * SUCCESS if the string has legal format and is parsed successfully,
25123457Sjc156560  * or FAILURE if it fails.
25133457Sjc156560  */
25143457Sjc156560 static int
get_ctl_tag(char * argp,uint32_t * ctl_tagp)25153457Sjc156560 get_ctl_tag(char *argp, uint32_t *ctl_tagp)
25163457Sjc156560 {
25173457Sjc156560 	if (argp == NULL || is_fully_numeric(argp) == FALSE ||
25183457Sjc156560 	    ctl_tagp == NULL) {
25193457Sjc156560 		return (FAILURE);
25200Sstevel@tonic-gate 	}
25213457Sjc156560 	*ctl_tagp = (atoi(argp));
25223457Sjc156560 	return (SUCCESS);
25233457Sjc156560 }
25243457Sjc156560 
25253457Sjc156560 /*
25263457Sjc156560  * get_array_tag(argp, ctl_tagp, array_tagp)
25273457Sjc156560  * This function parses array string to get array tag and controller tag.
25283457Sjc156560  * The return value is SUCCESS if the string has legal format, or
25293457Sjc156560  * FAILURE if it fails.
25303457Sjc156560  */
25313457Sjc156560 static int
get_array_tag(char * argp,uint32_t * ctl_tagp,array_tag_t * array_tagp)25323457Sjc156560 get_array_tag(char *argp, uint32_t *ctl_tagp, array_tag_t *array_tagp)
25333457Sjc156560 {
25343457Sjc156560 	char *t = NULL;
25353457Sjc156560 	char *cp = NULL;
25363457Sjc156560 	char *tp = NULL;
25373457Sjc156560 	char *dp = NULL;
25383457Sjc156560 
25393457Sjc156560 	uint32_t value_c = MAX32BIT;
25403457Sjc156560 	uint32_t value_t = MAX32BIT;
25413457Sjc156560 	uint32_t value_d = MAX32BIT;
25423457Sjc156560 
25433457Sjc156560 	int len = 0;
25443457Sjc156560 
25453457Sjc156560 	if (argp == NULL || (len = strlen(argp)) == 0 ||
25463457Sjc156560 	    array_tagp == NULL) {
25473457Sjc156560 		return (FAILURE);
25483457Sjc156560 	}
25493457Sjc156560 
25503457Sjc156560 	t = (char *)malloc(len + 1);
25513457Sjc156560 	if (t == NULL) {
25523457Sjc156560 		return (FAILURE);
25533457Sjc156560 	}
25543457Sjc156560 
25553457Sjc156560 	(void) memcpy(t, argp, len + 1);
25563457Sjc156560 
25573457Sjc156560 	/* Now remmber to release t memory if exception occurs */
25583457Sjc156560 	if (((dp = strchr(t, 'd')) == NULL) ||
25593457Sjc156560 	    ((tp = strchr(t, 't')) == NULL) ||
25603457Sjc156560 	    ((cp = strchr(t, 'c')) == NULL)) {
25613457Sjc156560 		free(t);
25623457Sjc156560 		return (FAILURE);
25633457Sjc156560 	}
25643457Sjc156560 	cp = t;
25653457Sjc156560 
25663457Sjc156560 	*dp = '\0';
25673457Sjc156560 	dp++;
25683457Sjc156560 	*tp = '\0';
25693457Sjc156560 	tp++;
25703457Sjc156560 	cp++;
25713457Sjc156560 
25723457Sjc156560 	if (is_fully_numeric(dp) == FALSE ||
25733457Sjc156560 	    is_fully_numeric(tp) == FALSE ||
25743457Sjc156560 	    is_fully_numeric(cp) == FALSE) {
25753457Sjc156560 		free(t);
25763457Sjc156560 		return (FAILURE);
25773457Sjc156560 	}
25783457Sjc156560 
25793457Sjc156560 	value_c = atoi(cp);
25803457Sjc156560 	value_t = atoi(tp);
25813457Sjc156560 	value_d = atoi(dp);
25823457Sjc156560 
25833457Sjc156560 	array_tagp->idl.target_id = value_t;
25843457Sjc156560 	array_tagp->idl.lun = value_d;
25853457Sjc156560 
25863457Sjc156560 	if (ctl_tagp != NULL) {
25873457Sjc156560 		*ctl_tagp = value_c;
25880Sstevel@tonic-gate 	}
25890Sstevel@tonic-gate 
25903457Sjc156560 	free(t);
25913457Sjc156560 	return (SUCCESS);
25923457Sjc156560 }
25933457Sjc156560 
25943457Sjc156560 /*
25953457Sjc156560  * get_disk_tag_ctd(argp, disk_tagp)
25963457Sjc156560  * This function parses disk string of ctd format, and translates it to
25973457Sjc156560  * disk tag and controller tag. The tags is returned by out parameters.
25983457Sjc156560  * The return value is SUCCESS if the string has legal format, or FAILURE
25993457Sjc156560  * if it fails.
26003457Sjc156560  */
26013457Sjc156560 static int
get_disk_tag_ctd(char * argp,disk_tag_t * disk_tagp,uint32_t * ctl_tag)26023457Sjc156560 get_disk_tag_ctd(char *argp, disk_tag_t *disk_tagp, uint32_t *ctl_tag)
26033457Sjc156560 {
26043457Sjc156560 	char *t = NULL;
26053457Sjc156560 	char *cp = NULL;
26063457Sjc156560 	char *tp = NULL;
26073457Sjc156560 	char *dp = NULL;
26083457Sjc156560 
26093457Sjc156560 	uint32_t value_c = MAX32BIT;
26103457Sjc156560 	uint32_t value_t = MAX32BIT;
26113457Sjc156560 	uint32_t value_d = MAX32BIT;
26123457Sjc156560 
26133457Sjc156560 	int len = 0;
26143457Sjc156560 
26153457Sjc156560 	if (argp == NULL || (len = strlen(argp)) == 0 ||
26163457Sjc156560 	    disk_tagp == NULL) {
26173457Sjc156560 		return (FAILURE);
26183457Sjc156560 	}
26193457Sjc156560 
26203457Sjc156560 	t = (char *)malloc(len + 1);
26213457Sjc156560 	if (t == NULL) {
26223457Sjc156560 		return (FAILURE);
26233457Sjc156560 	}
26243457Sjc156560 
26253457Sjc156560 	(void) memcpy(t, argp, len + 1);
26263457Sjc156560 
26273457Sjc156560 	/* Now remmber to release t memory if exception occurs */
26283457Sjc156560 	if (((dp = strchr(t, 'd')) == NULL) ||
26293457Sjc156560 	    ((tp = strchr(t, 't')) == NULL) ||
26303457Sjc156560 	    ((cp = strchr(t, 'c')) == NULL)) {
26313457Sjc156560 		free(t);
26323457Sjc156560 		return (FAILURE);
26333457Sjc156560 	}
26343457Sjc156560 	cp = t;
26353457Sjc156560 
26363457Sjc156560 	*dp = '\0';
26373457Sjc156560 	dp++;
26383457Sjc156560 	*tp = '\0';
26393457Sjc156560 	tp++;
26403457Sjc156560 	cp++;
26413457Sjc156560 
26423457Sjc156560 	if (is_fully_numeric(dp) == FALSE ||
26433457Sjc156560 	    is_fully_numeric(tp) == FALSE ||
26443457Sjc156560 	    is_fully_numeric(cp) == FALSE) {
26453457Sjc156560 		free(t);
26463457Sjc156560 		return (FAILURE);
26473457Sjc156560 	}
26483457Sjc156560 
26493457Sjc156560 	value_c = atoi(cp);
26503457Sjc156560 	value_t = atoi(tp);
26513457Sjc156560 	value_d = atoi(dp);
26523457Sjc156560 
26533457Sjc156560 	disk_tagp->cidl.bus = 0;
26543457Sjc156560 	disk_tagp->cidl.target_id = value_t;
26553457Sjc156560 	disk_tagp->cidl.lun = value_d;
26563457Sjc156560 	*ctl_tag = value_c;
26573457Sjc156560 
26583457Sjc156560 	free(t);
26593457Sjc156560 	return (SUCCESS);
26603457Sjc156560 }
26613457Sjc156560 
26623457Sjc156560 /*
26633457Sjc156560  * get_disk_tag_cidl(argp, disk_tagp)
26643457Sjc156560  * This function parses disk string of cidl format and translates it to tag.
26653457Sjc156560  * The return value is disk tag if the string has legal format, or FAILURE
26663457Sjc156560  * if it fails.
26673457Sjc156560  */
26683457Sjc156560 static int
get_disk_tag_cidl(char * argp,disk_tag_t * disk_tagp)26693457Sjc156560 get_disk_tag_cidl(char *argp, disk_tag_t *disk_tagp)
26703457Sjc156560 {
26713457Sjc156560 	int len = 0;
26723457Sjc156560 	char *p = NULL;
26733457Sjc156560 	char *t = NULL;
26743457Sjc156560 	char *dot1p = NULL;
26753457Sjc156560 	char *dot2p = NULL;
26763457Sjc156560 
26773457Sjc156560 	if (argp == NULL || (len = strlen(argp)) == 0) {
26783457Sjc156560 		return (FAILURE);
26793457Sjc156560 	}
26803457Sjc156560 
26813457Sjc156560 	if (disk_tagp == NULL) {
26823457Sjc156560 		return (FAILURE);
26833457Sjc156560 	}
26843457Sjc156560 
26853457Sjc156560 	t = (char *)malloc(len + 1);
26863457Sjc156560 	if (t == NULL) {
26873457Sjc156560 		return (FAILURE);
26883457Sjc156560 	}
26893457Sjc156560 
26903457Sjc156560 	(void) memcpy(t, argp, len + 1);
26913457Sjc156560 	p = t;
26923457Sjc156560 
26933457Sjc156560 	dot2p = strrchr(p, '.');
26943457Sjc156560 	if (dot2p == NULL) {
26953457Sjc156560 		free(t);
26963457Sjc156560 		return (FAILURE);
26973457Sjc156560 	}
26983457Sjc156560 	*dot2p = '\0';
26993457Sjc156560 	dot2p++;
27003457Sjc156560 
27013457Sjc156560 	dot1p = strrchr(p, '.');
27023457Sjc156560 	if (dot1p == NULL) {
27033457Sjc156560 		free(t);
27043457Sjc156560 		return (FAILURE);
27053457Sjc156560 	}
27063457Sjc156560 	*dot1p = '\0';
27073457Sjc156560 	dot1p++;
27083457Sjc156560 
27093457Sjc156560 	/* Assert only 2 dots in this string */
27103457Sjc156560 	if (strrchr(p, '.') != NULL) {
27113457Sjc156560 		free(t);
27123457Sjc156560 		return (FAILURE);
27130Sstevel@tonic-gate 	}
27143457Sjc156560 
27153457Sjc156560 	while (*p == ' ')
27163457Sjc156560 		p++;
27173457Sjc156560 
27183457Sjc156560 	if (is_fully_numeric(p) == FALSE ||
27193457Sjc156560 	    is_fully_numeric(dot1p) == FALSE ||
27203457Sjc156560 	    is_fully_numeric(dot2p) == FALSE) {
27213457Sjc156560 		free(t);
27223457Sjc156560 		return (FAILURE);
27233457Sjc156560 	}
27243457Sjc156560 
27253457Sjc156560 	disk_tagp->cidl.bus = atoi(p);
27263457Sjc156560 	disk_tagp->cidl.target_id = atoi(dot1p);
27273457Sjc156560 	disk_tagp->cidl.lun = atoi(dot2p);
27283457Sjc156560 
27293457Sjc156560 	free(t);
27303457Sjc156560 	return (SUCCESS);
27313457Sjc156560 }
27323457Sjc156560 
27333457Sjc156560 /*
27343457Sjc156560  * calc_size(sizep, valp)
27353457Sjc156560  * This function calculates the value represented by string sizep.
27363457Sjc156560  * The string sizep can be decomposed into three parts: an initial,
27373457Sjc156560  * possibly empty, sequence of white-space characters; a subject digital
27383457Sjc156560  * sequence interpreted as an integer with unit k/K/m/M/g/G/t/T; and a
27393457Sjc156560  * final string of one or more unrecognized characters or white-sapce
27403457Sjc156560  * characters, including the terminating null. If unrecognized character
27413457Sjc156560  * exists or overflow happens, the conversion must fail and return
27423457Sjc156560  * INVALID_ARG. If the conversion is performed successfully, result will
27433457Sjc156560  * be saved into valp and function returns SUCCESS. It returns FAILURE
27443457Sjc156560  * when memory allocation fails.
27453457Sjc156560  */
27463457Sjc156560 static int
calc_size(char * sizep,uint64_t * valp)27473457Sjc156560 calc_size(char *sizep, uint64_t *valp)
27483457Sjc156560 {
27493457Sjc156560 	int len;
27503457Sjc156560 	uint64_t size;
27513457Sjc156560 	uint64_t unit;
27523457Sjc156560 	char *t = NULL;
27533457Sjc156560 	char *tailp = NULL;
27543457Sjc156560 
27553457Sjc156560 	if (sizep == NULL || valp == NULL) {
27563457Sjc156560 		return (INVALID_ARG);
27573457Sjc156560 	}
27583457Sjc156560 
27594563Syw161884 	if (is_fully_numeric(sizep) == TRUE) {
27604563Syw161884 		*valp = atoi(sizep);
27614563Syw161884 		return (SUCCESS);
27624563Syw161884 	}
27634563Syw161884 
27643457Sjc156560 	len = strlen(sizep);
27653457Sjc156560 	if (len == 0) {
27663457Sjc156560 		return (INVALID_ARG);
27673457Sjc156560 	}
27683457Sjc156560 
27693457Sjc156560 	t = (char *)malloc(len + 1);
27703457Sjc156560 	if (t == NULL) {
27713457Sjc156560 		return (FAILURE);
27720Sstevel@tonic-gate 	}
27730Sstevel@tonic-gate 
27743457Sjc156560 	(void) memcpy(t, sizep, len + 1);
27753457Sjc156560 
27763457Sjc156560 	switch (*(t + len - 1)) {
27773457Sjc156560 	case 'k':
27783457Sjc156560 	case 'K':
27793457Sjc156560 		unit = 1024ull;
27803457Sjc156560 		errno = 0;
27813457Sjc156560 		size = strtoll(t, &tailp, 0);
27823457Sjc156560 		break;
27833457Sjc156560 	case 'm':
27843457Sjc156560 	case 'M':
27853457Sjc156560 		unit = 1024ull * 1024ull;
27863457Sjc156560 		errno = 0;
27873457Sjc156560 		size = strtoll(t, &tailp, 0);
27883457Sjc156560 		break;
27893457Sjc156560 	case 'g':
27903457Sjc156560 	case 'G':
27913457Sjc156560 		unit = 1024ull * 1024ull * 1024ull;
27923457Sjc156560 		errno = 0;
27933457Sjc156560 		size = strtoll(t, &tailp, 0);
27943457Sjc156560 		break;
27953457Sjc156560 	case 't':
27963457Sjc156560 	case 'T':
27973457Sjc156560 		unit = 1024ull * 1024ull * 1024ull * 1024ull;
27983457Sjc156560 		errno = 0;
27993457Sjc156560 		size = strtoll(t, &tailp, 0);
28003457Sjc156560 		break;
28013457Sjc156560 	default:
28023457Sjc156560 		/* The unit must be kilobyte at least. */
28033457Sjc156560 		free(t);
28043457Sjc156560 		return (INVALID_ARG);
28053457Sjc156560 	}
28063457Sjc156560 
28073457Sjc156560 	*(t + len - 1) = '\0';
28083457Sjc156560 	if (is_fully_numeric(t) != TRUE) {
28093457Sjc156560 		free(t);
28103457Sjc156560 		return (INVALID_ARG);
28113457Sjc156560 	}
28123457Sjc156560 
28133457Sjc156560 	errno = 0;
28143457Sjc156560 	size = strtoll(t, &tailp, 0);
28153457Sjc156560 
28163457Sjc156560 	/* Check overflow condition */
28173457Sjc156560 	if (errno == ERANGE || (size > (MAX64BIT / unit))) {
28183457Sjc156560 		free(t);
28193457Sjc156560 		return (INVALID_ARG);
28203457Sjc156560 	}
28213457Sjc156560 
28223457Sjc156560 	*valp = size * unit;
28233457Sjc156560 	free(t);
28243457Sjc156560 	return (SUCCESS);
28253457Sjc156560 }
28263457Sjc156560 
28273457Sjc156560 /*
28283457Sjc156560  * is_fully_numeric(str)
28293457Sjc156560  * This function checks if the string are legal numeric string. The beginning
28303457Sjc156560  * or ending characters can be white spaces.
28313457Sjc156560  * Return value is TRUE if the string are legal numeric string, or FALSE
28323457Sjc156560  * otherwise.
28333457Sjc156560  */
28343457Sjc156560 static int
is_fully_numeric(char * strp)28353457Sjc156560 is_fully_numeric(char *strp)
28363457Sjc156560 {
28373457Sjc156560 	uint32_t len;
28383457Sjc156560 	uint32_t i;
28393457Sjc156560 
28403457Sjc156560 	if (strp == NULL) {
28413457Sjc156560 		return (FALSE);
28423457Sjc156560 	}
28433457Sjc156560 
28443457Sjc156560 	len = strlen(strp);
28453457Sjc156560 	if (len == 0) {
28463457Sjc156560 		return (FALSE);
28473457Sjc156560 	}
28483457Sjc156560 
28493457Sjc156560 	/* Skip whitespace characters */
28503457Sjc156560 	for (i = 0; i < len; i++) {
28513457Sjc156560 		if (strp[i] != ' ') {
28520Sstevel@tonic-gate 			break;
28530Sstevel@tonic-gate 		}
28540Sstevel@tonic-gate 	}
28550Sstevel@tonic-gate 
28563457Sjc156560 	/* if strp points all space characters */
28573457Sjc156560 	if (i == len) {
28583457Sjc156560 		return (FALSE);
28590Sstevel@tonic-gate 	}
28600Sstevel@tonic-gate 
28613457Sjc156560 	/* Check the digitals in string */
28623457Sjc156560 	for (; i < len; i++) {
28633457Sjc156560 		if (!isdigit(strp[i])) {
2864902Syw161884 			break;
2865902Syw161884 		}
2866902Syw161884 	}
2867902Syw161884 
28683457Sjc156560 	/* Check the ending string */
28693457Sjc156560 	for (; i < len; i++) {
28703457Sjc156560 		if (strp[i] != ' ') {
28713457Sjc156560 			return (FALSE);
28720Sstevel@tonic-gate 		}
28730Sstevel@tonic-gate 	}
28743457Sjc156560 
28753457Sjc156560 	return (TRUE);
28760Sstevel@tonic-gate }
28770Sstevel@tonic-gate 
28780Sstevel@tonic-gate static int
yes(void)2879840Sjesseb yes(void)
28800Sstevel@tonic-gate {
28810Sstevel@tonic-gate 	int	i, b;
28820Sstevel@tonic-gate 	char    ans[SCHAR_MAX + 1];
28830Sstevel@tonic-gate 
28840Sstevel@tonic-gate 	for (i = 0; ; i++) {
28850Sstevel@tonic-gate 		b = getchar();
28860Sstevel@tonic-gate 		if (b == '\n' || b == '\0' || b == EOF) {
28870Sstevel@tonic-gate 			ans[i] = 0;
28880Sstevel@tonic-gate 			break;
28890Sstevel@tonic-gate 		}
28903457Sjc156560 		if (i < SCHAR_MAX) {
28910Sstevel@tonic-gate 			ans[i] = b;
28923457Sjc156560 		}
28930Sstevel@tonic-gate 	}
28940Sstevel@tonic-gate 	if (i >= SCHAR_MAX) {
28950Sstevel@tonic-gate 		i = SCHAR_MAX;
28960Sstevel@tonic-gate 		ans[SCHAR_MAX] = 0;
28970Sstevel@tonic-gate 	}
28983457Sjc156560 
28993457Sjc156560 	return (rpmatch(ans));
29000Sstevel@tonic-gate }
29010Sstevel@tonic-gate 
29020Sstevel@tonic-gate /*
29033457Sjc156560  * Function: int rpmatch(char *)
29043457Sjc156560  *
29053457Sjc156560  * Description:
29063457Sjc156560  *
29073457Sjc156560  *	Internationalized get yes / no answer.
29083457Sjc156560  *
29093457Sjc156560  * Inputs:
29103457Sjc156560  *	s	-> Pointer to answer to compare against.
29113457Sjc156560  *
29123457Sjc156560  * Returns:
29133457Sjc156560  *	TRUE	-> Answer was affirmative
29143457Sjc156560  *	FALSE	-> Answer was negative
29150Sstevel@tonic-gate  */
29163457Sjc156560 
29173457Sjc156560 static int
rpmatch(char * s)29183457Sjc156560 rpmatch(char *s)
29193457Sjc156560 {
29203457Sjc156560 	int	status;
29213457Sjc156560 
29223457Sjc156560 	/* match yesexpr */
29233457Sjc156560 	status = regexec(&re, s, (size_t)0, NULL, 0);
29243457Sjc156560 	if (status != 0) {
29253457Sjc156560 		return (FALSE);
29263457Sjc156560 	}
29273457Sjc156560 	return (TRUE);
29283457Sjc156560 }
29293457Sjc156560 
29303457Sjc156560 static int
size_to_string(uint64_t size,char * string,int len)29313457Sjc156560 size_to_string(uint64_t size, char *string, int len)
29323457Sjc156560 {
29333457Sjc156560 	int i = 0;
29343457Sjc156560 	uint32_t remainder;
29353457Sjc156560 	char unit[][2] = {" ", "K", "M", "G", "T"};
29363457Sjc156560 
29373457Sjc156560 	if (string == NULL) {
29383457Sjc156560 		return (FAILURE);
29393457Sjc156560 	}
29403457Sjc156560 	while (size > 1023) {
29413457Sjc156560 		remainder = size % 1024;
29423457Sjc156560 		size /= 1024;
29433457Sjc156560 		i++;
29443457Sjc156560 	}
29453457Sjc156560 
29463457Sjc156560 	if (i > 4) {
29473457Sjc156560 		return (FAILURE);
29483457Sjc156560 	}
29493457Sjc156560 
29503457Sjc156560 	remainder /= 103;
29513457Sjc156560 	if (remainder == 0) {
29523457Sjc156560 		(void) snprintf(string, len, "%llu", size);
29533457Sjc156560 	} else {
29543457Sjc156560 		(void) snprintf(string, len, "%llu.%1u", size,
29553457Sjc156560 		    remainder);
29563457Sjc156560 	}
29573457Sjc156560 
29583457Sjc156560 	/* make sure there is one byte for unit */
29593457Sjc156560 	if ((strlen(string) + 1) >=  len) {
29603457Sjc156560 		return (FAILURE);
29613457Sjc156560 	}
29627336SRyan.Wang@Sun.COM 	(void) strlcat(string, unit[i], len);
29633457Sjc156560 
29643457Sjc156560 	return (SUCCESS);
29653457Sjc156560 }
29660Sstevel@tonic-gate 
29670Sstevel@tonic-gate /*
29683457Sjc156560  * Only one raidctl is running at one time.
29690Sstevel@tonic-gate  */
29700Sstevel@tonic-gate static int
enter_raidctl_lock(int * fd)29713457Sjc156560 enter_raidctl_lock(int *fd)
29720Sstevel@tonic-gate {
29733457Sjc156560 	int fd0 = -1;
29743457Sjc156560 	struct flock lock;
29753457Sjc156560 
29763457Sjc156560 	fd0 = open(RAIDCTL_LOCKF, O_CREAT|O_WRONLY, 0600);
29773457Sjc156560 	if (fd0 < 0) {
29784545Sanbui 		if (errno == EACCES) {
29794545Sanbui 			(void) fprintf(stderr,
29804545Sanbui 			    gettext("raidctl:must be root to run raidctl"
29814545Sanbui 			    ": %s\n"), strerror(errno));
29824545Sanbui 		} else {
29834545Sanbui 			(void) fprintf(stderr,
29844545Sanbui 			    gettext("raidctl:failed to open lockfile"
29854545Sanbui 			    " '"RAIDCTL_LOCKF"': %s\n"), strerror(errno));
29864545Sanbui 		}
29873457Sjc156560 		return (FAILURE);
29880Sstevel@tonic-gate 	}
29890Sstevel@tonic-gate 
29903457Sjc156560 	*fd = fd0;
29913457Sjc156560 	lock.l_type = F_WRLCK;
29923457Sjc156560 	lock.l_whence = SEEK_SET;
29933457Sjc156560 	lock.l_start = 0;
29943457Sjc156560 	lock.l_len = 0;
29953457Sjc156560 
29963457Sjc156560 	if ((fcntl(fd0, F_SETLK, &lock) == -1) &&
29973457Sjc156560 	    (errno == EAGAIN || errno == EDEADLK)) {
29983457Sjc156560 		if (fcntl(fd0, F_GETLK, &lock) == -1) {
29993457Sjc156560 			(void) fprintf(stderr,
30003457Sjc156560 			    gettext("raidctl:enter_filelock error\n"));
30013457Sjc156560 			return (FAILURE);
30020Sstevel@tonic-gate 		}
30033457Sjc156560 		(void) fprintf(stderr, gettext("raidctl:"
30043457Sjc156560 		    "enter_filelock:filelock is owned "
30053457Sjc156560 		    "by 'process %d'\n"), lock.l_pid);
30063457Sjc156560 		return (FAILURE);
30070Sstevel@tonic-gate 	}
30083457Sjc156560 
30093457Sjc156560 	return (SUCCESS);
30100Sstevel@tonic-gate }
30113457Sjc156560 
30123457Sjc156560 static void
exit_raidctl_lock(int fd)30133457Sjc156560 exit_raidctl_lock(int fd)
30143457Sjc156560 {
30153457Sjc156560 	struct flock lock;
30163457Sjc156560 
30173457Sjc156560 	lock.l_type = F_UNLCK;
30183457Sjc156560 	lock.l_whence = SEEK_SET;
30193457Sjc156560 	lock.l_start = 0;
30203457Sjc156560 	lock.l_len = 0;
30213457Sjc156560 	if (fcntl(fd, F_SETLK, &lock) == -1) {
30223457Sjc156560 		(void) fprintf(stderr, gettext("raidctl: failed to"
30233457Sjc156560 		    " exit_filelock: %s\n"),
30243457Sjc156560 		    strerror(errno));
30253457Sjc156560 	}
30263457Sjc156560 	(void) close(fd);
30273457Sjc156560 }
3028