[CRIU] [PATCH] parasite/mem: unprotect VMAs if page dumping failed

Dmitry Safonov dsafonov at virtuozzo.com
Mon Mar 28 12:38:51 PDT 2016


Before patch parasite_dump_pages_seized tried to unprotect pages
by parasite command. But it had two issues:
1. parasite doesn't wait any command, except PARASITE_CMD_FINI after
   it failed;
2. return code for parasite_dump_pages_seized was not set according
   to __parasite_dump_pages_seized failure.

During fixing compatible patches set troubles, I saw the following picture,
which the patch fixes:

(00.010992) Sent msg to daemon 8 0 0
pie: __fetched msg: 8 0 0
(00.010995) Wait for ack 8 on daemon socket
pie: Error (pie/parasite.c:82): Can't splice pages to pipe (0/16)
pie: __sent ack msg: 8 8 -1
pie: Error (pie/parasite.c:721): Close the control socket for writing
>
pie: Daemon waits for command
(00.011023) Fetched ack: 8 8 -1
(00.011025) Error (parasite-syscall.c:345): Command 8 for daemon failed with -1
(00.011131) page-pipe: Killing page pipe
(00.011150) ----------------------------------------
(00.011151) Error (mem.c:375): Can't dump page with parasite
(00.011155) Sent msg to daemon 7 0 0
(00.011156) Wait for ack 7 on daemon socket
pie: __fetched msg: 7 0 0
(00.011157) Error (parasite-syscall.c:318): Message reply from daemon is trimmed (12/0)
pie: Error (pie/parasite.c:665): Command rejected
(00.011159) Error (mem.c:379): Can't rollback unprotected vmas with parasite
pie: Daemon waits for command

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/mem.c          |  4 +++-
 criu/pie/parasite.c | 21 ++++++++++++++++++++-
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/criu/mem.c b/criu/mem.c
index 5a7b5bb96ba9..a8e3953769d0 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -371,8 +371,10 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl,
 	}
 
 	ret = __parasite_dump_pages_seized(ctl, pargs, vma_area_list, pp);
-	if (ret)
+	if (ret) {
 		pr_err("Can't dump page with parasite\n");
+		ret = -1;
+	}
 
 	pargs->add_prot = 0;
 	if (parasite_execute_daemon(PARASITE_CMD_MPROTECT_VMAS, ctl)) {
diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
index 9d822bb2a93a..b1808bc7ed5c 100644
--- a/criu/pie/parasite.c
+++ b/criu/pie/parasite.c
@@ -644,6 +644,25 @@ static int fini()
 	return -1;
 }
 
+static inline bool after_fail_cmd_allowed(struct ctl_msg *m, void *args)
+{
+	if (m->cmd == PARASITE_CMD_FINI)
+		return true;
+
+	if (m->cmd == PARASITE_CMD_MPROTECT_VMAS) {
+		struct parasite_dump_pages_args *dp_args = args;
+
+		/*
+		 * We should allow parasite to unprotect VMAs back
+		 * from PROT_READ after failed pages dumping.
+		 */
+		if (!dp_args->add_prot)
+			return true;
+	}
+
+	return false;
+}
+
 static noinline __used int noinline parasite_daemon(void *args)
 {
 	struct ctl_msg m = { };
@@ -661,7 +680,7 @@ static noinline __used int noinline parasite_daemon(void *args)
 		if (__parasite_daemon_wait_msg(&m))
 			break;
 
-		if (ret && m.cmd != PARASITE_CMD_FINI) {
+		if (ret && !after_fail_cmd_allowed(&m, args)) {
 			pr_err("Command rejected\n");
 			continue;
 		}
-- 
2.7.4



More information about the CRIU mailing list