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

Andrei Vagin avagin at openvz.org
Tue Feb 28 15:53:05 PST 2017


From: Andrei Vagin <avagin at virtuozzo.com>

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

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

diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index 2302cff..050211b 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;
 };
@@ -129,6 +130,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 797e5ee..3ae1e59 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 b48440e..d9d94b4 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1080,7 +1080,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;
@@ -1101,7 +1101,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);
 		}
@@ -1233,7 +1232,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,
@@ -1284,7 +1283,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);
 
@@ -1301,7 +1300,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;
@@ -1310,9 +1309,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;
 
@@ -1320,54 +1319,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;
@@ -1670,12 +1702,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;
 
@@ -1683,35 +1716,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;
@@ -1849,7 +1884,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;
 
@@ -1859,15 +1894,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->id = netns->nsids[i]->id;
-		id->net_id = netns->nsids[i]->nsid;
+		id->id = ns->net.netns->nsids[i]->id;
+		id->net_id = ns->net.netns->nsids[i]->nsid;
 		list_add(&id->node, &ns->net.ids);
 
 		tg_ns = lookup_ns_by_id(id->id, &net_ns_desc);
@@ -1890,16 +1925,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);
-- 
2.7.4



More information about the CRIU mailing list