01c54c
From 2fdef836a59938b169ca3c8f2c813b35258f1ed5 Mon Sep 17 00:00:00 2001
01c54c
From: Adrian Reber <areber@redhat.com>
01c54c
Date: Tue, 14 Jun 2016 10:13:00 +0300
01c54c
Subject: [PATCH] criu: add an option to skip in-flight connections
01c54c
01c54c
Trying to migrate containers with tomcat and running ab as a test client
01c54c
(ab -n 1000000 -c 20 http://url/to/test) criu sometimes exited with an
01c54c
error if in-flight connections were detected. Criu can handle sockets
01c54c
listening and with established connection. In-flight connections can
01c54c
happen on sockets which do not yet have a full established connection
01c54c
(SYN, SYN-ACK, and the last ACK is missing).
01c54c
01c54c
This adds a new option to criu:
01c54c
01c54c
 --skip-in-flight  this option skips in-flight TCP connections.
01c54c
                   if TCP connections are found which are not yet completely
01c54c
                   established, criu will ignore these connections in favor
01c54c
                   of erroring out.
01c54c
01c54c
With this option criu will skip sockets in this state and let's the client
01c54c
handle the re-connection.
01c54c
01c54c
Signed-off-by: Adrian Reber <areber@redhat.com>
01c54c
Acked-by: Andrew Vagin <avagin@virtuozzo.com>
01c54c
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
01c54c
---
01c54c
 criu/crtools.c            | 9 +++++++++
01c54c
 criu/include/cr_options.h | 1 +
01c54c
 criu/include/sk-inet.h    | 1 +
01c54c
 criu/sk-inet.c            | 7 +++++++
01c54c
 4 files changed, 18 insertions(+)
01c54c
01c54c
diff --git a/criu/crtools.c b/criu/crtools.c
01c54c
index b527374..e7da5c7 100644
01c54c
--- a/criu/crtools.c
01c54c
+++ b/criu/crtools.c
01c54c
@@ -279,6 +279,7 @@ int main(int argc, char *argv[], char *envp[])
01c54c
 		{ "extra",			no_argument,		0, 1077	},
01c54c
 		{ "experimental",		no_argument,		0, 1078	},
01c54c
 		{ "all",			no_argument,		0, 1079	},
01c54c
+		{ SK_INFLIGHT_PARAM,		no_argument,		0, 1083	},
01c54c
 		{ },
01c54c
 	};
01c54c
 
01c54c
@@ -583,6 +584,10 @@ int main(int argc, char *argv[], char *envp[])
01c54c
 			opts.check_extra_features = true;
01c54c
 			opts.check_experimental_features = true;
01c54c
 			break;
01c54c
+		case 1083:
01c54c
+			pr_msg("Will skip in-flight TCP connections\n");
01c54c
+			opts.tcp_skip_in_flight = true;
01c54c
+			break;
01c54c
 		case 'V':
01c54c
 			pr_msg("Version: %s\n", CRIU_VERSION);
01c54c
 			if (strcmp(CRIU_GITID, "0"))
01c54c
@@ -791,6 +796,10 @@ int main(int argc, char *argv[], char *envp[])
01c54c
 "* Special resources support:\n"
01c54c
 "  -x|--" USK_EXT_PARAM "inode,.." "      allow external unix connections (optionally can be assign socket's inode that allows one-sided dump)\n"
01c54c
 "     --" SK_EST_PARAM "  checkpoint/restore established TCP connections\n"
01c54c
+"     --" SK_INFLIGHT_PARAM "   this option skips in-flight TCP connections.\n"
01c54c
+"                        if TCP connections are found which are not yet completely\n"
01c54c
+"                        established, criu will ignore these connections in favor\n"
01c54c
+"                        of erroring out.\n"
01c54c
 "  -r|--root PATH        change the root filesystem (when run in mount namespace)\n"
01c54c
 "  --evasive-devices     use any path to a device file if the original one\n"
01c54c
 "                        is inaccessible\n"
01c54c
diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h
01c54c
index 32c9d4f..bf9feee 100644
01c54c
--- a/criu/include/cr_options.h
01c54c
+++ b/criu/include/cr_options.h
01c54c
@@ -109,6 +109,7 @@ struct cr_options {
01c54c
 	char			*lsm_profile;
01c54c
 	unsigned int		timeout;
01c54c
 	unsigned int		empty_ns;
01c54c
+	bool			tcp_skip_in_flight;
01c54c
 };
01c54c
 
01c54c
 extern struct cr_options opts;
01c54c
diff --git a/criu/include/sk-inet.h b/criu/include/sk-inet.h
01c54c
index 4707a6e..9d2bda6 100644
01c54c
--- a/criu/include/sk-inet.h
01c54c
+++ b/criu/include/sk-inet.h
01c54c
@@ -72,6 +72,7 @@ extern int dump_one_tcp(int sk, struct inet_sk_desc *sd);
01c54c
 extern int restore_one_tcp(int sk, struct inet_sk_info *si);
01c54c
 
01c54c
 #define SK_EST_PARAM	"tcp-established"
01c54c
+#define SK_INFLIGHT_PARAM "skip-in-flight"
01c54c
 
01c54c
 extern int check_tcp(void);
01c54c
 extern mutex_t *inet_get_reuseaddr_lock(struct inet_sk_info *ii);
01c54c
diff --git a/criu/sk-inet.c b/criu/sk-inet.c
01c54c
index 20c6535..dfcfae6 100644
01c54c
--- a/criu/sk-inet.c
01c54c
+++ b/criu/sk-inet.c
01c54c
@@ -144,6 +144,11 @@ static int can_dump_inet_sk(const struct inet_sk_desc *sk)
01c54c
 	switch (sk->state) {
01c54c
 	case TCP_LISTEN:
01c54c
 		if (sk->rqlen != 0) {
01c54c
+			if (opts.tcp_skip_in_flight) {
01c54c
+				pr_info("Skipping in-flight connection (l) for %x\n",
01c54c
+						sk->sd.ino);
01c54c
+				break;
01c54c
+			}
01c54c
 			/*
01c54c
 			 * Currently the ICONS nla reports the conn
01c54c
 			 * requests for listen sockets. Need to pick
01c54c
@@ -151,6 +156,8 @@ static int can_dump_inet_sk(const struct inet_sk_desc *sk)
01c54c
 			 */
01c54c
 			pr_err("In-flight connection (l) for %x\n",
01c54c
 					sk->sd.ino);
01c54c
+			pr_err("In-flight connections can be ignored with the"
01c54c
+					"--%s option.\n", SK_INFLIGHT_PARAM);
01c54c
 			return 0;
01c54c
 		}
01c54c
 		break;