diff options
Diffstat (limited to 'mm/memcontrol.c')
| -rw-r--r-- | mm/memcontrol.c | 34 | 
1 files changed, 25 insertions, 9 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3a24e3b619f5..29459a6ce1c7 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -867,8 +867,13 @@ void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val)  	rcu_read_lock();  	memcg = mem_cgroup_from_obj(p); -	/* Untracked pages have no memcg, no lruvec. Update only the node */ -	if (!memcg || memcg == root_mem_cgroup) { +	/* +	 * Untracked pages have no memcg, no lruvec. Update only the +	 * node. If we reparent the slab objects to the root memcg, +	 * when we free the slab object, we need to update the per-memcg +	 * vmstats to keep it correct for the root memcg. +	 */ +	if (!memcg) {  		__mod_node_page_state(pgdat, idx, val);  	} else {  		lruvec = mem_cgroup_lruvec(memcg, pgdat); @@ -4110,11 +4115,17 @@ static int memcg_stat_show(struct seq_file *m, void *v)  			   (u64)memsw * PAGE_SIZE);  	for (i = 0; i < ARRAY_SIZE(memcg1_stats); i++) { +		unsigned long nr; +  		if (memcg1_stats[i] == MEMCG_SWAP && !do_memsw_account())  			continue; +		nr = memcg_page_state(memcg, memcg1_stats[i]); +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +		if (memcg1_stats[i] == NR_ANON_THPS) +			nr *= HPAGE_PMD_NR; +#endif  		seq_printf(m, "total_%s %llu\n", memcg1_stat_names[i], -			   (u64)memcg_page_state(memcg, memcg1_stats[i]) * -			   PAGE_SIZE); +						(u64)nr * PAGE_SIZE);  	}  	for (i = 0; i < ARRAY_SIZE(memcg1_events); i++) @@ -5339,17 +5350,22 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)  		memcg->swappiness = mem_cgroup_swappiness(parent);  		memcg->oom_kill_disable = parent->oom_kill_disable;  	} -	if (parent && parent->use_hierarchy) { +	if (!parent) { +		page_counter_init(&memcg->memory, NULL); +		page_counter_init(&memcg->swap, NULL); +		page_counter_init(&memcg->kmem, NULL); +		page_counter_init(&memcg->tcpmem, NULL); +	} else if (parent->use_hierarchy) {  		memcg->use_hierarchy = true;  		page_counter_init(&memcg->memory, &parent->memory);  		page_counter_init(&memcg->swap, &parent->swap);  		page_counter_init(&memcg->kmem, &parent->kmem);  		page_counter_init(&memcg->tcpmem, &parent->tcpmem);  	} else { -		page_counter_init(&memcg->memory, NULL); -		page_counter_init(&memcg->swap, NULL); -		page_counter_init(&memcg->kmem, NULL); -		page_counter_init(&memcg->tcpmem, NULL); +		page_counter_init(&memcg->memory, &root_mem_cgroup->memory); +		page_counter_init(&memcg->swap, &root_mem_cgroup->swap); +		page_counter_init(&memcg->kmem, &root_mem_cgroup->kmem); +		page_counter_init(&memcg->tcpmem, &root_mem_cgroup->tcpmem);  		/*  		 * Deeper hierachy with use_hierarchy == false doesn't make  		 * much sense so let cgroup subsystem know about this  | 
