From: Willy Tarreau Date: Tue, 2 Apr 2024 16:49:53 +0000 (+0200) Subject: MINOR: stick-tables: mark the seen stksess with a flag "seen" X-Git-Tag: v3.0-dev7~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c1480f13b;p=thirdparty%2Fhaproxy.git MINOR: stick-tables: mark the seen stksess with a flag "seen" Right now we're taking the stick-tables update lock for reads just for the sake of checking if the update index is past it or not. That's costly because even taking the read lock is sufficient to provoke a cache line write, while when under load or attack it's frequent that the update has not yet been propagated and wouldn't require anything. This commit brings a new field to the stksess, "seen", which is zeroed when the entry is updated, and set to one as soon as at least one peer starts to consult it. This way it will reflect that the entry must be updated again so that this peer can see it. Otherwise no update will be necessary. For now the flag is only set/reset but not exploited. A great care is taken to avoid writes whenever possible. --- diff --git a/include/haproxy/stick_table-t.h b/include/haproxy/stick_table-t.h index e170fcdea0..6c953ef09c 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 628b9358c6..1182c2117a 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 3dbf002598..a1f1efa180 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) {