memcg-vs-slab related fixes, improvements, cleanups
Subsystems (3)
v3 cover memcg-vs-slab related fixes, improvements, cleanups
Hi,
This patch set mostly cleanups memcg slab caches creation/destruction paths fixing a couple of bugs in the meanwhile. The only serious change it introduces is a rework of the sysfs layout for memcg slub caches (see patch 7).
Changes in v3 (thanks to Michal Hocko):
- improve patch descriptions
- overall cleanup
- rebase onto v3.14-rc3
Changes in v2 (thanks to David Rientjes):
- do not remove cgroup name part from memcg cache names
- do not export memcg cache id to userspace
Thanks,
Vladimir Davydov (7):
memcg, slab: never try to merge memcg caches
memcg, slab: cleanup memcg cache creation
memcg, slab: separate memcg vs root cache creation paths memcg, slab: unregister cache from memcg before starting to destroy
it
memcg, slab: do not destroy children caches if parent has aliases
slub: adjust memcg caches when creating cache alias
slub: rework sysfs layout for memcg caches
include/linux/memcontrol.h | 9 +- include/linux/slab.h | 6 +- include/linux/slub_def.h | 3 + mm/memcontrol.c | 109 ++++++++----------- mm/slab.h | 21 +--- mm/slab_common.c | 250 +++++++++++++++++++++++++++----------------- mm/slub.c | 58 ++++++++-- 7 files changed, 261 insertions(+), 195 deletions(-)
Signature · 7 lines
1.7.10.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 1/7 memcg, slab: never try to merge memcg caches
When a kmem cache is created (kmem_cache_create_memcg()), we first try to find a compatible cache that already exists and can handle requests from the new cache, i.e. has the same object size, alignment, ctor, etc. If there is such a cache, we do not create any new caches, instead we simply increment the refcount of the cache found and return it.
Currently we do this procedure not only when creating root caches, but also for memcg caches. However, there is no point in that, because, as every memcg cache has exactly the same parameters as its parent and cache merging cannot be turned off in runtime (only on boot by passing "slub_nomerge"), the root caches of any two potentially mergeable memcg caches should be merged already, i.e. it must be the same root cache, and therefore we couldn't even get to the memcg cache creation, because it already exists.
The only exception is boot caches - they are explicitly forbidden to be merged by setting their refcount to -1. There are currently only two of them - kmem_cache and kmem_cache_node, which are used in slab internals (I do not count kmalloc caches as their refcount is set to 1 immediately after creation). Since they are prevented from merging preliminary I guess we should avoid to merge their children too.
So let's remove the useless code responsible for merging memcg caches.
--- mm/slab.h | 21 ++++----------------- mm/slab_common.c | 8 +++++--- mm/slub.c | 19 +++++++++---------- 3 files changed, 18 insertions(+), 30 deletions(-)
mm/slab.h +4 -17
@@ -55,12 +55,12 @@ extern void create_boot_cache(struct kmem_cache *, const char *name,struct mem_cgroup ;#ifdef CONFIG_SLUB struct kmem_cache * -__kmem_cache_alias (struct mem_cgroup *memcg,const char *name,size_t size, -size_t align,unsigned long flags,void (*ctor)(void *)); +__kmem_cache_alias (const char *name,size_t size,size_t align, +unsigned long flags,void (*ctor)(void *));#else static inline struct kmem_cache * -__kmem_cache_alias (struct mem_cgroup *memcg,const char *name,size_t size, -size_t align,unsigned long flags,void (*ctor)(void *)) +__kmem_cache_alias (const char *name,size_t size,size_t align, +unsigned long flags,void (*ctor)(void *)) {return NULL ; }#endif
@@ -119,13 +119,6 @@ static inline bool is_root_cache(struct kmem_cache *s)return !s->memcg_params || s->memcg_params->is_root_cache; } -static inline bool cache_match_memcg (struct kmem_cache *cachep, -struct mem_cgroup *memcg) -{ -return (is_root_cache (cachep) && !memcg) || - (cachep->memcg_params->memcg == memcg); -} -static inline void memcg_bind_pages (struct kmem_cache *s,int order) {if (!is_root_cache (s))
@@ -204,12 +197,6 @@ static inline bool is_root_cache(struct kmem_cache *s)return true; } -static inline bool cache_match_memcg (struct kmem_cache *cachep, -struct mem_cgroup *memcg) -{ -return true; -} -static inline void memcg_bind_pages (struct kmem_cache *s,int order) { }
mm/slab_common.c +5 -3
@@ -200,9 +200,11 @@ kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size,*/ flags &=CACHE_CREATE_MASK ; - s =__kmem_cache_alias (memcg, name, size, align, flags, ctor); -if (s) - goto out_unlock; +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 );
mm/slub.c +9 -10
@@ -3685,6 +3685,9 @@ static int slab_unmergeable(struct kmem_cache *s)if (slub_nomerge || (s->flags &SLUB_NEVER_MERGE ))return 1 ; +if (!is_root_cache (s)) +return 1 ; +if (s->ctor)return 1 ;
@@ -3697,9 +3700,8 @@ static int slab_unmergeable(struct kmem_cache *s)return 0 ; } -static struct kmem_cache *find_mergeable (struct mem_cgroup *memcg,size_t size, -size_t align,unsigned long flags,const char *name, -void (*ctor)(void *)) +static struct kmem_cache *find_mergeable (size_t size,size_t align, +unsigned long flags,const char *name,void (*ctor)(void *)) {struct kmem_cache *s;
@@ -3722,7 +3724,7 @@ static struct kmem_cache *find_mergeable(struct mem_cgroup *memcg, size_t size,continue ;if ((flags &SLUB_MERGE_SAME ) != (s->flags &SLUB_MERGE_SAME )) -continue ; +continue ;/* * Check if alignment is compatible. * Courtesy of Adrian Drzewiecki
@@ -3733,21 +3735,18 @@ static struct kmem_cache *find_mergeable(struct mem_cgroup *memcg, size_t size,if (s->size - size >=sizeof (void *))continue ; -if (!cache_match_memcg (s, memcg)) -continue ; -return s; }return NULL ; }struct kmem_cache * -__kmem_cache_alias (struct mem_cgroup *memcg,const char *name,size_t size, -size_t align,unsigned long flags,void (*ctor)(void *)) +__kmem_cache_alias (const char *name,size_t size,size_t align, +unsigned long flags,void (*ctor)(void *)) {struct kmem_cache *s; - s =find_mergeable (memcg, size, align, flags, name, ctor); + s =find_mergeable (size, align, flags, name, ctor);if (s) { s->refcount++;/*
Signature · 7 lines
1.7.10.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 2/7 memcg, slab: cleanup memcg cache creation
In reply to Vladimir DavydovThis patch cleanups the memcg cache creation path as follows:
- Move memcg cache name creation to a separate function to be called from kmem_cache_create_memcg(). This allows us to get rid of the mutex protecting the temporary buffer used for the name formatting, because the whole cache creation path is protected by the slab_mutex.
- Get rid of memcg_create_kmem_cache(). This function serves as a proxy to kmem_cache_create_memcg(). After separating the cache name creation path, it would be reduced to a function call, so let's inline it.
--- include/linux/memcontrol.h | 9 +++++ mm/memcontrol.c | 89 +++++++++++++++++++------------------------- mm/slab_common.c | 5 ++- 3 files changed, 52 insertions(+), 51 deletions(-)
include/linux/memcontrol.h +9 -0
@@ -497,6 +497,9 @@ void __memcg_kmem_commit_charge(struct page *page,void __memcg_kmem_uncharge_pages (struct page *page,int order);int memcg_cache_id (struct mem_cgroup *memcg); + +char *memcg_create_cache_name (struct mem_cgroup *memcg, +struct kmem_cache *root_cache);int memcg_alloc_cache_params (struct mem_cgroup *memcg,struct kmem_cache *s,struct kmem_cache *root_cache);void memcg_free_cache_params (struct kmem_cache *s);
@@ -641,6 +644,12 @@ static inline int memcg_cache_id(struct mem_cgroup *memcg)return -1 ; } +static inline char *memcg_create_cache_name (struct mem_cgroup *memcg, +struct kmem_cache *root_cache) +{ +return NULL ; +} +static inline int memcg_alloc_cache_params (struct mem_cgroup *memcg,struct kmem_cache *s,struct kmem_cache *root_cache) {
mm/memcontrol.c +39 -50
116 lines not on this page · raw message
mm/slab_common.c +4 -1
@@ -215,7 +215,10 @@ kmem_cache_create_memcg(struct mem_cgroup *memcg, const char *name, size_t size, s->align =calculate_alignment (flags, align, size); s->ctor = ctor; - s->name =kstrdup (name,GFP_KERNEL ); +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;
Signature · 7 lines
1.7.10.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerRe: [PATCH -mm v3 2/7] memcg, slab: cleanup memcg cache creation
Quoted 9 lines · On Thu, 20 Feb 2014 11:22:04 +0400 Vladimir Davydov <[email protected]>…
This patch cleanups the memcg cache creation path as follows:
- Move memcg cache name creation to a separate function to be called fromkmem_cache_create_memcg(). This allows us to get rid of the mutex protecting the temporary buffer used for the name formatting, because the whole cache creation path is protected by theslab_mutex.
- Get rid ofmemcg_create_kmem_cache(). This function serves as a proxy tokmem_cache_create_memcg(). After separating the cache name creation path, it would be reduced to a function call, so let's inline it.
This patch makes a huge mess when it hits linux-next's e61734c5 ("cgroup: remove cgroup->name"). In the vicinity of memcg_create_kmem_cache(). That isn't the first mess e61734c5 made :(
I think I got it all fixed up - please check the end result in
http://ozlabs.org/~akpm/stuff/.
Re: [PATCH -mm v3 2/7] memcg, slab: cleanup memcg cache creation
Quoted 11 lines · Andrew Morton
Quoted 9 lines · On Thu, 20 Feb 2014 11:22:04 +0400 Vladimir Davydov <[email protected]>…
This patch cleanups the memcg cache creation path as follows:
- Move memcg cache name creation to a separate function to be called fromkmem_cache_create_memcg(). This allows us to get rid of the mutex protecting the temporary buffer used for the name formatting, because the whole cache creation path is protected by theslab_mutex.
- Get rid ofmemcg_create_kmem_cache(). This function serves as a proxy tokmem_cache_create_memcg(). After separating the cache name creation path, it would be reduced to a function call, so let's inline it.
Quoted 6 lines
This patch makes a huge mess when it hits linux-next's
e61734c5("cgroup: removecgroup->name"). In the vicinity ofmemcg_create_kmem_cache(). That isn't the first messe61734c5made :(I think I got it all fixed up - please check the end result in
http://ozlabs.org/~akpm/stuff/.
It looks good to me, thank you!
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 3/7 memcg, slab: separate memcg vs root cache creation paths
In reply to Vladimir DavydovMemcg-awareness turned kmem_cache_create() into a dirty interweaving of memcg-only and except-for-memcg calls. To clean this up, let's move the code responsible for memcg cache creation to a separate function.
--- include/linux/memcontrol.h | 6 -- include/linux/slab.h | 6 +- mm/memcontrol.c | 7 +- mm/slab_common.c | 187 +++++++++++++++++++++++++------------------- 4 files changed, 111 insertions(+), 95 deletions(-)
include/linux/memcontrol.h +0 -6
@@ -644,12 +644,6 @@ static inline int memcg_cache_id(struct mem_cgroup *memcg)return -1 ; } -static inline char *memcg_create_cache_name (struct mem_cgroup *memcg, -struct kmem_cache *root_cache) -{ -return NULL ; -} -static inline int memcg_alloc_cache_params (struct mem_cgroup *memcg,struct kmem_cache *s,struct kmem_cache *root_cache) {
include/linux/slab.h +3 -3
@@ -115,9 +115,9 @@ 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 *); +#ifdef CONFIG_MEMCG_KMEM +void 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 *);
mm/memcontrol.c +1 -6
@@ -3460,13 +3460,8 @@ 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 *cachep = cw->cachep; -struct kmem_cache *new; - new =kmem_cache_create_memcg (memcg, cachep->name, - cachep->object_size, cachep->align, - cachep->flags & ~SLAB_PANIC , cachep->ctor, cachep); -if (new) - new->allocflags |= __GFP_KMEMCG; +kmem_cache_create_memcg (memcg, cachep);css_put (&memcg->css);kfree (cw); }
mm/slab_common.c +107 -80
252 lines not on this page · raw message
Signature · 7 lines
1.7.10.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 4/7 memcg, slab: unregister cache from memcg before starting to destroy it
In reply to Vladimir DavydovCurrently, memcg_unregister_cache(), which deletes the cache being destroyed from the memcg_slab_caches list, is called after __kmem_cache_shutdown() (see kmem_cache_destroy()), which starts to destroy the cache. As a result, one can access a partially destroyed cache while traversing a memcg_slab_caches list, which can have deadly consequences (for instance, cache_show() called for each cache on a memcg_slab_caches list from mem_cgroup_slabinfo_read() will dereference pointers to already freed data).
To fix this, let's move memcg_unregister_cache() before the cache destruction process beginning, issuing memcg_register_cache() on failure.
--- mm/memcontrol.c | 12 ++++++------ mm/slab_common.c | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-)
mm/memcontrol.c +6 -6
@@ -3205,6 +3205,7 @@ int memcg_alloc_cache_params(struct mem_cgroup *memcg, struct kmem_cache *s, s->memcg_params->root_cache = root_cache;INIT_WORK (&s->memcg_params->destroy, kmem_cache_destroy_work_func); +css_get (&memcg->css); }else s->memcg_params->is_root_cache = true;
@@ -3213,6 +3214,10 @@ int memcg_alloc_cache_params(struct mem_cgroup *memcg, struct kmem_cache *s,void memcg_free_cache_params (struct kmem_cache *s) { +if (!s->memcg_params) +return ; +if (!s->memcg_params->is_root_cache) +css_put (&s->memcg_params->memcg->css);kfree (s->memcg_params); }
@@ -3235,9 +3240,6 @@ void memcg_register_cache(struct kmem_cache *s) memcg = s->memcg_params->memcg; id =memcg_cache_id (memcg); -css_get (&memcg->css); - -/* * Since readers won't lock (see cache_from_memcg_idx()), we need a * barrier here to ensure nobody will see the kmem_cache partially
@@ -3286,10 +3288,8 @@ void memcg_unregister_cache(struct kmem_cache *s)* after removing it from the memcg_slab_caches list, otherwise we can * fail to convert memcg_params_to_cache() while traversing the list. */ -VM_BUG_ON (!root->memcg_params->memcg_caches[id]); +VM_BUG_ON (root->memcg_params->memcg_caches[id] != s); root->memcg_params->memcg_caches[id] =NULL ; - -css_put (&memcg->css); }/*
mm/slab_common.c +2 -1
@@ -313,9 +313,9 @@ void kmem_cache_destroy(struct kmem_cache *s) s->refcount--;if (!s->refcount) {list_del (&s->list); +memcg_unregister_cache (s);if (!__kmem_cache_shutdown (s)) { -memcg_unregister_cache (s);mutex_unlock (&slab_mutex);if (s->flags &SLAB_DESTROY_BY_RCU )rcu_barrier ();
@@ -325,6 +325,7 @@ void kmem_cache_destroy(struct kmem_cache *s)kmem_cache_free (kmem_cache, s); }else {list_add (&s->list, &slab_caches); +memcg_register_cache (s);mutex_unlock (&slab_mutex);printk (KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n" , s->name);
Signature · 7 lines
1.7.10.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 5/7 memcg, slab: do not destroy children caches if parent has aliases
In reply to Vladimir DavydovCurrently we destroy children caches at the very beginning of kmem_cache_destroy(). This is wrong, because the root cache will not necessarily be destroyed in the end - if it has aliases (refcount > 0), kmem_cache_destroy() will simply decrement its refcount and return. In this case, at best we will get a bunch of warnings in dmesg, like this one:
kmem_cache_destroy kmalloc-32:0: Slab cache still has objects
CPU: 1 PID: 7139 Comm: modprobe Tainted: G B W 3.13.0+ #117 Hardware name: ffff88007d7a6368 ffff880039b07e48 ffffffff8168cc2e ffff88007d7a6d68 ffff88007d7a6300 ffff880039b07e68 ffffffff81175e9f 0000000000000000 ffff88007d7a6300 ffff880039b07e98 ffffffff811b67c7 ffff88003e803c00 Call Trace: [<ffffffff8168cc2e>] dump_stack+0x49/0x5b [<ffffffff81175e9f>] kmem_cache_destroy+0xdf/0xf0 [<ffffffff811b67c7>] kmem_cache_destroy_memcg_children+0x97/0xc0 [<ffffffff81175dcf>] kmem_cache_destroy+0xf/0xf0 [<ffffffffa0130b21>] xfs_mru_cache_uninit+0x21/0x30 [xfs] [<ffffffffa01893ea>] exit_xfs_fs+0x2e/0xc44 [xfs] [<ffffffff810eeb58>] SyS_delete_module+0x198/0x1f0 [<ffffffff816994f9>] system_call_fastpath+0x16/0x1b
At worst - if kmem_cache_destroy() will race with an allocation from a memcg cache - the kernel will panic.
This patch fixes this by moving children caches destruction after the check if the cache has aliases. Plus, it forbids destroying a root cache if it still has children caches, because each children cache keeps a reference to its parent.
--- include/linux/memcontrol.h | 6 +--- mm/memcontrol.c | 13 ++++---- mm/slab_common.c | 75 +++++++++++++++++++++++++++++--------------- 3 files changed, 57 insertions(+), 37 deletions(-)
include/linux/memcontrol.h +1 -5
@@ -513,7 +513,7 @@ struct kmem_cache * __memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp);void mem_cgroup_destroy_cache (struct kmem_cache *cachep); -void kmem_cache_destroy_memcg_children (struct kmem_cache *s); +int __kmem_cache_destroy_memcg_children (struct kmem_cache *s);/** * memcg_kmem_newpage_charge: verify if a new kmem allocation is allowed.
@@ -667,10 +667,6 @@ memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp) {return cachep; } - -static inline void kmem_cache_destroy_memcg_children (struct kmem_cache *s) -{ -}#endif /* CONFIG_MEMCG_KMEM */ #endif /* _LINUX_MEMCONTROL_H */
mm/memcontrol.c +6 -7
@@ -3386,15 +3386,10 @@ void mem_cgroup_destroy_cache(struct kmem_cache *cachep)schedule_work (&cachep->memcg_params->destroy); } -void kmem_cache_destroy_memcg_children (struct kmem_cache *s) +int __kmem_cache_destroy_memcg_children (struct kmem_cache *s) {struct kmem_cache *c; -int i; - -if (!s->memcg_params) -return ; -if (!s->memcg_params->is_root_cache) -return ; +int i, failed =0 ;/* * If the cache is being destroyed, we trust that there is no one else
@@ -3428,8 +3423,12 @@ void kmem_cache_destroy_memcg_children(struct kmem_cache *s) c->memcg_params->dead = false;cancel_work_sync (&c->memcg_params->destroy);kmem_cache_destroy (c); + +if (cache_from_memcg_idx (s, i)) + failed++; }mutex_unlock (&activate_kmem_mutex); +return failed; }static void mem_cgroup_destroy_all_caches (struct mem_cgroup *memcg)
mm/slab_common.c +50 -25
89 lines not on this page · raw message
Signature · 7 lines
1.7.10.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 6/7 slub: adjust memcg caches when creating cache alias
In reply to Vladimir DavydovOtherwise, kzalloc() called from a memcg won't clear the whole object.
--- mm/slub.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
mm/slub.c +13 -0
@@ -3748,7 +3748,11 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, s =find_mergeable (size, align, flags, name, ctor);if (s) { +int i; +struct kmem_cache *c; + s->refcount++; +/* * Adjust the object sizes so that we clear * the complete object on kzalloc.
@@ -3756,6 +3760,15 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, s->object_size =max (s->object_size, (int )size); s->inuse =max_t (int, s->inuse,ALIGN (size,sizeof (void *))); +for_each_memcg_cache_index (i) { + c =cache_from_memcg_idx (s, i); +if (!c) +continue ; + c->object_size = s->object_size; + c->inuse =max_t (int, c->inuse, +ALIGN (size,sizeof (void *))); + } +if (sysfs_slab_alias (s, name)) { s->refcount--; s =NULL ;
Signature · 7 lines
1.7.10.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 7/7 slub: rework sysfs layout for memcg caches
In reply to Vladimir DavydovCurrently, we try to arrange sysfs entries for memcg caches in the same manner as for global caches. Apart from turning /sys/kernel/slab into a mess when there are a lot of kmem-active memcgs created, it actually does not work properly - we won't create more than one link to a memcg cache in case its parent is merged with another cache. For instance, if A is a root cache merged with another root cache B, we will have the following sysfs setup:
X
A -> X
B -> X
where X is some unique id (see create_unique_id()). Now if memcgs M and N start to allocate from cache A (or B, which is the same), we will get:
X
X:M
X:N
A -> X
B -> X
A:M -> X:M
A:N -> X:N
Since B is an alias for A, we won't get entries B:M and B:N, which is confusing.
It is more logical to have entries for memcg caches under the corresponding root cache's sysfs directory. This would allow us to keep sysfs layout clean, and avoid such inconsistencies like one described above.
This patch does the trick. It creates a "cgroup" kset in each root cache kobject to keep its children caches there.
--- include/linux/slub_def.h | 3 +++ mm/slub.c | 26 +++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-)
include/linux/slub_def.h +3 -0
@@ -87,6 +87,9 @@ struct kmem_cache {#ifdef CONFIG_MEMCG_KMEM struct memcg_cache_params *memcg_params;int max_attr_size;/* for propagation, maximum size of a stored attr */ +#ifdef CONFIG_SYSFS +struct kset *memcg_kset; +#endif #endif #ifdef CONFIG_NUMA
mm/slub.c +25 -1
@@ -5138,6 +5138,15 @@ static const struct kset_uevent_ops slab_uevent_ops = {static struct kset *slab_kset; +static inline struct kset *cache_kset (struct kmem_cache *s) +{ +#ifdef CONFIG_MEMCG_KMEM +if (!is_root_cache (s)) +return s->memcg_params->root_cache->memcg_kset; +#endif +return slab_kset; +} +#define ID_STR_LENGTH 64/* Create a unique string id for a slab cache:
@@ -5203,7 +5212,7 @@ static int sysfs_slab_add(struct kmem_cache *s) name =create_unique_id (s); } - s->kobj.kset = slab_kset; + s->kobj.kset =cache_kset (s); err =kobject_init_and_add (&s->kobj, &slab_ktype,NULL ,"%s" , name);if (err) {kobject_put (&s->kobj);
@@ -5216,6 +5225,18 @@ static int sysfs_slab_add(struct kmem_cache *s)kobject_put (&s->kobj);return err; } + +#ifdef CONFIG_MEMCG_KMEM +if (is_root_cache (s)) { + s->memcg_kset =kset_create_and_add ("cgroup" ,NULL , &s->kobj); +if (!s->memcg_kset) { +kobject_del (&s->kobj); +kobject_put (&s->kobj); +return -ENOMEM ; + } + } +#endif +kobject_uevent (&s->kobj,KOBJ_ADD );if (!unmergeable) {/* Setup first alias */
@@ -5234,6 +5255,9 @@ static void sysfs_slab_remove(struct kmem_cache *s)*/ return ; +#ifdef CONFIG_MEMCG_KMEM +kset_unregister (s->memcg_kset); +#endif kobject_uevent (&s->kobj,KOBJ_REMOVE );kobject_del (&s->kobj);kobject_put (&s->kobj);
Signature · 7 lines
1.7.10.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>