[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <7d9df9c96529841caa9fbdfa37850bc36e5160fe.camel@web.de>
Date: Tue, 10 Sep 2024 23:10:08 +0200
From: Bert Karwatzki <spasswolf@....de>
To: Peter Zijlstra <peterz@...radead.org>
Cc: linux-kernel@...r.kernel.org, linux-next@...r.kernel.org, Thomas
Gleixner <tglx@...utronix.de>, "Darrick J . Wong" <djwong@...nel.org>,
x86@...nel.org, chandanbabu@...nel.org, willy@...radead.org,
spasswolf@....de
Subject: Re: commit de752774f38bb causes fatal error on boot
Am Dienstag, dem 10.09.2024 um 15:56 +0200 schrieb Peter Zijlstra:
> On Tue, Sep 10, 2024 at 01:11:09PM +0200, Bert Karwatzki wrote:
> > When booting linux-next-20240910 on my MSI alpha 15 Laptop running debian sid (amd64),
> > I get dropped to a shell and get the folllowing error in dmesg. I bisected this to
> > commit de752774f38bb ("jump_label: Fix static_key_slow_dec() yet again").
>
> I've just replaced that commit with the below -- which should be in
> tomorrows tree:
>
> ---
> commit 1d7f856c2ca449f04a22d876e36b464b7a9d28b6
> Author: Peter Zijlstra <peterz@...radead.org>
> Date: Mon Sep 9 12:50:09 2024 +0200
>
> jump_label: Fix static_key_slow_dec() yet again
>
> While commit 83ab38ef0a0b ("jump_label: Fix concurrency issues in
> static_key_slow_dec()") fixed one problem, it created yet another,
> notably the following is now possible:
>
> slow_dec
> if (try_dec) // dec_not_one-ish, false
> // enabled == 1
> slow_inc
> if (inc_not_disabled) // inc_not_zero-ish
> // enabled == 2
> return
>
> guard((mutex)(&jump_label_mutex);
> if (atomic_cmpxchg(1,0)==1) // false, we're 2
>
> slow_dec
> if (try-dec) // dec_not_one, true
> // enabled == 1
> return
> else
> try_dec() // dec_not_one, false
> WARN
>
> Use dec_and_test instead of cmpxchg(), like it was prior to
> 83ab38ef0a0b. Add a few WARNs for the paranoid.
>
> Fixes: 83ab38ef0a0b ("jump_label: Fix concurrency issues in static_key_slow_dec()")
> Reported-by: "Darrick J. Wong" <djwong@...nel.org>
> Tested-by: Klara Modin <klarasmodin@...il.com>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@...radead.org>
>
> diff --git a/kernel/jump_label.c b/kernel/jump_label.c
> index 6dc76b590703..93a822d3c468 100644
> --- a/kernel/jump_label.c
> +++ b/kernel/jump_label.c
> @@ -168,7 +168,7 @@ bool static_key_slow_inc_cpuslocked(struct static_key *key)
> jump_label_update(key);
> /*
> * Ensure that when static_key_fast_inc_not_disabled() or
> - * static_key_slow_try_dec() observe the positive value,
> + * static_key_dec_not_one() observe the positive value,
> * they must also observe all the text changes.
> */
> atomic_set_release(&key->enabled, 1);
> @@ -250,7 +250,7 @@ void static_key_disable(struct static_key *key)
> }
> EXPORT_SYMBOL_GPL(static_key_disable);
>
> -static bool static_key_slow_try_dec(struct static_key *key)
> +static bool static_key_dec_not_one(struct static_key *key)
> {
> int v;
>
> @@ -274,6 +274,14 @@ static bool static_key_slow_try_dec(struct static_key *key)
> * enabled. This suggests an ordering problem on the user side.
> */
> WARN_ON_ONCE(v < 0);
> +
> + /*
> + * Warn about underflow, and lie about success in an attempt to
> + * not make things worse.
> + */
> + if (WARN_ON_ONCE(v == 0))
> + return true;
> +
> if (v <= 1)
> return false;
> } while (!likely(atomic_try_cmpxchg(&key->enabled, &v, v - 1)));
> @@ -284,15 +292,27 @@ static bool static_key_slow_try_dec(struct static_key *key)
> static void __static_key_slow_dec_cpuslocked(struct static_key *key)
> {
> lockdep_assert_cpus_held();
> + int val;
>
> - if (static_key_slow_try_dec(key))
> + if (static_key_dec_not_one(key))
> return;
>
> guard(mutex)(&jump_label_mutex);
> - if (atomic_cmpxchg(&key->enabled, 1, 0) == 1)
> + val = atomic_read(&key->enabled);
> + /*
> + * It should be impossible to observe -1 with jump_label_mutex held,
> + * see static_key_slow_inc_cpuslocked().
> + */
> + if (WARN_ON_ONCE(val == -1))
> + return;
> + /*
> + * Cannot already be 0, something went sideways.
> + */
> + if (WARN_ON_ONCE(val == 0))
> + return;
> +
> + if (atomic_dec_and_test(&key->enabled))
> jump_label_update(key);
> - else
> - WARN_ON_ONCE(!static_key_slow_try_dec(key));
> }
>
> static void __static_key_slow_dec(struct static_key *key)
> @@ -329,7 +349,7 @@ void __static_key_slow_dec_deferred(struct static_key *key,
> {
> STATIC_KEY_CHECK_USE(key);
>
> - if (static_key_slow_try_dec(key))
> + if (static_key_dec_not_one(key))
> return;
>
> schedule_delayed_work(work, timeout);
Just tested the new version, no error here.
Bert karwatzki
Powered by blists - more mailing lists