From: "Xu Xin (vivo)" <xu.xin@linux.dev>
To: xu.xin@linux.dev
Cc: akpm@linux-foundation.org, chengming.zhou@linux.dev,
corbet@lwn.net, david@kernel.org, link@vivo.com,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org, linux-mm@kvack.org,
ljs@kernel.org, odys.yuan@gmail.com, rppt@kernel.org,
surenb@google.com, tujinjiang@huawei.com, vbabka@kernel.org,
xiao.wang@vivo.com
Subject: [PATCH 3/4] selftests/ksm: consolidate ksm_stat readers into ksm_get_self_stat()
Date: Tue, 10 Nov 2026 15:44:50 +0800 [thread overview]
Message-ID: <20261110074451.220524-3-xu.xin@linux.dev> (raw)
In-Reply-To: <20261110074451.220524-1-xu.xin@linux.dev>
ksm_get_self_zero_pages() and ksm_get_self_merging_pages() both read
/proc/self/ksm_stat and differ only in the key they look up. Replace
them with a single ksm_get_self_stat(key) helper in vm_util.c, which
reads one value from /proc/self/ksm_stat by key name and accepts only
the keys used by the tests.
This is a pure refactor with no functional change; it prepares for a
new test that also needs to read ksm_rmap_items from /proc/self/ksm_stat.
No functional change intended.
Signed-off-by: Xu Xin (vivo) <xu.xin@linux.dev>
---
.../selftests/mm/ksm_functional_tests.c | 18 ++++-----
tools/testing/selftests/mm/vm_util.c | 40 ++++++-------------
tools/testing/selftests/mm/vm_util.h | 3 +-
3 files changed, 22 insertions(+), 39 deletions(-)
diff --git a/tools/testing/selftests/mm/ksm_functional_tests.c b/tools/testing/selftests/mm/ksm_functional_tests.c
index 135191f99962..2ffb97ae3120 100644
--- a/tools/testing/selftests/mm/ksm_functional_tests.c
+++ b/tools/testing/selftests/mm/ksm_functional_tests.c
@@ -85,7 +85,7 @@ static char *__mmap_and_merge_range(char val, unsigned long size, int prot,
return err_map;
}
- if (ksm_get_self_merging_pages() > 0) {
+ if (ksm_get_self_stat("ksm_merging_pages") > 0) {
ksft_print_msg("Still pages merged\n");
return err_map;
}
@@ -144,7 +144,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 && !ksm_get_self_merging_pages()) {
+ if (val && !ksm_get_self_stat("ksm_merging_pages")) {
ksft_print_msg("No pages got merged\n");
goto unmap;
}
@@ -204,7 +204,7 @@ static void test_unmerge_zero_pages(void)
ksft_print_msg("[RUN] %s\n", __func__);
- if (ksm_get_self_zero_pages() < 0) {
+ if (ksm_get_self_stat("ksm_zero_pages") < 0) {
ksft_test_result_skip("accessing \"/proc/self/ksm_stat\" failed\n");
return;
}
@@ -221,7 +221,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 != ksm_get_self_zero_pages()) {
+ if (pages_expected != ksm_get_self_stat("ksm_zero_pages")) {
ksft_test_result_fail("'ksm_zero_pages' updated after merging\n");
goto unmap;
}
@@ -234,7 +234,7 @@ static void test_unmerge_zero_pages(void)
/* Check if ksm_zero_pages is updated correctly after unmerging */
pages_expected /= 2;
- if (pages_expected != ksm_get_self_zero_pages()) {
+ if (pages_expected != ksm_get_self_stat("ksm_zero_pages")) {
ksft_test_result_fail("'ksm_zero_pages' updated after unmerging\n");
goto unmap;
}
@@ -244,7 +244,7 @@ static void test_unmerge_zero_pages(void)
*((unsigned int *)&map[offs]) = offs;
/* Now we should have no zeropages remaining. */
- if (ksm_get_self_zero_pages()) {
+ if (ksm_get_self_stat("ksm_zero_pages")) {
ksft_test_result_fail("'ksm_zero_pages' updated after write fault\n");
goto unmap;
}
@@ -671,7 +671,7 @@ static void test_fork_ksm_merging_page_count(void)
child_pid = fork();
if (!child_pid) {
init_global_file_handles();
- exit(ksm_get_self_merging_pages());
+ exit(ksm_get_self_stat("ksm_merging_pages"));
} else if (child_pid < 0) {
ksft_test_result_fail("fork() failed\n");
goto unmap;
@@ -771,7 +771,7 @@ static void test_merge_aged_pairs(void)
goto unmap;
}
- ksft_test_result(ksm_get_self_merging_pages() == 2 * pairs,
+ ksft_test_result(ksm_get_self_stat("ksm_merging_pages") == 2 * pairs,
"Pages aged by smart scan got merged\n");
unmap:
ksm_stop();
@@ -793,7 +793,7 @@ static void init_global_file_handles(void)
pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
if (pagemap_fd < 0)
ksft_exit_skip("open(\"/proc/self/pagemap\") failed\n");
- if (ksm_get_self_merging_pages() < 0)
+ if (ksm_get_self_stat("ksm_merging_pages") < 0)
ksft_exit_skip("accessing \"/proc/self/ksm_merging_pages\") failed\n");
pages_to_scan_fd = open("/sys/kernel/mm/ksm/pages_to_scan", O_RDWR);
diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c
index f26f9e4bfdbe..8f1ee1f81e36 100644
--- a/tools/testing/selftests/mm/vm_util.c
+++ b/tools/testing/selftests/mm/vm_util.c
@@ -904,14 +904,20 @@ bool detect_huge_zeropage(void)
return enabled;
}
-long ksm_get_self_zero_pages(void)
+long ksm_get_self_stat(const char *key)
{
int proc_self_ksm_stat_fd;
char buf[200];
- char *substr_ksm_zero;
+ char *substr;
size_t value_pos;
ssize_t read_size;
+ /* Only the keys actually used by the tests are accepted. */
+ if (strcmp(key, "ksm_rmap_items") &&
+ strcmp(key, "ksm_zero_pages") &&
+ strcmp(key, "ksm_merging_pages"))
+ return -EINVAL;
+
proc_self_ksm_stat_fd = open("/proc/self/ksm_stat", O_RDONLY);
if (proc_self_ksm_stat_fd < 0)
return -errno;
@@ -925,34 +931,12 @@ long ksm_get_self_zero_pages(void)
buf[read_size] = 0;
- substr_ksm_zero = strstr(buf, "ksm_zero_pages");
- if (!substr_ksm_zero)
+ substr = strstr(buf, key);
+ if (!substr)
return 0;
- value_pos = strcspn(substr_ksm_zero, "0123456789");
- return strtol(substr_ksm_zero + value_pos, NULL, 10);
-}
-
-long ksm_get_self_merging_pages(void)
-{
- int proc_self_ksm_merging_pages_fd;
- char buf[10];
- ssize_t ret;
-
- proc_self_ksm_merging_pages_fd = open("/proc/self/ksm_merging_pages",
- O_RDONLY);
- if (proc_self_ksm_merging_pages_fd < 0)
- return -errno;
-
- ret = pread(proc_self_ksm_merging_pages_fd, buf, sizeof(buf) - 1, 0);
- close(proc_self_ksm_merging_pages_fd);
- if (ret < 0)
- return -errno;
- if (!ret)
- return -EIO;
- buf[ret] = 0;
-
- return strtol(buf, NULL, 10);
+ value_pos = strcspn(substr, "0123456789");
+ return strtol(substr + value_pos, NULL, 10);
}
long ksm_get_full_scans(void)
diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
index ab1325dc6580..2b25a9eab30c 100644
--- a/tools/testing/selftests/mm/vm_util.h
+++ b/tools/testing/selftests/mm/vm_util.h
@@ -159,8 +159,7 @@ static inline int sz2ord(size_t size, size_t pagesize)
void *sys_mremap(void *old_address, unsigned long old_size,
unsigned long new_size, int flags, void *new_address);
-long ksm_get_self_zero_pages(void);
-long ksm_get_self_merging_pages(void);
+long ksm_get_self_stat(const char *key);
long ksm_get_full_scans(void);
int ksm_wait_full_scans(long nr);
int ksm_get_smart_scan(void);
--
2.34.1
next prev parent reply other threads:[~2026-11-10 7:45 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 7:43 [PATCH v2 0/4] KSM: introduce only_merge_zero_pages Xu Xin (vivo)
2026-11-10 7:44 ` [PATCH 1/4] ksm: add only_merge_zero_pages to merge only empty anonymous pages Xu Xin (vivo)
2026-11-10 7:44 ` [PATCH 2/4] ksm: skip rmap_item allocation for non-zero pages under only_merge_zero_pages Xu Xin (vivo)
2026-11-10 10:05 ` Lorenzo Stoakes (ARM)
2026-11-10 11:22 ` Xu Xin (vivo)
2026-11-10 12:42 ` Lorenzo Stoakes (ARM)
2026-11-11 8:36 ` Xu Xin (vivo)
2026-11-11 8:48 ` Lorenzo Stoakes (ARM)
2026-11-11 9:04 ` David Hildenbrand (Arm)
2026-11-11 9:08 ` David Hildenbrand (Arm)
2026-11-11 9:36 ` Xu Xin (vivo)
2026-11-10 7:44 ` Xu Xin (vivo) [this message]
2026-11-10 7:44 ` [PATCH 4/4] selftests/ksm: add test for only_merge_zero_pages Xu Xin (vivo)
2026-11-11 9:10 ` [PATCH 1/4] ksm: add only_merge_zero_pages to merge only empty anonymous pages David Hildenbrand (Arm)
2026-11-10 10:08 ` [PATCH v2 0/4] KSM: introduce only_merge_zero_pages Lorenzo Stoakes (ARM)
2026-11-10 11:34 ` Xu Xin (vivo)
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=20261110074451.220524-3-xu.xin@linux.dev \
--to=xu.xin@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=chengming.zhou@linux.dev \
--cc=corbet@lwn.net \
--cc=david@kernel.org \
--cc=link@vivo.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=odys.yuan@gmail.com \
--cc=rppt@kernel.org \
--cc=surenb@google.com \
--cc=tujinjiang@huawei.com \
--cc=vbabka@kernel.org \
--cc=xiao.wang@vivo.com \
/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.