On (10/06/16 16:56), Petr Mladek wrote: [..] > > there are many WARN_ON_* on > > vprintk_alt()->alt_printk_log_store()->vsnprintf() path but they all > > seem to be calling printk(): > > > > - WARN_ON_ONCE() from vsnprintf() > > - WARN_ONCE() from vsnprintf()->format_decode() > > - WARN_ON vsnprintf()->set_field_width() > > - WARN_ON from vsnprintf()->set_precision() > > - WARN_ON from vsnprintf()->pointer()->flags_string() > > > > a side note, some of these WARNs are... 'funny'. e.g., to deadlock a > > system it's enough to just pass an unsupported flag in format string. > > vsnprintf() will > > WARN_ONCE(1, "Please remove unsupported %%%c in format string\n", *fmt) > > > > but the problem is that we are already in printk(): > > > > printk() > > raw_spin_lock(&logbuf_lock) > > text_len = vscnprintf(text, sizeof(textbuf), fmt, args) > > WARN_ONCE(1, "Please remove unsupported ...) > > printk() > > raw_spin_lock(&logbuf_lock) << > > deadlock > > Just for record. This vscnprintf() is called when logbuf_cpu is set. > Therefore this particular recursion is not possible at the moment.
ah, indeed. thanks. > Anyway, I agree that alt_printk_enter() calls might get nested. > The direct vprintk_emit() calls are one reason. I guess that > we will need to use the same counter/enter functions also > for WARN_*DEFERRED(). And it would cause nesting as well. > > Therefore we need to be careful about loosing the original > value of irq flags. > > The question is whether we need to store the flags in > a per-CPU variable. We might also store it on the stack > of the enter()/exit() function caller. I mean something like yes, let's keep it on the stack. this particular implementation was just an experiment, and I hate it. what I currently have in my tree: #define alt_printk_enter(flags) \ do { \ local_irq_save(flags); \ __alt_printk_enter(); \ } while (0) #define alt_printk_exit(flags) \ do { \ __alt_printk_exit(); \ local_irq_restore(flags); \ } while (0) -ss