[09/12] net: split restore_links on read and restore parts

Submitted by Andrei Vagin on March 22, 2017, 12:28 a.m.

Details

Message ID 1490142533-20654-10-git-send-email-avagin@openvz.org
State New
Series "Dump and restore internal veth devices"
Headers show

Commit Message

Andrei Vagin March 22, 2017, 12:28 a.m.
From: Andrei Vagin <avagin@virtuozzo.com>

It's a preparation for enumirating links a few times.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/include/namespaces.h |   4 +-
 criu/namespaces.c         |   1 +
 criu/net.c                | 159 ++++++++++++++++++++++++++++------------------
 3 files changed, 102 insertions(+), 62 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index 5fc3826..70d16e5 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -7,6 +7,7 @@ 
 #include "files.h"
 #include "common/list.h"
 #include "images/ns.pb-c.h"
+#include "images/netdev.pb-c.h"
 
 #ifndef CLONE_NEWNS
 #define CLONE_NEWNS	0x00020000
@@ -89,7 +90,7 @@  struct netns_id {
 };
 
 struct net_link {
-	unsigned int		ifindex;
+	NetDeviceEntry		*nde;
 	bool			created;
 	struct list_head	node;
 };
@@ -140,6 +141,7 @@  struct ns_id {
 			int seqsk;	/* to talk to parasite daemons */
 			struct list_head ids;
 			struct list_head links;
+			NetnsEntry *netns;
 		} net;
 		struct {
 			UsernsEntry *e;
diff --git a/criu/namespaces.c b/criu/namespaces.c
index c180977..f12f79b 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -311,6 +311,7 @@  struct ns_id *rst_new_ns_id(unsigned int id, pid_t pid,
 		if (nd == &net_ns_desc) {
 			INIT_LIST_HEAD(&nsid->net.ids);
 			INIT_LIST_HEAD(&nsid->net.links);
+			nsid->net.netns = NULL;
 		}
 	}
 
diff --git a/criu/net.c b/criu/net.c
index f7a76e2..af3c56e 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1090,7 +1090,7 @@  static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req,
 			struct net_link *link;
 
 			list_for_each_entry(link, &ns->net.links, node)
-				if (link->ifindex == nde->peer_ifindex && link->created) {
+				if (link->nde->ifindex == nde->peer_ifindex && link->created) {
 					pr_err("%d\n", nde->peer_ifindex);
 					req->h.nlmsg_type = RTM_SETLINK;
 					return 0;
@@ -1111,7 +1111,6 @@  static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req,
 			if (link == NULL)
 				return -1;
 
-			link->ifindex = nde->ifindex;
 			link->created = true;
 			list_add(&link->node, &ns->net.links);
 		}
@@ -1243,7 +1242,7 @@  out:
 	return ret;
 }
 
-static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int criu_nlsk)
+static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk)
 {
 	struct newlink_extras extras = {
 		.link = -1,
@@ -1294,7 +1293,7 @@  out:
 	return ret;
 }
 
-static int restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int criu_nlsk)
+static int __restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk)
 {
 	pr_info("Restoring link %s type %d\n", nde->name, nde->type);
 
@@ -1311,7 +1310,7 @@  static int restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int cri
 	case ND_TYPE__BRIDGE:
 		return restore_one_link(ns, nde, nlsk, bridge_link_info, NULL);
 	case ND_TYPE__MACVLAN:
-		return restore_one_macvlan(ns, nde, nlsk, criu_nlsk);
+		return restore_one_macvlan(ns, nde, nlsk);
 	default:
 		pr_err("Unsupported link type %d\n", nde->type);
 		break;
@@ -1320,9 +1319,9 @@  static int restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int cri
 	return -1;
 }
 
-static int restore_links(struct ns_id *ns, NetnsEntry **netns)
+static int read_links(struct ns_id *ns)
 {
-	int nlsk, criu_nlsk = -1, ret = -1, id = ns->id;
+	int ret = -1, id = ns->id;
 	struct cr_img *img;
 	NetDeviceEntry *nde;
 
@@ -1330,54 +1329,87 @@  static int restore_links(struct ns_id *ns, NetnsEntry **netns)
 	if (!img)
 		return -1;
 
-	nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-	if (nlsk < 0) {
-		pr_perror("Can't create nlk socket");
-		close_image(img);
-		return -1;
-	}
-
 	while (1) {
-		NetnsEntry **def_netns = netns;
+		struct net_link *link;
 
 		ret = pb_read_one_eof(img, &nde, PB_NETDEV);
 		if (ret <= 0)
 			break;
 
-		ret = restore_link(ns, nde, nlsk, criu_nlsk);
-		if (ret) {
-			pr_err("Can't restore link: %d\n", ret);
-			goto exit;
+		link = xmalloc(sizeof(*link));
+		if (link == NULL) {
+			ret = -1;
+			net_device_entry__free_unpacked(nde, NULL);
+			break;
 		}
 
-		/*
-		 * optimize restore of devices configuration except lo
-		 * lo is created with namespace and before default is set
-		 * so we can't optimize its restore
-		 */
-		if (nde->type == ND_TYPE__LOOPBACK)
-			def_netns = NULL;
+		link->nde = nde;
+		link->created = 0;
+		list_add(&link->node, &ns->net.links);
+	}
+	close_image(img);
 
-		if (nde->conf4)
-			ret = ipv4_conf_op(nde->name, nde->conf4, nde->n_conf4, CTL_WRITE, def_netns ? (*def_netns)->def_conf4 : NULL);
-		else if (nde->conf)
-			ret = ipv4_conf_op_old(nde->name, nde->conf, nde->n_conf, CTL_WRITE, def_netns ? (*def_netns)->def_conf : NULL);
-		if (ret)
-			goto exit;
+	return 0;
+}
+
+static int restore_link(int nlsk, struct ns_id *ns, struct net_link *link)
+{
+	NetDeviceEntry *nde = link->nde;
+	NetnsEntry **def_netns = &ns->net.netns;
+	int ret;
+
+	ret = __restore_link(ns, nde, nlsk);
+	if (ret) {
+		pr_err("Can't restore link: %d\n", ret);
+		goto exit;
+	}
+
+	/*
+	 * optimize restore of devices configuration except lo
+	 * lo is created with namespace and before default is set
+	 * so we can't optimize its restore
+	 */
+	if (nde->type == ND_TYPE__LOOPBACK)
+		def_netns = NULL;
 
-		if (nde->conf6)
-			ret = ipv6_conf_op(nde->name, nde->conf6, nde->n_conf6, CTL_WRITE, def_netns ? (*def_netns)->def_conf6 : NULL);
+	if (nde->conf4)
+		ret = ipv4_conf_op(nde->name, nde->conf4, nde->n_conf4, CTL_WRITE, def_netns ? (*def_netns)->def_conf4 : NULL);
+	else if (nde->conf)
+		ret = ipv4_conf_op_old(nde->name, nde->conf, nde->n_conf, CTL_WRITE, def_netns ? (*def_netns)->def_conf : NULL);
+	if (ret)
+		goto exit;
+
+	if (nde->conf6)
+		ret = ipv6_conf_op(nde->name, nde->conf6, nde->n_conf6, CTL_WRITE, def_netns ? (*def_netns)->def_conf6 : NULL);
 exit:
-		net_device_entry__free_unpacked(nde, NULL);
-		if (ret)
-			break;
+	return ret;
+}
+
+static int restore_links(struct ns_id *ns)
+{
+	struct net_link *link, *t;
+	int exit_code = -1, nlsk;
+
+	nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+	if (nlsk < 0) {
+		pr_perror("Can't create nlk socket");
+		return -1;
 	}
 
+	list_for_each_entry_safe(link, t, &ns->net.links, node) {
+		if (restore_link(nlsk, ns, link))
+			goto out;
+		xfree(link);
+	}
+
+	exit_code = 0;
+out:
 	close(nlsk);
-	close_image(img);
-	return ret;
+
+	return exit_code;
 }
 
+
 static int run_ip_tool(char *arg1, char *arg2, char *arg3, char *arg4, int fdin, int fdout, unsigned flags)
 {
 	char *ip_tool_cmd;
@@ -1680,12 +1712,13 @@  out:
 	return ret;
 }
 
-static int restore_netns_conf(int pid, NetnsEntry **netns)
+static int restore_netns_conf(struct ns_id *ns)
 {
+	NetnsEntry *netns;
 	int ret = 0;
 	struct cr_img *img;
 
-	img = open_image(CR_FD_NETNS, O_RSTR, pid);
+	img = open_image(CR_FD_NETNS, O_RSTR, ns->id);
 	if (!img)
 		return -1;
 
@@ -1693,35 +1726,37 @@  static int restore_netns_conf(int pid, NetnsEntry **netns)
 		/* Backward compatibility */
 		goto out;
 
-	ret = pb_read_one(img, netns, PB_NETNS);
+	ret = pb_read_one(img, &netns, PB_NETNS);
 	if (ret < 0) {
 		pr_err("Can not read netns object\n");
 		return -1;
 	}
 
-	if ((*netns)->def_conf4) {
-		ret = ipv4_conf_op("all", (*netns)->all_conf4, (*netns)->n_all_conf4, CTL_WRITE, NULL);
+	if ((netns)->def_conf4) {
+		ret = ipv4_conf_op("all", (netns)->all_conf4, (netns)->n_all_conf4, CTL_WRITE, NULL);
 		if (ret)
 			goto out;
-		ret = ipv4_conf_op("default", (*netns)->def_conf4, (*netns)->n_def_conf4, CTL_WRITE, NULL);
+		ret = ipv4_conf_op("default", (netns)->def_conf4, (netns)->n_def_conf4, CTL_WRITE, NULL);
 		if (ret)
 			goto out;
-	} else if ((*netns)->def_conf) {
+	} else if ((netns)->def_conf) {
 		/* Backward compatibility */
-		ret = ipv4_conf_op_old("all", (*netns)->all_conf, (*netns)->n_all_conf, CTL_WRITE, NULL);
+		ret = ipv4_conf_op_old("all", (netns)->all_conf, (netns)->n_all_conf, CTL_WRITE, NULL);
 		if (ret)
 			goto out;
-		ret = ipv4_conf_op_old("default", (*netns)->def_conf, (*netns)->n_def_conf, CTL_WRITE, NULL);
+		ret = ipv4_conf_op_old("default", (netns)->def_conf, (netns)->n_def_conf, CTL_WRITE, NULL);
 		if (ret)
 			goto out;
 	}
 
-	if ((*netns)->def_conf6) {
-		ret = ipv6_conf_op("all", (*netns)->all_conf6, (*netns)->n_all_conf6, CTL_WRITE, NULL);
+	if ((netns)->def_conf6) {
+		ret = ipv6_conf_op("all", (netns)->all_conf6, (netns)->n_all_conf6, CTL_WRITE, NULL);
 		if (ret)
 			goto out;
-		ret = ipv6_conf_op("default", (*netns)->def_conf6, (*netns)->n_def_conf6, CTL_WRITE, NULL);
+		ret = ipv6_conf_op("default", (netns)->def_conf6, (netns)->n_def_conf6, CTL_WRITE, NULL);
 	}
+
+	ns->net.netns = netns;
 out:
 	close_image(img);
 	return ret;
@@ -1866,7 +1901,7 @@  int dump_net_ns(struct ns_id *ns)
 }
 
 static int net_set_nsid(int rtsk, int fd, int nsid);
-static int restore_netns_ids(struct ns_id *ns, NetnsEntry *netns)
+static int restore_netns_ids(struct ns_id *ns)
 {
 	int i, sk, exit_code = -1;
 
@@ -1876,15 +1911,15 @@  static int restore_netns_ids(struct ns_id *ns, NetnsEntry *netns)
 		return -1;
 	}
 
-	for (i = 0; i < netns->n_nsids; i++) {
+	for (i = 0; i < ns->net.netns->n_nsids; i++) {
 		struct ns_id *tg_ns;
 		struct netns_id *id;
 
 		id = xmalloc(sizeof(*id));
 		if (!id)
 			goto out;
-		id->target_ns_id = netns->nsids[i]->target_ns_id;
-		id->netnsid_value = netns->nsids[i]->netnsid_value;
+		id->target_ns_id = ns->net.netns->nsids[i]->target_ns_id;
+		id->netnsid_value = ns->net.netns->nsids[i]->netnsid_value;
 		list_add(&id->node, &ns->net.ids);
 
 		tg_ns = lookup_ns_by_id(id->target_ns_id, &net_ns_desc);
@@ -1907,16 +1942,18 @@  out:
 static int prepare_net_ns(struct ns_id *ns)
 {
 	int ret = 0, nsid = ns->id;
-	NetnsEntry *netns = NULL;
 
 	if (!(opts.empty_ns & CLONE_NEWNET)) {
-		ret = restore_netns_conf(nsid, &netns);
+		ret = restore_netns_conf(ns);
+		if (!ret)
+			ret = restore_netns_ids(ns);
 		if (!ret)
-			ret = restore_netns_ids(ns, netns);
+			ret = read_links(ns);
 		if (!ret)
-			ret = restore_links(ns, &netns);
-		if (netns)
-			netns_entry__free_unpacked(netns, NULL);
+			ret = restore_links(ns);
+
+		if (ns->net.netns)
+			netns_entry__free_unpacked(ns->net.netns, NULL);
 
 		if (!ret)
 			ret = restore_ifaddr(nsid);