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*8452SJohn.Wren.Kennedy@Sun.COM * Common Development and Distribution License (the "License"). 6*8452SJohn.Wren.Kennedy@Sun.COM * 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*8452SJohn.Wren.Kennedy@Sun.COM 220Sstevel@tonic-gate /* 23*8452SJohn.Wren.Kennedy@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 "mdinclude.h" 280Sstevel@tonic-gate 290Sstevel@tonic-gate typedef struct submirror_cb { 300Sstevel@tonic-gate minor_t un_self_id; 310Sstevel@tonic-gate int un_nsm; 320Sstevel@tonic-gate ushort_t mm_un_nsm; 330Sstevel@tonic-gate }submirror_cb_t; 340Sstevel@tonic-gate 350Sstevel@tonic-gate void 360Sstevel@tonic-gate print_setname(int setno) 370Sstevel@tonic-gate { 380Sstevel@tonic-gate char setname[1024]; 390Sstevel@tonic-gate 400Sstevel@tonic-gate if (setno != 0) { 410Sstevel@tonic-gate if (mdb_readstr(setname, 1024, 420Sstevel@tonic-gate (uintptr_t)set_dbs[setno].s_setname) == -1) { 430Sstevel@tonic-gate mdb_warn("failed to read setname at 0x%p\n", 440Sstevel@tonic-gate set_dbs[setno].s_setname); 450Sstevel@tonic-gate } 460Sstevel@tonic-gate mdb_printf("%s/", setname); 470Sstevel@tonic-gate } 480Sstevel@tonic-gate } 490Sstevel@tonic-gate 500Sstevel@tonic-gate void 510Sstevel@tonic-gate print_stripe(void *un_addr, void *mdcptr, uint_t verbose) 520Sstevel@tonic-gate { 530Sstevel@tonic-gate ms_unit_t ms; 540Sstevel@tonic-gate int setno; 550Sstevel@tonic-gate minor_t un_self_id; 560Sstevel@tonic-gate md_parent_t un_parent; 570Sstevel@tonic-gate diskaddr_t un_total_blocks; 580Sstevel@tonic-gate 590Sstevel@tonic-gate /* read in the device */ 600Sstevel@tonic-gate un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; 610Sstevel@tonic-gate un_parent = ((mdc_unit_t *)mdcptr)->un_parent; 620Sstevel@tonic-gate un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; 630Sstevel@tonic-gate if (mdb_vread(&ms, sizeof (ms_unit_t), 640Sstevel@tonic-gate (uintptr_t)un_addr) == -1) { 650Sstevel@tonic-gate mdb_warn("failed to read ms_unit_t at %p\n", un_addr); 660Sstevel@tonic-gate return; 670Sstevel@tonic-gate } 680Sstevel@tonic-gate 690Sstevel@tonic-gate setno = MD_MIN2SET(un_self_id); 700Sstevel@tonic-gate print_setname(setno); 710Sstevel@tonic-gate 720Sstevel@tonic-gate mdb_printf("d%u: ", MD_MIN2UNIT(un_self_id)); 730Sstevel@tonic-gate if (un_parent == ((unit_t)-1)) { 740Sstevel@tonic-gate mdb_printf("Concat/Stripe"); 750Sstevel@tonic-gate } else { 760Sstevel@tonic-gate mdb_printf("Subdevice of d%u", MD_MIN2UNIT(un_parent)); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate if (verbose) { 790Sstevel@tonic-gate mdb_printf("\t< %p::print ms_unit_t >\n", un_addr); 800Sstevel@tonic-gate } else { 810Sstevel@tonic-gate mdb_printf("\t< %p>\n", un_addr); 820Sstevel@tonic-gate } 830Sstevel@tonic-gate mdb_inc_indent(2); 840Sstevel@tonic-gate mdb_printf("Size: %llu blocks\n", un_total_blocks); 850Sstevel@tonic-gate mdb_printf("Rows: %u\n", ms.un_nrows); 860Sstevel@tonic-gate mdb_dec_indent(2); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate /* ARGSUSED */ 900Sstevel@tonic-gate int 910Sstevel@tonic-gate print_submirror(uintptr_t addr, void *arg, submirror_cb_t *data) 920Sstevel@tonic-gate { 930Sstevel@tonic-gate uintptr_t un_addr; 940Sstevel@tonic-gate mdc_unit_t mdc_sm; 950Sstevel@tonic-gate 960Sstevel@tonic-gate if (mdb_vread(&un_addr, sizeof (void *), addr) == -1) { 970Sstevel@tonic-gate mdb_warn("failed to read submirror at %p\n", addr); 980Sstevel@tonic-gate return (WALK_ERR); 990Sstevel@tonic-gate } 1000Sstevel@tonic-gate if (un_addr != NULL) { 1010Sstevel@tonic-gate if (mdb_vread(&mdc_sm, sizeof (mdc_unit_t), un_addr) == -1) { 1020Sstevel@tonic-gate mdb_warn("failed to read mdc_unit_t at %p", un_addr); 1030Sstevel@tonic-gate return (WALK_ERR); 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate if (mdc_sm.un_parent == data->un_self_id) { 1060Sstevel@tonic-gate /* this is one of the sub mirrors */ 1070Sstevel@tonic-gate mdb_printf("Submirror %u: d%u ", 1080Sstevel@tonic-gate data->un_nsm, MD_MIN2UNIT(mdc_sm.un_self_id)); 1090Sstevel@tonic-gate mdb_printf("Size: %llu\n", mdc_sm.un_total_blocks); 1100Sstevel@tonic-gate data->un_nsm++; 1110Sstevel@tonic-gate if (data->un_nsm == data->mm_un_nsm) 1120Sstevel@tonic-gate return (WALK_DONE); 1130Sstevel@tonic-gate } 1140Sstevel@tonic-gate } 1150Sstevel@tonic-gate return (WALK_NEXT); 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 118*8452SJohn.Wren.Kennedy@Sun.COM /* 119*8452SJohn.Wren.Kennedy@Sun.COM * Construct an RLE count for the number of 'cleared' bits in the given 'bm' 120*8452SJohn.Wren.Kennedy@Sun.COM * Output the RLE count in form: [<set>.<cleared>.<set>.<cleared>...] 121*8452SJohn.Wren.Kennedy@Sun.COM * RLE is Run Length Encoding, a method for compactly describing a bitmap 122*8452SJohn.Wren.Kennedy@Sun.COM * as a series of numbers indicating the count of consecutive set or cleared 123*8452SJohn.Wren.Kennedy@Sun.COM * bits. 124*8452SJohn.Wren.Kennedy@Sun.COM * 125*8452SJohn.Wren.Kennedy@Sun.COM * Input: 126*8452SJohn.Wren.Kennedy@Sun.COM * <bm> bitmap to scan 127*8452SJohn.Wren.Kennedy@Sun.COM * <size> length of bitmap (in bits) 128*8452SJohn.Wren.Kennedy@Sun.COM * <comp_bm> RLE count array to be updated 129*8452SJohn.Wren.Kennedy@Sun.COM * <opstr> Descriptive text for bitmap RLE count display 130*8452SJohn.Wren.Kennedy@Sun.COM */ 131*8452SJohn.Wren.Kennedy@Sun.COM static void 132*8452SJohn.Wren.Kennedy@Sun.COM print_comp_bm(unsigned char *bm, uint_t size, ushort_t *comp_bm, char *opstr) 133*8452SJohn.Wren.Kennedy@Sun.COM { 134*8452SJohn.Wren.Kennedy@Sun.COM int cnt_clean, tot_dirty, cur_idx; 135*8452SJohn.Wren.Kennedy@Sun.COM int i, cur_clean, cur_dirty, printit, max_set_cnt, max_reset_cnt; 136*8452SJohn.Wren.Kennedy@Sun.COM 137*8452SJohn.Wren.Kennedy@Sun.COM cnt_clean = 1; 138*8452SJohn.Wren.Kennedy@Sun.COM printit = 0; 139*8452SJohn.Wren.Kennedy@Sun.COM cur_clean = 0; 140*8452SJohn.Wren.Kennedy@Sun.COM cur_dirty = 0; 141*8452SJohn.Wren.Kennedy@Sun.COM cur_idx = 0; 142*8452SJohn.Wren.Kennedy@Sun.COM tot_dirty = 0; 143*8452SJohn.Wren.Kennedy@Sun.COM max_set_cnt = max_reset_cnt = 0; 144*8452SJohn.Wren.Kennedy@Sun.COM for (i = 0; i < size; i++) { 145*8452SJohn.Wren.Kennedy@Sun.COM if (isset(bm, i)) { 146*8452SJohn.Wren.Kennedy@Sun.COM /* If we're counting clean bits, flush the count out */ 147*8452SJohn.Wren.Kennedy@Sun.COM if (cnt_clean) { 148*8452SJohn.Wren.Kennedy@Sun.COM cnt_clean = 0; 149*8452SJohn.Wren.Kennedy@Sun.COM comp_bm[cur_idx] = cur_clean; 150*8452SJohn.Wren.Kennedy@Sun.COM printit = 1; 151*8452SJohn.Wren.Kennedy@Sun.COM if (cur_clean > max_reset_cnt) { 152*8452SJohn.Wren.Kennedy@Sun.COM max_reset_cnt = cur_clean; 153*8452SJohn.Wren.Kennedy@Sun.COM } 154*8452SJohn.Wren.Kennedy@Sun.COM } 155*8452SJohn.Wren.Kennedy@Sun.COM cur_clean = 0; 156*8452SJohn.Wren.Kennedy@Sun.COM cur_dirty++; 157*8452SJohn.Wren.Kennedy@Sun.COM tot_dirty++; 158*8452SJohn.Wren.Kennedy@Sun.COM } else { 159*8452SJohn.Wren.Kennedy@Sun.COM if (!cnt_clean) { 160*8452SJohn.Wren.Kennedy@Sun.COM cnt_clean = 1; 161*8452SJohn.Wren.Kennedy@Sun.COM comp_bm[cur_idx] = cur_dirty; 162*8452SJohn.Wren.Kennedy@Sun.COM printit = 1; 163*8452SJohn.Wren.Kennedy@Sun.COM if (cur_dirty > max_set_cnt) { 164*8452SJohn.Wren.Kennedy@Sun.COM max_set_cnt = cur_dirty; 165*8452SJohn.Wren.Kennedy@Sun.COM } 166*8452SJohn.Wren.Kennedy@Sun.COM } 167*8452SJohn.Wren.Kennedy@Sun.COM cur_dirty = 0; 168*8452SJohn.Wren.Kennedy@Sun.COM cur_clean++; 169*8452SJohn.Wren.Kennedy@Sun.COM } 170*8452SJohn.Wren.Kennedy@Sun.COM if (printit) { 171*8452SJohn.Wren.Kennedy@Sun.COM mdb_printf("%u.", comp_bm[cur_idx++]); 172*8452SJohn.Wren.Kennedy@Sun.COM printit = 0; 173*8452SJohn.Wren.Kennedy@Sun.COM } 174*8452SJohn.Wren.Kennedy@Sun.COM } 175*8452SJohn.Wren.Kennedy@Sun.COM 176*8452SJohn.Wren.Kennedy@Sun.COM mdb_printf("\nTotal %s bits = %lu\n", opstr, tot_dirty); 177*8452SJohn.Wren.Kennedy@Sun.COM mdb_printf("Total %s transactions = %lu\n", opstr, cur_idx); 178*8452SJohn.Wren.Kennedy@Sun.COM mdb_printf("Maximum %s set count = %lu, reset count = %lu\n", opstr, 179*8452SJohn.Wren.Kennedy@Sun.COM max_set_cnt, max_reset_cnt); 180*8452SJohn.Wren.Kennedy@Sun.COM } 181*8452SJohn.Wren.Kennedy@Sun.COM 1820Sstevel@tonic-gate void 1830Sstevel@tonic-gate print_mirror(void *un_addr, void *mdcptr, uint_t verbose) 1840Sstevel@tonic-gate { 185*8452SJohn.Wren.Kennedy@Sun.COM mm_unit_t mm, *mmp; 1860Sstevel@tonic-gate void **ptr; 1870Sstevel@tonic-gate int setno = 0; 1880Sstevel@tonic-gate minor_t un_self_id; 1890Sstevel@tonic-gate diskaddr_t un_total_blocks; 1900Sstevel@tonic-gate ushort_t mm_un_nsm; 1910Sstevel@tonic-gate submirror_cb_t data; 192*8452SJohn.Wren.Kennedy@Sun.COM uint_t num_rr, rr_blksize; 193*8452SJohn.Wren.Kennedy@Sun.COM ushort_t *comp_rr; 194*8452SJohn.Wren.Kennedy@Sun.COM unsigned char *rr_dirty_bm, *rr_goingclean_bm; 195*8452SJohn.Wren.Kennedy@Sun.COM uintptr_t un_dbm, un_gcbm; 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate /* read in the device */ 1980Sstevel@tonic-gate if (mdb_vread(&mm, sizeof (mm_unit_t), 1990Sstevel@tonic-gate (uintptr_t)un_addr) == -1) { 2000Sstevel@tonic-gate mdb_warn("failed to read mm_unit_t at %p\n", un_addr); 2010Sstevel@tonic-gate return; 2020Sstevel@tonic-gate } 203*8452SJohn.Wren.Kennedy@Sun.COM 204*8452SJohn.Wren.Kennedy@Sun.COM mmp = &mm; 205*8452SJohn.Wren.Kennedy@Sun.COM 2060Sstevel@tonic-gate un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; 2070Sstevel@tonic-gate un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; 2080Sstevel@tonic-gate mm_un_nsm = mm.un_nsm; 2090Sstevel@tonic-gate setno = MD_MIN2SET(un_self_id); 2100Sstevel@tonic-gate print_setname(setno); 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate mdb_printf("d%u: Mirror", MD_MIN2UNIT(un_self_id)); 2130Sstevel@tonic-gate if (verbose) { 2140Sstevel@tonic-gate mdb_printf("\t< %p::print mm_unit_t >\n", un_addr); 2150Sstevel@tonic-gate } else { 2160Sstevel@tonic-gate mdb_printf("\t< %p >\n", un_addr); 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate mdb_inc_indent(2); 2190Sstevel@tonic-gate mdb_printf("Size: %llu blocks\n", un_total_blocks); 220*8452SJohn.Wren.Kennedy@Sun.COM 221*8452SJohn.Wren.Kennedy@Sun.COM /* 222*8452SJohn.Wren.Kennedy@Sun.COM * Dump out the current un_dirty_bm together with its size 223*8452SJohn.Wren.Kennedy@Sun.COM * Also, attempt to Run Length encode the bitmap to see if this 224*8452SJohn.Wren.Kennedy@Sun.COM * is a viable option 225*8452SJohn.Wren.Kennedy@Sun.COM */ 226*8452SJohn.Wren.Kennedy@Sun.COM num_rr = mm.un_rrd_num; 227*8452SJohn.Wren.Kennedy@Sun.COM rr_blksize = mm.un_rrd_blksize; 228*8452SJohn.Wren.Kennedy@Sun.COM 229*8452SJohn.Wren.Kennedy@Sun.COM un_dbm = (uintptr_t)mmp->un_dirty_bm; 230*8452SJohn.Wren.Kennedy@Sun.COM un_gcbm = (uintptr_t)mmp->un_goingclean_bm; 231*8452SJohn.Wren.Kennedy@Sun.COM 232*8452SJohn.Wren.Kennedy@Sun.COM mdb_printf("RR size: %lu bits\n", num_rr); 233*8452SJohn.Wren.Kennedy@Sun.COM mdb_printf("RR block size: %lu blocks\n", rr_blksize); 234*8452SJohn.Wren.Kennedy@Sun.COM 235*8452SJohn.Wren.Kennedy@Sun.COM rr_dirty_bm = (unsigned char *)mdb_alloc(num_rr, UM_SLEEP|UM_GC); 236*8452SJohn.Wren.Kennedy@Sun.COM rr_goingclean_bm = (unsigned char *)mdb_alloc(num_rr, UM_SLEEP|UM_GC); 237*8452SJohn.Wren.Kennedy@Sun.COM comp_rr = (ushort_t *)mdb_alloc(num_rr * sizeof (ushort_t), 238*8452SJohn.Wren.Kennedy@Sun.COM UM_SLEEP|UM_GC); 239*8452SJohn.Wren.Kennedy@Sun.COM 240*8452SJohn.Wren.Kennedy@Sun.COM if (mdb_vread(rr_dirty_bm, num_rr, un_dbm) == -1) { 241*8452SJohn.Wren.Kennedy@Sun.COM mdb_warn("failed to read un_dirty_bm at %p\n", un_dbm); 242*8452SJohn.Wren.Kennedy@Sun.COM return; 243*8452SJohn.Wren.Kennedy@Sun.COM } 244*8452SJohn.Wren.Kennedy@Sun.COM if (mdb_vread(rr_goingclean_bm, num_rr, un_gcbm) == -1) { 245*8452SJohn.Wren.Kennedy@Sun.COM mdb_warn("failed to read un_goingclean_bm at %p\n", un_gcbm); 246*8452SJohn.Wren.Kennedy@Sun.COM return; 247*8452SJohn.Wren.Kennedy@Sun.COM } 248*8452SJohn.Wren.Kennedy@Sun.COM 249*8452SJohn.Wren.Kennedy@Sun.COM print_comp_bm(rr_dirty_bm, num_rr, comp_rr, "dirty"); 250*8452SJohn.Wren.Kennedy@Sun.COM 251*8452SJohn.Wren.Kennedy@Sun.COM print_comp_bm(rr_goingclean_bm, num_rr, comp_rr, "clean"); 252*8452SJohn.Wren.Kennedy@Sun.COM 2530Sstevel@tonic-gate /* 2540Sstevel@tonic-gate * find the sub mirrors, search through each metadevice looking 2550Sstevel@tonic-gate * at the un_parent. 2560Sstevel@tonic-gate */ 2570Sstevel@tonic-gate ptr = mdset[setno].s_un; 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate data.un_self_id = un_self_id; 2600Sstevel@tonic-gate data.un_nsm = 0; 2610Sstevel@tonic-gate data.mm_un_nsm = mm_un_nsm; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate if (mdb_pwalk("md_units", (mdb_walk_cb_t)print_submirror, &data, 2640Sstevel@tonic-gate (uintptr_t)ptr) == -1) { 2650Sstevel@tonic-gate mdb_warn("unable to walk units\n"); 2660Sstevel@tonic-gate return; 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate mdb_dec_indent(2); 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate void 2730Sstevel@tonic-gate print_raid(void *un_addr, void *mdcptr, uint_t verbose) 2740Sstevel@tonic-gate { 2750Sstevel@tonic-gate mr_unit_t mr; 2760Sstevel@tonic-gate minor_t un_self_id; 2770Sstevel@tonic-gate diskaddr_t un_total_blocks; 2780Sstevel@tonic-gate mdc_unit_t mdc_sc; 2790Sstevel@tonic-gate void **ptr; 2800Sstevel@tonic-gate void *addr; 2810Sstevel@tonic-gate int setno = 0; 2820Sstevel@tonic-gate int i; 2830Sstevel@tonic-gate minor_t sc_un_self_id; 2840Sstevel@tonic-gate md_parent_t sc_parent; 2850Sstevel@tonic-gate diskaddr_t sc_total_blocks; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* read in the device */ 2880Sstevel@tonic-gate if (mdb_vread(&mr, sizeof (mr_unit_t), (uintptr_t)un_addr) == -1) { 2890Sstevel@tonic-gate mdb_warn("failed to read mr_unit_t at %p\n", un_addr); 2900Sstevel@tonic-gate return; 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; 2930Sstevel@tonic-gate un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; 2940Sstevel@tonic-gate setno = MD_MIN2SET(un_self_id); 2950Sstevel@tonic-gate print_setname(setno); 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate mdb_printf("d%u: Raid", MD_MIN2UNIT(un_self_id)); 2980Sstevel@tonic-gate if (verbose) { 2990Sstevel@tonic-gate mdb_printf("\t< %p ::print mr_unit_t>\n", un_addr); 3000Sstevel@tonic-gate } else { 3010Sstevel@tonic-gate mdb_printf("\t< %p >\n", un_addr); 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate mdb_inc_indent(2); 3040Sstevel@tonic-gate mdb_printf("Size: %llu\n", un_total_blocks); 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate /* 3070Sstevel@tonic-gate * find the sub components if any, search through each metadevice 3080Sstevel@tonic-gate * looking at the un_parent. 3090Sstevel@tonic-gate */ 3100Sstevel@tonic-gate ptr = mdset[setno].s_un; 3110Sstevel@tonic-gate for (i = 0; i < md_nunits; i++, ptr++) { 3120Sstevel@tonic-gate if (mdb_vread(&addr, sizeof (void *), (uintptr_t)ptr) == -1) { 3130Sstevel@tonic-gate mdb_warn("failed to read addr at %p\n", ptr); 3140Sstevel@tonic-gate continue; 3150Sstevel@tonic-gate } 3160Sstevel@tonic-gate if (addr != NULL) { 3170Sstevel@tonic-gate if (mdb_vread(&mdc_sc, sizeof (mdc_unit_t), 3180Sstevel@tonic-gate (uintptr_t)addr) == -1) { 3190Sstevel@tonic-gate mdb_warn("failed to read mdc_unit_t at %p", 3200Sstevel@tonic-gate un_addr); 3210Sstevel@tonic-gate continue; 3220Sstevel@tonic-gate } 3230Sstevel@tonic-gate sc_parent = mdc_sc.un_parent; 3240Sstevel@tonic-gate sc_un_self_id = mdc_sc.un_self_id; 3250Sstevel@tonic-gate sc_total_blocks = mdc_sc.un_total_blocks; 3260Sstevel@tonic-gate if (sc_parent == un_self_id) { 3270Sstevel@tonic-gate /* this is one of the sub components */ 3280Sstevel@tonic-gate mdb_printf("Subdevice %u ", 3290Sstevel@tonic-gate MD_MIN2UNIT(sc_un_self_id)); 3300Sstevel@tonic-gate mdb_printf("Size: %llu\n", sc_total_blocks); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate mdb_dec_indent(2); 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate void 3380Sstevel@tonic-gate print_sp(void *un_addr, void *mdcptr, uint_t verbose) 3390Sstevel@tonic-gate { 3400Sstevel@tonic-gate mp_unit_t mp; 3410Sstevel@tonic-gate minor_t un_self_id; 3420Sstevel@tonic-gate diskaddr_t un_total_blocks; 3430Sstevel@tonic-gate int setno = 0; 3440Sstevel@tonic-gate uintptr_t extaddr; 3450Sstevel@tonic-gate int i; 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* read in the device */ 3480Sstevel@tonic-gate if (mdb_vread(&mp, sizeof (mp_unit_t), (uintptr_t)un_addr) == -1) { 3490Sstevel@tonic-gate mdb_warn("failed to read mp_unit_t at %p\n", un_addr); 3500Sstevel@tonic-gate return; 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; 3530Sstevel@tonic-gate un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; 3540Sstevel@tonic-gate setno = MD_MIN2SET(un_self_id); 3550Sstevel@tonic-gate print_setname(setno); 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate mdb_printf("d%u: Soft Partition", MD_MIN2UNIT(un_self_id)); 3580Sstevel@tonic-gate if (verbose) { 3590Sstevel@tonic-gate mdb_printf("\t< %p ::print mp_unit_t >\n", un_addr); 3600Sstevel@tonic-gate } else { 3610Sstevel@tonic-gate mdb_printf("\t< %p >\n", un_addr); 3620Sstevel@tonic-gate } 3630Sstevel@tonic-gate mdb_inc_indent(2); 3640Sstevel@tonic-gate mdb_printf("Size: %llu\n", un_total_blocks); 3650Sstevel@tonic-gate mdb_inc_indent(2); 3660Sstevel@tonic-gate mdb_printf("Extent\tStart Block\tBlock count\n"); 3670Sstevel@tonic-gate extaddr = (uintptr_t)un_addr + sizeof (mp_unit_t) - sizeof (mp_ext_t); 3680Sstevel@tonic-gate for (i = 0; i < mp.un_numexts; i++) { 3690Sstevel@tonic-gate mp_ext_t mpext; 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate if (mdb_vread(&mpext, sizeof (mp_ext_t), extaddr) == -1) { 3720Sstevel@tonic-gate mdb_warn("failed to read mp_ext_t at %p\n", extaddr); 3730Sstevel@tonic-gate return; 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate mdb_printf(" %d \t %llu\t %llu\n", 3760Sstevel@tonic-gate i, mpext.un_poff, mpext.un_len); 3770Sstevel@tonic-gate extaddr += sizeof (mp_ext_t); 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate mdb_dec_indent(2); 3800Sstevel@tonic-gate mdb_dec_indent(2); 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate void 3850Sstevel@tonic-gate print_trans(void *un_addr, void *mdcptr, uint_t verbose) 3860Sstevel@tonic-gate { 3870Sstevel@tonic-gate mt_unit_t mt; 3880Sstevel@tonic-gate minor_t un_self_id; 3890Sstevel@tonic-gate int setno = 0; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate /* read in the device */ 3920Sstevel@tonic-gate if (mdb_vread(&mt, sizeof (mt_unit_t), (uintptr_t)un_addr) == -1) { 3930Sstevel@tonic-gate mdb_warn("failed to read mt_unit_t at %p\n", un_addr); 3940Sstevel@tonic-gate return; 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate un_self_id = ((mdc_unit32_od_t *)mdcptr)->un_self_id; 3970Sstevel@tonic-gate setno = MD_MIN2SET(un_self_id); 3980Sstevel@tonic-gate print_setname(setno); 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate mdb_printf("d%u: Trans", MD_MIN2UNIT(un_self_id)); 4010Sstevel@tonic-gate if (verbose) { 4020Sstevel@tonic-gate mdb_printf("\t< %p ::print mt_unit_t>\n", un_addr); 4030Sstevel@tonic-gate } else { 4040Sstevel@tonic-gate mdb_printf("\t< %p >\n", un_addr); 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate void 4100Sstevel@tonic-gate print_device(void *un_addr, void *mdcptr, uint_t verbose) 4110Sstevel@tonic-gate { 4120Sstevel@tonic-gate u_longlong_t un_type; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate un_type = ((mdc_unit_t *)mdcptr)->un_type; 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate switch (un_type) { 4170Sstevel@tonic-gate case MD_DEVICE: /* stripe/concat */ 4180Sstevel@tonic-gate print_stripe(un_addr, mdcptr, verbose); 4190Sstevel@tonic-gate break; 4200Sstevel@tonic-gate case MD_METAMIRROR: 4210Sstevel@tonic-gate print_mirror(un_addr, mdcptr, verbose); 4220Sstevel@tonic-gate break; 4230Sstevel@tonic-gate case MD_METATRANS: 4240Sstevel@tonic-gate print_trans(un_addr, mdcptr, verbose); 4250Sstevel@tonic-gate break; 4260Sstevel@tonic-gate case MD_METARAID: 4270Sstevel@tonic-gate print_raid(un_addr, mdcptr, verbose); 4280Sstevel@tonic-gate break; 4290Sstevel@tonic-gate case MD_METASP: 4300Sstevel@tonic-gate print_sp(un_addr, mdcptr, verbose); 4310Sstevel@tonic-gate break; 4320Sstevel@tonic-gate case MD_UNDEFINED: 4330Sstevel@tonic-gate mdb_warn("undefined metadevice at %p\n", un_addr); 4340Sstevel@tonic-gate break; 4350Sstevel@tonic-gate default: 4360Sstevel@tonic-gate mdb_warn("invalid metadevice at %p\n", un_addr); 4370Sstevel@tonic-gate break; 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate /* ARGSUSED */ 4420Sstevel@tonic-gate /* 4430Sstevel@tonic-gate * usage: ::metastat [-v] 4440Sstevel@tonic-gate */ 4450Sstevel@tonic-gate int 4460Sstevel@tonic-gate metastat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 4470Sstevel@tonic-gate { 4480Sstevel@tonic-gate mdc_unit_t mdc; 4490Sstevel@tonic-gate uintptr_t un_addr; 4500Sstevel@tonic-gate uint_t verbose = FALSE; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate snarf_sets(); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) 4550Sstevel@tonic-gate != argc) { 4560Sstevel@tonic-gate return (DCMD_USAGE); 4570Sstevel@tonic-gate } 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 4600Sstevel@tonic-gate if (mdb_walk_dcmd("md_units", "metastat", argc, 4610Sstevel@tonic-gate argv) == -1) { 4620Sstevel@tonic-gate mdb_warn("failed to walk units"); 4630Sstevel@tonic-gate return (DCMD_ERR); 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate return (DCMD_OK); 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate if (!(flags & DCMD_LOOP)) { 4680Sstevel@tonic-gate /* user passed set addr */ 4690Sstevel@tonic-gate if (mdb_pwalk_dcmd("md_units", "metastat", argc, 4700Sstevel@tonic-gate argv, addr) == -1) { 4710Sstevel@tonic-gate mdb_warn("failed to walk units"); 4720Sstevel@tonic-gate return (DCMD_ERR); 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate return (DCMD_OK); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate if (mdb_vread(&un_addr, sizeof (void *), addr) == -1) { 4780Sstevel@tonic-gate mdb_warn("failed to read un_addr at %p", addr); 4790Sstevel@tonic-gate return (DCMD_ERR); 4800Sstevel@tonic-gate } 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate if (un_addr != NULL) { 4830Sstevel@tonic-gate if (mdb_vread(&mdc, sizeof (mdc_unit_t), un_addr) == -1) { 4840Sstevel@tonic-gate mdb_warn("failed to read mdc_unit_t at %p", un_addr); 4850Sstevel@tonic-gate return (DCMD_ERR); 4860Sstevel@tonic-gate } 4870Sstevel@tonic-gate print_device((void *)un_addr, (void *)&mdc, verbose); 4880Sstevel@tonic-gate mdb_dec_indent(2); 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate return (DCMD_OK); 4910Sstevel@tonic-gate } 492