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 2005 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 #include <sys/param.h> 30*0Sstevel@tonic-gate #include <sys/systm.h> 31*0Sstevel@tonic-gate #include <sys/conf.h> 32*0Sstevel@tonic-gate #include <sys/file.h> 33*0Sstevel@tonic-gate #include <sys/user.h> 34*0Sstevel@tonic-gate #include <sys/uio.h> 35*0Sstevel@tonic-gate #include <sys/t_lock.h> 36*0Sstevel@tonic-gate #include <sys/buf.h> 37*0Sstevel@tonic-gate #include <sys/dkio.h> 38*0Sstevel@tonic-gate #include <sys/vtoc.h> 39*0Sstevel@tonic-gate #include <sys/kmem.h> 40*0Sstevel@tonic-gate #include <vm/page.h> 41*0Sstevel@tonic-gate #include <sys/cmn_err.h> 42*0Sstevel@tonic-gate #include <sys/sysmacros.h> 43*0Sstevel@tonic-gate #include <sys/types.h> 44*0Sstevel@tonic-gate #include <sys/mkdev.h> 45*0Sstevel@tonic-gate #include <sys/stat.h> 46*0Sstevel@tonic-gate #include <sys/open.h> 47*0Sstevel@tonic-gate #include <sys/lvm/mdio.h> 48*0Sstevel@tonic-gate #include <sys/lvm/mdvar.h> 49*0Sstevel@tonic-gate #include <sys/lvm/md_stripe.h> 50*0Sstevel@tonic-gate #include <sys/lvm/md_convert.h> 51*0Sstevel@tonic-gate #include <sys/lvm/md_notify.h> 52*0Sstevel@tonic-gate #include <sys/modctl.h> 53*0Sstevel@tonic-gate #include <sys/ddi.h> 54*0Sstevel@tonic-gate #include <sys/sunddi.h> 55*0Sstevel@tonic-gate #include <sys/debug.h> 56*0Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h> 57*0Sstevel@tonic-gate #include <sys/sysevent/svm.h> 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate md_ops_t stripe_md_ops; 60*0Sstevel@tonic-gate #ifndef lint 61*0Sstevel@tonic-gate static char _depends_on[] = "drv/md"; 62*0Sstevel@tonic-gate static md_ops_t *md_interface_ops = &stripe_md_ops; 63*0Sstevel@tonic-gate #endif 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate extern unit_t md_nunits; 66*0Sstevel@tonic-gate extern set_t md_nsets; 67*0Sstevel@tonic-gate extern md_set_t md_set[]; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate extern kmutex_t md_mx; 70*0Sstevel@tonic-gate extern kcondvar_t md_cv; 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate extern int md_status; 73*0Sstevel@tonic-gate extern major_t md_major; 74*0Sstevel@tonic-gate extern mdq_anchor_t md_done_daemon; 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate static int md_stripe_mcs_buf_off; 77*0Sstevel@tonic-gate static kmem_cache_t *stripe_parent_cache = NULL; 78*0Sstevel@tonic-gate static kmem_cache_t *stripe_child_cache = NULL; 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate /*ARGSUSED1*/ 81*0Sstevel@tonic-gate static int 82*0Sstevel@tonic-gate stripe_parent_constructor(void *p, void *d1, int d2) 83*0Sstevel@tonic-gate { 84*0Sstevel@tonic-gate mutex_init(&((md_sps_t *)p)->ps_mx, 85*0Sstevel@tonic-gate NULL, MUTEX_DEFAULT, NULL); 86*0Sstevel@tonic-gate return (0); 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate static void 90*0Sstevel@tonic-gate stripe_parent_init(void *ps) 91*0Sstevel@tonic-gate { 92*0Sstevel@tonic-gate bzero(ps, offsetof(md_sps_t, ps_mx)); 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /*ARGSUSED1*/ 96*0Sstevel@tonic-gate static void 97*0Sstevel@tonic-gate stripe_parent_destructor(void *p, void *d) 98*0Sstevel@tonic-gate { 99*0Sstevel@tonic-gate mutex_destroy(&((md_sps_t *)p)->ps_mx); 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate /*ARGSUSED1*/ 103*0Sstevel@tonic-gate static int 104*0Sstevel@tonic-gate stripe_child_constructor(void *p, void *d1, int d2) 105*0Sstevel@tonic-gate { 106*0Sstevel@tonic-gate bioinit(&((md_scs_t *)p)->cs_buf); 107*0Sstevel@tonic-gate return (0); 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate static void 111*0Sstevel@tonic-gate stripe_child_init(md_scs_t *cs) 112*0Sstevel@tonic-gate { 113*0Sstevel@tonic-gate cs->cs_mdunit = 0; 114*0Sstevel@tonic-gate cs->cs_ps = NULL; 115*0Sstevel@tonic-gate cs->cs_comp = NULL; 116*0Sstevel@tonic-gate md_bioreset(&cs->cs_buf); 117*0Sstevel@tonic-gate } 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /*ARGSUSED1*/ 120*0Sstevel@tonic-gate static void 121*0Sstevel@tonic-gate stripe_child_destructor(void *p, void *d) 122*0Sstevel@tonic-gate { 123*0Sstevel@tonic-gate biofini(&((md_scs_t *)p)->cs_buf); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate /*ARGSUSED*/ 127*0Sstevel@tonic-gate static void 128*0Sstevel@tonic-gate stripe_run_queue(void *d) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate if (!(md_status & MD_GBL_DAEMONS_LIVE)) 131*0Sstevel@tonic-gate md_daemon(1, &md_done_daemon); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate static void 135*0Sstevel@tonic-gate stripe_close_all_devs(ms_unit_t *un, int md_cflags) 136*0Sstevel@tonic-gate { 137*0Sstevel@tonic-gate int row; 138*0Sstevel@tonic-gate int i; 139*0Sstevel@tonic-gate int c; 140*0Sstevel@tonic-gate struct ms_comp *mdcomp; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 143*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 144*0Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 145*0Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) { 146*0Sstevel@tonic-gate struct ms_comp *mdc; 147*0Sstevel@tonic-gate mdc = &mdcomp[c++]; 148*0Sstevel@tonic-gate if (md_cflags & MD_OFLG_PROBEDEV) { 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate /* 151*0Sstevel@tonic-gate * It is possible that the md_layered_open 152*0Sstevel@tonic-gate * failed because the stripe unit structure 153*0Sstevel@tonic-gate * contained a NODEV. In such a case since 154*0Sstevel@tonic-gate * there is nothing to open, there is nothing 155*0Sstevel@tonic-gate * to close. 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate if (mdc->un_dev == NODEV64) 158*0Sstevel@tonic-gate continue; 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate if ((md_cflags & MD_OFLG_PROBEDEV) && 161*0Sstevel@tonic-gate (mdc->un_mirror.ms_flags & MDM_S_PROBEOPEN)) { 162*0Sstevel@tonic-gate md_layered_close(mdc->un_dev, 163*0Sstevel@tonic-gate md_cflags); 164*0Sstevel@tonic-gate mdc->un_mirror.ms_flags &= 165*0Sstevel@tonic-gate ~MDM_S_PROBEOPEN; 166*0Sstevel@tonic-gate } else if (mdc->un_mirror.ms_flags & MDM_S_ISOPEN) { 167*0Sstevel@tonic-gate md_layered_close(mdc->un_dev, md_cflags); 168*0Sstevel@tonic-gate mdc->un_mirror.ms_flags &= ~MDM_S_ISOPEN; 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate static int 175*0Sstevel@tonic-gate stripe_open_all_devs(ms_unit_t *un, int md_oflags) 176*0Sstevel@tonic-gate { 177*0Sstevel@tonic-gate minor_t mnum = MD_SID(un); 178*0Sstevel@tonic-gate int row; 179*0Sstevel@tonic-gate int i; 180*0Sstevel@tonic-gate int c; 181*0Sstevel@tonic-gate struct ms_comp *mdcomp; 182*0Sstevel@tonic-gate int err; 183*0Sstevel@tonic-gate int cont_on_errors = (md_oflags & MD_OFLG_CONT_ERRS); 184*0Sstevel@tonic-gate int probe_err_cnt = 0; 185*0Sstevel@tonic-gate int total_comp_cnt = 0; 186*0Sstevel@tonic-gate set_t setno = MD_MIN2SET(MD_SID(un)); 187*0Sstevel@tonic-gate side_t side = mddb_getsidenum(setno); 188*0Sstevel@tonic-gate mdkey_t key; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate /* 193*0Sstevel@tonic-gate * For a probe call, if any component of a stripe or a concat 194*0Sstevel@tonic-gate * can be opened, it is considered to be a success. The total number 195*0Sstevel@tonic-gate * of components in a stripe are computed prior to starting a probe. 196*0Sstevel@tonic-gate * This number is then compared against the number of components 197*0Sstevel@tonic-gate * that could be be successfully opened. If none of the components 198*0Sstevel@tonic-gate * in a stripe can be opened, only then an ENXIO is returned for a 199*0Sstevel@tonic-gate * probe type open. 200*0Sstevel@tonic-gate */ 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 203*0Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate if (md_oflags & MD_OFLG_PROBEDEV) 206*0Sstevel@tonic-gate total_comp_cnt += mdr->un_ncomp; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) { 209*0Sstevel@tonic-gate struct ms_comp *mdc; 210*0Sstevel@tonic-gate md_dev64_t tmpdev; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate mdc = &mdcomp[c++]; 213*0Sstevel@tonic-gate tmpdev = mdc->un_dev; 214*0Sstevel@tonic-gate /* 215*0Sstevel@tonic-gate * Do the open by device id 216*0Sstevel@tonic-gate * Check if this comp is hotspared and 217*0Sstevel@tonic-gate * if it is then use the key for hotspare. 218*0Sstevel@tonic-gate * MN disksets don't use devids, so we better don't use 219*0Sstevel@tonic-gate * md_devid_found/md_resolve_bydevid there. Rather do, 220*0Sstevel@tonic-gate * what's done in stripe_build_incore() 221*0Sstevel@tonic-gate */ 222*0Sstevel@tonic-gate if (MD_MNSET_SETNO(setno)) { 223*0Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) { 224*0Sstevel@tonic-gate (void) md_hot_spare_ifc(HS_MKDEV, 0, 0, 225*0Sstevel@tonic-gate 0, &mdc->un_mirror.ms_hs_id, NULL, 226*0Sstevel@tonic-gate &tmpdev, NULL); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate } else { 229*0Sstevel@tonic-gate key = mdc->un_mirror.ms_hs_id ? 230*0Sstevel@tonic-gate mdc->un_mirror.ms_hs_key : mdc->un_key; 231*0Sstevel@tonic-gate if ((md_getmajor(tmpdev) != md_major) && 232*0Sstevel@tonic-gate md_devid_found(setno, side, key) == 1) { 233*0Sstevel@tonic-gate tmpdev = md_resolve_bydevid(mnum, 234*0Sstevel@tonic-gate tmpdev, key); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate /* 239*0Sstevel@tonic-gate * For a submirror, we only want to open those devices 240*0Sstevel@tonic-gate * that are not errored. If the device is errored then 241*0Sstevel@tonic-gate * then there is no reason to open it and leaving it 242*0Sstevel@tonic-gate * closed allows the RCM/DR code to work so that the 243*0Sstevel@tonic-gate * errored device can be replaced. 244*0Sstevel@tonic-gate */ 245*0Sstevel@tonic-gate if ((md_oflags & MD_OFLG_PROBEDEV) || 246*0Sstevel@tonic-gate ! (mdc->un_mirror.ms_state & CS_ERRED)) { 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate err = md_layered_open(mnum, &tmpdev, md_oflags); 249*0Sstevel@tonic-gate } else { 250*0Sstevel@tonic-gate err = ENXIO; 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * Only set the un_dev if the tmpdev != NODEV64. If 255*0Sstevel@tonic-gate * it is NODEV64 then the md_layered_open() will have 256*0Sstevel@tonic-gate * failed in some manner. 257*0Sstevel@tonic-gate */ 258*0Sstevel@tonic-gate if (tmpdev != NODEV64) 259*0Sstevel@tonic-gate mdc->un_dev = tmpdev; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate if (err) { 262*0Sstevel@tonic-gate if (!cont_on_errors) { 263*0Sstevel@tonic-gate stripe_close_all_devs(un, md_oflags); 264*0Sstevel@tonic-gate return (ENXIO); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate if (md_oflags & MD_OFLG_PROBEDEV) 268*0Sstevel@tonic-gate probe_err_cnt++; 269*0Sstevel@tonic-gate } else { 270*0Sstevel@tonic-gate if (md_oflags & MD_OFLG_PROBEDEV) { 271*0Sstevel@tonic-gate mdc->un_mirror.ms_flags |= 272*0Sstevel@tonic-gate MDM_S_PROBEOPEN; 273*0Sstevel@tonic-gate } else 274*0Sstevel@tonic-gate mdc->un_mirror.ms_flags |= MDM_S_ISOPEN; 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* If every component in a stripe could not be opened fail */ 280*0Sstevel@tonic-gate if ((md_oflags & MD_OFLG_PROBEDEV) && 281*0Sstevel@tonic-gate (probe_err_cnt == total_comp_cnt)) 282*0Sstevel@tonic-gate return (ENXIO); 283*0Sstevel@tonic-gate else 284*0Sstevel@tonic-gate return (0); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate int 288*0Sstevel@tonic-gate stripe_build_incore(void *p, int snarfing) 289*0Sstevel@tonic-gate { 290*0Sstevel@tonic-gate ms_unit_t *un = (ms_unit_t *)p; 291*0Sstevel@tonic-gate struct ms_comp *mdcomp; 292*0Sstevel@tonic-gate minor_t mnum; 293*0Sstevel@tonic-gate int row; 294*0Sstevel@tonic-gate int i; 295*0Sstevel@tonic-gate int c; 296*0Sstevel@tonic-gate int ncomps; 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate mnum = MD_SID(un); 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate if (MD_UNIT(mnum) != NULL) 301*0Sstevel@tonic-gate return (0); 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate MD_STATUS(un) = 0; 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate /* 306*0Sstevel@tonic-gate * Reset all the is_open flags, these are probably set 307*0Sstevel@tonic-gate * cause they just came out of the database. 308*0Sstevel@tonic-gate */ 309*0Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate ncomps = 0; 312*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 313*0Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 314*0Sstevel@tonic-gate ncomps += mdr->un_ncomp; 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 318*0Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 319*0Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) { 320*0Sstevel@tonic-gate struct ms_comp *mdc; 321*0Sstevel@tonic-gate set_t setno; 322*0Sstevel@tonic-gate md_dev64_t tmpdev; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate mdc = &mdcomp[c++]; 325*0Sstevel@tonic-gate mdc->un_mirror.ms_flags &= 326*0Sstevel@tonic-gate ~(MDM_S_ISOPEN | MDM_S_IOERR | MDM_S_RS_TRIED); 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate if (!snarfing) 329*0Sstevel@tonic-gate continue; 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate tmpdev = md_getdevnum(setno, mddb_getsidenum(setno), 334*0Sstevel@tonic-gate mdc->un_key, MD_NOTRUST_DEVT); 335*0Sstevel@tonic-gate mdc->un_dev = tmpdev; 336*0Sstevel@tonic-gate /* 337*0Sstevel@tonic-gate * Check for hotspares. If the hotspares haven't been 338*0Sstevel@tonic-gate * snarfed yet, stripe_open_all_devs() will do the 339*0Sstevel@tonic-gate * remapping of the dev's later. 340*0Sstevel@tonic-gate */ 341*0Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) { 342*0Sstevel@tonic-gate mdc->un_mirror.ms_orig_dev = mdc->un_dev; 343*0Sstevel@tonic-gate (void) md_hot_spare_ifc(HS_MKDEV, 0, 0, 344*0Sstevel@tonic-gate 0, &mdc->un_mirror.ms_hs_id, NULL, 345*0Sstevel@tonic-gate &tmpdev, NULL); 346*0Sstevel@tonic-gate mdc->un_dev = tmpdev; 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate MD_UNIT(mnum) = un; 352*0Sstevel@tonic-gate return (0); 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate void 356*0Sstevel@tonic-gate reset_stripe(ms_unit_t *un, minor_t mnum, int removing) 357*0Sstevel@tonic-gate { 358*0Sstevel@tonic-gate ms_comp_t *mdcomp; 359*0Sstevel@tonic-gate struct ms_row *mdr; 360*0Sstevel@tonic-gate int i, c; 361*0Sstevel@tonic-gate int row; 362*0Sstevel@tonic-gate int nsv; 363*0Sstevel@tonic-gate int isv; 364*0Sstevel@tonic-gate sv_dev_t *sv; 365*0Sstevel@tonic-gate mddb_recid_t *recids; 366*0Sstevel@tonic-gate mddb_recid_t vtoc_id; 367*0Sstevel@tonic-gate int rid = 0; 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate md_destroy_unit_incore(mnum, &stripe_md_ops); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gate MD_UNIT(mnum) = NULL; 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate if (!removing) 374*0Sstevel@tonic-gate return; 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate nsv = 0; 377*0Sstevel@tonic-gate /* Count the number of devices */ 378*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 379*0Sstevel@tonic-gate mdr = &un->un_row[row]; 380*0Sstevel@tonic-gate nsv += mdr->un_ncomp; 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate sv = (sv_dev_t *)kmem_alloc(sizeof (sv_dev_t) * nsv, KM_SLEEP); 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * allocate recids array. since we may have to commit 386*0Sstevel@tonic-gate * underlying soft partition records, we need an array 387*0Sstevel@tonic-gate * of size: total number of components in stripe + 3 388*0Sstevel@tonic-gate * (one for the stripe itself, one for the hotspare, one 389*0Sstevel@tonic-gate * for the end marker). 390*0Sstevel@tonic-gate */ 391*0Sstevel@tonic-gate recids = kmem_alloc(sizeof (mddb_recid_t) * (nsv + 3), KM_SLEEP); 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate /* 394*0Sstevel@tonic-gate * Save the md_dev64_t's and driver nm indexes. 395*0Sstevel@tonic-gate * Because after the mddb_deleterec() we will 396*0Sstevel@tonic-gate * not be able to access the unit structure. 397*0Sstevel@tonic-gate * 398*0Sstevel@tonic-gate * NOTE: Deleting the names before deleting the 399*0Sstevel@tonic-gate * unit structure would cause problems if 400*0Sstevel@tonic-gate * the machine crashed in between the two. 401*0Sstevel@tonic-gate */ 402*0Sstevel@tonic-gate isv = 0; 403*0Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 406*0Sstevel@tonic-gate mdr = &un->un_row[row]; 407*0Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) { 408*0Sstevel@tonic-gate struct ms_comp *mdc; 409*0Sstevel@tonic-gate md_dev64_t child_dev; 410*0Sstevel@tonic-gate md_unit_t *child_un; 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate mdc = &mdcomp[c++]; 413*0Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) { 414*0Sstevel@tonic-gate mdkey_t hs_key; 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate hs_key = mdc->un_mirror.ms_hs_key; 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate mdc->un_dev = mdc->un_mirror.ms_orig_dev; 419*0Sstevel@tonic-gate mdc->un_start_block = 420*0Sstevel@tonic-gate mdc->un_mirror.ms_orig_blk; 421*0Sstevel@tonic-gate mdc->un_mirror.ms_hs_id = 0; 422*0Sstevel@tonic-gate mdc->un_mirror.ms_hs_key = 0; 423*0Sstevel@tonic-gate mdc->un_mirror.ms_orig_dev = 0; 424*0Sstevel@tonic-gate recids[0] = 0; 425*0Sstevel@tonic-gate recids[1] = 0; /* recids[1] filled in below */ 426*0Sstevel@tonic-gate recids[2] = 0; 427*0Sstevel@tonic-gate (void) md_hot_spare_ifc(HS_FREE, un->un_hsp_id, 428*0Sstevel@tonic-gate 0, 0, &recids[0], &hs_key, NULL, NULL); 429*0Sstevel@tonic-gate mddb_commitrecs_wrapper(recids); 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate /* 433*0Sstevel@tonic-gate * check if we've got metadevice below us and 434*0Sstevel@tonic-gate * deparent it if we do. 435*0Sstevel@tonic-gate * NOTE: currently soft partitions are the 436*0Sstevel@tonic-gate * the only metadevices stripes can be 437*0Sstevel@tonic-gate * built on top of. 438*0Sstevel@tonic-gate */ 439*0Sstevel@tonic-gate child_dev = mdc->un_dev; 440*0Sstevel@tonic-gate if (md_getmajor(child_dev) == md_major) { 441*0Sstevel@tonic-gate child_un = MD_UNIT(md_getminor(child_dev)); 442*0Sstevel@tonic-gate md_reset_parent(child_dev); 443*0Sstevel@tonic-gate recids[rid++] = MD_RECID(child_un); 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate sv[isv].setno = MD_MIN2SET(mnum); 447*0Sstevel@tonic-gate sv[isv++].key = mdc->un_key; 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate recids[rid++] = un->c.un_record_id; 452*0Sstevel@tonic-gate recids[rid] = 0; /* filled in below */ 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate /* 455*0Sstevel@tonic-gate * Decrement the HSP reference count and 456*0Sstevel@tonic-gate * remove the knowledge of the HSP from the unit struct. 457*0Sstevel@tonic-gate * This is done atomically to remove a window. 458*0Sstevel@tonic-gate */ 459*0Sstevel@tonic-gate if (un->un_hsp_id != -1) { 460*0Sstevel@tonic-gate (void) md_hot_spare_ifc(HSP_DECREF, un->un_hsp_id, 0, 0, 461*0Sstevel@tonic-gate &recids[rid++], NULL, NULL, NULL); 462*0Sstevel@tonic-gate un->un_hsp_id = -1; 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* set end marker and commit records */ 466*0Sstevel@tonic-gate recids[rid] = 0; 467*0Sstevel@tonic-gate mddb_commitrecs_wrapper(recids); 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate vtoc_id = un->c.un_vtoc_id; 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate /* Remove the unit structure */ 472*0Sstevel@tonic-gate mddb_deleterec_wrapper(un->c.un_record_id); 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate /* Remove the vtoc, if present */ 475*0Sstevel@tonic-gate if (vtoc_id) 476*0Sstevel@tonic-gate mddb_deleterec_wrapper(vtoc_id); 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_DELETE, SVM_TAG_METADEVICE, 479*0Sstevel@tonic-gate MD_MIN2SET(mnum), MD_MIN2UNIT(mnum)); 480*0Sstevel@tonic-gate md_rem_names(sv, nsv); 481*0Sstevel@tonic-gate kmem_free(sv, sizeof (sv_dev_t) * nsv); 482*0Sstevel@tonic-gate kmem_free(recids, sizeof (mddb_recid_t) * (nsv + 3)); 483*0Sstevel@tonic-gate } 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate static void 486*0Sstevel@tonic-gate stripe_error(md_sps_t *ps) 487*0Sstevel@tonic-gate { 488*0Sstevel@tonic-gate struct buf *pb = ps->ps_bp; 489*0Sstevel@tonic-gate mdi_unit_t *ui = ps->ps_ui; 490*0Sstevel@tonic-gate md_dev64_t dev = ps->ps_errcomp->un_dev; 491*0Sstevel@tonic-gate md_dev64_t md_dev = md_expldev(pb->b_edev); 492*0Sstevel@tonic-gate char *str; 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate if (pb->b_flags & B_READ) { 495*0Sstevel@tonic-gate ps->ps_errcomp->un_mirror.ms_flags |= MDM_S_READERR; 496*0Sstevel@tonic-gate str = "read"; 497*0Sstevel@tonic-gate } else { 498*0Sstevel@tonic-gate ps->ps_errcomp->un_mirror.ms_flags |= MDM_S_WRTERR; 499*0Sstevel@tonic-gate str = "write"; 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate if (!(ps->ps_flags & MD_SPS_DONTFREE)) { 502*0Sstevel@tonic-gate if (MUTEX_HELD(&ps->ps_mx)) { 503*0Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate } else { 506*0Sstevel@tonic-gate ASSERT(panicstr); 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate SPS_FREE(stripe_parent_cache, ps); 509*0Sstevel@tonic-gate pb->b_flags |= B_ERROR; 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate md_kstat_done(ui, pb, 0); 512*0Sstevel@tonic-gate md_unit_readerexit(ui); 513*0Sstevel@tonic-gate md_biodone(pb); 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate cmn_err(CE_WARN, "md: %s: %s error on %s", 516*0Sstevel@tonic-gate md_shortname(md_getminor(md_dev)), str, 517*0Sstevel@tonic-gate md_devname(MD_DEV2SET(md_dev), dev, NULL, 0)); 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate static int 521*0Sstevel@tonic-gate stripe_done(struct buf *cb) 522*0Sstevel@tonic-gate { 523*0Sstevel@tonic-gate struct buf *pb; 524*0Sstevel@tonic-gate mdi_unit_t *ui; 525*0Sstevel@tonic-gate md_sps_t *ps; 526*0Sstevel@tonic-gate md_scs_t *cs; 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate /*LINTED*/ 529*0Sstevel@tonic-gate cs = (md_scs_t *)((caddr_t)cb - md_stripe_mcs_buf_off); 530*0Sstevel@tonic-gate ps = cs->cs_ps; 531*0Sstevel@tonic-gate pb = ps->ps_bp; 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate mutex_enter(&ps->ps_mx); 534*0Sstevel@tonic-gate if (cb->b_flags & B_ERROR) { 535*0Sstevel@tonic-gate ps->ps_flags |= MD_SPS_ERROR; 536*0Sstevel@tonic-gate pb->b_error = cb->b_error; 537*0Sstevel@tonic-gate ps->ps_errcomp = cs->cs_comp; 538*0Sstevel@tonic-gate } 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate if (cb->b_flags & B_REMAPPED) 541*0Sstevel@tonic-gate bp_mapout(cb); 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate ps->ps_frags--; 544*0Sstevel@tonic-gate if (ps->ps_frags != 0) { 545*0Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 546*0Sstevel@tonic-gate kmem_cache_free(stripe_child_cache, cs); 547*0Sstevel@tonic-gate return (1); 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate kmem_cache_free(stripe_child_cache, cs); 550*0Sstevel@tonic-gate if (ps->ps_flags & MD_SPS_ERROR) { 551*0Sstevel@tonic-gate stripe_error(ps); 552*0Sstevel@tonic-gate return (1); 553*0Sstevel@tonic-gate } 554*0Sstevel@tonic-gate ui = ps->ps_ui; 555*0Sstevel@tonic-gate if (!(ps->ps_flags & MD_SPS_DONTFREE)) { 556*0Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 557*0Sstevel@tonic-gate } else { 558*0Sstevel@tonic-gate ASSERT(panicstr); 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate SPS_FREE(stripe_parent_cache, ps); 561*0Sstevel@tonic-gate md_kstat_done(ui, pb, 0); 562*0Sstevel@tonic-gate md_unit_readerexit(ui); 563*0Sstevel@tonic-gate md_biodone(pb); 564*0Sstevel@tonic-gate return (0); 565*0Sstevel@tonic-gate } 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate /* 569*0Sstevel@tonic-gate * This routine does the mapping from virtual (dev, blkno) of a metapartition 570*0Sstevel@tonic-gate * to the real (dev, blkno) of a real disk partition. 571*0Sstevel@tonic-gate * It goes to the md_conf[] table to find out the correct real partition 572*0Sstevel@tonic-gate * dev and block number for this buffer. 573*0Sstevel@tonic-gate * 574*0Sstevel@tonic-gate * A single buf request can not go across real disk partition boundary. 575*0Sstevel@tonic-gate * When the virtual request specified by (dev, blkno) spans more than one 576*0Sstevel@tonic-gate * real partition, md_mapbuf will return 1. Then the caller should prepare 577*0Sstevel@tonic-gate * another real buf and continue calling md_mapbuf to do the mapping until 578*0Sstevel@tonic-gate * it returns 0. 579*0Sstevel@tonic-gate * 580*0Sstevel@tonic-gate */ 581*0Sstevel@tonic-gate 582*0Sstevel@tonic-gate static int 583*0Sstevel@tonic-gate md_mapbuf( 584*0Sstevel@tonic-gate ms_unit_t *un, 585*0Sstevel@tonic-gate diskaddr_t blkno, 586*0Sstevel@tonic-gate u_longlong_t bcount, 587*0Sstevel@tonic-gate buf_t *bp, /* if bp==NULL, skip bp updates */ 588*0Sstevel@tonic-gate ms_comp_t **mdc) /* if bp==NULL, skip mdc update */ 589*0Sstevel@tonic-gate { 590*0Sstevel@tonic-gate struct ms_row *mdr; 591*0Sstevel@tonic-gate struct ms_comp *mdcomp; 592*0Sstevel@tonic-gate diskaddr_t stripe_blk; 593*0Sstevel@tonic-gate diskaddr_t fragment, blk_in_row, endblk; 594*0Sstevel@tonic-gate offset_t interlace; 595*0Sstevel@tonic-gate size_t dev_index; 596*0Sstevel@tonic-gate int row_index, more; 597*0Sstevel@tonic-gate extern unsigned md_maxphys; 598*0Sstevel@tonic-gate /* Work var's when bp==NULL */ 599*0Sstevel@tonic-gate u_longlong_t wb_bcount; 600*0Sstevel@tonic-gate diskaddr_t wb_blkno; 601*0Sstevel@tonic-gate md_dev64_t wb_edev; 602*0Sstevel@tonic-gate ms_comp_t *wmdc; 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate /* 605*0Sstevel@tonic-gate * Do a real calculation to derive the minor device of the 606*0Sstevel@tonic-gate * Virtual Disk, which in turn will let us derive the 607*0Sstevel@tonic-gate * device/minor of the underlying real device. 608*0Sstevel@tonic-gate */ 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate for (row_index = 0; row_index < un->un_nrows; row_index++) { 612*0Sstevel@tonic-gate mdr = &un->un_row[row_index]; 613*0Sstevel@tonic-gate if (blkno < mdr->un_cum_blocks) 614*0Sstevel@tonic-gate break; 615*0Sstevel@tonic-gate } 616*0Sstevel@tonic-gate ASSERT(row_index != un->un_nrows); 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate blk_in_row = blkno - mdr->un_cum_blocks + mdr->un_blocks; 621*0Sstevel@tonic-gate endblk = (diskaddr_t)(blkno + howmany(bcount, DEV_BSIZE)); 622*0Sstevel@tonic-gate if (mdr->un_ncomp == 1) { /* No striping */ 623*0Sstevel@tonic-gate if (endblk > mdr->un_cum_blocks) { 624*0Sstevel@tonic-gate wb_bcount = ldbtob(mdr->un_cum_blocks - blkno); 625*0Sstevel@tonic-gate if ((row_index + 1) == un->un_nrows) 626*0Sstevel@tonic-gate more = 0; 627*0Sstevel@tonic-gate else 628*0Sstevel@tonic-gate more = 1; 629*0Sstevel@tonic-gate } else { 630*0Sstevel@tonic-gate wb_bcount = bcount; 631*0Sstevel@tonic-gate more = 0; 632*0Sstevel@tonic-gate } 633*0Sstevel@tonic-gate wmdc = &mdcomp[mdr->un_icomp]; 634*0Sstevel@tonic-gate wb_blkno = blk_in_row; 635*0Sstevel@tonic-gate } else { /* Have striping */ 636*0Sstevel@tonic-gate interlace = mdr->un_interlace; 637*0Sstevel@tonic-gate fragment = blk_in_row % interlace; 638*0Sstevel@tonic-gate if (bcount > ldbtob(interlace - fragment)) { 639*0Sstevel@tonic-gate more = 1; 640*0Sstevel@tonic-gate wb_bcount = ldbtob(interlace - fragment); 641*0Sstevel@tonic-gate } else { 642*0Sstevel@tonic-gate more = 0; 643*0Sstevel@tonic-gate wb_bcount = bcount; 644*0Sstevel@tonic-gate } 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate stripe_blk = blk_in_row / interlace; 647*0Sstevel@tonic-gate dev_index = (size_t)(stripe_blk % mdr->un_ncomp); 648*0Sstevel@tonic-gate wmdc = &mdcomp[mdr->un_icomp + dev_index]; 649*0Sstevel@tonic-gate wb_blkno = (diskaddr_t)(((stripe_blk / mdr->un_ncomp) 650*0Sstevel@tonic-gate * interlace) + fragment); 651*0Sstevel@tonic-gate } 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate wb_blkno += wmdc->un_start_block; 654*0Sstevel@tonic-gate wb_edev = wmdc->un_dev; 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* only break up the I/O if we're not built on another metadevice */ 657*0Sstevel@tonic-gate if ((md_getmajor(wb_edev) != md_major) && (wb_bcount > md_maxphys)) { 658*0Sstevel@tonic-gate wb_bcount = md_maxphys; 659*0Sstevel@tonic-gate more = 1; 660*0Sstevel@tonic-gate } 661*0Sstevel@tonic-gate if (bp != (buf_t *)NULL) { 662*0Sstevel@tonic-gate /* 663*0Sstevel@tonic-gate * wb_bcount is limited by md_maxphys which is 'int' 664*0Sstevel@tonic-gate */ 665*0Sstevel@tonic-gate bp->b_bcount = (size_t)wb_bcount; 666*0Sstevel@tonic-gate bp->b_lblkno = wb_blkno; 667*0Sstevel@tonic-gate bp->b_edev = md_dev64_to_dev(wb_edev); 668*0Sstevel@tonic-gate *mdc = wmdc; 669*0Sstevel@tonic-gate } 670*0Sstevel@tonic-gate return (more); 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate static void 674*0Sstevel@tonic-gate md_stripe_strategy(buf_t *pb, int flag, void *private) 675*0Sstevel@tonic-gate { 676*0Sstevel@tonic-gate md_sps_t *ps; 677*0Sstevel@tonic-gate md_scs_t *cs; 678*0Sstevel@tonic-gate int doing_writes; 679*0Sstevel@tonic-gate int more; 680*0Sstevel@tonic-gate ms_unit_t *un; 681*0Sstevel@tonic-gate mdi_unit_t *ui; 682*0Sstevel@tonic-gate size_t current_count; 683*0Sstevel@tonic-gate diskaddr_t current_blkno; 684*0Sstevel@tonic-gate off_t current_offset; 685*0Sstevel@tonic-gate buf_t *cb; /* child buf pointer */ 686*0Sstevel@tonic-gate set_t setno; 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate setno = MD_MIN2SET(getminor(pb->b_edev)); 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate /* 691*0Sstevel@tonic-gate * When doing IO to a multi owner meta device, check if set is halted. 692*0Sstevel@tonic-gate * We do this check without the needed lock held, for performance 693*0Sstevel@tonic-gate * reasons. 694*0Sstevel@tonic-gate * If an IO just slips through while the set is locked via an 695*0Sstevel@tonic-gate * MD_MN_SUSPEND_SET, we don't care about it. 696*0Sstevel@tonic-gate * Only check for a suspended set if we are a top-level i/o request 697*0Sstevel@tonic-gate * (MD_STR_NOTTOP is cleared in 'flag'). 698*0Sstevel@tonic-gate */ 699*0Sstevel@tonic-gate if ((md_set[setno].s_status & (MD_SET_HALTED | MD_SET_MNSET)) == 700*0Sstevel@tonic-gate (MD_SET_HALTED | MD_SET_MNSET)) { 701*0Sstevel@tonic-gate if ((flag & MD_STR_NOTTOP) == 0) { 702*0Sstevel@tonic-gate mutex_enter(&md_mx); 703*0Sstevel@tonic-gate /* Here we loop until the set is no longer halted */ 704*0Sstevel@tonic-gate while (md_set[setno].s_status & MD_SET_HALTED) { 705*0Sstevel@tonic-gate cv_wait(&md_cv, &md_mx); 706*0Sstevel@tonic-gate } 707*0Sstevel@tonic-gate mutex_exit(&md_mx); 708*0Sstevel@tonic-gate } 709*0Sstevel@tonic-gate } 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate ui = MDI_UNIT(getminor(pb->b_edev)); 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate md_kstat_waitq_enter(ui); 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate un = (ms_unit_t *)md_unit_readerlock(ui); 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate if ((flag & MD_NOBLOCK) == 0) { 718*0Sstevel@tonic-gate if (md_inc_iocount(setno) != 0) { 719*0Sstevel@tonic-gate pb->b_flags |= B_ERROR; 720*0Sstevel@tonic-gate pb->b_error = ENXIO; 721*0Sstevel@tonic-gate pb->b_resid = pb->b_bcount; 722*0Sstevel@tonic-gate md_unit_readerexit(ui); 723*0Sstevel@tonic-gate biodone(pb); 724*0Sstevel@tonic-gate return; 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate } else { 727*0Sstevel@tonic-gate md_inc_iocount_noblock(setno); 728*0Sstevel@tonic-gate } 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate if (!(flag & MD_STR_NOTTOP)) { 731*0Sstevel@tonic-gate if (md_checkbuf(ui, (md_unit_t *)un, pb) != 0) { 732*0Sstevel@tonic-gate md_kstat_waitq_exit(ui); 733*0Sstevel@tonic-gate return; 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate ps = kmem_cache_alloc(stripe_parent_cache, MD_ALLOCFLAGS); 738*0Sstevel@tonic-gate stripe_parent_init(ps); 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate /* 741*0Sstevel@tonic-gate * Save essential information from the original buffhdr 742*0Sstevel@tonic-gate * in the md_save structure. 743*0Sstevel@tonic-gate */ 744*0Sstevel@tonic-gate ps->ps_un = un; 745*0Sstevel@tonic-gate ps->ps_ui = ui; 746*0Sstevel@tonic-gate ps->ps_bp = pb; 747*0Sstevel@tonic-gate ps->ps_addr = pb->b_un.b_addr; 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate if ((pb->b_flags & B_READ) == 0) 750*0Sstevel@tonic-gate doing_writes = 1; 751*0Sstevel@tonic-gate else 752*0Sstevel@tonic-gate doing_writes = 0; 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate current_count = pb->b_bcount; 756*0Sstevel@tonic-gate current_blkno = pb->b_lblkno; 757*0Sstevel@tonic-gate current_offset = 0; 758*0Sstevel@tonic-gate 759*0Sstevel@tonic-gate if (!(flag & MD_STR_NOTTOP) && panicstr) 760*0Sstevel@tonic-gate ps->ps_flags |= MD_SPS_DONTFREE; 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate md_kstat_waitq_to_runq(ui); 763*0Sstevel@tonic-gate 764*0Sstevel@tonic-gate ps->ps_frags++; 765*0Sstevel@tonic-gate do { 766*0Sstevel@tonic-gate cs = kmem_cache_alloc(stripe_child_cache, MD_ALLOCFLAGS); 767*0Sstevel@tonic-gate stripe_child_init(cs); 768*0Sstevel@tonic-gate cb = &cs->cs_buf; 769*0Sstevel@tonic-gate cs->cs_ps = ps; 770*0Sstevel@tonic-gate more = md_mapbuf(un, current_blkno, current_count, cb, 771*0Sstevel@tonic-gate &cs->cs_comp); 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate cb = md_bioclone(pb, current_offset, cb->b_bcount, cb->b_edev, 774*0Sstevel@tonic-gate cb->b_lblkno, stripe_done, cb, KM_NOSLEEP); 775*0Sstevel@tonic-gate /* 776*0Sstevel@tonic-gate * Do these calculations now, 777*0Sstevel@tonic-gate * so that we pickup a valid b_bcount from the chld_bp. 778*0Sstevel@tonic-gate */ 779*0Sstevel@tonic-gate current_offset += cb->b_bcount; 780*0Sstevel@tonic-gate current_count -= cb->b_bcount; 781*0Sstevel@tonic-gate current_blkno += (diskaddr_t)(lbtodb(cb->b_bcount)); 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate if (more) { 784*0Sstevel@tonic-gate mutex_enter(&ps->ps_mx); 785*0Sstevel@tonic-gate ps->ps_frags++; 786*0Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 787*0Sstevel@tonic-gate } 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate if (doing_writes && 790*0Sstevel@tonic-gate cs->cs_comp->un_mirror.ms_flags & MDM_S_NOWRITE) { 791*0Sstevel@tonic-gate (void) stripe_done(cb); 792*0Sstevel@tonic-gate continue; 793*0Sstevel@tonic-gate } 794*0Sstevel@tonic-gate md_call_strategy(cb, flag, private); 795*0Sstevel@tonic-gate } while (more); 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate if (!(flag & MD_STR_NOTTOP) && panicstr) { 798*0Sstevel@tonic-gate while (!(ps->ps_flags & MD_SPS_DONE)) { 799*0Sstevel@tonic-gate md_daemon(1, &md_done_daemon); 800*0Sstevel@tonic-gate drv_usecwait(10); 801*0Sstevel@tonic-gate } 802*0Sstevel@tonic-gate kmem_cache_free(stripe_parent_cache, ps); 803*0Sstevel@tonic-gate } 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate static int 807*0Sstevel@tonic-gate stripe_snarf(md_snarfcmd_t cmd, set_t setno) 808*0Sstevel@tonic-gate { 809*0Sstevel@tonic-gate ms_unit_t *un; 810*0Sstevel@tonic-gate mddb_recid_t recid; 811*0Sstevel@tonic-gate int gotsomething; 812*0Sstevel@tonic-gate int all_stripes_gotten; 813*0Sstevel@tonic-gate mddb_type_t typ1; 814*0Sstevel@tonic-gate mddb_de_ic_t *dep; 815*0Sstevel@tonic-gate mddb_rb32_t *rbp; 816*0Sstevel@tonic-gate size_t newreqsize; 817*0Sstevel@tonic-gate ms_unit_t *big_un; 818*0Sstevel@tonic-gate ms_unit32_od_t *small_un; 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate if (cmd == MD_SNARF_CLEANUP) 822*0Sstevel@tonic-gate return (0); 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate all_stripes_gotten = 1; 825*0Sstevel@tonic-gate gotsomething = 0; 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate typ1 = (mddb_type_t)md_getshared_key(setno, 828*0Sstevel@tonic-gate stripe_md_ops.md_driver.md_drivername); 829*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 830*0Sstevel@tonic-gate 831*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, 0)) > 0) { 832*0Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_GOTIT) 833*0Sstevel@tonic-gate continue; 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate dep = mddb_getrecdep(recid); 836*0Sstevel@tonic-gate dep->de_flags = MDDB_F_STRIPE; 837*0Sstevel@tonic-gate rbp = dep->de_rb; 838*0Sstevel@tonic-gate 839*0Sstevel@tonic-gate if ((rbp->rb_revision == MDDB_REV_RB) && 840*0Sstevel@tonic-gate ((rbp->rb_private & MD_PRV_CONVD) == 0)) { 841*0Sstevel@tonic-gate /* 842*0Sstevel@tonic-gate * This means, we have an old and small record 843*0Sstevel@tonic-gate * and this record hasn't already been converted. 844*0Sstevel@tonic-gate * Before we create an incore metadevice from this 845*0Sstevel@tonic-gate * we have to convert it to a big record. 846*0Sstevel@tonic-gate */ 847*0Sstevel@tonic-gate small_un = (ms_unit32_od_t *)mddb_getrecaddr(recid); 848*0Sstevel@tonic-gate newreqsize = get_big_stripe_req_size(small_un, 849*0Sstevel@tonic-gate COMPLETE_STRUCTURE); 850*0Sstevel@tonic-gate big_un = (ms_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP); 851*0Sstevel@tonic-gate stripe_convert((caddr_t)small_un, (caddr_t)big_un, 852*0Sstevel@tonic-gate SMALL_2_BIG); 853*0Sstevel@tonic-gate kmem_free(small_un, dep->de_reqsize); 854*0Sstevel@tonic-gate dep->de_rb_userdata = big_un; 855*0Sstevel@tonic-gate dep->de_reqsize = newreqsize; 856*0Sstevel@tonic-gate un = big_un; 857*0Sstevel@tonic-gate rbp->rb_private |= MD_PRV_CONVD; 858*0Sstevel@tonic-gate } else { 859*0Sstevel@tonic-gate /* Big device */ 860*0Sstevel@tonic-gate un = (ms_unit_t *)mddb_getrecaddr(recid); 861*0Sstevel@tonic-gate } 862*0Sstevel@tonic-gate 863*0Sstevel@tonic-gate /* Set revision and flag accordingly */ 864*0Sstevel@tonic-gate if (rbp->rb_revision == MDDB_REV_RB) { 865*0Sstevel@tonic-gate un->c.un_revision = MD_32BIT_META_DEV; 866*0Sstevel@tonic-gate } else { 867*0Sstevel@tonic-gate un->c.un_revision = MD_64BIT_META_DEV; 868*0Sstevel@tonic-gate un->c.un_flag |= MD_EFILABEL; 869*0Sstevel@tonic-gate } 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate /* Create minor node for snarfed unit. */ 872*0Sstevel@tonic-gate (void) md_create_minor_node(MD_MIN2SET(MD_SID(un)), MD_SID(un)); 873*0Sstevel@tonic-gate 874*0Sstevel@tonic-gate if (MD_UNIT(MD_SID(un)) != NULL) { 875*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_PENDDEL); 876*0Sstevel@tonic-gate continue; 877*0Sstevel@tonic-gate } 878*0Sstevel@tonic-gate all_stripes_gotten = 0; 879*0Sstevel@tonic-gate if (stripe_build_incore((void *)un, 1) == 0) { 880*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT); 881*0Sstevel@tonic-gate md_create_unit_incore(MD_SID(un), &stripe_md_ops, 0); 882*0Sstevel@tonic-gate gotsomething = 1; 883*0Sstevel@tonic-gate } 884*0Sstevel@tonic-gate } 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate if (!all_stripes_gotten) 887*0Sstevel@tonic-gate return (gotsomething); 888*0Sstevel@tonic-gate 889*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 890*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, 0)) > 0) 891*0Sstevel@tonic-gate if (!(mddb_getrecprivate(recid) & MD_PRV_GOTIT)) 892*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_PENDDEL); 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate return (0); 895*0Sstevel@tonic-gate } 896*0Sstevel@tonic-gate 897*0Sstevel@tonic-gate static int 898*0Sstevel@tonic-gate stripe_halt(md_haltcmd_t cmd, set_t setno) 899*0Sstevel@tonic-gate { 900*0Sstevel@tonic-gate int i; 901*0Sstevel@tonic-gate mdi_unit_t *ui; 902*0Sstevel@tonic-gate minor_t mnum; 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate if (cmd == MD_HALT_CLOSE) 905*0Sstevel@tonic-gate return (0); 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate if (cmd == MD_HALT_OPEN) 908*0Sstevel@tonic-gate return (0); 909*0Sstevel@tonic-gate 910*0Sstevel@tonic-gate if (cmd == MD_HALT_UNLOAD) 911*0Sstevel@tonic-gate return (0); 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate if (cmd == MD_HALT_CHECK) { 914*0Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 915*0Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 916*0Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 917*0Sstevel@tonic-gate continue; 918*0Sstevel@tonic-gate if (ui->ui_opsindex != stripe_md_ops.md_selfindex) 919*0Sstevel@tonic-gate continue; 920*0Sstevel@tonic-gate if (md_unit_isopen(ui)) 921*0Sstevel@tonic-gate return (1); 922*0Sstevel@tonic-gate } 923*0Sstevel@tonic-gate return (0); 924*0Sstevel@tonic-gate } 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate if (cmd != MD_HALT_DOIT) 927*0Sstevel@tonic-gate return (1); 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 930*0Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 931*0Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 932*0Sstevel@tonic-gate continue; 933*0Sstevel@tonic-gate if (ui->ui_opsindex != stripe_md_ops.md_selfindex) 934*0Sstevel@tonic-gate continue; 935*0Sstevel@tonic-gate reset_stripe((ms_unit_t *)MD_UNIT(mnum), mnum, 0); 936*0Sstevel@tonic-gate } 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate return (0); 939*0Sstevel@tonic-gate } 940*0Sstevel@tonic-gate 941*0Sstevel@tonic-gate /*ARGSUSED3*/ 942*0Sstevel@tonic-gate static int 943*0Sstevel@tonic-gate stripe_open(dev_t *dev, int flag, int otyp, cred_t *cred_p, int md_oflags) 944*0Sstevel@tonic-gate { 945*0Sstevel@tonic-gate minor_t mnum = getminor(*dev); 946*0Sstevel@tonic-gate mdi_unit_t *ui = MDI_UNIT(mnum); 947*0Sstevel@tonic-gate ms_unit_t *un; 948*0Sstevel@tonic-gate int err = 0; 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate /* single thread */ 951*0Sstevel@tonic-gate un = (ms_unit_t *)md_unit_openclose_enter(ui); 952*0Sstevel@tonic-gate 953*0Sstevel@tonic-gate /* open devices, if necessary */ 954*0Sstevel@tonic-gate if (! md_unit_isopen(ui) || (md_oflags & MD_OFLG_PROBEDEV)) { 955*0Sstevel@tonic-gate if ((err = stripe_open_all_devs(un, md_oflags)) != 0) { 956*0Sstevel@tonic-gate goto out; 957*0Sstevel@tonic-gate } 958*0Sstevel@tonic-gate } 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate /* count open */ 961*0Sstevel@tonic-gate if ((err = md_unit_incopen(mnum, flag, otyp)) != 0) 962*0Sstevel@tonic-gate goto out; 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate /* unlock, return success */ 965*0Sstevel@tonic-gate out: 966*0Sstevel@tonic-gate md_unit_openclose_exit(ui); 967*0Sstevel@tonic-gate return (err); 968*0Sstevel@tonic-gate } 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate /*ARGSUSED1*/ 971*0Sstevel@tonic-gate static int 972*0Sstevel@tonic-gate stripe_close( 973*0Sstevel@tonic-gate dev_t dev, 974*0Sstevel@tonic-gate int flag, 975*0Sstevel@tonic-gate int otyp, 976*0Sstevel@tonic-gate cred_t *cred_p, 977*0Sstevel@tonic-gate int md_cflags 978*0Sstevel@tonic-gate ) 979*0Sstevel@tonic-gate { 980*0Sstevel@tonic-gate minor_t mnum = getminor(dev); 981*0Sstevel@tonic-gate mdi_unit_t *ui = MDI_UNIT(mnum); 982*0Sstevel@tonic-gate ms_unit_t *un; 983*0Sstevel@tonic-gate int err = 0; 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate /* single thread */ 986*0Sstevel@tonic-gate un = (ms_unit_t *)md_unit_openclose_enter(ui); 987*0Sstevel@tonic-gate 988*0Sstevel@tonic-gate /* count closed */ 989*0Sstevel@tonic-gate if ((err = md_unit_decopen(mnum, otyp)) != 0) 990*0Sstevel@tonic-gate goto out; 991*0Sstevel@tonic-gate 992*0Sstevel@tonic-gate /* close devices, if necessary */ 993*0Sstevel@tonic-gate if (! md_unit_isopen(ui) || (md_cflags & MD_OFLG_PROBEDEV)) { 994*0Sstevel@tonic-gate stripe_close_all_devs(un, md_cflags); 995*0Sstevel@tonic-gate } 996*0Sstevel@tonic-gate 997*0Sstevel@tonic-gate /* unlock, return success */ 998*0Sstevel@tonic-gate out: 999*0Sstevel@tonic-gate md_unit_openclose_exit(ui); 1000*0Sstevel@tonic-gate return (err); 1001*0Sstevel@tonic-gate } 1002*0Sstevel@tonic-gate 1003*0Sstevel@tonic-gate 1004*0Sstevel@tonic-gate static struct buf dumpbuf; 1005*0Sstevel@tonic-gate 1006*0Sstevel@tonic-gate /* 1007*0Sstevel@tonic-gate * This routine dumps memory to the disk. It assumes that the memory has 1008*0Sstevel@tonic-gate * already been mapped into mainbus space. It is called at disk interrupt 1009*0Sstevel@tonic-gate * priority when the system is in trouble. 1010*0Sstevel@tonic-gate * 1011*0Sstevel@tonic-gate */ 1012*0Sstevel@tonic-gate static int 1013*0Sstevel@tonic-gate stripe_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) 1014*0Sstevel@tonic-gate { 1015*0Sstevel@tonic-gate ms_unit_t *un; 1016*0Sstevel@tonic-gate buf_t *bp; 1017*0Sstevel@tonic-gate ms_comp_t *mdc; 1018*0Sstevel@tonic-gate u_longlong_t nb; 1019*0Sstevel@tonic-gate diskaddr_t mapblk; 1020*0Sstevel@tonic-gate int result; 1021*0Sstevel@tonic-gate int more; 1022*0Sstevel@tonic-gate int saveresult = 0; 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate /* 1025*0Sstevel@tonic-gate * Don't need to grab the unit lock. 1026*0Sstevel@tonic-gate * Cause nothing else is suppose to be happenning. 1027*0Sstevel@tonic-gate * Also dump is not suppose to sleep. 1028*0Sstevel@tonic-gate */ 1029*0Sstevel@tonic-gate un = (ms_unit_t *)MD_UNIT(getminor(dev)); 1030*0Sstevel@tonic-gate 1031*0Sstevel@tonic-gate if ((diskaddr_t)blkno >= un->c.un_total_blocks) 1032*0Sstevel@tonic-gate return (EINVAL); 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate if ((diskaddr_t)blkno + nblk > un->c.un_total_blocks) 1035*0Sstevel@tonic-gate return (EINVAL); 1036*0Sstevel@tonic-gate 1037*0Sstevel@tonic-gate bp = &dumpbuf; 1038*0Sstevel@tonic-gate nb = ldbtob(nblk); 1039*0Sstevel@tonic-gate do { 1040*0Sstevel@tonic-gate bzero((caddr_t)bp, sizeof (*bp)); 1041*0Sstevel@tonic-gate more = md_mapbuf(un, (diskaddr_t)blkno, nb, bp, &mdc); 1042*0Sstevel@tonic-gate nblk = btodb(bp->b_bcount); 1043*0Sstevel@tonic-gate mapblk = bp->b_lblkno; 1044*0Sstevel@tonic-gate if (!(mdc->un_mirror.ms_flags & MDM_S_NOWRITE)) { 1045*0Sstevel@tonic-gate /* 1046*0Sstevel@tonic-gate * bdev_dump() is currently only able to take 1047*0Sstevel@tonic-gate * 32 bit wide blkno's. 1048*0Sstevel@tonic-gate */ 1049*0Sstevel@tonic-gate result = bdev_dump(bp->b_edev, addr, (daddr_t)mapblk, 1050*0Sstevel@tonic-gate nblk); 1051*0Sstevel@tonic-gate if (result) 1052*0Sstevel@tonic-gate saveresult = result; 1053*0Sstevel@tonic-gate } 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate nb -= bp->b_bcount; 1056*0Sstevel@tonic-gate addr += bp->b_bcount; 1057*0Sstevel@tonic-gate blkno += nblk; 1058*0Sstevel@tonic-gate } while (more); 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate return (saveresult); 1061*0Sstevel@tonic-gate } 1062*0Sstevel@tonic-gate 1063*0Sstevel@tonic-gate /*ARGSUSED*/ 1064*0Sstevel@tonic-gate static intptr_t 1065*0Sstevel@tonic-gate stripe_shared_by_blk( 1066*0Sstevel@tonic-gate md_dev64_t dev, 1067*0Sstevel@tonic-gate void *junk, 1068*0Sstevel@tonic-gate diskaddr_t blkno, 1069*0Sstevel@tonic-gate u_longlong_t *cnt) 1070*0Sstevel@tonic-gate { 1071*0Sstevel@tonic-gate ms_unit_t *un; 1072*0Sstevel@tonic-gate buf_t bp; 1073*0Sstevel@tonic-gate ms_comp_t *comp; 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 1076*0Sstevel@tonic-gate (void) md_mapbuf(un, blkno, ldbtob(*cnt), &bp, &comp); 1077*0Sstevel@tonic-gate *cnt = (u_longlong_t)lbtodb(bp.b_bcount); 1078*0Sstevel@tonic-gate return ((intptr_t)&comp->un_mirror); 1079*0Sstevel@tonic-gate } 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate /* 1082*0Sstevel@tonic-gate * stripe_block_count_skip_size() returns the following values 1083*0Sstevel@tonic-gate * so that the logical to physical block mappings can 1084*0Sstevel@tonic-gate * be calculated without intimate knowledge of the underpinnings. 1085*0Sstevel@tonic-gate * 1086*0Sstevel@tonic-gate * block - first logical block number of the device. 1087*0Sstevel@tonic-gate * block = [ # of blocks before THE row ] + 1088*0Sstevel@tonic-gate * [ # of blocks in THE row before the component ] 1089*0Sstevel@tonic-gate * count - # of segments (interlaced size). 1090*0Sstevel@tonic-gate * skip - # of logical blocks between segments, or delta to 1091*0Sstevel@tonic-gate * get to next segment 1092*0Sstevel@tonic-gate * size - interlace size used for the block, count, skip. 1093*0Sstevel@tonic-gate */ 1094*0Sstevel@tonic-gate /*ARGSUSED*/ 1095*0Sstevel@tonic-gate static intptr_t 1096*0Sstevel@tonic-gate stripe_block_count_skip_size( 1097*0Sstevel@tonic-gate md_dev64_t dev, 1098*0Sstevel@tonic-gate void *junk, 1099*0Sstevel@tonic-gate int ci, 1100*0Sstevel@tonic-gate diskaddr_t *block, 1101*0Sstevel@tonic-gate size_t *count, 1102*0Sstevel@tonic-gate u_longlong_t *skip, 1103*0Sstevel@tonic-gate u_longlong_t *size) 1104*0Sstevel@tonic-gate { 1105*0Sstevel@tonic-gate ms_unit_t *un; 1106*0Sstevel@tonic-gate int row; 1107*0Sstevel@tonic-gate struct ms_row *mdr; 1108*0Sstevel@tonic-gate int cmpcount = 0; 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 1111*0Sstevel@tonic-gate 1112*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 1113*0Sstevel@tonic-gate mdr = &un->un_row[row]; 1114*0Sstevel@tonic-gate if ((mdr->un_ncomp + cmpcount) > ci) 1115*0Sstevel@tonic-gate break; 1116*0Sstevel@tonic-gate cmpcount += mdr->un_ncomp; 1117*0Sstevel@tonic-gate } 1118*0Sstevel@tonic-gate ASSERT(row != un->un_nrows); 1119*0Sstevel@tonic-gate 1120*0Sstevel@tonic-gate /* 1121*0Sstevel@tonic-gate * Concatenations are always contiguous blocks, 1122*0Sstevel@tonic-gate * you cannot depend on the interlace being a usable 1123*0Sstevel@tonic-gate * value (except for stripes). 1124*0Sstevel@tonic-gate */ 1125*0Sstevel@tonic-gate if (mdr->un_ncomp == 1) { /* Concats */ 1126*0Sstevel@tonic-gate *block = mdr->un_cum_blocks - mdr->un_blocks; 1127*0Sstevel@tonic-gate *count = 1; 1128*0Sstevel@tonic-gate *skip = 0; 1129*0Sstevel@tonic-gate *size = mdr->un_blocks; 1130*0Sstevel@tonic-gate } else { /* Stripes */ 1131*0Sstevel@tonic-gate *block = (mdr->un_cum_blocks - mdr->un_blocks) + 1132*0Sstevel@tonic-gate ((ci - cmpcount) * mdr->un_interlace); 1133*0Sstevel@tonic-gate *count = (size_t)(mdr->un_blocks / (mdr->un_interlace 1134*0Sstevel@tonic-gate * mdr->un_ncomp)); 1135*0Sstevel@tonic-gate *skip = (mdr->un_interlace * mdr->un_ncomp) - mdr->un_interlace; 1136*0Sstevel@tonic-gate *size = mdr->un_interlace; 1137*0Sstevel@tonic-gate } 1138*0Sstevel@tonic-gate 1139*0Sstevel@tonic-gate return (0); 1140*0Sstevel@tonic-gate } 1141*0Sstevel@tonic-gate 1142*0Sstevel@tonic-gate /*ARGSUSED*/ 1143*0Sstevel@tonic-gate static intptr_t 1144*0Sstevel@tonic-gate stripe_shared_by_indx(md_dev64_t dev, void *junk, int indx) 1145*0Sstevel@tonic-gate { 1146*0Sstevel@tonic-gate ms_unit_t *un; 1147*0Sstevel@tonic-gate ms_comp_t *comp; 1148*0Sstevel@tonic-gate 1149*0Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 1150*0Sstevel@tonic-gate comp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 1151*0Sstevel@tonic-gate comp += indx; 1152*0Sstevel@tonic-gate return ((intptr_t)&comp->un_mirror); 1153*0Sstevel@tonic-gate } 1154*0Sstevel@tonic-gate 1155*0Sstevel@tonic-gate /*ARGSUSED*/ 1156*0Sstevel@tonic-gate intptr_t 1157*0Sstevel@tonic-gate stripe_component_count(md_dev64_t dev, void *junk) 1158*0Sstevel@tonic-gate { 1159*0Sstevel@tonic-gate /* 1160*0Sstevel@tonic-gate * See comments for stripe_get_dev 1161*0Sstevel@tonic-gate */ 1162*0Sstevel@tonic-gate 1163*0Sstevel@tonic-gate ms_unit_t *un; 1164*0Sstevel@tonic-gate int count = 0; 1165*0Sstevel@tonic-gate int row; 1166*0Sstevel@tonic-gate 1167*0Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 1168*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) 1169*0Sstevel@tonic-gate count += un->un_row[row].un_ncomp; 1170*0Sstevel@tonic-gate return (count); 1171*0Sstevel@tonic-gate } 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate /*ARGSUSED*/ 1174*0Sstevel@tonic-gate intptr_t 1175*0Sstevel@tonic-gate stripe_get_dev(md_dev64_t dev, void *junk, int indx, ms_cd_info_t *cd) 1176*0Sstevel@tonic-gate { 1177*0Sstevel@tonic-gate /* 1178*0Sstevel@tonic-gate * It should be noted that stripe_replace in stripe_ioctl.c calls this 1179*0Sstevel@tonic-gate * routine using makedevice(0, minor) for the first argument. 1180*0Sstevel@tonic-gate * 1181*0Sstevel@tonic-gate * If this routine at some point in the future needs to use the major 1182*0Sstevel@tonic-gate * number stripe_replace must be changed. 1183*0Sstevel@tonic-gate */ 1184*0Sstevel@tonic-gate 1185*0Sstevel@tonic-gate ms_unit_t *un; 1186*0Sstevel@tonic-gate ms_comp_t *comp; 1187*0Sstevel@tonic-gate md_dev64_t tmpdev; 1188*0Sstevel@tonic-gate 1189*0Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 1190*0Sstevel@tonic-gate comp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 1191*0Sstevel@tonic-gate comp += indx; 1192*0Sstevel@tonic-gate tmpdev = comp->un_dev; 1193*0Sstevel@tonic-gate /* 1194*0Sstevel@tonic-gate * Try to resolve devt again if NODEV64 1195*0Sstevel@tonic-gate * Check if this comp is hotspared and if it is 1196*0Sstevel@tonic-gate * then use key for hotspare 1197*0Sstevel@tonic-gate */ 1198*0Sstevel@tonic-gate if (tmpdev == NODEV64) { 1199*0Sstevel@tonic-gate tmpdev = md_resolve_bydevid(md_getminor(dev), tmpdev, 1200*0Sstevel@tonic-gate comp->un_mirror.ms_hs_id ? 1201*0Sstevel@tonic-gate comp->un_mirror.ms_hs_key : 1202*0Sstevel@tonic-gate comp->un_key); 1203*0Sstevel@tonic-gate comp->un_dev = tmpdev; 1204*0Sstevel@tonic-gate } 1205*0Sstevel@tonic-gate 1206*0Sstevel@tonic-gate cd->cd_dev = comp->un_dev; 1207*0Sstevel@tonic-gate cd->cd_orig_dev = comp->un_mirror.ms_orig_dev; 1208*0Sstevel@tonic-gate return (0); 1209*0Sstevel@tonic-gate } 1210*0Sstevel@tonic-gate 1211*0Sstevel@tonic-gate /*ARGSUSED*/ 1212*0Sstevel@tonic-gate void 1213*0Sstevel@tonic-gate stripe_replace_done(md_dev64_t dev, sv_dev_t *sv) 1214*0Sstevel@tonic-gate { 1215*0Sstevel@tonic-gate /* 1216*0Sstevel@tonic-gate * See comments for stripe_get_dev 1217*0Sstevel@tonic-gate */ 1218*0Sstevel@tonic-gate 1219*0Sstevel@tonic-gate minor_t mnum = md_getminor(dev); 1220*0Sstevel@tonic-gate 1221*0Sstevel@tonic-gate if (sv != NULL) { 1222*0Sstevel@tonic-gate md_rem_names(sv, 1); 1223*0Sstevel@tonic-gate kmem_free(sv, sizeof (sv_dev_t)); 1224*0Sstevel@tonic-gate } 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate md_unit_writerexit(MDI_UNIT(mnum)); 1227*0Sstevel@tonic-gate } 1228*0Sstevel@tonic-gate 1229*0Sstevel@tonic-gate /*ARGSUSED*/ 1230*0Sstevel@tonic-gate intptr_t 1231*0Sstevel@tonic-gate stripe_replace_dev(md_dev64_t dev, void *junk, int ci, ms_new_dev_t *nd, 1232*0Sstevel@tonic-gate mddb_recid_t *recids, int nrecids, void (**replace_done)(), 1233*0Sstevel@tonic-gate void **replace_data) 1234*0Sstevel@tonic-gate { 1235*0Sstevel@tonic-gate minor_t mnum; 1236*0Sstevel@tonic-gate ms_unit_t *un; 1237*0Sstevel@tonic-gate mdi_unit_t *ui; 1238*0Sstevel@tonic-gate ms_comp_t *comp; 1239*0Sstevel@tonic-gate diskaddr_t dev_size; 1240*0Sstevel@tonic-gate int row; 1241*0Sstevel@tonic-gate int ncomps = 0; 1242*0Sstevel@tonic-gate int cmpcount = 0; 1243*0Sstevel@tonic-gate int rid = 0; 1244*0Sstevel@tonic-gate struct ms_row *mdr; 1245*0Sstevel@tonic-gate sv_dev_t *sv = NULL; 1246*0Sstevel@tonic-gate mddb_recid_t hs_id = 0; 1247*0Sstevel@tonic-gate set_t setno; 1248*0Sstevel@tonic-gate side_t side; 1249*0Sstevel@tonic-gate md_dev64_t this_dev; 1250*0Sstevel@tonic-gate 1251*0Sstevel@tonic-gate mnum = md_getminor(dev); 1252*0Sstevel@tonic-gate ui = MDI_UNIT(mnum); 1253*0Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 1254*0Sstevel@tonic-gate side = mddb_getsidenum(setno); 1255*0Sstevel@tonic-gate 1256*0Sstevel@tonic-gate un = md_unit_writerlock(ui); 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate *replace_data = NULL; 1259*0Sstevel@tonic-gate comp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 1260*0Sstevel@tonic-gate 1261*0Sstevel@tonic-gate comp += ci; 1262*0Sstevel@tonic-gate 1263*0Sstevel@tonic-gate /* 1264*0Sstevel@tonic-gate * Count the number of components 1265*0Sstevel@tonic-gate */ 1266*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 1267*0Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 1268*0Sstevel@tonic-gate ncomps += mdr->un_ncomp; 1269*0Sstevel@tonic-gate } 1270*0Sstevel@tonic-gate 1271*0Sstevel@tonic-gate recids[0] = 0; 1272*0Sstevel@tonic-gate /* 1273*0Sstevel@tonic-gate * No need of checking size of new device, 1274*0Sstevel@tonic-gate * when hotsparing (it has already been done), or 1275*0Sstevel@tonic-gate * when enabling the device. 1276*0Sstevel@tonic-gate */ 1277*0Sstevel@tonic-gate if ((nd != NULL) && (nd->nd_hs_id == 0)) { 1278*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 1279*0Sstevel@tonic-gate mdr = &un->un_row[row]; 1280*0Sstevel@tonic-gate if ((mdr->un_ncomp + cmpcount) > ci) 1281*0Sstevel@tonic-gate break; 1282*0Sstevel@tonic-gate cmpcount += mdr->un_ncomp; 1283*0Sstevel@tonic-gate } 1284*0Sstevel@tonic-gate ASSERT(row != un->un_nrows); 1285*0Sstevel@tonic-gate 1286*0Sstevel@tonic-gate /* Concatenations have a ncomp = 1 */ 1287*0Sstevel@tonic-gate dev_size = mdr->un_blocks / mdr->un_ncomp; 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate /* 1290*0Sstevel@tonic-gate * now check to see if new comp can be used in 1291*0Sstevel@tonic-gate * place of old comp 1292*0Sstevel@tonic-gate */ 1293*0Sstevel@tonic-gate if ((un->c.un_flag & MD_LABELED) && (ci == 0) && 1294*0Sstevel@tonic-gate nd->nd_labeled) 1295*0Sstevel@tonic-gate nd->nd_start_blk = 0; 1296*0Sstevel@tonic-gate else 1297*0Sstevel@tonic-gate nd->nd_nblks -= nd->nd_start_blk; 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate if (dev_size > nd->nd_nblks) { 1300*0Sstevel@tonic-gate md_unit_writerexit(ui); 1301*0Sstevel@tonic-gate return (MDE_COMP_TOO_SMALL); 1302*0Sstevel@tonic-gate } 1303*0Sstevel@tonic-gate 1304*0Sstevel@tonic-gate sv = (sv_dev_t *)kmem_alloc(sizeof (sv_dev_t), KM_SLEEP); 1305*0Sstevel@tonic-gate sv->setno = MD_MIN2SET(mnum); 1306*0Sstevel@tonic-gate sv->key = comp->un_key; 1307*0Sstevel@tonic-gate } 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate /* 1310*0Sstevel@tonic-gate * Close this component. 1311*0Sstevel@tonic-gate */ 1312*0Sstevel@tonic-gate if (comp->un_mirror.ms_flags & MDM_S_ISOPEN) { 1313*0Sstevel@tonic-gate md_layered_close(comp->un_dev, MD_OFLG_NULL); 1314*0Sstevel@tonic-gate comp->un_mirror.ms_flags &= ~MDM_S_ISOPEN; 1315*0Sstevel@tonic-gate } 1316*0Sstevel@tonic-gate 1317*0Sstevel@tonic-gate /* 1318*0Sstevel@tonic-gate * If the component is hotspared, return to the pool. 1319*0Sstevel@tonic-gate */ 1320*0Sstevel@tonic-gate if (comp->un_mirror.ms_hs_id != 0) { 1321*0Sstevel@tonic-gate hs_cmds_t cmd; 1322*0Sstevel@tonic-gate mdkey_t hs_key; 1323*0Sstevel@tonic-gate 1324*0Sstevel@tonic-gate hs_key = comp->un_mirror.ms_hs_key; 1325*0Sstevel@tonic-gate comp->un_dev = comp->un_mirror.ms_orig_dev; 1326*0Sstevel@tonic-gate comp->un_start_block = comp->un_mirror.ms_orig_blk; 1327*0Sstevel@tonic-gate comp->un_mirror.ms_hs_key = 0; 1328*0Sstevel@tonic-gate comp->un_mirror.ms_hs_id = 0; 1329*0Sstevel@tonic-gate comp->un_mirror.ms_orig_dev = 0; 1330*0Sstevel@tonic-gate 1331*0Sstevel@tonic-gate cmd = HS_FREE; 1332*0Sstevel@tonic-gate if ((comp->un_mirror.ms_state != CS_OKAY) && 1333*0Sstevel@tonic-gate (comp->un_mirror.ms_state != CS_RESYNC)) 1334*0Sstevel@tonic-gate cmd = HS_BAD; 1335*0Sstevel@tonic-gate (void) md_hot_spare_ifc(cmd, un->un_hsp_id, 0, 0, &hs_id, 1336*0Sstevel@tonic-gate &hs_key, NULL, NULL); 1337*0Sstevel@tonic-gate } 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate /* 1340*0Sstevel@tonic-gate * Open by device id; for enable (indicated by a NULL 1341*0Sstevel@tonic-gate * nd pointer), use the existing component info. For 1342*0Sstevel@tonic-gate * replace, use the new device. 1343*0Sstevel@tonic-gate */ 1344*0Sstevel@tonic-gate if (nd == NULL) { 1345*0Sstevel@tonic-gate this_dev = md_resolve_bydevid(mnum, comp->un_dev, comp->un_key); 1346*0Sstevel@tonic-gate /* 1347*0Sstevel@tonic-gate * If someone replaced a new disk in the same slot 1348*0Sstevel@tonic-gate * we get NODEV64 since old device id cannot be 1349*0Sstevel@tonic-gate * resolved. The new devt is obtained from the 1350*0Sstevel@tonic-gate * mddb since devt is going to be unchanged for the 1351*0Sstevel@tonic-gate * enable case. No need to check for multiple 1352*0Sstevel@tonic-gate * keys here because the caller (comp_replace) 1353*0Sstevel@tonic-gate * has already sanity checked it for us. 1354*0Sstevel@tonic-gate */ 1355*0Sstevel@tonic-gate if (this_dev == NODEV64) { 1356*0Sstevel@tonic-gate this_dev = md_getdevnum(setno, side, comp->un_key, 1357*0Sstevel@tonic-gate MD_TRUST_DEVT); 1358*0Sstevel@tonic-gate } 1359*0Sstevel@tonic-gate } else { 1360*0Sstevel@tonic-gate /* 1361*0Sstevel@tonic-gate * If this is a hotspare, save the original dev_t for later 1362*0Sstevel@tonic-gate * use. If this has occured during boot then the value of 1363*0Sstevel@tonic-gate * comp->un_dev will be NODEV64 because of the failure to look 1364*0Sstevel@tonic-gate * up the devid of the device. 1365*0Sstevel@tonic-gate */ 1366*0Sstevel@tonic-gate if (nd->nd_hs_id != 0) 1367*0Sstevel@tonic-gate comp->un_mirror.ms_orig_dev = comp->un_dev; 1368*0Sstevel@tonic-gate this_dev = md_resolve_bydevid(mnum, nd->nd_dev, nd->nd_key); 1369*0Sstevel@tonic-gate } 1370*0Sstevel@tonic-gate 1371*0Sstevel@tonic-gate comp->un_dev = this_dev; 1372*0Sstevel@tonic-gate 1373*0Sstevel@tonic-gate /* 1374*0Sstevel@tonic-gate * Now open the new device if required. Note for a single component 1375*0Sstevel@tonic-gate * stripe it will not be open - leave this for the mirror driver to 1376*0Sstevel@tonic-gate * deal with. 1377*0Sstevel@tonic-gate */ 1378*0Sstevel@tonic-gate if (md_unit_isopen(ui)) { 1379*0Sstevel@tonic-gate if (md_layered_open(mnum, &this_dev, MD_OFLG_NULL)) { 1380*0Sstevel@tonic-gate mddb_recid_t ids[3]; 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate ids[0] = un->c.un_record_id; 1383*0Sstevel@tonic-gate ids[1] = hs_id; 1384*0Sstevel@tonic-gate ids[2] = 0; 1385*0Sstevel@tonic-gate mddb_commitrecs_wrapper(ids); 1386*0Sstevel@tonic-gate if ((nd != NULL) && (nd->nd_hs_id != 0)) { 1387*0Sstevel@tonic-gate /* 1388*0Sstevel@tonic-gate * Revert back to the original device. 1389*0Sstevel@tonic-gate */ 1390*0Sstevel@tonic-gate comp->un_dev = comp->un_mirror.ms_orig_dev; 1391*0Sstevel@tonic-gate 1392*0Sstevel@tonic-gate cmn_err(CE_WARN, 1393*0Sstevel@tonic-gate "md: %s: open error of hotspare %s", 1394*0Sstevel@tonic-gate md_shortname(mnum), 1395*0Sstevel@tonic-gate md_devname(MD_MIN2SET(mnum), nd->nd_dev, 1396*0Sstevel@tonic-gate NULL, 0)); 1397*0Sstevel@tonic-gate SE_NOTIFY(EC_SVM_STATE, ESC_SVM_OPEN_FAIL, 1398*0Sstevel@tonic-gate SVM_TAG_HS, MD_MIN2SET(mnum), nd->nd_dev); 1399*0Sstevel@tonic-gate } 1400*0Sstevel@tonic-gate md_unit_writerexit(ui); 1401*0Sstevel@tonic-gate return (MDE_COMP_OPEN_ERR); 1402*0Sstevel@tonic-gate } 1403*0Sstevel@tonic-gate if (nd != NULL) 1404*0Sstevel@tonic-gate nd->nd_dev = this_dev; 1405*0Sstevel@tonic-gate 1406*0Sstevel@tonic-gate comp->un_mirror.ms_flags |= MDM_S_ISOPEN; 1407*0Sstevel@tonic-gate } 1408*0Sstevel@tonic-gate 1409*0Sstevel@tonic-gate if (nd == NULL) { 1410*0Sstevel@tonic-gate recids[0] = un->c.un_record_id; 1411*0Sstevel@tonic-gate recids[1] = hs_id; 1412*0Sstevel@tonic-gate recids[2] = 0; 1413*0Sstevel@tonic-gate *replace_done = stripe_replace_done; 1414*0Sstevel@tonic-gate return (0); 1415*0Sstevel@tonic-gate } 1416*0Sstevel@tonic-gate 1417*0Sstevel@tonic-gate /* if hot sparing this device */ 1418*0Sstevel@tonic-gate if (nd->nd_hs_id != 0) { 1419*0Sstevel@tonic-gate char devname[MD_MAX_CTDLEN]; 1420*0Sstevel@tonic-gate char hs_devname[MD_MAX_CTDLEN]; 1421*0Sstevel@tonic-gate set_t setno; 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gate comp->un_mirror.ms_hs_id = nd->nd_hs_id; 1424*0Sstevel@tonic-gate comp->un_mirror.ms_hs_key = nd->nd_key; 1425*0Sstevel@tonic-gate 1426*0Sstevel@tonic-gate comp->un_mirror.ms_orig_blk = comp->un_start_block; 1427*0Sstevel@tonic-gate 1428*0Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 1429*0Sstevel@tonic-gate 1430*0Sstevel@tonic-gate (void) md_devname(setno, comp->un_mirror.ms_orig_dev, devname, 1431*0Sstevel@tonic-gate sizeof (devname)); 1432*0Sstevel@tonic-gate (void) md_devname(setno, nd->nd_dev, hs_devname, 1433*0Sstevel@tonic-gate sizeof (hs_devname)); 1434*0Sstevel@tonic-gate 1435*0Sstevel@tonic-gate cmn_err(CE_NOTE, "md: %s: hotspared device %s with %s", 1436*0Sstevel@tonic-gate md_shortname(mnum), devname, hs_devname); 1437*0Sstevel@tonic-gate 1438*0Sstevel@tonic-gate } else { /* replacing the device */ 1439*0Sstevel@tonic-gate comp->un_key = nd->nd_key; 1440*0Sstevel@tonic-gate *replace_data = (void *)sv; 1441*0Sstevel@tonic-gate 1442*0Sstevel@tonic-gate /* 1443*0Sstevel@tonic-gate * For the old device, make sure to reset the parent 1444*0Sstevel@tonic-gate * if it's a metadevice. 1445*0Sstevel@tonic-gate */ 1446*0Sstevel@tonic-gate if (md_getmajor(comp->un_dev) == md_major) { 1447*0Sstevel@tonic-gate minor_t comp_mnum = md_getminor(comp->un_dev); 1448*0Sstevel@tonic-gate md_unit_t *comp_un = MD_UNIT(comp_mnum); 1449*0Sstevel@tonic-gate 1450*0Sstevel@tonic-gate md_reset_parent(comp->un_dev); 1451*0Sstevel@tonic-gate recids[rid++] = MD_RECID(comp_un); 1452*0Sstevel@tonic-gate } 1453*0Sstevel@tonic-gate } 1454*0Sstevel@tonic-gate 1455*0Sstevel@tonic-gate comp->un_dev = nd->nd_dev; 1456*0Sstevel@tonic-gate comp->un_start_block = nd->nd_start_blk; 1457*0Sstevel@tonic-gate 1458*0Sstevel@tonic-gate /* 1459*0Sstevel@tonic-gate * For the new device, make sure to set the parent if it's a 1460*0Sstevel@tonic-gate * metadevice. 1461*0Sstevel@tonic-gate * 1462*0Sstevel@tonic-gate * If we ever support using metadevices as hot spares, this 1463*0Sstevel@tonic-gate * will need to be tested, and possibly moved into the 1464*0Sstevel@tonic-gate * preceding "else" clause, immediately following the parent 1465*0Sstevel@tonic-gate * reset block. For now, it's convenient to leave it here and 1466*0Sstevel@tonic-gate * only compress nd->nd_dev once. 1467*0Sstevel@tonic-gate */ 1468*0Sstevel@tonic-gate if (md_getmajor(comp->un_dev) == md_major) { 1469*0Sstevel@tonic-gate minor_t comp_mnum = md_getminor(comp->un_dev); 1470*0Sstevel@tonic-gate md_unit_t *comp_un = MD_UNIT(comp_mnum); 1471*0Sstevel@tonic-gate 1472*0Sstevel@tonic-gate md_set_parent(comp->un_dev, MD_SID(un)); 1473*0Sstevel@tonic-gate recids[rid++] = MD_RECID(comp_un); 1474*0Sstevel@tonic-gate } 1475*0Sstevel@tonic-gate 1476*0Sstevel@tonic-gate recids[rid++] = un->c.un_record_id; 1477*0Sstevel@tonic-gate recids[rid++] = hs_id; 1478*0Sstevel@tonic-gate recids[rid] = 0; 1479*0Sstevel@tonic-gate *replace_done = stripe_replace_done; 1480*0Sstevel@tonic-gate return (0); 1481*0Sstevel@tonic-gate } 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate /*ARGSUSED*/ 1484*0Sstevel@tonic-gate static intptr_t 1485*0Sstevel@tonic-gate stripe_hotspare_dev( 1486*0Sstevel@tonic-gate md_dev64_t dev, 1487*0Sstevel@tonic-gate void *junk, 1488*0Sstevel@tonic-gate int ci, 1489*0Sstevel@tonic-gate mddb_recid_t *recids, 1490*0Sstevel@tonic-gate int nrecids, 1491*0Sstevel@tonic-gate void (**replace_done)(), 1492*0Sstevel@tonic-gate void **replace_data) 1493*0Sstevel@tonic-gate { 1494*0Sstevel@tonic-gate ms_unit_t *un; 1495*0Sstevel@tonic-gate mdi_unit_t *ui; 1496*0Sstevel@tonic-gate ms_comp_t *comp; 1497*0Sstevel@tonic-gate int row; 1498*0Sstevel@tonic-gate struct ms_row *mdr; 1499*0Sstevel@tonic-gate ms_new_dev_t nd; 1500*0Sstevel@tonic-gate int err; 1501*0Sstevel@tonic-gate int i; 1502*0Sstevel@tonic-gate minor_t mnum; 1503*0Sstevel@tonic-gate set_t setno; 1504*0Sstevel@tonic-gate int cmpcount = 0; 1505*0Sstevel@tonic-gate 1506*0Sstevel@tonic-gate mnum = md_getminor(dev); 1507*0Sstevel@tonic-gate ui = MDI_UNIT(mnum); 1508*0Sstevel@tonic-gate un = MD_UNIT(mnum); 1509*0Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 1510*0Sstevel@tonic-gate 1511*0Sstevel@tonic-gate if (md_get_setstatus(setno) & MD_SET_STALE) 1512*0Sstevel@tonic-gate return (1); 1513*0Sstevel@tonic-gate 1514*0Sstevel@tonic-gate if (un->un_hsp_id == -1) 1515*0Sstevel@tonic-gate return (1); 1516*0Sstevel@tonic-gate 1517*0Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 1518*0Sstevel@tonic-gate mdr = &un->un_row[row]; 1519*0Sstevel@tonic-gate if ((mdr->un_ncomp + cmpcount) > ci) 1520*0Sstevel@tonic-gate break; 1521*0Sstevel@tonic-gate cmpcount += mdr->un_ncomp; 1522*0Sstevel@tonic-gate } 1523*0Sstevel@tonic-gate ASSERT(row != un->un_nrows); 1524*0Sstevel@tonic-gate 1525*0Sstevel@tonic-gate comp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 1526*0Sstevel@tonic-gate comp += ci; 1527*0Sstevel@tonic-gate /* Concatenations have a ncomp = 1 */ 1528*0Sstevel@tonic-gate nd.nd_nblks = mdr->un_blocks / mdr->un_ncomp; 1529*0Sstevel@tonic-gate 1530*0Sstevel@tonic-gate if ((un->c.un_flag & MD_LABELED) && (ci == 0)) 1531*0Sstevel@tonic-gate nd.nd_labeled = 1; 1532*0Sstevel@tonic-gate else 1533*0Sstevel@tonic-gate nd.nd_labeled = 0; 1534*0Sstevel@tonic-gate 1535*0Sstevel@tonic-gate again: 1536*0Sstevel@tonic-gate err = md_hot_spare_ifc(HS_GET, un->un_hsp_id, nd.nd_nblks, 1537*0Sstevel@tonic-gate nd.nd_labeled, &nd.nd_hs_id, &nd.nd_key, &nd.nd_dev, 1538*0Sstevel@tonic-gate &nd.nd_start_blk); 1539*0Sstevel@tonic-gate 1540*0Sstevel@tonic-gate if (err) { 1541*0Sstevel@tonic-gate if (!stripe_replace_dev(dev, junk, ci, NULL, recids, nrecids, 1542*0Sstevel@tonic-gate replace_done, replace_data)) { 1543*0Sstevel@tonic-gate mddb_commitrecs_wrapper(recids); 1544*0Sstevel@tonic-gate md_unit_writerexit(ui); 1545*0Sstevel@tonic-gate } 1546*0Sstevel@tonic-gate recids[0] = 0; 1547*0Sstevel@tonic-gate return (1); 1548*0Sstevel@tonic-gate } 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate if (stripe_replace_dev(dev, junk, ci, &nd, recids, nrecids, 1551*0Sstevel@tonic-gate replace_done, replace_data)) { 1552*0Sstevel@tonic-gate 1553*0Sstevel@tonic-gate (void) md_hot_spare_ifc(HS_BAD, un->un_hsp_id, 0, 0, 1554*0Sstevel@tonic-gate &nd.nd_hs_id, &nd.nd_key, NULL, NULL); 1555*0Sstevel@tonic-gate mddb_commitrec_wrapper(nd.nd_hs_id); 1556*0Sstevel@tonic-gate goto again; 1557*0Sstevel@tonic-gate } 1558*0Sstevel@tonic-gate 1559*0Sstevel@tonic-gate /* Leave a slot for the null recid */ 1560*0Sstevel@tonic-gate for (i = 0; i < (nrecids - 1); i++) { 1561*0Sstevel@tonic-gate if (recids[i] == 0) { 1562*0Sstevel@tonic-gate recids[i++] = nd.nd_hs_id; 1563*0Sstevel@tonic-gate recids[i] = 0; 1564*0Sstevel@tonic-gate } 1565*0Sstevel@tonic-gate } 1566*0Sstevel@tonic-gate return (0); 1567*0Sstevel@tonic-gate } 1568*0Sstevel@tonic-gate 1569*0Sstevel@tonic-gate static int 1570*0Sstevel@tonic-gate stripe_imp_set( 1571*0Sstevel@tonic-gate set_t setno 1572*0Sstevel@tonic-gate ) 1573*0Sstevel@tonic-gate { 1574*0Sstevel@tonic-gate 1575*0Sstevel@tonic-gate mddb_recid_t recid; 1576*0Sstevel@tonic-gate int i, row, c, gotsomething; 1577*0Sstevel@tonic-gate mddb_type_t typ1; 1578*0Sstevel@tonic-gate mddb_de_ic_t *dep; 1579*0Sstevel@tonic-gate mddb_rb32_t *rbp; 1580*0Sstevel@tonic-gate ms_unit32_od_t *un32; 1581*0Sstevel@tonic-gate ms_unit_t *un64; 1582*0Sstevel@tonic-gate minor_t *self_id; /* minor needs to be updated */ 1583*0Sstevel@tonic-gate md_parent_t *parent_id; /* parent needs to be updated */ 1584*0Sstevel@tonic-gate mddb_recid_t *record_id; /* record id needs to be updated */ 1585*0Sstevel@tonic-gate mddb_recid_t *hsp_id; 1586*0Sstevel@tonic-gate ms_comp32_od_t *comp32; 1587*0Sstevel@tonic-gate ms_comp_t *comp64; 1588*0Sstevel@tonic-gate 1589*0Sstevel@tonic-gate 1590*0Sstevel@tonic-gate gotsomething = 0; 1591*0Sstevel@tonic-gate 1592*0Sstevel@tonic-gate typ1 = (mddb_type_t)md_getshared_key(setno, 1593*0Sstevel@tonic-gate stripe_md_ops.md_driver.md_drivername); 1594*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 1595*0Sstevel@tonic-gate 1596*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, 0)) > 0) { 1597*0Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_GOTIT) 1598*0Sstevel@tonic-gate continue; 1599*0Sstevel@tonic-gate 1600*0Sstevel@tonic-gate dep = mddb_getrecdep(recid); 1601*0Sstevel@tonic-gate rbp = dep->de_rb; 1602*0Sstevel@tonic-gate 1603*0Sstevel@tonic-gate if (rbp->rb_revision == MDDB_REV_RB) { 1604*0Sstevel@tonic-gate /* 1605*0Sstevel@tonic-gate * Small device 1606*0Sstevel@tonic-gate */ 1607*0Sstevel@tonic-gate un32 = (ms_unit32_od_t *)mddb_getrecaddr(recid); 1608*0Sstevel@tonic-gate self_id = &(un32->c.un_self_id); 1609*0Sstevel@tonic-gate parent_id = &(un32->c.un_parent); 1610*0Sstevel@tonic-gate record_id = &(un32->c.un_record_id); 1611*0Sstevel@tonic-gate hsp_id = &(un32->un_hsp_id); 1612*0Sstevel@tonic-gate 1613*0Sstevel@tonic-gate comp32 = (ms_comp32_od_t *)((void *)&((char *)un32) 1614*0Sstevel@tonic-gate [un32->un_ocomp]); 1615*0Sstevel@tonic-gate for (row = 0; row < un32->un_nrows; row++) { 1616*0Sstevel@tonic-gate struct ms_row32_od *mdr = &un32->un_row[row]; 1617*0Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; 1618*0Sstevel@tonic-gate i < mdr->un_ncomp; i++) { 1619*0Sstevel@tonic-gate ms_comp32_od_t *mdc; 1620*0Sstevel@tonic-gate mdc = &comp32[c++]; 1621*0Sstevel@tonic-gate 1622*0Sstevel@tonic-gate if (!md_update_minor(setno, mddb_getsidenum 1623*0Sstevel@tonic-gate (setno), mdc->un_key)) 1624*0Sstevel@tonic-gate goto out; 1625*0Sstevel@tonic-gate 1626*0Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) 1627*0Sstevel@tonic-gate mdc->un_mirror.ms_hs_id = MAKERECID( 1628*0Sstevel@tonic-gate setno, mdc->un_mirror.ms_hs_id); 1629*0Sstevel@tonic-gate } 1630*0Sstevel@tonic-gate } 1631*0Sstevel@tonic-gate } else { 1632*0Sstevel@tonic-gate un64 = (ms_unit_t *)mddb_getrecaddr(recid); 1633*0Sstevel@tonic-gate self_id = &(un64->c.un_self_id); 1634*0Sstevel@tonic-gate parent_id = &(un64->c.un_parent); 1635*0Sstevel@tonic-gate record_id = &(un64->c.un_record_id); 1636*0Sstevel@tonic-gate hsp_id = &(un64->un_hsp_id); 1637*0Sstevel@tonic-gate 1638*0Sstevel@tonic-gate comp64 = (ms_comp_t *)((void *)&((char *)un64) 1639*0Sstevel@tonic-gate [un64->un_ocomp]); 1640*0Sstevel@tonic-gate for (row = 0; row < un64->un_nrows; row++) { 1641*0Sstevel@tonic-gate struct ms_row *mdr = &un64->un_row[row]; 1642*0Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; 1643*0Sstevel@tonic-gate i < mdr->un_ncomp; i++) { 1644*0Sstevel@tonic-gate ms_comp_t *mdc; 1645*0Sstevel@tonic-gate mdc = &comp64[c++]; 1646*0Sstevel@tonic-gate 1647*0Sstevel@tonic-gate if (!md_update_minor(setno, mddb_getsidenum 1648*0Sstevel@tonic-gate (setno), mdc->un_key)) 1649*0Sstevel@tonic-gate goto out; 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) 1652*0Sstevel@tonic-gate mdc->un_mirror.ms_hs_id = MAKERECID( 1653*0Sstevel@tonic-gate setno, mdc->un_mirror.ms_hs_id); 1654*0Sstevel@tonic-gate } 1655*0Sstevel@tonic-gate } 1656*0Sstevel@tonic-gate } 1657*0Sstevel@tonic-gate 1658*0Sstevel@tonic-gate /* 1659*0Sstevel@tonic-gate * Update unit with the imported setno 1660*0Sstevel@tonic-gate * 1661*0Sstevel@tonic-gate */ 1662*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT); 1663*0Sstevel@tonic-gate 1664*0Sstevel@tonic-gate *self_id = MD_MKMIN(setno, MD_MIN2UNIT(*self_id)); 1665*0Sstevel@tonic-gate 1666*0Sstevel@tonic-gate if (*hsp_id != -1) 1667*0Sstevel@tonic-gate *hsp_id = MAKERECID(setno, DBID(*hsp_id)); 1668*0Sstevel@tonic-gate 1669*0Sstevel@tonic-gate if (*parent_id != MD_NO_PARENT) 1670*0Sstevel@tonic-gate *parent_id = MD_MKMIN(setno, MD_MIN2UNIT(*parent_id)); 1671*0Sstevel@tonic-gate *record_id = MAKERECID(setno, DBID(*record_id)); 1672*0Sstevel@tonic-gate 1673*0Sstevel@tonic-gate gotsomething = 1; 1674*0Sstevel@tonic-gate } 1675*0Sstevel@tonic-gate 1676*0Sstevel@tonic-gate out: 1677*0Sstevel@tonic-gate return (gotsomething); 1678*0Sstevel@tonic-gate } 1679*0Sstevel@tonic-gate 1680*0Sstevel@tonic-gate static md_named_services_t stripe_named_services[] = { 1681*0Sstevel@tonic-gate {stripe_shared_by_blk, "shared by blk" }, 1682*0Sstevel@tonic-gate {stripe_shared_by_indx, "shared by indx" }, 1683*0Sstevel@tonic-gate {stripe_component_count, "get component count" }, 1684*0Sstevel@tonic-gate {stripe_block_count_skip_size, "get block count skip size" }, 1685*0Sstevel@tonic-gate {stripe_get_dev, "get device" }, 1686*0Sstevel@tonic-gate {stripe_replace_dev, "replace device" }, 1687*0Sstevel@tonic-gate {stripe_hotspare_dev, "hotspare device" }, 1688*0Sstevel@tonic-gate {stripe_rename_check, MDRNM_CHECK }, 1689*0Sstevel@tonic-gate {NULL, 0} 1690*0Sstevel@tonic-gate }; 1691*0Sstevel@tonic-gate 1692*0Sstevel@tonic-gate md_ops_t stripe_md_ops = { 1693*0Sstevel@tonic-gate stripe_open, /* open */ 1694*0Sstevel@tonic-gate stripe_close, /* close */ 1695*0Sstevel@tonic-gate md_stripe_strategy, /* strategy */ 1696*0Sstevel@tonic-gate NULL, /* print */ 1697*0Sstevel@tonic-gate stripe_dump, /* dump */ 1698*0Sstevel@tonic-gate NULL, /* read */ 1699*0Sstevel@tonic-gate NULL, /* write */ 1700*0Sstevel@tonic-gate md_stripe_ioctl, /* stripe_ioctl, */ 1701*0Sstevel@tonic-gate stripe_snarf, /* stripe_snarf */ 1702*0Sstevel@tonic-gate stripe_halt, /* stripe_halt */ 1703*0Sstevel@tonic-gate NULL, /* aread */ 1704*0Sstevel@tonic-gate NULL, /* awrite */ 1705*0Sstevel@tonic-gate stripe_imp_set, /* import set */ 1706*0Sstevel@tonic-gate stripe_named_services 1707*0Sstevel@tonic-gate }; 1708*0Sstevel@tonic-gate 1709*0Sstevel@tonic-gate static void 1710*0Sstevel@tonic-gate init_init() 1711*0Sstevel@tonic-gate { 1712*0Sstevel@tonic-gate md_stripe_mcs_buf_off = sizeof (md_scs_t) - sizeof (buf_t); 1713*0Sstevel@tonic-gate 1714*0Sstevel@tonic-gate stripe_parent_cache = kmem_cache_create("md_stripe_parent", 1715*0Sstevel@tonic-gate sizeof (md_sps_t), 0, stripe_parent_constructor, 1716*0Sstevel@tonic-gate stripe_parent_destructor, stripe_run_queue, NULL, NULL, 1717*0Sstevel@tonic-gate 0); 1718*0Sstevel@tonic-gate stripe_child_cache = kmem_cache_create("md_stripe_child", 1719*0Sstevel@tonic-gate sizeof (md_scs_t) - sizeof (buf_t) + biosize(), 0, 1720*0Sstevel@tonic-gate stripe_child_constructor, stripe_child_destructor, 1721*0Sstevel@tonic-gate stripe_run_queue, NULL, NULL, 0); 1722*0Sstevel@tonic-gate } 1723*0Sstevel@tonic-gate 1724*0Sstevel@tonic-gate static void 1725*0Sstevel@tonic-gate fini_uninit() 1726*0Sstevel@tonic-gate { 1727*0Sstevel@tonic-gate kmem_cache_destroy(stripe_parent_cache); 1728*0Sstevel@tonic-gate kmem_cache_destroy(stripe_child_cache); 1729*0Sstevel@tonic-gate stripe_parent_cache = stripe_child_cache = NULL; 1730*0Sstevel@tonic-gate } 1731*0Sstevel@tonic-gate 1732*0Sstevel@tonic-gate /* define the module linkage */ 1733*0Sstevel@tonic-gate MD_PLUGIN_MISC_MODULE("stripes module %I%", init_init(), fini_uninit()) 1734