summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2008-01-08 09:29:05 +0300
committerChristoph Lameter <clameter@sgi.com>2008-02-04 21:56:01 +0300
commit151c602f79cb9154c3f3d83223cae355af463d6f (patch)
tree140f75b7a100c50b9d337b3a128dd34b5731780f
parente374d4835668a8c6aec7cefc0a44df69f9679017 (diff)
downloadlinux-151c602f79cb9154c3f3d83223cae355af463d6f.tar.xz
SLUB: Fix sysfs refcounting
If CONFIG_SYSFS is set then free the kmem_cache structure when sysfs tells us its okay. Otherwise there is the danger (as pointed out by Al Viro) that sysfs thinks the kobject still exists after kmem_cache_destroy() removed it. Signed-off-by: Christoph Lameter <clameter@sgi.com> Reviewed-by: Pekka J Enberg <penberg@cs.helsinki.fi>
-rw-r--r--mm/slub.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/mm/slub.c b/mm/slub.c
index 93f5c288f024..65bf21dc996a 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -247,7 +247,10 @@ static void sysfs_slab_remove(struct kmem_cache *);
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 sysfs_slab_remove(struct kmem_cache *s) {}
+static inline void sysfs_slab_remove(struct kmem_cache *s)
+{
+ kfree(s);
+}
#endif
/********************************************************************
@@ -2322,7 +2325,6 @@ void kmem_cache_destroy(struct kmem_cache *s)
if (kmem_cache_close(s))
WARN_ON(1);
sysfs_slab_remove(s);
- kfree(s);
} else
up_write(&slub_lock);
}
@@ -3937,6 +3939,13 @@ static ssize_t slab_attr_store(struct kobject *kobj,
return err;
}
+static void kmem_cache_release(struct kobject *kobj)
+{
+ struct kmem_cache *s = to_slab(kobj);
+
+ kfree(s);
+}
+
static struct sysfs_ops slab_sysfs_ops = {
.show = slab_attr_show,
.store = slab_attr_store,
@@ -3944,6 +3953,7 @@ static struct sysfs_ops slab_sysfs_ops = {
static struct kobj_type slab_ktype = {
.sysfs_ops = &slab_sysfs_ops,
+ .release = kmem_cache_release
};
static int uevent_filter(struct kset *kset, struct kobject *kobj)
@@ -4045,6 +4055,7 @@ static void sysfs_slab_remove(struct kmem_cache *s)
{
kobject_uevent(&s->kobj, KOBJ_REMOVE);
kobject_del(&s->kobj);
+ kobject_put(&s->kobj);
}
/*