• I
    vt: fix console lock vs. kernfs s_active lock order · d364b5c3
    Imre Deak 提交于
    Currently there is a lock order problem between the console lock and the
    kernfs s_active lock of the console driver's bind sysfs entry. When
    writing to the sysfs entry the lock order is first s_active then console
    lock, when unregistering the console driver via
    do_unregister_con_driver() the order is the opposite. See the below
    bugzilla reference for one instance of a lockdep backtrace.
    
    Fix this by unregistering the console driver from a deferred work, where
    we can safely drop the console lock while unregistering the device and
    corresponding sysfs entries (which in turn acquire s_active). Note that
    we have to keep the console driver slot in the registered_con_driver
    array reserved for the driver that's being unregistered until it's fully
    removed. Otherwise a concurrent call to do_register_con_driver could
    try to reuse the same slot and fail when registering the corresponding
    device with a minor index that's still in use.
    
    Note that the referenced bug report contains two dmesg logs with two
    distinct lockdep reports: [1] is about a locking scenario involving
    s_active, console_lock and the fb_notifier list lock, while [2] is
    about a locking scenario involving only s_active and console_lock.
    In [1] locking fb_notifier triggers the lockdep warning only because
    of its dependence on console_lock, otherwise case [1] is the same
    s_active<->console_lock dependency problem fixed by this patch.
    Before this change we have the following locking scenarios involving
    the 3 locks:
    
    a) via do_unregister_framebuffer()->...->do_unregister_con_driver():
       1. console lock 2. fb_notifier lock 3. s_active lock
    b) for example via give_up_console()->do_unregister_con_driver():
       1. console lock 2. s_active lock
    c) via vt_bind()/vt_unbind():
       1. s_active lock 2. console lock
    
    Since c) is the console bind sysfs entry's write code path we can't
    change the locking order there. We can only fix this issue by removing
    s_active's dependence on the other two locks in a) and b). We can do
    this only in the vt code which owns the corresponding sysfs entry, so
    that after the change we have:
    
    a) 1. console lock 2. fb_notifier lock
    b) 1. console lock
    c) 1. s_active lock 2. console lock
    d) in the new con_driver_unregister_callback():
       1. s_active lock
    
    [1] https://bugs.freedesktop.org/attachment.cgi?id=87716
    [2] https://bugs.freedesktop.org/attachment.cgi?id=107602
    
    v2:
    - get console_lock earlier in con_driver_unregister_callback(), so we
      protect the following console driver field assignments there
    - add code coment explaining the reason for deferring the sysfs entry
      removal
    - add a third paragraph to the commit message explaining why there are
      two distinct lockdep reports and that this issue is independent of
      fb/fbcon. (Peter Hurley)
    v3:
    - clarify further the third paragraph
    v4:
    - rebased on v4 of patch 1/3
    Signed-off-by: NImre Deak <imre.deak@intel.com>
    Reviewed-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
    Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    d364b5c3
vt.c 103.3 KB