Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1561158 > unrolled thread
| Started by | Tejun Heo <tj@kernel.org> |
|---|---|
| First post | 2017-01-18 01:10 +0100 |
| Last post | 2017-01-27 22:20 +0100 |
| Articles | 4 — 2 participants |
Back to article view | Back to linux.kernel
[PATCHSET v3] slab: make memcg slab destruction scalable Tejun Heo <tj@kernel.org> - 2017-01-18 01:10 +0100
[PATCH 02/10] slub: separate out sysfs_slab_release() from sysfs_slab_remove() Tejun Heo <tj@kernel.org> - 2017-01-18 02:10 +0100
[PATCH v2 02/10] slub: separate out sysfs_slab_release() from sysfs_slab_remove() Tejun Heo <tj@kernel.org> - 2017-01-24 00:00 +0100
Re: [PATCH v2 02/10] slub: separate out sysfs_slab_release() from sysfs_slab_remove() Vladimir Davydov <vdavydov@tarantool.org> - 2017-01-27 22:20 +0100
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2017-01-18 01:10 +0100 |
| Subject | [PATCHSET v3] slab: make memcg slab destruction scalable |
| Message-ID | <t0LPs-54F-9@gated-at.bofh.it> |
Changes from [V2] to V3. * 0002-slub-separate-out-sysfs_slab_release-from-sysfs_slab.patch separated out from 0002-slab-remove-synchronous-rcu_barrier-call-in-memcg-ca.patch. * 0002-slab-remove-synchronous-rcu_barrier-call-in-memcg-ca.patch replaced with 0003-slab-remove-synchronous-rcu_barrier-call-in-memcg-ca.patch. It now keeps rcu_barrier() in the kmem_cache destruction path. * 0010-slab-memcg-wq.patch added to limit concurrency on destruction work items. Changes from [V1] to [V2]. * 0002-slab-remove-synchronous-rcu_barrier-call-in-memcg-ca.patch was incorrect and dropped. * 0006-slab-don-t-put-memcg-caches-on-slab_caches-list.patch incorrectly converted places which needed to walk all caches. Replaced with 0005-slab-implement-slab_root_caches-list.patch which adds root-only list instead of converting slab_caches list to list only root caches. * Misc fixes. With kmem cgroup support enabled, kmem_caches can be created and destroyed frequently and a great number of near empty kmem_caches can accumulate if there are a lot of transient cgroups and the system is not under memory pressure. When memory reclaim starts under such conditions, it can lead to consecutive deactivation and destruction of many kmem_caches, easily hundreds of thousands on moderately large systems, exposing scalability issues in the current slab management code. I've seen machines which end up with hundred thousands of caches and many millions of kernfs_nodes. The current code is O(N^2) on the total number of caches and has synchronous rcu_barrier() and synchronize_sched() in cgroup offline / release path which is executed while holding cgroup_mutex. Combined, this leads to very expensive and slow cache destruction operations which can easily keep running for half a day. This also messes up /proc/slabinfo along with other cache iterating operations. seq_file operates on 4k chunks and on each 4k boundary tries to seek to the last position in the list. With a huge number of caches on the list, this becomes very slow and very prone to the list content changing underneath it leading to a lot of missing and/or duplicate entries. This patchset addresses the scalability problem. * Add root and per-memcg lists. Update each user to use the appropriate list. * Make rcu_barrier() for SLAB_DESTROY_BY_RCU caches globally batched and asynchronous. * For dying empty slub caches, remove the sysfs files after deactivation so that we don't end up with millions of sysfs files without any useful information on them. This patchset contains the following nine patches. 0001-Revert-slub-move-synchronize_sched-out-of-slab_mutex.patch 0002-slub-separate-out-sysfs_slab_release-from-sysfs_slab.patch 0003-slab-remove-synchronous-rcu_barrier-call-in-memcg-ca.patch 0004-slab-reorganize-memcg_cache_params.patch 0005-slab-link-memcg-kmem_caches-on-their-associated-memo.patch 0006-slab-implement-slab_root_caches-list.patch 0007-slab-introduce-__kmemcg_cache_deactivate.patch 0008-slab-remove-synchronous-synchronize_sched-from-memcg.patch 0009-slab-remove-slub-sysfs-interface-files-early-for-emp.patch 0010-slab-use-memcg_kmem_cache_wq-for-slab-destruction-op.patch 0001 reverts an existing optimization to prepare for the following changes. 0002 is a prep patch. 0003 makes rcu_barrier() in release path batched and asynchronous. 0004-0006 separate out the lists. 0007-0008 replace synchronize_sched() in slub destruction path with call_rcu_sched(). 0009 removes sysfs files early for empty dying caches. 0010 makes destruction work items use a workqueue with limited concurrency. This patchset is on top of the current linus#master a121103c9228 and also available in the following git branch. git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git review-kmemcg-scalability diffstat follows. Thanks. include/linux/memcontrol.h | 2 include/linux/slab.h | 45 +++++-- include/linux/slub_def.h | 4 mm/memcontrol.c | 23 +-- mm/slab.c | 7 + mm/slab.h | 27 +++- mm/slab_common.c | 289 +++++++++++++++++++++++++++++---------------- mm/slub.c | 55 ++++++++ 8 files changed, 325 insertions(+), 127 deletions(-) -- tejun [V1] http://lkml.kernel.org/r/<20170114055449.11044-1-tj@kernel.org> [V2] http://lkml.kernel.org/r/<20170114184834.8658-1-tj@kernel.org>
[toc] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2017-01-18 02:10 +0100 |
| Subject | [PATCH 02/10] slub: separate out sysfs_slab_release() from sysfs_slab_remove() |
| Message-ID | <t0MVc-5Vf-25@gated-at.bofh.it> |
| In reply to | #1561158 |
Separate out slub sysfs removal and release, and call the former
earlier from __kmem_cache_shutdown(). There's no reason to defer
sysfs removal through RCU and this will later allow us to remove sysfs
files way earlier during memory cgroup offline instead of release.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
include/linux/slub_def.h | 4 ++--
mm/slab_common.c | 2 +-
mm/slub.c | 9 ++++++++-
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 75f56c2..07ef550 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -113,9 +113,9 @@ struct kmem_cache {
#ifdef CONFIG_SYSFS
#define SLAB_SUPPORTS_SYSFS
-void sysfs_slab_remove(struct kmem_cache *);
+void sysfs_slab_release(struct kmem_cache *);
#else
-static inline void sysfs_slab_remove(struct kmem_cache *s)
+static inline void sysfs_slab_release(struct kmem_cache *s)
{
}
#endif
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 46ff746..3bc4bb8 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -480,7 +480,7 @@ static void release_caches(struct list_head *release, bool need_rcu_barrier)
list_for_each_entry_safe(s, s2, release, list) {
#ifdef SLAB_SUPPORTS_SYSFS
- sysfs_slab_remove(s);
+ sysfs_slab_release(s);
#else
slab_kmem_cache_release(s);
#endif
diff --git a/mm/slub.c b/mm/slub.c
index 68b84f9..2b78c82 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -214,11 +214,13 @@ enum track_item { TRACK_ALLOC, TRACK_FREE };
static int sysfs_slab_add(struct kmem_cache *);
static int sysfs_slab_alias(struct kmem_cache *, const char *);
static void memcg_propagate_slab_attrs(struct kmem_cache *s);
+static void sysfs_slab_remove(struct kmem_cache *s);
#else
static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
{ return 0; }
static inline void memcg_propagate_slab_attrs(struct kmem_cache *s) { }
+static inline void sysfs_slab_remove(struct kmem_cache *s) { }
#endif
static inline void stat(const struct kmem_cache *s, enum stat_item si)
@@ -3679,6 +3681,7 @@ int __kmem_cache_shutdown(struct kmem_cache *s)
if (n->nr_partial || slabs_node(s, node))
return 1;
}
+ sysfs_slab_remove(s);
return 0;
}
@@ -5629,7 +5632,7 @@ static int sysfs_slab_add(struct kmem_cache *s)
goto out;
}
-void sysfs_slab_remove(struct kmem_cache *s)
+static void sysfs_slab_remove(struct kmem_cache *s)
{
if (slab_state < FULL)
/*
@@ -5643,6 +5646,10 @@ void sysfs_slab_remove(struct kmem_cache *s)
#endif
kobject_uevent(&s->kobj, KOBJ_REMOVE);
kobject_del(&s->kobj);
+}
+
+void sysfs_slab_release(struct kmem_cache *s)
+{
kobject_put(&s->kobj);
}
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2017-01-24 00:00 +0100 |
| Subject | [PATCH v2 02/10] slub: separate out sysfs_slab_release() from sysfs_slab_remove() |
| Message-ID | <t2VKG-48m-19@gated-at.bofh.it> |
| In reply to | #1561200 |
From 3b0cdd93b2d9bdea62ea6681e612bdae7a40d883 Mon Sep 17 00:00:00 2001
From: Tejun Heo <tj@kernel.org>
Date: Mon, 23 Jan 2017 17:53:18 -0500
Separate out slub sysfs removal and release, and call the former
earlier from __kmem_cache_shutdown(). There's no reason to defer
sysfs removal through RCU and this will later allow us to remove sysfs
files way earlier during memory cgroup offline instead of release.
v2: Add slab_state >= FULL test to sysfs_slab_release() so that
kobject_put() is skipped for caches which aren't fully initialized
as before. This most likely leaks the kmem_cache on init failure
as we're skipping the only release path. Let's fix that up later.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
v2 of the patch. Fixes boot failure reported by the test bot.
Thanks.
include/linux/slub_def.h | 4 ++--
mm/slab_common.c | 2 +-
mm/slub.c | 12 ++++++++++--
3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 75f56c2..07ef550 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -113,9 +113,9 @@ struct kmem_cache {
#ifdef CONFIG_SYSFS
#define SLAB_SUPPORTS_SYSFS
-void sysfs_slab_remove(struct kmem_cache *);
+void sysfs_slab_release(struct kmem_cache *);
#else
-static inline void sysfs_slab_remove(struct kmem_cache *s)
+static inline void sysfs_slab_release(struct kmem_cache *s)
{
}
#endif
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 46ff746..3bc4bb8 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -480,7 +480,7 @@ static void release_caches(struct list_head *release, bool need_rcu_barrier)
list_for_each_entry_safe(s, s2, release, list) {
#ifdef SLAB_SUPPORTS_SYSFS
- sysfs_slab_remove(s);
+ sysfs_slab_release(s);
#else
slab_kmem_cache_release(s);
#endif
diff --git a/mm/slub.c b/mm/slub.c
index 68b84f9..59ca718 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -214,11 +214,13 @@ enum track_item { TRACK_ALLOC, TRACK_FREE };
static int sysfs_slab_add(struct kmem_cache *);
static int sysfs_slab_alias(struct kmem_cache *, const char *);
static void memcg_propagate_slab_attrs(struct kmem_cache *s);
+static void sysfs_slab_remove(struct kmem_cache *s);
#else
static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
{ return 0; }
static inline void memcg_propagate_slab_attrs(struct kmem_cache *s) { }
+static inline void sysfs_slab_remove(struct kmem_cache *s) { }
#endif
static inline void stat(const struct kmem_cache *s, enum stat_item si)
@@ -3679,6 +3681,7 @@ int __kmem_cache_shutdown(struct kmem_cache *s)
if (n->nr_partial || slabs_node(s, node))
return 1;
}
+ sysfs_slab_remove(s);
return 0;
}
@@ -5629,7 +5632,7 @@ static int sysfs_slab_add(struct kmem_cache *s)
goto out;
}
-void sysfs_slab_remove(struct kmem_cache *s)
+static void sysfs_slab_remove(struct kmem_cache *s)
{
if (slab_state < FULL)
/*
@@ -5643,7 +5646,12 @@ void sysfs_slab_remove(struct kmem_cache *s)
#endif
kobject_uevent(&s->kobj, KOBJ_REMOVE);
kobject_del(&s->kobj);
- kobject_put(&s->kobj);
+}
+
+void sysfs_slab_release(struct kmem_cache *s)
+{
+ if (slab_state >= FULL)
+ kobject_put(&s->kobj);
}
/*
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Vladimir Davydov <vdavydov@tarantool.org> |
|---|---|
| Date | 2017-01-27 22:20 +0100 |
| Subject | Re: [PATCH v2 02/10] slub: separate out sysfs_slab_release() from sysfs_slab_remove() |
| Message-ID | <t4m66-Rh-15@gated-at.bofh.it> |
| In reply to | #1565351 |
On Mon, Jan 23, 2017 at 05:54:49PM -0500, Tejun Heo wrote: > From 3b0cdd93b2d9bdea62ea6681e612bdae7a40d883 Mon Sep 17 00:00:00 2001 > From: Tejun Heo <tj@kernel.org> > Date: Mon, 23 Jan 2017 17:53:18 -0500 > > Separate out slub sysfs removal and release, and call the former > earlier from __kmem_cache_shutdown(). There's no reason to defer > sysfs removal through RCU and this will later allow us to remove sysfs > files way earlier during memory cgroup offline instead of release. > > v2: Add slab_state >= FULL test to sysfs_slab_release() so that > kobject_put() is skipped for caches which aren't fully initialized > as before. This most likely leaks the kmem_cache on init failure > as we're skipping the only release path. Let's fix that up later. > > Signed-off-by: Tejun Heo <tj@kernel.org> > Cc: Vladimir Davydov <vdavydov.dev@gmail.com> > Cc: Christoph Lameter <cl@linux.com> > Cc: Pekka Enberg <penberg@kernel.org> > Cc: David Rientjes <rientjes@google.com> > Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> > Cc: Andrew Morton <akpm@linux-foundation.org> Acked-by: Vladimir Davydov <vdavydov.dev@gmail.com>
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web