1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that 31*0Sstevel@tonic-gate * TEXT_DOMAIN gets set to something. 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 34*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 35*0Sstevel@tonic-gate #endif 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* 38*0Sstevel@tonic-gate * stripe operations 39*0Sstevel@tonic-gate */ 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #include <limits.h> 42*0Sstevel@tonic-gate #include <stdlib.h> 43*0Sstevel@tonic-gate #include <meta.h> 44*0Sstevel@tonic-gate #include <sys/lvm/md_stripe.h> 45*0Sstevel@tonic-gate #include <sys/lvm/md_convert.h> 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate #define QUOTE(x) #x 48*0Sstevel@tonic-gate #define VAL2STR(x) QUOTE(x) 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* 51*0Sstevel@tonic-gate * replace stripe/concat 52*0Sstevel@tonic-gate */ 53*0Sstevel@tonic-gate int 54*0Sstevel@tonic-gate meta_stripe_replace( 55*0Sstevel@tonic-gate mdsetname_t *sp, 56*0Sstevel@tonic-gate mdname_t *stripenp, 57*0Sstevel@tonic-gate mdname_t *oldnp, 58*0Sstevel@tonic-gate mdname_t *newnp, 59*0Sstevel@tonic-gate mdcmdopts_t options, 60*0Sstevel@tonic-gate md_error_t *ep 61*0Sstevel@tonic-gate ) 62*0Sstevel@tonic-gate { 63*0Sstevel@tonic-gate replace_params_t params; 64*0Sstevel@tonic-gate md_dev64_t old_dev, 65*0Sstevel@tonic-gate new_dev; 66*0Sstevel@tonic-gate diskaddr_t new_start_blk, 67*0Sstevel@tonic-gate new_end_blk, 68*0Sstevel@tonic-gate label, 69*0Sstevel@tonic-gate size, 70*0Sstevel@tonic-gate start_blk; 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate /* should have same set */ 73*0Sstevel@tonic-gate assert(sp != NULL); 74*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate new_dev = newnp->dev; 77*0Sstevel@tonic-gate new_start_blk = newnp->start_blk; 78*0Sstevel@tonic-gate new_end_blk = newnp->end_blk; 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate meta_invalidate_name(stripenp); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* the old device binding is now established */ 83*0Sstevel@tonic-gate if ((old_dev = oldnp->dev) == NODEV64) 84*0Sstevel@tonic-gate return (mdsyserror(ep, ENODEV, oldnp->cname)); 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate if (((strcmp(oldnp->rname, newnp->rname) == 0) && 87*0Sstevel@tonic-gate (old_dev != new_dev))) { 88*0Sstevel@tonic-gate newnp->dev = new_dev; 89*0Sstevel@tonic-gate newnp->start_blk = new_start_blk; 90*0Sstevel@tonic-gate newnp->end_blk = new_end_blk; 91*0Sstevel@tonic-gate } 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate if ((size = metagetsize(newnp, ep)) == MD_DISKADDR_ERROR) 94*0Sstevel@tonic-gate return (-1); 95*0Sstevel@tonic-gate if ((label = metagetlabel(newnp, ep)) == MD_DISKADDR_ERROR) 96*0Sstevel@tonic-gate return (-1); 97*0Sstevel@tonic-gate if ((start_blk = metagetstart(sp, newnp, ep)) == MD_DISKADDR_ERROR) 98*0Sstevel@tonic-gate return (-1); 99*0Sstevel@tonic-gate if (start_blk >= size) { 100*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOSPC, newnp->cname); 101*0Sstevel@tonic-gate return (-1); 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate /* In dryrun mode (DOIT not set) we must not alter the mddb */ 105*0Sstevel@tonic-gate if (options & MDCMD_DOIT) { 106*0Sstevel@tonic-gate if (add_key_name(sp, newnp, NULL, ep) != 0) 107*0Sstevel@tonic-gate return (-1); 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* 111*0Sstevel@tonic-gate * There is no need to call meta_fixdevid() here as this function is 112*0Sstevel@tonic-gate * only called by the metareplace -c command which actually does 113*0Sstevel@tonic-gate * nothing (in terms of a resync) and thus does nothing with the devid. 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate (void) memset(¶ms, 0, sizeof (params)); 117*0Sstevel@tonic-gate params.mnum = meta_getminor(stripenp->dev); 118*0Sstevel@tonic-gate MD_SETDRIVERNAME(¶ms, MD_STRIPE, sp->setno); 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate params.cmd = REPLACE_COMP; 121*0Sstevel@tonic-gate params.old_dev = old_dev; 122*0Sstevel@tonic-gate params.new_dev = new_dev; 123*0Sstevel@tonic-gate params.new_key = newnp->key; 124*0Sstevel@tonic-gate params.start_blk = newnp->start_blk; 125*0Sstevel@tonic-gate params.number_blks = size; 126*0Sstevel@tonic-gate /* Is this just a dryrun ? */ 127*0Sstevel@tonic-gate if ((options & MDCMD_DOIT) == 0) { 128*0Sstevel@tonic-gate params.options |= MDIOCTL_DRYRUN; 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate if (label == 0) 131*0Sstevel@tonic-gate params.has_label = 0; 132*0Sstevel@tonic-gate else 133*0Sstevel@tonic-gate params.has_label = 1; 134*0Sstevel@tonic-gate if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) { 135*0Sstevel@tonic-gate if (options & MDCMD_DOIT) 136*0Sstevel@tonic-gate (void) del_key_name(sp, newnp, ep); 137*0Sstevel@tonic-gate return (mdstealerror(ep, ¶ms.mde)); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate meta_invalidate_name(oldnp); 140*0Sstevel@tonic-gate meta_invalidate_name(newnp); 141*0Sstevel@tonic-gate meta_invalidate_name(stripenp); 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 144*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 145*0Sstevel@tonic-gate "%s: device %s is replaced with %s\n"), 146*0Sstevel@tonic-gate stripenp->cname, oldnp->cname, newnp->cname); 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate return (0); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate /* 154*0Sstevel@tonic-gate * FUNCTION: meta_get_stripe_names() 155*0Sstevel@tonic-gate * INPUT: sp - the set name to get stripes from 156*0Sstevel@tonic-gate * options - options from the command line 157*0Sstevel@tonic-gate * OUTPUT: nlpp - list of all stripe names 158*0Sstevel@tonic-gate * ep - return error pointer 159*0Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 success 160*0Sstevel@tonic-gate * PURPOSE: returns a list of all stripes in the metadb 161*0Sstevel@tonic-gate * for all devices in the specified set 162*0Sstevel@tonic-gate */ 163*0Sstevel@tonic-gate int 164*0Sstevel@tonic-gate meta_get_stripe_names( 165*0Sstevel@tonic-gate mdsetname_t *sp, 166*0Sstevel@tonic-gate mdnamelist_t **nlpp, 167*0Sstevel@tonic-gate int options, 168*0Sstevel@tonic-gate md_error_t *ep 169*0Sstevel@tonic-gate ) 170*0Sstevel@tonic-gate { 171*0Sstevel@tonic-gate return (meta_get_names(MD_STRIPE, sp, nlpp, options, ep)); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* 175*0Sstevel@tonic-gate * free stripe 176*0Sstevel@tonic-gate */ 177*0Sstevel@tonic-gate void 178*0Sstevel@tonic-gate meta_free_stripe( 179*0Sstevel@tonic-gate md_stripe_t *stripep 180*0Sstevel@tonic-gate ) 181*0Sstevel@tonic-gate { 182*0Sstevel@tonic-gate uint_t row; 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 185*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate if (rp->comps.comps_val != NULL) { 188*0Sstevel@tonic-gate assert(rp->comps.comps_len > 0); 189*0Sstevel@tonic-gate Free(rp->comps.comps_val); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate if (stripep->rows.rows_val != NULL) { 193*0Sstevel@tonic-gate assert(stripep->rows.rows_len > 0); 194*0Sstevel@tonic-gate Free(stripep->rows.rows_val); 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate Free(stripep); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate /* 201*0Sstevel@tonic-gate * get stripe (common) 202*0Sstevel@tonic-gate */ 203*0Sstevel@tonic-gate md_stripe_t * 204*0Sstevel@tonic-gate meta_get_stripe_common( 205*0Sstevel@tonic-gate mdsetname_t *sp, 206*0Sstevel@tonic-gate mdname_t *stripenp, 207*0Sstevel@tonic-gate int fast, 208*0Sstevel@tonic-gate md_error_t *ep 209*0Sstevel@tonic-gate ) 210*0Sstevel@tonic-gate { 211*0Sstevel@tonic-gate mddrivename_t *dnp = stripenp->drivenamep; 212*0Sstevel@tonic-gate char *miscname; 213*0Sstevel@tonic-gate ms_unit_t *ms; 214*0Sstevel@tonic-gate md_stripe_t *stripep; 215*0Sstevel@tonic-gate uint_t row; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate /* must have set */ 218*0Sstevel@tonic-gate assert(sp != NULL); 219*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate /* short circuit */ 222*0Sstevel@tonic-gate if (dnp->unitp != NULL) { 223*0Sstevel@tonic-gate assert(dnp->unitp->type == MD_DEVICE); 224*0Sstevel@tonic-gate return ((md_stripe_t *)dnp->unitp); 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate /* get miscname and unit */ 228*0Sstevel@tonic-gate if ((miscname = metagetmiscname(stripenp, ep)) == NULL) 229*0Sstevel@tonic-gate return (NULL); 230*0Sstevel@tonic-gate if (strcmp(miscname, MD_STRIPE) != 0) { 231*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_NOT_STRIPE, 232*0Sstevel@tonic-gate meta_getminor(stripenp->dev), stripenp->cname); 233*0Sstevel@tonic-gate return (NULL); 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate if ((ms = (ms_unit_t *)meta_get_mdunit(sp, stripenp, ep)) == NULL) 236*0Sstevel@tonic-gate return (NULL); 237*0Sstevel@tonic-gate assert(ms->c.un_type == MD_DEVICE); 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate /* allocate stripe */ 240*0Sstevel@tonic-gate stripep = Zalloc(sizeof (*stripep)); 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* allocate rows */ 243*0Sstevel@tonic-gate assert(ms->un_nrows > 0); 244*0Sstevel@tonic-gate stripep->rows.rows_len = ms->un_nrows; 245*0Sstevel@tonic-gate stripep->rows.rows_val = Zalloc(stripep->rows.rows_len * 246*0Sstevel@tonic-gate sizeof (*stripep->rows.rows_val)); 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate /* get common info */ 249*0Sstevel@tonic-gate stripep->common.namep = stripenp; 250*0Sstevel@tonic-gate stripep->common.type = ms->c.un_type; 251*0Sstevel@tonic-gate stripep->common.state = ms->c.un_status; 252*0Sstevel@tonic-gate stripep->common.capabilities = ms->c.un_capabilities; 253*0Sstevel@tonic-gate stripep->common.parent = ms->c.un_parent; 254*0Sstevel@tonic-gate stripep->common.size = ms->c.un_total_blocks; 255*0Sstevel@tonic-gate stripep->common.user_flags = ms->c.un_user_flags; 256*0Sstevel@tonic-gate stripep->common.revision = ms->c.un_revision; 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate /* get options */ 259*0Sstevel@tonic-gate if ((ms->un_hsp_id != MD_HSP_NONE) && 260*0Sstevel@tonic-gate ((stripep->hspnamep = metahsphspname(&sp, ms->un_hsp_id, 261*0Sstevel@tonic-gate ep)) == NULL)) { 262*0Sstevel@tonic-gate goto out; 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate /* get rows */ 266*0Sstevel@tonic-gate for (row = 0; (row < ms->un_nrows); ++row) { 267*0Sstevel@tonic-gate struct ms_row *mdr = &ms->un_row[row]; 268*0Sstevel@tonic-gate struct ms_comp *mdcomp = (void *)&((char *)ms)[ms->un_ocomp]; 269*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 270*0Sstevel@tonic-gate uint_t comp, c; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate /* get interlace */ 273*0Sstevel@tonic-gate rp->interlace = mdr->un_interlace; 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* allocate comps */ 276*0Sstevel@tonic-gate assert(mdr->un_ncomp > 0); 277*0Sstevel@tonic-gate rp->comps.comps_len = mdr->un_ncomp; 278*0Sstevel@tonic-gate rp->comps.comps_val = Zalloc(rp->comps.comps_len * 279*0Sstevel@tonic-gate sizeof (*rp->comps.comps_val)); 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate /* get components */ 282*0Sstevel@tonic-gate for (comp = 0, c = mdr->un_icomp; (comp < mdr->un_ncomp); 283*0Sstevel@tonic-gate ++comp, ++c) { 284*0Sstevel@tonic-gate struct ms_comp *mdc = &mdcomp[c]; 285*0Sstevel@tonic-gate diskaddr_t comp_start_blk = mdc->un_start_block; 286*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* get the component name */ 289*0Sstevel@tonic-gate cp->compnamep = metakeyname(&sp, mdc->un_key, fast, ep); 290*0Sstevel@tonic-gate if (cp->compnamep == NULL) 291*0Sstevel@tonic-gate goto out; 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate /* if hotspared */ 294*0Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) { 295*0Sstevel@tonic-gate diskaddr_t hs_start_blk = mdc->un_start_block; 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate /* get the hotspare name */ 298*0Sstevel@tonic-gate cp->hsnamep = metakeyname(&sp, 299*0Sstevel@tonic-gate mdc->un_mirror.ms_hs_key, fast, ep); 300*0Sstevel@tonic-gate if (cp->hsnamep == NULL) 301*0Sstevel@tonic-gate goto out; 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate if (getenv("META_DEBUG_START_BLK") != NULL) { 304*0Sstevel@tonic-gate if (metagetstart(sp, cp->hsnamep, 305*0Sstevel@tonic-gate ep) == MD_DISKADDR_ERROR) 306*0Sstevel@tonic-gate mdclrerror(ep); 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate if ((cp->hsnamep->start_blk == 0) && 309*0Sstevel@tonic-gate (hs_start_blk != 0)) 310*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 311*0Sstevel@tonic-gate "%s: suspected bad start block," 312*0Sstevel@tonic-gate " seems labelled [stripe/hs]\n"), 313*0Sstevel@tonic-gate cp->hsnamep->cname); 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate if ((cp->hsnamep->start_blk > 0) && 316*0Sstevel@tonic-gate (hs_start_blk == 0) && 317*0Sstevel@tonic-gate ! ((row == 0) && (comp == 0))) 318*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 319*0Sstevel@tonic-gate "%s: suspected bad start block, " 320*0Sstevel@tonic-gate "seems unlabelled [stripe/hs]\n"), 321*0Sstevel@tonic-gate cp->hsnamep->cname); 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate /* override any start_blk */ 324*0Sstevel@tonic-gate cp->hsnamep->start_blk = hs_start_blk; 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* get the right component start_blk */ 327*0Sstevel@tonic-gate comp_start_blk = mdc->un_mirror.ms_orig_blk; 328*0Sstevel@tonic-gate } else { 329*0Sstevel@tonic-gate if (getenv("META_DEBUG_START_BLK") != NULL) { 330*0Sstevel@tonic-gate if (metagetstart(sp, cp->compnamep, 331*0Sstevel@tonic-gate ep) == MD_DISKADDR_ERROR) 332*0Sstevel@tonic-gate mdclrerror(ep); 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate if ((cp->compnamep->start_blk == 0) && 335*0Sstevel@tonic-gate (comp_start_blk != 0)) 336*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 337*0Sstevel@tonic-gate "%s: suspected bad start block," 338*0Sstevel@tonic-gate " seems labelled [stripe]"), 339*0Sstevel@tonic-gate cp->compnamep->cname); 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate if ((cp->compnamep->start_blk > 0) && 342*0Sstevel@tonic-gate (comp_start_blk == 0) && 343*0Sstevel@tonic-gate ! ((row == 0) && (comp == 0))) 344*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 345*0Sstevel@tonic-gate "%s: suspected bad start block, " 346*0Sstevel@tonic-gate "seems unlabelled [stripe]"), 347*0Sstevel@tonic-gate cp->compnamep->cname); 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate /* override any start_blk */ 352*0Sstevel@tonic-gate cp->compnamep->start_blk = comp_start_blk; 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate /* get state */ 355*0Sstevel@tonic-gate cp->state = mdc->un_mirror.ms_state; 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate /* get time of last state change */ 358*0Sstevel@tonic-gate cp->timestamp = mdc->un_mirror.ms_timestamp; 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /* get lasterr count */ 361*0Sstevel@tonic-gate cp->lasterrcnt = mdc->un_mirror.ms_lasterrcnt; 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate /* cleanup, return success */ 366*0Sstevel@tonic-gate Free(ms); 367*0Sstevel@tonic-gate dnp->unitp = (md_common_t *)stripep; 368*0Sstevel@tonic-gate return (stripep); 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate /* cleanup, return error */ 371*0Sstevel@tonic-gate out: 372*0Sstevel@tonic-gate Free(ms); 373*0Sstevel@tonic-gate meta_free_stripe(stripep); 374*0Sstevel@tonic-gate return (NULL); 375*0Sstevel@tonic-gate } 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate /* 378*0Sstevel@tonic-gate * get stripe 379*0Sstevel@tonic-gate */ 380*0Sstevel@tonic-gate md_stripe_t * 381*0Sstevel@tonic-gate meta_get_stripe( 382*0Sstevel@tonic-gate mdsetname_t *sp, 383*0Sstevel@tonic-gate mdname_t *stripenp, 384*0Sstevel@tonic-gate md_error_t *ep 385*0Sstevel@tonic-gate ) 386*0Sstevel@tonic-gate { 387*0Sstevel@tonic-gate return (meta_get_stripe_common(sp, stripenp, 0, ep)); 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate /* 391*0Sstevel@tonic-gate * check stripe for dev 392*0Sstevel@tonic-gate */ 393*0Sstevel@tonic-gate static int 394*0Sstevel@tonic-gate in_stripe( 395*0Sstevel@tonic-gate mdsetname_t *sp, 396*0Sstevel@tonic-gate mdname_t *stripenp, 397*0Sstevel@tonic-gate mdname_t *np, 398*0Sstevel@tonic-gate diskaddr_t slblk, 399*0Sstevel@tonic-gate diskaddr_t nblks, 400*0Sstevel@tonic-gate md_error_t *ep 401*0Sstevel@tonic-gate ) 402*0Sstevel@tonic-gate { 403*0Sstevel@tonic-gate md_stripe_t *stripep; 404*0Sstevel@tonic-gate uint_t row; 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate /* should be in the same set */ 407*0Sstevel@tonic-gate assert(sp != NULL); 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate /* get unit */ 410*0Sstevel@tonic-gate if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL) 411*0Sstevel@tonic-gate return (-1); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate /* look in rows */ 414*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 415*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 416*0Sstevel@tonic-gate uint_t comp; 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate /* look in columns */ 419*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 420*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 421*0Sstevel@tonic-gate mdname_t *compnp = cp->compnamep; 422*0Sstevel@tonic-gate diskaddr_t comp_sblk; 423*0Sstevel@tonic-gate int err; 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* check same drive since metagetstart() can fail */ 426*0Sstevel@tonic-gate if ((err = meta_check_samedrive(np, compnp, ep)) < 0) 427*0Sstevel@tonic-gate return (-1); 428*0Sstevel@tonic-gate else if (err == 0) 429*0Sstevel@tonic-gate continue; 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate /* check overlap */ 432*0Sstevel@tonic-gate if ((comp_sblk = metagetstart(sp, compnp, ep)) == 433*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 434*0Sstevel@tonic-gate return (-1); 435*0Sstevel@tonic-gate if (meta_check_overlap(stripenp->cname, np, 436*0Sstevel@tonic-gate slblk, nblks, compnp, comp_sblk, -1, 437*0Sstevel@tonic-gate ep) != 0) { 438*0Sstevel@tonic-gate return (-1); 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate } 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate /* return success */ 444*0Sstevel@tonic-gate return (0); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate /* 448*0Sstevel@tonic-gate * check to see if we're in a stripe 449*0Sstevel@tonic-gate */ 450*0Sstevel@tonic-gate int 451*0Sstevel@tonic-gate meta_check_instripe( 452*0Sstevel@tonic-gate mdsetname_t *sp, 453*0Sstevel@tonic-gate mdname_t *np, 454*0Sstevel@tonic-gate diskaddr_t slblk, 455*0Sstevel@tonic-gate diskaddr_t nblks, 456*0Sstevel@tonic-gate md_error_t *ep 457*0Sstevel@tonic-gate ) 458*0Sstevel@tonic-gate { 459*0Sstevel@tonic-gate mdnamelist_t *stripenlp = NULL; 460*0Sstevel@tonic-gate mdnamelist_t *p; 461*0Sstevel@tonic-gate int rval = 0; 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate /* should have a set */ 464*0Sstevel@tonic-gate assert(sp != NULL); 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate /* for each stripe */ 467*0Sstevel@tonic-gate if (meta_get_stripe_names(sp, &stripenlp, 0, ep) < 0) 468*0Sstevel@tonic-gate return (-1); 469*0Sstevel@tonic-gate for (p = stripenlp; (p != NULL); p = p->next) { 470*0Sstevel@tonic-gate mdname_t *stripenp = p->namep; 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate /* check stripe */ 473*0Sstevel@tonic-gate if (in_stripe(sp, stripenp, np, slblk, nblks, ep) != 0) { 474*0Sstevel@tonic-gate rval = -1; 475*0Sstevel@tonic-gate break; 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate /* cleanup, return success */ 480*0Sstevel@tonic-gate metafreenamelist(stripenlp); 481*0Sstevel@tonic-gate return (rval); 482*0Sstevel@tonic-gate } 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate /* 485*0Sstevel@tonic-gate * check component 486*0Sstevel@tonic-gate */ 487*0Sstevel@tonic-gate int 488*0Sstevel@tonic-gate meta_check_component( 489*0Sstevel@tonic-gate mdsetname_t *sp, 490*0Sstevel@tonic-gate mdname_t *np, 491*0Sstevel@tonic-gate int force, 492*0Sstevel@tonic-gate md_error_t *ep 493*0Sstevel@tonic-gate ) 494*0Sstevel@tonic-gate { 495*0Sstevel@tonic-gate mdchkopts_t options = (MDCHK_ALLOW_MDDB); 496*0Sstevel@tonic-gate md_common_t *mdp; 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate /* 499*0Sstevel@tonic-gate * See if we are a soft partition: meta_sp_issp() returns 0 if 500*0Sstevel@tonic-gate * np points to a soft partition, so the if and else clauses 501*0Sstevel@tonic-gate * here represent "not a soft partition" and "soft partition," 502*0Sstevel@tonic-gate * respectively. 503*0Sstevel@tonic-gate */ 504*0Sstevel@tonic-gate if (meta_sp_issp(sp, np, ep) != 0) { 505*0Sstevel@tonic-gate /* make sure we have a disk */ 506*0Sstevel@tonic-gate if (metachkcomp(np, ep) != 0) 507*0Sstevel@tonic-gate return (-1); 508*0Sstevel@tonic-gate } else { 509*0Sstevel@tonic-gate /* make sure soft partition can parent & doesn't have parent */ 510*0Sstevel@tonic-gate if ((mdp = meta_get_unit(sp, np, ep)) == NULL) 511*0Sstevel@tonic-gate return (mdmderror(ep, MDE_INVAL_UNIT, NULL, 512*0Sstevel@tonic-gate np->cname)); 513*0Sstevel@tonic-gate if (mdp->capabilities == MD_CANT_PARENT) 514*0Sstevel@tonic-gate return (mdmderror(ep, MDE_INVAL_UNIT, NULL, 515*0Sstevel@tonic-gate np->cname)); 516*0Sstevel@tonic-gate if (MD_HAS_PARENT(mdp->parent)) { 517*0Sstevel@tonic-gate mdname_t *pnp; 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate pnp = metamnumname(&sp, mdp->parent, 0, ep); 520*0Sstevel@tonic-gate if (pnp == NULL) { 521*0Sstevel@tonic-gate return (-1); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate return (mduseerror(ep, MDE_ALREADY, np->dev, 525*0Sstevel@tonic-gate pnp->cname, np->cname)); 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate /* check to ensure that it is not already in use */ 530*0Sstevel@tonic-gate if ((! force) && 531*0Sstevel@tonic-gate (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0)) { 532*0Sstevel@tonic-gate return (-1); 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate /* make sure it is in the set */ 536*0Sstevel@tonic-gate if (meta_check_inset(sp, np, ep) != 0) 537*0Sstevel@tonic-gate return (-1); 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate /* make sure its not in a metadevice */ 540*0Sstevel@tonic-gate if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0) 541*0Sstevel@tonic-gate return (-1); 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate /* return success */ 544*0Sstevel@tonic-gate return (0); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate /* 548*0Sstevel@tonic-gate * print stripe 549*0Sstevel@tonic-gate */ 550*0Sstevel@tonic-gate static int 551*0Sstevel@tonic-gate stripe_print( 552*0Sstevel@tonic-gate md_stripe_t *stripep, 553*0Sstevel@tonic-gate char *fname, 554*0Sstevel@tonic-gate FILE *fp, 555*0Sstevel@tonic-gate mdprtopts_t options, 556*0Sstevel@tonic-gate md_error_t *ep 557*0Sstevel@tonic-gate ) 558*0Sstevel@tonic-gate { 559*0Sstevel@tonic-gate uint_t row; 560*0Sstevel@tonic-gate int rval = -1; 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate if (options & PRINT_LARGEDEVICES) { 563*0Sstevel@tonic-gate if (stripep->common.revision != MD_64BIT_META_DEV) { 564*0Sstevel@tonic-gate rval = 0; 565*0Sstevel@tonic-gate goto out; 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate /* print name and num rows */ 570*0Sstevel@tonic-gate if (fprintf(fp, "%s %u", 571*0Sstevel@tonic-gate stripep->common.namep->cname, stripep->rows.rows_len) == EOF) 572*0Sstevel@tonic-gate goto out; 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate /* print rows */ 575*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 576*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 577*0Sstevel@tonic-gate uint_t comp; 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate /* print num components */ 580*0Sstevel@tonic-gate if (fprintf(fp, " %u", rp->comps.comps_len) == EOF) 581*0Sstevel@tonic-gate goto out; 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate /* print components */ 584*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 585*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate /* print component */ 588*0Sstevel@tonic-gate /* 589*0Sstevel@tonic-gate * If the path is our standard /dev/rdsk or /dev/md/rdsk 590*0Sstevel@tonic-gate * then just print out the cxtxdxsx or the dx, metainit 591*0Sstevel@tonic-gate * will assume the default, otherwise we need the full 592*0Sstevel@tonic-gate * pathname to make sure this works as we intend. 593*0Sstevel@tonic-gate */ 594*0Sstevel@tonic-gate if ((strstr(cp->compnamep->rname, "/dev/rdsk") == 595*0Sstevel@tonic-gate NULL) && (strstr(cp->compnamep->rname, 596*0Sstevel@tonic-gate "/dev/md/rdsk") == NULL) && 597*0Sstevel@tonic-gate (strstr(cp->compnamep->rname, "/dev/td/") == 598*0Sstevel@tonic-gate NULL)) { 599*0Sstevel@tonic-gate /* not standard path, print full pathname */ 600*0Sstevel@tonic-gate if (fprintf(fp, " %s", cp->compnamep->rname) 601*0Sstevel@tonic-gate == EOF) 602*0Sstevel@tonic-gate goto out; 603*0Sstevel@tonic-gate } else { 604*0Sstevel@tonic-gate /* standard path */ 605*0Sstevel@tonic-gate if (fprintf(fp, " %s", cp->compnamep->cname) 606*0Sstevel@tonic-gate == EOF) 607*0Sstevel@tonic-gate goto out; 608*0Sstevel@tonic-gate } 609*0Sstevel@tonic-gate } 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate /* print interlace */ 612*0Sstevel@tonic-gate if (rp->comps.comps_len > 1) 613*0Sstevel@tonic-gate if (fprintf(fp, " -i %lldb", rp->interlace) == EOF) 614*0Sstevel@tonic-gate goto out; 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate /* print continuation */ 617*0Sstevel@tonic-gate if (row != (stripep->rows.rows_len - 1)) 618*0Sstevel@tonic-gate if (fprintf(fp, " \\\n\t") == EOF) 619*0Sstevel@tonic-gate goto out; 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate /* print hotspare name */ 623*0Sstevel@tonic-gate if (stripep->hspnamep != NULL) 624*0Sstevel@tonic-gate if (fprintf(fp, " -h %s", stripep->hspnamep->hspname) == EOF) 625*0Sstevel@tonic-gate goto out; 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate /* terminate last line */ 628*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 629*0Sstevel@tonic-gate goto out; 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate /* success */ 632*0Sstevel@tonic-gate rval = 0; 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate /* cleanup, return error */ 635*0Sstevel@tonic-gate out: 636*0Sstevel@tonic-gate if (rval != 0) 637*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 638*0Sstevel@tonic-gate return (rval); 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate /* 642*0Sstevel@tonic-gate * convert component state to name 643*0Sstevel@tonic-gate */ 644*0Sstevel@tonic-gate char * 645*0Sstevel@tonic-gate comp_state_to_name( 646*0Sstevel@tonic-gate md_comp_t *mdcp, 647*0Sstevel@tonic-gate md_timeval32_t *tvp, 648*0Sstevel@tonic-gate uint_t tstate /* Errored tstate flags */ 649*0Sstevel@tonic-gate ) 650*0Sstevel@tonic-gate { 651*0Sstevel@tonic-gate comp_state_t state = mdcp->state; 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate /* grab time */ 654*0Sstevel@tonic-gate if (tvp != NULL) 655*0Sstevel@tonic-gate *tvp = mdcp->timestamp; 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate if (tstate != 0) { 658*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unavailable")); 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate /* return state */ 662*0Sstevel@tonic-gate switch (state) { 663*0Sstevel@tonic-gate case CS_OKAY: 664*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Okay")); 665*0Sstevel@tonic-gate case CS_ERRED: 666*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Maintenance")); 667*0Sstevel@tonic-gate case CS_LAST_ERRED: 668*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Last Erred")); 669*0Sstevel@tonic-gate case CS_RESYNC: 670*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resyncing")); 671*0Sstevel@tonic-gate default: 672*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "invalid")); 673*0Sstevel@tonic-gate } 674*0Sstevel@tonic-gate } 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate /* 677*0Sstevel@tonic-gate * print subdevice stripe row 678*0Sstevel@tonic-gate */ 679*0Sstevel@tonic-gate static int 680*0Sstevel@tonic-gate subdev_row_report( 681*0Sstevel@tonic-gate mdsetname_t *sp, 682*0Sstevel@tonic-gate md_row_t *rp, 683*0Sstevel@tonic-gate char *fname, 684*0Sstevel@tonic-gate FILE *fp, 685*0Sstevel@tonic-gate mdprtopts_t options, 686*0Sstevel@tonic-gate uint_t top_tstate, /* Errored tstate flags */ 687*0Sstevel@tonic-gate md_error_t *ep 688*0Sstevel@tonic-gate ) 689*0Sstevel@tonic-gate { 690*0Sstevel@tonic-gate uint_t comp; 691*0Sstevel@tonic-gate int rval = -1; 692*0Sstevel@tonic-gate ddi_devid_t dtp; 693*0Sstevel@tonic-gate int len = 0; 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate /* 697*0Sstevel@tonic-gate * building a format string on the fly that will be used 698*0Sstevel@tonic-gate * in fprintf. This is to allow really really long ctd names 699*0Sstevel@tonic-gate */ 700*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 701*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 702*0Sstevel@tonic-gate char *cname = cp->compnamep->cname; 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate len = max(len, strlen(cname)); 705*0Sstevel@tonic-gate } 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device"))); 708*0Sstevel@tonic-gate len += 2; 709*0Sstevel@tonic-gate /* print header */ 710*0Sstevel@tonic-gate if (! (options & PRINT_TIMES)) { 711*0Sstevel@tonic-gate if (fprintf(fp, 712*0Sstevel@tonic-gate "\t%-*.*s %-12.12s %5.5s %12.12s %5.5s %s\n", 713*0Sstevel@tonic-gate len, len, 714*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"), 715*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"), 716*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 717*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"), 718*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"), 719*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) { 720*0Sstevel@tonic-gate goto out; 721*0Sstevel@tonic-gate } 722*0Sstevel@tonic-gate } else { 723*0Sstevel@tonic-gate if (fprintf(fp, 724*0Sstevel@tonic-gate "\t%-*s %5s %5s %-11s %-5s %-9s %s\n", 725*0Sstevel@tonic-gate len, 726*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"), 727*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start"), 728*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 729*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"), 730*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"), 731*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare"), 732*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Time")) == EOF) { 733*0Sstevel@tonic-gate goto out; 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate /* print components */ 739*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 740*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 741*0Sstevel@tonic-gate mdname_t *namep = cp->compnamep; 742*0Sstevel@tonic-gate char *cname = namep->cname; 743*0Sstevel@tonic-gate diskaddr_t start_blk; 744*0Sstevel@tonic-gate int has_mddb; 745*0Sstevel@tonic-gate char *has_mddb_str; 746*0Sstevel@tonic-gate char *comp_state; 747*0Sstevel@tonic-gate md_timeval32_t tv; 748*0Sstevel@tonic-gate char *hsname = ((cp->hsnamep != NULL) ? 749*0Sstevel@tonic-gate cp->hsnamep->cname : ""); 750*0Sstevel@tonic-gate char *devid = " "; 751*0Sstevel@tonic-gate mdname_t *didnp = NULL; 752*0Sstevel@tonic-gate uint_t tstate = 0; 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate /* get info */ 755*0Sstevel@tonic-gate if ((start_blk = metagetstart(sp, namep, ep)) == 756*0Sstevel@tonic-gate MD_DISKADDR_ERROR) { 757*0Sstevel@tonic-gate return (-1); 758*0Sstevel@tonic-gate } 759*0Sstevel@tonic-gate if ((has_mddb = metahasmddb(sp, namep, ep)) < 0) { 760*0Sstevel@tonic-gate return (-1); 761*0Sstevel@tonic-gate } 762*0Sstevel@tonic-gate if (has_mddb) 763*0Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "Yes"); 764*0Sstevel@tonic-gate else 765*0Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "No"); 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate /* 768*0Sstevel@tonic-gate * If the component is a metadevice, print out either 769*0Sstevel@tonic-gate * unavailable or the state of the metadevice, if not 770*0Sstevel@tonic-gate * a metadevice, print nothing if the state of the 771*0Sstevel@tonic-gate * stripe is unavailable 772*0Sstevel@tonic-gate */ 773*0Sstevel@tonic-gate if (metaismeta(namep)) { 774*0Sstevel@tonic-gate if (meta_get_tstate(namep->dev, &tstate, ep) != 0) 775*0Sstevel@tonic-gate return (-1); 776*0Sstevel@tonic-gate comp_state = comp_state_to_name(cp, &tv, tstate & 777*0Sstevel@tonic-gate MD_DEV_ERRORED); 778*0Sstevel@tonic-gate } else { 779*0Sstevel@tonic-gate /* 780*0Sstevel@tonic-gate * if top_tstate is set, that implies that you have 781*0Sstevel@tonic-gate * a ctd type device with an unavailable metadevice 782*0Sstevel@tonic-gate * on top of it. If so, print a - for it's state 783*0Sstevel@tonic-gate */ 784*0Sstevel@tonic-gate if (top_tstate != 0) 785*0Sstevel@tonic-gate comp_state = "-"; 786*0Sstevel@tonic-gate else 787*0Sstevel@tonic-gate comp_state = comp_state_to_name(cp, &tv, 788*0Sstevel@tonic-gate tstate & MD_DEV_ERRORED); 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate /* populate the key in the name_p structure */ 792*0Sstevel@tonic-gate if ((didnp = metadevname(&sp, namep->dev, ep)) 793*0Sstevel@tonic-gate == NULL) { 794*0Sstevel@tonic-gate return (-1); 795*0Sstevel@tonic-gate } 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate /* determine if devid does NOT exist */ 798*0Sstevel@tonic-gate if (options & PRINT_DEVID) { 799*0Sstevel@tonic-gate if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep), 800*0Sstevel@tonic-gate didnp->key, ep)) == NULL) 801*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "No "); 802*0Sstevel@tonic-gate else { 803*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "Yes"); 804*0Sstevel@tonic-gate free(dtp); 805*0Sstevel@tonic-gate } 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate /* print info */ 808*0Sstevel@tonic-gate /* 809*0Sstevel@tonic-gate * building a format string on the fly that will be used 810*0Sstevel@tonic-gate * in fprintf. This is to allow really really long ctd names 811*0Sstevel@tonic-gate */ 812*0Sstevel@tonic-gate if (! (options & PRINT_TIMES)) { 813*0Sstevel@tonic-gate if (fprintf(fp, 814*0Sstevel@tonic-gate "\t%-*s %8lld %-5.5s %12.12s %5.5s %s\n", 815*0Sstevel@tonic-gate len, cname, start_blk, 816*0Sstevel@tonic-gate has_mddb_str, comp_state, devid, hsname) == EOF) { 817*0Sstevel@tonic-gate goto out; 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate } else { 820*0Sstevel@tonic-gate char *timep = meta_print_time(&tv); 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate if (fprintf(fp, 823*0Sstevel@tonic-gate "\t%-*s %5lld %-5s %-11s %-5s %-9s %s\n", 824*0Sstevel@tonic-gate len, cname, start_blk, 825*0Sstevel@tonic-gate has_mddb_str, comp_state, devid, hsname, 826*0Sstevel@tonic-gate timep) == EOF) { 827*0Sstevel@tonic-gate goto out; 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate } 831*0Sstevel@tonic-gate 832*0Sstevel@tonic-gate /* success */ 833*0Sstevel@tonic-gate rval = 0; 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate /* cleanup, return error */ 836*0Sstevel@tonic-gate out: 837*0Sstevel@tonic-gate if (rval != 0) 838*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 839*0Sstevel@tonic-gate return (rval); 840*0Sstevel@tonic-gate } 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate /* 843*0Sstevel@tonic-gate * print toplevel stripe row 844*0Sstevel@tonic-gate */ 845*0Sstevel@tonic-gate /*ARGSUSED4*/ 846*0Sstevel@tonic-gate static int 847*0Sstevel@tonic-gate toplev_row_report( 848*0Sstevel@tonic-gate mdsetname_t *sp, 849*0Sstevel@tonic-gate md_row_t *rp, 850*0Sstevel@tonic-gate char *fname, 851*0Sstevel@tonic-gate FILE *fp, 852*0Sstevel@tonic-gate mdprtopts_t options, 853*0Sstevel@tonic-gate md_error_t *ep 854*0Sstevel@tonic-gate ) 855*0Sstevel@tonic-gate { 856*0Sstevel@tonic-gate uint_t comp; 857*0Sstevel@tonic-gate int rval = -1; 858*0Sstevel@tonic-gate char *devid = " "; 859*0Sstevel@tonic-gate mdname_t *didnp = NULL; 860*0Sstevel@tonic-gate int len = 0; 861*0Sstevel@tonic-gate 862*0Sstevel@tonic-gate /* 863*0Sstevel@tonic-gate * building a format string on the fly that will be used 864*0Sstevel@tonic-gate * in fprintf. This is to allow really really long ctd names 865*0Sstevel@tonic-gate */ 866*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 867*0Sstevel@tonic-gate len = max(len, 868*0Sstevel@tonic-gate strlen(rp->comps.comps_val[comp].compnamep->cname)); 869*0Sstevel@tonic-gate } 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device"))); 872*0Sstevel@tonic-gate len += 2; 873*0Sstevel@tonic-gate /* print header */ 874*0Sstevel@tonic-gate if (fprintf(fp, 875*0Sstevel@tonic-gate "\t%-*.*s %-12.12s %-5.5s\t%s\n", 876*0Sstevel@tonic-gate len, len, 877*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"), 878*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"), 879*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 880*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc")) == EOF) { 881*0Sstevel@tonic-gate goto out; 882*0Sstevel@tonic-gate } 883*0Sstevel@tonic-gate 884*0Sstevel@tonic-gate /* print components */ 885*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 886*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 887*0Sstevel@tonic-gate mdname_t *namep = cp->compnamep; 888*0Sstevel@tonic-gate char *cname = namep->cname; 889*0Sstevel@tonic-gate diskaddr_t start_blk; 890*0Sstevel@tonic-gate int has_mddb; 891*0Sstevel@tonic-gate char *has_mddb_str; 892*0Sstevel@tonic-gate ddi_devid_t dtp; 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate /* get info */ 895*0Sstevel@tonic-gate if ((start_blk = metagetstart(sp, namep, ep)) == 896*0Sstevel@tonic-gate MD_DISKADDR_ERROR) { 897*0Sstevel@tonic-gate return (-1); 898*0Sstevel@tonic-gate } 899*0Sstevel@tonic-gate if ((has_mddb = metahasmddb(sp, namep, ep)) < 0) { 900*0Sstevel@tonic-gate return (-1); 901*0Sstevel@tonic-gate } 902*0Sstevel@tonic-gate if (has_mddb) 903*0Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "Yes"); 904*0Sstevel@tonic-gate else 905*0Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "No"); 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate /* populate the key in the name_p structure */ 908*0Sstevel@tonic-gate if ((didnp = metadevname(&sp, namep->dev, ep)) 909*0Sstevel@tonic-gate == NULL) { 910*0Sstevel@tonic-gate return (-1); 911*0Sstevel@tonic-gate } 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate /* determine if devid does NOT exist */ 914*0Sstevel@tonic-gate if (options & PRINT_DEVID) { 915*0Sstevel@tonic-gate if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep), 916*0Sstevel@tonic-gate didnp->key, ep)) == NULL) { 917*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "No "); 918*0Sstevel@tonic-gate } else { 919*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "Yes"); 920*0Sstevel@tonic-gate free(dtp); 921*0Sstevel@tonic-gate } 922*0Sstevel@tonic-gate } 923*0Sstevel@tonic-gate /* print info */ 924*0Sstevel@tonic-gate /* 925*0Sstevel@tonic-gate * building a format string on the fly that will be used 926*0Sstevel@tonic-gate * in fprintf. This is to allow really really long ctd names 927*0Sstevel@tonic-gate */ 928*0Sstevel@tonic-gate if (fprintf(fp, 929*0Sstevel@tonic-gate "\t%-*s %8lld %-5.5s\t%s\n", len, 930*0Sstevel@tonic-gate cname, start_blk, has_mddb_str, devid) == EOF) { 931*0Sstevel@tonic-gate goto out; 932*0Sstevel@tonic-gate } 933*0Sstevel@tonic-gate } 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate /* success */ 936*0Sstevel@tonic-gate rval = 0; 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate /* cleanup, return error */ 939*0Sstevel@tonic-gate out: 940*0Sstevel@tonic-gate if (rval != 0) 941*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 942*0Sstevel@tonic-gate return (rval); 943*0Sstevel@tonic-gate } 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate /* 946*0Sstevel@tonic-gate * print stripe options 947*0Sstevel@tonic-gate */ 948*0Sstevel@tonic-gate int 949*0Sstevel@tonic-gate meta_print_stripe_options( 950*0Sstevel@tonic-gate mdhspname_t *hspnamep, 951*0Sstevel@tonic-gate char *fname, 952*0Sstevel@tonic-gate FILE *fp, 953*0Sstevel@tonic-gate md_error_t *ep 954*0Sstevel@tonic-gate ) 955*0Sstevel@tonic-gate { 956*0Sstevel@tonic-gate char *hspname = ((hspnamep != NULL) ? hspnamep->hspname : 957*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "none")); 958*0Sstevel@tonic-gate int rval = -1; 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate /* print options */ 961*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 962*0Sstevel@tonic-gate " Hot spare pool: %s\n"), hspname) == EOF) { 963*0Sstevel@tonic-gate goto out; 964*0Sstevel@tonic-gate } 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate /* success */ 967*0Sstevel@tonic-gate rval = 0; 968*0Sstevel@tonic-gate 969*0Sstevel@tonic-gate /* cleanup, return error */ 970*0Sstevel@tonic-gate out: 971*0Sstevel@tonic-gate if (rval != 0) 972*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 973*0Sstevel@tonic-gate return (rval); 974*0Sstevel@tonic-gate } 975*0Sstevel@tonic-gate 976*0Sstevel@tonic-gate /* 977*0Sstevel@tonic-gate * report stripe 978*0Sstevel@tonic-gate */ 979*0Sstevel@tonic-gate static int 980*0Sstevel@tonic-gate stripe_report( 981*0Sstevel@tonic-gate mdsetname_t *sp, 982*0Sstevel@tonic-gate md_stripe_t *stripep, 983*0Sstevel@tonic-gate mdnamelist_t **nlpp, 984*0Sstevel@tonic-gate char *fname, 985*0Sstevel@tonic-gate FILE *fp, 986*0Sstevel@tonic-gate mdprtopts_t options, 987*0Sstevel@tonic-gate md_error_t *ep 988*0Sstevel@tonic-gate ) 989*0Sstevel@tonic-gate { 990*0Sstevel@tonic-gate uint_t row; 991*0Sstevel@tonic-gate int rval = -1; 992*0Sstevel@tonic-gate uint_t tstate = 0; 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate /* 995*0Sstevel@tonic-gate * if the -B option has been specified check to see if the 996*0Sstevel@tonic-gate * metadevice is s "big" one and print if so, also if a 997*0Sstevel@tonic-gate * big device we need to store the ctd involved for use in 998*0Sstevel@tonic-gate * printing out the relocation information. 999*0Sstevel@tonic-gate */ 1000*0Sstevel@tonic-gate if (options & PRINT_LARGEDEVICES) { 1001*0Sstevel@tonic-gate if (stripep->common.revision != MD_64BIT_META_DEV) { 1002*0Sstevel@tonic-gate rval = 0; 1003*0Sstevel@tonic-gate goto out; 1004*0Sstevel@tonic-gate } else { 1005*0Sstevel@tonic-gate if (meta_getdevs(sp, stripep->common.namep, 1006*0Sstevel@tonic-gate nlpp, ep) != 0) 1007*0Sstevel@tonic-gate goto out; 1008*0Sstevel@tonic-gate } 1009*0Sstevel@tonic-gate } 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate /* print header */ 1012*0Sstevel@tonic-gate if (options & PRINT_HEADER) { 1013*0Sstevel@tonic-gate if (fprintf(fp, "%s: Concat/Stripe\n", 1014*0Sstevel@tonic-gate stripep->common.namep->cname) == EOF) { 1015*0Sstevel@tonic-gate goto out; 1016*0Sstevel@tonic-gate } 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate } 1019*0Sstevel@tonic-gate 1020*0Sstevel@tonic-gate /* print hotspare pool */ 1021*0Sstevel@tonic-gate if (stripep->hspnamep != NULL) { 1022*0Sstevel@tonic-gate if (meta_print_stripe_options(stripep->hspnamep, 1023*0Sstevel@tonic-gate fname, fp, ep) != 0) { 1024*0Sstevel@tonic-gate return (-1); 1025*0Sstevel@tonic-gate } 1026*0Sstevel@tonic-gate } 1027*0Sstevel@tonic-gate 1028*0Sstevel@tonic-gate if (metaismeta(stripep->common.namep)) { 1029*0Sstevel@tonic-gate if (meta_get_tstate(stripep->common.namep->dev, &tstate, ep) 1030*0Sstevel@tonic-gate != 0) 1031*0Sstevel@tonic-gate return (-1); 1032*0Sstevel@tonic-gate } 1033*0Sstevel@tonic-gate if ((tstate & MD_DEV_ERRORED) != 0) { 1034*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1035*0Sstevel@tonic-gate " State: Unavailable\n" 1036*0Sstevel@tonic-gate " Reconnect disk and invoke: metastat -i\n")) == EOF) { 1037*0Sstevel@tonic-gate goto out; 1038*0Sstevel@tonic-gate } 1039*0Sstevel@tonic-gate } 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* print size */ 1042*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"), 1043*0Sstevel@tonic-gate stripep->common.size, 1044*0Sstevel@tonic-gate meta_number_to_string(stripep->common.size, DEV_BSIZE)) 1045*0Sstevel@tonic-gate == EOF) { 1046*0Sstevel@tonic-gate goto out; 1047*0Sstevel@tonic-gate } 1048*0Sstevel@tonic-gate 1049*0Sstevel@tonic-gate /* print rows */ 1050*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 1051*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1052*0Sstevel@tonic-gate 1053*0Sstevel@tonic-gate /* print stripe and interlace */ 1054*0Sstevel@tonic-gate if (rp->comps.comps_len > 1) { 1055*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1056*0Sstevel@tonic-gate " Stripe %u: (interlace: %lld blocks)\n"), 1057*0Sstevel@tonic-gate row, rp->interlace) == EOF) { 1058*0Sstevel@tonic-gate goto out; 1059*0Sstevel@tonic-gate } 1060*0Sstevel@tonic-gate } else { 1061*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1062*0Sstevel@tonic-gate " Stripe %u:\n"), 1063*0Sstevel@tonic-gate row) == EOF) { 1064*0Sstevel@tonic-gate goto out; 1065*0Sstevel@tonic-gate } 1066*0Sstevel@tonic-gate } 1067*0Sstevel@tonic-gate 1068*0Sstevel@tonic-gate /* print components appropriately */ 1069*0Sstevel@tonic-gate if (MD_HAS_PARENT(stripep->common.parent)) { 1070*0Sstevel@tonic-gate if (subdev_row_report(sp, rp, fname, fp, options, 1071*0Sstevel@tonic-gate tstate & MD_DEV_ERRORED, ep) != 0) { 1072*0Sstevel@tonic-gate return (-1); 1073*0Sstevel@tonic-gate } 1074*0Sstevel@tonic-gate } else { 1075*0Sstevel@tonic-gate if (toplev_row_report(sp, rp, fname, fp, options, 1076*0Sstevel@tonic-gate ep) != 0) { 1077*0Sstevel@tonic-gate return (-1); 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate } 1080*0Sstevel@tonic-gate } 1081*0Sstevel@tonic-gate 1082*0Sstevel@tonic-gate /* add extra line */ 1083*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 1084*0Sstevel@tonic-gate goto out; 1085*0Sstevel@tonic-gate 1086*0Sstevel@tonic-gate /* success */ 1087*0Sstevel@tonic-gate rval = 0; 1088*0Sstevel@tonic-gate 1089*0Sstevel@tonic-gate /* cleanup, return error */ 1090*0Sstevel@tonic-gate out: 1091*0Sstevel@tonic-gate if (rval != 0) 1092*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 1093*0Sstevel@tonic-gate return (rval); 1094*0Sstevel@tonic-gate } 1095*0Sstevel@tonic-gate 1096*0Sstevel@tonic-gate /* 1097*0Sstevel@tonic-gate * print/report stripe 1098*0Sstevel@tonic-gate */ 1099*0Sstevel@tonic-gate int 1100*0Sstevel@tonic-gate meta_stripe_print( 1101*0Sstevel@tonic-gate mdsetname_t *sp, 1102*0Sstevel@tonic-gate mdname_t *stripenp, 1103*0Sstevel@tonic-gate mdnamelist_t **nlpp, 1104*0Sstevel@tonic-gate char *fname, 1105*0Sstevel@tonic-gate FILE *fp, 1106*0Sstevel@tonic-gate mdprtopts_t options, 1107*0Sstevel@tonic-gate md_error_t *ep 1108*0Sstevel@tonic-gate ) 1109*0Sstevel@tonic-gate { 1110*0Sstevel@tonic-gate md_stripe_t *stripep; 1111*0Sstevel@tonic-gate int row, comp; 1112*0Sstevel@tonic-gate 1113*0Sstevel@tonic-gate /* should have same set */ 1114*0Sstevel@tonic-gate assert(sp != NULL); 1115*0Sstevel@tonic-gate assert((stripenp == NULL) || 1116*0Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)))); 1117*0Sstevel@tonic-gate 1118*0Sstevel@tonic-gate /* print all stripes */ 1119*0Sstevel@tonic-gate if (stripenp == NULL) { 1120*0Sstevel@tonic-gate mdnamelist_t *nlp = NULL; 1121*0Sstevel@tonic-gate mdnamelist_t *p; 1122*0Sstevel@tonic-gate int cnt; 1123*0Sstevel@tonic-gate int rval = 0; 1124*0Sstevel@tonic-gate 1125*0Sstevel@tonic-gate /* get list */ 1126*0Sstevel@tonic-gate if ((cnt = meta_get_stripe_names(sp, &nlp, options, ep)) < 0) 1127*0Sstevel@tonic-gate return (-1); 1128*0Sstevel@tonic-gate else if (cnt == 0) 1129*0Sstevel@tonic-gate return (0); 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate /* recurse */ 1132*0Sstevel@tonic-gate for (p = nlp; (p != NULL); p = p->next) { 1133*0Sstevel@tonic-gate mdname_t *np = p->namep; 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate if (meta_stripe_print(sp, np, nlpp, fname, fp, 1136*0Sstevel@tonic-gate options, ep) != 0) 1137*0Sstevel@tonic-gate rval = -1; 1138*0Sstevel@tonic-gate } 1139*0Sstevel@tonic-gate 1140*0Sstevel@tonic-gate /* cleanup, return success */ 1141*0Sstevel@tonic-gate metafreenamelist(nlp); 1142*0Sstevel@tonic-gate return (rval); 1143*0Sstevel@tonic-gate } 1144*0Sstevel@tonic-gate 1145*0Sstevel@tonic-gate /* get unit structure */ 1146*0Sstevel@tonic-gate if ((stripep = meta_get_stripe_common(sp, stripenp, 1147*0Sstevel@tonic-gate ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL) 1148*0Sstevel@tonic-gate return (-1); 1149*0Sstevel@tonic-gate 1150*0Sstevel@tonic-gate /* check for parented */ 1151*0Sstevel@tonic-gate if ((! (options & PRINT_SUBDEVS)) && 1152*0Sstevel@tonic-gate (MD_HAS_PARENT(stripep->common.parent))) { 1153*0Sstevel@tonic-gate return (0); 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate /* print appropriate detail */ 1157*0Sstevel@tonic-gate if (options & PRINT_SHORT) { 1158*0Sstevel@tonic-gate if (stripe_print(stripep, fname, fp, options, ep) != 0) 1159*0Sstevel@tonic-gate return (-1); 1160*0Sstevel@tonic-gate } else { 1161*0Sstevel@tonic-gate if (stripe_report(sp, stripep, nlpp, fname, fp, options, 1162*0Sstevel@tonic-gate ep) != 0) 1163*0Sstevel@tonic-gate return (-1); 1164*0Sstevel@tonic-gate } 1165*0Sstevel@tonic-gate 1166*0Sstevel@tonic-gate /* Recurse on components that are metadevices */ 1167*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 1168*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1169*0Sstevel@tonic-gate 1170*0Sstevel@tonic-gate /* look for components that are metadevices */ 1171*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1172*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 1173*0Sstevel@tonic-gate mdname_t *namep = cp->compnamep; 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate if ((metaismeta(namep)) && 1176*0Sstevel@tonic-gate (meta_print_name(sp, namep, nlpp, fname, fp, 1177*0Sstevel@tonic-gate (options | PRINT_HEADER | PRINT_SUBDEVS), 1178*0Sstevel@tonic-gate NULL, ep) != 0)) { 1179*0Sstevel@tonic-gate return (-1); 1180*0Sstevel@tonic-gate } 1181*0Sstevel@tonic-gate } 1182*0Sstevel@tonic-gate } 1183*0Sstevel@tonic-gate return (0); 1184*0Sstevel@tonic-gate } 1185*0Sstevel@tonic-gate 1186*0Sstevel@tonic-gate /* 1187*0Sstevel@tonic-gate * find stripe component to replace 1188*0Sstevel@tonic-gate */ 1189*0Sstevel@tonic-gate int 1190*0Sstevel@tonic-gate meta_find_erred_comp( 1191*0Sstevel@tonic-gate mdsetname_t *sp, 1192*0Sstevel@tonic-gate mdname_t *stripenp, 1193*0Sstevel@tonic-gate mdname_t **compnpp, 1194*0Sstevel@tonic-gate comp_state_t *compstate, 1195*0Sstevel@tonic-gate md_error_t *ep 1196*0Sstevel@tonic-gate ) 1197*0Sstevel@tonic-gate { 1198*0Sstevel@tonic-gate md_stripe_t *stripep; 1199*0Sstevel@tonic-gate md_comp_t *compp = NULL; 1200*0Sstevel@tonic-gate uint_t lasterrcnt = 0; 1201*0Sstevel@tonic-gate uint_t row; 1202*0Sstevel@tonic-gate 1203*0Sstevel@tonic-gate /* get stripe */ 1204*0Sstevel@tonic-gate *compnpp = NULL; 1205*0Sstevel@tonic-gate if ((stripep = meta_get_stripe_common(sp, stripenp, 1, ep)) == NULL) 1206*0Sstevel@tonic-gate return (-1); 1207*0Sstevel@tonic-gate 1208*0Sstevel@tonic-gate /* 1209*0Sstevel@tonic-gate * Try to find the first erred component. 1210*0Sstevel@tonic-gate * If there is not one, then look for the 1211*0Sstevel@tonic-gate * first last_erred component. 1212*0Sstevel@tonic-gate */ 1213*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 1214*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1215*0Sstevel@tonic-gate uint_t comp; 1216*0Sstevel@tonic-gate 1217*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1218*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 1219*0Sstevel@tonic-gate 1220*0Sstevel@tonic-gate if ((cp->state == CS_ERRED) && ((compp == NULL) || 1221*0Sstevel@tonic-gate (cp->lasterrcnt < lasterrcnt))) { 1222*0Sstevel@tonic-gate compp = cp; 1223*0Sstevel@tonic-gate lasterrcnt = cp->lasterrcnt; 1224*0Sstevel@tonic-gate } 1225*0Sstevel@tonic-gate } 1226*0Sstevel@tonic-gate } 1227*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 1228*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1229*0Sstevel@tonic-gate uint_t comp; 1230*0Sstevel@tonic-gate 1231*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1232*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 1233*0Sstevel@tonic-gate 1234*0Sstevel@tonic-gate if ((cp->state == CS_LAST_ERRED) && ((compp == NULL) || 1235*0Sstevel@tonic-gate (cp->lasterrcnt < lasterrcnt))) { 1236*0Sstevel@tonic-gate compp = cp; 1237*0Sstevel@tonic-gate lasterrcnt = cp->lasterrcnt; 1238*0Sstevel@tonic-gate } 1239*0Sstevel@tonic-gate } 1240*0Sstevel@tonic-gate } 1241*0Sstevel@tonic-gate 1242*0Sstevel@tonic-gate /* return component */ 1243*0Sstevel@tonic-gate if (compp != NULL) { 1244*0Sstevel@tonic-gate *compnpp = compp->compnamep; 1245*0Sstevel@tonic-gate *compstate = compp->state; 1246*0Sstevel@tonic-gate } 1247*0Sstevel@tonic-gate 1248*0Sstevel@tonic-gate /* return success */ 1249*0Sstevel@tonic-gate return (0); 1250*0Sstevel@tonic-gate } 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate /* 1253*0Sstevel@tonic-gate * invalidate component names 1254*0Sstevel@tonic-gate */ 1255*0Sstevel@tonic-gate static int 1256*0Sstevel@tonic-gate invalidate_components( 1257*0Sstevel@tonic-gate mdsetname_t *sp, 1258*0Sstevel@tonic-gate mdname_t *stripenp, 1259*0Sstevel@tonic-gate md_error_t *ep 1260*0Sstevel@tonic-gate ) 1261*0Sstevel@tonic-gate { 1262*0Sstevel@tonic-gate md_stripe_t *stripep; 1263*0Sstevel@tonic-gate uint_t row; 1264*0Sstevel@tonic-gate 1265*0Sstevel@tonic-gate if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL) 1266*0Sstevel@tonic-gate return (-1); 1267*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 1268*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1269*0Sstevel@tonic-gate uint_t comp; 1270*0Sstevel@tonic-gate 1271*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1272*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 1273*0Sstevel@tonic-gate mdname_t *compnp = cp->compnamep; 1274*0Sstevel@tonic-gate 1275*0Sstevel@tonic-gate meta_invalidate_name(compnp); 1276*0Sstevel@tonic-gate } 1277*0Sstevel@tonic-gate } 1278*0Sstevel@tonic-gate return (0); 1279*0Sstevel@tonic-gate } 1280*0Sstevel@tonic-gate 1281*0Sstevel@tonic-gate /* 1282*0Sstevel@tonic-gate * attach components to stripe 1283*0Sstevel@tonic-gate */ 1284*0Sstevel@tonic-gate int 1285*0Sstevel@tonic-gate meta_stripe_attach( 1286*0Sstevel@tonic-gate mdsetname_t *sp, 1287*0Sstevel@tonic-gate mdname_t *stripenp, 1288*0Sstevel@tonic-gate mdnamelist_t *nlp, 1289*0Sstevel@tonic-gate diskaddr_t interlace, 1290*0Sstevel@tonic-gate mdcmdopts_t options, 1291*0Sstevel@tonic-gate md_error_t *ep 1292*0Sstevel@tonic-gate ) 1293*0Sstevel@tonic-gate { 1294*0Sstevel@tonic-gate mdnamelist_t *lp; 1295*0Sstevel@tonic-gate ms_unit_t *old_un, *new_un; 1296*0Sstevel@tonic-gate struct ms_row *mdr, *new_mdr; 1297*0Sstevel@tonic-gate uint_t newcomps, ncomps, icomp; 1298*0Sstevel@tonic-gate uint_t row; 1299*0Sstevel@tonic-gate size_t mdsize, first_comp; 1300*0Sstevel@tonic-gate diskaddr_t new_blks; 1301*0Sstevel@tonic-gate diskaddr_t limit; 1302*0Sstevel@tonic-gate diskaddr_t disk_size = 0; 1303*0Sstevel@tonic-gate ms_comp_t *mdcomp, *new_comp; 1304*0Sstevel@tonic-gate uint_t write_reinstruct = 0; 1305*0Sstevel@tonic-gate uint_t read_reinstruct = 0; 1306*0Sstevel@tonic-gate mdnamelist_t *keynlp = NULL; 1307*0Sstevel@tonic-gate uint_t round_cyl = 1; 1308*0Sstevel@tonic-gate minor_t parent; 1309*0Sstevel@tonic-gate md_grow_params_t mgp; 1310*0Sstevel@tonic-gate int rval = -1; 1311*0Sstevel@tonic-gate md_timeval32_t creation_time; 1312*0Sstevel@tonic-gate int create_flag = MD_CRO_32BIT; 1313*0Sstevel@tonic-gate 1314*0Sstevel@tonic-gate /* should have a set */ 1315*0Sstevel@tonic-gate assert(sp != NULL); 1316*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gate /* check type */ 1319*0Sstevel@tonic-gate if (metachkmeta(stripenp, ep) != 0) 1320*0Sstevel@tonic-gate return (-1); 1321*0Sstevel@tonic-gate 1322*0Sstevel@tonic-gate /* check and count components */ 1323*0Sstevel@tonic-gate assert(nlp != NULL); 1324*0Sstevel@tonic-gate newcomps = 0; 1325*0Sstevel@tonic-gate for (lp = nlp; (lp != NULL); lp = lp->next) { 1326*0Sstevel@tonic-gate mdname_t *np = lp->namep; 1327*0Sstevel@tonic-gate mdnamelist_t *p; 1328*0Sstevel@tonic-gate 1329*0Sstevel@tonic-gate /* check against existing devices */ 1330*0Sstevel@tonic-gate if (meta_check_component(sp, np, 0, ep) != 0) 1331*0Sstevel@tonic-gate return (-1); 1332*0Sstevel@tonic-gate 1333*0Sstevel@tonic-gate /* check against ourselves */ 1334*0Sstevel@tonic-gate for (p = lp->next; (p != NULL); p = p->next) { 1335*0Sstevel@tonic-gate if (meta_check_overlap(np->cname, np, 0, -1, 1336*0Sstevel@tonic-gate p->namep, 0, -1, ep) != 0) { 1337*0Sstevel@tonic-gate return (-1); 1338*0Sstevel@tonic-gate } 1339*0Sstevel@tonic-gate } 1340*0Sstevel@tonic-gate 1341*0Sstevel@tonic-gate /* count */ 1342*0Sstevel@tonic-gate ++newcomps; 1343*0Sstevel@tonic-gate } 1344*0Sstevel@tonic-gate 1345*0Sstevel@tonic-gate /* get old unit */ 1346*0Sstevel@tonic-gate if ((old_un = (ms_unit_t *)meta_get_mdunit(sp, stripenp, ep)) == NULL) 1347*0Sstevel@tonic-gate return (-1); 1348*0Sstevel@tonic-gate 1349*0Sstevel@tonic-gate /* if zero, inherit the last rows interlace value */ 1350*0Sstevel@tonic-gate if (interlace == 0) { 1351*0Sstevel@tonic-gate mdr = &old_un->un_row[old_un->un_nrows - 1]; 1352*0Sstevel@tonic-gate interlace = mdr->un_interlace; 1353*0Sstevel@tonic-gate } 1354*0Sstevel@tonic-gate 1355*0Sstevel@tonic-gate /* 1356*0Sstevel@tonic-gate * calculate size of new unit structure 1357*0Sstevel@tonic-gate */ 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate /* unit + rows */ 1360*0Sstevel@tonic-gate mdsize = sizeof (ms_unit_t) - sizeof (struct ms_row); 1361*0Sstevel@tonic-gate mdsize += sizeof (struct ms_row) * (old_un->un_nrows + 1); 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gate /* number of new components being added */ 1364*0Sstevel@tonic-gate ncomps = newcomps; 1365*0Sstevel@tonic-gate 1366*0Sstevel@tonic-gate /* count the # of components in the old unit */ 1367*0Sstevel@tonic-gate mdr = &old_un->un_row[0]; 1368*0Sstevel@tonic-gate for (row = 0; (row < old_un->un_nrows); row++) 1369*0Sstevel@tonic-gate ncomps += mdr[row].un_ncomp; 1370*0Sstevel@tonic-gate first_comp = roundup(mdsize, sizeof (long long)); 1371*0Sstevel@tonic-gate mdsize += sizeof (ms_comp_t) * ncomps + (first_comp - mdsize); 1372*0Sstevel@tonic-gate 1373*0Sstevel@tonic-gate /* allocate new unit */ 1374*0Sstevel@tonic-gate new_un = Zalloc(mdsize); 1375*0Sstevel@tonic-gate new_un->un_ocomp = first_comp; 1376*0Sstevel@tonic-gate 1377*0Sstevel@tonic-gate /* compute new data */ 1378*0Sstevel@tonic-gate new_mdr = &new_un->un_row[old_un->un_nrows]; 1379*0Sstevel@tonic-gate new_mdr->un_icomp = ncomps - newcomps; 1380*0Sstevel@tonic-gate new_mdr->un_ncomp = newcomps; 1381*0Sstevel@tonic-gate new_mdr->un_blocks = 0; 1382*0Sstevel@tonic-gate new_mdr->un_cum_blocks = 1383*0Sstevel@tonic-gate old_un->un_row[old_un->un_nrows - 1].un_cum_blocks; 1384*0Sstevel@tonic-gate new_mdr->un_interlace = interlace; 1385*0Sstevel@tonic-gate 1386*0Sstevel@tonic-gate /* for each new device */ 1387*0Sstevel@tonic-gate mdcomp = (struct ms_comp *)(void *)&((char *)new_un)[new_un->un_ocomp]; 1388*0Sstevel@tonic-gate icomp = new_mdr->un_icomp; 1389*0Sstevel@tonic-gate if (meta_gettimeofday(&creation_time) == -1) 1390*0Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL)); 1391*0Sstevel@tonic-gate for (lp = nlp; (lp != NULL); lp = lp->next) { 1392*0Sstevel@tonic-gate mdname_t *np = lp->namep; 1393*0Sstevel@tonic-gate diskaddr_t size, start_blk; 1394*0Sstevel@tonic-gate mdgeom_t *geomp; 1395*0Sstevel@tonic-gate 1396*0Sstevel@tonic-gate /* figure out how big */ 1397*0Sstevel@tonic-gate if ((size = metagetsize(np, ep)) == MD_DISKADDR_ERROR) 1398*0Sstevel@tonic-gate goto out; 1399*0Sstevel@tonic-gate if ((start_blk = metagetstart(sp, np, ep)) == 1400*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 1401*0Sstevel@tonic-gate goto out; 1402*0Sstevel@tonic-gate if (start_blk >= size) { 1403*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOSPC, np->cname); 1404*0Sstevel@tonic-gate goto out; 1405*0Sstevel@tonic-gate } 1406*0Sstevel@tonic-gate size -= start_blk; 1407*0Sstevel@tonic-gate if (newcomps > 1) 1408*0Sstevel@tonic-gate size = rounddown(size, interlace); 1409*0Sstevel@tonic-gate 1410*0Sstevel@tonic-gate /* adjust for smallest disk */ 1411*0Sstevel@tonic-gate if (disk_size == 0) { 1412*0Sstevel@tonic-gate disk_size = size; 1413*0Sstevel@tonic-gate } else if (size < disk_size) { 1414*0Sstevel@tonic-gate disk_size = size; 1415*0Sstevel@tonic-gate } 1416*0Sstevel@tonic-gate 1417*0Sstevel@tonic-gate /* get worst reinstructs */ 1418*0Sstevel@tonic-gate if ((geomp = metagetgeom(np, ep)) == NULL) 1419*0Sstevel@tonic-gate goto out; 1420*0Sstevel@tonic-gate if (geomp->write_reinstruct > write_reinstruct) 1421*0Sstevel@tonic-gate write_reinstruct = geomp->write_reinstruct; 1422*0Sstevel@tonic-gate if (geomp->read_reinstruct > read_reinstruct) 1423*0Sstevel@tonic-gate read_reinstruct = geomp->read_reinstruct; 1424*0Sstevel@tonic-gate 1425*0Sstevel@tonic-gate /* In dryrun mode (DOIT not set) we must not alter the mddb */ 1426*0Sstevel@tonic-gate if (options & MDCMD_DOIT) { 1427*0Sstevel@tonic-gate /* store name in namespace */ 1428*0Sstevel@tonic-gate if (add_key_name(sp, np, &keynlp, ep) != 0) 1429*0Sstevel@tonic-gate goto out; 1430*0Sstevel@tonic-gate } 1431*0Sstevel@tonic-gate 1432*0Sstevel@tonic-gate /* build new component */ 1433*0Sstevel@tonic-gate new_comp = &mdcomp[icomp++]; 1434*0Sstevel@tonic-gate new_comp->un_key = np->key; 1435*0Sstevel@tonic-gate new_comp->un_dev = np->dev; 1436*0Sstevel@tonic-gate new_comp->un_start_block = start_blk; 1437*0Sstevel@tonic-gate new_comp->un_mirror.ms_state = CS_OKAY; 1438*0Sstevel@tonic-gate new_comp->un_mirror.ms_timestamp = creation_time; 1439*0Sstevel@tonic-gate } 1440*0Sstevel@tonic-gate 1441*0Sstevel@tonic-gate limit = LLONG_MAX; 1442*0Sstevel@tonic-gate 1443*0Sstevel@tonic-gate /* compute new size */ 1444*0Sstevel@tonic-gate new_mdr->un_blocks = new_mdr->un_ncomp * disk_size; 1445*0Sstevel@tonic-gate new_blks = new_mdr->un_cum_blocks + new_mdr->un_blocks; 1446*0Sstevel@tonic-gate if (new_blks > limit) { 1447*0Sstevel@tonic-gate new_mdr->un_cum_blocks = limit; 1448*0Sstevel@tonic-gate new_blks = limit; 1449*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 1450*0Sstevel@tonic-gate "unit size overflow, limit is %lld blocks\n"), 1451*0Sstevel@tonic-gate limit); 1452*0Sstevel@tonic-gate } else { 1453*0Sstevel@tonic-gate new_mdr->un_cum_blocks += new_mdr->un_blocks; 1454*0Sstevel@tonic-gate } 1455*0Sstevel@tonic-gate new_un->c.un_actual_tb = new_mdr->un_cum_blocks; 1456*0Sstevel@tonic-gate new_un->un_nrows = old_un->un_nrows + 1; 1457*0Sstevel@tonic-gate 1458*0Sstevel@tonic-gate /* adjust geometry */ 1459*0Sstevel@tonic-gate new_un->c.un_nhead = old_un->c.un_nhead; 1460*0Sstevel@tonic-gate new_un->c.un_nsect = old_un->c.un_nsect; 1461*0Sstevel@tonic-gate new_un->c.un_rpm = old_un->c.un_rpm; 1462*0Sstevel@tonic-gate new_un->c.un_wr_reinstruct = old_un->c.un_wr_reinstruct; 1463*0Sstevel@tonic-gate new_un->c.un_rd_reinstruct = old_un->c.un_rd_reinstruct; 1464*0Sstevel@tonic-gate if (meta_adjust_geom((md_unit_t *)new_un, stripenp, 1465*0Sstevel@tonic-gate write_reinstruct, read_reinstruct, round_cyl, ep) != 0) 1466*0Sstevel@tonic-gate goto out; 1467*0Sstevel@tonic-gate 1468*0Sstevel@tonic-gate /* if in dryrun mode, we are done here. */ 1469*0Sstevel@tonic-gate if ((options & MDCMD_DOIT) == 0) { 1470*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 1471*0Sstevel@tonic-gate if (newcomps == 1) { 1472*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1473*0Sstevel@tonic-gate "%s: attaching component would suceed\n"), 1474*0Sstevel@tonic-gate stripenp->cname); 1475*0Sstevel@tonic-gate } else { 1476*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1477*0Sstevel@tonic-gate "%s: attaching components would suceed\n"), 1478*0Sstevel@tonic-gate stripenp->cname); 1479*0Sstevel@tonic-gate } 1480*0Sstevel@tonic-gate } 1481*0Sstevel@tonic-gate rval = 0; /* success */ 1482*0Sstevel@tonic-gate goto out; 1483*0Sstevel@tonic-gate } 1484*0Sstevel@tonic-gate 1485*0Sstevel@tonic-gate create_flag = meta_check_devicesize(new_un->c.un_total_blocks); 1486*0Sstevel@tonic-gate 1487*0Sstevel@tonic-gate /* grow stripe */ 1488*0Sstevel@tonic-gate (void) memset(&mgp, 0, sizeof (mgp)); 1489*0Sstevel@tonic-gate mgp.mnum = MD_SID(old_un); 1490*0Sstevel@tonic-gate MD_SETDRIVERNAME(&mgp, MD_STRIPE, sp->setno); 1491*0Sstevel@tonic-gate mgp.size = mdsize; 1492*0Sstevel@tonic-gate mgp.mdp = (uintptr_t)new_un; 1493*0Sstevel@tonic-gate mgp.nrows = old_un->un_nrows; 1494*0Sstevel@tonic-gate if (create_flag == MD_CRO_32BIT) { 1495*0Sstevel@tonic-gate mgp.options = MD_CRO_32BIT; 1496*0Sstevel@tonic-gate new_un->c.un_revision = MD_32BIT_META_DEV; 1497*0Sstevel@tonic-gate } else { 1498*0Sstevel@tonic-gate mgp.options = MD_CRO_64BIT; 1499*0Sstevel@tonic-gate new_un->c.un_revision = MD_64BIT_META_DEV; 1500*0Sstevel@tonic-gate } 1501*0Sstevel@tonic-gate 1502*0Sstevel@tonic-gate if ((MD_HAS_PARENT(old_un->c.un_parent)) && 1503*0Sstevel@tonic-gate (old_un->c.un_parent != MD_MULTI_PARENT)) { 1504*0Sstevel@tonic-gate mgp.npar = 1; 1505*0Sstevel@tonic-gate parent = old_un->c.un_parent; 1506*0Sstevel@tonic-gate mgp.par = (uintptr_t)(&parent); 1507*0Sstevel@tonic-gate } 1508*0Sstevel@tonic-gate 1509*0Sstevel@tonic-gate if (metaioctl(MD_IOCGROW, &mgp, &mgp.mde, NULL) != 0) { 1510*0Sstevel@tonic-gate (void) mdstealerror(ep, &mgp.mde); 1511*0Sstevel@tonic-gate goto out; 1512*0Sstevel@tonic-gate } 1513*0Sstevel@tonic-gate 1514*0Sstevel@tonic-gate /* clear cache */ 1515*0Sstevel@tonic-gate if (invalidate_components(sp, stripenp, ep) != 0) 1516*0Sstevel@tonic-gate goto out; 1517*0Sstevel@tonic-gate meta_invalidate_name(stripenp); 1518*0Sstevel@tonic-gate 1519*0Sstevel@tonic-gate /* let em know */ 1520*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 1521*0Sstevel@tonic-gate if (newcomps == 1) { 1522*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1523*0Sstevel@tonic-gate "%s: component is attached\n"), stripenp->cname); 1524*0Sstevel@tonic-gate } else { 1525*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1526*0Sstevel@tonic-gate "%s: components are attached\n"), stripenp->cname); 1527*0Sstevel@tonic-gate } 1528*0Sstevel@tonic-gate (void) fflush(stdout); 1529*0Sstevel@tonic-gate } 1530*0Sstevel@tonic-gate 1531*0Sstevel@tonic-gate /* grow any parents */ 1532*0Sstevel@tonic-gate if (meta_concat_parent(sp, stripenp, ep) != 0) 1533*0Sstevel@tonic-gate return (-1); 1534*0Sstevel@tonic-gate 1535*0Sstevel@tonic-gate rval = 0; /* success */ 1536*0Sstevel@tonic-gate 1537*0Sstevel@tonic-gate /* cleanup, return error */ 1538*0Sstevel@tonic-gate out: 1539*0Sstevel@tonic-gate Free(old_un); 1540*0Sstevel@tonic-gate Free(new_un); 1541*0Sstevel@tonic-gate if (options & MDCMD_DOIT) { 1542*0Sstevel@tonic-gate if (rval != 0) 1543*0Sstevel@tonic-gate (void) del_key_names(sp, keynlp, NULL); 1544*0Sstevel@tonic-gate metafreenamelist(keynlp); 1545*0Sstevel@tonic-gate } 1546*0Sstevel@tonic-gate return (rval); 1547*0Sstevel@tonic-gate } 1548*0Sstevel@tonic-gate 1549*0Sstevel@tonic-gate /* 1550*0Sstevel@tonic-gate * get stripe parameters 1551*0Sstevel@tonic-gate */ 1552*0Sstevel@tonic-gate int 1553*0Sstevel@tonic-gate meta_stripe_get_params( 1554*0Sstevel@tonic-gate mdsetname_t *sp, 1555*0Sstevel@tonic-gate mdname_t *stripenp, 1556*0Sstevel@tonic-gate ms_params_t *paramsp, 1557*0Sstevel@tonic-gate md_error_t *ep 1558*0Sstevel@tonic-gate ) 1559*0Sstevel@tonic-gate { 1560*0Sstevel@tonic-gate md_stripe_t *stripep; 1561*0Sstevel@tonic-gate 1562*0Sstevel@tonic-gate /* should have a set */ 1563*0Sstevel@tonic-gate assert(sp != NULL); 1564*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 1565*0Sstevel@tonic-gate 1566*0Sstevel@tonic-gate /* check name */ 1567*0Sstevel@tonic-gate if (metachkmeta(stripenp, ep) != 0) 1568*0Sstevel@tonic-gate return (-1); 1569*0Sstevel@tonic-gate 1570*0Sstevel@tonic-gate /* get unit */ 1571*0Sstevel@tonic-gate if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL) 1572*0Sstevel@tonic-gate return (-1); 1573*0Sstevel@tonic-gate 1574*0Sstevel@tonic-gate /* return parameters */ 1575*0Sstevel@tonic-gate (void) memset(paramsp, 0, sizeof (*paramsp)); 1576*0Sstevel@tonic-gate if (stripep->hspnamep == NULL) 1577*0Sstevel@tonic-gate paramsp->hsp_id = MD_HSP_NONE; 1578*0Sstevel@tonic-gate else 1579*0Sstevel@tonic-gate paramsp->hsp_id = stripep->hspnamep->hsp; 1580*0Sstevel@tonic-gate return (0); 1581*0Sstevel@tonic-gate } 1582*0Sstevel@tonic-gate 1583*0Sstevel@tonic-gate /* 1584*0Sstevel@tonic-gate * set stripe parameters 1585*0Sstevel@tonic-gate */ 1586*0Sstevel@tonic-gate int 1587*0Sstevel@tonic-gate meta_stripe_set_params( 1588*0Sstevel@tonic-gate mdsetname_t *sp, 1589*0Sstevel@tonic-gate mdname_t *stripenp, 1590*0Sstevel@tonic-gate ms_params_t *paramsp, 1591*0Sstevel@tonic-gate md_error_t *ep 1592*0Sstevel@tonic-gate ) 1593*0Sstevel@tonic-gate { 1594*0Sstevel@tonic-gate md_stripe_params_t msp; 1595*0Sstevel@tonic-gate 1596*0Sstevel@tonic-gate /* should have a set */ 1597*0Sstevel@tonic-gate assert(sp != NULL); 1598*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev))); 1599*0Sstevel@tonic-gate 1600*0Sstevel@tonic-gate /* check name */ 1601*0Sstevel@tonic-gate if (metachkmeta(stripenp, ep) != 0) 1602*0Sstevel@tonic-gate return (-1); 1603*0Sstevel@tonic-gate 1604*0Sstevel@tonic-gate /* set parameters */ 1605*0Sstevel@tonic-gate (void) memset(&msp, 0, sizeof (msp)); 1606*0Sstevel@tonic-gate MD_SETDRIVERNAME(&msp, MD_STRIPE, sp->setno); 1607*0Sstevel@tonic-gate msp.mnum = meta_getminor(stripenp->dev); 1608*0Sstevel@tonic-gate msp.params = *paramsp; 1609*0Sstevel@tonic-gate if (metaioctl(MD_IOCCHANGE, &msp, &msp.mde, stripenp->cname) != 0) 1610*0Sstevel@tonic-gate return (mdstealerror(ep, &msp.mde)); 1611*0Sstevel@tonic-gate 1612*0Sstevel@tonic-gate /* clear cache */ 1613*0Sstevel@tonic-gate meta_invalidate_name(stripenp); 1614*0Sstevel@tonic-gate 1615*0Sstevel@tonic-gate /* return success */ 1616*0Sstevel@tonic-gate return (0); 1617*0Sstevel@tonic-gate } 1618*0Sstevel@tonic-gate 1619*0Sstevel@tonic-gate /* 1620*0Sstevel@tonic-gate * check for dups in the stripe itself 1621*0Sstevel@tonic-gate */ 1622*0Sstevel@tonic-gate static int 1623*0Sstevel@tonic-gate check_twice( 1624*0Sstevel@tonic-gate md_stripe_t *stripep, 1625*0Sstevel@tonic-gate uint_t row, 1626*0Sstevel@tonic-gate uint_t comp, 1627*0Sstevel@tonic-gate md_error_t *ep 1628*0Sstevel@tonic-gate ) 1629*0Sstevel@tonic-gate { 1630*0Sstevel@tonic-gate mdname_t *stripenp = stripep->common.namep; 1631*0Sstevel@tonic-gate mdname_t *thisnp; 1632*0Sstevel@tonic-gate uint_t r; 1633*0Sstevel@tonic-gate 1634*0Sstevel@tonic-gate thisnp = stripep->rows.rows_val[row].comps.comps_val[comp].compnamep; 1635*0Sstevel@tonic-gate for (r = 0; (r <= row); ++r) { 1636*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[r]; 1637*0Sstevel@tonic-gate uint_t e = ((r == row) ? comp : rp->comps.comps_len); 1638*0Sstevel@tonic-gate uint_t c; 1639*0Sstevel@tonic-gate 1640*0Sstevel@tonic-gate for (c = 0; (c < e); ++c) { 1641*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[c]; 1642*0Sstevel@tonic-gate mdname_t *compnp = cp->compnamep; 1643*0Sstevel@tonic-gate 1644*0Sstevel@tonic-gate if (meta_check_overlap(stripenp->cname, thisnp, 0, -1, 1645*0Sstevel@tonic-gate compnp, 0, -1, ep) != 0) { 1646*0Sstevel@tonic-gate return (-1); 1647*0Sstevel@tonic-gate } 1648*0Sstevel@tonic-gate } 1649*0Sstevel@tonic-gate } 1650*0Sstevel@tonic-gate return (0); 1651*0Sstevel@tonic-gate } 1652*0Sstevel@tonic-gate 1653*0Sstevel@tonic-gate /* 1654*0Sstevel@tonic-gate * default stripe interlace 1655*0Sstevel@tonic-gate */ 1656*0Sstevel@tonic-gate diskaddr_t 1657*0Sstevel@tonic-gate meta_default_stripe_interlace(void) 1658*0Sstevel@tonic-gate { 1659*0Sstevel@tonic-gate diskaddr_t interlace; 1660*0Sstevel@tonic-gate 1661*0Sstevel@tonic-gate /* default to 16k, round up if necessary */ 1662*0Sstevel@tonic-gate interlace = btodb(16 * 1024); 1663*0Sstevel@tonic-gate if (interlace < btodb(MININTERLACE)) 1664*0Sstevel@tonic-gate interlace = roundup(MININTERLACE, interlace); 1665*0Sstevel@tonic-gate return (interlace); 1666*0Sstevel@tonic-gate } 1667*0Sstevel@tonic-gate 1668*0Sstevel@tonic-gate /* 1669*0Sstevel@tonic-gate * convert interlaces 1670*0Sstevel@tonic-gate */ 1671*0Sstevel@tonic-gate int 1672*0Sstevel@tonic-gate meta_stripe_check_interlace( 1673*0Sstevel@tonic-gate diskaddr_t interlace, 1674*0Sstevel@tonic-gate char *uname, 1675*0Sstevel@tonic-gate md_error_t *ep 1676*0Sstevel@tonic-gate ) 1677*0Sstevel@tonic-gate { 1678*0Sstevel@tonic-gate if ((interlace < btodb(MININTERLACE)) || 1679*0Sstevel@tonic-gate (interlace > btodb(MAXINTERLACE))) { 1680*0Sstevel@tonic-gate return (mderror(ep, MDE_BAD_INTERLACE, uname)); 1681*0Sstevel@tonic-gate } 1682*0Sstevel@tonic-gate return (0); 1683*0Sstevel@tonic-gate } 1684*0Sstevel@tonic-gate 1685*0Sstevel@tonic-gate 1686*0Sstevel@tonic-gate /* 1687*0Sstevel@tonic-gate * check stripe 1688*0Sstevel@tonic-gate */ 1689*0Sstevel@tonic-gate int 1690*0Sstevel@tonic-gate meta_check_stripe( 1691*0Sstevel@tonic-gate mdsetname_t *sp, 1692*0Sstevel@tonic-gate md_stripe_t *stripep, 1693*0Sstevel@tonic-gate mdcmdopts_t options, 1694*0Sstevel@tonic-gate md_error_t *ep 1695*0Sstevel@tonic-gate ) 1696*0Sstevel@tonic-gate { 1697*0Sstevel@tonic-gate mdname_t *stripenp = stripep->common.namep; 1698*0Sstevel@tonic-gate int force = ((options & MDCMD_FORCE) ? 1 : 0); 1699*0Sstevel@tonic-gate int doit = ((options & MDCMD_DOIT) ? 1 : 0); 1700*0Sstevel@tonic-gate int updateit = ((options & MDCMD_UPDATE) ? 1 : 0); 1701*0Sstevel@tonic-gate uint_t row; 1702*0Sstevel@tonic-gate 1703*0Sstevel@tonic-gate /* check rows */ 1704*0Sstevel@tonic-gate if (stripep->rows.rows_len < 1) { 1705*0Sstevel@tonic-gate return (mdmderror(ep, MDE_BAD_STRIPE, 1706*0Sstevel@tonic-gate meta_getminor(stripenp->dev), stripenp->cname)); 1707*0Sstevel@tonic-gate } 1708*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 1709*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1710*0Sstevel@tonic-gate uint_t comp; 1711*0Sstevel@tonic-gate 1712*0Sstevel@tonic-gate /* check number */ 1713*0Sstevel@tonic-gate if (rp->comps.comps_len < 1) { 1714*0Sstevel@tonic-gate return (mdmderror(ep, MDE_BAD_STRIPE, 1715*0Sstevel@tonic-gate meta_getminor(stripenp->dev), stripenp->cname)); 1716*0Sstevel@tonic-gate } 1717*0Sstevel@tonic-gate 1718*0Sstevel@tonic-gate /* compute default interlace */ 1719*0Sstevel@tonic-gate if (rp->interlace == 0) { 1720*0Sstevel@tonic-gate rp->interlace = meta_default_stripe_interlace(); 1721*0Sstevel@tonic-gate } 1722*0Sstevel@tonic-gate 1723*0Sstevel@tonic-gate /* check interlace */ 1724*0Sstevel@tonic-gate if (meta_stripe_check_interlace(rp->interlace, stripenp->cname, 1725*0Sstevel@tonic-gate ep) != 0) { 1726*0Sstevel@tonic-gate return (-1); 1727*0Sstevel@tonic-gate } 1728*0Sstevel@tonic-gate 1729*0Sstevel@tonic-gate /* check components */ 1730*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 1731*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 1732*0Sstevel@tonic-gate mdname_t *compnp = cp->compnamep; 1733*0Sstevel@tonic-gate diskaddr_t start_blk, size; 1734*0Sstevel@tonic-gate 1735*0Sstevel@tonic-gate /* check component */ 1736*0Sstevel@tonic-gate if (!updateit) { 1737*0Sstevel@tonic-gate if (meta_check_component(sp, compnp, 1738*0Sstevel@tonic-gate force, ep) != 0) 1739*0Sstevel@tonic-gate return (-1); 1740*0Sstevel@tonic-gate if (((start_blk = metagetstart(sp, compnp, 1741*0Sstevel@tonic-gate ep)) == MD_DISKADDR_ERROR) || 1742*0Sstevel@tonic-gate ((size = metagetsize(compnp, ep)) == 1743*0Sstevel@tonic-gate MD_DISKADDR_ERROR)) { 1744*0Sstevel@tonic-gate return (-1); 1745*0Sstevel@tonic-gate } 1746*0Sstevel@tonic-gate if (start_blk >= size) 1747*0Sstevel@tonic-gate return (mdsyserror(ep, ENOSPC, 1748*0Sstevel@tonic-gate compnp->cname)); 1749*0Sstevel@tonic-gate size -= start_blk; 1750*0Sstevel@tonic-gate size = rounddown(size, rp->interlace); 1751*0Sstevel@tonic-gate if (size == 0) 1752*0Sstevel@tonic-gate return (mdsyserror(ep, ENOSPC, 1753*0Sstevel@tonic-gate compnp->cname)); 1754*0Sstevel@tonic-gate } 1755*0Sstevel@tonic-gate 1756*0Sstevel@tonic-gate /* check this stripe too */ 1757*0Sstevel@tonic-gate if (check_twice(stripep, row, comp, ep) != 0) 1758*0Sstevel@tonic-gate return (-1); 1759*0Sstevel@tonic-gate } 1760*0Sstevel@tonic-gate } 1761*0Sstevel@tonic-gate 1762*0Sstevel@tonic-gate /* check hotspare pool name */ 1763*0Sstevel@tonic-gate if (doit) { 1764*0Sstevel@tonic-gate if ((stripep->hspnamep != NULL) && 1765*0Sstevel@tonic-gate (metachkhsp(sp, stripep->hspnamep, ep) != 0)) { 1766*0Sstevel@tonic-gate return (-1); 1767*0Sstevel@tonic-gate } 1768*0Sstevel@tonic-gate } 1769*0Sstevel@tonic-gate 1770*0Sstevel@tonic-gate /* return success */ 1771*0Sstevel@tonic-gate return (0); 1772*0Sstevel@tonic-gate } 1773*0Sstevel@tonic-gate 1774*0Sstevel@tonic-gate /* 1775*0Sstevel@tonic-gate * setup stripe geometry 1776*0Sstevel@tonic-gate */ 1777*0Sstevel@tonic-gate static int 1778*0Sstevel@tonic-gate stripe_geom( 1779*0Sstevel@tonic-gate md_stripe_t *stripep, 1780*0Sstevel@tonic-gate ms_unit_t *ms, 1781*0Sstevel@tonic-gate md_error_t *ep 1782*0Sstevel@tonic-gate ) 1783*0Sstevel@tonic-gate { 1784*0Sstevel@tonic-gate uint_t nrow = stripep->rows.rows_len; 1785*0Sstevel@tonic-gate uint_t write_reinstruct = 0; 1786*0Sstevel@tonic-gate uint_t read_reinstruct = 0; 1787*0Sstevel@tonic-gate uint_t round_cyl = 1; 1788*0Sstevel@tonic-gate uint_t row; 1789*0Sstevel@tonic-gate mdgeom_t *geomp; 1790*0Sstevel@tonic-gate diskaddr_t first_row_size = 0; 1791*0Sstevel@tonic-gate char *miscname; 1792*0Sstevel@tonic-gate int is_sp = 0; 1793*0Sstevel@tonic-gate 1794*0Sstevel@tonic-gate /* get worst reinstructs */ 1795*0Sstevel@tonic-gate for (row = 0; (row < nrow); ++row) { 1796*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1797*0Sstevel@tonic-gate uint_t ncomp = rp->comps.comps_len; 1798*0Sstevel@tonic-gate uint_t comp; 1799*0Sstevel@tonic-gate 1800*0Sstevel@tonic-gate for (comp = 0; (comp < ncomp); ++comp) { 1801*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 1802*0Sstevel@tonic-gate mdname_t *compnp = cp->compnamep; 1803*0Sstevel@tonic-gate 1804*0Sstevel@tonic-gate if ((geomp = metagetgeom(compnp, ep)) == NULL) 1805*0Sstevel@tonic-gate return (-1); 1806*0Sstevel@tonic-gate if (geomp->write_reinstruct > write_reinstruct) 1807*0Sstevel@tonic-gate write_reinstruct = geomp->write_reinstruct; 1808*0Sstevel@tonic-gate if (geomp->read_reinstruct > read_reinstruct) 1809*0Sstevel@tonic-gate read_reinstruct = geomp->read_reinstruct; 1810*0Sstevel@tonic-gate } 1811*0Sstevel@tonic-gate } 1812*0Sstevel@tonic-gate 1813*0Sstevel@tonic-gate if ((geomp = metagetgeom( 1814*0Sstevel@tonic-gate stripep->rows.rows_val[0].comps.comps_val[0].compnamep, 1815*0Sstevel@tonic-gate ep)) == NULL) { 1816*0Sstevel@tonic-gate return (-1); 1817*0Sstevel@tonic-gate } 1818*0Sstevel@tonic-gate /* 1819*0Sstevel@tonic-gate * Figure out if the first component is a softpartition as the 1820*0Sstevel@tonic-gate * truncation check only occurs on them. 1821*0Sstevel@tonic-gate */ 1822*0Sstevel@tonic-gate if ((miscname = metagetmiscname( 1823*0Sstevel@tonic-gate stripep->rows.rows_val[0].comps.comps_val[0].compnamep, 1824*0Sstevel@tonic-gate ep)) == NULL) { 1825*0Sstevel@tonic-gate if (!mdisdeverror(ep, MDE_NOT_META)) 1826*0Sstevel@tonic-gate return (-1); 1827*0Sstevel@tonic-gate } else if (strcmp(miscname, MD_SP) == 0) { 1828*0Sstevel@tonic-gate is_sp = 1; 1829*0Sstevel@tonic-gate } 1830*0Sstevel@tonic-gate 1831*0Sstevel@tonic-gate 1832*0Sstevel@tonic-gate /* setup geometry from first device */ 1833*0Sstevel@tonic-gate if (meta_setup_geom((md_unit_t *)ms, stripep->common.namep, geomp, 1834*0Sstevel@tonic-gate write_reinstruct, read_reinstruct, round_cyl, ep) != 0) 1835*0Sstevel@tonic-gate return (-1); 1836*0Sstevel@tonic-gate 1837*0Sstevel@tonic-gate /* 1838*0Sstevel@tonic-gate * Here we want to make sure that any truncation did not 1839*0Sstevel@tonic-gate * result in lost data (or, more appropriately, inaccessible 1840*0Sstevel@tonic-gate * data). 1841*0Sstevel@tonic-gate * 1842*0Sstevel@tonic-gate * This is mainly a danger for (1, 1) concats, but it is 1843*0Sstevel@tonic-gate * mathematically possible for other somewhat contrived 1844*0Sstevel@tonic-gate * arrangements where in the sum of the lengths of each row 1845*0Sstevel@tonic-gate * beyond the first is smaller than the cylinder size of the 1846*0Sstevel@tonic-gate * only component in the first row. 1847*0Sstevel@tonic-gate * 1848*0Sstevel@tonic-gate * It is tempting to simply test for truncation here, by 1849*0Sstevel@tonic-gate * (md->c.un_total_blocks < md->c.un_actual_tb). That does 1850*0Sstevel@tonic-gate * not tell us, however, if rounding resulted in data loss, 1851*0Sstevel@tonic-gate * rather only that it occurred. The somewhat less obvious 1852*0Sstevel@tonic-gate * test below covers both the obvious (1, 1) case and the 1853*0Sstevel@tonic-gate * aforementioned corner case. 1854*0Sstevel@tonic-gate */ 1855*0Sstevel@tonic-gate first_row_size = ms->un_row[0].un_blocks; 1856*0Sstevel@tonic-gate if (is_sp == 1) { 1857*0Sstevel@tonic-gate md_unit_t *md = (md_unit_t *)ms; 1858*0Sstevel@tonic-gate 1859*0Sstevel@tonic-gate if (md->c.un_total_blocks < first_row_size) { 1860*0Sstevel@tonic-gate char buf[] = VAL2STR(ULLONG_MAX); 1861*0Sstevel@tonic-gate 1862*0Sstevel@tonic-gate /* 1863*0Sstevel@tonic-gate * The only difference here is the text of the error 1864*0Sstevel@tonic-gate * message, since the remediation is slightly 1865*0Sstevel@tonic-gate * different in the one-component versus 1866*0Sstevel@tonic-gate * multiple-component cases. 1867*0Sstevel@tonic-gate */ 1868*0Sstevel@tonic-gate if (nrow == 1) { 1869*0Sstevel@tonic-gate (void) mderror(ep, MDE_STRIPE_TRUNC_SINGLE, 1870*0Sstevel@tonic-gate stripep->common.namep->cname); 1871*0Sstevel@tonic-gate } else { 1872*0Sstevel@tonic-gate (void) mderror(ep, MDE_STRIPE_TRUNC_MULTIPLE, 1873*0Sstevel@tonic-gate stripep->common.namep->cname); 1874*0Sstevel@tonic-gate } 1875*0Sstevel@tonic-gate 1876*0Sstevel@tonic-gate /* 1877*0Sstevel@tonic-gate * By the size comparison above and the initialization 1878*0Sstevel@tonic-gate * of buf[] in terms of ULLONG_MAX, we guarantee that 1879*0Sstevel@tonic-gate * the value arg is non-negative and that we won't 1880*0Sstevel@tonic-gate * overflow the container. 1881*0Sstevel@tonic-gate */ 1882*0Sstevel@tonic-gate mderrorextra(ep, ulltostr((md->c.un_total_blocks + 1883*0Sstevel@tonic-gate (geomp->nhead * geomp->nsect)) 1884*0Sstevel@tonic-gate - first_row_size, &buf[sizeof (buf) - 1])); 1885*0Sstevel@tonic-gate 1886*0Sstevel@tonic-gate return (-1); 1887*0Sstevel@tonic-gate } 1888*0Sstevel@tonic-gate } 1889*0Sstevel@tonic-gate 1890*0Sstevel@tonic-gate /* return success */ 1891*0Sstevel@tonic-gate return (0); 1892*0Sstevel@tonic-gate } 1893*0Sstevel@tonic-gate 1894*0Sstevel@tonic-gate /* 1895*0Sstevel@tonic-gate * create stripe 1896*0Sstevel@tonic-gate */ 1897*0Sstevel@tonic-gate int 1898*0Sstevel@tonic-gate meta_create_stripe( 1899*0Sstevel@tonic-gate mdsetname_t *sp, 1900*0Sstevel@tonic-gate md_stripe_t *stripep, 1901*0Sstevel@tonic-gate mdcmdopts_t options, 1902*0Sstevel@tonic-gate md_error_t *ep 1903*0Sstevel@tonic-gate ) 1904*0Sstevel@tonic-gate { 1905*0Sstevel@tonic-gate mdname_t *stripenp = stripep->common.namep; 1906*0Sstevel@tonic-gate int force = ((options & MDCMD_FORCE) ? 1 : 0); 1907*0Sstevel@tonic-gate int doall = ((options & MDCMD_ALLOPTION) ? 1 : 0); 1908*0Sstevel@tonic-gate uint_t nrow = stripep->rows.rows_len; 1909*0Sstevel@tonic-gate uint_t ncomp = 0; 1910*0Sstevel@tonic-gate uint_t icomp = 0; 1911*0Sstevel@tonic-gate diskaddr_t cum_blocks = 0; 1912*0Sstevel@tonic-gate diskaddr_t limit; 1913*0Sstevel@tonic-gate size_t mdsize, first_comp; 1914*0Sstevel@tonic-gate uint_t row; 1915*0Sstevel@tonic-gate ms_unit_t *ms; 1916*0Sstevel@tonic-gate ms_comp_t *mdcomp; 1917*0Sstevel@tonic-gate mdnamelist_t *keynlp = NULL; 1918*0Sstevel@tonic-gate md_set_params_t set_params; 1919*0Sstevel@tonic-gate int rval = -1; 1920*0Sstevel@tonic-gate md_timeval32_t creation_time; 1921*0Sstevel@tonic-gate int create_flag = MD_CRO_32BIT; 1922*0Sstevel@tonic-gate 1923*0Sstevel@tonic-gate /* validate stripe */ 1924*0Sstevel@tonic-gate if (meta_check_stripe(sp, stripep, options, ep) != 0) 1925*0Sstevel@tonic-gate return (-1); 1926*0Sstevel@tonic-gate 1927*0Sstevel@tonic-gate /* allocate stripe unit */ 1928*0Sstevel@tonic-gate mdsize = sizeof (*ms) - sizeof (ms->un_row[0]); 1929*0Sstevel@tonic-gate mdsize += sizeof (ms->un_row) * nrow; 1930*0Sstevel@tonic-gate for (row = 0; (row < nrow); ++row) { 1931*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1932*0Sstevel@tonic-gate 1933*0Sstevel@tonic-gate ncomp += rp->comps.comps_len; 1934*0Sstevel@tonic-gate } 1935*0Sstevel@tonic-gate first_comp = roundup(mdsize, sizeof (long long)); 1936*0Sstevel@tonic-gate mdsize += (first_comp - mdsize) + (ncomp * sizeof (ms_comp_t)); 1937*0Sstevel@tonic-gate ms = Zalloc(mdsize); 1938*0Sstevel@tonic-gate ms->un_ocomp = first_comp; 1939*0Sstevel@tonic-gate if (meta_gettimeofday(&creation_time) == -1) 1940*0Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL)); 1941*0Sstevel@tonic-gate 1942*0Sstevel@tonic-gate /* do rows */ 1943*0Sstevel@tonic-gate mdcomp = (ms_comp_t *)(void *)&((char *)ms)[ms->un_ocomp]; 1944*0Sstevel@tonic-gate for (row = 0; (row < nrow); ++row) { 1945*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 1946*0Sstevel@tonic-gate uint_t ncomp = rp->comps.comps_len; 1947*0Sstevel@tonic-gate struct ms_row *mdr = &ms->un_row[row]; 1948*0Sstevel@tonic-gate diskaddr_t disk_size = 0; 1949*0Sstevel@tonic-gate uint_t comp; 1950*0Sstevel@tonic-gate 1951*0Sstevel@tonic-gate /* setup component count and offfset */ 1952*0Sstevel@tonic-gate mdr->un_icomp = icomp; 1953*0Sstevel@tonic-gate mdr->un_ncomp = ncomp; 1954*0Sstevel@tonic-gate 1955*0Sstevel@tonic-gate /* do components */ 1956*0Sstevel@tonic-gate for (comp = 0; (comp < ncomp); ++comp) { 1957*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 1958*0Sstevel@tonic-gate mdname_t *compnp = cp->compnamep; 1959*0Sstevel@tonic-gate ms_comp_t *mdc = &mdcomp[icomp++]; 1960*0Sstevel@tonic-gate diskaddr_t size, start_blk; 1961*0Sstevel@tonic-gate 1962*0Sstevel@tonic-gate /* 1963*0Sstevel@tonic-gate * get start and size 1964*0Sstevel@tonic-gate * if first component is labelled, include label 1965*0Sstevel@tonic-gate */ 1966*0Sstevel@tonic-gate if ((size = metagetsize(compnp, ep)) == 1967*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 1968*0Sstevel@tonic-gate goto out; 1969*0Sstevel@tonic-gate if ((start_blk = metagetstart(sp, compnp, ep)) == 1970*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 1971*0Sstevel@tonic-gate goto out; 1972*0Sstevel@tonic-gate if ((row == 0) && (comp == 0)) { 1973*0Sstevel@tonic-gate diskaddr_t label; 1974*0Sstevel@tonic-gate int has_db; 1975*0Sstevel@tonic-gate 1976*0Sstevel@tonic-gate if ((has_db = metahasmddb(sp, compnp, ep)) < 0) 1977*0Sstevel@tonic-gate goto out; 1978*0Sstevel@tonic-gate if ((label = metagetlabel(compnp, ep)) == 1979*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 1980*0Sstevel@tonic-gate goto out; 1981*0Sstevel@tonic-gate if ((has_db == 0) && (label != 0)) { 1982*0Sstevel@tonic-gate ms->c.un_flag |= MD_LABELED; 1983*0Sstevel@tonic-gate start_blk = compnp->start_blk = 0; 1984*0Sstevel@tonic-gate } 1985*0Sstevel@tonic-gate } 1986*0Sstevel@tonic-gate /* make sure we still have something left */ 1987*0Sstevel@tonic-gate if (start_blk >= size) { 1988*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOSPC, compnp->cname); 1989*0Sstevel@tonic-gate goto out; 1990*0Sstevel@tonic-gate } 1991*0Sstevel@tonic-gate size -= start_blk; 1992*0Sstevel@tonic-gate 1993*0Sstevel@tonic-gate /* 1994*0Sstevel@tonic-gate * round down by interlace: this only applies 1995*0Sstevel@tonic-gate * if this row is a stripe, as indicated by 1996*0Sstevel@tonic-gate * (ncomp > 1) 1997*0Sstevel@tonic-gate */ 1998*0Sstevel@tonic-gate if (ncomp > 1) 1999*0Sstevel@tonic-gate size = rounddown(size, rp->interlace); 2000*0Sstevel@tonic-gate 2001*0Sstevel@tonic-gate if (size == 0) { 2002*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOSPC, compnp->cname); 2003*0Sstevel@tonic-gate goto out; 2004*0Sstevel@tonic-gate } 2005*0Sstevel@tonic-gate 2006*0Sstevel@tonic-gate /* 2007*0Sstevel@tonic-gate * adjust for smallest disk: for a concat (any 2008*0Sstevel@tonic-gate * row with only one component), this will 2009*0Sstevel@tonic-gate * never hit the second conditional. 2010*0Sstevel@tonic-gate */ 2011*0Sstevel@tonic-gate if (disk_size == 0) { 2012*0Sstevel@tonic-gate disk_size = size; 2013*0Sstevel@tonic-gate } else if (size < disk_size) { 2014*0Sstevel@tonic-gate disk_size = size; 2015*0Sstevel@tonic-gate } 2016*0Sstevel@tonic-gate 2017*0Sstevel@tonic-gate if (options & MDCMD_DOIT) { 2018*0Sstevel@tonic-gate /* store name in namespace */ 2019*0Sstevel@tonic-gate if (add_key_name(sp, compnp, &keynlp, ep) != 0) 2020*0Sstevel@tonic-gate goto out; 2021*0Sstevel@tonic-gate } 2022*0Sstevel@tonic-gate 2023*0Sstevel@tonic-gate /* setup component */ 2024*0Sstevel@tonic-gate mdc->un_key = compnp->key; 2025*0Sstevel@tonic-gate mdc->un_dev = compnp->dev; 2026*0Sstevel@tonic-gate mdc->un_start_block = start_blk; 2027*0Sstevel@tonic-gate mdc->un_mirror.ms_state = CS_OKAY; 2028*0Sstevel@tonic-gate mdc->un_mirror.ms_timestamp = creation_time; 2029*0Sstevel@tonic-gate } 2030*0Sstevel@tonic-gate limit = LLONG_MAX; 2031*0Sstevel@tonic-gate 2032*0Sstevel@tonic-gate /* setup row */ 2033*0Sstevel@tonic-gate mdr->un_blocks = mdr->un_ncomp * disk_size; 2034*0Sstevel@tonic-gate cum_blocks += mdr->un_blocks; 2035*0Sstevel@tonic-gate if (cum_blocks > limit) { 2036*0Sstevel@tonic-gate cum_blocks = limit; 2037*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 2038*0Sstevel@tonic-gate "unit size overflow, limit is %lld blocks\n"), 2039*0Sstevel@tonic-gate limit); 2040*0Sstevel@tonic-gate } 2041*0Sstevel@tonic-gate mdr->un_cum_blocks = cum_blocks; 2042*0Sstevel@tonic-gate mdr->un_interlace = rp->interlace; 2043*0Sstevel@tonic-gate } 2044*0Sstevel@tonic-gate 2045*0Sstevel@tonic-gate /* setup unit */ 2046*0Sstevel@tonic-gate ms->c.un_type = MD_DEVICE; 2047*0Sstevel@tonic-gate MD_SID(ms) = meta_getminor(stripenp->dev); 2048*0Sstevel@tonic-gate ms->c.un_actual_tb = cum_blocks; 2049*0Sstevel@tonic-gate ms->c.un_size = mdsize; 2050*0Sstevel@tonic-gate if (stripep->hspnamep != NULL) 2051*0Sstevel@tonic-gate ms->un_hsp_id = stripep->hspnamep->hsp; 2052*0Sstevel@tonic-gate else 2053*0Sstevel@tonic-gate ms->un_hsp_id = MD_HSP_NONE; 2054*0Sstevel@tonic-gate ms->un_nrows = nrow; 2055*0Sstevel@tonic-gate 2056*0Sstevel@tonic-gate /* fill in the size of the stripe */ 2057*0Sstevel@tonic-gate if (options & MDCMD_UPDATE) { 2058*0Sstevel@tonic-gate stripep->common.size = ms->c.un_total_blocks; 2059*0Sstevel@tonic-gate for (row = 0; (row < nrow); ++row) { 2060*0Sstevel@tonic-gate stripep->rows.rows_val[row].row_size = 2061*0Sstevel@tonic-gate ms->un_row[row].un_blocks; 2062*0Sstevel@tonic-gate } 2063*0Sstevel@tonic-gate } 2064*0Sstevel@tonic-gate 2065*0Sstevel@tonic-gate if (stripe_geom(stripep, ms, ep) != 0) { 2066*0Sstevel@tonic-gate /* 2067*0Sstevel@tonic-gate * If the device is being truncated then only allow this 2068*0Sstevel@tonic-gate * if the user is aware (using the -f option) or they 2069*0Sstevel@tonic-gate * are in a recovery/complete build situation (using the -a 2070*0Sstevel@tonic-gate * option). 2071*0Sstevel@tonic-gate */ 2072*0Sstevel@tonic-gate if ((mdiserror(ep, MDE_STRIPE_TRUNC_SINGLE) || 2073*0Sstevel@tonic-gate mdiserror(ep, MDE_STRIPE_TRUNC_MULTIPLE)) && 2074*0Sstevel@tonic-gate (force || doall)) { 2075*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 2076*0Sstevel@tonic-gate "%s: WARNING: This form of metainit is not recommended.\n" 2077*0Sstevel@tonic-gate "The stripe is truncating the size of the underlying device.\n" 2078*0Sstevel@tonic-gate "Please see ERRORS in metainit(1M) for additional information.\n"), 2079*0Sstevel@tonic-gate stripenp->cname); 2080*0Sstevel@tonic-gate mdclrerror(ep); 2081*0Sstevel@tonic-gate } else { 2082*0Sstevel@tonic-gate goto out; 2083*0Sstevel@tonic-gate } 2084*0Sstevel@tonic-gate } 2085*0Sstevel@tonic-gate 2086*0Sstevel@tonic-gate create_flag = meta_check_devicesize(ms->c.un_total_blocks); 2087*0Sstevel@tonic-gate 2088*0Sstevel@tonic-gate /* if we're not doing anything, return success */ 2089*0Sstevel@tonic-gate if (! (options & MDCMD_DOIT)) { 2090*0Sstevel@tonic-gate rval = 0; /* success */ 2091*0Sstevel@tonic-gate goto out; 2092*0Sstevel@tonic-gate } 2093*0Sstevel@tonic-gate 2094*0Sstevel@tonic-gate /* create stripe */ 2095*0Sstevel@tonic-gate (void) memset(&set_params, 0, sizeof (set_params)); 2096*0Sstevel@tonic-gate 2097*0Sstevel@tonic-gate /* did the user tell us to generate a large device? */ 2098*0Sstevel@tonic-gate if (create_flag == MD_CRO_64BIT) { 2099*0Sstevel@tonic-gate ms->c.un_revision = MD_64BIT_META_DEV; 2100*0Sstevel@tonic-gate set_params.options = MD_CRO_64BIT; 2101*0Sstevel@tonic-gate } else { 2102*0Sstevel@tonic-gate ms->c.un_revision = MD_32BIT_META_DEV; 2103*0Sstevel@tonic-gate set_params.options = MD_CRO_32BIT; 2104*0Sstevel@tonic-gate } 2105*0Sstevel@tonic-gate 2106*0Sstevel@tonic-gate set_params.mnum = MD_SID(ms); 2107*0Sstevel@tonic-gate set_params.size = ms->c.un_size; 2108*0Sstevel@tonic-gate set_params.mdp = (uintptr_t)ms; 2109*0Sstevel@tonic-gate MD_SETDRIVERNAME(&set_params, MD_STRIPE, MD_MIN2SET(set_params.mnum)); 2110*0Sstevel@tonic-gate if (metaioctl(MD_IOCSET, &set_params, &set_params.mde, 2111*0Sstevel@tonic-gate stripenp->cname) != 0) { 2112*0Sstevel@tonic-gate (void) mdstealerror(ep, &set_params.mde); 2113*0Sstevel@tonic-gate goto out; 2114*0Sstevel@tonic-gate } 2115*0Sstevel@tonic-gate rval = 0; /* success */ 2116*0Sstevel@tonic-gate 2117*0Sstevel@tonic-gate /* cleanup, return success */ 2118*0Sstevel@tonic-gate out: 2119*0Sstevel@tonic-gate Free(ms); 2120*0Sstevel@tonic-gate if (rval != 0) { 2121*0Sstevel@tonic-gate (void) del_key_names(sp, keynlp, NULL); 2122*0Sstevel@tonic-gate } 2123*0Sstevel@tonic-gate 2124*0Sstevel@tonic-gate metafreenamelist(keynlp); 2125*0Sstevel@tonic-gate if ((rval == 0) && (options & MDCMD_DOIT)) { 2126*0Sstevel@tonic-gate if (invalidate_components(sp, stripenp, ep) != 0) 2127*0Sstevel@tonic-gate rval = -1; 2128*0Sstevel@tonic-gate meta_invalidate_name(stripenp); 2129*0Sstevel@tonic-gate } 2130*0Sstevel@tonic-gate return (rval); 2131*0Sstevel@tonic-gate } 2132*0Sstevel@tonic-gate 2133*0Sstevel@tonic-gate /* 2134*0Sstevel@tonic-gate * initialize stripe 2135*0Sstevel@tonic-gate * NOTE: this functions is metainit(1m)'s command line parser! 2136*0Sstevel@tonic-gate */ 2137*0Sstevel@tonic-gate int 2138*0Sstevel@tonic-gate meta_init_stripe( 2139*0Sstevel@tonic-gate mdsetname_t **spp, 2140*0Sstevel@tonic-gate int argc, 2141*0Sstevel@tonic-gate char *argv[], 2142*0Sstevel@tonic-gate mdcmdopts_t options, 2143*0Sstevel@tonic-gate md_error_t *ep 2144*0Sstevel@tonic-gate ) 2145*0Sstevel@tonic-gate { 2146*0Sstevel@tonic-gate char *uname = argv[0]; 2147*0Sstevel@tonic-gate mdname_t *stripenp = NULL; 2148*0Sstevel@tonic-gate int old_optind; 2149*0Sstevel@tonic-gate int c; 2150*0Sstevel@tonic-gate md_stripe_t *stripep = NULL; 2151*0Sstevel@tonic-gate uint_t nrow, row; 2152*0Sstevel@tonic-gate int rval = -1; 2153*0Sstevel@tonic-gate 2154*0Sstevel@tonic-gate /* get stripe name */ 2155*0Sstevel@tonic-gate assert(argc > 0); 2156*0Sstevel@tonic-gate if (argc < 1) 2157*0Sstevel@tonic-gate goto syntax; 2158*0Sstevel@tonic-gate 2159*0Sstevel@tonic-gate if ((stripenp = metaname(spp, uname, ep)) == NULL) 2160*0Sstevel@tonic-gate goto out; 2161*0Sstevel@tonic-gate assert(*spp != NULL); 2162*0Sstevel@tonic-gate uname = stripenp->cname; 2163*0Sstevel@tonic-gate if (metachkmeta(stripenp, ep) != 0) 2164*0Sstevel@tonic-gate goto out; 2165*0Sstevel@tonic-gate 2166*0Sstevel@tonic-gate if (!(options & MDCMD_NOLOCK)) { 2167*0Sstevel@tonic-gate /* grab set lock */ 2168*0Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep)) 2169*0Sstevel@tonic-gate goto out; 2170*0Sstevel@tonic-gate 2171*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 2172*0Sstevel@tonic-gate goto out; 2173*0Sstevel@tonic-gate } 2174*0Sstevel@tonic-gate 2175*0Sstevel@tonic-gate /* see if it exists already */ 2176*0Sstevel@tonic-gate if (metagetmiscname(stripenp, ep) != NULL) { 2177*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP, 2178*0Sstevel@tonic-gate meta_getminor(stripenp->dev), uname); 2179*0Sstevel@tonic-gate goto out; 2180*0Sstevel@tonic-gate } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) { 2181*0Sstevel@tonic-gate goto out; 2182*0Sstevel@tonic-gate } else { 2183*0Sstevel@tonic-gate mdclrerror(ep); 2184*0Sstevel@tonic-gate } 2185*0Sstevel@tonic-gate --argc, ++argv; 2186*0Sstevel@tonic-gate 2187*0Sstevel@tonic-gate /* parse general options */ 2188*0Sstevel@tonic-gate optind = 0; 2189*0Sstevel@tonic-gate opterr = 0; 2190*0Sstevel@tonic-gate if (getopt(argc, argv, "") != -1) 2191*0Sstevel@tonic-gate goto options; 2192*0Sstevel@tonic-gate 2193*0Sstevel@tonic-gate /* allocate stripe */ 2194*0Sstevel@tonic-gate stripep = Zalloc(sizeof (*stripep)); 2195*0Sstevel@tonic-gate 2196*0Sstevel@tonic-gate /* setup common */ 2197*0Sstevel@tonic-gate stripep->common.namep = stripenp; 2198*0Sstevel@tonic-gate stripep->common.type = MD_DEVICE; 2199*0Sstevel@tonic-gate 2200*0Sstevel@tonic-gate /* allocate and parse rows */ 2201*0Sstevel@tonic-gate if (argc < 1) { 2202*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_NROWS, meta_getminor(stripenp->dev), 2203*0Sstevel@tonic-gate uname); 2204*0Sstevel@tonic-gate goto out; 2205*0Sstevel@tonic-gate } else if ((sscanf(argv[0], "%u", &nrow) != 1) || ((int)nrow < 0)) { 2206*0Sstevel@tonic-gate goto syntax; 2207*0Sstevel@tonic-gate } else if (nrow < 1) { 2208*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_NROWS, meta_getminor(stripenp->dev), 2209*0Sstevel@tonic-gate uname); 2210*0Sstevel@tonic-gate goto out; 2211*0Sstevel@tonic-gate } 2212*0Sstevel@tonic-gate --argc, ++argv; 2213*0Sstevel@tonic-gate stripep->rows.rows_len = nrow; 2214*0Sstevel@tonic-gate stripep->rows.rows_val = 2215*0Sstevel@tonic-gate Zalloc(nrow * sizeof (*stripep->rows.rows_val)); 2216*0Sstevel@tonic-gate for (row = 0; (row < nrow); ++row) { 2217*0Sstevel@tonic-gate md_row_t *mdr = &stripep->rows.rows_val[row]; 2218*0Sstevel@tonic-gate uint_t ncomp, comp; 2219*0Sstevel@tonic-gate 2220*0Sstevel@tonic-gate /* allocate and parse components */ 2221*0Sstevel@tonic-gate if (argc < 1) { 2222*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_NROWS, 2223*0Sstevel@tonic-gate meta_getminor(stripenp->dev), uname); 2224*0Sstevel@tonic-gate goto out; 2225*0Sstevel@tonic-gate } else if ((sscanf(argv[0], "%u", &ncomp) != 1) || 2226*0Sstevel@tonic-gate ((int)ncomp < 0)) { 2227*0Sstevel@tonic-gate goto syntax; 2228*0Sstevel@tonic-gate } else if (ncomp < 1) { 2229*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_NCOMPS, 2230*0Sstevel@tonic-gate meta_getminor(stripenp->dev), uname); 2231*0Sstevel@tonic-gate goto out; 2232*0Sstevel@tonic-gate } 2233*0Sstevel@tonic-gate --argc, ++argv; 2234*0Sstevel@tonic-gate mdr->comps.comps_len = ncomp; 2235*0Sstevel@tonic-gate mdr->comps.comps_val = 2236*0Sstevel@tonic-gate Zalloc(ncomp * sizeof (*mdr->comps.comps_val)); 2237*0Sstevel@tonic-gate for (comp = 0; (comp < ncomp); ++comp) { 2238*0Sstevel@tonic-gate md_comp_t *mdc = &mdr->comps.comps_val[comp]; 2239*0Sstevel@tonic-gate mdname_t *compnp; 2240*0Sstevel@tonic-gate 2241*0Sstevel@tonic-gate /* parse component name */ 2242*0Sstevel@tonic-gate if (argc < 1) { 2243*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_NCOMPS, 2244*0Sstevel@tonic-gate meta_getminor(stripenp->dev), uname); 2245*0Sstevel@tonic-gate goto out; 2246*0Sstevel@tonic-gate } 2247*0Sstevel@tonic-gate if ((compnp = metaname(spp, argv[0], ep)) == NULL) { 2248*0Sstevel@tonic-gate goto out; 2249*0Sstevel@tonic-gate } 2250*0Sstevel@tonic-gate /* check for soft partition */ 2251*0Sstevel@tonic-gate if (meta_sp_issp(*spp, compnp, ep) != 0) { 2252*0Sstevel@tonic-gate /* check disk */ 2253*0Sstevel@tonic-gate if (metachkcomp(compnp, ep) != 0) { 2254*0Sstevel@tonic-gate goto out; 2255*0Sstevel@tonic-gate } 2256*0Sstevel@tonic-gate } 2257*0Sstevel@tonic-gate mdc->compnamep = compnp; 2258*0Sstevel@tonic-gate --argc, ++argv; 2259*0Sstevel@tonic-gate } 2260*0Sstevel@tonic-gate 2261*0Sstevel@tonic-gate /* parse row options */ 2262*0Sstevel@tonic-gate old_optind = optind = 0; 2263*0Sstevel@tonic-gate opterr = 0; 2264*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "i:")) != -1) { 2265*0Sstevel@tonic-gate switch (c) { 2266*0Sstevel@tonic-gate case 'i': 2267*0Sstevel@tonic-gate if (parse_interlace(uname, optarg, 2268*0Sstevel@tonic-gate &mdr->interlace, ep) != 0) { 2269*0Sstevel@tonic-gate goto out; 2270*0Sstevel@tonic-gate } 2271*0Sstevel@tonic-gate if (meta_stripe_check_interlace(mdr->interlace, 2272*0Sstevel@tonic-gate uname, ep)) 2273*0Sstevel@tonic-gate goto out; 2274*0Sstevel@tonic-gate break; 2275*0Sstevel@tonic-gate 2276*0Sstevel@tonic-gate default: 2277*0Sstevel@tonic-gate optind = old_optind; /* bomb out later */ 2278*0Sstevel@tonic-gate goto done_row_opts; 2279*0Sstevel@tonic-gate } 2280*0Sstevel@tonic-gate old_optind = optind; 2281*0Sstevel@tonic-gate } 2282*0Sstevel@tonic-gate done_row_opts: 2283*0Sstevel@tonic-gate argc -= optind; 2284*0Sstevel@tonic-gate argv += optind; 2285*0Sstevel@tonic-gate } 2286*0Sstevel@tonic-gate 2287*0Sstevel@tonic-gate /* parse stripe options */ 2288*0Sstevel@tonic-gate old_optind = optind = 0; 2289*0Sstevel@tonic-gate opterr = 0; 2290*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "h:")) != -1) { 2291*0Sstevel@tonic-gate switch (c) { 2292*0Sstevel@tonic-gate case 'h': 2293*0Sstevel@tonic-gate if ((stripep->hspnamep = metahspname(spp, optarg, 2294*0Sstevel@tonic-gate ep)) == NULL) { 2295*0Sstevel@tonic-gate goto out; 2296*0Sstevel@tonic-gate } 2297*0Sstevel@tonic-gate break; 2298*0Sstevel@tonic-gate 2299*0Sstevel@tonic-gate default: 2300*0Sstevel@tonic-gate argc += old_optind; 2301*0Sstevel@tonic-gate argv += old_optind; 2302*0Sstevel@tonic-gate goto options; 2303*0Sstevel@tonic-gate } 2304*0Sstevel@tonic-gate old_optind = optind; 2305*0Sstevel@tonic-gate } 2306*0Sstevel@tonic-gate argc -= optind; 2307*0Sstevel@tonic-gate argv += optind; 2308*0Sstevel@tonic-gate 2309*0Sstevel@tonic-gate /* we should be at the end */ 2310*0Sstevel@tonic-gate if (argc != 0) 2311*0Sstevel@tonic-gate goto syntax; 2312*0Sstevel@tonic-gate 2313*0Sstevel@tonic-gate /* create stripe */ 2314*0Sstevel@tonic-gate if (meta_create_stripe(*spp, stripep, options, ep) != 0) 2315*0Sstevel@tonic-gate goto out; 2316*0Sstevel@tonic-gate rval = 0; /* success */ 2317*0Sstevel@tonic-gate 2318*0Sstevel@tonic-gate /* let em know */ 2319*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 2320*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 2321*0Sstevel@tonic-gate "%s: Concat/Stripe is setup\n"), 2322*0Sstevel@tonic-gate uname); 2323*0Sstevel@tonic-gate (void) fflush(stdout); 2324*0Sstevel@tonic-gate } 2325*0Sstevel@tonic-gate goto out; 2326*0Sstevel@tonic-gate 2327*0Sstevel@tonic-gate /* syntax error */ 2328*0Sstevel@tonic-gate syntax: 2329*0Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_SYNTAX, uname, argc, argv); 2330*0Sstevel@tonic-gate goto out; 2331*0Sstevel@tonic-gate 2332*0Sstevel@tonic-gate /* options error */ 2333*0Sstevel@tonic-gate options: 2334*0Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_OPTION, uname, argc, argv); 2335*0Sstevel@tonic-gate goto out; 2336*0Sstevel@tonic-gate 2337*0Sstevel@tonic-gate /* cleanup, return error */ 2338*0Sstevel@tonic-gate out: 2339*0Sstevel@tonic-gate if (stripep != NULL) 2340*0Sstevel@tonic-gate meta_free_stripe(stripep); 2341*0Sstevel@tonic-gate return (rval); 2342*0Sstevel@tonic-gate } 2343*0Sstevel@tonic-gate 2344*0Sstevel@tonic-gate /* 2345*0Sstevel@tonic-gate * reset stripes 2346*0Sstevel@tonic-gate */ 2347*0Sstevel@tonic-gate int 2348*0Sstevel@tonic-gate meta_stripe_reset( 2349*0Sstevel@tonic-gate mdsetname_t *sp, 2350*0Sstevel@tonic-gate mdname_t *stripenp, 2351*0Sstevel@tonic-gate mdcmdopts_t options, 2352*0Sstevel@tonic-gate md_error_t *ep 2353*0Sstevel@tonic-gate ) 2354*0Sstevel@tonic-gate { 2355*0Sstevel@tonic-gate md_stripe_t *stripep; 2356*0Sstevel@tonic-gate int rval = -1; 2357*0Sstevel@tonic-gate int row, comp; 2358*0Sstevel@tonic-gate 2359*0Sstevel@tonic-gate /* should have same set */ 2360*0Sstevel@tonic-gate assert(sp != NULL); 2361*0Sstevel@tonic-gate assert((stripenp == NULL) || 2362*0Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(stripenp->dev)))); 2363*0Sstevel@tonic-gate 2364*0Sstevel@tonic-gate /* reset all stripes */ 2365*0Sstevel@tonic-gate if (stripenp == NULL) { 2366*0Sstevel@tonic-gate mdnamelist_t *stripenlp = NULL; 2367*0Sstevel@tonic-gate mdnamelist_t *p; 2368*0Sstevel@tonic-gate 2369*0Sstevel@tonic-gate /* for each stripe */ 2370*0Sstevel@tonic-gate rval = 0; 2371*0Sstevel@tonic-gate if (meta_get_stripe_names(sp, &stripenlp, 0, ep) < 0) 2372*0Sstevel@tonic-gate return (-1); 2373*0Sstevel@tonic-gate for (p = stripenlp; (p != NULL); p = p->next) { 2374*0Sstevel@tonic-gate /* reset stripe */ 2375*0Sstevel@tonic-gate stripenp = p->namep; 2376*0Sstevel@tonic-gate 2377*0Sstevel@tonic-gate /* 2378*0Sstevel@tonic-gate * If this is a multi-node set, we send a series 2379*0Sstevel@tonic-gate * of individual metaclear commands. 2380*0Sstevel@tonic-gate */ 2381*0Sstevel@tonic-gate if (meta_is_mn_set(sp, ep)) { 2382*0Sstevel@tonic-gate if (meta_mn_send_metaclear_command(sp, 2383*0Sstevel@tonic-gate stripenp->cname, options, 0, ep) != 0) { 2384*0Sstevel@tonic-gate rval = -1; 2385*0Sstevel@tonic-gate break; 2386*0Sstevel@tonic-gate } 2387*0Sstevel@tonic-gate } else { 2388*0Sstevel@tonic-gate if (meta_stripe_reset(sp, stripenp, 2389*0Sstevel@tonic-gate options, ep) != 0) { 2390*0Sstevel@tonic-gate rval = -1; 2391*0Sstevel@tonic-gate break; 2392*0Sstevel@tonic-gate } 2393*0Sstevel@tonic-gate } 2394*0Sstevel@tonic-gate } 2395*0Sstevel@tonic-gate 2396*0Sstevel@tonic-gate /* cleanup, return success */ 2397*0Sstevel@tonic-gate metafreenamelist(stripenlp); 2398*0Sstevel@tonic-gate return (rval); 2399*0Sstevel@tonic-gate } 2400*0Sstevel@tonic-gate 2401*0Sstevel@tonic-gate /* check name */ 2402*0Sstevel@tonic-gate if (metachkmeta(stripenp, ep) != 0) 2403*0Sstevel@tonic-gate return (-1); 2404*0Sstevel@tonic-gate 2405*0Sstevel@tonic-gate /* get unit structure */ 2406*0Sstevel@tonic-gate if ((stripep = meta_get_stripe(sp, stripenp, ep)) == NULL) 2407*0Sstevel@tonic-gate return (-1); 2408*0Sstevel@tonic-gate 2409*0Sstevel@tonic-gate /* make sure nobody owns us */ 2410*0Sstevel@tonic-gate if (MD_HAS_PARENT(stripep->common.parent)) { 2411*0Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_USE, meta_getminor(stripenp->dev), 2412*0Sstevel@tonic-gate stripenp->cname)); 2413*0Sstevel@tonic-gate } 2414*0Sstevel@tonic-gate 2415*0Sstevel@tonic-gate /* clear subdevices cache */ 2416*0Sstevel@tonic-gate if (invalidate_components(sp, stripenp, ep) != 0) 2417*0Sstevel@tonic-gate return (-1); 2418*0Sstevel@tonic-gate 2419*0Sstevel@tonic-gate /* clear metadevice */ 2420*0Sstevel@tonic-gate if (meta_reset(sp, stripenp, options, ep) != 0) 2421*0Sstevel@tonic-gate goto out; 2422*0Sstevel@tonic-gate rval = 0; /* success */ 2423*0Sstevel@tonic-gate 2424*0Sstevel@tonic-gate /* let em know */ 2425*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 2426*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 2427*0Sstevel@tonic-gate "%s: Concat/Stripe is cleared\n"), 2428*0Sstevel@tonic-gate stripenp->cname); 2429*0Sstevel@tonic-gate (void) fflush(stdout); 2430*0Sstevel@tonic-gate } 2431*0Sstevel@tonic-gate 2432*0Sstevel@tonic-gate /* clear subdevices */ 2433*0Sstevel@tonic-gate if (! (options & MDCMD_RECURSE)) 2434*0Sstevel@tonic-gate goto out; 2435*0Sstevel@tonic-gate 2436*0Sstevel@tonic-gate for (row = 0; (row < stripep->rows.rows_len); ++row) { 2437*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 2438*0Sstevel@tonic-gate for (comp = 0; (comp < rp->comps.comps_len); ++comp) { 2439*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 2440*0Sstevel@tonic-gate mdname_t *compnp = cp->compnamep; 2441*0Sstevel@tonic-gate 2442*0Sstevel@tonic-gate /* only recurse on metadevices */ 2443*0Sstevel@tonic-gate if (! metaismeta(compnp)) 2444*0Sstevel@tonic-gate continue; 2445*0Sstevel@tonic-gate 2446*0Sstevel@tonic-gate if (meta_reset_by_name(sp, compnp, options, ep) != 0) 2447*0Sstevel@tonic-gate rval = -1; 2448*0Sstevel@tonic-gate } 2449*0Sstevel@tonic-gate } 2450*0Sstevel@tonic-gate 2451*0Sstevel@tonic-gate /* cleanup, return success */ 2452*0Sstevel@tonic-gate out: 2453*0Sstevel@tonic-gate meta_invalidate_name(stripenp); 2454*0Sstevel@tonic-gate return (rval); 2455*0Sstevel@tonic-gate } 2456*0Sstevel@tonic-gate 2457*0Sstevel@tonic-gate /* 2458*0Sstevel@tonic-gate * reports TRUE if any stripe component is in error 2459*0Sstevel@tonic-gate */ 2460*0Sstevel@tonic-gate int 2461*0Sstevel@tonic-gate meta_stripe_anycomp_is_err(mdsetname_t *sp, mdnamelist_t *stripe_names) 2462*0Sstevel@tonic-gate { 2463*0Sstevel@tonic-gate mdnamelist_t *nlp; 2464*0Sstevel@tonic-gate md_error_t status = mdnullerror; 2465*0Sstevel@tonic-gate md_error_t *ep = &status; 2466*0Sstevel@tonic-gate int any_errs = FALSE; 2467*0Sstevel@tonic-gate 2468*0Sstevel@tonic-gate for (nlp = stripe_names; nlp; nlp = nlp->next) { 2469*0Sstevel@tonic-gate md_stripe_t *stripep; 2470*0Sstevel@tonic-gate int row; 2471*0Sstevel@tonic-gate 2472*0Sstevel@tonic-gate if ((stripep = meta_get_stripe(sp, nlp->namep, ep)) == NULL) { 2473*0Sstevel@tonic-gate any_errs |= TRUE; 2474*0Sstevel@tonic-gate goto out; 2475*0Sstevel@tonic-gate } 2476*0Sstevel@tonic-gate 2477*0Sstevel@tonic-gate for (row = 0; row < stripep->rows.rows_len; ++row) { 2478*0Sstevel@tonic-gate md_row_t *rp = &stripep->rows.rows_val[row]; 2479*0Sstevel@tonic-gate uint_t comp; 2480*0Sstevel@tonic-gate 2481*0Sstevel@tonic-gate for (comp = 0; comp < rp->comps.comps_len; ++comp) { 2482*0Sstevel@tonic-gate md_comp_t *cp = &rp->comps.comps_val[comp]; 2483*0Sstevel@tonic-gate 2484*0Sstevel@tonic-gate if (cp->state != CS_OKAY) { 2485*0Sstevel@tonic-gate any_errs |= TRUE; 2486*0Sstevel@tonic-gate goto out; 2487*0Sstevel@tonic-gate } 2488*0Sstevel@tonic-gate } 2489*0Sstevel@tonic-gate } 2490*0Sstevel@tonic-gate } 2491*0Sstevel@tonic-gate out: 2492*0Sstevel@tonic-gate if (!mdisok(ep)) 2493*0Sstevel@tonic-gate mdclrerror(ep); 2494*0Sstevel@tonic-gate 2495*0Sstevel@tonic-gate return (any_errs); 2496*0Sstevel@tonic-gate } 2497