[CRIU] [PATCH] page-server: check that all data have been accepted
Andrey Vagin
avagin at openvz.org
Wed Aug 7 09:08:28 EDT 2013
Currently criu sends data to the page server, but it doesn't get any
feedback, so it can't be sure that all data have been accepted.
This patch adds a flush command, which requires an answer from the page
server. This command is sent before disconnecting.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-dump.c | 6 ++++++
include/page-xfer.h | 1 +
page-xfer.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/cr-dump.c b/cr-dump.c
index 49677db..2de0311 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1608,6 +1608,9 @@ int cr_pre_dump_tasks(pid_t pid)
ret = 0;
err:
+ if (disconnect_from_page_server())
+ ret = -1;
+
pstree_switch_state(root_item,
ret ? TASK_ALIVE : opts.final_state);
free_pstree(root_item);
@@ -1726,6 +1729,9 @@ int cr_dump_tasks(pid_t pid)
fd_id_show_tree();
err:
+ if (disconnect_from_page_server())
+ ret = -1;
+
close_cr_fdset(&glob_fdset);
if (!ret) {
diff --git a/include/page-xfer.h b/include/page-xfer.h
index 67a59ec..7d2284a 100644
--- a/include/page-xfer.h
+++ b/include/page-xfer.h
@@ -30,4 +30,5 @@ struct page_pipe;
int page_xfer_dump_pages(struct page_xfer *, struct page_pipe *,
unsigned long off);
int connect_to_page_server(void);
+int disconnect_from_page_server(void);
#endif
diff --git a/page-xfer.c b/page-xfer.c
index 4efa20c..6098b92 100644
--- a/page-xfer.c
+++ b/page-xfer.c
@@ -21,6 +21,8 @@ struct page_server_iov {
#define PS_IOV_HOLE 2
#define PS_IOV_OPEN 3
+#define PS_IOV_FLUSH 0x1023
+
#define PS_TYPE_BITS 8
#define PS_TYPE_MASK ((1 << PS_TYPE_BITS) - 1)
@@ -145,6 +147,7 @@ static int page_server_hole(int sk, struct page_server_iov *pi)
static int page_server_serve(int sk)
{
int ret = -1;
+ bool flushed = false;
if (pipe(cxfer.p)) {
pr_perror("Can't make pipe for xfer");
@@ -168,6 +171,8 @@ static int page_server_serve(int sk)
break;
}
+ flushed = false;
+
switch (pi.cmd) {
case PS_IOV_OPEN:
ret = page_server_open(&pi);
@@ -178,6 +183,22 @@ static int page_server_serve(int sk)
case PS_IOV_HOLE:
ret = page_server_hole(sk, &pi);
break;
+ case PS_IOV_FLUSH:
+ {
+ int32_t status = 0;
+
+ /*
+ * An answer must be sent back to inform another side,
+ * that all data were received
+ */
+ if (write(sk, &status, sizeof(status)) != sizeof(status)) {
+ pr_perror("Can't send the final package");
+ ret = -1;
+ }
+
+ flushed = true;
+ break;
+ }
default:
pr_err("Unknown command %u\n", pi.cmd);
ret = -1;
@@ -188,6 +209,11 @@ static int page_server_serve(int sk)
break;
}
+ if (!flushed) {
+ pr_err("The data were not flushed");
+ ret = -1;
+ }
+
page_server_close();
pr_info("Session over\n");
@@ -273,6 +299,37 @@ int connect_to_page_server(void)
return 0;
}
+int disconnect_from_page_server(void)
+{
+ struct page_server_iov pi = { .cmd = PS_IOV_FLUSH };
+ int32_t status = -1;
+ int ret = -1;
+
+ if (!opts.use_page_server)
+ return 0;
+
+ if (page_server_sk == -1)
+ return 0;
+
+ pr_info("Disconnect from the page server %s:%u\n",
+ inet_ntoa(opts.ps_addr.sin_addr),
+ (int)ntohs(opts.ps_addr.sin_port));
+ if (write(page_server_sk, &pi, sizeof(pi)) != sizeof(pi)) {
+ pr_perror("Can't write the fini command to server");
+ goto out;
+ }
+
+ if (read(page_server_sk, &status, sizeof(status)) != sizeof(status)) {
+ pr_perror("The page server doesn't answer");
+ goto out;
+ }
+
+ ret = 0;
+out:
+ close_safe(&page_server_sk);
+ return ret ? : status;
+}
+
static int write_pagemap_to_server(struct page_xfer *xfer,
struct iovec *iov)
{
--
1.8.3.1
More information about the CRIU
mailing list