Print this page

        

@@ -116,11 +116,11 @@
  *         - per vnode (entity->vme_vnode_hash)
  *         - per shared amp (entity->vme_amp_hash)
  *      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
  * collectives:
  *

@@ -154,11 +154,10 @@
 #include <sys/systm.h>
 #include <sys/var.h>
 #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>
 #include <vm/seg_vn.h>
 #include <vm/seg_spt.h>

@@ -202,18 +201,10 @@
         short           vmo_type;
         avl_tree_t      vmo_bounds;
 } 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
  * (zone, project, etc), and hashes of vm structures that have already
  * been visited for the entity.

@@ -232,11 +223,11 @@
 typedef struct vmu_entity {
         struct vmu_entity *vme_next;
         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;
 
 /*
  * Hash of entities visited within a zone, and an entity for the zone

@@ -335,27 +326,10 @@
 
         return (1);
 }
 
 /*
- * 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
 vmu_free_bound(vmu_bound_t *bound)
 {

@@ -391,23 +365,18 @@
  */
 static void
 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;
 }
 
 /*

@@ -518,15 +487,15 @@
         if (entity->vme_amp_hash == NULL)
                 entity->vme_amp_hash = mod_hash_create_ptrhash(
                     "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++;
 
         return (entity);

@@ -647,23 +616,25 @@
         }
         return (object);
 }
 
 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);
 }
 
 static vmu_entity_t *

@@ -1371,11 +1342,12 @@
                                 result = &entity->vme_result;
                                 /*
                                  * 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);
                                 result->vmu_rss_private +=
                                     (pgcnt << PAGESHIFT);

@@ -1645,11 +1617,12 @@
                     vmu_data.vmu_free_entities->vme_next;
                 if (te->vme_vnode_hash != NULL)
                         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) {
                 tz = vmu_data.vmu_free_zones;
                 vmu_data.vmu_free_zones =