• Qi Zheng's avatar
    mm: shrinkers: fix deadlock in shrinker debugfs · badc28d4
    Qi Zheng authored
    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.
    
    [akpm@linux-foundation.org: fix CONFIG_SHRINKER_DEBUG=n stub]
    Link: https://lkml.kernel.org/r/20230202105612.64641-1-zhengqi.arch@bytedance.com
    Fixes: 5035ebc6 ("mm: shrinkers: introduce debugfs interface for memory shrinkers")
    Signed-off-by: default avatarQi Zheng <zhengqi.arch@bytedance.com>
    Reviewed-by: default avatarRoman Gushchin <roman.gushchin@linux.dev>
    Cc: Kent Overstreet <kent.overstreet@gmail.com>
    Cc: Muchun Song <songmuchun@bytedance.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    badc28d4
vmscan.c 214 KB