mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 13:21:29 +02:00
BUG/MINOR: stick-tables: never leave used entries without expiration
When trying to kill/expire entries, if a ref-counted entry is found, let's requeue it with its expiration timer instead of leaving it out, because other ref-counters (e.g. peers) will not purge it otherwise, leaving it orphan. This one seems trickier to trigger, though it seems to happen sometimes when peers are late and a long resync is active and competing with intense calls to process_table_expire() (i.e. when no other acitvity is there). This must be backported to 3.2. It's likely that older versions are affected as well, but possibly differently since the expiration mechanism changed between 3.1 and 3.2, so better not take unneeded risks there.
This commit is contained in:
parent
8da6ed6b6a
commit
324f0a60ab
@ -341,13 +341,14 @@ int stktable_trash_oldest(struct stktable *t, int to_batch)
|
||||
ts = eb32_entry(eb, struct stksess, exp);
|
||||
eb = eb32_next(eb);
|
||||
|
||||
/* don't delete an entry which is currently referenced */
|
||||
if (HA_ATOMIC_LOAD(&ts->ref_cnt) != 0)
|
||||
continue;
|
||||
|
||||
/* This entry's key is expired, we must delete it. It
|
||||
* may be properly requeued if the element is still in
|
||||
* use or not really expired though.
|
||||
*/
|
||||
eb32_delete(&ts->exp);
|
||||
|
||||
if (ts->expire != ts->exp.key) {
|
||||
if (ts->expire != ts->exp.key || HA_ATOMIC_LOAD(&ts->ref_cnt) != 0) {
|
||||
requeue:
|
||||
if (!tick_isset(ts->expire))
|
||||
continue;
|
||||
|
||||
@ -385,7 +386,7 @@ int stktable_trash_oldest(struct stktable *t, int to_batch)
|
||||
* existing ones already have the ref_cnt.
|
||||
*/
|
||||
if (HA_ATOMIC_LOAD(&ts->ref_cnt))
|
||||
continue;
|
||||
goto requeue;
|
||||
|
||||
/* session expired, trash it */
|
||||
ebmb_delete(&ts->key);
|
||||
@ -939,10 +940,6 @@ struct task *process_table_expire(struct task *task, void *context, unsigned int
|
||||
ts = eb32_entry(eb, struct stksess, exp);
|
||||
eb = eb32_next(eb);
|
||||
|
||||
/* don't delete an entry which is currently referenced */
|
||||
if (HA_ATOMIC_LOAD(&ts->ref_cnt) != 0)
|
||||
continue;
|
||||
|
||||
if (updt_locked == 1) {
|
||||
expired++;
|
||||
if (expired == STKTABLE_MAX_UPDATES_AT_ONCE) {
|
||||
@ -952,9 +949,14 @@ struct task *process_table_expire(struct task *task, void *context, unsigned int
|
||||
}
|
||||
}
|
||||
|
||||
/* This entry's key is expired, we must delete it. It
|
||||
* may be properly requeued if the element is still in
|
||||
* use or not really expired though.
|
||||
*/
|
||||
eb32_delete(&ts->exp);
|
||||
|
||||
if (!tick_is_expired(ts->expire, now_ms)) {
|
||||
if (!tick_is_expired(ts->expire, now_ms) || HA_ATOMIC_LOAD(&ts->ref_cnt) != 0) {
|
||||
requeue:
|
||||
if (!tick_isset(ts->expire))
|
||||
continue;
|
||||
|
||||
@ -991,7 +993,7 @@ struct task *process_table_expire(struct task *task, void *context, unsigned int
|
||||
* existing ones already have the ref_cnt.
|
||||
*/
|
||||
if (HA_ATOMIC_LOAD(&ts->ref_cnt))
|
||||
continue;
|
||||
goto requeue;
|
||||
|
||||
/* session expired, trash it */
|
||||
ebmb_delete(&ts->key);
|
||||
|
Loading…
x
Reference in New Issue
Block a user