[MINOR] Allow shutdown of sessions when a server becomes unavailable

This adds the "on-marked-down shutdown-sessions" statement on "server" lines,
which causes all sessions established on a server to be killed at once when
the server goes down. The task's priority is reniced to the highest value
(1024) so that servers holding many tasks don't cause a massive slowdown due
to the wakeup storm.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index f35971f..f397f41 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -6667,6 +6667,15 @@
 
   See also the "check", "observe" and "error-limit".
 
+on-marked-down <action>
+  Modify what occurs when a server is marked down.
+  Currently one action is available:
+  - shutdown-sessions: Shutdown peer sessions
+
+  Actions are disabled by default
+
+  Supported in default-server: Yes
+
 port <port>
   Using the "port" parameter, it becomes possible to use a different port to
   send health-checks. On some servers, it may be desirable to dedicate a port
diff --git a/include/types/checks.h b/include/types/checks.h
index 75e32b6..a414630 100644
--- a/include/types/checks.h
+++ b/include/types/checks.h
@@ -74,6 +74,12 @@
 };
 
 enum {
+	HANA_ONMARKEDDOWN_NONE	= 0,
+
+	HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS,	/* Shutdown peer sessions */
+};
+
+enum {
 	HANA_OBS_NONE		= 0,
 
 	HANA_OBS_LAYER4,		/* Observe L4 - for example tcp */
diff --git a/include/types/server.h b/include/types/server.h
index cf0a0df..1a9d60d 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -125,6 +125,7 @@
 	int rise, fall;				/* time in iterations */
 	int consecutive_errors_limit;		/* number of consecutive errors that triggers an event */
 	short observe, onerror;			/* observing mode: one of HANA_OBS_*; what to do on error: on of ANA_ONERR_* */
+	short onmarkeddown;			/* what to do when marked down: on of HANA_ONMARKEDDOWN_* */
 	int inter, fastinter, downinter;	/* checks: time in milliseconds */
 	int slowstart;				/* slowstart time in seconds (ms in the conf) */
 	int result;				/* health-check result : SRV_CHK_* */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index cd05d83..7b46df0 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4251,6 +4251,18 @@
 
 				cur_arg += 2;
 			}
+			else if (!strcmp(args[cur_arg], "on-marked-down")) {
+				if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
+					newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
+				else {
+					Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
+						file, linenum, args[cur_arg], args[cur_arg + 1]);
+					err_code |= ERR_ALERT | ERR_FATAL;
+					goto out;
+				}
+
+				cur_arg += 2;
+			}
 			else if (!strcmp(args[cur_arg], "error-limit")) {
 				if (!*args[cur_arg + 1]) {
 					Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
@@ -4430,7 +4442,7 @@
 			}
 			else {
 				if (!defsrv)
-					Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
+					Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
 					      file, linenum, newsrv->id);
 				else
 					Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
diff --git a/src/checks.c b/src/checks.c
index 82aceaa..6b34a37 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -45,6 +45,7 @@
 #include <proto/proto_tcp.h>
 #include <proto/proxy.h>
 #include <proto/server.h>
+#include <proto/session.h>
 #include <proto/stream_interface.h>
 #include <proto/task.h>
 
@@ -357,6 +358,24 @@
 	return xferred;
 }
 
+/* Shutdown connections when their server goes down.
+ */
+static void shutdown_sessions(struct server *srv)
+{
+	struct session *session, *session_bck;
+
+	list_for_each_entry_safe(session, session_bck,
+				 &srv->actconns, by_srv) {
+		if (session->srv_conn == srv &&
+		    !(session->req->flags & (BF_SHUTW|BF_SHUTW_NOW))) {
+				buffer_shutw_now(session->req);
+				buffer_shutr_now(session->rep);
+				session->task->nice = 1024;
+				task_wakeup(session->task, TASK_WOKEN_OTHER);
+		}
+	}
+}
+
 /* Sets server <s> down, notifies by all available means, recounts the
  * remaining servers on the proxy and transfers queued sessions whenever
  * possible to other servers. It automatically recomputes the number of
@@ -380,6 +399,9 @@
 		s->state &= ~(SRV_RUNNING | SRV_GOINGDOWN);
 		s->proxy->lbprm.set_server_status_down(s);
 
+		if (s->onmarkeddown & HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS)
+			shutdown_sessions(s);
+
 		/* we might have sessions queued on this server and waiting for
 		 * a connection. Those which are redispatchable will be queued
 		 * to another server or to the proxy itself.