From: Wei Yang <richard.weiyang@gmail.com>
To: akpm@linux-foundation.org, david@redhat.com,
lorenzo.stoakes@oracle.com, riel@surriel.com,
Liam.Howlett@oracle.com, vbabka@suse.cz, harry.yoo@oracle.com
Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org,
Wei Yang <richard.weiyang@gmail.com>
Subject: [RFC Patch 1/2] selftests/mm: put general ksm operation into vm_util
Date: Wed, 4 Jun 2025 08:21:44 +0000 [thread overview]
Message-ID: <20250604082145.13800-2-richard.weiyang@gmail.com> (raw)
In-Reply-To: <20250604082145.13800-1-richard.weiyang@gmail.com>
There are some general ksm operations could be used by other related
test case. Put them into vm_util for common use.
This is a preparation patch for later use.
Signed-off-by: Wei Yang <richard.weiyang@gmail.com>
Suggested-by: David Hildenbrand <david@redhat.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Rik van Riel <riel@surriel.com>
Cc: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Harry Yoo <harry.yoo@oracle.com>
---
.../selftests/mm/ksm_functional_tests.c | 76 +++----------------
tools/testing/selftests/mm/vm_util.c | 71 +++++++++++++++++
tools/testing/selftests/mm/vm_util.h | 7 ++
3 files changed, 88 insertions(+), 66 deletions(-)
diff --git a/tools/testing/selftests/mm/ksm_functional_tests.c b/tools/testing/selftests/mm/ksm_functional_tests.c
index b61803e36d1c..9fb79f6bf86d 100644
--- a/tools/testing/selftests/mm/ksm_functional_tests.c
+++ b/tools/testing/selftests/mm/ksm_functional_tests.c
@@ -73,74 +73,18 @@ static bool range_maps_duplicates(char *addr, unsigned long size)
return false;
}
-static long get_my_ksm_zero_pages(void)
-{
- char buf[200];
- char *substr_ksm_zero;
- size_t value_pos;
- ssize_t read_size;
- unsigned long my_ksm_zero_pages;
-
- if (!proc_self_ksm_stat_fd)
- return 0;
-
- read_size = pread(proc_self_ksm_stat_fd, buf, sizeof(buf) - 1, 0);
- if (read_size < 0)
- return -errno;
-
- buf[read_size] = 0;
-
- substr_ksm_zero = strstr(buf, "ksm_zero_pages");
- if (!substr_ksm_zero)
- return 0;
-
- value_pos = strcspn(substr_ksm_zero, "0123456789");
- my_ksm_zero_pages = strtol(substr_ksm_zero + value_pos, NULL, 10);
-
- return my_ksm_zero_pages;
-}
-
-static long get_my_merging_pages(void)
-{
- char buf[10];
- ssize_t ret;
-
- if (proc_self_ksm_merging_pages_fd < 0)
- return proc_self_ksm_merging_pages_fd;
-
- ret = pread(proc_self_ksm_merging_pages_fd, buf, sizeof(buf) - 1, 0);
- if (ret <= 0)
- return -errno;
- buf[ret] = 0;
-
- return strtol(buf, NULL, 10);
-}
-
-static long ksm_get_full_scans(void)
-{
- char buf[10];
- ssize_t ret;
-
- ret = pread(ksm_full_scans_fd, buf, sizeof(buf) - 1, 0);
- if (ret <= 0)
- return -errno;
- buf[ret] = 0;
-
- return strtol(buf, NULL, 10);
-}
-
static int ksm_merge(void)
{
long start_scans, end_scans;
/* Wait for two full scans such that any possible merging happened. */
- start_scans = ksm_get_full_scans();
+ start_scans = ksm_get_full_scans(ksm_full_scans_fd);
if (start_scans < 0)
return start_scans;
- if (write(ksm_fd, "1", 1) != 1)
+ if (ksm_start_and_merge(ksm_fd) != 1)
return -errno;
do {
- end_scans = ksm_get_full_scans();
+ end_scans = ksm_get_full_scans(ksm_full_scans_fd);
if (end_scans < 0)
return end_scans;
} while (end_scans < start_scans + 2);
@@ -150,7 +94,7 @@ static int ksm_merge(void)
static int ksm_unmerge(void)
{
- if (write(ksm_fd, "2", 1) != 1)
+ if (ksm_stop_and_unmerge(ksm_fd) != 1)
return -errno;
return 0;
}
@@ -168,7 +112,7 @@ static char *__mmap_and_merge_range(char val, unsigned long size, int prot,
return err_map;
}
- if (get_my_merging_pages() > 0) {
+ if (ksm_get_self_merging_pages(proc_self_ksm_merging_pages_fd) > 0) {
ksft_print_msg("Still pages merged\n");
return err_map;
}
@@ -227,7 +171,7 @@ static char *__mmap_and_merge_range(char val, unsigned long size, int prot,
* Check if anything was merged at all. Ignore the zero page that is
* accounted differently (depending on kernel support).
*/
- if (val && !get_my_merging_pages()) {
+ if (val && !ksm_get_self_merging_pages(proc_self_ksm_merging_pages_fd)) {
ksft_print_msg("No pages got merged\n");
goto unmap;
}
@@ -294,7 +238,7 @@ static void test_unmerge_zero_pages(void)
ksft_test_result_skip("open \"/sys/kernel/mm/ksm/use_zero_pages\" failed\n");
return;
}
- if (write(ksm_use_zero_pages_fd, "1", 1) != 1) {
+ if (ksm_use_zero_pages(ksm_use_zero_pages_fd) != 1) {
ksft_test_result_skip("write \"/sys/kernel/mm/ksm/use_zero_pages\" failed\n");
return;
}
@@ -306,7 +250,7 @@ static void test_unmerge_zero_pages(void)
/* Check if ksm_zero_pages is updated correctly after KSM merging */
pages_expected = size / pagesize;
- if (pages_expected != get_my_ksm_zero_pages()) {
+ if (pages_expected != ksm_get_self_zero_pages(proc_self_ksm_stat_fd)) {
ksft_test_result_fail("'ksm_zero_pages' updated after merging\n");
goto unmap;
}
@@ -319,7 +263,7 @@ static void test_unmerge_zero_pages(void)
/* Check if ksm_zero_pages is updated correctly after unmerging */
pages_expected /= 2;
- if (pages_expected != get_my_ksm_zero_pages()) {
+ if (pages_expected != ksm_get_self_zero_pages(proc_self_ksm_stat_fd)) {
ksft_test_result_fail("'ksm_zero_pages' updated after unmerging\n");
goto unmap;
}
@@ -329,7 +273,7 @@ static void test_unmerge_zero_pages(void)
*((unsigned int *)&map[offs]) = offs;
/* Now we should have no zeropages remaining. */
- if (get_my_ksm_zero_pages()) {
+ if (ksm_get_self_zero_pages(proc_self_ksm_stat_fd)) {
ksft_test_result_fail("'ksm_zero_pages' updated after write fault\n");
goto unmap;
}
diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
index 1357e2d6a7b6..115422e9eb68 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -486,3 +486,74 @@ int close_procmap(struct procmap_fd *procmap)
{
return close(procmap->fd);
}
+
+int ksm_use_zero_pages(int ksm_use_zero_pages_fd)
+{
+ return write(ksm_use_zero_pages_fd, "1", 1);
+}
+
+int ksm_start_and_merge(int ksm_fd)
+{
+ return write(ksm_fd, "1", 1);
+}
+
+int ksm_stop_and_unmerge(int ksm_fd)
+{
+ return write(ksm_fd, "2", 1);
+}
+
+long ksm_get_full_scans(int ksm_full_scans_fd)
+{
+ char buf[10];
+ ssize_t ret;
+
+ ret = pread(ksm_full_scans_fd, buf, sizeof(buf) - 1, 0);
+ if (ret <= 0)
+ return -errno;
+ buf[ret] = 0;
+
+ return strtol(buf, NULL, 10);
+}
+
+long ksm_get_self_merging_pages(int proc_self_ksm_merging_pages_fd)
+{
+ char buf[10];
+ ssize_t ret;
+
+ if (proc_self_ksm_merging_pages_fd < 0)
+ return proc_self_ksm_merging_pages_fd;
+
+ ret = pread(proc_self_ksm_merging_pages_fd, buf, sizeof(buf) - 1, 0);
+ if (ret <= 0)
+ return -errno;
+ buf[ret] = 0;
+
+ return strtol(buf, NULL, 10);
+}
+
+long ksm_get_self_zero_pages(int proc_self_ksm_stat_fd)
+{
+ char buf[200];
+ char *substr_ksm_zero;
+ size_t value_pos;
+ ssize_t read_size;
+ unsigned long my_ksm_zero_pages;
+
+ if (!proc_self_ksm_stat_fd)
+ return 0;
+
+ read_size = pread(proc_self_ksm_stat_fd, buf, sizeof(buf) - 1, 0);
+ if (read_size < 0)
+ return -errno;
+
+ buf[read_size] = 0;
+
+ substr_ksm_zero = strstr(buf, "ksm_zero_pages");
+ if (!substr_ksm_zero)
+ return 0;
+
+ value_pos = strcspn(substr_ksm_zero, "0123456789");
+ my_ksm_zero_pages = strtol(substr_ksm_zero + value_pos, NULL, 10);
+
+ return my_ksm_zero_pages;
+}
diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
index 9211ba640d9c..99c1b1aa1813 100644
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -95,6 +95,13 @@ static inline int open_self_procmap(struct procmap_fd *procmap_out)
return open_procmap(pid, procmap_out);
}
+int ksm_use_zero_pages(int ksm_use_zero_pages_fd);
+int ksm_start_and_merge(int ksm_fd);
+int ksm_stop_and_unmerge(int ksm_fd);
+long ksm_get_full_scans(int ksm_full_scans_fd);
+long ksm_get_self_merging_pages(int proc_self_ksm_merging_pages_fd);
+long ksm_get_self_zero_pages(int proc_self_ksm_stat_fd);
+
/*
* On ppc64 this will only work with radix 2M hugepage size
*/
--
2.34.1
next prev parent reply other threads:[~2025-06-04 8:22 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-04 8:21 [RFC Patch 0/2] selftests/mm: assert rmap behave as expected Wei Yang
2025-06-04 8:21 ` Wei Yang [this message]
2025-07-11 15:37 ` [RFC Patch 1/2] selftests/mm: put general ksm operation into vm_util David Hildenbrand
2025-07-14 2:45 ` Wei Yang
2025-06-04 8:21 ` [RFC Patch 2/2] selftests/mm: assert rmap behave as expected Wei Yang
2025-06-04 8:34 ` Wei Yang
2025-07-11 15:39 ` David Hildenbrand
2025-07-14 14:42 ` Wei Yang
2025-07-14 14:45 ` David Hildenbrand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250604082145.13800-2-richard.weiyang@gmail.com \
--to=richard.weiyang@gmail.com \
--cc=Liam.Howlett@oracle.com \
--cc=akpm@linux-foundation.org \
--cc=david@redhat.com \
--cc=harry.yoo@oracle.com \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=riel@surriel.com \
--cc=vbabka@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.