Added a new selftest to verify whether the `ksm_merging_pages` counter
in `mm_struct` is not inherited by a child process after fork. This helps
ensure correctness of KSM accounting across process creation.
Signed-off-by: Donet Tom <donettom@linux.ibm.com>
---
.../selftests/mm/ksm_functional_tests.c | 42 ++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/mm/ksm_functional_tests.c b/tools/testing/selftests/mm/ksm_functional_tests.c
index 712f43c87736..645cefba2126 100644
--- a/tools/testing/selftests/mm/ksm_functional_tests.c
+++ b/tools/testing/selftests/mm/ksm_functional_tests.c
@@ -602,6 +602,45 @@ static void test_prot_none(void)
munmap(map, size);
}
+static void test_fork_ksm_merging_page_count(void)
+{
+ const unsigned int size = 2 * MiB;
+ char *map;
+ pid_t child_pid;
+ int status;
+
+ ksft_print_msg("[RUN] %s\n", __func__);
+
+ map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, KSM_MERGE_MADVISE);
+ if (map == MAP_FAILED)
+ return;
+
+ child_pid = fork();
+ if (!child_pid) {
+ init_global_file_handles();
+ exit(ksm_get_self_merging_pages());
+ } else if (child_pid < 0) {
+ ksft_test_result_fail("fork() failed\n");
+ return;
+ }
+
+ if (waitpid(child_pid, &status, 0) < 0) {
+ ksft_test_result_fail("waitpid() failed\n");
+ return;
+ }
+
+ status = WEXITSTATUS(status);
+ if (status) {
+ ksft_test_result_fail("ksm_merging_page in child: %d\n", status);
+ return;
+ }
+
+ ksft_test_result_pass("ksm_merging_pages is not inherited after fork\n");
+
+ ksm_stop();
+ munmap(map, size);
+}
+
static void init_global_file_handles(void)
{
mem_fd = open("/proc/self/mem", O_RDWR);
@@ -620,7 +659,7 @@ static void init_global_file_handles(void)
int main(int argc, char **argv)
{
- unsigned int tests = 8;
+ unsigned int tests = 9;
int err;
if (argc > 1 && !strcmp(argv[1], FORK_EXEC_CHILD_PRG_NAME)) {
@@ -652,6 +691,7 @@ int main(int argc, char **argv)
test_prctl_fork();
test_prctl_fork_exec();
test_prctl_unmerge();
+ test_fork_ksm_merging_page_count();
err = ksft_get_fail_cnt();
if (err)
--
2.51.0
On 15.09.25 17:03, Donet Tom wrote: > Added a new selftest to verify whether the `ksm_merging_pages` counter > in `mm_struct` is not inherited by a child process after fork. This helps > ensure correctness of KSM accounting across process creation. > > Signed-off-by: Donet Tom <donettom@linux.ibm.com> > --- > .../selftests/mm/ksm_functional_tests.c | 42 ++++++++++++++++++- > 1 file changed, 41 insertions(+), 1 deletion(-) > > diff --git a/tools/testing/selftests/mm/ksm_functional_tests.c b/tools/testing/selftests/mm/ksm_functional_tests.c > index 712f43c87736..645cefba2126 100644 > --- a/tools/testing/selftests/mm/ksm_functional_tests.c > +++ b/tools/testing/selftests/mm/ksm_functional_tests.c > @@ -602,6 +602,45 @@ static void test_prot_none(void) > munmap(map, size); > } > > +static void test_fork_ksm_merging_page_count(void) > +{ > + const unsigned int size = 2 * MiB; > + char *map; > + pid_t child_pid; > + int status; > + > + ksft_print_msg("[RUN] %s\n", __func__); > + > + map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, KSM_MERGE_MADVISE); > + if (map == MAP_FAILED) > + return; > + > + child_pid = fork(); > + if (!child_pid) { > + init_global_file_handles(); > + exit(ksm_get_self_merging_pages()); > + } else if (child_pid < 0) { > + ksft_test_result_fail("fork() failed\n"); > + return; Probably goto out; in all these fail cases > + } > + > + if (waitpid(child_pid, &status, 0) < 0) { > + ksft_test_result_fail("waitpid() failed\n"); > + return; > + } > + > + status = WEXITSTATUS(status); > + if (status) { > + ksft_test_result_fail("ksm_merging_page in child: %d\n", status); > + return; > + } > + > + ksft_test_result_pass("ksm_merging_pages is not inherited after fork\n"); > + And have out: here With that: Acked-by: David Hildenbrand <david@redhat.com> -- Cheers David / dhildenb
On 9/17/25 6:45 PM, David Hildenbrand wrote: > On 15.09.25 17:03, Donet Tom wrote: >> Added a new selftest to verify whether the `ksm_merging_pages` counter >> in `mm_struct` is not inherited by a child process after fork. This >> helps >> ensure correctness of KSM accounting across process creation. >> >> Signed-off-by: Donet Tom <donettom@linux.ibm.com> >> --- >> .../selftests/mm/ksm_functional_tests.c | 42 ++++++++++++++++++- >> 1 file changed, 41 insertions(+), 1 deletion(-) >> >> diff --git a/tools/testing/selftests/mm/ksm_functional_tests.c >> b/tools/testing/selftests/mm/ksm_functional_tests.c >> index 712f43c87736..645cefba2126 100644 >> --- a/tools/testing/selftests/mm/ksm_functional_tests.c >> +++ b/tools/testing/selftests/mm/ksm_functional_tests.c >> @@ -602,6 +602,45 @@ static void test_prot_none(void) >> munmap(map, size); >> } >> +static void test_fork_ksm_merging_page_count(void) >> +{ >> + const unsigned int size = 2 * MiB; >> + char *map; >> + pid_t child_pid; >> + int status; >> + >> + ksft_print_msg("[RUN] %s\n", __func__); >> + >> + map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, >> KSM_MERGE_MADVISE); >> + if (map == MAP_FAILED) >> + return; >> + >> + child_pid = fork(); >> + if (!child_pid) { >> + init_global_file_handles(); >> + exit(ksm_get_self_merging_pages()); >> + } else if (child_pid < 0) { >> + ksft_test_result_fail("fork() failed\n"); >> + return; > > Probably > goto out; > > in all these fail cases > >> + } >> + >> + if (waitpid(child_pid, &status, 0) < 0) { >> + ksft_test_result_fail("waitpid() failed\n"); >> + return; >> + } >> + >> + status = WEXITSTATUS(status); >> + if (status) { >> + ksft_test_result_fail("ksm_merging_page in child: %d\n", >> status); >> + return; >> + } >> + >> + ksft_test_result_pass("ksm_merging_pages is not inherited after >> fork\n"); >> + > > And have > > out: > > here Sure, I will send a v3 with this change. > > With that: > > Acked-by: David Hildenbrand <david@redhat.com> >
© 2016 - 2025 Red Hat, Inc.