[CRIU] [PATCH 2/3] criu: add support for external net namespaces
Andrei Vagin
avagin at virtuozzo.com
Mon Jul 23 19:20:52 MSK 2018
It works like other external resources.
A user specify which namespaces are external and have not to be dumped.
On restore, the user gives file descriptors to preconfigured namespaces.
How to use:
dump:
--external net[INO]:KEY
restore:
--inherit-fd fd[NSFD]:KEY
The test script contains more details how to use this:
test/others/netns_ext/run.sh
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
criu/cr-restore.c | 6 +++++-
criu/include/namespaces.h | 1 +
criu/include/net.h | 2 ++
criu/net.c | 48 +++++++++++++++++++++++++++++++++++++++++++----
images/netdev.proto | 1 +
5 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 807a582d0..0e5b06456 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1674,7 +1674,11 @@ static int restore_task_with_children(void *_arg)
* ACT_SETUP_NS scripts, so the root netns has to be created here
*/
if (root_ns_mask & CLONE_NEWNET) {
- ret = unshare(CLONE_NEWNET);
+ struct ns_id *ns = net_get_root_ns();
+ if (ns->ext_key)
+ ret = net_set_ext(ns);
+ else
+ ret = unshare(CLONE_NEWNET);
if (ret) {
pr_perror("Can't unshare net-namespace");
goto err;
diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index c0ad0f419..5fe8038bf 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -91,6 +91,7 @@ struct ns_id {
struct ns_desc *nd;
struct ns_id *next;
enum ns_type type;
+ char *ext_key;
/*
* For mount namespaces on restore -- indicates that
diff --git a/criu/include/net.h b/criu/include/net.h
index 38b33a727..9976f6eb0 100644
--- a/criu/include/net.h
+++ b/criu/include/net.h
@@ -50,6 +50,8 @@ extern int net_get_nsid(int rtsk, int fd, int *nsid);
extern struct ns_id *net_get_root_ns();
extern int kerndat_nsid(void);
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();
extern int read_net_ns_img();
#endif /* __CR_NET_H__ */
diff --git a/criu/net.c b/criu/net.c
index e5b35fb54..cbd03dd0a 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -2199,6 +2199,22 @@ static int dump_netns_ids(int rtsk, struct ns_id *ns)
(void *)&arg);
}
+int net_set_ext(struct ns_id *ns)
+{
+ int fd, ret;
+
+ fd = inherit_fd_lookup_id(ns->ext_key);
+ if (fd < 0) {
+ pr_err("Unable to find an external netns: %s\n", ns->ext_key);
+ return -1;
+ }
+
+ ret = switch_ns_by_fd(fd, &net_ns_desc, NULL);
+ close(fd);
+
+ return ret;
+}
+
int dump_net_ns(struct ns_id *ns)
{
struct cr_imgset *fds;
@@ -2209,7 +2225,14 @@ int dump_net_ns(struct ns_id *ns)
return -1;
ret = mount_ns_sysfs();
- if (!(opts.empty_ns & CLONE_NEWNET)) {
+ if (ns->ext_key) {
+ NetnsEntry netns = NETNS_ENTRY__INIT;
+
+ netns.ext_key = ns->ext_key;
+ ret = pb_write_one(img_from_set(fds, CR_FD_NETNS), &netns, PB_NETNS);
+ if (ret)
+ goto out;
+ } else if (!(opts.empty_ns & CLONE_NEWNET)) {
int sk;
sk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
@@ -2253,6 +2276,7 @@ int dump_net_ns(struct ns_id *ns)
if (!ret)
ret = dump_nf_ct(fds, CR_FD_NETNF_EXP);
+out:
close(ns_sysfs_fd);
ns_sysfs_fd = -1;
@@ -2306,7 +2330,7 @@ static int prepare_net_ns_first_stage(struct ns_id *ns)
{
int ret = 0;
- if (opts.empty_ns & CLONE_NEWNET)
+ if (ns->ext_key || (opts.empty_ns & CLONE_NEWNET))
return 0;
ret = restore_netns_conf(ns);
@@ -2322,7 +2346,7 @@ static int prepare_net_ns_second_stage(struct ns_id *ns)
{
int ret = 0, nsid = ns->id;
- if (!(opts.empty_ns & CLONE_NEWNET)) {
+ if (!(opts.empty_ns & CLONE_NEWNET) && !ns->ext_key) {
if (ns->net.netns)
netns_entry__free_unpacked(ns->net.netns, NULL);
@@ -2370,7 +2394,14 @@ static int open_net_ns(struct ns_id *nsid)
static int do_create_net_ns(struct ns_id *ns)
{
- if (unshare(CLONE_NEWNET)) {
+ int ret;
+
+ if (ns->ext_key)
+ ret = net_set_ext(ns);
+ else
+ ret = unshare(CLONE_NEWNET);
+
+ if (ret) {
pr_perror("Unable to create a new netns");
return -1;
}
@@ -2717,9 +2748,18 @@ static int netns_nr;
static int collect_net_ns(struct ns_id *ns, void *oarg)
{
bool for_dump = (oarg == (void *)1);
+ char id[64], *val;
int ret;
pr_info("Collecting netns %d/%d\n", ns->id, ns->ns_pid);
+
+ snprintf(id, sizeof(id), "net[%u]", ns->kid);
+ val = external_lookup_by_key(id);
+ if (!IS_ERR_OR_NULL(val)) {
+ pr_debug("The %s netns is external\n", id);
+ ns->ext_key = val;
+ }
+
ret = prep_ns_sockets(ns, for_dump);
if (ret)
return ret;
diff --git a/images/netdev.proto b/images/netdev.proto
index b4b64d2cc..476a92ced 100644
--- a/images/netdev.proto
+++ b/images/netdev.proto
@@ -70,4 +70,5 @@ message netns_entry {
repeated sysctl_entry all_conf6 = 6;
repeated netns_id nsids = 7;
+ optional string ext_key = 8;
}
--
2.14.3
More information about the CRIU
mailing list