KSM: Mark new vma for deduplication
Subsystems (5)
v3 cover KSM: Mark new vma for deduplication
Good time of day List,
this tiny series of patches implement feature for auto deduping all anonymous memory.mark_new_vma - new ksm sysfs interface
Every time then new vma created and mark_new_vma set to 1, then will be vma marked as VM_MERGEABLE and added to ksm queue. This can produce small overheads
(I have not catch any problems or slowdown)
This is useful for:
Android (CM) devs which implement ksm support with patching system. Users of tiny pc.
Servers what not use KVM but use something very releated, like containers.
Can be pulled from:
https://github.com/Nefelim4ag/linux.git ksm_improvements
For tests:
I have tested it and it working very good. For testing apply it and enable ksm:
echo 1 | sudo tee /sys/kernel/mm/ksm/run
This show how much memory saved:
echo $[$(cat /sys/kernel/mm/ksm/pages_shared)*$(getconf PAGE_SIZE)/1024 ]KB
On my system i save ~1% of memory 26 Mb/2100 Mb (deduped)/(used)
v2:
Added Kconfig for control default value of mark_new_vma Added sysfs interface for control mark_new_vma Splitted in several patches
v3:
Documentation for ksm changed for clarify new cha
Timofey Titovets (4):
KSM: Add auto flag new VMA as VM_MERGEABLE
KSM: Add to sysfs - mark_new_vma
KSM: Add config to control mark_new_vma
KSM: mark_new_vma added to Documentation.
Documentation/vm/ksm.txt | 7 +++++++ include/linux/ksm.h | 39 +++++++++++++++++++++++++++++++++++++++ mm/Kconfig | 7 +++++++ mm/ksm.c | 39 ++++++++++++++++++++++++++++++++++++++- mm/mmap.c | 17 +++++++++++++++++ 5 files changed, 108 insertions(+), 1 deletion(-)
Signature · 7 lines
2.1.3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 1/4 KSM: Add auto flag new VMA as VM_MERGEABLE
Implement two functions:ksm_vm_flags_mod() - if existing flags supported by ksm - then mark like VM_MERGEABLE ksm_vma_add_new() - If vma marked as VM_MERGEABLE add it to ksm page queue
--- include/linux/ksm.h | 31 +++++++++++++++++++++++++++++++ mm/mmap.c | 17 +++++++++++++++++ 2 files changed, 48 insertions(+)
include/linux/ksm.h +31 -0
@@ -76,6 +76,29 @@ struct page *ksm_might_need_to_copy(struct page *page,int rmap_walk_ksm (struct page *page,struct rmap_walk_control *rwc);void ksm_migrate_page (struct page *newpage,struct page *oldpage); +/* +* Allow to mark new vma as VM_MERGEABLE +*/ +#ifndef VM_SAO +#define VM_SAO 0 +#endif +static inline void ksm_vm_flags_mod (unsigned long *vm_flags) +{ +if (*vm_flags & (VM_MERGEABLE |VM_SHARED |VM_MAYSHARE | +VM_PFNMAP |VM_IO |VM_DONTEXPAND | +VM_HUGETLB |VM_NONLINEAR |VM_MIXEDMAP |VM_SAO ) ) +return ; + *vm_flags |=VM_MERGEABLE ; +} + +static inline void ksm_vma_add_new (struct vm_area_struct *vma) +{ +struct mm_struct *mm = vma->vm_mm; +if (!test_bit (MMF_VM_MERGEABLE , &mm->flags)) { +__ksm_enter (mm); + } +} +#else /* !CONFIG_KSM */ static inline int ksm_fork (struct mm_struct *mm,struct mm_struct *oldmm)
@@ -92,6 +115,14 @@ static inline int PageKsm(struct page *page)return 0 ; } +static inline void ksm_vm_flags_mod (unsigned long *vm_flags_p) +{ +} + +void ksm_vma_add_new (struct vm_area_struct *vma) +{ +} +#ifdef CONFIG_MMU static inline int ksm_madvise (struct vm_area_struct *vma,unsigned long start,unsigned long end,int advice,unsigned long *vm_flags)
mm/mmap.c +17 -0
@@ -41,6 +41,7 @@#include <linux/notifier.h> #include <linux/memory.h> #include <linux/printk.h> +#include <linux/ksm.h> #include <asm/uaccess.h> #include <asm/cacheflush.h>
@@ -911,10 +912,14 @@ again: remove_next = 1 + (end > next->vm_end);vma_gap_update (next); else mm->highest_vm_end = end; + }else { +if (next && !insert) +ksm_vma_add_new (next); }if (insert && file)uprobe_mmap (insert); +ksm_vma_add_new (vma);validate_mm (mm);return 0 ;
@@ -1307,6 +1312,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, vm_flags =calc_vm_prot_bits (prot) |calc_vm_flag_bits (flags) | mm->def_flags |VM_MAYREAD |VM_MAYWRITE |VM_MAYEXEC ; +/* If ksm is enabled, we add VM_MERGABLE to new VMAs. */ +ksm_vm_flags_mod (&vm_flags); +if (flags &MAP_LOCKED )if (!can_do_mlock ())return -EPERM ;
@@ -1648,6 +1656,7 @@ munmap_back:allow_write_access (file); } file = vma->vm_file; +ksm_vma_add_new (vma); out:perf_event_mmap (vma);
@@ -2484,6 +2493,8 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,else err =vma_adjust (vma, vma->vm_start, addr, vma->vm_pgoff, new); +ksm_vma_add_new (vma); +/* Success. */ if (!err)return 0 ;
@@ -2659,6 +2670,9 @@ static unsigned long do_brk(unsigned long addr, unsigned long len)if (error)return error; +/* If ksm is enabled, we add VM_MERGABLE to new VMAs. */ +ksm_vm_flags_mod (&flags); +/* * mm->mmap_sem is required to protect against another thread * changing the mappings in case we sleep.
@@ -2708,6 +2722,7 @@ static unsigned long do_brk(unsigned long addr, unsigned long len) vma->vm_flags = flags; vma->vm_page_prot =vm_get_page_prot (flags);vma_link (mm, vma, prev, rb_link, rb_parent); +ksm_vma_add_new (vma); out:perf_event_mmap (vma); mm->total_vm += len >>PAGE_SHIFT ;
@@ -2887,6 +2902,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, new_vma->vm_ops->open (new_vma);vma_link (mm, new_vma, prev, rb_link, rb_parent); *need_rmap_locks = false; +ksm_vma_add_new (new_vma); } }return new_vma;
@@ -3004,6 +3020,7 @@ static struct vm_area_struct *__install_special_mapping( mm->total_vm += len >>PAGE_SHIFT ;perf_event_mmap (vma); +ksm_vma_add_new (vma);return vma;
Signature · 7 lines
2.1.3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 2/4 KSM: Add to sysfs - mark_new_vma
In reply to Timofey TitovetsIt allow to control user mark new vma as VM_MERGEABLE or not Create new sysfs interface /sys/kernel/mm/ksm/mark_new_vma
1 - enabled - mark new allocated vma as VM_MERGEABLE and add it to ksm queue 0 - disable it
--- include/linux/ksm.h | 10 +++++++++- mm/ksm.c | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-)
include/linux/ksm.h +9 -1
@@ -76,6 +76,12 @@ struct page *ksm_might_need_to_copy(struct page *page,int rmap_walk_ksm (struct page *page,struct rmap_walk_control *rwc);void ksm_migrate_page (struct page *newpage,struct page *oldpage); + +/* Mark new vma as mergeable */ +#define ALLOW 1 +#define DENY 0 +extern unsigned mark_new_vma__read_mostly ; +/* * Allow to mark new vma as VM_MERGEABLE */
@@ -84,6 +90,8 @@ void ksm_migrate_page(struct page *newpage, struct page *oldpage);#endif static inline void ksm_vm_flags_mod (unsigned long *vm_flags) { +if (!mark_new_vma) +return ;if (*vm_flags & (VM_MERGEABLE |VM_SHARED |VM_MAYSHARE |VM_PFNMAP |VM_IO |VM_DONTEXPAND |VM_HUGETLB |VM_NONLINEAR |VM_MIXEDMAP |VM_SAO ) )
@@ -94,7 +102,7 @@ static inline void ksm_vm_flags_mod(unsigned long *vm_flags)static inline void ksm_vma_add_new (struct vm_area_struct *vma) {struct mm_struct *mm = vma->vm_mm; -if (!test_bit (MMF_VM_MERGEABLE , &mm->flags)) { +if (mark_new_vma && !test_bit (MMF_VM_MERGEABLE , &mm->flags)) {__ksm_enter (mm); } }
mm/ksm.c +38 -1
@@ -223,6 +223,12 @@ static unsigned int ksm_thread_pages_to_scan = 100;/* Milliseconds ksmd should sleep between batches */ static unsigned int ksm_thread_sleep_millisecs =20 ; +/* Mark new vma as mergeable */ +#ifndef CONFIG_KSM_MARK_NEW_VMA +#define CONFIG_KSM_MARK_NEW_VMA DENY +#endif +unsigned mark_new_vma =CONFIG_KSM_MARK_NEW_VMA ; +#ifdef CONFIG_NUMA /* Zeroed when merging across nodes is not allowed */ static unsigned int ksm_merge_across_nodes =1 ;
@@ -2127,6 +2133,34 @@ static ssize_t pages_to_scan_store(struct kobject *kobj, }KSM_ATTR (pages_to_scan); +static ssize_t mark_new_vma_show (struct kobject *kobj,struct kobj_attribute *attr, +char *buf) +{ +return sprintf (buf,"%u\n" , mark_new_vma); +} +static ssize_t mark_new_vma_store (struct kobject *kobj, +struct kobj_attribute *attr, +const char *buf,size_t count) +{ +int err; +unsigned long flags; + + err =kstrtoul (buf,10 , &flags); +if (err || flags >UINT_MAX || flags >ALLOW ) +return -EINVAL ; + +/* +* ALLOW = 1 - sets allow for mark new vma as +* VM_MERGEABLE and adding it to ksm +* DENY = 0 - disable it +*/ +if (mark_new_vma != flags) { + mark_new_vma = flags; + } +return count; +} +KSM_ATTR (mark_new_vma); +static ssize_t run_show (struct kobject *kobj,struct kobj_attribute *attr,char *buf) {
@@ -2287,6 +2321,7 @@ static struct attribute *ksm_attrs[] = { &pages_unshared_attr.attr, &pages_volatile_attr.attr, &full_scans_attr.attr, + &mark_new_vma_attr.attr, #ifdef CONFIG_NUMA &merge_across_nodes_attr.attr, #endif
@@ -2323,7 +2358,9 @@ static int __init ksm_init(void) goto out_free; }#else - ksm_run =KSM_RUN_MERGE ;/* no way for user to start it */ +/* no way for user to start it */ + mark_new_vma =ALLOW ; + ksm_run =KSM_RUN_MERGE ;#endif /* CONFIG_SYSFS */
Signature · 7 lines
2.1.3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 3/4 KSM: Add config to control mark_new_vma
In reply to Timofey TitovetsAllowing to control mark_new_vma default value
Allowing work ksm on early allocated vmas
--- mm/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
mm/Kconfig +7 -0
@@ -340,6 +340,13 @@ config KSM until a program has madvised that an area is MADV_MERGEABLE, and root has set /sys/kernel/mm/ksm/run to 1 (if CONFIG_SYSFS is set). +config KSM_MARK_NEW_VMA + int "Marking new vma pages as VM_MERGEABLE" + depends on KSM + default 0 + range 0 1 + help + config DEFAULT_MMAP_MIN_ADDR int "Low address space to protect from user allocation" depends on MMU
Signature · 7 lines
2.1.3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v3 4/4 KSM: mark_new_vma added to Documentation.
In reply to Timofey Titovets--- Documentation/vm/ksm.txt | 7 +++++++ 1 file changed, 7 insertions(+)
Documentation/vm/ksm.txt +7 -0
@@ -24,6 +24,8 @@ KSM only operates on those areas of address space which an application has advised to be likely candidates for merging, by using the madvise(2) system call: int madvise(addr, length, MADV_MERGEABLE). +Also KSM can mark anonymous memory as mergeable, see below. + The app may call int madvise(addr, length, MADV_UNMERGEABLE) to cancel that advice and restore unshared pages: whereupon KSM unmerges whatever it merged in that range. Note: this unmerging call may suddenly require
@@ -73,6 +75,11 @@ merge_across_nodes - specifies if pages from different numa nodes can be merged. merge_across_nodes, to remerge according to the new setting. Default: 1 (merging across nodes as in earlier releases) +mark_new_vma - set 0 to disallow ksm marking every new allocated anonymous + memory as mergeable. + set 1 to allow ksm mark every new allocated anonymous memory + as mergeable + run - set 0 to stop ksmd from running but keep merged pages, set 1 to run ksmd e.g. "echo 1 > /sys/kernel/mm/ksm/run", set 2 to stop ksmd and unmerge all pages currently merged,
Signature · 7 lines
2.1.3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>