[CRIU] [PATCH] service: Add ability to inherit page server socket
Pavel Emelyanov
xemul at parallels.com
Mon Sep 1 13:45:03 PDT 2014
The swrk action is turning out to be a cool thing. We can
spawn criu with swrk action with some FD being open, then
ask for dump/pre-dump/page-server telling it that some
descriptor it needs is "out there".
This patch lets us specify that the page server communication
channel is already in criu's fdtable.
TODO: teach regular service to accept fd via service socket.
Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
cr-service.c | 7 +++++++
crtools.c | 1 +
include/cr_options.h | 1 +
page-xfer.c | 42 +++++++++++++++++++++++++++++++++++-------
protobuf/rpc.proto | 1 +
5 files changed, 45 insertions(+), 7 deletions(-)
diff --git a/cr-service.c b/cr-service.c
index d5a4737..9f7873b 100644
--- a/cr-service.c
+++ b/cr-service.c
@@ -278,6 +278,13 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
opts.use_page_server = true;
opts.addr = req->ps->address;
opts.ps_port = htons((short)req->ps->port);
+
+ if (req->ps->has_fd) {
+ if (!opts.swrk_restore)
+ return -1;
+
+ opts.ps_socket = req->ps->fd;
+ }
}
if (req->notify_scripts) {
diff --git a/crtools.c b/crtools.c
index fa1d375..21ca63a 100644
--- a/crtools.c
+++ b/crtools.c
@@ -52,6 +52,7 @@ void init_opts(void)
opts.cpu_cap = CPU_CAP_ALL;
opts.manage_cgroups = false;
+ opts.ps_socket = -1;
}
static int parse_ns_string(const char *ptr)
diff --git a/include/cr_options.h b/include/cr_options.h
index d715773..b603804 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -51,6 +51,7 @@ struct cr_options {
bool use_page_server;
unsigned short ps_port;
char *addr;
+ int ps_socket;
bool track_mem;
char *img_parent;
bool auto_dedup;
diff --git a/page-xfer.c b/page-xfer.c
index c71ca51..54340b1 100644
--- a/page-xfer.c
+++ b/page-xfer.c
@@ -40,6 +40,7 @@ static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, long id);
#define PS_IOV_OPEN 3
#define PS_IOV_FLUSH 0x1023
+#define PS_IOV_FLUSH_N_CLOSE 0x1024
#define PS_TYPE_BITS 8
#define PS_TYPE_MASK ((1 << PS_TYPE_BITS) - 1)
@@ -198,6 +199,7 @@ static int page_server_serve(int sk)
ret = page_server_hole(sk, &pi);
break;
case PS_IOV_FLUSH:
+ case PS_IOV_FLUSH_N_CLOSE:
{
int32_t status = 0;
@@ -220,7 +222,7 @@ static int page_server_serve(int sk)
break;
}
- if (ret)
+ if (ret || (pi.cmd == PS_IOV_FLUSH_N_CLOSE))
break;
}
@@ -254,12 +256,19 @@ static int get_sockaddr_in(struct sockaddr_in *addr)
int cr_page_server(bool daemon_mode)
{
- int sk, ask = -1, ret;
+ int sk = -1, ask = -1, ret;
struct sockaddr_in saddr, caddr;
socklen_t clen = sizeof(caddr);
up_page_ids_base();
+ if (opts.ps_socket != -1) {
+ ret = 0;
+ ask = opts.ps_socket;
+ pr_info("Re-using ps socket %d\n", ask);
+ goto no_server;
+ }
+
pr_info("Starting page server on port %u\n", (int)ntohs(opts.ps_port));
sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -281,6 +290,7 @@ int cr_page_server(bool daemon_mode)
goto out;
}
+no_server:
if (daemon_mode) {
ret = cr_daemon(1, 0);
if (ret == -1) {
@@ -298,11 +308,13 @@ int cr_page_server(bool daemon_mode)
}
}
- ret = ask = accept(sk, (struct sockaddr *)&caddr, &clen);
- if (ask < 0)
- pr_perror("Can't accept connection to server");
+ if (sk >= 0) {
+ ret = ask = accept(sk, (struct sockaddr *)&caddr, &clen);
+ if (ask < 0)
+ pr_perror("Can't accept connection to server");
- close(sk);
+ close(sk);
+ }
if (ask >= 0) {
pr_info("Accepted connection from %s:%u\n",
@@ -331,6 +343,12 @@ int connect_to_page_server(void)
if (!opts.use_page_server)
return 0;
+ if (opts.ps_socket != -1) {
+ page_server_sk = opts.ps_socket;
+ pr_info("Re-using ps socket %d\n", page_server_sk);
+ return 0;
+ }
+
pr_info("Connecting to server %s:%u\n",
opts.addr, (int)ntohs(opts.ps_port));
@@ -353,7 +371,7 @@ int connect_to_page_server(void)
int disconnect_from_page_server(void)
{
- struct page_server_iov pi = { .cmd = PS_IOV_FLUSH };
+ struct page_server_iov pi = { };
int32_t status = -1;
int ret = -1;
@@ -366,6 +384,16 @@ int disconnect_from_page_server(void)
pr_info("Disconnect from the page server %s:%u\n",
opts.addr, (int)ntohs(opts.ps_port));
+ if (opts.ps_socket != -1)
+ /*
+ * The socket might not get closed (held by
+ * the parent process) so we must order the
+ * page-server to terminate itself.
+ */
+ pi.cmd = PS_IOV_FLUSH_N_CLOSE;
+ else
+ pi.cmd = PS_IOV_FLUSH;
+
if (write(page_server_sk, &pi, sizeof(pi)) != sizeof(pi)) {
pr_perror("Can't write the fini command to server");
goto out;
diff --git a/protobuf/rpc.proto b/protobuf/rpc.proto
index 46fba60..e9a74b4 100644
--- a/protobuf/rpc.proto
+++ b/protobuf/rpc.proto
@@ -2,6 +2,7 @@ message criu_page_server_info {
optional string address = 1;
optional int32 port = 2;
optional int32 pid = 3;
+ optional int32 fd = 4;
}
message criu_veth_pair {
--
1.8.4.2
More information about the CRIU
mailing list