The branch main has been updated by kib:

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

commit a725d61825f32ea00d07a2064431a02fd640313a
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2024-08-16 05:45:52 +0000
Commit:     Konstantin Belousov <k...@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;
                        }
                }
 

Reply via email to