]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: channel: don't look at iobuf to report an empty channel
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 25 Jul 2023 06:30:01 +0000 (08:30 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 17 Oct 2023 16:51:13 +0000 (18:51 +0200)
It is important to split channels and I/O buffers. When data are pushed in
an I/O buffer, we consider them as forwarded. The channel never sees
them. Fast-forwarded data are now handled in the SE only.

include/haproxy/channel.h
src/stconn.c

index 64e95afbf0a7c6404f7fb1f19ed33d399d0c6de9..c0ff15ccc5ec289b90a85a99c38b953a8f5e1e76 100644 (file)
@@ -402,14 +402,13 @@ static inline void channel_htx_forward_forever(struct channel *chn, struct htx *
 /* These functions are used to compute various channel content sizes */
 /*********************************************************************/
 
-/* Reports non-zero if the channel is empty, which means both its
- * buffer and pipe on the opposite SE are empty. The construct looks
- * strange but is jump-less and much more efficient on both 32 and
- * 64-bit than the boolean test.
+/* Reports non-zero if the channel is empty, which means its buffer is
+ * empty. The construct looks strange but is jump-less and much more efficient
+ * on both 32 and 64-bit than the boolean test.
  */
 static inline unsigned int channel_is_empty(const struct channel *c)
 {
-       return (!co_data(c) && !sc_ep_have_ff_data(chn_cons(c)));
+       return !co_data(c);
 }
 
 /* Returns non-zero if the channel is rewritable, which means that the buffer
index 8a00b18cc5df66f17507ef59a3769b9be7399501..c41716da67bc77408e972b589ddcf615b0e0531e 100644 (file)
@@ -651,7 +651,7 @@ static void sc_app_chk_snd(struct stconn *sc)
                return;
 
        if (!sc_ep_test(sc, SE_FL_WAIT_DATA) ||  /* not waiting for data */
-           channel_is_empty(oc))                  /* called with nothing to send ! */
+           (channel_is_empty(oc) && !sc_ep_have_ff_data(sc)))  /* called with nothing to send ! */
                return;
 
        /* Otherwise there are remaining data to be sent in the buffer,
@@ -799,7 +799,7 @@ static void sc_app_chk_snd_conn(struct stconn *sc)
                     (sc->flags & SC_FL_SHUT_DONE)))
                return;
 
-       if (unlikely(channel_is_empty(oc)))  /* called with nothing to send ! */
+       if (unlikely(channel_is_empty(oc) && !sc_ep_have_ff_data(sc)))  /* called with nothing to send ! */
                return;
 
        if (!sc_ep_have_ff_data(sc) &&              /* data wants to be fast-forwarded ASAP */
@@ -970,7 +970,7 @@ static void sc_app_chk_snd_applet(struct stconn *sc)
        if (!sc_ep_test(sc, SE_FL_WAIT_DATA|SE_FL_WONT_CONSUME) && !(sc->flags & SC_FL_SHUT_WANTED))
                return;
 
-       if (!channel_is_empty(oc)) {
+       if (!channel_is_empty(oc) || sc_ep_have_ff_data(sc)) {
                /* (re)start sending */
                appctx_wakeup(__sc_appctx(sc));
        }
@@ -1702,7 +1702,7 @@ static int sc_conn_send(struct stconn *sc)
        }
 
        /* FIXME: Must be reviewed for FF */
-       if (channel_is_empty(oc)) {
+       if (channel_is_empty(oc) && !sc_ep_have_ff_data(sc)) {
                /* If fast-forwarding is blocked, unblock it now to check for
                 * receive on the other side
                 */
@@ -1760,7 +1760,8 @@ static int sc_conn_process(struct stconn *sc)
        BUG_ON(!conn);
 
        /* If we have data to send, try it now */
-       if (!channel_is_empty(oc) && !(sc->wait_event.events & SUB_RETRY_SEND))
+       if ((!channel_is_empty(oc) || sc_ep_have_ff_data(sc)) &&
+           !(sc->wait_event.events & SUB_RETRY_SEND))
                sc_conn_send(sc);
 
        /* First step, report to the stream connector what was detected at the
@@ -1852,7 +1853,7 @@ struct task *sc_conn_io_cb(struct task *t, void *ctx, unsigned int state)
        if (!sc_conn(sc))
                return t;
 
-       if (!(sc->wait_event.events & SUB_RETRY_SEND) && (!channel_is_empty(sc_oc(sc)) || (sc->sedesc->iobuf.flags & IOBUF_FL_FF_BLOCKED)))
+       if (!(sc->wait_event.events & SUB_RETRY_SEND) && (!channel_is_empty(sc_oc(sc)) || sc_ep_have_ff_data(sc) || (sc->sedesc->iobuf.flags & IOBUF_FL_FF_BLOCKED)))
                ret = sc_conn_send(sc);
        if (!(sc->wait_event.events & SUB_RETRY_RECV))
                ret |= sc_conn_recv(sc);