From d14844a7343073a4a290da3c8330f236a848f54d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 8 Nov 2018 18:15:29 +0100 Subject: [PATCH] MINOR: stream-int: replace si_update() with si_update_both() The function used to be called in turn for each side of the stream, but since it's called exclusively from process_stream(), it prevents us from making use of the knowledge we have of the operations in progress for each side, resulting in having to go all the way through functions like stream_int_notify() which are not appropriate there. That patch creates a new function, si_update_both() which takes two stream interfaces expected to belong to the same stream, and processes their flags in a more suitable order, but for now doesn't change the logic at all. The next step will consist in trying to reinsert the rest of the socket layer-specific update code to ultimately update the flags correctly at the end of the operation. --- include/proto/stream_interface.h | 1 + src/stream.c | 3 +-- src/stream_interface.c | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h index 54d9810f1..c8d0a4c34 100644 --- a/include/proto/stream_interface.h +++ b/include/proto/stream_interface.h @@ -56,6 +56,7 @@ void stream_int_notify(struct stream_interface *si); int si_cs_recv(struct conn_stream *cs); int si_cs_send(struct conn_stream *cs); struct task *si_cs_io_cb(struct task *t, void *ctx, unsigned short state); +void si_update_both(struct stream_interface *si_f, struct stream_interface *si_b); /* returns the channel which receives data from this stream interface (input channel) */ static inline struct channel *si_ic(struct stream_interface *si) diff --git a/src/stream.c b/src/stream.c index 920c6ad22..b4acc3f75 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2474,8 +2474,7 @@ redo: if ((sess->fe->options & PR_O_CONTSTATS) && (s->flags & SF_BE_ASSIGNED)) stream_process_counters(s); - si_update(si_f); - si_update(si_b); + si_update_both(si_f, si_b); if (si_f->state == SI_ST_DIS || si_b->state == SI_ST_DIS || (((req->flags ^ rqf_last) | (res->flags ^ rpf_last)) & CF_MASK_ANALYSER)) diff --git a/src/stream_interface.c b/src/stream_interface.c index b29cb2f75..8d223fabf 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -807,6 +807,40 @@ void stream_int_update(struct stream_interface *si) } } +/* updates both stream ints of a same stream at once */ +/* Updates at once the channel flags, and timers of both stream interfaces of a + * same stream, to complete the work after the analysers, then updates the data + * layer below. This will ensure that any synchronous update performed at the + * data layer will be reflected in the channel flags and/or stream-interface. + */ +void si_update_both(struct stream_interface *si_f, struct stream_interface *si_b) +{ + struct channel *req = si_ic(si_f); + struct channel *res = si_oc(si_f); + + /* let's recompute both sides states */ + if (si_f->state == SI_ST_EST) + stream_int_update(si_f); + + if (si_b->state == SI_ST_EST) + stream_int_update(si_b); + + req->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_READ_ATTACHED|CF_WRITE_NULL|CF_WRITE_PARTIAL); + res->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_READ_ATTACHED|CF_WRITE_NULL|CF_WRITE_PARTIAL); + + si_f->flags &= ~(SI_FL_ERR|SI_FL_EXP); + si_b->flags &= ~(SI_FL_ERR|SI_FL_EXP); + + si_f->prev_state = si_f->state; + si_b->prev_state = si_b->state; + + if (si_f->ops->update && si_f->state == SI_ST_EST) + si_f->ops->update(si_f); + + if (si_b->ops->update && (si_b->state == SI_ST_EST || si_b->state == SI_ST_CON)) + si_b->ops->update(si_b); +} + /* Updates the active status of a connection outside of the connection handler * based on the channel's flags and the stream interface's flags. It needs to * be called once after the channels' flags have settled down and the stream