selftests/mm: allow uffd test to skip properly with no privilege
Allow skip a unit test properly due to no privilege (e.g. sigbus and events tests). [colin.i.king@gmail.com: fix spelling mistake "priviledge" -> "privilege"] Link: https://lkml.kernel.org/r/20230414081506.1678998-1-colin.i.king@gmail.com Link: https://lkml.kernel.org/r/20230412164520.329163-1-peterx@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com> Signed-off-by: Colin Ian King <colin.i.king@gmail.com> Cc: Axel Rasmussen <axelrasmussen@google.com> Cc: David Hildenbrand <david@redhat.com> Cc: Dmitry Safonov <0x7f454c46@gmail.com> Cc: Mike Kravetz <mike.kravetz@oracle.com> Cc: Mike Rapoport (IBM) <rppt@kernel.org> Cc: Zach O'Keefe <zokeefe@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
4df9cefa94
commit
f9da24263d
@ -232,7 +232,7 @@ void uffd_stats_report(struct uffd_args *args, int n_cpus)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void userfaultfd_open(uint64_t *features)
|
||||
int userfaultfd_open(uint64_t *features)
|
||||
{
|
||||
struct uffdio_api uffdio_api;
|
||||
|
||||
@ -241,18 +241,19 @@ void userfaultfd_open(uint64_t *features)
|
||||
else
|
||||
uffd = uffd_open_sys(UFFD_FLAGS);
|
||||
if (uffd < 0)
|
||||
err("uffd open failed (dev=%d)", test_dev_userfaultfd);
|
||||
return -1;
|
||||
uffd_flags = fcntl(uffd, F_GETFD, NULL);
|
||||
|
||||
uffdio_api.api = UFFD_API;
|
||||
uffdio_api.features = *features;
|
||||
if (ioctl(uffd, UFFDIO_API, &uffdio_api))
|
||||
err("UFFDIO_API failed.\nPlease make sure to "
|
||||
"run with either root or ptrace capability.");
|
||||
/* Probably lack of CAP_PTRACE? */
|
||||
return -1;
|
||||
if (uffdio_api.api != UFFD_API)
|
||||
err("UFFDIO_API error: %" PRIu64, (uint64_t)uffdio_api.api);
|
||||
|
||||
*features = uffdio_api.features;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void munmap_area(void **area)
|
||||
@ -295,7 +296,7 @@ static void uffd_test_ctx_clear(void)
|
||||
munmap_area((void **)&area_remap);
|
||||
}
|
||||
|
||||
int uffd_test_ctx_init(uint64_t features)
|
||||
int uffd_test_ctx_init(uint64_t features, const char **errmsg)
|
||||
{
|
||||
unsigned long nr, cpu;
|
||||
int ret;
|
||||
@ -303,13 +304,19 @@ int uffd_test_ctx_init(uint64_t features)
|
||||
uffd_test_ctx_clear();
|
||||
|
||||
ret = uffd_test_ops->allocate_area((void **)&area_src, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = uffd_test_ops->allocate_area((void **)&area_dst, false);
|
||||
if (ret)
|
||||
ret |= uffd_test_ops->allocate_area((void **)&area_dst, false);
|
||||
if (ret) {
|
||||
if (errmsg)
|
||||
*errmsg = "memory allocation failed";
|
||||
return ret;
|
||||
}
|
||||
|
||||
userfaultfd_open(&features);
|
||||
ret = userfaultfd_open(&features);
|
||||
if (ret) {
|
||||
if (errmsg)
|
||||
*errmsg = "possible lack of priviledge";
|
||||
return ret;
|
||||
}
|
||||
|
||||
count_verify = malloc(nr_pages * sizeof(unsigned long long));
|
||||
if (!count_verify)
|
||||
|
@ -101,8 +101,8 @@ extern uffd_test_ops_t hugetlb_uffd_test_ops;
|
||||
extern uffd_test_ops_t *uffd_test_ops;
|
||||
|
||||
void uffd_stats_report(struct uffd_args *args, int n_cpus);
|
||||
int uffd_test_ctx_init(uint64_t features);
|
||||
void userfaultfd_open(uint64_t *features);
|
||||
int uffd_test_ctx_init(uint64_t features, const char **errmsg);
|
||||
int userfaultfd_open(uint64_t *features);
|
||||
int uffd_read_msg(int ufd, struct uffd_msg *msg);
|
||||
void wp_range(int ufd, __u64 start, __u64 len, bool wp);
|
||||
void uffd_handle_page_fault(struct uffd_msg *msg, struct uffd_args *args);
|
||||
|
@ -271,7 +271,8 @@ static int userfaultfd_stress(void)
|
||||
struct uffd_args args[nr_cpus];
|
||||
uint64_t mem_size = nr_pages * page_size;
|
||||
|
||||
uffd_test_ctx_init(UFFD_FEATURE_WP_UNPOPULATED);
|
||||
if (uffd_test_ctx_init(UFFD_FEATURE_WP_UNPOPULATED, NULL))
|
||||
err("context init failed");
|
||||
|
||||
if (posix_memalign(&area, page_size, page_size))
|
||||
err("out of memory");
|
||||
@ -435,7 +436,8 @@ static void parse_test_type_arg(const char *raw_type)
|
||||
* feature.
|
||||
*/
|
||||
|
||||
userfaultfd_open(&features);
|
||||
if (userfaultfd_open(&features))
|
||||
err("Userfaultfd open failed");
|
||||
|
||||
test_uffdio_wp = test_uffdio_wp &&
|
||||
(features & UFFD_FEATURE_PAGEFAULT_FLAG_WP);
|
||||
|
@ -172,7 +172,8 @@ out:
|
||||
* This function initializes the global variables. TODO: remove global
|
||||
* vars and then remove this.
|
||||
*/
|
||||
static int uffd_setup_environment(uffd_test_case_t *test, mem_type_t *mem_type)
|
||||
static int uffd_setup_environment(uffd_test_case_t *test, mem_type_t *mem_type,
|
||||
const char **errmsg)
|
||||
{
|
||||
map_shared = mem_type->shared;
|
||||
uffd_test_ops = mem_type->mem_ops;
|
||||
@ -186,7 +187,7 @@ static int uffd_setup_environment(uffd_test_case_t *test, mem_type_t *mem_type)
|
||||
/* TODO: remove this global var.. it's so ugly */
|
||||
nr_cpus = 1;
|
||||
|
||||
return uffd_test_ctx_init(test->uffd_feature_required);
|
||||
return uffd_test_ctx_init(test->uffd_feature_required, errmsg);
|
||||
}
|
||||
|
||||
static bool uffd_feature_supported(uffd_test_case_t *test)
|
||||
@ -835,6 +836,7 @@ int main(int argc, char *argv[])
|
||||
uffd_test_case_t *test;
|
||||
mem_type_t *mem_type;
|
||||
char test_name[128];
|
||||
const char *errmsg;
|
||||
int has_uffd;
|
||||
int i, j;
|
||||
|
||||
@ -860,8 +862,8 @@ int main(int argc, char *argv[])
|
||||
uffd_test_skip("feature missing");
|
||||
continue;
|
||||
}
|
||||
if (uffd_setup_environment(test, mem_type)) {
|
||||
uffd_test_skip("environment setup failed");
|
||||
if (uffd_setup_environment(test, mem_type, &errmsg)) {
|
||||
uffd_test_skip(errmsg);
|
||||
continue;
|
||||
}
|
||||
test->uffd_fn();
|
||||
|
Loading…
x
Reference in New Issue
Block a user