OpenVZ Forum - RDF feed
type: channel
items: [PATCH v4 00/25] kmem limitation for memcg
items: [PATCH v4 01/25] slab: rename gfpflags to allocflags
items: [PATCH v4 02/25] provide a common place for initcall processing in kmem_cache
items: [PATCH v4 03/25] slab: move FULL state transition to an initcall
items: [PATCH v4 04/25] Wipe out CFLGS_OFF_SLAB from flags during initial slab creation
items: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
items: [PATCH v4 06/25] memcg: Make it possible to use the stock for more than one page.
items: [PATCH v4 07/25] memcg: Reclaim when more than one page needed.
items: [PATCH v4 08/25] memcg: change defines to an enum
items: [PATCH v4 09/25] kmem slab accounting basic infrastructure
items: [PATCH v4 10/25] slab/slub: struct memcg_params
items: [PATCH v4 11/25] consider a memcg parameter in kmem_create_cache
items: [PATCH v4 12/25] sl[au]b: always get the cache from its page in kfree
items: [PATCH v4 13/25] Add a __GFP_SLABMEMCG flag
items: [PATCH v4 14/25] memcg: kmem controller dispatch infrastructure
items: [PATCH v4 15/25] allow enable_cpu_cache to use preset values for its tunables
items: [PATCH v4 16/25] don't do __ClearPageSlab before freeing slab page.
items: [PATCH v4 17/25] skip memcg kmem allocations in specified code regions
items: [PATCH v4 18/25] mm: Allocate kernel pages to the right memcg
items: [PATCH v4 19/25] memcg: disable kmem code when not in use.
items: [PATCH v4 20/25] memcg: destroy memcg caches
items: [PATCH v4 21/25] Track all the memcg children of a kmem_cache.
items: [PATCH v4 22/25] slab: slab-specific propagation changes.
items: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
items: [PATCH v4 24/25] memcg/slub: shrink dead caches
items: [PATCH v4 25/25] Documentation: add documentation for slab tracker for memcg
items: Re: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
items: Re: [PATCH v4 00/25] kmem limitation for memcg
items: Re: [PATCH v4 17/25] skip memcg kmem allocations in specified code regions
items: Re: [PATCH v4 19/25] memcg: disable kmem code when not in use.
items: Re: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
items: Re: [PATCH v4 08/25] memcg: change defines to an enum
items: Re: [PATCH v4 06/25] memcg: Make it possible to use the stock for more than one page.
items: Re: [PATCH v4 07/25] memcg: Reclaim when more than one page needed.
items: Re: [PATCH v4 24/25] memcg/slub: shrink dead caches

[PATCH v4 00/25] kmem limitation for memcg
type: item
description: Hello All, This is my new take for the memcg kmem accounting. This should merge all of the previous comments from you guys, specially concerning the big churn inside the allocators themselves. My focus in this new round was to keep the changes in the cache internals to a minimum. To do that, I relied upon two main pillars: * Cristoph's unification series, that allowed me to put must of the changes in a common file. Even then, the changes are not too many, since the overal level of invasiveness was decreased. * Accounting is done directly from the page allocator. This means some pages can fail to be accounted, but that can only happen when the task calling kmem_cache_alloc or kmalloc is not the same task allocating a new page. This never happens in steady state operation if the tasks are kept in the same memcg. Naturally, if the page ends up being accounted to a memcg that is not limited (such as root memcg), that particular page will simply not be accounted. The dispatcher code stays (mem_cgroup_get_kmem_cache), being the mechanism who guarantees that, during steady state operation, all objects allocated in a page will belong to the same memcg. I consider this a good compromise point between strict and loose accounting here. I should point out again that most, if not all, of the code in the caches are wrapped in static_key areas, meaning they will be completely patched out until the first limit is set. Enabling and disabling of static_keys incorporate the last fixes for sock memcg, and should be pretty robust. [ v4 ] * I decided to leave the file memory.kmem.slabinfo out of this series. It can be done a lot better if the caches have a common interface for that, which seems to be work in progress. * Accounting is done directly from the page allocator. * more code moved out of the cache internals. [ v3 ] * fixed lockdep bugs in slab (ordering of get_online_cpus() vs slab_mutex) * improved style in slab and slub with less #ifdefs in-code * tested and fixed hierarchical…
creator: Glauber Costa
date: 2012-06-18T10:27:53-00:00

[PATCH v4 01/25] slab: rename gfpflags to allocflags
type: item
description: A consistent name with slub saves us an acessor function. In both caches, this field represents the same thing. We would like to use it from the mem_cgroup code. Signed-off-by: Glauber Costa <glommer@parallels.com> Acked-by: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> --- include/linux/slab_def.h | 2 +- mm/slab.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 1d93f27..0c634fa 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -39,7 +39,7 @@ struct kmem_cache { unsigned int gfporder; /* force GFP flags, e.g. GFP_DMA */ - gfp_t gfpflags; + gfp_t allocflags; size_t colour; /* cache colouring range */ unsigned int colour_off; /* colour offset */ diff --git a/mm/slab.c b/mm/slab.c index 2476ad4..020605f 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1746,7 +1746,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) flags |= __GFP_COMP; #endif - flags |= cachep->gfpflags; + flags |= cachep->allocflags; if (cachep->flags & SLAB_RECLAIM_ACCOUNT) flags |= __GFP_RECLAIMABLE; @@ -2338,9 +2338,9 @@ int __kmem_cache_create(struct kmem_cache *cachep) cachep->colour = left_over / cachep->colour_off; cachep->slab_size = slab_size; cachep->flags = flags; - cachep->gfpflags = 0; + cachep->allocflags = 0; if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA)) - cachep->gfpflags |= GFP_DMA; + cachep->allocflags |= GFP_DMA; cachep->size = size; cachep->reciprocal_buffer_size = reciprocal_value(size); @@ -2653,9 +2653,9 @@ static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags) { if (CONFIG_ZONE_DMA_FLAG) { if (flags & GFP_DMA) - BUG_ON(!(cachep->gfpflags & GFP_DMA)); + BUG_ON(!(cachep->allocflags & GFP_DMA)); else - BUG_ON(cachep->gfpflags & GFP_DMA); + BUG_ON(cachep->allocflags & GFP_DMA); } } -- 1.7.10.2
creator: Glauber Costa
date: 2012-06-18T10:27:54-00:00

[PATCH v4 02/25] provide a common place for initcall processing in kmem_cache
type: item
description: Both SLAB and SLUB depend on some initialization to happen when the system is already booted, with all subsystems working. This is done by issuing an initcall that does the final initialization. This patch moves that to slab_common.c, while creating an empty placeholder for the SLOB. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: David Rientjes <rientjes@google.com> --- mm/slab.c | 5 ++--- mm/slab.h | 1 + mm/slab_common.c | 5 +++++ mm/slob.c | 5 +++++ mm/slub.c | 4 +--- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 020605f..e174e50 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -853,7 +853,7 @@ static void __cpuinit start_cpu_timer(int cpu) struct delayed_work *reap_work = &per_cpu(slab_reap_work, cpu); /* - * When this gets called from do_initcalls via cpucache_init(), + * When this gets called from do_initcalls via __kmem_cache_initcall(), * init_workqueues() has already run, so keventd will be setup * at that time. */ @@ -1666,7 +1666,7 @@ void __init kmem_cache_init_late(void) */ } -static int __init cpucache_init(void) +int __init __kmem_cache_initcall(void) { int cpu; @@ -1677,7 +1677,6 @@ static int __init cpucache_init(void) start_cpu_timer(cpu); return 0; } -__initcall(cpucache_init); static noinline void slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid) diff --git a/mm/slab.h b/mm/slab.h index b44a8cc..19e17c7 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -37,6 +37,7 @@ unsigned long calculate_alignment(unsigned long flags, /* Functions provided by the slab allocators */ int __kmem_cache_create(struct kmem_cache *s); +int __kmem_cache_initcall(void); #ifdef CONFIG_SLUB struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, diff --git a/mm/slab_common.c b/mm/slab_common.c index b5def07..15db694ac 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -203,3 +203,8 @@ int slab_is_available(void) r…
creator: Glauber Costa
date: 2012-06-18T10:27:55-00:00

[PATCH v4 03/25] slab: move FULL state transition to an initcall
type: item
description: During kmem_cache_init_late(), we transition to the LATE state, and after some more work, to the FULL state, its last state This is quite different from slub, that will only transition to its last state (previously SYSFS), in a (late)initcall, after a lot more of the kernel is ready. This means that in slab, we have no way to taking actions dependent on the initialization of other pieces of the kernel that are supposed to start way after kmem_init_late(), such as cgroups initialization. To achieve more consistency in this behavior, that patch only transitions to the UP state in kmem_init_late. In my analysis, setup_cpu_cache() should be happy to test for >= UP, instead of == FULL. It also has passed some tests I've made. We then only mark FULL state after the reap timers are in place, meaning that no further setup is expected. Signed-off-by: Glauber Costa <glommer@parallels.com> Acked-by: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: David Rientjes <rientjes@google.com> --- mm/slab.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index e174e50..2d5fe28 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1643,9 +1643,6 @@ void __init kmem_cache_init_late(void) BUG(); mutex_unlock(&slab_mutex); - /* Done! */ - slab_state = FULL; - /* * Register a cpu startup notifier callback that initializes * cpu_cache_get for all new cpus @@ -1675,6 +1672,9 @@ int __init __kmem_cache_initcall(void) */ for_each_online_cpu(cpu) start_cpu_timer(cpu); + + /* Done! */ + slab_state = FULL; return 0; } @@ -2120,7 +2120,7 @@ static size_t calculate_slab_order(struct kmem_cache *cachep, static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) { - if (slab_state == FULL) + if (slab_state >= UP) return enable_cpucache(cachep, gfp); if (slab_state == DOWN) { -- 1.7.10.2
creator: Glauber Costa
date: 2012-06-18T10:27:56-00:00

[PATCH v4 04/25] Wipe out CFLGS_OFF_SLAB from flags during initial slab creation
type: item
description: CFLGS_OFF_SLAB is not a valid flag to be passed to cache creation. If we are duplicating a cache - support added in a future patch - we will rely on the flags it has stored in itself. That may include CFLGS_OFF_SLAB. So it is better to clean this flag at cache creation. CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: David Rientjes <rientjes@google.com> --- mm/slab.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/slab.c b/mm/slab.c index 2d5fe28..c30a61c 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2201,6 +2201,12 @@ int __kmem_cache_create(struct kmem_cache *cachep) BUG_ON(flags & SLAB_POISON); #endif /* + * Passing this flag at creation time is invalid, but if we're + * duplicating a slab, it may happen. + */ + flags &= ~CFLGS_OFF_SLAB; + + /* * Always checks flags, a caller might be expecting debug support which * isn't available. */ -- 1.7.10.2
creator: Glauber Costa
date: 2012-06-18T10:27:57-00:00

[PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
type: item
description: Right now we free struct memcg with kfree right after a rcu grace period, but defer it if we need to use vfree() to get rid of that memory area. We do that by need, because we need vfree to be called in a process context. This patch unifies this behavior, by ensuring that even kfree will happen in a separate thread. The goal is to have a stable place to call the upcoming jump label destruction function outside the realm of the complicated and quite far-reaching cgroup lock (that can't be held when calling neither the cpu_hotplug.lock nor the jump_label_mutex) Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Tejun Heo <tj@kernel.org> CC: Li Zefan <lizefan@huawei.com> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Michal Hocko <mhocko@suse.cz> --- mm/memcontrol.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e3b528e..ce15be4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -245,8 +245,8 @@ struct mem_cgroup { */ struct rcu_head rcu_freeing; /* - * But when using vfree(), that cannot be done at - * interrupt time, so we must then queue the work. + * We also need some space for a worker in deferred freeing. + * By the time we call it, rcu_freeing is not longer in use. */ struct work_struct work_freeing; }; @@ -4826,23 +4826,28 @@ out_free: } /* - * Helpers for freeing a vzalloc()ed mem_cgroup by RCU, + * Helpers for freeing a kmalloc()ed/vzalloc()ed mem_cgroup by RCU, * but in process context. The work_freeing structure is overlaid * on the rcu_freeing structure, which itself is overlaid on memsw. */ -static void vfree_work(struct work_struct *work) +static void free_work(struct work_struct *work) { struct mem_cgroup *memcg; + int size = sizeof(struct mem_cgroup); memcg = container_of(work, struct mem_cgroup, work_freeing); - vfree(memcg); + if (size < PAGE_SIZE) + kfree(memcg); + else + vfree(memcg); } -static void vfr…
creator: Glauber Costa
date: 2012-06-18T10:27:58-00:00

[PATCH v4 06/25] memcg: Make it possible to use the stock for more than one page.
type: item
description: From: Suleiman Souhlal <ssouhlal@FreeBSD.org> Signed-off-by: Suleiman Souhlal <suleiman@google.com> Signed-off-by: Glauber Costa <glommer@parallels.com> Acked-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> --- mm/memcontrol.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index ce15be4..00b9f1e 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1998,19 +1998,19 @@ static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock); static DEFINE_MUTEX(percpu_charge_mutex); /* - * Try to consume stocked charge on this cpu. If success, one page is consumed - * from local stock and true is returned. If the stock is 0 or charges from a - * cgroup which is not current target, returns false. This stock will be - * refilled. + * Try to consume stocked charge on this cpu. If success, nr_pages pages are + * consumed from local stock and true is returned. If the stock is 0 or + * charges from a cgroup which is not current target, returns false. + * This stock will be refilled. */ -static bool consume_stock(struct mem_cgroup *memcg) +static bool consume_stock(struct mem_cgroup *memcg, int nr_pages) { struct memcg_stock_pcp *stock; bool ret = true; stock = &get_cpu_var(memcg_stock); - if (memcg == stock->cached && stock->nr_pages) - stock->nr_pages--; + if (memcg == stock->cached && stock->nr_pages >= nr_pages) + stock->nr_pages -= nr_pages; else /* need to call res_counter_charge */ ret = false; put_cpu_var(memcg_stock); @@ -2309,7 +2309,7 @@ again: VM_BUG_ON(css_is_removed(&memcg->css)); if (mem_cgroup_is_root(memcg)) goto done; - if (nr_pages == 1 && consume_stock(memcg)) + if (consume_stock(memcg, nr_pages)) goto done; css_get(&memcg->css); } else { @@ -2334,7 +2334,7 @@ again: rcu_read_unlock(); goto done; } - if (nr_pages == 1 && consume_stock(memcg)) { + if (consume_stock(memcg, nr_pages)) { /* * It seems dagerous to access memcg without css_get(). * But considering how consume_stok works, it's no…
creator: Glauber Costa
date: 2012-06-18T10:27:59-00:00

[PATCH v4 07/25] memcg: Reclaim when more than one page needed.
type: item
description: From: Suleiman Souhlal <ssouhlal@FreeBSD.org> mem_cgroup_do_charge() was written before slab accounting, and expects three cases: being called for 1 page, being called for a stock of 32 pages, or being called for a hugepage. If we call for 2 or 3 pages (and several slabs used in process creation are such, at least with the debug options I had), it assumed it's being called for stock and just retried without reclaiming. Fix that by passing down a minsize argument in addition to the csize. And what to do about that (csize == PAGE_SIZE && ret) retry? If it's needed at all (and presumably is since it's there, perhaps to handle races), then it should be extended to more than PAGE_SIZE, yet how far? And should there be a retry count limit, of what? For now retry up to COSTLY_ORDER (as page_alloc.c does), stay safe with a cond_resched(), and make sure not to do it if __GFP_NORETRY. [v4: fixed nr pages calculation pointed out by Christoph Lameter ] Signed-off-by: Suleiman Souhlal <suleiman@google.com> Signed-off-by: Glauber Costa <glommer@parallels.com> Reviewed-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> --- mm/memcontrol.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 00b9f1e..b6cb075 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2187,7 +2187,8 @@ enum { }; static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, - unsigned int nr_pages, bool oom_check) + unsigned int nr_pages, unsigned int min_pages, + bool oom_check) { unsigned long csize = nr_pages * PAGE_SIZE; struct mem_cgroup *mem_over_limit; @@ -2210,18 +2211,18 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, } else mem_over_limit = mem_cgroup_from_res_counter(fail_res, res); /* - * nr_pages can be either a huge page (HPAGE_PMD_NR), a batch - * of regular pages (CHARGE_BATCH), or a single regular page (1). - * * Never reclaim on behalf of optional batching, retry with a *…
creator: Glauber Costa
date: 2012-06-18T10:28:00-00:00

[PATCH v4 08/25] memcg: change defines to an enum
type: item
description: This is just a cleanup patch for clarity of expression. In earlier submissions, people asked it to be in a separate patch, so here it is. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Michal Hocko <mhocko@suse.cz> CC: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> --- mm/memcontrol.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index b6cb075..cc1fdb4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -374,9 +374,12 @@ enum charge_type { }; /* for encoding cft->private value on file */ -#define _MEM (0) -#define _MEMSWAP (1) -#define _OOM_TYPE (2) +enum res_type { + _MEM, + _MEMSWAP, + _OOM_TYPE, +}; + #define MEMFILE_PRIVATE(x, val) (((x) << 16) | (val)) #define MEMFILE_TYPE(val) (((val) >> 16) & 0xffff) #define MEMFILE_ATTR(val) ((val) & 0xffff) -- 1.7.10.2
creator: Glauber Costa
date: 2012-06-18T10:28:01-00:00

[PATCH v4 09/25] kmem slab accounting basic infrastructure
type: item
description: This patch adds the basic infrastructure for the accounting of the slab caches. To control that, the following files are created: * memory.kmem.usage_in_bytes * memory.kmem.limit_in_bytes * memory.kmem.failcnt * memory.kmem.max_usage_in_bytes They have the same meaning of their user memory counterparts. They reflect the state of the "kmem" res_counter. The code is not enabled until a limit is set. This can be tested by the flag "kmem_accounted". This means that after the patch is applied, no behavioral changes exists for whoever is still using memcg to control their memory usage. We always account to both user and kernel resource_counters. This effectively means that an independent kernel limit is in place when the limit is set to a lower value than the user memory. A equal or higher value means that the user limit will always hit first, meaning that kmem is effectively unlimited. People who want to track kernel memory but not limit it, can set this limit to a very high number (like RESOURCE_MAX - 1page - that no one will ever hit, or equal to the user memory) Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Michal Hocko <mhocko@suse.cz> CC: Johannes Weiner <hannes@cmpxchg.org> Reviewed-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> --- mm/memcontrol.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index cc1fdb4..04ac774 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -252,6 +252,10 @@ struct mem_cgroup { }; /* + * the counter to account for kernel memory usage. + */ + struct res_counter kmem; + /* * Per cgroup active and inactive list, similar to the * per zone LRU lists. */ @@ -266,6 +270,7 @@ struct mem_cgroup { * Should the accounting and control be hierarchical, per subtree? */ bool use_hierarchy; + bool kmem_accounted; bool oom_lock; atomic_t under_oom; @@ -378,6 +383,7 @@ enum res_type { _MEM, _MEMSWAP, _OOM_TYPE, + _KMEM, }; #def…
creator: Glauber Costa
date: 2012-06-18T10:28:02-00:00

[PATCH v4 10/25] slab/slub: struct memcg_params
type: item
description: For the kmem slab controller, we need to record some extra information in the kmem_cache structure. Signed-off-by: Glauber Costa <glommer@parallels.com> Signed-off-by: Suleiman Souhlal <suleiman@google.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> --- include/linux/slab.h | 8 ++++++++ include/linux/slab_def.h | 4 ++++ include/linux/slub_def.h | 3 +++ 3 files changed, 15 insertions(+) diff --git a/include/linux/slab.h b/include/linux/slab.h index 3c2181a..e007cc5 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -177,6 +177,14 @@ unsigned int kmem_cache_size(struct kmem_cache *); #define ARCH_SLAB_MINALIGN __alignof__(unsigned long long) #endif +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +struct mem_cgroup_cache_params { + struct mem_cgroup *memcg; + int id; + atomic_t refcnt; +}; +#endif + /* * Common kmalloc functions provided by all allocators */ diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 0c634fa..04ca5be 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -83,6 +83,10 @@ struct kmem_cache { int obj_offset; #endif /* CONFIG_DEBUG_SLAB */ +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + struct mem_cgroup_cache_params memcg_params; +#endif + /* 6) per-cpu/per-node data, touched during every alloc/free */ /* * We put array[] at the end of kmem_cache, because we want to size diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index df448ad..7637f3b 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -101,6 +101,9 @@ struct kmem_cache { #ifdef CONFIG_SYSFS struct kobject kobj; /* For sysfs */ #endif +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + struct mem_cgroup_cache_params memcg_params; +#endif #ifdef CONFIG_NUMA /* -- 1.7.10.2
creator: Glauber Costa
date: 2012-06-18T10:28:03-00:00

[PATCH v4 11/25] consider a memcg parameter in kmem_create_cache
type: item
description: Allow a memcg parameter to be passed during cache creation. When the slub allocator is being used, it will only merge caches that belong to the same memcg. Default function is created as a wrapper, passing NULL to the memcg version. We only merge caches that belong to the same memcg. >From the memcontrol.c side, 3 helper functions are created: 1) memcg_css_id: because slub needs a unique cache name for sysfs. Since this is visible, but not the canonical location for slab data, the cache name is not used, the css_id should suffice. 2) mem_cgroup_register_cache: is responsible for assigning a unique index to each cache, and other general purpose setup. The index is only assigned for the root caches. All others are assigned index == -1. 3) mem_cgroup_release_cache: can be called from the root cache destruction, and will release the index for other caches. We can't assign indexes until the basic slab is up and running this is because the ida subsystem will itself call slab functions such as kmalloc a couple of times. Because of that, we have a late_initcall that scan all caches and register them after the kernel is booted up. Only caches registered after that receive their index right away. This index mechanism was developed by Suleiman Souhlal. Changed to a idr/ida based approach based on suggestion from Kamezawa. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- include/linux/memcontrol.h | 14 ++++++++++++++ include/linux/slab.h | 10 ++++++++++ mm/memcontrol.c | 25 +++++++++++++++++++++++++ mm/slab.h | 22 +++++++++++++++++----- mm/slab_common.c | 36 +++++++++++++++++++++++++++++++----- mm/slub.c | 16 ++++++++++++---- 6 files changed, 109 insertions(+), 14 deletions(-) diff --git a/include/linux/memcontrol.h b/incl…
creator: Glauber Costa
date: 2012-06-18T10:28:04-00:00

[PATCH v4 12/25] sl[au]b: always get the cache from its page in kfree
type: item
description: struct page already have this information. If we start chaining caches, this information will always be more trustworthy than whatever is passed into the function A parent pointer is added to the slub structure, so we can make sure the freeing comes from either the right slab, or from its rightful parent. [ v3: added parent testing with VM_BUG_ON ] Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> --- mm/slab.c | 5 ++++- mm/slab.h | 10 ++++++++++ mm/slub.c | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index c30a61c..3783a6a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3712,9 +3712,12 @@ EXPORT_SYMBOL(__kmalloc); * Free an object which was previously allocated from this * cache. */ -void kmem_cache_free(struct kmem_cache *cachep, void *objp) +void kmem_cache_free(struct kmem_cache *s, void *objp) { unsigned long flags; + struct kmem_cache *cachep = virt_to_cache(objp); + + VM_BUG_ON(!((s == cachep) | slab_is_parent(s, cachep))); local_irq_save(flags); debug_check_no_locks_freed(objp, cachep->size); diff --git a/mm/slab.h b/mm/slab.h index 1781580..0a3e712 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -63,4 +63,14 @@ static inline bool cache_match_memcg(struct kmem_cache *cachep, } void __init memcg_slab_register_all(void); + +static inline bool slab_is_parent(struct kmem_cache *s, + struct kmem_cache *candidate) +{ +#if defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) && defined(CONFIG_DEBUG_VM) + return candidate == s->memcg_params.parent; +#else + return false; +#endif +} #endif diff --git a/mm/slub.c b/mm/slub.c index ca4b8e0..e685cfa 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2597,7 +2597,8 @@ void kmem_cache_free(struct kmem_cache *s, void *x) page = virt_to_head_page(x); - slab_free(s, page, x, _RET_IP_); + VM_BUG_ON(!((page->slab == s) | slab_is_parent(page->slab, s))); + slab_free(page->slab, page, x, _RET_IP_); trace_kmem_cache_free(_RET_IP_, x)…
creator: Glauber Costa
date: 2012-06-18T10:28:05-00:00

[PATCH v4 13/25] Add a __GFP_SLABMEMCG flag
type: item
description: This flag is used to indicate to the callees that this allocation will be serviced to the kernel. It is not supposed to be passed by the callers of kmem_cache_alloc, but rather by the cache core itself. CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- include/linux/gfp.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 581e74b..f904fe1 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -37,6 +37,9 @@ struct vm_area_struct; #define ___GFP_NO_KSWAPD 0x400000u #define ___GFP_OTHER_NODE 0x800000u #define ___GFP_WRITE 0x1000000u +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#define ___GFP_SLABMEMCG 0x2000000u +#endif /* * GFP bitmasks.. @@ -88,13 +91,16 @@ struct vm_area_struct; #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */ #define __GFP_WRITE ((__force gfp_t)___GFP_WRITE) /* Allocator intends to dirty page */ +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#define __GFP_SLABMEMCG ((__force gfp_t)___GFP_SLABMEMCG)/* Allocation comes from a memcg slab */ +#endif /* * This may seem redundant, but it's a way of annotating false positives vs. * allocations that simply cannot be supported (e.g. page tables). */ #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK) -#define __GFP_BITS_SHIFT 25 /* Room for N __GFP_FOO bits */ +#define __GFP_BITS_SHIFT 26 /* Room for N __GFP_FOO bits */ #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) /* This equals 0, but use constants in case they ever change */ -- 1.7.10.2
creator: Glauber Costa
date: 2012-06-18T10:28:06-00:00

[PATCH v4 14/25] memcg: kmem controller dispatch infrastructure
type: item
description: With all the dependencies already in place, this patch introduces the dispatcher functions for the slab cache accounting in memcg. Before we can charge a cache, we need to select the right cache. This is done by using the function __mem_cgroup_get_kmem_cache(). If we should use the root kmem cache, this function tries to detect that and return as early as possible. In memcontrol.h those functions are wrapped in inline acessors. The idea is to later on, patch those with jump labels, so we don't incur any overhead when no mem cgroups are being used. Because the slub allocator tends to inline the allocations whenever it can, those functions need to be exported so modules can make use of it properly. This code is inspired by the code written by Suleiman Souhlal, but heavily changed. Signed-off-by: Glauber Costa <glommer@parallels.com> Signed-off-by: Suleiman Souhlal <suleiman@google.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> --- include/linux/memcontrol.h | 80 +++++++++ init/Kconfig | 2 +- mm/memcontrol.c | 390 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 470 insertions(+), 2 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 99e14b9..27a3f16 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -21,6 +21,7 @@ #define _LINUX_MEMCONTROL_H #include <linux/cgroup.h> #include <linux/vm_event_item.h> +#include <linux/hardirq.h> struct mem_cgroup; struct page_cgroup; @@ -445,6 +446,19 @@ int memcg_css_id(struct mem_cgroup *memcg); void mem_cgroup_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s); void mem_cgroup_release_cache(struct kmem_cache *cachep); +void mem_cgroup_flush_cache_create_queue(void); +bool __mem_cgroup_new_kmem_page(gfp_t gfp, void *handle, int order); +void __mem_cgroup_commit_kmem_page(struct page *pa…
creator: Glauber Costa
date: 2012-06-18T10:28:07-00:00

[PATCH v4 15/25] allow enable_cpu_cache to use preset values for its tunables
type: item
description: SLAB allows us to tune a particular cache behavior with tunables. When creating a new memcg cache copy, we'd like to preserve any tunables the parent cache already had. This could be done by an explicit call to do_tune_cpucache() after the cache is created. But this is not very convenient now that the caches are created from common code, since this function is SLAB-specific. Another method of doing that is taking advantage of the fact that do_tune_cpucache() is always called from enable_cpucache(), which is called at cache initialization. We can just preset the values, and then things work as expected. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- include/linux/slab.h | 3 ++- mm/memcontrol.c | 2 +- mm/slab.c | 19 ++++++++++++++++--- mm/slab_common.c | 7 ++++--- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index d347616..d2d2fad 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -128,7 +128,7 @@ struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, void (*)(void *)); struct kmem_cache * kmem_cache_create_memcg(struct mem_cgroup *, const char *, size_t, size_t, - unsigned long, void (*)(void *)); + unsigned long, void (*)(void *), struct kmem_cache *); void kmem_cache_destroy(struct kmem_cache *); int kmem_cache_shrink(struct kmem_cache *); void kmem_cache_free(struct kmem_cache *, void *); @@ -184,6 +184,7 @@ unsigned int kmem_cache_size(struct kmem_cache *); #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM struct mem_cgroup_cache_params { struct mem_cgroup *memcg; + struct kmem_cache *parent; int id; atomic_t refcnt; }; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index beead5e..324e550 100644 --- a/mm/memcontrol.c +++ b/mm/memco…
creator: Glauber Costa
date: 2012-06-18T10:28:08-00:00

[PATCH v4 16/25] don't do __ClearPageSlab before freeing slab page.
type: item
description: This will give the oportunity to the page allocator to determine that a given page was previously a slab page, and take action accordingly. If memcg kmem is present, this means that that page needs to be unaccounted. The page allocator will now have the responsibility to clear that bit upon free_pages(). It is not uncommon to have the page allocator to check page flags. Mlock flag, for instance, is checked pervasively all over the place. So I hope this is okay for the slab as well. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- mm/page_alloc.c | 5 ++++- mm/slab.c | 5 ----- mm/slob.c | 1 - mm/slub.c | 1 - 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 918330f..a884a9c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -697,8 +697,10 @@ static bool free_pages_prepare(struct page *page, unsigned int order) if (PageAnon(page)) page->mapping = NULL; - for (i = 0; i < (1 << order); i++) + for (i = 0; i < (1 << order); i++) { + __ClearPageSlab(page + i); bad += free_pages_check(page + i); + } if (bad) return false; @@ -2505,6 +2507,7 @@ EXPORT_SYMBOL(get_zeroed_page); void __free_pages(struct page *page, unsigned int order) { if (put_page_testzero(page)) { + __ClearPageSlab(page); if (order == 0) free_hot_cold_page(page, 0); else diff --git a/mm/slab.c b/mm/slab.c index c548666..e537406 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1795,11 +1795,6 @@ static void kmem_freepages(struct kmem_cache *cachep, void *addr) else sub_zone_page_state(page_zone(page), NR_SLAB_UNRECLAIMABLE, nr_freed); - while (i--) { - BUG_ON(!PageSlab(page)); - __ClearPageSlab(page); - page++; - } if (current->reclaim_state) current->reclaim_state->reclaimed_slab += nr_freed; free_pages((unsigned long)addr, cachep->gfporder);…
creator: Glauber Costa
date: 2012-06-18T10:28:09-00:00

[PATCH v4 17/25] skip memcg kmem allocations in specified code regions
type: item
description: This patch creates a mechanism that skip memcg allocations during certain pieces of our core code. It basically works in the same way as preempt_disable()/preempt_enable(): By marking a region under which all allocations will be accounted to the root memcg. We need this to prevent races in early cache creation, when we allocate data using caches that are not necessarily created already. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- include/linux/sched.h | 1 + mm/memcontrol.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 81a173c..0761dda 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1613,6 +1613,7 @@ struct task_struct { unsigned long nr_pages; /* uncharged usage */ unsigned long memsw_nr_pages; /* uncharged mem+swap usage */ } memcg_batch; + unsigned int memcg_kmem_skip_account; #endif #ifdef CONFIG_HAVE_HW_BREAKPOINT atomic_t ptrace_bp_refcnt; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 324e550..233d3bc 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -479,6 +479,22 @@ struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg) EXPORT_SYMBOL(tcp_proto_cgroup); #endif /* CONFIG_INET */ +static void memcg_stop_kmem_account(void) +{ + if (!current->mm) + return; + + current->memcg_kmem_skip_account++; +} + +static void memcg_resume_kmem_account(void) +{ + if (!current->mm) + return; + + current->memcg_kmem_skip_account--; +} + static char *mem_cgroup_cache_name(struct mem_cgroup *memcg, struct kmem_cache *cachep) { char *name; @@ -555,7 +571,9 @@ static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg, if (new_cachep) goto out; + memcg_stop_kmem_account(); new_cachep = kmem…
creator: Glauber Costa
date: 2012-06-18T10:28:10-00:00

[PATCH v4 18/25] mm: Allocate kernel pages to the right memcg
type: item
description: This patch builds on the suggestion previously given by Cristoph, with one major difference: it still keeps the cache dispatcher and the cache duplicates. But its internals are completely different. I no longer mess with the cache cores when pages are allocated. (except for destruction, that happens a bit later, but that's quite simple). All of that is done by the page allocator, by recognizing the __GFP_SLABMEMCG flag. The catch here is that 99% of the time, the task doing the dispatch will be the same allocating the page. It doesn't hold only when tasks are moving around. But that's an acceptable price to pay, at least for me. Moving around won't break, it will at the most put us on a state where a cache has a page that is acconted to a different cgroup. Or, if that cgroups is destroyed, not accounted to anyone. If that ever hurts anyone, this is solvable by a reaper, or by a full cache scan when the task moves. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- include/linux/page-flags.h | 2 +- include/linux/slub_def.h | 18 +++++++++++++----- mm/memcontrol.c | 2 ++ mm/page_alloc.c | 13 ++++++++++++- mm/slab.c | 4 ++++ mm/slub.c | 1 + 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index c88d2a9..9b065d7 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -201,7 +201,7 @@ PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty) PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru) PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active) TESTCLEARFLAG(Active, active) -__PAGEFLAG(Slab, slab) +__PAGEFLAG(Slab, slab) __TESTCLEARFLAG(Slab, slab) PAGEFLAG(Checked, checked) /* Used by some filesystems */ PAGEFLAG…
creator: Glauber Costa
date: 2012-06-18T10:28:11-00:00

[PATCH v4 19/25] memcg: disable kmem code when not in use.
type: item
description: We can use jump labels to patch the code in or out when not used. Because the assignment: memcg->kmem_accounted = true is done after the jump labels increment, we guarantee that the root memcg will always be selected until all call sites are patched (see mem_cgroup_kmem_enabled). This guarantees that no mischarges are applied. Jump label decrement happens when the last reference count from the memcg dies. This will only happen when the caches are all dead. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- include/linux/memcontrol.h | 5 ++++- mm/memcontrol.c | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 27a3f16..47ccd80 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -22,6 +22,7 @@ #include <linux/cgroup.h> #include <linux/vm_event_item.h> #include <linux/hardirq.h> +#include <linux/jump_label.h> struct mem_cgroup; struct page_cgroup; @@ -451,7 +452,6 @@ bool __mem_cgroup_new_kmem_page(gfp_t gfp, void *handle, int order); void __mem_cgroup_commit_kmem_page(struct page *page, void *handle, int order); void __mem_cgroup_free_kmem_page(struct page *page, int order); -#define mem_cgroup_kmem_on 1 struct kmem_cache * __mem_cgroup_get_kmem_cache(struct kmem_cache *cachep, gfp_t gfp); @@ -459,6 +459,9 @@ static inline bool has_memcg_flag(gfp_t gfp) { return gfp & __GFP_SLABMEMCG; } + +extern struct static_key mem_cgroup_kmem_enabled_key; +#define mem_cgroup_kmem_on static_key_false(&mem_cgroup_kmem_enabled_key) #else static inline void mem_cgroup_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index b47ab87..5295ab6 100644 ---…
creator: Glauber Costa
date: 2012-06-18T10:28:12-00:00

[PATCH v4 20/25] memcg: destroy memcg caches
type: item
description: This patch implements destruction of memcg caches. Right now, only caches where our reference counter is the last remaining are deleted. If there are any other reference counters around, we just leave the caches lying around until they go away. When that happen, a destruction function is called from the cache code. Caches are only destroyed in process context, so we queue them up for later processing in the general case. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- include/linux/memcontrol.h | 2 + include/linux/slab.h | 4 +- mm/memcontrol.c | 95 +++++++++++++++++++++++++++++++++++++++++++- mm/slab.c | 4 ++ mm/slab.h | 24 +++++++++++ mm/slub.c | 6 ++- 6 files changed, 131 insertions(+), 4 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 47ccd80..8ebbcc9 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -462,6 +462,8 @@ static inline bool has_memcg_flag(gfp_t gfp) extern struct static_key mem_cgroup_kmem_enabled_key; #define mem_cgroup_kmem_on static_key_false(&mem_cgroup_kmem_enabled_key) + +void mem_cgroup_destroy_cache(struct kmem_cache *cachep); #else static inline void mem_cgroup_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s) diff --git a/include/linux/slab.h b/include/linux/slab.h index d2d2fad..fb4fb7b 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -186,7 +186,9 @@ struct mem_cgroup_cache_params { struct mem_cgroup *memcg; struct kmem_cache *parent; int id; - atomic_t refcnt; + bool dead; + atomic_t nr_pages; + struct list_head destroyed_list; /* Used when deleting memcg cache */ }; #endif diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 5295ab6..e0b79f0 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol…
creator: Glauber Costa
date: 2012-06-18T10:28:13-00:00

[PATCH v4 21/25] Track all the memcg children of a kmem_cache.
type: item
description: This enables us to remove all the children of a kmem_cache being destroyed, if for example the kernel module it's being used in gets unloaded. Otherwise, the children will still point to the destroyed parent. Signed-off-by: Suleiman Souhlal <suleiman@google.com> Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> --- include/linux/memcontrol.h | 1 + include/linux/slab.h | 1 + mm/memcontrol.c | 16 +++++++++++++++- mm/slab_common.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 8ebbcc9..8884a4e 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -464,6 +464,7 @@ extern struct static_key mem_cgroup_kmem_enabled_key; #define mem_cgroup_kmem_on static_key_false(&mem_cgroup_kmem_enabled_key) void mem_cgroup_destroy_cache(struct kmem_cache *cachep); +void mem_cgroup_remove_child_kmem_cache(struct kmem_cache *cachep, int id); #else static inline void mem_cgroup_register_cache(struct mem_cgroup *memcg, struct kmem_cache *s) diff --git a/include/linux/slab.h b/include/linux/slab.h index fb4fb7b..155d19f 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -189,6 +189,7 @@ struct mem_cgroup_cache_params { bool dead; atomic_t nr_pages; struct list_head destroyed_list; /* Used when deleting memcg cache */ + struct list_head sibling_list; }; #endif diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e0b79f0..e32b53e 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -539,8 +539,11 @@ static struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg, new = kmem_cache_create_memcg(memcg, name, s->object_size, s->align, (s->flags & ~SLAB_PANIC), s->ctor, s); - if (new) + if (new) { new->allocflags |= __GFP_SLABMEMCG; + list_ad…
creator: Glauber Costa
date: 2012-06-18T10:28:14-00:00

[PATCH v4 22/25] slab: slab-specific propagation changes.
type: item
description: When a parent cache does tune_cpucache, we need to propagate that to the children as well. For that, we unfortunately need to tap into the slab core. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- mm/slab.c | 28 +++++++++++++++++++++++++++- mm/slab_common.c | 1 + 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mm/slab.c b/mm/slab.c index 4951c81..c280dc6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3874,7 +3874,7 @@ static void do_ccupdate_local(void *info) } /* Always called with the slab_mutex held */ -static int do_tune_cpucache(struct kmem_cache *cachep, int limit, +static int __do_tune_cpucache(struct kmem_cache *cachep, int limit, int batchcount, int shared, gfp_t gfp) { struct ccupdate_struct *new; @@ -3917,6 +3917,32 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, return alloc_kmemlist(cachep, gfp); } +static int do_tune_cpucache(struct kmem_cache *cachep, int limit, + int batchcount, int shared, gfp_t gfp) +{ + int ret; +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + struct kmem_cache *c; + struct mem_cgroup_cache_params *p; +#endif + + ret = __do_tune_cpucache(cachep, limit, batchcount, shared, gfp); +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + if (slab_state < FULL) + return ret; + + if ((ret < 0) || (cachep->memcg_params.id == -1)) + return ret; + + list_for_each_entry(p, &cachep->memcg_params.sibling_list, sibling_list) { + c = container_of(p, struct kmem_cache, memcg_params); + /* return value determined by the parent cache only */ + __do_tune_cpucache(c, limit, batchcount, shared, gfp); + } +#endif + return ret; +} + /* Called with slab_mutex held always */ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) { diff --git a/mm/slab_common.c b/mm/slab_common.c…
creator: Glauber Costa
date: 2012-06-18T10:28:15-00:00

[PATCH v4 23/25] memcg: propagate kmem limiting information to children
type: item
description: The current memcg slab cache management fails to present satisfatory hierarchical behavior in the following scenario: -> /cgroups/memory/A/B/C * kmem limit set at A * A and B empty taskwise * bash in C does find / Because kmem_accounted is a boolean that was not set for C, no accounting would be done. This is, however, not what we expect. The basic idea, is that when a cgroup is limited, we walk the tree upwards (something Kame and I already thought about doing for other purposes), and make sure that we store the information about the parent being limited in kmem_accounted (that is turned into a bitmap: two booleans would not be space efficient). The code for that is taken from sched/core.c. My reasons for not putting it into a common place is to dodge the type issues that would arise from a common implementation between memcg and the scheduler - but I think that it should ultimately happen, so if you want me to do it now, let me know. We do the reverse operation when a formerly limited cgroup becomes unlimited. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 131 insertions(+), 16 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e32b53e..972e83f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -259,6 +259,9 @@ struct mem_cgroup { * the counter to account for kernel memory usage. */ struct res_counter kmem; + + struct list_head children; + struct list_head siblings; /* * Per cgroup active and inactive list, similar to the * per zone LRU lists. @@ -274,7 +277,11 @@ struct mem_cgroup { * Should the accounting and control be hierarchical, per subtree? */ bool use_hierarchy; - bool kmem_accounted; + /…
creator: Glauber Costa
date: 2012-06-18T10:28:16-00:00

[PATCH v4 24/25] memcg/slub: shrink dead caches
type: item
description: In the slub allocator, when the last object of a page goes away, we don't necessarily free it - there is not necessarily a test for empty page in any slab_free path. This means that when we destroy a memcg cache that happened to be empty, those caches may take a lot of time to go away: removing the memcg reference won't destroy them - because there are pending references, and the empty pages will stay there, until a shrinker is called upon for any reason. This patch marks all memcg caches as dead. kmem_cache_shrink is called for the ones who are not yet dead - this will force internal cache reorganization, and then all references to empty pages will be removed. An unlikely branch is used to make sure this case does not affect performance in the usual slab_free path. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> --- include/linux/slab.h | 3 +++ include/linux/slub_def.h | 8 ++++++++ mm/memcontrol.c | 44 +++++++++++++++++++++++++++++++++++++++++++- mm/slub.c | 1 + 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 155d19f..7e13055 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -182,6 +182,8 @@ unsigned int kmem_cache_size(struct kmem_cache *); #endif #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#include <linux/workqueue.h> + struct mem_cgroup_cache_params { struct mem_cgroup *memcg; struct kmem_cache *parent; @@ -190,6 +192,7 @@ struct mem_cgroup_cache_params { atomic_t nr_pages; struct list_head destroyed_list; /* Used when deleting memcg cache */ struct list_head sibling_list; + struct work_struct cache_shrinker; }; #endif diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 7183596..871f82b 100644 --- a/include/linux/slub_…
creator: Glauber Costa
date: 2012-06-18T10:28:17-00:00

[PATCH v4 25/25] Documentation: add documentation for slab tracker for memcg
type: item
description: In a separate patch, to aid reviewers. Signed-off-by: Glauber Costa <glommer@parallels.com> CC: Christoph Lameter <cl@linux.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Michal Hocko <mhocko@suse.cz> CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> CC: Johannes Weiner <hannes@cmpxchg.org> CC: Suleiman Souhlal <suleiman@google.com> CC: Randy Dunlap <rdunlap@xenotime.net> --- Documentation/cgroups/memory.txt | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 9b1067a..9ea82b5 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -74,6 +74,12 @@ Brief summary of control files. memory.kmem.tcp.limit_in_bytes # set/show hard limit for tcp buf memory memory.kmem.tcp.usage_in_bytes # show current tcp buf memory allocation + memory.kmem.limit_in_bytes # set/show hard limit for general kmem memory + memory.kmem.usage_in_bytes # show current general kmem memory allocation + memory.kmem.failcnt # show current number of kmem limit hits + memory.kmem.max_usage_in_bytes # show max kmem usage + memory.kmem.slabinfo # show cgroup-specific slab usage information + 1. History The memory controller has a long history. A request for comments for the memory @@ -270,6 +276,14 @@ cgroup may or may not be accounted. Currently no soft limit is implemented for kernel memory. It is future work to trigger slab reclaim when those limits are reached. +Kernel memory is not accounted until it is limited. Users that want to just +track kernel memory usage can set the limit value to a big enough value so +the limit is guaranteed to never hit. A kernel memory limit bigger than the +current memory limit will have this effect as well. + +This guarantes that this extension is backwards compatible to any previous +memory cgroup version. + 2.7.1 Current Kernel Memory resources accounted * sockets memory pressure: some sockets protocols have memory pressure…
creator: Glauber Costa
date: 2012-06-18T10:28:18-00:00

Re: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
type: item
description: (2012/06/18 19:27), Glauber Costa wrote: > Right now we free struct memcg with kfree right after a > rcu grace period, but defer it if we need to use vfree() to get > rid of that memory area. We do that by need, because we need vfree > to be called in a process context. > > This patch unifies this behavior, by ensuring that even kfree will > happen in a separate thread. The goal is to have a stable place to > call the upcoming jump label destruction function outside the realm > of the complicated and quite far-reaching cgroup lock (that can't be > held when calling neither the cpu_hotplug.lock nor the jump_label_mutex) > > Signed-off-by: Glauber Costa<glommer@parallels.com> > CC: Tejun Heo<tj@kernel.org> > CC: Li Zefan<lizefan@huawei.com> > CC: Kamezawa Hiroyuki<kamezawa.hiroyu@jp.fujitsu.com> > CC: Johannes Weiner<hannes@cmpxchg.org> > CC: Michal Hocko<mhocko@suse.cz> How about cut out this patch and merge first as simple cleanu up and to reduce patch stack on your side ? Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> > --- > mm/memcontrol.c | 24 +++++++++++++----------- > 1 file changed, 13 insertions(+), 11 deletions(-) > > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index e3b528e..ce15be4 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -245,8 +245,8 @@ struct mem_cgroup { > */ > struct rcu_head rcu_freeing; > /* > - * But when using vfree(), that cannot be done at > - * interrupt time, so we must then queue the work. > + * We also need some space for a worker in deferred freeing. > + * By the time we call it, rcu_freeing is not longer in use. > */ > struct work_struct work_freeing; > }; > @@ -4826,23 +4826,28 @@ out_free: > } > > /* > - * Helpers for freeing a vzalloc()ed mem_cgroup by RCU, > + * Helpers for freeing a kmalloc()ed/vzalloc()ed mem_cgroup by RCU, > * but in process context. The work_freeing structure is overlaid > * on the rcu_freeing structure, which itself is overlaid on memsw. > */ > -static void vfree_work(struct …
creator: KAMEZAWA Hiroyuki
date: 2012-06-18T12:07:41-00:00

Re: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
type: item
description: On 06/18/2012 04:07 PM, Kamezawa Hiroyuki wrote: > (2012/06/18 19:27), Glauber Costa wrote: >> Right now we free struct memcg with kfree right after a >> rcu grace period, but defer it if we need to use vfree() to get >> rid of that memory area. We do that by need, because we need vfree >> to be called in a process context. >> >> This patch unifies this behavior, by ensuring that even kfree will >> happen in a separate thread. The goal is to have a stable place to >> call the upcoming jump label destruction function outside the realm >> of the complicated and quite far-reaching cgroup lock (that can't be >> held when calling neither the cpu_hotplug.lock nor the jump_label_mutex) >> >> Signed-off-by: Glauber Costa<glommer@parallels.com> >> CC: Tejun Heo<tj@kernel.org> >> CC: Li Zefan<lizefan@huawei.com> >> CC: Kamezawa Hiroyuki<kamezawa.hiroyu@jp.fujitsu.com> >> CC: Johannes Weiner<hannes@cmpxchg.org> >> CC: Michal Hocko<mhocko@suse.cz> > > How about cut out this patch and merge first as simple cleanu up and > to reduce patch stack on your side ? > > Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> I believe this is already in the -mm tree (from the sock memcg fixes) But actually, my main trouble with this series here, is that I am basing it on Pekka's tree, while some of the fixes are in -mm already. If I'd base it on -mm I would lose some of the stuff as well. Maybe Pekka can merge the current -mm with his tree? So far I am happy with getting comments from people about the code, so I did not get overly concerned about that.
creator: Glauber Costa
date: 2012-06-18T12:10:22-00:00

Re: [PATCH v4 00/25] kmem limitation for memcg
type: item
description: (2012/06/18 19:27), Glauber Costa wrote: > Hello All, > > This is my new take for the memcg kmem accounting. This should merge > all of the previous comments from you guys, specially concerning the big churn > inside the allocators themselves. > > My focus in this new round was to keep the changes in the cache internals to > a minimum. To do that, I relied upon two main pillars: > > * Cristoph's unification series, that allowed me to put must of the changes > in a common file. Even then, the changes are not too many, since the overal > level of invasiveness was decreased. > * Accounting is done directly from the page allocator. This means some pages > can fail to be accounted, but that can only happen when the task calling > kmem_cache_alloc or kmalloc is not the same task allocating a new page. > This never happens in steady state operation if the tasks are kept in the > same memcg. Naturally, if the page ends up being accounted to a memcg that > is not limited (such as root memcg), that particular page will simply not > be accounted. > > The dispatcher code stays (mem_cgroup_get_kmem_cache), being the mechanism who > guarantees that, during steady state operation, all objects allocated in a page > will belong to the same memcg. I consider this a good compromise point between > strict and loose accounting here. > 2 questions. - Do you have performance numbers ? - Do you think user-memory memcg should be switched to page-allocator level accounting ? (it will require some study for modifying current bached-freeing and per-cpu-stock logics...) Thanks, -Kame
creator: KAMEZAWA Hiroyuki
date: 2012-06-18T12:10:38-00:00

Re: [PATCH v4 00/25] kmem limitation for memcg
type: item
description: On 06/18/2012 04:10 PM, Kamezawa Hiroyuki wrote: > (2012/06/18 19:27), Glauber Costa wrote: >> Hello All, >> >> This is my new take for the memcg kmem accounting. This should merge >> all of the previous comments from you guys, specially concerning the big churn >> inside the allocators themselves. >> >> My focus in this new round was to keep the changes in the cache internals to >> a minimum. To do that, I relied upon two main pillars: >> >> * Cristoph's unification series, that allowed me to put must of the changes >> in a common file. Even then, the changes are not too many, since the overal >> level of invasiveness was decreased. >> * Accounting is done directly from the page allocator. This means some pages >> can fail to be accounted, but that can only happen when the task calling >> kmem_cache_alloc or kmalloc is not the same task allocating a new page. >> This never happens in steady state operation if the tasks are kept in the >> same memcg. Naturally, if the page ends up being accounted to a memcg that >> is not limited (such as root memcg), that particular page will simply not >> be accounted. >> >> The dispatcher code stays (mem_cgroup_get_kmem_cache), being the mechanism who >> guarantees that, during steady state operation, all objects allocated in a page >> will belong to the same memcg. I consider this a good compromise point between >> strict and loose accounting here. >> > > 2 questions. > > - Do you have performance numbers ? Not extensive. I've run some microbenchmarks trying to determine the effect of my code on kmem_cache_alloc, and found it to be in the order of 2 to 3 %. I would expect that to vanish in a workload benchmark. > > - Do you think user-memory memcg should be switched to page-allocator level accounting ? > (it will require some study for modifying current bached-freeing and per-cpu-stock > logics...) I don't see a reason for that. My main goal by doing that was to reduce the churn in the cache internal structures, but specially be…
creator: Glauber Costa
date: 2012-06-18T12:14:35-00:00

Re: [PATCH v4 17/25] skip memcg kmem allocations in specified code regions
type: item
description: (2012/06/18 19:28), Glauber Costa wrote: > This patch creates a mechanism that skip memcg allocations during > certain pieces of our core code. It basically works in the same way > as preempt_disable()/preempt_enable(): By marking a region under > which all allocations will be accounted to the root memcg. > > We need this to prevent races in early cache creation, when we > allocate data using caches that are not necessarily created already. > > Signed-off-by: Glauber Costa<glommer@parallels.com> > CC: Christoph Lameter<cl@linux.com> > CC: Pekka Enberg<penberg@cs.helsinki.fi> > CC: Michal Hocko<mhocko@suse.cz> > CC: Kamezawa Hiroyuki<kamezawa.hiroyu@jp.fujitsu.com> > CC: Johannes Weiner<hannes@cmpxchg.org> > CC: Suleiman Souhlal<suleiman@google.com> I'm ok with this approach. Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
creator: KAMEZAWA Hiroyuki
date: 2012-06-18T12:19:49-00:00

Re: [PATCH v4 19/25] memcg: disable kmem code when not in use.
type: item
description: (2012/06/18 19:28), Glauber Costa wrote: > We can use jump labels to patch the code in or out > when not used. > > Because the assignment: memcg->kmem_accounted = true > is done after the jump labels increment, we guarantee > that the root memcg will always be selected until > all call sites are patched (see mem_cgroup_kmem_enabled). > This guarantees that no mischarges are applied. > > Jump label decrement happens when the last reference > count from the memcg dies. This will only happen when > the caches are all dead. > > Signed-off-by: Glauber Costa<glommer@parallels.com> > CC: Christoph Lameter<cl@linux.com> > CC: Pekka Enberg<penberg@cs.helsinki.fi> > CC: Michal Hocko<mhocko@suse.cz> > CC: Kamezawa Hiroyuki<kamezawa.hiroyu@jp.fujitsu.com> > CC: Johannes Weiner<hannes@cmpxchg.org> > CC: Suleiman Souhlal<suleiman@google.com> > --- > include/linux/memcontrol.h | 5 ++++- > mm/memcontrol.c | 22 +++++++++++++++++++++- > 2 files changed, 25 insertions(+), 2 deletions(-) > > diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h > index 27a3f16..47ccd80 100644 > --- a/include/linux/memcontrol.h > +++ b/include/linux/memcontrol.h > @@ -22,6 +22,7 @@ > #include<linux/cgroup.h> > #include<linux/vm_event_item.h> > #include<linux/hardirq.h> > +#include<linux/jump_label.h> > > struct mem_cgroup; > struct page_cgroup; > @@ -451,7 +452,6 @@ bool __mem_cgroup_new_kmem_page(gfp_t gfp, void *handle, int order); > void __mem_cgroup_commit_kmem_page(struct page *page, void *handle, int order); > void __mem_cgroup_free_kmem_page(struct page *page, int order); > > -#define mem_cgroup_kmem_on 1 > struct kmem_cache * > __mem_cgroup_get_kmem_cache(struct kmem_cache *cachep, gfp_t gfp); > > @@ -459,6 +459,9 @@ static inline bool has_memcg_flag(gfp_t gfp) > { > return gfp& __GFP_SLABMEMCG; > } > + > +extern struct static_key mem_cgroup_kmem_enabled_key; > +#define mem_cgroup_kmem_on static_key_false(&mem_cgroup_kmem_enabled_key) > #else > static inline void mem_cgroup_regist…
creator: KAMEZAWA Hiroyuki
date: 2012-06-18T12:22:14-00:00

Re: [PATCH v4 19/25] memcg: disable kmem code when not in use.
type: item
description: >> >> static void drain_all_stock_async(struct mem_cgroup *memcg); >> @@ -4344,8 +4358,13 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft, >> * >> * But it is not worth the trouble >> */ >> - if (!memcg->kmem_accounted&& val != RESOURCE_MAX) >> + mutex_lock(&set_limit_mutex); >> + if (!memcg->kmem_accounted&& val != RESOURCE_MAX >> + && !memcg->kmem_accounted) { > > I'm sorry why you check the value twice ? > Hi Kame, For no reason, it should be removed. I never noticed this because 1) This is the kind of thing testing will never reveal, and 2), this actually goes away in a later patch (memcg: propagate kmem limiting information to children) In any case, I will update my tree here. Thanks for spotting this
creator: Glauber Costa
date: 2012-06-18T12:26:49-00:00

Re: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
type: item
description: (2012/06/18 19:28), Glauber Costa wrote: > The current memcg slab cache management fails to present satisfatory hierarchical > behavior in the following scenario: > > -> /cgroups/memory/A/B/C > > * kmem limit set at A > * A and B empty taskwise > * bash in C does find / > > Because kmem_accounted is a boolean that was not set for C, no accounting > would be done. This is, however, not what we expect. > Hmm....do we need this new routines even while we have mem_cgroup_iter() ? Doesn't this work ? struct mem_cgroup { ..... bool kmem_accounted_this; atomic_t kmem_accounted; .... } at set limit ....set_limit(memcg) { if (newly accounted) { mem_cgroup_iter() { atomic_inc(&iter->kmem_accounted) } } else { mem_cgroup_iter() { atomic_dec(&iter->kmem_accounted); } } hm ? Then, you can see kmem is accounted or not by atomic_read(&memcg->kmem_accounted); Thanks, -Kame
creator: KAMEZAWA Hiroyuki
date: 2012-06-18T12:37:01-00:00

Re: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
type: item
description: On 06/18/2012 04:37 PM, Kamezawa Hiroyuki wrote: > (2012/06/18 19:28), Glauber Costa wrote: >> The current memcg slab cache management fails to present satisfatory hierarchical >> behavior in the following scenario: >> >> -> /cgroups/memory/A/B/C >> >> * kmem limit set at A >> * A and B empty taskwise >> * bash in C does find / >> >> Because kmem_accounted is a boolean that was not set for C, no accounting >> would be done. This is, however, not what we expect. >> > > Hmm....do we need this new routines even while we have mem_cgroup_iter() ? > > Doesn't this work ? > > struct mem_cgroup { > ..... > bool kmem_accounted_this; > atomic_t kmem_accounted; > .... > } > > at set limit > > ....set_limit(memcg) { > > if (newly accounted) { > mem_cgroup_iter() { > atomic_inc(&iter->kmem_accounted) > } > } else { > mem_cgroup_iter() { > atomic_dec(&iter->kmem_accounted); > } > } > > > hm ? Then, you can see kmem is accounted or not by atomic_read(&memcg->kmem_accounted); > Accounted by itself / parent is still useful, and I see no reason to use an atomic + bool if we can use a pair of bits. As for the routine, I guess mem_cgroup_iter will work... It does a lot more than I need, but for the sake of using what's already in there, I can switch to it with no problems.
creator: Glauber Costa
date: 2012-06-18T12:43:39-00:00

Re: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
type: item
description: (2012/06/18 21:10), Glauber Costa wrote: > On 06/18/2012 04:07 PM, Kamezawa Hiroyuki wrote: >> (2012/06/18 19:27), Glauber Costa wrote: >>> Right now we free struct memcg with kfree right after a >>> rcu grace period, but defer it if we need to use vfree() to get >>> rid of that memory area. We do that by need, because we need vfree >>> to be called in a process context. >>> >>> This patch unifies this behavior, by ensuring that even kfree will >>> happen in a separate thread. The goal is to have a stable place to >>> call the upcoming jump label destruction function outside the realm >>> of the complicated and quite far-reaching cgroup lock (that can't be >>> held when calling neither the cpu_hotplug.lock nor the jump_label_mutex) >>> >>> Signed-off-by: Glauber Costa<glommer@parallels.com> >>> CC: Tejun Heo<tj@kernel.org> >>> CC: Li Zefan<lizefan@huawei.com> >>> CC: Kamezawa Hiroyuki<kamezawa.hiroyu@jp.fujitsu.com> >>> CC: Johannes Weiner<hannes@cmpxchg.org> >>> CC: Michal Hocko<mhocko@suse.cz> >> >> How about cut out this patch and merge first as simple cleanu up and >> to reduce patch stack on your side ? >> >> Acked-by: KAMEZAWA Hiroyuki<kamezawa.hiroyu@jp.fujitsu.com> > > I believe this is already in the -mm tree (from the sock memcg fixes) > > But actually, my main trouble with this series here, is that I am basing > it on Pekka's tree, while some of the fixes are in -mm already. > If I'd base it on -mm I would lose some of the stuff as well. > > Maybe Pekka can merge the current -mm with his tree? > > So far I am happy with getting comments from people about the code, so I > did not get overly concerned about that. > Sure. thank you. -Kame
creator: KAMEZAWA Hiroyuki
date: 2012-06-19T00:11:20-00:00

Re: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
type: item
description: (2012/06/18 21:43), Glauber Costa wrote: > On 06/18/2012 04:37 PM, Kamezawa Hiroyuki wrote: >> (2012/06/18 19:28), Glauber Costa wrote: >>> The current memcg slab cache management fails to present satisfatory hierarchical >>> behavior in the following scenario: >>> >>> -> /cgroups/memory/A/B/C >>> >>> * kmem limit set at A >>> * A and B empty taskwise >>> * bash in C does find / >>> >>> Because kmem_accounted is a boolean that was not set for C, no accounting >>> would be done. This is, however, not what we expect. >>> >> >> Hmm....do we need this new routines even while we have mem_cgroup_iter() ? >> >> Doesn't this work ? >> >> struct mem_cgroup { >> ..... >> bool kmem_accounted_this; >> atomic_t kmem_accounted; >> .... >> } >> >> at set limit >> >> ....set_limit(memcg) { >> >> if (newly accounted) { >> mem_cgroup_iter() { >> atomic_inc(&iter->kmem_accounted) >> } >> } else { >> mem_cgroup_iter() { >> atomic_dec(&iter->kmem_accounted); >> } >> } >> >> >> hm ? Then, you can see kmem is accounted or not by atomic_read(&memcg->kmem_accounted); >> > > Accounted by itself / parent is still useful, and I see no reason to use > an atomic + bool if we can use a pair of bits. > > As for the routine, I guess mem_cgroup_iter will work... It does a lot > more than I need, but for the sake of using what's already in there, I > can switch to it with no problems. > Hmm. please start from reusing existing routines. If it's not enough, some enhancement for generic cgroup will be welcomed rather than completely new one only for memcg. Thanks, -Kame
creator: KAMEZAWA Hiroyuki
date: 2012-06-19T00:16:20-00:00

Re: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
type: item
description: On 06/19/2012 04:16 AM, Kamezawa Hiroyuki wrote: > (2012/06/18 21:43), Glauber Costa wrote: >> On 06/18/2012 04:37 PM, Kamezawa Hiroyuki wrote: >>> (2012/06/18 19:28), Glauber Costa wrote: >>>> The current memcg slab cache management fails to present satisfatory hierarchical >>>> behavior in the following scenario: >>>> >>>> -> /cgroups/memory/A/B/C >>>> >>>> * kmem limit set at A >>>> * A and B empty taskwise >>>> * bash in C does find / >>>> >>>> Because kmem_accounted is a boolean that was not set for C, no accounting >>>> would be done. This is, however, not what we expect. >>>> >>> >>> Hmm....do we need this new routines even while we have mem_cgroup_iter() ? >>> >>> Doesn't this work ? >>> >>> struct mem_cgroup { >>> ..... >>> bool kmem_accounted_this; >>> atomic_t kmem_accounted; >>> .... >>> } >>> >>> at set limit >>> >>> ....set_limit(memcg) { >>> >>> if (newly accounted) { >>> mem_cgroup_iter() { >>> atomic_inc(&iter->kmem_accounted) >>> } >>> } else { >>> mem_cgroup_iter() { >>> atomic_dec(&iter->kmem_accounted); >>> } >>> } >>> >>> >>> hm ? Then, you can see kmem is accounted or not by atomic_read(&memcg->kmem_accounted); >>> >> >> Accounted by itself / parent is still useful, and I see no reason to use >> an atomic + bool if we can use a pair of bits. >> >> As for the routine, I guess mem_cgroup_iter will work... It does a lot >> more than I need, but for the sake of using what's already in there, I >> can switch to it with no problems. >> > > Hmm. please start from reusing existing routines. > If it's not enough, some enhancement for generic cgroup will be welcomed > rather than completely new one only for memcg. > And now that I am trying to adapt the code to the new function, I remember clearly why I done this way. Sorry for my failed memory. That has to do with the order of the walk. I need to enforce hierarchy, which means whenever a cgroup has !use_hierarchy, I need to cut out that branch, but continue scanning the tree for other branches. That is…
creator: Glauber Costa
date: 2012-06-19T08:35:05-00:00

Re: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
type: item
description: On 06/19/2012 12:35 PM, Glauber Costa wrote: > On 06/19/2012 04:16 AM, Kamezawa Hiroyuki wrote: >> (2012/06/18 21:43), Glauber Costa wrote: >>> On 06/18/2012 04:37 PM, Kamezawa Hiroyuki wrote: >>>> (2012/06/18 19:28), Glauber Costa wrote: >>>>> The current memcg slab cache management fails to present satisfatory hierarchical >>>>> behavior in the following scenario: >>>>> >>>>> -> /cgroups/memory/A/B/C >>>>> >>>>> * kmem limit set at A >>>>> * A and B empty taskwise >>>>> * bash in C does find / >>>>> >>>>> Because kmem_accounted is a boolean that was not set for C, no accounting >>>>> would be done. This is, however, not what we expect. >>>>> >>>> >>>> Hmm....do we need this new routines even while we have mem_cgroup_iter() ? >>>> >>>> Doesn't this work ? >>>> >>>> struct mem_cgroup { >>>> ..... >>>> bool kmem_accounted_this; >>>> atomic_t kmem_accounted; >>>> .... >>>> } >>>> >>>> at set limit >>>> >>>> ....set_limit(memcg) { >>>> >>>> if (newly accounted) { >>>> mem_cgroup_iter() { >>>> atomic_inc(&iter->kmem_accounted) >>>> } >>>> } else { >>>> mem_cgroup_iter() { >>>> atomic_dec(&iter->kmem_accounted); >>>> } >>>> } >>>> >>>> >>>> hm ? Then, you can see kmem is accounted or not by atomic_read(&memcg->kmem_accounted); >>>> >>> >>> Accounted by itself / parent is still useful, and I see no reason to use >>> an atomic + bool if we can use a pair of bits. >>> >>> As for the routine, I guess mem_cgroup_iter will work... It does a lot >>> more than I need, but for the sake of using what's already in there, I >>> can switch to it with no problems. >>> >> >> Hmm. please start from reusing existing routines. >> If it's not enough, some enhancement for generic cgroup will be welcomed >> rather than completely new one only for memcg. >> > > And now that I am trying to adapt the code to the new function, I > remember clearly why I done this way. Sorry for my failed memory. > > That has to do with the order of the walk. I need to enforce hierarchy, > which means whenever a …
creator: Glauber Costa
date: 2012-06-19T08:54:35-00:00

Re: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
type: item
description: On Mon, 18 Jun 2012, Glauber Costa wrote: > I believe this is already in the -mm tree (from the sock memcg fixes) > > But actually, my main trouble with this series here, is that I am basing > it on Pekka's tree, while some of the fixes are in -mm already. > If I'd base it on -mm I would lose some of the stuff as well. > > Maybe Pekka can merge the current -mm with his tree? I first want to have a stable base from Christoph's "common slab" series before I am comfortable with going forward with the memcg parts. Feel free to push forward any preparational patches to the slab allocators, though. Pekka
creator: Pekka Enberg
date: 2012-06-20T07:32:50-00:00

Re: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
type: item
description: On 06/20/2012 11:32 AM, Pekka Enberg wrote: >> >Maybe Pekka can merge the current -mm with his tree? > I first want to have a stable base from Christoph's "common slab" series > before I am comfortable with going forward with the memcg parts. > > Feel free to push forward any preparational patches to the slab > allocators, though. > > Pekka Kame and others: If you are already comfortable with the general shape of the series, it would do me good to do the same with the memcg preparation patches, so we have less code to review and merge in the next window. They are: memcg: Make it possible to use the stock for more than one page. memcg: Reclaim when more than one page needed. memcg: change defines to an enum Do you see any value in merging them now ?
creator: Glauber Costa
date: 2012-06-20T08:40:11-00:00

Re: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
type: item
description: On 06/19/2012 12:54 PM, Glauber Costa wrote: > On 06/19/2012 12:35 PM, Glauber Costa wrote: >> On 06/19/2012 04:16 AM, Kamezawa Hiroyuki wrote: >>> (2012/06/18 21:43), Glauber Costa wrote: >>>> On 06/18/2012 04:37 PM, Kamezawa Hiroyuki wrote: >>>>> (2012/06/18 19:28), Glauber Costa wrote: >>>>>> The current memcg slab cache management fails to present satisfatory hierarchical >>>>>> behavior in the following scenario: >>>>>> >>>>>> -> /cgroups/memory/A/B/C >>>>>> >>>>>> * kmem limit set at A >>>>>> * A and B empty taskwise >>>>>> * bash in C does find / >>>>>> >>>>>> Because kmem_accounted is a boolean that was not set for C, no accounting >>>>>> would be done. This is, however, not what we expect. >>>>>> >>>>> >>>>> Hmm....do we need this new routines even while we have mem_cgroup_iter() ? >>>>> >>>>> Doesn't this work ? >>>>> >>>>> struct mem_cgroup { >>>>> ..... >>>>> bool kmem_accounted_this; >>>>> atomic_t kmem_accounted; >>>>> .... >>>>> } >>>>> >>>>> at set limit >>>>> >>>>> ....set_limit(memcg) { >>>>> >>>>> if (newly accounted) { >>>>> mem_cgroup_iter() { >>>>> atomic_inc(&iter->kmem_accounted) >>>>> } >>>>> } else { >>>>> mem_cgroup_iter() { >>>>> atomic_dec(&iter->kmem_accounted); >>>>> } >>>>> } >>>>> >>>>> >>>>> hm ? Then, you can see kmem is accounted or not by atomic_read(&memcg->kmem_accounted); >>>>> >>>> >>>> Accounted by itself / parent is still useful, and I see no reason to use >>>> an atomic + bool if we can use a pair of bits. >>>> >>>> As for the routine, I guess mem_cgroup_iter will work... It does a lot >>>> more than I need, but for the sake of using what's already in there, I >>>> can switch to it with no problems. >>>> >>> >>> Hmm. please start from reusing existing routines. >>> If it's not enough, some enhancement for generic cgroup will be welcomed >>> rather than completely new one only for memcg. >>> >> >> And now that I am trying to adapt the code to the new function, I >> remember clearly why I done this way. Sorry for my failed m…
creator: Glauber Costa
date: 2012-06-20T08:59:46-00:00

Re: [PATCH v4 08/25] memcg: change defines to an enum
type: item
description: [Sorry for late reply. I am aware of the series, I am just too busy to give it serious time needed for review. It doesn't make much sense to delay these preparational pieces so...] On Mon 18-06-12 14:28:01, Glauber Costa wrote: > This is just a cleanup patch for clarity of expression. > In earlier submissions, people asked it to be in a separate > patch, so here it is. > > Signed-off-by: Glauber Costa <glommer@parallels.com> > CC: Michal Hocko <mhocko@suse.cz> > CC: Johannes Weiner <hannes@cmpxchg.org> > Acked-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: Michal Hocko <mhocko@suse.cz> > --- > mm/memcontrol.c | 9 ++++++--- > 1 file changed, 6 insertions(+), 3 deletions(-) > > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index b6cb075..cc1fdb4 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -374,9 +374,12 @@ enum charge_type { > }; > > /* for encoding cft->private value on file */ > -#define _MEM (0) > -#define _MEMSWAP (1) > -#define _OOM_TYPE (2) > +enum res_type { > + _MEM, > + _MEMSWAP, > + _OOM_TYPE, > +}; > + > #define MEMFILE_PRIVATE(x, val) (((x) << 16) | (val)) > #define MEMFILE_TYPE(val) (((val) >> 16) & 0xffff) > #define MEMFILE_ATTR(val) ((val) & 0xffff) > -- > 1.7.10.2 > > -- > To unsubscribe, send a message with 'unsubscribe linux-mm' in > the body to majordomo@kvack.org. For more info on Linux MM, > see: http://www.linux-mm.org/ . > Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org -- Michal Hocko SUSE Labs SUSE LINUX s.r.o. Lihovarska 1060/12 190 00 Praha 9 Czech Republic
creator: Michal Hocko
date: 2012-06-20T13:13:22-00:00

Re: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
type: item
description: On Mon 18-06-12 14:27:58, Glauber Costa wrote: > Right now we free struct memcg with kfree right after a > rcu grace period, but defer it if we need to use vfree() to get > rid of that memory area. We do that by need, because we need vfree > to be called in a process context. > > This patch unifies this behavior, by ensuring that even kfree will > happen in a separate thread. The goal is to have a stable place to > call the upcoming jump label destruction function outside the realm > of the complicated and quite far-reaching cgroup lock (that can't be > held when calling neither the cpu_hotplug.lock nor the jump_label_mutex) This one is in memcg-devel (mmotm) tree for quite some time with acks from me and Kamezawa. > Signed-off-by: Glauber Costa <glommer@parallels.com> > CC: Tejun Heo <tj@kernel.org> > CC: Li Zefan <lizefan@huawei.com> > CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> > CC: Johannes Weiner <hannes@cmpxchg.org> > CC: Michal Hocko <mhocko@suse.cz> > --- > mm/memcontrol.c | 24 +++++++++++++----------- > 1 file changed, 13 insertions(+), 11 deletions(-) > > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index e3b528e..ce15be4 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -245,8 +245,8 @@ struct mem_cgroup { > */ > struct rcu_head rcu_freeing; > /* > - * But when using vfree(), that cannot be done at > - * interrupt time, so we must then queue the work. > + * We also need some space for a worker in deferred freeing. > + * By the time we call it, rcu_freeing is not longer in use. > */ > struct work_struct work_freeing; > }; > @@ -4826,23 +4826,28 @@ out_free: > } > > /* > - * Helpers for freeing a vzalloc()ed mem_cgroup by RCU, > + * Helpers for freeing a kmalloc()ed/vzalloc()ed mem_cgroup by RCU, > * but in process context. The work_freeing structure is overlaid > * on the rcu_freeing structure, which itself is overlaid on memsw. > */ > -static void vfree_work(struct work_struct *work) > +static void free_work(struct work_struct *w…
creator: Michal Hocko
date: 2012-06-20T13:20:50-00:00

Re: [PATCH v4 06/25] memcg: Make it possible to use the stock for more than one page.
type: item
description: On Mon 18-06-12 14:27:59, Glauber Costa wrote: > From: Suleiman Souhlal <ssouhlal@FreeBSD.org> > > Signed-off-by: Suleiman Souhlal <suleiman@google.com> > Signed-off-by: Glauber Costa <glommer@parallels.com> > Acked-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> I am not sure the patch is good to merge on its own without the rest. One comment bellow. > --- > mm/memcontrol.c | 18 +++++++++--------- > 1 file changed, 9 insertions(+), 9 deletions(-) > > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index ce15be4..00b9f1e 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -1998,19 +1998,19 @@ static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock); > static DEFINE_MUTEX(percpu_charge_mutex); > > /* > - * Try to consume stocked charge on this cpu. If success, one page is consumed > - * from local stock and true is returned. If the stock is 0 or charges from a > - * cgroup which is not current target, returns false. This stock will be > - * refilled. > + * Try to consume stocked charge on this cpu. If success, nr_pages pages are > + * consumed from local stock and true is returned. If the stock is 0 or > + * charges from a cgroup which is not current target, returns false. > + * This stock will be refilled. > */ > -static bool consume_stock(struct mem_cgroup *memcg) > +static bool consume_stock(struct mem_cgroup *memcg, int nr_pages) > { > struct memcg_stock_pcp *stock; > bool ret = true; I guess you want: if (nr_pages > CHARGE_BATCH) return false; because you don't want to try to use stock for THP pages. > > stock = &get_cpu_var(memcg_stock); > - if (memcg == stock->cached && stock->nr_pages) > - stock->nr_pages--; > + if (memcg == stock->cached && stock->nr_pages >= nr_pages) > + stock->nr_pages -= nr_pages; > else /* need to call res_counter_charge */ > ret = false; > put_cpu_var(memcg_stock); > @@ -2309,7 +2309,7 @@ again: > VM_BUG_ON(css_is_removed(&memcg->css)); > if (mem_cgroup_is_root(memcg)) > goto done; > - if (nr_pages == 1 && consume_sto…
creator: Michal Hocko
date: 2012-06-20T13:28:04-00:00

Re: [PATCH v4 07/25] memcg: Reclaim when more than one page needed.
type: item
description: On Mon 18-06-12 14:28:00, Glauber Costa wrote: > From: Suleiman Souhlal <ssouhlal@FreeBSD.org> > > mem_cgroup_do_charge() was written before slab accounting, and expects > three cases: being called for 1 page, being called for a stock of 32 pages, > or being called for a hugepage. If we call for 2 or 3 pages (and several > slabs used in process creation are such, at least with the debug options I > had), it assumed it's being called for stock and just retried without reclaiming. > > Fix that by passing down a minsize argument in addition to the csize. > > And what to do about that (csize == PAGE_SIZE && ret) retry? If it's > needed at all (and presumably is since it's there, perhaps to handle > races), then it should be extended to more than PAGE_SIZE, yet how far? > And should there be a retry count limit, of what? For now retry up to > COSTLY_ORDER (as page_alloc.c does), stay safe with a cond_resched(), > and make sure not to do it if __GFP_NORETRY. > > [v4: fixed nr pages calculation pointed out by Christoph Lameter ] > > Signed-off-by: Suleiman Souhlal <suleiman@google.com> > Signed-off-by: Glauber Costa <glommer@parallels.com> > Reviewed-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> I think this is not ready to be merged yet. Two comments below. [...] > @@ -2210,18 +2211,18 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, > } else > mem_over_limit = mem_cgroup_from_res_counter(fail_res, res); > /* > - * nr_pages can be either a huge page (HPAGE_PMD_NR), a batch > - * of regular pages (CHARGE_BATCH), or a single regular page (1). > - * > * Never reclaim on behalf of optional batching, retry with a > * single page instead. > */ > - if (nr_pages == CHARGE_BATCH) > + if (nr_pages > min_pages) > return CHARGE_RETRY; > > if (!(gfp_mask & __GFP_WAIT)) > return CHARGE_WOULDBLOCK; > > + if (gfp_mask & __GFP_NORETRY) > + return CHARGE_NOMEM; This is kmem specific and should be preparated out in case this should be merged before the r…
creator: Michal Hocko
date: 2012-06-20T13:47:38-00:00

Re: [PATCH v4 06/25] memcg: Make it possible to use the stock for more than one page.
type: item
description: On 06/20/2012 05:28 PM, Michal Hocko wrote: > On Mon 18-06-12 14:27:59, Glauber Costa wrote: >> From: Suleiman Souhlal <ssouhlal@FreeBSD.org> >> >> Signed-off-by: Suleiman Souhlal <suleiman@google.com> >> Signed-off-by: Glauber Costa <glommer@parallels.com> >> Acked-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> > > I am not sure the patch is good to merge on its own without the rest. > One comment bellow. > >> --- >> mm/memcontrol.c | 18 +++++++++--------- >> 1 file changed, 9 insertions(+), 9 deletions(-) >> >> diff --git a/mm/memcontrol.c b/mm/memcontrol.c >> index ce15be4..00b9f1e 100644 >> --- a/mm/memcontrol.c >> +++ b/mm/memcontrol.c >> @@ -1998,19 +1998,19 @@ static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock); >> static DEFINE_MUTEX(percpu_charge_mutex); >> >> /* >> - * Try to consume stocked charge on this cpu. If success, one page is consumed >> - * from local stock and true is returned. If the stock is 0 or charges from a >> - * cgroup which is not current target, returns false. This stock will be >> - * refilled. >> + * Try to consume stocked charge on this cpu. If success, nr_pages pages are >> + * consumed from local stock and true is returned. If the stock is 0 or >> + * charges from a cgroup which is not current target, returns false. >> + * This stock will be refilled. >> */ >> -static bool consume_stock(struct mem_cgroup *memcg) >> +static bool consume_stock(struct mem_cgroup *memcg, int nr_pages) >> { >> struct memcg_stock_pcp *stock; >> bool ret = true; > > I guess you want: > if (nr_pages > CHARGE_BATCH) > return false; > > because you don't want to try to use stock for THP pages. The code reads: + if (memcg == stock->cached && stock->nr_pages >= nr_pages) + stock->nr_pages -= nr_pages; Isn't stock->nr_pages always <= CHARGE_BATCH by definition?
creator: Glauber Costa
date: 2012-06-20T19:36:47-00:00

Re: [PATCH v4 07/25] memcg: Reclaim when more than one page needed.
type: item
description: On 06/20/2012 05:47 PM, Michal Hocko wrote: > On Mon 18-06-12 14:28:00, Glauber Costa wrote: >> From: Suleiman Souhlal <ssouhlal@FreeBSD.org> >> >> mem_cgroup_do_charge() was written before slab accounting, and expects >> three cases: being called for 1 page, being called for a stock of 32 pages, >> or being called for a hugepage. If we call for 2 or 3 pages (and several >> slabs used in process creation are such, at least with the debug options I >> had), it assumed it's being called for stock and just retried without reclaiming. >> >> Fix that by passing down a minsize argument in addition to the csize. >> >> And what to do about that (csize == PAGE_SIZE && ret) retry? If it's >> needed at all (and presumably is since it's there, perhaps to handle >> races), then it should be extended to more than PAGE_SIZE, yet how far? >> And should there be a retry count limit, of what? For now retry up to >> COSTLY_ORDER (as page_alloc.c does), stay safe with a cond_resched(), >> and make sure not to do it if __GFP_NORETRY. >> >> [v4: fixed nr pages calculation pointed out by Christoph Lameter ] >> >> Signed-off-by: Suleiman Souhlal <suleiman@google.com> >> Signed-off-by: Glauber Costa <glommer@parallels.com> >> Reviewed-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> > > I think this is not ready to be merged yet. Fair Enough > Two comments below. > > [...] >> @@ -2210,18 +2211,18 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, >> } else >> mem_over_limit = mem_cgroup_from_res_counter(fail_res, res); >> /* >> - * nr_pages can be either a huge page (HPAGE_PMD_NR), a batch >> - * of regular pages (CHARGE_BATCH), or a single regular page (1). >> - * >> * Never reclaim on behalf of optional batching, retry with a >> * single page instead. >> */ >> - if (nr_pages == CHARGE_BATCH) >> + if (nr_pages > min_pages) >> return CHARGE_RETRY; >> >> if (!(gfp_mask & __GFP_WAIT)) >> return CHARGE_WOULDBLOCK; >> >> + if (gfp_mask & __GFP_NORETRY) >> + retur…
creator: Glauber Costa
date: 2012-06-20T19:43:52-00:00

Re: [PATCH v4 05/25] memcg: Always free struct memcg through schedule_work()
type: item
description: (2012/06/20 17:40), Glauber Costa wrote: > On 06/20/2012 11:32 AM, Pekka Enberg wrote: >>> >Maybe Pekka can merge the current -mm with his tree? >> I first want to have a stable base from Christoph's "common slab" series >> before I am comfortable with going forward with the memcg parts. >> >> Feel free to push forward any preparational patches to the slab >> allocators, though. >> >> Pekka > > Kame and others: > > If you are already comfortable with the general shape of the series, it would do me good to do the same with the memcg preparation patches, so we have less code to review and merge in the next window. > > They are: > > memcg: Make it possible to use the stock for more than one page. > memcg: Reclaim when more than one page needed. > memcg: change defines to an enum > > Do you see any value in merging them now ? > I'll be okay with the 3 patches for memcg. Thanks, -Kame
creator: KAMEZAWA Hiroyuki
date: 2012-06-21T11:39:14-00:00

Re: [PATCH v4 06/25] memcg: Make it possible to use the stock for more than one page.
type: item
description: On Wed 20-06-12 23:36:47, Glauber Costa wrote: > On 06/20/2012 05:28 PM, Michal Hocko wrote: > >On Mon 18-06-12 14:27:59, Glauber Costa wrote: > >>From: Suleiman Souhlal <ssouhlal@FreeBSD.org> > >> > >>Signed-off-by: Suleiman Souhlal <suleiman@google.com> > >>Signed-off-by: Glauber Costa <glommer@parallels.com> > >>Acked-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> > > > >I am not sure the patch is good to merge on its own without the rest. > >One comment bellow. > > > >>--- > >> mm/memcontrol.c | 18 +++++++++--------- > >> 1 file changed, 9 insertions(+), 9 deletions(-) > >> > >>diff --git a/mm/memcontrol.c b/mm/memcontrol.c > >>index ce15be4..00b9f1e 100644 > >>--- a/mm/memcontrol.c > >>+++ b/mm/memcontrol.c > >>@@ -1998,19 +1998,19 @@ static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock); > >> static DEFINE_MUTEX(percpu_charge_mutex); > >> > >> /* > >>- * Try to consume stocked charge on this cpu. If success, one page is consumed > >>- * from local stock and true is returned. If the stock is 0 or charges from a > >>- * cgroup which is not current target, returns false. This stock will be > >>- * refilled. > >>+ * Try to consume stocked charge on this cpu. If success, nr_pages pages are > >>+ * consumed from local stock and true is returned. If the stock is 0 or > >>+ * charges from a cgroup which is not current target, returns false. > >>+ * This stock will be refilled. > >> */ > >>-static bool consume_stock(struct mem_cgroup *memcg) > >>+static bool consume_stock(struct mem_cgroup *memcg, int nr_pages) > >> { > >> struct memcg_stock_pcp *stock; > >> bool ret = true; > > > >I guess you want: > > if (nr_pages > CHARGE_BATCH) > > return false; > > > >because you don't want to try to use stock for THP pages. > > > The code reads: > > + if (memcg == stock->cached && stock->nr_pages >= nr_pages) > + stock->nr_pages -= nr_pages; > > Isn't stock->nr_pages always <= CHARGE_BATCH by definition? Yes it is, but why to disable preemption if we know this has no…
creator: Michal Hocko
date: 2012-06-21T21:14:52-00:00

Re: [PATCH v4 07/25] memcg: Reclaim when more than one page needed.
type: item
description: On Wed 20-06-12 23:43:52, Glauber Costa wrote: > On 06/20/2012 05:47 PM, Michal Hocko wrote: > >On Mon 18-06-12 14:28:00, Glauber Costa wrote: > >>From: Suleiman Souhlal <ssouhlal@FreeBSD.org> > >> > >>mem_cgroup_do_charge() was written before slab accounting, and expects > >>three cases: being called for 1 page, being called for a stock of 32 pages, > >>or being called for a hugepage. If we call for 2 or 3 pages (and several > >>slabs used in process creation are such, at least with the debug options I > >>had), it assumed it's being called for stock and just retried without reclaiming. > >> > >>Fix that by passing down a minsize argument in addition to the csize. > >> > >>And what to do about that (csize == PAGE_SIZE && ret) retry? If it's > >>needed at all (and presumably is since it's there, perhaps to handle > >>races), then it should be extended to more than PAGE_SIZE, yet how far? > >>And should there be a retry count limit, of what? For now retry up to > >>COSTLY_ORDER (as page_alloc.c does), stay safe with a cond_resched(), > >>and make sure not to do it if __GFP_NORETRY. > >> > >>[v4: fixed nr pages calculation pointed out by Christoph Lameter ] > >> > >>Signed-off-by: Suleiman Souhlal <suleiman@google.com> > >>Signed-off-by: Glauber Costa <glommer@parallels.com> > >>Reviewed-by: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> > > > >I think this is not ready to be merged yet. > Fair Enough > > >Two comments below. > > > >[...] > >>@@ -2210,18 +2211,18 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, > >> } else > >> mem_over_limit = mem_cgroup_from_res_counter(fail_res, res); > >> /* > >>- * nr_pages can be either a huge page (HPAGE_PMD_NR), a batch > >>- * of regular pages (CHARGE_BATCH), or a single regular page (1). > >>- * > >> * Never reclaim on behalf of optional batching, retry with a > >> * single page instead. > >> */ > >>- if (nr_pages == CHARGE_BATCH) > >>+ if (nr_pages > min_pages) > >> return CHARGE_RETRY; > >> …
creator: Michal Hocko
date: 2012-06-21T21:19:23-00:00

Re: [PATCH v4 23/25] memcg: propagate kmem limiting information to children
type: item
description: (2012/06/20 17:59), Glauber Costa wrote: > On 06/19/2012 12:54 PM, Glauber Costa wrote: >> On 06/19/2012 12:35 PM, Glauber Costa wrote: >>> On 06/19/2012 04:16 AM, Kamezawa Hiroyuki wrote: >>>> (2012/06/18 21:43), Glauber Costa wrote: >>>>> On 06/18/2012 04:37 PM, Kamezawa Hiroyuki wrote: >>>>>> (2012/06/18 19:28), Glauber Costa wrote: >>>>>>> The current memcg slab cache management fails to present satisfatory hierarchical >>>>>>> behavior in the following scenario: >>>>>>> >>>>>>> -> /cgroups/memory/A/B/C >>>>>>> >>>>>>> * kmem limit set at A >>>>>>> * A and B empty taskwise >>>>>>> * bash in C does find / >>>>>>> >>>>>>> Because kmem_accounted is a boolean that was not set for C, no accounting >>>>>>> would be done. This is, however, not what we expect. >>>>>>> >>>>>> >>>>>> Hmm....do we need this new routines even while we have mem_cgroup_iter() ? >>>>>> >>>>>> Doesn't this work ? >>>>>> >>>>>> struct mem_cgroup { >>>>>> ..... >>>>>> bool kmem_accounted_this; >>>>>> atomic_t kmem_accounted; >>>>>> .... >>>>>> } >>>>>> >>>>>> at set limit >>>>>> >>>>>> ....set_limit(memcg) { >>>>>> >>>>>> if (newly accounted) { >>>>>> mem_cgroup_iter() { >>>>>> atomic_inc(&iter->kmem_accounted) >>>>>> } >>>>>> } else { >>>>>> mem_cgroup_iter() { >>>>>> atomic_dec(&iter->kmem_accounted); >>>>>> } >>>>>> } >>>>>> >>>>>> >>>>>> hm ? Then, you can see kmem is accounted or not by atomic_read(&memcg->kmem_accounted); >>>>>> >>>>> >>>>> Accounted by itself / parent is still useful, and I see no reason to use >>>>> an atomic + bool if we can use a pair of bits. >>>>> >>>>> As for the routine, I guess mem_cgroup_iter will work... It does a lot >>>>> more than I need, but for the sake of using what's already in there, I >>>>> can switch to it with no problems. >>>>> >>>> >>>> Hmm. please start from reusing existing routines. >>>> If it's not enough, some enhancement for generic cgroup will be welcomed >>>> rather than completely new one only for memcg. >>>> >>> >>> And now that I am trying…
creator: KAMEZAWA Hiroyuki
date: 2012-06-23T04:19:37-00:00

Re: [PATCH v4 06/25] memcg: Make it possible to use the stock for more than one page.
type: item
description: On 06/20/2012 05:28 PM, Michal Hocko wrote: > I guess you want: > if (nr_pages > CHARGE_BATCH) > return false; > > because you don't want to try to use stock for THP pages. Done, thanks.
creator: Glauber Costa
date: 2012-06-25T13:03:04-00:00

Re: [PATCH v4 07/25] memcg: Reclaim when more than one page needed.
type: item
description: >>>> + >>>> ret = mem_cgroup_reclaim(mem_over_limit, gfp_mask, flags); >>>> if (mem_cgroup_margin(mem_over_limit) >= nr_pages) >>>> return CHARGE_RETRY; >>>> @@ -2234,8 +2235,10 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, >>>> * unlikely to succeed so close to the limit, and we fall back >>>> * to regular pages anyway in case of failure. >>>> */ >>>> - if (nr_pages == 1 && ret) >>>> + if (nr_pages <= (1 << PAGE_ALLOC_COSTLY_ORDER) && ret) { >>>> + cond_resched(); >>>> return CHARGE_RETRY; >>>> + } >>> >>> What prevents us from looping for unbounded amount of time here? >>> Maybe you need to consider the number of reclaimed pages here. >> >> Why would we even loop here? It will just return CHARGE_RETRY, it is >> up to the caller to decide whether or not it will retry. > > Yes, but the test was original to prevent oom when we managed to reclaim > something. And something might be enough for a single page but now you > have high order allocations so we can retry without any success. > So, Most of the kmem allocations are likely to be quite small as well. For the slab, we're dealing with the order of 2-3 pages, and for other allocations that may happen, like stack, they will be in the order of 2 pages as well. So one thing I could do here, is define a threshold, say, 3, and only retry for that very low threshold, instead of following COSTLY_ORDER. I don't expect two or three pages to be much less likely to be freed than a single page. I am fine with ripping of the cond_resched as well. Let me know if you would be okay with that.
creator: Glauber Costa
date: 2012-06-25T13:13:53-00:00

Re: [PATCH v4 07/25] memcg: Reclaim when more than one page needed.
type: item
description: On 06/25/2012 05:13 PM, Glauber Costa wrote: > >>>>> + >>>>> ret = mem_cgroup_reclaim(mem_over_limit, gfp_mask, flags); >>>>> if (mem_cgroup_margin(mem_over_limit) >= nr_pages) >>>>> return CHARGE_RETRY; >>>>> @@ -2234,8 +2235,10 @@ static int mem_cgroup_do_charge(struct >>>>> mem_cgroup *memcg, gfp_t gfp_mask, >>>>> * unlikely to succeed so close to the limit, and we fall back >>>>> * to regular pages anyway in case of failure. >>>>> */ >>>>> - if (nr_pages == 1 && ret) >>>>> + if (nr_pages <= (1 << PAGE_ALLOC_COSTLY_ORDER) && ret) { >>>>> + cond_resched(); >>>>> return CHARGE_RETRY; >>>>> + } >>>> >>>> What prevents us from looping for unbounded amount of time here? >>>> Maybe you need to consider the number of reclaimed pages here. >>> >>> Why would we even loop here? It will just return CHARGE_RETRY, it is >>> up to the caller to decide whether or not it will retry. >> >> Yes, but the test was original to prevent oom when we managed to reclaim >> something. And something might be enough for a single page but now you >> have high order allocations so we can retry without any success. >> > > So, > > Most of the kmem allocations are likely to be quite small as well. For > the slab, we're dealing with the order of 2-3 pages, and for other > allocations that may happen, like stack, they will be in the order of 2 > pages as well. > > So one thing I could do here, is define a threshold, say, 3, and only > retry for that very low threshold, instead of following COSTLY_ORDER. > I don't expect two or three pages to be much less likely to be freed > than a single page. > > I am fine with ripping of the cond_resched as well. > > Let me know if you would be okay with that. > > For the record, here's the patch I would propose. At this point, I think it would be nice to Suleiman to say if he is still okay with the changes.
creator: Glauber Costa
date: 2012-06-25T14:04:08-00:00

Re: [PATCH v4 24/25] memcg/slub: shrink dead caches
type: item
description: On Mon, 18 Jun 2012, Glauber Costa wrote: > In the slub allocator, when the last object of a page goes away, we > don't necessarily free it - there is not necessarily a test for empty > page in any slab_free path. This is the same btw in SLAB which keeps objects in per cpu caches and keeps empty slab pages on special queues. > This patch marks all memcg caches as dead. kmem_cache_shrink is called > for the ones who are not yet dead - this will force internal cache > reorganization, and then all references to empty pages will be removed. You need to call this also for slab to drain the caches and free the pages on the empty list.
creator: Christoph Lameter
date: 2012-07-06T15:16:36-00:00

Re: [PATCH v4 24/25] memcg/slub: shrink dead caches
type: item
description: On 07/06/2012 12:16 PM, Christoph Lameter wrote: > On Mon, 18 Jun 2012, Glauber Costa wrote: > >> In the slub allocator, when the last object of a page goes away, we >> don't necessarily free it - there is not necessarily a test for empty >> page in any slab_free path. > > This is the same btw in SLAB which keeps objects in per cpu caches and > keeps empty slab pages on special queues. > >> This patch marks all memcg caches as dead. kmem_cache_shrink is called >> for the ones who are not yet dead - this will force internal cache >> reorganization, and then all references to empty pages will be removed. > > You need to call this also for slab to drain the caches and free the pages > on the empty list. > Doesn't the SLAB have a time-based reaper for that? That's why I was less concerned with the SLAB, but I can certainly call it for both.
creator: Glauber Costa
date: 2012-07-20T22:16:56-00:00

Re: [PATCH v4 24/25] memcg/slub: shrink dead caches
type: item
description: On Fri, 20 Jul 2012, Glauber Costa wrote: > > This is the same btw in SLAB which keeps objects in per cpu caches and > > keeps empty slab pages on special queues. > > > >> This patch marks all memcg caches as dead. kmem_cache_shrink is called > >> for the ones who are not yet dead - this will force internal cache > >> reorganization, and then all references to empty pages will be removed. > > > > You need to call this also for slab to drain the caches and free the pages > > on the empty list. > > > Doesn't the SLAB have a time-based reaper for that? Yes but it will take a couple of minutes to drain the caches.
creator: Christoph Lameter
date: 2012-07-25T15:23:40-00:00

Re: [PATCH v4 24/25] memcg/slub: shrink dead caches
type: item
description: On 07/25/2012 07:23 PM, Christoph Lameter wrote: > On Fri, 20 Jul 2012, Glauber Costa wrote: > >>> This is the same btw in SLAB which keeps objects in per cpu caches and >>> keeps empty slab pages on special queues. >>> >>>> This patch marks all memcg caches as dead. kmem_cache_shrink is called >>>> for the ones who are not yet dead - this will force internal cache >>>> reorganization, and then all references to empty pages will be removed. >>> >>> You need to call this also for slab to drain the caches and free the pages >>> on the empty list. >>> >> Doesn't the SLAB have a time-based reaper for that? > > Yes but it will take a couple of minutes to drain the caches. > You might have seen in my last submission that included this in the slab as well.
creator: Glauber Costa
date: 2012-07-25T18:15:12-00:00