[v6,1/9] restore: Use pstree_pid_cmp helper in pid_rst_prio

Submitted by Cyrill Gorcunov on May 21, 2018, 8:05 p.m.

Details

Message ID 20180521200601.26297-2-gorcunov@gmail.com
State New
Series "Add support of deleted unix sockets"
Headers show

Commit Message

Cyrill Gorcunov May 21, 2018, 8:05 p.m.
The pid number is absolutely not a guarantee to
introduce order relationship into pid set because
they might be reused. Instead we should consider
parent->child relationship.

Otherwise we might get

 |  31964  31964  31964       epoll
 |    585  31964  31964           epoll
 |    586  31964  31964           epoll
 |...
 | (04.797121)    585: Error (criu/eventpoll.c:180): epoll: Unexpected state for tfd (id 0 fd 8)

vz7 commit 1c0c47e44ec589f3782d9aa1e6e3292450550d29

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 criu/include/pid.h | 12 +++++++++++-
 criu/pstree.c      | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/pid.h b/criu/include/pid.h
index 37e39428e0d6..d8869fde0a09 100644
--- a/criu/include/pid.h
+++ b/criu/include/pid.h
@@ -69,13 +69,23 @@  static inline pid_t last_level_pid(struct pid *pid)
 	return pid->ns[pid->level-1].virt;
 }
 
+extern int pstree_pid_cmp(pid_t a, pid_t b);
+
 /*
  * When we have to restore a shared resource, we mush select which
  * task should do it, and make other(s) wait for it. In order to
  * avoid deadlocks, always make task with lower pid be the restorer.
  */
-static inline bool pid_rst_prio(unsigned pid_a, unsigned pid_b)
+static inline bool pid_rst_prio(pid_t pid_a, pid_t pid_b)
 {
+	int ret = pstree_pid_cmp(pid_a, pid_b);
+
+	if (ret == 1)
+		return true;
+	else if (ret == 2)
+		return false;
+
+	/* Fallback into plain pid comparision */
 	return pid_a < pid_b;
 }
 
diff --git a/criu/pstree.c b/criu/pstree.c
index 6047d29ccc97..f180b9b221ed 100644
--- a/criu/pstree.c
+++ b/criu/pstree.c
@@ -655,6 +655,42 @@  int fixup_pid_for_children_ns(TaskKobjIdsEntry *ids)
 	return 0;
 }
 
+/*
+ *  0 -- pids are the same
+ *  1 -- @a is a parent of @b
+ *  2 -- @b is a parent of @a
+ *  3 -- pids are not connected
+ *  -1 -- pid not found
+ */
+int pstree_pid_cmp(pid_t a, pid_t b)
+{
+	struct pstree_item *pstree_a, *pstree_b, *t;
+	struct pid *pid_a, *pid_b;
+
+	if (a == b)
+		return 0;
+
+	pid_a = pstree_pid_by_virt(a);
+	pid_b = pstree_pid_by_virt(b);
+	if (!pid_a || !pid_b)
+		return -1;
+
+	pstree_a = pid_a->item;
+	pstree_b = pid_b->item;
+
+	for (t = pstree_b; t->parent; t = t->parent) {
+		if (t == pstree_a)
+			return 1;
+	}
+
+	for (t = pstree_a; t->parent; t = t->parent) {
+		if (t == pstree_b)
+			return 2;
+	}
+
+	return 3;
+}
+
 static int read_pstree_ids(pid_t pid, TaskKobjIdsEntry **ids)
 {
 	struct cr_img *img;