Skip to content

Commit

Permalink
slub: rework sysfs layout for memcg caches
Browse files Browse the repository at this point in the history
Currently, 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.

Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Glauber Costa <glommer@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Vladimir Davydov authored and Linus Torvalds committed Apr 7, 2014
1 parent 84d0ddd commit 9a41707
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/linux/slub_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 25 additions & 1 deletion mm/slub.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand All @@ -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 */
Expand All @@ -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);
Expand Down

0 comments on commit 9a41707

Please sign in to comment.