From: Michal Hocko <mhocko@suse.com>
To: Doug Anderson <dianders@chromium.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Petr Mladek <pmladek@suse.com>, kernel test robot <lkp@intel.com>,
Lecopzer Chen <lecopzer.chen@mediatek.com>,
Pingfan Liu <kernelfans@gmail.com>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] watchdog/hardlockup: Avoid large stack frames in watchdog_hardlockup_check()
Date: Tue, 1 Aug 2023 17:26:46 +0200 [thread overview]
Message-ID: <ZMkkNpYcaYPAMj0Z@dhcp22.suse.cz> (raw)
In-Reply-To: <CAD=FV=V5hx7Zy-XMB=sPYcD_h-iP5VknmEoJwvw3Akd_1wDnRw@mail.gmail.com>
On Tue 01-08-23 07:16:15, Doug Anderson wrote:
> Hi,
>
> On Tue, Aug 1, 2023 at 5:58 AM Michal Hocko <mhocko@suse.com> wrote:
> >
> > On Mon 31-07-23 09:17:59, Douglas Anderson wrote:
> > > After commit 77c12fc95980 ("watchdog/hardlockup: add a "cpu" param to
> > > watchdog_hardlockup_check()") we started storing a `struct cpumask` on
> > > the stack in watchdog_hardlockup_check(). On systems with
> > > CONFIG_NR_CPUS set to 8192 this takes up 1K on the stack. That
> > > triggers warnings with `CONFIG_FRAME_WARN` set to 1024.
> > >
> > > Instead of putting this `struct cpumask` on the stack, let's declare
> > > it as `static`. This has the downside of taking up 1K of memory all
> > > the time on systems with `CONFIG_NR_CPUS` to 8192, but on systems with
> > > smaller `CONFIG_NR_CPUS` it's not much emory (with 128 CPUs it's only
> > > 16 bytes of memory). Presumably anyone building a system with
> > > `CONFIG_NR_CPUS=8192` can afford the extra 1K of memory.
> > >
> > > NOTE: as part of this change, we no longer check the return value of
> > > trigger_single_cpu_backtrace(). While we could do this and only call
> > > cpumask_clear_cpu() if trigger_single_cpu_backtrace() didn't fail,
> > > that's probably not worth it. There's no reason to believe that
> > > trigger_cpumask_backtrace() will succeed at backtracing the CPU when
> > > trigger_single_cpu_backtrace() failed.
> > >
> > > Alternatives considered:
> > > - Use kmalloc with GFP_ATOMIC to allocate. I decided against this
> > > since relying on kmalloc when the system is hard locked up seems
> > > like a bad idea.
> > > - Change the arch_trigger_cpumask_backtrace() across all architectures
> > > to take an extra parameter to get the needed behavior. This seems
> > > like a lot of churn for a small savings.
> > >
> > > Fixes: 77c12fc95980 ("watchdog/hardlockup: add a "cpu" param to watchdog_hardlockup_check()")
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Closes: https://lore.kernel.org/r/202307310955.pLZDhpnl-lkp@intel.com
> > > Signed-off-by: Douglas Anderson <dianders@chromium.org>
> > > ---
> > >
> > > kernel/watchdog.c | 14 +++++++-------
> > > 1 file changed, 7 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/kernel/watchdog.c b/kernel/watchdog.c
> > > index be38276a365f..19db2357969a 100644
> > > --- a/kernel/watchdog.c
> > > +++ b/kernel/watchdog.c
> > > @@ -151,9 +151,6 @@ void watchdog_hardlockup_check(unsigned int cpu, struct pt_regs *regs)
> > > */
> > > if (is_hardlockup(cpu)) {
> > > unsigned int this_cpu = smp_processor_id();
> > > - struct cpumask backtrace_mask;
> > > -
> > > - cpumask_copy(&backtrace_mask, cpu_online_mask);
> > >
> > > /* Only print hardlockups once. */
> > > if (per_cpu(watchdog_hardlockup_warned, cpu))
> > > @@ -167,10 +164,8 @@ void watchdog_hardlockup_check(unsigned int cpu, struct pt_regs *regs)
> > > show_regs(regs);
> > > else
> > > dump_stack();
> > > - cpumask_clear_cpu(cpu, &backtrace_mask);
> > > } else {
> > > - if (trigger_single_cpu_backtrace(cpu))
> > > - cpumask_clear_cpu(cpu, &backtrace_mask);
> > > + trigger_single_cpu_backtrace(cpu);
> > > }
> > >
> > > /*
> > > @@ -178,8 +173,13 @@ void watchdog_hardlockup_check(unsigned int cpu, struct pt_regs *regs)
> > > * hardlockups generating interleaving traces
> > > */
> > > if (sysctl_hardlockup_all_cpu_backtrace &&
> > > - !test_and_set_bit(0, &watchdog_hardlockup_all_cpu_dumped))
> > > + !test_and_set_bit(0, &watchdog_hardlockup_all_cpu_dumped)) {
> > > + static struct cpumask backtrace_mask;
> > > +
> > > + cpumask_copy(&backtrace_mask, cpu_online_mask);
> > > + cpumask_clear_cpu(cpu, &backtrace_mask);
> > > trigger_cpumask_backtrace(&backtrace_mask);
> >
> > This looks rather wasteful to just copy the cpumask over to
> > backtrace_mask in nmi_trigger_cpumask_backtrace (which all but sparc
> > arches do AFAICS).
> >
> > Would it be possible to use arch_trigger_cpumask_backtrace(cpu_online_mask, false)
> > and special case cpu != this_cpu && sysctl_hardlockup_all_cpu_backtrace?
>
> So you're saying optimize the case where cpu == this_cpu and then have
> a special case (where we still copy) for cpu != this_cpu? I can do
> that if that's what people want, but (assuming I understand correctly)
> that's making the wrong tradeoff. Specifically, this code runs one
> time right as we're crashing and if it takes an extra millisecond to
> run it's not a huge deal. It feels better to avoid the special case
> and keep the code smaller.
>
> Let me know if I misunderstood.
I meant something like this (untested but it should give an idea what I
mean hopefully). Maybe it can be simplified even further. TBH I am not
entirely sure why cpu == this_cpu needs this special handling.
---
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index be38276a365f..0eedac9f1019 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -151,9 +151,7 @@ void watchdog_hardlockup_check(unsigned int cpu, struct pt_regs *regs)
*/
if (is_hardlockup(cpu)) {
unsigned int this_cpu = smp_processor_id();
- struct cpumask backtrace_mask;
-
- cpumask_copy(&backtrace_mask, cpu_online_mask);
+ bool dump_all = false;
/* Only print hardlockups once. */
if (per_cpu(watchdog_hardlockup_warned, cpu))
@@ -167,10 +165,6 @@ void watchdog_hardlockup_check(unsigned int cpu, struct pt_regs *regs)
show_regs(regs);
else
dump_stack();
- cpumask_clear_cpu(cpu, &backtrace_mask);
- } else {
- if (trigger_single_cpu_backtrace(cpu))
- cpumask_clear_cpu(cpu, &backtrace_mask);
}
/*
@@ -179,7 +173,12 @@ void watchdog_hardlockup_check(unsigned int cpu, struct pt_regs *regs)
*/
if (sysctl_hardlockup_all_cpu_backtrace &&
!test_and_set_bit(0, &watchdog_hardlockup_all_cpu_dumped))
- trigger_cpumask_backtrace(&backtrace_mask);
+ dump_all = true;
+
+ if (dump_all)
+ arch_trigger_cpumask_backtrace(cpu_online_mask, cpu != this_cpu);
+ else if (cpu != this_cpu)
+ trigger_single_cpu_backtrace(cpu);
if (hardlockup_panic)
nmi_panic(regs, "Hard LOCKUP");
--
Michal Hocko
SUSE Labs
next prev parent reply other threads:[~2023-08-01 15:26 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-31 16:17 [PATCH] watchdog/hardlockup: Avoid large stack frames in watchdog_hardlockup_check() Douglas Anderson
2023-08-01 12:58 ` Michal Hocko
2023-08-01 14:16 ` Doug Anderson
2023-08-01 15:26 ` Michal Hocko [this message]
2023-08-01 15:41 ` Doug Anderson
2023-08-02 7:27 ` Michal Hocko
2023-08-02 14:12 ` Doug Anderson
2023-08-02 16:05 ` Michal Hocko
2023-08-03 8:12 ` Petr Mladek
2023-08-03 8:30 ` Michal Hocko
2023-08-03 23:10 ` Doug Anderson
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=ZMkkNpYcaYPAMj0Z@dhcp22.suse.cz \
--to=mhocko@suse.com \
--cc=akpm@linux-foundation.org \
--cc=dianders@chromium.org \
--cc=kernelfans@gmail.com \
--cc=lecopzer.chen@mediatek.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lkp@intel.com \
--cc=pmladek@suse.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.