]> git.karo-electronics.de Git - linux-beck.git/commit
vt: fix console lock vs. kernfs s_active lock order
authorImre Deak <imre.deak@intel.com>
Wed, 1 Apr 2015 18:06:16 +0000 (21:06 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 10 May 2015 17:29:51 +0000 (19:29 +0200)
commitd364b5c3e446bbf9892edbb000bf4c358f86bd8b
tree191b00942c308a7809e1b0d7222feead25b95882
parent80463501fe3a6cfdfb0aca92b1f2abbda61092a1
vt: fix console lock vs. kernfs s_active lock order

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: Imre Deak <imre.deak@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/vt/vt.c