From 1759378307a29ad1f09be636e04b762add9d259c Mon Sep 17 00:00:00 2001
From: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Date: Wed, 7 May 2014 17:15:01 +0400
Subject: [PATCH 1/2] dump referenced dnodes at umount

---
 module/zfs/dnode.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/module/zfs/dnode.c b/module/zfs/dnode.c
index 5cb5fcc..8e9a46d 100644
--- a/module/zfs/dnode.c
+++ b/module/zfs/dnode.c
@@ -931,10 +931,52 @@ dnode_move(void *buf, void *newbuf, size_t size, void *arg)
 }
 #endif	/* _KERNEL */
 
+#ifdef __KERNEL__
+static void
+dbuf_dump_dnodes(dmu_buf_impl_t *db)
+{
+	dnode_children_t *children_dnodes;
+	dnode_handle_t *dnh;
+#ifdef __ZFS_DEBUG
+	reference_t *ref;
+#endif
+	dnode_t *dn;
+	int i, epb;
+
+	children_dnodes = dmu_buf_get_user(&db->db);
+	if (children_dnodes == NULL)
+		return;
+
+	epb = db->db.db_size >> DNODE_SHIFT;
+
+	for (i = 0; i < epb-1; i++) {
+		dnh = &children_dnodes->dnc_children[i];
+		if ((dn = dnh->dnh_dnode) == NULL)
+			continue;
+		if (refcount_count(&dn->dn_holds) == 0)
+			continue;
+		printk("   dnode %Lu, db %p, refcount %d\n",
+			dn->dn_object, dn->dn_bonus,
+			(int)refcount_count(&dn->dn_holds));
+#ifdef ZFS_DEBUG
+		for (ref = list_head(&dn->dn_holds.rc_list); ref;
+		     ref = list_next(&dn->dn_holds.rc_list, ref)) {
+			printk("    %d, %s\n", (int)ref->ref_number,
+				(char *)ref->ref_holder);
+		}
+#endif
+	}
+}
+#endif
+
 void
 dnode_special_close(dnode_handle_t *dnh)
 {
 	dnode_t *dn = dnh->dnh_dnode;
+#ifdef __KERNEL__
+	dmu_buf_impl_t *db, *db_next;
+#endif
+	int count = 0;
 
 	/*
 	 * Wait for final references to the dnode to clear.  This can
@@ -942,8 +984,24 @@ dnode_special_close(dnode_handle_t *dnh)
 	 * has a hold on this dnode while we are trying to evict this
 	 * dnode.
 	 */
-	while (refcount_count(&dn->dn_holds) > 0)
+	while (refcount_count(&dn->dn_holds) > 0) {
 		delay(1);
+		if (++count != 100)
+			continue;
+#ifdef __KERNEL__
+		printk("dnode %Lu\n", dn->dn_object);
+		for (db = list_head(&dn->dn_dbufs); db; db = db_next) {
+			db_next = list_next(&dn->dn_dbufs, db);
+			printk("db %p, blkid %Lu -> objid %Lu-%Lu\n",
+				db, db->db_blkid,
+				(db->db_blkid << dn->dn_datablkshift)
+					/ sizeof (dnode_phys_t),
+				((db->db_blkid+1) << dn->dn_datablkshift)
+					/ sizeof (dnode_phys_t));
+			dbuf_dump_dnodes(db);
+		}
+#endif
+	}
 	zrl_add(&dnh->dnh_zrlock);
 	dnode_destroy(dn); /* implicit zrl_remove() */
 	zrl_destroy(&dnh->dnh_zrlock);
-- 
1.9.3 (Apple Git-50)