diff --git a/include/haproxy/stick_table-t.h b/include/haproxy/stick_table-t.h index e170fcdea..6c953ef09 100644 --- a/include/haproxy/stick_table-t.h +++ b/include/haproxy/stick_table-t.h @@ -147,7 +147,8 @@ struct stksess { unsigned int expire; /* session expiration date */ unsigned int ref_cnt; /* reference count, can only purge when zero */ __decl_thread(HA_RWLOCK_T lock); /* lock related to the table entry */ - int shard; /* shard */ + int shard; /* shard number used by peers */ + int seen; /* 0 only when no peer has seen this entry yet */ struct eb32_node exp; /* ebtree node used to hold the session in expiration tree */ struct eb32_node upd; /* ebtree node used to hold the update sequence tree */ struct ebmb_node key; /* ebtree node used to hold the session in table */ diff --git a/src/peers.c b/src/peers.c index 628b9358c..1182c2117 100644 --- a/src/peers.c +++ b/src/peers.c @@ -1478,6 +1478,7 @@ static inline int peer_send_error_protomsg(struct appctx *appctx) static inline struct stksess *peer_teach_process_stksess_lookup(struct shared_table *st) { struct eb32_node *eb; + struct stksess *ret; eb = eb32_lookup_ge(&st->table->updates, st->last_pushed+1); if (!eb) { @@ -1497,7 +1498,10 @@ static inline struct stksess *peer_teach_process_stksess_lookup(struct shared_ta return NULL; } - return eb32_entry(eb, struct stksess, upd); + ret = eb32_entry(eb, struct stksess, upd); + if (!_HA_ATOMIC_LOAD(&ret->seen)) + _HA_ATOMIC_STORE(&ret->seen, 1); + return ret; } /* @@ -1507,6 +1511,7 @@ static inline struct stksess *peer_teach_process_stksess_lookup(struct shared_ta static inline struct stksess *peer_teach_stage1_stksess_lookup(struct shared_table *st) { struct eb32_node *eb; + struct stksess *ret; eb = eb32_lookup_ge(&st->table->updates, st->last_pushed+1); if (!eb) { @@ -1517,7 +1522,10 @@ static inline struct stksess *peer_teach_stage1_stksess_lookup(struct shared_tab return NULL; } - return eb32_entry(eb, struct stksess, upd); + ret = eb32_entry(eb, struct stksess, upd); + if (!_HA_ATOMIC_LOAD(&ret->seen)) + _HA_ATOMIC_STORE(&ret->seen, 1); + return ret; } /* @@ -1527,6 +1535,7 @@ static inline struct stksess *peer_teach_stage1_stksess_lookup(struct shared_tab static inline struct stksess *peer_teach_stage2_stksess_lookup(struct shared_table *st) { struct eb32_node *eb; + struct stksess *ret; eb = eb32_lookup_ge(&st->table->updates, st->last_pushed+1); if (!eb || eb->key > st->teaching_origin) { @@ -1534,7 +1543,10 @@ static inline struct stksess *peer_teach_stage2_stksess_lookup(struct shared_tab return NULL; } - return eb32_entry(eb, struct stksess, upd); + ret = eb32_entry(eb, struct stksess, upd); + if (!_HA_ATOMIC_LOAD(&ret->seen)) + _HA_ATOMIC_STORE(&ret->seen, 1); + return ret; } /* diff --git a/src/stick_table.c b/src/stick_table.c index 3dbf00259..a1f1efa18 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -215,6 +215,7 @@ static struct stksess *__stksess_init(struct stktable *t, struct stksess * ts) memset((void *)ts - t->data_size, 0, t->data_size); ts->ref_cnt = 0; ts->shard = 0; + ts->seen = 0; ts->key.node.leaf_p = NULL; ts->exp.node.leaf_p = NULL; ts->upd.node.leaf_p = NULL; @@ -523,6 +524,7 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local, /* here we're write-locked */ + ts->seen = 0; ts->upd.key = ++t->update; t->localupdate = t->update; eb32_delete(&ts->upd); @@ -552,6 +554,7 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local, /* here we're write-locked */ + ts->seen = 0; ts->upd.key= (++t->update)+(2147483648U); eb = eb32_insert(&t->updates, &ts->upd); if (eb != &ts->upd) {