Re: [RFC PATCH 00/11] printk: safe printing in NMI context

From: Paul E. McKenney
Date: Wed Jun 18 2014 - 17:08:16 EST


On Wed, Jun 18, 2014 at 10:36:10PM +0200, Jiri Kosina wrote:
> On Wed, 18 Jun 2014, Paul E. McKenney wrote:
>
> > OK, unconditional non-use of NMIs is even easier. ;-)
> >
> > Something like the following.
> >
> > Thanx, Paul
> >
> > ------------------------------------------------------------------------
> >
> > rcu: Don't use NMIs to dump other CPUs' stacks
> >
> > Although NMI-based stack dumps are in principle more accurate, they are
> > also more likely to trigger deadlocks. This commit therefore replaces
> > all uses of trigger_all_cpu_backtrace() with rcu_dump_cpu_stacks(), so
> > that the CPU detecting an RCU CPU stall does the stack dumping.
> >
> > Signed-off-by: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx>
> >
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index c590e1201c74..777624e1329b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -932,10 +932,7 @@ static void record_gp_stall_check_time(struct rcu_state *rsp)
> > }
> >
> > /*
> > - * Dump stacks of all tasks running on stalled CPUs. This is a fallback
> > - * for architectures that do not implement trigger_all_cpu_backtrace().
> > - * The NMI-triggered stack traces are more accurate because they are
> > - * printed by the target CPU.
> > + * Dump stacks of all tasks running on stalled CPUs.
> > */
> > static void rcu_dump_cpu_stacks(struct rcu_state *rsp)
> > {
> > @@ -1013,7 +1010,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
> > (long)rsp->gpnum, (long)rsp->completed, totqlen);
> > if (ndetected == 0)
> > pr_err("INFO: Stall ended before state dump start\n");
> > - else if (!trigger_all_cpu_backtrace())
> > + else
> > rcu_dump_cpu_stacks(rsp);
> >
> > /* Complain about tasks blocking the grace period. */
> > @@ -1044,8 +1041,7 @@ static void print_cpu_stall(struct rcu_state *rsp)
> > pr_cont(" (t=%lu jiffies g=%ld c=%ld q=%lu)\n",
> > jiffies - rsp->gp_start,
> > (long)rsp->gpnum, (long)rsp->completed, totqlen);
> > - if (!trigger_all_cpu_backtrace())
> > - dump_stack();
> > + rcu_dump_cpu_stacks(rsp);
>
> This is prone to producing not really consistent stacktraces though,
> right? As the target task is still running at the time the stack is being
> walked, it might produce stacktraces that are potentially nonsensial.

If a CPU is stuck, the stack trace down to where it is stuck is
likely to be static. But yes, there is some potential for confusion.
My (admittedly limited) rcutorture testing produced sensible stack traces,
but things might be a bit uglier in other situations.

> How about sending NMI to the target CPU, so that the task is actually
> stopped, but printing its stacktrace from the CPU that detected the stall
> while it's stopped?
>
> That way, there is no printk()-from-NMI, but also the stacktrace is
> guaranteed to be self-consistent.

I believe that this was what Steven was suggesting, though by using
tracing. Of course, if my current approach isn't up to the job,
then something like this general approach would look quite good.

Thanx, Paul

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/