[CRIU] Adding checkpoint/restore support to podman question
Andrei Vagin
avagin at virtuozzo.com
Sat Jul 21 07:30:17 MSK 2018
On Fri, Jul 20, 2018 at 08:31:16PM +0200, Adrian Reber wrote:
> On Wed, Jul 18, 2018 at 03:25:09PM +0200, Adrian Reber wrote:
> > > On Fri, May 04, 2018 at 02:01:08PM -0700, Andrei Vagin wrote:
> > > > On Thu, May 03, 2018 at 07:48:55PM +0200, Adrian Reber wrote:
> > > > > If you could implement the CRIU part that would be great. I have not
> > > > > started yet but I would then do the necessary changes in runc (and
> > > > > higher).
> > > >
> > > > Here is a criu part:
> > > > https://github.com/avagin/criu/tree/netns_ext
> > > >
> > > > Let me know if you will have any questions or comments.
>
> As your patch does not apply anymore (I guess due to the removal of
> nested namespaces) I tried to port your patch to the current criu-dev
> branch. And it almost works. I am storing the ext_key now in
> 'netns_entry', but the problem is that that image file is read to late.
>
> So at the point the network namespace is restored the necessary
> information is not yet read from the image file and the network
> namespace is never restored as described via inherit_fd.
>
> Please have a look at my attached patch and maybe you have an idea how
> to correctly implement it. Maybe you could just let me know which image
> file would be best suited for the ext_key of the network namespace and
> how to make sure it is available at restore time. Thanks.
>
Hi Adrian,
Could you try out this branch
https://github.com/avagin/criu/tree/netns_ext2
>
> Adrian
> diff --git a/criu/cr-restore.c b/criu/cr-restore.c
> index 807a582..0e5b064 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 c0ad0f4..5fe8038 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 1f6be06..e9419a9 100644
> --- a/criu/include/net.h
> +++ b/criu/include/net.h
> @@ -50,5 +50,6 @@ 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);
>
> #endif /* __CR_NET_H__ */
> diff --git a/criu/net.c b/criu/net.c
> index cf3ef5c..b7a4fcc 100644
> --- a/criu/net.c
> +++ b/criu/net.c
> @@ -1827,6 +1827,7 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
> char all_stable_secret[MAX_STR_CONF_LEN + 1] = {};
> NetnsId *ids;
> struct netns_id *p;
> + char id[64], *val;
>
> i = 0;
> list_for_each_entry(p, &ns->net.ids, node)
> @@ -1840,6 +1841,15 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
> if (!buf)
> goto out;
>
> + 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;
> + }
> +
> + netns.ext_key = ns->ext_key;
> +
> netns.nsids = xptr_pull_s(&buf, i * sizeof(NetnsId*));
> ids = xptr_pull_s(&buf, i * sizeof(NetnsId));
> i = 0;
> @@ -2178,6 +2188,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;
> @@ -2188,7 +2214,7 @@ int dump_net_ns(struct ns_id *ns)
> return -1;
>
> ret = mount_ns_sysfs();
> - if (!(opts.empty_ns & CLONE_NEWNET)) {
> + if (!(opts.empty_ns & CLONE_NEWNET) && !ns->ext_key) {
> int sk;
>
> sk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
> @@ -2285,7 +2311,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);
> @@ -2301,7 +2327,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);
>
> @@ -2349,7 +2375,13 @@ 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;
> }
> @@ -2378,6 +2410,9 @@ static int __prepare_net_namespaces(void *unused)
> if (nsid->type == NS_ROOT) {
> nsid->net.ns_fd = root_ns;
> } else {
> + pr_debug("nsid->net.netns %p\n", nsid->net.netns);
> + if (nsid->net.netns && nsid->net.netns->ext_key)
> + nsid->ext_key = xstrdup(nsid->net.netns->ext_key);
> if (do_create_net_ns(nsid))
> goto err;
> }
> diff --git a/images/netdev.proto b/images/netdev.proto
> index b4b64d2..28b162a 100644
> --- a/images/netdev.proto
> +++ b/images/netdev.proto
> @@ -70,4 +70,6 @@ message netns_entry {
> repeated sysctl_entry all_conf6 = 6;
>
> repeated netns_id nsids = 7;
> +
> + optional string ext_key = 8;
> }
More information about the CRIU
mailing list