Skip to content
Snippets Groups Projects
Commit 58e724e0 authored by Qian Cai's avatar Qian Cai Committed by 谢秀奇
Browse files

mm/slub: fix a deadlock in show_slab_objects()

commit e4f8e513 upstream.

A long time ago we fixed a similar deadlock in show_slab_objects() [1].
However, it is apparently due to the commits like 01fb58bc ("slab:
remove synchronous synchronize_sched() from memcg cache deactivation
path") and 03afc0e2 ("slab: get_online_mems for
kmem_cache_{create,destroy,shrink}"), this kind of deadlock is back by
just reading files in /sys/kernel/slab which will generate a lockdep
splat below.

Since the "mem_hotplug_lock" here is only to obtain a stable online node
mask while racing with NUMA node hotplug, in the worst case, the results
may me miscalculated while doing NUMA node hotplug, but they shall be
corrected by later reads of the same files.

  WARNING: possible circular locking dependency detected
  ------------------------------------------------------
  cat/5224 is trying to acquire lock:
  ffff900012ac3120 (mem_hotplug_lock.rw_sem){++++}, at:
  show_slab_objects+0x94/0x...
parent 663e8322
No related branches found
No related tags found
No related merge requests found
...@@ -4792,7 +4792,17 @@ static ssize_t show_slab_objects(struct kmem_cache *s, ...@@ -4792,7 +4792,17 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
} }
} }
get_online_mems(); /*
* It is impossible to take "mem_hotplug_lock" here with "kernfs_mutex"
* already held which will conflict with an existing lock order:
*
* mem_hotplug_lock->slab_mutex->kernfs_mutex
*
* We don't really need mem_hotplug_lock (to hold off
* slab_mem_going_offline_callback) here because slab's memory hot
* unplug code doesn't destroy the kmem_cache->node[] data.
*/
#ifdef CONFIG_SLUB_DEBUG #ifdef CONFIG_SLUB_DEBUG
if (flags & SO_ALL) { if (flags & SO_ALL) {
struct kmem_cache_node *n; struct kmem_cache_node *n;
...@@ -4833,7 +4843,6 @@ static ssize_t show_slab_objects(struct kmem_cache *s, ...@@ -4833,7 +4843,6 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
x += sprintf(buf + x, " N%d=%lu", x += sprintf(buf + x, " N%d=%lu",
node, nodes[node]); node, nodes[node]);
#endif #endif
put_online_mems();
kfree(nodes); kfree(nodes);
return x + sprintf(buf + x, "\n"); return x + sprintf(buf + x, "\n");
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment