[CRIU] [PATCH v5 16/19] epoll: Add kid_lookup_epoll_tfd helper

Cyrill Gorcunov gorcunov at gmail.com
Wed Jul 4 18:51:44 MSK 2018


To find target files with help of our collected
rbtree.

Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
---
 criu/file-ids.c         |  2 +-
 criu/include/file-ids.h |  2 ++
 criu/include/kcmp-ids.h |  4 ++++
 criu/kcmp-ids.c         | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/criu/file-ids.c b/criu/file-ids.c
index 36973cbdd939..006e47d64f7e 100644
--- a/criu/file-ids.c
+++ b/criu/file-ids.c
@@ -19,7 +19,7 @@
 #include "irmap.h"
 #include "files.h"
 
-static DECLARE_KCMP_TREE(fd_tree, KCMP_FILE);
+DECLARE_KCMP_TREE(fd_tree, KCMP_FILE);
 
 #define FDID_BITS	5
 #define FDID_SIZE	(1 << FDID_BITS)
diff --git a/criu/include/file-ids.h b/criu/include/file-ids.h
index 845cfaa9f9db..9a39f0d2d36a 100644
--- a/criu/include/file-ids.h
+++ b/criu/include/file-ids.h
@@ -16,4 +16,6 @@ struct fd_parms;
 extern int fd_id_generate(pid_t pid, FdinfoEntry *fe, struct fd_parms *p);
 extern int fd_id_generate_special(struct fd_parms *p, u32 *id);
 
+extern struct kid_tree fd_tree;
+
 #endif /* __CR_FILE_IDS_H__ */
diff --git a/criu/include/kcmp-ids.h b/criu/include/kcmp-ids.h
index 37e2398db206..a37622c504a0 100644
--- a/criu/include/kcmp-ids.h
+++ b/criu/include/kcmp-ids.h
@@ -29,4 +29,8 @@ struct kid_elem {
 extern uint32_t kid_generate_gen(struct kid_tree *tree,
 				 struct kid_elem *elem, int *new_id);
 
+extern struct kid_elem *kid_lookup_epoll_tfd(struct kid_tree *tree,
+					     struct kid_elem *elem,
+					     kcmp_epoll_slot_t *slot);
+
 #endif /* __CR_KCMP_IDS_H__ */
diff --git a/criu/kcmp-ids.c b/criu/kcmp-ids.c
index 5b91fb66b886..4fde10e67e75 100644
--- a/criu/kcmp-ids.c
+++ b/criu/kcmp-ids.c
@@ -152,5 +152,57 @@ uint32_t kid_generate_gen(struct kid_tree *tree,
 	rb_link_and_balance(&tree->root, &e->node, parent, new);
 	*new_id = 1;
 	return e->subid;
+}
+
+static struct kid_elem *kid_lookup_epoll_tfd_sub(struct kid_tree *tree,
+						 struct kid_entry *e,
+						 struct kid_elem *elem,
+						 kcmp_epoll_slot_t *slot)
+{
+	struct rb_node *node = e->subtree_root.rb_node;
+	struct rb_node **new = &e->subtree_root.rb_node;
+
+	BUG_ON(!node);
+
+	while (node) {
+		struct kid_entry *this = rb_entry(node, struct kid_entry, subtree_node);
+		int ret = syscall(SYS_kcmp, this->elem.pid, elem->pid, KCMP_EPOLL_TFD,
+				  this->elem.idx, slot);
+
+		if (ret == 1)
+			node = node->rb_left, new = &((*new)->rb_left);
+		else if (ret == 2)
+			node = node->rb_right, new = &((*new)->rb_right);
+		else if (ret == 0)
+			return &this->elem;
+		else {
+			pr_perror("kcmp-epoll failed: pid (%d %d) type %u idx (%u %u)",
+				  this->elem.pid, elem->pid, KCMP_EPOLL_TFD,
+				  this->elem.idx, elem->idx);
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+struct kid_elem *kid_lookup_epoll_tfd(struct kid_tree *tree,
+				      struct kid_elem *elem,
+				      kcmp_epoll_slot_t *slot)
+{
+	struct rb_node *node = tree->root.rb_node;
+	struct rb_node **new = &tree->root.rb_node;
+
+	while (node) {
+		struct kid_entry *this = rb_entry(node, struct kid_entry, node);
+
+		if (elem->genid < this->elem.genid)
+			node = node->rb_left, new = &((*new)->rb_left);
+		else if (elem->genid > this->elem.genid)
+			node = node->rb_right, new = &((*new)->rb_right);
+		else
+			return kid_lookup_epoll_tfd_sub(tree, this, elem, slot);
+	}
 
+	return NULL;
 }
-- 
2.14.4



More information about the CRIU mailing list