Currently each test can specify unique operations using uffd_test_ops, however these operations are per-memory type and not per-test. Add uffd_test_case_ops which each test case can customize for its own needs regardless of the memory type being used. Post- and pre- allocation and release operations are added, some of which will be used in the next patch to implement test-specific customizations like area re-alignment, page size overrides and madvise after memory allocations but before memory is accessed.
Signed-off-by: Suren Baghdasaryan surenb@google.com --- tools/testing/selftests/mm/uffd-common.c | 25 ++++++++++++++++++++ tools/testing/selftests/mm/uffd-common.h | 9 +++++++ tools/testing/selftests/mm/uffd-unit-tests.c | 2 ++ 3 files changed, 36 insertions(+)
diff --git a/tools/testing/selftests/mm/uffd-common.c b/tools/testing/selftests/mm/uffd-common.c index 583e5a4cc0fd..69e6653ad255 100644 --- a/tools/testing/selftests/mm/uffd-common.c +++ b/tools/testing/selftests/mm/uffd-common.c @@ -17,6 +17,7 @@ bool map_shared; bool test_uffdio_wp = true; unsigned long long *count_verify; uffd_test_ops_t *uffd_test_ops; +uffd_test_case_ops_t *uffd_test_case_ops;
static int uffd_mem_fd_create(off_t mem_size, bool hugetlb) { @@ -286,11 +287,17 @@ void uffd_test_ctx_clear(void) uffd = -1; }
+ if (uffd_test_case_ops && uffd_test_case_ops->pre_release) + uffd_test_case_ops->pre_release(); + munmap_area((void **)&area_src); munmap_area((void **)&area_src_alias); munmap_area((void **)&area_dst); munmap_area((void **)&area_dst_alias); munmap_area((void **)&area_remap); + + if (uffd_test_case_ops && uffd_test_case_ops->post_release) + uffd_test_case_ops->post_release(); }
int uffd_test_ctx_init(uint64_t features, const char **errmsg) @@ -298,6 +305,15 @@ int uffd_test_ctx_init(uint64_t features, const char **errmsg) unsigned long nr, cpu; int ret;
+ if (uffd_test_case_ops && uffd_test_case_ops->pre_alloc) { + ret = uffd_test_case_ops->pre_alloc(); + if (ret) { + if (errmsg) + *errmsg = "pre-allocation operation failed"; + return ret; + } + } + ret = uffd_test_ops->allocate_area((void **)&area_src, true); ret |= uffd_test_ops->allocate_area((void **)&area_dst, false); if (ret) { @@ -306,6 +322,15 @@ int uffd_test_ctx_init(uint64_t features, const char **errmsg) return ret; }
+ if (uffd_test_case_ops && uffd_test_case_ops->post_alloc) { + ret = uffd_test_case_ops->post_alloc(); + if (ret) { + if (errmsg) + *errmsg = "post-allocation operation failed"; + return ret; + } + } + ret = userfaultfd_open(&features); if (ret) { if (errmsg) diff --git a/tools/testing/selftests/mm/uffd-common.h b/tools/testing/selftests/mm/uffd-common.h index 870776b5a323..19930fd6682b 100644 --- a/tools/testing/selftests/mm/uffd-common.h +++ b/tools/testing/selftests/mm/uffd-common.h @@ -90,6 +90,14 @@ struct uffd_test_ops { }; typedef struct uffd_test_ops uffd_test_ops_t;
+struct uffd_test_case_ops { + int (*pre_alloc)(void); + int (*post_alloc)(void); + void (*pre_release)(void); + void (*post_release)(void); +}; +typedef struct uffd_test_case_ops uffd_test_case_ops_t; + extern unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size; extern char *area_src, *area_src_alias, *area_dst, *area_dst_alias, *area_remap; extern int uffd, uffd_flags, finished, *pipefd, test_type; @@ -102,6 +110,7 @@ extern uffd_test_ops_t anon_uffd_test_ops; extern uffd_test_ops_t shmem_uffd_test_ops; extern uffd_test_ops_t hugetlb_uffd_test_ops; extern uffd_test_ops_t *uffd_test_ops; +extern uffd_test_case_ops_t *uffd_test_case_ops;
void uffd_stats_report(struct uffd_args *args, int n_cpus); int uffd_test_ctx_init(uint64_t features, const char **errmsg); diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c b/tools/testing/selftests/mm/uffd-unit-tests.c index e7d43c198041..debc423bdbf4 100644 --- a/tools/testing/selftests/mm/uffd-unit-tests.c +++ b/tools/testing/selftests/mm/uffd-unit-tests.c @@ -78,6 +78,7 @@ typedef struct { uffd_test_fn uffd_fn; unsigned int mem_targets; uint64_t uffd_feature_required; + uffd_test_case_ops_t *test_case_ops; } uffd_test_case_t;
static void uffd_test_report(void) @@ -185,6 +186,7 @@ uffd_setup_environment(uffd_test_args_t *args, uffd_test_case_t *test, { map_shared = mem_type->shared; uffd_test_ops = mem_type->mem_ops; + uffd_test_case_ops = test->test_case_ops;
if (mem_type->mem_flag & (MEM_HUGETLB_PRIVATE | MEM_HUGETLB)) page_size = default_huge_page_size();