OpenVZ Forum - RDF feed
type: channel
items: [PATCH v2 00/13] Memcg Kernel Memory Tracking.
items: [PATCH v2 01/13] memcg: Consolidate various flags into a single flags field.
items: [PATCH v2 02/13] memcg: Kernel memory accounting infrastructure.
items: [PATCH v2 03/13] memcg: Uncharge all kmem when deleting a cgroup.
items: [PATCH v2 04/13] memcg: Make it possible to use the stock for more than one page.
items: [PATCH v2 06/13] slab: Add kmem_cache_gfp_flags() helper function.
items: [PATCH v2 07/13] memcg: Slab accounting.
items: [PATCH v2 08/13] memcg: Make dentry slab memory accounted in kernel memory accounting.
items: [PATCH v2 09/13] memcg: Account for kmalloc in kernel memory accounting.
items: [PATCH v2 10/13] memcg: Track all the memcg children of a kmem_cache.
items: [PATCH v2 11/13] memcg: Handle bypassed kernel memory charges.
items: [PATCH v2 12/13] memcg: Per-memcg memory.kmem.slabinfo file.
items: [PATCH v2 13/13] memcg: Document kernel memory accounting.
items: Re: [PATCH v2 00/13] Memcg Kernel Memory Tracking.

[PATCH v2 00/13] Memcg Kernel Memory Tracking.
type: item
description: This is v2 of my kernel memory tracking patchset for memcg. Lots of changes based on feedback from Glauber and Kamezawa. In particular, I changed it to be opt-in instead of opt-out: In order for a slab type to be tracked, it has to be marked with SLAB_MEMCG_ACCT at kmem_cache_create() time. Currently, only dentries and kmalloc are tracked. Planned for v3: - Slub support. - Using a static_branch to remove overhead when no cgroups have been created. - Getting rid of kmem_cache_get_ref/drop_ref pair in kmem_cache_free. Detailed change list from v1 (http://marc.info/?l=linux-mm&m=133038361014525): - Fixed misspelling in documentation. - Added flags field to struct mem_cgroup. - Moved independent_kmem_limit into flags. - Renamed kmem_bytes to kmem. - Divided consume_stock changes into two changes. - Fixed crash at boot when not every commit is applied. - Moved the new fields in kmem_cache into their own struct. - Got rid of SLAB_MEMCG slab flag. - Dropped accounting to root. - Added css_id into memcg slab name. - Changed memcg cache creation to always be deferred to workqueue. - Replaced bypass_bytes with overcharging the cgroup. - Got rid of #ifdef CONFIG_SLAB from memcontrol.c. - Got rid of __GFP_NOACCOUNT, changing to an opt-in model. - Remove kmem limit when turning off independent limit. - Moved the accounting of kmalloc to its own patch. - Removed useless parameters from memcg_create_kmem_cache(). - Get a ref to the css when enqueing cache for creation. - increased MAX_KMEM_CACHE_TYPES to 400. Suleiman Souhlal (13): memcg: Consolidate various flags into a single flags field. memcg: Kernel memory accounting infrastructure. memcg: Uncharge all kmem when deleting a cgroup. memcg: Make it possible to use the stock for more than one page. memcg: Reclaim when more than one page needed. slab: Add kmem_cache_gfp_flags() helper function. memcg: Slab accounting. memcg: Make dentry slab memory accounted in kernel memory accounting. memcg: Account for kmalloc in kernel memory …
creator: Suleiman Souhlal
date: 2012-03-09T20:39:03-00:00

[PATCH v2 01/13] memcg: Consolidate various flags into a single flags field.
type: item
description: Since there is an ever-increasing number of flags in the memcg struct, consolidate them into a single flags field. The flags that we consolidate are: - use_hierarchy - memsw_is_minimum - oom_kill_disable Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 112 ++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 78 insertions(+), 34 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 5585dc3..37ad2cb 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -213,6 +213,15 @@ struct mem_cgroup_eventfd_list { static void mem_cgroup_threshold(struct mem_cgroup *memcg); static void mem_cgroup_oom_notify(struct mem_cgroup *memcg); +enum memcg_flags { + MEMCG_USE_HIERARCHY, /* + * Should the accounting and control be + * hierarchical, per subtree? + */ + MEMCG_MEMSW_IS_MINIMUM, /* Set when res.limit == memsw.limit */ + MEMCG_OOM_KILL_DISABLE, /* OOM-Killer disable */ +}; + /* * The memory controller data structure. The memory controller controls both * page cache and RSS per cgroup. We would eventually like to provide @@ -245,10 +254,7 @@ struct mem_cgroup { atomic_t numainfo_events; atomic_t numainfo_updating; #endif - /* - * Should the accounting and control be hierarchical, per subtree? - */ - bool use_hierarchy; + unsigned long flags; bool oom_lock; atomic_t under_oom; @@ -256,11 +262,6 @@ struct mem_cgroup { atomic_t refcnt; int swappiness; - /* OOM-Killer disable */ - int oom_kill_disable; - - /* set when res.limit == memsw.limit */ - bool memsw_is_minimum; /* protect arrays of thresholds */ struct mutex thresholds_lock; @@ -371,6 +372,24 @@ enum charge_type { static void mem_cgroup_get(struct mem_cgroup *memcg); static void mem_cgroup_put(struct mem_cgroup *memcg); +static inline bool +mem_cgroup_test_flag(const struct mem_cgroup *memcg, enum memcg_flags flag) +{ + return test_bit(flag, &memcg->flags); +} + +static inline void +mem_cgroup_set_flag(struct mem_cgroup *memcg, enum memcg_flags flag) +{ + set_bit(flag…
creator: Suleiman Souhlal
date: 2012-03-09T20:39:04-00:00

[PATCH v2 02/13] memcg: Kernel memory accounting infrastructure.
type: item
description: Enabled with CONFIG_CGROUP_MEM_RES_CTLR_KMEM. Adds the following files: - memory.kmem.independent_kmem_limit - memory.kmem.usage_in_bytes - memory.kmem.limit_in_bytes Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 135 insertions(+), 1 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 37ad2cb..e6fd558 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -220,6 +220,10 @@ enum memcg_flags { */ MEMCG_MEMSW_IS_MINIMUM, /* Set when res.limit == memsw.limit */ MEMCG_OOM_KILL_DISABLE, /* OOM-Killer disable */ + MEMCG_INDEPENDENT_KMEM_LIMIT, /* + * kernel memory is not counted in + * memory.usage_in_bytes + */ }; /* @@ -244,6 +248,10 @@ struct mem_cgroup { */ struct res_counter memsw; /* + * 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. */ @@ -355,6 +363,7 @@ enum charge_type { #define _MEM (0) #define _MEMSWAP (1) #define _OOM_TYPE (2) +#define _KMEM (3) #define MEMFILE_PRIVATE(x, val) (((x) << 16) | (val)) #define MEMFILE_TYPE(val) (((val) >> 16) & 0xffff) #define MEMFILE_ATTR(val) ((val) & 0xffff) @@ -371,6 +380,8 @@ enum charge_type { static void mem_cgroup_get(struct mem_cgroup *memcg); static void mem_cgroup_put(struct mem_cgroup *memcg); +static void memcg_kmem_init(struct mem_cgroup *memcg, + struct mem_cgroup *parent); static inline bool mem_cgroup_test_flag(const struct mem_cgroup *memcg, enum memcg_flags flag) @@ -1435,6 +1446,10 @@ done: res_counter_read_u64(&memcg->memsw, RES_USAGE) >> 10, res_counter_read_u64(&memcg->memsw, RES_LIMIT) >> 10, res_counter_read_u64(&memcg->memsw, RES_FAILCNT)); + printk(KERN_INFO "kmem: usage %llukB, limit %llukB, failcnt %llu\n", + res_counter_read_u64(&memcg->kmem, RES_USAGE) >> 10, + res_counter_read_u64(&memcg->kmem, RES_LIMIT) >> 10, + res_counter_read_u64(&memcg->kmem, RES_FAILCNT)); } /* @…
creator: Suleiman Souhlal
date: 2012-03-09T20:39:05-00:00

[PATCH v2 03/13] memcg: Uncharge all kmem when deleting a cgroup.
type: item
description: Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 31 ++++++++++++++++++++++++++++++- 1 files changed, 30 insertions(+), 1 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e6fd558..6fbb438 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -382,6 +382,7 @@ static void mem_cgroup_get(struct mem_cgroup *memcg); static void mem_cgroup_put(struct mem_cgroup *memcg); static void memcg_kmem_init(struct mem_cgroup *memcg, struct mem_cgroup *parent); +static void memcg_kmem_move(struct mem_cgroup *memcg); static inline bool mem_cgroup_test_flag(const struct mem_cgroup *memcg, enum memcg_flags flag) @@ -3700,6 +3701,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg, bool free_all) int ret; int node, zid, shrink; int nr_retries = MEM_CGROUP_RECLAIM_RETRIES; + unsigned long usage; struct cgroup *cgrp = memcg->css.cgroup; css_get(&memcg->css); @@ -3719,6 +3721,8 @@ move_account: /* This is for making all *used* pages to be on LRU. */ lru_add_drain_all(); drain_all_stock_sync(memcg); + if (!free_all) + memcg_kmem_move(memcg); ret = 0; mem_cgroup_start_move(memcg); for_each_node_state(node, N_HIGH_MEMORY) { @@ -3740,8 +3744,14 @@ move_account: if (ret == -ENOMEM) goto try_to_free; cond_resched(); + usage = memcg->res.usage; +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + if (free_all && !mem_cgroup_test_flag(memcg, + MEMCG_INDEPENDENT_KMEM_LIMIT)) + usage -= memcg->kmem.usage; +#endif /* "ret" should also be checked to ensure all lists are empty. */ - } while (memcg->res.usage > 0 || ret); + } while (usage > 0 || ret); out: css_put(&memcg->css); return ret; @@ -5689,9 +5699,28 @@ memcg_kmem_init(struct mem_cgroup *memcg, struct mem_cgroup *parent) parent_res = &parent->kmem; res_counter_init(&memcg->kmem, parent_res); } + +static void +memcg_kmem_move(struct mem_cgroup *memcg) +{ + unsigned long flags; + long kmem; + + spin_lock_irqsave(&memcg->kmem.lock, flags); + kmem = memcg->kmem.usage; + res_counter_uncharge_locked(&memcg-…
creator: Suleiman Souhlal
date: 2012-03-09T20:39:06-00:00

[PATCH v2 04/13] memcg: Make it possible to use the stock for more than one page.
type: item
description: Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 6fbb438..f605100 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1965,19 +1965,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); @@ -2290,7 +2290,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 { @@ -2315,7 +2315,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 not -- 1.7.7.3
creator: Suleiman Souhlal
date: 2012-03-09T20:39:07-00:00

[PATCH v2 06/13] slab: Add kmem_cache_gfp_flags() helper function.
type: item
description: This function returns the gfp flags that are always applied to allocations of a kmem_cache. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- include/linux/slab_def.h | 6 ++++++ include/linux/slob_def.h | 6 ++++++ include/linux/slub_def.h | 6 ++++++ 3 files changed, 18 insertions(+), 0 deletions(-) diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index fbd1117..25f9a6a 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -159,6 +159,12 @@ found: return __kmalloc(size, flags); } +static inline gfp_t +kmem_cache_gfp_flags(struct kmem_cache *cachep) +{ + return cachep->gfpflags; +} + #ifdef CONFIG_NUMA extern void *__kmalloc_node(size_t size, gfp_t flags, int node); extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h index 0ec00b3..3fa527d 100644 --- a/include/linux/slob_def.h +++ b/include/linux/slob_def.h @@ -34,4 +34,10 @@ static __always_inline void *__kmalloc(size_t size, gfp_t flags) return kmalloc(size, flags); } +static inline gfp_t +kmem_cache_gfp_flags(struct kmem_cache *cachep) +{ + return 0; +} + #endif /* __LINUX_SLOB_DEF_H */ diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index a32bcfd..5911d81 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -313,4 +313,10 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) } #endif +static inline gfp_t +kmem_cache_gfp_flags(struct kmem_cache *cachep) +{ + return cachep->allocflags; +} + #endif /* _LINUX_SLUB_DEF_H */ -- 1.7.7.3
creator: Suleiman Souhlal
date: 2012-03-09T20:39:09-00:00

[PATCH v2 07/13] memcg: Slab accounting.
type: item
description: Introduce per-cgroup kmem_caches for memcg slab accounting, that get created asynchronously the first time we do an allocation of that type in the cgroup. The cgroup cache gets used in subsequent allocations, and permits accounting of slab on a per-page basis. For a slab type to getaccounted, the SLAB_MEMCG_ACCT flag has to be passed to kmem_cache_create(). The per-cgroup kmem_caches get looked up at slab allocation time, in a MAX_KMEM_CACHE_TYPES-sized array in the memcg structure, based on the original kmem_cache's id, which gets allocated when the original cache gets created. Only allocations that can be attributed to a cgroup get charged. Each cgroup kmem_cache has a refcount that dictates the lifetime of the cache: We destroy a cgroup cache when its cgroup has been destroyed and there are no more active objects in the cache. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- include/linux/memcontrol.h | 30 +++++- include/linux/slab.h | 41 ++++++ include/linux/slab_def.h | 72 +++++++++++- include/linux/slub_def.h | 3 + init/Kconfig | 2 +- mm/memcontrol.c | 290 ++++++++++++++++++++++++++++++++++++++++++++ mm/slab.c | 248 ++++++++++++++++++++++++++++++++++--- 7 files changed, 663 insertions(+), 23 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index b80de52..b6b8388 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -416,13 +416,41 @@ struct sock; #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM void sock_update_memcg(struct sock *sk); void sock_release_memcg(struct sock *sk); -#else +struct kmem_cache *mem_cgroup_get_kmem_cache(struct kmem_cache *cachep, + gfp_t gfp); +bool mem_cgroup_charge_slab(struct kmem_cache *cachep, gfp_t gfp, size_t size); +void mem_cgroup_uncharge_slab(struct kmem_cache *cachep, size_t size); +void mem_cgroup_flush_cache_create_queue(void); +void mem_cgroup_remove_child_kmem_cache(struct kmem_cache *cachep, int id); +#else /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */ static inline void so…
creator: Suleiman Souhlal
date: 2012-03-09T20:39:10-00:00

[PATCH v2 08/13] memcg: Make dentry slab memory accounted in kernel memory accounting.
type: item
description: Signed-off-by: <suleiman@google.com> --- fs/dcache.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index bcbdb33..cc6dd92 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -3022,8 +3022,8 @@ static void __init dcache_init(void) * but it is probably not worth it because of the cache nature * of the dcache. */ - dentry_cache = KMEM_CACHE(dentry, - SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD); + dentry_cache = KMEM_CACHE(dentry, SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | + SLAB_MEM_SPREAD | SLAB_MEMCG_ACCT); /* Hash may have been set up in dcache_init_early */ if (!hashdist) -- 1.7.7.3
creator: Suleiman Souhlal
date: 2012-03-09T20:39:11-00:00

[PATCH v2 09/13] memcg: Account for kmalloc in kernel memory accounting.
type: item
description: In order to do this, we have to create a kmalloc_no_account() function that is used for kmalloc allocations that we do not want to account, because the kernel memory accounting code has to make some kmalloc allocations and is not allowed to recurse. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- include/linux/slab.h | 8 ++++++++ mm/memcontrol.c | 2 +- mm/slab.c | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index bc9f87f..906a015 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -377,6 +377,8 @@ struct kmem_cache *kmem_cache_create_memcg(struct kmem_cache *cachep, char *name); void kmem_cache_drop_ref(struct kmem_cache *cachep); +void *kmalloc_no_account(size_t size, gfp_t flags); + #else /* !CONFIG_CGROUP_MEM_RES_CTLR_KMEM || !CONFIG_SLAB */ #define MAX_KMEM_CACHE_TYPES 0 @@ -392,6 +394,12 @@ static inline void kmem_cache_drop_ref(struct kmem_cache *cachep) { } + +static inline void *kmalloc_no_account(size_t size, gfp_t flags) +{ + return kmalloc(size, flags); +} + #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM && CONFIG_SLAB */ #endif /* _LINUX_SLAB_H */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a5593cf..72e83af 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5824,7 +5824,7 @@ memcg_create_cache_enqueue(struct mem_cgroup *memcg, struct kmem_cache *cachep) if (!css_tryget(&memcg->css)) return; - cw = kmalloc(sizeof(struct create_work), GFP_NOWAIT); + cw = kmalloc_no_account(sizeof(struct create_work), GFP_NOWAIT); if (cw == NULL) { css_put(&memcg->css); return; diff --git a/mm/slab.c b/mm/slab.c index 95b024c..7af7384 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1623,8 +1623,8 @@ void __init kmem_cache_init(void) sizes->cs_cachep = kmem_cache_create(names->name, sizes->cs_size, ARCH_KMALLOC_MINALIGN, - ARCH_KMALLOC_FLAGS|SLAB_PANIC, - NULL); + ARCH_KMALLOC_FLAGS | SLAB_PANIC | + SLAB_MEMCG_ACCT, NULL); } #ifdef CONFIG_ZONE…
creator: Suleiman Souhlal
date: 2012-03-09T20:39:12-00:00

[PATCH v2 10/13] memcg: 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. We also use this to propagate /proc/slabinfo settings to all the children of a cache, when, for example, changing its batchsize. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- include/linux/slab.h | 1 + mm/slab.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 906a015..fd1d2ba 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -166,6 +166,7 @@ struct mem_cgroup_cache_params { struct kmem_cache *orig_cache; struct list_head destroyed_list; /* Used when deleting cpuset cache */ + struct list_head sibling_list; }; #endif diff --git a/mm/slab.c b/mm/slab.c index 7af7384..02239ed 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2511,6 +2511,7 @@ __kmem_cache_create(const char *name, size_t size, size_t align, cachep->memcg_params.orig_cache = NULL; atomic_set(&cachep->refcnt, 1); INIT_LIST_HEAD(&cachep->memcg_params.destroyed_list); + INIT_LIST_HEAD(&cachep->memcg_params.sibling_list); if (!memcg) { int id; @@ -2582,6 +2583,8 @@ kmem_cache_create_memcg(struct kmem_cache *cachep, char *name) } new->memcg_params.orig_cache = cachep; + list_add(&new->memcg_params.sibling_list, + &cachep->memcg_params.sibling_list); if ((cachep->limit != new->limit) || (cachep->batchcount != new->batchcount) || (cachep->shared != new->shared)) @@ -2769,6 +2772,29 @@ void kmem_cache_destroy(struct kmem_cache *cachep) { BUG_ON(!cachep || in_interrupt()); +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + /* Destroy all the children caches if we aren't a memcg cache */ + if (cachep->memcg_params.id != -1) { + struct kmem_cache *c; + struct mem_cgroup_cache_params *p, *tmp; + + mutex_lock(&cache_chain_mutex); + list_for_each_entry_safe(p, tmp, + &cachep->memcg_par…
creator: Suleiman Souhlal
date: 2012-03-09T20:39:13-00:00

[PATCH v2 11/13] memcg: Handle bypassed kernel memory charges.
type: item
description: When __mem_cgroup_try_charge() decides to bypass a slab charge (because we are getting OOM killed or have a fatal signal pending), we may end up with a slab that belongs to a memcg, but wasn't charged to it. When we free such a slab page, we end up uncharging it from the memcg, even though it was never charged, which may lead to res_counter underflows. To avoid this, when a charge is bypassed, we force the charge, without checking for the bypass conditions or doing any reclaim. This may cause the cgroup's usage to temporarily go above its limit. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 72e83af..9f5e9d8 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5672,16 +5672,27 @@ memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, long long delta) ret = 0; - _memcg = memcg; if (memcg && !mem_cgroup_test_flag(memcg, MEMCG_INDEPENDENT_KMEM_LIMIT)) { + _memcg = memcg; ret = __mem_cgroup_try_charge(NULL, gfp, delta / PAGE_SIZE, &_memcg, may_oom); if (ret == -ENOMEM) return ret; + else if (ret == -EINTR) { + /* + * __mem_cgroup_try_charge() chose to bypass to root due + * to OOM kill or fatal signal. + * Since our only options are to either fail the + * allocation or charge it to this cgroup, force the + * change, going above the limit if needed. + */ + ret = res_counter_charge_nofail(&memcg->res, delta, + &fail_res); + } } - if (memcg && _memcg == memcg) + if (memcg) ret = res_counter_charge(&memcg->kmem, delta, &fail_res); return ret; -- 1.7.7.3
creator: Suleiman Souhlal
date: 2012-03-09T20:39:14-00:00

[PATCH v2 12/13] memcg: Per-memcg memory.kmem.slabinfo file.
type: item
description: This file shows all the kmem_caches used by a memcg. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- include/linux/slab.h | 6 +++ include/linux/slab_def.h | 1 + mm/memcontrol.c | 18 +++++++++ mm/slab.c | 88 ++++++++++++++++++++++++++++++++++------------ 4 files changed, 90 insertions(+), 23 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index fd1d2ba..0ff5ee2 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -401,6 +401,12 @@ static inline void *kmalloc_no_account(size_t size, gfp_t flags) return kmalloc(size, flags); } +static inline int +mem_cgroup_slabinfo(struct mem_cgroup *mem, struct seq_file *m) +{ + return 0; +} + #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM && CONFIG_SLAB */ #endif /* _LINUX_SLAB_H */ diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 248b8a9..fa6b272 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -227,6 +227,7 @@ found: #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM void kmem_cache_drop_ref(struct kmem_cache *cachep); +int mem_cgroup_slabinfo(struct mem_cgroup *mem, struct seq_file *m); static inline void kmem_cache_get_ref(struct kmem_cache *cachep) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9f5e9d8..4a4fa48 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4672,6 +4672,20 @@ static int mem_cgroup_independent_kmem_limit_write(struct cgroup *cgrp, return 0; } +static int +mem_cgroup_slabinfo_show(struct cgroup *cgroup, struct cftype *ctf, + struct seq_file *m) +{ + struct mem_cgroup *mem; + + mem = mem_cgroup_from_cont(cgroup); + + if (mem == root_mem_cgroup) + mem = NULL; + + return mem_cgroup_slabinfo(mem, m); +} + static struct cftype kmem_cgroup_files[] = { { .name = "kmem.independent_kmem_limit", @@ -4689,6 +4703,10 @@ static struct cftype kmem_cgroup_files[] = { .private = MEMFILE_PRIVATE(_KMEM, RES_USAGE), .read_u64 = mem_cgroup_read, }, + { + .name = "kmem.slabinfo", + .read_seq_string = mem_cgroup_slabinfo_show, + }, }; static int regis…
creator: Suleiman Souhlal
date: 2012-03-09T20:39:15-00:00

[PATCH v2 13/13] memcg: Document kernel memory accounting.
type: item
description: Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- Documentation/cgroups/memory.txt | 44 ++++++++++++++++++++++++++++++++++--- 1 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 4c95c00..73f2e38 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -74,6 +74,11 @@ 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.usage_in_bytes # show current kernel memory usage + memory.kmem.limit_in_bytes # show/set limit of kernel memory usage + memory.kmem.independent_kmem_limit # show/set control of kernel memory limit + (See 2.7 for details) + memory.kmem.slabinfo # show cgroup's slabinfo 1. History @@ -265,11 +270,19 @@ the amount of kernel memory used by the system. Kernel memory is fundamentally different than user memory, since it can't be swapped out, which makes it possible to DoS the system by consuming too much of this precious resource. -Kernel memory limits are not imposed for the root cgroup. Usage for the root -cgroup may or may not be accounted. +Kernel memory limits are not imposed for the root cgroup. -Currently no soft limit is implemented for kernel memory. It is future work -to trigger slab reclaim when those limits are reached. +A cgroup's kernel memory is counted into its memory.kmem.usage_in_bytes. + +memory.kmem.independent_kmem_limit controls whether or not kernel memory +should also be counted into the cgroup's memory.usage_in_bytes. +If it is set, it is possible to specify a limit for kernel memory with +memory.kmem.limit_in_bytes. + +Upon cgroup deletion, all the remaining kernel memory becomes unaccounted. + +An accounted kernel memory allocation may trigger reclaim in that cgroup, +and may also OOM. 2.7.1 Current Kernel Memory resources accounted @@ -279,6 +292,29 @@ per cgroup, instead …
creator: Suleiman Souhlal
date: 2012-03-09T20:39:16-00:00

Re: [PATCH v2 00/13] Memcg Kernel Memory Tracking.
type: item
description: On Fri, Mar 9, 2012 at 12:39 PM, Suleiman Souhlal <ssouhlal@freebsd.org> wrote: > This is v2 of my kernel memory tracking patchset for memcg. I just realized that I forgot to test without the config option enabled, so that doesn't compile. :-( I will make sure to fix this in v3 and test more thoroughly. Hopefully this shouldn't impede discussion on the patchset. Sorry about that. -- Suleiman
creator: Suleiman Souhlal
date: 2012-03-10T06:25:58-00:00