From 3844747536adbb1914740d14dadb0e91a5b9d25a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 22 May 2019 19:55:24 +0200 Subject: [PATCH] CLEANUP: raw_sock: remove support for very old linux splice bug workaround We've been dealing with a workaround for a bug in splice that used to affect version 2.6.25 to 2.6.27.12 and which was fixed 10 years ago in kernel versions which are not supported anymore. Given that people who would use a kernel in such a range would face much more serious stability and security issues, it's about time to get rid of this workaround and of the ASSUME_SPLICE_WORKS build option used to disable it. --- Makefile | 6 +----- src/raw_sock.c | 44 +++++++------------------------------------- 2 files changed, 8 insertions(+), 42 deletions(-) diff --git a/Makefile b/Makefile index a0e3bb32c..cf4a3d9e6 100644 --- a/Makefile +++ b/Makefile @@ -345,7 +345,7 @@ ifeq ($(TARGET),linux2628) set_target_defaults = $(call default_opts, \ USE_POLL USE_TPROXY USE_LIBCRYPT USE_DL USE_RT USE_CRYPT_H USE_NETFILTER \ USE_CPU_AFFINITY USE_THREAD USE_EPOLL USE_FUTEX USE_LINUX_TPROXY \ - USE_ACCEPT4 USE_LINUX_SPLICE USE_PRCTL ASSUME_SPLICE_WORKS USE_THREAD_DUMP) + USE_ACCEPT4 USE_LINUX_SPLICE USE_PRCTL USE_THREAD_DUMP) endif # Solaris 8 and above @@ -504,10 +504,6 @@ ifneq ($(USE_VSYSCALL),) OPTIONS_OBJS += src/i386-linux-vsys.o endif -ifneq ($(ASSUME_SPLICE_WORKS),) -OPTIONS_CFLAGS += -DASSUME_SPLICE_WORKS -endif - ifneq ($(USE_REGPARM),) OPTIONS_CFLAGS += -DCONFIG_REGPARM=3 endif diff --git a/src/raw_sock.c b/src/raw_sock.c index 59a7cbc2f..1090dfc67 100644 --- a/src/raw_sock.c +++ b/src/raw_sock.c @@ -54,12 +54,6 @@ * infinite forwarding */ #define MAX_SPLICE_AT_ONCE (1<<30) -/* Versions of splice between 2.6.25 and 2.6.27.12 were bogus and would return EAGAIN - * on incoming shutdowns. On these versions, we have to call recv() after such a return - * in order to find whether splice is OK or not. Since 2.6.27.13 we don't need to do - * this anymore, and we can avoid this logic by defining ASSUME_SPLICE_WORKS. - */ - /* Returns : * -1 if splice() is not supported * >= 0 to report the amount of spliced bytes. @@ -68,9 +62,6 @@ */ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe, unsigned int count) { -#ifndef ASSUME_SPLICE_WORKS - static THREAD_LOCAL int splice_detects_close; -#endif int ret; int retval = 0; @@ -109,28 +100,18 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); if (ret <= 0) { - if (ret == 0) { - /* connection closed. This is only detected by - * recent kernels (>= 2.6.27.13). If we notice - * it works, we store the info for later use. - */ -#ifndef ASSUME_SPLICE_WORKS - splice_detects_close = 1; -#endif + if (ret == 0) goto out_read0; - } if (errno == EAGAIN) { /* there are two reasons for EAGAIN : * - nothing in the socket buffer (standard) * - pipe is full - * - the connection is closed (kernel < 2.6.27.13) - * The last case is annoying but know if we can detect it - * and if we can't then we rely on the call to recv() to - * get a valid verdict. The difference between the first - * two situations is problematic. Since we don't know if - * the pipe is full, we'll stop if the pipe is not empty. - * Anyway, we will almost always fill/empty the pipe. + * The difference between these two situations + * is problematic. Since we don't know if the + * pipe is full, we'll stop if the pipe is not + * empty. Anyway, we will almost always fill or + * empty the pipe. */ if (pipe->data) { /* alway stop reading until the pipe is flushed */ @@ -138,18 +119,7 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe, break; } - /* We don't know if the connection was closed, - * but if we know splice detects close, then we - * know it for sure. - * But if we're called upon POLLIN with an empty - * pipe and get EAGAIN, it is suspect enough to - * try to fall back to the normal recv scheme - * which will be able to deal with the situation. - */ -#ifndef ASSUME_SPLICE_WORKS - if (splice_detects_close) -#endif - fd_cant_recv(conn->handle.fd); /* we know for sure that it's EAGAIN */ + fd_cant_recv(conn->handle.fd); break; } else if (errno == ENOSYS || errno == EINVAL || errno == EBADF) {