From 4d7a88482770cb1ce401ec9b625bc367bcfb411b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 31 Jul 2019 16:00:48 +0200 Subject: [PATCH] MEDIUM: mux-h2: don't try to read more than needed The h2_recv() loop was historically built around a loop to deal with the callback model but this is not needed anymore, as it the upper layer wants more data, it will simply try to read again. Right now 50% of the recvfrom() calls made over H2 return EAGAIN. With this change it doesn't happen anymore. Note that the code simply consists in breaking the loop, and reporting real data receipt instead of always returning 1. A test was made not to subscribe if we actually read data but it doesn't change anything since we might be subscribed very early already. --- src/mux_h2.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/mux_h2.c b/src/mux_h2.c index cf6ad9dcf9..b58ba20bc0 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -2735,28 +2735,23 @@ static int h2_recv(struct h2c *h2c) return 0; } - do { - b_realign_if_empty(buf); - if (!b_data(buf)) { - /* try to pre-align the buffer like the - * rxbufs will be to optimize memory copies. We'll make - * sure that the frame header lands at the end of the - * HTX block to alias it upon recv. We cannot use the - * head because rcv_buf() will realign the buffer if - * it's empty. Thus we cheat and pretend we already - * have a few bytes there. - */ - max = buf_room_for_htx_data(buf) + 9; - buf->head = sizeof(struct htx) - 9; - } - else - max = b_room(buf); + b_realign_if_empty(buf); + if (!b_data(buf)) { + /* try to pre-align the buffer like the + * rxbufs will be to optimize memory copies. We'll make + * sure that the frame header lands at the end of the + * HTX block to alias it upon recv. We cannot use the + * head because rcv_buf() will realign the buffer if + * it's empty. Thus we cheat and pretend we already + * have a few bytes there. + */ + max = buf_room_for_htx_data(buf) + 9; + buf->head = sizeof(struct htx) - 9; + } + else + max = b_room(buf); - if (max) - ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, max, 0); - else - ret = 0; - } while (ret > 0); + ret = max ? conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, max, 0) : 0; if (h2_recv_allowed(h2c) && (b_data(buf) < buf->size)) conn->xprt->subscribe(conn, conn->xprt_ctx, SUB_RETRY_RECV, &h2c->wait_event); @@ -2768,7 +2763,7 @@ static int h2_recv(struct h2c *h2c) if (b_data(buf) == buf->size) h2c->flags |= H2_CF_DEM_DFULL; - return 1; + return !!ret || (conn->flags & CO_FL_ERROR) || conn_xprt_read0_pending(conn); } /* Try to send data if possible. -- 2.39.5