[CRIU] [PATCH 09/12] net: split restore_links on read and restore parts
Andrei Vagin
avagin at openvz.org
Tue Mar 21 17:28:50 PDT 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 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);
--
2.7.4
More information about the CRIU
mailing list