BUG/MAJOR: pools: second fix for incomplete backport of lockless pool fix
Commit bc76411e0 ("BUG/MAJOR: pools: fix possible race with free() in
the lockless variant") was missing another unprotected access to the
pool's free_list in __pool_refill_alloc() because this one was completely
dropped from 2.4 and above. There we need to loop over POOL_BUSY just like
in the __pool_free() code, otherwise we risk to insert such a POOL_BUSY
into the list.
This fix is only for 2.3 and 2.2 since 2.2 now also contains the faulty
backport of the patch above.
diff --git a/src/pool.c b/src/pool.c
index 799c29f..1a4d1f8 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -273,11 +273,16 @@
if (++allocated > avail)
break;
- free_list = pool->free_list;
+ free_list = _HA_ATOMIC_LOAD(&pool->free_list);
do {
- *POOL_LINK(pool, ptr) = free_list;
- __ha_barrier_store();
- } while (_HA_ATOMIC_CAS(&pool->free_list, &free_list, ptr) == 0);
+ while (unlikely(free_list == POOL_BUSY)) {
+ pl_cpu_relax();
+ free_list = _HA_ATOMIC_LOAD(&pool->free_list);
+ }
+ _HA_ATOMIC_STORE(POOL_LINK(pool, ptr), (void *)free_list);
+ __ha_barrier_atomic_store();
+ } while (!_HA_ATOMIC_CAS(&pool->free_list, &free_list, ptr));
+ __ha_barrier_atomic_store();
}
__ha_barrier_atomic_store();