[5/9] epoll: kdat -- Check if we have KCMP_EPOLL_TFD support

Submitted by Cyrill Gorcunov on June 20, 2018, 12:01 p.m.

Details

Message ID 20180620120143.8604-6-gorcunov@gmail.com
State New
Series "epoll: Add support for duped targets"
Headers show

Commit Message

Cyrill Gorcunov June 20, 2018, 12:01 p.m.
We will need it to make sure the target files in epolls are present
in current process.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 criu/include/kerndat.h |  1 +
 criu/kerndat.c         | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
index 28a84fb0d583..af6b5c5c3a38 100644
--- a/criu/include/kerndat.h
+++ b/criu/include/kerndat.h
@@ -77,6 +77,7 @@  struct kerndat_s {
 	bool has_pid_for_children_ns;
 	bool x86_has_ptrace_fpu_xsave_bug;
 	bool has_inotify_setnextwd;
+	bool has_kcmp_epoll_tfd;
 };
 
 extern struct kerndat_s kdat;
diff --git a/criu/kerndat.c b/criu/kerndat.c
index 9b93487cc5ef..f26187f7bfbe 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -40,6 +40,7 @@ 
 #include "prctl.h"
 #include "uffd.h"
 #include "vdso.h"
+#include "kcmp.h"
 
 struct kerndat_s kdat = {
 };
@@ -819,6 +820,51 @@  int kerndat_has_inotify_setnextwd(void)
 	return ret;
 }
 
+int has_kcmp_epoll_tfd(void)
+{
+	kcmp_epoll_slot_t slot = { };
+	int ret = -1, efd, tfd;
+	pid_t pid = getpid();
+	struct epoll_event ev;
+	int pipefd[2];
+
+	efd = epoll_create(1);
+	if (efd < 0) {
+		pr_perror("Can't create epoll");
+		return -1;
+	}
+
+	memset(&ev, 0xff, sizeof(ev));
+	ev.events = EPOLLIN | EPOLLOUT;
+
+	if (pipe(pipefd)) {
+		pr_perror("Can't create pipe");
+		close(efd);
+		return -1;
+	}
+
+	tfd = pipefd[0];
+	if (epoll_ctl(efd, EPOLL_CTL_ADD, tfd, &ev)) {
+		pr_perror("Can't add event");
+		goto out;
+	}
+
+	slot.efd = efd;
+	slot.tfd = tfd;
+
+	if (syscall(SYS_kcmp, pid, pid, KCMP_EPOLL_TFD, tfd, &slot) == 0)
+		kdat.has_kcmp_epoll_tfd = true;
+	else
+		kdat.has_kcmp_epoll_tfd = false;
+	ret = 0;
+
+out:
+	close(pipefd[0]);
+	close(pipefd[1]);
+	close(efd);
+	return ret;
+}
+
 int __attribute__((weak)) kdat_x86_has_ptrace_fpu_xsave_bug(void)
 {
 	return 0;
@@ -1120,6 +1166,8 @@  int kerndat_init(void)
 		ret = kerndat_x86_has_ptrace_fpu_xsave_bug();
 	if (!ret)
 		ret = kerndat_has_inotify_setnextwd();
+	if (!ret)
+		ret = has_kcmp_epoll_tfd();
 
 	kerndat_lsm();
 	kerndat_mmap_min_addr();