git: a725d61825f3 - main - rangelock: if CAS for removal failed, restart list iteration

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Wed, 21 Aug 2024 15:21:44 UTC
The branch main has been updated by kib:

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

commit a725d61825f32ea00d07a2064431a02fd640313a
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-08-16 05:45:52 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-08-21 15:19:36 +0000

    rangelock: if CAS for removal failed, restart list iteration
    
    Our next pointer is invalid and cannot be followed.
    
    Tested by:      markj, pho
    Sponsored by:   The FreeBSD Foundation
---
 sys/kern/kern_rangelock.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/sys/kern/kern_rangelock.c b/sys/kern/kern_rangelock.c
index 2667bf30fb6f..d9042f364737 100644
--- a/sys/kern/kern_rangelock.c
+++ b/sys/kern/kern_rangelock.c
@@ -539,6 +539,7 @@ rl_r_validate(struct rangelock *lock, struct rl_q_entry *e, bool trylock,
 {
 	struct rl_q_entry *cur, *next, **prev;
 
+again:
 	prev = &e->rl_q_next;
 	cur = rl_q_load(prev);
 	MPASS(!rl_e_is_marked(cur));	/* nobody can unlock e yet */
@@ -551,9 +552,10 @@ rl_r_validate(struct rangelock *lock, struct rl_q_entry *e, bool trylock,
 			if (rl_q_cas(prev, cur, next)) {
 				cur->rl_q_free = *free;
 				*free = cur;
+				cur = next;
+				continue;
 			}
-			cur = next;
-			continue;
+			goto again;
 		}
 		if (rl_e_is_rlock(cur)) {
 			prev = &cur->rl_q_next;
@@ -583,6 +585,7 @@ rl_w_validate(struct rangelock *lock, struct rl_q_entry *e,
 {
 	struct rl_q_entry *cur, *next, **prev;
 
+again:
 	prev = (struct rl_q_entry **)&lock->head;
 	cur = rl_q_load(prev);
 	MPASS(!rl_e_is_marked(cur));	/* head is not marked */
@@ -595,9 +598,10 @@ rl_w_validate(struct rangelock *lock, struct rl_q_entry *e,
 			if (rl_q_cas(prev, cur, next)) {
 				cur->rl_q_next = *free;
 				*free = cur;
+				cur = next;
+				continue;
 			}
-			cur = next;
-			continue;
+			goto again;
 		}
 		if (cur->rl_q_end <= e->rl_q_start) {
 			prev = &cur->rl_q_next;
@@ -642,9 +646,10 @@ again:
 #endif
 					cur->rl_q_free = *free;
 					*free = cur;
+					cur = next;
+					continue;
 				}
-				cur = next;
-				continue;
+				goto again;
 			}
 		}