[CRIU] [RFC] sockets,
unix: Use general machnism for checkpoint/restore
Cyrill Gorcunov
gorcunov at openvz.org
Fri May 11 12:20:45 EDT 2012
Pavel, tell me please how the attached patch looks for you.
If it's ok I'll continue with other socket types.
Cyrill
-------------- next part --------------
>From 15b5c6309dfdac177c750d2491431136e32bd5a0 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Fri, 11 May 2012 20:19:02 +0400
Subject: [PATCH] sockets, unix: Use general machnism for checkpoint/restore
Use fdtype_ops facility to c/r unix sockets.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
files.c | 21 +++++++++++
include/files.h | 4 ++
include/image.h | 1 +
include/sockets.h | 3 +-
sk-unix.c | 96 ++++++++++++++++++++++++++++++----------------------
sockets.c | 19 +++++++---
6 files changed, 95 insertions(+), 49 deletions(-)
diff --git a/files.c b/files.c
index 6ca1978..5a43580 100644
--- a/files.c
+++ b/files.c
@@ -56,6 +56,27 @@ void file_desc_add(struct file_desc *d, u32 id,
list_add_tail(&d->hash, &file_descs[id % FDESC_HASH_SIZE]);
}
+struct file_desc *
+find_file_desc_slow_by(int type, void *p,
+ int (*cb)(struct file_desc *d, void *p))
+{
+ struct file_desc *d;
+ struct list_head *chain;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(file_descs); i++) {
+ chain = &file_descs[i];
+ list_for_each_entry(d, chain, hash) {
+ if (d->ops->type == type) {
+ if (cb(d, p))
+ return d;
+ }
+ }
+ }
+
+ return NULL;
+}
+
struct file_desc *find_file_desc_raw(int type, u32 id)
{
struct file_desc *d;
diff --git a/include/files.h b/include/files.h
index 2e97c76..662b4ab 100644
--- a/include/files.h
+++ b/include/files.h
@@ -55,6 +55,10 @@ struct fdtype_ops {
int (*dump)(int lfd, u32 id, const struct fd_parms *p);
};
+extern struct file_desc *
+find_file_desc_slow_by(int type, void *p,
+ int (*cb)(struct file_desc *d, void *p));
+
extern u32 make_gen_id(const struct fd_parms *p);
struct cr_fdset;
extern int do_dump_gen_file(struct fd_parms *p, int lfd,
diff --git a/include/image.h b/include/image.h
index 650ebf1..e004dd4 100644
--- a/include/image.h
+++ b/include/image.h
@@ -177,6 +177,7 @@ struct sk_opts_entry {
struct unix_sk_entry {
u32 id;
+ u32 ino;
u8 type;
u8 state;
u8 namelen; /* fits UNIX_PATH_MAX */
diff --git a/include/sockets.h b/include/sockets.h
index b94fab4..d683960 100644
--- a/include/sockets.h
+++ b/include/sockets.h
@@ -49,8 +49,7 @@ extern struct socket_desc *lookup_socket(int ino);
extern int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p,
int lfd, const struct cr_fdset *cr_fdset);
-extern int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
- int lfd, const struct cr_fdset *cr_fdset);
+extern int dump_one_unix(struct fd_parms *p, int lfd, const struct cr_fdset *set);
extern int inet_collect_one(struct nlmsghdr *h, int family, int type, int proto);
extern int unix_receive_one(struct nlmsghdr *h);
diff --git a/sk-unix.c b/sk-unix.c
index 193b12e..0c8153d 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -11,6 +11,7 @@
#include "crtools.h"
#include "unix_diag.h"
#include "files.h"
+#include "file-ids.h"
#include "image.h"
#include "log.h"
#include "util.h"
@@ -72,8 +73,8 @@ static void show_one_unix(char *act, const struct unix_sk_desc *sk)
static void show_one_unix_img(const char *act, const struct unix_sk_entry *e)
{
- pr_info("\t%s: id 0x%x peer 0x%x type %d state %d name %d bytes\n",
- act, e->id, e->peer, e->type, e->state, e->namelen);
+ pr_info("\t%s: id 0x%x ino 0x%x peer 0x%x type %d state %d name %d bytes\n",
+ act, e->id, e->ino, e->peer, e->type, e->state, e->namelen);
}
static int can_dump_unix_sk(const struct unix_sk_desc *sk)
@@ -104,28 +105,24 @@ static int can_dump_unix_sk(const struct unix_sk_desc *sk)
return 1;
}
-int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
- int lfd, const struct cr_fdset *cr_fdset)
+static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
{
- struct unix_sk_desc *sk = (struct unix_sk_desc *)_sk;
+ struct unix_sk_desc *sk;
struct fdinfo_entry fe;
struct unix_sk_entry ue;
- if (!can_dump_unix_sk(sk))
+ sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino);
+ if (!sk)
goto err;
- fe.fd = p->fd;
- fe.type = FDINFO_UNIXSK;
- fe.id = sk->sd.ino;
- fe.flags = p->fd_flags;
-
- if (write_img(fdset_fd(cr_fdset, CR_FD_FDINFO), &fe))
+ if (!can_dump_unix_sk(sk))
goto err;
if (sk->sd.already_dumped)
return 0;
- ue.id = sk->sd.ino;
+ ue.id = id;
+ ue.ino = sk->sd.ino;
ue.type = sk->type;
ue.state = sk->state;
ue.namelen = sk->namelen;
@@ -141,7 +138,7 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
peer = (struct unix_sk_desc *)lookup_socket(ue.peer);
if (!peer) {
pr_err("Unix socket %#x without peer %#x\n",
- ue.id, ue.peer);
+ ue.ino, ue.peer);
goto err;
}
@@ -149,10 +146,10 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
* Peer should have us as peer or have a name by which
* we can access one.
*/
- if (peer->peer_ino != ue.id) {
+ if (peer->peer_ino != ue.ino) {
if (!peer->name) {
pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n",
- ue.id, ue.peer, peer->peer_ino, peer->name);
+ ue.ino, ue.peer, peer->peer_ino, peer->name);
goto err;
}
@@ -175,23 +172,23 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
* not now, just to reduce size of dump files.
*/
- e = lookup_unix_listen_icons(ue.id);
+ e = lookup_unix_listen_icons(ue.ino);
if (!e) {
- pr_err("Dangling in-flight connection %d\n", ue.id);
+ pr_err("Dangling in-flight connection %d\n", ue.ino);
goto err;
}
/* e->sk_desc is _never_ NULL */
if (e->sk_desc->state != TCP_LISTEN) {
pr_err("In-flight connection on "
- "non-listening socket %d\n", ue.id);
+ "non-listening socket %d\n", ue.ino);
goto err;
}
ue.peer = e->sk_desc->sd.ino;
pr_debug("\t\tFixed inflight socket %#x peer %#x)\n",
- ue.id, ue.peer);
+ ue.ino, ue.peer);
}
if (dump_socket_opts(lfd, &ue.opts))
@@ -219,6 +216,17 @@ err:
return -1;
}
+static const struct fdtype_ops unix_dump_ops = {
+ .type = FDINFO_UNIXSK,
+ .make_gen_id = make_gen_id,
+ .dump = dump_one_unix_fd,
+};
+
+int dump_one_unix(struct fd_parms *p, int lfd, const struct cr_fdset *set)
+{
+ return do_dump_gen_file(p, lfd, &unix_dump_ops, set);
+}
+
static int unix_collect_one(const struct unix_diag_msg *m,
struct rtattr **tb)
{
@@ -384,7 +392,8 @@ int fix_external_unix_sockets(void)
goto err;
}
- e.id = sk->sd.ino;
+ e.id = fd_id_generate_special();
+ e.ino = sk->sd.ino;
e.type = SOCK_DGRAM;
e.state = TCP_LISTEN;
e.namelen = sk->namelen;
@@ -419,11 +428,16 @@ struct unix_sk_info {
#define USK_PAIR_MASTER 0x1
#define USK_PAIR_SLAVE 0x2
-static struct unix_sk_info *find_unix_sk(int id)
+static int find_unix_sk_cb(struct file_desc *d, void *p)
{
- struct file_desc *d;
+ struct unix_sk_info *ui = container_of(d, struct unix_sk_info, d);
+ return ui->ue.ino == (u32)(long)p;
+}
- d = find_file_desc_raw(FDINFO_UNIXSK, id);
+static struct unix_sk_info *find_unix_sk(int ino)
+{
+ struct file_desc *d;
+ d = find_file_desc_slow_by(FDINFO_UNIXSK, (void *)(long)ino, find_unix_sk_cb);
if (d)
return container_of(d, struct unix_sk_info, d);
return NULL;
@@ -441,8 +455,8 @@ void show_unixsk(int fd, struct cr_options *o)
if (ret <= 0)
goto out;
- pr_msg("id 0x%8x type %s state %s namelen %4d backlog %4d peer 0x%8x flags 0x%2x uflags 0x%2x",
- ue.id, sktype2s(ue.type), skstate2s(ue.state),
+ pr_msg("id 0x%8x ino 0x%8x type %s state %s namelen %4d backlog %4d peer 0x%8x flags 0x%2x uflags 0x%2x",
+ ue.id, ue.ino, sktype2s(ue.type), skstate2s(ue.state),
ue.namelen, ue.backlog, ue.peer, ue.flags, ue.uflags);
if (ue.namelen) {
@@ -501,7 +515,7 @@ int run_unix_connections(void)
struct fdinfo_list_entry *fle;
struct sockaddr_un addr;
- pr_info("\tConnect %#x to %#x\n", ui->ue.id, peer->ue.id);
+ pr_info("\tConnect %#x to %#x\n", ui->ue.ino, peer->ue.ino);
fle = file_master(&ui->d);
@@ -518,7 +532,7 @@ try_again:
goto try_again; /* FIXME use futex waiters */
}
- pr_perror("Can't connect %#x socket", ui->ue.id);
+ pr_perror("Can't connect %#x socket", ui->ue.ino);
return -1;
}
@@ -579,8 +593,8 @@ static int open_unixsk_pair_master(struct unix_sk_info *ui)
struct unix_sk_info *peer = ui->peer;
struct fdinfo_list_entry *fle;
- pr_info("Opening pair master (id %#x peer %#x)\n",
- ui->ue.id, ui->ue.peer);
+ pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
+ ui->ue.id, ui->ue.ino, ui->ue.peer);
if (socketpair(PF_UNIX, ui->ue.type, 0, sk) < 0) {
pr_perror("Can't make socketpair");
@@ -623,8 +637,8 @@ static int open_unixsk_pair_slave(struct unix_sk_info *ui)
fle = file_master(&ui->d);
- pr_info("Opening pair slave (id %#x peer %#x) on %d\n",
- ui->ue.id, ui->ue.peer, fle->fe.fd);
+ pr_info("Opening pair slave (id %#x ino %#x peer %#x) on %d\n",
+ ui->ue.id, ui->ue.ino, ui->ue.peer, fle->fe.fd);
sk = recv_fd(fle->fe.fd);
if (sk < 0) {
@@ -649,8 +663,8 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
{
int sk;
- pr_info("Opening standalone socket (id %#x peer %#x)\n",
- ui->ue.id, ui->ue.peer);
+ pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
+ ui->ue.id, ui->ue.ino, ui->ue.peer);
sk = socket(PF_UNIX, ui->ue.type, 0);
if (sk < 0) {
@@ -662,7 +676,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
return -1;
if (ui->ue.state == TCP_LISTEN) {
- pr_info("\tPutting %#x into listen state\n", ui->ue.id);
+ pr_info("\tPutting %#x into listen state\n", ui->ue.ino);
if (listen(sk, ui->ue.backlog) < 0) {
pr_perror("Can't make usk listen");
return -1;
@@ -675,7 +689,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
return -1;
} else if (ui->peer) {
- pr_info("\tWill connect %#x to %#x later\n", ui->ue.id, ui->ue.peer);
+ pr_info("\tWill connect %#x to %#x later\n", ui->ue.ino, ui->ue.peer);
if (schedule_conn_job(ui))
return -1;
}
@@ -758,7 +772,7 @@ int collect_unix_sockets(void)
ui->peer = NULL;
ui->flags = 0;
- pr_info(" `- Got 0x%x peer 0x%x\n", ui->ue.id, ui->ue.peer);
+ pr_info(" `- Got 0x%x peer 0x%x\n", ui->ue.ino, ui->ue.peer);
file_desc_add(&ui->d, ui->ue.id, &unix_desc_ops);
list_add_tail(&ui->list, &unix_sockets);
}
@@ -792,7 +806,7 @@ int resolve_unix_peers(void)
if (!peer) {
pr_err("FATAL: Peer %#x unresolved for %#x\n",
- ui->ue.peer, ui->ue.id);
+ ui->ue.peer, ui->ue.ino);
return -1;
}
@@ -800,7 +814,7 @@ int resolve_unix_peers(void)
if (ui == peer)
/* socket connected to self %) */
continue;
- if (peer->ue.peer != ui->ue.id)
+ if (peer->ue.peer != ui->ue.ino)
continue;
/* socketpair or interconnected sockets */
@@ -830,8 +844,8 @@ int resolve_unix_peers(void)
list_for_each_entry(ui, &unix_sockets, list) {
struct fdinfo_list_entry *fle;
- pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue.id, ui->ue.peer,
- ui->peer ? ui->peer->ue.id : 0, ui->flags);
+ pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue.ino, ui->ue.peer,
+ ui->peer ? ui->peer->ue.ino : 0, ui->flags);
list_for_each_entry(fle, &ui->d.fd_info_head, desc_list)
pr_info("\t\tfd %d in pid %d\n",
fle->fe.fd, fle->pid);
diff --git a/sockets.c b/sockets.c
index 260e941..d9732c1 100644
--- a/sockets.c
+++ b/sockets.c
@@ -42,7 +42,7 @@ static char buf[4096];
static struct socket_desc *sockets[SK_HASH_SIZE];
-struct socket_desc *lookup_socket(int ino)
+static struct socket_desc *__lookup_socket(int ino)
{
struct socket_desc *sd;
@@ -52,6 +52,16 @@ struct socket_desc *lookup_socket(int ino)
return NULL;
}
+struct socket_desc *lookup_socket(int ino)
+{
+ struct socket_desc *sk;
+
+ sk = __lookup_socket(ino);
+ if (!sk)
+ pr_err("Uncollected socket 0x%8x\n", ino);
+ return sk;
+}
+
int sk_collect_one(int ino, int family, struct socket_desc *d)
{
struct socket_desc **chain;
@@ -125,16 +135,13 @@ int dump_socket_opts(int sk, struct sk_opts_entry *soe)
int dump_socket(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset)
{
struct socket_desc *sk;
-
sk = lookup_socket(p->stat.st_ino);
- if (!sk) {
- pr_err("Uncollected socket 0x%8x\n", (int)p->stat.st_ino);
+ if (!sk)
return -1;
- }
switch (sk->family) {
case AF_UNIX:
- return dump_one_unix(sk, p, lfd, cr_fdset);
+ return dump_one_unix(p, lfd, cr_fdset);
case AF_INET:
case AF_INET6:
return dump_one_inet(sk, p, lfd, cr_fdset);
--
1.7.7.6
More information about the CRIU
mailing list