From: Petr Mladek <pmladek@suse.com>
To: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Jan Kara <jack@suse.cz>, Tejun Heo <tj@kernel.org>,
Calvin Owens <calvinowens@fb.com>,
Thomas Gleixner <tglx@linutronix.de>,
Mel Gorman <mgorman@techsingularity.net>,
Steven Rostedt <rostedt@goodmis.org>,
Ingo Molnar <mingo@redhat.com>,
Peter Zijlstra <peterz@infradead.org>,
Laura Abbott <labbott@redhat.com>,
Andy Lutomirski <luto@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Kees Cook <keescook@chromium.org>,
linux-kernel@vger.kernel.org,
Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Subject: Re: [RFC][PATCHv4 3/6] printk: introduce per-cpu safe_print seq buffer
Date: Thu, 24 Nov 2016 17:58:21 +0100 [thread overview]
Message-ID: <20161124165821.GG24103@pathway.suse.cz> (raw)
In-Reply-To: <20161027154933.1211-4-sergey.senozhatsky@gmail.com>
On Fri 2016-10-28 00:49:30, Sergey Senozhatsky wrote:
> This patch extends the idea of NMI per-cpu buffers to regions
> that may cause recursive printk() calls and possible deadlocks.
> Namely, printk() can't handle printk calls from schedule code
> or printk() calls from lock debugging code (spin_dump() for instance);
> because those may be called with `sem->lock' already taken or any
> other `critical' locks (p->pi_lock, etc.). An example of deadlock
> can be
>
> vprintk_emit()
> console_unlock()
> up() << raw_spin_lock_irqsave(&sem->lock, flags);
> wake_up_process()
> try_to_wake_up()
> ttwu_queue()
> ttwu_activate()
> activate_task()
> enqueue_task()
> enqueue_task_fair()
> cfs_rq_of()
> task_of()
> WARN_ON_ONCE(!entity_is_task(se))
> vprintk_emit()
> console_trylock()
> down_trylock()
> raw_spin_lock_irqsave(&sem->lock, flags)
> ^^^^ deadlock
>
> and some other cases.
>
> Just like in NMI implementation, the solution uses a per-cpu
> `printk_func' pointer to 'redirect' printk() calls to a 'safe'
> callback, that store messages in a per-cpu buffer and flushes
> them back to logbuf buffer later.
>
> Usage example:
>
> printk()
> printk_safe_enter(flags)
> //
> // any printk() call from here will endup in vprintk_safe(),
> // that stores messages in a special per-CPU buffer.
> //
> printk_safe_exit(flags)
>
> The 'redirection' mechanism, though, has been reworked, as suggested
> by Petr Mladek. Instead of using a per-cpu @print_func callback we now
> keep a per-cpu printk-context variable and call either default or nmi
> vprintk function depending on its value. printk_nmi_entrer/exit and
> printk_safe_enter/exit, thus, just set/celar corresponding bits in
> printk-context functions.
>
> The patch only adds printk_safe support, we don't use it yet.
>
> Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
> index 7fd2838..87c784b 100644
> --- a/kernel/printk/internal.h
> +++ b/kernel/printk/internal.h
> #endif /* CONFIG_PRINTK_NMI */
> +
> +#ifdef CONFIG_PRINTK
> +
> +#define PRINTK_SAFE_CONTEXT_MASK 0x7fffffff
> +#define PRINTK_SAFE_NMI_CONTEXT_MASK 0x80000000
What about shorter name PRINTK_NMI_CONTEXT_MASK?
> diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
> index 1f66163..af74d9c 100644
> --- a/kernel/printk/printk_safe.c
> +++ b/kernel/printk/printk_safe.c
> @@ -50,27 +49,26 @@ struct printk_safe_seq_buf {
> struct irq_work work; /* IRQ work that flushes the buffer */
> unsigned char buffer[SAFE_LOG_BUF_LEN];
> };
> +
> +static DEFINE_PER_CPU(struct printk_safe_seq_buf, safe_print_seq);
> +static DEFINE_PER_CPU(int, printk_safe_context);
I would personally use the short name "printk_context". It is a generic
value. Zero value means that it is a normal context. Also there is
an idea to add KDB context that would use its own vprintk_kdb()
implementation and will not use the printk_safe buffer.
> +#ifdef CONFIG_PRINTK_NMI
> static DEFINE_PER_CPU(struct printk_safe_seq_buf, nmi_print_seq);
> +atomic_t nmi_message_lost;
> +#endif
>
> -/*
> - * Safe printk() for NMI context. It uses a per-CPU buffer to
> - * store the message. NMIs are not nested, so there is always only
> - * one writer running. But the buffer might get flushed from another
> - * CPU, so we need to be careful.
> - */
> -static int vprintk_safe_nmi(const char *fmt, va_list args)
> +static int printk_safe_log_store(struct printk_safe_seq_buf *s,
> + const char *fmt, va_list args)
> {
> - struct printk_safe_seq_buf *s = this_cpu_ptr(&nmi_print_seq);
> - int add = 0;
> + int add;
> size_t len;
>
> again:
> len = atomic_read(&s->len);
>
> - if (len >= sizeof(s->buffer)) {
> - atomic_inc(&nmi_message_lost);
> - return 0;
> - }
> + if (len >= sizeof(s->buffer))
> + return -E2BIG;
E2BIG means "argument list too long" and does not fit much here.
I would suggest to use -ENOSPC. It is not ideal either but it fits
slightly better.
> +/*
> + * Lockless printk(), to avoid deadlocks should the printk() recurse
> + * into itself. It uses a per-CPU buffer to store the message, just like
> + * NMI.
> + */
> +static int vprintk_safe(const char *fmt, va_list args)
> +{
> + struct printk_safe_seq_buf *s = this_cpu_ptr(&safe_print_seq);
> +
> + return printk_safe_log_store(s, fmt, args);
We should return zero if printk_safe_log_store() returns an error.
I know that it will get fixed in the next patch. But we should do
some minimum sanity check here because of bisection.
Best Regards,
Petr
next prev parent reply other threads:[~2016-11-24 16:58 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-27 15:49 [RFC][PATCHv4 0/6] printk: use printk_safe to handle printk() recursive calls Sergey Senozhatsky
2016-10-27 15:49 ` [RFC][PATCHv4 1/6] printk: use vprintk_func in vprintk() Sergey Senozhatsky
2016-11-24 16:28 ` Petr Mladek
2016-10-27 15:49 ` [RFC][PATCHv4 2/6] printk: rename nmi.c and exported api Sergey Senozhatsky
2016-11-24 16:35 ` Petr Mladek
2016-12-01 1:07 ` Sergey Senozhatsky
2016-12-01 12:12 ` Petr Mladek
2016-10-27 15:49 ` [RFC][PATCHv4 3/6] printk: introduce per-cpu safe_print seq buffer Sergey Senozhatsky
2016-11-24 16:58 ` Petr Mladek [this message]
2016-12-01 1:08 ` Sergey Senozhatsky
2016-12-01 5:32 ` Sergey Senozhatsky
2016-10-27 15:49 ` [RFC][PATCHv4 4/6] printk: report lost messages in printk safe/nmi contexts Sergey Senozhatsky
2016-11-25 11:07 ` Petr Mladek
2016-12-01 2:10 ` Sergey Senozhatsky
2016-12-01 12:50 ` Petr Mladek
2016-10-27 15:49 ` [RFC][PATCHv4 5/6] printk: use printk_safe buffers Sergey Senozhatsky
2016-11-25 14:28 ` Petr Mladek
2016-12-01 2:14 ` Sergey Senozhatsky
2016-10-27 15:49 ` [RFC][PATCHv4 6/6] printk: remove zap_locks() function Sergey Senozhatsky
2016-11-25 15:01 ` Petr Mladek
2016-11-25 15:17 ` Peter Zijlstra
2016-12-01 2:34 ` Sergey Senozhatsky
2016-12-01 5:42 ` Peter Zijlstra
2016-12-01 13:36 ` Petr Mladek
2016-12-02 1:11 ` Sergey Senozhatsky
2016-12-01 2:18 ` Sergey Senozhatsky
2016-12-01 12:50 ` Sergey Senozhatsky
2016-12-01 13:15 ` Petr Mladek
2016-10-28 3:30 ` [RFC][PATCHv4 0/6] printk: use printk_safe to handle printk() recursive calls Linus Torvalds
2016-10-28 4:05 ` Sergey Senozhatsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161124165821.GG24103@pathway.suse.cz \
--to=pmladek@suse.com \
--cc=akpm@linux-foundation.org \
--cc=calvinowens@fb.com \
--cc=jack@suse.cz \
--cc=keescook@chromium.org \
--cc=labbott@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mgorman@techsingularity.net \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=sergey.senozhatsky.work@gmail.com \
--cc=sergey.senozhatsky@gmail.com \
--cc=tglx@linutronix.de \
--cc=tj@kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox