From 3c2e684aa77084c85d517328c011955864bed0d6 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Thu, 18 Feb 2021 23:55:30 +0100 Subject: [PATCH] BUG/MEDIUM: lists: Avoid an infinite loop in MT_LIST_TRY_ADDQ(). In MT_LIST_TRY_ADDQ(), deal with the "prev" field of the element before the "next". If the element is the first in the list, then its next will already have been locked when we locked list->prev->next, so locking it again will fail, and we'll start over and over. This should be backported to 2.3. (cherry picked from commit 5567f41d0ab61dd6843535edc8081407d599024d) Signed-off-by: Christopher Faulet (cherry picked from commit 6f682bea6ab08830d17ef3e973be6cc4d2474e69) [wt: in 2.2 the macro is there, it's MT_LIST_ADDQ() which was later renamed] Signed-off-by: Willy Tarreau (cherry picked from commit cd721385380410d9432d7fba9fe257415bfb09f2) [wt: also present in 2.1] Signed-off-by: Willy Tarreau --- include/common/mini-clist.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/common/mini-clist.h b/include/common/mini-clist.h index 0bd5622..89d77ce 100644 --- a/include/common/mini-clist.h +++ b/include/common/mini-clist.h @@ -300,28 +300,28 @@ struct cond_wordlist { __ha_barrier_store(); \ continue; \ } \ - n2 = _HA_ATOMIC_XCHG(&el->next, MT_LIST_BUSY); \ - if (n2 != el) { /* element already linked */ \ - if (n2 != MT_LIST_BUSY) \ - el->next = n2; \ + p2 = _HA_ATOMIC_XCHG(&el->prev, MT_LIST_BUSY); \ + if (p2 != el) { \ + if (p2 != MT_LIST_BUSY) \ + el->prev = p2; \ p->next = n; \ __ha_barrier_store(); \ lh->prev = p; \ __ha_barrier_store(); \ - if (n2 == MT_LIST_BUSY) \ + if (p2 == MT_LIST_BUSY) \ continue; \ break; \ } \ - p2 = _HA_ATOMIC_XCHG(&el->prev, MT_LIST_BUSY); \ - if (p2 != el) { \ - if (p2 != MT_LIST_BUSY) \ - el->prev = p2; \ + n2 = _HA_ATOMIC_XCHG(&el->next, MT_LIST_BUSY); \ + if (n2 != el) { /* element already linked */ \ + if (n2 != MT_LIST_BUSY) \ + el->next = n2; \ p->next = n; \ - el->next = el; \ + el->prev = el; \ __ha_barrier_store(); \ lh->prev = p; \ __ha_barrier_store(); \ - if (p2 == MT_LIST_BUSY) \ + if (n2 == MT_LIST_BUSY) \ continue; \ break; \ } \ -- 1.7.10.4