diff for duplicates of <52F13D3C.801@parallels.com> diff --git a/a/2.txt b/N1/2.txt index 8b13789..c2ae173 100644 --- a/a/2.txt +++ b/N1/2.txt @@ -1 +1,314 @@ +>From 55f0916c794ad25a8bf45566f6d333bea956e0d4 Mon Sep 17 00:00:00 2001 +From: Vladimir Davydov <vdavydov@parallels.com> +Date: Mon, 3 Feb 2014 19:18:22 +0400 +Subject: [PATCH] memcg, slab: separate memcg vs root cache creation paths +Memcg-awareness turned kmem_cache_create() into a dirty interweaving of +memcg-only and except-for-memcg calls. To clean this up, let's create a +separate function handling memcg caches creation. Although this will +result in the two functions having several hunks of practically the same +code, I guess this is the case when readability fully covers the cost of +code duplication. + +Signed-off-by: Vladimir Davydov <vdavydov@parallels.com> +--- + include/linux/slab.h | 9 ++- + mm/memcontrol.c | 12 +--- + mm/slab_common.c | 174 +++++++++++++++++++++++++++----------------------- + 3 files changed, 101 insertions(+), 94 deletions(-) + +diff --git a/include/linux/slab.h b/include/linux/slab.h +index 9260abdd67df..e8c95d0bb879 100644 +--- a/include/linux/slab.h ++++ b/include/linux/slab.h +@@ -113,11 +113,10 @@ void __init kmem_cache_init(void); + int slab_is_available(void); + + struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, +- unsigned long, +- void (*)(void *)); +-struct kmem_cache * +-kmem_cache_create_memcg(struct mem_cgroup *, const char *, size_t, size_t, +- unsigned long, void (*)(void *), struct kmem_cache *); ++ unsigned long, void (*)(void *)); ++#ifdef CONFIG_MEMCG_KMEM ++int kmem_cache_create_memcg(struct mem_cgroup *, struct kmem_cache *); ++#endif + void kmem_cache_destroy(struct kmem_cache *); + int kmem_cache_shrink(struct kmem_cache *); + void kmem_cache_free(struct kmem_cache *, void *); +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 43e08b7bb365..3857033c2718 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -3495,15 +3495,9 @@ struct create_work { + static void memcg_create_cache_work_func(struct work_struct *w) + { + struct create_work *cw = container_of(w, struct create_work, work); +- struct mem_cgroup *memcg = cw->memcg; +- struct kmem_cache *s = cw->cachep; +- struct kmem_cache *new; +- +- new = kmem_cache_create_memcg(memcg, s->name, s->object_size, s->align, +- (s->flags & ~SLAB_PANIC), s->ctor, s); +- if (new) +- new->allocflags |= __GFP_KMEMCG; +- css_put(&memcg->css); ++ ++ kmem_cache_create_memcg(cw->memcg, cw->cachep); ++ css_put(&cw->memcg->css); + kfree(cw); + } + +diff --git a/mm/slab_common.c b/mm/slab_common.c +index 11857abf7057..6bee919ece80 100644 +--- a/mm/slab_common.c ++++ b/mm/slab_common.c +@@ -29,8 +29,7 @@ DEFINE_MUTEX(slab_mutex); + struct kmem_cache *kmem_cache; + + #ifdef CONFIG_DEBUG_VM +-static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name, +- size_t size) ++static int kmem_cache_sanity_check(const char *name, size_t size) + { + struct kmem_cache *s = NULL; + +@@ -57,13 +56,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name, + } + + #if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON) +- /* +- * For simplicity, we won't check this in the list of memcg +- * caches. We have control over memcg naming, and if there +- * aren't duplicates in the global list, there won't be any +- * duplicates in the memcg lists as well. +- */ +- if (!memcg && !strcmp(s->name, name)) { ++ if (!strcmp(s->name, name)) { + pr_err("%s (%s): Cache name already exists.\n", + __func__, name); + dump_stack(); +@@ -77,8 +70,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name, + return 0; + } + #else +-static inline int kmem_cache_sanity_check(struct mem_cgroup *memcg, +- const char *name, size_t size) ++static inline int kmem_cache_sanity_check(const char *name, size_t size) + { + return 0; + } +@@ -139,6 +131,47 @@ unsigned long calculate_alignment(unsigned long flags, + return ALIGN(align, sizeof(void *)); + } + ++static struct kmem_cache * ++do_kmem_cache_create(char *name, size_t object_size, size_t size, size_t align, ++ unsigned long flags, void (*ctor)(void *), ++ struct mem_cgroup *memcg, struct kmem_cache *cachep) ++{ ++ struct kmem_cache *s = NULL; ++ int err = -ENOMEM; ++ ++ if (!name) ++ goto out; ++ ++ s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL); ++ if (!s) ++ goto out; ++ ++ s->name = name; ++ s->object_size = object_size; ++ s->size = size; ++ s->align = align; ++ s->ctor = ctor; ++ ++ err = memcg_alloc_cache_params(memcg, s, cachep); ++ if (err) ++ goto out; ++ ++ err = __kmem_cache_create(s, flags); ++ if (err) ++ goto out; ++ ++ s->refcount = 1; ++ list_add(&s->list, &slab_caches); ++ memcg_register_cache(s); ++out: ++ if (err) { ++ memcg_free_cache_params(s); ++ kfree(name); ++ kfree(s); ++ s = ERR_PTR(err); ++ } ++ return s; ++} + + /* + * kmem_cache_create - Create a cache. +@@ -164,11 +197,9 @@ unsigned long calculate_alignment(unsigned long flags, + * cacheline. This can be beneficial if you're counting cycles as closely + * as davem. + */ +- + struct kmem_cache * +-kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size, +- size_t align, unsigned long flags, void (*ctor)(void *), +- struct kmem_cache *parent_cache) ++kmem_cache_create(const char *name, size_t size, size_t align, ++ unsigned long flags, void (*ctor)(void *)) + { + struct kmem_cache *s = NULL; + int err; +@@ -176,22 +207,10 @@ kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size, + get_online_cpus(); + mutex_lock(&slab_mutex); + +- err = kmem_cache_sanity_check(memcg, name, size); ++ err = kmem_cache_sanity_check(name, size); + if (err) + goto out_unlock; + +- if (memcg) { +- /* +- * Since per-memcg caches are created asynchronously on first +- * allocation (see memcg_kmem_get_cache()), several threads can +- * try to create the same cache, but only one of them may +- * succeed. Therefore if we get here and see the cache has +- * already been created, we silently return NULL. +- */ +- if (cache_from_memcg_idx(parent_cache, memcg_cache_id(memcg))) +- goto out_unlock; +- } +- + /* + * Some allocators will constraint the set of valid flags to a subset + * of all flags. We expect them to define CACHE_CREATE_MASK in this +@@ -200,55 +219,20 @@ kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size, + */ + flags &= CACHE_CREATE_MASK; + +- if (!memcg) { +- s = __kmem_cache_alias(name, size, align, flags, ctor); +- if (s) +- goto out_unlock; +- } +- +- err = -ENOMEM; +- s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL); +- if (!s) ++ s = __kmem_cache_alias(name, size, align, flags, ctor); ++ if (s) + goto out_unlock; + +- s->object_size = s->size = size; +- s->align = calculate_alignment(flags, align, size); +- s->ctor = ctor; +- +- if (memcg) +- s->name = memcg_create_cache_name(memcg, parent_cache); +- else +- s->name = kstrdup(name, GFP_KERNEL); +- if (!s->name) +- goto out_free_cache; +- +- err = memcg_alloc_cache_params(memcg, s, parent_cache); +- if (err) +- goto out_free_cache; +- +- err = __kmem_cache_create(s, flags); +- if (err) +- goto out_free_cache; +- +- s->refcount = 1; +- list_add(&s->list, &slab_caches); +- memcg_register_cache(s); ++ s = do_kmem_cache_create(kstrdup(name, GFP_KERNEL), ++ size, size, calculate_alignment(flags, align, size), ++ flags, ctor, NULL, NULL); ++ err = IS_ERR(s) ? PTR_ERR(s) : 0; + + out_unlock: + mutex_unlock(&slab_mutex); + put_online_cpus(); + + if (err) { +- /* +- * There is no point in flooding logs with warnings or +- * especially crashing the system if we fail to create a cache +- * for a memcg. In this case we will be accounting the memcg +- * allocation to the root cgroup until we succeed to create its +- * own cache, but it isn't that critical. +- */ +- if (!memcg) +- return NULL; +- + if (flags & SLAB_PANIC) + panic("kmem_cache_create: Failed to create slab '%s'. Error %d\n", + name, err); +@@ -260,21 +244,51 @@ out_unlock: + return NULL; + } + return s; +- +-out_free_cache: +- memcg_free_cache_params(s); +- kfree(s->name); +- kmem_cache_free(kmem_cache, s); +- goto out_unlock; + } ++EXPORT_SYMBOL(kmem_cache_create); + +-struct kmem_cache * +-kmem_cache_create(const char *name, size_t size, size_t align, +- unsigned long flags, void (*ctor)(void *)) ++#ifdef CONFIG_MEMCG_KMEM ++/* ++ * kmem_cache_create_memcg - Create a cache for a memory cgroup. ++ * @memcg: The memory cgroup the new cache is for. ++ * @cachep: The parent of the new cache. ++ * ++ * This function creates a kmem cache that will serve allocation requests going ++ * from @memcg to @cachep. The new cache inherits properties from its parent. ++ * ++ * Returns 0 on success, -errno on failure. ++ */ ++int kmem_cache_create_memcg(struct mem_cgroup *memcg, struct kmem_cache *cachep) + { +- return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL); ++ struct kmem_cache *s; ++ int err; ++ ++ get_online_cpus(); ++ mutex_lock(&slab_mutex); ++ ++ /* ++ * Since per-memcg caches are created asynchronously on first ++ * allocation (see memcg_kmem_get_cache()), several threads can try to ++ * create the same cache, but only one of them may succeed. ++ */ ++ err = -EEXIST; ++ if (cache_from_memcg_idx(cachep, memcg_cache_id(memcg))) ++ goto out_unlock; ++ ++ s = do_kmem_cache_create(memcg_create_cache_name(memcg, cachep), ++ cachep->object_size, cachep->size, cachep->align, ++ cachep->flags & ~SLAB_PANIC, cachep->ctor, ++ memcg, cachep); ++ err = IS_ERR(s) ? PTR_ERR(s) : 0; ++ if (!err) ++ s->allocflags |= __GFP_KMEMCG; ++ ++out_unlock: ++ mutex_unlock(&slab_mutex); ++ put_online_cpus(); ++ return err; + } +-EXPORT_SYMBOL(kmem_cache_create); ++#endif /* CONFIG_MEMCG_KMEM */ + + void kmem_cache_destroy(struct kmem_cache *s) + { +-- +1.7.10.4 diff --git a/a/content_digest b/N1/content_digest index ddda389..6354fdd 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -5,14 +5,14 @@ "Subject\0Re: [PATCH v2 3/7] memcg, slab: separate memcg vs root cache creation paths\0" "Date\0Tue, 4 Feb 2014 23:19:24 +0400\0" "To\0Michal Hocko <mhocko@suse.cz>\0" - "Cc\0akpm@linux-foundation.org" - rientjes@google.com - penberg@kernel.org - cl@linux.com - glommer@gmail.com - linux-mm@kvack.org - linux-kernel@vger.kernel.org - " devel@openvz.org\0" + "Cc\0<akpm@linux-foundation.org>" + <rientjes@google.com> + <penberg@kernel.org> + <cl@linux.com> + <glommer@gmail.com> + <linux-mm@kvack.org> + <linux-kernel@vger.kernel.org> + " <devel@openvz.org>\0" "\01:1\0" "b\0" "On 02/04/2014 08:03 PM, Michal Hocko wrote:\n" @@ -77,5 +77,319 @@ "\01:2\0" "fn\00001-memcg-slab-separate-memcg-vs-root-cache-creation-pat.patch\0" "b\0" + ">From 55f0916c794ad25a8bf45566f6d333bea956e0d4 Mon Sep 17 00:00:00 2001\n" + "From: Vladimir Davydov <vdavydov@parallels.com>\n" + "Date: Mon, 3 Feb 2014 19:18:22 +0400\n" + "Subject: [PATCH] memcg, slab: separate memcg vs root cache creation paths\n" + "\n" + "Memcg-awareness turned kmem_cache_create() into a dirty interweaving of\n" + "memcg-only and except-for-memcg calls. To clean this up, let's create a\n" + "separate function handling memcg caches creation. Although this will\n" + "result in the two functions having several hunks of practically the same\n" + "code, I guess this is the case when readability fully covers the cost of\n" + "code duplication.\n" + "\n" + "Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>\n" + "---\n" + " include/linux/slab.h | 9 ++-\n" + " mm/memcontrol.c | 12 +---\n" + " mm/slab_common.c | 174 +++++++++++++++++++++++++++-----------------------\n" + " 3 files changed, 101 insertions(+), 94 deletions(-)\n" + "\n" + "diff --git a/include/linux/slab.h b/include/linux/slab.h\n" + "index 9260abdd67df..e8c95d0bb879 100644\n" + "--- a/include/linux/slab.h\n" + "+++ b/include/linux/slab.h\n" + "@@ -113,11 +113,10 @@ void __init kmem_cache_init(void);\n" + " int slab_is_available(void);\n" + " \n" + " struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,\n" + "-\t\t\tunsigned long,\n" + "-\t\t\tvoid (*)(void *));\n" + "-struct kmem_cache *\n" + "-kmem_cache_create_memcg(struct mem_cgroup *, const char *, size_t, size_t,\n" + "-\t\t\tunsigned long, void (*)(void *), struct kmem_cache *);\n" + "+\t\t\t\t unsigned long, void (*)(void *));\n" + "+#ifdef CONFIG_MEMCG_KMEM\n" + "+int kmem_cache_create_memcg(struct mem_cgroup *, struct kmem_cache *);\n" + "+#endif\n" + " void kmem_cache_destroy(struct kmem_cache *);\n" + " int kmem_cache_shrink(struct kmem_cache *);\n" + " void kmem_cache_free(struct kmem_cache *, void *);\n" + "diff --git a/mm/memcontrol.c b/mm/memcontrol.c\n" + "index 43e08b7bb365..3857033c2718 100644\n" + "--- a/mm/memcontrol.c\n" + "+++ b/mm/memcontrol.c\n" + "@@ -3495,15 +3495,9 @@ struct create_work {\n" + " static void memcg_create_cache_work_func(struct work_struct *w)\n" + " {\n" + " \tstruct create_work *cw = container_of(w, struct create_work, work);\n" + "-\tstruct mem_cgroup *memcg = cw->memcg;\n" + "-\tstruct kmem_cache *s = cw->cachep;\n" + "-\tstruct kmem_cache *new;\n" + "-\n" + "-\tnew = kmem_cache_create_memcg(memcg, s->name, s->object_size, s->align,\n" + "-\t\t\t\t (s->flags & ~SLAB_PANIC), s->ctor, s);\n" + "-\tif (new)\n" + "-\t\tnew->allocflags |= __GFP_KMEMCG;\n" + "-\tcss_put(&memcg->css);\n" + "+\n" + "+\tkmem_cache_create_memcg(cw->memcg, cw->cachep);\n" + "+\tcss_put(&cw->memcg->css);\n" + " \tkfree(cw);\n" + " }\n" + " \n" + "diff --git a/mm/slab_common.c b/mm/slab_common.c\n" + "index 11857abf7057..6bee919ece80 100644\n" + "--- a/mm/slab_common.c\n" + "+++ b/mm/slab_common.c\n" + "@@ -29,8 +29,7 @@ DEFINE_MUTEX(slab_mutex);\n" + " struct kmem_cache *kmem_cache;\n" + " \n" + " #ifdef CONFIG_DEBUG_VM\n" + "-static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,\n" + "-\t\t\t\t size_t size)\n" + "+static int kmem_cache_sanity_check(const char *name, size_t size)\n" + " {\n" + " \tstruct kmem_cache *s = NULL;\n" + " \n" + "@@ -57,13 +56,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,\n" + " \t\t}\n" + " \n" + " #if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON)\n" + "-\t\t/*\n" + "-\t\t * For simplicity, we won't check this in the list of memcg\n" + "-\t\t * caches. We have control over memcg naming, and if there\n" + "-\t\t * aren't duplicates in the global list, there won't be any\n" + "-\t\t * duplicates in the memcg lists as well.\n" + "-\t\t */\n" + "-\t\tif (!memcg && !strcmp(s->name, name)) {\n" + "+\t\tif (!strcmp(s->name, name)) {\n" + " \t\t\tpr_err(\"%s (%s): Cache name already exists.\\n\",\n" + " \t\t\t __func__, name);\n" + " \t\t\tdump_stack();\n" + "@@ -77,8 +70,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name,\n" + " \treturn 0;\n" + " }\n" + " #else\n" + "-static inline int kmem_cache_sanity_check(struct mem_cgroup *memcg,\n" + "-\t\t\t\t\t const char *name, size_t size)\n" + "+static inline int kmem_cache_sanity_check(const char *name, size_t size)\n" + " {\n" + " \treturn 0;\n" + " }\n" + "@@ -139,6 +131,47 @@ unsigned long calculate_alignment(unsigned long flags,\n" + " \treturn ALIGN(align, sizeof(void *));\n" + " }\n" + " \n" + "+static struct kmem_cache *\n" + "+do_kmem_cache_create(char *name, size_t object_size, size_t size, size_t align,\n" + "+\t\t unsigned long flags, void (*ctor)(void *),\n" + "+\t\t struct mem_cgroup *memcg, struct kmem_cache *cachep)\n" + "+{\n" + "+\tstruct kmem_cache *s = NULL;\n" + "+\tint err = -ENOMEM;\n" + "+\n" + "+\tif (!name)\n" + "+\t\tgoto out;\n" + "+\n" + "+\ts = kmem_cache_zalloc(kmem_cache, GFP_KERNEL);\n" + "+\tif (!s)\n" + "+\t\tgoto out;\n" + "+\n" + "+\ts->name = name;\n" + "+\ts->object_size = object_size;\n" + "+\ts->size = size;\n" + "+\ts->align = align;\n" + "+\ts->ctor = ctor;\n" + "+\n" + "+\terr = memcg_alloc_cache_params(memcg, s, cachep);\n" + "+\tif (err)\n" + "+\t\tgoto out;\n" + "+\n" + "+\terr = __kmem_cache_create(s, flags);\n" + "+\tif (err)\n" + "+\t\tgoto out;\n" + "+\n" + "+\ts->refcount = 1;\n" + "+\tlist_add(&s->list, &slab_caches);\n" + "+\tmemcg_register_cache(s);\n" + "+out:\n" + "+\tif (err) {\n" + "+\t\tmemcg_free_cache_params(s);\n" + "+\t\tkfree(name);\n" + "+\t\tkfree(s);\n" + "+\t\ts = ERR_PTR(err);\n" + "+\t}\n" + "+\treturn s;\n" + "+}\n" + " \n" + " /*\n" + " * kmem_cache_create - Create a cache.\n" + "@@ -164,11 +197,9 @@ unsigned long calculate_alignment(unsigned long flags,\n" + " * cacheline. This can be beneficial if you're counting cycles as closely\n" + " * as davem.\n" + " */\n" + "-\n" + " struct kmem_cache *\n" + "-kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size,\n" + "-\t\t\tsize_t align, unsigned long flags, void (*ctor)(void *),\n" + "-\t\t\tstruct kmem_cache *parent_cache)\n" + "+kmem_cache_create(const char *name, size_t size, size_t align,\n" + "+\t\t unsigned long flags, void (*ctor)(void *))\n" + " {\n" + " \tstruct kmem_cache *s = NULL;\n" + " \tint err;\n" + "@@ -176,22 +207,10 @@ kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size,\n" + " \tget_online_cpus();\n" + " \tmutex_lock(&slab_mutex);\n" + " \n" + "-\terr = kmem_cache_sanity_check(memcg, name, size);\n" + "+\terr = kmem_cache_sanity_check(name, size);\n" + " \tif (err)\n" + " \t\tgoto out_unlock;\n" + " \n" + "-\tif (memcg) {\n" + "-\t\t/*\n" + "-\t\t * Since per-memcg caches are created asynchronously on first\n" + "-\t\t * allocation (see memcg_kmem_get_cache()), several threads can\n" + "-\t\t * try to create the same cache, but only one of them may\n" + "-\t\t * succeed. Therefore if we get here and see the cache has\n" + "-\t\t * already been created, we silently return NULL.\n" + "-\t\t */\n" + "-\t\tif (cache_from_memcg_idx(parent_cache, memcg_cache_id(memcg)))\n" + "-\t\t\tgoto out_unlock;\n" + "-\t}\n" + "-\n" + " \t/*\n" + " \t * Some allocators will constraint the set of valid flags to a subset\n" + " \t * of all flags. We expect them to define CACHE_CREATE_MASK in this\n" + "@@ -200,55 +219,20 @@ kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size,\n" + " \t */\n" + " \tflags &= CACHE_CREATE_MASK;\n" + " \n" + "-\tif (!memcg) {\n" + "-\t\ts = __kmem_cache_alias(name, size, align, flags, ctor);\n" + "-\t\tif (s)\n" + "-\t\t\tgoto out_unlock;\n" + "-\t}\n" + "-\n" + "-\terr = -ENOMEM;\n" + "-\ts = kmem_cache_zalloc(kmem_cache, GFP_KERNEL);\n" + "-\tif (!s)\n" + "+\ts = __kmem_cache_alias(name, size, align, flags, ctor);\n" + "+\tif (s)\n" + " \t\tgoto out_unlock;\n" + " \n" + "-\ts->object_size = s->size = size;\n" + "-\ts->align = calculate_alignment(flags, align, size);\n" + "-\ts->ctor = ctor;\n" + "-\n" + "-\tif (memcg)\n" + "-\t\ts->name = memcg_create_cache_name(memcg, parent_cache);\n" + "-\telse\n" + "-\t\ts->name = kstrdup(name, GFP_KERNEL);\n" + "-\tif (!s->name)\n" + "-\t\tgoto out_free_cache;\n" + "-\n" + "-\terr = memcg_alloc_cache_params(memcg, s, parent_cache);\n" + "-\tif (err)\n" + "-\t\tgoto out_free_cache;\n" + "-\n" + "-\terr = __kmem_cache_create(s, flags);\n" + "-\tif (err)\n" + "-\t\tgoto out_free_cache;\n" + "-\n" + "-\ts->refcount = 1;\n" + "-\tlist_add(&s->list, &slab_caches);\n" + "-\tmemcg_register_cache(s);\n" + "+\ts = do_kmem_cache_create(kstrdup(name, GFP_KERNEL),\n" + "+\t\t\tsize, size, calculate_alignment(flags, align, size),\n" + "+\t\t\tflags, ctor, NULL, NULL);\n" + "+\terr = IS_ERR(s) ? PTR_ERR(s) : 0;\n" + " \n" + " out_unlock:\n" + " \tmutex_unlock(&slab_mutex);\n" + " \tput_online_cpus();\n" + " \n" + " \tif (err) {\n" + "-\t\t/*\n" + "-\t\t * There is no point in flooding logs with warnings or\n" + "-\t\t * especially crashing the system if we fail to create a cache\n" + "-\t\t * for a memcg. In this case we will be accounting the memcg\n" + "-\t\t * allocation to the root cgroup until we succeed to create its\n" + "-\t\t * own cache, but it isn't that critical.\n" + "-\t\t */\n" + "-\t\tif (!memcg)\n" + "-\t\t\treturn NULL;\n" + "-\n" + " \t\tif (flags & SLAB_PANIC)\n" + " \t\t\tpanic(\"kmem_cache_create: Failed to create slab '%s'. Error %d\\n\",\n" + " \t\t\t\tname, err);\n" + "@@ -260,21 +244,51 @@ out_unlock:\n" + " \t\treturn NULL;\n" + " \t}\n" + " \treturn s;\n" + "-\n" + "-out_free_cache:\n" + "-\tmemcg_free_cache_params(s);\n" + "-\tkfree(s->name);\n" + "-\tkmem_cache_free(kmem_cache, s);\n" + "-\tgoto out_unlock;\n" + " }\n" + "+EXPORT_SYMBOL(kmem_cache_create);\n" + " \n" + "-struct kmem_cache *\n" + "-kmem_cache_create(const char *name, size_t size, size_t align,\n" + "-\t\t unsigned long flags, void (*ctor)(void *))\n" + "+#ifdef CONFIG_MEMCG_KMEM\n" + "+/*\n" + "+ * kmem_cache_create_memcg - Create a cache for a memory cgroup.\n" + "+ * @memcg: The memory cgroup the new cache is for.\n" + "+ * @cachep: The parent of the new cache.\n" + "+ *\n" + "+ * This function creates a kmem cache that will serve allocation requests going\n" + "+ * from @memcg to @cachep. The new cache inherits properties from its parent.\n" + "+ *\n" + "+ * Returns 0 on success, -errno on failure.\n" + "+ */\n" + "+int kmem_cache_create_memcg(struct mem_cgroup *memcg, struct kmem_cache *cachep)\n" + " {\n" + "-\treturn kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);\n" + "+\tstruct kmem_cache *s;\n" + "+\tint err;\n" + "+\n" + "+\tget_online_cpus();\n" + "+\tmutex_lock(&slab_mutex);\n" + "+\n" + "+\t/*\n" + "+\t * Since per-memcg caches are created asynchronously on first\n" + "+\t * allocation (see memcg_kmem_get_cache()), several threads can try to\n" + "+\t * create the same cache, but only one of them may succeed.\n" + "+\t */\n" + "+\terr = -EEXIST;\n" + "+\tif (cache_from_memcg_idx(cachep, memcg_cache_id(memcg)))\n" + "+\t\tgoto out_unlock;\n" + "+\n" + "+\ts = do_kmem_cache_create(memcg_create_cache_name(memcg, cachep),\n" + "+\t\t\tcachep->object_size, cachep->size, cachep->align,\n" + "+\t\t\tcachep->flags & ~SLAB_PANIC, cachep->ctor,\n" + "+\t\t\tmemcg, cachep);\n" + "+\terr = IS_ERR(s) ? PTR_ERR(s) : 0;\n" + "+\tif (!err)\n" + "+\t\ts->allocflags |= __GFP_KMEMCG;\n" + "+\n" + "+out_unlock:\n" + "+\tmutex_unlock(&slab_mutex);\n" + "+\tput_online_cpus();\n" + "+\treturn err;\n" + " }\n" + "-EXPORT_SYMBOL(kmem_cache_create);\n" + "+#endif /* CONFIG_MEMCG_KMEM */\n" + " \n" + " void kmem_cache_destroy(struct kmem_cache *s)\n" + " {\n" + "-- \n" + 1.7.10.4 -4bc74367b492c772758c5df6560dd37ddeb3d981f3e9dc635046adaa0de4ec49 +b572f405ffd91bd3b893629bf672f2c9ed53ce760bacb0f20cc364b9069040c1
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.