[MEDIUM] splice: add the global "nosplice" option

Setting "nosplice" in the global section will disable the use of TCP
splicing (both tcpsplice and linux 2.6 splice). The same will be
achieved using the "-dS" parameter on the command line.
diff --git a/include/types/global.h b/include/types/global.h
index 7862e91..0c3c8ad 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -51,6 +51,8 @@
 #define GTUNE_USE_EPOLL          (1<<2)
 #define GTUNE_USE_KQUEUE         (1<<3)
 #define GTUNE_USE_SEPOLL         (1<<4)
+/* platform-specific options */
+#define GTUNE_USE_SPLICE         (1<<5)
 
 
 /* FIXME : this will have to be redefined correctly */
diff --git a/src/backend.c b/src/backend.c
index 573e799..be3dcf6 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1675,7 +1675,8 @@
 	}
 
 #ifdef CONFIG_HAP_TCPSPLICE
-	if ((s->fe->options & s->be->options) & PR_O_TCPSPLICE) {
+	if ((global.tune.options & GTUNE_USE_SPLICE) &&
+	    (s->fe->options & s->be->options) & PR_O_TCPSPLICE) {
 		/* TCP splicing supported by both FE and BE */
 		tcp_splice_initfd(s->req->prod->fd, fd);
 	}
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 6defe9e..f98d07e 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -302,6 +302,9 @@
 	else if (!strcmp(args[0], "nopoll")) {
 		global.tune.options &= ~GTUNE_USE_POLL;
 	}
+	else if (!strcmp(args[0], "nosplice")) {
+		global.tune.options &= ~GTUNE_USE_SPLICE;
+	}
 	else if (!strcmp(args[0], "quiet")) {
 		global.mode |= MODE_QUIET;
 	}
diff --git a/src/haproxy.c b/src/haproxy.c
index 0c16e14..abf6eef 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -221,6 +221,9 @@
 #if defined(ENABLE_POLL)
 		"        -dp disables poll() usage even when available\n"
 #endif
+#if defined(CONFIG_HAP_LINUX_SPLICE) || defined(CONFIG_HAP_TCPSPLICE)
+		"        -dS disables splice usage (broken on old kernels)\n"
+#endif
 		"        -sf/-st [pid ]* finishes/terminates old pids. Must be last arguments.\n"
 		"\n",
 		name, DEFAULT_MAXCONN, cfg_maxpconn);
@@ -421,6 +424,9 @@
 #if defined(ENABLE_KQUEUE)
 	global.tune.options |= GTUNE_USE_KQUEUE;
 #endif
+#if defined(CONFIG_HAP_LINUX_SPLICE) || defined(CONFIG_HAP_TCPSPLICE)
+	global.tune.options |= GTUNE_USE_SPLICE;
+#endif
 
 	pid = getpid();
 	progname = *argv;
@@ -457,6 +463,10 @@
 			else if (*flag == 'd' && flag[1] == 'k')
 				global.tune.options &= ~GTUNE_USE_KQUEUE;
 #endif
+#if defined(CONFIG_HAP_LINUX_SPLICE) || defined(CONFIG_HAP_TCPSPLICE)
+			else if (*flag == 'd' && flag[1] == 'S')
+				global.tune.options &= ~GTUNE_USE_SPLICE;
+#endif
 			else if (*flag == 'V')
 				arg_mode |= MODE_VERBOSE;
 			else if (*flag == 'd' && flag[1] == 'b')
@@ -1011,11 +1021,12 @@
 	}
 
 #ifdef CONFIG_HAP_TCPSPLICE
-	if (global.last_checks & LSTCHK_TCPSPLICE) {
+	if ((global.tune.options & GTUNE_USE_SPLICE) && (global.last_checks & LSTCHK_TCPSPLICE)) {
 		if (tcp_splice_start() < 0) {
 			Alert("[%s.main()] Cannot enable tcp_splice.\n"
 			      "  Make sure you have enough permissions and that the module is loadable.\n"
-			      "  Alternatively, you may disable the 'tcpsplice' options in the configuration.\n"
+			      "  Alternatively, you may disable the 'tcpsplice' options in the configuration\n"
+			      "  or add 'nosplice' in the global section, or start with '-dS'.\n"
 			      "", argv[0], global.gid);
 			protocol_unbind_all();
 			exit(1);
diff --git a/src/session.c b/src/session.c
index c7dbf6f..d1bc052 100644
--- a/src/session.c
+++ b/src/session.c
@@ -32,6 +32,9 @@
 #include <proto/stream_sock.h>
 #include <proto/task.h>
 
+#ifdef CONFIG_HAP_TCPSPLICE
+#include <libtcpsplice.h>
+#endif
 
 struct pool_head *pool2_session;
 struct list sessions;
@@ -315,7 +318,8 @@
 			s->do_log(s);
 		}
 #ifdef CONFIG_HAP_TCPSPLICE
-		if ((s->fe->options & s->be->options) & PR_O_TCPSPLICE) {
+		if ((global.tune.options & GTUNE_USE_SPLICE) &&
+		    (s->fe->options & s->be->options) & PR_O_TCPSPLICE) {
 			/* TCP splicing supported by both FE and BE */
 			tcp_splice_splicefd(req->prod->fd, si->fd, 0);
 		}
@@ -761,6 +765,7 @@
 	    !s->req->analysers && !(s->req->flags & BF_HIJACK)) {
 		/* check if it is wise to enable kernel splicing on the request buffer */
 		if (!(s->req->flags & BF_KERN_SPLICING) &&
+		    (global.tune.options & GTUNE_USE_SPLICE) &&
 		    (pipes_used < global.maxpipes) &&
 		    (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
 		     (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
@@ -884,6 +889,7 @@
 	    !s->rep->analysers && !(s->rep->flags & BF_HIJACK)) {
 		/* check if it is wise to enable kernel splicing on the response buffer */
 		if (!(s->rep->flags & BF_KERN_SPLICING) &&
+		    (global.tune.options & GTUNE_USE_SPLICE) &&
 		    (pipes_used < global.maxpipes) &&
 		    (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
 		     (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&