--- old/usr/src/uts/common/vm/vm_usage.c	Wed Oct  5 00:33:58 2016
+++ new/usr/src/uts/common/vm/vm_usage.c	Wed Oct  5 00:33:58 2016
@@ -118,7 +118,7 @@
  *	For accurate counting of map-shared and COW-shared pages.
  *
  *    - visited private anons (refcnt > 1) for each collective.
- *	(entity->vme_anon)
+ *	(entity->vme_anon_hash)
  *	For accurate counting of COW-shared pages.
  *
  * The common accounting structure is the vmu_entity_t, which represents
@@ -156,7 +156,6 @@
 #include <sys/vm_usage.h>
 #include <sys/zone.h>
 #include <sys/sunddi.h>
-#include <sys/sysmacros.h>
 #include <sys/avl.h>
 #include <vm/anon.h>
 #include <vm/as.h>
@@ -204,14 +203,6 @@
 } vmu_object_t;
 
 /*
- * Node for tree of visited COW anons.
- */
-typedef struct vmu_anon {
-	avl_node_t vma_node;
-	uintptr_t vma_addr;
-} vmu_anon_t;
-
-/*
  * Entity by which to count results.
  *
  * The entity structure keeps the current rss/swap counts for each entity
@@ -234,7 +225,7 @@
 	struct vmu_entity *vme_next_calc;
 	mod_hash_t	*vme_vnode_hash; /* vnodes visited for entity */
 	mod_hash_t	*vme_amp_hash;	 /* shared amps visited for entity */
-	avl_tree_t	vme_anon;	 /* COW anons visited for entity */
+	mod_hash_t	*vme_anon_hash;	 /* COW anons visited for entity */
 	vmusage_t	vme_result;	 /* identifies entity and results */
 } vmu_entity_t;
 
@@ -337,23 +328,6 @@
 }
 
 /*
- * Comparison routine for our AVL tree of anon structures.
- */
-static int
-vmu_anon_cmp(const void *lhs, const void *rhs)
-{
-	const vmu_anon_t *l = lhs, *r = rhs;
-
-	if (l->vma_addr == r->vma_addr)
-		return (0);
-
-	if (l->vma_addr < r->vma_addr)
-		return (-1);
-
-	return (1);
-}
-
-/*
  * Save a bound on the free list.
  */
 static void
@@ -393,19 +367,14 @@
 vmu_free_entity(mod_hash_val_t val)
 {
 	vmu_entity_t *entity = (vmu_entity_t *)val;
-	vmu_anon_t *anon;
-	void *cookie = NULL;
 
 	if (entity->vme_vnode_hash != NULL)
 		i_mod_hash_clear_nosync(entity->vme_vnode_hash);
 	if (entity->vme_amp_hash != NULL)
 		i_mod_hash_clear_nosync(entity->vme_amp_hash);
+	if (entity->vme_anon_hash != NULL)
+		i_mod_hash_clear_nosync(entity->vme_anon_hash);
 
-	while ((anon = avl_destroy_nodes(&entity->vme_anon, &cookie)) != NULL)
-		kmem_free(anon, sizeof (vmu_anon_t));
-
-	avl_destroy(&entity->vme_anon);
-
 	entity->vme_next = vmu_data.vmu_free_entities;
 	vmu_data.vmu_free_entities = entity;
 }
@@ -520,11 +489,11 @@
 		    "vmusage amp hash", VMUSAGE_HASH_SIZE, vmu_free_object,
 		    sizeof (struct anon_map));
 
-	VERIFY(avl_first(&entity->vme_anon) == NULL);
+	if (entity->vme_anon_hash == NULL)
+		entity->vme_anon_hash = mod_hash_create_ptrhash(
+		    "vmusage anon hash", VMUSAGE_HASH_SIZE,
+		    mod_hash_null_valdtor, sizeof (struct anon));
 
-	avl_create(&entity->vme_anon, vmu_anon_cmp, sizeof (struct vmu_anon),
-	    offsetof(struct vmu_anon, vma_node));
-
 	entity->vme_next = vmu_data.vmu_entities;
 	vmu_data.vmu_entities = entity;
 	vmu_data.vmu_nentities++;
@@ -649,19 +618,21 @@
 }
 
 static int
-vmu_find_insert_anon(vmu_entity_t *entity, void *key)
+vmu_find_insert_anon(mod_hash_t *hash, caddr_t key)
 {
-	vmu_anon_t anon, *ap;
+	int ret;
+	caddr_t val;
 
-	anon.vma_addr = (uintptr_t)key;
+	ret = i_mod_hash_find_nosync(hash, (mod_hash_key_t)key,
+	    (mod_hash_val_t *)&val);
 
-	if (avl_find(&entity->vme_anon, &anon, NULL) != NULL)
+	if (ret == 0)
 		return (0);
 
-	ap = kmem_alloc(sizeof (vmu_anon_t), KM_SLEEP);
-	ap->vma_addr = (uintptr_t)key;
+	ret = i_mod_hash_insert_nosync(hash, (mod_hash_key_t)key,
+	    (mod_hash_val_t)key, (mod_hash_hndl_t)0);
 
-	avl_add(&entity->vme_anon, ap);
+	ASSERT(ret == 0);
 
 	return (1);
 }
@@ -1373,7 +1344,8 @@
 				 * Track COW anons per entity so
 				 * they are not double counted.
 				 */
-				if (vmu_find_insert_anon(entity, ap) == 0)
+				if (vmu_find_insert_anon(entity->vme_anon_hash,
+				    (caddr_t)ap) == 0)
 					continue;
 
 				result->vmu_rss_all += (pgcnt << PAGESHIFT);
@@ -1647,7 +1619,8 @@
 			mod_hash_destroy_hash(te->vme_vnode_hash);
 		if (te->vme_amp_hash != NULL)
 			mod_hash_destroy_hash(te->vme_amp_hash);
-		VERIFY(avl_first(&te->vme_anon) == NULL);
+		if (te->vme_anon_hash != NULL)
+			mod_hash_destroy_hash(te->vme_anon_hash);
 		kmem_free(te, sizeof (vmu_entity_t));
 	}
 	while (vmu_data.vmu_free_zones != NULL) {
@@ -1805,8 +1778,8 @@
 		if (rp->vmu_type == VMUSAGE_ZONE &&
 		    rp->vmu_zoneid != ALL_ZONES) {
 			if ((zp = zone_find_by_id(rp->vmu_zoneid)) != NULL) {
-				zp->zone_phys_mem = rp->vmu_rss_all;
-				zone_rele(zp);
+			        zp->zone_phys_mem = rp->vmu_rss_all;
+			        zone_rele(zp);
 			}
 		}
 	}
