changeset 14005:55fc53126003

3654 zdb should print number of ganged blocks 3655 ::rrwlock and ::refcount print errors on non-debug kernels 3656 remove unused function zap_cursor_move_to_key() 3657 mdb_ctf_vread() should allow conversion of pointer to uintptr_t Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Dan McDonald <danmcd@nexenta.com> Approved by: Garrett D'Amore <garrett@damore.org>
author Matthew Ahrens <mahrens@delphix.com>
date Sun, 07 Apr 2013 18:40:39 -0800
parents dd91fed709a7
children 09f0146de94b
files usr/src/cmd/mdb/common/mdb/mdb_ctf.c usr/src/cmd/mdb/common/modules/zfs/zfs.c usr/src/cmd/zdb/zdb.c usr/src/uts/common/fs/zfs/sys/zap.h usr/src/uts/common/fs/zfs/sys/zap_impl.h usr/src/uts/common/fs/zfs/zap.c usr/src/uts/common/fs/zfs/zap_micro.c
diffstat 7 files changed, 129 insertions(+), 158 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c	Tue Apr 02 18:57:48 2013 -0700
+++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c	Sun Apr 07 18:40:39 2013 -0800
@@ -1159,12 +1159,6 @@
 		return (-1); /* errno is set for us */
 	}
 
-	if (tgtkind != modkind) {
-		mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n",
-		    typename, tgtname);
-		return (set_errno(EMDB_INCOMPAT));
-	}
-
 	if ((modsz = mdb_ctf_type_size(modid)) == -1UL) {
 		mdb_ctf_warn(flags, "couldn't determine type size of "
 		    "mdb module type %s\n", mdbtypename);
@@ -1176,7 +1170,17 @@
 		return (-1); /* errno is set for us */
 	}
 
-	switch (modkind) {
+	if (tgtkind == CTF_K_POINTER && modkind == CTF_K_INTEGER &&
+	    strcmp(mdbtypename, "uintptr_t") == 0) {
+		/* allow them to convert a pointer to a uintptr_t */
+		ASSERT(modsz == tgtsz);
+	} else if (tgtkind != modkind) {
+		mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n",
+		    typename, tgtname);
+		return (set_errno(EMDB_INCOMPAT));
+	}
+
+	switch (tgtkind) {
 	case CTF_K_INTEGER:
 	case CTF_K_FLOAT:
 		/*
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c	Tue Apr 02 18:57:48 2013 -0700
+++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c	Sun Apr 07 18:40:39 2013 -0800
@@ -380,7 +380,7 @@
 	struct {
 		uint64_t db_object;
 	} db;
-	void *db_objset;
+	uintptr_t db_objset;
 	uint64_t db_level;
 	uint64_t db_blkid;
 	struct {
@@ -416,7 +416,7 @@
 		(void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx",
 		    (u_longlong_t)db.db_blkid);
 
-	if (objset_name((uintptr_t)db.db_objset, path)) {
+	if (objset_name(db.db_objset, path)) {
 		return (DCMD_ERR);
 	}
 
@@ -1078,7 +1078,7 @@
 }
 
 typedef struct mdb_spa_config_spa {
-	nvlist_t *spa_config;
+	uintptr_t spa_config;
 } mdb_spa_config_spa_t;
 
 /*
@@ -1101,12 +1101,12 @@
 	    addr, 0) == -1)
 		return (DCMD_ERR);
 
-	if (spa.spa_config == NULL) {
+	if (spa.spa_config == 0) {
 		mdb_printf("(none)\n");
 		return (DCMD_OK);
 	}
 
-	return (mdb_call_dcmd("nvlist", (uintptr_t)spa.spa_config, flags,
+	return (mdb_call_dcmd("nvlist", spa.spa_config, flags,
 	    0, NULL));
 }
 
@@ -1736,11 +1736,11 @@
 typedef struct mdb_zio {
 	enum zio_type io_type;
 	enum zio_stage io_stage;
-	void *io_waiter;
-	void *io_spa;
+	uintptr_t io_waiter;
+	uintptr_t io_spa;
 	struct {
 		struct {
-			void *list_next;
+			uintptr_t list_next;
 		} list_head;
 	} io_parent_list;
 	int io_error;
@@ -1797,8 +1797,8 @@
 		} else {
 			mdb_printf("%*s%-*p %-5s %-16s ", indent, "",
 			    ZIO_MAXWIDTH - indent, addr, type, stage);
-			if (zio.io_waiter)
-				mdb_printf("%-16p ", zio.io_waiter);
+			if (zio.io_waiter != 0)
+				mdb_printf("%-16lx ", zio.io_waiter);
 			else
 				mdb_printf("%-16s ", "-");
 #ifdef _KERNEL
@@ -2065,7 +2065,7 @@
 static int
 zio_walk_init(mdb_walk_state_t *wsp)
 {
-	wsp->walk_data = (void *)wsp->walk_addr;
+	wsp->walk_data = &wsp->walk_addr;
 
 	if (mdb_layered_walk("zio_cache", wsp) == -1) {
 		mdb_warn("failed to walk 'zio_cache'\n");
@@ -2079,12 +2079,13 @@
 zio_walk_step(mdb_walk_state_t *wsp)
 {
 	mdb_zio_t zio;
+	uintptr_t *spap = wsp->walk_data;
 
 	if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t",
 	    wsp->walk_addr, 0) == -1)
 		return (WALK_ERR);
 
-	if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa)
+	if (*spap != 0 && *spap != zio.io_spa)
 		return (WALK_NEXT);
 
 	return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata));
@@ -2099,16 +2100,17 @@
 zio_walk_root_step(mdb_walk_state_t *wsp)
 {
 	mdb_zio_t zio;
+	uintptr_t *spap = wsp->walk_data;
 
 	if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t",
 	    wsp->walk_addr, 0) == -1)
 		return (WALK_ERR);
 
-	if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa)
+	if (*spap != 0 && *spap != zio.io_spa)
 		return (WALK_NEXT);
 
 	/* If the parent list is not empty, ignore */
-	if ((uintptr_t)zio.io_parent_list.list_head.list_next !=
+	if (zio.io_parent_list.list_head.list_next !=
 	    wsp->walk_addr +
 	    mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", "io_parent_list") +
 	    mdb_ctf_offsetof_by_name("struct list", "list_head"))
@@ -2288,41 +2290,35 @@
 	return (DCMD_OK);
 }
 
+typedef struct mdb_reference {
+	uintptr_t ref_holder;
+	uintptr_t ref_removed;
+	uint64_t ref_number;
+} mdb_reference_t;
+
 /* ARGSUSED */
 static int
 reference_cb(uintptr_t addr, const void *ignored, void *arg)
 {
-	static int gotid;
-	static mdb_ctf_id_t ref_id;
-	uintptr_t ref_holder;
-	uintptr_t ref_removed;
-	uint64_t ref_number;
+	mdb_reference_t ref;
 	boolean_t holder_is_str = B_FALSE;
 	char holder_str[128];
 	boolean_t removed = (boolean_t)arg;
 
-	if (!gotid) {
-		if (mdb_ctf_lookup_by_name("struct reference", &ref_id) == -1) {
-			mdb_warn("couldn't find struct reference");
-			return (WALK_ERR);
-		}
-		gotid = TRUE;
-	}
-
-	if (GETMEMBID(addr, &ref_id, ref_holder, ref_holder) ||
-	    GETMEMBID(addr, &ref_id, ref_removed, ref_removed) ||
-	    GETMEMBID(addr, &ref_id, ref_number, ref_number))
-		return (WALK_ERR);
-
-	if (mdb_readstr(holder_str, sizeof (holder_str), ref_holder) != -1)
+	if (mdb_ctf_vread(&ref, "reference_t", "mdb_reference_t", addr,
+	    0) == -1)
+		return (DCMD_ERR);
+
+	if (mdb_readstr(holder_str, sizeof (holder_str),
+	    ref.ref_holder) != -1)
 		holder_is_str = strisprint(holder_str);
 
 	if (removed)
 		mdb_printf("removed ");
 	mdb_printf("reference ");
-	if (ref_number != 1)
-		mdb_printf("with count=%llu ", ref_number);
-	mdb_printf("with tag %p", (void*)ref_holder);
+	if (ref.ref_number != 1)
+		mdb_printf("with count=%llu ", ref.ref_number);
+	mdb_printf("with tag %lx", ref.ref_holder);
 	if (holder_is_str)
 		mdb_printf(" \"%s\"", holder_str);
 	mdb_printf(", held at:\n");
@@ -2331,7 +2327,7 @@
 
 	if (removed) {
 		mdb_printf("removed at:\n");
-		(void) mdb_call_dcmd("whatis", ref_removed,
+		(void) mdb_call_dcmd("whatis", ref.ref_removed,
 		    DCMD_ADDRSPEC, 0, NULL);
 	}
 
@@ -2340,15 +2336,26 @@
 	return (WALK_NEXT);
 }
 
+typedef struct mdb_refcount {
+	uint64_t rc_count;
+} mdb_refcount_t;
+
+typedef struct mdb_refcount_removed {
+	uint64_t rc_removed_count;
+} mdb_refcount_removed_t;
+
+typedef struct mdb_refcount_tracked {
+	boolean_t rc_tracked;
+} mdb_refcount_tracked_t;
+
 /* ARGSUSED */
 static int
 refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 {
-	uint64_t rc_count, rc_removed_count;
-	uintptr_t rc_list, rc_removed;
-	static int gotid;
-	static mdb_ctf_id_t rc_id;
-	ulong_t off;
+	mdb_refcount_t rc;
+	mdb_refcount_removed_t rcr;
+	mdb_refcount_tracked_t rct;
+	int off;
 	boolean_t released = B_FALSE;
 
 	if (!(flags & DCMD_ADDRSPEC))
@@ -2359,48 +2366,41 @@
 	    NULL) != argc)
 		return (DCMD_USAGE);
 
-	if (!gotid) {
-		/*
-		 * The refcount structure is different when compiled debug
-		 * vs nondebug.  Therefore, we want to make sure we get the
-		 * refcount definition from the ZFS module, in case it has
-		 * been compiled debug but genunix is nondebug.
-		 */
-		if (mdb_ctf_lookup_by_name(ZFS_STRUCT "refcount",
-		    &rc_id) == -1) {
-			mdb_warn("couldn't find struct refcount");
-			return (DCMD_ERR);
-		}
-		gotid = TRUE;
+	if (mdb_ctf_vread(&rc, "refcount_t", "mdb_refcount_t", addr,
+	    0) == -1)
+		return (DCMD_ERR);
+
+	if (mdb_ctf_vread(&rcr, "refcount_t", "mdb_refcount_removed_t", addr,
+	    MDB_CTF_VREAD_QUIET) == -1) {
+		mdb_printf("refcount_t at %p has %llu holds (untracked)\n",
+		    addr, (longlong_t)rc.rc_count);
+		return (DCMD_OK);
 	}
 
-	if (GETMEMBID(addr, &rc_id, rc_count, rc_count))
-		return (DCMD_ERR);
-
-	if (GETMEMBID(addr, &rc_id, rc_removed_count, rc_removed_count)) {
-		mdb_printf("refcount_t at %p has %llu current holds\n",
-		    addr, (longlong_t)rc_count);
-		return (DCMD_OK);
+	if (mdb_ctf_vread(&rct, "refcount_t", "mdb_refcount_tracked_t", addr,
+	    MDB_CTF_VREAD_QUIET) == -1) {
+		/* If this is an old target, it might be tracked. */
+		rct.rc_tracked = B_TRUE;
 	}
 
 	mdb_printf("refcount_t at %p has %llu current holds, "
 	    "%llu recently released holds\n",
-	    addr, (longlong_t)rc_count, (longlong_t)rc_removed_count);
-
-	if (rc_count > 0)
+	    addr, (longlong_t)rc.rc_count, (longlong_t)rcr.rc_removed_count);
+
+	if (rct.rc_tracked && rc.rc_count > 0)
 		mdb_printf("current holds:\n");
-	if (mdb_ctf_offsetof(rc_id, "rc_list", &off) == -1)
+	off = mdb_ctf_offsetof_by_name("refcount_t", "rc_list");
+	if (off == -1)
 		return (DCMD_ERR);
-	rc_list = addr + off/NBBY;
-	mdb_pwalk("list", reference_cb, (void*)B_FALSE, rc_list);
-
-	if (released) {
-		if (rc_removed_count > 0)
-			mdb_printf("released holds:\n");
-		if (mdb_ctf_offsetof(rc_id, "rc_removed", &off) == -1)
+	mdb_pwalk("list", reference_cb, (void*)B_FALSE, addr + off);
+
+	if (released && rcr.rc_removed_count > 0) {
+		mdb_printf("released holds:\n");
+
+		off = mdb_ctf_offsetof_by_name("refcount_t", "rc_removed");
+		if (off == -1)
 			return (DCMD_ERR);
-		rc_removed = addr + off/NBBY;
-		mdb_pwalk("list", reference_cb, (void*)B_TRUE, rc_removed);
+		mdb_pwalk("list", reference_cb, (void*)B_FALSE, addr + off);
 	}
 
 	return (DCMD_OK);
@@ -3004,7 +3004,7 @@
 }
 
 typedef struct mdb_zfs_rrwlock {
-	kthread_t	*rr_writer;
+	uintptr_t	rr_writer;
 	boolean_t	rr_writer_wanted;
 } mdb_zfs_rrwlock_t;
 
@@ -3025,8 +3025,8 @@
 	    0) == -1)
 		return (DCMD_ERR);
 
-	if (rrw.rr_writer != NULL) {
-		mdb_printf("write lock held by thread %p\n", rrw.rr_writer);
+	if (rrw.rr_writer != 0) {
+		mdb_printf("write lock held by thread %lx\n", rrw.rr_writer);
 		return (DCMD_OK);
 	}
 
--- a/usr/src/cmd/zdb/zdb.c	Tue Apr 02 18:57:48 2013 -0700
+++ b/usr/src/cmd/zdb/zdb.c	Sun Apr 07 18:40:39 2013 -0800
@@ -1997,6 +1997,8 @@
 	uint64_t zb_lsize;
 	uint64_t zb_psize;
 	uint64_t zb_count;
+	uint64_t zb_gangs;
+	uint64_t zb_ditto_samevdev;
 	uint64_t zb_psize_histogram[PSIZE_HISTO_SIZE];
 } zdb_blkstats_t;
 
@@ -2044,6 +2046,7 @@
 	for (int i = 0; i < 4; i++) {
 		int l = (i < 2) ? BP_GET_LEVEL(bp) : ZB_TOTAL;
 		int t = (i & 1) ? type : ZDB_OT_TOTAL;
+		int equal;
 		zdb_blkstats_t *zb = &zcb->zcb_type[l][t];
 
 		zb->zb_asize += BP_GET_ASIZE(bp);
@@ -2051,6 +2054,27 @@
 		zb->zb_psize += BP_GET_PSIZE(bp);
 		zb->zb_count++;
 		zb->zb_psize_histogram[BP_GET_PSIZE(bp) >> SPA_MINBLOCKSHIFT]++;
+
+		zb->zb_gangs += BP_COUNT_GANG(bp);
+
+		switch (BP_GET_NDVAS(bp)) {
+		case 2:
+			if (DVA_GET_VDEV(&bp->blk_dva[0]) ==
+			    DVA_GET_VDEV(&bp->blk_dva[1]))
+				zb->zb_ditto_samevdev++;
+			break;
+		case 3:
+			equal = (DVA_GET_VDEV(&bp->blk_dva[0]) ==
+			    DVA_GET_VDEV(&bp->blk_dva[1])) +
+			    (DVA_GET_VDEV(&bp->blk_dva[0]) ==
+			    DVA_GET_VDEV(&bp->blk_dva[2])) +
+			    (DVA_GET_VDEV(&bp->blk_dva[1]) ==
+			    DVA_GET_VDEV(&bp->blk_dva[2]));
+			if (equal != 0)
+				zb->zb_ditto_samevdev++;
+			break;
+		}
+
 	}
 
 	if (dump_opt['L'])
@@ -2439,6 +2463,8 @@
 	(void) printf("\n");
 	(void) printf("\tbp count:      %10llu\n",
 	    (u_longlong_t)tzb->zb_count);
+	(void) printf("\tganged count:  %10llu\n",
+	    (longlong_t)tzb->zb_gangs);
 	(void) printf("\tbp logical:    %10llu      avg: %6llu\n",
 	    (u_longlong_t)tzb->zb_lsize,
 	    (u_longlong_t)(tzb->zb_lsize / tzb->zb_count));
@@ -2460,6 +2486,11 @@
 	(void) printf("\tSPA allocated: %10llu     used: %5.2f%%\n",
 	    (u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space);
 
+	if (tzb->zb_ditto_samevdev != 0) {
+		(void) printf("\tDittoed blocks on same vdev: %llu\n",
+		    (longlong_t)tzb->zb_ditto_samevdev);
+	}
+
 	if (dump_opt['b'] >= 2) {
 		int l, t, level;
 		(void) printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
@@ -2467,7 +2498,7 @@
 
 		for (t = 0; t <= ZDB_OT_TOTAL; t++) {
 			char csize[32], lsize[32], psize[32], asize[32];
-			char avg[32];
+			char avg[32], gang[32];
 			char *typename;
 
 			if (t < DMU_OT_NUMTYPES)
@@ -2508,6 +2539,7 @@
 				zdb_nicenum(zb->zb_psize, psize);
 				zdb_nicenum(zb->zb_asize, asize);
 				zdb_nicenum(zb->zb_asize / zb->zb_count, avg);
+				zdb_nicenum(zb->zb_gangs, gang);
 
 				(void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
 				    "\t%5.2f\t%6.2f\t",
@@ -2521,6 +2553,11 @@
 					(void) printf("    L%d %s\n",
 					    level, typename);
 
+				if (dump_opt['b'] >= 3 && zb->zb_gangs > 0) {
+					(void) printf("\t number of ganged "
+					    "blocks: %s\n", gang);
+				}
+
 				if (dump_opt['b'] >= 4) {
 					(void) printf("psize "
 					    "(in 512-byte sectors): "
--- a/usr/src/uts/common/fs/zfs/sys/zap.h	Tue Apr 02 18:57:48 2013 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/zap.h	Sun Apr 07 18:40:39 2013 -0800
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #ifndef	_SYS_ZAP_H
@@ -368,11 +368,6 @@
 uint64_t zap_cursor_serialize(zap_cursor_t *zc);
 
 /*
- * Advance the cursor to the attribute having the given key.
- */
-int zap_cursor_move_to_key(zap_cursor_t *zc, const char *name, matchtype_t mt);
-
-/*
  * Initialize a zap cursor pointing to the position recorded by
  * zap_cursor_serialize (in the "serialized" argument).  You can also
  * use a "serialized" argument of 0 to start at the beginning of the
--- a/usr/src/uts/common/fs/zfs/sys/zap_impl.h	Tue Apr 02 18:57:48 2013 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/zap_impl.h	Sun Apr 07 18:40:39 2013 -0800
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #ifndef	_SYS_ZAP_IMPL_H
@@ -219,7 +220,6 @@
     uint64_t integer_size, uint64_t num_integers,
     const void *val, uint32_t cd, dmu_tx_t *tx);
 void fzap_upgrade(zap_t *zap, dmu_tx_t *tx, zap_flags_t flags);
-int fzap_cursor_move_to_key(zap_cursor_t *zc, zap_name_t *zn);
 
 #ifdef	__cplusplus
 }
--- a/usr/src/uts/common/fs/zfs/zap.c	Tue Apr 02 18:57:48 2013 -0700
+++ b/usr/src/uts/common/fs/zfs/zap.c	Sun Apr 07 18:40:39 2013 -0800
@@ -1242,31 +1242,6 @@
 	}
 }
 
-int
-fzap_cursor_move_to_key(zap_cursor_t *zc, zap_name_t *zn)
-{
-	int err;
-	zap_leaf_t *l;
-	zap_entry_handle_t zeh;
-
-	if (zn->zn_key_orig_numints * zn->zn_key_intlen > ZAP_MAXNAMELEN)
-		return (SET_ERROR(ENAMETOOLONG));
-
-	err = zap_deref_leaf(zc->zc_zap, zn->zn_hash, NULL, RW_READER, &l);
-	if (err != 0)
-		return (err);
-
-	err = zap_leaf_lookup(l, zn, &zeh);
-	if (err != 0)
-		return (err);
-
-	zc->zc_leaf = l;
-	zc->zc_hash = zeh.zeh_hash;
-	zc->zc_cd = zeh.zeh_cd;
-
-	return (err);
-}
-
 void
 fzap_get_stats(zap_t *zap, zap_stats_t *zs)
 {
--- a/usr/src/uts/common/fs/zfs/zap_micro.c	Tue Apr 02 18:57:48 2013 -0700
+++ b/usr/src/uts/common/fs/zfs/zap_micro.c	Sun Apr 07 18:40:39 2013 -0800
@@ -1316,46 +1316,6 @@
 }
 
 int
-zap_cursor_move_to_key(zap_cursor_t *zc, const char *name, matchtype_t mt)
-{
-	int err = 0;
-	mzap_ent_t *mze;
-	zap_name_t *zn;
-
-	if (zc->zc_zap == NULL) {
-		err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL,
-		    RW_READER, TRUE, FALSE, &zc->zc_zap);
-		if (err)
-			return (err);
-	} else {
-		rw_enter(&zc->zc_zap->zap_rwlock, RW_READER);
-	}
-
-	zn = zap_name_alloc(zc->zc_zap, name, mt);
-	if (zn == NULL) {
-		rw_exit(&zc->zc_zap->zap_rwlock);
-		return (SET_ERROR(ENOTSUP));
-	}
-
-	if (!zc->zc_zap->zap_ismicro) {
-		err = fzap_cursor_move_to_key(zc, zn);
-	} else {
-		mze = mze_find(zn);
-		if (mze == NULL) {
-			err = SET_ERROR(ENOENT);
-			goto out;
-		}
-		zc->zc_hash = mze->mze_hash;
-		zc->zc_cd = mze->mze_cd;
-	}
-
-out:
-	zap_name_free(zn);
-	rw_exit(&zc->zc_zap->zap_rwlock);
-	return (err);
-}
-
-int
 zap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs)
 {
 	int err;