[RFC][PATCHv5 0/7] printk: use printk_safe to handle printk() recursive calls

Sergey Senozhatsky
2016-12-01T13:57:28Z

Hello,

This patch set extends a lock-less NMI per-cpu buffers idea to
handle recursive printk() calls. The basic mechanism is pretty much the
same -- at the beginning of a deadlock-prone section we switch to lock-less
printk callback, and return back to a default printk implementation at the
end; the messages are getting flushed to a logbuf buffer from a safer
context.

The question is how do we want to handle this? It might be too late
for the 4.10 merge window, so I'm OK with
a) this patch set and deferred+async printk (which I can send out
tomorrow) both will stay in mmotm/linux-next until 4.11 merge window,
which should give us enough time for testing.

I'm perhaps a bit less OK with
b) this will go into 4.11 and, thus, deferred+async printk will wait
for 4.11 merge window.

Option "a)" looks quite good. What do you think? Andrew, can we do this?
(if so, then how can I help?)

Deadlock scenarios that printk_safe can handle:

a) printk recursion from logbuf_lock spin_lock section in printk()
printk()
raw_spin_lock(&logbuf_lock);
WARN_ON(1);
raw_spin_unlock(&logbuf_lock);

b) printk from sem->lock spin_lock section
printk()
console_trylock()
down_trylock()
raw_spin_lock_irqsave(&sem->lock, flags);
WARN_ON(1);
raw_spin_unlock_irqrestore(&sem->lock, flags);

c) printk from logbuf_lock spin_lock section in console_unlock()
printk()
console_unlock()
raw_spin_lock(&logbuf_lock);
WARN_ON(1);
raw_spin_unlock(&logbuf_lock);

d) printk from ->pi_lock from semaphore up
printk()
console_unlock()
up()
try_to_wake_up()
raw_spin_lock_irqsave(&p->pi_lock, flags);
WARN_ON(1);
raw_spin_unlock_irqrestore(&p->pi_lock, flags);

e) printk from console_cont_flush() /*and down the call chain */
printk()
console_unlock()
call_console_drivers()
...
WARN_ON(1);

v5:
-- some style clean-ups and renamings (Petr)
-- use deferred printk when flush nmi/safe messages (Petr)

v4:
-- addressed Steven's review points
-- use printk_safe in console_cont_flush()

v3: (review by Petr)
-- renamed to printk_safe
-- !NMI config build fix
-- report lost messages for both printk_sae and printk_nmi
-- dropped recursion reporting patch
-- etc.

v2:
-- fix build error on !NMI configs, reported by Fengguang
-- reworked the series based on Petr's feedback
-- added a new patch to drop zap_locks()

Sergey Senozhatsky (7):
printk: use vprintk_func in vprintk()
printk: rename nmi.c and exported api
printk: introduce per-cpu safe_print seq buffer
printk: always use deferred printk when flush printk_safe lines
printk: report lost messages in printk safe/nmi contexts
printk: use printk_safe buffers in printk
printk: remove zap_locks() function

arch/arm/kernel/smp.c | 4 +-
include/linux/hardirq.h | 4 +-
include/linux/printk.h | 29 ++--
init/Kconfig | 16 ++-
init/main.c | 2 +-
kernel/kexec_core.c | 2 +-
kernel/panic.c | 4 +-
kernel/printk/Makefile | 2 +-
kernel/printk/internal.h | 63 ++++-----
kernel/printk/printk.c | 124 +++++------------
kernel/printk/{nmi.c => printk_safe.c} | 242 ++++++++++++++++++++++++---------
lib/nmi_backtrace.c | 2 +-
12 files changed, 275 insertions(+), 219 deletions(-)
rename kernel/printk/{nmi.c => printk_safe.c} (53%)

--
2.10.2