[CRIU] [PATCH 1/3] Add dump for unnamed unix sockets

artem.kuzmitskiy at lge.com artem.kuzmitskiy at lge.com
Mon Jul 27 09:19:34 PDT 2015


From: Artem Kuzmitskiy <artem.kuzmitskiy at lge.com>
Subject: [PATCH 1/3] Add dump for unnamed unix sockets

Added functionality for dumping unnamed unix sockets.
when we call CRIU with dump option, for unnamed socket we should pass it
inode    into --ext-unix-sk. Details about this problem described in
http://criu.org/External_UNIX_socket#What_to_do_with_socketpair.28.29-s.3F.
Usage example:
                criu dump -D images -o dump.log -v4 --ext-unix-sk=4529709 -t 13506

Signed-off-by: Artem Kuzmitskiy <artem.kuzmitskiy at lge.com>
---
cr-service.c         |  8 ++++-
crtools.c            |  9 ++++--
files.c              |  4 ++-
include/cr_options.h |  1 +
include/sockets.h    |  3 ++
lib/criu.c           | 47 +++++++++++++++++++++++++++
lib/criu.h           |  4 +--
protobuf/rpc.proto   | 61 ++++++++++++++++++-----------------
sk-unix.c            | 89 ++++++++++++++++++++++++++++++++++++++++++++++------
9 files changed, 182 insertions(+), 44 deletions(-)

diff --git a/cr-service.c b/cr-service.c
index 9c40989..105787e 100644
--- a/cr-service.c
+++ b/cr-service.c
@@ -30,6 +30,7 @@
#include "cgroup.h"
#include "action-scripts.h"
#include "security.h"
+#include "sockets.h"

#include "setproctitle.h"

@@ -285,8 +286,13 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
                               req->pid = ids.pid;
               }

-              if (req->has_ext_unix_sk)
+             if (req->has_ext_unix_sk) {
                               opts.ext_unix_sk = req->ext_unix_sk;
+                             for (i = 0; i < req->n_unix_sk_ino; i++) {
+                                             if (unix_sk_id_add(req->unix_sk_ino[i]->inode) < 0)
+                                                             goto err;
+                             }
+             }

               if (req->root)
                               opts.root = req->root;
diff --git a/crtools.c b/crtools.c
index b085d33..6af6080 100644
--- a/crtools.c
+++ b/crtools.c
@@ -50,6 +50,7 @@ void init_opts(void)

               /* Default options */
               opts.final_state = TASK_DEAD;
+             INIT_LIST_HEAD(&opts.ext_unixsk_ids);
               INIT_LIST_HEAD(&opts.veth_pairs);
               INIT_LIST_HEAD(&opts.scripts);
               INIT_LIST_HEAD(&opts.ext_mounts);
@@ -184,7 +185,7 @@ int main(int argc, char *argv[], char *envp[])
               int log_level = LOG_UNSET;
               char *imgs_dir = ".";
               char *work_dir = NULL;
-              static const char short_opts[] = "dSsRf:F:t:p:hcD:o:n:v::xVr:jlW:L:M:";
+             static const char short_opts[] = "dSsRf:F:t:p:hcD:o:n:v::x::Vr:jlW:L:M:";
               static struct option long_opts[] = {
                               { "tree",                                               required_argument,      0, 't'        },
                               { "pid",                                  required_argument,      0, 'p'       },
@@ -201,7 +202,7 @@ int main(int argc, char *argv[], char *envp[])
                               { "log-file",                                          required_argument,      0, 'o'       },
                               { "namespaces",                                               required_argument,      0, 'n'       },
                               { "root",                                               required_argument,      0, 'r'        },
-                              { USK_EXT_PARAM,                       no_argument,                   0, 'x'       },
+                             { USK_EXT_PARAM,                       optional_argument,       0, 'x'       },
                               { "help",                                               no_argument,                   0, 'h'       },
                               { SK_EST_PARAM,                                           no_argument,                   0, 1042  },
                               { "close",                                              required_argument,      0, 1043  },
@@ -278,6 +279,8 @@ int main(int argc, char *argv[], char *envp[])
                                               opts.final_state = TASK_ALIVE;
                                               break;
                               case 'x':
+                                             if (optarg && unix_sk_ids_parse(optarg) < 0)
+                                                             return 1;
                                               opts.ext_unix_sk = true;
                                               break;
                               case 'p':
@@ -675,7 +678,7 @@ usage:
"                        restore making it the parent of the restored process\n"
"\n"
"* Special resources support:\n"
-"  -x|--" USK_EXT_PARAM "      allow external unix connections\n"
+"  -x|--" USK_EXT_PARAM "inode,.." "      allow external unix connections (optionally can be assign socket's inode that allows one-sided dump)\n"
"     --" SK_EST_PARAM "  checkpoint/restore established TCP connections\n"
"  -r|--root PATH        change the root filesystem (when run in mount namespace)\n"
"  --evasive-devices     use any path to a device file if the original one\n"
diff --git a/files.c b/files.c
index 071fa69..613289a 100644
--- a/files.c
+++ b/files.c
@@ -1421,8 +1421,10 @@ bool inherited_fd(struct file_desc *d, int *fd_p)
                               return true;

               *fd_p = dup(i_fd);
-              if (*fd_p < 0)
+             if (*fd_p < 0) {
                               pr_perror("Inherit fd DUP failed");
+                             return false;
+             }
               else
                               pr_info("File %s will be restored from fd %d duped "
                                                               "from inherit fd %d\n", id_str, *fd_p, i_fd);
diff --git a/include/cr_options.h b/include/cr_options.h
index bf57ef9..19c2f77 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -45,6 +45,7 @@ struct cr_options {
               };
               bool                                       restore_sibling;
               bool                                       ext_unix_sk;
+             struct list_head        ext_unixsk_ids;
               bool                                       shell_job;
               bool                                       handle_file_locks;
               bool                                       tcp_established_ok;
diff --git a/include/sockets.h b/include/sockets.h
index a3010e1..39c22fd 100644
--- a/include/sockets.h
+++ b/include/sockets.h
@@ -60,6 +60,9 @@ extern int inet_collect_one(struct nlmsghdr *h, int family, int type);
extern int unix_receive_one(struct nlmsghdr *h, void *);
extern int netlink_receive_one(struct nlmsghdr *hdr, void *arg);

+extern int unix_sk_id_add(ino_t ino);
+extern int unix_sk_ids_parse(char *optarg);
+
extern int do_dump_opt(int sk, int level, int name, void *val, int len);
#define dump_opt(s, l, n, f)       do_dump_opt(s, l, n, f, sizeof(*f))
extern int do_restore_opt(int sk, int level, int name, void *val, int len);
diff --git a/lib/criu.c b/lib/criu.c
index be848bb..95bc2f6 100644
--- a/lib/criu.c
+++ b/lib/criu.c
@@ -225,6 +225,53 @@ void criu_set_ext_unix_sk(bool ext_unix_sk)
               criu_local_set_ext_unix_sk(global_opts, ext_unix_sk);
}

+int criu_local_add_unix_sk(criu_opts *opts, unsigned int inode)
+{
+             int nr;
+             UnixSk **a, *u;
+
+             /*if caller forgot enable ext_unix_sk option we do it*/
+             if (!opts->rpc->has_ext_unix_sk) {
+                             criu_local_set_ext_unix_sk(opts, true);
+             }
+
+             /*if user disabled ext_unix_sk and try to add unixsk inode after that*/
+             if (opts->rpc->has_ext_unix_sk && !opts->rpc->ext_unix_sk) {
+                             if (opts->rpc->n_unix_sk_ino > 0) {
+                                             free(opts->rpc->unix_sk_ino);
+                                             opts->rpc->n_unix_sk_ino = 0;
+                             }
+                             return -1;
+             }
+
+             u = malloc(sizeof(*u));
+             if (!u)
+                             goto er;
+             unix_sk__init(u);
+
+             u->inode = inode;
+
+             nr = opts->rpc->n_unix_sk_ino + 1;
+             a = realloc(opts->rpc->unix_sk_ino, nr * sizeof(u));
+             if (!a)
+                             goto er_u;
+
+             a[nr - 1] = u;
+             opts->rpc->unix_sk_ino = a;
+             opts->rpc->n_unix_sk_ino = nr;
+             return 0;
+
+er_u:
+             free(u);
+er:
+             return -ENOMEM;
+}
+
+int criu_add_unix_sk(unsigned int inode)
+{
+             return criu_local_add_unix_sk(global_opts, inode);
+}
+
void criu_local_set_tcp_established(criu_opts *opts, bool tcp_established)
{
               opts->rpc->has_tcp_established              = true;
diff --git a/lib/criu.h b/lib/criu.h
index 1655c02..eab42f6 100644
--- a/lib/criu.h
+++ b/lib/criu.h
@@ -48,6 +48,7 @@ void criu_set_parent_images(char *path);
void criu_set_work_dir_fd(int fd);
void criu_set_leave_running(bool leave_running);
void criu_set_ext_unix_sk(bool ext_unix_sk);
+int criu_add_unix_sk(unsigned int inode);
void criu_set_tcp_established(bool tcp_established);
void criu_set_evasive_devices(bool evasive_devices);
void criu_set_shell_job(bool shell_job);
@@ -71,8 +72,6 @@ int criu_add_cg_root(char *ctrl, char *path);
int criu_add_enable_fs(char *fs);
int criu_add_skip_mnt(char *mnt);

-
-
/*
  * The criu_notify_arg_t na argument is an opaque
  * value that callbacks (cb-s) should pass into
@@ -157,6 +156,7 @@ void criu_local_set_parent_images(criu_opts *opts, char *path);
void criu_local_set_work_dir_fd(criu_opts *opts, int fd);
void criu_local_set_leave_running(criu_opts *opts, bool leave_running);
void criu_local_set_ext_unix_sk(criu_opts *opts, bool ext_unix_sk);
+int criu_local_add_unix_sk(criu_opts *opts, unsigned int inode);
void criu_local_set_tcp_established(criu_opts *opts, bool tcp_established);
void criu_local_set_evasive_devices(criu_opts *opts, bool evasive_devices);
void criu_local_set_shell_job(criu_opts *opts, bool shell_job);
diff --git a/protobuf/rpc.proto b/protobuf/rpc.proto
index c1969c6..e434dbb 100644
--- a/protobuf/rpc.proto
+++ b/protobuf/rpc.proto
@@ -25,49 +25,54 @@ message cgroup_root {
               required string                  path       = 2;
};

+message unix_sk {
+             required uint32                 inode    = 1;
+};
+
message criu_opts {
               required int32                                   images_dir_fd   = 1;
               optional int32                                    pid                          = 2; /* if not set on dump, will dump requesting process */

               optional bool                                     leave_running   = 3;
               optional bool                                     ext_unix_sk       = 4;
-              optional bool                                     tcp_established                = 5;
-              optional bool                                     evasive_devices               = 6;
-              optional bool                                     shell_job             = 7;
-              optional bool                                     file_locks             = 8;
-              optional int32                                    log_level              = 9 [default = 2];
-              optional string                                   log_file = 10; /* No subdirs are allowed. Consider using work-dir */
+             repeated unix_sk                unix_sk_ino     = 5;
+             optional bool                                     tcp_established                = 6;
+             optional bool                                     evasive_devices               = 7;
+             optional bool                                     shell_job             = 8;
+             optional bool                                     file_locks             = 9;
+             optional int32                                    log_level              = 10 [default = 2];
+             optional string                                   log_file = 11; /* No subdirs are allowed. Consider using work-dir */

-              optional criu_page_server_info                ps                           = 11;
+             optional criu_page_server_info                ps                           = 12;

-              optional bool                                     notify_scripts    = 12;
+             optional bool                                     notify_scripts    = 13;

-              optional string                                   root                       = 13;
-              optional string                                   parent_img        = 14;
-              optional bool                                     track_mem         = 15;
-              optional bool                                     auto_dedup       = 16;
+             optional string                                   root                       = 14;
+             optional string                                   parent_img        = 15;
+             optional bool                                     track_mem         = 16;
+             optional bool                                     auto_dedup       = 17;

-              optional int32                                    work_dir_fd       = 17;
-              optional bool                                     link_remap         = 18;
-              repeated criu_veth_pair                              veths                     = 19;
+             optional int32                                    work_dir_fd       = 18;
+             optional bool                                     link_remap         = 19;
+             repeated criu_veth_pair                              veths                     = 20;

-              optional uint32                                  cpu_cap                               = 20 [default = 0xffffffff];
-              optional bool                                     force_irmap       = 21;
-              repeated string                                 exec_cmd           = 22;
+             optional uint32                                  cpu_cap                               = 21 [default = 0xffffffff];
+             optional bool                                     force_irmap       = 22;
+             repeated string                                 exec_cmd           = 23;

-              repeated ext_mount_map                         ext_mnt                              = 23;
-              optional bool                                     manage_cgroups             = 24;
-              repeated cgroup_root                   cg_root                                = 25;
+             repeated ext_mount_map                         ext_mnt                              = 24;
+             optional bool                                     manage_cgroups             = 25;
+             repeated cgroup_root                   cg_root                                = 26;

-              optional bool                                     rst_sibling           = 26; /* swrk only */
-              repeated inherit_fd                        inherit_fd            = 27; /* swrk only */
+             optional bool                                     rst_sibling           = 27; /* swrk only */
+             repeated inherit_fd                        inherit_fd            = 28; /* swrk only */

-              optional bool                                     auto_ext_mnt  = 28;
-              optional bool                                     ext_sharing        = 29;
-              optional bool                                     ext_masters      = 30;
+             optional bool                                     auto_ext_mnt  = 29;
+             optional bool                                     ext_sharing        = 30;
+             optional bool                                     ext_masters      = 31;

-              repeated string                                 skip_mnt             = 31;
-              repeated string                                 enable_fs            = 32;
+             repeated string                                 skip_mnt             = 32;
+             repeated string                                 enable_fs            = 33;
}

message criu_dump_resp {
diff --git a/sk-unix.c b/sk-unix.c
index 6c9ec25..33d83e6 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -65,6 +65,11 @@ struct unix_sk_listen_icon {
               struct unix_sk_listen_icon           *next;
};

+struct  unix_sk_exception {
+             struct list_head unix_sk_list;
+             ino_t unix_sk_ino;
+};
+
#define SK_HASH_SIZE                                32

static struct unix_sk_listen_icon *unix_listen_icons[SK_HASH_SIZE];
@@ -129,6 +134,23 @@ static int can_dump_unix_sk(const struct unix_sk_desc *sk)
               return 1;
}

+static bool unix_sk_exception_lookup_id(ino_t ino)
+{
+             bool ret = false;
+             struct unix_sk_exception *sk;
+
+             list_for_each_entry(sk, &opts.ext_unixsk_ids, unix_sk_list) {
+                             if (sk->unix_sk_ino == ino) {
+                                             pr_debug("Found ino %u in exception unix sk list\n", (unsigned int)ino);
+                                             ret = true;
+                                             break;
+                             }
+             }
+
+             return ret;
+}
+
+
static int write_unix_entry(struct unix_sk_desc *sk)
{
               int ret;
@@ -559,16 +581,21 @@ static int dump_external_sockets(struct unix_sk_desc *peer)
                                                               return -1;
                                               }

-                                              if (peer->type != SOCK_DGRAM) {
-                                                              show_one_unix("Ext stream not supported", peer);
-                                                              pr_err("Can't dump half of stream unix connection.\n");
-                                                              return -1;
-                                              }
+                                             if (unix_sk_exception_lookup_id(sk->sd.ino)) {
+                                                             pr_debug("found exception for unix name-less external socket.\n");
+                                             } else {
+                                                             if (peer->type != SOCK_DGRAM) {
+                                                                             show_one_unix("Ext stream not supported", peer);
+                                                                             pr_err("Can't dump half of stream unix connection.\n");
+                                                                             return -1;
+                                                             }

-                                              if (!peer->name) {
-                                                              show_one_unix("Ext dgram w/o name", peer);
-                                                              pr_err("Can't dump name-less external socket.\n");
-                                                              return -1;
+                                                             if (!peer->name) {
+                                                                             show_one_unix("Ext dgram w/o name", peer);
+                                                                             pr_err("Can't dump name-less external socket.\n");
+                                                                             pr_err("%d\n", sk->fd);
+                                                                             return -1;
+                                                             }
                                               }
                               } else if (ret < 0)
                                               return -1;
@@ -1105,3 +1132,47 @@ int resolve_unix_peers(void)
               return 0;
}

+int unix_sk_id_add(ino_t ino)
+{
+             struct unix_sk_exception *unix_sk;
+
+             /* TODO: validate inode here? */
+
+             unix_sk = xmalloc(sizeof *unix_sk);
+             if (unix_sk == NULL)
+                             return -1;
+             unix_sk->unix_sk_ino = ino;
+             list_add_tail(&unix_sk->unix_sk_list, &opts.ext_unixsk_ids);
+
+             return 0;
+}
+
+int unix_sk_ids_parse(char *optarg)
+{
+             /*
+             * parsing option of the following form: --ext-unix-sk=<inode value>,<inode
+             * value>... or short form -x<inode>,<inode>...
+             */
+
+             char *iter = optarg;
+
+             while (*iter != '\0') {
+                             if (*iter == ',')
+                                             iter++;
+                             else {
+                                             ino_t ino = (ino_t)strtoul(iter, &iter, 10);
+
+                                             if (0 == ino) {
+                                                             pr_err("Can't parse unix socket inode from optarg: %s\n", optarg);
+                                                             return -1;
+                                             }
+                                             if (unix_sk_id_add(ino) < 0) {
+                                                             pr_err("Can't add unix socket inode in list: %s\n", optarg);
+                                                             return -1;
+                                             }
+                             }
+             }
+
+             return 0;
+}
+
--
2.1.4


Best regards,
Artem Kuzmitskiy
LG Russia R&D Lab, St.-Petersburg
Web Team Web 3 Part
Local phone 128


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvz.org/pipermail/criu/attachments/20150727/a180b685/attachment-0001.html>


More information about the CRIU mailing list