OpenVZ Forum - RDF feed
type: channel
items: [PATCH 00/10] memcg: Kernel Memory Accounting.
items: [PATCH 01/10] memcg: Kernel memory accounting infrastructure.
items: [PATCH 02/10] memcg: Uncharge all kmem when deleting a cgroup.
items: [PATCH 03/10] memcg: Reclaim when more than one page needed.
items: [PATCH 04/10] memcg: Introduce __GFP_NOACCOUNT.
items: [PATCH 05/10] memcg: Slab accounting.
items: [PATCH 06/10] memcg: Track all the memcg children of a kmem_cache.
items: [PATCH 07/10] memcg: Stop res_counter underflows.
items: [PATCH 08/10] memcg: Add CONFIG_CGROUP_MEM_RES_CTLR_KMEM_ACCT_ROOT.
items: [PATCH 09/10] memcg: Per-memcg memory.kmem.slabinfo file.
items: [PATCH 10/10] memcg: Document kernel memory accounting.
items: Re: [PATCH 00/10] memcg: Kernel Memory Accounting.

[PATCH 00/10] memcg: Kernel Memory Accounting.
type: item
description: This patch series introduces kernel memory accounting to memcg. It currently only accounts for slab. It's very similar to the patchset I sent back in October, but with a number of fixes and improvements. There is also overlap with Glauber's patchset, but I decided to send this because there are some pretty significant differences. With this patchset, kernel memory gets counted in a memcg's memory.kmem.usage_in_bytes. It's possible to have a limit to the kernel memory by setting memory.kmem.independent_kmem_limit to 1 and setting the limit in memory.kmem.limit_in_bytes. If memory.kmem.independent_kmem_limit is unset, kernel memory also gets counted in the cgroup's memory.usage_in_bytes, and kernel memory allocations may trigger memcg reclaim or OOM. Slab gets accounted per-page, by using per-cgroup kmem_caches that get created the first time an allocation of that type is done by that cgroup. The main difference with Glauber's patches is here: We try to track all the slab allocations, while Glauber only tracks ones that are explicitly marked. We feel that it's important to track everything, because there are a lot of different slab allocations that may use significant amounts of memory, that we may not know of ahead of time. This is also the main source of complexity in the patchset. The per-cgroup kmem_cache approach makes it so that we only have to do charges/uncharges in the slow path of the slab allocator, which should have low performance impacts. A per-cgroup kmem_cache will appear in slabinfo named like its original cache, with the cgroup's name in parenthesis. On cgroup deletion, the accounting gets moved to the root cgroup and any existing cgroup kmem_cache gets "dead" appended to its name, to indicate that its accounting was migrated. The dead caches get removed once they no longer have any active objects in them. This patchset does not include any shrinker changes. We already have patches for that, but I felt like it's more important to get the accounting r…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:43-00:00

[PATCH 01/10] 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 | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 120 insertions(+), 1 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 228d646..11e31d6 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -235,6 +235,10 @@ struct mem_cgroup { */ struct res_counter memsw; /* + * the counter to account for kernel memory usage. + */ + struct res_counter kmem_bytes; + /* * Per cgroup active and inactive list, similar to the * per zone LRU lists. */ @@ -293,6 +297,7 @@ struct mem_cgroup { #ifdef CONFIG_INET struct tcp_memcontrol tcp_mem; #endif + int independent_kmem_limit; }; /* Stuffs for move charges at task migration. */ @@ -354,6 +359,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) @@ -370,6 +376,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); /* Writing them here to avoid exposing memcg's inner layout */ #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM @@ -1402,6 +1410,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_bytes, RES_USAGE) >> 10, + res_counter_read_u64(&memcg->kmem_bytes, RES_LIMIT) >> 10, + res_counter_read_u64(&memcg->kmem_bytes, RES_FAILCNT)); } /* @@ -3840,6 +3852,9 @@ static u64 mem_cgroup_read(struct…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:44-00:00

[PATCH 02/10] memcg: Uncharge all kmem when deleting a cgroup.
type: item
description: A later patch will also use this to move the accounting to the root cgroup. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 30 +++++++++++++++++++++++++++++- 1 files changed, 29 insertions(+), 1 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 11e31d6..6f44fcb 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -378,6 +378,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); /* Writing them here to avoid exposing memcg's inner layout */ #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM @@ -3674,6 +3675,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); @@ -3693,6 +3695,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) { @@ -3714,8 +3718,13 @@ 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 && !memcg->independent_kmem_limit) + usage -= memcg->kmem_bytes.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; @@ -5632,9 +5641,28 @@ memcg_kmem_init(struct mem_cgroup *memcg, struct mem_cgroup *parent) res_counter_init(&memcg->kmem_bytes, parent_res); memcg->independent_kmem_limit = 0; } + +static void +memcg_kmem_move(struct mem_cgroup *memcg) +{ + unsigned long flags; + long kmem_bytes; + + spin_lock_irqsave(&memcg->kmem_by…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:45-00:00

[PATCH 03/10] memcg: Reclaim when more than one page needed.
type: item
description: From: Hugh Dickins <hughd@google.com> 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 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 pass minsize to consume_stock() also, so that it can draw on stock for higher order slabs, instead of accumulating an increasing surplus of stock, as its "nr_pages == 1" tests previously caused. 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. Signed-off-by: Hugh Dickins <hughd@google.com> Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 35 +++++++++++++++++++---------------- 1 files changed, 19 insertions(+), 16 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 6f44fcb..c82ca1c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1928,19 +1928,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 fa…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:46-00:00

[PATCH 04/10] memcg: Introduce __GFP_NOACCOUNT.
type: item
description: This is used to indicate that we don't want an allocation to be accounted to the current cgroup. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- include/linux/gfp.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 581e74b..765c20f 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -23,6 +23,7 @@ struct vm_area_struct; #define ___GFP_REPEAT 0x400u #define ___GFP_NOFAIL 0x800u #define ___GFP_NORETRY 0x1000u +#define ___GFP_NOACCOUNT 0x2000u #define ___GFP_COMP 0x4000u #define ___GFP_ZERO 0x8000u #define ___GFP_NOMEMALLOC 0x10000u @@ -76,6 +77,7 @@ struct vm_area_struct; #define __GFP_REPEAT ((__force gfp_t)___GFP_REPEAT) /* See above */ #define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL) /* See above */ #define __GFP_NORETRY ((__force gfp_t)___GFP_NORETRY) /* See above */ +#define __GFP_NOACCOUNT ((__force gfp_t)___GFP_NOACCOUNT) /* Don't account to the current cgroup */ #define __GFP_COMP ((__force gfp_t)___GFP_COMP) /* Add compound page metadata */ #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) /* Return zeroed page on success */ #define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves */ -- 1.7.7.3
creator: Suleiman Souhlal
date: 2012-02-27T22:58:47-00:00

[PATCH 05/10] memcg: Slab accounting.
type: item
description: Introduce per-cgroup kmem_caches for memcg slab accounting, that get created the first time we do an allocation of that type in the cgroup. If we are not permitted to sleep in that allocation, the cache gets created asynchronously. The cgroup cache gets used in subsequent allocations, and permits accounting of slab on a per-page basis. 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. Allocations that cannot be attributed to a cgroup get charged to the root cgroup. 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 | 1 + include/linux/slab_def.h | 94 +++++++++++++- mm/memcontrol.c | 316 ++++++++++++++++++++++++++++++++++++++++++++ mm/slab.c | 266 +++++++++++++++++++++++++++++++++---- 5 files changed, 680 insertions(+), 27 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 4d34356..f5458b0 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -421,13 +421,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 sock_update_memcg(struct sock *sk) { } static inline void sock_…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:48-00:00

[PATCH 06/10] 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_def.h | 1 + mm/slab.c | 45 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 449a0de..185e4a2 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -100,6 +100,7 @@ struct kmem_cache { atomic_t refcnt; struct list_head destroyed_list; /* Used when deleting cpuset cache */ + struct list_head sibling_list; #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */ /* 6) per-cpu/per-node data, touched during every alloc/free */ diff --git a/mm/slab.c b/mm/slab.c index 6c6bc49..bf38af6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2508,6 +2508,7 @@ __kmem_cache_create(const char *name, size_t size, size_t align, cachep->orig_cache = NULL; atomic_set(&cachep->refcnt, 1); INIT_LIST_HEAD(&cachep->destroyed_list); + INIT_LIST_HEAD(&cachep->sibling_list); if (!memcg) { int id; @@ -2580,6 +2581,7 @@ kmem_cache_create_memcg(struct kmem_cache *cachep, char *name) new->flags |= SLAB_MEMCG; new->orig_cache = cachep; + list_add(&new->sibling_list, &cachep->sibling_list); if ((cachep->limit != new->limit) || (cachep->batchcount != new->batchcount) || (cachep->shared != new->shared)) @@ -2767,6 +2769,26 @@ 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->id != -1) { + struct kmem_cache *c, *tmp; + + mutex_lock(&cache_chain_mutex); + list_for_each_entry_safe(c, tmp, &cachep->sibling_list, + sibling_list)…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:49-00:00

[PATCH 07/10] memcg: Stop res_counter underflows.
type: item
description: From: Hugh Dickins <hughd@google.com> If __mem_cgroup_try_charge() goes the "bypass" route in charging slab (typically when the task has been OOM-killed), that later results in res_counter_uncharge_locked() underflows - a stream of warnings from kernel/res_counter.c:96! Solve this by accounting kmem_bypass when we shift that charge to root, and whenever a memcg has any kmem_bypass outstanding, deduct from that when unaccounting kmem, before deducting from kmem_bytes: so that its kmem_bytes soon returns to being a fair account. The amount of memory bypassed is shown in memory.stat as kernel_bypassed_memory. Signed-off-by: Hugh Dickins <hughd@google.com> Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- mm/memcontrol.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 40 insertions(+), 3 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d1c0cd7..6a475ed 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -302,6 +302,9 @@ struct mem_cgroup { /* Slab accounting */ struct kmem_cache *slabs[MAX_KMEM_CACHE_TYPES]; #endif +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + atomic64_t kmem_bypassed; +#endif int independent_kmem_limit; }; @@ -4037,6 +4040,7 @@ enum { MCS_INACTIVE_FILE, MCS_ACTIVE_FILE, MCS_UNEVICTABLE, + MCS_KMEM_BYPASSED, NR_MCS_STAT, }; @@ -4060,7 +4064,8 @@ struct { {"active_anon", "total_active_anon"}, {"inactive_file", "total_inactive_file"}, {"active_file", "total_active_file"}, - {"unevictable", "total_unevictable"} + {"unevictable", "total_unevictable"}, + {"kernel_bypassed_memory", "total_kernel_bypassed_memory"} }; @@ -4100,6 +4105,10 @@ mem_cgroup_get_local_stat(struct mem_cgroup *memcg, struct mcs_total_stat *s) s->stat[MCS_ACTIVE_FILE] += val * PAGE_SIZE; val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE)); s->stat[MCS_UNEVICTABLE] += val * PAGE_SIZE; + +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + s->stat[MCS_KMEM_BYPASSED] += atomic64_read(&memcg->kmem_bypassed); +#endif } static void @@ -5616,14 +5625,24 @@ m…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:50-00:00

[PATCH 08/10] memcg: Add CONFIG_CGROUP_MEM_RES_CTLR_KMEM_ACCT_ROOT.
type: item
description: This config option dictates whether or not kernel memory in the root cgroup should be accounted. This may be useful in an environment where everything is supposed to be in a cgroup and accounted for. Large amounts of kernel memory in the root cgroup would indicate problems with memory isolation or accounting. Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- init/Kconfig | 8 ++++++++ mm/memcontrol.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 0 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 3f42cd6..a119270 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -714,6 +714,14 @@ config CGROUP_MEM_RES_CTLR_KMEM Memory Controller, which are page-based, and can be swapped. Users of the kmem extension can use it to guarantee that no group of processes will ever exhaust kernel resources alone. +config CGROUP_MEM_RES_CTLR_KMEM_ACCT_ROOT + bool "Root Cgroup Kernel Memory Accounting (EXPERIMENTAL)" + depends on CGROUP_MEM_RES_CTLR_KMEM + default n + help + Account for kernel memory used by the root cgroup. This may be useful + to know how much kernel memory isn't currently accounted to any + cgroup. config CGROUP_PERF bool "Enable perf_event per-cpu per-container group (cgroup) monitoring" diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 6a475ed..d4cdb8e 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -61,6 +61,10 @@ struct cgroup_subsys mem_cgroup_subsys __read_mostly; #define MEM_CGROUP_RECLAIM_RETRIES 5 struct mem_cgroup *root_mem_cgroup __read_mostly; +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM_ACCT_ROOT +atomic64_t pre_memcg_kmem_bytes; /* kmem usage before memcg is enabled */ +#endif + #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP /* Turned on only when memory cgroup is enabled && really_do_swap_account = 1 */ int do_swap_account __read_mostly; @@ -5643,6 +5647,13 @@ memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, long long delta) if (memcg) ret = res_counter_charge(&memcg->kmem_bytes, delta, &fail_res); +#i…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:51-00:00

[PATCH 09/10] 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_def.h | 7 ++++ mm/memcontrol.c | 22 +++++++++++ mm/slab.c | 88 ++++++++++++++++++++++++++++++++++------------ 3 files changed, 94 insertions(+), 23 deletions(-) diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 185e4a2..407eaf5 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -242,6 +242,7 @@ struct kmem_cache *kmem_cache_create_memcg(struct kmem_cache *cachep, char *name); void kmem_cache_destroy_cpuset(struct kmem_cache *cachep); 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) @@ -301,6 +302,12 @@ static inline void mem_cgroup_kmem_cache_finish_sleep(struct kmem_cache *cachep) { } + +static inline int +memcg_slabinfo(void *unused, struct seq_file *m) +{ + return 0; +} #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */ #endif /* _LINUX_SLAB_DEF_H */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d4cdb8e..d4a6053 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4637,6 +4637,22 @@ static int mem_cgroup_independent_kmem_limit_write(struct cgroup *cgrp, return 0; } +#ifdef CONFIG_SLAB +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); +} +#endif + static struct cftype kmem_cgroup_files[] = { { .name = "kmem.independent_kmem_limit", @@ -4654,6 +4670,12 @@ static struct cftype kmem_cgroup_files[] = { .private = MEMFILE_PRIVATE(_KMEM, RES_USAGE), .read_u64 = mem_cgroup_read, }, +#ifdef CONFIG_SLAB + { + .name = "kmem.slabinfo", + .read_seq_string = mem_cgroup_slabinfo_show, + }, +#endif }; static int register_kmem_files(struct cgroup *cont, struct cgroup_…
creator: Suleiman Souhlal
date: 2012-02-27T22:58:52-00:00

[PATCH 10/10] memcg: Document kernel memory accounting.
type: item
description: Signed-off-by: Suleiman Souhlal <suleiman@google.com> --- Documentation/cgroups/memory.txt | 44 +++++++++++++++++++++++++++++++++++-- 1 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 4c95c00..64c6cc8 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 @@ -266,10 +271,20 @@ 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. +cgroup is accounted if CONFIG_CGROUP_MEM_RES_CTLR_KMEM_ACCT_ROOT is set. -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 gets moved to the +root cgroup (if CONFIG_CGROUP_MEM_RES_CTLR_KMEM_ACCT_ROOT is set). + +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 +294,26 @@ per cgroup, instead …
creator: Suleiman Souhlal
date: 2012-02-27T22:58:53-00:00

Re: [PATCH 00/10] memcg: Kernel Memory Accounting.
type: item
description: On Mon, 27 Feb 2012, Suleiman Souhlal wrote: > The main difference with Glauber's patches is here: We try to > track all the slab allocations, while Glauber only tracks ones > that are explicitly marked. > We feel that it's important to track everything, because there > are a lot of different slab allocations that may use significant > amounts of memory, that we may not know of ahead of time. > This is also the main source of complexity in the patchset. Well, what are the performance implications of your patches? Can we reasonably expect distributions to be able to enable this thing on generic kernels and leave the feature disabled by default? Can we accommodate your patches to support Glauber's use case? Pekka
creator: Pekka Enberg
date: 2012-02-28T08:49:46-00:00

Re: [PATCH 00/10] memcg: Kernel Memory Accounting.
type: item
description: Hello, On Tue, Feb 28, 2012 at 12:49 AM, Pekka Enberg <penberg@kernel.org> wrote: > On Mon, 27 Feb 2012, Suleiman Souhlal wrote: >> The main difference with Glauber's patches is here: We try to >> track all the slab allocations, while Glauber only tracks ones >> that are explicitly marked. >> We feel that it's important to track everything, because there >> are a lot of different slab allocations that may use significant >> amounts of memory, that we may not know of ahead of time. >> This is also the main source of complexity in the patchset. > > Well, what are the performance implications of your patches? Can we > reasonably expect distributions to be able to enable this thing on > generic kernels and leave the feature disabled by default? Can we > accommodate your patches to support Glauber's use case? I don't have up to date performance numbers, but we haven't found any critical performance degradations on our workloads, with our internal versions of this patchset. There are some conditional branches added to the slab fast paths, but I think it should be possible to come with a way to get rid of those when the feature is disabled, maybe by using a static_branch. This should hopefully make it possible to keep the feature compiled in but disabled at runtime. I think it's definitely possible to accommodate my patches to support Glauber's use case, with a bit of work. -- Suleiman
creator: Suleiman Souhlal
date: 2012-02-28T22:12:47-00:00