--- old/usr/src/uts/common/fs/zfs/dbuf.c	2016-04-06 14:26:56.408667608 -0400
+++ new/usr/src/uts/common/fs/zfs/dbuf.c	2016-04-06 14:26:56.415994042 -0400
@@ -58,7 +58,8 @@
 
 #ifndef __lint
 extern inline void dmu_buf_init_user(dmu_buf_user_t *dbu,
-    dmu_buf_evict_func_t *evict_func, dmu_buf_t **clear_on_evict_dbufp);
+    dmu_buf_evict_func_t *evict_func_prep, dmu_buf_evict_func_t *evict_func,
+    dmu_buf_t **clear_on_evict_dbufp);
 #endif /* ! __lint */
 
 /*
@@ -299,6 +300,9 @@
 		*dbu->dbu_clear_on_evict_dbufp = NULL;
 #endif
 
+	if (dbu->dbu_evict_func_prep != NULL)
+		dbu->dbu_evict_func_prep(dbu);
+
 	/*
 	 * Invoke the callback from a taskq to avoid lock order reversals
 	 * and limit stack depth.
--- old/usr/src/uts/common/fs/zfs/dnode.c	2016-04-06 14:26:56.617591085 -0400
+++ new/usr/src/uts/common/fs/zfs/dnode.c	2016-04-06 14:26:56.622083277 -0400
@@ -1140,7 +1140,7 @@
 		for (i = 0; i < epb; i++) {
 			zrl_init(&dnh[i].dnh_zrlock);
 		}
-		dmu_buf_init_user(&children_dnodes->dnc_dbu,
+		dmu_buf_init_user(&children_dnodes->dnc_dbu, NULL,
 		    dnode_buf_pageout, NULL);
 		winner = dmu_buf_set_user(&db->db, &children_dnodes->dnc_dbu);
 		if (winner != NULL) {
--- old/usr/src/uts/common/fs/zfs/dsl_dataset.c	2016-04-06 14:26:56.785720153 -0400
+++ new/usr/src/uts/common/fs/zfs/dsl_dataset.c	2016-04-06 14:26:56.789924574 -0400
@@ -270,6 +270,16 @@
 }
 
 static void
+dsl_dataset_evict_prep(void *dbu)
+{
+	dsl_dataset_t *ds = dbu;
+
+	ASSERT(ds->ds_owner == NULL);
+
+	unique_remove(ds->ds_fsid_guid);
+}
+
+static void
 dsl_dataset_evict(void *dbu)
 {
 	dsl_dataset_t *ds = dbu;
@@ -278,8 +288,6 @@
 
 	ds->ds_dbuf = NULL;
 
-	unique_remove(ds->ds_fsid_guid);
-
 	if (ds->ds_objset != NULL)
 		dmu_objset_evict(ds->ds_objset);
 
@@ -512,7 +520,8 @@
 			ds->ds_reserved = ds->ds_quota = 0;
 		}
 
-		dmu_buf_init_user(&ds->ds_dbu, dsl_dataset_evict, &ds->ds_dbuf);
+		dmu_buf_init_user(&ds->ds_dbu, dsl_dataset_evict_prep,
+		    dsl_dataset_evict, &ds->ds_dbuf);
 		if (err == 0)
 			winner = dmu_buf_set_user_ie(dbuf, &ds->ds_dbu);
 
--- old/usr/src/uts/common/fs/zfs/dsl_dir.c	2016-04-06 14:26:57.005804019 -0400
+++ new/usr/src/uts/common/fs/zfs/dsl_dir.c	2016-04-06 14:26:57.009892260 -0400
@@ -235,7 +235,8 @@
 			dmu_buf_rele(origin_bonus, FTAG);
 		}
 
-		dmu_buf_init_user(&dd->dd_dbu, dsl_dir_evict, &dd->dd_dbuf);
+		dmu_buf_init_user(&dd->dd_dbu, NULL, dsl_dir_evict,
+		    &dd->dd_dbuf);
 		winner = dmu_buf_set_user_ie(dbuf, &dd->dd_dbu);
 		if (winner != NULL) {
 			if (dd->dd_parent)
--- old/usr/src/uts/common/fs/zfs/sa.c	2016-04-06 14:26:57.173670138 -0400
+++ new/usr/src/uts/common/fs/zfs/sa.c	2016-04-06 14:26:57.177895946 -0400
@@ -1380,6 +1380,7 @@
 		sa_handle_t *winner = NULL;
 
 		handle = kmem_cache_alloc(sa_cache, KM_SLEEP);
+		handle->sa_dbu.dbu_evict_func_prep = NULL;
 		handle->sa_dbu.dbu_evict_func = NULL;
 		handle->sa_userp = userp;
 		handle->sa_bonus = db;
@@ -1391,7 +1392,8 @@
 		error = sa_build_index(handle, SA_BONUS);
 
 		if (hdl_type == SA_HDL_SHARED) {
-			dmu_buf_init_user(&handle->sa_dbu, sa_evict, NULL);
+			dmu_buf_init_user(&handle->sa_dbu, NULL, sa_evict,
+			    NULL);
 			winner = dmu_buf_set_user_ie(db, &handle->sa_dbu);
 		}
 
--- old/usr/src/uts/common/fs/zfs/sys/dmu.h	2016-04-06 14:26:57.339555541 -0400
+++ new/usr/src/uts/common/fs/zfs/sys/dmu.h	2016-04-06 14:26:57.343723261 -0400
@@ -533,7 +533,13 @@
 	 */
 	taskq_ent_t	dbu_tqent;
 
-	/* This instance's eviction function pointer. */
+	/*
+	 * This instance's eviction function pointers.
+	 *
+	 * dbu_evict_func_prep is called synchronously while dbu_evict_func
+	 * is executed asynchronously on a taskq.
+	 */
+	dmu_buf_evict_func_t *dbu_evict_func_prep;
 	dmu_buf_evict_func_t *dbu_evict_func;
 #ifdef ZFS_DEBUG
 	/*
@@ -557,15 +563,17 @@
 #ifdef __lint
 /* Very ugly, but it beats issuing suppression directives in many Makefiles. */
 extern void
-dmu_buf_init_user(dmu_buf_user_t *dbu, dmu_buf_evict_func_t *evict_func,
-    dmu_buf_t **clear_on_evict_dbufp);
+dmu_buf_init_user(dmu_buf_user_t *dbu, dmu_buf_evict_func_t *evict_func_prep,
+    dmu_buf_evict_func_t *evict_func, dmu_buf_t **clear_on_evict_dbufp);
 #else /* __lint */
 inline void
-dmu_buf_init_user(dmu_buf_user_t *dbu, dmu_buf_evict_func_t *evict_func,
-    dmu_buf_t **clear_on_evict_dbufp)
+dmu_buf_init_user(dmu_buf_user_t *dbu, dmu_buf_evict_func_t *evict_func_prep,
+    dmu_buf_evict_func_t *evict_func, dmu_buf_t **clear_on_evict_dbufp)
 {
+	ASSERT(dbu->dbu_evict_func_prep == NULL);
 	ASSERT(dbu->dbu_evict_func == NULL);
 	ASSERT(evict_func != NULL);
+	dbu->dbu_evict_func_prep = evict_func_prep;
 	dbu->dbu_evict_func = evict_func;
 #ifdef ZFS_DEBUG
 	dbu->dbu_clear_on_evict_dbufp = clear_on_evict_dbufp;
--- old/usr/src/uts/common/fs/zfs/zap.c	2016-04-06 14:26:57.484115949 -0400
+++ new/usr/src/uts/common/fs/zfs/zap.c	2016-04-06 14:26:57.488330504 -0400
@@ -81,6 +81,7 @@
 	ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
 	zap->zap_ismicro = FALSE;
 
+	zap->zap_dbu.dbu_evict_func_prep = NULL;
 	zap->zap_dbu.dbu_evict_func = zap_evict;
 
 	mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0);
@@ -413,7 +414,7 @@
 	VERIFY(0 == dmu_buf_hold(zap->zap_objset, zap->zap_object,
 	    l->l_blkid << FZAP_BLOCK_SHIFT(zap), NULL, &l->l_dbuf,
 	    DMU_READ_NO_PREFETCH));
-	dmu_buf_init_user(&l->l_dbu, zap_leaf_pageout, &l->l_dbuf);
+	dmu_buf_init_user(&l->l_dbu, NULL, zap_leaf_pageout, &l->l_dbuf);
 	winner = dmu_buf_set_user(l->l_dbuf, &l->l_dbu);
 	ASSERT(winner == NULL);
 	dmu_buf_will_dirty(l->l_dbuf, tx);
@@ -460,7 +461,7 @@
 	l->l_bs = highbit64(db->db_size) - 1;
 	l->l_dbuf = db;
 
-	dmu_buf_init_user(&l->l_dbu, zap_leaf_pageout, &l->l_dbuf);
+	dmu_buf_init_user(&l->l_dbu, NULL, zap_leaf_pageout, &l->l_dbuf);
 	winner = dmu_buf_set_user(db, &l->l_dbu);
 
 	rw_exit(&l->l_rwlock);
--- old/usr/src/uts/common/fs/zfs/zap_micro.c	2016-04-06 14:26:57.635601900 -0400
+++ new/usr/src/uts/common/fs/zfs/zap_micro.c	2016-04-06 14:26:57.639911022 -0400
@@ -389,7 +389,7 @@
 	 * it, because zap_lockdir() checks zap_ismicro without the lock
 	 * held.
 	 */
-	dmu_buf_init_user(&zap->zap_dbu, zap_evict, &zap->zap_dbuf);
+	dmu_buf_init_user(&zap->zap_dbu, NULL, zap_evict, &zap->zap_dbuf);
 	winner = dmu_buf_set_user(db, &zap->zap_dbu);
 
 	if (winner != NULL) {
