From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1946145Ab2EKRwq (ORCPT ); Fri, 11 May 2012 13:52:46 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:24066 "EHLO relay.sw.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1946071Ab2EKRwk (ORCPT ); Fri, 11 May 2012 13:52:40 -0400 From: Glauber Costa To: Cc: , , , Tejun Heo , Li Zefan , Greg Thelen , Suleiman Souhlal , Michal Hocko , Johannes Weiner , , Glauber Costa , Christoph Lameter , Pekka Enberg Subject: [PATCH v2 28/29] slub: track all children of a kmem cache Date: Fri, 11 May 2012 14:44:30 -0300 Message-Id: <1336758272-24284-29-git-send-email-glommer@parallels.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1336758272-24284-1-git-send-email-glommer@parallels.com> References: <1336758272-24284-1-git-send-email-glommer@parallels.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When we destroy a cache (like for instance, if we're unloading a module) we need to go through the list of memcg caches and destroy them as well. The caches are expected to be empty by themselves, so nothing is changed here. All previous guarantees are kept and no new guarantees are given. So given all memcg caches are expected to be empty - even though they are likely to be hanging around in the system, we just need to scan a list of sibling caches, and destroy each one of them. This is very similar to the work done by Suleiman for the slab. Signed-off-by: Glauber Costa CC: Christoph Lameter CC: Pekka Enberg CC: Michal Hocko CC: Kamezawa Hiroyuki CC: Johannes Weiner CC: Suleiman Souhlal --- mm/slub.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 47 insertions(+), 14 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index afe29ef..cfa6295 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3267,6 +3267,20 @@ static inline int kmem_cache_close(struct kmem_cache *s) return 0; } +void kmem_cache_destroy_unlocked(struct kmem_cache *s) +{ + mem_cgroup_release_cache(s); + if (kmem_cache_close(s)) { + printk(KERN_ERR "SLUB %s: %s called for cache that " + "still has objects.\n", s->name, __func__); + dump_stack(); + } + + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); + sysfs_slab_remove(s); +} + /* * Close a cache and release the kmem_cache structure * (must be used for caches created using kmem_cache_create) @@ -3275,24 +3289,41 @@ void kmem_cache_destroy(struct kmem_cache *s) { down_write(&slub_lock); s->refcount--; - if (!s->refcount) { - list_del(&s->list); + #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - /* Not a memcg cache */ - if (s->memcg_params.id != -1) { - mem_cgroup_release_cache(s); - mem_cgroup_flush_cache_create_queue(); + /* Not a memcg cache */ + if (s->memcg_params.id != -1) { + struct mem_cgroup_cache_params *p, *tmp, *this; + struct kmem_cache *c; + int id = s->memcg_params.id; + + this = &s->memcg_params; + mem_cgroup_flush_cache_create_queue(); + list_for_each_entry_safe(p, tmp, &this->sibling_list, sibling_list) { + c = container_of(p, struct kmem_cache, memcg_params); + /* We never added the main cache to the sibling list */ + if (WARN_ON(c == s)) + continue; + + c->refcount--; + if (c->refcount) + continue; + + list_del(&c->list); + list_del(&c->memcg_params.sibling_list); + s->refcount--; /* parent reference */ + up_write(&slub_lock); + mem_cgroup_remove_child_kmem_cache(c, id); + kmem_cache_destroy_unlocked(c); + down_write(&slub_lock); } + } #endif + + if (!s->refcount) { + list_del(&s->list); up_write(&slub_lock); - if (kmem_cache_close(s)) { - printk(KERN_ERR "SLUB %s: %s called for cache that " - "still has objects.\n", s->name, __func__); - dump_stack(); - } - if (s->flags & SLAB_DESTROY_BY_RCU) - rcu_barrier(); - sysfs_slab_remove(s); + kmem_cache_destroy_unlocked(s); } else up_write(&slub_lock); } @@ -4150,6 +4181,8 @@ struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg, */ if (new) { down_write(&slub_lock); + list_add(&new->memcg_params.sibling_list, + &s->memcg_params.sibling_list); s->refcount++; up_write(&slub_lock); } -- 1.7.7.6 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from psmtp.com (na3sys010amx185.postini.com [74.125.245.185]) by kanga.kvack.org (Postfix) with SMTP id 8997A8D0020 for ; Fri, 11 May 2012 13:51:30 -0400 (EDT) From: Glauber Costa Subject: [PATCH v2 28/29] slub: track all children of a kmem cache Date: Fri, 11 May 2012 14:44:30 -0300 Message-Id: <1336758272-24284-29-git-send-email-glommer@parallels.com> In-Reply-To: <1336758272-24284-1-git-send-email-glommer@parallels.com> References: <1336758272-24284-1-git-send-email-glommer@parallels.com> Sender: owner-linux-mm@kvack.org List-ID: To: linux-kernel@vger.kernel.org Cc: cgroups@vger.kernel.org, linux-mm@kvack.org, kamezawa.hiroyu@jp.fujitsu.com, Tejun Heo , Li Zefan , Greg Thelen , Suleiman Souhlal , Michal Hocko , Johannes Weiner , devel@openvz.org, Glauber Costa , Christoph Lameter , Pekka Enberg When we destroy a cache (like for instance, if we're unloading a module) we need to go through the list of memcg caches and destroy them as well. The caches are expected to be empty by themselves, so nothing is changed here. All previous guarantees are kept and no new guarantees are given. So given all memcg caches are expected to be empty - even though they are likely to be hanging around in the system, we just need to scan a list of sibling caches, and destroy each one of them. This is very similar to the work done by Suleiman for the slab. Signed-off-by: Glauber Costa CC: Christoph Lameter CC: Pekka Enberg CC: Michal Hocko CC: Kamezawa Hiroyuki CC: Johannes Weiner CC: Suleiman Souhlal --- mm/slub.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 47 insertions(+), 14 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index afe29ef..cfa6295 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3267,6 +3267,20 @@ static inline int kmem_cache_close(struct kmem_cache *s) return 0; } +void kmem_cache_destroy_unlocked(struct kmem_cache *s) +{ + mem_cgroup_release_cache(s); + if (kmem_cache_close(s)) { + printk(KERN_ERR "SLUB %s: %s called for cache that " + "still has objects.\n", s->name, __func__); + dump_stack(); + } + + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); + sysfs_slab_remove(s); +} + /* * Close a cache and release the kmem_cache structure * (must be used for caches created using kmem_cache_create) @@ -3275,24 +3289,41 @@ void kmem_cache_destroy(struct kmem_cache *s) { down_write(&slub_lock); s->refcount--; - if (!s->refcount) { - list_del(&s->list); + #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - /* Not a memcg cache */ - if (s->memcg_params.id != -1) { - mem_cgroup_release_cache(s); - mem_cgroup_flush_cache_create_queue(); + /* Not a memcg cache */ + if (s->memcg_params.id != -1) { + struct mem_cgroup_cache_params *p, *tmp, *this; + struct kmem_cache *c; + int id = s->memcg_params.id; + + this = &s->memcg_params; + mem_cgroup_flush_cache_create_queue(); + list_for_each_entry_safe(p, tmp, &this->sibling_list, sibling_list) { + c = container_of(p, struct kmem_cache, memcg_params); + /* We never added the main cache to the sibling list */ + if (WARN_ON(c == s)) + continue; + + c->refcount--; + if (c->refcount) + continue; + + list_del(&c->list); + list_del(&c->memcg_params.sibling_list); + s->refcount--; /* parent reference */ + up_write(&slub_lock); + mem_cgroup_remove_child_kmem_cache(c, id); + kmem_cache_destroy_unlocked(c); + down_write(&slub_lock); } + } #endif + + if (!s->refcount) { + list_del(&s->list); up_write(&slub_lock); - if (kmem_cache_close(s)) { - printk(KERN_ERR "SLUB %s: %s called for cache that " - "still has objects.\n", s->name, __func__); - dump_stack(); - } - if (s->flags & SLAB_DESTROY_BY_RCU) - rcu_barrier(); - sysfs_slab_remove(s); + kmem_cache_destroy_unlocked(s); } else up_write(&slub_lock); } @@ -4150,6 +4181,8 @@ struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg, */ if (new) { down_write(&slub_lock); + list_add(&new->memcg_params.sibling_list, + &s->memcg_params.sibling_list); s->refcount++; up_write(&slub_lock); } -- 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: email@kvack.org From mboxrd@z Thu Jan 1 00:00:00 1970 From: Glauber Costa Subject: [PATCH v2 28/29] slub: track all children of a kmem cache Date: Fri, 11 May 2012 14:44:30 -0300 Message-ID: <1336758272-24284-29-git-send-email-glommer@parallels.com> References: <1336758272-24284-1-git-send-email-glommer@parallels.com> Return-path: In-Reply-To: <1336758272-24284-1-git-send-email-glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org> Sender: cgroups-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org List-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org, kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org, Tejun Heo , Li Zefan , Greg Thelen , Suleiman Souhlal , Michal Hocko , Johannes Weiner , devel-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org, Glauber Costa , Christoph Lameter , Pekka Enberg When we destroy a cache (like for instance, if we're unloading a module) we need to go through the list of memcg caches and destroy them as well. The caches are expected to be empty by themselves, so nothing is changed here. All previous guarantees are kept and no new guarantees are given. So given all memcg caches are expected to be empty - even though they are likely to be hanging around in the system, we just need to scan a list of sibling caches, and destroy each one of them. This is very similar to the work done by Suleiman for the slab. Signed-off-by: Glauber Costa CC: Christoph Lameter CC: Pekka Enberg CC: Michal Hocko CC: Kamezawa Hiroyuki CC: Johannes Weiner CC: Suleiman Souhlal --- mm/slub.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 47 insertions(+), 14 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index afe29ef..cfa6295 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3267,6 +3267,20 @@ static inline int kmem_cache_close(struct kmem_cache *s) return 0; } +void kmem_cache_destroy_unlocked(struct kmem_cache *s) +{ + mem_cgroup_release_cache(s); + if (kmem_cache_close(s)) { + printk(KERN_ERR "SLUB %s: %s called for cache that " + "still has objects.\n", s->name, __func__); + dump_stack(); + } + + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); + sysfs_slab_remove(s); +} + /* * Close a cache and release the kmem_cache structure * (must be used for caches created using kmem_cache_create) @@ -3275,24 +3289,41 @@ void kmem_cache_destroy(struct kmem_cache *s) { down_write(&slub_lock); s->refcount--; - if (!s->refcount) { - list_del(&s->list); + #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - /* Not a memcg cache */ - if (s->memcg_params.id != -1) { - mem_cgroup_release_cache(s); - mem_cgroup_flush_cache_create_queue(); + /* Not a memcg cache */ + if (s->memcg_params.id != -1) { + struct mem_cgroup_cache_params *p, *tmp, *this; + struct kmem_cache *c; + int id = s->memcg_params.id; + + this = &s->memcg_params; + mem_cgroup_flush_cache_create_queue(); + list_for_each_entry_safe(p, tmp, &this->sibling_list, sibling_list) { + c = container_of(p, struct kmem_cache, memcg_params); + /* We never added the main cache to the sibling list */ + if (WARN_ON(c == s)) + continue; + + c->refcount--; + if (c->refcount) + continue; + + list_del(&c->list); + list_del(&c->memcg_params.sibling_list); + s->refcount--; /* parent reference */ + up_write(&slub_lock); + mem_cgroup_remove_child_kmem_cache(c, id); + kmem_cache_destroy_unlocked(c); + down_write(&slub_lock); } + } #endif + + if (!s->refcount) { + list_del(&s->list); up_write(&slub_lock); - if (kmem_cache_close(s)) { - printk(KERN_ERR "SLUB %s: %s called for cache that " - "still has objects.\n", s->name, __func__); - dump_stack(); - } - if (s->flags & SLAB_DESTROY_BY_RCU) - rcu_barrier(); - sysfs_slab_remove(s); + kmem_cache_destroy_unlocked(s); } else up_write(&slub_lock); } @@ -4150,6 +4181,8 @@ struct kmem_cache *kmem_cache_dup(struct mem_cgroup *memcg, */ if (new) { down_write(&slub_lock); + list_add(&new->memcg_params.sibling_list, + &s->memcg_params.sibling_list); s->refcount++; up_write(&slub_lock); } -- 1.7.7.6