From 9c56992f2bc7567eec3de16f83c119445bb391ac Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 16 Aug 2017 10:32:26 +0300 Subject: [PATCH] cr-service: require non-cooperative userfaultfd for lazy-pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without non-cooperative userfaultfd some programs may fail during lazy restore because they perform operations that cannot be handled by the lazy-pages daemon. ✓ travis-ci: success for lazy-pages: update checks for availability of userfaultfd (rev3) Signed-off-by: Mike Rapoport Signed-off-by: Pavel Emelyanov --- criu/cr-check.c | 9 ++------- criu/cr-service.c | 10 ++-------- criu/include/uffd.h | 1 + criu/uffd.c | 7 +++++++ 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/criu/cr-check.c b/criu/cr-check.c index ef706bf7b..ba47f410c 100644 --- a/criu/cr-check.c +++ b/criu/cr-check.c @@ -50,7 +50,7 @@ #include "libnetlink.h" #include "net.h" #include "restorer.h" -#include "linux/userfaultfd.h" +#include "uffd.h" static char *feature_name(int (*func)()); @@ -1043,15 +1043,10 @@ static int check_uffd(void) static int check_uffd_noncoop(void) { - unsigned long features = UFFD_FEATURE_EVENT_FORK | - UFFD_FEATURE_EVENT_REMAP | - UFFD_FEATURE_EVENT_UNMAP | - UFFD_FEATURE_EVENT_REMOVE; - if (check_uffd()) return -1; - if ((kdat.uffd_features & features) != features) { + if (!uffd_noncooperative()) { pr_err("Non-cooperative UFFD is not supported\n"); return -1; } diff --git a/criu/cr-service.c b/criu/cr-service.c index 84d7eb2be..2a4f37f58 100644 --- a/criu/cr-service.c +++ b/criu/cr-service.c @@ -40,6 +40,7 @@ #include #include #include "common/scm.h" +#include "uffd.h" #include "setproctitle.h" @@ -891,14 +892,7 @@ static int handle_feature_check(int sk, CriuReq * msg) if ((msg->features->has_lazy_pages == 1) && (msg->features->lazy_pages == true)) - /* - * Not checking for specific UFFD features yet. - * If no error is returned it is probably - * enough for basic UFFD functionality. This can - * be extended in the future for a more detailed - * UFFD feature check. - */ - feat.lazy_pages = kdat.has_uffd; + feat.lazy_pages = kdat.has_uffd && uffd_noncooperative(); resp.features = &feat; resp.type = msg->type; diff --git a/criu/include/uffd.h b/criu/include/uffd.h index e2b9be693..79abc1669 100644 --- a/criu/include/uffd.h +++ b/criu/include/uffd.h @@ -4,6 +4,7 @@ struct task_restore_args; extern int uffd_open(int flags, unsigned long *features); +extern bool uffd_noncooperative(void); extern int setup_uffd(int pid, struct task_restore_args *task_args); extern int lazy_pages_setup_zombie(int pid); extern int prepare_lazy_pages_socket(void); diff --git a/criu/uffd.c b/criu/uffd.c index d3142ae8b..077724b0d 100644 --- a/criu/uffd.c +++ b/criu/uffd.c @@ -211,6 +211,13 @@ int lazy_pages_setup_zombie(int pid) return 0; } +bool uffd_noncooperative(void) +{ + unsigned long features = NEED_UFFD_API_FEATURES; + + return (kdat.uffd_features & features) == features; +} + int uffd_open(int flags, unsigned long *features) { struct uffdio_api uffdio_api = { 0 };