Re: [RFC][PATCHv5 6/7] printk: use printk_safe buffers in printk
On (12/12/16 17:30), Petr Mladek wrote: > On Thu 2016-12-01 22:55:45, Sergey Senozhatsky wrote: > > Use printk_safe per-CPU buffers in printk recursion-prone blocks: > > -- around logbuf_lock protected sections in vprintk_emit() and > >console_unlock() > > -- around down_trylock_console_sem() and up_console_sem() > > > > Note that this solution addresses deadlocks caused by printk() > > recursive calls only. That is vprintk_emit() and console_unlock(). > > > > Another thing to note is that we now keep lockdep enabled in printk, > > because we are protected against the printk recursion caused by lockdep > > in vprintk_emit() by the printk-safe mechanism - we first switch to > > per-CPU buffers and only then access the deadlock-prone locks. > > > > Signed-off-by: Sergey Senozhatsky> > Looks fine and safe to me. > > Reviewed-by: Petr Mladek thanks. -ss
Re: [RFC][PATCHv5 6/7] printk: use printk_safe buffers in printk
On (12/12/16 17:30), Petr Mladek wrote: > On Thu 2016-12-01 22:55:45, Sergey Senozhatsky wrote: > > Use printk_safe per-CPU buffers in printk recursion-prone blocks: > > -- around logbuf_lock protected sections in vprintk_emit() and > >console_unlock() > > -- around down_trylock_console_sem() and up_console_sem() > > > > Note that this solution addresses deadlocks caused by printk() > > recursive calls only. That is vprintk_emit() and console_unlock(). > > > > Another thing to note is that we now keep lockdep enabled in printk, > > because we are protected against the printk recursion caused by lockdep > > in vprintk_emit() by the printk-safe mechanism - we first switch to > > per-CPU buffers and only then access the deadlock-prone locks. > > > > Signed-off-by: Sergey Senozhatsky > > Looks fine and safe to me. > > Reviewed-by: Petr Mladek thanks. -ss
Re: [RFC][PATCHv5 6/7] printk: use printk_safe buffers in printk
On Thu 2016-12-01 22:55:45, Sergey Senozhatsky wrote: > Use printk_safe per-CPU buffers in printk recursion-prone blocks: > -- around logbuf_lock protected sections in vprintk_emit() and >console_unlock() > -- around down_trylock_console_sem() and up_console_sem() > > Note that this solution addresses deadlocks caused by printk() > recursive calls only. That is vprintk_emit() and console_unlock(). > > Another thing to note is that we now keep lockdep enabled in printk, > because we are protected against the printk recursion caused by lockdep > in vprintk_emit() by the printk-safe mechanism - we first switch to > per-CPU buffers and only then access the deadlock-prone locks. > > Signed-off-by: Sergey SenozhatskyLooks fine and safe to me. Reviewed-by: Petr Mladek Best Regards, Petr
Re: [RFC][PATCHv5 6/7] printk: use printk_safe buffers in printk
On Thu 2016-12-01 22:55:45, Sergey Senozhatsky wrote: > Use printk_safe per-CPU buffers in printk recursion-prone blocks: > -- around logbuf_lock protected sections in vprintk_emit() and >console_unlock() > -- around down_trylock_console_sem() and up_console_sem() > > Note that this solution addresses deadlocks caused by printk() > recursive calls only. That is vprintk_emit() and console_unlock(). > > Another thing to note is that we now keep lockdep enabled in printk, > because we are protected against the printk recursion caused by lockdep > in vprintk_emit() by the printk-safe mechanism - we first switch to > per-CPU buffers and only then access the deadlock-prone locks. > > Signed-off-by: Sergey Senozhatsky Looks fine and safe to me. Reviewed-by: Petr Mladek Best Regards, Petr
[RFC][PATCHv5 6/7] printk: use printk_safe buffers in printk
Use printk_safe per-CPU buffers in printk recursion-prone blocks: -- around logbuf_lock protected sections in vprintk_emit() and console_unlock() -- around down_trylock_console_sem() and up_console_sem() Note that this solution addresses deadlocks caused by printk() recursive calls only. That is vprintk_emit() and console_unlock(). Another thing to note is that we now keep lockdep enabled in printk, because we are protected against the printk recursion caused by lockdep in vprintk_emit() by the printk-safe mechanism - we first switch to per-CPU buffers and only then access the deadlock-prone locks. Examples: 1) printk() from logbuf_lock spin_lock section Assume the following code: printk() raw_spin_lock(_lock); WARN_ON(1); raw_spin_unlock(_lock); which now produces: [ cut here ] WARNING: CPU: 0 PID: 366 at kernel/printk/printk.c:1811 vprintk_emit+0x1cd/0x438 CPU: 0 PID: 366 Comm: bash Call Trace: [] warn_slowpath_null+0x1d/0x1f [] vprintk_emit+0x1cd/0x438 [] vprintk_default+0x1d/0x1f [] printk+0x48/0x50 [..] [] entry_SYSCALL_64_fastpath+0x18/0xad ---[ end trace ]--- 2) printk() from semaphore sem->lock spin_lock section Assume the following code printk() console_trylock() down_trylock() raw_spin_lock_irqsave(>lock, flags); WARN_ON(1); raw_spin_unlock_irqrestore(>lock, flags); which now produces: [ cut here ] WARNING: CPU: 1 PID: 363 at kernel/locking/semaphore.c:141 down_trylock+0x3d/0x62 CPU: 1 PID: 363 Comm: bash Call Trace: [] warn_slowpath_null+0x1d/0x1f [] down_trylock+0x3d/0x62 [] ? vprintk_emit+0x3f9/0x414 [] console_trylock+0x31/0xeb [] vprintk_emit+0x3f9/0x414 [] vprintk_default+0x1d/0x1f [] printk+0x48/0x50 [..] [] entry_SYSCALL_64_fastpath+0x18/0xad ---[ end trace ]--- 3) printk() from console_unlock() Assume the following code: printk() console_unlock() raw_spin_lock(_lock); WARN_ON(1); raw_spin_unlock(_lock); which now produces: [ cut here ] WARNING: CPU: 1 PID: 329 at kernel/printk/printk.c:2384 console_unlock+0x12d/0x559 CPU: 1 PID: 329 Comm: bash Call Trace: [] warn_slowpath_null+0x18/0x1a [] console_unlock+0x12d/0x559 [] ? trace_hardirqs_on_caller+0x16d/0x189 [] ? trace_hardirqs_on+0xd/0xf [] vprintk_emit+0x363/0x374 [] vprintk_default+0x18/0x1a [] printk+0x43/0x4b [..] [] entry_SYSCALL_64_fastpath+0x18/0xad ---[ end trace ]--- 4) printk() from try_to_wake_up() Assume the following code: printk() console_unlock() up() try_to_wake_up() raw_spin_lock_irqsave(>pi_lock, flags); WARN_ON(1); raw_spin_unlock_irqrestore(>pi_lock, flags); which now produces: [ cut here ] WARNING: CPU: 3 PID: 363 at kernel/sched/core.c:2028 try_to_wake_up+0x7f/0x4f7 CPU: 3 PID: 363 Comm: bash Call Trace: [] warn_slowpath_null+0x1d/0x1f [] try_to_wake_up+0x7f/0x4f7 [] wake_up_process+0x15/0x17 [] __up.isra.0+0x56/0x63 [] up+0x32/0x42 [] __up_console_sem+0x37/0x55 [] console_unlock+0x21e/0x4c2 [] vprintk_emit+0x41c/0x462 [] vprintk_default+0x1d/0x1f [] printk+0x48/0x50 [..] [] entry_SYSCALL_64_fastpath+0x18/0xad ---[ end trace ]--- 5) printk() from call_console_drivers() Assume the following code: printk() console_unlock() call_console_drivers() ... WARN_ON(1); which now produces: [ cut here ] WARNING: CPU: 2 PID: 305 at kernel/printk/printk.c:1604 call_console_drivers+0x3a/0xb0 CPU: 2 PID: 305 Comm: bash Call Trace: [] warn_slowpath_null+0x18/0x1a [] call_console_drivers.isra.6.constprop.16+0x3a/0xb0 [] console_unlock+0x471/0x48e [] vprintk_emit+0x1f4/0x206 [] vprintk_default+0x18/0x1a [] vprintk_func+0x6e/0x70 [] printk+0x3e/0x46 [..] [] entry_SYSCALL_64_fastpath+0x13/0x94 ---[ end trace ]--- Signed-off-by: Sergey Senozhatsky--- kernel/printk/printk.c | 50 -- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 6f7b217..80f0177 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -213,17 +213,31 @@ static int nr_ext_console_drivers; static int __down_trylock_console_sem(unsigned long ip) { - if (down_trylock(_sem)) + int lock_failed; + unsigned long flags; + + printk_safe_enter(flags); + lock_failed = down_trylock(_sem); + printk_safe_exit(flags); + + if (lock_failed) return 1; mutex_acquire(_lock_dep_map, 0, 1, ip); return 0; } #define down_trylock_console_sem() __down_trylock_console_sem(_RET_IP_) -#define up_console_sem() do { \ - mutex_release(_lock_dep_map, 1, _RET_IP_);\ - up(_sem);\ -} while (0) +static void __up_console_sem(unsigned long ip) +{
[RFC][PATCHv5 6/7] printk: use printk_safe buffers in printk
Use printk_safe per-CPU buffers in printk recursion-prone blocks: -- around logbuf_lock protected sections in vprintk_emit() and console_unlock() -- around down_trylock_console_sem() and up_console_sem() Note that this solution addresses deadlocks caused by printk() recursive calls only. That is vprintk_emit() and console_unlock(). Another thing to note is that we now keep lockdep enabled in printk, because we are protected against the printk recursion caused by lockdep in vprintk_emit() by the printk-safe mechanism - we first switch to per-CPU buffers and only then access the deadlock-prone locks. Examples: 1) printk() from logbuf_lock spin_lock section Assume the following code: printk() raw_spin_lock(_lock); WARN_ON(1); raw_spin_unlock(_lock); which now produces: [ cut here ] WARNING: CPU: 0 PID: 366 at kernel/printk/printk.c:1811 vprintk_emit+0x1cd/0x438 CPU: 0 PID: 366 Comm: bash Call Trace: [] warn_slowpath_null+0x1d/0x1f [] vprintk_emit+0x1cd/0x438 [] vprintk_default+0x1d/0x1f [] printk+0x48/0x50 [..] [] entry_SYSCALL_64_fastpath+0x18/0xad ---[ end trace ]--- 2) printk() from semaphore sem->lock spin_lock section Assume the following code printk() console_trylock() down_trylock() raw_spin_lock_irqsave(>lock, flags); WARN_ON(1); raw_spin_unlock_irqrestore(>lock, flags); which now produces: [ cut here ] WARNING: CPU: 1 PID: 363 at kernel/locking/semaphore.c:141 down_trylock+0x3d/0x62 CPU: 1 PID: 363 Comm: bash Call Trace: [] warn_slowpath_null+0x1d/0x1f [] down_trylock+0x3d/0x62 [] ? vprintk_emit+0x3f9/0x414 [] console_trylock+0x31/0xeb [] vprintk_emit+0x3f9/0x414 [] vprintk_default+0x1d/0x1f [] printk+0x48/0x50 [..] [] entry_SYSCALL_64_fastpath+0x18/0xad ---[ end trace ]--- 3) printk() from console_unlock() Assume the following code: printk() console_unlock() raw_spin_lock(_lock); WARN_ON(1); raw_spin_unlock(_lock); which now produces: [ cut here ] WARNING: CPU: 1 PID: 329 at kernel/printk/printk.c:2384 console_unlock+0x12d/0x559 CPU: 1 PID: 329 Comm: bash Call Trace: [] warn_slowpath_null+0x18/0x1a [] console_unlock+0x12d/0x559 [] ? trace_hardirqs_on_caller+0x16d/0x189 [] ? trace_hardirqs_on+0xd/0xf [] vprintk_emit+0x363/0x374 [] vprintk_default+0x18/0x1a [] printk+0x43/0x4b [..] [] entry_SYSCALL_64_fastpath+0x18/0xad ---[ end trace ]--- 4) printk() from try_to_wake_up() Assume the following code: printk() console_unlock() up() try_to_wake_up() raw_spin_lock_irqsave(>pi_lock, flags); WARN_ON(1); raw_spin_unlock_irqrestore(>pi_lock, flags); which now produces: [ cut here ] WARNING: CPU: 3 PID: 363 at kernel/sched/core.c:2028 try_to_wake_up+0x7f/0x4f7 CPU: 3 PID: 363 Comm: bash Call Trace: [] warn_slowpath_null+0x1d/0x1f [] try_to_wake_up+0x7f/0x4f7 [] wake_up_process+0x15/0x17 [] __up.isra.0+0x56/0x63 [] up+0x32/0x42 [] __up_console_sem+0x37/0x55 [] console_unlock+0x21e/0x4c2 [] vprintk_emit+0x41c/0x462 [] vprintk_default+0x1d/0x1f [] printk+0x48/0x50 [..] [] entry_SYSCALL_64_fastpath+0x18/0xad ---[ end trace ]--- 5) printk() from call_console_drivers() Assume the following code: printk() console_unlock() call_console_drivers() ... WARN_ON(1); which now produces: [ cut here ] WARNING: CPU: 2 PID: 305 at kernel/printk/printk.c:1604 call_console_drivers+0x3a/0xb0 CPU: 2 PID: 305 Comm: bash Call Trace: [] warn_slowpath_null+0x18/0x1a [] call_console_drivers.isra.6.constprop.16+0x3a/0xb0 [] console_unlock+0x471/0x48e [] vprintk_emit+0x1f4/0x206 [] vprintk_default+0x18/0x1a [] vprintk_func+0x6e/0x70 [] printk+0x3e/0x46 [..] [] entry_SYSCALL_64_fastpath+0x13/0x94 ---[ end trace ]--- Signed-off-by: Sergey Senozhatsky --- kernel/printk/printk.c | 50 -- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 6f7b217..80f0177 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -213,17 +213,31 @@ static int nr_ext_console_drivers; static int __down_trylock_console_sem(unsigned long ip) { - if (down_trylock(_sem)) + int lock_failed; + unsigned long flags; + + printk_safe_enter(flags); + lock_failed = down_trylock(_sem); + printk_safe_exit(flags); + + if (lock_failed) return 1; mutex_acquire(_lock_dep_map, 0, 1, ip); return 0; } #define down_trylock_console_sem() __down_trylock_console_sem(_RET_IP_) -#define up_console_sem() do { \ - mutex_release(_lock_dep_map, 1, _RET_IP_);\ - up(_sem);\ -} while (0) +static void __up_console_sem(unsigned long ip) +{ + unsigned long flags; +