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