10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1366Spetede * Common Development and Distribution License (the "License"). 6*1366Spetede * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1366Spetede * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/param.h> 290Sstevel@tonic-gate #include <sys/systm.h> 300Sstevel@tonic-gate #include <sys/conf.h> 310Sstevel@tonic-gate #include <sys/file.h> 320Sstevel@tonic-gate #include <sys/user.h> 330Sstevel@tonic-gate #include <sys/uio.h> 340Sstevel@tonic-gate #include <sys/t_lock.h> 350Sstevel@tonic-gate #include <sys/buf.h> 360Sstevel@tonic-gate #include <sys/dkio.h> 370Sstevel@tonic-gate #include <sys/vtoc.h> 380Sstevel@tonic-gate #include <sys/kmem.h> 390Sstevel@tonic-gate #include <vm/page.h> 400Sstevel@tonic-gate #include <sys/cmn_err.h> 410Sstevel@tonic-gate #include <sys/sysmacros.h> 420Sstevel@tonic-gate #include <sys/types.h> 430Sstevel@tonic-gate #include <sys/mkdev.h> 440Sstevel@tonic-gate #include <sys/stat.h> 450Sstevel@tonic-gate #include <sys/open.h> 460Sstevel@tonic-gate #include <sys/lvm/mdio.h> 470Sstevel@tonic-gate #include <sys/lvm/mdvar.h> 480Sstevel@tonic-gate #include <sys/lvm/md_stripe.h> 490Sstevel@tonic-gate #include <sys/lvm/md_convert.h> 500Sstevel@tonic-gate #include <sys/lvm/md_notify.h> 510Sstevel@tonic-gate #include <sys/modctl.h> 520Sstevel@tonic-gate #include <sys/ddi.h> 530Sstevel@tonic-gate #include <sys/sunddi.h> 540Sstevel@tonic-gate #include <sys/debug.h> 550Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h> 560Sstevel@tonic-gate #include <sys/sysevent/svm.h> 570Sstevel@tonic-gate 580Sstevel@tonic-gate md_ops_t stripe_md_ops; 590Sstevel@tonic-gate #ifndef lint 60*1366Spetede char _depends_on[] = "drv/md"; 610Sstevel@tonic-gate static md_ops_t *md_interface_ops = &stripe_md_ops; 620Sstevel@tonic-gate #endif 630Sstevel@tonic-gate 640Sstevel@tonic-gate extern unit_t md_nunits; 650Sstevel@tonic-gate extern set_t md_nsets; 660Sstevel@tonic-gate extern md_set_t md_set[]; 670Sstevel@tonic-gate 680Sstevel@tonic-gate extern kmutex_t md_mx; 690Sstevel@tonic-gate extern kcondvar_t md_cv; 700Sstevel@tonic-gate 710Sstevel@tonic-gate extern int md_status; 720Sstevel@tonic-gate extern major_t md_major; 730Sstevel@tonic-gate extern mdq_anchor_t md_done_daemon; 740Sstevel@tonic-gate 750Sstevel@tonic-gate static int md_stripe_mcs_buf_off; 760Sstevel@tonic-gate static kmem_cache_t *stripe_parent_cache = NULL; 770Sstevel@tonic-gate static kmem_cache_t *stripe_child_cache = NULL; 780Sstevel@tonic-gate 790Sstevel@tonic-gate /*ARGSUSED1*/ 800Sstevel@tonic-gate static int 810Sstevel@tonic-gate stripe_parent_constructor(void *p, void *d1, int d2) 820Sstevel@tonic-gate { 830Sstevel@tonic-gate mutex_init(&((md_sps_t *)p)->ps_mx, 840Sstevel@tonic-gate NULL, MUTEX_DEFAULT, NULL); 850Sstevel@tonic-gate return (0); 860Sstevel@tonic-gate } 870Sstevel@tonic-gate 880Sstevel@tonic-gate static void 890Sstevel@tonic-gate stripe_parent_init(void *ps) 900Sstevel@tonic-gate { 910Sstevel@tonic-gate bzero(ps, offsetof(md_sps_t, ps_mx)); 920Sstevel@tonic-gate } 930Sstevel@tonic-gate 940Sstevel@tonic-gate /*ARGSUSED1*/ 950Sstevel@tonic-gate static void 960Sstevel@tonic-gate stripe_parent_destructor(void *p, void *d) 970Sstevel@tonic-gate { 980Sstevel@tonic-gate mutex_destroy(&((md_sps_t *)p)->ps_mx); 990Sstevel@tonic-gate } 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate /*ARGSUSED1*/ 1020Sstevel@tonic-gate static int 1030Sstevel@tonic-gate stripe_child_constructor(void *p, void *d1, int d2) 1040Sstevel@tonic-gate { 1050Sstevel@tonic-gate bioinit(&((md_scs_t *)p)->cs_buf); 1060Sstevel@tonic-gate return (0); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate static void 1100Sstevel@tonic-gate stripe_child_init(md_scs_t *cs) 1110Sstevel@tonic-gate { 1120Sstevel@tonic-gate cs->cs_mdunit = 0; 1130Sstevel@tonic-gate cs->cs_ps = NULL; 1140Sstevel@tonic-gate cs->cs_comp = NULL; 1150Sstevel@tonic-gate md_bioreset(&cs->cs_buf); 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /*ARGSUSED1*/ 1190Sstevel@tonic-gate static void 1200Sstevel@tonic-gate stripe_child_destructor(void *p, void *d) 1210Sstevel@tonic-gate { 1220Sstevel@tonic-gate biofini(&((md_scs_t *)p)->cs_buf); 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate /*ARGSUSED*/ 1260Sstevel@tonic-gate static void 1270Sstevel@tonic-gate stripe_run_queue(void *d) 1280Sstevel@tonic-gate { 1290Sstevel@tonic-gate if (!(md_status & MD_GBL_DAEMONS_LIVE)) 1300Sstevel@tonic-gate md_daemon(1, &md_done_daemon); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate static void 1340Sstevel@tonic-gate stripe_close_all_devs(ms_unit_t *un, int md_cflags) 1350Sstevel@tonic-gate { 1360Sstevel@tonic-gate int row; 1370Sstevel@tonic-gate int i; 1380Sstevel@tonic-gate int c; 1390Sstevel@tonic-gate struct ms_comp *mdcomp; 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 1420Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 1430Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 1440Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) { 1450Sstevel@tonic-gate struct ms_comp *mdc; 1460Sstevel@tonic-gate mdc = &mdcomp[c++]; 1470Sstevel@tonic-gate if (md_cflags & MD_OFLG_PROBEDEV) { 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate /* 1500Sstevel@tonic-gate * It is possible that the md_layered_open 1510Sstevel@tonic-gate * failed because the stripe unit structure 1520Sstevel@tonic-gate * contained a NODEV. In such a case since 1530Sstevel@tonic-gate * there is nothing to open, there is nothing 1540Sstevel@tonic-gate * to close. 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate if (mdc->un_dev == NODEV64) 1570Sstevel@tonic-gate continue; 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate if ((md_cflags & MD_OFLG_PROBEDEV) && 1600Sstevel@tonic-gate (mdc->un_mirror.ms_flags & MDM_S_PROBEOPEN)) { 1610Sstevel@tonic-gate md_layered_close(mdc->un_dev, 1620Sstevel@tonic-gate md_cflags); 1630Sstevel@tonic-gate mdc->un_mirror.ms_flags &= 1640Sstevel@tonic-gate ~MDM_S_PROBEOPEN; 1650Sstevel@tonic-gate } else if (mdc->un_mirror.ms_flags & MDM_S_ISOPEN) { 1660Sstevel@tonic-gate md_layered_close(mdc->un_dev, md_cflags); 1670Sstevel@tonic-gate mdc->un_mirror.ms_flags &= ~MDM_S_ISOPEN; 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate static int 1740Sstevel@tonic-gate stripe_open_all_devs(ms_unit_t *un, int md_oflags) 1750Sstevel@tonic-gate { 1760Sstevel@tonic-gate minor_t mnum = MD_SID(un); 1770Sstevel@tonic-gate int row; 1780Sstevel@tonic-gate int i; 1790Sstevel@tonic-gate int c; 1800Sstevel@tonic-gate struct ms_comp *mdcomp; 1810Sstevel@tonic-gate int err; 1820Sstevel@tonic-gate int cont_on_errors = (md_oflags & MD_OFLG_CONT_ERRS); 1830Sstevel@tonic-gate int probe_err_cnt = 0; 1840Sstevel@tonic-gate int total_comp_cnt = 0; 1850Sstevel@tonic-gate set_t setno = MD_MIN2SET(MD_SID(un)); 1860Sstevel@tonic-gate side_t side = mddb_getsidenum(setno); 1870Sstevel@tonic-gate mdkey_t key; 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate /* 1920Sstevel@tonic-gate * For a probe call, if any component of a stripe or a concat 1930Sstevel@tonic-gate * can be opened, it is considered to be a success. The total number 1940Sstevel@tonic-gate * of components in a stripe are computed prior to starting a probe. 1950Sstevel@tonic-gate * This number is then compared against the number of components 1960Sstevel@tonic-gate * that could be be successfully opened. If none of the components 1970Sstevel@tonic-gate * in a stripe can be opened, only then an ENXIO is returned for a 1980Sstevel@tonic-gate * probe type open. 1990Sstevel@tonic-gate */ 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 2020Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate if (md_oflags & MD_OFLG_PROBEDEV) 2050Sstevel@tonic-gate total_comp_cnt += mdr->un_ncomp; 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) { 2080Sstevel@tonic-gate struct ms_comp *mdc; 2090Sstevel@tonic-gate md_dev64_t tmpdev; 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate mdc = &mdcomp[c++]; 2120Sstevel@tonic-gate tmpdev = mdc->un_dev; 2130Sstevel@tonic-gate /* 2140Sstevel@tonic-gate * Do the open by device id 2150Sstevel@tonic-gate * Check if this comp is hotspared and 2160Sstevel@tonic-gate * if it is then use the key for hotspare. 2170Sstevel@tonic-gate * MN disksets don't use devids, so we better don't use 2180Sstevel@tonic-gate * md_devid_found/md_resolve_bydevid there. Rather do, 2190Sstevel@tonic-gate * what's done in stripe_build_incore() 2200Sstevel@tonic-gate */ 2210Sstevel@tonic-gate if (MD_MNSET_SETNO(setno)) { 2220Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) { 2230Sstevel@tonic-gate (void) md_hot_spare_ifc(HS_MKDEV, 0, 0, 2240Sstevel@tonic-gate 0, &mdc->un_mirror.ms_hs_id, NULL, 2250Sstevel@tonic-gate &tmpdev, NULL); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate } else { 2280Sstevel@tonic-gate key = mdc->un_mirror.ms_hs_id ? 2290Sstevel@tonic-gate mdc->un_mirror.ms_hs_key : mdc->un_key; 2300Sstevel@tonic-gate if ((md_getmajor(tmpdev) != md_major) && 2310Sstevel@tonic-gate md_devid_found(setno, side, key) == 1) { 2320Sstevel@tonic-gate tmpdev = md_resolve_bydevid(mnum, 2330Sstevel@tonic-gate tmpdev, key); 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate /* 2380Sstevel@tonic-gate * For a submirror, we only want to open those devices 2390Sstevel@tonic-gate * that are not errored. If the device is errored then 2400Sstevel@tonic-gate * then there is no reason to open it and leaving it 2410Sstevel@tonic-gate * closed allows the RCM/DR code to work so that the 2420Sstevel@tonic-gate * errored device can be replaced. 2430Sstevel@tonic-gate */ 2440Sstevel@tonic-gate if ((md_oflags & MD_OFLG_PROBEDEV) || 2450Sstevel@tonic-gate ! (mdc->un_mirror.ms_state & CS_ERRED)) { 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate err = md_layered_open(mnum, &tmpdev, md_oflags); 2480Sstevel@tonic-gate } else { 2490Sstevel@tonic-gate err = ENXIO; 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate /* 2530Sstevel@tonic-gate * Only set the un_dev if the tmpdev != NODEV64. If 2540Sstevel@tonic-gate * it is NODEV64 then the md_layered_open() will have 2550Sstevel@tonic-gate * failed in some manner. 2560Sstevel@tonic-gate */ 2570Sstevel@tonic-gate if (tmpdev != NODEV64) 2580Sstevel@tonic-gate mdc->un_dev = tmpdev; 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate if (err) { 2610Sstevel@tonic-gate if (!cont_on_errors) { 2620Sstevel@tonic-gate stripe_close_all_devs(un, md_oflags); 2630Sstevel@tonic-gate return (ENXIO); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate if (md_oflags & MD_OFLG_PROBEDEV) 2670Sstevel@tonic-gate probe_err_cnt++; 2680Sstevel@tonic-gate } else { 2690Sstevel@tonic-gate if (md_oflags & MD_OFLG_PROBEDEV) { 2700Sstevel@tonic-gate mdc->un_mirror.ms_flags |= 2710Sstevel@tonic-gate MDM_S_PROBEOPEN; 2720Sstevel@tonic-gate } else 2730Sstevel@tonic-gate mdc->un_mirror.ms_flags |= MDM_S_ISOPEN; 2740Sstevel@tonic-gate } 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate /* If every component in a stripe could not be opened fail */ 2790Sstevel@tonic-gate if ((md_oflags & MD_OFLG_PROBEDEV) && 2800Sstevel@tonic-gate (probe_err_cnt == total_comp_cnt)) 2810Sstevel@tonic-gate return (ENXIO); 2820Sstevel@tonic-gate else 2830Sstevel@tonic-gate return (0); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate int 2870Sstevel@tonic-gate stripe_build_incore(void *p, int snarfing) 2880Sstevel@tonic-gate { 2890Sstevel@tonic-gate ms_unit_t *un = (ms_unit_t *)p; 2900Sstevel@tonic-gate struct ms_comp *mdcomp; 2910Sstevel@tonic-gate minor_t mnum; 2920Sstevel@tonic-gate int row; 2930Sstevel@tonic-gate int i; 2940Sstevel@tonic-gate int c; 2950Sstevel@tonic-gate int ncomps; 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate mnum = MD_SID(un); 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate if (MD_UNIT(mnum) != NULL) 3000Sstevel@tonic-gate return (0); 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate MD_STATUS(un) = 0; 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate /* 3050Sstevel@tonic-gate * Reset all the is_open flags, these are probably set 3060Sstevel@tonic-gate * cause they just came out of the database. 3070Sstevel@tonic-gate */ 3080Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate ncomps = 0; 3110Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 3120Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 3130Sstevel@tonic-gate ncomps += mdr->un_ncomp; 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 3170Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 3180Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) { 3190Sstevel@tonic-gate struct ms_comp *mdc; 3200Sstevel@tonic-gate set_t setno; 3210Sstevel@tonic-gate md_dev64_t tmpdev; 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate mdc = &mdcomp[c++]; 3240Sstevel@tonic-gate mdc->un_mirror.ms_flags &= 3250Sstevel@tonic-gate ~(MDM_S_ISOPEN | MDM_S_IOERR | MDM_S_RS_TRIED); 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate if (!snarfing) 3280Sstevel@tonic-gate continue; 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate tmpdev = md_getdevnum(setno, mddb_getsidenum(setno), 3330Sstevel@tonic-gate mdc->un_key, MD_NOTRUST_DEVT); 3340Sstevel@tonic-gate mdc->un_dev = tmpdev; 3350Sstevel@tonic-gate /* 3360Sstevel@tonic-gate * Check for hotspares. If the hotspares haven't been 3370Sstevel@tonic-gate * snarfed yet, stripe_open_all_devs() will do the 3380Sstevel@tonic-gate * remapping of the dev's later. 3390Sstevel@tonic-gate */ 3400Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) { 3410Sstevel@tonic-gate mdc->un_mirror.ms_orig_dev = mdc->un_dev; 3420Sstevel@tonic-gate (void) md_hot_spare_ifc(HS_MKDEV, 0, 0, 3430Sstevel@tonic-gate 0, &mdc->un_mirror.ms_hs_id, NULL, 3440Sstevel@tonic-gate &tmpdev, NULL); 3450Sstevel@tonic-gate mdc->un_dev = tmpdev; 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate 3500Sstevel@tonic-gate MD_UNIT(mnum) = un; 3510Sstevel@tonic-gate return (0); 3520Sstevel@tonic-gate } 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate void 3550Sstevel@tonic-gate reset_stripe(ms_unit_t *un, minor_t mnum, int removing) 3560Sstevel@tonic-gate { 3570Sstevel@tonic-gate ms_comp_t *mdcomp; 3580Sstevel@tonic-gate struct ms_row *mdr; 3590Sstevel@tonic-gate int i, c; 3600Sstevel@tonic-gate int row; 3610Sstevel@tonic-gate int nsv; 3620Sstevel@tonic-gate int isv; 3630Sstevel@tonic-gate sv_dev_t *sv; 3640Sstevel@tonic-gate mddb_recid_t *recids; 3650Sstevel@tonic-gate mddb_recid_t vtoc_id; 3660Sstevel@tonic-gate int rid = 0; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate md_destroy_unit_incore(mnum, &stripe_md_ops); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate MD_UNIT(mnum) = NULL; 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate if (!removing) 3730Sstevel@tonic-gate return; 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate nsv = 0; 3760Sstevel@tonic-gate /* Count the number of devices */ 3770Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 3780Sstevel@tonic-gate mdr = &un->un_row[row]; 3790Sstevel@tonic-gate nsv += mdr->un_ncomp; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate sv = (sv_dev_t *)kmem_alloc(sizeof (sv_dev_t) * nsv, KM_SLEEP); 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* 3840Sstevel@tonic-gate * allocate recids array. since we may have to commit 3850Sstevel@tonic-gate * underlying soft partition records, we need an array 3860Sstevel@tonic-gate * of size: total number of components in stripe + 3 3870Sstevel@tonic-gate * (one for the stripe itself, one for the hotspare, one 3880Sstevel@tonic-gate * for the end marker). 3890Sstevel@tonic-gate */ 3900Sstevel@tonic-gate recids = kmem_alloc(sizeof (mddb_recid_t) * (nsv + 3), KM_SLEEP); 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate /* 3930Sstevel@tonic-gate * Save the md_dev64_t's and driver nm indexes. 3940Sstevel@tonic-gate * Because after the mddb_deleterec() we will 3950Sstevel@tonic-gate * not be able to access the unit structure. 3960Sstevel@tonic-gate * 3970Sstevel@tonic-gate * NOTE: Deleting the names before deleting the 3980Sstevel@tonic-gate * unit structure would cause problems if 3990Sstevel@tonic-gate * the machine crashed in between the two. 4000Sstevel@tonic-gate */ 4010Sstevel@tonic-gate isv = 0; 4020Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 4050Sstevel@tonic-gate mdr = &un->un_row[row]; 4060Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) { 4070Sstevel@tonic-gate struct ms_comp *mdc; 4080Sstevel@tonic-gate md_dev64_t child_dev; 4090Sstevel@tonic-gate md_unit_t *child_un; 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate mdc = &mdcomp[c++]; 4120Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) { 4130Sstevel@tonic-gate mdkey_t hs_key; 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate hs_key = mdc->un_mirror.ms_hs_key; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate mdc->un_dev = mdc->un_mirror.ms_orig_dev; 4180Sstevel@tonic-gate mdc->un_start_block = 4190Sstevel@tonic-gate mdc->un_mirror.ms_orig_blk; 4200Sstevel@tonic-gate mdc->un_mirror.ms_hs_id = 0; 4210Sstevel@tonic-gate mdc->un_mirror.ms_hs_key = 0; 4220Sstevel@tonic-gate mdc->un_mirror.ms_orig_dev = 0; 4230Sstevel@tonic-gate recids[0] = 0; 4240Sstevel@tonic-gate recids[1] = 0; /* recids[1] filled in below */ 4250Sstevel@tonic-gate recids[2] = 0; 4260Sstevel@tonic-gate (void) md_hot_spare_ifc(HS_FREE, un->un_hsp_id, 4270Sstevel@tonic-gate 0, 0, &recids[0], &hs_key, NULL, NULL); 4280Sstevel@tonic-gate mddb_commitrecs_wrapper(recids); 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * check if we've got metadevice below us and 4330Sstevel@tonic-gate * deparent it if we do. 4340Sstevel@tonic-gate * NOTE: currently soft partitions are the 4350Sstevel@tonic-gate * the only metadevices stripes can be 4360Sstevel@tonic-gate * built on top of. 4370Sstevel@tonic-gate */ 4380Sstevel@tonic-gate child_dev = mdc->un_dev; 4390Sstevel@tonic-gate if (md_getmajor(child_dev) == md_major) { 4400Sstevel@tonic-gate child_un = MD_UNIT(md_getminor(child_dev)); 4410Sstevel@tonic-gate md_reset_parent(child_dev); 4420Sstevel@tonic-gate recids[rid++] = MD_RECID(child_un); 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate sv[isv].setno = MD_MIN2SET(mnum); 4460Sstevel@tonic-gate sv[isv++].key = mdc->un_key; 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate } 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate recids[rid++] = un->c.un_record_id; 4510Sstevel@tonic-gate recids[rid] = 0; /* filled in below */ 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate /* 4540Sstevel@tonic-gate * Decrement the HSP reference count and 4550Sstevel@tonic-gate * remove the knowledge of the HSP from the unit struct. 4560Sstevel@tonic-gate * This is done atomically to remove a window. 4570Sstevel@tonic-gate */ 4580Sstevel@tonic-gate if (un->un_hsp_id != -1) { 4590Sstevel@tonic-gate (void) md_hot_spare_ifc(HSP_DECREF, un->un_hsp_id, 0, 0, 4600Sstevel@tonic-gate &recids[rid++], NULL, NULL, NULL); 4610Sstevel@tonic-gate un->un_hsp_id = -1; 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate /* set end marker and commit records */ 4650Sstevel@tonic-gate recids[rid] = 0; 4660Sstevel@tonic-gate mddb_commitrecs_wrapper(recids); 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate vtoc_id = un->c.un_vtoc_id; 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate /* Remove the unit structure */ 4710Sstevel@tonic-gate mddb_deleterec_wrapper(un->c.un_record_id); 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate /* Remove the vtoc, if present */ 4740Sstevel@tonic-gate if (vtoc_id) 4750Sstevel@tonic-gate mddb_deleterec_wrapper(vtoc_id); 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_DELETE, SVM_TAG_METADEVICE, 4780Sstevel@tonic-gate MD_MIN2SET(mnum), MD_MIN2UNIT(mnum)); 4790Sstevel@tonic-gate md_rem_names(sv, nsv); 4800Sstevel@tonic-gate kmem_free(sv, sizeof (sv_dev_t) * nsv); 4810Sstevel@tonic-gate kmem_free(recids, sizeof (mddb_recid_t) * (nsv + 3)); 4820Sstevel@tonic-gate } 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate static void 4850Sstevel@tonic-gate stripe_error(md_sps_t *ps) 4860Sstevel@tonic-gate { 4870Sstevel@tonic-gate struct buf *pb = ps->ps_bp; 4880Sstevel@tonic-gate mdi_unit_t *ui = ps->ps_ui; 4890Sstevel@tonic-gate md_dev64_t dev = ps->ps_errcomp->un_dev; 4900Sstevel@tonic-gate md_dev64_t md_dev = md_expldev(pb->b_edev); 4910Sstevel@tonic-gate char *str; 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate if (pb->b_flags & B_READ) { 4940Sstevel@tonic-gate ps->ps_errcomp->un_mirror.ms_flags |= MDM_S_READERR; 4950Sstevel@tonic-gate str = "read"; 4960Sstevel@tonic-gate } else { 4970Sstevel@tonic-gate ps->ps_errcomp->un_mirror.ms_flags |= MDM_S_WRTERR; 4980Sstevel@tonic-gate str = "write"; 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate if (!(ps->ps_flags & MD_SPS_DONTFREE)) { 5010Sstevel@tonic-gate if (MUTEX_HELD(&ps->ps_mx)) { 5020Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate } else { 5050Sstevel@tonic-gate ASSERT(panicstr); 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate SPS_FREE(stripe_parent_cache, ps); 5080Sstevel@tonic-gate pb->b_flags |= B_ERROR; 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate md_kstat_done(ui, pb, 0); 5110Sstevel@tonic-gate md_unit_readerexit(ui); 5120Sstevel@tonic-gate md_biodone(pb); 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate cmn_err(CE_WARN, "md: %s: %s error on %s", 5150Sstevel@tonic-gate md_shortname(md_getminor(md_dev)), str, 5160Sstevel@tonic-gate md_devname(MD_DEV2SET(md_dev), dev, NULL, 0)); 5170Sstevel@tonic-gate } 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate static int 5200Sstevel@tonic-gate stripe_done(struct buf *cb) 5210Sstevel@tonic-gate { 5220Sstevel@tonic-gate struct buf *pb; 5230Sstevel@tonic-gate mdi_unit_t *ui; 5240Sstevel@tonic-gate md_sps_t *ps; 5250Sstevel@tonic-gate md_scs_t *cs; 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate /*LINTED*/ 5280Sstevel@tonic-gate cs = (md_scs_t *)((caddr_t)cb - md_stripe_mcs_buf_off); 5290Sstevel@tonic-gate ps = cs->cs_ps; 5300Sstevel@tonic-gate pb = ps->ps_bp; 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate mutex_enter(&ps->ps_mx); 5330Sstevel@tonic-gate if (cb->b_flags & B_ERROR) { 5340Sstevel@tonic-gate ps->ps_flags |= MD_SPS_ERROR; 5350Sstevel@tonic-gate pb->b_error = cb->b_error; 5360Sstevel@tonic-gate ps->ps_errcomp = cs->cs_comp; 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate if (cb->b_flags & B_REMAPPED) 5400Sstevel@tonic-gate bp_mapout(cb); 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate ps->ps_frags--; 5430Sstevel@tonic-gate if (ps->ps_frags != 0) { 5440Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 5450Sstevel@tonic-gate kmem_cache_free(stripe_child_cache, cs); 5460Sstevel@tonic-gate return (1); 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate kmem_cache_free(stripe_child_cache, cs); 5490Sstevel@tonic-gate if (ps->ps_flags & MD_SPS_ERROR) { 5500Sstevel@tonic-gate stripe_error(ps); 5510Sstevel@tonic-gate return (1); 5520Sstevel@tonic-gate } 5530Sstevel@tonic-gate ui = ps->ps_ui; 5540Sstevel@tonic-gate if (!(ps->ps_flags & MD_SPS_DONTFREE)) { 5550Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 5560Sstevel@tonic-gate } else { 5570Sstevel@tonic-gate ASSERT(panicstr); 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate SPS_FREE(stripe_parent_cache, ps); 5600Sstevel@tonic-gate md_kstat_done(ui, pb, 0); 5610Sstevel@tonic-gate md_unit_readerexit(ui); 5620Sstevel@tonic-gate md_biodone(pb); 5630Sstevel@tonic-gate return (0); 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate /* 5680Sstevel@tonic-gate * This routine does the mapping from virtual (dev, blkno) of a metapartition 5690Sstevel@tonic-gate * to the real (dev, blkno) of a real disk partition. 5700Sstevel@tonic-gate * It goes to the md_conf[] table to find out the correct real partition 5710Sstevel@tonic-gate * dev and block number for this buffer. 5720Sstevel@tonic-gate * 5730Sstevel@tonic-gate * A single buf request can not go across real disk partition boundary. 5740Sstevel@tonic-gate * When the virtual request specified by (dev, blkno) spans more than one 5750Sstevel@tonic-gate * real partition, md_mapbuf will return 1. Then the caller should prepare 5760Sstevel@tonic-gate * another real buf and continue calling md_mapbuf to do the mapping until 5770Sstevel@tonic-gate * it returns 0. 5780Sstevel@tonic-gate * 5790Sstevel@tonic-gate */ 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate static int 5820Sstevel@tonic-gate md_mapbuf( 5830Sstevel@tonic-gate ms_unit_t *un, 5840Sstevel@tonic-gate diskaddr_t blkno, 5850Sstevel@tonic-gate u_longlong_t bcount, 5860Sstevel@tonic-gate buf_t *bp, /* if bp==NULL, skip bp updates */ 5870Sstevel@tonic-gate ms_comp_t **mdc) /* if bp==NULL, skip mdc update */ 5880Sstevel@tonic-gate { 5890Sstevel@tonic-gate struct ms_row *mdr; 5900Sstevel@tonic-gate struct ms_comp *mdcomp; 5910Sstevel@tonic-gate diskaddr_t stripe_blk; 5920Sstevel@tonic-gate diskaddr_t fragment, blk_in_row, endblk; 5930Sstevel@tonic-gate offset_t interlace; 5940Sstevel@tonic-gate size_t dev_index; 5950Sstevel@tonic-gate int row_index, more; 5960Sstevel@tonic-gate extern unsigned md_maxphys; 5970Sstevel@tonic-gate /* Work var's when bp==NULL */ 5980Sstevel@tonic-gate u_longlong_t wb_bcount; 5990Sstevel@tonic-gate diskaddr_t wb_blkno; 6000Sstevel@tonic-gate md_dev64_t wb_edev; 6010Sstevel@tonic-gate ms_comp_t *wmdc; 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate /* 6040Sstevel@tonic-gate * Do a real calculation to derive the minor device of the 6050Sstevel@tonic-gate * Virtual Disk, which in turn will let us derive the 6060Sstevel@tonic-gate * device/minor of the underlying real device. 6070Sstevel@tonic-gate */ 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate for (row_index = 0; row_index < un->un_nrows; row_index++) { 6110Sstevel@tonic-gate mdr = &un->un_row[row_index]; 6120Sstevel@tonic-gate if (blkno < mdr->un_cum_blocks) 6130Sstevel@tonic-gate break; 6140Sstevel@tonic-gate } 6150Sstevel@tonic-gate ASSERT(row_index != un->un_nrows); 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate blk_in_row = blkno - mdr->un_cum_blocks + mdr->un_blocks; 6200Sstevel@tonic-gate endblk = (diskaddr_t)(blkno + howmany(bcount, DEV_BSIZE)); 6210Sstevel@tonic-gate if (mdr->un_ncomp == 1) { /* No striping */ 6220Sstevel@tonic-gate if (endblk > mdr->un_cum_blocks) { 6230Sstevel@tonic-gate wb_bcount = ldbtob(mdr->un_cum_blocks - blkno); 6240Sstevel@tonic-gate if ((row_index + 1) == un->un_nrows) 6250Sstevel@tonic-gate more = 0; 6260Sstevel@tonic-gate else 6270Sstevel@tonic-gate more = 1; 6280Sstevel@tonic-gate } else { 6290Sstevel@tonic-gate wb_bcount = bcount; 6300Sstevel@tonic-gate more = 0; 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate wmdc = &mdcomp[mdr->un_icomp]; 6330Sstevel@tonic-gate wb_blkno = blk_in_row; 6340Sstevel@tonic-gate } else { /* Have striping */ 6350Sstevel@tonic-gate interlace = mdr->un_interlace; 6360Sstevel@tonic-gate fragment = blk_in_row % interlace; 6370Sstevel@tonic-gate if (bcount > ldbtob(interlace - fragment)) { 6380Sstevel@tonic-gate more = 1; 6390Sstevel@tonic-gate wb_bcount = ldbtob(interlace - fragment); 6400Sstevel@tonic-gate } else { 6410Sstevel@tonic-gate more = 0; 6420Sstevel@tonic-gate wb_bcount = bcount; 6430Sstevel@tonic-gate } 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate stripe_blk = blk_in_row / interlace; 6460Sstevel@tonic-gate dev_index = (size_t)(stripe_blk % mdr->un_ncomp); 6470Sstevel@tonic-gate wmdc = &mdcomp[mdr->un_icomp + dev_index]; 6480Sstevel@tonic-gate wb_blkno = (diskaddr_t)(((stripe_blk / mdr->un_ncomp) 6490Sstevel@tonic-gate * interlace) + fragment); 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate wb_blkno += wmdc->un_start_block; 6530Sstevel@tonic-gate wb_edev = wmdc->un_dev; 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate /* only break up the I/O if we're not built on another metadevice */ 6560Sstevel@tonic-gate if ((md_getmajor(wb_edev) != md_major) && (wb_bcount > md_maxphys)) { 6570Sstevel@tonic-gate wb_bcount = md_maxphys; 6580Sstevel@tonic-gate more = 1; 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate if (bp != (buf_t *)NULL) { 6610Sstevel@tonic-gate /* 6620Sstevel@tonic-gate * wb_bcount is limited by md_maxphys which is 'int' 6630Sstevel@tonic-gate */ 6640Sstevel@tonic-gate bp->b_bcount = (size_t)wb_bcount; 6650Sstevel@tonic-gate bp->b_lblkno = wb_blkno; 6660Sstevel@tonic-gate bp->b_edev = md_dev64_to_dev(wb_edev); 6670Sstevel@tonic-gate *mdc = wmdc; 6680Sstevel@tonic-gate } 6690Sstevel@tonic-gate return (more); 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate static void 6730Sstevel@tonic-gate md_stripe_strategy(buf_t *pb, int flag, void *private) 6740Sstevel@tonic-gate { 6750Sstevel@tonic-gate md_sps_t *ps; 6760Sstevel@tonic-gate md_scs_t *cs; 6770Sstevel@tonic-gate int doing_writes; 6780Sstevel@tonic-gate int more; 6790Sstevel@tonic-gate ms_unit_t *un; 6800Sstevel@tonic-gate mdi_unit_t *ui; 6810Sstevel@tonic-gate size_t current_count; 6820Sstevel@tonic-gate diskaddr_t current_blkno; 6830Sstevel@tonic-gate off_t current_offset; 6840Sstevel@tonic-gate buf_t *cb; /* child buf pointer */ 6850Sstevel@tonic-gate set_t setno; 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate setno = MD_MIN2SET(getminor(pb->b_edev)); 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate /* 6900Sstevel@tonic-gate * When doing IO to a multi owner meta device, check if set is halted. 6910Sstevel@tonic-gate * We do this check without the needed lock held, for performance 6920Sstevel@tonic-gate * reasons. 6930Sstevel@tonic-gate * If an IO just slips through while the set is locked via an 6940Sstevel@tonic-gate * MD_MN_SUSPEND_SET, we don't care about it. 6950Sstevel@tonic-gate * Only check for a suspended set if we are a top-level i/o request 6960Sstevel@tonic-gate * (MD_STR_NOTTOP is cleared in 'flag'). 6970Sstevel@tonic-gate */ 6980Sstevel@tonic-gate if ((md_set[setno].s_status & (MD_SET_HALTED | MD_SET_MNSET)) == 6990Sstevel@tonic-gate (MD_SET_HALTED | MD_SET_MNSET)) { 7000Sstevel@tonic-gate if ((flag & MD_STR_NOTTOP) == 0) { 7010Sstevel@tonic-gate mutex_enter(&md_mx); 7020Sstevel@tonic-gate /* Here we loop until the set is no longer halted */ 7030Sstevel@tonic-gate while (md_set[setno].s_status & MD_SET_HALTED) { 7040Sstevel@tonic-gate cv_wait(&md_cv, &md_mx); 7050Sstevel@tonic-gate } 7060Sstevel@tonic-gate mutex_exit(&md_mx); 7070Sstevel@tonic-gate } 7080Sstevel@tonic-gate } 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate ui = MDI_UNIT(getminor(pb->b_edev)); 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate md_kstat_waitq_enter(ui); 7130Sstevel@tonic-gate 7140Sstevel@tonic-gate un = (ms_unit_t *)md_unit_readerlock(ui); 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate if ((flag & MD_NOBLOCK) == 0) { 7170Sstevel@tonic-gate if (md_inc_iocount(setno) != 0) { 7180Sstevel@tonic-gate pb->b_flags |= B_ERROR; 7190Sstevel@tonic-gate pb->b_error = ENXIO; 7200Sstevel@tonic-gate pb->b_resid = pb->b_bcount; 7210Sstevel@tonic-gate md_unit_readerexit(ui); 7220Sstevel@tonic-gate biodone(pb); 7230Sstevel@tonic-gate return; 7240Sstevel@tonic-gate } 7250Sstevel@tonic-gate } else { 7260Sstevel@tonic-gate md_inc_iocount_noblock(setno); 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate if (!(flag & MD_STR_NOTTOP)) { 7300Sstevel@tonic-gate if (md_checkbuf(ui, (md_unit_t *)un, pb) != 0) { 7310Sstevel@tonic-gate md_kstat_waitq_exit(ui); 7320Sstevel@tonic-gate return; 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate ps = kmem_cache_alloc(stripe_parent_cache, MD_ALLOCFLAGS); 7370Sstevel@tonic-gate stripe_parent_init(ps); 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate /* 7400Sstevel@tonic-gate * Save essential information from the original buffhdr 7410Sstevel@tonic-gate * in the md_save structure. 7420Sstevel@tonic-gate */ 7430Sstevel@tonic-gate ps->ps_un = un; 7440Sstevel@tonic-gate ps->ps_ui = ui; 7450Sstevel@tonic-gate ps->ps_bp = pb; 7460Sstevel@tonic-gate ps->ps_addr = pb->b_un.b_addr; 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate if ((pb->b_flags & B_READ) == 0) 7490Sstevel@tonic-gate doing_writes = 1; 7500Sstevel@tonic-gate else 7510Sstevel@tonic-gate doing_writes = 0; 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate current_count = pb->b_bcount; 7550Sstevel@tonic-gate current_blkno = pb->b_lblkno; 7560Sstevel@tonic-gate current_offset = 0; 7570Sstevel@tonic-gate 7580Sstevel@tonic-gate if (!(flag & MD_STR_NOTTOP) && panicstr) 7590Sstevel@tonic-gate ps->ps_flags |= MD_SPS_DONTFREE; 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate md_kstat_waitq_to_runq(ui); 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate ps->ps_frags++; 7640Sstevel@tonic-gate do { 7650Sstevel@tonic-gate cs = kmem_cache_alloc(stripe_child_cache, MD_ALLOCFLAGS); 7660Sstevel@tonic-gate stripe_child_init(cs); 7670Sstevel@tonic-gate cb = &cs->cs_buf; 7680Sstevel@tonic-gate cs->cs_ps = ps; 7690Sstevel@tonic-gate more = md_mapbuf(un, current_blkno, current_count, cb, 7700Sstevel@tonic-gate &cs->cs_comp); 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate cb = md_bioclone(pb, current_offset, cb->b_bcount, cb->b_edev, 7730Sstevel@tonic-gate cb->b_lblkno, stripe_done, cb, KM_NOSLEEP); 7740Sstevel@tonic-gate /* 7750Sstevel@tonic-gate * Do these calculations now, 7760Sstevel@tonic-gate * so that we pickup a valid b_bcount from the chld_bp. 7770Sstevel@tonic-gate */ 7780Sstevel@tonic-gate current_offset += cb->b_bcount; 7790Sstevel@tonic-gate current_count -= cb->b_bcount; 7800Sstevel@tonic-gate current_blkno += (diskaddr_t)(lbtodb(cb->b_bcount)); 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate if (more) { 7830Sstevel@tonic-gate mutex_enter(&ps->ps_mx); 7840Sstevel@tonic-gate ps->ps_frags++; 7850Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 7860Sstevel@tonic-gate } 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate if (doing_writes && 7890Sstevel@tonic-gate cs->cs_comp->un_mirror.ms_flags & MDM_S_NOWRITE) { 7900Sstevel@tonic-gate (void) stripe_done(cb); 7910Sstevel@tonic-gate continue; 7920Sstevel@tonic-gate } 7930Sstevel@tonic-gate md_call_strategy(cb, flag, private); 7940Sstevel@tonic-gate } while (more); 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate if (!(flag & MD_STR_NOTTOP) && panicstr) { 7970Sstevel@tonic-gate while (!(ps->ps_flags & MD_SPS_DONE)) { 7980Sstevel@tonic-gate md_daemon(1, &md_done_daemon); 7990Sstevel@tonic-gate drv_usecwait(10); 8000Sstevel@tonic-gate } 8010Sstevel@tonic-gate kmem_cache_free(stripe_parent_cache, ps); 8020Sstevel@tonic-gate } 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate static int 8060Sstevel@tonic-gate stripe_snarf(md_snarfcmd_t cmd, set_t setno) 8070Sstevel@tonic-gate { 8080Sstevel@tonic-gate ms_unit_t *un; 8090Sstevel@tonic-gate mddb_recid_t recid; 8100Sstevel@tonic-gate int gotsomething; 8110Sstevel@tonic-gate int all_stripes_gotten; 8120Sstevel@tonic-gate mddb_type_t typ1; 8130Sstevel@tonic-gate mddb_de_ic_t *dep; 8140Sstevel@tonic-gate mddb_rb32_t *rbp; 8150Sstevel@tonic-gate size_t newreqsize; 8160Sstevel@tonic-gate ms_unit_t *big_un; 8170Sstevel@tonic-gate ms_unit32_od_t *small_un; 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate if (cmd == MD_SNARF_CLEANUP) 8210Sstevel@tonic-gate return (0); 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate all_stripes_gotten = 1; 8240Sstevel@tonic-gate gotsomething = 0; 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate typ1 = (mddb_type_t)md_getshared_key(setno, 8270Sstevel@tonic-gate stripe_md_ops.md_driver.md_drivername); 8280Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, 0)) > 0) { 8310Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_GOTIT) 8320Sstevel@tonic-gate continue; 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate dep = mddb_getrecdep(recid); 8350Sstevel@tonic-gate dep->de_flags = MDDB_F_STRIPE; 8360Sstevel@tonic-gate rbp = dep->de_rb; 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate if ((rbp->rb_revision == MDDB_REV_RB) && 8390Sstevel@tonic-gate ((rbp->rb_private & MD_PRV_CONVD) == 0)) { 8400Sstevel@tonic-gate /* 8410Sstevel@tonic-gate * This means, we have an old and small record 8420Sstevel@tonic-gate * and this record hasn't already been converted. 8430Sstevel@tonic-gate * Before we create an incore metadevice from this 8440Sstevel@tonic-gate * we have to convert it to a big record. 8450Sstevel@tonic-gate */ 8460Sstevel@tonic-gate small_un = (ms_unit32_od_t *)mddb_getrecaddr(recid); 8470Sstevel@tonic-gate newreqsize = get_big_stripe_req_size(small_un, 8480Sstevel@tonic-gate COMPLETE_STRUCTURE); 8490Sstevel@tonic-gate big_un = (ms_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP); 8500Sstevel@tonic-gate stripe_convert((caddr_t)small_un, (caddr_t)big_un, 8510Sstevel@tonic-gate SMALL_2_BIG); 8520Sstevel@tonic-gate kmem_free(small_un, dep->de_reqsize); 8530Sstevel@tonic-gate dep->de_rb_userdata = big_un; 8540Sstevel@tonic-gate dep->de_reqsize = newreqsize; 8550Sstevel@tonic-gate un = big_un; 8560Sstevel@tonic-gate rbp->rb_private |= MD_PRV_CONVD; 8570Sstevel@tonic-gate } else { 8580Sstevel@tonic-gate /* Big device */ 8590Sstevel@tonic-gate un = (ms_unit_t *)mddb_getrecaddr(recid); 8600Sstevel@tonic-gate } 8610Sstevel@tonic-gate 8620Sstevel@tonic-gate /* Set revision and flag accordingly */ 8630Sstevel@tonic-gate if (rbp->rb_revision == MDDB_REV_RB) { 8640Sstevel@tonic-gate un->c.un_revision = MD_32BIT_META_DEV; 8650Sstevel@tonic-gate } else { 8660Sstevel@tonic-gate un->c.un_revision = MD_64BIT_META_DEV; 8670Sstevel@tonic-gate un->c.un_flag |= MD_EFILABEL; 8680Sstevel@tonic-gate } 8690Sstevel@tonic-gate 8700Sstevel@tonic-gate /* Create minor node for snarfed unit. */ 8710Sstevel@tonic-gate (void) md_create_minor_node(MD_MIN2SET(MD_SID(un)), MD_SID(un)); 8720Sstevel@tonic-gate 8730Sstevel@tonic-gate if (MD_UNIT(MD_SID(un)) != NULL) { 8740Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_PENDDEL); 8750Sstevel@tonic-gate continue; 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate all_stripes_gotten = 0; 8780Sstevel@tonic-gate if (stripe_build_incore((void *)un, 1) == 0) { 8790Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT); 8800Sstevel@tonic-gate md_create_unit_incore(MD_SID(un), &stripe_md_ops, 0); 8810Sstevel@tonic-gate gotsomething = 1; 8820Sstevel@tonic-gate } 8830Sstevel@tonic-gate } 8840Sstevel@tonic-gate 8850Sstevel@tonic-gate if (!all_stripes_gotten) 8860Sstevel@tonic-gate return (gotsomething); 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 8890Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, 0)) > 0) 8900Sstevel@tonic-gate if (!(mddb_getrecprivate(recid) & MD_PRV_GOTIT)) 8910Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_PENDDEL); 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate return (0); 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate 8960Sstevel@tonic-gate static int 8970Sstevel@tonic-gate stripe_halt(md_haltcmd_t cmd, set_t setno) 8980Sstevel@tonic-gate { 8990Sstevel@tonic-gate int i; 9000Sstevel@tonic-gate mdi_unit_t *ui; 9010Sstevel@tonic-gate minor_t mnum; 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate if (cmd == MD_HALT_CLOSE) 9040Sstevel@tonic-gate return (0); 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate if (cmd == MD_HALT_OPEN) 9070Sstevel@tonic-gate return (0); 9080Sstevel@tonic-gate 9090Sstevel@tonic-gate if (cmd == MD_HALT_UNLOAD) 9100Sstevel@tonic-gate return (0); 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate if (cmd == MD_HALT_CHECK) { 9130Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 9140Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 9150Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 9160Sstevel@tonic-gate continue; 9170Sstevel@tonic-gate if (ui->ui_opsindex != stripe_md_ops.md_selfindex) 9180Sstevel@tonic-gate continue; 9190Sstevel@tonic-gate if (md_unit_isopen(ui)) 9200Sstevel@tonic-gate return (1); 9210Sstevel@tonic-gate } 9220Sstevel@tonic-gate return (0); 9230Sstevel@tonic-gate } 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate if (cmd != MD_HALT_DOIT) 9260Sstevel@tonic-gate return (1); 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 9290Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 9300Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 9310Sstevel@tonic-gate continue; 9320Sstevel@tonic-gate if (ui->ui_opsindex != stripe_md_ops.md_selfindex) 9330Sstevel@tonic-gate continue; 9340Sstevel@tonic-gate reset_stripe((ms_unit_t *)MD_UNIT(mnum), mnum, 0); 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate return (0); 9380Sstevel@tonic-gate } 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate /*ARGSUSED3*/ 9410Sstevel@tonic-gate static int 9420Sstevel@tonic-gate stripe_open(dev_t *dev, int flag, int otyp, cred_t *cred_p, int md_oflags) 9430Sstevel@tonic-gate { 9440Sstevel@tonic-gate minor_t mnum = getminor(*dev); 9450Sstevel@tonic-gate mdi_unit_t *ui = MDI_UNIT(mnum); 9460Sstevel@tonic-gate ms_unit_t *un; 9470Sstevel@tonic-gate int err = 0; 94846Sskamm set_t setno; 94946Sskamm 95046Sskamm /* 95146Sskamm * When doing an open of a multi owner metadevice, check to see if this 95246Sskamm * node is a starting node and if a reconfig cycle is underway. 95346Sskamm * If so, the system isn't sufficiently set up enough to handle the 95446Sskamm * open (which involves I/O during sp_validate), so fail with ENXIO. 95546Sskamm */ 95646Sskamm setno = MD_MIN2SET(mnum); 95746Sskamm if ((md_set[setno].s_status & (MD_SET_MNSET | MD_SET_MN_START_RC)) == 95846Sskamm (MD_SET_MNSET | MD_SET_MN_START_RC)) { 95946Sskamm return (ENXIO); 96046Sskamm } 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate /* single thread */ 9630Sstevel@tonic-gate un = (ms_unit_t *)md_unit_openclose_enter(ui); 9640Sstevel@tonic-gate 9650Sstevel@tonic-gate /* open devices, if necessary */ 9660Sstevel@tonic-gate if (! md_unit_isopen(ui) || (md_oflags & MD_OFLG_PROBEDEV)) { 9670Sstevel@tonic-gate if ((err = stripe_open_all_devs(un, md_oflags)) != 0) { 9680Sstevel@tonic-gate goto out; 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate } 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate /* count open */ 9730Sstevel@tonic-gate if ((err = md_unit_incopen(mnum, flag, otyp)) != 0) 9740Sstevel@tonic-gate goto out; 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate /* unlock, return success */ 9770Sstevel@tonic-gate out: 9780Sstevel@tonic-gate md_unit_openclose_exit(ui); 9790Sstevel@tonic-gate return (err); 9800Sstevel@tonic-gate } 9810Sstevel@tonic-gate 9820Sstevel@tonic-gate /*ARGSUSED1*/ 9830Sstevel@tonic-gate static int 9840Sstevel@tonic-gate stripe_close( 9850Sstevel@tonic-gate dev_t dev, 9860Sstevel@tonic-gate int flag, 9870Sstevel@tonic-gate int otyp, 9880Sstevel@tonic-gate cred_t *cred_p, 9890Sstevel@tonic-gate int md_cflags 9900Sstevel@tonic-gate ) 9910Sstevel@tonic-gate { 9920Sstevel@tonic-gate minor_t mnum = getminor(dev); 9930Sstevel@tonic-gate mdi_unit_t *ui = MDI_UNIT(mnum); 9940Sstevel@tonic-gate ms_unit_t *un; 9950Sstevel@tonic-gate int err = 0; 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate /* single thread */ 9980Sstevel@tonic-gate un = (ms_unit_t *)md_unit_openclose_enter(ui); 9990Sstevel@tonic-gate 10000Sstevel@tonic-gate /* count closed */ 10010Sstevel@tonic-gate if ((err = md_unit_decopen(mnum, otyp)) != 0) 10020Sstevel@tonic-gate goto out; 10030Sstevel@tonic-gate 10040Sstevel@tonic-gate /* close devices, if necessary */ 10050Sstevel@tonic-gate if (! md_unit_isopen(ui) || (md_cflags & MD_OFLG_PROBEDEV)) { 10060Sstevel@tonic-gate stripe_close_all_devs(un, md_cflags); 10070Sstevel@tonic-gate } 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate /* unlock, return success */ 10100Sstevel@tonic-gate out: 10110Sstevel@tonic-gate md_unit_openclose_exit(ui); 10120Sstevel@tonic-gate return (err); 10130Sstevel@tonic-gate } 10140Sstevel@tonic-gate 10150Sstevel@tonic-gate 10160Sstevel@tonic-gate static struct buf dumpbuf; 10170Sstevel@tonic-gate 10180Sstevel@tonic-gate /* 10190Sstevel@tonic-gate * This routine dumps memory to the disk. It assumes that the memory has 10200Sstevel@tonic-gate * already been mapped into mainbus space. It is called at disk interrupt 10210Sstevel@tonic-gate * priority when the system is in trouble. 10220Sstevel@tonic-gate * 10230Sstevel@tonic-gate */ 10240Sstevel@tonic-gate static int 10250Sstevel@tonic-gate stripe_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) 10260Sstevel@tonic-gate { 10270Sstevel@tonic-gate ms_unit_t *un; 10280Sstevel@tonic-gate buf_t *bp; 10290Sstevel@tonic-gate ms_comp_t *mdc; 10300Sstevel@tonic-gate u_longlong_t nb; 10310Sstevel@tonic-gate diskaddr_t mapblk; 10320Sstevel@tonic-gate int result; 10330Sstevel@tonic-gate int more; 10340Sstevel@tonic-gate int saveresult = 0; 10350Sstevel@tonic-gate 10360Sstevel@tonic-gate /* 10370Sstevel@tonic-gate * Don't need to grab the unit lock. 10380Sstevel@tonic-gate * Cause nothing else is suppose to be happenning. 10390Sstevel@tonic-gate * Also dump is not suppose to sleep. 10400Sstevel@tonic-gate */ 10410Sstevel@tonic-gate un = (ms_unit_t *)MD_UNIT(getminor(dev)); 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate if ((diskaddr_t)blkno >= un->c.un_total_blocks) 10440Sstevel@tonic-gate return (EINVAL); 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate if ((diskaddr_t)blkno + nblk > un->c.un_total_blocks) 10470Sstevel@tonic-gate return (EINVAL); 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate bp = &dumpbuf; 10500Sstevel@tonic-gate nb = ldbtob(nblk); 10510Sstevel@tonic-gate do { 10520Sstevel@tonic-gate bzero((caddr_t)bp, sizeof (*bp)); 10530Sstevel@tonic-gate more = md_mapbuf(un, (diskaddr_t)blkno, nb, bp, &mdc); 10540Sstevel@tonic-gate nblk = btodb(bp->b_bcount); 10550Sstevel@tonic-gate mapblk = bp->b_lblkno; 10560Sstevel@tonic-gate if (!(mdc->un_mirror.ms_flags & MDM_S_NOWRITE)) { 10570Sstevel@tonic-gate /* 10580Sstevel@tonic-gate * bdev_dump() is currently only able to take 10590Sstevel@tonic-gate * 32 bit wide blkno's. 10600Sstevel@tonic-gate */ 10610Sstevel@tonic-gate result = bdev_dump(bp->b_edev, addr, (daddr_t)mapblk, 10620Sstevel@tonic-gate nblk); 10630Sstevel@tonic-gate if (result) 10640Sstevel@tonic-gate saveresult = result; 10650Sstevel@tonic-gate } 10660Sstevel@tonic-gate 10670Sstevel@tonic-gate nb -= bp->b_bcount; 10680Sstevel@tonic-gate addr += bp->b_bcount; 10690Sstevel@tonic-gate blkno += nblk; 10700Sstevel@tonic-gate } while (more); 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate return (saveresult); 10730Sstevel@tonic-gate } 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate /*ARGSUSED*/ 10760Sstevel@tonic-gate static intptr_t 10770Sstevel@tonic-gate stripe_shared_by_blk( 10780Sstevel@tonic-gate md_dev64_t dev, 10790Sstevel@tonic-gate void *junk, 10800Sstevel@tonic-gate diskaddr_t blkno, 10810Sstevel@tonic-gate u_longlong_t *cnt) 10820Sstevel@tonic-gate { 10830Sstevel@tonic-gate ms_unit_t *un; 10840Sstevel@tonic-gate buf_t bp; 10850Sstevel@tonic-gate ms_comp_t *comp; 10860Sstevel@tonic-gate 10870Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 10880Sstevel@tonic-gate (void) md_mapbuf(un, blkno, ldbtob(*cnt), &bp, &comp); 10890Sstevel@tonic-gate *cnt = (u_longlong_t)lbtodb(bp.b_bcount); 10900Sstevel@tonic-gate return ((intptr_t)&comp->un_mirror); 10910Sstevel@tonic-gate } 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate /* 10940Sstevel@tonic-gate * stripe_block_count_skip_size() returns the following values 10950Sstevel@tonic-gate * so that the logical to physical block mappings can 10960Sstevel@tonic-gate * be calculated without intimate knowledge of the underpinnings. 10970Sstevel@tonic-gate * 10980Sstevel@tonic-gate * block - first logical block number of the device. 10990Sstevel@tonic-gate * block = [ # of blocks before THE row ] + 11000Sstevel@tonic-gate * [ # of blocks in THE row before the component ] 11010Sstevel@tonic-gate * count - # of segments (interlaced size). 11020Sstevel@tonic-gate * skip - # of logical blocks between segments, or delta to 11030Sstevel@tonic-gate * get to next segment 11040Sstevel@tonic-gate * size - interlace size used for the block, count, skip. 11050Sstevel@tonic-gate */ 11060Sstevel@tonic-gate /*ARGSUSED*/ 11070Sstevel@tonic-gate static intptr_t 11080Sstevel@tonic-gate stripe_block_count_skip_size( 11090Sstevel@tonic-gate md_dev64_t dev, 11100Sstevel@tonic-gate void *junk, 11110Sstevel@tonic-gate int ci, 11120Sstevel@tonic-gate diskaddr_t *block, 11130Sstevel@tonic-gate size_t *count, 11140Sstevel@tonic-gate u_longlong_t *skip, 11150Sstevel@tonic-gate u_longlong_t *size) 11160Sstevel@tonic-gate { 11170Sstevel@tonic-gate ms_unit_t *un; 11180Sstevel@tonic-gate int row; 11190Sstevel@tonic-gate struct ms_row *mdr; 11200Sstevel@tonic-gate int cmpcount = 0; 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 11250Sstevel@tonic-gate mdr = &un->un_row[row]; 11260Sstevel@tonic-gate if ((mdr->un_ncomp + cmpcount) > ci) 11270Sstevel@tonic-gate break; 11280Sstevel@tonic-gate cmpcount += mdr->un_ncomp; 11290Sstevel@tonic-gate } 11300Sstevel@tonic-gate ASSERT(row != un->un_nrows); 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate /* 11330Sstevel@tonic-gate * Concatenations are always contiguous blocks, 11340Sstevel@tonic-gate * you cannot depend on the interlace being a usable 11350Sstevel@tonic-gate * value (except for stripes). 11360Sstevel@tonic-gate */ 11370Sstevel@tonic-gate if (mdr->un_ncomp == 1) { /* Concats */ 11380Sstevel@tonic-gate *block = mdr->un_cum_blocks - mdr->un_blocks; 11390Sstevel@tonic-gate *count = 1; 11400Sstevel@tonic-gate *skip = 0; 11410Sstevel@tonic-gate *size = mdr->un_blocks; 11420Sstevel@tonic-gate } else { /* Stripes */ 11430Sstevel@tonic-gate *block = (mdr->un_cum_blocks - mdr->un_blocks) + 11440Sstevel@tonic-gate ((ci - cmpcount) * mdr->un_interlace); 11450Sstevel@tonic-gate *count = (size_t)(mdr->un_blocks / (mdr->un_interlace 11460Sstevel@tonic-gate * mdr->un_ncomp)); 11470Sstevel@tonic-gate *skip = (mdr->un_interlace * mdr->un_ncomp) - mdr->un_interlace; 11480Sstevel@tonic-gate *size = mdr->un_interlace; 11490Sstevel@tonic-gate } 11500Sstevel@tonic-gate 11510Sstevel@tonic-gate return (0); 11520Sstevel@tonic-gate } 11530Sstevel@tonic-gate 11540Sstevel@tonic-gate /*ARGSUSED*/ 11550Sstevel@tonic-gate static intptr_t 11560Sstevel@tonic-gate stripe_shared_by_indx(md_dev64_t dev, void *junk, int indx) 11570Sstevel@tonic-gate { 11580Sstevel@tonic-gate ms_unit_t *un; 11590Sstevel@tonic-gate ms_comp_t *comp; 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 11620Sstevel@tonic-gate comp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 11630Sstevel@tonic-gate comp += indx; 11640Sstevel@tonic-gate return ((intptr_t)&comp->un_mirror); 11650Sstevel@tonic-gate } 11660Sstevel@tonic-gate 11670Sstevel@tonic-gate /*ARGSUSED*/ 11680Sstevel@tonic-gate intptr_t 11690Sstevel@tonic-gate stripe_component_count(md_dev64_t dev, void *junk) 11700Sstevel@tonic-gate { 11710Sstevel@tonic-gate /* 11720Sstevel@tonic-gate * See comments for stripe_get_dev 11730Sstevel@tonic-gate */ 11740Sstevel@tonic-gate 11750Sstevel@tonic-gate ms_unit_t *un; 11760Sstevel@tonic-gate int count = 0; 11770Sstevel@tonic-gate int row; 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 11800Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) 11810Sstevel@tonic-gate count += un->un_row[row].un_ncomp; 11820Sstevel@tonic-gate return (count); 11830Sstevel@tonic-gate } 11840Sstevel@tonic-gate 11850Sstevel@tonic-gate /*ARGSUSED*/ 11860Sstevel@tonic-gate intptr_t 11870Sstevel@tonic-gate stripe_get_dev(md_dev64_t dev, void *junk, int indx, ms_cd_info_t *cd) 11880Sstevel@tonic-gate { 11890Sstevel@tonic-gate /* 11900Sstevel@tonic-gate * It should be noted that stripe_replace in stripe_ioctl.c calls this 11910Sstevel@tonic-gate * routine using makedevice(0, minor) for the first argument. 11920Sstevel@tonic-gate * 11930Sstevel@tonic-gate * If this routine at some point in the future needs to use the major 11940Sstevel@tonic-gate * number stripe_replace must be changed. 11950Sstevel@tonic-gate */ 11960Sstevel@tonic-gate 11970Sstevel@tonic-gate ms_unit_t *un; 11980Sstevel@tonic-gate ms_comp_t *comp; 11990Sstevel@tonic-gate md_dev64_t tmpdev; 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate un = MD_UNIT(md_getminor(dev)); 12020Sstevel@tonic-gate comp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 12030Sstevel@tonic-gate comp += indx; 12040Sstevel@tonic-gate tmpdev = comp->un_dev; 12050Sstevel@tonic-gate /* 12060Sstevel@tonic-gate * Try to resolve devt again if NODEV64 12070Sstevel@tonic-gate * Check if this comp is hotspared and if it is 12080Sstevel@tonic-gate * then use key for hotspare 12090Sstevel@tonic-gate */ 12100Sstevel@tonic-gate if (tmpdev == NODEV64) { 12110Sstevel@tonic-gate tmpdev = md_resolve_bydevid(md_getminor(dev), tmpdev, 12120Sstevel@tonic-gate comp->un_mirror.ms_hs_id ? 12130Sstevel@tonic-gate comp->un_mirror.ms_hs_key : 12140Sstevel@tonic-gate comp->un_key); 12150Sstevel@tonic-gate comp->un_dev = tmpdev; 12160Sstevel@tonic-gate } 12170Sstevel@tonic-gate 12180Sstevel@tonic-gate cd->cd_dev = comp->un_dev; 12190Sstevel@tonic-gate cd->cd_orig_dev = comp->un_mirror.ms_orig_dev; 12200Sstevel@tonic-gate return (0); 12210Sstevel@tonic-gate } 12220Sstevel@tonic-gate 12230Sstevel@tonic-gate /*ARGSUSED*/ 12240Sstevel@tonic-gate void 12250Sstevel@tonic-gate stripe_replace_done(md_dev64_t dev, sv_dev_t *sv) 12260Sstevel@tonic-gate { 12270Sstevel@tonic-gate /* 12280Sstevel@tonic-gate * See comments for stripe_get_dev 12290Sstevel@tonic-gate */ 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate minor_t mnum = md_getminor(dev); 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate if (sv != NULL) { 12340Sstevel@tonic-gate md_rem_names(sv, 1); 12350Sstevel@tonic-gate kmem_free(sv, sizeof (sv_dev_t)); 12360Sstevel@tonic-gate } 12370Sstevel@tonic-gate 12380Sstevel@tonic-gate md_unit_writerexit(MDI_UNIT(mnum)); 12390Sstevel@tonic-gate } 12400Sstevel@tonic-gate 12410Sstevel@tonic-gate /*ARGSUSED*/ 12420Sstevel@tonic-gate intptr_t 12430Sstevel@tonic-gate stripe_replace_dev(md_dev64_t dev, void *junk, int ci, ms_new_dev_t *nd, 12440Sstevel@tonic-gate mddb_recid_t *recids, int nrecids, void (**replace_done)(), 12450Sstevel@tonic-gate void **replace_data) 12460Sstevel@tonic-gate { 12470Sstevel@tonic-gate minor_t mnum; 12480Sstevel@tonic-gate ms_unit_t *un; 12490Sstevel@tonic-gate mdi_unit_t *ui; 12500Sstevel@tonic-gate ms_comp_t *comp; 12510Sstevel@tonic-gate diskaddr_t dev_size; 12520Sstevel@tonic-gate int row; 12530Sstevel@tonic-gate int ncomps = 0; 12540Sstevel@tonic-gate int cmpcount = 0; 12550Sstevel@tonic-gate int rid = 0; 12560Sstevel@tonic-gate struct ms_row *mdr; 12570Sstevel@tonic-gate sv_dev_t *sv = NULL; 12580Sstevel@tonic-gate mddb_recid_t hs_id = 0; 12590Sstevel@tonic-gate set_t setno; 12600Sstevel@tonic-gate side_t side; 12610Sstevel@tonic-gate md_dev64_t this_dev; 12620Sstevel@tonic-gate 12630Sstevel@tonic-gate mnum = md_getminor(dev); 12640Sstevel@tonic-gate ui = MDI_UNIT(mnum); 12650Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 12660Sstevel@tonic-gate side = mddb_getsidenum(setno); 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate un = md_unit_writerlock(ui); 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate *replace_data = NULL; 12710Sstevel@tonic-gate comp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate comp += ci; 12740Sstevel@tonic-gate 12750Sstevel@tonic-gate /* 12760Sstevel@tonic-gate * Count the number of components 12770Sstevel@tonic-gate */ 12780Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 12790Sstevel@tonic-gate struct ms_row *mdr = &un->un_row[row]; 12800Sstevel@tonic-gate ncomps += mdr->un_ncomp; 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate 12830Sstevel@tonic-gate recids[0] = 0; 12840Sstevel@tonic-gate /* 12850Sstevel@tonic-gate * No need of checking size of new device, 12860Sstevel@tonic-gate * when hotsparing (it has already been done), or 12870Sstevel@tonic-gate * when enabling the device. 12880Sstevel@tonic-gate */ 12890Sstevel@tonic-gate if ((nd != NULL) && (nd->nd_hs_id == 0)) { 12900Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 12910Sstevel@tonic-gate mdr = &un->un_row[row]; 12920Sstevel@tonic-gate if ((mdr->un_ncomp + cmpcount) > ci) 12930Sstevel@tonic-gate break; 12940Sstevel@tonic-gate cmpcount += mdr->un_ncomp; 12950Sstevel@tonic-gate } 12960Sstevel@tonic-gate ASSERT(row != un->un_nrows); 12970Sstevel@tonic-gate 12980Sstevel@tonic-gate /* Concatenations have a ncomp = 1 */ 12990Sstevel@tonic-gate dev_size = mdr->un_blocks / mdr->un_ncomp; 13000Sstevel@tonic-gate 13010Sstevel@tonic-gate /* 13020Sstevel@tonic-gate * now check to see if new comp can be used in 13030Sstevel@tonic-gate * place of old comp 13040Sstevel@tonic-gate */ 13050Sstevel@tonic-gate if ((un->c.un_flag & MD_LABELED) && (ci == 0) && 13060Sstevel@tonic-gate nd->nd_labeled) 13070Sstevel@tonic-gate nd->nd_start_blk = 0; 13080Sstevel@tonic-gate else 13090Sstevel@tonic-gate nd->nd_nblks -= nd->nd_start_blk; 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate if (dev_size > nd->nd_nblks) { 13120Sstevel@tonic-gate md_unit_writerexit(ui); 13130Sstevel@tonic-gate return (MDE_COMP_TOO_SMALL); 13140Sstevel@tonic-gate } 13150Sstevel@tonic-gate 13160Sstevel@tonic-gate sv = (sv_dev_t *)kmem_alloc(sizeof (sv_dev_t), KM_SLEEP); 13170Sstevel@tonic-gate sv->setno = MD_MIN2SET(mnum); 13180Sstevel@tonic-gate sv->key = comp->un_key; 13190Sstevel@tonic-gate } 13200Sstevel@tonic-gate 13210Sstevel@tonic-gate /* 13220Sstevel@tonic-gate * Close this component. 13230Sstevel@tonic-gate */ 13240Sstevel@tonic-gate if (comp->un_mirror.ms_flags & MDM_S_ISOPEN) { 13250Sstevel@tonic-gate md_layered_close(comp->un_dev, MD_OFLG_NULL); 13260Sstevel@tonic-gate comp->un_mirror.ms_flags &= ~MDM_S_ISOPEN; 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate /* 13300Sstevel@tonic-gate * If the component is hotspared, return to the pool. 13310Sstevel@tonic-gate */ 13320Sstevel@tonic-gate if (comp->un_mirror.ms_hs_id != 0) { 13330Sstevel@tonic-gate hs_cmds_t cmd; 13340Sstevel@tonic-gate mdkey_t hs_key; 13350Sstevel@tonic-gate 13360Sstevel@tonic-gate hs_key = comp->un_mirror.ms_hs_key; 13370Sstevel@tonic-gate comp->un_dev = comp->un_mirror.ms_orig_dev; 13380Sstevel@tonic-gate comp->un_start_block = comp->un_mirror.ms_orig_blk; 13390Sstevel@tonic-gate comp->un_mirror.ms_hs_key = 0; 13400Sstevel@tonic-gate comp->un_mirror.ms_hs_id = 0; 13410Sstevel@tonic-gate comp->un_mirror.ms_orig_dev = 0; 13420Sstevel@tonic-gate 13430Sstevel@tonic-gate cmd = HS_FREE; 13440Sstevel@tonic-gate if ((comp->un_mirror.ms_state != CS_OKAY) && 13450Sstevel@tonic-gate (comp->un_mirror.ms_state != CS_RESYNC)) 13460Sstevel@tonic-gate cmd = HS_BAD; 13470Sstevel@tonic-gate (void) md_hot_spare_ifc(cmd, un->un_hsp_id, 0, 0, &hs_id, 13480Sstevel@tonic-gate &hs_key, NULL, NULL); 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate /* 13520Sstevel@tonic-gate * Open by device id; for enable (indicated by a NULL 13530Sstevel@tonic-gate * nd pointer), use the existing component info. For 13540Sstevel@tonic-gate * replace, use the new device. 13550Sstevel@tonic-gate */ 13560Sstevel@tonic-gate if (nd == NULL) { 13570Sstevel@tonic-gate this_dev = md_resolve_bydevid(mnum, comp->un_dev, comp->un_key); 13580Sstevel@tonic-gate /* 13590Sstevel@tonic-gate * If someone replaced a new disk in the same slot 13600Sstevel@tonic-gate * we get NODEV64 since old device id cannot be 13610Sstevel@tonic-gate * resolved. The new devt is obtained from the 13620Sstevel@tonic-gate * mddb since devt is going to be unchanged for the 13630Sstevel@tonic-gate * enable case. No need to check for multiple 13640Sstevel@tonic-gate * keys here because the caller (comp_replace) 13650Sstevel@tonic-gate * has already sanity checked it for us. 13660Sstevel@tonic-gate */ 13670Sstevel@tonic-gate if (this_dev == NODEV64) { 13680Sstevel@tonic-gate this_dev = md_getdevnum(setno, side, comp->un_key, 13690Sstevel@tonic-gate MD_TRUST_DEVT); 13700Sstevel@tonic-gate } 13710Sstevel@tonic-gate } else { 13720Sstevel@tonic-gate /* 13730Sstevel@tonic-gate * If this is a hotspare, save the original dev_t for later 13740Sstevel@tonic-gate * use. If this has occured during boot then the value of 13750Sstevel@tonic-gate * comp->un_dev will be NODEV64 because of the failure to look 13760Sstevel@tonic-gate * up the devid of the device. 13770Sstevel@tonic-gate */ 13780Sstevel@tonic-gate if (nd->nd_hs_id != 0) 13790Sstevel@tonic-gate comp->un_mirror.ms_orig_dev = comp->un_dev; 13800Sstevel@tonic-gate this_dev = md_resolve_bydevid(mnum, nd->nd_dev, nd->nd_key); 13810Sstevel@tonic-gate } 13820Sstevel@tonic-gate 13830Sstevel@tonic-gate comp->un_dev = this_dev; 13840Sstevel@tonic-gate 13850Sstevel@tonic-gate /* 13860Sstevel@tonic-gate * Now open the new device if required. Note for a single component 13870Sstevel@tonic-gate * stripe it will not be open - leave this for the mirror driver to 13880Sstevel@tonic-gate * deal with. 13890Sstevel@tonic-gate */ 13900Sstevel@tonic-gate if (md_unit_isopen(ui)) { 13910Sstevel@tonic-gate if (md_layered_open(mnum, &this_dev, MD_OFLG_NULL)) { 13920Sstevel@tonic-gate mddb_recid_t ids[3]; 13930Sstevel@tonic-gate 13940Sstevel@tonic-gate ids[0] = un->c.un_record_id; 13950Sstevel@tonic-gate ids[1] = hs_id; 13960Sstevel@tonic-gate ids[2] = 0; 13970Sstevel@tonic-gate mddb_commitrecs_wrapper(ids); 13980Sstevel@tonic-gate if ((nd != NULL) && (nd->nd_hs_id != 0)) { 13990Sstevel@tonic-gate /* 14000Sstevel@tonic-gate * Revert back to the original device. 14010Sstevel@tonic-gate */ 14020Sstevel@tonic-gate comp->un_dev = comp->un_mirror.ms_orig_dev; 14030Sstevel@tonic-gate 14040Sstevel@tonic-gate cmn_err(CE_WARN, 14050Sstevel@tonic-gate "md: %s: open error of hotspare %s", 14060Sstevel@tonic-gate md_shortname(mnum), 14070Sstevel@tonic-gate md_devname(MD_MIN2SET(mnum), nd->nd_dev, 14080Sstevel@tonic-gate NULL, 0)); 14090Sstevel@tonic-gate SE_NOTIFY(EC_SVM_STATE, ESC_SVM_OPEN_FAIL, 14100Sstevel@tonic-gate SVM_TAG_HS, MD_MIN2SET(mnum), nd->nd_dev); 14110Sstevel@tonic-gate } 14120Sstevel@tonic-gate md_unit_writerexit(ui); 14130Sstevel@tonic-gate return (MDE_COMP_OPEN_ERR); 14140Sstevel@tonic-gate } 14150Sstevel@tonic-gate if (nd != NULL) 14160Sstevel@tonic-gate nd->nd_dev = this_dev; 14170Sstevel@tonic-gate 14180Sstevel@tonic-gate comp->un_mirror.ms_flags |= MDM_S_ISOPEN; 14190Sstevel@tonic-gate } 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate if (nd == NULL) { 14220Sstevel@tonic-gate recids[0] = un->c.un_record_id; 14230Sstevel@tonic-gate recids[1] = hs_id; 14240Sstevel@tonic-gate recids[2] = 0; 14250Sstevel@tonic-gate *replace_done = stripe_replace_done; 14260Sstevel@tonic-gate return (0); 14270Sstevel@tonic-gate } 14280Sstevel@tonic-gate 14290Sstevel@tonic-gate /* if hot sparing this device */ 14300Sstevel@tonic-gate if (nd->nd_hs_id != 0) { 14310Sstevel@tonic-gate char devname[MD_MAX_CTDLEN]; 14320Sstevel@tonic-gate char hs_devname[MD_MAX_CTDLEN]; 14330Sstevel@tonic-gate set_t setno; 14340Sstevel@tonic-gate 14350Sstevel@tonic-gate comp->un_mirror.ms_hs_id = nd->nd_hs_id; 14360Sstevel@tonic-gate comp->un_mirror.ms_hs_key = nd->nd_key; 14370Sstevel@tonic-gate 14380Sstevel@tonic-gate comp->un_mirror.ms_orig_blk = comp->un_start_block; 14390Sstevel@tonic-gate 14400Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 14410Sstevel@tonic-gate 14420Sstevel@tonic-gate (void) md_devname(setno, comp->un_mirror.ms_orig_dev, devname, 14430Sstevel@tonic-gate sizeof (devname)); 14440Sstevel@tonic-gate (void) md_devname(setno, nd->nd_dev, hs_devname, 14450Sstevel@tonic-gate sizeof (hs_devname)); 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate cmn_err(CE_NOTE, "md: %s: hotspared device %s with %s", 14480Sstevel@tonic-gate md_shortname(mnum), devname, hs_devname); 14490Sstevel@tonic-gate 14500Sstevel@tonic-gate } else { /* replacing the device */ 14510Sstevel@tonic-gate comp->un_key = nd->nd_key; 14520Sstevel@tonic-gate *replace_data = (void *)sv; 14530Sstevel@tonic-gate 14540Sstevel@tonic-gate /* 14550Sstevel@tonic-gate * For the old device, make sure to reset the parent 14560Sstevel@tonic-gate * if it's a metadevice. 14570Sstevel@tonic-gate */ 14580Sstevel@tonic-gate if (md_getmajor(comp->un_dev) == md_major) { 14590Sstevel@tonic-gate minor_t comp_mnum = md_getminor(comp->un_dev); 14600Sstevel@tonic-gate md_unit_t *comp_un = MD_UNIT(comp_mnum); 14610Sstevel@tonic-gate 14620Sstevel@tonic-gate md_reset_parent(comp->un_dev); 14630Sstevel@tonic-gate recids[rid++] = MD_RECID(comp_un); 14640Sstevel@tonic-gate } 14650Sstevel@tonic-gate } 14660Sstevel@tonic-gate 14670Sstevel@tonic-gate comp->un_dev = nd->nd_dev; 14680Sstevel@tonic-gate comp->un_start_block = nd->nd_start_blk; 14690Sstevel@tonic-gate 14700Sstevel@tonic-gate /* 14710Sstevel@tonic-gate * For the new device, make sure to set the parent if it's a 14720Sstevel@tonic-gate * metadevice. 14730Sstevel@tonic-gate * 14740Sstevel@tonic-gate * If we ever support using metadevices as hot spares, this 14750Sstevel@tonic-gate * will need to be tested, and possibly moved into the 14760Sstevel@tonic-gate * preceding "else" clause, immediately following the parent 14770Sstevel@tonic-gate * reset block. For now, it's convenient to leave it here and 14780Sstevel@tonic-gate * only compress nd->nd_dev once. 14790Sstevel@tonic-gate */ 14800Sstevel@tonic-gate if (md_getmajor(comp->un_dev) == md_major) { 14810Sstevel@tonic-gate minor_t comp_mnum = md_getminor(comp->un_dev); 14820Sstevel@tonic-gate md_unit_t *comp_un = MD_UNIT(comp_mnum); 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate md_set_parent(comp->un_dev, MD_SID(un)); 14850Sstevel@tonic-gate recids[rid++] = MD_RECID(comp_un); 14860Sstevel@tonic-gate } 14870Sstevel@tonic-gate 14880Sstevel@tonic-gate recids[rid++] = un->c.un_record_id; 14890Sstevel@tonic-gate recids[rid++] = hs_id; 14900Sstevel@tonic-gate recids[rid] = 0; 14910Sstevel@tonic-gate *replace_done = stripe_replace_done; 14920Sstevel@tonic-gate return (0); 14930Sstevel@tonic-gate } 14940Sstevel@tonic-gate 14950Sstevel@tonic-gate /*ARGSUSED*/ 14960Sstevel@tonic-gate static intptr_t 14970Sstevel@tonic-gate stripe_hotspare_dev( 14980Sstevel@tonic-gate md_dev64_t dev, 14990Sstevel@tonic-gate void *junk, 15000Sstevel@tonic-gate int ci, 15010Sstevel@tonic-gate mddb_recid_t *recids, 15020Sstevel@tonic-gate int nrecids, 15030Sstevel@tonic-gate void (**replace_done)(), 15040Sstevel@tonic-gate void **replace_data) 15050Sstevel@tonic-gate { 15060Sstevel@tonic-gate ms_unit_t *un; 15070Sstevel@tonic-gate mdi_unit_t *ui; 15080Sstevel@tonic-gate ms_comp_t *comp; 15090Sstevel@tonic-gate int row; 15100Sstevel@tonic-gate struct ms_row *mdr; 15110Sstevel@tonic-gate ms_new_dev_t nd; 15120Sstevel@tonic-gate int err; 15130Sstevel@tonic-gate int i; 15140Sstevel@tonic-gate minor_t mnum; 15150Sstevel@tonic-gate set_t setno; 15160Sstevel@tonic-gate int cmpcount = 0; 15170Sstevel@tonic-gate 15180Sstevel@tonic-gate mnum = md_getminor(dev); 15190Sstevel@tonic-gate ui = MDI_UNIT(mnum); 15200Sstevel@tonic-gate un = MD_UNIT(mnum); 15210Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 15220Sstevel@tonic-gate 15230Sstevel@tonic-gate if (md_get_setstatus(setno) & MD_SET_STALE) 15240Sstevel@tonic-gate return (1); 15250Sstevel@tonic-gate 15260Sstevel@tonic-gate if (un->un_hsp_id == -1) 15270Sstevel@tonic-gate return (1); 15280Sstevel@tonic-gate 15290Sstevel@tonic-gate for (row = 0; row < un->un_nrows; row++) { 15300Sstevel@tonic-gate mdr = &un->un_row[row]; 15310Sstevel@tonic-gate if ((mdr->un_ncomp + cmpcount) > ci) 15320Sstevel@tonic-gate break; 15330Sstevel@tonic-gate cmpcount += mdr->un_ncomp; 15340Sstevel@tonic-gate } 15350Sstevel@tonic-gate ASSERT(row != un->un_nrows); 15360Sstevel@tonic-gate 15370Sstevel@tonic-gate comp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]); 15380Sstevel@tonic-gate comp += ci; 15390Sstevel@tonic-gate /* Concatenations have a ncomp = 1 */ 15400Sstevel@tonic-gate nd.nd_nblks = mdr->un_blocks / mdr->un_ncomp; 15410Sstevel@tonic-gate 15420Sstevel@tonic-gate if ((un->c.un_flag & MD_LABELED) && (ci == 0)) 15430Sstevel@tonic-gate nd.nd_labeled = 1; 15440Sstevel@tonic-gate else 15450Sstevel@tonic-gate nd.nd_labeled = 0; 15460Sstevel@tonic-gate 15470Sstevel@tonic-gate again: 15480Sstevel@tonic-gate err = md_hot_spare_ifc(HS_GET, un->un_hsp_id, nd.nd_nblks, 15490Sstevel@tonic-gate nd.nd_labeled, &nd.nd_hs_id, &nd.nd_key, &nd.nd_dev, 15500Sstevel@tonic-gate &nd.nd_start_blk); 15510Sstevel@tonic-gate 15520Sstevel@tonic-gate if (err) { 15530Sstevel@tonic-gate if (!stripe_replace_dev(dev, junk, ci, NULL, recids, nrecids, 15540Sstevel@tonic-gate replace_done, replace_data)) { 15550Sstevel@tonic-gate mddb_commitrecs_wrapper(recids); 15560Sstevel@tonic-gate md_unit_writerexit(ui); 15570Sstevel@tonic-gate } 15580Sstevel@tonic-gate recids[0] = 0; 15590Sstevel@tonic-gate return (1); 15600Sstevel@tonic-gate } 15610Sstevel@tonic-gate 15620Sstevel@tonic-gate if (stripe_replace_dev(dev, junk, ci, &nd, recids, nrecids, 15630Sstevel@tonic-gate replace_done, replace_data)) { 15640Sstevel@tonic-gate 15650Sstevel@tonic-gate (void) md_hot_spare_ifc(HS_BAD, un->un_hsp_id, 0, 0, 15660Sstevel@tonic-gate &nd.nd_hs_id, &nd.nd_key, NULL, NULL); 15670Sstevel@tonic-gate mddb_commitrec_wrapper(nd.nd_hs_id); 15680Sstevel@tonic-gate goto again; 15690Sstevel@tonic-gate } 15700Sstevel@tonic-gate 15710Sstevel@tonic-gate /* Leave a slot for the null recid */ 15720Sstevel@tonic-gate for (i = 0; i < (nrecids - 1); i++) { 15730Sstevel@tonic-gate if (recids[i] == 0) { 15740Sstevel@tonic-gate recids[i++] = nd.nd_hs_id; 15750Sstevel@tonic-gate recids[i] = 0; 15760Sstevel@tonic-gate } 15770Sstevel@tonic-gate } 15780Sstevel@tonic-gate return (0); 15790Sstevel@tonic-gate } 15800Sstevel@tonic-gate 15810Sstevel@tonic-gate static int 15820Sstevel@tonic-gate stripe_imp_set( 15830Sstevel@tonic-gate set_t setno 15840Sstevel@tonic-gate ) 15850Sstevel@tonic-gate { 15860Sstevel@tonic-gate 15870Sstevel@tonic-gate mddb_recid_t recid; 15880Sstevel@tonic-gate int i, row, c, gotsomething; 15890Sstevel@tonic-gate mddb_type_t typ1; 15900Sstevel@tonic-gate mddb_de_ic_t *dep; 15910Sstevel@tonic-gate mddb_rb32_t *rbp; 15920Sstevel@tonic-gate ms_unit32_od_t *un32; 15930Sstevel@tonic-gate ms_unit_t *un64; 15940Sstevel@tonic-gate minor_t *self_id; /* minor needs to be updated */ 15950Sstevel@tonic-gate md_parent_t *parent_id; /* parent needs to be updated */ 15960Sstevel@tonic-gate mddb_recid_t *record_id; /* record id needs to be updated */ 15970Sstevel@tonic-gate mddb_recid_t *hsp_id; 15980Sstevel@tonic-gate ms_comp32_od_t *comp32; 15990Sstevel@tonic-gate ms_comp_t *comp64; 16000Sstevel@tonic-gate 16010Sstevel@tonic-gate 16020Sstevel@tonic-gate gotsomething = 0; 16030Sstevel@tonic-gate 16040Sstevel@tonic-gate typ1 = (mddb_type_t)md_getshared_key(setno, 16050Sstevel@tonic-gate stripe_md_ops.md_driver.md_drivername); 16060Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 16070Sstevel@tonic-gate 16080Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, 0)) > 0) { 16090Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_GOTIT) 16100Sstevel@tonic-gate continue; 16110Sstevel@tonic-gate 16120Sstevel@tonic-gate dep = mddb_getrecdep(recid); 16130Sstevel@tonic-gate rbp = dep->de_rb; 16140Sstevel@tonic-gate 16150Sstevel@tonic-gate if (rbp->rb_revision == MDDB_REV_RB) { 16160Sstevel@tonic-gate /* 16170Sstevel@tonic-gate * Small device 16180Sstevel@tonic-gate */ 16190Sstevel@tonic-gate un32 = (ms_unit32_od_t *)mddb_getrecaddr(recid); 16200Sstevel@tonic-gate self_id = &(un32->c.un_self_id); 16210Sstevel@tonic-gate parent_id = &(un32->c.un_parent); 16220Sstevel@tonic-gate record_id = &(un32->c.un_record_id); 16230Sstevel@tonic-gate hsp_id = &(un32->un_hsp_id); 16240Sstevel@tonic-gate 16250Sstevel@tonic-gate comp32 = (ms_comp32_od_t *)((void *)&((char *)un32) 16260Sstevel@tonic-gate [un32->un_ocomp]); 16270Sstevel@tonic-gate for (row = 0; row < un32->un_nrows; row++) { 16280Sstevel@tonic-gate struct ms_row32_od *mdr = &un32->un_row[row]; 16290Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; 16300Sstevel@tonic-gate i < mdr->un_ncomp; i++) { 16310Sstevel@tonic-gate ms_comp32_od_t *mdc; 16320Sstevel@tonic-gate mdc = &comp32[c++]; 16330Sstevel@tonic-gate 16340Sstevel@tonic-gate if (!md_update_minor(setno, mddb_getsidenum 16350Sstevel@tonic-gate (setno), mdc->un_key)) 16360Sstevel@tonic-gate goto out; 16370Sstevel@tonic-gate 16380Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) 16390Sstevel@tonic-gate mdc->un_mirror.ms_hs_id = MAKERECID( 16400Sstevel@tonic-gate setno, mdc->un_mirror.ms_hs_id); 16410Sstevel@tonic-gate } 16420Sstevel@tonic-gate } 16430Sstevel@tonic-gate } else { 16440Sstevel@tonic-gate un64 = (ms_unit_t *)mddb_getrecaddr(recid); 16450Sstevel@tonic-gate self_id = &(un64->c.un_self_id); 16460Sstevel@tonic-gate parent_id = &(un64->c.un_parent); 16470Sstevel@tonic-gate record_id = &(un64->c.un_record_id); 16480Sstevel@tonic-gate hsp_id = &(un64->un_hsp_id); 16490Sstevel@tonic-gate 16500Sstevel@tonic-gate comp64 = (ms_comp_t *)((void *)&((char *)un64) 16510Sstevel@tonic-gate [un64->un_ocomp]); 16520Sstevel@tonic-gate for (row = 0; row < un64->un_nrows; row++) { 16530Sstevel@tonic-gate struct ms_row *mdr = &un64->un_row[row]; 16540Sstevel@tonic-gate for (i = 0, c = mdr->un_icomp; 16550Sstevel@tonic-gate i < mdr->un_ncomp; i++) { 16560Sstevel@tonic-gate ms_comp_t *mdc; 16570Sstevel@tonic-gate mdc = &comp64[c++]; 16580Sstevel@tonic-gate 16590Sstevel@tonic-gate if (!md_update_minor(setno, mddb_getsidenum 16600Sstevel@tonic-gate (setno), mdc->un_key)) 16610Sstevel@tonic-gate goto out; 16620Sstevel@tonic-gate 16630Sstevel@tonic-gate if (mdc->un_mirror.ms_hs_id != 0) 16640Sstevel@tonic-gate mdc->un_mirror.ms_hs_id = MAKERECID( 16650Sstevel@tonic-gate setno, mdc->un_mirror.ms_hs_id); 16660Sstevel@tonic-gate } 16670Sstevel@tonic-gate } 16680Sstevel@tonic-gate } 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate /* 16710Sstevel@tonic-gate * Update unit with the imported setno 16720Sstevel@tonic-gate * 16730Sstevel@tonic-gate */ 16740Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT); 16750Sstevel@tonic-gate 16760Sstevel@tonic-gate *self_id = MD_MKMIN(setno, MD_MIN2UNIT(*self_id)); 16770Sstevel@tonic-gate 16780Sstevel@tonic-gate if (*hsp_id != -1) 16790Sstevel@tonic-gate *hsp_id = MAKERECID(setno, DBID(*hsp_id)); 16800Sstevel@tonic-gate 16810Sstevel@tonic-gate if (*parent_id != MD_NO_PARENT) 16820Sstevel@tonic-gate *parent_id = MD_MKMIN(setno, MD_MIN2UNIT(*parent_id)); 16830Sstevel@tonic-gate *record_id = MAKERECID(setno, DBID(*record_id)); 16840Sstevel@tonic-gate 16850Sstevel@tonic-gate gotsomething = 1; 16860Sstevel@tonic-gate } 16870Sstevel@tonic-gate 16880Sstevel@tonic-gate out: 16890Sstevel@tonic-gate return (gotsomething); 16900Sstevel@tonic-gate } 16910Sstevel@tonic-gate 16920Sstevel@tonic-gate static md_named_services_t stripe_named_services[] = { 16930Sstevel@tonic-gate {stripe_shared_by_blk, "shared by blk" }, 16940Sstevel@tonic-gate {stripe_shared_by_indx, "shared by indx" }, 16950Sstevel@tonic-gate {stripe_component_count, "get component count" }, 16960Sstevel@tonic-gate {stripe_block_count_skip_size, "get block count skip size" }, 16970Sstevel@tonic-gate {stripe_get_dev, "get device" }, 16980Sstevel@tonic-gate {stripe_replace_dev, "replace device" }, 16990Sstevel@tonic-gate {stripe_hotspare_dev, "hotspare device" }, 17000Sstevel@tonic-gate {stripe_rename_check, MDRNM_CHECK }, 17010Sstevel@tonic-gate {NULL, 0} 17020Sstevel@tonic-gate }; 17030Sstevel@tonic-gate 17040Sstevel@tonic-gate md_ops_t stripe_md_ops = { 17050Sstevel@tonic-gate stripe_open, /* open */ 17060Sstevel@tonic-gate stripe_close, /* close */ 17070Sstevel@tonic-gate md_stripe_strategy, /* strategy */ 17080Sstevel@tonic-gate NULL, /* print */ 17090Sstevel@tonic-gate stripe_dump, /* dump */ 17100Sstevel@tonic-gate NULL, /* read */ 17110Sstevel@tonic-gate NULL, /* write */ 17120Sstevel@tonic-gate md_stripe_ioctl, /* stripe_ioctl, */ 17130Sstevel@tonic-gate stripe_snarf, /* stripe_snarf */ 17140Sstevel@tonic-gate stripe_halt, /* stripe_halt */ 17150Sstevel@tonic-gate NULL, /* aread */ 17160Sstevel@tonic-gate NULL, /* awrite */ 17170Sstevel@tonic-gate stripe_imp_set, /* import set */ 17180Sstevel@tonic-gate stripe_named_services 17190Sstevel@tonic-gate }; 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate static void 17220Sstevel@tonic-gate init_init() 17230Sstevel@tonic-gate { 17240Sstevel@tonic-gate md_stripe_mcs_buf_off = sizeof (md_scs_t) - sizeof (buf_t); 17250Sstevel@tonic-gate 17260Sstevel@tonic-gate stripe_parent_cache = kmem_cache_create("md_stripe_parent", 17270Sstevel@tonic-gate sizeof (md_sps_t), 0, stripe_parent_constructor, 17280Sstevel@tonic-gate stripe_parent_destructor, stripe_run_queue, NULL, NULL, 17290Sstevel@tonic-gate 0); 17300Sstevel@tonic-gate stripe_child_cache = kmem_cache_create("md_stripe_child", 17310Sstevel@tonic-gate sizeof (md_scs_t) - sizeof (buf_t) + biosize(), 0, 17320Sstevel@tonic-gate stripe_child_constructor, stripe_child_destructor, 17330Sstevel@tonic-gate stripe_run_queue, NULL, NULL, 0); 17340Sstevel@tonic-gate } 17350Sstevel@tonic-gate 17360Sstevel@tonic-gate static void 17370Sstevel@tonic-gate fini_uninit() 17380Sstevel@tonic-gate { 17390Sstevel@tonic-gate kmem_cache_destroy(stripe_parent_cache); 17400Sstevel@tonic-gate kmem_cache_destroy(stripe_child_cache); 17410Sstevel@tonic-gate stripe_parent_cache = stripe_child_cache = NULL; 17420Sstevel@tonic-gate } 17430Sstevel@tonic-gate 17440Sstevel@tonic-gate /* define the module linkage */ 17450Sstevel@tonic-gate MD_PLUGIN_MISC_MODULE("stripes module %I%", init_init(), fini_uninit()) 1746