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
51623Stw21770 * Common Development and Distribution License (the "License").
61623Stw21770 * 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
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
227087Ssk102515 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that
280Sstevel@tonic-gate * TEXT_DOMAIN gets set to something.
290Sstevel@tonic-gate */
300Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
310Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
320Sstevel@tonic-gate #endif
330Sstevel@tonic-gate
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate * RAID operations
360Sstevel@tonic-gate */
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include <stdlib.h>
390Sstevel@tonic-gate #include <meta.h>
400Sstevel@tonic-gate #include <sys/lvm/md_raid.h>
410Sstevel@tonic-gate #include <sys/lvm/mdvar.h>
420Sstevel@tonic-gate #include <sys/lvm/md_convert.h>
430Sstevel@tonic-gate #include <stddef.h>
440Sstevel@tonic-gate
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate * FUNCTION: meta_get_raid_names()
470Sstevel@tonic-gate * INPUT: sp - the set name to get raid from
480Sstevel@tonic-gate * options - options from the command line
490Sstevel@tonic-gate * OUTPUT: nlpp - list of all raid names
500Sstevel@tonic-gate * ep - return error pointer
510Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 success
520Sstevel@tonic-gate * PURPOSE: returns a list of all raid in the metadb
530Sstevel@tonic-gate * for all devices in the specified set
540Sstevel@tonic-gate */
550Sstevel@tonic-gate int
meta_get_raid_names(mdsetname_t * sp,mdnamelist_t ** nlpp,int options,md_error_t * ep)560Sstevel@tonic-gate meta_get_raid_names(
570Sstevel@tonic-gate mdsetname_t *sp,
580Sstevel@tonic-gate mdnamelist_t **nlpp,
590Sstevel@tonic-gate int options,
600Sstevel@tonic-gate md_error_t *ep
610Sstevel@tonic-gate )
620Sstevel@tonic-gate {
630Sstevel@tonic-gate return (meta_get_names(MD_RAID, sp, nlpp, options, ep));
640Sstevel@tonic-gate }
650Sstevel@tonic-gate
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate * free raid unit
680Sstevel@tonic-gate */
690Sstevel@tonic-gate void
meta_free_raid(md_raid_t * raidp)700Sstevel@tonic-gate meta_free_raid(
710Sstevel@tonic-gate md_raid_t *raidp
720Sstevel@tonic-gate )
730Sstevel@tonic-gate {
740Sstevel@tonic-gate if (raidp->cols.cols_val != NULL) {
750Sstevel@tonic-gate assert(raidp->cols.cols_len > 0);
760Sstevel@tonic-gate Free(raidp->cols.cols_val);
770Sstevel@tonic-gate }
780Sstevel@tonic-gate Free(raidp);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate
810Sstevel@tonic-gate /*
820Sstevel@tonic-gate * get raid (common)
830Sstevel@tonic-gate */
840Sstevel@tonic-gate md_raid_t *
meta_get_raid_common(mdsetname_t * sp,mdname_t * raidnp,int fast,md_error_t * ep)850Sstevel@tonic-gate meta_get_raid_common(
860Sstevel@tonic-gate mdsetname_t *sp,
870Sstevel@tonic-gate mdname_t *raidnp,
880Sstevel@tonic-gate int fast,
890Sstevel@tonic-gate md_error_t *ep
900Sstevel@tonic-gate )
910Sstevel@tonic-gate {
920Sstevel@tonic-gate mddrivename_t *dnp = raidnp->drivenamep;
930Sstevel@tonic-gate char *miscname;
940Sstevel@tonic-gate mr_unit_t *mr;
950Sstevel@tonic-gate md_raid_t *raidp;
960Sstevel@tonic-gate uint_t ncol;
970Sstevel@tonic-gate uint_t col;
980Sstevel@tonic-gate md_resync_ioctl_t ri;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /* must have set */
1010Sstevel@tonic-gate assert(sp != NULL);
1020Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate /* short circuit */
1050Sstevel@tonic-gate if (dnp->unitp != NULL) {
1060Sstevel@tonic-gate assert(dnp->unitp->type == MD_METARAID);
1070Sstevel@tonic-gate return ((md_raid_t *)dnp->unitp);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate /* get miscname and unit */
1110Sstevel@tonic-gate if ((miscname = metagetmiscname(raidnp, ep)) == NULL)
1120Sstevel@tonic-gate return (NULL);
1130Sstevel@tonic-gate if (strcmp(miscname, MD_RAID) != 0) {
1140Sstevel@tonic-gate (void) mdmderror(ep, MDE_NOT_RAID, meta_getminor(raidnp->dev),
1150Sstevel@tonic-gate raidnp->cname);
1160Sstevel@tonic-gate return (NULL);
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
1190Sstevel@tonic-gate return (NULL);
1200Sstevel@tonic-gate assert(mr->c.un_type == MD_METARAID);
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate /* allocate raid */
1230Sstevel@tonic-gate raidp = Zalloc(sizeof (*raidp));
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /* allocate columns */
1260Sstevel@tonic-gate ncol = mr->un_totalcolumncnt;
1270Sstevel@tonic-gate assert(ncol >= MD_RAID_MIN);
1280Sstevel@tonic-gate raidp->cols.cols_len = ncol;
1290Sstevel@tonic-gate raidp->cols.cols_val = Zalloc(raidp->cols.cols_len *
1300Sstevel@tonic-gate sizeof (*raidp->cols.cols_val));
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /* get common info */
1330Sstevel@tonic-gate raidp->common.namep = raidnp;
1340Sstevel@tonic-gate raidp->common.type = mr->c.un_type;
1350Sstevel@tonic-gate raidp->common.state = mr->c.un_status;
1360Sstevel@tonic-gate raidp->common.capabilities = mr->c.un_capabilities;
1370Sstevel@tonic-gate raidp->common.parent = mr->c.un_parent;
1380Sstevel@tonic-gate raidp->common.size = mr->c.un_total_blocks;
1390Sstevel@tonic-gate raidp->common.user_flags = mr->c.un_user_flags;
1400Sstevel@tonic-gate raidp->common.revision = mr->c.un_revision;
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate /* get options */
1430Sstevel@tonic-gate raidp->state = mr->un_state;
1440Sstevel@tonic-gate raidp->timestamp = mr->un_timestamp;
1450Sstevel@tonic-gate raidp->interlace = mr->un_segsize;
1460Sstevel@tonic-gate raidp->orig_ncol = mr->un_origcolumncnt;
1470Sstevel@tonic-gate raidp->column_size = mr->un_segsize * mr->un_segsincolumn;
1480Sstevel@tonic-gate raidp->pw_count = mr->un_pwcnt;
1490Sstevel@tonic-gate assert(raidp->orig_ncol <= ncol);
1500Sstevel@tonic-gate if ((mr->un_hsp_id != MD_HSP_NONE) &&
1510Sstevel@tonic-gate ((raidp->hspnamep = metahsphspname(&sp, mr->un_hsp_id,
1520Sstevel@tonic-gate ep)) == NULL)) {
1530Sstevel@tonic-gate goto out;
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate /* get columns, update unit state */
1570Sstevel@tonic-gate for (col = 0; (col < ncol); ++col) {
1580Sstevel@tonic-gate mr_column_t *rcp = &mr->un_column[col];
1590Sstevel@tonic-gate md_raidcol_t *mdrcp = &raidp->cols.cols_val[col];
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate /* get column name */
1620Sstevel@tonic-gate mdrcp->colnamep = metakeyname(&sp, rcp->un_orig_key, fast, ep);
1630Sstevel@tonic-gate if (mdrcp->colnamep == NULL)
1640Sstevel@tonic-gate goto out;
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate /* override any start_blk */
1670Sstevel@tonic-gate #ifdef DEBUG
1680Sstevel@tonic-gate if (metagetstart(sp, mdrcp->colnamep, ep) !=
1690Sstevel@tonic-gate MD_DISKADDR_ERROR) {
1700Sstevel@tonic-gate assert(mdrcp->colnamep->start_blk <=
1710Sstevel@tonic-gate rcp->un_orig_devstart);
1720Sstevel@tonic-gate } else {
1730Sstevel@tonic-gate mdclrerror(ep);
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate #endif /* DEBUG */
1760Sstevel@tonic-gate mdrcp->colnamep->start_blk = rcp->un_orig_devstart;
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate /* if hotspared */
1790Sstevel@tonic-gate if (HOTSPARED(mr, col)) {
1800Sstevel@tonic-gate /* get hotspare name */
1810Sstevel@tonic-gate mdrcp->hsnamep = metakeyname(&sp, rcp->un_hs_key,
1820Sstevel@tonic-gate fast, ep);
1830Sstevel@tonic-gate if (mdrcp->hsnamep == NULL)
1840Sstevel@tonic-gate goto out;
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate if (getenv("META_DEBUG_START_BLK") != NULL) {
1870Sstevel@tonic-gate if (metagetstart(sp, mdrcp->hsnamep, ep) ==
1880Sstevel@tonic-gate MD_DISKADDR_ERROR)
1890Sstevel@tonic-gate mdclrerror(ep);
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate if ((mdrcp->hsnamep->start_blk == 0) &&
1920Sstevel@tonic-gate (rcp->un_hs_pwstart != 0))
1930Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN,
1940Sstevel@tonic-gate "%s: suspected bad start block,"
1950Sstevel@tonic-gate " seems labelled [raid]\n"),
1960Sstevel@tonic-gate mdrcp->hsnamep->cname);
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate if ((mdrcp->hsnamep->start_blk > 0) &&
1990Sstevel@tonic-gate (rcp->un_hs_pwstart == 0))
2000Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN,
2010Sstevel@tonic-gate "%s: suspected bad start block, "
2020Sstevel@tonic-gate " seems unlabelled [raid]\n"),
2030Sstevel@tonic-gate mdrcp->hsnamep->cname);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate /* override any start_blk */
2070Sstevel@tonic-gate mdrcp->hsnamep->start_blk = rcp->un_hs_devstart;
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate /* get state, flags, and timestamp */
2110Sstevel@tonic-gate mdrcp->state = rcp->un_devstate;
2120Sstevel@tonic-gate mdrcp->flags = rcp->un_devflags;
2130Sstevel@tonic-gate mdrcp->timestamp = rcp->un_devtimestamp;
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate /* get resync info */
2170Sstevel@tonic-gate (void) memset(&ri, 0, sizeof (ri));
2180Sstevel@tonic-gate ri.ri_mnum = meta_getminor(raidnp->dev);
2190Sstevel@tonic-gate MD_SETDRIVERNAME(&ri, MD_RAID, sp->setno);
2200Sstevel@tonic-gate if (metaioctl(MD_IOCGETSYNC, &ri, &ri.mde, raidnp->cname) != 0) {
2210Sstevel@tonic-gate (void) mdstealerror(ep, &ri.mde);
2220Sstevel@tonic-gate goto out;
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate raidp->resync_flags = ri.ri_flags;
2250Sstevel@tonic-gate raidp->percent_dirty = ri.ri_percent_dirty;
2260Sstevel@tonic-gate raidp->percent_done = ri.ri_percent_done;
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate /* cleanup, return success */
2290Sstevel@tonic-gate Free(mr);
2300Sstevel@tonic-gate dnp->unitp = (md_common_t *)raidp;
2310Sstevel@tonic-gate return (raidp);
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /* cleanup, return error */
2340Sstevel@tonic-gate out:
2350Sstevel@tonic-gate Free(mr);
2360Sstevel@tonic-gate meta_free_raid(raidp);
2370Sstevel@tonic-gate return (NULL);
2380Sstevel@tonic-gate }
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate /*
2410Sstevel@tonic-gate * get raid
2420Sstevel@tonic-gate */
2430Sstevel@tonic-gate md_raid_t *
meta_get_raid(mdsetname_t * sp,mdname_t * raidnp,md_error_t * ep)2440Sstevel@tonic-gate meta_get_raid(
2450Sstevel@tonic-gate mdsetname_t *sp,
2460Sstevel@tonic-gate mdname_t *raidnp,
2470Sstevel@tonic-gate md_error_t *ep
2480Sstevel@tonic-gate )
2490Sstevel@tonic-gate {
2500Sstevel@tonic-gate return (meta_get_raid_common(sp, raidnp, 0, ep));
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate /*
2540Sstevel@tonic-gate * check raid for dev
2550Sstevel@tonic-gate */
2560Sstevel@tonic-gate static int
in_raid(mdsetname_t * sp,mdname_t * raidnp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)2570Sstevel@tonic-gate in_raid(
2580Sstevel@tonic-gate mdsetname_t *sp,
2590Sstevel@tonic-gate mdname_t *raidnp,
2600Sstevel@tonic-gate mdname_t *np,
2610Sstevel@tonic-gate diskaddr_t slblk,
2620Sstevel@tonic-gate diskaddr_t nblks,
2630Sstevel@tonic-gate md_error_t *ep
2640Sstevel@tonic-gate )
2650Sstevel@tonic-gate {
2660Sstevel@tonic-gate md_raid_t *raidp;
2670Sstevel@tonic-gate uint_t col;
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate /* should be in the same set */
2700Sstevel@tonic-gate assert(sp != NULL);
2710Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate /* get unit */
2740Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL)
2750Sstevel@tonic-gate return (-1);
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate /* look in columns */
2780Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) {
2790Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
2800Sstevel@tonic-gate mdname_t *colnp = cp->colnamep;
2810Sstevel@tonic-gate diskaddr_t col_sblk;
2820Sstevel@tonic-gate int err;
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate /* check same drive since metagetstart() can fail */
2850Sstevel@tonic-gate if ((err = meta_check_samedrive(np, colnp, ep)) < 0)
2860Sstevel@tonic-gate return (-1);
2870Sstevel@tonic-gate else if (err == 0)
2880Sstevel@tonic-gate continue;
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate /* check overlap */
2910Sstevel@tonic-gate if ((col_sblk = metagetstart(sp, colnp, ep)) ==
2920Sstevel@tonic-gate MD_DISKADDR_ERROR)
2930Sstevel@tonic-gate return (-1);
2940Sstevel@tonic-gate if (meta_check_overlap(raidnp->cname, np, slblk, nblks,
2950Sstevel@tonic-gate colnp, col_sblk, -1, ep) != 0) {
2960Sstevel@tonic-gate return (-1);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /* return success */
3010Sstevel@tonic-gate return (0);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate /*
3050Sstevel@tonic-gate * check to see if we're in a raid
3060Sstevel@tonic-gate */
3070Sstevel@tonic-gate int
meta_check_inraid(mdsetname_t * sp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)3080Sstevel@tonic-gate meta_check_inraid(
3090Sstevel@tonic-gate mdsetname_t *sp,
3100Sstevel@tonic-gate mdname_t *np,
3110Sstevel@tonic-gate diskaddr_t slblk,
3120Sstevel@tonic-gate diskaddr_t nblks,
3130Sstevel@tonic-gate md_error_t *ep
3140Sstevel@tonic-gate )
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate mdnamelist_t *raidnlp = NULL;
3170Sstevel@tonic-gate mdnamelist_t *p;
3180Sstevel@tonic-gate int rval = 0;
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate /* should have a set */
3210Sstevel@tonic-gate assert(sp != NULL);
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate /* for each raid */
3240Sstevel@tonic-gate if (meta_get_raid_names(sp, &raidnlp, 0, ep) < 0)
3250Sstevel@tonic-gate return (-1);
3260Sstevel@tonic-gate for (p = raidnlp; (p != NULL); p = p->next) {
3270Sstevel@tonic-gate mdname_t *raidnp = p->namep;
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate /* check raid */
3300Sstevel@tonic-gate if (in_raid(sp, raidnp, np, slblk, nblks, ep) != 0) {
3310Sstevel@tonic-gate rval = -1;
3320Sstevel@tonic-gate break;
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate /* cleanup, return success */
3370Sstevel@tonic-gate metafreenamelist(raidnlp);
3380Sstevel@tonic-gate return (rval);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate /*
3420Sstevel@tonic-gate * check column
3430Sstevel@tonic-gate */
3440Sstevel@tonic-gate int
meta_check_column(mdsetname_t * sp,mdname_t * np,md_error_t * ep)3450Sstevel@tonic-gate meta_check_column(
3460Sstevel@tonic-gate mdsetname_t *sp,
3470Sstevel@tonic-gate mdname_t *np,
3480Sstevel@tonic-gate md_error_t *ep
3490Sstevel@tonic-gate )
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate mdchkopts_t options = (MDCHK_ALLOW_MDDB);
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate /* check for soft partitions */
3540Sstevel@tonic-gate if (meta_sp_issp(sp, np, ep) != 0) {
3550Sstevel@tonic-gate /* make sure we have a disk */
3560Sstevel@tonic-gate if (metachkcomp(np, ep) != 0)
3570Sstevel@tonic-gate return (-1);
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate /* check to ensure that it is not already in use */
3610Sstevel@tonic-gate if (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0) {
3620Sstevel@tonic-gate return (-1);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate /* make sure it is in the set */
3660Sstevel@tonic-gate if (meta_check_inset(sp, np, ep) != 0)
3670Sstevel@tonic-gate return (-1);
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate /* make sure its not in a metadevice */
3700Sstevel@tonic-gate if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0)
3710Sstevel@tonic-gate return (-1);
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate /* return success */
3740Sstevel@tonic-gate return (0);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate /*
3780Sstevel@tonic-gate * print raid
3790Sstevel@tonic-gate */
3800Sstevel@tonic-gate static int
raid_print(md_raid_t * raidp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)3810Sstevel@tonic-gate raid_print(
3820Sstevel@tonic-gate md_raid_t *raidp,
3830Sstevel@tonic-gate char *fname,
3840Sstevel@tonic-gate FILE *fp,
3850Sstevel@tonic-gate mdprtopts_t options,
3860Sstevel@tonic-gate md_error_t *ep
3870Sstevel@tonic-gate )
3880Sstevel@tonic-gate {
3890Sstevel@tonic-gate uint_t col;
3900Sstevel@tonic-gate int rval = -1;
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate if (options & PRINT_LARGEDEVICES) {
3941623Stw21770 if ((raidp->common.revision & MD_64BIT_META_DEV) == 0) {
3951623Stw21770 rval = 0;
3961623Stw21770 goto out;
3971623Stw21770 }
3981623Stw21770 }
3991623Stw21770
4001623Stw21770 if (options & PRINT_FN) {
4011623Stw21770 if ((raidp->common.revision & MD_FN_META_DEV) == 0) {
4020Sstevel@tonic-gate rval = 0;
4030Sstevel@tonic-gate goto out;
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate /* print name and -r */
4080Sstevel@tonic-gate if (fprintf(fp, "%s -r", raidp->common.namep->cname) == EOF)
4090Sstevel@tonic-gate goto out;
4100Sstevel@tonic-gate
4111623Stw21770 /*
4121623Stw21770 * Print columns. Always print the full path.
4131623Stw21770 */
4140Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) {
4150Sstevel@tonic-gate md_raidcol_t *mdrcp = &raidp->cols.cols_val[col];
4160Sstevel@tonic-gate
4171623Stw21770 if (fprintf(fp, " %s", mdrcp->colnamep->rname) == EOF)
4181623Stw21770 goto out;
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate if (fprintf(fp, " -k") == EOF)
4220Sstevel@tonic-gate goto out;
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate /* print options */
4250Sstevel@tonic-gate if (fprintf(fp, " -i %lldb", raidp->interlace) == EOF)
4260Sstevel@tonic-gate goto out;
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate if (raidp->pw_count != PWCNT_MIN)
4290Sstevel@tonic-gate if (fprintf(fp, " -w %d", raidp->pw_count) == EOF)
4300Sstevel@tonic-gate goto out;
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate if (raidp->hspnamep != NULL) {
4330Sstevel@tonic-gate if (fprintf(fp, " -h %s", raidp->hspnamep->hspname) == EOF)
4340Sstevel@tonic-gate goto out;
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate if (raidp->orig_ncol != raidp->cols.cols_len) {
4370Sstevel@tonic-gate assert(raidp->orig_ncol < raidp->cols.cols_len);
4380Sstevel@tonic-gate if (fprintf(fp, " -o %u", raidp->orig_ncol) == EOF)
4390Sstevel@tonic-gate goto out;
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate /* terminate last line */
4430Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF)
4440Sstevel@tonic-gate goto out;
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /* success */
4470Sstevel@tonic-gate rval = 0;
4480Sstevel@tonic-gate
4490Sstevel@tonic-gate /* cleanup, return error */
4500Sstevel@tonic-gate out:
4510Sstevel@tonic-gate if (rval != 0)
4520Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname);
4530Sstevel@tonic-gate return (rval);
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate static int
find_resyncing_column(md_raid_t * raidp)4570Sstevel@tonic-gate find_resyncing_column(
4580Sstevel@tonic-gate md_raid_t *raidp
4590Sstevel@tonic-gate )
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate int col;
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) {
4640Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
4650Sstevel@tonic-gate if (cp->state & RCS_RESYNC)
4660Sstevel@tonic-gate return (col);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate /* No resyncing columns */
4700Sstevel@tonic-gate return (-1);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /*
4740Sstevel@tonic-gate * convert raid state to name
4750Sstevel@tonic-gate */
4760Sstevel@tonic-gate char *
raid_state_to_name(md_raid_t * raidp,md_timeval32_t * tvp,uint_t tstate)4770Sstevel@tonic-gate raid_state_to_name(
4780Sstevel@tonic-gate md_raid_t *raidp,
4790Sstevel@tonic-gate md_timeval32_t *tvp,
4800Sstevel@tonic-gate uint_t tstate /* Errored tstate flags */
4810Sstevel@tonic-gate )
4820Sstevel@tonic-gate {
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate /* grab time */
4850Sstevel@tonic-gate if (tvp != NULL)
4860Sstevel@tonic-gate *tvp = raidp->timestamp;
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate /*
4890Sstevel@tonic-gate * If the device has a transient error state (due to it being DR'ed or
4900Sstevel@tonic-gate * failed) and there has been no I/O to it (the actual device is still
4910Sstevel@tonic-gate * marked as 'Okay') then we cannot know what the state is or what
4920Sstevel@tonic-gate * action to take on it. Therefore report the device as 'Unavailable'.
4930Sstevel@tonic-gate * A subsequent I/O to the device will cause the 'Okay' status to
4940Sstevel@tonic-gate * disappear if the device is actually gone and then we will print out
4950Sstevel@tonic-gate * the appropriate status. The MD_INACCESSIBLE state is only set
4960Sstevel@tonic-gate * on the raid when we open it or probe it. One the raid is open
4970Sstevel@tonic-gate * then we will just have regular error status on the device.
4980Sstevel@tonic-gate */
4990Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) {
5000Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unavailable"));
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate /* resyncing */
5040Sstevel@tonic-gate if (find_resyncing_column(raidp) >= 0)
5050Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resyncing"));
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate /* everything else */
5080Sstevel@tonic-gate switch (raidp->state) {
5090Sstevel@tonic-gate case RUS_INIT :
5100Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Initializing"));
5110Sstevel@tonic-gate case RUS_OKAY :
5120Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Okay"));
5130Sstevel@tonic-gate case RUS_ERRED :
5140Sstevel@tonic-gate /*FALLTHROUGH*/
5150Sstevel@tonic-gate case RUS_LAST_ERRED :
5160Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Needs Maintenance"));
5170Sstevel@tonic-gate case RUS_DOI :
5180Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Initialization Failed"));
5190Sstevel@tonic-gate case RUS_REGEN :
5200Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Regen"));
5210Sstevel@tonic-gate default :
5220Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "invalid"));
5230Sstevel@tonic-gate } /* switch */
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate static int
find_erred_column(md_raid_t * raidp,rcs_state_t state)5270Sstevel@tonic-gate find_erred_column(md_raid_t *raidp, rcs_state_t state)
5280Sstevel@tonic-gate {
5290Sstevel@tonic-gate int col;
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) {
5320Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
5330Sstevel@tonic-gate if (cp->state & state)
5340Sstevel@tonic-gate return (col);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate /* No erred columns */
5380Sstevel@tonic-gate return (-1);
5390Sstevel@tonic-gate }
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate /*
5420Sstevel@tonic-gate * convert raid state to repair action
5430Sstevel@tonic-gate */
5440Sstevel@tonic-gate char *
raid_state_to_action(md_raid_t * raidp)5450Sstevel@tonic-gate raid_state_to_action(md_raid_t *raidp)
5460Sstevel@tonic-gate {
5470Sstevel@tonic-gate static char emsg[1024];
5480Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep;
5490Sstevel@tonic-gate int err_col;
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate /* first check for full init failure */
5520Sstevel@tonic-gate if (raidp->state & RUS_DOI) {
5530Sstevel@tonic-gate (void) snprintf(emsg, sizeof (emsg),
5540Sstevel@tonic-gate "metaclear -f %s", raidnp->cname);
5550Sstevel@tonic-gate return (emsg);
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate /* replace errored or init errored raid column */
5590Sstevel@tonic-gate if ((err_col = find_erred_column(raidp,
5600Sstevel@tonic-gate (RCS_ERRED | RCS_INIT_ERRED))) >= 0) {
5610Sstevel@tonic-gate mdname_t *colnp;
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /* get column with error */
5640Sstevel@tonic-gate assert(err_col < raidp->cols.cols_len);
5650Sstevel@tonic-gate colnp = raidp->cols.cols_val[err_col].colnamep;
5660Sstevel@tonic-gate (void) snprintf(emsg, sizeof (emsg),
5670Sstevel@tonic-gate "metareplace %s%s %s <%s>",
5680Sstevel@tonic-gate ((raidp->state == RUS_LAST_ERRED) ? "-f " : ""),
5690Sstevel@tonic-gate raidnp->cname, colnp->cname,
5700Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "new device"));
5710Sstevel@tonic-gate return (emsg);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate /* replace last errored raid column */
5760Sstevel@tonic-gate if ((err_col = find_erred_column(raidp, RCS_LAST_ERRED)) >= 0) {
5770Sstevel@tonic-gate mdname_t *colnp;
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate assert(err_col < raidp->cols.cols_len);
5800Sstevel@tonic-gate colnp = raidp->cols.cols_val[err_col].colnamep;
5810Sstevel@tonic-gate (void) snprintf(emsg, sizeof (emsg),
5820Sstevel@tonic-gate "metareplace %s %s %s <%s>",
5830Sstevel@tonic-gate ((raidp->state == RUS_LAST_ERRED) ? "-f " : ""),
5840Sstevel@tonic-gate raidnp->cname, colnp->cname,
5850Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "new device"));
5860Sstevel@tonic-gate return (emsg);
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate /* OK */
5900Sstevel@tonic-gate return (NULL);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate /*
5940Sstevel@tonic-gate * get printable raid column state
5950Sstevel@tonic-gate */
5960Sstevel@tonic-gate char *
raid_col_state_to_name(md_raidcol_t * colp,md_timeval32_t * tvp,uint_t tstate)5970Sstevel@tonic-gate raid_col_state_to_name(
5980Sstevel@tonic-gate md_raidcol_t *colp,
5990Sstevel@tonic-gate md_timeval32_t *tvp,
6000Sstevel@tonic-gate uint_t tstate
6010Sstevel@tonic-gate )
6020Sstevel@tonic-gate {
6030Sstevel@tonic-gate /* grab time */
6040Sstevel@tonic-gate if (tvp != NULL)
6050Sstevel@tonic-gate *tvp = colp->timestamp;
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate if (tstate != 0) {
6080Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unavailable"));
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate /* everything else */
6120Sstevel@tonic-gate switch (colp->state) {
6130Sstevel@tonic-gate case RCS_INIT:
6140Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Initializing"));
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate case RCS_OKAY:
6170Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Okay"));
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate case RCS_INIT_ERRED:
6200Sstevel@tonic-gate /*FALLTHROUGH*/
6210Sstevel@tonic-gate case RCS_ERRED:
6220Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Maintenance"));
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate case RCS_LAST_ERRED:
6250Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Last Erred"));
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate case RCS_RESYNC:
6280Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resyncing"));
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate default:
6310Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unknown"));
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate }
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate /*
6360Sstevel@tonic-gate * print raid column
6370Sstevel@tonic-gate */
6380Sstevel@tonic-gate static int
display_raid_device_info(mdsetname_t * sp,md_raidcol_t * colp,char * fname,FILE * fp,mdprtopts_t options,int print_len,uint_t top_tstate,md_error_t * ep)6390Sstevel@tonic-gate display_raid_device_info(
6400Sstevel@tonic-gate mdsetname_t *sp,
6410Sstevel@tonic-gate md_raidcol_t *colp,
6420Sstevel@tonic-gate char *fname,
6430Sstevel@tonic-gate FILE *fp,
6440Sstevel@tonic-gate mdprtopts_t options,
6450Sstevel@tonic-gate int print_len,
6460Sstevel@tonic-gate uint_t top_tstate, /* Errored tstate flags */
6470Sstevel@tonic-gate md_error_t *ep
6480Sstevel@tonic-gate )
6490Sstevel@tonic-gate {
6500Sstevel@tonic-gate mdname_t *namep = ((colp->hsnamep != NULL) ?
6517087Ssk102515 colp->hsnamep : colp->colnamep);
6520Sstevel@tonic-gate char *devid = "";
6530Sstevel@tonic-gate char *cname = colp->colnamep->cname;
6540Sstevel@tonic-gate diskaddr_t start_blk;
6550Sstevel@tonic-gate int has_mddb;
6560Sstevel@tonic-gate char *has_mddb_str;
6570Sstevel@tonic-gate char *col_state;
6580Sstevel@tonic-gate md_timeval32_t tv;
6590Sstevel@tonic-gate char *hsname = ((colp->hsnamep != NULL) ?
6607087Ssk102515 colp->hsnamep->cname : "");
6610Sstevel@tonic-gate int rval = -1;
6620Sstevel@tonic-gate mdname_t *didnp = NULL;
6630Sstevel@tonic-gate ddi_devid_t dtp;
6640Sstevel@tonic-gate uint_t tstate = 0;
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate /* get info */
6670Sstevel@tonic-gate if ((start_blk = metagetstart(sp, namep, ep)) == MD_DISKADDR_ERROR)
6680Sstevel@tonic-gate return (-1);
6690Sstevel@tonic-gate if ((has_mddb = metahasmddb(sp, namep, ep)) < 0)
6700Sstevel@tonic-gate return (-1);
6710Sstevel@tonic-gate if (has_mddb)
6720Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "Yes");
6730Sstevel@tonic-gate else
6740Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "No");
6750Sstevel@tonic-gate
6760Sstevel@tonic-gate if (metaismeta(namep)) {
6770Sstevel@tonic-gate if (meta_get_tstate(namep->dev, &tstate, ep) != 0)
6780Sstevel@tonic-gate return (-1);
6790Sstevel@tonic-gate col_state = raid_col_state_to_name(colp, &tv,
6800Sstevel@tonic-gate tstate & MD_DEV_ERRORED);
6810Sstevel@tonic-gate } else {
6820Sstevel@tonic-gate /*
6830Sstevel@tonic-gate * if top_tstate is set, that implies that you have
6840Sstevel@tonic-gate * a ctd type device with an unavailable metadevice
6850Sstevel@tonic-gate * on top of it. If so, print a - for it's state
6860Sstevel@tonic-gate */
6870Sstevel@tonic-gate if (top_tstate != 0)
6880Sstevel@tonic-gate col_state = "-";
6890Sstevel@tonic-gate else
6900Sstevel@tonic-gate col_state = raid_col_state_to_name(colp, &tv, tstate);
6910Sstevel@tonic-gate }
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate /* populate the key in the name_p structure */
6940Sstevel@tonic-gate if ((didnp = metadevname(&sp, namep->dev, ep)) == NULL)
6950Sstevel@tonic-gate return (-1);
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate /* determine if devid does NOT exist */
6980Sstevel@tonic-gate if (options & PRINT_DEVID) {
6990Sstevel@tonic-gate if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep),
7007087Ssk102515 didnp->key, ep)) == NULL)
7010Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "No ");
7020Sstevel@tonic-gate else {
7030Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "Yes");
7040Sstevel@tonic-gate free(dtp);
7050Sstevel@tonic-gate }
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate /* print column */
7080Sstevel@tonic-gate /*
7090Sstevel@tonic-gate * Building a format string on the fly that will
7100Sstevel@tonic-gate * be used in (f)printf. This allows the length
7110Sstevel@tonic-gate * of the ctd to vary from small to large without
7120Sstevel@tonic-gate * looking horrible.
7130Sstevel@tonic-gate */
7140Sstevel@tonic-gate if (! (options & PRINT_TIMES)) {
7150Sstevel@tonic-gate if (fprintf(fp,
7160Sstevel@tonic-gate "\t%-*.*s %8lld %5.5s %12.12s %5.5s %s\n",
7170Sstevel@tonic-gate print_len, print_len, cname, start_blk, has_mddb_str,
7180Sstevel@tonic-gate col_state, devid, hsname) == EOF) {
7190Sstevel@tonic-gate goto out;
7200Sstevel@tonic-gate }
7210Sstevel@tonic-gate } else {
7220Sstevel@tonic-gate char *timep = meta_print_time(&tv);
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate if (fprintf(fp,
7250Sstevel@tonic-gate "\t%-*s %5lld %-5s %-11s %-5s %-9s %s\n",
7260Sstevel@tonic-gate print_len, cname, start_blk, has_mddb_str,
7270Sstevel@tonic-gate col_state, devid, hsname, timep) == EOF) {
7280Sstevel@tonic-gate goto out;
7290Sstevel@tonic-gate }
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate /* success */
7330Sstevel@tonic-gate rval = 0;
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate /* cleanup, return error */
7360Sstevel@tonic-gate out:
7370Sstevel@tonic-gate if (rval != 0)
7380Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname);
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate return (rval);
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate
7430Sstevel@tonic-gate /*
7440Sstevel@tonic-gate * print raid options
7450Sstevel@tonic-gate */
7460Sstevel@tonic-gate int
meta_print_raid_options(mdhspname_t * hspnamep,char * fname,FILE * fp,md_error_t * ep)7470Sstevel@tonic-gate meta_print_raid_options(
7480Sstevel@tonic-gate mdhspname_t *hspnamep,
7490Sstevel@tonic-gate char *fname,
7500Sstevel@tonic-gate FILE *fp,
7510Sstevel@tonic-gate md_error_t *ep
7520Sstevel@tonic-gate )
7530Sstevel@tonic-gate {
7540Sstevel@tonic-gate char *hspname = ((hspnamep != NULL) ? hspnamep->hspname :
7557087Ssk102515 dgettext(TEXT_DOMAIN, "none"));
7560Sstevel@tonic-gate int rval = -1;
7570Sstevel@tonic-gate
7580Sstevel@tonic-gate /* print options */
7590Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
7600Sstevel@tonic-gate " Hot spare pool: %s\n"), hspname) == EOF) {
7610Sstevel@tonic-gate goto out;
7620Sstevel@tonic-gate }
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate /* success */
7650Sstevel@tonic-gate rval = 0;
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate /* cleanup, return error */
7680Sstevel@tonic-gate out:
7690Sstevel@tonic-gate if (rval != 0)
7700Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname);
7710Sstevel@tonic-gate return (rval);
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate /*
7750Sstevel@tonic-gate * report raid
7760Sstevel@tonic-gate */
7770Sstevel@tonic-gate static int
raid_report(mdsetname_t * sp,md_raid_t * raidp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)7780Sstevel@tonic-gate raid_report(
7790Sstevel@tonic-gate mdsetname_t *sp,
7800Sstevel@tonic-gate md_raid_t *raidp,
7810Sstevel@tonic-gate char *fname,
7820Sstevel@tonic-gate FILE *fp,
7830Sstevel@tonic-gate mdprtopts_t options,
7840Sstevel@tonic-gate md_error_t *ep
7850Sstevel@tonic-gate )
7860Sstevel@tonic-gate {
7870Sstevel@tonic-gate char *p;
7880Sstevel@tonic-gate uint_t ncol = raidp->cols.cols_len;
7890Sstevel@tonic-gate uint_t orig_ncol = raidp->orig_ncol;
7900Sstevel@tonic-gate diskaddr_t column_size = raidp->column_size;
7910Sstevel@tonic-gate char *raid_state;
7920Sstevel@tonic-gate md_timeval32_t tv;
7930Sstevel@tonic-gate char *timep;
7940Sstevel@tonic-gate uint_t col;
7950Sstevel@tonic-gate int rval = -1;
7960Sstevel@tonic-gate int len = 0;
7970Sstevel@tonic-gate uint_t tstate = 0;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate if (options & PRINT_LARGEDEVICES) {
8001623Stw21770 if ((raidp->common.revision & MD_64BIT_META_DEV) == 0) {
8011623Stw21770 rval = 0;
8021623Stw21770 goto out;
8031623Stw21770 }
8041623Stw21770 }
8051623Stw21770
8061623Stw21770 if (options & PRINT_FN) {
8071623Stw21770 if ((raidp->common.revision & MD_FN_META_DEV) == 0) {
8080Sstevel@tonic-gate rval = 0;
8090Sstevel@tonic-gate goto out;
8100Sstevel@tonic-gate }
8110Sstevel@tonic-gate }
8120Sstevel@tonic-gate
8130Sstevel@tonic-gate /* print header */
8140Sstevel@tonic-gate if (options & PRINT_HEADER) {
8150Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: RAID\n"),
8160Sstevel@tonic-gate raidp->common.namep->cname) == EOF) {
8170Sstevel@tonic-gate goto out;
8180Sstevel@tonic-gate }
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate
8220Sstevel@tonic-gate /* print state */
8230Sstevel@tonic-gate if (metaismeta(raidp->common.namep)) {
8240Sstevel@tonic-gate if (meta_get_tstate(raidp->common.namep->dev, &tstate, ep) != 0)
8250Sstevel@tonic-gate return (-1);
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate tstate &= MD_DEV_ERRORED; /* extract the errored tstate bits */
8280Sstevel@tonic-gate raid_state = raid_state_to_name(raidp, &tv, tstate);
8290Sstevel@tonic-gate if (options & PRINT_TIMES) {
8300Sstevel@tonic-gate timep = meta_print_time(&tv);
8310Sstevel@tonic-gate } else {
8320Sstevel@tonic-gate timep = "";
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " State: %-12s %s\n"),
8360Sstevel@tonic-gate raid_state, timep) == EOF) {
8370Sstevel@tonic-gate goto out;
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate /*
8410Sstevel@tonic-gate * Display recovery action if we're marked in the Unavailable state.
8420Sstevel@tonic-gate */
8430Sstevel@tonic-gate if ((tstate == 0) || (tstate & MD_INACCESSIBLE)) {
8440Sstevel@tonic-gate /* print what to do */
8450Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) {
8460Sstevel@tonic-gate char sname[MD_MAX_SETNAME + 3]; /* 3 = sizeof("-s ") */
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate if (metaislocalset(sp)) {
8490Sstevel@tonic-gate sname[0] = '\0';
8500Sstevel@tonic-gate } else {
8510Sstevel@tonic-gate (void) snprintf(sname, MD_MAX_SETNAME + 3,
8520Sstevel@tonic-gate "-s %s", sp->setname);
8530Sstevel@tonic-gate }
8540Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
8550Sstevel@tonic-gate " Invoke: metastat -i %s\n"), sname) == EOF) {
8560Sstevel@tonic-gate goto out;
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate } else if ((p = raid_state_to_action(raidp)) != NULL) {
8590Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
8600Sstevel@tonic-gate " Invoke: %s\n"), p) == EOF) {
8610Sstevel@tonic-gate goto out;
8620Sstevel@tonic-gate }
8630Sstevel@tonic-gate }
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate /* resync status */
8660Sstevel@tonic-gate if (raidp->resync_flags & MD_RI_INPROGRESS) {
8670Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
8680Sstevel@tonic-gate " Resync in progress: %2d.%1d%% done\n"),
8690Sstevel@tonic-gate raidp->percent_done/10,
8700Sstevel@tonic-gate raidp->percent_done % 10) == EOF) {
8710Sstevel@tonic-gate goto out;
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate } else if (raidp->resync_flags & MD_GROW_INPROGRESS) {
8740Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
8750Sstevel@tonic-gate " Initialization in progress: %2d.%1d%% "
8760Sstevel@tonic-gate "done\n"),
8770Sstevel@tonic-gate raidp->percent_done/10,
8780Sstevel@tonic-gate raidp->percent_done % 10) == EOF) {
8790Sstevel@tonic-gate goto out;
8800Sstevel@tonic-gate }
8810Sstevel@tonic-gate } else if (raidp->state & RUS_REGEN) {
8820Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
8830Sstevel@tonic-gate " Parity regeneration in progress: %2d.%1d%% "
8840Sstevel@tonic-gate "done\n"),
8850Sstevel@tonic-gate raidp->percent_done/10,
8860Sstevel@tonic-gate raidp->percent_done % 10) == EOF) {
8870Sstevel@tonic-gate goto out;
8880Sstevel@tonic-gate }
8890Sstevel@tonic-gate }
8900Sstevel@tonic-gate }
8910Sstevel@tonic-gate
8920Sstevel@tonic-gate /* print hotspare pool */
8930Sstevel@tonic-gate if (raidp->hspnamep != NULL) {
8940Sstevel@tonic-gate if (meta_print_raid_options(raidp->hspnamep,
8950Sstevel@tonic-gate fname, fp, ep) != 0) {
8960Sstevel@tonic-gate return (-1);
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate /* print interlace */
9010Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Interlace: %lld blocks\n"),
9020Sstevel@tonic-gate raidp->interlace) == EOF) {
9030Sstevel@tonic-gate goto out;
9040Sstevel@tonic-gate }
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate /* print size */
9070Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"),
9080Sstevel@tonic-gate raidp->common.size,
9090Sstevel@tonic-gate meta_number_to_string(raidp->common.size, DEV_BSIZE)) == EOF) {
9100Sstevel@tonic-gate goto out;
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate /* MD_DEBUG stuff */
9140Sstevel@tonic-gate if (options & PRINT_DEBUG) {
9150Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep;
9160Sstevel@tonic-gate mr_unit_t *mr;
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate /* get additional info */
9190Sstevel@tonic-gate if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
9200Sstevel@tonic-gate return (-1);
9210Sstevel@tonic-gate assert(mr->c.un_type == MD_METARAID);
9220Sstevel@tonic-gate
9230Sstevel@tonic-gate /* print prewrite count and size */
9240Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
9250Sstevel@tonic-gate " Prewrite Count: %u slots\n"),
9260Sstevel@tonic-gate mr->un_pwcnt) == EOF) {
9270Sstevel@tonic-gate Free(mr);
9280Sstevel@tonic-gate goto out;
9290Sstevel@tonic-gate }
9300Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
9310Sstevel@tonic-gate " Prewrite Slot Size: %u blocks\n"),
9320Sstevel@tonic-gate (mr->un_pwsize / mr->un_pwcnt)) == EOF) {
9330Sstevel@tonic-gate Free(mr);
9340Sstevel@tonic-gate goto out;
9350Sstevel@tonic-gate }
9360Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
9370Sstevel@tonic-gate " Prewrite Total Size: %u blocks\n"),
9380Sstevel@tonic-gate mr->un_pwsize) == EOF) {
9390Sstevel@tonic-gate Free(mr);
9400Sstevel@tonic-gate goto out;
9410Sstevel@tonic-gate }
9420Sstevel@tonic-gate Free(mr);
9430Sstevel@tonic-gate }
9440Sstevel@tonic-gate
9450Sstevel@tonic-gate /* print original devices */
9460Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, "Original device:\n")) == EOF)
9470Sstevel@tonic-gate goto out;
9480Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"),
9490Sstevel@tonic-gate column_size * (orig_ncol - 1),
9500Sstevel@tonic-gate meta_number_to_string(column_size * (orig_ncol - 1), DEV_BSIZE))
9510Sstevel@tonic-gate == EOF) {
9520Sstevel@tonic-gate goto out;
9530Sstevel@tonic-gate }
9540Sstevel@tonic-gate /*
9550Sstevel@tonic-gate * Building a format string on the fly that will
9560Sstevel@tonic-gate * be used in (f)printf. This allows the length
9570Sstevel@tonic-gate * of the ctd to vary from small to large without
9580Sstevel@tonic-gate * looking horrible.
9590Sstevel@tonic-gate */
9600Sstevel@tonic-gate for (col = 0; (col < orig_ncol); ++col) {
9610Sstevel@tonic-gate len = max(len,
9620Sstevel@tonic-gate strlen(raidp->cols.cols_val[col].colnamep->cname));
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device")));
9660Sstevel@tonic-gate len += 2;
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate if (! (options & PRINT_TIMES)) {
9690Sstevel@tonic-gate if (fprintf(fp,
9700Sstevel@tonic-gate "\t%-*.*s %-12.12s %-5.5s %12.12s %-5.5s %s\n",
9710Sstevel@tonic-gate len, len,
9720Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"),
9730Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"),
9740Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"),
9750Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"),
9760Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"),
9770Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) {
9780Sstevel@tonic-gate goto out;
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate } else {
9810Sstevel@tonic-gate if (fprintf(fp,
9820Sstevel@tonic-gate "\t%-*s %5s %-5s %-11s %-5s %-9s %s\n",
9830Sstevel@tonic-gate len,
9840Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"),
9850Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start"),
9860Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"),
9870Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"),
9880Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"),
9890Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare"),
9900Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Time")) == EOF) {
9910Sstevel@tonic-gate goto out;
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate }
9940Sstevel@tonic-gate for (col = 0; (col < orig_ncol); ++col) {
9950Sstevel@tonic-gate md_raidcol_t *mdrcp = &raidp->cols.cols_val[col];
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate if (display_raid_device_info(sp, mdrcp, fname, fp, options,
9980Sstevel@tonic-gate len, tstate, ep) != 0) {
9990Sstevel@tonic-gate return (-1);
10000Sstevel@tonic-gate }
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate /* print concatenated devices */
10040Sstevel@tonic-gate if (col < ncol) {
10050Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
10060Sstevel@tonic-gate "Concatenated Devices:\n")) == EOF) {
10070Sstevel@tonic-gate goto out;
10080Sstevel@tonic-gate }
10090Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
10100Sstevel@tonic-gate " Size: %lld blocks (%s)\n"),
10110Sstevel@tonic-gate column_size * (ncol - orig_ncol),
10120Sstevel@tonic-gate meta_number_to_string(column_size * (ncol - orig_ncol),
10130Sstevel@tonic-gate DEV_BSIZE))
10140Sstevel@tonic-gate == EOF) {
10150Sstevel@tonic-gate goto out;
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate /*
10180Sstevel@tonic-gate * This allows the length
10190Sstevel@tonic-gate * of the ctd to vary from small to large without
10200Sstevel@tonic-gate * looking horrible.
10210Sstevel@tonic-gate */
10220Sstevel@tonic-gate if (! (options & PRINT_TIMES)) {
10230Sstevel@tonic-gate if (fprintf(fp,
10240Sstevel@tonic-gate "\t%-*.*s %-12.12s %-5.5s %-12.12s %5.5s %s\n",
10250Sstevel@tonic-gate len, len,
10260Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"),
10270Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"),
10280Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"),
10290Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"),
10300Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"),
10310Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) {
10320Sstevel@tonic-gate goto out;
10330Sstevel@tonic-gate }
10340Sstevel@tonic-gate } else {
10350Sstevel@tonic-gate if (fprintf(fp,
10360Sstevel@tonic-gate "\t%-*s %5s %-5s %-11s %-9s %s\t%s\n",
10370Sstevel@tonic-gate len,
10380Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"),
10390Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start"),
10400Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"),
10410Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"),
10420Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"),
10430Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare"),
10440Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Time")) == EOF) {
10450Sstevel@tonic-gate goto out;
10460Sstevel@tonic-gate }
10470Sstevel@tonic-gate }
10480Sstevel@tonic-gate assert(col == orig_ncol);
10490Sstevel@tonic-gate for (/* void */; (col < ncol); col++) {
10500Sstevel@tonic-gate md_raidcol_t *mdrcp = &raidp->cols.cols_val[col];
10510Sstevel@tonic-gate
10520Sstevel@tonic-gate if (display_raid_device_info(sp, mdrcp, fname, fp,
10530Sstevel@tonic-gate options, len, tstate, ep) != 0) {
10540Sstevel@tonic-gate return (-1);
10550Sstevel@tonic-gate }
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate }
10580Sstevel@tonic-gate
10590Sstevel@tonic-gate /* add extra line */
10600Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF)
10610Sstevel@tonic-gate goto out;
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate /* success */
10640Sstevel@tonic-gate rval = 0;
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate /* cleanup, return error */
10670Sstevel@tonic-gate out:
10680Sstevel@tonic-gate if (rval != 0)
10690Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname);
10700Sstevel@tonic-gate return (rval);
10710Sstevel@tonic-gate }
10720Sstevel@tonic-gate
10730Sstevel@tonic-gate /*
10740Sstevel@tonic-gate * print/report raid
10750Sstevel@tonic-gate */
10760Sstevel@tonic-gate int
meta_raid_print(mdsetname_t * sp,mdname_t * raidnp,mdnamelist_t ** nlpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)10770Sstevel@tonic-gate meta_raid_print(
10780Sstevel@tonic-gate mdsetname_t *sp,
10790Sstevel@tonic-gate mdname_t *raidnp,
10800Sstevel@tonic-gate mdnamelist_t **nlpp,
10810Sstevel@tonic-gate char *fname,
10820Sstevel@tonic-gate FILE *fp,
10830Sstevel@tonic-gate mdprtopts_t options,
10840Sstevel@tonic-gate md_error_t *ep
10850Sstevel@tonic-gate )
10860Sstevel@tonic-gate {
10870Sstevel@tonic-gate md_raid_t *raidp;
10880Sstevel@tonic-gate int col;
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate /* should have same set */
10910Sstevel@tonic-gate assert(sp != NULL);
10920Sstevel@tonic-gate assert((raidnp == NULL) ||
10930Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))));
10940Sstevel@tonic-gate
10950Sstevel@tonic-gate /* print all raids */
10960Sstevel@tonic-gate if (raidnp == NULL) {
10970Sstevel@tonic-gate mdnamelist_t *nlp = NULL;
10980Sstevel@tonic-gate mdnamelist_t *p;
10990Sstevel@tonic-gate int cnt;
11000Sstevel@tonic-gate int rval = 0;
11010Sstevel@tonic-gate
11020Sstevel@tonic-gate /* get list */
11030Sstevel@tonic-gate if ((cnt = meta_get_raid_names(sp, &nlp, options, ep)) < 0)
11040Sstevel@tonic-gate return (-1);
11050Sstevel@tonic-gate else if (cnt == 0)
11060Sstevel@tonic-gate return (0);
11070Sstevel@tonic-gate
11080Sstevel@tonic-gate /* recurse */
11090Sstevel@tonic-gate for (p = nlp; (p != NULL); p = p->next) {
11100Sstevel@tonic-gate mdname_t *np = p->namep;
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate if (meta_raid_print(sp, np, nlpp, fname, fp,
11130Sstevel@tonic-gate options, ep) != 0)
11140Sstevel@tonic-gate rval = -1;
11150Sstevel@tonic-gate }
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate /* cleanup, return success */
11180Sstevel@tonic-gate metafreenamelist(nlp);
11190Sstevel@tonic-gate return (rval);
11200Sstevel@tonic-gate }
11210Sstevel@tonic-gate
11220Sstevel@tonic-gate /* get unit structure */
11230Sstevel@tonic-gate if ((raidp = meta_get_raid_common(sp, raidnp,
11240Sstevel@tonic-gate ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL)
11250Sstevel@tonic-gate return (-1);
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate /* check for parented */
11280Sstevel@tonic-gate if ((! (options & PRINT_SUBDEVS)) &&
11290Sstevel@tonic-gate (MD_HAS_PARENT(raidp->common.parent))) {
11300Sstevel@tonic-gate return (0);
11310Sstevel@tonic-gate }
11320Sstevel@tonic-gate
11330Sstevel@tonic-gate /* print appropriate detail */
11340Sstevel@tonic-gate if (options & PRINT_SHORT) {
11350Sstevel@tonic-gate if (raid_print(raidp, fname, fp, options, ep) != 0)
11360Sstevel@tonic-gate return (-1);
11370Sstevel@tonic-gate } else {
11380Sstevel@tonic-gate if (raid_report(sp, raidp, fname, fp, options, ep) != 0)
11390Sstevel@tonic-gate return (-1);
11400Sstevel@tonic-gate }
11410Sstevel@tonic-gate
11420Sstevel@tonic-gate /* Recurse on components that are metadevices */
11430Sstevel@tonic-gate for (col = 0; col < raidp->cols.cols_len; ++col) {
11440Sstevel@tonic-gate md_raidcol_t *colp = &raidp->cols.cols_val[col];
11450Sstevel@tonic-gate mdname_t *namep = colp->colnamep;
11460Sstevel@tonic-gate
11470Sstevel@tonic-gate if ((metaismeta(namep)) &&
11480Sstevel@tonic-gate (meta_print_name(sp, namep, nlpp, fname, fp,
11490Sstevel@tonic-gate (options | PRINT_HEADER | PRINT_SUBDEVS),
11500Sstevel@tonic-gate NULL, ep) != 0)) {
11510Sstevel@tonic-gate return (-1);
11520Sstevel@tonic-gate }
11530Sstevel@tonic-gate }
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate return (0);
11560Sstevel@tonic-gate }
11570Sstevel@tonic-gate
11580Sstevel@tonic-gate /*
11590Sstevel@tonic-gate * adjust raid geometry
11600Sstevel@tonic-gate */
11610Sstevel@tonic-gate static int
adjust_geom(mdname_t * raidnp,mdname_t * colnp,mr_unit_t * mr,md_error_t * ep)11620Sstevel@tonic-gate adjust_geom(
11630Sstevel@tonic-gate mdname_t *raidnp,
11640Sstevel@tonic-gate mdname_t *colnp,
11650Sstevel@tonic-gate mr_unit_t *mr,
11660Sstevel@tonic-gate md_error_t *ep
11670Sstevel@tonic-gate )
11680Sstevel@tonic-gate {
11690Sstevel@tonic-gate uint_t round_cyl = 1;
11700Sstevel@tonic-gate mdgeom_t *geomp;
11710Sstevel@tonic-gate
11720Sstevel@tonic-gate /* get reinstructs */
11730Sstevel@tonic-gate if ((geomp = metagetgeom(colnp, ep)) == NULL)
11740Sstevel@tonic-gate return (-1);
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate /* adjust geometry */
11770Sstevel@tonic-gate if (meta_adjust_geom((md_unit_t *)mr, raidnp, geomp->write_reinstruct,
11780Sstevel@tonic-gate geomp->read_reinstruct, round_cyl, ep) != 0)
11790Sstevel@tonic-gate return (-1);
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate /* return success */
11820Sstevel@tonic-gate return (0);
11830Sstevel@tonic-gate }
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate /*
11860Sstevel@tonic-gate * add another column to the raid unit structure
11870Sstevel@tonic-gate */
11880Sstevel@tonic-gate static int
attach_raid_col(mdsetname_t * sp,mdname_t * raidnp,mr_unit_t * mr,mr_column_t * mdc,mdname_t * colnp,rcs_state_t state,mdnamelist_t ** keynlpp,mdcmdopts_t options,md_error_t * ep)11890Sstevel@tonic-gate attach_raid_col(
11900Sstevel@tonic-gate mdsetname_t *sp,
11910Sstevel@tonic-gate mdname_t *raidnp,
11920Sstevel@tonic-gate mr_unit_t *mr,
11930Sstevel@tonic-gate mr_column_t *mdc,
11940Sstevel@tonic-gate mdname_t *colnp,
11950Sstevel@tonic-gate rcs_state_t state,
11960Sstevel@tonic-gate mdnamelist_t **keynlpp,
11970Sstevel@tonic-gate mdcmdopts_t options,
11980Sstevel@tonic-gate md_error_t *ep
11990Sstevel@tonic-gate )
12000Sstevel@tonic-gate {
12010Sstevel@tonic-gate diskaddr_t column_size = mr->un_segsize * mr->un_segsincolumn;
12020Sstevel@tonic-gate diskaddr_t size;
12030Sstevel@tonic-gate uint_t maxio;
12040Sstevel@tonic-gate mdcinfo_t *cinfop;
12050Sstevel@tonic-gate md_timeval32_t tmp_time;
12060Sstevel@tonic-gate
12070Sstevel@tonic-gate /* setup state and timestamp */
12080Sstevel@tonic-gate mdc->un_devstate = state;
12090Sstevel@tonic-gate if (meta_gettimeofday(&tmp_time) == -1)
12100Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate mdc->un_devtimestamp = tmp_time;
12130Sstevel@tonic-gate /* get start, size, and maxio */
12140Sstevel@tonic-gate if ((mdc->un_orig_devstart = metagetstart(sp, colnp, ep)) ==
12150Sstevel@tonic-gate MD_DISKADDR_ERROR)
12160Sstevel@tonic-gate return (-1);
12170Sstevel@tonic-gate if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR)
12180Sstevel@tonic-gate return (-1);
12190Sstevel@tonic-gate if ((cinfop = metagetcinfo(colnp, ep)) == NULL)
12200Sstevel@tonic-gate return (-1);
12210Sstevel@tonic-gate maxio = cinfop->maxtransfer;
12220Sstevel@tonic-gate
12230Sstevel@tonic-gate /* adjust start and size by prewrite */
12240Sstevel@tonic-gate mdc->un_orig_pwstart = mdc->un_orig_devstart;
12250Sstevel@tonic-gate mdc->un_orig_devstart += mr->un_pwsize;
12260Sstevel@tonic-gate
12270Sstevel@tonic-gate /* make sure we still have something left */
12280Sstevel@tonic-gate if ((mdc->un_orig_devstart >= size) ||
12290Sstevel@tonic-gate ((size - mdc->un_orig_devstart) < column_size)) {
12300Sstevel@tonic-gate return (mdsyserror(ep, ENOSPC, colnp->cname));
12310Sstevel@tonic-gate }
12320Sstevel@tonic-gate size -= mdc->un_orig_devstart;
12330Sstevel@tonic-gate if (maxio < mr->un_maxio) {
12340Sstevel@tonic-gate return (mdcomperror(ep, MDE_MAXIO,
12350Sstevel@tonic-gate meta_getminor(raidnp->dev), colnp->dev, colnp->cname));
12360Sstevel@tonic-gate }
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate if (options & MDCMD_DOIT) {
12390Sstevel@tonic-gate /* store name in namespace */
12400Sstevel@tonic-gate if (add_key_name(sp, colnp, keynlpp, ep) != 0)
12410Sstevel@tonic-gate return (-1);
12420Sstevel@tonic-gate }
12430Sstevel@tonic-gate
12440Sstevel@tonic-gate /* setup column */
12450Sstevel@tonic-gate mdc->un_orig_dev = colnp->dev;
12460Sstevel@tonic-gate mdc->un_orig_key = colnp->key;
12470Sstevel@tonic-gate mdc->un_dev = colnp->dev;
12480Sstevel@tonic-gate mdc->un_pwstart = mdc->un_orig_pwstart;
12490Sstevel@tonic-gate mdc->un_devstart = mdc->un_orig_devstart;
12500Sstevel@tonic-gate mdc->un_alt_dev = NODEV64;
12510Sstevel@tonic-gate mdc->un_alt_pwstart = 0;
12520Sstevel@tonic-gate mdc->un_alt_devstart = 0;
12530Sstevel@tonic-gate mdc->un_hs_id = 0;
12540Sstevel@tonic-gate
12550Sstevel@tonic-gate /* add the size (we use) of the device to the total */
12560Sstevel@tonic-gate mr->c.un_actual_tb += column_size;
12570Sstevel@tonic-gate
12580Sstevel@tonic-gate /* adjust geometry */
12590Sstevel@tonic-gate if (adjust_geom(raidnp, colnp, mr, ep) != 0)
12600Sstevel@tonic-gate return (-1);
12610Sstevel@tonic-gate
12620Sstevel@tonic-gate /* count column */
12630Sstevel@tonic-gate mr->un_totalcolumncnt++;
12640Sstevel@tonic-gate
12650Sstevel@tonic-gate /* return success */
12660Sstevel@tonic-gate return (0);
12670Sstevel@tonic-gate }
12680Sstevel@tonic-gate
12690Sstevel@tonic-gate /*
12700Sstevel@tonic-gate * invalidate column names
12710Sstevel@tonic-gate */
12720Sstevel@tonic-gate static int
invalidate_columns(mdsetname_t * sp,mdname_t * raidnp,md_error_t * ep)12730Sstevel@tonic-gate invalidate_columns(
12740Sstevel@tonic-gate mdsetname_t *sp,
12750Sstevel@tonic-gate mdname_t *raidnp,
12760Sstevel@tonic-gate md_error_t *ep
12770Sstevel@tonic-gate )
12780Sstevel@tonic-gate {
12790Sstevel@tonic-gate md_raid_t *raidp;
12800Sstevel@tonic-gate uint_t col;
12810Sstevel@tonic-gate
12820Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL)
12830Sstevel@tonic-gate return (-1);
12840Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) {
12850Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
12860Sstevel@tonic-gate mdname_t *colnp = cp->colnamep;
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate meta_invalidate_name(colnp);
12890Sstevel@tonic-gate }
12900Sstevel@tonic-gate return (0);
12910Sstevel@tonic-gate }
12920Sstevel@tonic-gate
12930Sstevel@tonic-gate /*
12940Sstevel@tonic-gate * attach columns to raid
12950Sstevel@tonic-gate */
12960Sstevel@tonic-gate int
meta_raid_attach(mdsetname_t * sp,mdname_t * raidnp,mdnamelist_t * colnlp,mdcmdopts_t options,md_error_t * ep)12970Sstevel@tonic-gate meta_raid_attach(
12980Sstevel@tonic-gate mdsetname_t *sp,
12990Sstevel@tonic-gate mdname_t *raidnp,
13000Sstevel@tonic-gate mdnamelist_t *colnlp,
13010Sstevel@tonic-gate mdcmdopts_t options,
13020Sstevel@tonic-gate md_error_t *ep
13030Sstevel@tonic-gate )
13040Sstevel@tonic-gate {
13050Sstevel@tonic-gate uint_t concat_cnt = 0;
13060Sstevel@tonic-gate mdnamelist_t *p;
13070Sstevel@tonic-gate mr_unit_t *old_mr;
13080Sstevel@tonic-gate mr_unit_t *new_mr;
13090Sstevel@tonic-gate size_t old_rusize;
13100Sstevel@tonic-gate size_t new_rusize;
13110Sstevel@tonic-gate mdnamelist_t *keynlp = NULL;
13120Sstevel@tonic-gate md_grow_params_t mgp;
13130Sstevel@tonic-gate int rval = -1;
13140Sstevel@tonic-gate int create_flag = MD_CRO_32BIT;
13150Sstevel@tonic-gate
13160Sstevel@tonic-gate /* should have a set */
13170Sstevel@tonic-gate assert(sp != NULL);
13180Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
13190Sstevel@tonic-gate
13200Sstevel@tonic-gate /* check type */
13210Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0)
13220Sstevel@tonic-gate return (-1);
13230Sstevel@tonic-gate
13240Sstevel@tonic-gate /* check and count new columns */
13250Sstevel@tonic-gate for (p = colnlp; (p != NULL); p = p->next) {
13260Sstevel@tonic-gate mdname_t *np = p->namep;
13270Sstevel@tonic-gate mdnamelist_t *p2;
13280Sstevel@tonic-gate
13290Sstevel@tonic-gate /* check against existing devices */
13300Sstevel@tonic-gate if (meta_check_column(sp, np, ep) != 0)
13310Sstevel@tonic-gate return (-1);
13320Sstevel@tonic-gate
13330Sstevel@tonic-gate /* check against ourselves */
13340Sstevel@tonic-gate for (p2 = p->next; (p2 != NULL); p2 = p2->next) {
13350Sstevel@tonic-gate if (meta_check_overlap(np->cname, np, 0, -1,
13360Sstevel@tonic-gate p2->namep, 0, -1, ep) != 0) {
13370Sstevel@tonic-gate return (-1);
13380Sstevel@tonic-gate }
13390Sstevel@tonic-gate }
13400Sstevel@tonic-gate
13410Sstevel@tonic-gate /* count */
13420Sstevel@tonic-gate ++concat_cnt;
13430Sstevel@tonic-gate }
13440Sstevel@tonic-gate
13450Sstevel@tonic-gate /* get old unit */
13460Sstevel@tonic-gate if ((old_mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
13470Sstevel@tonic-gate return (-1);
13480Sstevel@tonic-gate
13490Sstevel@tonic-gate /*
13500Sstevel@tonic-gate * calculate the size needed for the new raid unit and allocate
13510Sstevel@tonic-gate * the appropriate structure. allocate new unit.
13520Sstevel@tonic-gate */
13530Sstevel@tonic-gate old_rusize = sizeof (*old_mr) - sizeof (old_mr->un_column[0]);
13540Sstevel@tonic-gate old_rusize += old_mr->un_totalcolumncnt * sizeof (old_mr->un_column[0]);
13550Sstevel@tonic-gate new_rusize = sizeof (*new_mr) - sizeof (new_mr->un_column[0]);
13560Sstevel@tonic-gate new_rusize += (old_mr->un_totalcolumncnt + concat_cnt)
13570Sstevel@tonic-gate * sizeof (new_mr->un_column[0]);
13580Sstevel@tonic-gate new_mr = Zalloc(new_rusize);
13590Sstevel@tonic-gate (void) memcpy(new_mr, old_mr, old_rusize);
13600Sstevel@tonic-gate
13610Sstevel@tonic-gate /* We always want a do-it, this is for attach_raid_col below */
13620Sstevel@tonic-gate options |= MDCMD_DOIT;
13630Sstevel@tonic-gate
13640Sstevel@tonic-gate /* build new unit structure */
13650Sstevel@tonic-gate for (p = colnlp; (p != NULL); p = p->next) {
13660Sstevel@tonic-gate mdname_t *colnp = p->namep;
13670Sstevel@tonic-gate mr_column_t *mdc;
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate /* attach column */
13700Sstevel@tonic-gate mdc = &new_mr->un_column[new_mr->un_totalcolumncnt];
13710Sstevel@tonic-gate if (attach_raid_col(sp, raidnp, new_mr, mdc, colnp,
13720Sstevel@tonic-gate RCS_INIT, &keynlp, options, ep) != 0) {
13730Sstevel@tonic-gate goto out;
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate }
13760Sstevel@tonic-gate assert(new_mr->un_totalcolumncnt
13770Sstevel@tonic-gate == (old_mr->un_totalcolumncnt + concat_cnt));
13780Sstevel@tonic-gate
13790Sstevel@tonic-gate
13800Sstevel@tonic-gate create_flag = meta_check_devicesize(new_mr->c.un_total_blocks);
13810Sstevel@tonic-gate
13820Sstevel@tonic-gate /* grow raid */
13830Sstevel@tonic-gate (void) memset(&mgp, 0, sizeof (mgp));
13840Sstevel@tonic-gate mgp.mnum = MD_SID(new_mr);
13850Sstevel@tonic-gate MD_SETDRIVERNAME(&mgp, MD_RAID, sp->setno);
13860Sstevel@tonic-gate mgp.size = new_rusize;
13870Sstevel@tonic-gate mgp.mdp = (uintptr_t)new_mr;
13880Sstevel@tonic-gate
13890Sstevel@tonic-gate if (create_flag == MD_CRO_32BIT) {
13900Sstevel@tonic-gate mgp.options = MD_CRO_32BIT;
13911623Stw21770 new_mr->c.un_revision &= ~MD_64BIT_META_DEV;
13920Sstevel@tonic-gate } else {
13930Sstevel@tonic-gate mgp.options = MD_CRO_64BIT;
13941623Stw21770 new_mr->c.un_revision |= MD_64BIT_META_DEV;
13950Sstevel@tonic-gate }
13960Sstevel@tonic-gate if (metaioctl(MD_IOCGROW, &mgp, &mgp.mde, NULL) != 0) {
13970Sstevel@tonic-gate (void) mdstealerror(ep, &mgp.mde);
13980Sstevel@tonic-gate goto out;
13990Sstevel@tonic-gate }
14000Sstevel@tonic-gate
14010Sstevel@tonic-gate /* clear cache */
14020Sstevel@tonic-gate if (invalidate_columns(sp, raidnp, ep) != 0)
14030Sstevel@tonic-gate goto out;
14040Sstevel@tonic-gate meta_invalidate_name(raidnp);
14050Sstevel@tonic-gate
14060Sstevel@tonic-gate /* let em know */
14070Sstevel@tonic-gate if (options & MDCMD_PRINT) {
14080Sstevel@tonic-gate if (concat_cnt == 1) {
14090Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
14100Sstevel@tonic-gate "%s: component is attached\n"),
14110Sstevel@tonic-gate raidnp->cname);
14120Sstevel@tonic-gate } else {
14130Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
14140Sstevel@tonic-gate "%s: components are attached\n"),
14150Sstevel@tonic-gate raidnp->cname);
14160Sstevel@tonic-gate }
14170Sstevel@tonic-gate (void) fflush(stdout);
14180Sstevel@tonic-gate }
14190Sstevel@tonic-gate
14200Sstevel@tonic-gate
14210Sstevel@tonic-gate /* grow any parents */
14220Sstevel@tonic-gate if (meta_concat_parent(sp, raidnp, ep) != 0)
14230Sstevel@tonic-gate goto out;
14240Sstevel@tonic-gate rval = 0; /* success */
14250Sstevel@tonic-gate
14260Sstevel@tonic-gate /* cleanup, return error */
14270Sstevel@tonic-gate out:
14280Sstevel@tonic-gate Free(old_mr);
14290Sstevel@tonic-gate Free(new_mr);
14300Sstevel@tonic-gate if (rval != 0)
14310Sstevel@tonic-gate (void) del_key_names(sp, keynlp, NULL);
14320Sstevel@tonic-gate metafreenamelist(keynlp);
14330Sstevel@tonic-gate return (rval);
14340Sstevel@tonic-gate }
14350Sstevel@tonic-gate
14360Sstevel@tonic-gate /*
14370Sstevel@tonic-gate * get raid parameters
14380Sstevel@tonic-gate */
14390Sstevel@tonic-gate int
meta_raid_get_params(mdsetname_t * sp,mdname_t * raidnp,mr_params_t * paramsp,md_error_t * ep)14400Sstevel@tonic-gate meta_raid_get_params(
14410Sstevel@tonic-gate mdsetname_t *sp,
14420Sstevel@tonic-gate mdname_t *raidnp,
14430Sstevel@tonic-gate mr_params_t *paramsp,
14440Sstevel@tonic-gate md_error_t *ep
14450Sstevel@tonic-gate )
14460Sstevel@tonic-gate {
14470Sstevel@tonic-gate md_raid_t *raidp;
14480Sstevel@tonic-gate
14490Sstevel@tonic-gate /* should have a set */
14500Sstevel@tonic-gate assert(sp != NULL);
14510Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
14520Sstevel@tonic-gate
14530Sstevel@tonic-gate /* check name */
14540Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0)
14550Sstevel@tonic-gate return (-1);
14560Sstevel@tonic-gate
14570Sstevel@tonic-gate /* get unit */
14580Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL)
14590Sstevel@tonic-gate return (-1);
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate /* return parameters */
14620Sstevel@tonic-gate (void) memset(paramsp, 0, sizeof (*paramsp));
14630Sstevel@tonic-gate if (raidp->hspnamep == NULL)
14640Sstevel@tonic-gate paramsp->hsp_id = MD_HSP_NONE;
14650Sstevel@tonic-gate else
14660Sstevel@tonic-gate paramsp->hsp_id = raidp->hspnamep->hsp;
14670Sstevel@tonic-gate return (0);
14680Sstevel@tonic-gate }
14690Sstevel@tonic-gate
14700Sstevel@tonic-gate /*
14710Sstevel@tonic-gate * set raid parameters
14720Sstevel@tonic-gate */
14730Sstevel@tonic-gate int
meta_raid_set_params(mdsetname_t * sp,mdname_t * raidnp,mr_params_t * paramsp,md_error_t * ep)14740Sstevel@tonic-gate meta_raid_set_params(
14750Sstevel@tonic-gate mdsetname_t *sp,
14760Sstevel@tonic-gate mdname_t *raidnp,
14770Sstevel@tonic-gate mr_params_t *paramsp,
14780Sstevel@tonic-gate md_error_t *ep
14790Sstevel@tonic-gate )
14800Sstevel@tonic-gate {
14810Sstevel@tonic-gate md_raid_params_t msp;
14820Sstevel@tonic-gate
14830Sstevel@tonic-gate /* should have a set */
14840Sstevel@tonic-gate assert(sp != NULL);
14850Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
14860Sstevel@tonic-gate
14870Sstevel@tonic-gate /* check name */
14880Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0)
14890Sstevel@tonic-gate return (-1);
14900Sstevel@tonic-gate
14910Sstevel@tonic-gate /* set parameters */
14920Sstevel@tonic-gate (void) memset(&msp, 0, sizeof (msp));
14930Sstevel@tonic-gate MD_SETDRIVERNAME(&msp, MD_RAID, sp->setno);
14940Sstevel@tonic-gate msp.mnum = meta_getminor(raidnp->dev);
14950Sstevel@tonic-gate msp.params = *paramsp;
14960Sstevel@tonic-gate if (metaioctl(MD_IOCCHANGE, &msp, &msp.mde, raidnp->cname) != 0)
14970Sstevel@tonic-gate return (mdstealerror(ep, &msp.mde));
14980Sstevel@tonic-gate
14990Sstevel@tonic-gate /* clear cache */
15000Sstevel@tonic-gate meta_invalidate_name(raidnp);
15010Sstevel@tonic-gate
15020Sstevel@tonic-gate /* return success */
15030Sstevel@tonic-gate return (0);
15040Sstevel@tonic-gate }
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate /*
15070Sstevel@tonic-gate * validate raid replace column
15080Sstevel@tonic-gate */
15090Sstevel@tonic-gate static int
validate_new_raid(mdsetname_t * sp,mdname_t * raidnp,mdname_t * colnp,replace_params_t * paramsp,int dup_ok,md_error_t * ep)15100Sstevel@tonic-gate validate_new_raid(
15110Sstevel@tonic-gate mdsetname_t *sp,
15120Sstevel@tonic-gate mdname_t *raidnp,
15130Sstevel@tonic-gate mdname_t *colnp,
15140Sstevel@tonic-gate replace_params_t *paramsp,
15150Sstevel@tonic-gate int dup_ok,
15160Sstevel@tonic-gate md_error_t *ep
15170Sstevel@tonic-gate )
15180Sstevel@tonic-gate {
15190Sstevel@tonic-gate mr_unit_t *mr;
15200Sstevel@tonic-gate diskaddr_t column_size;
15210Sstevel@tonic-gate diskaddr_t label;
15220Sstevel@tonic-gate mdcinfo_t *cinfop;
15230Sstevel@tonic-gate int rval = -1;
15240Sstevel@tonic-gate
15250Sstevel@tonic-gate /* get raid unit */
15260Sstevel@tonic-gate if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL)
15270Sstevel@tonic-gate return (-1);
15280Sstevel@tonic-gate column_size = mr->un_segsize * mr->un_segsincolumn;
15290Sstevel@tonic-gate
15300Sstevel@tonic-gate /* check it out */
15310Sstevel@tonic-gate if (meta_check_column(sp, colnp, ep) != 0) {
15320Sstevel@tonic-gate if ((! dup_ok) || (! mdisuseerror(ep, MDE_ALREADY)))
15330Sstevel@tonic-gate goto out;
15340Sstevel@tonic-gate mdclrerror(ep);
15350Sstevel@tonic-gate }
15360Sstevel@tonic-gate if ((paramsp->number_blks = metagetsize(colnp, ep)) ==
15370Sstevel@tonic-gate MD_DISKADDR_ERROR)
15380Sstevel@tonic-gate goto out;
15390Sstevel@tonic-gate if ((label = metagetlabel(colnp, ep)) == MD_DISKADDR_ERROR)
15400Sstevel@tonic-gate goto out;
15410Sstevel@tonic-gate paramsp->has_label = ((label > 0) ? 1 : 0);
15420Sstevel@tonic-gate if ((paramsp->start_blk = metagetstart(sp, colnp, ep)) ==
15430Sstevel@tonic-gate MD_DISKADDR_ERROR)
15440Sstevel@tonic-gate goto out;
15450Sstevel@tonic-gate if ((paramsp->number_blks - paramsp->start_blk) < column_size) {
15460Sstevel@tonic-gate (void) mdsyserror(ep, ENOSPC, colnp->cname);
15470Sstevel@tonic-gate goto out;
15480Sstevel@tonic-gate }
15490Sstevel@tonic-gate if ((cinfop = metagetcinfo(colnp, ep)) == NULL)
15500Sstevel@tonic-gate goto out;
15510Sstevel@tonic-gate if (cinfop->maxtransfer < mr->un_maxio) {
15520Sstevel@tonic-gate (void) mdcomperror(ep, MDE_MAXIO, meta_getminor(raidnp->dev),
15530Sstevel@tonic-gate colnp->dev, colnp->cname);
15540Sstevel@tonic-gate goto out;
15550Sstevel@tonic-gate }
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate /* success */
15580Sstevel@tonic-gate rval = 0;
15590Sstevel@tonic-gate
15600Sstevel@tonic-gate /* cleanup, return error */
15610Sstevel@tonic-gate out:
15620Sstevel@tonic-gate Free(mr);
15630Sstevel@tonic-gate return (rval);
15640Sstevel@tonic-gate }
15650Sstevel@tonic-gate
15660Sstevel@tonic-gate /*
15670Sstevel@tonic-gate * replace raid column
15680Sstevel@tonic-gate */
15690Sstevel@tonic-gate int
meta_raid_replace(mdsetname_t * sp,mdname_t * raidnp,mdname_t * oldnp,mdname_t * newnp,mdcmdopts_t options,md_error_t * ep)15700Sstevel@tonic-gate meta_raid_replace(
15710Sstevel@tonic-gate mdsetname_t *sp,
15720Sstevel@tonic-gate mdname_t *raidnp,
15730Sstevel@tonic-gate mdname_t *oldnp,
15740Sstevel@tonic-gate mdname_t *newnp,
15750Sstevel@tonic-gate mdcmdopts_t options,
15760Sstevel@tonic-gate md_error_t *ep
15770Sstevel@tonic-gate )
15780Sstevel@tonic-gate {
15790Sstevel@tonic-gate int force = ((options & MDCMD_FORCE) ? 1 : 0);
15800Sstevel@tonic-gate replace_params_t params;
15810Sstevel@tonic-gate md_dev64_t old_dev, new_dev;
15820Sstevel@tonic-gate diskaddr_t new_start_blk, new_end_blk;
15830Sstevel@tonic-gate int rebind;
15840Sstevel@tonic-gate char *new_devidp = NULL;
15850Sstevel@tonic-gate md_error_t xep = mdnullerror;
15860Sstevel@tonic-gate int ret;
15870Sstevel@tonic-gate md_set_desc *sd;
15880Sstevel@tonic-gate uint_t tstate;
15890Sstevel@tonic-gate
15900Sstevel@tonic-gate /* should have same set */
15910Sstevel@tonic-gate assert(sp != NULL);
15920Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
15930Sstevel@tonic-gate
15940Sstevel@tonic-gate /* check name */
15950Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0)
15960Sstevel@tonic-gate return (-1);
15970Sstevel@tonic-gate
15980Sstevel@tonic-gate /* save new binding incase this is a rebind where oldnp==newnp */
15990Sstevel@tonic-gate new_dev = newnp->dev;
16000Sstevel@tonic-gate new_start_blk = newnp->start_blk;
16010Sstevel@tonic-gate new_end_blk = newnp->end_blk;
16020Sstevel@tonic-gate
16030Sstevel@tonic-gate /* invalidate, then get the raid (fill in oldnp from metadb) */
16040Sstevel@tonic-gate meta_invalidate_name(raidnp);
16050Sstevel@tonic-gate if (meta_get_raid(sp, raidnp, ep) == NULL)
16060Sstevel@tonic-gate return (-1);
16070Sstevel@tonic-gate
16080Sstevel@tonic-gate /* can't replace a component if the raid inaccessible */
16090Sstevel@tonic-gate if (meta_get_tstate(raidnp->dev, &tstate, ep) != 0) {
16100Sstevel@tonic-gate return (-1);
16110Sstevel@tonic-gate }
16120Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) {
16130Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_UNAVAIL_STATE,
16140Sstevel@tonic-gate meta_getminor(raidnp->dev), raidnp->cname));
16150Sstevel@tonic-gate }
16160Sstevel@tonic-gate
16170Sstevel@tonic-gate /* the old device binding is now established */
16180Sstevel@tonic-gate if ((old_dev = oldnp->dev) == NODEV64)
16190Sstevel@tonic-gate return (mdsyserror(ep, ENODEV, oldnp->cname));
16200Sstevel@tonic-gate
16210Sstevel@tonic-gate
16220Sstevel@tonic-gate /* setup raid info */
16230Sstevel@tonic-gate (void) memset(¶ms, 0, sizeof (params));
16240Sstevel@tonic-gate params.mnum = meta_getminor(raidnp->dev);
16250Sstevel@tonic-gate MD_SETDRIVERNAME(¶ms, MD_RAID, sp->setno);
16260Sstevel@tonic-gate params.old_dev = old_dev;
16270Sstevel@tonic-gate params.cmd = force ? FORCE_REPLACE_COMP : REPLACE_COMP;
16280Sstevel@tonic-gate
16291623Stw21770 if ((strcmp(oldnp->rname, newnp->rname) == 0) &&
16301623Stw21770 (old_dev != new_dev)) {
16311623Stw21770 rebind = 1;
16320Sstevel@tonic-gate } else {
16331623Stw21770 rebind = 0;
16341623Stw21770 }
16351623Stw21770 if (rebind) {
16361623Stw21770 newnp->dev = new_dev;
16371623Stw21770 newnp->start_blk = new_start_blk;
16381623Stw21770 newnp->end_blk = new_end_blk;
16391623Stw21770 }
16401623Stw21770
16411623Stw21770 /*
16421623Stw21770 * Save a copy of the devid associated with the new disk, the
16431623Stw21770 * reason is that the checks for the column (meta_check_column)
16441623Stw21770 * via validate_new_raid(), could cause the disk's devid to be
16451623Stw21770 * changed to that of the devid that is currently stored in the
16461623Stw21770 * replica namespace for the disk in question. This devid could
16471623Stw21770 * be stale if we are replacing the disk. The actual function
16481623Stw21770 * that overwrites the devid is dr2drivedesc().
16491623Stw21770 */
16500Sstevel@tonic-gate
16511623Stw21770 /* don't setup new_devid if no devid's or MN diskset */
16521623Stw21770 if (newnp->drivenamep->devid != NULL)
16531623Stw21770 new_devidp = Strdup(newnp->drivenamep->devid);
16540Sstevel@tonic-gate
16551623Stw21770 if (!metaislocalset(sp)) {
16561623Stw21770 if ((sd = metaget_setdesc(sp, ep)) == NULL)
16571623Stw21770 return (-1);
16581623Stw21770 if (MD_MNSET_DESC(sd))
16591623Stw21770 new_devidp = NULL;
16601623Stw21770 }
16610Sstevel@tonic-gate
16621623Stw21770 /* check out new (sets up start_blk, has_label, number_blks) */
16631623Stw21770 if (validate_new_raid(sp, raidnp, newnp, ¶ms, rebind,
16641623Stw21770 ep) != 0) {
16651623Stw21770 Free(new_devidp);
16661623Stw21770 return (-1);
16671623Stw21770 }
16680Sstevel@tonic-gate
16691623Stw21770 /*
16701623Stw21770 * Copy back the saved devid.
16711623Stw21770 */
16721623Stw21770 Free(newnp->drivenamep->devid);
16731623Stw21770 if (new_devidp) {
16741623Stw21770 newnp->drivenamep->devid = Strdup(new_devidp);
16751623Stw21770 Free(new_devidp);
16760Sstevel@tonic-gate }
16770Sstevel@tonic-gate
16780Sstevel@tonic-gate /* store name in namespace, allocate new key */
16790Sstevel@tonic-gate if (add_key_name(sp, newnp, NULL, ep) != 0)
16800Sstevel@tonic-gate return (-1);
16810Sstevel@tonic-gate
16820Sstevel@tonic-gate if (rebind && !metaislocalset(sp)) {
16830Sstevel@tonic-gate /*
16840Sstevel@tonic-gate * We are 'rebind'ing a disk that is in a diskset so as well
16850Sstevel@tonic-gate * as updating the diskset's namespace the local set needs
16860Sstevel@tonic-gate * to be updated because it also contains a reference to the
16870Sstevel@tonic-gate * disk in question.
16880Sstevel@tonic-gate */
16890Sstevel@tonic-gate ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET,
16900Sstevel@tonic-gate newnp->cname, ep);
16910Sstevel@tonic-gate
16920Sstevel@tonic-gate if (ret != METADEVADM_SUCCESS) {
16930Sstevel@tonic-gate (void) del_key_name(sp, newnp, &xep);
16940Sstevel@tonic-gate return (-1);
16950Sstevel@tonic-gate }
16960Sstevel@tonic-gate }
16970Sstevel@tonic-gate
16980Sstevel@tonic-gate /* replace column */
16990Sstevel@tonic-gate params.new_dev = new_dev;
17000Sstevel@tonic-gate params.new_key = newnp->key;
17010Sstevel@tonic-gate if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) {
17020Sstevel@tonic-gate (void) del_key_name(sp, newnp, ep);
17030Sstevel@tonic-gate return (mdstealerror(ep, ¶ms.mde));
17040Sstevel@tonic-gate }
17050Sstevel@tonic-gate
17060Sstevel@tonic-gate /* clear cache */
17070Sstevel@tonic-gate meta_invalidate_name(oldnp);
17080Sstevel@tonic-gate meta_invalidate_name(newnp);
17090Sstevel@tonic-gate meta_invalidate_name(raidnp);
17100Sstevel@tonic-gate
17110Sstevel@tonic-gate /* let em know */
17120Sstevel@tonic-gate if (options & MDCMD_PRINT) {
17130Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
17140Sstevel@tonic-gate "%s: device %s is replaced with %s\n"),
17150Sstevel@tonic-gate raidnp->cname, oldnp->cname, newnp->cname);
17160Sstevel@tonic-gate (void) fflush(stdout);
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate /* return success */
17200Sstevel@tonic-gate return (0);
17210Sstevel@tonic-gate }
17220Sstevel@tonic-gate
17230Sstevel@tonic-gate /*
17240Sstevel@tonic-gate * enable raid column
17250Sstevel@tonic-gate */
17260Sstevel@tonic-gate int
meta_raid_enable(mdsetname_t * sp,mdname_t * raidnp,mdname_t * colnp,mdcmdopts_t options,md_error_t * ep)17270Sstevel@tonic-gate meta_raid_enable(
17280Sstevel@tonic-gate mdsetname_t *sp,
17290Sstevel@tonic-gate mdname_t *raidnp,
17300Sstevel@tonic-gate mdname_t *colnp,
17310Sstevel@tonic-gate mdcmdopts_t options,
17320Sstevel@tonic-gate md_error_t *ep
17330Sstevel@tonic-gate )
17340Sstevel@tonic-gate {
17350Sstevel@tonic-gate int force = ((options & MDCMD_FORCE) ? 1 : 0);
17360Sstevel@tonic-gate replace_params_t params;
17370Sstevel@tonic-gate md_dev64_t fs_dev, del_dev;
17380Sstevel@tonic-gate int err = 0;
17390Sstevel@tonic-gate char *devnm;
17400Sstevel@tonic-gate int ret;
17410Sstevel@tonic-gate uint_t tstate;
17420Sstevel@tonic-gate
17430Sstevel@tonic-gate /* should have same set */
17440Sstevel@tonic-gate assert(sp != NULL);
17450Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
17460Sstevel@tonic-gate
17470Sstevel@tonic-gate /* check name */
17480Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0)
17490Sstevel@tonic-gate return (-1);
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate /* get the file_system dev binding */
17520Sstevel@tonic-gate if (meta_getdev(sp, colnp, ep) != 0)
17530Sstevel@tonic-gate return (-1);
17540Sstevel@tonic-gate fs_dev = colnp->dev;
17550Sstevel@tonic-gate
17560Sstevel@tonic-gate /* get the raid unit (fill in colnp->dev with metadb version) */
17570Sstevel@tonic-gate meta_invalidate_name(raidnp);
17580Sstevel@tonic-gate if (meta_get_raid(sp, raidnp, ep) == NULL)
17590Sstevel@tonic-gate return (-1);
17600Sstevel@tonic-gate
17610Sstevel@tonic-gate /* enabling a component can't work if the raid inaccessible */
17620Sstevel@tonic-gate if (meta_get_tstate(raidnp->dev, &tstate, ep) != 0) {
17630Sstevel@tonic-gate return (-1);
17640Sstevel@tonic-gate }
17650Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) {
17660Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_UNAVAIL_STATE,
17670Sstevel@tonic-gate meta_getminor(raidnp->dev), raidnp->cname));
17680Sstevel@tonic-gate }
17690Sstevel@tonic-gate
17700Sstevel@tonic-gate /* the metadb device binding is now established */
17710Sstevel@tonic-gate if (colnp->dev == NODEV64)
17720Sstevel@tonic-gate return (mdsyserror(ep, ENODEV, colnp->cname));
17730Sstevel@tonic-gate
17740Sstevel@tonic-gate /*
17750Sstevel@tonic-gate * check for the case where the dev_t has changed between the
17760Sstevel@tonic-gate * filesystem and the metadb. This is called a rebind, and
17770Sstevel@tonic-gate * is handled by meta_raid_replace.
17780Sstevel@tonic-gate */
17790Sstevel@tonic-gate if (fs_dev != colnp->dev) {
17800Sstevel@tonic-gate /*
17810Sstevel@tonic-gate * Save the devt of mddb version
17820Sstevel@tonic-gate */
17830Sstevel@tonic-gate del_dev = colnp->dev;
17840Sstevel@tonic-gate
17850Sstevel@tonic-gate /* establish file system binding with invalid start/end */
17860Sstevel@tonic-gate colnp->dev = fs_dev;
17870Sstevel@tonic-gate colnp->start_blk = -1;
17880Sstevel@tonic-gate colnp->end_blk = -1;
17890Sstevel@tonic-gate err = meta_raid_replace(sp, raidnp, colnp, colnp, options, ep);
17900Sstevel@tonic-gate
17910Sstevel@tonic-gate /*
17920Sstevel@tonic-gate * Don't do it if meta_raid_replace returns an error
17930Sstevel@tonic-gate */
17940Sstevel@tonic-gate if (!err && (devnm = meta_getnmentbydev(sp->setno, MD_SIDEWILD,
17957087Ssk102515 del_dev, NULL, NULL, &colnp->key, ep)) != NULL) {
17960Sstevel@tonic-gate (void) del_key_name(sp, colnp, ep);
17970Sstevel@tonic-gate Free(devnm);
17980Sstevel@tonic-gate }
17990Sstevel@tonic-gate return (err);
18000Sstevel@tonic-gate }
18010Sstevel@tonic-gate
18020Sstevel@tonic-gate /* setup raid info */
18030Sstevel@tonic-gate (void) memset(¶ms, 0, sizeof (params));
18040Sstevel@tonic-gate params.mnum = meta_getminor(raidnp->dev);
18050Sstevel@tonic-gate MD_SETDRIVERNAME(¶ms, MD_RAID, sp->setno);
18060Sstevel@tonic-gate params.old_dev = params.new_dev = colnp->dev;
18070Sstevel@tonic-gate if (force)
18080Sstevel@tonic-gate params.cmd = FORCE_ENABLE_COMP;
18090Sstevel@tonic-gate else
18100Sstevel@tonic-gate params.cmd = ENABLE_COMP;
18110Sstevel@tonic-gate
18120Sstevel@tonic-gate /* check it out */
18130Sstevel@tonic-gate if (validate_new_raid(sp, raidnp, colnp, ¶ms, 1, ep) != 0)
18140Sstevel@tonic-gate return (-1);
18150Sstevel@tonic-gate
18160Sstevel@tonic-gate /* enable column */
18170Sstevel@tonic-gate if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0)
18180Sstevel@tonic-gate return (mdstealerror(ep, ¶ms.mde));
18190Sstevel@tonic-gate
18200Sstevel@tonic-gate /*
18210Sstevel@tonic-gate * are we dealing with a non-local set? If so need to update the
18220Sstevel@tonic-gate * local namespace so that the disk record has the correct devid.
18230Sstevel@tonic-gate */
18240Sstevel@tonic-gate if (!metaislocalset(sp)) {
18250Sstevel@tonic-gate ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET, colnp->cname,
18260Sstevel@tonic-gate ep);
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate if (ret != METADEVADM_SUCCESS) {
18290Sstevel@tonic-gate /*
18300Sstevel@tonic-gate * Failed to update the local set. Nothing to do here
18310Sstevel@tonic-gate * apart from report the error. The namespace is
18320Sstevel@tonic-gate * most likely broken and some form of remedial
18330Sstevel@tonic-gate * recovery is going to be required.
18340Sstevel@tonic-gate */
18350Sstevel@tonic-gate mde_perror(ep, "");
18360Sstevel@tonic-gate mdclrerror(ep);
18370Sstevel@tonic-gate }
18380Sstevel@tonic-gate }
18390Sstevel@tonic-gate
18400Sstevel@tonic-gate /* clear cache */
18410Sstevel@tonic-gate meta_invalidate_name(colnp);
18420Sstevel@tonic-gate meta_invalidate_name(raidnp);
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate /* let em know */
18450Sstevel@tonic-gate if (options & MDCMD_PRINT) {
18460Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
18470Sstevel@tonic-gate "%s: device %s is enabled\n"),
18480Sstevel@tonic-gate raidnp->cname, colnp->cname);
18490Sstevel@tonic-gate (void) fflush(stdout);
18500Sstevel@tonic-gate }
18510Sstevel@tonic-gate
18520Sstevel@tonic-gate /* return success */
18530Sstevel@tonic-gate return (0);
18540Sstevel@tonic-gate }
18550Sstevel@tonic-gate
18560Sstevel@tonic-gate /*
18570Sstevel@tonic-gate * check for dups in the raid itself
18580Sstevel@tonic-gate */
18590Sstevel@tonic-gate static int
check_twice(md_raid_t * raidp,uint_t col,md_error_t * ep)18600Sstevel@tonic-gate check_twice(
18610Sstevel@tonic-gate md_raid_t *raidp,
18620Sstevel@tonic-gate uint_t col,
18630Sstevel@tonic-gate md_error_t *ep
18640Sstevel@tonic-gate )
18650Sstevel@tonic-gate {
18660Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep;
18670Sstevel@tonic-gate mdname_t *thisnp;
18680Sstevel@tonic-gate uint_t c;
18690Sstevel@tonic-gate
18700Sstevel@tonic-gate thisnp = raidp->cols.cols_val[col].colnamep;
18710Sstevel@tonic-gate for (c = 0; (c < col); ++c) {
18720Sstevel@tonic-gate md_raidcol_t *mdcp = &raidp->cols.cols_val[c];
18730Sstevel@tonic-gate mdname_t *colnp = mdcp->colnamep;
18740Sstevel@tonic-gate
18750Sstevel@tonic-gate if (meta_check_overlap(raidnp->cname, thisnp, 0, -1,
18760Sstevel@tonic-gate colnp, 0, -1, ep) != 0) {
18770Sstevel@tonic-gate return (-1);
18780Sstevel@tonic-gate }
18790Sstevel@tonic-gate }
18800Sstevel@tonic-gate return (0);
18810Sstevel@tonic-gate }
18820Sstevel@tonic-gate
18830Sstevel@tonic-gate /*
18840Sstevel@tonic-gate * default raid interlace
18850Sstevel@tonic-gate */
18860Sstevel@tonic-gate diskaddr_t
meta_default_raid_interlace(void)18870Sstevel@tonic-gate meta_default_raid_interlace(void)
18880Sstevel@tonic-gate {
18890Sstevel@tonic-gate diskaddr_t interlace;
18900Sstevel@tonic-gate
1891456Stn143363 /* default to 512k, round up if necessary */
1892456Stn143363 interlace = btodb(512 * 1024);
18930Sstevel@tonic-gate if (interlace < lbtodb(MININTERLACE))
18940Sstevel@tonic-gate interlace = roundup(MININTERLACE, interlace);
18950Sstevel@tonic-gate return (interlace);
18960Sstevel@tonic-gate }
18970Sstevel@tonic-gate
18980Sstevel@tonic-gate /*
18990Sstevel@tonic-gate * convert interlaces
19000Sstevel@tonic-gate */
19010Sstevel@tonic-gate int
meta_raid_check_interlace(diskaddr_t interlace,char * uname,md_error_t * ep)19020Sstevel@tonic-gate meta_raid_check_interlace(
19030Sstevel@tonic-gate diskaddr_t interlace,
19040Sstevel@tonic-gate char *uname,
19050Sstevel@tonic-gate md_error_t *ep
19060Sstevel@tonic-gate )
19070Sstevel@tonic-gate {
19080Sstevel@tonic-gate if ((interlace < btodb(RAID_MIN_INTERLACE)) ||
19090Sstevel@tonic-gate (interlace > btodb(MAXINTERLACE))) {
19100Sstevel@tonic-gate return (mderror(ep, MDE_BAD_INTERLACE, uname));
19110Sstevel@tonic-gate }
19120Sstevel@tonic-gate return (0);
19130Sstevel@tonic-gate }
19140Sstevel@tonic-gate
19150Sstevel@tonic-gate /*
19160Sstevel@tonic-gate * check raid
19170Sstevel@tonic-gate */
19180Sstevel@tonic-gate int
meta_check_raid(mdsetname_t * sp,md_raid_t * raidp,mdcmdopts_t options,md_error_t * ep)19190Sstevel@tonic-gate meta_check_raid(
19200Sstevel@tonic-gate mdsetname_t *sp,
19210Sstevel@tonic-gate md_raid_t *raidp,
19220Sstevel@tonic-gate mdcmdopts_t options,
19230Sstevel@tonic-gate md_error_t *ep
19240Sstevel@tonic-gate )
19250Sstevel@tonic-gate {
19260Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep;
19270Sstevel@tonic-gate int doit = ((options & MDCMD_DOIT) ? 1 : 0);
19280Sstevel@tonic-gate int updateit = ((options & MDCMD_UPDATE) ? 1 : 0);
19290Sstevel@tonic-gate uint_t ncol;
19300Sstevel@tonic-gate uint_t col;
19310Sstevel@tonic-gate minor_t mnum = meta_getminor(raidnp->dev);
19320Sstevel@tonic-gate
19330Sstevel@tonic-gate /* check number */
19340Sstevel@tonic-gate if (((ncol = raidp->cols.cols_len) < MD_RAID_MIN) ||
19350Sstevel@tonic-gate (raidp->orig_ncol > ncol)) {
19360Sstevel@tonic-gate return (mdmderror(ep, MDE_BAD_RAID, mnum, raidnp->cname));
19370Sstevel@tonic-gate }
19380Sstevel@tonic-gate
19390Sstevel@tonic-gate /* compute default interlace */
19400Sstevel@tonic-gate if (raidp->interlace == 0) {
19410Sstevel@tonic-gate raidp->interlace = meta_default_raid_interlace();
19420Sstevel@tonic-gate }
19430Sstevel@tonic-gate
19440Sstevel@tonic-gate /* check state */
19450Sstevel@tonic-gate switch (raidp->state) {
19460Sstevel@tonic-gate case RUS_INIT:
19470Sstevel@tonic-gate case RUS_OKAY:
19480Sstevel@tonic-gate break;
19490Sstevel@tonic-gate
19500Sstevel@tonic-gate default:
19510Sstevel@tonic-gate return (mdmderror(ep, MDE_BAD_RAID, mnum, raidnp->cname));
19520Sstevel@tonic-gate }
19530Sstevel@tonic-gate
19540Sstevel@tonic-gate /* check interlace */
19550Sstevel@tonic-gate if (meta_raid_check_interlace(raidp->interlace, raidnp->cname, ep) != 0)
19560Sstevel@tonic-gate return (-1);
19570Sstevel@tonic-gate
19580Sstevel@tonic-gate /* check hotspare pool name */
19590Sstevel@tonic-gate if (doit) {
19600Sstevel@tonic-gate if ((raidp->hspnamep != NULL) &&
19610Sstevel@tonic-gate (metachkhsp(sp, raidp->hspnamep, ep) != 0)) {
19620Sstevel@tonic-gate return (-1);
19630Sstevel@tonic-gate }
19640Sstevel@tonic-gate }
19650Sstevel@tonic-gate
19660Sstevel@tonic-gate /* check columns */
19670Sstevel@tonic-gate for (col = 0; (col < ncol); ++col) {
19680Sstevel@tonic-gate md_raidcol_t *mdcp = &raidp->cols.cols_val[col];
19690Sstevel@tonic-gate mdname_t *colnp = mdcp->colnamep;
19700Sstevel@tonic-gate diskaddr_t start_blk, size;
19710Sstevel@tonic-gate
19720Sstevel@tonic-gate /* setup column */
19730Sstevel@tonic-gate if (raidp->state == RUS_INIT)
19740Sstevel@tonic-gate mdcp->state = RCS_INIT;
19750Sstevel@tonic-gate else
19760Sstevel@tonic-gate mdcp->state = RCS_OKAY;
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate /* check column */
19790Sstevel@tonic-gate if (!updateit) {
19800Sstevel@tonic-gate if (meta_check_column(sp, colnp, ep) != 0)
19810Sstevel@tonic-gate return (-1);
19820Sstevel@tonic-gate if (((start_blk = metagetstart(sp, colnp, ep)) ==
19830Sstevel@tonic-gate MD_DISKADDR_ERROR) || ((size = metagetsize(colnp,
19840Sstevel@tonic-gate ep)) == MD_DISKADDR_ERROR)) {
19850Sstevel@tonic-gate return (-1);
19860Sstevel@tonic-gate }
19870Sstevel@tonic-gate if (start_blk >= size)
19880Sstevel@tonic-gate return (mdsyserror(ep, ENOSPC, colnp->cname));
19890Sstevel@tonic-gate size -= start_blk;
19900Sstevel@tonic-gate size = rounddown(size, raidp->interlace);
19910Sstevel@tonic-gate if (size == 0)
19920Sstevel@tonic-gate return (mdsyserror(ep, ENOSPC, colnp->cname));
19930Sstevel@tonic-gate }
19940Sstevel@tonic-gate
19950Sstevel@tonic-gate /* check this raid too */
19960Sstevel@tonic-gate if (check_twice(raidp, col, ep) != 0)
19970Sstevel@tonic-gate return (-1);
19980Sstevel@tonic-gate }
19990Sstevel@tonic-gate
20000Sstevel@tonic-gate /* return success */
20010Sstevel@tonic-gate return (0);
20020Sstevel@tonic-gate }
20030Sstevel@tonic-gate
20040Sstevel@tonic-gate /*
20050Sstevel@tonic-gate * setup raid geometry
20060Sstevel@tonic-gate */
20070Sstevel@tonic-gate static int
raid_geom(md_raid_t * raidp,mr_unit_t * mr,md_error_t * ep)20080Sstevel@tonic-gate raid_geom(
20090Sstevel@tonic-gate md_raid_t *raidp,
20100Sstevel@tonic-gate mr_unit_t *mr,
20110Sstevel@tonic-gate md_error_t *ep
20120Sstevel@tonic-gate )
20130Sstevel@tonic-gate {
20140Sstevel@tonic-gate uint_t write_reinstruct = 0;
20150Sstevel@tonic-gate uint_t read_reinstruct = 0;
20160Sstevel@tonic-gate uint_t round_cyl = 1;
20170Sstevel@tonic-gate uint_t col;
20180Sstevel@tonic-gate mdgeom_t *geomp;
20190Sstevel@tonic-gate
20200Sstevel@tonic-gate /* get worst reinstructs */
20210Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) {
20220Sstevel@tonic-gate md_raidcol_t *mdcp = &raidp->cols.cols_val[col];
20230Sstevel@tonic-gate mdname_t *colnp = mdcp->colnamep;
20240Sstevel@tonic-gate
20250Sstevel@tonic-gate if ((geomp = metagetgeom(colnp, ep)) == NULL)
20260Sstevel@tonic-gate return (-1);
20270Sstevel@tonic-gate if (geomp->write_reinstruct > write_reinstruct)
20280Sstevel@tonic-gate write_reinstruct = geomp->write_reinstruct;
20290Sstevel@tonic-gate if (geomp->read_reinstruct > read_reinstruct)
20300Sstevel@tonic-gate read_reinstruct = geomp->read_reinstruct;
20310Sstevel@tonic-gate }
20320Sstevel@tonic-gate
20330Sstevel@tonic-gate /* setup geometry from first column */
20340Sstevel@tonic-gate assert(raidp->cols.cols_len > 0);
20350Sstevel@tonic-gate if ((geomp = metagetgeom(raidp->cols.cols_val[0].colnamep,
20360Sstevel@tonic-gate ep)) == NULL) {
20370Sstevel@tonic-gate return (-1);
20380Sstevel@tonic-gate }
20390Sstevel@tonic-gate if (meta_setup_geom((md_unit_t *)mr, raidp->common.namep, geomp,
20400Sstevel@tonic-gate write_reinstruct, read_reinstruct, round_cyl, ep) != 0)
20410Sstevel@tonic-gate return (-1);
20420Sstevel@tonic-gate
20430Sstevel@tonic-gate /* return success */
20440Sstevel@tonic-gate return (0);
20450Sstevel@tonic-gate }
20460Sstevel@tonic-gate
20470Sstevel@tonic-gate int
meta_raid_state_cnt(mr_unit_t * mr,rcs_state_t state)20480Sstevel@tonic-gate meta_raid_state_cnt(mr_unit_t *mr, rcs_state_t state)
20490Sstevel@tonic-gate {
20500Sstevel@tonic-gate int statecnt = 0;
20510Sstevel@tonic-gate int col;
20520Sstevel@tonic-gate
20530Sstevel@tonic-gate for (col = 0; col < mr->un_totalcolumncnt; col++)
20540Sstevel@tonic-gate if (mr->un_column[col].un_devstate & state)
20550Sstevel@tonic-gate statecnt++;
20560Sstevel@tonic-gate return (statecnt);
20570Sstevel@tonic-gate }
20580Sstevel@tonic-gate /*
20590Sstevel@tonic-gate * validate that a raid device being created with the -k flag is a real
20600Sstevel@tonic-gate * raid device
20610Sstevel@tonic-gate */
20620Sstevel@tonic-gate int
meta_raid_valid(md_raid_t * raidp,mr_unit_t * mr)20630Sstevel@tonic-gate meta_raid_valid(md_raid_t *raidp, mr_unit_t *mr)
20640Sstevel@tonic-gate {
20650Sstevel@tonic-gate long long buf[DEV_BSIZE / sizeof (long long)];
20660Sstevel@tonic-gate raid_pwhdr_t pwhdr;
20670Sstevel@tonic-gate raid_pwhdr_t *rpw = &pwhdr;
20680Sstevel@tonic-gate minor_t mnum;
20690Sstevel@tonic-gate int col;
20700Sstevel@tonic-gate int fd;
20710Sstevel@tonic-gate
20720Sstevel@tonic-gate for (col = 0; col < mr->un_totalcolumncnt; col++) {
20730Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
20740Sstevel@tonic-gate mdname_t *colnp = cp->colnamep;
20750Sstevel@tonic-gate
20760Sstevel@tonic-gate if ((fd = open(colnp->rname, O_RDONLY)) < 0)
20770Sstevel@tonic-gate goto error_exit;
20780Sstevel@tonic-gate
20790Sstevel@tonic-gate if (lseek64(fd,
20800Sstevel@tonic-gate (mr->un_column[col].un_pwstart * DEV_BSIZE), SEEK_SET) < 0)
20810Sstevel@tonic-gate goto error_exit;
20820Sstevel@tonic-gate
20830Sstevel@tonic-gate if (read(fd, buf, DEV_BSIZE) < 0)
20840Sstevel@tonic-gate goto error_exit;
20850Sstevel@tonic-gate
20860Sstevel@tonic-gate /*
20870Sstevel@tonic-gate * If our raid device is a 64 bit device, we can accept the
20880Sstevel@tonic-gate * pw header we just read in.
20890Sstevel@tonic-gate * Otherwise it's of type raid_pwhdr32_od_t and has to
20900Sstevel@tonic-gate * be converted.
20910Sstevel@tonic-gate */
20921623Stw21770 if (mr->c.un_revision & MD_64BIT_META_DEV) {
20930Sstevel@tonic-gate rpw = (raid_pwhdr_t *)buf;
20940Sstevel@tonic-gate } else {
20950Sstevel@tonic-gate RAID_CONVERT_RPW((raid_pwhdr32_od_t *)buf, rpw);
20960Sstevel@tonic-gate }
20970Sstevel@tonic-gate
20980Sstevel@tonic-gate if (rpw->rpw_column != col)
20990Sstevel@tonic-gate goto error_exit;
21000Sstevel@tonic-gate
21010Sstevel@tonic-gate if (col == 0)
21020Sstevel@tonic-gate mnum = rpw->rpw_unit;
21030Sstevel@tonic-gate
21040Sstevel@tonic-gate if (rpw->rpw_unit != mnum)
21050Sstevel@tonic-gate goto error_exit;
21060Sstevel@tonic-gate
21070Sstevel@tonic-gate if (rpw->rpw_magic_ext == RAID_PWMAGIC) {
21080Sstevel@tonic-gate /* 4.1 prewrite header */
21090Sstevel@tonic-gate if ((rpw->rpw_origcolumncnt != mr->un_origcolumncnt) ||
21107087Ssk102515 (rpw->rpw_totalcolumncnt !=
21117087Ssk102515 mr->un_totalcolumncnt) ||
21120Sstevel@tonic-gate (rpw->rpw_segsize != mr->un_segsize) ||
21130Sstevel@tonic-gate (rpw->rpw_segsincolumn != mr->un_segsincolumn) ||
21140Sstevel@tonic-gate (rpw->rpw_pwcnt != mr->un_pwcnt) ||
21150Sstevel@tonic-gate (rpw->rpw_pwstart !=
21167087Ssk102515 mr->un_column[col].un_pwstart) ||
21170Sstevel@tonic-gate (rpw->rpw_devstart !=
21187087Ssk102515 mr->un_column[col].un_devstart) ||
21190Sstevel@tonic-gate (rpw->rpw_pwsize != mr->un_pwsize))
21200Sstevel@tonic-gate goto error_exit;
21210Sstevel@tonic-gate }
21220Sstevel@tonic-gate /*
21230Sstevel@tonic-gate * this is an old prewrite header (4.0) the unit structure
21240Sstevel@tonic-gate * will have to be trusted.
21250Sstevel@tonic-gate */
21260Sstevel@tonic-gate (void) close(fd);
21270Sstevel@tonic-gate }
21280Sstevel@tonic-gate
21290Sstevel@tonic-gate return (0);
21300Sstevel@tonic-gate
21310Sstevel@tonic-gate error_exit:
21320Sstevel@tonic-gate (void) close(fd);
21330Sstevel@tonic-gate return (-1);
21340Sstevel@tonic-gate }
21350Sstevel@tonic-gate
21360Sstevel@tonic-gate /*
21370Sstevel@tonic-gate * create raid
21380Sstevel@tonic-gate */
21390Sstevel@tonic-gate int
meta_create_raid(mdsetname_t * sp,md_raid_t * raidp,mdcmdopts_t options,md_error_t * ep)21400Sstevel@tonic-gate meta_create_raid(
21410Sstevel@tonic-gate mdsetname_t *sp,
21420Sstevel@tonic-gate md_raid_t *raidp,
21430Sstevel@tonic-gate mdcmdopts_t options,
21440Sstevel@tonic-gate md_error_t *ep
21450Sstevel@tonic-gate )
21460Sstevel@tonic-gate {
21470Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep;
21480Sstevel@tonic-gate uint_t ncol = raidp->cols.cols_len;
21490Sstevel@tonic-gate uint_t orig_ncol = raidp->orig_ncol;
21500Sstevel@tonic-gate size_t rdsize;
21510Sstevel@tonic-gate mr_unit_t *mr;
21520Sstevel@tonic-gate uint_t col;
21530Sstevel@tonic-gate diskaddr_t disk_size = 0;
21540Sstevel@tonic-gate uint_t disk_maxio = 0;
21550Sstevel@tonic-gate uint_t pwes;
21560Sstevel@tonic-gate diskaddr_t non_pw_blks, column_size;
21570Sstevel@tonic-gate mdnamelist_t *keynlp = NULL;
21580Sstevel@tonic-gate md_set_params_t set_params;
21590Sstevel@tonic-gate int rval = -1;
21600Sstevel@tonic-gate md_timeval32_t creation_time;
21610Sstevel@tonic-gate int create_flag = MD_CRO_32BIT;
21620Sstevel@tonic-gate
21630Sstevel@tonic-gate /* validate raid */
21640Sstevel@tonic-gate if (meta_check_raid(sp, raidp, options, ep) != 0)
21650Sstevel@tonic-gate return (-1);
21660Sstevel@tonic-gate
21670Sstevel@tonic-gate /* allocate raid unit */
21680Sstevel@tonic-gate rdsize = sizeof (*mr) - sizeof (mr->un_column[0]);
21690Sstevel@tonic-gate rdsize += ncol * sizeof (mr->un_column[0]);
21700Sstevel@tonic-gate mr = Zalloc(rdsize);
21710Sstevel@tonic-gate
21720Sstevel@tonic-gate if (meta_gettimeofday(&creation_time) == -1)
21730Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
21740Sstevel@tonic-gate /*
21750Sstevel@tonic-gate * initialize the top level mr_unit_t structure
21760Sstevel@tonic-gate * setup the unit state to indicate whether to retain
21770Sstevel@tonic-gate * any data currently on the metadevice or to clear it
21780Sstevel@tonic-gate */
21790Sstevel@tonic-gate mr->c.un_type = MD_METARAID;
21800Sstevel@tonic-gate MD_SID(mr) = meta_getminor(raidnp->dev);
21810Sstevel@tonic-gate mr->c.un_size = rdsize;
21820Sstevel@tonic-gate mr->un_magic = RAID_UNMAGIC;
21830Sstevel@tonic-gate mr->un_state = raidp->state;
21840Sstevel@tonic-gate mr->un_timestamp = creation_time;
21850Sstevel@tonic-gate mr->un_origcolumncnt = orig_ncol;
21860Sstevel@tonic-gate mr->un_segsize = (uint_t)raidp->interlace;
21870Sstevel@tonic-gate if (raidp->hspnamep != NULL) {
21880Sstevel@tonic-gate mr->un_hsp_id = raidp->hspnamep->hsp;
21890Sstevel@tonic-gate } else {
21900Sstevel@tonic-gate mr->un_hsp_id = MD_HSP_NONE;
21910Sstevel@tonic-gate }
21920Sstevel@tonic-gate /*
21930Sstevel@tonic-gate * setup original columns, saving start_block and
21940Sstevel@tonic-gate * finding smallest size and maxio
21950Sstevel@tonic-gate */
21960Sstevel@tonic-gate for (col = 0; (col < orig_ncol); ++col) {
21970Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
21980Sstevel@tonic-gate mdname_t *colnp = cp->colnamep;
21990Sstevel@tonic-gate mr_column_t *mdc = &mr->un_column[col];
22000Sstevel@tonic-gate diskaddr_t size;
22010Sstevel@tonic-gate uint_t maxio;
22020Sstevel@tonic-gate mdcinfo_t *cinfop;
22030Sstevel@tonic-gate
22040Sstevel@tonic-gate /* setup state */
22050Sstevel@tonic-gate mdc->un_devstate = cp->state;
22060Sstevel@tonic-gate
22070Sstevel@tonic-gate /* setup creation time */
22080Sstevel@tonic-gate mdc->un_devtimestamp = creation_time;
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate /* get start, size, and maxio */
22110Sstevel@tonic-gate if ((mdc->un_orig_devstart = metagetstart(sp, colnp, ep)) ==
22120Sstevel@tonic-gate MD_DISKADDR_ERROR)
22130Sstevel@tonic-gate goto out;
22140Sstevel@tonic-gate if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR)
22150Sstevel@tonic-gate goto out;
22160Sstevel@tonic-gate size -= mdc->un_orig_devstart;
22170Sstevel@tonic-gate if ((cinfop = metagetcinfo(colnp, ep)) == NULL)
22180Sstevel@tonic-gate goto out;
22190Sstevel@tonic-gate maxio = cinfop->maxtransfer;
22200Sstevel@tonic-gate
22210Sstevel@tonic-gate if (options & MDCMD_DOIT) {
22220Sstevel@tonic-gate /* store name in namespace */
22230Sstevel@tonic-gate if (add_key_name(sp, colnp, &keynlp, ep) != 0)
22240Sstevel@tonic-gate goto out;
22250Sstevel@tonic-gate }
22260Sstevel@tonic-gate
22270Sstevel@tonic-gate /* setup column */
22280Sstevel@tonic-gate mdc->un_orig_key = colnp->key;
22290Sstevel@tonic-gate mdc->un_orig_dev = colnp->dev;
22300Sstevel@tonic-gate mdc->un_dev = mdc->un_orig_dev;
22310Sstevel@tonic-gate mdc->un_pwstart = mdc->un_orig_pwstart;
22320Sstevel@tonic-gate mdc->un_devstart = mdc->un_orig_devstart;
22330Sstevel@tonic-gate mdc->un_alt_dev = NODEV64;
22340Sstevel@tonic-gate mdc->un_alt_pwstart = 0;
22350Sstevel@tonic-gate mdc->un_alt_devstart = 0;
22360Sstevel@tonic-gate mdc->un_hs_id = 0;
22370Sstevel@tonic-gate if (mr->un_state == RUS_INIT)
22380Sstevel@tonic-gate mdc->un_devstate = RCS_INIT;
22390Sstevel@tonic-gate else
22400Sstevel@tonic-gate mdc->un_devstate = RCS_OKAY;
22410Sstevel@tonic-gate
22420Sstevel@tonic-gate /* adjust for smallest disk */
22430Sstevel@tonic-gate if (disk_size == 0) {
22440Sstevel@tonic-gate disk_size = size;
22450Sstevel@tonic-gate } else if (size < disk_size) {
22460Sstevel@tonic-gate disk_size = size;
22470Sstevel@tonic-gate }
22480Sstevel@tonic-gate if (disk_maxio == 0) {
22490Sstevel@tonic-gate disk_maxio = maxio;
22500Sstevel@tonic-gate } else if (maxio < disk_maxio) {
22510Sstevel@tonic-gate disk_maxio = maxio;
22520Sstevel@tonic-gate }
22530Sstevel@tonic-gate }
22540Sstevel@tonic-gate assert(col == mr->un_origcolumncnt);
22550Sstevel@tonic-gate
22560Sstevel@tonic-gate /*
22570Sstevel@tonic-gate * before processing any of the attached column(s)
22580Sstevel@tonic-gate * set up the composition of the metadevice for column
22590Sstevel@tonic-gate * sizes and pre-write information
22600Sstevel@tonic-gate */
22610Sstevel@tonic-gate mr->un_maxio = disk_maxio; /* smallest maxio */
22620Sstevel@tonic-gate mr->un_iosize = min(mr->un_maxio, (mr->un_segsize + 1));
22630Sstevel@tonic-gate pwes = mr->un_iosize;
22640Sstevel@tonic-gate if (raidp->pw_count)
22650Sstevel@tonic-gate mr->un_pwcnt = raidp->pw_count;
22660Sstevel@tonic-gate else
22670Sstevel@tonic-gate mr->un_pwcnt = PWCNT_MIN;
22680Sstevel@tonic-gate if ((mr->un_pwcnt < PWCNT_MIN) || (mr->un_pwcnt > PWCNT_MAX)) {
22690Sstevel@tonic-gate (void) mderror(ep, MDE_RAID_BAD_PW_CNT, raidnp->cname);
22700Sstevel@tonic-gate goto out;
22710Sstevel@tonic-gate }
22720Sstevel@tonic-gate mr->un_pwsize = roundup((mr->un_pwcnt * pwes), 2);
22730Sstevel@tonic-gate
22740Sstevel@tonic-gate /* now calculate the number of segments per column */
22750Sstevel@tonic-gate non_pw_blks = disk_size - mr->un_pwsize; /* smallest disk */
22760Sstevel@tonic-gate if ((mr->un_pwsize > disk_size) ||
22770Sstevel@tonic-gate (non_pw_blks < (diskaddr_t)mr->un_segsize)) {
22780Sstevel@tonic-gate (void) mdsyserror(ep, ENOSPC, raidnp->cname);
22790Sstevel@tonic-gate goto out;
22800Sstevel@tonic-gate }
22810Sstevel@tonic-gate mr->un_segsincolumn = non_pw_blks / mr->un_segsize;
22820Sstevel@tonic-gate column_size = mr->un_segsize * mr->un_segsincolumn;
22830Sstevel@tonic-gate
22840Sstevel@tonic-gate /*
22850Sstevel@tonic-gate * adjust the pw_cnt, pw_size, to fit into any fragmentation
22860Sstevel@tonic-gate * left over after column_size has been computed
22870Sstevel@tonic-gate */
22880Sstevel@tonic-gate mr->un_pwsize = rounddown(((uint_t)(disk_size - column_size)), 2);
22890Sstevel@tonic-gate mr->un_pwcnt = mr->un_pwsize / pwes;
22900Sstevel@tonic-gate assert(mr->un_pwcnt >= PWCNT_MIN);
22910Sstevel@tonic-gate mr->un_pwsize = roundup((mr->un_pwcnt * pwes), 2);
22920Sstevel@tonic-gate assert((mr->un_pwsize + column_size) <= disk_size);
22930Sstevel@tonic-gate
22940Sstevel@tonic-gate /*
22950Sstevel@tonic-gate * calculate the actual block count available based on the
22960Sstevel@tonic-gate * segment size and the number of segments per column ...
22970Sstevel@tonic-gate * ... and adjust for the number of parity segments
22980Sstevel@tonic-gate */
22990Sstevel@tonic-gate mr->c.un_actual_tb = column_size * (mr->un_origcolumncnt - 1);
23000Sstevel@tonic-gate
23010Sstevel@tonic-gate if (raid_geom(raidp, mr, ep) != 0)
23020Sstevel@tonic-gate goto out;
23030Sstevel@tonic-gate
23040Sstevel@tonic-gate create_flag = meta_check_devicesize(mr->c.un_total_blocks);
23050Sstevel@tonic-gate
23060Sstevel@tonic-gate /*
23070Sstevel@tonic-gate * now calculate the pre-write offset and update the column
23080Sstevel@tonic-gate * structures to include the address of the individual pre-write
23090Sstevel@tonic-gate * areas
23100Sstevel@tonic-gate */
23110Sstevel@tonic-gate for (col = 0; (col < orig_ncol); ++col) {
23120Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
23130Sstevel@tonic-gate mdname_t *colnp = cp->colnamep;
23140Sstevel@tonic-gate mr_column_t *mdc = &mr->un_column[col];
23150Sstevel@tonic-gate diskaddr_t size;
23160Sstevel@tonic-gate
23170Sstevel@tonic-gate /* get size */
23180Sstevel@tonic-gate if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR)
23190Sstevel@tonic-gate goto out;
23200Sstevel@tonic-gate
23210Sstevel@tonic-gate /* adjust start and size by prewrite */
23220Sstevel@tonic-gate mdc->un_orig_pwstart = mdc->un_orig_devstart;
23230Sstevel@tonic-gate mdc->un_orig_devstart += mr->un_pwsize;
23240Sstevel@tonic-gate mdc->un_pwstart = mdc->un_orig_pwstart;
23250Sstevel@tonic-gate mdc->un_devstart = mdc->un_orig_devstart;
23260Sstevel@tonic-gate
23270Sstevel@tonic-gate assert(size >= mdc->un_orig_devstart);
23280Sstevel@tonic-gate size -= mdc->un_orig_devstart;
23290Sstevel@tonic-gate
23300Sstevel@tonic-gate /* make sure we still have something left */
23310Sstevel@tonic-gate assert(size >= column_size);
23320Sstevel@tonic-gate }
23330Sstevel@tonic-gate
23340Sstevel@tonic-gate /* do concat cols */
23350Sstevel@tonic-gate mr->un_totalcolumncnt = mr->un_origcolumncnt;
23360Sstevel@tonic-gate assert(col == mr->un_origcolumncnt);
23370Sstevel@tonic-gate for (col = orig_ncol; (col < ncol); ++col) {
23380Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
23390Sstevel@tonic-gate mdname_t *colnp = cp->colnamep;
23400Sstevel@tonic-gate mr_column_t *mdc = &mr->un_column[col];
23410Sstevel@tonic-gate
23420Sstevel@tonic-gate /* attach column */
23430Sstevel@tonic-gate if (attach_raid_col(sp, raidnp, mr, mdc, colnp,
23440Sstevel@tonic-gate cp->state, &keynlp, options, ep) != 0) {
23450Sstevel@tonic-gate goto out;
23460Sstevel@tonic-gate }
23470Sstevel@tonic-gate }
23480Sstevel@tonic-gate assert(mr->un_totalcolumncnt == ncol);
23490Sstevel@tonic-gate
23500Sstevel@tonic-gate /* fill in the size of the raid */
23510Sstevel@tonic-gate if (options & MDCMD_UPDATE) {
23520Sstevel@tonic-gate raidp->common.size = mr->c.un_total_blocks;
23530Sstevel@tonic-gate raidp->column_size = mr->un_segsize * mr->un_segsincolumn;
23540Sstevel@tonic-gate }
23550Sstevel@tonic-gate
23560Sstevel@tonic-gate /* if we're not doing anything, return success */
23570Sstevel@tonic-gate if (! (options & MDCMD_DOIT)) {
23580Sstevel@tonic-gate rval = 0; /* success */
23590Sstevel@tonic-gate goto out;
23600Sstevel@tonic-gate }
23610Sstevel@tonic-gate
23620Sstevel@tonic-gate if ((mr->un_state & RUS_OKAY) &&
23630Sstevel@tonic-gate (meta_raid_valid(raidp, mr) != 0)) {
23640Sstevel@tonic-gate (void) mderror(ep, MDE_RAID_INVALID, raidnp->cname);
23650Sstevel@tonic-gate goto out;
23660Sstevel@tonic-gate }
23670Sstevel@tonic-gate
23680Sstevel@tonic-gate /* create raid */
23690Sstevel@tonic-gate (void) memset(&set_params, 0, sizeof (set_params));
23700Sstevel@tonic-gate /* did the user tell us to generate a large device? */
23710Sstevel@tonic-gate if (create_flag == MD_CRO_64BIT) {
23721623Stw21770 mr->c.un_revision |= MD_64BIT_META_DEV;
23730Sstevel@tonic-gate set_params.options = MD_CRO_64BIT;
23740Sstevel@tonic-gate } else {
23751623Stw21770 mr->c.un_revision &= ~MD_64BIT_META_DEV;
23760Sstevel@tonic-gate set_params.options = MD_CRO_32BIT;
23770Sstevel@tonic-gate }
23780Sstevel@tonic-gate set_params.mnum = MD_SID(mr);
23790Sstevel@tonic-gate set_params.size = mr->c.un_size;
23800Sstevel@tonic-gate set_params.mdp = (uintptr_t)mr;
23810Sstevel@tonic-gate MD_SETDRIVERNAME(&set_params, MD_RAID, MD_MIN2SET(set_params.mnum));
23820Sstevel@tonic-gate if (metaioctl(MD_IOCSET, &set_params, &set_params.mde,
23830Sstevel@tonic-gate raidnp->cname) != 0) {
23840Sstevel@tonic-gate (void) mdstealerror(ep, &set_params.mde);
23850Sstevel@tonic-gate goto out;
23860Sstevel@tonic-gate }
23870Sstevel@tonic-gate rval = 0; /* success */
23880Sstevel@tonic-gate
23890Sstevel@tonic-gate /* cleanup, return success */
23900Sstevel@tonic-gate out:
23910Sstevel@tonic-gate Free(mr);
23920Sstevel@tonic-gate if (rval != 0) {
23930Sstevel@tonic-gate (void) del_key_names(sp, keynlp, NULL);
23940Sstevel@tonic-gate }
23950Sstevel@tonic-gate metafreenamelist(keynlp);
23960Sstevel@tonic-gate if ((rval == 0) && (options & MDCMD_DOIT)) {
23970Sstevel@tonic-gate if (invalidate_columns(sp, raidnp, ep) != 0)
23980Sstevel@tonic-gate rval = -1;
23990Sstevel@tonic-gate meta_invalidate_name(raidnp);
24000Sstevel@tonic-gate }
24010Sstevel@tonic-gate return (rval);
24020Sstevel@tonic-gate }
24030Sstevel@tonic-gate
24040Sstevel@tonic-gate /*
24050Sstevel@tonic-gate * initialize raid
24060Sstevel@tonic-gate * NOTE: this functions is metainit(1m)'s command line parser!
24070Sstevel@tonic-gate */
24080Sstevel@tonic-gate int
meta_init_raid(mdsetname_t ** spp,int argc,char * argv[],mdcmdopts_t options,md_error_t * ep)24090Sstevel@tonic-gate meta_init_raid(
24100Sstevel@tonic-gate mdsetname_t **spp,
24110Sstevel@tonic-gate int argc,
24120Sstevel@tonic-gate char *argv[],
24130Sstevel@tonic-gate mdcmdopts_t options,
24140Sstevel@tonic-gate md_error_t *ep
24150Sstevel@tonic-gate )
24160Sstevel@tonic-gate {
24170Sstevel@tonic-gate char *uname = argv[0];
24180Sstevel@tonic-gate mdname_t *raidnp = NULL;
24190Sstevel@tonic-gate int old_optind;
24200Sstevel@tonic-gate int c;
24210Sstevel@tonic-gate md_raid_t *raidp = NULL;
24220Sstevel@tonic-gate uint_t ncol, col;
24230Sstevel@tonic-gate int rval = -1;
24240Sstevel@tonic-gate md_set_desc *sd;
24250Sstevel@tonic-gate
24260Sstevel@tonic-gate /* get raid name */
24270Sstevel@tonic-gate assert(argc > 0);
24280Sstevel@tonic-gate if (argc < 1)
24290Sstevel@tonic-gate goto syntax;
24301623Stw21770 if ((raidnp = metaname(spp, uname, META_DEVICE, ep)) == NULL)
24310Sstevel@tonic-gate goto out;
24320Sstevel@tonic-gate assert(*spp != NULL);
24330Sstevel@tonic-gate
24340Sstevel@tonic-gate /*
24350Sstevel@tonic-gate * Raid metadevice not allowed on multi-node diskset.
24360Sstevel@tonic-gate */
24370Sstevel@tonic-gate if (! metaislocalset(*spp)) {
24380Sstevel@tonic-gate if ((sd = metaget_setdesc(*spp, ep)) == NULL)
24390Sstevel@tonic-gate goto out;
24400Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) {
24410Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_MNSET_NORAID, uname,
24427087Ssk102515 argc, argv);
24430Sstevel@tonic-gate goto out;
24440Sstevel@tonic-gate }
24450Sstevel@tonic-gate }
24460Sstevel@tonic-gate
24470Sstevel@tonic-gate uname = raidnp->cname;
24480Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0)
24490Sstevel@tonic-gate goto out;
24500Sstevel@tonic-gate
24510Sstevel@tonic-gate if (!(options & MDCMD_NOLOCK)) {
24520Sstevel@tonic-gate /* grab set lock */
24530Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep) != 0)
24540Sstevel@tonic-gate goto out;
24550Sstevel@tonic-gate
24560Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0)
24570Sstevel@tonic-gate goto out;
24580Sstevel@tonic-gate }
24590Sstevel@tonic-gate
24600Sstevel@tonic-gate /* see if it exists already */
24610Sstevel@tonic-gate if (metagetmiscname(raidnp, ep) != NULL) {
24620Sstevel@tonic-gate (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP,
24630Sstevel@tonic-gate meta_getminor(raidnp->dev), uname);
24640Sstevel@tonic-gate goto out;
24650Sstevel@tonic-gate } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) {
24660Sstevel@tonic-gate goto out;
24670Sstevel@tonic-gate } else {
24680Sstevel@tonic-gate mdclrerror(ep);
24690Sstevel@tonic-gate }
24700Sstevel@tonic-gate --argc, ++argv;
24710Sstevel@tonic-gate
24720Sstevel@tonic-gate /* grab -r */
24730Sstevel@tonic-gate if ((argc < 1) || (strcmp(argv[0], "-r") != 0))
24740Sstevel@tonic-gate goto syntax;
24750Sstevel@tonic-gate --argc, ++argv;
24760Sstevel@tonic-gate
24770Sstevel@tonic-gate /* parse general options */
24780Sstevel@tonic-gate optind = 0;
24790Sstevel@tonic-gate opterr = 0;
24800Sstevel@tonic-gate if (getopt(argc, argv, "") != -1)
24810Sstevel@tonic-gate goto options;
24820Sstevel@tonic-gate
24830Sstevel@tonic-gate /* allocate raid */
24840Sstevel@tonic-gate raidp = Zalloc(sizeof (*raidp));
24850Sstevel@tonic-gate
24860Sstevel@tonic-gate /* setup common */
24870Sstevel@tonic-gate raidp->common.namep = raidnp;
24880Sstevel@tonic-gate raidp->common.type = MD_METARAID;
24890Sstevel@tonic-gate raidp->state = RUS_INIT;
24900Sstevel@tonic-gate
24910Sstevel@tonic-gate /* allocate and parse cols */
24920Sstevel@tonic-gate for (ncol = 0; ((ncol < argc) && (argv[ncol][0] != '-')); ++ncol)
24930Sstevel@tonic-gate ;
24940Sstevel@tonic-gate raidp->cols.cols_len = ncol;
24950Sstevel@tonic-gate if (ncol != 0) {
24960Sstevel@tonic-gate raidp->cols.cols_val =
24970Sstevel@tonic-gate Zalloc(ncol * sizeof (*raidp->cols.cols_val));
24980Sstevel@tonic-gate }
24990Sstevel@tonic-gate for (col = 0; ((argc > 0) && (col < ncol)); ++col) {
25000Sstevel@tonic-gate md_raidcol_t *mdc = &raidp->cols.cols_val[col];
25010Sstevel@tonic-gate mdname_t *colnp;
25020Sstevel@tonic-gate
25030Sstevel@tonic-gate /* parse column name */
25041623Stw21770 if ((colnp = metaname(spp, argv[0], UNKNOWN, ep)) == NULL)
25050Sstevel@tonic-gate goto out;
25060Sstevel@tonic-gate /* check for soft partitions */
25070Sstevel@tonic-gate if (meta_sp_issp(*spp, colnp, ep) != 0) {
25080Sstevel@tonic-gate /* check disks */
25090Sstevel@tonic-gate if (metachkcomp(colnp, ep) != 0)
25100Sstevel@tonic-gate goto out;
25110Sstevel@tonic-gate }
25120Sstevel@tonic-gate mdc->colnamep = colnp;
25130Sstevel@tonic-gate --argc, ++argv;
25140Sstevel@tonic-gate }
25150Sstevel@tonic-gate
25160Sstevel@tonic-gate /* parse raid options */
25170Sstevel@tonic-gate old_optind = optind = 0;
25180Sstevel@tonic-gate opterr = 0;
25190Sstevel@tonic-gate while ((c = getopt(argc, argv, "h:i:ko:w:")) != -1) {
25200Sstevel@tonic-gate switch (c) {
25210Sstevel@tonic-gate case 'h':
25220Sstevel@tonic-gate if ((raidp->hspnamep = metahspname(spp, optarg,
25230Sstevel@tonic-gate ep)) == NULL) {
25240Sstevel@tonic-gate goto out;
25250Sstevel@tonic-gate }
25262099Stn143363
25272099Stn143363 /*
25282099Stn143363 * Get out if the specified hotspare pool really
25292099Stn143363 * doesn't exist.
25302099Stn143363 */
25312099Stn143363 if (raidp->hspnamep->hsp == MD_HSP_NONE) {
25322099Stn143363 (void) mdhsperror(ep, MDE_INVAL_HSP,
25332099Stn143363 raidp->hspnamep->hsp, optarg);
25342099Stn143363 goto out;
25352099Stn143363 }
25360Sstevel@tonic-gate break;
25370Sstevel@tonic-gate
25380Sstevel@tonic-gate case 'i':
25390Sstevel@tonic-gate if (parse_interlace(uname, optarg, &raidp->interlace,
25400Sstevel@tonic-gate ep) != 0) {
25410Sstevel@tonic-gate goto out;
25420Sstevel@tonic-gate }
25430Sstevel@tonic-gate if (meta_raid_check_interlace(raidp->interlace,
25440Sstevel@tonic-gate uname, ep))
25450Sstevel@tonic-gate goto out;
25460Sstevel@tonic-gate break;
25470Sstevel@tonic-gate
25480Sstevel@tonic-gate case 'k':
25490Sstevel@tonic-gate raidp->state = RUS_OKAY;
25500Sstevel@tonic-gate break;
25510Sstevel@tonic-gate
25520Sstevel@tonic-gate case 'o':
25530Sstevel@tonic-gate if ((sscanf(optarg, "%u", &raidp->orig_ncol) != 1) ||
25540Sstevel@tonic-gate ((int)raidp->orig_ncol < 0)) {
25550Sstevel@tonic-gate goto syntax;
25560Sstevel@tonic-gate }
25570Sstevel@tonic-gate if ((raidp->orig_ncol < MD_RAID_MIN) ||
25580Sstevel@tonic-gate (raidp->orig_ncol > ncol)) {
25590Sstevel@tonic-gate rval = mderror(ep, MDE_BAD_ORIG_NCOL, uname);
25600Sstevel@tonic-gate goto out;
25610Sstevel@tonic-gate }
25620Sstevel@tonic-gate break;
25630Sstevel@tonic-gate case 'w':
25640Sstevel@tonic-gate if ((sscanf(optarg, "%d", &raidp->pw_count) != 1) ||
25650Sstevel@tonic-gate ((int)raidp->pw_count < 0))
25660Sstevel@tonic-gate goto syntax;
25670Sstevel@tonic-gate if (((int)raidp->pw_count < PWCNT_MIN) ||
25680Sstevel@tonic-gate ((int)raidp->pw_count > PWCNT_MAX)) {
25690Sstevel@tonic-gate rval = mderror(ep, MDE_RAID_BAD_PW_CNT, uname);
25700Sstevel@tonic-gate goto out;
25710Sstevel@tonic-gate }
25720Sstevel@tonic-gate break;
25730Sstevel@tonic-gate default:
25740Sstevel@tonic-gate argc += old_optind;
25750Sstevel@tonic-gate argv -= old_optind;
25760Sstevel@tonic-gate goto options;
25770Sstevel@tonic-gate }
25780Sstevel@tonic-gate old_optind = optind;
25790Sstevel@tonic-gate }
25800Sstevel@tonic-gate argc -= optind;
25810Sstevel@tonic-gate argv += optind;
25820Sstevel@tonic-gate
25830Sstevel@tonic-gate /* we should be at the end */
25840Sstevel@tonic-gate if (argc != 0)
25850Sstevel@tonic-gate goto syntax;
25860Sstevel@tonic-gate
25870Sstevel@tonic-gate /* default to all original columns */
25880Sstevel@tonic-gate if (raidp->orig_ncol == 0)
25890Sstevel@tonic-gate raidp->orig_ncol = ncol;
25900Sstevel@tonic-gate
25910Sstevel@tonic-gate /* create raid */
25920Sstevel@tonic-gate if (meta_create_raid(*spp, raidp, options, ep) != 0)
25930Sstevel@tonic-gate goto out;
25940Sstevel@tonic-gate rval = 0; /* success */
25950Sstevel@tonic-gate
25960Sstevel@tonic-gate /* let em know */
25970Sstevel@tonic-gate if (options & MDCMD_PRINT) {
25980Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "%s: RAID is setup\n"),
25990Sstevel@tonic-gate uname);
26000Sstevel@tonic-gate (void) fflush(stdout);
26010Sstevel@tonic-gate }
26020Sstevel@tonic-gate goto out;
26030Sstevel@tonic-gate
26040Sstevel@tonic-gate /* syntax error */
26050Sstevel@tonic-gate syntax:
26060Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_SYNTAX, uname, argc, argv);
26070Sstevel@tonic-gate goto out;
26080Sstevel@tonic-gate
26090Sstevel@tonic-gate /* options error */
26100Sstevel@tonic-gate options:
26110Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_OPTION, uname, argc, argv);
26120Sstevel@tonic-gate goto out;
26130Sstevel@tonic-gate
26140Sstevel@tonic-gate /* cleanup, return error */
26150Sstevel@tonic-gate out:
26160Sstevel@tonic-gate if (raidp != NULL)
26170Sstevel@tonic-gate meta_free_raid(raidp);
26180Sstevel@tonic-gate return (rval);
26190Sstevel@tonic-gate }
26200Sstevel@tonic-gate
26210Sstevel@tonic-gate /*
26220Sstevel@tonic-gate * reset RAIDs
26230Sstevel@tonic-gate */
26240Sstevel@tonic-gate int
meta_raid_reset(mdsetname_t * sp,mdname_t * raidnp,mdcmdopts_t options,md_error_t * ep)26250Sstevel@tonic-gate meta_raid_reset(
26260Sstevel@tonic-gate mdsetname_t *sp,
26270Sstevel@tonic-gate mdname_t *raidnp,
26280Sstevel@tonic-gate mdcmdopts_t options,
26290Sstevel@tonic-gate md_error_t *ep
26300Sstevel@tonic-gate )
26310Sstevel@tonic-gate {
26320Sstevel@tonic-gate md_raid_t *raidp;
26330Sstevel@tonic-gate int rval = -1;
26340Sstevel@tonic-gate int col;
26350Sstevel@tonic-gate
26360Sstevel@tonic-gate /* should have same set */
26370Sstevel@tonic-gate assert(sp != NULL);
26380Sstevel@tonic-gate assert((raidnp == NULL) ||
26390Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))));
26400Sstevel@tonic-gate
26410Sstevel@tonic-gate /* reset all raids */
26420Sstevel@tonic-gate if (raidnp == NULL) {
26430Sstevel@tonic-gate mdnamelist_t *raidnlp = NULL;
26440Sstevel@tonic-gate mdnamelist_t *p;
26450Sstevel@tonic-gate
26460Sstevel@tonic-gate /* for each raid */
26470Sstevel@tonic-gate rval = 0;
26480Sstevel@tonic-gate if (meta_get_raid_names(sp, &raidnlp, 0, ep) < 0)
26490Sstevel@tonic-gate return (-1);
26500Sstevel@tonic-gate for (p = raidnlp; (p != NULL); p = p->next) {
26510Sstevel@tonic-gate /* reset RAID */
26520Sstevel@tonic-gate raidnp = p->namep;
26530Sstevel@tonic-gate if (meta_raid_reset(sp, raidnp, options, ep) != 0) {
26540Sstevel@tonic-gate rval = -1;
26550Sstevel@tonic-gate break;
26560Sstevel@tonic-gate }
26570Sstevel@tonic-gate }
26580Sstevel@tonic-gate
26590Sstevel@tonic-gate /* cleanup, return success */
26600Sstevel@tonic-gate metafreenamelist(raidnlp);
26610Sstevel@tonic-gate return (rval);
26620Sstevel@tonic-gate }
26630Sstevel@tonic-gate
26640Sstevel@tonic-gate /* check name */
26650Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0)
26660Sstevel@tonic-gate return (-1);
26670Sstevel@tonic-gate
26680Sstevel@tonic-gate /* get unit structure */
26690Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL)
26700Sstevel@tonic-gate return (-1);
26710Sstevel@tonic-gate
26720Sstevel@tonic-gate /* make sure nobody owns us */
26730Sstevel@tonic-gate if (MD_HAS_PARENT(raidp->common.parent)) {
26740Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_USE, meta_getminor(raidnp->dev),
26750Sstevel@tonic-gate raidnp->cname));
26760Sstevel@tonic-gate }
26770Sstevel@tonic-gate
26780Sstevel@tonic-gate /* clear subdevices cache */
26790Sstevel@tonic-gate if (invalidate_columns(sp, raidnp, ep) != 0)
26800Sstevel@tonic-gate return (-1);
26810Sstevel@tonic-gate
26820Sstevel@tonic-gate /* clear metadevice */
26830Sstevel@tonic-gate if (meta_reset(sp, raidnp, options, ep) != 0)
26840Sstevel@tonic-gate goto out;
26850Sstevel@tonic-gate rval = 0; /* success */
26860Sstevel@tonic-gate
26870Sstevel@tonic-gate /* let em know */
26880Sstevel@tonic-gate if (options & MDCMD_PRINT) {
26890Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "%s: RAID is cleared\n"),
26900Sstevel@tonic-gate raidnp->cname);
26910Sstevel@tonic-gate (void) fflush(stdout);
26920Sstevel@tonic-gate }
26930Sstevel@tonic-gate
26940Sstevel@tonic-gate /* clear subdevices */
26950Sstevel@tonic-gate if (! (options & MDCMD_RECURSE))
26960Sstevel@tonic-gate goto out;
26970Sstevel@tonic-gate
26980Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) {
26990Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col];
27000Sstevel@tonic-gate mdname_t *colnp = cp->colnamep;
27010Sstevel@tonic-gate
27020Sstevel@tonic-gate /* only recurse on metadevices */
27030Sstevel@tonic-gate if (! metaismeta(colnp))
27040Sstevel@tonic-gate continue;
27050Sstevel@tonic-gate
27060Sstevel@tonic-gate if (meta_reset_by_name(sp, colnp, options, ep) != 0)
27070Sstevel@tonic-gate rval = -1;
27080Sstevel@tonic-gate }
27090Sstevel@tonic-gate
27100Sstevel@tonic-gate /* cleanup, return success */
27110Sstevel@tonic-gate out:
27120Sstevel@tonic-gate meta_invalidate_name(raidnp);
27130Sstevel@tonic-gate return (rval);
27140Sstevel@tonic-gate }
27150Sstevel@tonic-gate
27160Sstevel@tonic-gate /*
27170Sstevel@tonic-gate * reports TRUE if any RAID component is in error
27180Sstevel@tonic-gate */
27190Sstevel@tonic-gate int
meta_raid_anycomp_is_err(mdsetname_t * sp,mdnamelist_t * raid_names)27200Sstevel@tonic-gate meta_raid_anycomp_is_err(mdsetname_t *sp, mdnamelist_t *raid_names)
27210Sstevel@tonic-gate {
27220Sstevel@tonic-gate mdnamelist_t *nlp;
27230Sstevel@tonic-gate md_error_t status = mdnullerror;
27240Sstevel@tonic-gate md_error_t *ep = &status;
27250Sstevel@tonic-gate int any_errs = FALSE;
27260Sstevel@tonic-gate
27270Sstevel@tonic-gate for (nlp = raid_names; nlp; nlp = nlp->next) {
27280Sstevel@tonic-gate md_raid_t *raidp;
27290Sstevel@tonic-gate
27300Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, nlp->namep, ep)) == NULL) {
27310Sstevel@tonic-gate any_errs |= TRUE;
27320Sstevel@tonic-gate goto out;
27330Sstevel@tonic-gate }
27340Sstevel@tonic-gate if (raidp->state != RUS_OKAY && raidp->state != RUS_INIT) {
27350Sstevel@tonic-gate any_errs |= TRUE;
27360Sstevel@tonic-gate goto out;
27370Sstevel@tonic-gate }
27380Sstevel@tonic-gate }
27390Sstevel@tonic-gate out:
27400Sstevel@tonic-gate if (!mdisok(ep))
27410Sstevel@tonic-gate mdclrerror(ep);
27420Sstevel@tonic-gate
27430Sstevel@tonic-gate return (any_errs);
27440Sstevel@tonic-gate }
27450Sstevel@tonic-gate /*
27460Sstevel@tonic-gate * regen parity on a raid
27470Sstevel@tonic-gate */
27480Sstevel@tonic-gate int
meta_raid_regen_byname(mdsetname_t * sp,mdname_t * raidnp,diskaddr_t size,md_error_t * ep)27490Sstevel@tonic-gate meta_raid_regen_byname(mdsetname_t *sp, mdname_t *raidnp, diskaddr_t size,
27500Sstevel@tonic-gate md_error_t *ep)
27510Sstevel@tonic-gate {
27520Sstevel@tonic-gate char *miscname;
27530Sstevel@tonic-gate md_resync_ioctl_t ri;
27540Sstevel@tonic-gate
27550Sstevel@tonic-gate /* should have a set */
27560Sstevel@tonic-gate assert(sp != NULL);
27570Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)));
27580Sstevel@tonic-gate
27590Sstevel@tonic-gate /* make sure we have a raid */
27600Sstevel@tonic-gate if ((miscname = metagetmiscname(raidnp, ep)) == NULL)
27610Sstevel@tonic-gate return (-1);
27620Sstevel@tonic-gate if (strcmp(miscname, MD_RAID) != 0) {
27630Sstevel@tonic-gate return (mdmderror(ep, MDE_NOT_RAID, meta_getminor(raidnp->dev),
27640Sstevel@tonic-gate raidnp->cname));
27650Sstevel@tonic-gate }
27660Sstevel@tonic-gate
27670Sstevel@tonic-gate /* start resync */
27680Sstevel@tonic-gate (void) memset(&ri, 0, sizeof (ri));
27690Sstevel@tonic-gate MD_SETDRIVERNAME(&ri, MD_RAID, sp->setno);
27700Sstevel@tonic-gate ri.ri_mnum = meta_getminor(raidnp->dev);
27710Sstevel@tonic-gate ri.ri_copysize = size;
27720Sstevel@tonic-gate if (metaioctl(MD_IOCSETREGEN, &ri, &ri.mde, raidnp->cname) != 0)
27730Sstevel@tonic-gate return (mdstealerror(ep, &ri.mde));
27740Sstevel@tonic-gate
27750Sstevel@tonic-gate /* return success */
27760Sstevel@tonic-gate return (0);
27770Sstevel@tonic-gate }
27787087Ssk102515
27797087Ssk102515 int
meta_raid_check_component(mdsetname_t * sp,mdname_t * np,md_dev64_t mydevs,md_error_t * ep)27807087Ssk102515 meta_raid_check_component(
27817087Ssk102515 mdsetname_t *sp,
27827087Ssk102515 mdname_t *np,
27837087Ssk102515 md_dev64_t mydevs,
27847087Ssk102515 md_error_t *ep
27857087Ssk102515 )
27867087Ssk102515 {
27877087Ssk102515 md_raid_t *raid;
27887087Ssk102515 mdnm_params_t nm;
27897087Ssk102515 md_getdevs_params_t mgd;
27907087Ssk102515 side_t sideno;
27917087Ssk102515 char *miscname;
27927087Ssk102515 md_dev64_t *mydev = NULL;
27937087Ssk102515 mdkey_t key;
2794*7779SPeter.Dennis@Sun.COM char *pname = NULL, *t;
2795*7779SPeter.Dennis@Sun.COM char *ctd_name = NULL;
2796*7779SPeter.Dennis@Sun.COM char *devname = NULL;
27977087Ssk102515 int len;
27987087Ssk102515 int i;
27997087Ssk102515 int rval = -1;
28007087Ssk102515
28017087Ssk102515 (void) memset(&nm, '\0', sizeof (nm));
28027087Ssk102515 if ((raid = meta_get_raid_common(sp, np, 0, ep)) == NULL)
28037087Ssk102515 return (-1);
28047087Ssk102515
28057087Ssk102515 if ((miscname = metagetmiscname(np, ep)) == NULL)
28067087Ssk102515 return (-1);
28077087Ssk102515
28087087Ssk102515 sideno = getmyside(sp, ep);
28097087Ssk102515
28107087Ssk102515 /* get count of underlying devices */
28117087Ssk102515
28127087Ssk102515 (void) memset(&mgd, '\0', sizeof (mgd));
28137087Ssk102515 MD_SETDRIVERNAME(&mgd, miscname, sp->setno);
28147087Ssk102515 mgd.mnum = meta_getminor(np->dev);
28157087Ssk102515 mgd.cnt = 0;
28167087Ssk102515 mgd.devs = NULL;
28177087Ssk102515 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) {
28187087Ssk102515 (void) mdstealerror(ep, &mgd.mde);
28197087Ssk102515 rval = 0;
28207087Ssk102515 goto out;
28217087Ssk102515 } else if (mgd.cnt <= 0) {
28227087Ssk102515 assert(mgd.cnt >= 0);
28237087Ssk102515 rval = 0;
28247087Ssk102515 goto out;
28257087Ssk102515 }
28267087Ssk102515
28277087Ssk102515 /*
28287087Ssk102515 * Now get the data from the unit structure.
28297087Ssk102515 * The compnamep stuff contains the data from
28307087Ssk102515 * the namespace and we need the un_dev
28317087Ssk102515 * from the unit structure.
28327087Ssk102515 */
28337087Ssk102515 mydev = Zalloc(sizeof (*mydev) * mgd.cnt);
28347087Ssk102515 mgd.devs = (uintptr_t)mydev;
28357087Ssk102515 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) {
28367087Ssk102515 (void) mdstealerror(ep, &mgd.mde);
28377087Ssk102515 rval = 0;
28387087Ssk102515 goto out;
28397087Ssk102515 } else if (mgd.cnt <= 0) {
28407087Ssk102515 assert(mgd.cnt >= 0);
28417087Ssk102515 rval = 0;
28427087Ssk102515 goto out;
28437087Ssk102515 }
28447087Ssk102515
28457087Ssk102515 for (i = 0; i < raid->orig_ncol; i++) {
28467087Ssk102515 md_raidcol_t *colp = &raid->cols.cols_val[i];
28477087Ssk102515 mdname_t *compnp = colp->colnamep;
28487087Ssk102515
28497087Ssk102515 if (mydevs == mydev[i]) {
28507087Ssk102515 /* Get the devname from the name space. */
28517087Ssk102515 if ((devname = meta_getnmentbydev(sp->setno, sideno,
28527087Ssk102515 compnp->dev, NULL, NULL, &key, ep)) == NULL) {
28537087Ssk102515 goto out;
28547087Ssk102515 }
28557087Ssk102515
28567087Ssk102515 if (compnp->dev != meta_getminor(mydev[i])) {
28577087Ssk102515 /*
28587087Ssk102515 * The minor numbers are different. Update
28597087Ssk102515 * the namespace with the information from
28607087Ssk102515 * the component.
28617087Ssk102515 */
28627087Ssk102515
28637087Ssk102515 t = strrchr(devname, '/');
28647087Ssk102515 t++;
28657087Ssk102515 ctd_name = Strdup(t);
28667087Ssk102515
28677087Ssk102515 len = strlen(devname);
28687087Ssk102515 t = strrchr(devname, '/');
28697087Ssk102515 t++;
28707087Ssk102515 pname = Zalloc((len - strlen(t)) + 1);
28717087Ssk102515 (void) strncpy(pname, devname,
28727087Ssk102515 (len - strlen(t)));
28737087Ssk102515
28747087Ssk102515 if (meta_update_namespace(sp->setno, sideno,
28757087Ssk102515 ctd_name, mydev[i], key, pname,
28767087Ssk102515 ep) != 0) {
28777087Ssk102515 goto out;
28787087Ssk102515 }
28797087Ssk102515 }
28807087Ssk102515 rval = 0;
28817087Ssk102515 break;
28827087Ssk102515 } /* End of if (mydevs == mydev[i]) */
28837087Ssk102515 } /* end of for loop */
28847087Ssk102515 out:
28857087Ssk102515 if (pname != NULL)
28867087Ssk102515 Free(pname);
28877087Ssk102515 if (ctd_name != NULL)
28887087Ssk102515 Free(ctd_name);
28897087Ssk102515 if (devname != NULL)
28907087Ssk102515 Free(devname);
28917087Ssk102515 if (mydev != NULL)
28927087Ssk102515 Free(mydev);
28937087Ssk102515 return (rval);
28947087Ssk102515 }
2895