diff options
| author | Christoph Lameter <cl@linux.com> | 2014-05-06 15:50:08 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-05-06 16:04:59 -0400 |
| commit | 41a212859a4dd583d3aa032cdd3efa564c4f189f (patch) | |
| tree | 09b335c4840e913e67268812f2467e77592dbc38 | |
| parent | 623762517e2370be3b3f95f4fe08d6c063a49b06 (diff) | |
slub: use sysfs'es release mechanism for kmem_cache
debugobjects warning during netfilter exit:
------------[ cut here ]------------
WARNING: CPU: 6 PID: 4178 at lib/debugobjects.c:260 debug_print_object+0x8d/0xb0()
ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x20
Modules linked in:
CPU: 6 PID: 4178 Comm: kworker/u16:2 Tainted: G W 3.11.0-next-20130906-sasha #3984
Workqueue: netns cleanup_net
Call Trace:
dump_stack+0x52/0x87
warn_slowpath_common+0x8c/0xc0
warn_slowpath_fmt+0x46/0x50
debug_print_object+0x8d/0xb0
__debug_check_no_obj_freed+0xa5/0x220
debug_check_no_obj_freed+0x15/0x20
kmem_cache_free+0x197/0x340
kmem_cache_destroy+0x86/0xe0
nf_conntrack_cleanup_net_list+0x131/0x170
nf_conntrack_pernet_exit+0x5d/0x70
ops_exit_list+0x5e/0x70
cleanup_net+0xfb/0x1c0
process_one_work+0x338/0x550
worker_thread+0x215/0x350
kthread+0xe7/0xf0
ret_from_fork+0x7c/0xb0
Also during dcookie cleanup:
WARNING: CPU: 12 PID: 9725 at lib/debugobjects.c:260 debug_print_object+0x8c/0xb0()
ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x20
Modules linked in:
CPU: 12 PID: 9725 Comm: trinity-c141 Not tainted 3.15.0-rc2-next-20140423-sasha-00018-gc4ff6c4 #408
Call Trace:
dump_stack (lib/dump_stack.c:52)
warn_slowpath_common (kernel/panic.c:430)
warn_slowpath_fmt (kernel/panic.c:445)
debug_print_object (lib/debugobjects.c:262)
__debug_check_no_obj_freed (lib/debugobjects.c:697)
debug_check_no_obj_freed (lib/debugobjects.c:726)
kmem_cache_free (mm/slub.c:2689 mm/slub.c:2717)
kmem_cache_destroy (mm/slab_common.c:363)
dcookie_unregister (fs/dcookies.c:302 fs/dcookies.c:343)
event_buffer_release (arch/x86/oprofile/../../../drivers/oprofile/event_buffer.c:153)
__fput (fs/file_table.c:217)
____fput (fs/file_table.c:253)
task_work_run (kernel/task_work.c:125 (discriminator 1))
do_notify_resume (include/linux/tracehook.h:196 arch/x86/kernel/signal.c:751)
int_signal (arch/x86/kernel/entry_64.S:807)
Sysfs has a release mechanism. Use that to release the kmem_cache
structure if CONFIG_SYSFS is enabled.
Only slub is changed - slab currently only supports /proc/slabinfo and
not /sys/kernel/slab/*. We talked about adding that and someone was
working on it.
[akpm@linux-foundation.org: fix CONFIG_SYSFS=n build]
[akpm@linux-foundation.org: fix CONFIG_SYSFS=n build even more]
Signed-off-by: Christoph Lameter <cl@linux.com>
Reported-by: Sasha Levin <sasha.levin@oracle.com>
Tested-by: Sasha Levin <sasha.levin@oracle.com>
Acked-by: Greg KH <greg@kroah.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Bart Van Assche <bvanassche@acm.org>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | include/linux/slub_def.h | 9 | ||||
| -rw-r--r-- | mm/slab.h | 1 | ||||
| -rw-r--r-- | mm/slab_common.c | 13 | ||||
| -rw-r--r-- | mm/slub.c | 30 |
4 files changed, 29 insertions, 24 deletions
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index f2f7398848cf..d82abd40a3c0 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h | |||
| @@ -101,4 +101,13 @@ struct kmem_cache { | |||
| 101 | struct kmem_cache_node *node[MAX_NUMNODES]; | 101 | struct kmem_cache_node *node[MAX_NUMNODES]; |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | #ifdef CONFIG_SYSFS | ||
| 105 | #define SLAB_SUPPORTS_SYSFS | ||
| 106 | void sysfs_slab_remove(struct kmem_cache *); | ||
| 107 | #else | ||
| 108 | static inline void sysfs_slab_remove(struct kmem_cache *s) | ||
| 109 | { | ||
| 110 | } | ||
| 111 | #endif | ||
| 112 | |||
| 104 | #endif /* _LINUX_SLUB_DEF_H */ | 113 | #endif /* _LINUX_SLUB_DEF_H */ |
| @@ -91,6 +91,7 @@ __kmem_cache_alias(const char *name, size_t size, size_t align, | |||
| 91 | #define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS) | 91 | #define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS) |
| 92 | 92 | ||
| 93 | int __kmem_cache_shutdown(struct kmem_cache *); | 93 | int __kmem_cache_shutdown(struct kmem_cache *); |
| 94 | void slab_kmem_cache_release(struct kmem_cache *); | ||
| 94 | 95 | ||
| 95 | struct seq_file; | 96 | struct seq_file; |
| 96 | struct file; | 97 | struct file; |
diff --git a/mm/slab_common.c b/mm/slab_common.c index f3cfccf76dda..102cc6fca3d3 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c | |||
| @@ -323,6 +323,12 @@ static int kmem_cache_destroy_memcg_children(struct kmem_cache *s) | |||
| 323 | } | 323 | } |
| 324 | #endif /* CONFIG_MEMCG_KMEM */ | 324 | #endif /* CONFIG_MEMCG_KMEM */ |
| 325 | 325 | ||
| 326 | void slab_kmem_cache_release(struct kmem_cache *s) | ||
| 327 | { | ||
| 328 | kfree(s->name); | ||
| 329 | kmem_cache_free(kmem_cache, s); | ||
| 330 | } | ||
| 331 | |||
| 326 | void kmem_cache_destroy(struct kmem_cache *s) | 332 | void kmem_cache_destroy(struct kmem_cache *s) |
| 327 | { | 333 | { |
| 328 | get_online_cpus(); | 334 | get_online_cpus(); |
| @@ -352,8 +358,11 @@ void kmem_cache_destroy(struct kmem_cache *s) | |||
| 352 | rcu_barrier(); | 358 | rcu_barrier(); |
| 353 | 359 | ||
| 354 | memcg_free_cache_params(s); | 360 | memcg_free_cache_params(s); |
| 355 | kfree(s->name); | 361 | #ifdef SLAB_SUPPORTS_SYSFS |
| 356 | kmem_cache_free(kmem_cache, s); | 362 | sysfs_slab_remove(s); |
| 363 | #else | ||
| 364 | slab_kmem_cache_release(s); | ||
| 365 | #endif | ||
| 357 | goto out_put_cpus; | 366 | goto out_put_cpus; |
| 358 | 367 | ||
| 359 | out_unlock: | 368 | out_unlock: |
| @@ -210,14 +210,11 @@ enum track_item { TRACK_ALLOC, TRACK_FREE }; | |||
| 210 | #ifdef CONFIG_SYSFS | 210 | #ifdef CONFIG_SYSFS |
| 211 | static int sysfs_slab_add(struct kmem_cache *); | 211 | static int sysfs_slab_add(struct kmem_cache *); |
| 212 | static int sysfs_slab_alias(struct kmem_cache *, const char *); | 212 | static int sysfs_slab_alias(struct kmem_cache *, const char *); |
| 213 | static void sysfs_slab_remove(struct kmem_cache *); | ||
| 214 | static void memcg_propagate_slab_attrs(struct kmem_cache *s); | 213 | static void memcg_propagate_slab_attrs(struct kmem_cache *s); |
| 215 | #else | 214 | #else |
| 216 | static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; } | 215 | static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; } |
| 217 | static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p) | 216 | static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p) |
| 218 | { return 0; } | 217 | { return 0; } |
| 219 | static inline void sysfs_slab_remove(struct kmem_cache *s) { } | ||
| 220 | |||
| 221 | static inline void memcg_propagate_slab_attrs(struct kmem_cache *s) { } | 218 | static inline void memcg_propagate_slab_attrs(struct kmem_cache *s) { } |
| 222 | #endif | 219 | #endif |
| 223 | 220 | ||
| @@ -3238,24 +3235,7 @@ static inline int kmem_cache_close(struct kmem_cache *s) | |||
| 3238 | 3235 | ||
| 3239 | int __kmem_cache_shutdown(struct kmem_cache *s) | 3236 | int __kmem_cache_shutdown(struct kmem_cache *s) |
| 3240 | { | 3237 | { |
| 3241 | int rc = kmem_cache_close(s); | 3238 | return kmem_cache_close(s); |
| 3242 | |||
| 3243 | if (!rc) { | ||
| 3244 | /* | ||
| 3245 | * Since slab_attr_store may take the slab_mutex, we should | ||
| 3246 | * release the lock while removing the sysfs entry in order to | ||
| 3247 | * avoid a deadlock. Because this is pretty much the last | ||
| 3248 | * operation we do and the lock will be released shortly after | ||
| 3249 | * that in slab_common.c, we could just move sysfs_slab_remove | ||
| 3250 | * to a later point in common code. We should do that when we | ||
| 3251 | * have a common sysfs framework for all allocators. | ||
| 3252 | */ | ||
| 3253 | mutex_unlock(&slab_mutex); | ||
| 3254 | sysfs_slab_remove(s); | ||
| 3255 | mutex_lock(&slab_mutex); | ||
| 3256 | } | ||
| 3257 | |||
| 3258 | return rc; | ||
| 3259 | } | 3239 | } |
| 3260 | 3240 | ||
| 3261 | /******************************************************************** | 3241 | /******************************************************************** |
| @@ -5122,6 +5102,11 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s) | |||
| 5122 | #endif | 5102 | #endif |
| 5123 | } | 5103 | } |
| 5124 | 5104 | ||
| 5105 | static void kmem_cache_release(struct kobject *k) | ||
| 5106 | { | ||
| 5107 | slab_kmem_cache_release(to_slab(k)); | ||
| 5108 | } | ||
| 5109 | |||
| 5125 | static const struct sysfs_ops slab_sysfs_ops = { | 5110 | static const struct sysfs_ops slab_sysfs_ops = { |
| 5126 | .show = slab_attr_show, | 5111 | .show = slab_attr_show, |
| 5127 | .store = slab_attr_store, | 5112 | .store = slab_attr_store, |
| @@ -5129,6 +5114,7 @@ static const struct sysfs_ops slab_sysfs_ops = { | |||
| 5129 | 5114 | ||
| 5130 | static struct kobj_type slab_ktype = { | 5115 | static struct kobj_type slab_ktype = { |
| 5131 | .sysfs_ops = &slab_sysfs_ops, | 5116 | .sysfs_ops = &slab_sysfs_ops, |
| 5117 | .release = kmem_cache_release, | ||
| 5132 | }; | 5118 | }; |
| 5133 | 5119 | ||
| 5134 | static int uevent_filter(struct kset *kset, struct kobject *kobj) | 5120 | static int uevent_filter(struct kset *kset, struct kobject *kobj) |
| @@ -5255,7 +5241,7 @@ out_put_kobj: | |||
| 5255 | goto out; | 5241 | goto out; |
| 5256 | } | 5242 | } |
| 5257 | 5243 | ||
| 5258 | static void sysfs_slab_remove(struct kmem_cache *s) | 5244 | void sysfs_slab_remove(struct kmem_cache *s) |
| 5259 | { | 5245 | { |
| 5260 | if (slab_state < FULL) | 5246 | if (slab_state < FULL) |
| 5261 | /* | 5247 | /* |
