summaryrefslogtreecommitdiff
path: root/usr/src/cmd/mdb/common/modules
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/mdb/common/modules')
-rw-r--r--usr/src/cmd/mdb/common/modules/md/dumpmirror.c230
-rw-r--r--usr/src/cmd/mdb/common/modules/md/md.c12
-rw-r--r--usr/src/cmd/mdb/common/modules/md/metastat.c116
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.