Commit c26b68dc authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

sockets, unix: Use general machnism for checkpoint/restore v2

Use fdtype_ops facility to c/r unix sockets.

v2
 - BUG_ON added in dump_one_unix_fd if socket
   is already dumped since we never should dump
   same socket several times
 - The order of restore remains as it was before,
   the lookup is done via socket inode numbers
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 41195598
...@@ -179,6 +179,7 @@ struct sk_opts_entry { ...@@ -179,6 +179,7 @@ struct sk_opts_entry {
struct unix_sk_entry { struct unix_sk_entry {
u32 id; u32 id;
u32 ino;
u8 type; u8 type;
u8 state; u8 state;
u8 namelen; /* fits UNIX_PATH_MAX */ u8 namelen; /* fits UNIX_PATH_MAX */
......
...@@ -49,8 +49,7 @@ extern struct socket_desc *lookup_socket(int ino); ...@@ -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, extern int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p,
int lfd, const struct cr_fdset *cr_fdset); int lfd, const struct cr_fdset *cr_fdset);
extern int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p, extern int dump_one_unix(struct fd_parms *p, int lfd, const struct cr_fdset *set);
int lfd, const struct cr_fdset *cr_fdset);
extern int inet_collect_one(struct nlmsghdr *h, int family, int type, int proto); extern int inet_collect_one(struct nlmsghdr *h, int family, int type, int proto);
extern int unix_receive_one(struct nlmsghdr *h); extern int unix_receive_one(struct nlmsghdr *h);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "crtools.h" #include "crtools.h"
#include "unix_diag.h" #include "unix_diag.h"
#include "files.h" #include "files.h"
#include "file-ids.h"
#include "image.h" #include "image.h"
#include "log.h" #include "log.h"
#include "util.h" #include "util.h"
...@@ -73,8 +74,8 @@ static void show_one_unix(char *act, const struct unix_sk_desc *sk) ...@@ -73,8 +74,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) 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", 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->peer, e->type, e->state, e->namelen); 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) static int can_dump_unix_sk(const struct unix_sk_desc *sk)
...@@ -105,28 +106,22 @@ static int can_dump_unix_sk(const struct unix_sk_desc *sk) ...@@ -105,28 +106,22 @@ static int can_dump_unix_sk(const struct unix_sk_desc *sk)
return 1; return 1;
} }
int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p, static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
int lfd, const struct cr_fdset *cr_fdset)
{ {
struct unix_sk_desc *sk = (struct unix_sk_desc *)_sk; struct unix_sk_desc *sk;
struct fdinfo_entry fe;
struct unix_sk_entry ue; 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; goto err;
fe.fd = p->fd; if (!can_dump_unix_sk(sk))
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))
goto err; goto err;
if (sk->sd.already_dumped) BUG_ON(sk->sd.already_dumped);
return 0;
ue.id = sk->sd.ino; ue.id = id;
ue.ino = sk->sd.ino;
ue.type = sk->type; ue.type = sk->type;
ue.state = sk->state; ue.state = sk->state;
ue.namelen = sk->namelen; ue.namelen = sk->namelen;
...@@ -142,7 +137,7 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p, ...@@ -142,7 +137,7 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
peer = (struct unix_sk_desc *)lookup_socket(ue.peer); peer = (struct unix_sk_desc *)lookup_socket(ue.peer);
if (!peer) { if (!peer) {
pr_err("Unix socket %#x without peer %#x\n", pr_err("Unix socket %#x without peer %#x\n",
ue.id, ue.peer); ue.ino, ue.peer);
goto err; goto err;
} }
...@@ -150,10 +145,10 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p, ...@@ -150,10 +145,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 * Peer should have us as peer or have a name by which
* we can access one. * we can access one.
*/ */
if (peer->peer_ino != ue.id) { if (peer->peer_ino != ue.ino) {
if (!peer->name) { if (!peer->name) {
pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n", 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; goto err;
} }
...@@ -176,23 +171,23 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p, ...@@ -176,23 +171,23 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
* not now, just to reduce size of dump files. * 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) { if (!e) {
pr_err("Dangling in-flight connection %d\n", ue.id); pr_err("Dangling in-flight connection %d\n", ue.ino);
goto err; goto err;
} }
/* e->sk_desc is _never_ NULL */ /* e->sk_desc is _never_ NULL */
if (e->sk_desc->state != TCP_LISTEN) { if (e->sk_desc->state != TCP_LISTEN) {
pr_err("In-flight connection on " pr_err("In-flight connection on "
"non-listening socket %d\n", ue.id); "non-listening socket %d\n", ue.ino);
goto err; goto err;
} }
ue.peer = e->sk_desc->sd.ino; ue.peer = e->sk_desc->sd.ino;
pr_debug("\t\tFixed inflight socket %#x peer %#x)\n", 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)) if (dump_socket_opts(lfd, &ue.opts))
...@@ -220,6 +215,17 @@ err: ...@@ -220,6 +215,17 @@ err:
return -1; 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, static int unix_collect_one(const struct unix_diag_msg *m,
struct rtattr **tb) struct rtattr **tb)
{ {
...@@ -384,7 +390,8 @@ int fix_external_unix_sockets(void) ...@@ -384,7 +390,8 @@ int fix_external_unix_sockets(void)
goto err; goto err;
} }
e.id = sk->sd.ino; e.id = fd_id_generate_special();
e.ino = sk->sd.ino;
e.type = SOCK_DGRAM; e.type = SOCK_DGRAM;
e.state = TCP_LISTEN; e.state = TCP_LISTEN;
e.namelen = sk->namelen; e.namelen = sk->namelen;
...@@ -419,13 +426,15 @@ struct unix_sk_info { ...@@ -419,13 +426,15 @@ struct unix_sk_info {
#define USK_PAIR_MASTER 0x1 #define USK_PAIR_MASTER 0x1
#define USK_PAIR_SLAVE 0x2 #define USK_PAIR_SLAVE 0x2
static struct unix_sk_info *find_unix_sk(int id) static struct unix_sk_info *find_unix_sk_by_ino(int ino)
{ {
struct file_desc *d; struct unix_sk_info *ui;
list_for_each_entry(ui, &unix_sockets, list) {
if (ui->ue.ino == ino)
return ui;
}
d = find_file_desc_raw(FDINFO_UNIXSK, id);
if (d)
return container_of(d, struct unix_sk_info, d);
return NULL; return NULL;
} }
...@@ -441,8 +450,8 @@ void show_unixsk(int fd, struct cr_options *o) ...@@ -441,8 +450,8 @@ void show_unixsk(int fd, struct cr_options *o)
if (ret <= 0) if (ret <= 0)
goto out; goto out;
pr_msg("id 0x%8x type %s state %s namelen %4d backlog %4d peer 0x%8x flags 0x%2x uflags 0x%2x", 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, sktype2s(ue.type), skstate2s(ue.state), ue.id, ue.ino, sktype2s(ue.type), skstate2s(ue.state),
ue.namelen, ue.backlog, ue.peer, ue.flags, ue.uflags); ue.namelen, ue.backlog, ue.peer, ue.flags, ue.uflags);
if (ue.namelen) { if (ue.namelen) {
...@@ -501,7 +510,7 @@ int run_unix_connections(void) ...@@ -501,7 +510,7 @@ int run_unix_connections(void)
struct fdinfo_list_entry *fle; struct fdinfo_list_entry *fle;
struct sockaddr_un addr; 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); fle = file_master(&ui->d);
...@@ -518,7 +527,7 @@ try_again: ...@@ -518,7 +527,7 @@ try_again:
goto try_again; /* FIXME use futex waiters */ 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; return -1;
} }
...@@ -579,8 +588,8 @@ static int open_unixsk_pair_master(struct unix_sk_info *ui) ...@@ -579,8 +588,8 @@ static int open_unixsk_pair_master(struct unix_sk_info *ui)
struct unix_sk_info *peer = ui->peer; struct unix_sk_info *peer = ui->peer;
struct fdinfo_list_entry *fle; struct fdinfo_list_entry *fle;
pr_info("Opening pair master (id %#x peer %#x)\n", pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
ui->ue.id, ui->ue.peer); ui->ue.id, ui->ue.ino, ui->ue.peer);
if (socketpair(PF_UNIX, ui->ue.type, 0, sk) < 0) { if (socketpair(PF_UNIX, ui->ue.type, 0, sk) < 0) {
pr_perror("Can't make socketpair"); pr_perror("Can't make socketpair");
...@@ -623,8 +632,8 @@ static int open_unixsk_pair_slave(struct unix_sk_info *ui) ...@@ -623,8 +632,8 @@ static int open_unixsk_pair_slave(struct unix_sk_info *ui)
fle = file_master(&ui->d); fle = file_master(&ui->d);
pr_info("Opening pair slave (id %#x peer %#x) on %d\n", pr_info("Opening pair slave (id %#x ino %#x peer %#x) on %d\n",
ui->ue.id, ui->ue.peer, fle->fe.fd); ui->ue.id, ui->ue.ino, ui->ue.peer, fle->fe.fd);
sk = recv_fd(fle->fe.fd); sk = recv_fd(fle->fe.fd);
if (sk < 0) { if (sk < 0) {
...@@ -649,8 +658,8 @@ static int open_unixsk_standalone(struct unix_sk_info *ui) ...@@ -649,8 +658,8 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
{ {
int sk; int sk;
pr_info("Opening standalone socket (id %#x peer %#x)\n", pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
ui->ue.id, ui->ue.peer); ui->ue.id, ui->ue.ino, ui->ue.peer);
sk = socket(PF_UNIX, ui->ue.type, 0); sk = socket(PF_UNIX, ui->ue.type, 0);
if (sk < 0) { if (sk < 0) {
...@@ -662,7 +671,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui) ...@@ -662,7 +671,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
return -1; return -1;
if (ui->ue.state == TCP_LISTEN) { 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) { if (listen(sk, ui->ue.backlog) < 0) {
pr_perror("Can't make usk listen"); pr_perror("Can't make usk listen");
return -1; return -1;
...@@ -675,7 +684,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui) ...@@ -675,7 +684,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
return -1; return -1;
} else if (ui->peer) { } 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)) if (schedule_conn_job(ui))
return -1; return -1;
} }
...@@ -758,7 +767,7 @@ int collect_unix_sockets(void) ...@@ -758,7 +767,7 @@ int collect_unix_sockets(void)
ui->peer = NULL; ui->peer = NULL;
ui->flags = 0; 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); file_desc_add(&ui->d, ui->ue.id, &unix_desc_ops);
list_add_tail(&ui->list, &unix_sockets); list_add_tail(&ui->list, &unix_sockets);
} }
...@@ -779,7 +788,7 @@ int resolve_unix_peers(void) ...@@ -779,7 +788,7 @@ int resolve_unix_peers(void)
if (!ui->ue.peer) if (!ui->ue.peer)
continue; continue;
peer = find_unix_sk(ui->ue.peer); peer = find_unix_sk_by_ino(ui->ue.peer);
/* /*
* Connect to external sockets requires * Connect to external sockets requires
...@@ -792,7 +801,7 @@ int resolve_unix_peers(void) ...@@ -792,7 +801,7 @@ int resolve_unix_peers(void)
if (!peer) { if (!peer) {
pr_err("FATAL: Peer %#x unresolved for %#x\n", pr_err("FATAL: Peer %#x unresolved for %#x\n",
ui->ue.peer, ui->ue.id); ui->ue.peer, ui->ue.ino);
return -1; return -1;
} }
...@@ -800,7 +809,7 @@ int resolve_unix_peers(void) ...@@ -800,7 +809,7 @@ int resolve_unix_peers(void)
if (ui == peer) if (ui == peer)
/* socket connected to self %) */ /* socket connected to self %) */
continue; continue;
if (peer->ue.peer != ui->ue.id) if (peer->ue.peer != ui->ue.ino)
continue; continue;
/* socketpair or interconnected sockets */ /* socketpair or interconnected sockets */
...@@ -830,8 +839,8 @@ int resolve_unix_peers(void) ...@@ -830,8 +839,8 @@ int resolve_unix_peers(void)
list_for_each_entry(ui, &unix_sockets, list) { list_for_each_entry(ui, &unix_sockets, list) {
struct fdinfo_list_entry *fle; struct fdinfo_list_entry *fle;
pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue.id, ui->ue.peer, pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue.ino, ui->ue.peer,
ui->peer ? ui->peer->ue.id : 0, ui->flags); ui->peer ? ui->peer->ue.ino : 0, ui->flags);
list_for_each_entry(fle, &ui->d.fd_info_head, desc_list) list_for_each_entry(fle, &ui->d.fd_info_head, desc_list)
pr_info("\t\tfd %d in pid %d\n", pr_info("\t\tfd %d in pid %d\n",
fle->fe.fd, fle->pid); fle->fe.fd, fle->pid);
......
...@@ -119,7 +119,7 @@ int dump_socket(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset) ...@@ -119,7 +119,7 @@ int dump_socket(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset)
switch (sk->family) { switch (sk->family) {
case AF_UNIX: 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_INET:
case AF_INET6: case AF_INET6:
return dump_one_inet(sk, p, lfd, cr_fdset); return dump_one_inet(sk, p, lfd, cr_fdset);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment