diff options
Diffstat (limited to 'usr/src/cmd/mdb/common/modules')
-rw-r--r-- | usr/src/cmd/mdb/common/modules/md/dumpmirror.c | 230 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/md/md.c | 12 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/md/metastat.c | 116 |
3 files changed, 345 insertions, 13 deletions
diff --git a/usr/src/cmd/mdb/common/modules/md/dumpmirror.c b/usr/src/cmd/mdb/common/modules/md/dumpmirror.c new file mode 100644 index 0000000000..53e70438b7 --- /dev/null +++ b/usr/src/cmd/mdb/common/modules/md/dumpmirror.c @@ -0,0 +1,230 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "mdinclude.h" + +/* + * Display an arbitrary bitmap by showing the set bits in the array. + * Output will be <start>-<end> for ranges or <position> for singleton bits. + */ +static void +print_mm_bm(unsigned char *bm, uint_t size, char *bm_name) +{ + int i; + int first_set = -1; + int need_comma = 0; + + mdb_printf("%s set bits: ", bm_name); + for (i = 0; i < size; i++) { + if (isset(bm, i)) { + if (first_set == -1) { + first_set = i; + } + } else { + if (first_set != -1) { + if (first_set != (i-1)) { + mdb_printf("%s%u-%u", + (need_comma ? "," : ""), + first_set, (i-1)); + } else { + mdb_printf("%s%u", + (need_comma ? "," : ""), first_set); + } + need_comma = 1; + first_set = -1; + } + } + } + if (first_set != -1) { + mdb_printf("%s%u-%u", (need_comma ? "," : ""), first_set, + size-1); + } + mdb_printf("\n"); +} + +/* + * Print uchar_t sized count fields (typically un_pernode_dirty_map entries) + */ + +static void +print_mm_cnt_c(unsigned char *bm, uint_t size, char *bm_name) +{ + int i; + int need_comma = 0; + + mdb_printf("%s set counts: ", bm_name); + for (i = 0; i < size; i++) { + if (bm[i]) { + mdb_printf("%s(%d,%3d)", (need_comma ? "," : ""), i, + (uint_t)bm[i]); + need_comma = 1; + } + } + mdb_printf("\n"); +} + +static void +print_mm_cnt_w(unsigned short *bm, uint_t size, char *bm_name) +{ + int i; + int need_comma = 0; + + mdb_printf("%s set counts: ", bm_name); + for (i = 0; i < size; i++) { + if (bm[i]) { + mdb_printf("%s(%d,%5d)", (need_comma ? "," : ""), i, + (uint_t)bm[i]); + need_comma = 1; + } + } + mdb_printf("\n"); +} + +/* + * Print the associated bitmaps for the specified mm_unit_t + * These are: + * un_pernode_dirty_bm + * un_goingclean_bm + * un_dirty_bm + * un_goingdirty_bm + * un_resync_bm + * + * Associated counts for unit: + * un_pernode_dirty_sum[] (uchar_t) + * un_outstanding_writes[] (ushort_t) + * + */ + +/* ARGSUSED */ +int +printmmbm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + mm_unit_t mm, *mmp; + unsigned char *rr_dirty_bm, *rr_goingclean_bm, *rr_goingdirty_bm; + unsigned char *rr_resync_bm; + uintptr_t un_dbm, un_gcbm, un_gdbm, un_rrbm, un_pnds, un_ow; + uint_t num_rr, rr_bitmap_size; + int i; + uintptr_t un_pernode_bm; + unsigned char *rr_pernode_dirty, *rr_pnds; + unsigned short *rr_ow; + /* just enough for un_pernode_dirty_bm[] plus three digits */ + char pernode_str[25]; + + if (argc != 0) + return (DCMD_USAGE); + + if (!(flags & DCMD_ADDRSPEC)) { + mdb_warn("No mm_unit_t address specified"); + return (DCMD_ERR); + } + + if (mdb_vread(&mm, sizeof (mm_unit_t), addr) == -1) { + mdb_warn("failed to read mm_unit_t at %p\n", addr); + return (DCMD_ERR); + } + + mmp = &mm; + + num_rr = mm.un_rrd_num; + + un_dbm = (uintptr_t)mmp->un_dirty_bm; + un_gcbm = (uintptr_t)mmp->un_goingclean_bm; + un_gdbm = (uintptr_t)mmp->un_goingdirty_bm; + un_rrbm = (uintptr_t)mmp->un_resync_bm; + un_pnds = (uintptr_t)mmp->un_pernode_dirty_sum; + un_ow = (uintptr_t)mmp->un_outstanding_writes; + + rr_bitmap_size = howmany(num_rr, NBBY); + rr_dirty_bm = (unsigned char *)mdb_alloc(rr_bitmap_size, + UM_SLEEP|UM_GC); + rr_goingclean_bm = (unsigned char *)mdb_alloc(rr_bitmap_size, + UM_SLEEP|UM_GC); + rr_goingdirty_bm = (unsigned char *)mdb_alloc(rr_bitmap_size, + UM_SLEEP|UM_GC); + rr_resync_bm = (unsigned char *)mdb_alloc(rr_bitmap_size, + UM_SLEEP|UM_GC); + rr_pnds = (unsigned char *)mdb_alloc(num_rr, UM_SLEEP|UM_GC); + rr_ow = (unsigned short *)mdb_alloc(num_rr * sizeof (unsigned short), + UM_SLEEP|UM_GC); + + if (mdb_vread(rr_dirty_bm, rr_bitmap_size, un_dbm) == -1) { + mdb_warn("failed to read un_dirty_bm at %p\n", un_dbm); + return (DCMD_ERR); + } + if (mdb_vread(rr_goingclean_bm, rr_bitmap_size, un_gcbm) == -1) { + mdb_warn("failed to read un_goingclean_bm at %p\n", un_gcbm); + return (DCMD_ERR); + } + if (mdb_vread(rr_goingdirty_bm, rr_bitmap_size, un_gdbm) == -1) { + mdb_warn("failed to read un_goingdirty_bm at %p\n", un_gdbm); + return (DCMD_ERR); + } + if (mdb_vread(rr_resync_bm, rr_bitmap_size, un_rrbm) == -1) { + mdb_warn("failed to read un_resync_bm at %p\n", un_rrbm); + return (DCMD_ERR); + } + if (mdb_vread(rr_pnds, num_rr, un_pnds) == -1) { + mdb_warn("failed to read un_pernode_dirty_sum at %p\n", + un_pnds); + return (DCMD_ERR); + } + if (mdb_vread(rr_ow, num_rr * sizeof (unsigned short), un_ow) == -1) { + mdb_warn("failed to read un_outstanding_writes at %p\n", un_ow); + return (DCMD_ERR); + } + + print_mm_bm(rr_dirty_bm, num_rr, "un_dirty_bm"); + print_mm_bm(rr_goingclean_bm, num_rr, "un_goingclean_bm"); + print_mm_bm(rr_goingdirty_bm, num_rr, "un_goingdirty_bm"); + print_mm_bm(rr_resync_bm, num_rr, "un_resync_bm"); + + /* + * Load all the un_pernode_bm[] entries and iterate through the non- + * NULL entries + */ + rr_pernode_dirty = (unsigned char *)mdb_alloc(rr_bitmap_size, + UM_SLEEP|UM_GC); + + for (i = 0; i < 128; i++) { + un_pernode_bm = (uintptr_t)mmp->un_pernode_dirty_bm[i]; + if (un_pernode_bm) { + mdb_snprintf(pernode_str, sizeof (pernode_str), + "un_pernode_dirty_bm[%d]", i); + if (mdb_vread(rr_pernode_dirty, rr_bitmap_size, + un_pernode_bm) == -1) { + mdb_warn("failed to read %s at %p\n", + pernode_str, un_pernode_bm); + return (DCMD_ERR); + } + print_mm_bm(rr_pernode_dirty, num_rr, pernode_str); + } + } + print_mm_cnt_c(rr_pnds, num_rr, "un_pernode_dirty_sum"); + + print_mm_cnt_w(rr_ow, num_rr, "un_outstanding_writes"); + + return (DCMD_OK); +} diff --git a/usr/src/cmd/mdb/common/modules/md/md.c b/usr/src/cmd/mdb/common/modules/md/md.c index b23804c10b..371dfa14f3 100644 --- a/usr/src/cmd/mdb/common/modules/md/md.c +++ b/usr/src/cmd/mdb/common/modules/md/md.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/mdb_modapi.h> @@ -37,6 +34,7 @@ extern int set_io(uintptr_t, uint_t, int, const mdb_arg_t *); extern int dumpnamespace(uintptr_t, uint_t, int, const mdb_arg_t *); extern int dumpsetaddr(uintptr_t, uint_t, int, const mdb_arg_t *); extern int dumphotspare(uintptr_t, uint_t, int, const mdb_arg_t *); +extern int printmmbm(uintptr_t, uint_t, int, const mdb_arg_t *); extern void set_io_help(); /* from mdbgen */ @@ -79,6 +77,8 @@ const mdb_dcmd_t dcmds[] = { dumpsetaddr }, { "simple_de_ic", NULL, "simple mddb_de_ic_t", simple_de_ic }, + { "printmmbm", NULL, "print bitmaps for given mm_unit_t", + printmmbm }, { NULL } }; diff --git a/usr/src/cmd/mdb/common/modules/md/metastat.c b/usr/src/cmd/mdb/common/modules/md/metastat.c index cf01c779f0..d3f27ec233 100644 --- a/usr/src/cmd/mdb/common/modules/md/metastat.c +++ b/usr/src/cmd/mdb/common/modules/md/metastat.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,13 +18,12 @@ * * CDDL HEADER END */ + /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mdinclude.h" typedef struct submirror_cb { @@ -117,16 +115,84 @@ print_submirror(uintptr_t addr, void *arg, submirror_cb_t *data) return (WALK_NEXT); } +/* + * Construct an RLE count for the number of 'cleared' bits in the given 'bm' + * Output the RLE count in form: [<set>.<cleared>.<set>.<cleared>...] + * RLE is Run Length Encoding, a method for compactly describing a bitmap + * as a series of numbers indicating the count of consecutive set or cleared + * bits. + * + * Input: + * <bm> bitmap to scan + * <size> length of bitmap (in bits) + * <comp_bm> RLE count array to be updated + * <opstr> Descriptive text for bitmap RLE count display + */ +static void +print_comp_bm(unsigned char *bm, uint_t size, ushort_t *comp_bm, char *opstr) +{ + int cnt_clean, tot_dirty, cur_idx; + int i, cur_clean, cur_dirty, printit, max_set_cnt, max_reset_cnt; + + cnt_clean = 1; + printit = 0; + cur_clean = 0; + cur_dirty = 0; + cur_idx = 0; + tot_dirty = 0; + max_set_cnt = max_reset_cnt = 0; + for (i = 0; i < size; i++) { + if (isset(bm, i)) { + /* If we're counting clean bits, flush the count out */ + if (cnt_clean) { + cnt_clean = 0; + comp_bm[cur_idx] = cur_clean; + printit = 1; + if (cur_clean > max_reset_cnt) { + max_reset_cnt = cur_clean; + } + } + cur_clean = 0; + cur_dirty++; + tot_dirty++; + } else { + if (!cnt_clean) { + cnt_clean = 1; + comp_bm[cur_idx] = cur_dirty; + printit = 1; + if (cur_dirty > max_set_cnt) { + max_set_cnt = cur_dirty; + } + } + cur_dirty = 0; + cur_clean++; + } + if (printit) { + mdb_printf("%u.", comp_bm[cur_idx++]); + printit = 0; + } + } + + mdb_printf("\nTotal %s bits = %lu\n", opstr, tot_dirty); + mdb_printf("Total %s transactions = %lu\n", opstr, cur_idx); + mdb_printf("Maximum %s set count = %lu, reset count = %lu\n", opstr, + max_set_cnt, max_reset_cnt); +} + void print_mirror(void *un_addr, void *mdcptr, uint_t verbose) { - mm_unit_t mm; + mm_unit_t mm, *mmp; void **ptr; int setno = 0; minor_t un_self_id; diskaddr_t un_total_blocks; ushort_t mm_un_nsm; submirror_cb_t data; + uint_t num_rr, rr_blksize; + ushort_t *comp_rr; + unsigned char *rr_dirty_bm, *rr_goingclean_bm; + uintptr_t un_dbm, un_gcbm; /* read in the device */ if (mdb_vread(&mm, sizeof (mm_unit_t), @@ -134,6 +200,9 @@ print_mirror(void *un_addr, void *mdcptr, uint_t verbose) mdb_warn("failed to read mm_unit_t at %p\n", un_addr); return; } + + mmp = &mm; + un_self_id = ((mdc_unit_t *)mdcptr)->un_self_id; un_total_blocks = ((mdc_unit_t *)mdcptr)->un_total_blocks; mm_un_nsm = mm.un_nsm; @@ -148,6 +217,39 @@ print_mirror(void *un_addr, void *mdcptr, uint_t verbose) } mdb_inc_indent(2); mdb_printf("Size: %llu blocks\n", un_total_blocks); + + /* + * Dump out the current un_dirty_bm together with its size + * Also, attempt to Run Length encode the bitmap to see if this + * is a viable option + */ + num_rr = mm.un_rrd_num; + rr_blksize = mm.un_rrd_blksize; + + un_dbm = (uintptr_t)mmp->un_dirty_bm; + un_gcbm = (uintptr_t)mmp->un_goingclean_bm; + + mdb_printf("RR size: %lu bits\n", num_rr); + mdb_printf("RR block size: %lu blocks\n", rr_blksize); + + rr_dirty_bm = (unsigned char *)mdb_alloc(num_rr, UM_SLEEP|UM_GC); + rr_goingclean_bm = (unsigned char *)mdb_alloc(num_rr, UM_SLEEP|UM_GC); + comp_rr = (ushort_t *)mdb_alloc(num_rr * sizeof (ushort_t), + UM_SLEEP|UM_GC); + + if (mdb_vread(rr_dirty_bm, num_rr, un_dbm) == -1) { + mdb_warn("failed to read un_dirty_bm at %p\n", un_dbm); + return; + } + if (mdb_vread(rr_goingclean_bm, num_rr, un_gcbm) == -1) { + mdb_warn("failed to read un_goingclean_bm at %p\n", un_gcbm); + return; + } + + print_comp_bm(rr_dirty_bm, num_rr, comp_rr, "dirty"); + + print_comp_bm(rr_goingclean_bm, num_rr, comp_rr, "clean"); + /* * find the sub mirrors, search through each metadevice looking * at the un_parent. |