Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 139661
b: refs/heads/master
c: 14067bb
h: refs/heads/master
i:
  139659: 9e3c017
v: v3
  • Loading branch information
KAMEZAWA Hiroyuki authored and Linus Torvalds committed Apr 3, 2009
1 parent 89441fb commit 31d7fcd
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 42 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 04046e1a0a34286382e913f8fc461440c21d88e8
refs/heads/master: 14067bb3e24b96d92e22d19c18c0119edf5575e5
160 changes: 119 additions & 41 deletions trunk/mm/memcontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ page_cgroup_zoneinfo(struct page_cgroup *pc)
return mem_cgroup_zoneinfo(mem, nid, zid);
}

static unsigned long mem_cgroup_get_all_zonestat(struct mem_cgroup *mem,
static unsigned long mem_cgroup_get_local_zonestat(struct mem_cgroup *mem,
enum lru_list idx)
{
int nid, zid;
Expand Down Expand Up @@ -317,6 +317,42 @@ static bool mem_cgroup_is_obsolete(struct mem_cgroup *mem)
return css_is_removed(&mem->css);
}


/*
* Call callback function against all cgroup under hierarchy tree.
*/
static int mem_cgroup_walk_tree(struct mem_cgroup *root, void *data,
int (*func)(struct mem_cgroup *, void *))
{
int found, ret, nextid;
struct cgroup_subsys_state *css;
struct mem_cgroup *mem;

if (!root->use_hierarchy)
return (*func)(root, data);

nextid = 1;
do {
ret = 0;
mem = NULL;

rcu_read_lock();
css = css_get_next(&mem_cgroup_subsys, nextid, &root->css,
&found);
if (css && css_tryget(css))
mem = container_of(css, struct mem_cgroup, css);
rcu_read_unlock();

if (mem) {
ret = (*func)(mem, data);
css_put(&mem->css);
}
nextid = found + 1;
} while (!ret && css);

return ret;
}

/*
* Following LRU functions are allowed to be used without PCG_LOCK.
* Operations are called by routine of global LRU independently from memcg.
Expand Down Expand Up @@ -510,8 +546,8 @@ static int calc_inactive_ratio(struct mem_cgroup *memcg, unsigned long *present_
unsigned long gb;
unsigned long inactive_ratio;

inactive = mem_cgroup_get_all_zonestat(memcg, LRU_INACTIVE_ANON);
active = mem_cgroup_get_all_zonestat(memcg, LRU_ACTIVE_ANON);
inactive = mem_cgroup_get_local_zonestat(memcg, LRU_INACTIVE_ANON);
active = mem_cgroup_get_local_zonestat(memcg, LRU_ACTIVE_ANON);

gb = (inactive + active) >> (30 - PAGE_SHIFT);
if (gb)
Expand Down Expand Up @@ -1838,54 +1874,90 @@ static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
return 0;
}

static const struct mem_cgroup_stat_desc {
const char *msg;
u64 unit;
} mem_cgroup_stat_desc[] = {
[MEM_CGROUP_STAT_CACHE] = { "cache", PAGE_SIZE, },
[MEM_CGROUP_STAT_RSS] = { "rss", PAGE_SIZE, },
[MEM_CGROUP_STAT_PGPGIN_COUNT] = {"pgpgin", 1, },
[MEM_CGROUP_STAT_PGPGOUT_COUNT] = {"pgpgout", 1, },

/* For read statistics */
enum {
MCS_CACHE,
MCS_RSS,
MCS_PGPGIN,
MCS_PGPGOUT,
MCS_INACTIVE_ANON,
MCS_ACTIVE_ANON,
MCS_INACTIVE_FILE,
MCS_ACTIVE_FILE,
MCS_UNEVICTABLE,
NR_MCS_STAT,
};

struct mcs_total_stat {
s64 stat[NR_MCS_STAT];
};

struct {
char *local_name;
char *total_name;
} memcg_stat_strings[NR_MCS_STAT] = {
{"cache", "total_cache"},
{"rss", "total_rss"},
{"pgpgin", "total_pgpgin"},
{"pgpgout", "total_pgpgout"},
{"inactive_anon", "total_inactive_anon"},
{"active_anon", "total_active_anon"},
{"inactive_file", "total_inactive_file"},
{"active_file", "total_active_file"},
{"unevictable", "total_unevictable"}
};


static int mem_cgroup_get_local_stat(struct mem_cgroup *mem, void *data)
{
struct mcs_total_stat *s = data;
s64 val;

/* per cpu stat */
val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_CACHE);
s->stat[MCS_CACHE] += val * PAGE_SIZE;
val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_RSS);
s->stat[MCS_RSS] += val * PAGE_SIZE;
val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGIN_COUNT);
s->stat[MCS_PGPGIN] += val;
val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGOUT_COUNT);
s->stat[MCS_PGPGOUT] += val;

/* per zone stat */
val = mem_cgroup_get_local_zonestat(mem, LRU_INACTIVE_ANON);
s->stat[MCS_INACTIVE_ANON] += val * PAGE_SIZE;
val = mem_cgroup_get_local_zonestat(mem, LRU_ACTIVE_ANON);
s->stat[MCS_ACTIVE_ANON] += val * PAGE_SIZE;
val = mem_cgroup_get_local_zonestat(mem, LRU_INACTIVE_FILE);
s->stat[MCS_INACTIVE_FILE] += val * PAGE_SIZE;
val = mem_cgroup_get_local_zonestat(mem, LRU_ACTIVE_FILE);
s->stat[MCS_ACTIVE_FILE] += val * PAGE_SIZE;
val = mem_cgroup_get_local_zonestat(mem, LRU_UNEVICTABLE);
s->stat[MCS_UNEVICTABLE] += val * PAGE_SIZE;
return 0;
}

static void
mem_cgroup_get_total_stat(struct mem_cgroup *mem, struct mcs_total_stat *s)
{
mem_cgroup_walk_tree(mem, s, mem_cgroup_get_local_stat);
}

static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
struct cgroup_map_cb *cb)
{
struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont);
struct mem_cgroup_stat *stat = &mem_cont->stat;
struct mcs_total_stat mystat;
int i;

for (i = 0; i < ARRAY_SIZE(stat->cpustat[0].count); i++) {
s64 val;
memset(&mystat, 0, sizeof(mystat));
mem_cgroup_get_local_stat(mem_cont, &mystat);

val = mem_cgroup_read_stat(stat, i);
val *= mem_cgroup_stat_desc[i].unit;
cb->fill(cb, mem_cgroup_stat_desc[i].msg, val);
}
/* showing # of active pages */
{
unsigned long active_anon, inactive_anon;
unsigned long active_file, inactive_file;
unsigned long unevictable;

inactive_anon = mem_cgroup_get_all_zonestat(mem_cont,
LRU_INACTIVE_ANON);
active_anon = mem_cgroup_get_all_zonestat(mem_cont,
LRU_ACTIVE_ANON);
inactive_file = mem_cgroup_get_all_zonestat(mem_cont,
LRU_INACTIVE_FILE);
active_file = mem_cgroup_get_all_zonestat(mem_cont,
LRU_ACTIVE_FILE);
unevictable = mem_cgroup_get_all_zonestat(mem_cont,
LRU_UNEVICTABLE);

cb->fill(cb, "active_anon", (active_anon) * PAGE_SIZE);
cb->fill(cb, "inactive_anon", (inactive_anon) * PAGE_SIZE);
cb->fill(cb, "active_file", (active_file) * PAGE_SIZE);
cb->fill(cb, "inactive_file", (inactive_file) * PAGE_SIZE);
cb->fill(cb, "unevictable", unevictable * PAGE_SIZE);
for (i = 0; i < NR_MCS_STAT; i++)
cb->fill(cb, memcg_stat_strings[i].local_name, mystat.stat[i]);

}
/* Hierarchical information */
{
unsigned long long limit, memsw_limit;
memcg_get_hierarchical_limit(mem_cont, &limit, &memsw_limit);
Expand All @@ -1894,6 +1966,12 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
cb->fill(cb, "hierarchical_memsw_limit", memsw_limit);
}

memset(&mystat, 0, sizeof(mystat));
mem_cgroup_get_total_stat(mem_cont, &mystat);
for (i = 0; i < NR_MCS_STAT; i++)
cb->fill(cb, memcg_stat_strings[i].total_name, mystat.stat[i]);


#ifdef CONFIG_DEBUG_VM
cb->fill(cb, "inactive_ratio", calc_inactive_ratio(mem_cont, NULL));

Expand Down

0 comments on commit 31d7fcd

Please sign in to comment.