From: Glauber Costa <glommer@parallels.com>
To: linux-kernel@vger.kernel.org
Cc: cgroups@vger.kernel.org, linux-mm@kvack.org,
kamezawa.hiroyu@jp.fujitsu.com, Tejun Heo <tj@kernel.org>,
Li Zefan <lizefan@huawei.com>, Greg Thelen <gthelen@google.com>,
Suleiman Souhlal <suleiman@google.com>,
Michal Hocko <mhocko@suse.cz>,
Johannes Weiner <hannes@cmpxchg.org>,
devel@openvz.org, David Rientjes <rientjes@google.com>,
Glauber Costa <glommer@parallels.com>,
Christoph Lameter <cl@linux.com>,
Pekka Enberg <penberg@cs.helsinki.fi>
Subject: [PATCH v3 23/28] slab: Track all the memcg children of a kmem_cache.
Date: Fri, 25 May 2012 17:03:43 +0400 [thread overview]
Message-ID: <1337951028-3427-24-git-send-email-glommer@parallels.com> (raw)
In-Reply-To: <1337951028-3427-1-git-send-email-glommer@parallels.com>
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.
Code is inspired by Suleiman's, with adaptations to
the patchset and simplifications by me.
Signed-off-by: Suleiman Souhlal <suleiman@google.com>
Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: Christoph Lameter <cl@linux.com>
CC: Pekka Enberg <penberg@cs.helsinki.fi>
CC: Michal Hocko <mhocko@suse.cz>
CC: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
CC: Johannes Weiner <hannes@cmpxchg.org>
---
include/linux/memcontrol.h | 1 +
include/linux/slab.h | 1 +
mm/memcontrol.c | 13 ++++++++-
mm/slab.c | 61 +++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index df049e1..63113de 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -465,6 +465,7 @@ extern struct static_key mem_cgroup_kmem_enabled_key;
#define mem_cgroup_kmem_on static_key_false(&mem_cgroup_kmem_enabled_key)
void mem_cgroup_destroy_cache(struct kmem_cache *cachep);
+void mem_cgroup_remove_child_kmem_cache(struct kmem_cache *cachep, int id);
#else
static inline void mem_cgroup_register_cache(struct mem_cgroup *memcg,
struct kmem_cache *s)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 25f073e..714aeab 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -172,6 +172,7 @@ struct mem_cgroup_cache_params {
struct kmem_cache *parent;
#endif
struct list_head destroyed_list; /* Used when deleting memcg cache */
+ struct list_head sibling_list;
};
#endif
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e2576c5..08f3c3e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -542,10 +542,11 @@ void mem_cgroup_register_cache(struct mem_cgroup *memcg,
cachep->memcg_params.memcg = memcg;
- if (!memcg)
+ if (!memcg) {
id = ida_simple_get(&cache_types, 0, MAX_KMEM_CACHE_TYPES,
GFP_KERNEL);
- else
+ INIT_LIST_HEAD(&cachep->memcg_params.sibling_list);
+ } else
INIT_LIST_HEAD(&cachep->memcg_params.destroyed_list);
cachep->memcg_params.id = id;
}
@@ -845,6 +846,14 @@ struct kmem_cache *__mem_cgroup_get_kmem_cache(struct kmem_cache *cachep,
}
EXPORT_SYMBOL(__mem_cgroup_get_kmem_cache);
+void mem_cgroup_remove_child_kmem_cache(struct kmem_cache *cachep, int id)
+{
+ mutex_lock(&memcg_cache_mutex);
+ cachep->memcg_params.memcg->slabs[id] = NULL;
+ mutex_unlock(&memcg_cache_mutex);
+ mem_cgroup_put(cachep->memcg_params.memcg);
+}
+
bool __mem_cgroup_new_kmem_page(struct page *page, gfp_t gfp)
{
struct mem_cgroup *memcg;
diff --git a/mm/slab.c b/mm/slab.c
index 59f1027..cb409ae 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2661,6 +2661,8 @@ struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg,
goto out;
}
+ list_add(&new->memcg_params.sibling_list,
+ &cachep->memcg_params.sibling_list);
if ((cachep->limit != new->limit) ||
(cachep->batchcount != new->batchcount) ||
(cachep->shared != new->shared))
@@ -2829,6 +2831,33 @@ int kmem_cache_shrink(struct kmem_cache *cachep)
}
EXPORT_SYMBOL(kmem_cache_shrink);
+static void kmem_cache_destroy_memcg_children(struct kmem_cache *cachep)
+{
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+ struct kmem_cache *c;
+ struct mem_cgroup_cache_params *p, *tmp;
+ int id = cachep->memcg_params.id;
+
+ if (id == -1)
+ return;
+
+ mutex_lock(&cache_chain_mutex);
+ list_for_each_entry_safe(p, tmp,
+ &cachep->memcg_params.sibling_list, sibling_list) {
+ c = container_of(p, struct kmem_cache, memcg_params);
+ if (WARN_ON(c == cachep))
+ continue;
+
+ mutex_unlock(&cache_chain_mutex);
+ BUG_ON(c->memcg_params.id != -1);
+ mem_cgroup_remove_child_kmem_cache(c, id);
+ kmem_cache_destroy(c);
+ mutex_lock(&cache_chain_mutex);
+ }
+ mutex_unlock(&cache_chain_mutex);
+#endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
+}
+
/**
* kmem_cache_destroy - delete a cache
* @cachep: the cache to destroy
@@ -2849,6 +2878,9 @@ void kmem_cache_destroy(struct kmem_cache *cachep)
{
BUG_ON(!cachep || in_interrupt());
+ /* Destroy all the children caches if we aren't a memcg cache */
+ kmem_cache_destroy_memcg_children(cachep);
+
/* Find the cache in the chain of caches. */
get_online_cpus();
mutex_lock(&cache_chain_mutex);
@@ -2869,6 +2901,7 @@ void kmem_cache_destroy(struct kmem_cache *cachep)
mem_cgroup_release_cache(cachep);
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+ list_del(&cachep->memcg_params.sibling_list);
/* memcg cache: free the name string. Doing it here saves us
* a pointer to it outside the slab code */
if (cachep->memcg_params.id == -1)
@@ -4243,7 +4276,7 @@ static void do_ccupdate_local(void *info)
}
/* Always called with the cache_chain_mutex held */
-static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
+static int __do_tune_cpucache(struct kmem_cache *cachep, int limit,
int batchcount, int shared, gfp_t gfp)
{
struct ccupdate_struct *new;
@@ -4286,6 +4319,32 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
return alloc_kmemlist(cachep, gfp);
}
+static int do_tune_cpucache(struct kmem_cache *cachep, int limit,
+ int batchcount, int shared, gfp_t gfp)
+{
+ int ret;
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+ struct kmem_cache *c;
+ struct mem_cgroup_cache_params *p;
+#endif
+
+ ret = __do_tune_cpucache(cachep, limit, batchcount, shared, gfp);
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+ if (g_cpucache_up < FULL)
+ return ret;
+
+ if ((ret < 0) || (cachep->memcg_params.id == -1))
+ return ret;
+
+ list_for_each_entry(p, &cachep->memcg_params.sibling_list, sibling_list) {
+ c = container_of(p, struct kmem_cache, memcg_params);
+ /* return value determined by the parent cache only */
+ __do_tune_cpucache(c, limit, batchcount, shared, gfp);
+ }
+#endif
+ return ret;
+}
+
/* Called with cache_chain_mutex held always */
static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp)
{
--
1.7.7.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2012-05-25 13:08 UTC|newest]
Thread overview: 90+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-25 13:03 [PATCH v3 00/28] kmem limitation for memcg Glauber Costa
2012-05-25 13:03 ` [PATCH v3 01/28] slab: move FULL state transition to an initcall Glauber Costa
2012-05-25 13:03 ` [PATCH v3 02/28] memcg: Always free struct memcg through schedule_work() Glauber Costa
2012-05-25 13:03 ` [PATCH v3 03/28] slab: rename gfpflags to allocflags Glauber Costa
2012-05-25 13:03 ` [PATCH v3 04/28] memcg: Make it possible to use the stock for more than one page Glauber Costa
2012-05-25 13:03 ` [PATCH v3 05/28] memcg: Reclaim when more than one page needed Glauber Costa
2012-05-29 14:19 ` Christoph Lameter
2012-05-29 14:20 ` Christoph Lameter
2012-05-29 15:45 ` Glauber Costa
2012-05-25 13:03 ` [PATCH v3 06/28] slab: use obj_size field of struct kmem_cache when not debugging Glauber Costa
2012-05-25 13:03 ` [PATCH v3 07/28] memcg: change defines to an enum Glauber Costa
2012-05-25 13:03 ` [PATCH v3 08/28] res_counter: don't force return value checking in res_counter_charge_nofail Glauber Costa
2012-05-25 13:03 ` [PATCH v3 09/28] kmem slab accounting basic infrastructure Glauber Costa
2012-05-25 13:03 ` [PATCH v3 10/28] slab/slub: struct memcg_params Glauber Costa
2012-05-25 13:03 ` [PATCH v3 11/28] slub: consider a memcg parameter in kmem_create_cache Glauber Costa
2012-05-25 13:03 ` [PATCH v3 12/28] slab: pass memcg parameter to kmem_cache_create Glauber Costa
2012-05-29 14:27 ` Christoph Lameter
2012-05-29 15:50 ` Glauber Costa
2012-05-29 16:33 ` Christoph Lameter
2012-05-29 16:36 ` Glauber Costa
2012-05-29 16:52 ` Christoph Lameter
2012-05-29 16:59 ` Glauber Costa
2012-05-30 11:01 ` Frederic Weisbecker
2012-05-25 13:03 ` [PATCH v3 13/28] slub: create duplicate cache Glauber Costa
2012-05-29 14:36 ` Christoph Lameter
2012-05-29 15:56 ` Glauber Costa
2012-05-29 16:05 ` Christoph Lameter
2012-05-29 17:05 ` Glauber Costa
2012-05-29 17:25 ` Christoph Lameter
2012-05-29 17:27 ` Glauber Costa
2012-05-29 19:26 ` Christoph Lameter
2012-05-29 19:40 ` Glauber Costa
2012-05-29 19:55 ` Christoph Lameter
2012-05-29 20:08 ` Glauber Costa
2012-05-29 20:21 ` Christoph Lameter
2012-05-29 20:25 ` Glauber Costa
2012-05-30 1:29 ` Tejun Heo
2012-05-30 7:28 ` [Devel] " James Bottomley
2012-05-30 7:54 ` Glauber Costa
2012-05-30 8:02 ` Tejun Heo
2012-05-30 15:37 ` Christoph Lameter
2012-05-29 20:57 ` Suleiman Souhlal
2012-05-25 13:03 ` [PATCH v3 14/28] slab: " Glauber Costa
2012-05-25 13:03 ` [PATCH v3 15/28] slub: always get the cache from its page in kfree Glauber Costa
2012-05-29 14:42 ` Christoph Lameter
2012-05-29 15:59 ` Glauber Costa
2012-05-25 13:03 ` [PATCH v3 16/28] memcg: kmem controller charge/uncharge infrastructure Glauber Costa
2012-05-29 14:47 ` Christoph Lameter
2012-05-29 16:00 ` Glauber Costa
2012-05-30 12:17 ` Frederic Weisbecker
2012-05-30 12:26 ` Glauber Costa
2012-05-30 12:34 ` Frederic Weisbecker
2012-05-30 12:38 ` Glauber Costa
2012-05-30 13:11 ` Frederic Weisbecker
2012-05-30 13:09 ` Glauber Costa
2012-05-30 13:04 ` Frederic Weisbecker
2012-05-30 13:06 ` Glauber Costa
2012-05-30 13:37 ` Frederic Weisbecker
2012-05-30 13:37 ` Glauber Costa
2012-05-30 13:53 ` Frederic Weisbecker
2012-05-30 13:55 ` Glauber Costa
2012-05-30 15:33 ` Frederic Weisbecker
2012-05-30 16:16 ` Glauber Costa
2012-05-25 13:03 ` [PATCH v3 17/28] skip memcg kmem allocations in specified code regions Glauber Costa
2012-05-25 13:03 ` [PATCH v3 18/28] slub: charge allocation to a memcg Glauber Costa
2012-05-29 14:51 ` Christoph Lameter
2012-05-29 16:06 ` Glauber Costa
2012-05-25 13:03 ` [PATCH v3 19/28] slab: per-memcg accounting of slab caches Glauber Costa
2012-05-29 14:52 ` Christoph Lameter
2012-05-29 16:07 ` Glauber Costa
2012-05-29 16:13 ` Glauber Costa
2012-05-25 13:03 ` [PATCH v3 20/28] memcg: disable kmem code when not in use Glauber Costa
2012-05-25 13:03 ` [PATCH v3 21/28] memcg: destroy memcg caches Glauber Costa
2012-05-25 13:03 ` [PATCH v3 22/28] memcg/slub: shrink dead caches Glauber Costa
2012-05-25 13:03 ` Glauber Costa [this message]
2012-05-25 13:03 ` [PATCH v3 24/28] memcg: Per-memcg memory.kmem.slabinfo file Glauber Costa
2012-05-25 13:03 ` [PATCH v3 25/28] slub: create slabinfo file for memcg Glauber Costa
2012-05-25 13:03 ` [PATCH v3 26/28] slub: track all children of a kmem cache Glauber Costa
2012-05-25 13:03 ` [PATCH v3 27/28] memcg: propagate kmem limiting information to children Glauber Costa
2012-05-25 13:03 ` [PATCH v3 28/28] Documentation: add documentation for slab tracker for memcg Glauber Costa
2012-05-25 13:34 ` [PATCH v3 00/28] kmem limitation " Michal Hocko
2012-05-25 14:34 ` Christoph Lameter
2012-05-28 8:32 ` Glauber Costa
2012-05-29 15:07 ` Christoph Lameter
2012-05-29 15:44 ` Glauber Costa
2012-05-29 16:01 ` Christoph Lameter
2012-06-07 10:26 ` Frederic Weisbecker
2012-06-07 10:53 ` Glauber Costa
2012-06-07 14:00 ` Frederic Weisbecker
2012-06-14 2:24 ` Kamezawa Hiroyuki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1337951028-3427-24-git-send-email-glommer@parallels.com \
--to=glommer@parallels.com \
--cc=cgroups@vger.kernel.org \
--cc=cl@linux.com \
--cc=devel@openvz.org \
--cc=gthelen@google.com \
--cc=hannes@cmpxchg.org \
--cc=kamezawa.hiroyu@jp.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lizefan@huawei.com \
--cc=mhocko@suse.cz \
--cc=penberg@cs.helsinki.fi \
--cc=rientjes@google.com \
--cc=suleiman@google.com \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox