]> Git Repo - linux.git/commit
mm: shrinkers: fix deadlock in shrinker debugfs
authorQi Zheng <[email protected]>
Thu, 2 Feb 2023 10:56:12 +0000 (18:56 +0800)
committerAndrew Morton <[email protected]>
Thu, 9 Feb 2023 23:56:51 +0000 (15:56 -0800)
commitbadc28d4924bfed73efc93f716a0c3aa3afbdf6f
tree71a94e24eaf573ef94b3544d5db872a15a5fef7d
parent6b970599e807ea95c653926d41b095a92fd381e2
mm: shrinkers: fix deadlock in shrinker debugfs

The debugfs_remove_recursive() is invoked by unregister_shrinker(), which
is holding the write lock of shrinker_rwsem.  It will waits for the
handler of debugfs file complete.  The handler also needs to hold the read
lock of shrinker_rwsem to do something.  So it may cause the following
deadlock:

  CPU0 CPU1

debugfs_file_get()
shrinker_debugfs_count_show()/shrinker_debugfs_scan_write()

      unregister_shrinker()
--> down_write(&shrinker_rwsem);
    debugfs_remove_recursive()
// wait for (A)
    --> wait_for_completion();

    // wait for (B)
--> down_read_killable(&shrinker_rwsem)
debugfs_file_put() -- (A)

    up_write() -- (B)

The down_read_killable() can be killed, so that the above deadlock can be
recovered.  But it still requires an extra kill action, otherwise it will
block all subsequent shrinker-related operations, so it's better to fix
it.

[[email protected]: fix CONFIG_SHRINKER_DEBUG=n stub]
Link: https://lkml.kernel.org/r/[email protected]
Fixes: 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")
Signed-off-by: Qi Zheng <[email protected]>
Reviewed-by: Roman Gushchin <[email protected]>
Cc: Kent Overstreet <[email protected]>
Cc: Muchun Song <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
include/linux/shrinker.h
mm/shrinker_debug.c
mm/vmscan.c
This page took 0.056848 seconds and 4 git commands to generate.