diff --git a/Documentation/criu.txt b/Documentation/criu.txt index b121f8b2b..779bca095 100644 --- a/Documentation/criu.txt +++ b/Documentation/criu.txt @@ -264,6 +264,9 @@ For example, the command line for the above example should look like this: The TCP stack on the client side is expected to handle the re-connect gracefully. +*--tcp-close*:: + Restore connected TCP sockets in closed state. + *--evasive-devices*:: Use any path to a device file if the original one is inaccessible. diff --git a/criu/crtools.c b/criu/crtools.c index 5213a6ff5..c3950cb16 100644 --- a/criu/crtools.c +++ b/criu/crtools.c @@ -290,6 +290,7 @@ int main(int argc, char *argv[], char *envp[]) BOOL_OPT("display-stats", &opts.display_stats), BOOL_OPT("weak-sysctls", &opts.weak_sysctls), { "status-fd", required_argument, 0, 1088 }, + { SK_CLOSE_PARAM, no_argument, 0, 1089 }, { }, }; @@ -568,6 +569,9 @@ int main(int argc, char *argv[], char *envp[]) return 1; } break; + case 1089: + opts.tcp_close = true; + break; case 'V': pr_msg("Version: %s\n", CRIU_VERSION); if (strcmp(CRIU_GITID, "0")) @@ -826,6 +830,7 @@ usage: "* Special resources support:\n" " --" SK_EST_PARAM " checkpoint/restore established TCP connections\n" " --" SK_INFLIGHT_PARAM " skip (ignore) in-flight TCP connections\n" +" --" SK_CLOSE_PARAM " restore connected TCP sockets in closed state\n" " -r|--root PATH change the root filesystem (when run in mount namespace)\n" " --evasive-devices use any path to a device file if the original one\n" " is inaccessible\n" diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h index c879de97a..45ee6cb1b 100644 --- a/criu/include/cr_options.h +++ b/criu/include/cr_options.h @@ -63,6 +63,7 @@ struct cr_options { int shell_job; int handle_file_locks; int tcp_established_ok; + bool tcp_close; int evasive_devices; int link_remap_ok; int log_file_per_pid; diff --git a/criu/include/sk-inet.h b/criu/include/sk-inet.h index bf6fb1d77..3b302ff70 100644 --- a/criu/include/sk-inet.h +++ b/criu/include/sk-inet.h @@ -75,6 +75,7 @@ extern int restore_one_tcp(int sk, struct inet_sk_info *si); #define SK_EST_PARAM "tcp-established" #define SK_INFLIGHT_PARAM "skip-in-flight" +#define SK_CLOSE_PARAM "tcp-close" struct task_restore_args; int prepare_tcp_socks(struct task_restore_args *); diff --git a/criu/sk-inet.c b/criu/sk-inet.c index 046d04be5..7ad4cd993 100644 --- a/criu/sk-inet.c +++ b/criu/sk-inet.c @@ -648,7 +648,7 @@ static int open_inet_sk(struct file_desc *d, int *new_fd) goto err; if (tcp_connection(ie)) { - if (!opts.tcp_established_ok) { + if (!opts.tcp_established_ok && !opts.tcp_close) { pr_err("Connected TCP socket in image\n"); goto err; } diff --git a/criu/sk-tcp.c b/criu/sk-tcp.c index 3acc71093..20ea528bb 100644 --- a/criu/sk-tcp.c +++ b/criu/sk-tcp.c @@ -8,6 +8,7 @@ #include "../soccr/soccr.h" +#include "cr_options.h" #include "util.h" #include "common/list.h" #include "log.h" @@ -407,6 +408,11 @@ int restore_one_tcp(int fd, struct inet_sk_info *ii) pr_info("Restoring TCP connection\n"); + if (opts.tcp_close && + ii->ie->state != TCP_LISTEN && ii->ie->state != TCP_CLOSE) { + return 0; + } + sk = libsoccr_pause(fd); if (!sk) return -1;