From: Chris Mason <mason@kernel.org>
To: peterz@infradead.org, tglx@kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] futex: sample poll cookie after publishing new hash
Date: Mon, 17 Aug 2026 18:01:42 -0700 [thread overview]
Message-ID: <20260818011036.1138213-2-mason@kernel.org> (raw)
In-Reply-To: <20260818011036.1138213-1-mason@kernel.org>
futex_ref_drop() may only skip its grace period when one has already
elapsed since the current private hash was published:
kernel/futex/core.c:futex_ref_drop
if (poll_state_synchronize_rcu(mm->futex.phash.batches)) {
/*
* There was a grace-period, we can begin now.
*/
__futex_ref_atomic_begin(fph);
return;
}
The cookie it polls is sampled one statement before that publication:
kernel/futex/core.c:__futex_pivot_hash
new->state = FR_PERCPU;
scoped_guard(rcu) {
mmph->batches = get_state_synchronize_rcu();
rcu_assign_pointer(mmph->hash, new);
}
kvfree_rcu(fph, rcu);
get_state_synchronize_rcu() anchors its guarantee at the snapshot, so
the cookie is cleared by the first grace period that starts from there
on, including one starting between the two stores which never waited
for a reader that loaded the old hash after it began.
CPU 0 (resize) CPU 1 (futex_hash)
============== ==================
__futex_pivot_hash()
batches = get_state_...()
grace period starts
guard(rcu)
fph = old hash
rcu_assign_pointer(hash, new)
kvfree_rcu(old hash)
futex_hash_allocate()
futex_ref_drop(new hash)
poll_state_...() -> true
__futex_ref_atomic_begin()
atomic = LONG_MAX
futex_ref_get(old hash) -> true
spin_lock(&fph->queues[i].lock)
The reference count lives in the mm and has just been biased for the
new generation, so the stalled reader pins and then locks the retired
hash that is already queued for free, and its later put is charged
against the live generation.
Fix by sampling the cookie after rcu_assign_pointer() publishes the
new hash. Drop the surrounding scoped_guard(rcu) while at it: it only
delayed completion of the prematurely anchored grace-period and serves
no purpose once the cookie is sampled after publication. The writer
side is serialized by mm->futex.phash.lock and neither
rcu_assign_pointer() nor kvfree_rcu() requires a read-side section.
Fixes: 56180dd20c19 ("futex: Use RCU-based per-CPU reference counting instead of rcuref_t")
Assisted-by: kres:claude-opus-5
Signed-off-by: Chris Mason <mason@kernel.org>
---
kernel/futex/core.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 128c5752f225..05619eb8329c 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -209,10 +209,14 @@ static bool __futex_pivot_hash(struct mm_struct *mm, struct futex_private_hash *
futex_rehash_private(fph, new);
}
new->state = FR_PERCPU;
- scoped_guard(rcu) {
- mmph->batches = get_state_synchronize_rcu();
- rcu_assign_pointer(mmph->hash, new);
- }
+ rcu_assign_pointer(mmph->hash, new);
+ /*
+ * Pairs with futex_ref_drop(): ->batches must be sampled at or after
+ * the rcu_assign_pointer() above, so any grace-period satisfying
+ * poll_state_synchronize_rcu() provably started once no reader could
+ * still load the retired fph. Both stores are done under mmph->lock.
+ */
+ mmph->batches = get_state_synchronize_rcu();
kvfree_rcu(fph, rcu);
return true;
}
--
2.53.0-Meta
prev parent reply other threads:[~2026-08-18 1:10 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 1:01 [PATCH RFC] __futex_pivot_hash() race Chris Mason
2026-08-18 1:01 ` Chris Mason [this message]
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=20260818011036.1138213-2-mason@kernel.org \
--to=mason@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@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.