Skip to content

Commit 405a41d

Browse files
committed
Merge tag 'locking-urgent-2025-02-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking fix from Ingo Molnar: "Fix an rcuref_put() slowpath race" * tag 'locking-urgent-2025-02-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: rcuref: Plug slowpath race in rcuref_put()
2 parents 5c44dda + b9a4952 commit 405a41d

File tree

2 files changed

+8
-6
lines changed

2 files changed

+8
-6
lines changed

include/linux/rcuref.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,27 +71,30 @@ static inline __must_check bool rcuref_get(rcuref_t *ref)
7171
return rcuref_get_slowpath(ref);
7272
}
7373

74-
extern __must_check bool rcuref_put_slowpath(rcuref_t *ref);
74+
extern __must_check bool rcuref_put_slowpath(rcuref_t *ref, unsigned int cnt);
7575

7676
/*
7777
* Internal helper. Do not invoke directly.
7878
*/
7979
static __always_inline __must_check bool __rcuref_put(rcuref_t *ref)
8080
{
81+
int cnt;
82+
8183
RCU_LOCKDEP_WARN(!rcu_read_lock_held() && preemptible(),
8284
"suspicious rcuref_put_rcusafe() usage");
8385
/*
8486
* Unconditionally decrease the reference count. The saturation and
8587
* dead zones provide enough tolerance for this.
8688
*/
87-
if (likely(!atomic_add_negative_release(-1, &ref->refcnt)))
89+
cnt = atomic_sub_return_release(1, &ref->refcnt);
90+
if (likely(cnt >= 0))
8891
return false;
8992

9093
/*
9194
* Handle the last reference drop and cases inside the saturation
9295
* and dead zones.
9396
*/
94-
return rcuref_put_slowpath(ref);
97+
return rcuref_put_slowpath(ref, cnt);
9598
}
9699

97100
/**

lib/rcuref.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ EXPORT_SYMBOL_GPL(rcuref_get_slowpath);
220220
/**
221221
* rcuref_put_slowpath - Slowpath of __rcuref_put()
222222
* @ref: Pointer to the reference count
223+
* @cnt: The resulting value of the fastpath decrement
223224
*
224225
* Invoked when the reference count is outside of the valid zone.
225226
*
@@ -233,10 +234,8 @@ EXPORT_SYMBOL_GPL(rcuref_get_slowpath);
233234
* with a concurrent get()/put() pair. Caller is not allowed to
234235
* deconstruct the protected object.
235236
*/
236-
bool rcuref_put_slowpath(rcuref_t *ref)
237+
bool rcuref_put_slowpath(rcuref_t *ref, unsigned int cnt)
237238
{
238-
unsigned int cnt = atomic_read(&ref->refcnt);
239-
240239
/* Did this drop the last reference? */
241240
if (likely(cnt == RCUREF_NOREF)) {
242241
/*

0 commit comments

Comments
 (0)