diff --git a/src/haterm.c b/src/haterm.c index d4a2e80a4..e66c41f23 100644 --- a/src/haterm.c +++ b/src/haterm.c @@ -1,3 +1,6 @@ +#define _GNU_SOURCE +#include + #include #include #include @@ -6,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +66,11 @@ static char common_chunk_resp[RESPSIZE]; static char *random_resp; static int random_resp_len = RESPSIZE; +#if defined(USE_LINUX_SPLICE) +struct pipe *master_pipe = NULL; +size_t master_pipesize = 0; +#endif + static size_t hstream_add_ff_data(struct hstream *hs, struct sedesc *sd, unsigned long long len); static size_t hstream_add_htx_data(struct hstream *hs, struct htx *htx, unsigned long long len); @@ -1158,4 +1167,55 @@ static int hstream_build_responses(void) return 1; } +#if defined(USE_LINUX_SPLICE) +static void hstream_init_splicing(void) +{ + if (!(global.tune.options & GTUNE_USE_SPLICE)) + return; + + if (!global.tune.pipesize) + global.tune.pipesize = 65536 * 5 / 4; + + master_pipe = get_pipe(); + if (master_pipe) { + struct iovec v = { .iov_base = common_response, + .iov_len = sizeof(common_response) }; + int total, ret; + + total = ret = 0; + do { + ret = vmsplice(master_pipe->prod, &v, 1, SPLICE_F_NONBLOCK); + if (ret > 0) + total += ret; + } while (ret > 0 && total < global.tune.pipesize); + master_pipesize = total; + + if (master_pipesize < global.tune.pipesize) { + if (master_pipesize < 60*1024) { + /* Older kernels were limited to around 60-61 kB */ + ha_warning("Failed to vmsplice response buffer after %lu bytes, splicing disabled\n", master_pipesize); + global.tune.options &= ~GTUNE_USE_SPLICE; + put_pipe(master_pipe); + master_pipe = NULL; + } + else + ha_warning("Splicing is limited to %lu bytes (too old kernel)\n", master_pipesize); + } + } + else { + ha_warning("Unable to allocate master pipe for splicing, splicing disabled\n"); + global.tune.options &= ~GTUNE_USE_SPLICE; + } +} + +static void hstream_deinit(void) +{ + if (master_pipe) + put_pipe(master_pipe); +} + +REGISTER_POST_DEINIT(hstream_deinit); +INITCALL0(STG_INIT_2, hstream_init_splicing); +#endif + REGISTER_POST_CHECK(hstream_build_responses); diff --git a/src/haterm_init.c b/src/haterm_init.c index 94e8a96a1..797e636d2 100644 --- a/src/haterm_init.c +++ b/src/haterm_init.c @@ -186,6 +186,10 @@ void haproxy_init_args(int argc, char **argv) /* save the arguments */ sargc = argc; sargv = argv; +#if defined(USE_LINUX_SPLICE) + global.tune.options |= GTUNE_USE_SPLICE; +#endif + /* THIS PART MUST NOT MODIFY THE ARGUMENTS */ /* Parse the arguments which must be reused to build the conf. */ while (argc > 0) {