Home | History | Annotate | Download | only in util
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   1623   tw21770  * Common Development and Distribution License (the "License").
      6   1623   tw21770  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21      0    stevel /*
     22   9818    Andrew  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0    stevel  * Use is subject to license terms.
     24      0    stevel  */
     25      0    stevel 
     26      0    stevel 
     27      0    stevel #include <stdio.h>
     28      0    stevel #include <errno.h>
     29      0    stevel #include <unistd.h>
     30      0    stevel #include <string.h>
     31      0    stevel 
     32      0    stevel #include <meta.h>
     33      0    stevel #include <sys/lvm/md_mddb.h>
     34      0    stevel #include <sdssc.h>
     35      0    stevel 
     36      0    stevel /*
     37      0    stevel  * print metadevice status
     38      0    stevel  */
     39      0    stevel 
     40      0    stevel 
     41      0    stevel #define	MD_PROBE_OPEN_T "probe open test"
     42      0    stevel 
     43      0    stevel /* used to keep track of the softparts on the same underlying device */
     44      0    stevel struct sp_base_list {
     45      0    stevel 	struct sp_base_list	*next;
     46      0    stevel 	char			*base;
     47      0    stevel };
     48      0    stevel 
     49      0    stevel /*
     50      0    stevel  * Function prototypes
     51      0    stevel  */
     52      0    stevel static void probe_all_devs(mdsetname_t *sp);
     53      0    stevel 
     54      0    stevel static int print_devid(mdsetname_t *sp, mdnamelist_t *nlp, FILE *fp,
     55      0    stevel     md_error_t   *ep);
     56      0    stevel 
     57      0    stevel static md_common_t	*get_concise_unit(mdsetname_t *sp, mdname_t *np,
     58      0    stevel 			    md_error_t *ep);
     59      0    stevel static void	print_all_sets(mdprtopts_t options, int concise_flag,
     60      0    stevel 		    int quiet_flg);
     61      0    stevel static void	print_specific_set(mdsetname_t *sp, mdprtopts_t options,
     62      0    stevel 		    int concise_flag, int quiet_flg);
     63      0    stevel static void	print_concise_diskset(mdsetname_t *sp);
     64      0    stevel static void	print_concise_namelist(mdsetname_t *sp, mdnamelist_t **nl,
     65      0    stevel 		    char mtype);
     66      0    stevel static void	print_concise_md(int indent, mdsetname_t *sp, mdname_t *np);
     67      0    stevel static void	print_concise_mirror(int indent, mdsetname_t *sp,
     68      0    stevel 		    md_mirror_t *mirror);
     69      0    stevel static void	print_concise_raid(int indent, mdsetname_t *sp,
     70      0    stevel 		    md_raid_t *raid);
     71      0    stevel static void	print_concise_stripe(int indent, mdsetname_t *sp,
     72      0    stevel 		    md_stripe_t *stripe);
     73      0    stevel static void	print_concise_sp(int indent, mdsetname_t *sp, md_sp_t *part);
     74      0    stevel static void	print_concise_trans(int indent, mdsetname_t *sp,
     75      0    stevel 		    md_trans_t *trans);
     76      0    stevel static void	free_names(mdnamelist_t **nlp);
     77      0    stevel static char	*get_sm_state(md_mirror_t *mirror, int i,
     78      0    stevel 		    md_status_t mirror_status, uint_t tstate);
     79      0    stevel static char	*get_raid_col_state(md_raidcol_t *colp, uint_t tstate);
     80      0    stevel static char	*get_stripe_state(md_comp_t *mdcp, uint_t tstate);
     81      0    stevel static char	*get_hs_state(md_hs_t *hsp);
     82      0    stevel static struct sp_base_list *sp_add_done(md_sp_t *part, struct sp_base_list *lp);
     83      0    stevel static int	sp_done(md_sp_t *part, struct sp_base_list *lp);
     84      0    stevel static int	sp_match(md_sp_t *part, struct sp_base_list *lp);
     85      0    stevel static void	sp_free_list(struct sp_base_list *lp);
     86      0    stevel 
     87      0    stevel 
     88      0    stevel /*
     89      0    stevel  * print named hotspare pool or metadevice
     90      0    stevel  */
     91      0    stevel static int
     92      0    stevel print_name(
     93      0    stevel 	mdsetname_t	**spp,
     94      0    stevel 	char		*uname,
     95      0    stevel 	mdnamelist_t	**nlistpp,
     96      0    stevel 	char		*fname,
     97      0    stevel 	FILE		*fp,
     98      0    stevel 	mdprtopts_t	options,
     99      0    stevel 	int		*meta_print_trans_msgp,
    100      0    stevel 	mdnamelist_t	**lognlpp,
    101      0    stevel 	md_error_t	*ep
    102      0    stevel )
    103      0    stevel {
    104      0    stevel 	mdname_t	*namep;
    105      0    stevel 	char		*miscname;
    106      0    stevel 
    107      0    stevel 	/* recurse */
    108      0    stevel 	options |= PRINT_SUBDEVS;
    109      0    stevel 
    110      0    stevel 	/* hotspare pool */
    111   1623   tw21770 	if (is_existing_hsp(*spp, uname)) {
    112      0    stevel 		mdhspname_t	*hspnamep;
    113      0    stevel 
    114      0    stevel 		/* get hotsparepool */
    115      0    stevel 		if ((hspnamep = metahspname(spp, uname, ep)) == NULL)
    116      0    stevel 			return (-1);
    117      0    stevel 
    118      0    stevel 		/* check for ownership */
    119      0    stevel 		assert(*spp != NULL);
    120      0    stevel 		if (meta_check_ownership(*spp, ep) != 0)
    121      0    stevel 			return (-1);
    122      0    stevel 
    123      0    stevel 		/* print hotspare pool */
    124      0    stevel 		return (meta_hsp_print(*spp, hspnamep, lognlpp, fname, fp,
    125      0    stevel 		    options, ep));
    126      0    stevel 	}
    127      0    stevel 
    128      0    stevel 	/* get metadevice */
    129   1623   tw21770 	if (((namep = metaname(spp, uname, META_DEVICE, ep)) == NULL) ||
    130      0    stevel 	    (metachkmeta(namep, ep) != 0))
    131      0    stevel 		return (-1);
    132      0    stevel 
    133      0    stevel 	/* check for ownership */
    134      0    stevel 	assert(*spp != NULL);
    135      0    stevel 	if (meta_check_ownership(*spp, ep) != 0)
    136      0    stevel 		return (-1);
    137      0    stevel 
    138      0    stevel 	if ((miscname = metagetmiscname(namep, ep)) != NULL) {
    139      0    stevel 		if (strcmp(miscname, MD_TRANS) == 0) {
    140      0    stevel 			*meta_print_trans_msgp = 1;
    141      0    stevel 		}
    142      0    stevel 	}
    143      0    stevel 
    144      0    stevel 	/* print metadevice */
    145      0    stevel 	return (meta_print_name(*spp, namep, nlistpp, fname, fp, options,
    146      0    stevel 	    lognlpp, ep));
    147      0    stevel }
    148      0    stevel 
    149      0    stevel /*
    150      0    stevel  * print the per set flags
    151      0    stevel  */
    152      0    stevel /*ARGSUSED*/
    153      0    stevel static int
    154      0    stevel print_setstat(
    155      0    stevel 	mdsetname_t		**spp,
    156      0    stevel 	char			*fname,
    157      0    stevel 	FILE			*fp,
    158      0    stevel 	mdprtopts_t		options,
    159      0    stevel 	md_error_t		*ep
    160      0    stevel )
    161      0    stevel {
    162      0    stevel 	int			rval = -1;
    163   1623   tw21770 	char			*cname = NULL;
    164      0    stevel 	char			*cp = NULL;
    165      0    stevel 	md_gs_stat_parm_t	gsp;
    166      0    stevel 
    167      0    stevel 
    168   1623   tw21770 	if (fname != NULL && strchr(fname, '/') != NULL) {
    169   1623   tw21770 		/* get the canonical name */
    170   1623   tw21770 		cname = meta_name_getname(spp, fname, META_DEVICE, ep);
    171   2077   tw21770 		if (cname == NULL)
    172   1623   tw21770 			return (-1);
    173   1623   tw21770 		Free(cname);
    174      0    stevel 	}
    175      0    stevel 
    176      0    stevel 	if ((cp = getenv("MD_DEBUG")) == NULL)
    177      0    stevel 		return (0);
    178      0    stevel 
    179      0    stevel 	if (strstr(cp, "SETINFO") == NULL)
    180      0    stevel 		return (0);
    181      0    stevel 
    182      0    stevel 	(void) memset(&gsp, '\0', sizeof (md_gs_stat_parm_t));
    183      0    stevel 	gsp.gs_setno = (*spp)->setno;
    184      0    stevel 
    185      0    stevel 	if (metaioctl(MD_GET_SETSTAT, &gsp, &gsp.gs_mde, NULL) != 0)
    186      0    stevel 		return (mdstealerror(ep, &gsp.gs_mde));
    187      0    stevel 
    188      0    stevel 	if (fprintf(fp, "Status for set %d = ", gsp.gs_setno) == EOF)
    189      0    stevel 		goto out;
    190      0    stevel 
    191      0    stevel 	if (meta_prbits(fp, NULL, gsp.gs_status, MD_SET_STAT_BITS) == EOF)
    192      0    stevel 		goto out;
    193      0    stevel 
    194      0    stevel 
    195      0    stevel 	if (fprintf(fp, "\n") == EOF)
    196      0    stevel 		goto out;
    197      0    stevel 
    198      0    stevel 	/* success */
    199      0    stevel 	rval = 0;
    200      0    stevel 
    201      0    stevel 	/* cleanup, return error */
    202      0    stevel out:
    203      0    stevel 	if (rval != 0)
    204      0    stevel 		(void) mdsyserror(ep, errno, fname);
    205      0    stevel 
    206      0    stevel 	return (rval);
    207      0    stevel }
    208      0    stevel 
    209      0    stevel /*
    210      0    stevel  * check_replica_state:
    211      0    stevel  * 	If the replica state is stale or the set has been halted
    212      0    stevel  * 	this routine returns an error.
    213      0    stevel  */
    214      0    stevel static int
    215      0    stevel check_replica_state(mdsetname_t *sp, md_error_t *ep)
    216      0    stevel {
    217      0    stevel 	mddb_config_t	c;
    218      0    stevel 
    219      0    stevel 	(void) memset(&c, 0, sizeof (c));
    220      0    stevel 	c.c_id = 0;
    221      0    stevel 	c.c_setno = sp->setno;
    222      0    stevel 
    223      0    stevel 	if (metaioctl(MD_DB_GETDEV, &c, &c.c_mde, NULL) != 0) {
    224      0    stevel 		if (mdismddberror(&c.c_mde, MDE_DB_INVALID))
    225  11053     Surya 			(void) mdstealerror(ep, &c.c_mde);
    226      0    stevel 		return (-1);
    227      0    stevel 	}
    228      0    stevel 
    229      0    stevel 	if (c.c_flags & MDDB_C_STALE) {
    230      0    stevel 		return (mdmddberror(ep, MDE_DB_STALE, NODEV32, sp->setno,
    231   6630  sk102515 		    0, NULL));
    232      0    stevel 	} else
    233      0    stevel 		return (0);
    234      0    stevel }
    235      0    stevel 
    236      0    stevel static void
    237      0    stevel print_trans_msg(mdprtopts_t	options, int	meta_print_trans_msg)
    238      0    stevel {
    239      0    stevel 	if (meta_print_trans_msg != 0) {
    240  11053     Surya 		(void) fprintf(stderr, "\n\n");
    241      0    stevel 		if (options & PRINT_SHORT) {
    242  11053     Surya 			(void) fprintf(stderr, gettext(MD_SHORT_EOF_TRANS_MSG));
    243  11053     Surya 			(void) fprintf(stderr,
    244  11053     Surya 			    gettext(MD_SHORT_EOF_TRANS_WARNING));
    245      0    stevel 		} else {
    246  11053     Surya 			(void) fprintf(stderr, gettext(MD_EOF_TRANS_MSG));
    247  11053     Surya 			(void) fprintf(stderr, gettext(MD_EOF_TRANS_WARNING));
    248      0    stevel 		}
    249      0    stevel 	}
    250      0    stevel }
    251      0    stevel 
    252      0    stevel /*
    253      0    stevel  * print usage message
    254      0    stevel  *
    255      0    stevel  */
    256      0    stevel static void
    257      0    stevel usage(
    258      0    stevel 	mdsetname_t	*sp,
    259      0    stevel 	int		eval
    260      0    stevel )
    261      0    stevel {
    262      0    stevel 	(void) fprintf(stderr, gettext("\
    263   1623   tw21770 usage:	%s [-s setname] [-a][-c][-B][-D][-r][-i][-p] [-t] [metadevice...]\n"),
    264      0    stevel 	    myname);
    265      0    stevel 	md_exit(sp, eval);
    266      0    stevel }
    267      0    stevel 
    268      0    stevel /*
    269      0    stevel  * mainline. crack command line arguments.
    270      0    stevel  */
    271      0    stevel int
    272      0    stevel main(
    273      0    stevel 	int	argc,
    274      0    stevel 	char	*argv[]
    275      0    stevel )
    276      0    stevel {
    277   1623   tw21770 	char		*sname = MD_LOCAL_NAME;
    278      0    stevel 	mdsetname_t	*sp = NULL;
    279      0    stevel 	mdprtopts_t	options = PRINT_HEADER | PRINT_DEVID | PRINT_FAST;
    280      0    stevel 	int		c;
    281      0    stevel 	char		*p;
    282      0    stevel 	md_error_t	status = mdnullerror;
    283      0    stevel 	md_error_t	*ep = &status;
    284      0    stevel 	int		eval = 0;
    285      0    stevel 	int		inquire = 0;
    286      0    stevel 	int		quiet_flg = 0;
    287   1623   tw21770 	int		set_flg = 0;
    288      0    stevel 	int		error;
    289      0    stevel 	int		all_sets_flag = 0;
    290      0    stevel 	int		concise_flag = 0;
    291      0    stevel 	mdnamelist_t	*nlistp = NULL;
    292      0    stevel 	mdname_t		*namep;
    293      0    stevel 	int		devcnt = 0;
    294      0    stevel 	mdnamelist_t	*lognlp = NULL;
    295      0    stevel 	uint_t hsi;
    296      0    stevel 	int		meta_print_trans_msg = 0;
    297      0    stevel 
    298      0    stevel 	/*
    299      0    stevel 	 * Get the locale set up before calling any other routines
    300      0    stevel 	 * with messages to ouput.  Just in case we're not in a build
    301      0    stevel 	 * environment, make sure that TEXT_DOMAIN gets set to
    302      0    stevel 	 * something.
    303      0    stevel 	 */
    304      0    stevel #if !defined(TEXT_DOMAIN)
    305      0    stevel #define	TEXT_DOMAIN "SYS_TEST"
    306      0    stevel #endif
    307      0    stevel 	(void) setlocale(LC_ALL, "");
    308      0    stevel 	(void) textdomain(TEXT_DOMAIN);
    309      0    stevel 
    310      0    stevel 	if (sdssc_bind_library() == SDSSC_OKAY)
    311      0    stevel 		if (sdssc_cmd_proxy(argc, argv, SDSSC_PROXY_PRIMARY,
    312   6630  sk102515 		    &error) == SDSSC_PROXY_DONE)
    313      0    stevel 			exit(error);
    314      0    stevel 
    315      0    stevel 	/* initialize */
    316      0    stevel 	if (md_init(argc, argv, 0, 1, ep) != 0) {
    317      0    stevel 		mde_perror(ep, "");
    318      0    stevel 		md_exit(sp, 1);
    319      0    stevel 	}
    320      0    stevel 
    321      0    stevel 	/* parse arguments */
    322      0    stevel 	optind = 1;
    323      0    stevel 	opterr = 1;
    324   1623   tw21770 	while ((c = getopt(argc, argv, "acSs:hpBDrtiq?")) != -1) {
    325      0    stevel 		switch (c) {
    326      0    stevel 		case 'a':
    327      0    stevel 			all_sets_flag++;
    328      0    stevel 			break;
    329      0    stevel 
    330      0    stevel 		case 'c':
    331      0    stevel 			concise_flag++;
    332      0    stevel 			quiet_flg++;
    333      0    stevel 			break;
    334      0    stevel 
    335      0    stevel 		case 'S':
    336      0    stevel 			options |= PRINT_SETSTAT_ONLY;
    337      0    stevel 			break;
    338      0    stevel 
    339      0    stevel 		case 's':
    340      0    stevel 			sname = optarg;
    341   1623   tw21770 			set_flg++;
    342      0    stevel 			break;
    343      0    stevel 
    344      0    stevel 		case 'h':
    345      0    stevel 			usage(sp, 0);
    346      0    stevel 			break;
    347      0    stevel 
    348      0    stevel 		case 'p':
    349      0    stevel 			options |= PRINT_SHORT;
    350      0    stevel 			options &= ~PRINT_DEVID;
    351      0    stevel 			break;
    352      0    stevel 
    353      0    stevel 		case 't':
    354      0    stevel 			options |= PRINT_TIMES;
    355      0    stevel 			break;
    356      0    stevel 
    357      0    stevel 		case 'i':
    358      0    stevel 			inquire++;
    359      0    stevel 			break;
    360      0    stevel 
    361      0    stevel 		case 'B':
    362      0    stevel 			options |= PRINT_LARGEDEVICES;
    363      0    stevel 			break;
    364   1623   tw21770 		case 'D':
    365   1623   tw21770 			options |= PRINT_FN;
    366   1623   tw21770 			break;
    367      0    stevel 		case 'r':		/* defunct option */
    368      0    stevel 			break;
    369      0    stevel 		case 'q':
    370      0    stevel 			quiet_flg++;
    371      0    stevel 			break;
    372      0    stevel 		case '?':
    373      0    stevel 			if (optopt == '?')
    374      0    stevel 				usage(sp, 0);
    375      0    stevel 			/*FALLTHROUGH*/
    376      0    stevel 		default:
    377      0    stevel 			usage(sp, 1);
    378      0    stevel 			break;
    379      0    stevel 		}
    380      0    stevel 	}
    381      0    stevel 	argc -= optind;
    382      0    stevel 	argv += optind;
    383      0    stevel 
    384   1623   tw21770 	if (all_sets_flag && set_flg) {
    385  11053     Surya 		(void) fprintf(stderr, gettext("metastat: "
    386   1623   tw21770 		    "incompatible options: -a and -s\n"));
    387   1623   tw21770 		usage(sp, 1);
    388   1623   tw21770 	}
    389      0    stevel 
    390   1623   tw21770 	/* get set context */
    391   1623   tw21770 	if ((sp = metasetname(sname, ep)) == NULL) {
    392   1623   tw21770 		mde_perror(ep, "");
    393   1623   tw21770 		md_exit(sp, 1);
    394      0    stevel 	}
    395      0    stevel 
    396      0    stevel 	/* make sure that the mddb is not stale. Else print a warning */
    397      0    stevel 
    398      0    stevel 	if (check_replica_state(sp, ep)) {
    399      0    stevel 		if (mdismddberror(ep, MDE_DB_STALE)) {
    400  11053     Surya 			(void) fprintf(stdout, gettext(
    401      0    stevel 			    "****\nWARNING: Stale "
    402      0    stevel 			    "state database replicas. Metastat output "
    403      0    stevel 			    "may be inaccurate.\n****\n\n"));
    404      0    stevel 		}
    405      0    stevel 	}
    406      0    stevel 
    407      0    stevel 	/* if inquire is set. We probe first */
    408      0    stevel 	if (inquire) {
    409      0    stevel 		if (geteuid() != 0) {
    410  11053     Surya 			(void) fprintf(stderr, gettext("metastat: -i "
    411   6630  sk102515 			    "option requires super-user privilages\n"));
    412      0    stevel 			md_exit(sp, 1);
    413      0    stevel 		}
    414      0    stevel 		probe_all_devs(sp);
    415      0    stevel 	}
    416      0    stevel 	/* print debug stuff */
    417      0    stevel 	if (((p = getenv("MD_DEBUG")) != NULL) &&
    418      0    stevel 	    (strstr(p, "STAT") != NULL)) {
    419      0    stevel 		options |= (PRINT_SETSTAT | PRINT_DEBUG | PRINT_TIMES);
    420      0    stevel 	}
    421      0    stevel 
    422      0    stevel 	if ((options & PRINT_SETSTAT) || (options & PRINT_SETSTAT_ONLY)) {
    423      0    stevel 		if (print_setstat(&sp, argv[0], stdout, options, ep)) {
    424      0    stevel 			mde_perror(ep, "");
    425      0    stevel 			md_exit(sp, 1);
    426      0    stevel 		}
    427      0    stevel 		if (options & PRINT_SETSTAT_ONLY)
    428      0    stevel 			md_exit(sp, 0);
    429      0    stevel 	}
    430      0    stevel 
    431      0    stevel 	/* status all devices */
    432      0    stevel 	if (argc == 0) {
    433      0    stevel 		if (all_sets_flag) {
    434   6630  sk102515 			print_all_sets(options, concise_flag, quiet_flg);
    435      0    stevel 		} else {
    436   6630  sk102515 			print_specific_set(sp, options, concise_flag,
    437   6630  sk102515 			    quiet_flg);
    438      0    stevel 		}
    439      0    stevel 
    440      0    stevel 		if (meta_smf_isonline(meta_smf_getmask(), ep) == 0) {
    441      0    stevel 			mde_perror(ep, "");
    442      0    stevel 			md_exit(sp, 1);
    443      0    stevel 		}
    444      0    stevel 
    445      0    stevel 		/* success */
    446      0    stevel 		md_exit(sp, 0);
    447      0    stevel 	}
    448      0    stevel 	/* print named device types */
    449      0    stevel 	while (devcnt < argc) {
    450      0    stevel 		char	*uname = argv[devcnt];
    451   1623   tw21770 		char	*cname = NULL;
    452   1623   tw21770 
    453   1623   tw21770 		/* get the canonical name */
    454   1623   tw21770 		cname = meta_name_getname(&sp, uname, META_DEVICE, ep);
    455   1623   tw21770 		if (cname == NULL) {
    456   1623   tw21770 			/* already printed the error */
    457   1623   tw21770 			mdclrerror(ep);
    458   1623   tw21770 			eval = 1;
    459   1623   tw21770 			++devcnt;
    460   1623   tw21770 			continue;
    461   1623   tw21770 		}
    462      0    stevel 
    463      0    stevel 		if (concise_flag) {
    464   6630  sk102515 			mdname_t *np;
    465      0    stevel 
    466   6630  sk102515 			np = metaname(&sp, cname, META_DEVICE, ep);
    467   6630  sk102515 			if (np == NULL) {
    468   6630  sk102515 				mde_perror(ep, "");
    469   6630  sk102515 				mdclrerror(ep);
    470   6630  sk102515 				eval = 1;
    471   6630  sk102515 			} else {
    472   6630  sk102515 				print_concise_md(0, sp, np);
    473   6630  sk102515 			}
    474      0    stevel 
    475      0    stevel 		} else {
    476   6630  sk102515 			if (print_name(&sp, cname, &nlistp, NULL, stdout,
    477   6630  sk102515 			    options, &meta_print_trans_msg, &lognlp, ep) != 0) {
    478   6630  sk102515 				mde_perror(ep, "");
    479   6630  sk102515 				mdclrerror(ep);
    480   6630  sk102515 				eval = 1;
    481   6630  sk102515 			}
    482      0    stevel 		}
    483   1623   tw21770 		Free(cname);
    484      0    stevel 		++devcnt;
    485      0    stevel 	}
    486      0    stevel 
    487      0    stevel 	/* print metadevice & relocation device id */
    488      0    stevel 	if ((options & PRINT_DEVID) && (eval != 1) && !quiet_flg) {
    489      0    stevel 		devcnt = 0;
    490      0    stevel 
    491      0    stevel 		while (devcnt < argc) {
    492      0    stevel 			char	*uname = argv[devcnt];
    493   1623   tw21770 			char	*cname = NULL;
    494   1623   tw21770 
    495   1623   tw21770 			/* get the canonical name */
    496   1623   tw21770 			cname = meta_name_getname(&sp, uname, META_DEVICE, ep);
    497   1623   tw21770 			if (cname == NULL) {
    498   1623   tw21770 				mde_perror(ep, "");
    499   1623   tw21770 				mdclrerror(ep);
    500   1623   tw21770 				++devcnt;
    501   1623   tw21770 				continue;
    502   1623   tw21770 			}
    503      0    stevel 
    504      0    stevel 			/* hotspare pools */
    505   1623   tw21770 			if (is_existing_hsp(sp, cname)) {
    506      0    stevel 				mdhspname_t	*hspnamep;
    507      0    stevel 				md_hsp_t	*hsp;
    508      0    stevel 
    509      0    stevel 				/* get hotsparepool */
    510   1623   tw21770 				if ((hspnamep = metahspname(&sp, cname,
    511   6630  sk102515 				    ep)) == NULL)
    512      0    stevel 					eval = 1;
    513      0    stevel 
    514      0    stevel 				if ((hsp = meta_get_hsp(sp, hspnamep,
    515   6630  sk102515 				    ep)) == NULL)
    516      0    stevel 					eval = 1;
    517      0    stevel 
    518      0    stevel 				for (hsi = 0;
    519      0    stevel 				    hsi < hsp->hotspares.hotspares_len;
    520      0    stevel 				    hsi++) {
    521      0    stevel 
    522      0    stevel 					namep = hsp->hotspares.
    523      0    stevel 					    hotspares_val[hsi].hsnamep;
    524      0    stevel 
    525   1623   tw21770 					if (!(options &
    526   1623   tw21770 					    (PRINT_LARGEDEVICES | PRINT_FN))) {
    527      0    stevel 						/* meta_getdevs populates the */
    528      0    stevel 						/* nlistp structure for use   */
    529      0    stevel 						if (meta_getdevs(sp, namep,
    530      0    stevel 						    &nlistp, ep) != 0)
    531      0    stevel 							eval =  1;
    532      0    stevel 					}
    533      0    stevel 
    534      0    stevel 				}
    535      0    stevel 
    536      0    stevel 			} else {
    537      0    stevel 
    538      0    stevel 				/* get metadevice */
    539   1623   tw21770 				if (((namep = metaname(&sp, cname,
    540   6630  sk102515 				    META_DEVICE, ep)) == NULL) ||
    541   6630  sk102515 				    (metachkmeta(namep, ep) != 0))
    542      0    stevel 					eval = 1;
    543      0    stevel 
    544   1623   tw21770 				if (!(options &
    545   1623   tw21770 				    (PRINT_LARGEDEVICES | PRINT_FN))) {
    546      0    stevel 					/* meta_getdevs populates the	*/
    547      0    stevel 					/* nlistp structure for use 	*/
    548      0    stevel 					if (meta_getdevs(sp, namep, &nlistp, ep)
    549      0    stevel 					    != 0)
    550      0    stevel 						eval =  1;
    551      0    stevel 				}
    552      0    stevel 			}
    553   1623   tw21770 			Free(cname);
    554      0    stevel 			++devcnt;
    555      0    stevel 		}
    556      0    stevel 		if (print_devid(sp, nlistp, stdout, ep) != 0)
    557      0    stevel 			eval =  1;
    558      0    stevel 
    559      0    stevel 
    560      0    stevel 	}
    561      0    stevel 
    562      0    stevel 	print_trans_msg(options, meta_print_trans_msg);
    563      0    stevel 
    564      0    stevel 	if (meta_smf_isonline(meta_smf_getmask(), ep) == 0) {
    565      0    stevel 		mde_perror(ep, "");
    566      0    stevel 		md_exit(sp, 1);
    567      0    stevel 	}
    568      0    stevel 
    569      0    stevel 	/* return success */
    570      0    stevel 	md_exit(sp, eval);
    571      0    stevel 	/*NOTREACHED*/
    572      0    stevel 	return (eval);
    573      0    stevel }
    574      0    stevel 
    575      0    stevel static void
    576      0    stevel print_all_sets(mdprtopts_t options, int concise_flag, int quiet_flg)
    577      0    stevel {
    578      0    stevel 	uint_t		max_sets;
    579      0    stevel 	md_error_t	error = mdnullerror;
    580      0    stevel 	int		i;
    581      0    stevel 
    582      0    stevel 	if ((max_sets = get_max_sets(&error)) == 0) {
    583   6630  sk102515 		return;
    584      0    stevel 	}
    585      0    stevel 
    586      0    stevel 	if (!mdisok(&error)) {
    587   6630  sk102515 		mdclrerror(&error);
    588   6630  sk102515 		return;
    589      0    stevel 	}
    590      0    stevel 
    591      0    stevel 	/* for each possible set number, see if we really have a diskset */
    592      0    stevel 	for (i = 0; i < max_sets; i++) {
    593   6630  sk102515 		mdsetname_t		*sp;
    594      0    stevel 
    595   6630  sk102515 		if ((sp = metasetnosetname(i, &error)) == NULL) {
    596   6630  sk102515 			if (!mdisok(&error) &&
    597   6630  sk102515 			    mdisrpcerror(&error, RPC_PROGNOTREGISTERED)) {
    598   6630  sk102515 			/* metad rpc program not registered - no metasets */
    599   6630  sk102515 				break;
    600   6630  sk102515 			}
    601   6630  sk102515 
    602   6630  sk102515 			mdclrerror(&error);
    603   6630  sk102515 			continue;
    604   6630  sk102515 		}
    605   6630  sk102515 		mdclrerror(&error);
    606   6630  sk102515 
    607   6630  sk102515 		if (meta_check_ownership(sp, &error) == 0) {
    608   6630  sk102515 			/* we own the set, so we can print the metadevices */
    609   6630  sk102515 			print_specific_set(sp, options, concise_flag,
    610   6630  sk102515 			    quiet_flg);
    611   6630  sk102515 			(void) printf("\n");
    612      0    stevel 		}
    613      0    stevel 
    614   6630  sk102515 		metaflushsetname(sp);
    615      0    stevel 	}
    616      0    stevel }
    617      0    stevel 
    618      0    stevel static void
    619      0    stevel print_specific_set(mdsetname_t *sp, mdprtopts_t options, int concise_flag,
    620      0    stevel 	int quiet_flg)
    621      0    stevel {
    622      0    stevel 	md_error_t	status = mdnullerror;
    623      0    stevel 	md_error_t	*ep = &status;
    624      0    stevel 	int		meta_print_trans_msg = 0;
    625      0    stevel 
    626      0    stevel 	/* check for ownership */
    627      0    stevel 	assert(sp != NULL);
    628      0    stevel 	if (meta_check_ownership(sp, ep) != 0) {
    629   6630  sk102515 		mde_perror(ep, "");
    630   6630  sk102515 		md_exit(sp, 1);
    631      0    stevel 	}
    632      0    stevel 
    633      0    stevel 	if (concise_flag) {
    634   6630  sk102515 		print_concise_diskset(sp);
    635      0    stevel 
    636      0    stevel 	} else {
    637   6630  sk102515 		mdnamelist_t	*nlistp = NULL;
    638      0    stevel 
    639   6630  sk102515 		/* status devices */
    640   6630  sk102515 		if (meta_print_all(sp, NULL, &nlistp, stdout, options,
    641   6630  sk102515 		    &meta_print_trans_msg, ep) != 0) {
    642      0    stevel 			mde_perror(ep, "");
    643      0    stevel 			md_exit(sp, 1);
    644      0    stevel 		}
    645   6630  sk102515 
    646   6630  sk102515 		/* print relocation device id on all dev's */
    647   6630  sk102515 		if ((options & PRINT_DEVID) && !quiet_flg) {
    648   6630  sk102515 			/*
    649   6630  sk102515 			 * Ignore return value from meta_getalldevs since
    650   6630  sk102515 			 * it will return a failure if even one device cannot
    651   6630  sk102515 			 * be found - which could occur in the case of device
    652   6630  sk102515 			 * failure or a device being powered off during
    653   6630  sk102515 			 * upgrade.  Even if meta_getalldevs fails, the
    654   6630  sk102515 			 * data in nlistp is still valid.
    655   6630  sk102515 			 */
    656   6630  sk102515 			if (!(options & (PRINT_LARGEDEVICES | PRINT_FN))) {
    657   6630  sk102515 				(void) meta_getalldevs(sp, &nlistp, 0, ep);
    658   6630  sk102515 			}
    659   6630  sk102515 			if (nlistp != NULL) {
    660   6630  sk102515 				if (print_devid(sp, nlistp, stdout, ep) != 0) {
    661   6630  sk102515 					mde_perror(ep, "");
    662   6630  sk102515 					md_exit(sp, 1);
    663   6630  sk102515 				}
    664   6630  sk102515 			}
    665   6630  sk102515 		}
    666      0    stevel 	}
    667      0    stevel 
    668      0    stevel 	print_trans_msg(options, meta_print_trans_msg);
    669      0    stevel }
    670      0    stevel 
    671      0    stevel /*
    672      0    stevel  * print_devid prints out cxtxdx and devid for devices passed in a
    673      0    stevel  * mdnamelist_t structure
    674      0    stevel  */
    675      0    stevel static int
    676      0    stevel print_devid(
    677      0    stevel 	mdsetname_t  *sp,
    678      0    stevel 	mdnamelist_t *nlp,
    679      0    stevel 	FILE		 *fp,
    680      0    stevel 	md_error_t   *ep
    681      0    stevel )
    682      0    stevel {
    683      0    stevel 	int 			retval = 0;
    684      0    stevel 	mdnamelist_t		*onlp = NULL;
    685      0    stevel 	mddevid_t 		*ldevidp = NULL;
    686      0    stevel 	mddevid_t		*nextp;
    687      0    stevel 
    688      0    stevel 	/* make a non-duplicate list of nlp */
    689      0    stevel 	for (onlp = nlp; (onlp != NULL); onlp = onlp->next) {
    690      0    stevel 		meta_create_non_dup_list(onlp->namep, &ldevidp);
    691      0    stevel 	}
    692      0    stevel 
    693      0    stevel 	retval = meta_print_devid(sp, fp, ldevidp, ep);
    694      0    stevel 
    695      0    stevel 	/* cleanup */
    696      0    stevel 	for (nextp = ldevidp; nextp != NULL; ldevidp = nextp) {
    697      0    stevel 		Free(ldevidp->ctdname);
    698      0    stevel 		nextp = ldevidp->next;
    699      0    stevel 		Free(ldevidp);
    700      0    stevel 	}
    701      0    stevel 
    702      0    stevel 	return (retval);
    703      0    stevel }
    704      0    stevel 
    705      0    stevel /*
    706      0    stevel  * probedev issues ioctls for all the metadevices
    707      0    stevel  */
    708      0    stevel 
    709      0    stevel 
    710      0    stevel 
    711      0    stevel 
    712      0    stevel /*
    713      0    stevel  * Failure return's a 1
    714      0    stevel  */
    715      0    stevel int
    716      0    stevel hotspare_ok(char *bname)
    717      0    stevel {
    718      0    stevel 	int fd;
    719      0    stevel 	char buf[512];
    720      0    stevel 
    721      0    stevel 	if ((fd = open(bname, O_RDONLY)) < 0)
    722      0    stevel 		return (0);
    723   6630  sk102515 	if (read(fd, buf, sizeof (buf)) < 0) {
    724   6630  sk102515 		(void) close(fd);
    725      0    stevel 		return (0);
    726   6630  sk102515 	}
    727   6630  sk102515 	(void) close(fd);
    728      0    stevel 	return (1);
    729      0    stevel }
    730      0    stevel 
    731      0    stevel void
    732      0    stevel delete_hotspares_impl(mdsetname_t *sp, mdhspname_t *hspnp, md_hsp_t *hspp)
    733      0    stevel {
    734      0    stevel 	md_hs_t *hsp;
    735      0    stevel 	uint_t		hsi;
    736      0    stevel 	char    *bname;
    737      0    stevel 	md_error_t e = mdnullerror;
    738      0    stevel 	int deleted_hs = 0;
    739      0    stevel 
    740      0    stevel 	for (hsi = 0; (hsi < hspp->hotspares.hotspares_len); ++hsi) {
    741      0    stevel 		mdnamelist_t *nlp;
    742      0    stevel 
    743      0    stevel 		hsp = &hspp->hotspares.hotspares_val[hsi];
    744      0    stevel 		bname = hsp->hsnamep->bname;
    745      0    stevel 		nlp = NULL;
    746  11053     Surya 		(void) metanamelist_append(&nlp, hsp->hsnamep);
    747      0    stevel 		/* print hotspare */
    748      0    stevel 		if (hsp->state == HSS_AVAILABLE) {
    749      0    stevel 			if (hotspare_ok(bname))
    750      0    stevel 				continue;
    751      0    stevel 
    752  11053     Surya 			(void) fprintf(stderr,
    753   6630  sk102515 			    "NOTICE: Hotspare %s in %s has failed.\n"
    754   6630  sk102515 			    "\tDeleting %s since it not in use\n\n",
    755   6630  sk102515 			    bname, hspnp->hspname, bname);
    756      0    stevel 
    757      0    stevel 			if (meta_hs_delete(sp, hspnp, nlp, 0, &e) != NULL) {
    758      0    stevel 				mde_perror(&e, "");
    759   9818    Andrew 				mdclrerror(&e);
    760      0    stevel 			} else {
    761      0    stevel 				deleted_hs++;
    762      0    stevel 			}
    763      0    stevel 		}
    764      0    stevel 	}
    765      0    stevel }
    766      0    stevel 
    767      0    stevel 
    768      0    stevel 
    769      0    stevel /*
    770      0    stevel  * Generic routine to issue ioctls
    771      0    stevel  */
    772      0    stevel 
    773      0    stevel void
    774      0    stevel md_setprobetest(md_probedev_t *iocp)
    775      0    stevel {
    776      0    stevel 	(void) strcpy(iocp->test_name, MD_PROBE_OPEN_T);
    777      0    stevel }
    778      0    stevel 
    779      0    stevel int
    780      0    stevel md_probe_ioctl(mdsetname_t *sp, mdnamelist_t *nlp, int ndevs, char *drvname)
    781      0    stevel {
    782      0    stevel 	mdnamelist_t	*p;
    783      0    stevel 	mdname_t	*np;
    784   6630  sk102515 	md_probedev_t	probe_ioc, *iocp;
    785   6630  sk102515 	int		i, retval = 0;
    786      0    stevel 	/*
    787      0    stevel 	 * Allocate space for all the metadevices and fill in
    788      0    stevel 	 * the minor numbers.
    789      0    stevel 	 */
    790      0    stevel 
    791  11053     Surya 	(void) memset(&probe_ioc, 0, sizeof (probe_ioc));
    792      0    stevel 	iocp = &probe_ioc;
    793      0    stevel 
    794      0    stevel 	if ((iocp->mnum_list = (uintptr_t)calloc(ndevs, sizeof (minor_t)))
    795      0    stevel 	    == 0) {
    796      0    stevel 		perror("md_probe_ioctl: calloc");
    797      0    stevel 		return (-1);
    798      0    stevel 	}
    799      0    stevel 
    800      0    stevel 	MD_SETDRIVERNAME(iocp, drvname, sp->setno);
    801      0    stevel 	md_setprobetest(iocp);
    802      0    stevel 
    803      0    stevel 	iocp->nmdevs = ndevs;
    804      0    stevel 
    805      0    stevel 	for (p = nlp, i = 0; p; p = p->next, i++) {
    806      0    stevel 		np = p->namep;
    807     62     jeanm 		((minor_t *)(uintptr_t)iocp->mnum_list)[i] =
    808     62     jeanm 		    meta_getminor(np->dev);
    809      0    stevel 	}
    810      0    stevel 
    811      0    stevel 
    812      0    stevel 	if (metaioctl(MD_IOCPROBE_DEV, iocp, &(iocp->mde), NULL) != 0)
    813      0    stevel 			retval = -1;
    814   9818    Andrew 	Free((void *)(uintptr_t)iocp->mnum_list);
    815      0    stevel 	return (retval);
    816      0    stevel }
    817      0    stevel /*
    818      0    stevel  *
    819      0    stevel  *  - remove p from nlp list
    820      0    stevel  *  - put it on the toplp list.
    821      0    stevel  *  - update the p to the next element
    822      0    stevel  */
    823      0    stevel 
    824      0    stevel void
    825      0    stevel add_to_list(mdnamelist_t **curpp, mdnamelist_t **prevpp, mdnamelist_t **newlpp)
    826      0    stevel {
    827      0    stevel 	mdnamelist_t	*p, *prevp, *nlp;
    828      0    stevel 
    829      0    stevel 	p = *curpp;
    830      0    stevel 	prevp = *prevpp;
    831      0    stevel 	nlp = *newlpp;
    832      0    stevel 
    833      0    stevel 	if (prevp == p) {
    834      0    stevel 		/* if first element reset prevp */
    835      0    stevel 			prevp = p->next;
    836      0    stevel 			p->next = nlp;
    837      0    stevel 			nlp = p;
    838      0    stevel 			p = prevp;
    839      0    stevel 	} else {
    840      0    stevel 		prevp->next = p->next;
    841      0    stevel 		p->next = nlp;
    842      0    stevel 		nlp = p;
    843      0    stevel 		p = prevp->next;
    844      0    stevel 	}
    845      0    stevel 	*curpp = p;
    846      0    stevel 	*prevpp = prevp;
    847      0    stevel 	*newlpp = nlp;
    848      0    stevel }
    849      0    stevel /*
    850      0    stevel  * Scans the given list of metadeivces and returns a list of top level
    851      0    stevel  * metadevices.
    852      0    stevel  * Note: The orignal list is not valid at the end and is set to NULL.
    853      0    stevel  */
    854      0    stevel 
    855      0    stevel int
    856      0    stevel get_toplevel_mds(mdsetname_t *sp, mdnamelist_t **lpp,
    857      0    stevel 			mdnamelist_t **top_pp)
    858      0    stevel {
    859      0    stevel 	mdnamelist_t	*p, *prevp, *toplp;
    860      0    stevel 	int		ntopmd;
    861      0    stevel 	md_common_t	*mdp;
    862      0    stevel 	md_error_t	e = mdnullerror;
    863      0    stevel 
    864      0    stevel 	ntopmd = 0;
    865      0    stevel 	prevp = p = *lpp;
    866      0    stevel 	toplp = NULL;
    867      0    stevel 
    868      0    stevel 	while (p) {
    869      0    stevel 		if ((mdp = meta_get_unit(sp, p->namep, &e)) == NULL) {
    870      0    stevel 				prevp = p;
    871      0    stevel 				p = p->next;
    872      0    stevel 				continue;
    873      0    stevel 		}
    874      0    stevel 
    875      0    stevel 		if (mdp->parent == MD_NO_PARENT) {
    876      0    stevel 			/* increment the top level md count. */
    877      0    stevel 			ntopmd++;
    878      0    stevel 			add_to_list(&p, &prevp, &toplp);
    879      0    stevel 		} else {
    880      0    stevel 			prevp = p;
    881      0    stevel 			p = p->next;
    882      0    stevel 		}
    883      0    stevel 	}
    884      0    stevel 	*lpp = NULL;
    885      0    stevel 	*top_pp = toplp;
    886      0    stevel 
    887      0    stevel 	return (ntopmd);
    888      0    stevel }
    889      0    stevel 
    890      0    stevel int
    891      0    stevel get_namelist(mdnamelist_t **transdevlist, mdnamelist_t **devlist,
    892      0    stevel 					char *dev_type)
    893      0    stevel {
    894      0    stevel 	mdnamelist_t *np, *prevp;
    895      0    stevel 	md_error_t	e = mdnullerror;
    896      0    stevel 	char		*type_name;
    897      0    stevel 	int		i = 0;
    898      0    stevel 
    899      0    stevel 	prevp = np = *transdevlist;
    900      0    stevel 	while (np) {
    901      0    stevel 		if ((type_name = metagetmiscname(np->namep, &e)) == NULL) {
    902      0    stevel 			*devlist = NULL;
    903      0    stevel 			return (-1);
    904      0    stevel 		}
    905      0    stevel 		if (strcmp(type_name, dev_type) == 0) {
    906      0    stevel 			/* move it to the devlist */
    907      0    stevel 			add_to_list(&np, &prevp, devlist);
    908      0    stevel 			i++;
    909      0    stevel 		} else {
    910      0    stevel 			prevp = np;
    911      0    stevel 			np = np->next;
    912      0    stevel 		}
    913      0    stevel 	}
    914      0    stevel 	return (i);
    915      0    stevel }
    916      0    stevel 
    917      0    stevel 
    918      0    stevel mdnamelist_t *
    919      0    stevel create_nlp(mdsetname_t *sp)
    920      0    stevel {
    921      0    stevel 	mdnamelist_t *np;
    922      0    stevel 	md_error_t   e = mdnullerror;
    923      0    stevel 
    924      0    stevel 	if (np = (mdnamelist_t *)malloc(sizeof (mdnamelist_t))) {
    925      0    stevel 		np->next = NULL;
    926      0    stevel 		return (np);
    927      0    stevel 	} else {
    928      0    stevel 		/* error condition below */
    929      0    stevel 		mde_perror(&e, "create_nlp: malloc failed\n");
    930      0    stevel 		md_exit(sp, 1);
    931      0    stevel 	}
    932     62     jeanm 	return (0);
    933      0    stevel }
    934      0    stevel 
    935      0    stevel /*
    936      0    stevel  * Create a list of metadevices associated with trans. top_pp points to
    937      0    stevel  * this list. The number of components in the list are also returned.
    938      0    stevel  */
    939      0    stevel int
    940      0    stevel create_trans_compslist(mdsetname_t *sp, mdnamelist_t **lpp,
    941      0    stevel 				mdnamelist_t **top_pp)
    942      0    stevel {
    943      0    stevel 	mdnamelist_t	*p, *tailp, *toplp, *newlp;
    944      0    stevel 	int		ntoptrans;
    945      0    stevel 	md_error_t	e = mdnullerror;
    946      0    stevel 	md_trans_t	*tp;
    947      0    stevel 
    948      0    stevel 	ntoptrans = 0;
    949      0    stevel 	p = *lpp;
    950      0    stevel 	tailp = toplp = NULL;
    951      0    stevel 	/*
    952      0    stevel 	 * Scan the current list of trans devices. From that
    953      0    stevel 	 * extract all the lower level metadevices and put them on
    954      0    stevel 	 * toplp list.
    955      0    stevel 	 */
    956      0    stevel 
    957      0    stevel 	while (p) {
    958      0    stevel 		if (tp = meta_get_trans(sp, p->namep, &e)) {
    959      0    stevel 			/*
    960      0    stevel 			 * Check the master and log devices to see if they
    961      0    stevel 			 * are metadevices
    962      0    stevel 			 */
    963      0    stevel 			if (metaismeta(tp->masternamep)) {
    964      0    stevel 				/* get a mdnamelist_t. */
    965      0    stevel 				newlp = create_nlp(sp);
    966      0    stevel 				newlp->namep = tp->masternamep;
    967      0    stevel 				if (toplp == NULL) {
    968      0    stevel 					toplp = tailp = newlp;
    969      0    stevel 				} else {
    970      0    stevel 					tailp->next = newlp;
    971      0    stevel 					tailp = newlp;
    972      0    stevel 				}
    973      0    stevel 				ntoptrans++;
    974      0    stevel 			}
    975      0    stevel 
    976      0    stevel 			if (tp->lognamep && metaismeta(tp->lognamep)) {
    977      0    stevel 				newlp = create_nlp(sp);
    978      0    stevel 				newlp->namep = tp->lognamep;
    979      0    stevel 				if (toplp == NULL) {
    980      0    stevel 					toplp = tailp = newlp;
    981      0    stevel 				} else {
    982      0    stevel 					tailp->next = newlp;
    983      0    stevel 					tailp = newlp;
    984      0    stevel 				}
    985      0    stevel 				ntoptrans++;
    986      0    stevel 			}
    987      0    stevel 			p = p->next;
    988      0    stevel 		}
    989      0    stevel 	}
    990      0    stevel 	*top_pp = toplp;
    991      0    stevel 	return (ntoptrans);
    992      0    stevel }
    993      0    stevel 
    994      0    stevel void
    995      0    stevel probe_mirror_devs(mdsetname_t *sp)
    996      0    stevel {
    997      0    stevel 	mdnamelist_t	*nlp, *toplp;
    998      0    stevel 	int		cnt;
    999      0    stevel 	md_error_t	e = mdnullerror;
   1000      0    stevel 
   1001      0    stevel 	nlp = toplp = NULL;
   1002      0    stevel 
   1003      0    stevel 	if (meta_get_mirror_names(sp, &nlp, 0, &e) > 0) {
   1004      0    stevel 		/*
   1005      0    stevel 		 * We have some mirrors to probe
   1006      0    stevel 		 * get a list of top-level mirrors
   1007      0    stevel 		 */
   1008      0    stevel 
   1009      0    stevel 		cnt = get_toplevel_mds(sp, &nlp, &toplp);
   1010      0    stevel 		if (cnt && (md_probe_ioctl(sp, toplp, cnt, MD_MIRROR) < 0))
   1011      0    stevel 				perror("MD_IOCPROBE_DEV");
   1012   9818    Andrew 	} else {
   1013   9818    Andrew 		mdclrerror(&e);
   1014      0    stevel 	}
   1015      0    stevel 	metafreenamelist(nlp);
   1016      0    stevel 	metafreenamelist(toplp);
   1017      0    stevel 
   1018      0    stevel }
   1019      0    stevel 
   1020      0    stevel void
   1021      0    stevel probe_raid_devs(mdsetname_t *sp)
   1022      0    stevel {
   1023      0    stevel 	mdnamelist_t	*nlp, *toplp;
   1024      0    stevel 	int		cnt;
   1025      0    stevel 	md_error_t	e = mdnullerror;
   1026      0    stevel 
   1027      0    stevel 	nlp = toplp = NULL;
   1028      0    stevel 
   1029      0    stevel 	if (meta_get_raid_names(sp, &nlp, 0, &e) > 0) {
   1030      0    stevel 		/*
   1031      0    stevel 		 * We have some mirrors to probe
   1032      0    stevel 		 * get a list of top-level mirrors
   1033      0    stevel 		 */
   1034      0    stevel 
   1035      0    stevel 		cnt = get_toplevel_mds(sp, &nlp, &toplp);
   1036      0    stevel 
   1037      0    stevel 		if (cnt && (md_probe_ioctl(sp, toplp, cnt, MD_RAID) < 0))
   1038      0    stevel 			perror("MD_IOCPROBE_DEV");
   1039   9818    Andrew 	} else {
   1040   9818    Andrew 		mdclrerror(&e);
   1041      0    stevel 	}
   1042      0    stevel 	metafreenamelist(nlp);
   1043      0    stevel 	metafreenamelist(toplp);
   1044      0    stevel }
   1045      0    stevel 
   1046      0    stevel /*
   1047      0    stevel  * Trans probes are diffenent. -- so whats new.
   1048      0    stevel  * we separate out the master and log device and then issue the
   1049      0    stevel  * probe calls.
   1050      0    stevel  * Since the underlying device could be disk, stripe, RAID or miror,
   1051      0    stevel  * we have to sort them out and then call the ioctl for each.
   1052      0    stevel  */
   1053      0    stevel 
   1054      0    stevel void
   1055      0    stevel probe_trans_devs(mdsetname_t *sp)
   1056      0    stevel {
   1057      0    stevel 	mdnamelist_t	*nlp, *toplp;
   1058      0    stevel 	mdnamelist_t	*trans_raidlp, *trans_mmlp, *trans_stripelp;
   1059      0    stevel 	int		cnt;
   1060      0    stevel 	md_error_t	e = mdnullerror;
   1061      0    stevel 
   1062      0    stevel 	nlp = toplp = NULL;
   1063      0    stevel 	trans_raidlp = trans_mmlp = trans_stripelp = NULL;
   1064      0    stevel 
   1065      0    stevel 	if (meta_get_trans_names(sp, &nlp, 0, &e) > 0) {
   1066      0    stevel 		/*
   1067      0    stevel 		 * get a list of master and log metadevices.
   1068      0    stevel 		 */
   1069      0    stevel 
   1070      0    stevel 		cnt = create_trans_compslist(sp, &nlp, &toplp);
   1071      0    stevel 
   1072      0    stevel 		/* underlying RAID-5 components */
   1073      0    stevel 
   1074      0    stevel 		cnt = get_namelist(&toplp, &trans_raidlp, MD_RAID);
   1075      0    stevel 		if ((cnt > 0) && (md_probe_ioctl(sp, trans_raidlp, cnt,
   1076      0    stevel 		    MD_RAID) < 0))
   1077      0    stevel 			perror("MD_IOCPROBE_DEV");
   1078      0    stevel 
   1079      0    stevel 		metafreenamelist(trans_raidlp);
   1080      0    stevel 
   1081      0    stevel 		/* underlying mirror components */
   1082      0    stevel 
   1083      0    stevel 		cnt = get_namelist(&toplp, &trans_mmlp, MD_MIRROR);
   1084      0    stevel 
   1085      0    stevel 		if ((cnt > 0) && (md_probe_ioctl(sp, trans_mmlp, cnt,
   1086      0    stevel 		    MD_MIRROR) < 0))
   1087      0    stevel 			perror("MD_IOCPROBE_DEV");
   1088      0    stevel 
   1089      0    stevel 		metafreenamelist(trans_mmlp);
   1090      0    stevel 
   1091      0    stevel 		/* underlying stripe components */
   1092      0    stevel 
   1093      0    stevel 		cnt = get_namelist(&toplp, &trans_stripelp, MD_STRIPE);
   1094      0    stevel 		if ((cnt > 0) && (md_probe_ioctl(sp, trans_stripelp, cnt,
   1095      0    stevel 		    MD_STRIPE) < 0))
   1096      0    stevel 			perror("MD_IOCPROBE_DEV");
   1097      0    stevel 		metafreenamelist(trans_stripelp);
   1098      0    stevel 		metafreenamelist(nlp);
   1099   9818    Andrew 	} else {
   1100   9818    Andrew 		mdclrerror(&e);
   1101      0    stevel 	}
   1102      0    stevel }
   1103      0    stevel 
   1104      0    stevel /*
   1105      0    stevel  * probe hot spares. This is differs from other approaches since
   1106      0    stevel  * there are no read/write routines through md. We check at the physical
   1107      0    stevel  * component level and then delete it if its bad.
   1108      0    stevel  */
   1109      0    stevel 
   1110      0    stevel void
   1111      0    stevel probe_hotspare_devs(mdsetname_t *sp)
   1112      0    stevel {
   1113      0    stevel 	mdhspnamelist_t *hspnlp = NULL;
   1114      0    stevel 	mdhspnamelist_t	*p;
   1115      0    stevel 	md_hsp_t	*hspp;
   1116      0    stevel 	md_error_t	e = mdnullerror;
   1117      0    stevel 
   1118   9818    Andrew 	if (meta_get_hsp_names(sp, &hspnlp, 0, &e) <= 0) {
   1119   9818    Andrew 		mdclrerror(&e);
   1120      0    stevel 		return;
   1121      0    stevel 	}
   1122      0    stevel 	for (p = hspnlp; (p != NULL); p = p->next) {
   1123      0    stevel 		mdhspname_t	*hspnp = p->hspnamep;
   1124      0    stevel 
   1125      0    stevel 		if ((hspp = meta_get_hsp(sp, hspnp, &e)) == NULL)
   1126      0    stevel 			continue;
   1127      0    stevel 
   1128      0    stevel 		if (hspp->hotspares.hotspares_len != 0) {
   1129      0    stevel 			delete_hotspares_impl(sp, hspnp, hspp);
   1130      0    stevel 		}
   1131      0    stevel 	}
   1132      0    stevel 	metafreehspnamelist(hspnlp);
   1133   9818    Andrew 	mdclrerror(&e);
   1134      0    stevel }
   1135      0    stevel 
   1136      0    stevel static void
   1137      0    stevel probe_all_devs(mdsetname_t *sp)
   1138      0    stevel {
   1139      0    stevel 	probe_hotspare_devs(sp);
   1140      0    stevel 	probe_mirror_devs(sp);
   1141      0    stevel 	probe_raid_devs(sp);
   1142      0    stevel 	probe_trans_devs(sp);
   1143      0    stevel }
   1144      0    stevel 
   1145      0    stevel /*
   1146      0    stevel  * The following functions are used to print the concise output
   1147      0    stevel  * of the metastat coommand (-c option).
   1148      0    stevel  *
   1149      0    stevel  * Normally the output for metastat is performed within libmeta via
   1150      0    stevel  * the *_report functions within each of the metadevice specific files in
   1151      0    stevel  * libmeta.  However, it is usually bad architecture for a library to
   1152      0    stevel  * perform output since there are so many different ways that an application
   1153      0    stevel  * can choose to do output (e.g. GUI, CLI, CIM, SNMP, etc.).  So, for the
   1154      0    stevel  * concise output option we have moved the CLI output to the metastat
   1155      0    stevel  * code and just use libmeta as the source of data to be printed.
   1156      0    stevel  *
   1157      0    stevel  * This function gets all of the different top-level metadevices in the set
   1158      0    stevel  * and prints them.  It calls the print_concise_md() function to recursively
   1159      0    stevel  * print the metadevices that underly the top-level metadevices.  It does
   1160      0    stevel  * special handling for soft partitions so that all of the SPs on the
   1161      0    stevel  * same underlying device are grouped and then that underlying device
   1162      0    stevel  * is only printed once.
   1163      0    stevel  */
   1164      0    stevel static void
   1165      0    stevel print_concise_diskset(mdsetname_t *sp)
   1166      0    stevel {
   1167      0    stevel 	md_error_t		error = mdnullerror;
   1168      0    stevel 	mdnamelist_t		*nl = NULL;
   1169      0    stevel 	mdhspnamelist_t		*hsp_list = NULL;
   1170      0    stevel 
   1171      0    stevel 	/*
   1172      0    stevel 	 * We do extra handling for soft parts since we want to find
   1173      0    stevel 	 * all of the SPs on the same underlying device, group them and
   1174      0    stevel 	 * print them together before printing the underlying device just
   1175      0    stevel 	 * once.  This logic doesn't apply to any other metadevice type.
   1176      0    stevel 	 */
   1177      0    stevel 	if (meta_get_sp_names(sp, &nl, 0, &error) >= 0) {
   1178   6630  sk102515 		mdnamelist_t	*nlp;
   1179   6630  sk102515 		/* keep track of the softparts on the same underlying device */
   1180   6630  sk102515 		struct sp_base_list	*base_list = NULL;
   1181      0    stevel 
   1182   6630  sk102515 		for (nlp = nl; nlp != NULL; nlp = nlp->next) {
   1183   6630  sk102515 			mdname_t	*mdn;
   1184   6630  sk102515 			md_sp_t		*soft_part;
   1185   6630  sk102515 			mdnamelist_t	*tnlp;
   1186      0    stevel 
   1187   6630  sk102515 			mdn = metaname(&sp, nlp->namep->cname,
   1188   6630  sk102515 			    META_DEVICE, &error);
   1189   6630  sk102515 			mdclrerror(&error);
   1190   6630  sk102515 			if (mdn == NULL) {
   1191   6630  sk102515 				print_concise_entry(0, nlp->namep->cname,
   1192   6630  sk102515 				    0, 'p');
   1193  11053     Surya 				(void) printf("\n");
   1194   6630  sk102515 				continue;
   1195   6630  sk102515 			}
   1196   6630  sk102515 
   1197   6630  sk102515 			soft_part = meta_get_sp_common(sp, mdn, 1, &error);
   1198   6630  sk102515 			mdclrerror(&error);
   1199   6630  sk102515 
   1200   6630  sk102515 			if (soft_part == NULL ||
   1201   6630  sk102515 			    MD_HAS_PARENT(soft_part->common.parent) ||
   1202   6630  sk102515 			    sp_done(soft_part, base_list))
   1203   6630  sk102515 				continue;
   1204   6630  sk102515 
   1205   6630  sk102515 			/* print this soft part */
   1206   6630  sk102515 			print_concise_entry(0, soft_part->common.namep->cname,
   1207   6630  sk102515 			    soft_part->common.size, 'p');
   1208   6630  sk102515 			(void) printf(" %s\n", soft_part->compnamep->cname);
   1209   6630  sk102515 
   1210   6630  sk102515 			/*
   1211   6630  sk102515 			 * keep track of the underlying device of
   1212   6630  sk102515 			 * this soft part
   1213   6630  sk102515 			 */
   1214   6630  sk102515 			base_list = sp_add_done(soft_part, base_list);
   1215   6630  sk102515 
   1216   6630  sk102515 			/*
   1217   6630  sk102515 			 * now print all of the other soft parts on the same
   1218   6630  sk102515 			 * underlying device
   1219   6630  sk102515 			 */
   1220   6630  sk102515 			for (tnlp = nlp->next; tnlp != NULL; tnlp =
   1221   6630  sk102515 			    tnlp->next) {
   1222   6630  sk102515 				md_sp_t		*part;
   1223   6630  sk102515 
   1224   6630  sk102515 				mdn = metaname(&sp, tnlp->namep->cname,
   1225   6630  sk102515 				    META_DEVICE, &error);
   1226   6630  sk102515 
   1227   6630  sk102515 				mdclrerror(&error);
   1228   6630  sk102515 				if (mdn == NULL)
   1229   6630  sk102515 					continue;
   1230   6630  sk102515 
   1231   6630  sk102515 				part = meta_get_sp_common(sp, mdn, 1, &error);
   1232   6630  sk102515 				mdclrerror(&error);
   1233   6630  sk102515 
   1234   6630  sk102515 				if (part == NULL || MD_HAS_PARENT(
   1235   6630  sk102515 				    part->common.parent) ||
   1236   6630  sk102515 				    ! sp_match(part, base_list))
   1237   6630  sk102515 					continue;
   1238   6630  sk102515 
   1239   6630  sk102515 				/* on the same base so print this soft part */
   1240   6630  sk102515 				print_concise_entry(0,
   1241   6630  sk102515 				    part->common.namep->cname,
   1242   6630  sk102515 				    part->common.size, 'p');
   1243   6630  sk102515 				(void) printf(" %s\n", part->compnamep->cname);
   1244   6630  sk102515 			}
   1245   6630  sk102515 
   1246   6630  sk102515 			/*
   1247   6630  sk102515 			 * print the common metadevice hierarchy
   1248   6630  sk102515 			 * under these soft parts
   1249   6630  sk102515 			 */
   1250   6630  sk102515 			print_concise_md(META_INDENT, sp, soft_part->compnamep);
   1251      0    stevel 		}
   1252      0    stevel 
   1253   6630  sk102515 		free_names(&nl);
   1254   6630  sk102515 		sp_free_list(base_list);
   1255      0    stevel 	}
   1256      0    stevel 	mdclrerror(&error);
   1257      0    stevel 
   1258      0    stevel 	if (meta_get_trans_names(sp, &nl, 0, &error) >= 0)
   1259   6630  sk102515 		print_concise_namelist(sp, &nl, 't');
   1260      0    stevel 	mdclrerror(&error);
   1261      0    stevel 
   1262      0    stevel 	if (meta_get_mirror_names(sp, &nl, 0, &error) >= 0)
   1263   6630  sk102515 		print_concise_namelist(sp, &nl, 'm');
   1264      0    stevel 	mdclrerror(&error);
   1265      0    stevel 
   1266      0    stevel 	if (meta_get_raid_names(sp, &nl, 0, &error) >= 0)
   1267   6630  sk102515 		print_concise_namelist(sp, &nl, 'r');
   1268      0    stevel 	mdclrerror(&error);
   1269      0    stevel 
   1270      0    stevel 	if (meta_get_stripe_names(sp, &nl, 0, &error) >= 0)
   1271   6630  sk102515 		print_concise_namelist(sp, &nl, 's');
   1272      0    stevel 	mdclrerror(&error);
   1273      0    stevel 
   1274      0    stevel 	if (meta_get_hsp_names(sp, &hsp_list, 0, &error) >= 0) {
   1275   6630  sk102515 		mdhspnamelist_t *nlp;
   1276      0    stevel 
   1277   6630  sk102515 	for (nlp = hsp_list; nlp != NULL; nlp = nlp->next) {
   1278      0    stevel 		md_hsp_t	*hsp;
   1279      0    stevel 
   1280      0    stevel 		print_concise_entry(0, nlp->hspnamep->hspname, 0, 'h');
   1281      0    stevel 
   1282      0    stevel 		hsp = meta_get_hsp_common(sp, nlp->hspnamep, 1, &error);
   1283      0    stevel 		mdclrerror(&error);
   1284      0    stevel 		if (hsp != NULL) {
   1285   6630  sk102515 			int	i;
   1286      0    stevel 
   1287   6630  sk102515 			for (i = 0; i < hsp->hotspares.hotspares_len; i++) {
   1288   6630  sk102515 				md_hs_t	*hs;
   1289   6630  sk102515 				char	*state;
   1290      0    stevel 
   1291   6630  sk102515 				hs = &hsp->hotspares.hotspares_val[i];
   1292      0    stevel 
   1293   6630  sk102515 				(void) printf(" %s", hs->hsnamep->cname);
   1294      0    stevel 
   1295   6630  sk102515 				state = get_hs_state(hs);
   1296   6630  sk102515 				if (state != NULL)
   1297   6630  sk102515 					(void) printf(" (%s)", state);
   1298   6630  sk102515 			}
   1299      0    stevel 		}
   1300      0    stevel 
   1301      0    stevel 		(void) printf("\n");
   1302   6630  sk102515 	}
   1303      0    stevel 
   1304   9818    Andrew 	mdclrerror(&error);
   1305   6630  sk102515 	metafreehspnamelist(hsp_list);
   1306      0    stevel 	}
   1307      0    stevel }
   1308      0    stevel 
   1309      0    stevel /*
   1310      0    stevel  * Print the top-level metadevices in the name list for concise output.
   1311      0    stevel  */
   1312      0    stevel static void
   1313      0    stevel print_concise_namelist(mdsetname_t *sp, mdnamelist_t **nl, char mtype)
   1314      0    stevel {
   1315      0    stevel 	mdnamelist_t	*nlp;
   1316      0    stevel 	md_error_t	error = mdnullerror;
   1317      0    stevel 
   1318      0    stevel 	for (nlp = *nl; nlp != NULL; nlp = nlp->next) {
   1319   6630  sk102515 		mdname_t	*mdn;
   1320   6630  sk102515 		md_common_t	*u;
   1321      0    stevel 
   1322   6630  sk102515 		mdn = metaname(&sp, nlp->namep->cname, META_DEVICE, &error);
   1323   6630  sk102515 		mdclrerror(&error);
   1324   6630  sk102515 		if (mdn == NULL) {
   1325   6630  sk102515 			print_concise_entry(0, nlp->namep->cname, 0, mtype);
   1326  11053     Surya 			(void) printf("\n");
   1327   6630  sk102515 			continue;
   1328   6630  sk102515 		}
   1329      0    stevel 
   1330   6630  sk102515 		u = get_concise_unit(sp, mdn, &error);
   1331   6630  sk102515 		mdclrerror(&error);
   1332      0    stevel 
   1333   6630  sk102515 		if (u != NULL && !MD_HAS_PARENT(u->parent))
   1334   6630  sk102515 			print_concise_md(0, sp, mdn);
   1335      0    stevel 	}
   1336      0    stevel 
   1337      0    stevel 	free_names(nl);
   1338      0    stevel }
   1339      0    stevel 
   1340      0    stevel /*
   1341      0    stevel  * Concise mirror output.
   1342      0    stevel  */
   1343      0    stevel static void
   1344      0    stevel print_concise_mirror(int indent, mdsetname_t *sp, md_mirror_t *mirror)
   1345      0    stevel {
   1346      0    stevel 	md_error_t	error = mdnullerror;
   1347      0    stevel 	int		i;
   1348      0    stevel 	md_status_t	status = mirror->common.state;
   1349      0    stevel 
   1350      0    stevel 	if (mirror == NULL)
   1351   6630  sk102515 		return;
   1352      0    stevel 
   1353      0    stevel 	print_concise_entry(indent, mirror->common.namep->cname,
   1354      0    stevel 	    mirror->common.size, 'm');
   1355      0    stevel 
   1356      0    stevel 	for (i = 0; i < NMIRROR; i++) {
   1357   6630  sk102515 		uint_t	tstate = 0;
   1358   6630  sk102515 		char	*state;
   1359      0    stevel 
   1360   6630  sk102515 		if (mirror->submirrors[i].submirnamep == NULL)
   1361   6630  sk102515 			continue;
   1362   6630  sk102515 		(void) printf(" %s", mirror->submirrors[i].submirnamep->cname);
   1363      0    stevel 
   1364   6630  sk102515 		if (mirror->submirrors[i].state & SMS_OFFLINE) {
   1365   6630  sk102515 			(void) printf(gettext(" (offline)"));
   1366   6630  sk102515 			continue;
   1367   6630  sk102515 		}
   1368      0    stevel 
   1369   6630  sk102515 		if (metaismeta(mirror->submirrors[i].submirnamep))
   1370   6630  sk102515 			(void) meta_get_tstate(
   1371   6630  sk102515 			    mirror->submirrors[i].submirnamep->dev,
   1372   6630  sk102515 			    &tstate, &error);
   1373      0    stevel 
   1374   9818    Andrew 		mdclrerror(&error);
   1375   6630  sk102515 		state = get_sm_state(mirror, i, status, tstate);
   1376   6630  sk102515 		if (state != NULL)
   1377   6630  sk102515 			(void) printf(" (%s)", state);
   1378      0    stevel 	}
   1379      0    stevel 
   1380      0    stevel 	(void) printf("\n");
   1381      0    stevel 
   1382    734  mw145384 	indent += META_INDENT;
   1383      0    stevel 	for (i = 0; i < NMIRROR; i++) {
   1384   6630  sk102515 		if (mirror->submirrors[i].submirnamep == NULL)
   1385   6630  sk102515 			continue;
   1386      0    stevel 
   1387   6630  sk102515 		print_concise_md(indent, sp, mirror->submirrors[i].submirnamep);
   1388      0    stevel 	}
   1389      0    stevel }
   1390      0    stevel 
   1391      0    stevel /*
   1392      0    stevel  * Concise raid output.
   1393      0    stevel  */
   1394      0    stevel static void
   1395      0    stevel print_concise_raid(int indent, mdsetname_t *sp, md_raid_t *raid)
   1396      0    stevel {
   1397      0    stevel 	md_error_t	error = mdnullerror;
   1398      0    stevel 	int		i;
   1399      0    stevel 	uint_t		tstate = 0;
   1400      0    stevel 
   1401      0    stevel 	if (raid == NULL)
   1402   6630  sk102515 		return;
   1403      0    stevel 
   1404      0    stevel 	print_concise_entry(indent, raid->common.namep->cname,
   1405      0    stevel 	    raid->common.size, 'r');
   1406      0    stevel 
   1407      0    stevel 	if (metaismeta(raid->common.namep))
   1408   6630  sk102515 		(void) meta_get_tstate(raid->common.namep->dev,
   1409   6630  sk102515 		    &tstate, &error);
   1410      0    stevel 
   1411      0    stevel 	for (i = 0; i < raid->cols.cols_len; i++) {
   1412   6630  sk102515 		md_raidcol_t	*colp = &raid->cols.cols_val[i];
   1413   6630  sk102515 		mdname_t	*namep = ((colp->hsnamep != NULL) ?
   1414   6630  sk102515 		    colp->hsnamep : colp->colnamep);
   1415   6630  sk102515 		char	*hsname = ((colp->hsnamep != NULL) ?
   1416   6630  sk102515 		    colp->hsnamep->cname : NULL);
   1417   6630  sk102515 		char	*col_state = NULL;
   1418      0    stevel 
   1419   6630  sk102515 		(void) printf(" %s", colp->colnamep->cname);
   1420      0    stevel 
   1421   6630  sk102515 		if (metaismeta(namep)) {
   1422   6630  sk102515 			uint_t tstate = 0;
   1423      0    stevel 
   1424   6630  sk102515 			(void) meta_get_tstate(namep->dev, &tstate, &error);
   1425   9818    Andrew 			mdclrerror(&error);
   1426   6630  sk102515 			col_state = get_raid_col_state(colp, tstate);
   1427      0    stevel 
   1428   6630  sk102515 		} else {
   1429   6630  sk102515 			if (tstate != 0)
   1430   6630  sk102515 				col_state = "-";
   1431   6630  sk102515 			else
   1432   6630  sk102515 				col_state = get_raid_col_state(colp, tstate);
   1433   6630  sk102515 		}
   1434      0    stevel 
   1435   6630  sk102515 		if (col_state != NULL) {
   1436   6630  sk102515 			if (hsname != NULL)
   1437   6630  sk102515 				(void) printf(" (%s-%s)", col_state, hsname);
   1438   6630  sk102515 			else
   1439   6630  sk102515 				(void) printf(" (%s)", col_state);
   1440      0    stevel 
   1441   6630  sk102515 		} else if (hsname != NULL) {
   1442   6630  sk102515 			(void) printf(gettext(" (spared-%s)"), hsname);
   1443   6630  sk102515 		}
   1444      0    stevel 	}
   1445      0    stevel 
   1446      0    stevel 	(void) printf("\n");
   1447      0    stevel 
   1448    734  mw145384 	indent += META_INDENT;
   1449      0    stevel 	for (i = 0; i < raid->cols.cols_len; i++) {
   1450   6630  sk102515 		print_concise_md(indent, sp, raid->cols.cols_val[i].colnamep);
   1451      0    stevel 	}
   1452      0    stevel }
   1453      0    stevel 
   1454      0    stevel /*
   1455      0    stevel  * Concise stripe output.
   1456      0    stevel  */
   1457      0    stevel static void
   1458      0    stevel print_concise_stripe(int indent, mdsetname_t *sp, md_stripe_t *stripe)
   1459      0    stevel {
   1460      0    stevel 	md_error_t	error = mdnullerror;
   1461      0    stevel 	int		i;
   1462      0    stevel 	uint_t		top_tstate = 0;
   1463      0    stevel 
   1464      0    stevel 	if (stripe == NULL)
   1465   6630  sk102515 		return;
   1466      0    stevel 
   1467      0    stevel 	print_concise_entry(indent, stripe->common.namep->cname,
   1468      0    stevel 	    stripe->common.size, 's');
   1469      0    stevel 
   1470      0    stevel 	if (metaismeta(stripe->common.namep))
   1471   6630  sk102515 		(void) meta_get_tstate(stripe->common.namep->dev, &top_tstate,
   1472   6630  sk102515 		    &error);
   1473      0    stevel 	mdclrerror(&error);
   1474      0    stevel 
   1475      0    stevel 	for (i = 0; i < stripe->rows.rows_len; i++) {
   1476   6630  sk102515 		md_row_t	*rowp;
   1477   6630  sk102515 		int		j;
   1478      0    stevel 
   1479   6630  sk102515 		rowp = &stripe->rows.rows_val[i];
   1480      0    stevel 
   1481   6630  sk102515 		for (j = 0; j < rowp->comps.comps_len; j++) {
   1482   6630  sk102515 			md_comp_t	*comp;
   1483   6630  sk102515 			uint_t		tstate = 0;
   1484   6630  sk102515 			char		*comp_state = NULL;
   1485   6630  sk102515 			char		*hsname;
   1486      0    stevel 
   1487   6630  sk102515 			comp = &rowp->comps.comps_val[j];
   1488   6630  sk102515 			(void) printf(" %s", comp->compnamep->cname);
   1489      0    stevel 
   1490   6630  sk102515 			if (metaismeta(comp->compnamep)) {
   1491   6630  sk102515 				uint_t tstate = 0;
   1492   6630  sk102515 				(void) meta_get_tstate(comp->compnamep->dev,
   1493   6630  sk102515 				    &tstate, &error);
   1494   9818    Andrew 				mdclrerror(&error);
   1495   6630  sk102515 				comp_state = get_stripe_state(comp, tstate);
   1496   6630  sk102515 			} else {
   1497   6630  sk102515 			if (top_tstate != 0)
   1498   6630  sk102515 				comp_state = "-";
   1499   6630  sk102515 			else
   1500   6630  sk102515 				comp_state = get_stripe_state(comp, tstate);
   1501   6630  sk102515 			}
   1502   6630  sk102515 
   1503   6630  sk102515 			hsname = ((comp->hsnamep != NULL) ?
   1504   6630  sk102515 			    comp->hsnamep->cname : NULL);
   1505   6630  sk102515 
   1506   6630  sk102515 			if (comp_state != NULL) {
   1507   6630  sk102515 				if (hsname != NULL)
   1508   6630  sk102515 					(void) printf(" (%s-%s)",
   1509   6630  sk102515 					    comp_state, hsname);
   1510   6630  sk102515 				else
   1511   6630  sk102515 					(void) printf(" (%s)", comp_state);
   1512   6630  sk102515 
   1513   6630  sk102515 			} else if (hsname != NULL) {
   1514   6630  sk102515 				(void) printf(gettext(" (spared-%s)"), hsname);
   1515   6630  sk102515 			}
   1516      0    stevel 		}
   1517      0    stevel 	}
   1518      0    stevel 
   1519      0    stevel 	(void) printf("\n");
   1520      0    stevel 
   1521    734  mw145384 	indent += META_INDENT;
   1522      0    stevel 	for (i = 0; i < stripe->rows.rows_len; i++) {
   1523   6630  sk102515 		md_row_t	*rowp;
   1524   6630  sk102515 		int		j;
   1525      0    stevel 
   1526   6630  sk102515 		rowp = &stripe->rows.rows_val[i];
   1527      0    stevel 
   1528   6630  sk102515 		for (j = 0; j < rowp->comps.comps_len; j++) {
   1529   6630  sk102515 			print_concise_md(indent, sp,
   1530   6630  sk102515 			    rowp->comps.comps_val[j].compnamep);
   1531   6630  sk102515 		}
   1532      0    stevel 	}
   1533      0    stevel }
   1534      0    stevel 
   1535      0    stevel /*
   1536      0    stevel  * Concise soft partition output.
   1537      0    stevel  */
   1538      0    stevel static void
   1539      0    stevel print_concise_sp(int indent, mdsetname_t *sp, md_sp_t *part)
   1540      0    stevel {
   1541      0    stevel 	if (part == NULL)
   1542   6630  sk102515 	return;
   1543      0    stevel 
   1544      0    stevel 	print_concise_entry(indent, part->common.namep->cname,
   1545      0    stevel 	    part->common.size, 'p');
   1546      0    stevel 
   1547      0    stevel 	(void) printf(" %s\n", part->compnamep->cname);
   1548      0    stevel 
   1549    734  mw145384 	print_concise_md(indent + META_INDENT, sp, part->compnamep);
   1550      0    stevel }
   1551      0    stevel 
   1552      0    stevel /*
   1553      0    stevel  * Concise trans output.
   1554      0    stevel  */
   1555      0    stevel static void
   1556      0    stevel print_concise_trans(int indent, mdsetname_t *sp, md_trans_t *trans)
   1557      0    stevel {
   1558      0    stevel 	if (trans == NULL)
   1559   6630  sk102515 		return;
   1560      0    stevel 
   1561      0    stevel 	print_concise_entry(indent, trans->common.namep->cname,
   1562      0    stevel 	    trans->common.size, 't');
   1563      0    stevel 
   1564      0    stevel 	if (trans->masternamep != NULL)
   1565   6630  sk102515 		(void) printf(" %s", trans->masternamep->cname);
   1566      0    stevel 
   1567      0    stevel 	if (trans->lognamep != NULL)
   1568   6630  sk102515 		(void) printf(" %s", trans->lognamep->cname);
   1569      0    stevel 
   1570      0    stevel 	(void) printf("\n");
   1571      0    stevel 
   1572    734  mw145384 	indent += META_INDENT;
   1573      0    stevel 
   1574      0    stevel 	print_concise_md(indent, sp, trans->masternamep);
   1575      0    stevel 
   1576      0    stevel 	print_concise_md(indent, sp, trans->lognamep);
   1577      0    stevel }
   1578      0    stevel 
   1579      0    stevel /*
   1580      0    stevel  * Recursive function for concise metadevice nested output.
   1581      0    stevel  */
   1582      0    stevel static void
   1583      0    stevel print_concise_md(int indent, mdsetname_t *sp, mdname_t *np)
   1584      0    stevel {
   1585      0    stevel 	md_error_t	error = mdnullerror;
   1586      0    stevel 	md_unit_t	*u;
   1587      0    stevel 	md_mirror_t	*mirror;
   1588      0    stevel 	md_raid_t	*raid;
   1589      0    stevel 	md_sp_t		*soft_part;
   1590      0    stevel 	md_stripe_t	*stripe;
   1591      0    stevel 	md_trans_t	*trans;
   1592      0    stevel 
   1593      0    stevel 	if (np == NULL || !metaismeta(np))
   1594   6630  sk102515 		return;
   1595      0    stevel 
   1596   9818    Andrew 	if ((u = meta_get_mdunit(sp, np, &error)) == NULL) {
   1597   9818    Andrew 		mdclrerror(&error);
   1598   6630  sk102515 		return;
   1599   9818    Andrew 	}
   1600      0    stevel 
   1601      0    stevel 	switch (u->c.un_type) {
   1602   6630  sk102515 		case MD_DEVICE:
   1603   6630  sk102515 			stripe = meta_get_stripe_common(sp, np, 1, &error);
   1604   6630  sk102515 			print_concise_stripe(indent, sp, stripe);
   1605   6630  sk102515 			break;
   1606      0    stevel 
   1607   6630  sk102515 		case MD_METAMIRROR:
   1608   6630  sk102515 			mirror = meta_get_mirror(sp, np, &error);
   1609   6630  sk102515 			print_concise_mirror(indent, sp, mirror);
   1610   6630  sk102515 			break;
   1611      0    stevel 
   1612   6630  sk102515 		case MD_METATRANS:
   1613   6630  sk102515 			trans = meta_get_trans_common(sp, np, 1, &error);
   1614   6630  sk102515 			print_concise_trans(indent, sp, trans);
   1615   6630  sk102515 			break;
   1616      0    stevel 
   1617   6630  sk102515 		case MD_METARAID:
   1618   6630  sk102515 			raid = meta_get_raid_common(sp, np, 1, &error);
   1619   6630  sk102515 			print_concise_raid(indent, sp, raid);
   1620   6630  sk102515 			break;
   1621      0    stevel 
   1622   6630  sk102515 		case MD_METASP:
   1623   6630  sk102515 			soft_part = meta_get_sp_common(sp, np, 1, &error);
   1624   6630  sk102515 			print_concise_sp(indent, sp, soft_part);
   1625   6630  sk102515 			break;
   1626      0    stevel 
   1627   6630  sk102515 		default:
   1628   6630  sk102515 			return;
   1629      0    stevel 	}
   1630   9818    Andrew 	mdclrerror(&error);
   1631      0    stevel }
   1632      0    stevel 
   1633      0    stevel /*
   1634      0    stevel  * Given a name get the unit for use in concise output.  We use the *_common
   1635      0    stevel  * routines in libmeta which allow us to specify the "fast" flag, thereby
   1636      0    stevel  * avoiding the DKIOCGGEOM ioctl that normally happens.
   1637      0    stevel  */
   1638      0    stevel static md_common_t *
   1639      0    stevel get_concise_unit(mdsetname_t *sp, mdname_t *np, md_error_t *ep)
   1640      0    stevel {
   1641      0    stevel 	char		*miscname;
   1642      0    stevel 
   1643      0    stevel 	/* short circuit */
   1644      0    stevel 	if (np->drivenamep->unitp != NULL)
   1645      0    stevel 		return (np->drivenamep->unitp);
   1646      0    stevel 	if (metachkmeta(np, ep) != 0)
   1647      0    stevel 		return (NULL);
   1648      0    stevel 
   1649      0    stevel 	/* dispatch */
   1650      0    stevel 	if ((miscname = metagetmiscname(np, ep)) == NULL)
   1651      0    stevel 		return (NULL);
   1652      0    stevel 	else if (strcmp(miscname, MD_STRIPE) == 0)
   1653      0    stevel 		return ((md_common_t *)meta_get_stripe_common(sp, np, 1, ep));
   1654      0    stevel 	else if (strcmp(miscname, MD_MIRROR) == 0)
   1655      0    stevel 		return ((md_common_t *)meta_get_mirror(sp, np, ep));
   1656      0    stevel 	else if (strcmp(miscname, MD_TRANS) == 0)
   1657      0    stevel 		return ((md_common_t *)meta_get_trans_common(sp, np, 1, ep));
   1658      0    stevel 	else if (strcmp(miscname, MD_RAID) == 0)
   1659      0    stevel 		return ((md_common_t *)meta_get_raid_common(sp, np, 1, ep));
   1660      0    stevel 	else if (strcmp(miscname, MD_SP) == 0)
   1661      0    stevel 		return ((md_common_t *)meta_get_sp_common(sp, np, 1, ep));
   1662      0    stevel 	else {
   1663      0    stevel 		(void) mdmderror(ep, MDE_UNKNOWN_TYPE, meta_getminor(np->dev),
   1664      0    stevel 		    np->cname);
   1665      0    stevel 		return (NULL);
   1666      0    stevel 	}
   1667      0    stevel }
   1668      0    stevel 
   1669      0    stevel static void
   1670      0    stevel free_names(mdnamelist_t **nlp)
   1671      0    stevel {
   1672      0    stevel 	mdnamelist_t *p;
   1673      0    stevel 
   1674      0    stevel 	for (p = *nlp; p != NULL; p = p->next) {
   1675   6630  sk102515 		meta_invalidate_name(p->namep);
   1676   6630  sk102515 		p->namep = NULL;
   1677      0    stevel 	}
   1678      0    stevel 	metafreenamelist(*nlp);
   1679      0    stevel 	*nlp = NULL;
   1680      0    stevel }
   1681      0    stevel 
   1682      0    stevel /*
   1683      0    stevel  * Submirror state for concise output.
   1684      0    stevel  */
   1685      0    stevel static char *
   1686      0    stevel get_sm_state(md_mirror_t *mirror, int i, md_status_t mirror_status,
   1687      0    stevel 	uint_t tstate)
   1688      0    stevel {
   1689      0    stevel 	sm_state_t	state = mirror->submirrors[i].state;
   1690   6630  sk102515 	uint_t	is_target =
   1691   6630  sk102515 	    mirror->submirrors[i].flags & MD_SM_RESYNC_TARGET;
   1692      0    stevel 
   1693      0    stevel 	/*
   1694      0    stevel 	 * Only return Unavailable if there is no flagged error on the
   1695      0    stevel 	 * submirror. If the mirror has received any writes since the submirror
   1696      0    stevel 	 * went into Unavailable state a resync is required. To alert the
   1697      0    stevel 	 * administrator to this we return a 'Needs maintenance' message.
   1698      0    stevel 	 */
   1699      0    stevel 	if ((tstate != 0) && (state & SMS_RUNNING))
   1700      0    stevel 		return (gettext("unavail"));
   1701      0    stevel 
   1702      0    stevel 	/* all is well */
   1703      0    stevel 	if (state & SMS_RUNNING) {
   1704      0    stevel 		if (!(mirror_status & MD_UN_OPT_NOT_DONE) ||
   1705      0    stevel 		    ((mirror_status & MD_UN_OPT_NOT_DONE) && !is_target))
   1706      0    stevel 			return (NULL);
   1707      0    stevel 	}
   1708      0    stevel 
   1709      0    stevel 	/* resyncing, needs repair */
   1710      0    stevel 	if ((state & (SMS_COMP_RESYNC | SMS_ATTACHED_RESYNC |
   1711      0    stevel 	    SMS_OFFLINE_RESYNC)) || (mirror_status & MD_UN_OPT_NOT_DONE)) {
   1712      0    stevel 		static char buf[MAXPATHLEN];
   1713      0    stevel 
   1714      0    stevel 		if (mirror_status & MD_UN_RESYNC_ACTIVE) {
   1715      0    stevel 
   1716   6630  sk102515 			if (mirror->common.revision & MD_64BIT_META_DEV) {
   1717   6630  sk102515 				(void) snprintf(buf, sizeof (buf),
   1718   6630  sk102515 				    gettext("resync-%2d.%1d%%"),
   1719   6630  sk102515 				    mirror->percent_done / 10,
   1720   6630  sk102515 				    mirror->percent_done % 10);
   1721   6630  sk102515 			} else {
   1722   6630  sk102515 				(void) snprintf(buf, sizeof (buf),
   1723   6630  sk102515 				gettext("resync-%d%%"), mirror->percent_done);
   1724   6630  sk102515 			}
   1725   6630  sk102515 			return (buf);
   1726      0    stevel 		}
   1727      0    stevel 		return (gettext("maint"));
   1728      0    stevel 	}
   1729      0    stevel 
   1730      0    stevel 	/* needs repair */
   1731      0    stevel 	if (state & (SMS_COMP_ERRED | SMS_ATTACHED | SMS_OFFLINE))
   1732      0    stevel 		return (gettext("maint"));
   1733      0    stevel 
   1734      0    stevel 	/* unknown */
   1735      0    stevel 	return (gettext("unknown"));
   1736      0    stevel }
   1737      0    stevel 
   1738      0    stevel /*
   1739      0    stevel  * Raid component state for concise output.
   1740      0    stevel  */
   1741      0    stevel static char *
   1742      0    stevel get_raid_col_state(md_raidcol_t *colp, uint_t tstate)
   1743      0    stevel {
   1744      0    stevel 	if (tstate != 0)
   1745   6630  sk102515 		return (gettext("unavail"));
   1746      0    stevel 
   1747    734  mw145384 	return (meta_get_raid_col_state(colp->state));
   1748      0    stevel }
   1749      0    stevel 
   1750      0    stevel /*
   1751      0    stevel  * Stripe state for concise output.
   1752      0    stevel  */
   1753      0    stevel static char *
   1754      0    stevel get_stripe_state(md_comp_t *mdcp, uint_t tstate)
   1755      0    stevel {
   1756      0    stevel 	comp_state_t	state = mdcp->state;
   1757      0    stevel 
   1758      0    stevel 	if (tstate != 0)
   1759   6630  sk102515 		return ("unavail");
   1760      0    stevel 
   1761    734  mw145384 	return (meta_get_stripe_state(state));
   1762      0    stevel }
   1763      0    stevel 
   1764      0    stevel /*
   1765      0    stevel  * Hostspare state for concise output.
   1766      0    stevel  */
   1767      0    stevel static char *
   1768      0    stevel get_hs_state(md_hs_t *hsp)
   1769      0    stevel {
   1770      0    stevel 	hotspare_states_t	state = hsp->state;
   1771      0    stevel 
   1772    734  mw145384 	return (meta_get_hs_state(state));
   1773      0    stevel }
   1774      0    stevel 
   1775      0    stevel 
   1776      0    stevel /*
   1777      0    stevel  * Keep track of printed soft partitions for concise output.
   1778      0    stevel  */
   1779      0    stevel static struct sp_base_list *
   1780      0    stevel sp_add_done(md_sp_t *part, struct sp_base_list *lp)
   1781      0    stevel {
   1782      0    stevel 	struct sp_base_list *n;
   1783      0    stevel 
   1784      0    stevel 	n = (struct sp_base_list *)malloc(sizeof (struct sp_base_list));
   1785      0    stevel 	if (n == NULL)
   1786   6630  sk102515 		return (lp);
   1787      0    stevel 
   1788      0    stevel 	if ((n->base = strdup(part->compnamep->cname)) == NULL) {
   1789   6630  sk102515 		free(n);
   1790   6630  sk102515 		return (lp);
   1791      0    stevel 	}
   1792      0    stevel 
   1793      0    stevel 	n->next = lp;
   1794      0    stevel 
   1795      0    stevel 	return (n);
   1796      0    stevel }
   1797      0    stevel 
   1798      0    stevel /*
   1799      0    stevel  * Keep track of printed soft partitions for concise output.
   1800      0    stevel  */
   1801      0    stevel static int
   1802      0    stevel sp_done(md_sp_t *part, struct sp_base_list *lp)
   1803      0    stevel {
   1804      0    stevel 	for (; lp != NULL; lp = lp->next) {
   1805   6630  sk102515 		if (strcmp(lp->base, part->compnamep->cname) == 0)
   1806   6630  sk102515 			return (1);
   1807      0    stevel 	}
   1808      0    stevel 
   1809      0    stevel 	return (0);
   1810      0    stevel }
   1811      0    stevel 
   1812      0    stevel /*
   1813      0    stevel  * Check the first element for a match.
   1814      0    stevel  */
   1815      0    stevel static int
   1816      0    stevel sp_match(md_sp_t *part, struct sp_base_list *lp)
   1817      0    stevel {
   1818      0    stevel 	if (lp != NULL && strcmp(lp->base, part->compnamep->cname) == 0)
   1819   6630  sk102515 		return (1);
   1820      0    stevel 
   1821      0    stevel 	return (0);
   1822      0    stevel }
   1823      0    stevel 
   1824      0    stevel /*
   1825      0    stevel  * Free memory used for soft partition printed status in concise output.
   1826      0    stevel  */
   1827      0    stevel static void
   1828      0    stevel sp_free_list(struct sp_base_list *lp)
   1829      0    stevel {
   1830      0    stevel 	struct sp_base_list *n;
   1831      0    stevel 
   1832      0    stevel 	for (; lp != NULL; lp = n) {
   1833   6630  sk102515 		n = lp->next;
   1834   6630  sk102515 		free(lp->base);
   1835   6630  sk102515 		free(lp);
   1836      0    stevel 	}
   1837      0    stevel }
   1838