[CRIU] [PATCH 02/10] unux: postpone dumping sockets
Andrey Vagin
avagin at openvz.org
Wed Dec 18 03:36:31 PST 2013
Unix sockets are dumped, when a peer socket is found.
We are going to dump external sockets with help plugins. For the we need
to set the USK_CALLBACK flags in unix entry. Currently a socket is
dumped immediately when it's transfered, but we can be sure that a
socket is not external, only when we have its peer.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
sk-unix.c | 163 +++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 103 insertions(+), 60 deletions(-)
diff --git a/sk-unix.c b/sk-unix.c
index da65368..f46546d 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -49,6 +49,10 @@ struct unix_sk_desc {
int fd;
struct list_head peer_list;
struct list_head peer_node;
+
+ u32 id;
+ unsigned int flags;
+ FownEntry fown;
};
static LIST_HEAD(unix_sockets);
@@ -123,37 +127,26 @@ static int can_dump_unix_sk(const struct unix_sk_desc *sk)
return 1;
}
-static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
+static int write_unix_entry(struct unix_sk_desc *sk,
+ struct unix_sk_desc *peer, unsigned int uflags)
{
- struct unix_sk_desc *sk, *peer;
UnixSkEntry ue = UNIX_SK_ENTRY__INIT;
SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
FilePermsEntry perms = FILE_PERMS_ENTRY__INIT;
- sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino, PF_UNIX, 0);
- if (IS_ERR_OR_NULL(sk)) {
- pr_err("Unix socket %#x not found\n", (int)p->stat.st_ino);
- goto err;
- }
-
- if (!can_dump_unix_sk(sk))
- goto err;
-
- BUG_ON(sk->sd.already_dumped);
-
ue.name.len = (size_t)sk->namelen;
ue.name.data = (void *)sk->name;
- ue.id = id;
+ ue.id = sk->id;
ue.ino = sk->sd.ino;
ue.type = sk->type;
ue.state = sk->state;
- ue.flags = p->flags;
+ ue.flags = sk->flags;
ue.backlog = sk->wqlen;
ue.peer = sk->peer_ino;
- ue.fown = (FownEntry *)&p->fown;
+ ue.fown = &sk->fown;
ue.opts = &skopts;
- ue.uflags = 0;
+ ue.uflags = uflags;
/*
* Check if this socket is connected to criu service.
@@ -176,43 +169,6 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
sk_encode_shutdown(&ue, sk->shutdown);
if (ue.peer) {
- peer = (struct unix_sk_desc *)lookup_socket(ue.peer, PF_UNIX, 0);
- if (IS_ERR_OR_NULL(peer)) {
- pr_err("Unix socket %#x without peer %#x\n",
- ue.ino, ue.peer);
- goto err;
- }
-
- /*
- * Peer should have us as peer or have a name by which
- * we can access one.
- */
- if (peer->peer_ino != ue.ino) {
- if (!peer->name) {
- pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n",
- ue.ino, ue.peer, peer->peer_ino, peer->name);
- goto err;
- }
- }
-
- /*
- * It can be external socket, so we defer dumping
- * until all sockets the program owns are processed.
- */
- if (!peer->sd.already_dumped) {
- if (list_empty(&peer->list)) {
- show_one_unix("Add a peer", peer);
- list_add_tail(&peer->list, &unix_sockets);
- }
-
- list_add(&sk->peer_node, &peer->peer_list);
- sk->fd = dup(lfd);
- if (sk->fd < 0) {
- pr_perror("Unable to dup(%d)", lfd);
- goto err;
- }
- }
-
if ((ue.type != SOCK_DGRAM) && (
((ue.shutdown == SK_SHUTDOWN__READ) &&
(peer->shutdown != SK_SHUTDOWN__WRITE)) ||
@@ -270,12 +226,85 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
ue.ino, ue.peer);
}
dump:
- if (dump_socket_opts(lfd, &skopts))
+ if (dump_socket_opts(sk->fd, &skopts))
goto err;
if (pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), &ue, PB_UNIX_SK))
goto err;
+ show_one_unix_img("Dumped", &ue);
+ release_skopts(&skopts);
+ return 0;
+err:
+ release_skopts(&skopts);
+ return -1;
+}
+
+static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
+{
+ struct unix_sk_desc *sk, *peer = NULL;
+ unsigned int ino;
+
+ sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino, PF_UNIX, 0);
+ if (IS_ERR_OR_NULL(sk)) {
+ pr_err("Unix socket %#x not found\n", (int)p->stat.st_ino);
+ goto err;
+ }
+
+ if (!can_dump_unix_sk(sk))
+ goto err;
+
+ BUG_ON(sk->sd.already_dumped);
+
+ ino = sk->sd.ino;
+ sk->id = id;
+ sk->fown = p->fown;
+ sk->fd = lfd;
+
+ if (sk->peer_ino) {
+ peer = (struct unix_sk_desc *)lookup_socket(sk->peer_ino, PF_UNIX, 0);
+ if (IS_ERR_OR_NULL(peer)) {
+ pr_err("Unix socket %#x without peer %#x\n",
+ ino, sk->peer_ino);
+ goto err;
+ }
+
+ /*
+ * Peer should have us as peer or have a name by which
+ * we can access one.
+ */
+ if (peer->peer_ino != ino) {
+ if (!peer->name) {
+ pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n",
+ ino, sk->peer_ino, peer->peer_ino, peer->name);
+ goto err;
+ }
+ }
+
+ /*
+ * It can be external socket, so we defer dumping
+ * until all sockets the program owns are processed.
+ */
+ if (!peer->sd.already_dumped) {
+ if (list_empty(&peer->list)) {
+ show_one_unix("Add a peer", peer);
+ list_add_tail(&peer->list, &unix_sockets);
+ }
+
+ list_add(&sk->peer_node, &peer->peer_list);
+ sk->fd = dup(lfd);
+ if (sk->fd < 0) {
+ pr_perror("Unable to dup(%d)", lfd);
+ goto err;
+ }
+ pr_err("\n");
+ goto dump_queue;
+ }
+ }
+
+ if (write_unix_entry(sk, peer, 0))
+ goto err;
+dump_queue:
/*
* If a stream listening socket has non-zero rqueue, this
* means there are in-flight connections waiting to get
@@ -284,13 +313,11 @@ dump:
*/
if (sk->rqlen != 0 && !(sk->type == SOCK_STREAM &&
sk->state == TCP_LISTEN))
- if (dump_sk_queue(lfd, ue.id))
+ if (dump_sk_queue(lfd, id))
goto err;
pr_info("Dumping unix socket at %d\n", p->fd);
show_one_unix("Dumping", sk);
- show_one_unix_img("Dumped", &ue);
- release_skopts(&skopts);
list_del_init(&sk->list);
sk->sd.already_dumped = 1;
@@ -298,14 +325,14 @@ dump:
while (!list_empty(&sk->peer_list)) {
struct unix_sk_desc *psk;
psk = list_first_entry(&sk->peer_list, struct unix_sk_desc, peer_node);
+ if (write_unix_entry(psk, sk, 0))
+ goto err;
close_safe(&psk->fd);
list_del(&psk->peer_node);
}
return 0;
-
err:
- release_skopts(&skopts);
return -1;
}
@@ -473,6 +500,19 @@ int unix_receive_one(struct nlmsghdr *h, void *arg)
return unix_collect_one(m, tb);
}
+static int dump_external_sockets(struct unix_sk_desc *peer)
+{
+ struct unix_sk_desc *sk;
+
+ list_for_each_entry(sk, &peer->peer_list, peer_node) {
+ if (write_unix_entry(sk, peer, 0))
+ return -1;
+ close_safe(&sk->fd);
+ }
+
+ return 0;
+}
+
int fix_external_unix_sockets(void)
{
struct unix_sk_desc *sk;
@@ -501,6 +541,9 @@ int fix_external_unix_sockets(void)
goto err;
}
+ if (dump_external_sockets(sk))
+ goto err;
+
e.id = fd_id_generate_special();
e.ino = sk->sd.ino;
e.type = SOCK_DGRAM;
--
1.8.3.1
More information about the CRIU
mailing list