git: 57cc80e6e39e - main - rangelocks: re-check that the lock is still in the cheating mode after setting of DRAINING failed

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 08 Aug 2024 08:33:35 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=57cc80e6e39ecef3d11b7a787866f79ad1310da1

commit 57cc80e6e39ecef3d11b7a787866f79ad1310da1
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-08-07 15:02:24 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-08-08 08:32:36 +0000

    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 89b52d2550f0..20b65778c06d 100644
--- a/sys/kern/kern_rangelock.c
+++ b/sys/kern/kern_rangelock.c
@@ -128,12 +128,13 @@ drain1:
 					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 @@ drain1:
 					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)