[CRIU] [PATCH 3/4] sk-unix: Handle bindmounted dgram sockets on restore
Andrei Vagin
avagin at gmail.com
Thu Aug 10 02:42:15 MSK 2017
On Tue, Aug 08, 2017 at 02:25:09PM +0300, Cyrill Gorcunov wrote:
> If a socket is bindmounted one we open it early (thus mount engine
> will be eable to proceed), put it into fdstore and then simply fetch
> it from there.
>
> Note it's important that only basic scenario with dgram/closed sockets
> is supported by now: established, listening sockets requires a way
> more code change and we will do it only when really needed.
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> criu/include/sockets.h | 2 ++
> criu/mount.c | 7 +++++++
> criu/sk-unix.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 62 insertions(+)
>
> diff --git a/criu/include/sockets.h b/criu/include/sockets.h
> index 64673c5e5dc8..3d4669859182 100644
> --- a/criu/include/sockets.h
> +++ b/criu/include/sockets.h
> @@ -8,6 +8,7 @@
>
> struct fdinfo_list_entry;
> struct sk_opts_entry;
> +struct mount_info;
> struct file_desc;
> struct fd_parms;
> struct cr_imgset;
> @@ -38,6 +39,7 @@ extern struct collect_image_info inet_sk_cinfo;
> extern struct collect_image_info unix_sk_cinfo;
> extern int fix_external_unix_sockets(void);
> extern int collect_unix_bindmounts(void);
> +extern int unix_prepare_bindmount(struct mount_info *mi);
>
> extern struct collect_image_info netlink_sk_cinfo;
>
> diff --git a/criu/mount.c b/criu/mount.c
> index 59fd17870db8..174cc4639209 100644
> --- a/criu/mount.c
> +++ b/criu/mount.c
> @@ -27,6 +27,7 @@
> #include "files-reg.h"
> #include "external.h"
> #include "fdstore.h"
> +#include "sockets.h"
>
> #include "images/mnt.pb-c.h"
>
> @@ -2042,6 +2043,12 @@ static int do_bind_mount(struct mount_info *mi)
> }
> }
>
> + if (unix_prepare_bindmount(mi)) {
Why do we call this function for all mounts?
> + pr_err("Failed to prepare bindmount on unix at %s\n",
> + mi->mountpoint);
> + goto err;
> + }
> +
> if (mount(root, mi->mountpoint, NULL, MS_BIND | (mi->flags & MS_REC), NULL) < 0) {
> pr_perror("Can't mount at %s", mi->mountpoint);
> goto err;
> diff --git a/criu/sk-unix.c b/criu/sk-unix.c
> index bf013c5ca4de..adc6d58aa173 100644
> --- a/criu/sk-unix.c
> +++ b/criu/sk-unix.c
> @@ -867,6 +867,7 @@ struct unix_sk_info {
> struct file_desc d;
> struct list_head connected; /* List of sockets, connected to me */
> struct list_head node; /* To link in peer's connected list */
> + int fdstore_id;
>
> /*
> * For DGRAM sockets with queues, we should only restore the queue
> @@ -1241,6 +1242,12 @@ static int open_unixsk_standalone(struct unix_sk_info *ui, int *new_fd)
> pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
> ui->ue->id, ui->ue->ino, ui->ue->peer);
>
> + if (ui->fdstore_id >= 0) {
> + pr_debug("\tObtaining from fdstore id %#x\n", ui->fdstore_id);
> + *new_fd = fdstore_get(ui->fdstore_id);
> + return 0;
> + }
> +
> if (set_netns(ui->ue->ns_id))
> return -1;
>
> @@ -1453,6 +1460,9 @@ static void unlink_stale(struct unix_sk_info *ui)
> {
> int ret, cwd_fd = -1, root_fd = -1;
>
> + if (ui->fdstore_id >= 0)
> + return;
> +
> if (ui->name[0] == '\0' || (ui->ue->uflags & USK_EXTERN))
> return;
>
> @@ -1509,6 +1519,7 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
> INIT_LIST_HEAD(&ui->connected);
> INIT_LIST_HEAD(&ui->node);
> ui->flags = 0;
> + ui->fdstore_id = -1;
> fixup_sock_net_ns_id(&ui->ue->ns_id, &ui->ue->has_ns_id);
>
> uname = ui->name;
> @@ -1553,6 +1564,48 @@ struct collect_image_info unix_sk_cinfo = {
> .flags = COLLECT_SHARED,
> };
>
> +int unix_prepare_bindmount(struct mount_info *mi)
> +{
> + char name_dir[PATH_MAX], ns_root[PATH_MAX];
> + struct unix_sk_info *ui, *t = NULL;
> + char *old_name_dir = NULL;
> + int ret, sk;
> +
> + list_for_each_entry(ui, &unix_sockets, list) {
> + if (!ui->ue->has_mnt_id || ui->ue->mnt_id != mi->mnt_id)
I don't like an idea to run this loop for each mount
> + continue;
> + t = ui;
> + break;
> + }
> +
> + if (!t)
> + return 0;
> +
> + print_ns_root(mi->nsid, 0, ns_root, sizeof(ns_root));
> + if (ui->name_dir) {
> + old_name_dir = ui->name_dir;
> + snprintf(name_dir, sizeof(name_dir), "%s/%s", ns_root, ui->name_dir);
> + ui->name_dir = name_dir;
> + }
> +
> + ret = open_unixsk_standalone(ui, &sk);
> + if (ui->name_dir)
> + ui->name_dir = old_name_dir;
> + BUG_ON(ret > 0);
> +
> + if (ret)
> + return -1;
> +
> + ui->fdstore_id = fdstore_add(sk);
> + if (ui->fdstore_id < 0)
> + return -1;
> + close(sk);
> +
> + pr_debug("Standalone socket moved into fdstore (id %#x ino %#x peer %#x)\n",
> + ui->ue->id, ui->ue->ino, ui->ue->peer);
> + return 0;
> +}
> +
> static void set_peer(struct unix_sk_info *ui, struct unix_sk_info *peer)
> {
> ui->peer = peer;
> --
> 2.7.5
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list