Skip to content

Commit e294206

Browse files
xu xinakpm00
authored andcommitted
ksm: count all zero pages placed by KSM
As pages_sharing and pages_shared don't include the number of zero pages merged by KSM, we cannot know how many pages are zero pages placed by KSM when enabling use_zero_pages, which leads to KSM not being transparent with all actual merged pages by KSM. In the early days of use_zero_pages, zero-pages was unable to get unshared by the ways like MADV_UNMERGEABLE so it's hard to count how many times one of those zeropages was then unmerged. But now, unsharing KSM-placed zero page accurately has been achieved, so we can easily count both how many times a page full of zeroes was merged with zero-page and how many times one of those pages was then unmerged. and so, it helps to estimate memory demands when each and every shared page could get unshared. So we add ksm_zero_pages under /sys/kernel/mm/ksm/ to show the number of all zero pages placed by KSM. Meanwhile, we update the Documentation. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: xu xin <[email protected]> Acked-by: David Hildenbrand <[email protected]> Cc: Claudio Imbrenda <[email protected]> Cc: Xuexin Jiang <[email protected]> Reviewed-by: Xiaokai Ran <[email protected]> Reviewed-by: Yang Yang <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7927147 commit e294206

File tree

5 files changed

+37
-1
lines changed

5 files changed

+37
-1
lines changed

Documentation/admin-guide/mm/ksm.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,13 @@ stable_node_chains
173173
the number of KSM pages that hit the ``max_page_sharing`` limit
174174
stable_node_dups
175175
number of duplicated KSM pages
176+
ksm_zero_pages
177+
how many zero pages that are still mapped into processes were mapped by
178+
KSM when deduplicating.
179+
180+
When ``use_zero_pages`` is/was enabled, the sum of ``pages_sharing`` +
181+
``ksm_zero_pages`` represents the actual number of pages saved by KSM.
182+
if ``use_zero_pages`` has never been enabled, ``ksm_zero_pages`` is 0.
176183

177184
A high ratio of ``pages_sharing`` to ``pages_shared`` indicates good
178185
sharing, but a high ratio of ``pages_unshared`` to ``pages_sharing``

include/linux/ksm.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ void __ksm_exit(struct mm_struct *mm);
3333
*/
3434
#define is_ksm_zero_pte(pte) (is_zero_pfn(pte_pfn(pte)) && pte_dirty(pte))
3535

36+
extern unsigned long ksm_zero_pages;
37+
38+
static inline void ksm_might_unmap_zero_page(pte_t pte)
39+
{
40+
if (is_ksm_zero_pte(pte))
41+
ksm_zero_pages--;
42+
}
43+
3644
static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm)
3745
{
3846
int ret;
@@ -101,6 +109,10 @@ static inline void ksm_exit(struct mm_struct *mm)
101109
{
102110
}
103111

112+
static inline void ksm_might_unmap_zero_page(pte_t pte)
113+
{
114+
}
115+
104116
#ifdef CONFIG_MEMORY_FAILURE
105117
static inline void collect_procs_ksm(struct page *page,
106118
struct list_head *to_kill, int force_early)

mm/khugepaged.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/page_table_check.h>
2020
#include <linux/swapops.h>
2121
#include <linux/shmem_fs.h>
22+
#include <linux/ksm.h>
2223

2324
#include <asm/tlb.h>
2425
#include <asm/pgalloc.h>
@@ -709,6 +710,7 @@ static void __collapse_huge_page_copy_succeeded(pte_t *pte,
709710
spin_lock(ptl);
710711
ptep_clear(vma->vm_mm, address, _pte);
711712
spin_unlock(ptl);
713+
ksm_might_unmap_zero_page(pteval);
712714
}
713715
} else {
714716
src_page = pte_page(pteval);

mm/ksm.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,9 @@ static unsigned int zero_checksum __read_mostly;
278278
/* Whether to merge empty (zeroed) pages with actual zero pages */
279279
static bool ksm_use_zero_pages __read_mostly;
280280

281+
/* The number of zero pages which is placed by KSM */
282+
unsigned long ksm_zero_pages;
283+
281284
#ifdef CONFIG_NUMA
282285
/* Zeroed when merging across nodes is not allowed */
283286
static unsigned int ksm_merge_across_nodes = 1;
@@ -1229,6 +1232,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
12291232
* the dirty bit in zero page's PTE is set.
12301233
*/
12311234
newpte = pte_mkdirty(pte_mkspecial(pfn_pte(page_to_pfn(kpage), vma->vm_page_prot)));
1235+
ksm_zero_pages++;
12321236
/*
12331237
* We're replacing an anonymous page with a zero page, which is
12341238
* not anonymous. We need to do proper accounting otherwise we
@@ -3356,6 +3360,13 @@ static ssize_t pages_volatile_show(struct kobject *kobj,
33563360
}
33573361
KSM_ATTR_RO(pages_volatile);
33583362

3363+
static ssize_t ksm_zero_pages_show(struct kobject *kobj,
3364+
struct kobj_attribute *attr, char *buf)
3365+
{
3366+
return sysfs_emit(buf, "%ld\n", ksm_zero_pages);
3367+
}
3368+
KSM_ATTR_RO(ksm_zero_pages);
3369+
33593370
static ssize_t general_profit_show(struct kobject *kobj,
33603371
struct kobj_attribute *attr, char *buf)
33613372
{
@@ -3423,6 +3434,7 @@ static struct attribute *ksm_attrs[] = {
34233434
&pages_sharing_attr.attr,
34243435
&pages_unshared_attr.attr,
34253436
&pages_volatile_attr.attr,
3437+
&ksm_zero_pages_attr.attr,
34263438
&full_scans_attr.attr,
34273439
#ifdef CONFIG_NUMA
34283440
&merge_across_nodes_attr.attr,

mm/memory.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1433,8 +1433,10 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
14331433
tlb_remove_tlb_entry(tlb, pte, addr);
14341434
zap_install_uffd_wp_if_needed(vma, addr, pte, details,
14351435
ptent);
1436-
if (unlikely(!page))
1436+
if (unlikely(!page)) {
1437+
ksm_might_unmap_zero_page(ptent);
14371438
continue;
1439+
}
14381440

14391441
delay_rmap = 0;
14401442
if (!PageAnon(page)) {
@@ -3128,6 +3130,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
31283130
inc_mm_counter(mm, MM_ANONPAGES);
31293131
}
31303132
} else {
3133+
ksm_might_unmap_zero_page(vmf->orig_pte);
31313134
inc_mm_counter(mm, MM_ANONPAGES);
31323135
}
31333136
flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte));

0 commit comments

Comments
 (0)