From c55015ee5b9f24b2855056bbae9c95324d7e4759 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 7 Sep 2018 19:02:32 +0200 Subject: [PATCH] MEDIUM: snapshots: dynamically allocate the snapshots Now upon error we dynamically allocate the snapshot instead of overwriting it. This way there is no more memory wasted in the proxy to hold the two error snapshot descriptors. Also an appreciable side effect of this is that the proxy's lock is only taken during the pointer swap, no more while copying the buffer's contents. This saves 480 bytes of memory per proxy. --- include/types/proxy.h | 2 +- src/proxy.c | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/include/types/proxy.h b/include/types/proxy.h index 9695b9c2d7..ca3bc7de23 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -410,7 +410,7 @@ struct proxy { /* warning: these structs are huge, keep them at the bottom */ struct sockaddr_storage dispatch_addr; /* the default address to connect to */ - struct error_snapshot invalid_req, invalid_rep; /* captures of last errors */ + struct error_snapshot *invalid_req, *invalid_rep; /* captures of last errors */ /* used only during configuration parsing */ int no_options; /* PR_O_REDISP, PR_O_TRANSP, ... */ diff --git a/src/proxy.c b/src/proxy.c index 9306637722..9f9fec878c 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1356,6 +1356,15 @@ void proxy_capture_error(struct proxy *proxy, int is_back, struct error_snapshot *es; unsigned int buf_len; int len1, len2; + unsigned int ev_id; + + ev_id = HA_ATOMIC_XADD(&error_snapshot_id, 1); + + es = malloc(sizeof(*es)); + if (!es) + return; + + es->ev_id = ev_id; buf_len = b_data(buf) - buf_out; len1 = b_size(buf) - buf_len; @@ -1363,9 +1372,6 @@ void proxy_capture_error(struct proxy *proxy, int is_back, len1 = buf_len; len2 = buf_len - len1; - HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock); - es = is_back ? &proxy->invalid_rep : &proxy->invalid_req; - es->buf_len = buf_len; if (!es->buf) @@ -1386,7 +1392,6 @@ void proxy_capture_error(struct proxy *proxy, int is_back, else memset(&es->src, 0, sizeof(es->src)); - es->ev_id = HA_ATOMIC_XADD(&error_snapshot_id, 1); es->buf_wrap = b_wrap(buf) - b_peek(buf, buf_out); es->buf_out = buf_out; es->buf_ofs = buf_ofs; @@ -1403,6 +1408,17 @@ void proxy_capture_error(struct proxy *proxy, int is_back, else memset(&es->ctx, 0, sizeof(es->ctx)); es->show = show; + + /* note: we still lock since we have to be certain that nobody is + * dumping the output while we free. + */ + HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock); + if (is_back) { + es = HA_ATOMIC_XCHG(&proxy->invalid_rep, es); + } else { + es = HA_ATOMIC_XCHG(&proxy->invalid_req, es); + } + free(es); HA_SPIN_UNLOCK(PROXY_LOCK, &proxy->lock); } @@ -2012,17 +2028,17 @@ static int cli_io_handler_show_errors(struct appctx *appctx) HA_SPIN_LOCK(PROXY_LOCK, &appctx->ctx.errors.px->lock); if ((appctx->ctx.errors.flag & 1) == 0) { - es = &appctx->ctx.errors.px->invalid_req; + es = appctx->ctx.errors.px->invalid_req; if (appctx->ctx.errors.flag & 2) // skip req goto next; } else { - es = &appctx->ctx.errors.px->invalid_rep; + es = appctx->ctx.errors.px->invalid_rep; if (appctx->ctx.errors.flag & 4) // skip resp goto next; } - if (!es->when.tv_sec) + if (!es) goto next; if (appctx->ctx.errors.iid >= 0 && -- 2.39.5