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 * Just in case we're not in a build environment, make sure that 30*0Sstevel@tonic-gate * TEXT_DOMAIN gets set to something. 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 33*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 34*0Sstevel@tonic-gate #endif 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate /* 37*0Sstevel@tonic-gate * RAID operations 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #include <stdlib.h> 41*0Sstevel@tonic-gate #include <meta.h> 42*0Sstevel@tonic-gate #include <sys/lvm/md_raid.h> 43*0Sstevel@tonic-gate #include <sys/lvm/mdvar.h> 44*0Sstevel@tonic-gate #include <sys/lvm/md_convert.h> 45*0Sstevel@tonic-gate #include <stddef.h> 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate /* 48*0Sstevel@tonic-gate * FUNCTION: meta_get_raid_names() 49*0Sstevel@tonic-gate * INPUT: sp - the set name to get raid from 50*0Sstevel@tonic-gate * options - options from the command line 51*0Sstevel@tonic-gate * OUTPUT: nlpp - list of all raid names 52*0Sstevel@tonic-gate * ep - return error pointer 53*0Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 success 54*0Sstevel@tonic-gate * PURPOSE: returns a list of all raid in the metadb 55*0Sstevel@tonic-gate * for all devices in the specified set 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate int 58*0Sstevel@tonic-gate meta_get_raid_names( 59*0Sstevel@tonic-gate mdsetname_t *sp, 60*0Sstevel@tonic-gate mdnamelist_t **nlpp, 61*0Sstevel@tonic-gate int options, 62*0Sstevel@tonic-gate md_error_t *ep 63*0Sstevel@tonic-gate ) 64*0Sstevel@tonic-gate { 65*0Sstevel@tonic-gate return (meta_get_names(MD_RAID, sp, nlpp, options, ep)); 66*0Sstevel@tonic-gate } 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate /* 69*0Sstevel@tonic-gate * free raid unit 70*0Sstevel@tonic-gate */ 71*0Sstevel@tonic-gate void 72*0Sstevel@tonic-gate meta_free_raid( 73*0Sstevel@tonic-gate md_raid_t *raidp 74*0Sstevel@tonic-gate ) 75*0Sstevel@tonic-gate { 76*0Sstevel@tonic-gate if (raidp->cols.cols_val != NULL) { 77*0Sstevel@tonic-gate assert(raidp->cols.cols_len > 0); 78*0Sstevel@tonic-gate Free(raidp->cols.cols_val); 79*0Sstevel@tonic-gate } 80*0Sstevel@tonic-gate Free(raidp); 81*0Sstevel@tonic-gate } 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * get raid (common) 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate md_raid_t * 87*0Sstevel@tonic-gate meta_get_raid_common( 88*0Sstevel@tonic-gate mdsetname_t *sp, 89*0Sstevel@tonic-gate mdname_t *raidnp, 90*0Sstevel@tonic-gate int fast, 91*0Sstevel@tonic-gate md_error_t *ep 92*0Sstevel@tonic-gate ) 93*0Sstevel@tonic-gate { 94*0Sstevel@tonic-gate mddrivename_t *dnp = raidnp->drivenamep; 95*0Sstevel@tonic-gate char *miscname; 96*0Sstevel@tonic-gate mr_unit_t *mr; 97*0Sstevel@tonic-gate md_raid_t *raidp; 98*0Sstevel@tonic-gate uint_t ncol; 99*0Sstevel@tonic-gate uint_t col; 100*0Sstevel@tonic-gate md_resync_ioctl_t ri; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate /* must have set */ 103*0Sstevel@tonic-gate assert(sp != NULL); 104*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate /* short circuit */ 107*0Sstevel@tonic-gate if (dnp->unitp != NULL) { 108*0Sstevel@tonic-gate assert(dnp->unitp->type == MD_METARAID); 109*0Sstevel@tonic-gate return ((md_raid_t *)dnp->unitp); 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* get miscname and unit */ 113*0Sstevel@tonic-gate if ((miscname = metagetmiscname(raidnp, ep)) == NULL) 114*0Sstevel@tonic-gate return (NULL); 115*0Sstevel@tonic-gate if (strcmp(miscname, MD_RAID) != 0) { 116*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_NOT_RAID, meta_getminor(raidnp->dev), 117*0Sstevel@tonic-gate raidnp->cname); 118*0Sstevel@tonic-gate return (NULL); 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL) 121*0Sstevel@tonic-gate return (NULL); 122*0Sstevel@tonic-gate assert(mr->c.un_type == MD_METARAID); 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate /* allocate raid */ 125*0Sstevel@tonic-gate raidp = Zalloc(sizeof (*raidp)); 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* allocate columns */ 128*0Sstevel@tonic-gate ncol = mr->un_totalcolumncnt; 129*0Sstevel@tonic-gate assert(ncol >= MD_RAID_MIN); 130*0Sstevel@tonic-gate raidp->cols.cols_len = ncol; 131*0Sstevel@tonic-gate raidp->cols.cols_val = Zalloc(raidp->cols.cols_len * 132*0Sstevel@tonic-gate sizeof (*raidp->cols.cols_val)); 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* get common info */ 135*0Sstevel@tonic-gate raidp->common.namep = raidnp; 136*0Sstevel@tonic-gate raidp->common.type = mr->c.un_type; 137*0Sstevel@tonic-gate raidp->common.state = mr->c.un_status; 138*0Sstevel@tonic-gate raidp->common.capabilities = mr->c.un_capabilities; 139*0Sstevel@tonic-gate raidp->common.parent = mr->c.un_parent; 140*0Sstevel@tonic-gate raidp->common.size = mr->c.un_total_blocks; 141*0Sstevel@tonic-gate raidp->common.user_flags = mr->c.un_user_flags; 142*0Sstevel@tonic-gate raidp->common.revision = mr->c.un_revision; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate /* get options */ 145*0Sstevel@tonic-gate raidp->state = mr->un_state; 146*0Sstevel@tonic-gate raidp->timestamp = mr->un_timestamp; 147*0Sstevel@tonic-gate raidp->interlace = mr->un_segsize; 148*0Sstevel@tonic-gate raidp->orig_ncol = mr->un_origcolumncnt; 149*0Sstevel@tonic-gate raidp->column_size = mr->un_segsize * mr->un_segsincolumn; 150*0Sstevel@tonic-gate raidp->pw_count = mr->un_pwcnt; 151*0Sstevel@tonic-gate assert(raidp->orig_ncol <= ncol); 152*0Sstevel@tonic-gate if ((mr->un_hsp_id != MD_HSP_NONE) && 153*0Sstevel@tonic-gate ((raidp->hspnamep = metahsphspname(&sp, mr->un_hsp_id, 154*0Sstevel@tonic-gate ep)) == NULL)) { 155*0Sstevel@tonic-gate goto out; 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate /* get columns, update unit state */ 159*0Sstevel@tonic-gate for (col = 0; (col < ncol); ++col) { 160*0Sstevel@tonic-gate mr_column_t *rcp = &mr->un_column[col]; 161*0Sstevel@tonic-gate md_raidcol_t *mdrcp = &raidp->cols.cols_val[col]; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /* get column name */ 164*0Sstevel@tonic-gate mdrcp->colnamep = metakeyname(&sp, rcp->un_orig_key, fast, ep); 165*0Sstevel@tonic-gate if (mdrcp->colnamep == NULL) 166*0Sstevel@tonic-gate goto out; 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate /* override any start_blk */ 169*0Sstevel@tonic-gate #ifdef DEBUG 170*0Sstevel@tonic-gate if (metagetstart(sp, mdrcp->colnamep, ep) != 171*0Sstevel@tonic-gate MD_DISKADDR_ERROR) { 172*0Sstevel@tonic-gate assert(mdrcp->colnamep->start_blk <= 173*0Sstevel@tonic-gate rcp->un_orig_devstart); 174*0Sstevel@tonic-gate } else { 175*0Sstevel@tonic-gate mdclrerror(ep); 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate #endif /* DEBUG */ 178*0Sstevel@tonic-gate mdrcp->colnamep->start_blk = rcp->un_orig_devstart; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* if hotspared */ 181*0Sstevel@tonic-gate if (HOTSPARED(mr, col)) { 182*0Sstevel@tonic-gate /* get hotspare name */ 183*0Sstevel@tonic-gate mdrcp->hsnamep = metakeyname(&sp, rcp->un_hs_key, 184*0Sstevel@tonic-gate fast, ep); 185*0Sstevel@tonic-gate if (mdrcp->hsnamep == NULL) 186*0Sstevel@tonic-gate goto out; 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate if (getenv("META_DEBUG_START_BLK") != NULL) { 189*0Sstevel@tonic-gate if (metagetstart(sp, mdrcp->hsnamep, ep) == 190*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 191*0Sstevel@tonic-gate mdclrerror(ep); 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate if ((mdrcp->hsnamep->start_blk == 0) && 194*0Sstevel@tonic-gate (rcp->un_hs_pwstart != 0)) 195*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 196*0Sstevel@tonic-gate "%s: suspected bad start block," 197*0Sstevel@tonic-gate " seems labelled [raid]\n"), 198*0Sstevel@tonic-gate mdrcp->hsnamep->cname); 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate if ((mdrcp->hsnamep->start_blk > 0) && 201*0Sstevel@tonic-gate (rcp->un_hs_pwstart == 0)) 202*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 203*0Sstevel@tonic-gate "%s: suspected bad start block, " 204*0Sstevel@tonic-gate " seems unlabelled [raid]\n"), 205*0Sstevel@tonic-gate mdrcp->hsnamep->cname); 206*0Sstevel@tonic-gate } 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate /* override any start_blk */ 209*0Sstevel@tonic-gate mdrcp->hsnamep->start_blk = rcp->un_hs_devstart; 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate /* get state, flags, and timestamp */ 213*0Sstevel@tonic-gate mdrcp->state = rcp->un_devstate; 214*0Sstevel@tonic-gate mdrcp->flags = rcp->un_devflags; 215*0Sstevel@tonic-gate mdrcp->timestamp = rcp->un_devtimestamp; 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate /* get resync info */ 219*0Sstevel@tonic-gate (void) memset(&ri, 0, sizeof (ri)); 220*0Sstevel@tonic-gate ri.ri_mnum = meta_getminor(raidnp->dev); 221*0Sstevel@tonic-gate MD_SETDRIVERNAME(&ri, MD_RAID, sp->setno); 222*0Sstevel@tonic-gate if (metaioctl(MD_IOCGETSYNC, &ri, &ri.mde, raidnp->cname) != 0) { 223*0Sstevel@tonic-gate (void) mdstealerror(ep, &ri.mde); 224*0Sstevel@tonic-gate goto out; 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate raidp->resync_flags = ri.ri_flags; 227*0Sstevel@tonic-gate raidp->percent_dirty = ri.ri_percent_dirty; 228*0Sstevel@tonic-gate raidp->percent_done = ri.ri_percent_done; 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate /* cleanup, return success */ 231*0Sstevel@tonic-gate Free(mr); 232*0Sstevel@tonic-gate dnp->unitp = (md_common_t *)raidp; 233*0Sstevel@tonic-gate return (raidp); 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* cleanup, return error */ 236*0Sstevel@tonic-gate out: 237*0Sstevel@tonic-gate Free(mr); 238*0Sstevel@tonic-gate meta_free_raid(raidp); 239*0Sstevel@tonic-gate return (NULL); 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* 243*0Sstevel@tonic-gate * get raid 244*0Sstevel@tonic-gate */ 245*0Sstevel@tonic-gate md_raid_t * 246*0Sstevel@tonic-gate meta_get_raid( 247*0Sstevel@tonic-gate mdsetname_t *sp, 248*0Sstevel@tonic-gate mdname_t *raidnp, 249*0Sstevel@tonic-gate md_error_t *ep 250*0Sstevel@tonic-gate ) 251*0Sstevel@tonic-gate { 252*0Sstevel@tonic-gate return (meta_get_raid_common(sp, raidnp, 0, ep)); 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate /* 256*0Sstevel@tonic-gate * check raid for dev 257*0Sstevel@tonic-gate */ 258*0Sstevel@tonic-gate static int 259*0Sstevel@tonic-gate in_raid( 260*0Sstevel@tonic-gate mdsetname_t *sp, 261*0Sstevel@tonic-gate mdname_t *raidnp, 262*0Sstevel@tonic-gate mdname_t *np, 263*0Sstevel@tonic-gate diskaddr_t slblk, 264*0Sstevel@tonic-gate diskaddr_t nblks, 265*0Sstevel@tonic-gate md_error_t *ep 266*0Sstevel@tonic-gate ) 267*0Sstevel@tonic-gate { 268*0Sstevel@tonic-gate md_raid_t *raidp; 269*0Sstevel@tonic-gate uint_t col; 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate /* should be in the same set */ 272*0Sstevel@tonic-gate assert(sp != NULL); 273*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* get unit */ 276*0Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL) 277*0Sstevel@tonic-gate return (-1); 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* look in columns */ 280*0Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) { 281*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 282*0Sstevel@tonic-gate mdname_t *colnp = cp->colnamep; 283*0Sstevel@tonic-gate diskaddr_t col_sblk; 284*0Sstevel@tonic-gate int err; 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate /* check same drive since metagetstart() can fail */ 287*0Sstevel@tonic-gate if ((err = meta_check_samedrive(np, colnp, ep)) < 0) 288*0Sstevel@tonic-gate return (-1); 289*0Sstevel@tonic-gate else if (err == 0) 290*0Sstevel@tonic-gate continue; 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate /* check overlap */ 293*0Sstevel@tonic-gate if ((col_sblk = metagetstart(sp, colnp, ep)) == 294*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 295*0Sstevel@tonic-gate return (-1); 296*0Sstevel@tonic-gate if (meta_check_overlap(raidnp->cname, np, slblk, nblks, 297*0Sstevel@tonic-gate colnp, col_sblk, -1, ep) != 0) { 298*0Sstevel@tonic-gate return (-1); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate /* return success */ 303*0Sstevel@tonic-gate return (0); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate /* 307*0Sstevel@tonic-gate * check to see if we're in a raid 308*0Sstevel@tonic-gate */ 309*0Sstevel@tonic-gate int 310*0Sstevel@tonic-gate meta_check_inraid( 311*0Sstevel@tonic-gate mdsetname_t *sp, 312*0Sstevel@tonic-gate mdname_t *np, 313*0Sstevel@tonic-gate diskaddr_t slblk, 314*0Sstevel@tonic-gate diskaddr_t nblks, 315*0Sstevel@tonic-gate md_error_t *ep 316*0Sstevel@tonic-gate ) 317*0Sstevel@tonic-gate { 318*0Sstevel@tonic-gate mdnamelist_t *raidnlp = NULL; 319*0Sstevel@tonic-gate mdnamelist_t *p; 320*0Sstevel@tonic-gate int rval = 0; 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate /* should have a set */ 323*0Sstevel@tonic-gate assert(sp != NULL); 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate /* for each raid */ 326*0Sstevel@tonic-gate if (meta_get_raid_names(sp, &raidnlp, 0, ep) < 0) 327*0Sstevel@tonic-gate return (-1); 328*0Sstevel@tonic-gate for (p = raidnlp; (p != NULL); p = p->next) { 329*0Sstevel@tonic-gate mdname_t *raidnp = p->namep; 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate /* check raid */ 332*0Sstevel@tonic-gate if (in_raid(sp, raidnp, np, slblk, nblks, ep) != 0) { 333*0Sstevel@tonic-gate rval = -1; 334*0Sstevel@tonic-gate break; 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* cleanup, return success */ 339*0Sstevel@tonic-gate metafreenamelist(raidnlp); 340*0Sstevel@tonic-gate return (rval); 341*0Sstevel@tonic-gate } 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate /* 344*0Sstevel@tonic-gate * check column 345*0Sstevel@tonic-gate */ 346*0Sstevel@tonic-gate int 347*0Sstevel@tonic-gate meta_check_column( 348*0Sstevel@tonic-gate mdsetname_t *sp, 349*0Sstevel@tonic-gate mdname_t *np, 350*0Sstevel@tonic-gate md_error_t *ep 351*0Sstevel@tonic-gate ) 352*0Sstevel@tonic-gate { 353*0Sstevel@tonic-gate mdchkopts_t options = (MDCHK_ALLOW_MDDB); 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate /* check for soft partitions */ 356*0Sstevel@tonic-gate if (meta_sp_issp(sp, np, ep) != 0) { 357*0Sstevel@tonic-gate /* make sure we have a disk */ 358*0Sstevel@tonic-gate if (metachkcomp(np, ep) != 0) 359*0Sstevel@tonic-gate return (-1); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* check to ensure that it is not already in use */ 363*0Sstevel@tonic-gate if (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0) { 364*0Sstevel@tonic-gate return (-1); 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate /* make sure it is in the set */ 368*0Sstevel@tonic-gate if (meta_check_inset(sp, np, ep) != 0) 369*0Sstevel@tonic-gate return (-1); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate /* make sure its not in a metadevice */ 372*0Sstevel@tonic-gate if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0) 373*0Sstevel@tonic-gate return (-1); 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate /* return success */ 376*0Sstevel@tonic-gate return (0); 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate /* 380*0Sstevel@tonic-gate * print raid 381*0Sstevel@tonic-gate */ 382*0Sstevel@tonic-gate static int 383*0Sstevel@tonic-gate raid_print( 384*0Sstevel@tonic-gate md_raid_t *raidp, 385*0Sstevel@tonic-gate char *fname, 386*0Sstevel@tonic-gate FILE *fp, 387*0Sstevel@tonic-gate mdprtopts_t options, 388*0Sstevel@tonic-gate md_error_t *ep 389*0Sstevel@tonic-gate ) 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate uint_t col; 392*0Sstevel@tonic-gate int rval = -1; 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate if (options & PRINT_LARGEDEVICES) { 396*0Sstevel@tonic-gate if (raidp->common.revision != MD_64BIT_META_DEV) { 397*0Sstevel@tonic-gate rval = 0; 398*0Sstevel@tonic-gate goto out; 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate } 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate /* print name and -r */ 403*0Sstevel@tonic-gate if (fprintf(fp, "%s -r", raidp->common.namep->cname) == EOF) 404*0Sstevel@tonic-gate goto out; 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate /* print columns */ 407*0Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) { 408*0Sstevel@tonic-gate md_raidcol_t *mdrcp = &raidp->cols.cols_val[col]; 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /* print column */ 411*0Sstevel@tonic-gate /* 412*0Sstevel@tonic-gate * If the path is our standard /dev/rdsk or /dev/md/rdsk 413*0Sstevel@tonic-gate * then just print out the cxtxdxsx or the dx, metainit 414*0Sstevel@tonic-gate * will assume the default, otherwise we need the full 415*0Sstevel@tonic-gate * pathname to make sure this works as we intend. 416*0Sstevel@tonic-gate */ 417*0Sstevel@tonic-gate if ((strstr(mdrcp->colnamep->rname, "/dev/rdsk") == NULL) && 418*0Sstevel@tonic-gate (strstr(mdrcp->colnamep->rname, "/dev/md/rdsk") == NULL) && 419*0Sstevel@tonic-gate (strstr(mdrcp->colnamep->rname, "/dev/td/") == NULL)) { 420*0Sstevel@tonic-gate /* not standard path, print full pathname */ 421*0Sstevel@tonic-gate if (fprintf(fp, " %s", mdrcp->colnamep->rname) == EOF) 422*0Sstevel@tonic-gate goto out; 423*0Sstevel@tonic-gate } else { 424*0Sstevel@tonic-gate /* standard path so print ctd or d number */ 425*0Sstevel@tonic-gate if (fprintf(fp, " %s", mdrcp->colnamep->cname) == EOF) 426*0Sstevel@tonic-gate goto out; 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate if (fprintf(fp, " -k") == EOF) 431*0Sstevel@tonic-gate goto out; 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate /* print options */ 434*0Sstevel@tonic-gate if (fprintf(fp, " -i %lldb", raidp->interlace) == EOF) 435*0Sstevel@tonic-gate goto out; 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate if (raidp->pw_count != PWCNT_MIN) 438*0Sstevel@tonic-gate if (fprintf(fp, " -w %d", raidp->pw_count) == EOF) 439*0Sstevel@tonic-gate goto out; 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate if (raidp->hspnamep != NULL) { 442*0Sstevel@tonic-gate if (fprintf(fp, " -h %s", raidp->hspnamep->hspname) == EOF) 443*0Sstevel@tonic-gate goto out; 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate if (raidp->orig_ncol != raidp->cols.cols_len) { 446*0Sstevel@tonic-gate assert(raidp->orig_ncol < raidp->cols.cols_len); 447*0Sstevel@tonic-gate if (fprintf(fp, " -o %u", raidp->orig_ncol) == EOF) 448*0Sstevel@tonic-gate goto out; 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate /* terminate last line */ 452*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 453*0Sstevel@tonic-gate goto out; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate /* success */ 456*0Sstevel@tonic-gate rval = 0; 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate /* cleanup, return error */ 459*0Sstevel@tonic-gate out: 460*0Sstevel@tonic-gate if (rval != 0) 461*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 462*0Sstevel@tonic-gate return (rval); 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate static int 466*0Sstevel@tonic-gate find_resyncing_column( 467*0Sstevel@tonic-gate md_raid_t *raidp 468*0Sstevel@tonic-gate ) 469*0Sstevel@tonic-gate { 470*0Sstevel@tonic-gate int col; 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) { 473*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 474*0Sstevel@tonic-gate if (cp->state & RCS_RESYNC) 475*0Sstevel@tonic-gate return (col); 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate /* No resyncing columns */ 479*0Sstevel@tonic-gate return (-1); 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate /* 483*0Sstevel@tonic-gate * convert raid state to name 484*0Sstevel@tonic-gate */ 485*0Sstevel@tonic-gate char * 486*0Sstevel@tonic-gate raid_state_to_name( 487*0Sstevel@tonic-gate md_raid_t *raidp, 488*0Sstevel@tonic-gate md_timeval32_t *tvp, 489*0Sstevel@tonic-gate uint_t tstate /* Errored tstate flags */ 490*0Sstevel@tonic-gate ) 491*0Sstevel@tonic-gate { 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate /* grab time */ 494*0Sstevel@tonic-gate if (tvp != NULL) 495*0Sstevel@tonic-gate *tvp = raidp->timestamp; 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate /* 498*0Sstevel@tonic-gate * If the device has a transient error state (due to it being DR'ed or 499*0Sstevel@tonic-gate * failed) and there has been no I/O to it (the actual device is still 500*0Sstevel@tonic-gate * marked as 'Okay') then we cannot know what the state is or what 501*0Sstevel@tonic-gate * action to take on it. Therefore report the device as 'Unavailable'. 502*0Sstevel@tonic-gate * A subsequent I/O to the device will cause the 'Okay' status to 503*0Sstevel@tonic-gate * disappear if the device is actually gone and then we will print out 504*0Sstevel@tonic-gate * the appropriate status. The MD_INACCESSIBLE state is only set 505*0Sstevel@tonic-gate * on the raid when we open it or probe it. One the raid is open 506*0Sstevel@tonic-gate * then we will just have regular error status on the device. 507*0Sstevel@tonic-gate */ 508*0Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) { 509*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unavailable")); 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate /* resyncing */ 513*0Sstevel@tonic-gate if (find_resyncing_column(raidp) >= 0) 514*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resyncing")); 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate /* everything else */ 517*0Sstevel@tonic-gate switch (raidp->state) { 518*0Sstevel@tonic-gate case RUS_INIT : 519*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Initializing")); 520*0Sstevel@tonic-gate case RUS_OKAY : 521*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Okay")); 522*0Sstevel@tonic-gate case RUS_ERRED : 523*0Sstevel@tonic-gate /*FALLTHROUGH*/ 524*0Sstevel@tonic-gate case RUS_LAST_ERRED : 525*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Needs Maintenance")); 526*0Sstevel@tonic-gate case RUS_DOI : 527*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Initialization Failed")); 528*0Sstevel@tonic-gate case RUS_REGEN : 529*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Regen")); 530*0Sstevel@tonic-gate default : 531*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "invalid")); 532*0Sstevel@tonic-gate } /* switch */ 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate static int 536*0Sstevel@tonic-gate find_erred_column(md_raid_t *raidp, rcs_state_t state) 537*0Sstevel@tonic-gate { 538*0Sstevel@tonic-gate int col; 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) { 541*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 542*0Sstevel@tonic-gate if (cp->state & state) 543*0Sstevel@tonic-gate return (col); 544*0Sstevel@tonic-gate } 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate /* No erred columns */ 547*0Sstevel@tonic-gate return (-1); 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate /* 551*0Sstevel@tonic-gate * convert raid state to repair action 552*0Sstevel@tonic-gate */ 553*0Sstevel@tonic-gate char * 554*0Sstevel@tonic-gate raid_state_to_action(md_raid_t *raidp) 555*0Sstevel@tonic-gate { 556*0Sstevel@tonic-gate static char emsg[1024]; 557*0Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep; 558*0Sstevel@tonic-gate int err_col; 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate /* first check for full init failure */ 561*0Sstevel@tonic-gate if (raidp->state & RUS_DOI) { 562*0Sstevel@tonic-gate (void) snprintf(emsg, sizeof (emsg), 563*0Sstevel@tonic-gate "metaclear -f %s", raidnp->cname); 564*0Sstevel@tonic-gate return (emsg); 565*0Sstevel@tonic-gate } 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate /* replace errored or init errored raid column */ 568*0Sstevel@tonic-gate if ((err_col = find_erred_column(raidp, 569*0Sstevel@tonic-gate (RCS_ERRED | RCS_INIT_ERRED))) >= 0) { 570*0Sstevel@tonic-gate mdname_t *colnp; 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate /* get column with error */ 573*0Sstevel@tonic-gate assert(err_col < raidp->cols.cols_len); 574*0Sstevel@tonic-gate colnp = raidp->cols.cols_val[err_col].colnamep; 575*0Sstevel@tonic-gate (void) snprintf(emsg, sizeof (emsg), 576*0Sstevel@tonic-gate "metareplace %s%s %s <%s>", 577*0Sstevel@tonic-gate ((raidp->state == RUS_LAST_ERRED) ? "-f " : ""), 578*0Sstevel@tonic-gate raidnp->cname, colnp->cname, 579*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "new device")); 580*0Sstevel@tonic-gate return (emsg); 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate /* replace last errored raid column */ 585*0Sstevel@tonic-gate if ((err_col = find_erred_column(raidp, RCS_LAST_ERRED)) >= 0) { 586*0Sstevel@tonic-gate mdname_t *colnp; 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate assert(err_col < raidp->cols.cols_len); 589*0Sstevel@tonic-gate colnp = raidp->cols.cols_val[err_col].colnamep; 590*0Sstevel@tonic-gate (void) snprintf(emsg, sizeof (emsg), 591*0Sstevel@tonic-gate "metareplace %s %s %s <%s>", 592*0Sstevel@tonic-gate ((raidp->state == RUS_LAST_ERRED) ? "-f " : ""), 593*0Sstevel@tonic-gate raidnp->cname, colnp->cname, 594*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "new device")); 595*0Sstevel@tonic-gate return (emsg); 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate /* OK */ 599*0Sstevel@tonic-gate return (NULL); 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate /* 603*0Sstevel@tonic-gate * get printable raid column state 604*0Sstevel@tonic-gate */ 605*0Sstevel@tonic-gate char * 606*0Sstevel@tonic-gate raid_col_state_to_name( 607*0Sstevel@tonic-gate md_raidcol_t *colp, 608*0Sstevel@tonic-gate md_timeval32_t *tvp, 609*0Sstevel@tonic-gate uint_t tstate 610*0Sstevel@tonic-gate ) 611*0Sstevel@tonic-gate { 612*0Sstevel@tonic-gate /* grab time */ 613*0Sstevel@tonic-gate if (tvp != NULL) 614*0Sstevel@tonic-gate *tvp = colp->timestamp; 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate if (tstate != 0) { 617*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unavailable")); 618*0Sstevel@tonic-gate } 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate /* everything else */ 621*0Sstevel@tonic-gate switch (colp->state) { 622*0Sstevel@tonic-gate case RCS_INIT: 623*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Initializing")); 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate case RCS_OKAY: 626*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Okay")); 627*0Sstevel@tonic-gate 628*0Sstevel@tonic-gate case RCS_INIT_ERRED: 629*0Sstevel@tonic-gate /*FALLTHROUGH*/ 630*0Sstevel@tonic-gate case RCS_ERRED: 631*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Maintenance")); 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate case RCS_LAST_ERRED: 634*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Last Erred")); 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate case RCS_RESYNC: 637*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Resyncing")); 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate default: 640*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unknown")); 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate } 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate /* 645*0Sstevel@tonic-gate * print raid column 646*0Sstevel@tonic-gate */ 647*0Sstevel@tonic-gate static int 648*0Sstevel@tonic-gate display_raid_device_info( 649*0Sstevel@tonic-gate mdsetname_t *sp, 650*0Sstevel@tonic-gate md_raidcol_t *colp, 651*0Sstevel@tonic-gate char *fname, 652*0Sstevel@tonic-gate FILE *fp, 653*0Sstevel@tonic-gate mdprtopts_t options, 654*0Sstevel@tonic-gate int print_len, 655*0Sstevel@tonic-gate uint_t top_tstate, /* Errored tstate flags */ 656*0Sstevel@tonic-gate md_error_t *ep 657*0Sstevel@tonic-gate ) 658*0Sstevel@tonic-gate { 659*0Sstevel@tonic-gate mdname_t *namep = ((colp->hsnamep != NULL) ? 660*0Sstevel@tonic-gate colp->hsnamep : colp->colnamep); 661*0Sstevel@tonic-gate char *devid = ""; 662*0Sstevel@tonic-gate char *cname = colp->colnamep->cname; 663*0Sstevel@tonic-gate diskaddr_t start_blk; 664*0Sstevel@tonic-gate int has_mddb; 665*0Sstevel@tonic-gate char *has_mddb_str; 666*0Sstevel@tonic-gate char *col_state; 667*0Sstevel@tonic-gate md_timeval32_t tv; 668*0Sstevel@tonic-gate char *hsname = ((colp->hsnamep != NULL) ? 669*0Sstevel@tonic-gate colp->hsnamep->cname : ""); 670*0Sstevel@tonic-gate int rval = -1; 671*0Sstevel@tonic-gate mdname_t *didnp = NULL; 672*0Sstevel@tonic-gate ddi_devid_t dtp; 673*0Sstevel@tonic-gate uint_t tstate = 0; 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* get info */ 676*0Sstevel@tonic-gate if ((start_blk = metagetstart(sp, namep, ep)) == MD_DISKADDR_ERROR) 677*0Sstevel@tonic-gate return (-1); 678*0Sstevel@tonic-gate if ((has_mddb = metahasmddb(sp, namep, ep)) < 0) 679*0Sstevel@tonic-gate return (-1); 680*0Sstevel@tonic-gate if (has_mddb) 681*0Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "Yes"); 682*0Sstevel@tonic-gate else 683*0Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "No"); 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate if (metaismeta(namep)) { 686*0Sstevel@tonic-gate if (meta_get_tstate(namep->dev, &tstate, ep) != 0) 687*0Sstevel@tonic-gate return (-1); 688*0Sstevel@tonic-gate col_state = raid_col_state_to_name(colp, &tv, 689*0Sstevel@tonic-gate tstate & MD_DEV_ERRORED); 690*0Sstevel@tonic-gate } else { 691*0Sstevel@tonic-gate /* 692*0Sstevel@tonic-gate * if top_tstate is set, that implies that you have 693*0Sstevel@tonic-gate * a ctd type device with an unavailable metadevice 694*0Sstevel@tonic-gate * on top of it. If so, print a - for it's state 695*0Sstevel@tonic-gate */ 696*0Sstevel@tonic-gate if (top_tstate != 0) 697*0Sstevel@tonic-gate col_state = "-"; 698*0Sstevel@tonic-gate else 699*0Sstevel@tonic-gate col_state = raid_col_state_to_name(colp, &tv, tstate); 700*0Sstevel@tonic-gate } 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate /* populate the key in the name_p structure */ 703*0Sstevel@tonic-gate if ((didnp = metadevname(&sp, namep->dev, ep)) == NULL) 704*0Sstevel@tonic-gate return (-1); 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate /* determine if devid does NOT exist */ 707*0Sstevel@tonic-gate if (options & PRINT_DEVID) { 708*0Sstevel@tonic-gate if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep), 709*0Sstevel@tonic-gate didnp->key, ep)) == NULL) 710*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "No "); 711*0Sstevel@tonic-gate else { 712*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "Yes"); 713*0Sstevel@tonic-gate free(dtp); 714*0Sstevel@tonic-gate } 715*0Sstevel@tonic-gate } 716*0Sstevel@tonic-gate /* print column */ 717*0Sstevel@tonic-gate /* 718*0Sstevel@tonic-gate * Building a format string on the fly that will 719*0Sstevel@tonic-gate * be used in (f)printf. This allows the length 720*0Sstevel@tonic-gate * of the ctd to vary from small to large without 721*0Sstevel@tonic-gate * looking horrible. 722*0Sstevel@tonic-gate */ 723*0Sstevel@tonic-gate if (! (options & PRINT_TIMES)) { 724*0Sstevel@tonic-gate if (fprintf(fp, 725*0Sstevel@tonic-gate "\t%-*.*s %8lld %5.5s %12.12s %5.5s %s\n", 726*0Sstevel@tonic-gate print_len, print_len, cname, start_blk, has_mddb_str, 727*0Sstevel@tonic-gate col_state, devid, hsname) == EOF) { 728*0Sstevel@tonic-gate goto out; 729*0Sstevel@tonic-gate } 730*0Sstevel@tonic-gate } else { 731*0Sstevel@tonic-gate char *timep = meta_print_time(&tv); 732*0Sstevel@tonic-gate 733*0Sstevel@tonic-gate if (fprintf(fp, 734*0Sstevel@tonic-gate "\t%-*s %5lld %-5s %-11s %-5s %-9s %s\n", 735*0Sstevel@tonic-gate print_len, cname, start_blk, has_mddb_str, 736*0Sstevel@tonic-gate col_state, devid, hsname, timep) == EOF) { 737*0Sstevel@tonic-gate goto out; 738*0Sstevel@tonic-gate } 739*0Sstevel@tonic-gate } 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate /* success */ 742*0Sstevel@tonic-gate rval = 0; 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate /* cleanup, return error */ 745*0Sstevel@tonic-gate out: 746*0Sstevel@tonic-gate if (rval != 0) 747*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate return (rval); 750*0Sstevel@tonic-gate } 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate /* 753*0Sstevel@tonic-gate * print raid options 754*0Sstevel@tonic-gate */ 755*0Sstevel@tonic-gate int 756*0Sstevel@tonic-gate meta_print_raid_options( 757*0Sstevel@tonic-gate mdhspname_t *hspnamep, 758*0Sstevel@tonic-gate char *fname, 759*0Sstevel@tonic-gate FILE *fp, 760*0Sstevel@tonic-gate md_error_t *ep 761*0Sstevel@tonic-gate ) 762*0Sstevel@tonic-gate { 763*0Sstevel@tonic-gate char *hspname = ((hspnamep != NULL) ? hspnamep->hspname : 764*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "none")); 765*0Sstevel@tonic-gate int rval = -1; 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate /* print options */ 768*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 769*0Sstevel@tonic-gate " Hot spare pool: %s\n"), hspname) == EOF) { 770*0Sstevel@tonic-gate goto out; 771*0Sstevel@tonic-gate } 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate /* success */ 774*0Sstevel@tonic-gate rval = 0; 775*0Sstevel@tonic-gate 776*0Sstevel@tonic-gate /* cleanup, return error */ 777*0Sstevel@tonic-gate out: 778*0Sstevel@tonic-gate if (rval != 0) 779*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 780*0Sstevel@tonic-gate return (rval); 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate /* 784*0Sstevel@tonic-gate * report raid 785*0Sstevel@tonic-gate */ 786*0Sstevel@tonic-gate static int 787*0Sstevel@tonic-gate raid_report( 788*0Sstevel@tonic-gate mdsetname_t *sp, 789*0Sstevel@tonic-gate md_raid_t *raidp, 790*0Sstevel@tonic-gate char *fname, 791*0Sstevel@tonic-gate FILE *fp, 792*0Sstevel@tonic-gate mdprtopts_t options, 793*0Sstevel@tonic-gate md_error_t *ep 794*0Sstevel@tonic-gate ) 795*0Sstevel@tonic-gate { 796*0Sstevel@tonic-gate char *p; 797*0Sstevel@tonic-gate uint_t ncol = raidp->cols.cols_len; 798*0Sstevel@tonic-gate uint_t orig_ncol = raidp->orig_ncol; 799*0Sstevel@tonic-gate diskaddr_t column_size = raidp->column_size; 800*0Sstevel@tonic-gate char *raid_state; 801*0Sstevel@tonic-gate md_timeval32_t tv; 802*0Sstevel@tonic-gate char *timep; 803*0Sstevel@tonic-gate uint_t col; 804*0Sstevel@tonic-gate int rval = -1; 805*0Sstevel@tonic-gate int len = 0; 806*0Sstevel@tonic-gate uint_t tstate = 0; 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate if (options & PRINT_LARGEDEVICES) { 809*0Sstevel@tonic-gate if (raidp->common.revision != MD_64BIT_META_DEV) { 810*0Sstevel@tonic-gate rval = 0; 811*0Sstevel@tonic-gate goto out; 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate } 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate /* print header */ 816*0Sstevel@tonic-gate if (options & PRINT_HEADER) { 817*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: RAID\n"), 818*0Sstevel@tonic-gate raidp->common.namep->cname) == EOF) { 819*0Sstevel@tonic-gate goto out; 820*0Sstevel@tonic-gate } 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate /* print state */ 825*0Sstevel@tonic-gate if (metaismeta(raidp->common.namep)) { 826*0Sstevel@tonic-gate if (meta_get_tstate(raidp->common.namep->dev, &tstate, ep) != 0) 827*0Sstevel@tonic-gate return (-1); 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate tstate &= MD_DEV_ERRORED; /* extract the errored tstate bits */ 830*0Sstevel@tonic-gate raid_state = raid_state_to_name(raidp, &tv, tstate); 831*0Sstevel@tonic-gate if (options & PRINT_TIMES) { 832*0Sstevel@tonic-gate timep = meta_print_time(&tv); 833*0Sstevel@tonic-gate } else { 834*0Sstevel@tonic-gate timep = ""; 835*0Sstevel@tonic-gate } 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " State: %-12s %s\n"), 838*0Sstevel@tonic-gate raid_state, timep) == EOF) { 839*0Sstevel@tonic-gate goto out; 840*0Sstevel@tonic-gate } 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate /* 843*0Sstevel@tonic-gate * Display recovery action if we're marked in the Unavailable state. 844*0Sstevel@tonic-gate */ 845*0Sstevel@tonic-gate if ((tstate == 0) || (tstate & MD_INACCESSIBLE)) { 846*0Sstevel@tonic-gate /* print what to do */ 847*0Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) { 848*0Sstevel@tonic-gate char sname[MD_MAX_SETNAME + 3]; /* 3 = sizeof("-s ") */ 849*0Sstevel@tonic-gate 850*0Sstevel@tonic-gate if (metaislocalset(sp)) { 851*0Sstevel@tonic-gate sname[0] = '\0'; 852*0Sstevel@tonic-gate } else { 853*0Sstevel@tonic-gate (void) snprintf(sname, MD_MAX_SETNAME + 3, 854*0Sstevel@tonic-gate "-s %s", sp->setname); 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 857*0Sstevel@tonic-gate " Invoke: metastat -i %s\n"), sname) == EOF) { 858*0Sstevel@tonic-gate goto out; 859*0Sstevel@tonic-gate } 860*0Sstevel@tonic-gate } else if ((p = raid_state_to_action(raidp)) != NULL) { 861*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 862*0Sstevel@tonic-gate " Invoke: %s\n"), p) == EOF) { 863*0Sstevel@tonic-gate goto out; 864*0Sstevel@tonic-gate } 865*0Sstevel@tonic-gate } 866*0Sstevel@tonic-gate 867*0Sstevel@tonic-gate /* resync status */ 868*0Sstevel@tonic-gate if (raidp->resync_flags & MD_RI_INPROGRESS) { 869*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 870*0Sstevel@tonic-gate " Resync in progress: %2d.%1d%% done\n"), 871*0Sstevel@tonic-gate raidp->percent_done/10, 872*0Sstevel@tonic-gate raidp->percent_done % 10) == EOF) { 873*0Sstevel@tonic-gate goto out; 874*0Sstevel@tonic-gate } 875*0Sstevel@tonic-gate } else if (raidp->resync_flags & MD_GROW_INPROGRESS) { 876*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 877*0Sstevel@tonic-gate " Initialization in progress: %2d.%1d%% " 878*0Sstevel@tonic-gate "done\n"), 879*0Sstevel@tonic-gate raidp->percent_done/10, 880*0Sstevel@tonic-gate raidp->percent_done % 10) == EOF) { 881*0Sstevel@tonic-gate goto out; 882*0Sstevel@tonic-gate } 883*0Sstevel@tonic-gate } else if (raidp->state & RUS_REGEN) { 884*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 885*0Sstevel@tonic-gate " Parity regeneration in progress: %2d.%1d%% " 886*0Sstevel@tonic-gate "done\n"), 887*0Sstevel@tonic-gate raidp->percent_done/10, 888*0Sstevel@tonic-gate raidp->percent_done % 10) == EOF) { 889*0Sstevel@tonic-gate goto out; 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate } 892*0Sstevel@tonic-gate } 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate /* print hotspare pool */ 895*0Sstevel@tonic-gate if (raidp->hspnamep != NULL) { 896*0Sstevel@tonic-gate if (meta_print_raid_options(raidp->hspnamep, 897*0Sstevel@tonic-gate fname, fp, ep) != 0) { 898*0Sstevel@tonic-gate return (-1); 899*0Sstevel@tonic-gate } 900*0Sstevel@tonic-gate } 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate /* print interlace */ 903*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Interlace: %lld blocks\n"), 904*0Sstevel@tonic-gate raidp->interlace) == EOF) { 905*0Sstevel@tonic-gate goto out; 906*0Sstevel@tonic-gate } 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate /* print size */ 909*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"), 910*0Sstevel@tonic-gate raidp->common.size, 911*0Sstevel@tonic-gate meta_number_to_string(raidp->common.size, DEV_BSIZE)) == EOF) { 912*0Sstevel@tonic-gate goto out; 913*0Sstevel@tonic-gate } 914*0Sstevel@tonic-gate 915*0Sstevel@tonic-gate /* MD_DEBUG stuff */ 916*0Sstevel@tonic-gate if (options & PRINT_DEBUG) { 917*0Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep; 918*0Sstevel@tonic-gate mr_unit_t *mr; 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate /* get additional info */ 921*0Sstevel@tonic-gate if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL) 922*0Sstevel@tonic-gate return (-1); 923*0Sstevel@tonic-gate assert(mr->c.un_type == MD_METARAID); 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate /* print prewrite count and size */ 926*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 927*0Sstevel@tonic-gate " Prewrite Count: %u slots\n"), 928*0Sstevel@tonic-gate mr->un_pwcnt) == EOF) { 929*0Sstevel@tonic-gate Free(mr); 930*0Sstevel@tonic-gate goto out; 931*0Sstevel@tonic-gate } 932*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 933*0Sstevel@tonic-gate " Prewrite Slot Size: %u blocks\n"), 934*0Sstevel@tonic-gate (mr->un_pwsize / mr->un_pwcnt)) == EOF) { 935*0Sstevel@tonic-gate Free(mr); 936*0Sstevel@tonic-gate goto out; 937*0Sstevel@tonic-gate } 938*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 939*0Sstevel@tonic-gate " Prewrite Total Size: %u blocks\n"), 940*0Sstevel@tonic-gate mr->un_pwsize) == EOF) { 941*0Sstevel@tonic-gate Free(mr); 942*0Sstevel@tonic-gate goto out; 943*0Sstevel@tonic-gate } 944*0Sstevel@tonic-gate Free(mr); 945*0Sstevel@tonic-gate } 946*0Sstevel@tonic-gate 947*0Sstevel@tonic-gate /* print original devices */ 948*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, "Original device:\n")) == EOF) 949*0Sstevel@tonic-gate goto out; 950*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"), 951*0Sstevel@tonic-gate column_size * (orig_ncol - 1), 952*0Sstevel@tonic-gate meta_number_to_string(column_size * (orig_ncol - 1), DEV_BSIZE)) 953*0Sstevel@tonic-gate == EOF) { 954*0Sstevel@tonic-gate goto out; 955*0Sstevel@tonic-gate } 956*0Sstevel@tonic-gate /* 957*0Sstevel@tonic-gate * Building a format string on the fly that will 958*0Sstevel@tonic-gate * be used in (f)printf. This allows the length 959*0Sstevel@tonic-gate * of the ctd to vary from small to large without 960*0Sstevel@tonic-gate * looking horrible. 961*0Sstevel@tonic-gate */ 962*0Sstevel@tonic-gate for (col = 0; (col < orig_ncol); ++col) { 963*0Sstevel@tonic-gate len = max(len, 964*0Sstevel@tonic-gate strlen(raidp->cols.cols_val[col].colnamep->cname)); 965*0Sstevel@tonic-gate } 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device"))); 968*0Sstevel@tonic-gate len += 2; 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate if (! (options & PRINT_TIMES)) { 971*0Sstevel@tonic-gate if (fprintf(fp, 972*0Sstevel@tonic-gate "\t%-*.*s %-12.12s %-5.5s %12.12s %-5.5s %s\n", 973*0Sstevel@tonic-gate len, len, 974*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"), 975*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"), 976*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 977*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"), 978*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"), 979*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) { 980*0Sstevel@tonic-gate goto out; 981*0Sstevel@tonic-gate } 982*0Sstevel@tonic-gate } else { 983*0Sstevel@tonic-gate if (fprintf(fp, 984*0Sstevel@tonic-gate "\t%-*s %5s %-5s %-11s %-5s %-9s %s\n", 985*0Sstevel@tonic-gate len, 986*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"), 987*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start"), 988*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 989*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"), 990*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"), 991*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare"), 992*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Time")) == EOF) { 993*0Sstevel@tonic-gate goto out; 994*0Sstevel@tonic-gate } 995*0Sstevel@tonic-gate } 996*0Sstevel@tonic-gate for (col = 0; (col < orig_ncol); ++col) { 997*0Sstevel@tonic-gate md_raidcol_t *mdrcp = &raidp->cols.cols_val[col]; 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate if (display_raid_device_info(sp, mdrcp, fname, fp, options, 1000*0Sstevel@tonic-gate len, tstate, ep) != 0) { 1001*0Sstevel@tonic-gate return (-1); 1002*0Sstevel@tonic-gate } 1003*0Sstevel@tonic-gate } 1004*0Sstevel@tonic-gate 1005*0Sstevel@tonic-gate /* print concatenated devices */ 1006*0Sstevel@tonic-gate if (col < ncol) { 1007*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1008*0Sstevel@tonic-gate "Concatenated Devices:\n")) == EOF) { 1009*0Sstevel@tonic-gate goto out; 1010*0Sstevel@tonic-gate } 1011*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1012*0Sstevel@tonic-gate " Size: %lld blocks (%s)\n"), 1013*0Sstevel@tonic-gate column_size * (ncol - orig_ncol), 1014*0Sstevel@tonic-gate meta_number_to_string(column_size * (ncol - orig_ncol), 1015*0Sstevel@tonic-gate DEV_BSIZE)) 1016*0Sstevel@tonic-gate == EOF) { 1017*0Sstevel@tonic-gate goto out; 1018*0Sstevel@tonic-gate } 1019*0Sstevel@tonic-gate /* 1020*0Sstevel@tonic-gate * This allows the length 1021*0Sstevel@tonic-gate * of the ctd to vary from small to large without 1022*0Sstevel@tonic-gate * looking horrible. 1023*0Sstevel@tonic-gate */ 1024*0Sstevel@tonic-gate if (! (options & PRINT_TIMES)) { 1025*0Sstevel@tonic-gate if (fprintf(fp, 1026*0Sstevel@tonic-gate "\t%-*.*s %-12.12s %-5.5s %-12.12s %5.5s %s\n", 1027*0Sstevel@tonic-gate len, len, 1028*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"), 1029*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"), 1030*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 1031*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"), 1032*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"), 1033*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare")) == EOF) { 1034*0Sstevel@tonic-gate goto out; 1035*0Sstevel@tonic-gate } 1036*0Sstevel@tonic-gate } else { 1037*0Sstevel@tonic-gate if (fprintf(fp, 1038*0Sstevel@tonic-gate "\t%-*s %5s %-5s %-11s %-9s %s\t%s\n", 1039*0Sstevel@tonic-gate len, 1040*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"), 1041*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start"), 1042*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 1043*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "State"), 1044*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc"), 1045*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Hot Spare"), 1046*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Time")) == EOF) { 1047*0Sstevel@tonic-gate goto out; 1048*0Sstevel@tonic-gate } 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate assert(col == orig_ncol); 1051*0Sstevel@tonic-gate for (/* void */; (col < ncol); col++) { 1052*0Sstevel@tonic-gate md_raidcol_t *mdrcp = &raidp->cols.cols_val[col]; 1053*0Sstevel@tonic-gate 1054*0Sstevel@tonic-gate if (display_raid_device_info(sp, mdrcp, fname, fp, 1055*0Sstevel@tonic-gate options, len, tstate, ep) != 0) { 1056*0Sstevel@tonic-gate return (-1); 1057*0Sstevel@tonic-gate } 1058*0Sstevel@tonic-gate } 1059*0Sstevel@tonic-gate } 1060*0Sstevel@tonic-gate 1061*0Sstevel@tonic-gate /* add extra line */ 1062*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 1063*0Sstevel@tonic-gate goto out; 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate /* success */ 1066*0Sstevel@tonic-gate rval = 0; 1067*0Sstevel@tonic-gate 1068*0Sstevel@tonic-gate /* cleanup, return error */ 1069*0Sstevel@tonic-gate out: 1070*0Sstevel@tonic-gate if (rval != 0) 1071*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 1072*0Sstevel@tonic-gate return (rval); 1073*0Sstevel@tonic-gate } 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate /* 1076*0Sstevel@tonic-gate * print/report raid 1077*0Sstevel@tonic-gate */ 1078*0Sstevel@tonic-gate int 1079*0Sstevel@tonic-gate meta_raid_print( 1080*0Sstevel@tonic-gate mdsetname_t *sp, 1081*0Sstevel@tonic-gate mdname_t *raidnp, 1082*0Sstevel@tonic-gate mdnamelist_t **nlpp, 1083*0Sstevel@tonic-gate char *fname, 1084*0Sstevel@tonic-gate FILE *fp, 1085*0Sstevel@tonic-gate mdprtopts_t options, 1086*0Sstevel@tonic-gate md_error_t *ep 1087*0Sstevel@tonic-gate ) 1088*0Sstevel@tonic-gate { 1089*0Sstevel@tonic-gate md_raid_t *raidp; 1090*0Sstevel@tonic-gate int col; 1091*0Sstevel@tonic-gate 1092*0Sstevel@tonic-gate /* should have same set */ 1093*0Sstevel@tonic-gate assert(sp != NULL); 1094*0Sstevel@tonic-gate assert((raidnp == NULL) || 1095*0Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)))); 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate /* print all raids */ 1098*0Sstevel@tonic-gate if (raidnp == NULL) { 1099*0Sstevel@tonic-gate mdnamelist_t *nlp = NULL; 1100*0Sstevel@tonic-gate mdnamelist_t *p; 1101*0Sstevel@tonic-gate int cnt; 1102*0Sstevel@tonic-gate int rval = 0; 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate /* get list */ 1105*0Sstevel@tonic-gate if ((cnt = meta_get_raid_names(sp, &nlp, options, ep)) < 0) 1106*0Sstevel@tonic-gate return (-1); 1107*0Sstevel@tonic-gate else if (cnt == 0) 1108*0Sstevel@tonic-gate return (0); 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate /* recurse */ 1111*0Sstevel@tonic-gate for (p = nlp; (p != NULL); p = p->next) { 1112*0Sstevel@tonic-gate mdname_t *np = p->namep; 1113*0Sstevel@tonic-gate 1114*0Sstevel@tonic-gate if (meta_raid_print(sp, np, nlpp, fname, fp, 1115*0Sstevel@tonic-gate options, ep) != 0) 1116*0Sstevel@tonic-gate rval = -1; 1117*0Sstevel@tonic-gate } 1118*0Sstevel@tonic-gate 1119*0Sstevel@tonic-gate /* cleanup, return success */ 1120*0Sstevel@tonic-gate metafreenamelist(nlp); 1121*0Sstevel@tonic-gate return (rval); 1122*0Sstevel@tonic-gate } 1123*0Sstevel@tonic-gate 1124*0Sstevel@tonic-gate /* get unit structure */ 1125*0Sstevel@tonic-gate if ((raidp = meta_get_raid_common(sp, raidnp, 1126*0Sstevel@tonic-gate ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL) 1127*0Sstevel@tonic-gate return (-1); 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate /* check for parented */ 1130*0Sstevel@tonic-gate if ((! (options & PRINT_SUBDEVS)) && 1131*0Sstevel@tonic-gate (MD_HAS_PARENT(raidp->common.parent))) { 1132*0Sstevel@tonic-gate return (0); 1133*0Sstevel@tonic-gate } 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate /* print appropriate detail */ 1136*0Sstevel@tonic-gate if (options & PRINT_SHORT) { 1137*0Sstevel@tonic-gate if (raid_print(raidp, fname, fp, options, ep) != 0) 1138*0Sstevel@tonic-gate return (-1); 1139*0Sstevel@tonic-gate } else { 1140*0Sstevel@tonic-gate if (raid_report(sp, raidp, fname, fp, options, ep) != 0) 1141*0Sstevel@tonic-gate return (-1); 1142*0Sstevel@tonic-gate } 1143*0Sstevel@tonic-gate 1144*0Sstevel@tonic-gate /* Recurse on components that are metadevices */ 1145*0Sstevel@tonic-gate for (col = 0; col < raidp->cols.cols_len; ++col) { 1146*0Sstevel@tonic-gate md_raidcol_t *colp = &raidp->cols.cols_val[col]; 1147*0Sstevel@tonic-gate mdname_t *namep = colp->colnamep; 1148*0Sstevel@tonic-gate 1149*0Sstevel@tonic-gate if ((metaismeta(namep)) && 1150*0Sstevel@tonic-gate (meta_print_name(sp, namep, nlpp, fname, fp, 1151*0Sstevel@tonic-gate (options | PRINT_HEADER | PRINT_SUBDEVS), 1152*0Sstevel@tonic-gate NULL, ep) != 0)) { 1153*0Sstevel@tonic-gate return (-1); 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate } 1156*0Sstevel@tonic-gate 1157*0Sstevel@tonic-gate return (0); 1158*0Sstevel@tonic-gate } 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate /* 1161*0Sstevel@tonic-gate * adjust raid geometry 1162*0Sstevel@tonic-gate */ 1163*0Sstevel@tonic-gate static int 1164*0Sstevel@tonic-gate adjust_geom( 1165*0Sstevel@tonic-gate mdname_t *raidnp, 1166*0Sstevel@tonic-gate mdname_t *colnp, 1167*0Sstevel@tonic-gate mr_unit_t *mr, 1168*0Sstevel@tonic-gate md_error_t *ep 1169*0Sstevel@tonic-gate ) 1170*0Sstevel@tonic-gate { 1171*0Sstevel@tonic-gate uint_t round_cyl = 1; 1172*0Sstevel@tonic-gate mdgeom_t *geomp; 1173*0Sstevel@tonic-gate 1174*0Sstevel@tonic-gate /* get reinstructs */ 1175*0Sstevel@tonic-gate if ((geomp = metagetgeom(colnp, ep)) == NULL) 1176*0Sstevel@tonic-gate return (-1); 1177*0Sstevel@tonic-gate 1178*0Sstevel@tonic-gate /* adjust geometry */ 1179*0Sstevel@tonic-gate if (meta_adjust_geom((md_unit_t *)mr, raidnp, geomp->write_reinstruct, 1180*0Sstevel@tonic-gate geomp->read_reinstruct, round_cyl, ep) != 0) 1181*0Sstevel@tonic-gate return (-1); 1182*0Sstevel@tonic-gate 1183*0Sstevel@tonic-gate /* return success */ 1184*0Sstevel@tonic-gate return (0); 1185*0Sstevel@tonic-gate } 1186*0Sstevel@tonic-gate 1187*0Sstevel@tonic-gate /* 1188*0Sstevel@tonic-gate * add another column to the raid unit structure 1189*0Sstevel@tonic-gate */ 1190*0Sstevel@tonic-gate static int 1191*0Sstevel@tonic-gate attach_raid_col( 1192*0Sstevel@tonic-gate mdsetname_t *sp, 1193*0Sstevel@tonic-gate mdname_t *raidnp, 1194*0Sstevel@tonic-gate mr_unit_t *mr, 1195*0Sstevel@tonic-gate mr_column_t *mdc, 1196*0Sstevel@tonic-gate mdname_t *colnp, 1197*0Sstevel@tonic-gate rcs_state_t state, 1198*0Sstevel@tonic-gate mdnamelist_t **keynlpp, 1199*0Sstevel@tonic-gate mdcmdopts_t options, 1200*0Sstevel@tonic-gate md_error_t *ep 1201*0Sstevel@tonic-gate ) 1202*0Sstevel@tonic-gate { 1203*0Sstevel@tonic-gate diskaddr_t column_size = mr->un_segsize * mr->un_segsincolumn; 1204*0Sstevel@tonic-gate diskaddr_t size; 1205*0Sstevel@tonic-gate uint_t maxio; 1206*0Sstevel@tonic-gate mdcinfo_t *cinfop; 1207*0Sstevel@tonic-gate md_timeval32_t tmp_time; 1208*0Sstevel@tonic-gate 1209*0Sstevel@tonic-gate /* setup state and timestamp */ 1210*0Sstevel@tonic-gate mdc->un_devstate = state; 1211*0Sstevel@tonic-gate if (meta_gettimeofday(&tmp_time) == -1) 1212*0Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL)); 1213*0Sstevel@tonic-gate 1214*0Sstevel@tonic-gate mdc->un_devtimestamp = tmp_time; 1215*0Sstevel@tonic-gate /* get start, size, and maxio */ 1216*0Sstevel@tonic-gate if ((mdc->un_orig_devstart = metagetstart(sp, colnp, ep)) == 1217*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 1218*0Sstevel@tonic-gate return (-1); 1219*0Sstevel@tonic-gate if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR) 1220*0Sstevel@tonic-gate return (-1); 1221*0Sstevel@tonic-gate if ((cinfop = metagetcinfo(colnp, ep)) == NULL) 1222*0Sstevel@tonic-gate return (-1); 1223*0Sstevel@tonic-gate maxio = cinfop->maxtransfer; 1224*0Sstevel@tonic-gate 1225*0Sstevel@tonic-gate /* adjust start and size by prewrite */ 1226*0Sstevel@tonic-gate mdc->un_orig_pwstart = mdc->un_orig_devstart; 1227*0Sstevel@tonic-gate mdc->un_orig_devstart += mr->un_pwsize; 1228*0Sstevel@tonic-gate 1229*0Sstevel@tonic-gate /* make sure we still have something left */ 1230*0Sstevel@tonic-gate if ((mdc->un_orig_devstart >= size) || 1231*0Sstevel@tonic-gate ((size - mdc->un_orig_devstart) < column_size)) { 1232*0Sstevel@tonic-gate return (mdsyserror(ep, ENOSPC, colnp->cname)); 1233*0Sstevel@tonic-gate } 1234*0Sstevel@tonic-gate size -= mdc->un_orig_devstart; 1235*0Sstevel@tonic-gate if (maxio < mr->un_maxio) { 1236*0Sstevel@tonic-gate return (mdcomperror(ep, MDE_MAXIO, 1237*0Sstevel@tonic-gate meta_getminor(raidnp->dev), colnp->dev, colnp->cname)); 1238*0Sstevel@tonic-gate } 1239*0Sstevel@tonic-gate 1240*0Sstevel@tonic-gate if (options & MDCMD_DOIT) { 1241*0Sstevel@tonic-gate /* store name in namespace */ 1242*0Sstevel@tonic-gate if (add_key_name(sp, colnp, keynlpp, ep) != 0) 1243*0Sstevel@tonic-gate return (-1); 1244*0Sstevel@tonic-gate } 1245*0Sstevel@tonic-gate 1246*0Sstevel@tonic-gate /* setup column */ 1247*0Sstevel@tonic-gate mdc->un_orig_dev = colnp->dev; 1248*0Sstevel@tonic-gate mdc->un_orig_key = colnp->key; 1249*0Sstevel@tonic-gate mdc->un_dev = colnp->dev; 1250*0Sstevel@tonic-gate mdc->un_pwstart = mdc->un_orig_pwstart; 1251*0Sstevel@tonic-gate mdc->un_devstart = mdc->un_orig_devstart; 1252*0Sstevel@tonic-gate mdc->un_alt_dev = NODEV64; 1253*0Sstevel@tonic-gate mdc->un_alt_pwstart = 0; 1254*0Sstevel@tonic-gate mdc->un_alt_devstart = 0; 1255*0Sstevel@tonic-gate mdc->un_hs_id = 0; 1256*0Sstevel@tonic-gate 1257*0Sstevel@tonic-gate /* add the size (we use) of the device to the total */ 1258*0Sstevel@tonic-gate mr->c.un_actual_tb += column_size; 1259*0Sstevel@tonic-gate 1260*0Sstevel@tonic-gate /* adjust geometry */ 1261*0Sstevel@tonic-gate if (adjust_geom(raidnp, colnp, mr, ep) != 0) 1262*0Sstevel@tonic-gate return (-1); 1263*0Sstevel@tonic-gate 1264*0Sstevel@tonic-gate /* count column */ 1265*0Sstevel@tonic-gate mr->un_totalcolumncnt++; 1266*0Sstevel@tonic-gate 1267*0Sstevel@tonic-gate /* return success */ 1268*0Sstevel@tonic-gate return (0); 1269*0Sstevel@tonic-gate } 1270*0Sstevel@tonic-gate 1271*0Sstevel@tonic-gate /* 1272*0Sstevel@tonic-gate * invalidate column names 1273*0Sstevel@tonic-gate */ 1274*0Sstevel@tonic-gate static int 1275*0Sstevel@tonic-gate invalidate_columns( 1276*0Sstevel@tonic-gate mdsetname_t *sp, 1277*0Sstevel@tonic-gate mdname_t *raidnp, 1278*0Sstevel@tonic-gate md_error_t *ep 1279*0Sstevel@tonic-gate ) 1280*0Sstevel@tonic-gate { 1281*0Sstevel@tonic-gate md_raid_t *raidp; 1282*0Sstevel@tonic-gate uint_t col; 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL) 1285*0Sstevel@tonic-gate return (-1); 1286*0Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) { 1287*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 1288*0Sstevel@tonic-gate mdname_t *colnp = cp->colnamep; 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate meta_invalidate_name(colnp); 1291*0Sstevel@tonic-gate } 1292*0Sstevel@tonic-gate return (0); 1293*0Sstevel@tonic-gate } 1294*0Sstevel@tonic-gate 1295*0Sstevel@tonic-gate /* 1296*0Sstevel@tonic-gate * attach columns to raid 1297*0Sstevel@tonic-gate */ 1298*0Sstevel@tonic-gate int 1299*0Sstevel@tonic-gate meta_raid_attach( 1300*0Sstevel@tonic-gate mdsetname_t *sp, 1301*0Sstevel@tonic-gate mdname_t *raidnp, 1302*0Sstevel@tonic-gate mdnamelist_t *colnlp, 1303*0Sstevel@tonic-gate mdcmdopts_t options, 1304*0Sstevel@tonic-gate md_error_t *ep 1305*0Sstevel@tonic-gate ) 1306*0Sstevel@tonic-gate { 1307*0Sstevel@tonic-gate uint_t concat_cnt = 0; 1308*0Sstevel@tonic-gate mdnamelist_t *p; 1309*0Sstevel@tonic-gate mr_unit_t *old_mr; 1310*0Sstevel@tonic-gate mr_unit_t *new_mr; 1311*0Sstevel@tonic-gate size_t old_rusize; 1312*0Sstevel@tonic-gate size_t new_rusize; 1313*0Sstevel@tonic-gate mdnamelist_t *keynlp = NULL; 1314*0Sstevel@tonic-gate md_grow_params_t mgp; 1315*0Sstevel@tonic-gate int rval = -1; 1316*0Sstevel@tonic-gate int create_flag = MD_CRO_32BIT; 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gate /* should have a set */ 1319*0Sstevel@tonic-gate assert(sp != NULL); 1320*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 1321*0Sstevel@tonic-gate 1322*0Sstevel@tonic-gate /* check type */ 1323*0Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0) 1324*0Sstevel@tonic-gate return (-1); 1325*0Sstevel@tonic-gate 1326*0Sstevel@tonic-gate /* check and count new columns */ 1327*0Sstevel@tonic-gate for (p = colnlp; (p != NULL); p = p->next) { 1328*0Sstevel@tonic-gate mdname_t *np = p->namep; 1329*0Sstevel@tonic-gate mdnamelist_t *p2; 1330*0Sstevel@tonic-gate 1331*0Sstevel@tonic-gate /* check against existing devices */ 1332*0Sstevel@tonic-gate if (meta_check_column(sp, np, ep) != 0) 1333*0Sstevel@tonic-gate return (-1); 1334*0Sstevel@tonic-gate 1335*0Sstevel@tonic-gate /* check against ourselves */ 1336*0Sstevel@tonic-gate for (p2 = p->next; (p2 != NULL); p2 = p2->next) { 1337*0Sstevel@tonic-gate if (meta_check_overlap(np->cname, np, 0, -1, 1338*0Sstevel@tonic-gate p2->namep, 0, -1, ep) != 0) { 1339*0Sstevel@tonic-gate return (-1); 1340*0Sstevel@tonic-gate } 1341*0Sstevel@tonic-gate } 1342*0Sstevel@tonic-gate 1343*0Sstevel@tonic-gate /* count */ 1344*0Sstevel@tonic-gate ++concat_cnt; 1345*0Sstevel@tonic-gate } 1346*0Sstevel@tonic-gate 1347*0Sstevel@tonic-gate /* get old unit */ 1348*0Sstevel@tonic-gate if ((old_mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL) 1349*0Sstevel@tonic-gate return (-1); 1350*0Sstevel@tonic-gate 1351*0Sstevel@tonic-gate /* 1352*0Sstevel@tonic-gate * calculate the size needed for the new raid unit and allocate 1353*0Sstevel@tonic-gate * the appropriate structure. allocate new unit. 1354*0Sstevel@tonic-gate */ 1355*0Sstevel@tonic-gate old_rusize = sizeof (*old_mr) - sizeof (old_mr->un_column[0]); 1356*0Sstevel@tonic-gate old_rusize += old_mr->un_totalcolumncnt * sizeof (old_mr->un_column[0]); 1357*0Sstevel@tonic-gate new_rusize = sizeof (*new_mr) - sizeof (new_mr->un_column[0]); 1358*0Sstevel@tonic-gate new_rusize += (old_mr->un_totalcolumncnt + concat_cnt) 1359*0Sstevel@tonic-gate * sizeof (new_mr->un_column[0]); 1360*0Sstevel@tonic-gate new_mr = Zalloc(new_rusize); 1361*0Sstevel@tonic-gate (void) memcpy(new_mr, old_mr, old_rusize); 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gate /* We always want a do-it, this is for attach_raid_col below */ 1364*0Sstevel@tonic-gate options |= MDCMD_DOIT; 1365*0Sstevel@tonic-gate 1366*0Sstevel@tonic-gate /* build new unit structure */ 1367*0Sstevel@tonic-gate for (p = colnlp; (p != NULL); p = p->next) { 1368*0Sstevel@tonic-gate mdname_t *colnp = p->namep; 1369*0Sstevel@tonic-gate mr_column_t *mdc; 1370*0Sstevel@tonic-gate 1371*0Sstevel@tonic-gate /* attach column */ 1372*0Sstevel@tonic-gate mdc = &new_mr->un_column[new_mr->un_totalcolumncnt]; 1373*0Sstevel@tonic-gate if (attach_raid_col(sp, raidnp, new_mr, mdc, colnp, 1374*0Sstevel@tonic-gate RCS_INIT, &keynlp, options, ep) != 0) { 1375*0Sstevel@tonic-gate goto out; 1376*0Sstevel@tonic-gate } 1377*0Sstevel@tonic-gate } 1378*0Sstevel@tonic-gate assert(new_mr->un_totalcolumncnt 1379*0Sstevel@tonic-gate == (old_mr->un_totalcolumncnt + concat_cnt)); 1380*0Sstevel@tonic-gate 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate create_flag = meta_check_devicesize(new_mr->c.un_total_blocks); 1383*0Sstevel@tonic-gate 1384*0Sstevel@tonic-gate /* grow raid */ 1385*0Sstevel@tonic-gate (void) memset(&mgp, 0, sizeof (mgp)); 1386*0Sstevel@tonic-gate mgp.mnum = MD_SID(new_mr); 1387*0Sstevel@tonic-gate MD_SETDRIVERNAME(&mgp, MD_RAID, sp->setno); 1388*0Sstevel@tonic-gate mgp.size = new_rusize; 1389*0Sstevel@tonic-gate mgp.mdp = (uintptr_t)new_mr; 1390*0Sstevel@tonic-gate 1391*0Sstevel@tonic-gate if (create_flag == MD_CRO_32BIT) { 1392*0Sstevel@tonic-gate mgp.options = MD_CRO_32BIT; 1393*0Sstevel@tonic-gate new_mr->c.un_revision = MD_32BIT_META_DEV; 1394*0Sstevel@tonic-gate } else { 1395*0Sstevel@tonic-gate mgp.options = MD_CRO_64BIT; 1396*0Sstevel@tonic-gate new_mr->c.un_revision = MD_64BIT_META_DEV; 1397*0Sstevel@tonic-gate } 1398*0Sstevel@tonic-gate if (metaioctl(MD_IOCGROW, &mgp, &mgp.mde, NULL) != 0) { 1399*0Sstevel@tonic-gate (void) mdstealerror(ep, &mgp.mde); 1400*0Sstevel@tonic-gate goto out; 1401*0Sstevel@tonic-gate } 1402*0Sstevel@tonic-gate 1403*0Sstevel@tonic-gate /* clear cache */ 1404*0Sstevel@tonic-gate if (invalidate_columns(sp, raidnp, ep) != 0) 1405*0Sstevel@tonic-gate goto out; 1406*0Sstevel@tonic-gate meta_invalidate_name(raidnp); 1407*0Sstevel@tonic-gate 1408*0Sstevel@tonic-gate /* let em know */ 1409*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 1410*0Sstevel@tonic-gate if (concat_cnt == 1) { 1411*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1412*0Sstevel@tonic-gate "%s: component is attached\n"), 1413*0Sstevel@tonic-gate raidnp->cname); 1414*0Sstevel@tonic-gate } else { 1415*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1416*0Sstevel@tonic-gate "%s: components are attached\n"), 1417*0Sstevel@tonic-gate raidnp->cname); 1418*0Sstevel@tonic-gate } 1419*0Sstevel@tonic-gate (void) fflush(stdout); 1420*0Sstevel@tonic-gate } 1421*0Sstevel@tonic-gate 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gate /* grow any parents */ 1424*0Sstevel@tonic-gate if (meta_concat_parent(sp, raidnp, ep) != 0) 1425*0Sstevel@tonic-gate goto out; 1426*0Sstevel@tonic-gate rval = 0; /* success */ 1427*0Sstevel@tonic-gate 1428*0Sstevel@tonic-gate /* cleanup, return error */ 1429*0Sstevel@tonic-gate out: 1430*0Sstevel@tonic-gate Free(old_mr); 1431*0Sstevel@tonic-gate Free(new_mr); 1432*0Sstevel@tonic-gate if (rval != 0) 1433*0Sstevel@tonic-gate (void) del_key_names(sp, keynlp, NULL); 1434*0Sstevel@tonic-gate metafreenamelist(keynlp); 1435*0Sstevel@tonic-gate return (rval); 1436*0Sstevel@tonic-gate } 1437*0Sstevel@tonic-gate 1438*0Sstevel@tonic-gate /* 1439*0Sstevel@tonic-gate * get raid parameters 1440*0Sstevel@tonic-gate */ 1441*0Sstevel@tonic-gate int 1442*0Sstevel@tonic-gate meta_raid_get_params( 1443*0Sstevel@tonic-gate mdsetname_t *sp, 1444*0Sstevel@tonic-gate mdname_t *raidnp, 1445*0Sstevel@tonic-gate mr_params_t *paramsp, 1446*0Sstevel@tonic-gate md_error_t *ep 1447*0Sstevel@tonic-gate ) 1448*0Sstevel@tonic-gate { 1449*0Sstevel@tonic-gate md_raid_t *raidp; 1450*0Sstevel@tonic-gate 1451*0Sstevel@tonic-gate /* should have a set */ 1452*0Sstevel@tonic-gate assert(sp != NULL); 1453*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 1454*0Sstevel@tonic-gate 1455*0Sstevel@tonic-gate /* check name */ 1456*0Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0) 1457*0Sstevel@tonic-gate return (-1); 1458*0Sstevel@tonic-gate 1459*0Sstevel@tonic-gate /* get unit */ 1460*0Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL) 1461*0Sstevel@tonic-gate return (-1); 1462*0Sstevel@tonic-gate 1463*0Sstevel@tonic-gate /* return parameters */ 1464*0Sstevel@tonic-gate (void) memset(paramsp, 0, sizeof (*paramsp)); 1465*0Sstevel@tonic-gate if (raidp->hspnamep == NULL) 1466*0Sstevel@tonic-gate paramsp->hsp_id = MD_HSP_NONE; 1467*0Sstevel@tonic-gate else 1468*0Sstevel@tonic-gate paramsp->hsp_id = raidp->hspnamep->hsp; 1469*0Sstevel@tonic-gate return (0); 1470*0Sstevel@tonic-gate } 1471*0Sstevel@tonic-gate 1472*0Sstevel@tonic-gate /* 1473*0Sstevel@tonic-gate * set raid parameters 1474*0Sstevel@tonic-gate */ 1475*0Sstevel@tonic-gate int 1476*0Sstevel@tonic-gate meta_raid_set_params( 1477*0Sstevel@tonic-gate mdsetname_t *sp, 1478*0Sstevel@tonic-gate mdname_t *raidnp, 1479*0Sstevel@tonic-gate mr_params_t *paramsp, 1480*0Sstevel@tonic-gate md_error_t *ep 1481*0Sstevel@tonic-gate ) 1482*0Sstevel@tonic-gate { 1483*0Sstevel@tonic-gate md_raid_params_t msp; 1484*0Sstevel@tonic-gate 1485*0Sstevel@tonic-gate /* should have a set */ 1486*0Sstevel@tonic-gate assert(sp != NULL); 1487*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 1488*0Sstevel@tonic-gate 1489*0Sstevel@tonic-gate /* check name */ 1490*0Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0) 1491*0Sstevel@tonic-gate return (-1); 1492*0Sstevel@tonic-gate 1493*0Sstevel@tonic-gate /* set parameters */ 1494*0Sstevel@tonic-gate (void) memset(&msp, 0, sizeof (msp)); 1495*0Sstevel@tonic-gate MD_SETDRIVERNAME(&msp, MD_RAID, sp->setno); 1496*0Sstevel@tonic-gate msp.mnum = meta_getminor(raidnp->dev); 1497*0Sstevel@tonic-gate msp.params = *paramsp; 1498*0Sstevel@tonic-gate if (metaioctl(MD_IOCCHANGE, &msp, &msp.mde, raidnp->cname) != 0) 1499*0Sstevel@tonic-gate return (mdstealerror(ep, &msp.mde)); 1500*0Sstevel@tonic-gate 1501*0Sstevel@tonic-gate /* clear cache */ 1502*0Sstevel@tonic-gate meta_invalidate_name(raidnp); 1503*0Sstevel@tonic-gate 1504*0Sstevel@tonic-gate /* return success */ 1505*0Sstevel@tonic-gate return (0); 1506*0Sstevel@tonic-gate } 1507*0Sstevel@tonic-gate 1508*0Sstevel@tonic-gate /* 1509*0Sstevel@tonic-gate * validate raid replace column 1510*0Sstevel@tonic-gate */ 1511*0Sstevel@tonic-gate static int 1512*0Sstevel@tonic-gate validate_new_raid( 1513*0Sstevel@tonic-gate mdsetname_t *sp, 1514*0Sstevel@tonic-gate mdname_t *raidnp, 1515*0Sstevel@tonic-gate mdname_t *colnp, 1516*0Sstevel@tonic-gate replace_params_t *paramsp, 1517*0Sstevel@tonic-gate int dup_ok, 1518*0Sstevel@tonic-gate md_error_t *ep 1519*0Sstevel@tonic-gate ) 1520*0Sstevel@tonic-gate { 1521*0Sstevel@tonic-gate mr_unit_t *mr; 1522*0Sstevel@tonic-gate diskaddr_t column_size; 1523*0Sstevel@tonic-gate diskaddr_t label; 1524*0Sstevel@tonic-gate mdcinfo_t *cinfop; 1525*0Sstevel@tonic-gate int rval = -1; 1526*0Sstevel@tonic-gate 1527*0Sstevel@tonic-gate /* get raid unit */ 1528*0Sstevel@tonic-gate if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL) 1529*0Sstevel@tonic-gate return (-1); 1530*0Sstevel@tonic-gate column_size = mr->un_segsize * mr->un_segsincolumn; 1531*0Sstevel@tonic-gate 1532*0Sstevel@tonic-gate /* check it out */ 1533*0Sstevel@tonic-gate if (meta_check_column(sp, colnp, ep) != 0) { 1534*0Sstevel@tonic-gate if ((! dup_ok) || (! mdisuseerror(ep, MDE_ALREADY))) 1535*0Sstevel@tonic-gate goto out; 1536*0Sstevel@tonic-gate mdclrerror(ep); 1537*0Sstevel@tonic-gate } 1538*0Sstevel@tonic-gate if ((paramsp->number_blks = metagetsize(colnp, ep)) == 1539*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 1540*0Sstevel@tonic-gate goto out; 1541*0Sstevel@tonic-gate if ((label = metagetlabel(colnp, ep)) == MD_DISKADDR_ERROR) 1542*0Sstevel@tonic-gate goto out; 1543*0Sstevel@tonic-gate paramsp->has_label = ((label > 0) ? 1 : 0); 1544*0Sstevel@tonic-gate if ((paramsp->start_blk = metagetstart(sp, colnp, ep)) == 1545*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 1546*0Sstevel@tonic-gate goto out; 1547*0Sstevel@tonic-gate if ((paramsp->number_blks - paramsp->start_blk) < column_size) { 1548*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOSPC, colnp->cname); 1549*0Sstevel@tonic-gate goto out; 1550*0Sstevel@tonic-gate } 1551*0Sstevel@tonic-gate if ((cinfop = metagetcinfo(colnp, ep)) == NULL) 1552*0Sstevel@tonic-gate goto out; 1553*0Sstevel@tonic-gate if (cinfop->maxtransfer < mr->un_maxio) { 1554*0Sstevel@tonic-gate (void) mdcomperror(ep, MDE_MAXIO, meta_getminor(raidnp->dev), 1555*0Sstevel@tonic-gate colnp->dev, colnp->cname); 1556*0Sstevel@tonic-gate goto out; 1557*0Sstevel@tonic-gate } 1558*0Sstevel@tonic-gate 1559*0Sstevel@tonic-gate /* success */ 1560*0Sstevel@tonic-gate rval = 0; 1561*0Sstevel@tonic-gate 1562*0Sstevel@tonic-gate /* cleanup, return error */ 1563*0Sstevel@tonic-gate out: 1564*0Sstevel@tonic-gate Free(mr); 1565*0Sstevel@tonic-gate return (rval); 1566*0Sstevel@tonic-gate } 1567*0Sstevel@tonic-gate 1568*0Sstevel@tonic-gate /* 1569*0Sstevel@tonic-gate * replace raid column 1570*0Sstevel@tonic-gate */ 1571*0Sstevel@tonic-gate int 1572*0Sstevel@tonic-gate meta_raid_replace( 1573*0Sstevel@tonic-gate mdsetname_t *sp, 1574*0Sstevel@tonic-gate mdname_t *raidnp, 1575*0Sstevel@tonic-gate mdname_t *oldnp, 1576*0Sstevel@tonic-gate mdname_t *newnp, 1577*0Sstevel@tonic-gate mdcmdopts_t options, 1578*0Sstevel@tonic-gate md_error_t *ep 1579*0Sstevel@tonic-gate ) 1580*0Sstevel@tonic-gate { 1581*0Sstevel@tonic-gate int force = ((options & MDCMD_FORCE) ? 1 : 0); 1582*0Sstevel@tonic-gate replace_params_t params; 1583*0Sstevel@tonic-gate md_dev64_t old_dev, new_dev; 1584*0Sstevel@tonic-gate diskaddr_t new_start_blk, new_end_blk; 1585*0Sstevel@tonic-gate int rebind; 1586*0Sstevel@tonic-gate mr_unit_t *mr; 1587*0Sstevel@tonic-gate char *new_devidp = NULL; 1588*0Sstevel@tonic-gate md_error_t xep = mdnullerror; 1589*0Sstevel@tonic-gate int ret; 1590*0Sstevel@tonic-gate md_set_desc *sd; 1591*0Sstevel@tonic-gate uint_t tstate; 1592*0Sstevel@tonic-gate 1593*0Sstevel@tonic-gate /* should have same set */ 1594*0Sstevel@tonic-gate assert(sp != NULL); 1595*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 1596*0Sstevel@tonic-gate 1597*0Sstevel@tonic-gate /* check name */ 1598*0Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0) 1599*0Sstevel@tonic-gate return (-1); 1600*0Sstevel@tonic-gate 1601*0Sstevel@tonic-gate /* save new binding incase this is a rebind where oldnp==newnp */ 1602*0Sstevel@tonic-gate new_dev = newnp->dev; 1603*0Sstevel@tonic-gate new_start_blk = newnp->start_blk; 1604*0Sstevel@tonic-gate new_end_blk = newnp->end_blk; 1605*0Sstevel@tonic-gate 1606*0Sstevel@tonic-gate /* invalidate, then get the raid (fill in oldnp from metadb) */ 1607*0Sstevel@tonic-gate meta_invalidate_name(raidnp); 1608*0Sstevel@tonic-gate if (meta_get_raid(sp, raidnp, ep) == NULL) 1609*0Sstevel@tonic-gate return (-1); 1610*0Sstevel@tonic-gate 1611*0Sstevel@tonic-gate /* can't replace a component if the raid inaccessible */ 1612*0Sstevel@tonic-gate if (meta_get_tstate(raidnp->dev, &tstate, ep) != 0) { 1613*0Sstevel@tonic-gate return (-1); 1614*0Sstevel@tonic-gate } 1615*0Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) { 1616*0Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_UNAVAIL_STATE, 1617*0Sstevel@tonic-gate meta_getminor(raidnp->dev), raidnp->cname)); 1618*0Sstevel@tonic-gate } 1619*0Sstevel@tonic-gate 1620*0Sstevel@tonic-gate /* the old device binding is now established */ 1621*0Sstevel@tonic-gate if ((old_dev = oldnp->dev) == NODEV64) 1622*0Sstevel@tonic-gate return (mdsyserror(ep, ENODEV, oldnp->cname)); 1623*0Sstevel@tonic-gate 1624*0Sstevel@tonic-gate 1625*0Sstevel@tonic-gate /* setup raid info */ 1626*0Sstevel@tonic-gate (void) memset(¶ms, 0, sizeof (params)); 1627*0Sstevel@tonic-gate params.mnum = meta_getminor(raidnp->dev); 1628*0Sstevel@tonic-gate MD_SETDRIVERNAME(¶ms, MD_RAID, sp->setno); 1629*0Sstevel@tonic-gate params.old_dev = old_dev; 1630*0Sstevel@tonic-gate params.cmd = force ? FORCE_REPLACE_COMP : REPLACE_COMP; 1631*0Sstevel@tonic-gate 1632*0Sstevel@tonic-gate if (options & MDCMD_CLUSTER_REPLACE) { 1633*0Sstevel@tonic-gate if ((mr = (mr_unit_t *)meta_get_mdunit(sp, raidnp, ep)) == NULL) 1634*0Sstevel@tonic-gate return (NULL); 1635*0Sstevel@tonic-gate Free(mr); 1636*0Sstevel@tonic-gate params.options = MDIOCTL_NO_RESYNC_RAID; 1637*0Sstevel@tonic-gate params.number_blks = metagetsize(newnp, ep); 1638*0Sstevel@tonic-gate if ((metagetlabel(newnp, ep) == MD_DISKADDR_ERROR) || 1639*0Sstevel@tonic-gate (metagetlabel(newnp, ep) == 0)) 1640*0Sstevel@tonic-gate params.has_label = 0; 1641*0Sstevel@tonic-gate else 1642*0Sstevel@tonic-gate params.has_label = 1; 1643*0Sstevel@tonic-gate params.start_blk = metagetstart(sp, newnp, ep); 1644*0Sstevel@tonic-gate } else { 1645*0Sstevel@tonic-gate if ((strcmp(oldnp->rname, newnp->rname) == 0) && 1646*0Sstevel@tonic-gate (old_dev != new_dev)) { 1647*0Sstevel@tonic-gate rebind = 1; 1648*0Sstevel@tonic-gate } else { 1649*0Sstevel@tonic-gate rebind = 0; 1650*0Sstevel@tonic-gate } 1651*0Sstevel@tonic-gate if (rebind) { 1652*0Sstevel@tonic-gate newnp->dev = new_dev; 1653*0Sstevel@tonic-gate newnp->start_blk = new_start_blk; 1654*0Sstevel@tonic-gate newnp->end_blk = new_end_blk; 1655*0Sstevel@tonic-gate } 1656*0Sstevel@tonic-gate 1657*0Sstevel@tonic-gate /* 1658*0Sstevel@tonic-gate * Save a copy of the devid associated with the new disk, the 1659*0Sstevel@tonic-gate * reason is that the checks for the column (meta_check_column) 1660*0Sstevel@tonic-gate * via validate_new_raid(), could cause the disk's devid to be 1661*0Sstevel@tonic-gate * changed to that of the devid that is currently stored in the 1662*0Sstevel@tonic-gate * replica namespace for the disk in question. This devid could 1663*0Sstevel@tonic-gate * be stale if we are replacing the disk. The actual function 1664*0Sstevel@tonic-gate * that overwrites the devid is dr2drivedesc(). 1665*0Sstevel@tonic-gate */ 1666*0Sstevel@tonic-gate 1667*0Sstevel@tonic-gate /* don't setup new_devid if no devid's or MN diskset */ 1668*0Sstevel@tonic-gate if (newnp->drivenamep->devid != NULL) 1669*0Sstevel@tonic-gate new_devidp = Strdup(newnp->drivenamep->devid); 1670*0Sstevel@tonic-gate 1671*0Sstevel@tonic-gate if (!metaislocalset(sp)) { 1672*0Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) 1673*0Sstevel@tonic-gate return (-1); 1674*0Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) 1675*0Sstevel@tonic-gate new_devidp = NULL; 1676*0Sstevel@tonic-gate } 1677*0Sstevel@tonic-gate 1678*0Sstevel@tonic-gate /* check out new (sets up start_blk, has_label, number_blks) */ 1679*0Sstevel@tonic-gate if (validate_new_raid(sp, raidnp, newnp, ¶ms, rebind, 1680*0Sstevel@tonic-gate ep) != 0) { 1681*0Sstevel@tonic-gate Free(new_devidp); 1682*0Sstevel@tonic-gate return (-1); 1683*0Sstevel@tonic-gate } 1684*0Sstevel@tonic-gate 1685*0Sstevel@tonic-gate /* 1686*0Sstevel@tonic-gate * Copy back the saved devid. 1687*0Sstevel@tonic-gate */ 1688*0Sstevel@tonic-gate Free(newnp->drivenamep->devid); 1689*0Sstevel@tonic-gate if (new_devidp) { 1690*0Sstevel@tonic-gate newnp->drivenamep->devid = Strdup(new_devidp); 1691*0Sstevel@tonic-gate Free(new_devidp); 1692*0Sstevel@tonic-gate } 1693*0Sstevel@tonic-gate } 1694*0Sstevel@tonic-gate 1695*0Sstevel@tonic-gate /* store name in namespace, allocate new key */ 1696*0Sstevel@tonic-gate if (add_key_name(sp, newnp, NULL, ep) != 0) 1697*0Sstevel@tonic-gate return (-1); 1698*0Sstevel@tonic-gate 1699*0Sstevel@tonic-gate if (rebind && !metaislocalset(sp)) { 1700*0Sstevel@tonic-gate /* 1701*0Sstevel@tonic-gate * We are 'rebind'ing a disk that is in a diskset so as well 1702*0Sstevel@tonic-gate * as updating the diskset's namespace the local set needs 1703*0Sstevel@tonic-gate * to be updated because it also contains a reference to the 1704*0Sstevel@tonic-gate * disk in question. 1705*0Sstevel@tonic-gate */ 1706*0Sstevel@tonic-gate ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET, 1707*0Sstevel@tonic-gate newnp->cname, ep); 1708*0Sstevel@tonic-gate 1709*0Sstevel@tonic-gate if (ret != METADEVADM_SUCCESS) { 1710*0Sstevel@tonic-gate (void) del_key_name(sp, newnp, &xep); 1711*0Sstevel@tonic-gate return (-1); 1712*0Sstevel@tonic-gate } 1713*0Sstevel@tonic-gate } 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate /* replace column */ 1716*0Sstevel@tonic-gate params.new_dev = new_dev; 1717*0Sstevel@tonic-gate params.new_key = newnp->key; 1718*0Sstevel@tonic-gate if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) { 1719*0Sstevel@tonic-gate (void) del_key_name(sp, newnp, ep); 1720*0Sstevel@tonic-gate return (mdstealerror(ep, ¶ms.mde)); 1721*0Sstevel@tonic-gate } 1722*0Sstevel@tonic-gate 1723*0Sstevel@tonic-gate /* clear cache */ 1724*0Sstevel@tonic-gate meta_invalidate_name(oldnp); 1725*0Sstevel@tonic-gate meta_invalidate_name(newnp); 1726*0Sstevel@tonic-gate meta_invalidate_name(raidnp); 1727*0Sstevel@tonic-gate 1728*0Sstevel@tonic-gate /* let em know */ 1729*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 1730*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1731*0Sstevel@tonic-gate "%s: device %s is replaced with %s\n"), 1732*0Sstevel@tonic-gate raidnp->cname, oldnp->cname, newnp->cname); 1733*0Sstevel@tonic-gate (void) fflush(stdout); 1734*0Sstevel@tonic-gate } 1735*0Sstevel@tonic-gate 1736*0Sstevel@tonic-gate /* return success */ 1737*0Sstevel@tonic-gate return (0); 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate 1740*0Sstevel@tonic-gate /* 1741*0Sstevel@tonic-gate * enable raid column 1742*0Sstevel@tonic-gate */ 1743*0Sstevel@tonic-gate int 1744*0Sstevel@tonic-gate meta_raid_enable( 1745*0Sstevel@tonic-gate mdsetname_t *sp, 1746*0Sstevel@tonic-gate mdname_t *raidnp, 1747*0Sstevel@tonic-gate mdname_t *colnp, 1748*0Sstevel@tonic-gate mdcmdopts_t options, 1749*0Sstevel@tonic-gate md_error_t *ep 1750*0Sstevel@tonic-gate ) 1751*0Sstevel@tonic-gate { 1752*0Sstevel@tonic-gate int force = ((options & MDCMD_FORCE) ? 1 : 0); 1753*0Sstevel@tonic-gate replace_params_t params; 1754*0Sstevel@tonic-gate md_dev64_t fs_dev, del_dev; 1755*0Sstevel@tonic-gate int err = 0; 1756*0Sstevel@tonic-gate char *devnm; 1757*0Sstevel@tonic-gate int ret; 1758*0Sstevel@tonic-gate uint_t tstate; 1759*0Sstevel@tonic-gate 1760*0Sstevel@tonic-gate /* should have same set */ 1761*0Sstevel@tonic-gate assert(sp != NULL); 1762*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 1763*0Sstevel@tonic-gate 1764*0Sstevel@tonic-gate /* check name */ 1765*0Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0) 1766*0Sstevel@tonic-gate return (-1); 1767*0Sstevel@tonic-gate 1768*0Sstevel@tonic-gate /* get the file_system dev binding */ 1769*0Sstevel@tonic-gate if (meta_getdev(sp, colnp, ep) != 0) 1770*0Sstevel@tonic-gate return (-1); 1771*0Sstevel@tonic-gate fs_dev = colnp->dev; 1772*0Sstevel@tonic-gate 1773*0Sstevel@tonic-gate /* get the raid unit (fill in colnp->dev with metadb version) */ 1774*0Sstevel@tonic-gate meta_invalidate_name(raidnp); 1775*0Sstevel@tonic-gate if (meta_get_raid(sp, raidnp, ep) == NULL) 1776*0Sstevel@tonic-gate return (-1); 1777*0Sstevel@tonic-gate 1778*0Sstevel@tonic-gate /* enabling a component can't work if the raid inaccessible */ 1779*0Sstevel@tonic-gate if (meta_get_tstate(raidnp->dev, &tstate, ep) != 0) { 1780*0Sstevel@tonic-gate return (-1); 1781*0Sstevel@tonic-gate } 1782*0Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) { 1783*0Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_UNAVAIL_STATE, 1784*0Sstevel@tonic-gate meta_getminor(raidnp->dev), raidnp->cname)); 1785*0Sstevel@tonic-gate } 1786*0Sstevel@tonic-gate 1787*0Sstevel@tonic-gate /* the metadb device binding is now established */ 1788*0Sstevel@tonic-gate if (colnp->dev == NODEV64) 1789*0Sstevel@tonic-gate return (mdsyserror(ep, ENODEV, colnp->cname)); 1790*0Sstevel@tonic-gate 1791*0Sstevel@tonic-gate /* 1792*0Sstevel@tonic-gate * check for the case where the dev_t has changed between the 1793*0Sstevel@tonic-gate * filesystem and the metadb. This is called a rebind, and 1794*0Sstevel@tonic-gate * is handled by meta_raid_replace. 1795*0Sstevel@tonic-gate */ 1796*0Sstevel@tonic-gate if (fs_dev != colnp->dev) { 1797*0Sstevel@tonic-gate /* 1798*0Sstevel@tonic-gate * Save the devt of mddb version 1799*0Sstevel@tonic-gate */ 1800*0Sstevel@tonic-gate del_dev = colnp->dev; 1801*0Sstevel@tonic-gate 1802*0Sstevel@tonic-gate /* establish file system binding with invalid start/end */ 1803*0Sstevel@tonic-gate colnp->dev = fs_dev; 1804*0Sstevel@tonic-gate colnp->start_blk = -1; 1805*0Sstevel@tonic-gate colnp->end_blk = -1; 1806*0Sstevel@tonic-gate err = meta_raid_replace(sp, raidnp, colnp, colnp, options, ep); 1807*0Sstevel@tonic-gate 1808*0Sstevel@tonic-gate /* 1809*0Sstevel@tonic-gate * Don't do it if meta_raid_replace returns an error 1810*0Sstevel@tonic-gate */ 1811*0Sstevel@tonic-gate if (!err && (devnm = meta_getnmentbydev(sp->setno, MD_SIDEWILD, 1812*0Sstevel@tonic-gate del_dev, NULL, NULL, &colnp->key, ep)) != NULL) { 1813*0Sstevel@tonic-gate (void) del_key_name(sp, colnp, ep); 1814*0Sstevel@tonic-gate Free(devnm); 1815*0Sstevel@tonic-gate } 1816*0Sstevel@tonic-gate return (err); 1817*0Sstevel@tonic-gate } 1818*0Sstevel@tonic-gate 1819*0Sstevel@tonic-gate /* setup raid info */ 1820*0Sstevel@tonic-gate (void) memset(¶ms, 0, sizeof (params)); 1821*0Sstevel@tonic-gate params.mnum = meta_getminor(raidnp->dev); 1822*0Sstevel@tonic-gate MD_SETDRIVERNAME(¶ms, MD_RAID, sp->setno); 1823*0Sstevel@tonic-gate params.old_dev = params.new_dev = colnp->dev; 1824*0Sstevel@tonic-gate if (force) 1825*0Sstevel@tonic-gate params.cmd = FORCE_ENABLE_COMP; 1826*0Sstevel@tonic-gate else 1827*0Sstevel@tonic-gate params.cmd = ENABLE_COMP; 1828*0Sstevel@tonic-gate 1829*0Sstevel@tonic-gate /* check it out */ 1830*0Sstevel@tonic-gate if (validate_new_raid(sp, raidnp, colnp, ¶ms, 1, ep) != 0) 1831*0Sstevel@tonic-gate return (-1); 1832*0Sstevel@tonic-gate 1833*0Sstevel@tonic-gate /* enable column */ 1834*0Sstevel@tonic-gate if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) 1835*0Sstevel@tonic-gate return (mdstealerror(ep, ¶ms.mde)); 1836*0Sstevel@tonic-gate 1837*0Sstevel@tonic-gate /* 1838*0Sstevel@tonic-gate * are we dealing with a non-local set? If so need to update the 1839*0Sstevel@tonic-gate * local namespace so that the disk record has the correct devid. 1840*0Sstevel@tonic-gate */ 1841*0Sstevel@tonic-gate if (!metaislocalset(sp)) { 1842*0Sstevel@tonic-gate ret = meta_fixdevid(sp, DEV_UPDATE|DEV_LOCAL_SET, colnp->cname, 1843*0Sstevel@tonic-gate ep); 1844*0Sstevel@tonic-gate 1845*0Sstevel@tonic-gate if (ret != METADEVADM_SUCCESS) { 1846*0Sstevel@tonic-gate /* 1847*0Sstevel@tonic-gate * Failed to update the local set. Nothing to do here 1848*0Sstevel@tonic-gate * apart from report the error. The namespace is 1849*0Sstevel@tonic-gate * most likely broken and some form of remedial 1850*0Sstevel@tonic-gate * recovery is going to be required. 1851*0Sstevel@tonic-gate */ 1852*0Sstevel@tonic-gate mde_perror(ep, ""); 1853*0Sstevel@tonic-gate mdclrerror(ep); 1854*0Sstevel@tonic-gate } 1855*0Sstevel@tonic-gate } 1856*0Sstevel@tonic-gate 1857*0Sstevel@tonic-gate /* clear cache */ 1858*0Sstevel@tonic-gate meta_invalidate_name(colnp); 1859*0Sstevel@tonic-gate meta_invalidate_name(raidnp); 1860*0Sstevel@tonic-gate 1861*0Sstevel@tonic-gate /* let em know */ 1862*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 1863*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1864*0Sstevel@tonic-gate "%s: device %s is enabled\n"), 1865*0Sstevel@tonic-gate raidnp->cname, colnp->cname); 1866*0Sstevel@tonic-gate (void) fflush(stdout); 1867*0Sstevel@tonic-gate } 1868*0Sstevel@tonic-gate 1869*0Sstevel@tonic-gate /* return success */ 1870*0Sstevel@tonic-gate return (0); 1871*0Sstevel@tonic-gate } 1872*0Sstevel@tonic-gate 1873*0Sstevel@tonic-gate /* 1874*0Sstevel@tonic-gate * check for dups in the raid itself 1875*0Sstevel@tonic-gate */ 1876*0Sstevel@tonic-gate static int 1877*0Sstevel@tonic-gate check_twice( 1878*0Sstevel@tonic-gate md_raid_t *raidp, 1879*0Sstevel@tonic-gate uint_t col, 1880*0Sstevel@tonic-gate md_error_t *ep 1881*0Sstevel@tonic-gate ) 1882*0Sstevel@tonic-gate { 1883*0Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep; 1884*0Sstevel@tonic-gate mdname_t *thisnp; 1885*0Sstevel@tonic-gate uint_t c; 1886*0Sstevel@tonic-gate 1887*0Sstevel@tonic-gate thisnp = raidp->cols.cols_val[col].colnamep; 1888*0Sstevel@tonic-gate for (c = 0; (c < col); ++c) { 1889*0Sstevel@tonic-gate md_raidcol_t *mdcp = &raidp->cols.cols_val[c]; 1890*0Sstevel@tonic-gate mdname_t *colnp = mdcp->colnamep; 1891*0Sstevel@tonic-gate 1892*0Sstevel@tonic-gate if (meta_check_overlap(raidnp->cname, thisnp, 0, -1, 1893*0Sstevel@tonic-gate colnp, 0, -1, ep) != 0) { 1894*0Sstevel@tonic-gate return (-1); 1895*0Sstevel@tonic-gate } 1896*0Sstevel@tonic-gate } 1897*0Sstevel@tonic-gate return (0); 1898*0Sstevel@tonic-gate } 1899*0Sstevel@tonic-gate 1900*0Sstevel@tonic-gate /* 1901*0Sstevel@tonic-gate * default raid interlace 1902*0Sstevel@tonic-gate */ 1903*0Sstevel@tonic-gate diskaddr_t 1904*0Sstevel@tonic-gate meta_default_raid_interlace(void) 1905*0Sstevel@tonic-gate { 1906*0Sstevel@tonic-gate diskaddr_t interlace; 1907*0Sstevel@tonic-gate 1908*0Sstevel@tonic-gate /* default to 16k, round up if necessary */ 1909*0Sstevel@tonic-gate interlace = btodb(16 * 1024); 1910*0Sstevel@tonic-gate if (interlace < lbtodb(MININTERLACE)) 1911*0Sstevel@tonic-gate interlace = roundup(MININTERLACE, interlace); 1912*0Sstevel@tonic-gate return (interlace); 1913*0Sstevel@tonic-gate } 1914*0Sstevel@tonic-gate 1915*0Sstevel@tonic-gate /* 1916*0Sstevel@tonic-gate * convert interlaces 1917*0Sstevel@tonic-gate */ 1918*0Sstevel@tonic-gate int 1919*0Sstevel@tonic-gate meta_raid_check_interlace( 1920*0Sstevel@tonic-gate diskaddr_t interlace, 1921*0Sstevel@tonic-gate char *uname, 1922*0Sstevel@tonic-gate md_error_t *ep 1923*0Sstevel@tonic-gate ) 1924*0Sstevel@tonic-gate { 1925*0Sstevel@tonic-gate if ((interlace < btodb(RAID_MIN_INTERLACE)) || 1926*0Sstevel@tonic-gate (interlace > btodb(MAXINTERLACE))) { 1927*0Sstevel@tonic-gate return (mderror(ep, MDE_BAD_INTERLACE, uname)); 1928*0Sstevel@tonic-gate } 1929*0Sstevel@tonic-gate return (0); 1930*0Sstevel@tonic-gate } 1931*0Sstevel@tonic-gate 1932*0Sstevel@tonic-gate /* 1933*0Sstevel@tonic-gate * check raid 1934*0Sstevel@tonic-gate */ 1935*0Sstevel@tonic-gate int 1936*0Sstevel@tonic-gate meta_check_raid( 1937*0Sstevel@tonic-gate mdsetname_t *sp, 1938*0Sstevel@tonic-gate md_raid_t *raidp, 1939*0Sstevel@tonic-gate mdcmdopts_t options, 1940*0Sstevel@tonic-gate md_error_t *ep 1941*0Sstevel@tonic-gate ) 1942*0Sstevel@tonic-gate { 1943*0Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep; 1944*0Sstevel@tonic-gate int doit = ((options & MDCMD_DOIT) ? 1 : 0); 1945*0Sstevel@tonic-gate int updateit = ((options & MDCMD_UPDATE) ? 1 : 0); 1946*0Sstevel@tonic-gate uint_t ncol; 1947*0Sstevel@tonic-gate uint_t col; 1948*0Sstevel@tonic-gate minor_t mnum = meta_getminor(raidnp->dev); 1949*0Sstevel@tonic-gate 1950*0Sstevel@tonic-gate /* check number */ 1951*0Sstevel@tonic-gate if (((ncol = raidp->cols.cols_len) < MD_RAID_MIN) || 1952*0Sstevel@tonic-gate (raidp->orig_ncol > ncol)) { 1953*0Sstevel@tonic-gate return (mdmderror(ep, MDE_BAD_RAID, mnum, raidnp->cname)); 1954*0Sstevel@tonic-gate } 1955*0Sstevel@tonic-gate 1956*0Sstevel@tonic-gate /* compute default interlace */ 1957*0Sstevel@tonic-gate if (raidp->interlace == 0) { 1958*0Sstevel@tonic-gate raidp->interlace = meta_default_raid_interlace(); 1959*0Sstevel@tonic-gate } 1960*0Sstevel@tonic-gate 1961*0Sstevel@tonic-gate /* check state */ 1962*0Sstevel@tonic-gate switch (raidp->state) { 1963*0Sstevel@tonic-gate case RUS_INIT: 1964*0Sstevel@tonic-gate case RUS_OKAY: 1965*0Sstevel@tonic-gate break; 1966*0Sstevel@tonic-gate 1967*0Sstevel@tonic-gate default: 1968*0Sstevel@tonic-gate return (mdmderror(ep, MDE_BAD_RAID, mnum, raidnp->cname)); 1969*0Sstevel@tonic-gate } 1970*0Sstevel@tonic-gate 1971*0Sstevel@tonic-gate /* check interlace */ 1972*0Sstevel@tonic-gate if (meta_raid_check_interlace(raidp->interlace, raidnp->cname, ep) != 0) 1973*0Sstevel@tonic-gate return (-1); 1974*0Sstevel@tonic-gate 1975*0Sstevel@tonic-gate /* check hotspare pool name */ 1976*0Sstevel@tonic-gate if (doit) { 1977*0Sstevel@tonic-gate if ((raidp->hspnamep != NULL) && 1978*0Sstevel@tonic-gate (metachkhsp(sp, raidp->hspnamep, ep) != 0)) { 1979*0Sstevel@tonic-gate return (-1); 1980*0Sstevel@tonic-gate } 1981*0Sstevel@tonic-gate } 1982*0Sstevel@tonic-gate 1983*0Sstevel@tonic-gate /* check columns */ 1984*0Sstevel@tonic-gate for (col = 0; (col < ncol); ++col) { 1985*0Sstevel@tonic-gate md_raidcol_t *mdcp = &raidp->cols.cols_val[col]; 1986*0Sstevel@tonic-gate mdname_t *colnp = mdcp->colnamep; 1987*0Sstevel@tonic-gate diskaddr_t start_blk, size; 1988*0Sstevel@tonic-gate 1989*0Sstevel@tonic-gate /* setup column */ 1990*0Sstevel@tonic-gate if (raidp->state == RUS_INIT) 1991*0Sstevel@tonic-gate mdcp->state = RCS_INIT; 1992*0Sstevel@tonic-gate else 1993*0Sstevel@tonic-gate mdcp->state = RCS_OKAY; 1994*0Sstevel@tonic-gate 1995*0Sstevel@tonic-gate /* check column */ 1996*0Sstevel@tonic-gate if (!updateit) { 1997*0Sstevel@tonic-gate if (meta_check_column(sp, colnp, ep) != 0) 1998*0Sstevel@tonic-gate return (-1); 1999*0Sstevel@tonic-gate if (((start_blk = metagetstart(sp, colnp, ep)) == 2000*0Sstevel@tonic-gate MD_DISKADDR_ERROR) || ((size = metagetsize(colnp, 2001*0Sstevel@tonic-gate ep)) == MD_DISKADDR_ERROR)) { 2002*0Sstevel@tonic-gate return (-1); 2003*0Sstevel@tonic-gate } 2004*0Sstevel@tonic-gate if (start_blk >= size) 2005*0Sstevel@tonic-gate return (mdsyserror(ep, ENOSPC, colnp->cname)); 2006*0Sstevel@tonic-gate size -= start_blk; 2007*0Sstevel@tonic-gate size = rounddown(size, raidp->interlace); 2008*0Sstevel@tonic-gate if (size == 0) 2009*0Sstevel@tonic-gate return (mdsyserror(ep, ENOSPC, colnp->cname)); 2010*0Sstevel@tonic-gate } 2011*0Sstevel@tonic-gate 2012*0Sstevel@tonic-gate /* check this raid too */ 2013*0Sstevel@tonic-gate if (check_twice(raidp, col, ep) != 0) 2014*0Sstevel@tonic-gate return (-1); 2015*0Sstevel@tonic-gate } 2016*0Sstevel@tonic-gate 2017*0Sstevel@tonic-gate /* return success */ 2018*0Sstevel@tonic-gate return (0); 2019*0Sstevel@tonic-gate } 2020*0Sstevel@tonic-gate 2021*0Sstevel@tonic-gate /* 2022*0Sstevel@tonic-gate * setup raid geometry 2023*0Sstevel@tonic-gate */ 2024*0Sstevel@tonic-gate static int 2025*0Sstevel@tonic-gate raid_geom( 2026*0Sstevel@tonic-gate md_raid_t *raidp, 2027*0Sstevel@tonic-gate mr_unit_t *mr, 2028*0Sstevel@tonic-gate md_error_t *ep 2029*0Sstevel@tonic-gate ) 2030*0Sstevel@tonic-gate { 2031*0Sstevel@tonic-gate uint_t write_reinstruct = 0; 2032*0Sstevel@tonic-gate uint_t read_reinstruct = 0; 2033*0Sstevel@tonic-gate uint_t round_cyl = 1; 2034*0Sstevel@tonic-gate uint_t col; 2035*0Sstevel@tonic-gate mdgeom_t *geomp; 2036*0Sstevel@tonic-gate 2037*0Sstevel@tonic-gate /* get worst reinstructs */ 2038*0Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) { 2039*0Sstevel@tonic-gate md_raidcol_t *mdcp = &raidp->cols.cols_val[col]; 2040*0Sstevel@tonic-gate mdname_t *colnp = mdcp->colnamep; 2041*0Sstevel@tonic-gate 2042*0Sstevel@tonic-gate if ((geomp = metagetgeom(colnp, ep)) == NULL) 2043*0Sstevel@tonic-gate return (-1); 2044*0Sstevel@tonic-gate if (geomp->write_reinstruct > write_reinstruct) 2045*0Sstevel@tonic-gate write_reinstruct = geomp->write_reinstruct; 2046*0Sstevel@tonic-gate if (geomp->read_reinstruct > read_reinstruct) 2047*0Sstevel@tonic-gate read_reinstruct = geomp->read_reinstruct; 2048*0Sstevel@tonic-gate } 2049*0Sstevel@tonic-gate 2050*0Sstevel@tonic-gate /* setup geometry from first column */ 2051*0Sstevel@tonic-gate assert(raidp->cols.cols_len > 0); 2052*0Sstevel@tonic-gate if ((geomp = metagetgeom(raidp->cols.cols_val[0].colnamep, 2053*0Sstevel@tonic-gate ep)) == NULL) { 2054*0Sstevel@tonic-gate return (-1); 2055*0Sstevel@tonic-gate } 2056*0Sstevel@tonic-gate if (meta_setup_geom((md_unit_t *)mr, raidp->common.namep, geomp, 2057*0Sstevel@tonic-gate write_reinstruct, read_reinstruct, round_cyl, ep) != 0) 2058*0Sstevel@tonic-gate return (-1); 2059*0Sstevel@tonic-gate 2060*0Sstevel@tonic-gate /* return success */ 2061*0Sstevel@tonic-gate return (0); 2062*0Sstevel@tonic-gate } 2063*0Sstevel@tonic-gate 2064*0Sstevel@tonic-gate int 2065*0Sstevel@tonic-gate meta_raid_state_cnt(mr_unit_t *mr, rcs_state_t state) 2066*0Sstevel@tonic-gate { 2067*0Sstevel@tonic-gate int statecnt = 0; 2068*0Sstevel@tonic-gate int col; 2069*0Sstevel@tonic-gate 2070*0Sstevel@tonic-gate for (col = 0; col < mr->un_totalcolumncnt; col++) 2071*0Sstevel@tonic-gate if (mr->un_column[col].un_devstate & state) 2072*0Sstevel@tonic-gate statecnt++; 2073*0Sstevel@tonic-gate return (statecnt); 2074*0Sstevel@tonic-gate } 2075*0Sstevel@tonic-gate /* 2076*0Sstevel@tonic-gate * validate that a raid device being created with the -k flag is a real 2077*0Sstevel@tonic-gate * raid device 2078*0Sstevel@tonic-gate */ 2079*0Sstevel@tonic-gate int 2080*0Sstevel@tonic-gate meta_raid_valid(md_raid_t *raidp, mr_unit_t *mr) 2081*0Sstevel@tonic-gate { 2082*0Sstevel@tonic-gate long long buf[DEV_BSIZE / sizeof (long long)]; 2083*0Sstevel@tonic-gate raid_pwhdr_t pwhdr; 2084*0Sstevel@tonic-gate raid_pwhdr_t *rpw = &pwhdr; 2085*0Sstevel@tonic-gate minor_t mnum; 2086*0Sstevel@tonic-gate int col; 2087*0Sstevel@tonic-gate int fd; 2088*0Sstevel@tonic-gate 2089*0Sstevel@tonic-gate for (col = 0; col < mr->un_totalcolumncnt; col++) { 2090*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 2091*0Sstevel@tonic-gate mdname_t *colnp = cp->colnamep; 2092*0Sstevel@tonic-gate 2093*0Sstevel@tonic-gate if ((fd = open(colnp->rname, O_RDONLY)) < 0) 2094*0Sstevel@tonic-gate goto error_exit; 2095*0Sstevel@tonic-gate 2096*0Sstevel@tonic-gate if (lseek64(fd, 2097*0Sstevel@tonic-gate (mr->un_column[col].un_pwstart * DEV_BSIZE), SEEK_SET) < 0) 2098*0Sstevel@tonic-gate goto error_exit; 2099*0Sstevel@tonic-gate 2100*0Sstevel@tonic-gate if (read(fd, buf, DEV_BSIZE) < 0) 2101*0Sstevel@tonic-gate goto error_exit; 2102*0Sstevel@tonic-gate 2103*0Sstevel@tonic-gate /* 2104*0Sstevel@tonic-gate * If our raid device is a 64 bit device, we can accept the 2105*0Sstevel@tonic-gate * pw header we just read in. 2106*0Sstevel@tonic-gate * Otherwise it's of type raid_pwhdr32_od_t and has to 2107*0Sstevel@tonic-gate * be converted. 2108*0Sstevel@tonic-gate */ 2109*0Sstevel@tonic-gate if (mr->c.un_revision == MD_64BIT_META_DEV) { 2110*0Sstevel@tonic-gate rpw = (raid_pwhdr_t *)buf; 2111*0Sstevel@tonic-gate } else { 2112*0Sstevel@tonic-gate RAID_CONVERT_RPW((raid_pwhdr32_od_t *)buf, rpw); 2113*0Sstevel@tonic-gate } 2114*0Sstevel@tonic-gate 2115*0Sstevel@tonic-gate if (rpw->rpw_column != col) 2116*0Sstevel@tonic-gate goto error_exit; 2117*0Sstevel@tonic-gate 2118*0Sstevel@tonic-gate if (col == 0) 2119*0Sstevel@tonic-gate mnum = rpw->rpw_unit; 2120*0Sstevel@tonic-gate 2121*0Sstevel@tonic-gate if (rpw->rpw_unit != mnum) 2122*0Sstevel@tonic-gate goto error_exit; 2123*0Sstevel@tonic-gate 2124*0Sstevel@tonic-gate if (rpw->rpw_magic_ext == RAID_PWMAGIC) { 2125*0Sstevel@tonic-gate /* 4.1 prewrite header */ 2126*0Sstevel@tonic-gate if ((rpw->rpw_origcolumncnt != mr->un_origcolumncnt) || 2127*0Sstevel@tonic-gate (rpw->rpw_totalcolumncnt 2128*0Sstevel@tonic-gate != mr->un_totalcolumncnt) || 2129*0Sstevel@tonic-gate (rpw->rpw_segsize != mr->un_segsize) || 2130*0Sstevel@tonic-gate (rpw->rpw_segsincolumn != mr->un_segsincolumn) || 2131*0Sstevel@tonic-gate (rpw->rpw_pwcnt != mr->un_pwcnt) || 2132*0Sstevel@tonic-gate (rpw->rpw_pwstart != 2133*0Sstevel@tonic-gate mr->un_column[col].un_pwstart) || 2134*0Sstevel@tonic-gate (rpw->rpw_devstart != 2135*0Sstevel@tonic-gate mr->un_column[col].un_devstart) || 2136*0Sstevel@tonic-gate (rpw->rpw_pwsize != mr->un_pwsize)) 2137*0Sstevel@tonic-gate goto error_exit; 2138*0Sstevel@tonic-gate } 2139*0Sstevel@tonic-gate /* 2140*0Sstevel@tonic-gate * this is an old prewrite header (4.0) the unit structure 2141*0Sstevel@tonic-gate * will have to be trusted. 2142*0Sstevel@tonic-gate */ 2143*0Sstevel@tonic-gate (void) close(fd); 2144*0Sstevel@tonic-gate } 2145*0Sstevel@tonic-gate 2146*0Sstevel@tonic-gate return (0); 2147*0Sstevel@tonic-gate 2148*0Sstevel@tonic-gate error_exit: 2149*0Sstevel@tonic-gate (void) close(fd); 2150*0Sstevel@tonic-gate return (-1); 2151*0Sstevel@tonic-gate } 2152*0Sstevel@tonic-gate 2153*0Sstevel@tonic-gate /* 2154*0Sstevel@tonic-gate * create raid 2155*0Sstevel@tonic-gate */ 2156*0Sstevel@tonic-gate int 2157*0Sstevel@tonic-gate meta_create_raid( 2158*0Sstevel@tonic-gate mdsetname_t *sp, 2159*0Sstevel@tonic-gate md_raid_t *raidp, 2160*0Sstevel@tonic-gate mdcmdopts_t options, 2161*0Sstevel@tonic-gate md_error_t *ep 2162*0Sstevel@tonic-gate ) 2163*0Sstevel@tonic-gate { 2164*0Sstevel@tonic-gate mdname_t *raidnp = raidp->common.namep; 2165*0Sstevel@tonic-gate uint_t ncol = raidp->cols.cols_len; 2166*0Sstevel@tonic-gate uint_t orig_ncol = raidp->orig_ncol; 2167*0Sstevel@tonic-gate size_t rdsize; 2168*0Sstevel@tonic-gate mr_unit_t *mr; 2169*0Sstevel@tonic-gate uint_t col; 2170*0Sstevel@tonic-gate diskaddr_t disk_size = 0; 2171*0Sstevel@tonic-gate uint_t disk_maxio = 0; 2172*0Sstevel@tonic-gate uint_t pwes; 2173*0Sstevel@tonic-gate diskaddr_t non_pw_blks, column_size; 2174*0Sstevel@tonic-gate mdnamelist_t *keynlp = NULL; 2175*0Sstevel@tonic-gate md_set_params_t set_params; 2176*0Sstevel@tonic-gate int rval = -1; 2177*0Sstevel@tonic-gate md_timeval32_t creation_time; 2178*0Sstevel@tonic-gate int create_flag = MD_CRO_32BIT; 2179*0Sstevel@tonic-gate 2180*0Sstevel@tonic-gate /* validate raid */ 2181*0Sstevel@tonic-gate if (meta_check_raid(sp, raidp, options, ep) != 0) 2182*0Sstevel@tonic-gate return (-1); 2183*0Sstevel@tonic-gate 2184*0Sstevel@tonic-gate /* allocate raid unit */ 2185*0Sstevel@tonic-gate rdsize = sizeof (*mr) - sizeof (mr->un_column[0]); 2186*0Sstevel@tonic-gate rdsize += ncol * sizeof (mr->un_column[0]); 2187*0Sstevel@tonic-gate mr = Zalloc(rdsize); 2188*0Sstevel@tonic-gate 2189*0Sstevel@tonic-gate if (meta_gettimeofday(&creation_time) == -1) 2190*0Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL)); 2191*0Sstevel@tonic-gate /* 2192*0Sstevel@tonic-gate * initialize the top level mr_unit_t structure 2193*0Sstevel@tonic-gate * setup the unit state to indicate whether to retain 2194*0Sstevel@tonic-gate * any data currently on the metadevice or to clear it 2195*0Sstevel@tonic-gate */ 2196*0Sstevel@tonic-gate mr->c.un_type = MD_METARAID; 2197*0Sstevel@tonic-gate MD_SID(mr) = meta_getminor(raidnp->dev); 2198*0Sstevel@tonic-gate mr->c.un_size = rdsize; 2199*0Sstevel@tonic-gate mr->un_magic = RAID_UNMAGIC; 2200*0Sstevel@tonic-gate mr->un_state = raidp->state; 2201*0Sstevel@tonic-gate mr->un_timestamp = creation_time; 2202*0Sstevel@tonic-gate mr->un_origcolumncnt = orig_ncol; 2203*0Sstevel@tonic-gate mr->un_segsize = (uint_t)raidp->interlace; 2204*0Sstevel@tonic-gate if (raidp->hspnamep != NULL) { 2205*0Sstevel@tonic-gate mr->un_hsp_id = raidp->hspnamep->hsp; 2206*0Sstevel@tonic-gate } else { 2207*0Sstevel@tonic-gate mr->un_hsp_id = MD_HSP_NONE; 2208*0Sstevel@tonic-gate } 2209*0Sstevel@tonic-gate /* 2210*0Sstevel@tonic-gate * setup original columns, saving start_block and 2211*0Sstevel@tonic-gate * finding smallest size and maxio 2212*0Sstevel@tonic-gate */ 2213*0Sstevel@tonic-gate for (col = 0; (col < orig_ncol); ++col) { 2214*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 2215*0Sstevel@tonic-gate mdname_t *colnp = cp->colnamep; 2216*0Sstevel@tonic-gate mr_column_t *mdc = &mr->un_column[col]; 2217*0Sstevel@tonic-gate diskaddr_t size; 2218*0Sstevel@tonic-gate uint_t maxio; 2219*0Sstevel@tonic-gate mdcinfo_t *cinfop; 2220*0Sstevel@tonic-gate 2221*0Sstevel@tonic-gate /* setup state */ 2222*0Sstevel@tonic-gate mdc->un_devstate = cp->state; 2223*0Sstevel@tonic-gate 2224*0Sstevel@tonic-gate /* setup creation time */ 2225*0Sstevel@tonic-gate mdc->un_devtimestamp = creation_time; 2226*0Sstevel@tonic-gate 2227*0Sstevel@tonic-gate /* get start, size, and maxio */ 2228*0Sstevel@tonic-gate if ((mdc->un_orig_devstart = metagetstart(sp, colnp, ep)) == 2229*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 2230*0Sstevel@tonic-gate goto out; 2231*0Sstevel@tonic-gate if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR) 2232*0Sstevel@tonic-gate goto out; 2233*0Sstevel@tonic-gate size -= mdc->un_orig_devstart; 2234*0Sstevel@tonic-gate if ((cinfop = metagetcinfo(colnp, ep)) == NULL) 2235*0Sstevel@tonic-gate goto out; 2236*0Sstevel@tonic-gate maxio = cinfop->maxtransfer; 2237*0Sstevel@tonic-gate 2238*0Sstevel@tonic-gate if (options & MDCMD_DOIT) { 2239*0Sstevel@tonic-gate /* store name in namespace */ 2240*0Sstevel@tonic-gate if (add_key_name(sp, colnp, &keynlp, ep) != 0) 2241*0Sstevel@tonic-gate goto out; 2242*0Sstevel@tonic-gate } 2243*0Sstevel@tonic-gate 2244*0Sstevel@tonic-gate /* setup column */ 2245*0Sstevel@tonic-gate mdc->un_orig_key = colnp->key; 2246*0Sstevel@tonic-gate mdc->un_orig_dev = colnp->dev; 2247*0Sstevel@tonic-gate mdc->un_dev = mdc->un_orig_dev; 2248*0Sstevel@tonic-gate mdc->un_pwstart = mdc->un_orig_pwstart; 2249*0Sstevel@tonic-gate mdc->un_devstart = mdc->un_orig_devstart; 2250*0Sstevel@tonic-gate mdc->un_alt_dev = NODEV64; 2251*0Sstevel@tonic-gate mdc->un_alt_pwstart = 0; 2252*0Sstevel@tonic-gate mdc->un_alt_devstart = 0; 2253*0Sstevel@tonic-gate mdc->un_hs_id = 0; 2254*0Sstevel@tonic-gate if (mr->un_state == RUS_INIT) 2255*0Sstevel@tonic-gate mdc->un_devstate = RCS_INIT; 2256*0Sstevel@tonic-gate else 2257*0Sstevel@tonic-gate mdc->un_devstate = RCS_OKAY; 2258*0Sstevel@tonic-gate 2259*0Sstevel@tonic-gate /* adjust for smallest disk */ 2260*0Sstevel@tonic-gate if (disk_size == 0) { 2261*0Sstevel@tonic-gate disk_size = size; 2262*0Sstevel@tonic-gate } else if (size < disk_size) { 2263*0Sstevel@tonic-gate disk_size = size; 2264*0Sstevel@tonic-gate } 2265*0Sstevel@tonic-gate if (disk_maxio == 0) { 2266*0Sstevel@tonic-gate disk_maxio = maxio; 2267*0Sstevel@tonic-gate } else if (maxio < disk_maxio) { 2268*0Sstevel@tonic-gate disk_maxio = maxio; 2269*0Sstevel@tonic-gate } 2270*0Sstevel@tonic-gate } 2271*0Sstevel@tonic-gate assert(col == mr->un_origcolumncnt); 2272*0Sstevel@tonic-gate 2273*0Sstevel@tonic-gate /* 2274*0Sstevel@tonic-gate * before processing any of the attached column(s) 2275*0Sstevel@tonic-gate * set up the composition of the metadevice for column 2276*0Sstevel@tonic-gate * sizes and pre-write information 2277*0Sstevel@tonic-gate */ 2278*0Sstevel@tonic-gate mr->un_maxio = disk_maxio; /* smallest maxio */ 2279*0Sstevel@tonic-gate mr->un_iosize = min(mr->un_maxio, (mr->un_segsize + 1)); 2280*0Sstevel@tonic-gate pwes = mr->un_iosize; 2281*0Sstevel@tonic-gate if (raidp->pw_count) 2282*0Sstevel@tonic-gate mr->un_pwcnt = raidp->pw_count; 2283*0Sstevel@tonic-gate else 2284*0Sstevel@tonic-gate mr->un_pwcnt = PWCNT_MIN; 2285*0Sstevel@tonic-gate if ((mr->un_pwcnt < PWCNT_MIN) || (mr->un_pwcnt > PWCNT_MAX)) { 2286*0Sstevel@tonic-gate (void) mderror(ep, MDE_RAID_BAD_PW_CNT, raidnp->cname); 2287*0Sstevel@tonic-gate goto out; 2288*0Sstevel@tonic-gate } 2289*0Sstevel@tonic-gate mr->un_pwsize = roundup((mr->un_pwcnt * pwes), 2); 2290*0Sstevel@tonic-gate 2291*0Sstevel@tonic-gate /* now calculate the number of segments per column */ 2292*0Sstevel@tonic-gate non_pw_blks = disk_size - mr->un_pwsize; /* smallest disk */ 2293*0Sstevel@tonic-gate if ((mr->un_pwsize > disk_size) || 2294*0Sstevel@tonic-gate (non_pw_blks < (diskaddr_t)mr->un_segsize)) { 2295*0Sstevel@tonic-gate (void) mdsyserror(ep, ENOSPC, raidnp->cname); 2296*0Sstevel@tonic-gate goto out; 2297*0Sstevel@tonic-gate } 2298*0Sstevel@tonic-gate mr->un_segsincolumn = non_pw_blks / mr->un_segsize; 2299*0Sstevel@tonic-gate column_size = mr->un_segsize * mr->un_segsincolumn; 2300*0Sstevel@tonic-gate 2301*0Sstevel@tonic-gate /* 2302*0Sstevel@tonic-gate * adjust the pw_cnt, pw_size, to fit into any fragmentation 2303*0Sstevel@tonic-gate * left over after column_size has been computed 2304*0Sstevel@tonic-gate */ 2305*0Sstevel@tonic-gate mr->un_pwsize = rounddown(((uint_t)(disk_size - column_size)), 2); 2306*0Sstevel@tonic-gate mr->un_pwcnt = mr->un_pwsize / pwes; 2307*0Sstevel@tonic-gate assert(mr->un_pwcnt >= PWCNT_MIN); 2308*0Sstevel@tonic-gate mr->un_pwsize = roundup((mr->un_pwcnt * pwes), 2); 2309*0Sstevel@tonic-gate assert((mr->un_pwsize + column_size) <= disk_size); 2310*0Sstevel@tonic-gate 2311*0Sstevel@tonic-gate /* 2312*0Sstevel@tonic-gate * calculate the actual block count available based on the 2313*0Sstevel@tonic-gate * segment size and the number of segments per column ... 2314*0Sstevel@tonic-gate * ... and adjust for the number of parity segments 2315*0Sstevel@tonic-gate */ 2316*0Sstevel@tonic-gate mr->c.un_actual_tb = column_size * (mr->un_origcolumncnt - 1); 2317*0Sstevel@tonic-gate 2318*0Sstevel@tonic-gate if (raid_geom(raidp, mr, ep) != 0) 2319*0Sstevel@tonic-gate goto out; 2320*0Sstevel@tonic-gate 2321*0Sstevel@tonic-gate create_flag = meta_check_devicesize(mr->c.un_total_blocks); 2322*0Sstevel@tonic-gate 2323*0Sstevel@tonic-gate /* 2324*0Sstevel@tonic-gate * now calculate the pre-write offset and update the column 2325*0Sstevel@tonic-gate * structures to include the address of the individual pre-write 2326*0Sstevel@tonic-gate * areas 2327*0Sstevel@tonic-gate */ 2328*0Sstevel@tonic-gate for (col = 0; (col < orig_ncol); ++col) { 2329*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 2330*0Sstevel@tonic-gate mdname_t *colnp = cp->colnamep; 2331*0Sstevel@tonic-gate mr_column_t *mdc = &mr->un_column[col]; 2332*0Sstevel@tonic-gate diskaddr_t size; 2333*0Sstevel@tonic-gate 2334*0Sstevel@tonic-gate /* get size */ 2335*0Sstevel@tonic-gate if ((size = metagetsize(colnp, ep)) == MD_DISKADDR_ERROR) 2336*0Sstevel@tonic-gate goto out; 2337*0Sstevel@tonic-gate 2338*0Sstevel@tonic-gate /* adjust start and size by prewrite */ 2339*0Sstevel@tonic-gate mdc->un_orig_pwstart = mdc->un_orig_devstart; 2340*0Sstevel@tonic-gate mdc->un_orig_devstart += mr->un_pwsize; 2341*0Sstevel@tonic-gate mdc->un_pwstart = mdc->un_orig_pwstart; 2342*0Sstevel@tonic-gate mdc->un_devstart = mdc->un_orig_devstart; 2343*0Sstevel@tonic-gate 2344*0Sstevel@tonic-gate assert(size >= mdc->un_orig_devstart); 2345*0Sstevel@tonic-gate size -= mdc->un_orig_devstart; 2346*0Sstevel@tonic-gate 2347*0Sstevel@tonic-gate /* make sure we still have something left */ 2348*0Sstevel@tonic-gate assert(size >= column_size); 2349*0Sstevel@tonic-gate } 2350*0Sstevel@tonic-gate 2351*0Sstevel@tonic-gate /* do concat cols */ 2352*0Sstevel@tonic-gate mr->un_totalcolumncnt = mr->un_origcolumncnt; 2353*0Sstevel@tonic-gate assert(col == mr->un_origcolumncnt); 2354*0Sstevel@tonic-gate for (col = orig_ncol; (col < ncol); ++col) { 2355*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 2356*0Sstevel@tonic-gate mdname_t *colnp = cp->colnamep; 2357*0Sstevel@tonic-gate mr_column_t *mdc = &mr->un_column[col]; 2358*0Sstevel@tonic-gate 2359*0Sstevel@tonic-gate /* attach column */ 2360*0Sstevel@tonic-gate if (attach_raid_col(sp, raidnp, mr, mdc, colnp, 2361*0Sstevel@tonic-gate cp->state, &keynlp, options, ep) != 0) { 2362*0Sstevel@tonic-gate goto out; 2363*0Sstevel@tonic-gate } 2364*0Sstevel@tonic-gate } 2365*0Sstevel@tonic-gate assert(mr->un_totalcolumncnt == ncol); 2366*0Sstevel@tonic-gate 2367*0Sstevel@tonic-gate /* fill in the size of the raid */ 2368*0Sstevel@tonic-gate if (options & MDCMD_UPDATE) { 2369*0Sstevel@tonic-gate raidp->common.size = mr->c.un_total_blocks; 2370*0Sstevel@tonic-gate raidp->column_size = mr->un_segsize * mr->un_segsincolumn; 2371*0Sstevel@tonic-gate } 2372*0Sstevel@tonic-gate 2373*0Sstevel@tonic-gate /* if we're not doing anything, return success */ 2374*0Sstevel@tonic-gate if (! (options & MDCMD_DOIT)) { 2375*0Sstevel@tonic-gate rval = 0; /* success */ 2376*0Sstevel@tonic-gate goto out; 2377*0Sstevel@tonic-gate } 2378*0Sstevel@tonic-gate 2379*0Sstevel@tonic-gate if ((mr->un_state & RUS_OKAY) && 2380*0Sstevel@tonic-gate (meta_raid_valid(raidp, mr) != 0)) { 2381*0Sstevel@tonic-gate (void) mderror(ep, MDE_RAID_INVALID, raidnp->cname); 2382*0Sstevel@tonic-gate goto out; 2383*0Sstevel@tonic-gate } 2384*0Sstevel@tonic-gate 2385*0Sstevel@tonic-gate /* create raid */ 2386*0Sstevel@tonic-gate (void) memset(&set_params, 0, sizeof (set_params)); 2387*0Sstevel@tonic-gate /* did the user tell us to generate a large device? */ 2388*0Sstevel@tonic-gate if (create_flag == MD_CRO_64BIT) { 2389*0Sstevel@tonic-gate mr->c.un_revision = MD_64BIT_META_DEV; 2390*0Sstevel@tonic-gate set_params.options = MD_CRO_64BIT; 2391*0Sstevel@tonic-gate } else { 2392*0Sstevel@tonic-gate mr->c.un_revision = MD_32BIT_META_DEV; 2393*0Sstevel@tonic-gate set_params.options = MD_CRO_32BIT; 2394*0Sstevel@tonic-gate } 2395*0Sstevel@tonic-gate set_params.mnum = MD_SID(mr); 2396*0Sstevel@tonic-gate set_params.size = mr->c.un_size; 2397*0Sstevel@tonic-gate set_params.mdp = (uintptr_t)mr; 2398*0Sstevel@tonic-gate MD_SETDRIVERNAME(&set_params, MD_RAID, MD_MIN2SET(set_params.mnum)); 2399*0Sstevel@tonic-gate if (metaioctl(MD_IOCSET, &set_params, &set_params.mde, 2400*0Sstevel@tonic-gate raidnp->cname) != 0) { 2401*0Sstevel@tonic-gate (void) mdstealerror(ep, &set_params.mde); 2402*0Sstevel@tonic-gate goto out; 2403*0Sstevel@tonic-gate } 2404*0Sstevel@tonic-gate rval = 0; /* success */ 2405*0Sstevel@tonic-gate 2406*0Sstevel@tonic-gate /* cleanup, return success */ 2407*0Sstevel@tonic-gate out: 2408*0Sstevel@tonic-gate Free(mr); 2409*0Sstevel@tonic-gate if (rval != 0) { 2410*0Sstevel@tonic-gate (void) del_key_names(sp, keynlp, NULL); 2411*0Sstevel@tonic-gate } 2412*0Sstevel@tonic-gate metafreenamelist(keynlp); 2413*0Sstevel@tonic-gate if ((rval == 0) && (options & MDCMD_DOIT)) { 2414*0Sstevel@tonic-gate if (invalidate_columns(sp, raidnp, ep) != 0) 2415*0Sstevel@tonic-gate rval = -1; 2416*0Sstevel@tonic-gate meta_invalidate_name(raidnp); 2417*0Sstevel@tonic-gate } 2418*0Sstevel@tonic-gate return (rval); 2419*0Sstevel@tonic-gate } 2420*0Sstevel@tonic-gate 2421*0Sstevel@tonic-gate /* 2422*0Sstevel@tonic-gate * initialize raid 2423*0Sstevel@tonic-gate * NOTE: this functions is metainit(1m)'s command line parser! 2424*0Sstevel@tonic-gate */ 2425*0Sstevel@tonic-gate int 2426*0Sstevel@tonic-gate meta_init_raid( 2427*0Sstevel@tonic-gate mdsetname_t **spp, 2428*0Sstevel@tonic-gate int argc, 2429*0Sstevel@tonic-gate char *argv[], 2430*0Sstevel@tonic-gate mdcmdopts_t options, 2431*0Sstevel@tonic-gate md_error_t *ep 2432*0Sstevel@tonic-gate ) 2433*0Sstevel@tonic-gate { 2434*0Sstevel@tonic-gate char *uname = argv[0]; 2435*0Sstevel@tonic-gate mdname_t *raidnp = NULL; 2436*0Sstevel@tonic-gate int old_optind; 2437*0Sstevel@tonic-gate int c; 2438*0Sstevel@tonic-gate md_raid_t *raidp = NULL; 2439*0Sstevel@tonic-gate uint_t ncol, col; 2440*0Sstevel@tonic-gate int rval = -1; 2441*0Sstevel@tonic-gate md_set_desc *sd; 2442*0Sstevel@tonic-gate 2443*0Sstevel@tonic-gate /* get raid name */ 2444*0Sstevel@tonic-gate assert(argc > 0); 2445*0Sstevel@tonic-gate if (argc < 1) 2446*0Sstevel@tonic-gate goto syntax; 2447*0Sstevel@tonic-gate if ((raidnp = metaname(spp, uname, ep)) == NULL) 2448*0Sstevel@tonic-gate goto out; 2449*0Sstevel@tonic-gate assert(*spp != NULL); 2450*0Sstevel@tonic-gate 2451*0Sstevel@tonic-gate /* 2452*0Sstevel@tonic-gate * Raid metadevice not allowed on multi-node diskset. 2453*0Sstevel@tonic-gate */ 2454*0Sstevel@tonic-gate if (! metaislocalset(*spp)) { 2455*0Sstevel@tonic-gate if ((sd = metaget_setdesc(*spp, ep)) == NULL) 2456*0Sstevel@tonic-gate goto out; 2457*0Sstevel@tonic-gate if (MD_MNSET_DESC(sd)) { 2458*0Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_MNSET_NORAID, uname, 2459*0Sstevel@tonic-gate argc, argv); 2460*0Sstevel@tonic-gate goto out; 2461*0Sstevel@tonic-gate } 2462*0Sstevel@tonic-gate } 2463*0Sstevel@tonic-gate 2464*0Sstevel@tonic-gate uname = raidnp->cname; 2465*0Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0) 2466*0Sstevel@tonic-gate goto out; 2467*0Sstevel@tonic-gate 2468*0Sstevel@tonic-gate if (!(options & MDCMD_NOLOCK)) { 2469*0Sstevel@tonic-gate /* grab set lock */ 2470*0Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep) != 0) 2471*0Sstevel@tonic-gate goto out; 2472*0Sstevel@tonic-gate 2473*0Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0) 2474*0Sstevel@tonic-gate goto out; 2475*0Sstevel@tonic-gate } 2476*0Sstevel@tonic-gate 2477*0Sstevel@tonic-gate /* see if it exists already */ 2478*0Sstevel@tonic-gate if (metagetmiscname(raidnp, ep) != NULL) { 2479*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP, 2480*0Sstevel@tonic-gate meta_getminor(raidnp->dev), uname); 2481*0Sstevel@tonic-gate goto out; 2482*0Sstevel@tonic-gate } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) { 2483*0Sstevel@tonic-gate goto out; 2484*0Sstevel@tonic-gate } else { 2485*0Sstevel@tonic-gate mdclrerror(ep); 2486*0Sstevel@tonic-gate } 2487*0Sstevel@tonic-gate --argc, ++argv; 2488*0Sstevel@tonic-gate 2489*0Sstevel@tonic-gate /* grab -r */ 2490*0Sstevel@tonic-gate if ((argc < 1) || (strcmp(argv[0], "-r") != 0)) 2491*0Sstevel@tonic-gate goto syntax; 2492*0Sstevel@tonic-gate --argc, ++argv; 2493*0Sstevel@tonic-gate 2494*0Sstevel@tonic-gate /* parse general options */ 2495*0Sstevel@tonic-gate optind = 0; 2496*0Sstevel@tonic-gate opterr = 0; 2497*0Sstevel@tonic-gate if (getopt(argc, argv, "") != -1) 2498*0Sstevel@tonic-gate goto options; 2499*0Sstevel@tonic-gate 2500*0Sstevel@tonic-gate /* allocate raid */ 2501*0Sstevel@tonic-gate raidp = Zalloc(sizeof (*raidp)); 2502*0Sstevel@tonic-gate 2503*0Sstevel@tonic-gate /* setup common */ 2504*0Sstevel@tonic-gate raidp->common.namep = raidnp; 2505*0Sstevel@tonic-gate raidp->common.type = MD_METARAID; 2506*0Sstevel@tonic-gate raidp->state = RUS_INIT; 2507*0Sstevel@tonic-gate 2508*0Sstevel@tonic-gate /* allocate and parse cols */ 2509*0Sstevel@tonic-gate for (ncol = 0; ((ncol < argc) && (argv[ncol][0] != '-')); ++ncol) 2510*0Sstevel@tonic-gate ; 2511*0Sstevel@tonic-gate raidp->cols.cols_len = ncol; 2512*0Sstevel@tonic-gate if (ncol != 0) { 2513*0Sstevel@tonic-gate raidp->cols.cols_val = 2514*0Sstevel@tonic-gate Zalloc(ncol * sizeof (*raidp->cols.cols_val)); 2515*0Sstevel@tonic-gate } 2516*0Sstevel@tonic-gate for (col = 0; ((argc > 0) && (col < ncol)); ++col) { 2517*0Sstevel@tonic-gate md_raidcol_t *mdc = &raidp->cols.cols_val[col]; 2518*0Sstevel@tonic-gate mdname_t *colnp; 2519*0Sstevel@tonic-gate 2520*0Sstevel@tonic-gate /* parse column name */ 2521*0Sstevel@tonic-gate if ((colnp = metaname(spp, argv[0], ep)) == NULL) 2522*0Sstevel@tonic-gate goto out; 2523*0Sstevel@tonic-gate /* check for soft partitions */ 2524*0Sstevel@tonic-gate if (meta_sp_issp(*spp, colnp, ep) != 0) { 2525*0Sstevel@tonic-gate /* check disks */ 2526*0Sstevel@tonic-gate if (metachkcomp(colnp, ep) != 0) 2527*0Sstevel@tonic-gate goto out; 2528*0Sstevel@tonic-gate } 2529*0Sstevel@tonic-gate mdc->colnamep = colnp; 2530*0Sstevel@tonic-gate --argc, ++argv; 2531*0Sstevel@tonic-gate } 2532*0Sstevel@tonic-gate 2533*0Sstevel@tonic-gate /* parse raid options */ 2534*0Sstevel@tonic-gate old_optind = optind = 0; 2535*0Sstevel@tonic-gate opterr = 0; 2536*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "h:i:ko:w:")) != -1) { 2537*0Sstevel@tonic-gate switch (c) { 2538*0Sstevel@tonic-gate case 'h': 2539*0Sstevel@tonic-gate if ((raidp->hspnamep = metahspname(spp, optarg, 2540*0Sstevel@tonic-gate ep)) == NULL) { 2541*0Sstevel@tonic-gate goto out; 2542*0Sstevel@tonic-gate } 2543*0Sstevel@tonic-gate break; 2544*0Sstevel@tonic-gate 2545*0Sstevel@tonic-gate case 'i': 2546*0Sstevel@tonic-gate if (parse_interlace(uname, optarg, &raidp->interlace, 2547*0Sstevel@tonic-gate ep) != 0) { 2548*0Sstevel@tonic-gate goto out; 2549*0Sstevel@tonic-gate } 2550*0Sstevel@tonic-gate if (meta_raid_check_interlace(raidp->interlace, 2551*0Sstevel@tonic-gate uname, ep)) 2552*0Sstevel@tonic-gate goto out; 2553*0Sstevel@tonic-gate break; 2554*0Sstevel@tonic-gate 2555*0Sstevel@tonic-gate case 'k': 2556*0Sstevel@tonic-gate raidp->state = RUS_OKAY; 2557*0Sstevel@tonic-gate break; 2558*0Sstevel@tonic-gate 2559*0Sstevel@tonic-gate case 'o': 2560*0Sstevel@tonic-gate if ((sscanf(optarg, "%u", &raidp->orig_ncol) != 1) || 2561*0Sstevel@tonic-gate ((int)raidp->orig_ncol < 0)) { 2562*0Sstevel@tonic-gate goto syntax; 2563*0Sstevel@tonic-gate } 2564*0Sstevel@tonic-gate if ((raidp->orig_ncol < MD_RAID_MIN) || 2565*0Sstevel@tonic-gate (raidp->orig_ncol > ncol)) { 2566*0Sstevel@tonic-gate rval = mderror(ep, MDE_BAD_ORIG_NCOL, uname); 2567*0Sstevel@tonic-gate goto out; 2568*0Sstevel@tonic-gate } 2569*0Sstevel@tonic-gate break; 2570*0Sstevel@tonic-gate case 'w': 2571*0Sstevel@tonic-gate if ((sscanf(optarg, "%d", &raidp->pw_count) != 1) || 2572*0Sstevel@tonic-gate ((int)raidp->pw_count < 0)) 2573*0Sstevel@tonic-gate goto syntax; 2574*0Sstevel@tonic-gate if (((int)raidp->pw_count < PWCNT_MIN) || 2575*0Sstevel@tonic-gate ((int)raidp->pw_count > PWCNT_MAX)) { 2576*0Sstevel@tonic-gate rval = mderror(ep, MDE_RAID_BAD_PW_CNT, uname); 2577*0Sstevel@tonic-gate goto out; 2578*0Sstevel@tonic-gate } 2579*0Sstevel@tonic-gate break; 2580*0Sstevel@tonic-gate default: 2581*0Sstevel@tonic-gate argc += old_optind; 2582*0Sstevel@tonic-gate argv -= old_optind; 2583*0Sstevel@tonic-gate goto options; 2584*0Sstevel@tonic-gate } 2585*0Sstevel@tonic-gate old_optind = optind; 2586*0Sstevel@tonic-gate } 2587*0Sstevel@tonic-gate argc -= optind; 2588*0Sstevel@tonic-gate argv += optind; 2589*0Sstevel@tonic-gate 2590*0Sstevel@tonic-gate /* we should be at the end */ 2591*0Sstevel@tonic-gate if (argc != 0) 2592*0Sstevel@tonic-gate goto syntax; 2593*0Sstevel@tonic-gate 2594*0Sstevel@tonic-gate /* default to all original columns */ 2595*0Sstevel@tonic-gate if (raidp->orig_ncol == 0) 2596*0Sstevel@tonic-gate raidp->orig_ncol = ncol; 2597*0Sstevel@tonic-gate 2598*0Sstevel@tonic-gate /* create raid */ 2599*0Sstevel@tonic-gate if (meta_create_raid(*spp, raidp, options, ep) != 0) 2600*0Sstevel@tonic-gate goto out; 2601*0Sstevel@tonic-gate rval = 0; /* success */ 2602*0Sstevel@tonic-gate 2603*0Sstevel@tonic-gate /* let em know */ 2604*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 2605*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "%s: RAID is setup\n"), 2606*0Sstevel@tonic-gate uname); 2607*0Sstevel@tonic-gate (void) fflush(stdout); 2608*0Sstevel@tonic-gate } 2609*0Sstevel@tonic-gate goto out; 2610*0Sstevel@tonic-gate 2611*0Sstevel@tonic-gate /* syntax error */ 2612*0Sstevel@tonic-gate syntax: 2613*0Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_SYNTAX, uname, argc, argv); 2614*0Sstevel@tonic-gate goto out; 2615*0Sstevel@tonic-gate 2616*0Sstevel@tonic-gate /* options error */ 2617*0Sstevel@tonic-gate options: 2618*0Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_OPTION, uname, argc, argv); 2619*0Sstevel@tonic-gate goto out; 2620*0Sstevel@tonic-gate 2621*0Sstevel@tonic-gate /* cleanup, return error */ 2622*0Sstevel@tonic-gate out: 2623*0Sstevel@tonic-gate if (raidp != NULL) 2624*0Sstevel@tonic-gate meta_free_raid(raidp); 2625*0Sstevel@tonic-gate return (rval); 2626*0Sstevel@tonic-gate } 2627*0Sstevel@tonic-gate 2628*0Sstevel@tonic-gate /* 2629*0Sstevel@tonic-gate * reset RAIDs 2630*0Sstevel@tonic-gate */ 2631*0Sstevel@tonic-gate int 2632*0Sstevel@tonic-gate meta_raid_reset( 2633*0Sstevel@tonic-gate mdsetname_t *sp, 2634*0Sstevel@tonic-gate mdname_t *raidnp, 2635*0Sstevel@tonic-gate mdcmdopts_t options, 2636*0Sstevel@tonic-gate md_error_t *ep 2637*0Sstevel@tonic-gate ) 2638*0Sstevel@tonic-gate { 2639*0Sstevel@tonic-gate md_raid_t *raidp; 2640*0Sstevel@tonic-gate int rval = -1; 2641*0Sstevel@tonic-gate int col; 2642*0Sstevel@tonic-gate 2643*0Sstevel@tonic-gate /* should have same set */ 2644*0Sstevel@tonic-gate assert(sp != NULL); 2645*0Sstevel@tonic-gate assert((raidnp == NULL) || 2646*0Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev)))); 2647*0Sstevel@tonic-gate 2648*0Sstevel@tonic-gate /* reset all raids */ 2649*0Sstevel@tonic-gate if (raidnp == NULL) { 2650*0Sstevel@tonic-gate mdnamelist_t *raidnlp = NULL; 2651*0Sstevel@tonic-gate mdnamelist_t *p; 2652*0Sstevel@tonic-gate 2653*0Sstevel@tonic-gate /* for each raid */ 2654*0Sstevel@tonic-gate rval = 0; 2655*0Sstevel@tonic-gate if (meta_get_raid_names(sp, &raidnlp, 0, ep) < 0) 2656*0Sstevel@tonic-gate return (-1); 2657*0Sstevel@tonic-gate for (p = raidnlp; (p != NULL); p = p->next) { 2658*0Sstevel@tonic-gate /* reset RAID */ 2659*0Sstevel@tonic-gate raidnp = p->namep; 2660*0Sstevel@tonic-gate if (meta_raid_reset(sp, raidnp, options, ep) != 0) { 2661*0Sstevel@tonic-gate rval = -1; 2662*0Sstevel@tonic-gate break; 2663*0Sstevel@tonic-gate } 2664*0Sstevel@tonic-gate } 2665*0Sstevel@tonic-gate 2666*0Sstevel@tonic-gate /* cleanup, return success */ 2667*0Sstevel@tonic-gate metafreenamelist(raidnlp); 2668*0Sstevel@tonic-gate return (rval); 2669*0Sstevel@tonic-gate } 2670*0Sstevel@tonic-gate 2671*0Sstevel@tonic-gate /* check name */ 2672*0Sstevel@tonic-gate if (metachkmeta(raidnp, ep) != 0) 2673*0Sstevel@tonic-gate return (-1); 2674*0Sstevel@tonic-gate 2675*0Sstevel@tonic-gate /* get unit structure */ 2676*0Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, raidnp, ep)) == NULL) 2677*0Sstevel@tonic-gate return (-1); 2678*0Sstevel@tonic-gate 2679*0Sstevel@tonic-gate /* make sure nobody owns us */ 2680*0Sstevel@tonic-gate if (MD_HAS_PARENT(raidp->common.parent)) { 2681*0Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_USE, meta_getminor(raidnp->dev), 2682*0Sstevel@tonic-gate raidnp->cname)); 2683*0Sstevel@tonic-gate } 2684*0Sstevel@tonic-gate 2685*0Sstevel@tonic-gate /* clear subdevices cache */ 2686*0Sstevel@tonic-gate if (invalidate_columns(sp, raidnp, ep) != 0) 2687*0Sstevel@tonic-gate return (-1); 2688*0Sstevel@tonic-gate 2689*0Sstevel@tonic-gate /* clear metadevice */ 2690*0Sstevel@tonic-gate if (meta_reset(sp, raidnp, options, ep) != 0) 2691*0Sstevel@tonic-gate goto out; 2692*0Sstevel@tonic-gate rval = 0; /* success */ 2693*0Sstevel@tonic-gate 2694*0Sstevel@tonic-gate /* let em know */ 2695*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 2696*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "%s: RAID is cleared\n"), 2697*0Sstevel@tonic-gate raidnp->cname); 2698*0Sstevel@tonic-gate (void) fflush(stdout); 2699*0Sstevel@tonic-gate } 2700*0Sstevel@tonic-gate 2701*0Sstevel@tonic-gate /* clear subdevices */ 2702*0Sstevel@tonic-gate if (! (options & MDCMD_RECURSE)) 2703*0Sstevel@tonic-gate goto out; 2704*0Sstevel@tonic-gate 2705*0Sstevel@tonic-gate for (col = 0; (col < raidp->cols.cols_len); ++col) { 2706*0Sstevel@tonic-gate md_raidcol_t *cp = &raidp->cols.cols_val[col]; 2707*0Sstevel@tonic-gate mdname_t *colnp = cp->colnamep; 2708*0Sstevel@tonic-gate 2709*0Sstevel@tonic-gate /* only recurse on metadevices */ 2710*0Sstevel@tonic-gate if (! metaismeta(colnp)) 2711*0Sstevel@tonic-gate continue; 2712*0Sstevel@tonic-gate 2713*0Sstevel@tonic-gate if (meta_reset_by_name(sp, colnp, options, ep) != 0) 2714*0Sstevel@tonic-gate rval = -1; 2715*0Sstevel@tonic-gate } 2716*0Sstevel@tonic-gate 2717*0Sstevel@tonic-gate /* cleanup, return success */ 2718*0Sstevel@tonic-gate out: 2719*0Sstevel@tonic-gate meta_invalidate_name(raidnp); 2720*0Sstevel@tonic-gate return (rval); 2721*0Sstevel@tonic-gate } 2722*0Sstevel@tonic-gate 2723*0Sstevel@tonic-gate /* 2724*0Sstevel@tonic-gate * reports TRUE if any RAID component is in error 2725*0Sstevel@tonic-gate */ 2726*0Sstevel@tonic-gate int 2727*0Sstevel@tonic-gate meta_raid_anycomp_is_err(mdsetname_t *sp, mdnamelist_t *raid_names) 2728*0Sstevel@tonic-gate { 2729*0Sstevel@tonic-gate mdnamelist_t *nlp; 2730*0Sstevel@tonic-gate md_error_t status = mdnullerror; 2731*0Sstevel@tonic-gate md_error_t *ep = &status; 2732*0Sstevel@tonic-gate int any_errs = FALSE; 2733*0Sstevel@tonic-gate 2734*0Sstevel@tonic-gate for (nlp = raid_names; nlp; nlp = nlp->next) { 2735*0Sstevel@tonic-gate md_raid_t *raidp; 2736*0Sstevel@tonic-gate 2737*0Sstevel@tonic-gate if ((raidp = meta_get_raid(sp, nlp->namep, ep)) == NULL) { 2738*0Sstevel@tonic-gate any_errs |= TRUE; 2739*0Sstevel@tonic-gate goto out; 2740*0Sstevel@tonic-gate } 2741*0Sstevel@tonic-gate if (raidp->state != RUS_OKAY && raidp->state != RUS_INIT) { 2742*0Sstevel@tonic-gate any_errs |= TRUE; 2743*0Sstevel@tonic-gate goto out; 2744*0Sstevel@tonic-gate } 2745*0Sstevel@tonic-gate } 2746*0Sstevel@tonic-gate out: 2747*0Sstevel@tonic-gate if (!mdisok(ep)) 2748*0Sstevel@tonic-gate mdclrerror(ep); 2749*0Sstevel@tonic-gate 2750*0Sstevel@tonic-gate return (any_errs); 2751*0Sstevel@tonic-gate } 2752*0Sstevel@tonic-gate /* 2753*0Sstevel@tonic-gate * regen parity on a raid 2754*0Sstevel@tonic-gate */ 2755*0Sstevel@tonic-gate int 2756*0Sstevel@tonic-gate meta_raid_regen_byname(mdsetname_t *sp, mdname_t *raidnp, diskaddr_t size, 2757*0Sstevel@tonic-gate md_error_t *ep) 2758*0Sstevel@tonic-gate { 2759*0Sstevel@tonic-gate char *miscname; 2760*0Sstevel@tonic-gate md_resync_ioctl_t ri; 2761*0Sstevel@tonic-gate 2762*0Sstevel@tonic-gate /* should have a set */ 2763*0Sstevel@tonic-gate assert(sp != NULL); 2764*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(raidnp->dev))); 2765*0Sstevel@tonic-gate 2766*0Sstevel@tonic-gate /* make sure we have a raid */ 2767*0Sstevel@tonic-gate if ((miscname = metagetmiscname(raidnp, ep)) == NULL) 2768*0Sstevel@tonic-gate return (-1); 2769*0Sstevel@tonic-gate if (strcmp(miscname, MD_RAID) != 0) { 2770*0Sstevel@tonic-gate return (mdmderror(ep, MDE_NOT_RAID, meta_getminor(raidnp->dev), 2771*0Sstevel@tonic-gate raidnp->cname)); 2772*0Sstevel@tonic-gate } 2773*0Sstevel@tonic-gate 2774*0Sstevel@tonic-gate /* start resync */ 2775*0Sstevel@tonic-gate (void) memset(&ri, 0, sizeof (ri)); 2776*0Sstevel@tonic-gate MD_SETDRIVERNAME(&ri, MD_RAID, sp->setno); 2777*0Sstevel@tonic-gate ri.ri_mnum = meta_getminor(raidnp->dev); 2778*0Sstevel@tonic-gate ri.ri_copysize = size; 2779*0Sstevel@tonic-gate if (metaioctl(MD_IOCSETREGEN, &ri, &ri.mde, raidnp->cname) != 0) 2780*0Sstevel@tonic-gate return (mdstealerror(ep, &ri.mde)); 2781*0Sstevel@tonic-gate 2782*0Sstevel@tonic-gate /* return success */ 2783*0Sstevel@tonic-gate return (0); 2784*0Sstevel@tonic-gate } 2785