diff --git a/criu/cr-check.c b/criu/cr-check.c index 0320b445a..ced084df2 100644 --- a/criu/cr-check.c +++ b/criu/cr-check.c @@ -1368,6 +1368,14 @@ static int check_ns_pid(void) return 0; } +static int check_memfd_hugetlb(void) +{ + if (!kdat.has_memfd_hugetlb) + return -1; + + return 0; +} + static int check_network_lock_nftables(void) { if (!kdat.has_nftables_concat) { @@ -1505,6 +1513,7 @@ int cr_check(void) ret |= check_apparmor_stacking(); ret |= check_network_lock_nftables(); ret |= check_sockopt_buf_lock(); + ret |= check_memfd_hugetlb(); } /* @@ -1618,6 +1627,7 @@ static struct feature_list feature_list[] = { { "apparmor_stacking", check_apparmor_stacking }, { "network_lock_nftables", check_network_lock_nftables }, { "sockopt_buf_lock", check_sockopt_buf_lock }, + { "memfd_hugetlb", check_memfd_hugetlb }, { NULL, NULL }, }; diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h index a28a95802..0de5eb778 100644 --- a/criu/include/kerndat.h +++ b/criu/include/kerndat.h @@ -36,6 +36,7 @@ struct kerndat_s { u64 zero_page_pfn; bool has_dirty_track; bool has_memfd; + bool has_memfd_hugetlb; bool has_fdinfo_lock; unsigned long task_size; bool ipv6; diff --git a/criu/kerndat.c b/criu/kerndat.c index 9f6a6ec42..b13ebee81 100644 --- a/criu/kerndat.c +++ b/criu/kerndat.c @@ -420,6 +420,29 @@ static bool kerndat_has_memfd_create(void) return 0; } +static bool kerndat_has_memfd_hugetlb(void) +{ + int ret; + + if (!kdat.has_memfd) { + kdat.has_memfd_hugetlb = false; + return 0; + } + + ret = memfd_create("", MFD_HUGETLB); + if (ret >= 0) { + kdat.has_memfd_hugetlb = true; + close(ret); + } else if (ret == -1 && errno == EINVAL) { + kdat.has_memfd_hugetlb = false; + } else { + pr_perror("Unexpected error from memfd_create(\"\", MFD_HUGETLB)"); + return -1; + } + + return 0; +} + static int get_task_size(void) { kdat.task_size = compel_task_size(); @@ -1320,6 +1343,10 @@ int kerndat_init(void) pr_err("kerndat_has_memfd_create failed when initializing kerndat.\n"); ret = -1; } + if (!ret && kerndat_has_memfd_hugetlb()) { + pr_err("kerndat_has_memfd_hugetlb failed when initializing kerndat.\n"); + ret = -1; + } if (!ret && kerndat_detect_stack_guard_gap()) { pr_err("kerndat_detect_stack_guard_gap failed when initializing kerndat.\n"); ret = -1;