From d74073a593467b19c01c79905aabaec803a85b7e Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Fri, 13 Sep 2013 13:44:15 +0400 Subject: [PATCH] unix: Handle service socket on dump and restore Service connection is actually an 'external' one from unix sockets engine POV, but we don't want to dump it as such. Thus, we explicitly find one and dump it as half-closed connection. On restore we push an artificial message into it to report to the program that the dump-request was served, but the program is restored. Signed-off-by: Ruslan Kuprieiev Signed-off-by: Pavel Emelyanov --- include/image.h | 1 + sk-unix.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/image.h b/include/image.h index 1968908bb..37203cb2b 100644 --- a/include/image.h +++ b/include/image.h @@ -31,6 +31,7 @@ */ #define USK_EXTERN (1 << 0) +#define USK_SERVICE (1 << 1) #define VMA_AREA_NONE (0 << 0) #define VMA_AREA_REGULAR (1 << 0) /* Dumpable area */ diff --git a/sk-unix.c b/sk-unix.c index 2e43fad33..74636d4bd 100644 --- a/sk-unix.c +++ b/sk-unix.c @@ -21,6 +21,7 @@ #include "sockets.h" #include "sk-queue.h" #include "mount.h" +#include "cr-service.h" #include "protobuf.h" #include "protobuf/sk-unix.pb-c.h" @@ -89,8 +90,14 @@ static void show_one_unix_img(const char *act, const UnixSkEntry *e) static int can_dump_unix_sk(const struct unix_sk_desc *sk) { + /* + * The last case in this "if" is seqpacket socket, + * that is connected to cr_service. We will dump + * it properly below. + */ if (sk->type != SOCK_STREAM && - sk->type != SOCK_DGRAM) { + sk->type != SOCK_DGRAM && + sk->peer_ino != cr_service_client->sk_ino) { pr_err("Only stream/dgram sockets for now\n"); return 0; } @@ -138,6 +145,16 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p) ue.opts = &skopts; ue.uflags = 0; + /* + * Check if this socket is connected to criu service. + * Dump it like closed one and mark it for restore. + */ + if (ue.peer == cr_service_client->sk_ino) { + ue.state = TCP_CLOSE; + ue.peer = 0; + ue.uflags |= USK_SERVICE; + } + if (sk->namelen && *sk->name) { ue.file_perms = &perms; @@ -722,7 +739,29 @@ static int open_unixsk_standalone(struct unix_sk_info *ui) pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n", ui->ue->id, ui->ue->ino, ui->ue->peer); - if ((ui->ue->state == TCP_ESTABLISHED) && !ui->ue->peer) { + /* + * Check if this socket was connected to criu service. + * If so, put response, that dumping and restoring + * was successful. + */ + if (ui->ue->uflags & USK_SERVICE) { + int sks[2]; + CriuDumpResp resp = CRIU_DUMP_RESP__INIT; + + resp.success = true; + resp.restored = true; + + if (socketpair(PF_UNIX, ui->ue->type, 0, sks)) { + pr_perror("Can't create socketpair"); + return -1; + } + + if (send_criu_dump_resp(sks[1], &resp) == -1) + return -1; + + close(sks[1]); + sk = sks[0]; + } else if ((ui->ue->state == TCP_ESTABLISHED) && !ui->ue->peer) { int ret, sks[2]; if (ui->ue->type != SOCK_STREAM) {