SLUB duplicates the cache name string passed into kmem_cache_create().
However if the cache could be merged to others during early boot, the
name pointer is saved in saved_alias list, and the string needs to be
kept valid before slab_sysfs_init() is finished. With this patch, the
name string (if kmalloced) could be kfreed after calling
kmem_cache_create().
Some more details:
kmem_cache_create() checks whether it is mergeable before creating one.
If not mergeable, the name is duplicated: n = kstrdup(name, GFP_KERNEL);
If it is mergeable, it calls sysfs_slab_alias(). If the sysfs is ready
(slab_state == SYSFS), then the name is duplicated (or dropped if no
SYSFS support) in sysfs_create_link() for use.
For the above cases, we could safely kfree the name string after calling
cache create.
However, during early boot, before sysfs is ready (slab_state < SYSFS),
the sysfs_slab_alias() saves the pointer of name in the alias_list.
Those entries in the list are added to sysfs later in slab_sysfs_init()
to set up the sysfs stuff, and we need keep the name string passed in
valid until it finishes. By duplicating the name string here also, we
are able to safely kfree the name string after calling cache create.
v2: removed an unnecessary assignment in v1; some changes in change log,
added more details
v3: changed slab/slot to let them also duplicate the name string, so the
code is not slub-dependent, and in patch 2/2, we could call kfree()
after cache create without #ifdef slub.
for slab, the name of the sizes caches created before
slab_is_available() is not duplicated, and it is not checked in
kmem_cache_destroy(), as I think these caches won't be destroyed.
Signed-off-by: Li Zhong <redacted>
---
mm/slab.c | 15 ++++++++++++++-
mm/slob.c | 17 ++++++++++++++---
mm/slub.c | 7 ++++++-
3 files changed, 34 insertions(+), 5 deletions(-)
size_t align,
BUG();
}
+ if (slab_is_available()) {
+ lname = kstrdup(name, GFP_KERNEL);
+ if (!lname)
+ goto oops;
+ } else
+ lname = name;
+
/*
* We use cache_chain_mutex to ensure a consistent view of
* cpu_online_mask as well. Please see cpuup_callback
@@ -569,13 +569,18 @@ struct kmem_cache {structkmem_cache*kmem_cache_create(constchar*name,size_tsize,size_talign,unsignedlongflags,void(*ctor)(void*)){-structkmem_cache*c;+structkmem_cache*c=NULL;+constchar*lname;++lname=kstrdup(name,GFP_KERNEL);+if(!lname)+gotooops;c=slob_alloc(sizeof(structkmem_cache),GFP_KERNEL,ARCH_KMALLOC_MINALIGN,-1);if(c){-c->name=name;+c->name=lname;c->size=size;if(flags&SLAB_DESTROY_BY_RCU){/* leave room for rcu footer at the end of object */
This patch tries to kfree the cache name of pgtables cache. It depends
on patch 1/2 -- ([PATCH SLAB 1/2 v3] duplicate the cache name in SLUB's
saved_alias list, SLAB, and SLOB) in this mail thread.
For SLUB, as the pgtables cache might be mergeable to other caches.
During early boot, the name string is saved in the save_alias list. In
this case, the name could be safely kfreed after calling
kmem_cache_create() with patch 1.
For SLAB/SLOB, we need the changes in patch 1, which duplicates the name
strings in cache create.
v3: with patch 1/2 updated to make slab/slob consistent, #ifdef
CONFIG_SLUB is no longer needed.
Signed-off-by: Li Zhong <redacted>
---
arch/powerpc/mm/init_64.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
From: Christoph Lameter <hidden> Date: 2012-07-06 13:56:14
I thought I posted this a couple of days ago. Would this not fix things
without having to change all the allocators?
Subject: slub: Dup name earlier in kmem_cache_create
Dup the name earlier in kmem_cache_create so that alias
processing is done using the copy of the string and not
the string itself.
Signed-off-by: Christoph Lameter <redacted>
---
mm/slub.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
Index: linux-2.6/mm/slub.c
===================================================================
On Fri, 2012-07-06 at 08:56 -0500, Christoph Lameter wrote:
I thought I posted this a couple of days ago. Would this not fix things
without having to change all the allocators?
I was pointed by Glauber to the slab common code patches. I need some
more time to read the patches. Now I think the slab/slot changes in this
v3 are not needed, and can be ignored.
But for the SLUB's saved_alias list issue, I don't think the following
patch helps. Details below: (Maybe I am wrong, as I'm reading the patch
based on the 3.5-rc6 code ...)
quoted hunk
Subject: slub: Dup name earlier in kmem_cache_create
Dup the name earlier in kmem_cache_create so that alias
processing is done using the copy of the string and not
the string itself.
Signed-off-by: Christoph Lameter <redacted>
---
mm/slub.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
Index: linux-2.6/mm/slub.c
===================================================================
......
up_write(&slub_lock);
return s;
}
Here, the function returns without name string n be kfreed.
But we couldn't kfree n here, because in sysfs_slab_alias(), if
(slab_state < SYS_FS), the name need to be kept valid until
slab_sysfs_init() is finished adding the entry into sysfs.
From: Christoph Lameter <hidden> Date: 2012-07-09 14:01:17
I was pointed by Glauber to the slab common code patches. I need some
more time to read the patches. Now I think the slab/slot changes in this
v3 are not needed, and can be ignored.
That may take some kernel cycles. You have a current issue here that needs
to be fixed.
quoted
down_write(&slub_lock);
- s = find_mergeable(size, align, flags, name, ctor);
+ s = find_mergeable(size, align, flags, n, ctor);
if (s) {
s->refcount++;
/*
......
up_write(&slub_lock);
return s;
}
Here, the function returns without name string n be kfreed.
That is intentional since the string n is still referenced by the entry
that sysfs_slab_alias has created.
But we couldn't kfree n here, because in sysfs_slab_alias(), if
(slab_state < SYS_FS), the name need to be kept valid until
slab_sysfs_init() is finished adding the entry into sysfs.
Right that is why it is not freed and that is what fixes the issue you
see.
On Mon, 2012-07-09 at 09:01 -0500, Christoph Lameter wrote:
quoted
I was pointed by Glauber to the slab common code patches. I need some
more time to read the patches. Now I think the slab/slot changes in this
v3 are not needed, and can be ignored.
That may take some kernel cycles. You have a current issue here that needs
to be fixed.
I'm a little confused ... and what need I do for the next step?
quoted
quoted
down_write(&slub_lock);
- s = find_mergeable(size, align, flags, name, ctor);
+ s = find_mergeable(size, align, flags, n, ctor);
if (s) {
s->refcount++;
/*
......
up_write(&slub_lock);
return s;
}
Here, the function returns without name string n be kfreed.
That is intentional since the string n is still referenced by the entry
that sysfs_slab_alias has created.
I'm not sure whether the "referenced by ..." you mentioned is what I
understood. From my understanding:
if slab_state == SYS_FS, after
return sysfs_create_link(&slab_kset->kobj, &s->kobj, name);
is called, the name string passed in sysfs_slab_alias is no longer
referenced (sysfs_new_dirent duplicates the string for sysfs to use).
else, the name sting is referenced by
al->name = name;
temporarily. After slab_sysfs_init is finished, the name is not
referenced any more.
So in my patch (slub part), the string is duplicated here, and kfreed in
slab_sysfs_init.
quoted
But we couldn't kfree n here, because in sysfs_slab_alias(), if
(slab_state < SYS_FS), the name need to be kept valid until
slab_sysfs_init() is finished adding the entry into sysfs.
Right that is why it is not freed and that is what fixes the issue you
see.