Fix an rcuref_put() slowpath race.
Signed-off-by: Ingo Molnar <mingo@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmfCB+4RHG1pbmdvQGtl cm5lbC5vcmcACgkQEnMQ0APhK1h75Q/+NuJhVxipKT1ZVGJ8X1OyL4XvevELshU0 HhsKYkwrAO+AIPZ/5zxVo4v5qsPZ0JeIHZQITykfgjy180z4c4LemBcUyrxzcehW bYz5HLyJa20gbyiTzNe6RlGWkQ52tivM8Tk4yBmfJNocgvkril7P1Fc02tbQsj5u lXOm/NMKSiHInoEXDKB9PZk5GK0qnZnSDdRFFuPQiqRuLOt1BbiLpRRGlxPhWLkk qwrJQMZyrqqe5MggdDhm21HPvJIZPa/IKU3W6V3ykhd8Va6rfQ7RsJfQ3CJlQR1I oVflGPDVhZlirRhlswgBzUBUfPcmUISLTyZ/PlwwNyaBYWVqCn1YyDTacJlIkqc4 hD7Nds4UitmVmFaENQLmkroSObvEpdDj/qyl6RI8pk+6pf58496+HoRRpfC3Am/2 Oa8q/rx0xG2TPFvVpnnBCxw2cPqIxG1ZyMbA70GuF1wlYxExccGWLQmB246TORB3 3HWw7+heBrOJ5yspiXpeNdtMMQoMYiImsxTJuKjhwCSRPZyOCyTiIionk5lX2QVy oOykELFFfp2g+/UoxJf5NfbucQyshTofetQry6sAHKl7iCg/5QBr04OqlMRxQ231 Ej/1Urq8mkXC8flAujv5UIIIpXlTeKNtSfNhahkyZZ3YlUijatiJs5bU5CHTvyBu GH4m0TUgFNI= =39Cx -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
405a41d759
|
@ -71,27 +71,30 @@ static inline __must_check bool rcuref_get(rcuref_t *ref)
|
||||||
return rcuref_get_slowpath(ref);
|
return rcuref_get_slowpath(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern __must_check bool rcuref_put_slowpath(rcuref_t *ref);
|
extern __must_check bool rcuref_put_slowpath(rcuref_t *ref, unsigned int cnt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal helper. Do not invoke directly.
|
* Internal helper. Do not invoke directly.
|
||||||
*/
|
*/
|
||||||
static __always_inline __must_check bool __rcuref_put(rcuref_t *ref)
|
static __always_inline __must_check bool __rcuref_put(rcuref_t *ref)
|
||||||
{
|
{
|
||||||
|
int cnt;
|
||||||
|
|
||||||
RCU_LOCKDEP_WARN(!rcu_read_lock_held() && preemptible(),
|
RCU_LOCKDEP_WARN(!rcu_read_lock_held() && preemptible(),
|
||||||
"suspicious rcuref_put_rcusafe() usage");
|
"suspicious rcuref_put_rcusafe() usage");
|
||||||
/*
|
/*
|
||||||
* Unconditionally decrease the reference count. The saturation and
|
* Unconditionally decrease the reference count. The saturation and
|
||||||
* dead zones provide enough tolerance for this.
|
* dead zones provide enough tolerance for this.
|
||||||
*/
|
*/
|
||||||
if (likely(!atomic_add_negative_release(-1, &ref->refcnt)))
|
cnt = atomic_sub_return_release(1, &ref->refcnt);
|
||||||
|
if (likely(cnt >= 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle the last reference drop and cases inside the saturation
|
* Handle the last reference drop and cases inside the saturation
|
||||||
* and dead zones.
|
* and dead zones.
|
||||||
*/
|
*/
|
||||||
return rcuref_put_slowpath(ref);
|
return rcuref_put_slowpath(ref, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -220,6 +220,7 @@ EXPORT_SYMBOL_GPL(rcuref_get_slowpath);
|
||||||
/**
|
/**
|
||||||
* rcuref_put_slowpath - Slowpath of __rcuref_put()
|
* rcuref_put_slowpath - Slowpath of __rcuref_put()
|
||||||
* @ref: Pointer to the reference count
|
* @ref: Pointer to the reference count
|
||||||
|
* @cnt: The resulting value of the fastpath decrement
|
||||||
*
|
*
|
||||||
* Invoked when the reference count is outside of the valid zone.
|
* Invoked when the reference count is outside of the valid zone.
|
||||||
*
|
*
|
||||||
|
@ -233,10 +234,8 @@ EXPORT_SYMBOL_GPL(rcuref_get_slowpath);
|
||||||
* with a concurrent get()/put() pair. Caller is not allowed to
|
* with a concurrent get()/put() pair. Caller is not allowed to
|
||||||
* deconstruct the protected object.
|
* deconstruct the protected object.
|
||||||
*/
|
*/
|
||||||
bool rcuref_put_slowpath(rcuref_t *ref)
|
bool rcuref_put_slowpath(rcuref_t *ref, unsigned int cnt)
|
||||||
{
|
{
|
||||||
unsigned int cnt = atomic_read(&ref->refcnt);
|
|
||||||
|
|
||||||
/* Did this drop the last reference? */
|
/* Did this drop the last reference? */
|
||||||
if (likely(cnt == RCUREF_NOREF)) {
|
if (likely(cnt == RCUREF_NOREF)) {
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue