[CRIU] [PATCH 5/6] kdat: Check for KCMP_EPOLL_TFD
Cyrill Gorcunov
gorcunov at gmail.com
Tue Apr 3 20:46:49 MSK 2018
This feature will be needed to support duplicated
target file descriptors in epoll.
Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
---
criu/include/kcmp.h | 10 ++++++++
criu/include/kerndat.h | 1 +
criu/kerndat.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/criu/include/kcmp.h b/criu/include/kcmp.h
index 76f557bff047..b6d3519a0c5c 100644
--- a/criu/include/kcmp.h
+++ b/criu/include/kcmp.h
@@ -1,6 +1,8 @@
#ifndef __CR_KCMP_H__
#define __CR_KCMP_H__
+#include <stdint.h>
+
enum kcmp_type {
KCMP_FILE,
KCMP_VM,
@@ -9,8 +11,16 @@ enum kcmp_type {
KCMP_SIGHAND,
KCMP_IO,
KCMP_SYSVSEM,
+ KCMP_EPOLL_TFD,
KCMP_TYPES,
};
+/* Slot for KCMP_EPOLL_TFD */
+typedef struct {
+ uint32_t efd; /* epoll file descriptor */
+ uint32_t tfd; /* target file number */
+ uint32_t toff; /* target offset within same numbered sequence */
+} kcmp_epoll_slot_t;
+
#endif /* __CR_KCMP_H__ */
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 227d429f9dde..456adbf2851f 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -13,7 +13,7 @@
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */
#include <sys/prctl.h>
#include <sys/inotify.h>
-
+#include <sys/epoll.h>
#include "common/config.h"
#include "int.h"
@@ -40,6 +40,7 @@
#include "prctl.h"
#include "uffd.h"
#include "vdso.h"
+#include "kcmp.h"
struct kerndat_s kdat = {
};
@@ -819,6 +820,65 @@ int kerndat_has_inotify_setnextwd(void)
return ret;
}
+static int kerndat_has_kcmp_epoll_tfd(void)
+{
+ kcmp_epoll_slot_t epoll_slot = { };
+ struct epoll_event ev;
+ int ret = -1;
+ int pipefd[2];
+ int epollfd;
+ int fddup;
+
+ if (pipe(pipefd)) {
+ pr_perror("Can't create pipe");
+ return -1;
+ }
+
+ epollfd = epoll_create1(0);
+ if (epollfd < 0) {
+ pr_perror("epoll_create1 failed");
+ return -1;
+ }
+
+ memset(&ev, 0xff, sizeof(ev));
+ ev.events = EPOLLIN | EPOLLOUT;
+
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd[0], &ev)) {
+ pr_perror("epoll_ctl failed");
+ return -1;
+ }
+
+ fddup = dup(pipefd[1]);
+ if (fddup < 0) {
+ pr_perror("dup2 failed");
+ goto out;
+ }
+
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fddup, &ev)) {
+ pr_perror("epoll_ctl failed");
+ close(fddup);
+ goto out;
+ }
+ close(fddup);
+
+ epoll_slot = (kcmp_epoll_slot_t) {
+ .efd = epollfd,
+ .tfd = fddup,
+ .toff = 0,
+ };
+
+ ret = syscall(SYS_kcmp, getpid(), getpid(),
+ KCMP_EPOLL_TFD, pipefd[1], (void *)&epoll_slot);
+ if (ret == 0)
+ kdat.has_kcmp_epoll_tfd = true;
+
+out:
+ close(pipefd[0]);
+ close(pipefd[1]);
+ close(epollfd);
+ return ret;
+}
+
int __attribute__((weak)) kdat_x86_has_ptrace_fpu_xsave_bug(void)
{
return 0;
@@ -1124,6 +1184,8 @@ int kerndat_init(void)
ret = kerndat_x86_has_ptrace_fpu_xsave_bug();
if (!ret)
ret = kerndat_has_inotify_setnextwd();
+ if (!ret)
+ ret = kerndat_has_kcmp_epoll_tfd();
kerndat_lsm();
kerndat_mmap_min_addr();
--
2.14.3
More information about the CRIU
mailing list