MEDIUM: tree-wide: Change sc API to specify required free space to progress

sc_need_room() now takes the required free space to receive more data as
parameter. All calls to this function are updated accordingly. For now, this
value is set but not used. When we are waiting for a buffer, 0 is used. So
we expect to be unblocked ASAP. However this must be reviewed because
SC_FL_NEED_BUF is probably enough in this case and this flag is already set
if the input buffer allocation fails.
This commit is contained in:
Christopher Faulet 2023-05-05 11:28:45 +02:00
parent 9aed1124ed
commit 7b3d38a633
14 changed files with 60 additions and 51 deletions

View File

@ -1365,7 +1365,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stconn *sc, struct
return 1;
full:
sc_need_room(sc);
sc_need_room(sc, channel_htx_recv_max(sc_ic(appctx_sc(appctx)), htx) + 1);
return 0;
error:
/* unrecoverable error */
@ -1512,7 +1512,7 @@ static int promex_send_headers(struct appctx *appctx, struct stconn *sc, struct
return 1;
full:
htx_reset(htx);
sc_need_room(sc);
sc_need_room(sc, 0);
return 0;
}
@ -1544,7 +1544,7 @@ static void promex_appctx_handle_io(struct appctx *appctx)
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
sc_need_room(sc);
sc_need_room(sc, 0);
goto out;
}
@ -1585,7 +1585,7 @@ static void promex_appctx_handle_io(struct appctx *appctx)
*/
if (htx_is_empty(res_htx)) {
if (!htx_add_endof(res_htx, HTX_BLK_EOT)) {
sc_need_room(sc);
sc_need_room(sc, sizeof(struct htx_blk) + 1);
goto out;
}
channel_add_input(res, 1);

View File

@ -178,7 +178,7 @@ static inline int applet_putchk(struct appctx *appctx, struct buffer *chunk)
ret = ci_putchk(sc_ic(se->sc), chunk);
if (ret == -1)
sc_need_room(se->sc);
sc_need_room(se->sc, chunk->data);
return ret;
}
@ -194,7 +194,7 @@ static inline int applet_putblk(struct appctx *appctx, const char *blk, int len)
ret = ci_putblk(sc_ic(se->sc), blk, len);
if (ret == -1)
sc_need_room(se->sc);
sc_need_room(se->sc, len);
return ret;
}
@ -211,7 +211,7 @@ static inline int applet_putstr(struct appctx *appctx, const char *str)
ret = ci_putstr(sc_ic(se->sc), str);
if (ret == -1)
sc_need_room(se->sc);
sc_need_room(se->sc, strlen(str));
return ret;
}
@ -227,7 +227,7 @@ static inline int applet_putchr(struct appctx *appctx, char chr)
ret = ci_putchr(sc_ic(se->sc), chr);
if (ret == -1)
sc_need_room(se->sc);
sc_need_room(se->sc, 1);
return ret;
}

View File

@ -433,6 +433,7 @@ static inline void sc_have_room(struct stconn *sc)
{
if (sc->flags & SC_FL_NEED_ROOM) {
sc->flags &= ~SC_FL_NEED_ROOM;
sc->room_needed = 0;
sc_ep_report_read_activity(sc);
}
}
@ -441,10 +442,14 @@ static inline void sc_have_room(struct stconn *sc)
* by lack of room. Since it indicates a willingness to deliver data to the
* buffer that will have to be retried. Usually the caller will also clear
* SE_FL_HAVE_NO_DATA to be called again as soon as SC_FL_NEED_ROOM is cleared.
*
* The caller is responsible to specified the amount of free space required to
* progress.
*/
static inline void sc_need_room(struct stconn *sc)
static inline void sc_need_room(struct stconn *sc, ssize_t room_needed)
{
sc->flags |= SC_FL_NEED_ROOM;
sc->room_needed = room_needed;
}
/* The stream endpoint indicates that it's ready to consume data from the

View File

@ -1471,7 +1471,7 @@ static void http_cache_io_handler(struct appctx *appctx)
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
sc_need_room(sc);
sc_need_room(sc, 0);
goto out;
}
@ -1513,7 +1513,7 @@ static void http_cache_io_handler(struct appctx *appctx)
if (len) {
ret = htx_cache_dump_msg(appctx, res_htx, len, HTX_BLK_UNUSED);
if (ret < len) {
sc_need_room(sc);
sc_need_room(sc, len - ret);
goto out;
}
}

View File

@ -900,7 +900,7 @@ static void cli_io_handler(struct appctx *appctx)
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
sc_need_room(sc);
sc_need_room(sc, 0);
goto out;
}
@ -937,7 +937,7 @@ static void cli_io_handler(struct appctx *appctx)
* would want to return some info right after parsing.
*/
if (buffer_almost_full(sc_ib(sc))) {
sc_need_room(sc);
sc_need_room(sc, b_size(&res->buf) / 2);
break;
}

View File

@ -525,7 +525,7 @@ static void dns_session_io_handler(struct appctx *appctx)
/* check if there is enough room to put message len and query id */
if (available_room < sizeof(slen) + sizeof(new_qid)) {
sc_need_room(sc);
sc_need_room(sc, sizeof(slen) + sizeof(new_qid));
ret = 0;
break;
}
@ -583,7 +583,7 @@ static void dns_session_io_handler(struct appctx *appctx)
/* check if it remains available room on output chan */
if (unlikely(!available_room)) {
sc_need_room(sc);
sc_need_room(sc, 1);
ret = 0;
break;
}
@ -617,8 +617,7 @@ static void dns_session_io_handler(struct appctx *appctx)
if (ds->tx_msg_offset) {
/* msg was not fully processed, we must be awake to drain pending data */
sc_need_room(sc);
sc_need_room(sc, 0);
ret = 0;
break;
}

View File

@ -1147,9 +1147,9 @@ spoe_send_frame(struct appctx *appctx, char *buf, size_t framesz)
memcpy(buf, (char *)&netint, 4);
ret = applet_putblk(appctx, buf, framesz+4);
if (ret <= 0) {
if ((ret == -3 && b_is_null(&sc_ic(sc)->buf)) || ret == -1) {
if (ret == -3 && b_is_null(&sc_ic(sc)->buf)) {
/* WT: is this still needed for the case ret==-3 ? */
sc_need_room(sc);
sc_need_room(sc, 0);
return 1; /* retry */
}
SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_IO;

View File

@ -4929,7 +4929,7 @@ __LJMP static int hlua_applet_tcp_send_yield(lua_State *L, int status, lua_KCont
* applet, and returns a yield.
*/
if (l < len) {
sc_need_room(sc);
sc_need_room(sc, channel_recv_max(chn) + 1);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_send_yield, TICK_ETERNITY, 0));
}
@ -5472,7 +5472,7 @@ __LJMP static int hlua_applet_http_send_yield(lua_State *L, int status, lua_KCon
if (l < len) {
snd_yield:
htx_to_buf(htx, &res->buf);
sc_need_room(sc);
sc_need_room(sc, channel_recv_max(res) + 1);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_send_yield, TICK_ETERNITY, 0));
}
@ -5776,7 +5776,7 @@ __LJMP static int hlua_applet_http_start_response_yield(lua_State *L, int status
struct channel *res = sc_ic(sc);
if (co_data(res)) {
sc_need_room(sc);
sc_need_room(sc, -1);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_start_response_yield, TICK_ETERNITY, 0));
}
return MAY_LJMP(hlua_applet_http_send_response(L));
@ -10390,7 +10390,7 @@ void hlua_applet_http_fct(struct appctx *ctx)
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
sc_need_room(sc);
sc_need_room(sc, 0);
goto out;
}
@ -10463,7 +10463,7 @@ void hlua_applet_http_fct(struct appctx *ctx)
*/
if (htx_is_empty(res_htx) && (strm->txn->rsp.flags & (HTTP_MSGF_XFER_LEN|HTTP_MSGF_CNT_LEN)) == HTTP_MSGF_XFER_LEN) {
if (!htx_add_endof(res_htx, HTX_BLK_EOT)) {
sc_need_room(sc);
sc_need_room(sc, sizeof(struct htx_blk)+1);
goto out;
}
channel_add_input(res, 1);
@ -11029,7 +11029,7 @@ static int hlua_cli_io_handler_fct(struct appctx *appctx)
case HLUA_E_AGAIN:
/* We want write. */
if (HLUA_IS_WAKERESWR(hlua))
sc_need_room(sc);
sc_need_room(sc, -1);
/* Set the timeout. */
if (hlua->wake_time != TICK_ETERNITY)
task_schedule(hlua->task, hlua->wake_time);

View File

@ -726,15 +726,19 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
* it's the first call, we can freely copy the
* request from the httpclient buffer */
ret = b_xfer(&req->buf, &hc->req.buf, b_data(&hc->req.buf));
if (!ret)
goto full;
if (!ret) {
sc_need_room(sc, 0);
goto out;
}
if (!b_data(&hc->req.buf))
b_free(&hc->req.buf);
htx = htx_from_buf(&req->buf);
if (!htx)
goto full;
if (!htx) {
sc_need_room(sc, 0);
goto out;
}
channel_add_input(req, htx->data);
@ -983,11 +987,6 @@ static void httpclient_applet_io_handler(struct appctx *appctx)
sc_will_read(sc);
goto out;
full:
/* There was not enough room in the response channel */
sc_need_room(sc);
goto out;
error:
se_fl_set(appctx->sedesc, SE_FL_ERROR);
goto out;

View File

@ -1623,7 +1623,7 @@ static inline int peer_send_teachmsgs(struct appctx *appctx, struct peer *p,
/* pretend we're full so that we get back ASAP */
struct stconn *sc = appctx_sc(appctx);
sc_need_room(sc);
sc_need_room(sc, 0);
ret = -1;
break;
}
@ -2652,7 +2652,7 @@ static inline int peer_send_msgs(struct appctx *appctx,
/* pretend we're full so that we get back ASAP */
struct stconn *sc = appctx_sc(appctx);
sc_need_room(sc);
sc_need_room(sc, 0);
return -1;
}
}
@ -2925,7 +2925,7 @@ static void peer_io_handler(struct appctx *appctx)
/* Check if the input buffer is available. */
if (sc_ib(sc)->size == 0) {
sc_need_room(sc);
sc_need_room(sc, 0);
goto out;
}

View File

@ -3386,8 +3386,10 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
newline = ctx->bol;
newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->buf_len, &newline, ctx->ptr);
if (newptr == ctx->ptr)
if (newptr == ctx->ptr) {
sc_need_room(sc, 0);
goto cant_send_unlock;
}
if (applet_putchk(appctx, &trash) == -1)
goto cant_send_unlock;
@ -3410,7 +3412,6 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
cant_send_unlock:
HA_RWLOCK_RDUNLOCK(PROXY_LOCK, &ctx->px->lock);
cant_send:
sc_need_room(sc);
return 0;
}

View File

@ -2722,8 +2722,10 @@ int stats_dump_resolvers(struct stconn *sc,
list_for_each_entry_from(ns, &resolver->nameservers, list) {
ctx->obj2 = ns;
if (buffer_almost_full(&rep->buf))
if (buffer_almost_full(&rep->buf)) {
sc_need_room(sc, b_size(&rep->buf) / 2);
goto full;
}
if (!stats_dump_resolv_to_buffer(sc, ns,
stats, stats_count,

View File

@ -3853,12 +3853,16 @@ static int stats_dump_proxies(struct stconn *sc,
/* dump proxies */
while (ctx->obj1) {
if (htx) {
if (htx_almost_full(htx))
if (htx_almost_full(htx)) {
sc_need_room(sc, htx->size / 2);
goto full;
}
}
else {
if (buffer_almost_full(&rep->buf))
if (buffer_almost_full(&rep->buf)) {
sc_need_room(sc, b_size(&rep->buf) / 2);
goto full;
}
}
px = ctx->obj1;
@ -3880,7 +3884,6 @@ static int stats_dump_proxies(struct stconn *sc,
return 1;
full:
sc_need_room(sc);
return 0;
}
@ -4378,7 +4381,7 @@ static int stats_send_http_headers(struct stconn *sc, struct htx *htx)
full:
htx_reset(htx);
sc_need_room(sc);
sc_need_room(sc, 0);
return 0;
}
@ -4438,7 +4441,7 @@ static int stats_send_http_redirect(struct stconn *sc, struct htx *htx)
full:
htx_reset(htx);
sc_need_room(sc);
sc_need_room(sc, 0);
return 0;
}
@ -4469,7 +4472,7 @@ static void http_stats_io_handler(struct appctx *appctx)
/* Check if the input buffer is available. */
if (!b_size(&res->buf)) {
sc_need_room(sc);
sc_need_room(sc, 0);
goto out;
}
@ -4513,7 +4516,7 @@ static void http_stats_io_handler(struct appctx *appctx)
*/
if (htx_is_empty(res_htx)) {
if (!htx_add_endof(res_htx, HTX_BLK_EOT)) {
sc_need_room(sc);
sc_need_room(sc, sizeof(struct htx_blk) + 1);
goto out;
}
channel_add_input(res, 1);

View File

@ -609,7 +609,7 @@ static void sc_app_chk_rcv(struct stconn *sc)
if (ic->pipe) {
/* stop reading */
sc_need_room(sc);
sc_need_room(sc, -1);
}
else {
/* (re)start reading */
@ -1269,7 +1269,7 @@ static int sc_conn_recv(struct stconn *sc)
/* the pipe is full or we have read enough data that it
* could soon be full. Let's stop before needing to poll.
*/
sc_need_room(sc);
sc_need_room(sc, 0);
goto done_recv;
}
@ -1339,7 +1339,7 @@ static int sc_conn_recv(struct stconn *sc)
*/
BUG_ON(c_empty(ic));
sc_need_room(sc);
sc_need_room(sc, channel_recv_max(ic) + 1);
/* Add READ_PARTIAL because some data are pending but
* cannot be xferred to the channel
*/
@ -1353,7 +1353,7 @@ static int sc_conn_recv(struct stconn *sc)
* here to proceed.
*/
if (flags & CO_RFL_BUF_FLUSH)
sc_need_room(sc);
sc_need_room(sc, -1);
break;
}