From 9b556899d67d7b20c64422fbde6292528772094d Mon Sep 17 00:00:00 2001 From: Xiaoguang Li Date: Mon, 29 Mar 2021 20:58:28 -0400 Subject: [PATCH 34/72] netlink: add repair modes and clear resource when failure Signed-off-by: Jingxian He --- criu/cr-dump.c | 3 +++ criu/include/net.h | 1 + criu/sk-netlink.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/criu/cr-dump.c b/criu/cr-dump.c index e0e11cc..b7e0214 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -2073,6 +2073,9 @@ static int cr_dump_finish(int ret) } else if (ret != 0 && opts.pin_memory) { pr_info("clear pin mem info\n"); clear_pin_mem(0); + } else if (ret != 0 && opts.with_notifier_kup) { + pr_info("repair off netlink fd\n"); + netlink_repair_off(); } if (ret != 0 && opts.with_notifier_kup) { diff --git a/criu/include/net.h b/criu/include/net.h index 0da4cad..718cc45 100644 --- a/criu/include/net.h +++ b/criu/include/net.h @@ -55,5 +55,6 @@ extern void check_has_netns_ioc(int fd, bool *kdat_val, const char *name); extern int net_set_ext(struct ns_id *ns); extern struct ns_id *get_root_netns(void); extern int read_net_ns_img(void); +extern int netlink_repair_off(void); #endif /* __CR_NET_H__ */ diff --git a/criu/sk-netlink.c b/criu/sk-netlink.c index 754eed9..d4b3b7b 100644 --- a/criu/sk-netlink.c +++ b/criu/sk-netlink.c @@ -68,6 +68,47 @@ int netlink_receive_one(struct nlmsghdr *hdr, struct ns_id *ns, void *arg) return sk_collect_one(m->ndiag_ino, PF_NETLINK, &sd->sd, ns); } +struct netlink_repair_fd { + int netlink_fd; + struct list_head nlist; +}; + +static LIST_HEAD(netlink_repair_fds); + +static int netlink_repair_on(int fd) +{ + int ret, aux = 1; + struct netlink_repair_fd *nrf; + + ret = setsockopt(fd, SOL_NETLINK, TCP_REPAIR, &aux, sizeof(aux)); + if (ret < 0) { + pr_err("Can't turn netlink repair mode ON, error: %d\n", ret); + return ret; + } + nrf = malloc(sizeof(*nrf)); + if (!nrf) + return -ENOMEM; + nrf->netlink_fd = dup(fd); + list_add_tail(&nrf->nlist, &netlink_repair_fds); + return ret; +} + +int netlink_repair_off(void) +{ + int aux = 0, ret; + struct netlink_repair_fd *nrf, *n; + + list_for_each_entry_safe(nrf, n, &netlink_repair_fds, nlist) { + ret = setsockopt(nrf->netlink_fd, SOL_NETLINK, TCP_REPAIR, &aux, sizeof(aux)); + if (ret < 0) + pr_err("Failed to turn off repair mode on netlink\n"); + close(nrf->netlink_fd); + list_del(&nrf->nlist); + free(nrf); + } + return 0; +} + static bool can_dump_netlink_sk(int lfd) { int ret; @@ -90,6 +131,10 @@ static int dump_one_netlink_fd(int lfd, u32 id, const struct fd_parms *p) if (IS_ERR(sk)) goto err; + if (netlink_repair_on(lfd) < 0) { + goto err; + } + ne.id = id; ne.ino = p->stat.st_ino; -- 2.34.1