333 lines
8.6 KiB
Diff
333 lines
8.6 KiB
Diff
From a22542173083d2eeb5dde627c47452ea641c98c1 Mon Sep 17 00:00:00 2001
|
|
From: Sang Yan <sangyan@huawei.com>
|
|
Date: Mon, 12 Jul 2021 16:14:45 +0800
|
|
Subject: [PATCH 40/72] net: add shared socket recover method for criu
|
|
|
|
When the socket file is shared with another process,
|
|
it will not be freed during dumping process.
|
|
We can repair the socket file by installing it to
|
|
the old fd number.
|
|
|
|
Add new options: "--share-dst-ports" and "--share-src-ports"
|
|
for user to tell criu which socket ports are shared.
|
|
|
|
Conflict:NA
|
|
Reference:https://gitee.com/src-openeuler/criu/pulls/21
|
|
Signed-off-by: Jingxian He <hejingxian@huawei.com>
|
|
---
|
|
criu/config.c | 8 ++
|
|
criu/crtools.c | 3 +
|
|
criu/files.c | 18 ++++-
|
|
criu/include/cr_options.h | 2 +
|
|
criu/include/files.h | 4 +
|
|
criu/include/net.h | 1 +
|
|
criu/include/sk-inet.h | 3 +
|
|
criu/sk-inet.c | 151 ++++++++++++++++++++++++++++++++++++++
|
|
8 files changed, 189 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/criu/config.c b/criu/config.c
|
|
index 0a0623a..7e92731 100644
|
|
--- a/criu/config.c
|
|
+++ b/criu/config.c
|
|
@@ -706,6 +706,8 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd,
|
|
BOOL_OPT("mask-exit-notify", &opts.mask_exit_notify),
|
|
BOOL_OPT("weak-file-check", &opts.weak_file_check),
|
|
BOOL_OPT("file-locks-repair", &opts.file_locks_repair),
|
|
+ { "share-dst-ports", required_argument, 0, 2000 },
|
|
+ { "share-src-ports", required_argument, 0, 2001 },
|
|
{},
|
|
};
|
|
|
|
@@ -1041,6 +1043,12 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd,
|
|
return 1;
|
|
}
|
|
break;
|
|
+ case 2000:
|
|
+ SET_CHAR_OPTS(share_dst_ports, optarg);
|
|
+ break;
|
|
+ case 2001:
|
|
+ SET_CHAR_OPTS(share_src_ports, optarg);
|
|
+ break;
|
|
case 'V':
|
|
pr_msg("Version: %s\n", CRIU_VERSION);
|
|
if (strcmp(CRIU_GITID, "0"))
|
|
diff --git a/criu/crtools.c b/criu/crtools.c
|
|
index 7358918..cfa149a 100644
|
|
--- a/criu/crtools.c
|
|
+++ b/criu/crtools.c
|
|
@@ -104,6 +104,9 @@ int main(int argc, char *argv[], char *envp[])
|
|
goto usage;
|
|
}
|
|
|
|
+ if (parse_share_ports())
|
|
+ goto usage;
|
|
+
|
|
log_set_loglevel(opts.log_level);
|
|
|
|
if (optind < argc && !strcmp(argv[optind], "swrk")) {
|
|
diff --git a/criu/files.c b/criu/files.c
|
|
index 1ec5281..1c52cf4 100644
|
|
--- a/criu/files.c
|
|
+++ b/criu/files.c
|
|
@@ -705,6 +705,8 @@ int dump_my_file(int lfd, u32 *id, int *type)
|
|
return 0;
|
|
}
|
|
|
|
+int dst_pid;
|
|
+
|
|
int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item, struct parasite_drain_fd *dfds)
|
|
{
|
|
int *lfds = NULL;
|
|
@@ -728,7 +730,7 @@ int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item, s
|
|
img = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id);
|
|
if (!img)
|
|
goto err;
|
|
-
|
|
+ dst_pid = item->pid->real;
|
|
ret = 0; /* Don't fail if nr_fds == 0 */
|
|
for (off = 0; ret == 0 && off < dfds->nr_fds; off += nr_fds) {
|
|
if (nr_fds + off > dfds->nr_fds)
|
|
@@ -1237,6 +1239,20 @@ static int open_fd(struct fdinfo_list_entry *fle)
|
|
goto out;
|
|
}
|
|
|
|
+ if (d->ops->type == FD_TYPES__INETSK) {
|
|
+ if (check_need_repair(d)) {
|
|
+ ret = repair_share_socket(d->id);
|
|
+ if (!ret) {
|
|
+ new_fd = get_share_socket();
|
|
+ pr_info("get share socket:%d\n", new_fd);
|
|
+ if (new_fd <= 0 || setup_and_serve_out(fle, new_fd) < 0)
|
|
+ return -1;
|
|
+ fle->stage = FLE_RESTORED;
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
/*
|
|
* Open method returns the following values:
|
|
* 0 -- restore is successfully finished;
|
|
diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h
|
|
index 9ec8034..b7c1e34 100644
|
|
--- a/criu/include/cr_options.h
|
|
+++ b/criu/include/cr_options.h
|
|
@@ -198,6 +198,8 @@ struct cr_options {
|
|
int mask_exit_notify;
|
|
int weak_file_check;
|
|
int file_locks_repair;
|
|
+ char *share_dst_ports;
|
|
+ char *share_src_ports;
|
|
};
|
|
|
|
extern struct cr_options opts;
|
|
diff --git a/criu/include/files.h b/criu/include/files.h
|
|
index 1d979a9..0521c7e 100644
|
|
--- a/criu/include/files.h
|
|
+++ b/criu/include/files.h
|
|
@@ -201,4 +201,8 @@ extern int open_transport_socket(void);
|
|
extern int set_fds_event(pid_t virt);
|
|
extern void wait_fds_event(void);
|
|
|
|
+extern int repair_share_socket(int id);
|
|
+extern int check_need_repair(struct file_desc *d);
|
|
+extern int get_share_socket(void);
|
|
+
|
|
#endif /* __CR_FILES_H__ */
|
|
diff --git a/criu/include/net.h b/criu/include/net.h
|
|
index 718cc45..ec47b61 100644
|
|
--- a/criu/include/net.h
|
|
+++ b/criu/include/net.h
|
|
@@ -16,6 +16,7 @@ extern int dump_net_ns(struct ns_id *ns);
|
|
extern int prepare_net_namespaces(void);
|
|
extern void fini_net_namespaces(void);
|
|
extern int netns_keep_nsfd(void);
|
|
+extern int parse_share_ports(void);
|
|
|
|
struct pstree_item;
|
|
extern int restore_task_net_ns(struct pstree_item *current);
|
|
diff --git a/criu/include/sk-inet.h b/criu/include/sk-inet.h
|
|
index c832d63..27deceb 100644
|
|
--- a/criu/include/sk-inet.h
|
|
+++ b/criu/include/sk-inet.h
|
|
@@ -101,4 +101,7 @@ struct rst_tcp_sock {
|
|
union libsoccr_addr;
|
|
int restore_sockaddr(union libsoccr_addr *sa, int family, u32 pb_port, u32 *pb_addr, u32 ifindex);
|
|
|
|
+#define MAX_SHARE_PORT_NUM 64
|
|
+extern int dst_pid;
|
|
+
|
|
#endif /* __CR_SK_INET_H__ */
|
|
diff --git a/criu/sk-inet.c b/criu/sk-inet.c
|
|
index 05048c8..c7de793 100644
|
|
--- a/criu/sk-inet.c
|
|
+++ b/criu/sk-inet.c
|
|
@@ -431,6 +431,152 @@ static bool needs_scope_id(uint32_t *src_addr)
|
|
return false;
|
|
}
|
|
|
|
+#define ADD_SHARE_SOCKET_PATH "/sys/kernel/add_share_socket"
|
|
+#define REPAIR_SHARE_SOCKET_PATH "/sys/kernel/repair_share_socket"
|
|
+#define SHARE_SOCKET_PATH "/sys/kernel/share_socket"
|
|
+
|
|
+int add_share_socket(u32 id, int fd, int pid, int port)
|
|
+{
|
|
+ int retval;
|
|
+ char buf[256] = {0};
|
|
+
|
|
+ retval = snprintf(buf, 256, "%u,%d,%d,%d", id, fd, pid, port);
|
|
+ if (retval <= 0)
|
|
+ return -EFAULT;
|
|
+
|
|
+ fd = open(ADD_SHARE_SOCKET_PATH, O_WRONLY, 0);
|
|
+ if (fd < 0) {
|
|
+ pr_err("open file:%s fail\n", ADD_SHARE_SOCKET_PATH);
|
|
+ return fd;
|
|
+ }
|
|
+
|
|
+ retval = write(fd, buf, strlen(buf));
|
|
+ close(fd);
|
|
+ return retval < 0 ? -1 : 0;
|
|
+}
|
|
+
|
|
+
|
|
+int repair_share_socket(int id)
|
|
+{
|
|
+ int retval, fd;
|
|
+ char buf[256] = {0};
|
|
+
|
|
+ retval = snprintf(buf, 256, "%u", id);
|
|
+ if (retval <= 0)
|
|
+ return -EFAULT;
|
|
+
|
|
+ fd = open(REPAIR_SHARE_SOCKET_PATH, O_WRONLY, 0);
|
|
+ if (fd < 0) {
|
|
+ pr_err("open file:%s fail\n", REPAIR_SHARE_SOCKET_PATH);
|
|
+ return fd;
|
|
+ }
|
|
+ retval = write(fd, buf, strlen(buf));
|
|
+
|
|
+ close(fd);
|
|
+ return retval < 0 ? -1 : 0;
|
|
+}
|
|
+
|
|
+int get_share_socket(void)
|
|
+{
|
|
+ int fd;
|
|
+ ssize_t count;
|
|
+ int retval = -1;
|
|
+ char buf[32] = {0};
|
|
+
|
|
+ fd = open(SHARE_SOCKET_PATH, O_RDONLY, 0);
|
|
+ if (fd < 0) {
|
|
+ pr_err("open file:%s fail\n", SHARE_SOCKET_PATH);
|
|
+ return fd;
|
|
+ }
|
|
+
|
|
+ count = read(fd, buf, sizeof(buf));
|
|
+ if (count > 0)
|
|
+ retval = atoi(buf);
|
|
+
|
|
+ close(fd);
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+int g_share_dst_ports[MAX_SHARE_PORT_NUM];
|
|
+int g_share_dst_port_num;
|
|
+int g_share_src_ports[MAX_SHARE_PORT_NUM];
|
|
+int g_share_src_port_num;
|
|
+
|
|
+int parse_share_ports(void)
|
|
+{
|
|
+ char *save, *p;
|
|
+
|
|
+ if (opts.share_dst_ports) {
|
|
+ p = strtok_r(opts.share_dst_ports, ",", &save);
|
|
+ while (p != NULL) {
|
|
+ if (g_share_dst_port_num >= MAX_SHARE_PORT_NUM)
|
|
+ return -1;
|
|
+ g_share_dst_ports[g_share_dst_port_num] = atoi(p);
|
|
+ if (!g_share_dst_ports[g_share_dst_port_num])
|
|
+ return -1;
|
|
+ g_share_dst_port_num++;
|
|
+ p = strtok_r(NULL, ",", &save);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (opts.share_src_ports) {
|
|
+ p = strtok_r(opts.share_src_ports, ",", &save);
|
|
+ while (p != NULL) {
|
|
+ if (g_share_src_port_num >= MAX_SHARE_PORT_NUM)
|
|
+ return -1;
|
|
+ g_share_src_ports[g_share_src_port_num] = atoi(p);
|
|
+ if (!g_share_src_ports[g_share_src_port_num])
|
|
+ return -1;
|
|
+ g_share_src_port_num++;
|
|
+ p = strtok_r(NULL, ",", &save);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int check_share_dst_port(int dst_port)
|
|
+{
|
|
+ int i;
|
|
+ int ret = 0;
|
|
+
|
|
+ for (i = 0; i < g_share_dst_port_num; i++) {
|
|
+ if (dst_port == g_share_dst_ports[i]) {
|
|
+ ret = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int check_share_src_port(int src_port)
|
|
+{
|
|
+ int i;
|
|
+ int ret = 0;
|
|
+
|
|
+ for (i = 0; i < g_share_src_port_num; i++) {
|
|
+ if (src_port == g_share_src_ports[i]) {
|
|
+ ret = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int check_need_repair(struct file_desc *d)
|
|
+{
|
|
+ struct inet_sk_info *ii;
|
|
+ InetSkEntry *ie;
|
|
+
|
|
+ ii = container_of(d, struct inet_sk_info, d);
|
|
+ ie = ii->ie;
|
|
+ if (check_share_dst_port(ie->dst_port) ||
|
|
+ check_share_src_port(ie->src_port))
|
|
+ return 1;
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int family)
|
|
{
|
|
struct inet_sk_desc *sk;
|
|
@@ -488,6 +634,11 @@ static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int fa
|
|
|
|
BUG_ON(sk->sd.already_dumped);
|
|
|
|
+ if (check_share_dst_port(sk->dst_port) || check_share_src_port(sk->src_port)) {
|
|
+ pr_info("Start add share prot:%d src %d\n", sk->dst_port, sk->src_port);
|
|
+ add_share_socket(id, lfd, dst_pid, sk->src_port);
|
|
+ }
|
|
+
|
|
ie.id = id;
|
|
ie.ino = sk->sd.ino;
|
|
if (sk->sd.sk_ns) {
|
|
--
|
|
2.34.1
|
|
|