From: "Darrick J. Wong" <djwong@kernel.org>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Chandan Babu R <chandanbabu@kernel.org>,
Matthew Wilcox <willy@infradead.org>,
xfs <linux-xfs@vger.kernel.org>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>,
linux-kernel <linux-kernel@vger.kernel.org>,
x86@kernel.org, tglx@linutronix.de
Subject: Re: Are jump labels broken on 6.11-rc1?
Date: Tue, 6 Aug 2024 15:01:16 -0700 [thread overview]
Message-ID: <20240806220116.GH623957@frogsfrogsfrogs> (raw)
In-Reply-To: <20240806103808.GT37996@noisy.programming.kicks-ass.net>
On Tue, Aug 06, 2024 at 12:38:08PM +0200, Peter Zijlstra wrote:
> On Tue, Aug 06, 2024 at 11:44:13AM +0200, Peter Zijlstra wrote:
> > On Mon, Aug 05, 2024 at 07:35:22AM -0700, Darrick J. Wong wrote:
> > > On Wed, Jul 31, 2024 at 12:55:57PM +0200, Peter Zijlstra wrote:
> > > > On Tue, Jul 30, 2024 at 10:33:41PM -0700, Darrick J. Wong wrote:
> > > >
> > > > > Sooooo... it turns out that somehow your patch got mismerged on the
> > > > > first go-round, and that worked. The second time, there was no
> > > > > mismerge, which mean that the wrong atomic_cmpxchg() callsite was
> > > > > tested.
> > > > >
> > > > > Looking back at the mismerge, it actually changed
> > > > > __static_key_slow_dec_cpuslocked, which had in 6.10:
> > > > >
> > > > > if (atomic_dec_and_test(&key->enabled))
> > > > > jump_label_update(key);
> > > > >
> > > > > Decrement, then return true if the value was set to zero. With the 6.11
> > > > > code, it looks like we want to exchange a 1 with a 0, and act only if
> > > > > the previous value had been 1.
> > > > >
> > > > > So perhaps we really want this change? I'll send it out to the fleet
> > > > > and we'll see what it reports tomorrow morning.
> > > >
> > > > Bah yes, I missed we had it twice. Definitely both sites want this.
> > > >
> > > > I'll tentatively merge the below patch in tip/locking/urgent. I can
> > > > rebase if there is need.
> > >
> > > Hi Peter,
> > >
> > > This morning, I noticed the splat below with -rc2.
> > >
> > > WARNING: CPU: 0 PID: 8578 at kernel/jump_label.c:295 __static_key_slow_dec_cpuslocked.part.0+0x50/0x60
> > >
> > > Line 295 is the else branch of this code:
> > >
> > > if (atomic_cmpxchg(&key->enabled, 1, 0) == 1)
> > > jump_label_update(key);
> > > else
> > > WARN_ON_ONCE(!static_key_slow_try_dec(key));
> > >
> > > Apparently static_key_slow_try_dec returned false? Looking at that
> > > function, I suppose the atomic_read of key->enabled returned 0, since it
> > > didn't trigger the "WARN_ON_ONCE(v < 0)" code. Does that mean the value
> > > must have dropped from positive N to 0 without anyone ever taking the
> > > jump_label_mutex?
> >
> > One possible scenario I see:
> >
> > 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
> >
> >
> > Let me go play to see how best to cure this.
>
> I've ended up with this, not exactly pretty :/
>
> Thomas?
It seems to survive a short test, will send it out for overnight testing
on the full fleet, thanks.
--D
> ---
> diff --git a/kernel/jump_label.c b/kernel/jump_label.c
> index 6dc76b590703..5fa2c9f094b1 100644
> --- a/kernel/jump_label.c
> +++ b/kernel/jump_label.c
> @@ -168,8 +168,8 @@ 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,
> - * they must also observe all the text changes.
> + * static_key_dec() observe the positive value, they must also
> + * observe all the text changes.
> */
> atomic_set_release(&key->enabled, 1);
> } else {
> @@ -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(struct static_key *key, bool fast)
> {
> int v;
>
> @@ -268,31 +268,45 @@ static bool static_key_slow_try_dec(struct static_key *key)
> v = atomic_read(&key->enabled);
> do {
> /*
> - * Warn about the '-1' case though; since that means a
> - * decrement is concurrent with a first (0->1) increment. IOW
> - * people are trying to disable something that wasn't yet fully
> - * enabled. This suggests an ordering problem on the user side.
> + * Warn about the '-1' case; since that means a decrement is
> + * concurrent with a first (0->1) increment. IOW people are
> + * trying to disable something that wasn't yet fully enabled.
> + * This suggests an ordering problem on the user side.
> + *
> + * Warn about the '0' case; simple underflow.
> + *
> + * Neither case should succeed and change things.
> + */
> + if (WARN_ON_ONCE(v <= 0))
> + return false;
> +
> + /*
> + * Lockless fast-path, dec-not-one like behaviour.
> */
> - WARN_ON_ONCE(v < 0);
> - if (v <= 1)
> + if (fast && v <= 1)
> return false;
> } while (!likely(atomic_try_cmpxchg(&key->enabled, &v, v - 1)));
>
> - return true;
> + if (fast)
> + return true;
> +
> + /*
> + * Locked slow path, dec-and-test like behaviour.
> + */
> + lockdep_assert_held(&jump_label_mutex);
> + return v == 1;
> }
>
> static void __static_key_slow_dec_cpuslocked(struct static_key *key)
> {
> lockdep_assert_cpus_held();
>
> - if (static_key_slow_try_dec(key))
> + if (static_key_dec(key, true)) // dec-not-one
> return;
>
> guard(mutex)(&jump_label_mutex);
> - if (atomic_cmpxchg(&key->enabled, 1, 0) == 1)
> + if (static_key_dec(key, false)) // dec-and-test
> 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 +343,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(key, true)) // dec-not-one
> return;
>
> schedule_delayed_work(work, timeout);
next prev parent reply other threads:[~2024-08-06 22:01 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-30 3:38 Are jump labels broken on 6.11-rc1? Darrick J. Wong
2024-07-30 7:30 ` Chandan Babu R
2024-07-30 13:26 ` Peter Zijlstra
2024-07-30 13:59 ` Darrick J. Wong
2024-07-31 0:19 ` Darrick J. Wong
2024-07-31 3:10 ` Darrick J. Wong
2024-07-31 5:33 ` Darrick J. Wong
2024-07-31 10:55 ` Peter Zijlstra
2024-07-31 11:07 ` [tip: locking/urgent] jump_label: Fix the fix, brown paper bags galore tip-bot2 for Peter Zijlstra
2024-08-05 14:35 ` Are jump labels broken on 6.11-rc1? Darrick J. Wong
2024-08-06 9:44 ` Peter Zijlstra
2024-08-06 10:38 ` Peter Zijlstra
2024-08-06 22:01 ` Darrick J. Wong [this message]
2024-08-07 14:03 ` Thomas Gleixner
2024-08-07 14:34 ` Peter Zijlstra
2024-08-07 14:55 ` Thomas Gleixner
2024-08-07 15:05 ` Darrick J. Wong
2024-08-07 22:51 ` Darrick J. Wong
2024-08-27 3:35 ` Darrick J. Wong
2024-09-05 8:12 ` Peter Zijlstra
2024-09-05 9:16 ` Peter Zijlstra
2024-09-16 16:08 ` Darrick J. Wong
2024-09-19 23:41 ` Darrick J. Wong
2024-09-06 14:41 ` [tip: locking/urgent] jump_label: Fix static_key_slow_dec() yet again tip-bot2 for Peter Zijlstra
2024-09-10 20:16 ` Mark Brown
2024-09-21 13:52 ` Mark Rutland
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=20240806220116.GH623957@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=chandanbabu@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=willy@infradead.org \
--cc=x86@kernel.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 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.