Print this page
*** 116,126 ****
* - 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)
* For accurate counting of COW-shared pages.
*
* The common accounting structure is the vmu_entity_t, which represents
* collectives:
*
--- 116,126 ----
* - 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_hash)
* For accurate counting of COW-shared pages.
*
* The common accounting structure is the vmu_entity_t, which represents
* collectives:
*
*** 154,164 ****
#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>
--- 154,163 ----
*** 202,219 ****
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.
--- 201,210 ----
*** 232,242 ****
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 */
vmusage_t vme_result; /* identifies entity and results */
} vmu_entity_t;
/*
* Hash of entities visited within a zone, and an entity for the zone
--- 223,233 ----
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 */
! 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,361 ****
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)
{
--- 326,335 ----
*** 391,413 ****
*/
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);
- 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;
}
/*
--- 365,382 ----
*/
static void
vmu_free_entity(mod_hash_val_t val)
{
vmu_entity_t *entity = (vmu_entity_t *)val;
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);
entity->vme_next = vmu_data.vmu_free_entities;
vmu_data.vmu_free_entities = entity;
}
/*
*** 518,532 ****
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);
- 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);
--- 487,501 ----
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));
! 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));
entity->vme_next = vmu_data.vmu_entities;
vmu_data.vmu_entities = entity;
vmu_data.vmu_nentities++;
return (entity);
*** 647,669 ****
}
return (object);
}
static int
! vmu_find_insert_anon(vmu_entity_t *entity, void *key)
{
! vmu_anon_t anon, *ap;
! anon.vma_addr = (uintptr_t)key;
! if (avl_find(&entity->vme_anon, &anon, NULL) != NULL)
return (0);
! ap = kmem_alloc(sizeof (vmu_anon_t), KM_SLEEP);
! ap->vma_addr = (uintptr_t)key;
! avl_add(&entity->vme_anon, ap);
return (1);
}
static vmu_entity_t *
--- 616,640 ----
}
return (object);
}
static int
! vmu_find_insert_anon(mod_hash_t *hash, caddr_t key)
{
! int ret;
! caddr_t val;
! ret = i_mod_hash_find_nosync(hash, (mod_hash_key_t)key,
! (mod_hash_val_t *)&val);
! if (ret == 0)
return (0);
! ret = i_mod_hash_insert_nosync(hash, (mod_hash_key_t)key,
! (mod_hash_val_t)key, (mod_hash_hndl_t)0);
! ASSERT(ret == 0);
return (1);
}
static vmu_entity_t *
*** 1371,1381 ****
result = &entity->vme_result;
/*
* Track COW anons per entity so
* they are not double counted.
*/
! if (vmu_find_insert_anon(entity, ap) == 0)
continue;
result->vmu_rss_all += (pgcnt << PAGESHIFT);
result->vmu_rss_private +=
(pgcnt << PAGESHIFT);
--- 1342,1353 ----
result = &entity->vme_result;
/*
* Track COW anons per entity so
* they are not double counted.
*/
! 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,1655 ****
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);
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 =
--- 1617,1628 ----
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);
! 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 =