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