From 57cc80e6e39ecef3d11b7a787866f79ad1310da1 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 7 Aug 2024 18:02:24 +0300 Subject: [PATCH] rangelocks: re-check that the lock is still in the cheating mode after setting of DRAINING failed Noted by: markj Tested by: dougm, pho (previous version) Reviewed by: markj (previous version), dougm Fixes: 9ef425e560a97cabd1862e803eeb48468f89de18 Sponsored by: The FreeBSD Foundation --- sys/kern/kern_rangelock.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sys/kern/kern_rangelock.c b/sys/kern/kern_rangelock.c index 89b52d2550f059..20b65778c06d1d 100644 --- a/sys/kern/kern_rangelock.c +++ b/sys/kern/kern_rangelock.c @@ -128,12 +128,13 @@ rangelock_cheat_lock(struct rangelock *lock, int locktype, bool trylock, goto drain1; sleepq_release(&lock->head); /* Possibly forgive passed conflict */ - continue; + } else { + x = (v & ~RL_CHEAT_MASK) + RL_CHEAT_READER; + x |= RL_CHEAT_CHEATING; + if (atomic_fcmpset_acq_ptr(&lock->head, &v, + x) != 0) + break; } - x = (v & ~RL_CHEAT_MASK) + RL_CHEAT_READER; - x |= RL_CHEAT_CHEATING; - if (atomic_fcmpset_acq_ptr(&lock->head, &v, x) != 0) - break; if ((v & RL_CHEAT_CHEATING) == 0) return (false); if ((v & RL_CHEAT_DRAINING) != 0) @@ -156,11 +157,12 @@ rangelock_cheat_lock(struct rangelock *lock, int locktype, bool trylock, goto drain1; sleepq_release(&lock->head); /* Possibly forgive passed conflict */ - continue; + } else { + x = RL_CHEAT_WLOCKED | RL_CHEAT_CHEATING; + if (atomic_fcmpset_acq_ptr(&lock->head, &v, + x) != 0) + break; } - x = RL_CHEAT_WLOCKED | RL_CHEAT_CHEATING; - if (atomic_fcmpset_acq_ptr(&lock->head, &v, x) != 0) - break; if ((v & RL_CHEAT_CHEATING) == 0) return (false); if ((v & RL_CHEAT_DRAINING) != 0)