* [PATCH] selftests/mm: disable smart scan for ksm_tests
@ 2026-08-23 18:43 Zenghui Yu
2026-08-24 10:33 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 3+ messages in thread
From: Zenghui Yu @ 2026-08-23 18:43 UTC (permalink / raw)
To: linux-mm, linux-kselftest, linux-kernel
Cc: akpm, david, xu.xin16, chengming.zhou, shr, ljs, vbabka, rppt,
surenb, mhocko, shuah, Zenghui Yu (Huawei)
From: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev>
The "KSM NUMA merging" test allocates two identical pages on two NUMA nodes
and verifies KSM will merge these two pages after 2 scans (see
ksm_merge_pages()). But when smart scan is enabled, pages that have
previously not been de-duplicated may get skipped for some scans. Verifying
KSM behavior after only 2 scans may not be enough.
$ ./ksm_tests -N -d
TAP version 13
1..1
pages_shared : 0
pages_sharing : 0
max_page_sharing : 256
full_scans : 211
pages_unshared : 1
pages_volatile : 2
stable_node_chains: 0
stable_node_dups : 0
general_profit : -128
ksm_rmap_items 2
ksm_zero_pages 0
ksm_merging_pages 0
ksm_process_profit -128
ksm_merge_any: no
ksm_mergeable: yes
not ok 1 KSM NUMA merging
# Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0
This specific test fails because KSM started scanning the second page
whilst the first page had already been scanned for 16 times
(ksm_rmap_item::age of page 0 is 16 greater than page 1). It's not
difficult to infer that should_skip_rmap_item() cannot be false at the same
time for these two pages - they cannot be merged even after 211 full scans.
Given the current implementation of smart scan, it may not be appropriate
to enable it for selftests. Let's disable it for now.
Signed-off-by: Zenghui Yu (Huawei) <zenghui.yu@linux.dev>
---
tools/testing/selftests/mm/ksm_tests.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/testing/selftests/mm/ksm_tests.c b/tools/testing/selftests/mm/ksm_tests.c
index 5fd7792a0d47..e72681090ff9 100644
--- a/tools/testing/selftests/mm/ksm_tests.c
+++ b/tools/testing/selftests/mm/ksm_tests.c
@@ -33,6 +33,7 @@ struct ksm_sysfs {
unsigned long pages_to_scan;
unsigned long run;
unsigned long sleep_millisecs;
+ unsigned long smart_scan;
unsigned long stable_node_chains_prune_millisecs;
unsigned long use_zero_pages;
};
@@ -293,6 +294,7 @@ static int ksm_save_def(struct ksm_sysfs *ksm_sysfs)
ksm_read_sysfs(KSM_FP("sleep_millisecs"), &ksm_sysfs->sleep_millisecs) ||
ksm_read_sysfs(KSM_FP("pages_to_scan"), &ksm_sysfs->pages_to_scan) ||
ksm_read_sysfs(KSM_FP("run"), &ksm_sysfs->run) ||
+ ksm_read_sysfs(KSM_FP("smart_scan"), &ksm_sysfs->smart_scan) ||
ksm_read_sysfs(KSM_FP("stable_node_chains_prune_millisecs"),
&ksm_sysfs->stable_node_chains_prune_millisecs) ||
ksm_read_sysfs(KSM_FP("use_zero_pages"), &ksm_sysfs->use_zero_pages))
@@ -309,6 +311,7 @@ static int ksm_restore(struct ksm_sysfs *ksm_sysfs)
ksm_write_sysfs(KSM_FP("pages_to_scan"), ksm_sysfs->pages_to_scan) ||
ksm_write_sysfs(KSM_FP("run"), ksm_sysfs->run) ||
ksm_write_sysfs(KSM_FP("sleep_millisecs"), ksm_sysfs->sleep_millisecs) ||
+ ksm_write_sysfs(KSM_FP("smart_scan"), ksm_sysfs->smart_scan) ||
ksm_write_sysfs(KSM_FP("stable_node_chains_prune_millisecs"),
ksm_sysfs->stable_node_chains_prune_millisecs) ||
ksm_write_sysfs(KSM_FP("use_zero_pages"), ksm_sysfs->use_zero_pages))
@@ -846,6 +849,7 @@ int main(int argc, char *argv[])
if (ksm_write_sysfs(KSM_FP("run"), 2) ||
ksm_write_sysfs(KSM_FP("sleep_millisecs"), 0) ||
+ ksm_write_sysfs(KSM_FP("smart_scan"), 0) ||
(numa_available() ? 0 :
ksm_write_sysfs(KSM_FP("merge_across_nodes"), 1)) ||
ksm_write_sysfs(KSM_FP("pages_to_scan"), page_count))
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] selftests/mm: disable smart scan for ksm_tests
2026-08-23 18:43 [PATCH] selftests/mm: disable smart scan for ksm_tests Zenghui Yu
@ 2026-08-24 10:33 ` David Hildenbrand (Arm)
2026-08-24 11:55 ` Zenghui Yu
0 siblings, 1 reply; 3+ messages in thread
From: David Hildenbrand (Arm) @ 2026-08-24 10:33 UTC (permalink / raw)
To: Zenghui Yu, linux-mm, linux-kselftest, linux-kernel
Cc: akpm, xu.xin16, chengming.zhou, shr, ljs, vbabka, rppt, surenb,
mhocko, shuah
On 8/23/26 20:43, Zenghui Yu wrote:
> From: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev>
>
> The "KSM NUMA merging" test allocates two identical pages on two NUMA nodes
> and verifies KSM will merge these two pages after 2 scans (see
> ksm_merge_pages()). But when smart scan is enabled, pages that have
> previously not been de-duplicated may get skipped for some scans. Verifying
> KSM behavior after only 2 scans may not be enough.
>
> $ ./ksm_tests -N -d
> TAP version 13
> 1..1
> pages_shared : 0
> pages_sharing : 0
> max_page_sharing : 256
> full_scans : 211
> pages_unshared : 1
> pages_volatile : 2
> stable_node_chains: 0
> stable_node_dups : 0
> general_profit : -128
> ksm_rmap_items 2
> ksm_zero_pages 0
> ksm_merging_pages 0
> ksm_process_profit -128
> ksm_merge_any: no
> ksm_mergeable: yes
> not ok 1 KSM NUMA merging
> # Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0
How did you reproduce this? Is this an actual test result?
~/linux/tools/testing/selftests/mm$ cat /sys/kernel/mm/ksm/smart_scan
1
~/linux/tools/testing/selftests/mm$ sudo ./ksm_tests -N -d
TAP version 13
1..1
pages_shared : 1
pages_sharing : 1
max_page_sharing : 256
full_scans : 1283
pages_unshared : 0
pages_volatile : 0
stable_node_chains: 0
stable_node_dups : 0
general_profit : 3968
ksm_rmap_items 2
ksm_zero_pages 0
ksm_merging_pages 2
ksm_process_profit 8064
ksm_merge_any: no
ksm_mergeable: yes
ok 1 KSM NUMA merging
# Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0
>
> This specific test fails because KSM started scanning the second page
> whilst the first page had already been scanned for 16 times
How is that supposed to happen? The sequence we have is:
numa1_map_ptr = numa_alloc_onnode(page_size, first_node);
numa2_map_ptr = numa_alloc_onnode(page_size, second_node);
...
memset(numa1_map_ptr, '*', page_size);
memset(numa2_map_ptr, '*', page_size);
...
if (ksm_merge_pages(merge_type, numa1_map_ptr, page_size, start_time, timeout) ...
KSM smart scan operates on rmap entries. rmap entries are per MM.
--
Cheers,
David
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] selftests/mm: disable smart scan for ksm_tests
2026-08-24 10:33 ` David Hildenbrand (Arm)
@ 2026-08-24 11:55 ` Zenghui Yu
0 siblings, 0 replies; 3+ messages in thread
From: Zenghui Yu @ 2026-08-24 11:55 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: linux-mm, linux-kselftest, linux-kernel, akpm, xu.xin16,
chengming.zhou, shr, ljs, vbabka, rppt, surenb, mhocko, shuah
Hi David,
On 8/24/26 6:33 PM, David Hildenbrand (Arm) wrote:
> On 8/23/26 20:43, Zenghui Yu wrote:
> > From: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev>
> >
> > The "KSM NUMA merging" test allocates two identical pages on two NUMA nodes
> > and verifies KSM will merge these two pages after 2 scans (see
> > ksm_merge_pages()). But when smart scan is enabled, pages that have
> > previously not been de-duplicated may get skipped for some scans. Verifying
> > KSM behavior after only 2 scans may not be enough.
> >
> > $ ./ksm_tests -N -d
> > TAP version 13
> > 1..1
> > pages_shared : 0
> > pages_sharing : 0
> > max_page_sharing : 256
> > full_scans : 211
> > pages_unshared : 1
> > pages_volatile : 2
> > stable_node_chains: 0
> > stable_node_dups : 0
> > general_profit : -128
> > ksm_rmap_items 2
> > ksm_zero_pages 0
> > ksm_merging_pages 0
> > ksm_process_profit -128
> > ksm_merge_any: no
> > ksm_mergeable: yes
> > not ok 1 KSM NUMA merging
> > # Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0
>
> How did you reproduce this? Is this an actual test result?
I reproduced this in a guest, using arm64's virtconfig. I don't think there
is any particular configuration. This is an actual test result but this is
not 100% reproducible.
> ~/linux/tools/testing/selftests/mm$ cat /sys/kernel/mm/ksm/smart_scan
> 1
> ~/linux/tools/testing/selftests/mm$ sudo ./ksm_tests -N -d
> TAP version 13
> 1..1
> pages_shared : 1
> pages_sharing : 1
> max_page_sharing : 256
> full_scans : 1283
> pages_unshared : 0
> pages_volatile : 0
> stable_node_chains: 0
> stable_node_dups : 0
> general_profit : 3968
> ksm_rmap_items 2
> ksm_zero_pages 0
> ksm_merging_pages 2
> ksm_process_profit 8064
> ksm_merge_any: no
> ksm_mergeable: yes
> ok 1 KSM NUMA merging
> # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0
>
>
> >
> > This specific test fails because KSM started scanning the second page
> > whilst the first page had already been scanned for 16 times
>
> How is that supposed to happen? The sequence we have is:
>
> numa1_map_ptr = numa_alloc_onnode(page_size, first_node);
> numa2_map_ptr = numa_alloc_onnode(page_size, second_node);
> ...
> memset(numa1_map_ptr, '*', page_size);
> memset(numa2_map_ptr, '*', page_size);
> ...
> if (ksm_merge_pages(merge_type, numa1_map_ptr, page_size, start_time, timeout) ...
>
> KSM smart scan operates on rmap entries. rmap entries are per MM.
This is what I had for debugging:
diff --git a/mm/ksm.c b/mm/ksm.c
index 49d48d1e0998..aec2a292cba5 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -2495,6 +2495,8 @@ static bool should_skip_rmap_item(struct folio *folio,
if (age != U8_MAX)
rmap_item->age++;
+ pr_info("addr=%lx age=%u r_skips=%u\n", rmap_item->address, age, rmap_item->remaining_skips);
+
/*
* Smaller ages are not skipped, they need to get a chance to go
* through the different phases of the KSM merging.
@@ -2820,8 +2822,10 @@ static void ksm_do_scan(unsigned int scan_npages)
while (scan_npages-- && likely(!freezing(current))) {
cond_resched();
rmap_item = scan_get_next_rmap_item(&page);
- if (!rmap_item)
+ if (!rmap_item) {
+ pr_info("\n");
return;
+ }
cmp_and_merge_page(page, rmap_item);
put_page(page);
ksm_pages_scanned++;
$ dmesg
[ 309.111144] addr=7fff959d4000 age=0 r_skips=0
[ 309.111215] addr=7fff959d4000 age=1 r_skips=0
[ 309.111223] addr=7fff959d4101 age=2 r_skips=0
[ 309.111230] addr=7fff959d4102 age=3 r_skips=0
[ 309.111237] addr=7fff959d4103 age=4 r_skips=1
[ 309.111241] addr=7fff959d4000 age=5 r_skips=0
[ 309.111248] addr=7fff959d4105 age=6 r_skips=2
[ 309.111251] addr=7fff959d4000 age=7 r_skips=1
[ 309.111255] addr=7fff959d4000 age=8 r_skips=0
[ 309.111262] addr=7fff959d4108 age=9 r_skips=4
[ 309.111265] addr=7fff959d4000 age=10 r_skips=3
[ 309.111269] addr=7fff959d4000 age=11 r_skips=2
[ 309.111272] addr=7fff959d4000 age=12 r_skips=1
[ 309.111297] addr=7fff959ac000 age=0 r_skips=0
[ 309.111303] addr=7fff959d4000 age=13 r_skips=0 -> page 0's age is 13 greater that page 1's
[ 309.111311] addr=7fff959ac000 age=1 r_skips=0
[ 309.111316] addr=7fff959d410d age=14 r_skips=8
[ 309.111320] addr=7fff959ac10e age=2 r_skips=0
[ 309.111325] addr=7fff959d4000 age=15 r_skips=7
[ 309.111329] addr=7fff959ac10f age=3 r_skips=0
[ 309.111334] addr=7fff959d4000 age=16 r_skips=6
[ 309.111338] addr=7fff959ac110 age=4 r_skips=1
[ 309.111339] addr=7fff959d4000 age=17 r_skips=5
[ 309.111343] addr=7fff959ac000 age=5 r_skips=0
[ 309.111348] addr=7fff959d4000 age=18 r_skips=4
[ 309.111352] addr=7fff959ac112 age=6 r_skips=2
[ 309.111353] addr=7fff959d4000 age=19 r_skips=3
[ 309.111357] addr=7fff959ac000 age=7 r_skips=1
[ 309.111358] addr=7fff959d4000 age=20 r_skips=2
[ 309.111362] addr=7fff959ac000 age=8 r_skips=0
[ 309.111367] addr=7fff959d4000 age=21 r_skips=1
[ 309.111372] addr=7fff959ac115 age=9 r_skips=4
[ 309.111373] addr=7fff959d4000 age=22 r_skips=0 -> remaining_skips can not be 0 at the same time for both pages
Not sure if I had misunderstood something.
Thanks,
Zenghui
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-24 11:55 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-23 18:43 [PATCH] selftests/mm: disable smart scan for ksm_tests Zenghui Yu
2026-08-24 10:33 ` David Hildenbrand (Arm)
2026-08-24 11:55 ` Zenghui Yu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox