MADV_FREE support
Subsystems (16)
v12 cover MADV_FREE support
This patch enable MADV_FREE hint for madvise syscall, which have been supported by other OSes. [PATCH 1] includes the details.
[1] support MADVISE_FREE for !THP page so if VM encounter THP page in syscall context, it splits THP page.
[2-7] is to preparing to call madvise syscall without THP plitting
[8] enable THP page support for MADV_FREE.
* From v11
* Fix arm build - Steve
* Separate patch for arm and arm64 - Steve
* Remove unnecessary check - Kirill
* Skip non-vm_normal page - Kirill
* Add Acked-by - Zhang
* Sparc64 build fix
* Pagetable walker THP handling fix
* From v10
* Add Acked-by from arch stuff(x86, s390)
* Pagewalker based pagetable working - Kirill
* Fix try_to_unmap_one broken with hwpoison - Kirill
* Use VM_BUG_ON_PAGE in madvise_free_pmd - Kirill
* Fix pgtable-3level.h for arm - Steve
* From v9
* Add Acked-by - Rik
* Add THP page support - Kirill
* From v8
* Rebased-on v3.16-rc2-mmotm-2014-06-25-16-44
* From v7
* Rebased-on next-20140613
* From v6
* Remove page from swapcache in syscal time
* Move utility functions from memory.c to madvise.c - Johannes
* Rename untilify functtions - Johannes
* Remove unnecessary checks from vmscan.c - Johannes
* Rebased-on v3.15-rc5-mmotm-2014-05-16-16-56
* Drop Reviewe-by because there was some changes since then.
* From v5
* Fix PPC problem which don't flush TLB - Rik
* Remove unnecessary lazyfree_range stub function - Rik
* Rebased on v3.15-rc5
* From v4
* Add Reviewed-by: Zhang Yanfei
* Rebase on v3.15-rc1-mmotm-2014-04-15-16-14
* From v3
* Add "how to work part" in description - Zhang
* Add page_discardable utility function - Zhang
* Clean up
* From v2
* Remove forceful dirty marking of swap-readed page - Johannes
* Remove deactivation logic of lazyfreed page
* Rebased on 3.14
* Remove RFC tag
* From v1
* Use custom page table walker for madvise_free - Johannes
* Remove PG_lazypage flag - Johannes
* Do madvise_dontneed instead of madvise_freein swapless system
Minchan Kim (8):
[1] mm: support madvise(MADV_FREE)
[2] x86: add pmd_[dirty|mkclean] for THP
[3] sparc: add pmd_[dirty|mkclean] for THP
[4] powerpc: add pmd_[dirty|mkclean] for THP
[5] s390: add pmd_[dirty|mkclean] for THP
[6] arm: add pmd_[dirty|mkclean] for THP
[7] arm64: add pmd_[dirty|mkclean] for THP
[8] mm: Don't split THP page when syscall is called
arch/arm/include/asm/pgtable-3level.h | 3 + arch/arm64/include/asm/pgtable.h | 2 + arch/powerpc/include/asm/pgtable-ppc64.h | 2 + arch/s390/include/asm/pgtable.h | 12 +++ arch/sparc/include/asm/pgtable_64.h | 16 ++++ arch/x86/include/asm/pgtable.h | 10 ++ include/linux/huge_mm.h | 4 + include/linux/rmap.h | 9 +- include/linux/vm_event_item.h | 1 + include/uapi/asm-generic/mman-common.h | 1 + mm/huge_memory.c | 35 +++++++ mm/madvise.c | 155 +++++++++++++++++++++++++++++++ mm/rmap.c | 46 ++++++++- mm/vmscan.c | 64 +++++++++---- mm/vmstat.c | 1 + 15 files changed, 341 insertions(+), 20 deletions(-)
Signature · 1 line
2.0.0
PATCH v12 1/8 mm: support madvise(MADV_FREE)
Linux doesn't have an ability to free pages lazy while other OS already have been supported that named by madvise(MADV_FREE).
The gain is clear that kernel can discard freed pages rather than swapping out or OOM if memory pressure happens.
Without memory pressure, freed pages would be reused by userspace without another additional overhead(ex, page fault + allocation
+ zeroing).
How to work is following as.
When madvise syscall is called, VM clears dirty bit of ptes of the range. If memory pressure happens, VM checks dirty bit of page table and if it found still "clean", it means it's a "lazyfree pages" so VM could discard the page instead of swapping out. Once there was store operation for the page before VM peek a page to reclaim, dirty bit is set so VM can swap out the page instead of discarding.
Firstly, heavy users would be general allocators(ex, jemalloc, tcmalloc and hope glibc supports it) and jemalloc/tcmalloc already have supported the feature for other OS(ex, FreeBSD)
barrios@blaptop:~/benchmark/ebizzy$ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 2 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 42 Stepping: 7 CPU MHz: 2801.000 BogoMIPS: 5581.64 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 4096K NUMA node0 CPU(s): 0-3
ebizzy benchmark(./ebizzy -S 10 -n 512)
vanilla-jemalloc MADV_free-jemalloc
1 thread
records: 10 records: 10 avg: 7682.10 avg: 15306.10 std: 62.35(0.81%) std: 347.99(2.27%) max: 7770.00 max: 15622.00 min: 7598.00 min: 14772.00
2 thread
records: 10 records: 10 avg: 12747.50 avg: 24171.00 std: 792.06(6.21%) std: 895.18(3.70%) max: 13337.00 max: 26023.00 min: 10535.00 min: 23152.00
4 thread
records: 10 records: 10 avg: 16474.60 avg: 33717.90 std: 1496.45(9.08%) std: 2008.97(5.96%) max: 17877.00 max: 35958.00 min: 12224.00 min: 29565.00
8 thread
records: 10 records: 10 avg: 16778.50 avg: 33308.10 std: 825.53(4.92%) std: 1668.30(5.01%) max: 17543.00 max: 36010.00 min: 14576.00 min: 29577.00
16 thread
records: 10 records: 10 avg: 20614.40 avg: 35516.30 std: 602.95(2.92%) std: 1283.65(3.61%) max: 21753.00 max: 37178.00 min: 19605.00 min: 33217.00
32 thread
records: 10 records: 10 avg: 22771.70 avg: 36018.50 std: 598.94(2.63%) std: 1046.76(2.91%) max: 24035.00 max: 37266.00 min: 22108.00 min: 34149.00
In summary, MADV_FREE is about 2 time faster than MADV_DONTNEED.
--- include/linux/rmap.h | 9 ++- include/linux/vm_event_item.h | 1 + include/uapi/asm-generic/mman-common.h | 1 + mm/madvise.c | 136 +++++++++++++++++++++++++++++++++ mm/rmap.c | 42 +++++++++- mm/vmscan.c | 40 ++++++++-- mm/vmstat.c | 1 + 7 files changed, 218 insertions(+), 12 deletions(-)
include/linux/rmap.h +7 -2
@@ -75,6 +75,7 @@ enum ttu_flags {TTU_UNMAP =1 ,/* unmap mode */ TTU_MIGRATION =2 ,/* migration mode */ TTU_MUNLOCK =4 ,/* munlock mode */ +TTU_FREE =8 ,/* free mode */ TTU_IGNORE_MLOCK = (1 <<8 ),/* ignore mlock */ TTU_IGNORE_ACCESS = (1 << 9), /* don't age */
@@ -181,7 +182,8 @@ static inline void page_dup_rmap(struct page *page)* Called from mm/vmscan.c to handle paging out */ int page_referenced (struct page *,int is_locked, -struct mem_cgroup *memcg,unsigned long *vm_flags); +struct mem_cgroup *memcg,unsigned long *vm_flags, +int *is_dirty);#define TTU_ACTION (x) ((x) & TTU_ACTION_MASK)
@@ -260,9 +262,12 @@ int rmap_walk(struct page *page, struct rmap_walk_control *rwc);static inline int page_referenced (struct page *page,int is_locked,struct mem_cgroup *memcg, -unsigned long *vm_flags) +unsigned long *vm_flags, +int *is_pte_dirty) { *vm_flags =0 ; +if (is_pte_dirty) + *is_pte_dirty =0 ;return 0 ; }
include/linux/vm_event_item.h +1 -0
@@ -25,6 +25,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,FOR_ALL_ZONES (PGALLOC ),PGFREE ,PGACTIVATE ,PGDEACTIVATE ,PGFAULT ,PGMAJFAULT , +PGLAZYFREED ,FOR_ALL_ZONES (PGREFILL ),FOR_ALL_ZONES (PGSTEAL_KSWAPD ), FOR_ALL_ZONES(PGSTEAL_DIRECT),
include/uapi/asm-generic/mman-common.h +1 -0
@@ -34,6 +34,7 @@#define MADV_SEQUENTIAL 2/* expect sequential page references */ #define MADV_WILLNEED 3/* will need these pages */ #define MADV_DONTNEED 4/* don't need these pages */ +#define MADV_FREE 5/* free pages only if memory pressure */ /* common parameters: try to keep these consistent across architectures */ #define MADV_REMOVE 9/* remove these pages & resources */
mm/madvise.c +136 -0
166 lines not on this page · raw message
mm/rmap.c +40 -2
120 lines not on this page · raw message
mm/vmscan.c +32 -8
@@ -707,13 +707,17 @@ enum page_references { };static enum page_references page_check_references (struct page *page, -struct scan_control *sc) +struct scan_control *sc, +bool *freeable) {int referenced_ptes, referenced_page;unsigned long vm_flags; +int pte_dirty; + +VM_BUG_ON_PAGE (!PageLocked (page), page); referenced_ptes =page_referenced (page,1 , sc->target_mem_cgroup, - &vm_flags); + &vm_flags, &pte_dirty); referenced_page =TestClearPageReferenced (page);/*
@@ -754,6 +758,10 @@ static enum page_references page_check_references(struct page *page,return PAGEREF_KEEP ; } +if (PageAnon (page) && !pte_dirty && !PageSwapCache (page) && + !PageDirty (page)) + *freeable = true; +/* Reclaim if clean, defer dirty pages to writeback */ if (referenced_page && !PageSwapBacked (page))return PAGEREF_RECLAIM_CLEAN ;
@@ -823,6 +831,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,int may_enter_fs;enum page_references references =PAGEREF_RECLAIM_CLEAN ;bool dirty, writeback; +bool freeable = false;cond_resched ();
@@ -945,7 +954,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, }if (!force_reclaim) - references =page_check_references (page, sc); + references =page_check_references (page, sc, + &freeable);switch (references) {case PAGEREF_ACTIVATE :
@@ -961,7 +971,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,* Anonymous process memory has backing store? * Try to allocate it some swap space here. */ -if (PageAnon (page) && !PageSwapCache (page)) { +if (PageAnon (page) && !PageSwapCache (page) && !freeable) {if (!(sc->gfp_mask & __GFP_IO)) goto keep_locked;if (!add_to_swap (page, page_list))
@@ -976,8 +986,9 @@ static unsigned long shrink_page_list(struct list_head *page_list,* The page is mapped into the page tables of one or more * processes. Try to unmap it here. */ -if (page_mapped (page) && mapping) { -switch (try_to_unmap (page, ttu_flags)) { +if (page_mapped (page) && (mapping || freeable)) { +switch (try_to_unmap (page, + freeable ?TTU_FREE : ttu_flags)) {case SWAP_FAIL : goto activate_locked;case SWAP_AGAIN :
@@ -985,7 +996,20 @@ static unsigned long shrink_page_list(struct list_head *page_list,case SWAP_MLOCK : goto cull_mlocked;case SWAP_SUCCESS : - ;/* try to free the page below */ +/* try to free the page below */ +if (!freeable) +break ; +/* +* Freeable anon page doesn't have mapping +* due to skipping of swapcache so we free +* page in here rather than __remove_mapping. +*/ +VM_BUG_ON_PAGE (PageSwapCache (page), page); +if (!page_freeze_refs (page,1 )) + goto keep_locked; +__clear_page_locked (page); +count_vm_event (PGLAZYFREED ); + goto free_it; } }
@@ -1727,7 +1751,7 @@ static void shrink_active_list(unsigned long nr_to_scan, }if (page_referenced (page,0 , sc->target_mem_cgroup, - &vm_flags)) { + &vm_flags,NULL )) { nr_rotated +=hpage_nr_pages (page);/* * Identify referenced, file-backed active pages and
mm/vmstat.c +1 -0
@@ -794,6 +794,7 @@ const char * const vmstat_text[] = {"pgfault" ,"pgmajfault" , +"pglazyfreed" , TEXTS_FOR_ZONES("pgrefill")TEXTS_FOR_ZONES ("pgsteal_kswapd" )
Signature · 7 lines
2.0.0 -- 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>
Re: [PATCH v12 1/8] mm: support madvise(MADV_FREE)
Quoted 229 lines · Minchan Kim
Linux doesn't have an ability to free pages lazy while other OS already have been supported that named by
madvise(MADV_FREE).The gain is clear that kernel can discard freed pages rather than swapping out or OOM if memory pressure happens.
Without memory pressure, freed pages would be reused by userspace without another additional overhead(ex, page fault + allocation
+ zeroing).How to work is following as.
When madvise syscall is called, VM clears dirty bit of ptes of the range. If memory pressure happens, VM checks dirty bit of page table and if it found still "clean", it means it's a "lazyfree pages" so VM could discard the page instead of swapping out. Once there was store operation for the page before VM peek a page to reclaim, dirty bit is set so VM can swap out the page instead of discarding.
Firstly, heavy users would be general
allocators(ex, jemalloc, tcmalloc and hope glibc supports it)and jemalloc/tcmalloc already have supported the feature for otherOS(ex, FreeBSD)barrios@blaptop:~/benchmark/ebizzy$ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 2 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 42 Stepping: 7 CPU MHz: 2801.000 BogoMIPS: 5581.64 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 4096K NUMA node0 CPU(s): 0-3ebizzy benchmark(./ebizzy -S 10 -n 512)
vanilla-jemalloc MADV_free-jemalloc
1 thread
records: 10 records: 10 avg: 7682.10 avg: 15306.10 std: 62.35(0.81%) std: 347.99(2.27%) max: 7770.00 max: 15622.00 min: 7598.00 min: 14772.002 thread
records: 10 records: 10 avg: 12747.50 avg: 24171.00 std: 792.06(6.21%) std: 895.18(3.70%) max: 13337.00 max: 26023.00 min: 10535.00 min: 23152.004 thread
records: 10 records: 10 avg: 16474.60 avg: 33717.90 std: 1496.45(9.08%) std: 2008.97(5.96%) max: 17877.00 max: 35958.00 min: 12224.00 min: 29565.008 thread
records: 10 records: 10 avg: 16778.50 avg: 33308.10 std: 825.53(4.92%) std: 1668.30(5.01%) max: 17543.00 max: 36010.00 min: 14576.00 min: 29577.0016 thread
records: 10 records: 10 avg: 20614.40 avg: 35516.30 std: 602.95(2.92%) std: 1283.65(3.61%) max: 21753.00 max: 37178.00 min: 19605.00 min: 33217.0032 thread
records: 10 records: 10 avg: 22771.70 avg: 36018.50 std: 598.94(2.63%) std: 1046.76(2.91%) max: 24035.00 max: 37266.00 min: 22108.00 min: 34149.00In summary,
MADV_FREEis about 2 time faster thanMADV_DONTNEED.Cc Michael Kerrisk <[email protected]>Cc Linux API <[email protected]>Cc Hugh Dickins <[email protected]>Cc Johannes Weiner <[email protected]>Cc KOSAKI Motohiro <[email protected]>Cc Mel Gorman <[email protected]>Cc Jason Evans <[email protected]>Acked-by Zhang Yanfei <[email protected]>Acked-by Rik van Riel <[email protected]>Signed-off-by Minchan Kim <[email protected]>--- include/linux/rmap.h | 9 ++- include/linux/vm_event_item.h | 1 + include/uapi/asm-generic/mman-common.h | 1 + mm/madvise.c | 136 +++++++++++++++++++++++++++++++++ mm/rmap.c | 42 +++++++++- mm/vmscan.c | 40 ++++++++-- mm/vmstat.c | 1 + 7 files changed, 218 insertions(+), 12 deletions(-)include/linux/rmap.h +7
-2@@ -75,6 +75,7 @@ enum ttu_flags {TTU_UNMAP =1 ,/* unmap mode */ TTU_MIGRATION =2 ,/* migration mode */ TTU_MUNLOCK =4 ,/* munlock mode */ +TTU_FREE =8 ,/* free mode */ TTU_IGNORE_MLOCK = (1 <<8 ),/* ignore mlock */ TTU_IGNORE_ACCESS = (1 << 9), /* don't age */@@ -181,7 +182,8 @@ static inline void page_dup_rmap(struct page *page)* Called from mm/vmscan.c to handle paging out */ int page_referenced (struct page *,int is_locked, -struct mem_cgroup *memcg,unsigned long *vm_flags); +struct mem_cgroup *memcg,unsigned long *vm_flags, +int *is_dirty);#define TTU_ACTION (x) ((x) & TTU_ACTION_MASK)@@ -260,9 +262,12 @@ int rmap_walk(struct page *page, struct rmap_walk_control *rwc);static inline int page_referenced (struct page *page,int is_locked,struct mem_cgroup *memcg, -unsigned long *vm_flags) +unsigned long *vm_flags, +int *is_pte_dirty) { *vm_flags =0 ; +if (is_pte_dirty) + *is_pte_dirty =0 ;return 0 ; }include/linux/vm_event_item.h +1
-0@@ -25,6 +25,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,FOR_ALL_ZONES (PGALLOC ),PGFREE ,PGACTIVATE ,PGDEACTIVATE ,PGFAULT ,PGMAJFAULT , +PGLAZYFREED ,FOR_ALL_ZONES (PGREFILL ),FOR_ALL_ZONES (PGSTEAL_KSWAPD ), FOR_ALL_ZONES(PGSTEAL_DIRECT),include/uapi/asm-generic/mman-common.h +1
-0@@ -34,6 +34,7 @@#define MADV_SEQUENTIAL 2/* expect sequential page references */ #define MADV_WILLNEED 3/* will need these pages */ #define MADV_DONTNEED 4/* don't need these pages */ +#define MADV_FREE 5/* free pages only if memory pressure */ /* common parameters: try to keep these consistent across architectures */ #define MADV_REMOVE 9/* remove these pages & resources */ mm/madvise.c +32
-0@@ -19,6 +19,14 @@#include <linux/blkdev.h> #include <linux/swap.h> #include <linux/swapops.h> +#include <linux/mmu_notifier.h> + +#include <asm/tlb.h> + +struct madvise_free_private { +struct vm_area_struct *vma; +struct mmu_gather *tlb; +};/* * Any behaviour which results in changes to the vma->vm_flags needs to @@ -31,6 +39,7 @@ static int madvise_need_mmap_write(int behavior)case MADV_REMOVE :case MADV_WILLNEED :case MADV_DONTNEED : +case MADV_FREE :return 0 ;default :/* be safe, default to 1. list exceptions explicitly */ @@ -251,6 +260,124 @@ static long madvise_willneed(struct vm_area_struct *vma,return 0 ; } +static int madvise_free_pte_range (pmd_t *pmd,unsigned long addr, +unsigned long end,struct mm_walk *walk) + +{ +struct madvise_free_private *fp = walk->private; +struct mmu_gather *tlb = fp->tlb; +struct mm_struct *mm = tlb->mm; +struct vm_area_struct *vma = fp->vma; +spinlock_t *ptl; +pte_t *pte, ptent; +struct page *page; + +split_huge_page_pmd (vma, addr, pmd); +if (pmd_trans_unstable (pmd)) +return 0 ; + + pte =pte_offset_map_lock (mm, pmd, addr, &ptl); +arch_enter_lazy_mmu_mode (); +for (; addr != end; pte++, addr +=PAGE_SIZE ) { + ptent = *pte; + +if (!pte_present (ptent)) +continue ;
mm/madvise.c static long madvise_willneed(struct vm_area_struct *vma, · line 295
Quoted 10 lines
mm/madvise.c +10
-0+ + page =vm_normal_page (vma, addr, ptent); +if (!page) +continue ; + +if (PageSwapCache (page)) { +if (trylock_page (page)) { +if (try_to_free_swap (page)) +ClearPageDirty (page); +unlock_page (page);
'continue' for !try_to_free_swap(page) case?
Quoted 42 lines
mm/madvise.c +42
-0+ }else +continue ; + } + +/* +* Some of architecture(ex, PPC) don't update TLB +* with set_pte_at and tlb_remove_tlb_entry so for +* the portability, remap the pte with old|clean +* after pte clearing. +*/ + ptent =ptep_get_and_clear_full (mm, addr, pte, + tlb->fullmm); + ptent =pte_mkold (ptent); + ptent =pte_mkclean (ptent); +set_pte_at (mm, addr, pte, ptent); +tlb_remove_tlb_entry (tlb, pte, addr); + } +arch_leave_lazy_mmu_mode (); +pte_unmap_unlock (pte -1 , ptl); +cond_resched (); +return 0 ; +} + +static void madvise_free_page_range (struct mmu_gather *tlb, +struct vm_area_struct *vma, +unsigned long addr,unsigned long end) +{ +struct madvise_free_private fp = { + .vma = vma, + .tlb = tlb, + }; + +struct mm_walk free_walk = { + .pmd_entry = madvise_free_pte_range, + .mm = vma->vm_mm, + .private = &fp, + }; + +BUG_ON (addr >= end); +tlb_start_vma (tlb, vma); +walk_page_range (addr, end, &free_walk); +tlb_end_vma (tlb, vma);
mm/madvise.c static long madvise_willneed(struct vm_area_struct *vma, · line 347
Quoted 10 lines
mm/madvise.c +10
-0+} + +static int madvise_free_single_vma (struct vm_area_struct *vma, +unsigned long start_addr,unsigned long end_addr) +{ +unsigned long start, end; +struct mm_struct *mm = vma->vm_mm; +struct mmu_gather tlb; + +if (vma->vm_flags & (VM_LOCKED |VM_HUGETLB |VM_PFNMAP ))
THP uses VM_SPECIAL | VM_HUGETLB | VM_SHARED | VM_MAYSHARE to filter out 'special' VMAs. Looks reasonable here too.
Otherwise:
Signature · 7 lines
Kirill A. Shutemov -- 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>
Re: [PATCH v12 1/8] mm: support madvise(MADV_FREE)
Quoted 234 lines · Kirill A. Shutemov
Quoted 233 lines · Minchan Kim
Linux doesn't have an ability to free pages lazy while other OS already have been supported that named by
madvise(MADV_FREE).The gain is clear that kernel can discard freed pages rather than swapping out or OOM if memory pressure happens.
Without memory pressure, freed pages would be reused by userspace without another additional overhead(ex, page fault + allocation
+ zeroing).How to work is following as.
When madvise syscall is called, VM clears dirty bit of ptes of the range. If memory pressure happens, VM checks dirty bit of page table and if it found still "clean", it means it's a "lazyfree pages" so VM could discard the page instead of swapping out. Once there was store operation for the page before VM peek a page to reclaim, dirty bit is set so VM can swap out the page instead of discarding.
Firstly, heavy users would be general
allocators(ex, jemalloc, tcmalloc and hope glibc supports it)and jemalloc/tcmalloc already have supported the feature for otherOS(ex, FreeBSD)barrios@blaptop:~/benchmark/ebizzy$ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 2 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 42 Stepping: 7 CPU MHz: 2801.000 BogoMIPS: 5581.64 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 4096K NUMA node0 CPU(s): 0-3ebizzy benchmark(./ebizzy -S 10 -n 512)
vanilla-jemalloc MADV_free-jemalloc
1 thread
records: 10 records: 10 avg: 7682.10 avg: 15306.10 std: 62.35(0.81%) std: 347.99(2.27%) max: 7770.00 max: 15622.00 min: 7598.00 min: 14772.002 thread
records: 10 records: 10 avg: 12747.50 avg: 24171.00 std: 792.06(6.21%) std: 895.18(3.70%) max: 13337.00 max: 26023.00 min: 10535.00 min: 23152.004 thread
records: 10 records: 10 avg: 16474.60 avg: 33717.90 std: 1496.45(9.08%) std: 2008.97(5.96%) max: 17877.00 max: 35958.00 min: 12224.00 min: 29565.008 thread
records: 10 records: 10 avg: 16778.50 avg: 33308.10 std: 825.53(4.92%) std: 1668.30(5.01%) max: 17543.00 max: 36010.00 min: 14576.00 min: 29577.0016 thread
records: 10 records: 10 avg: 20614.40 avg: 35516.30 std: 602.95(2.92%) std: 1283.65(3.61%) max: 21753.00 max: 37178.00 min: 19605.00 min: 33217.0032 thread
records: 10 records: 10 avg: 22771.70 avg: 36018.50 std: 598.94(2.63%) std: 1046.76(2.91%) max: 24035.00 max: 37266.00 min: 22108.00 min: 34149.00In summary,
MADV_FREEis about 2 time faster thanMADV_DONTNEED.Cc Michael Kerrisk <[email protected]>Cc Linux API <[email protected]>Cc Hugh Dickins <[email protected]>Cc Johannes Weiner <[email protected]>Cc KOSAKI Motohiro <[email protected]>Cc Mel Gorman <[email protected]>Cc Jason Evans <[email protected]>Acked-by Zhang Yanfei <[email protected]>Acked-by Rik van Riel <[email protected]>Signed-off-by Minchan Kim <[email protected]>--- include/linux/rmap.h | 9 ++- include/linux/vm_event_item.h | 1 + include/uapi/asm-generic/mman-common.h | 1 + mm/madvise.c | 136 +++++++++++++++++++++++++++++++++ mm/rmap.c | 42 +++++++++- mm/vmscan.c | 40 ++++++++-- mm/vmstat.c | 1 + 7 files changed, 218 insertions(+), 12 deletions(-)include/linux/rmap.h +7
-2@@ -75,6 +75,7 @@ enum ttu_flags {TTU_UNMAP =1 ,/* unmap mode */ TTU_MIGRATION =2 ,/* migration mode */ TTU_MUNLOCK =4 ,/* munlock mode */ +TTU_FREE =8 ,/* free mode */ TTU_IGNORE_MLOCK = (1 <<8 ),/* ignore mlock */ TTU_IGNORE_ACCESS = (1 << 9), /* don't age */@@ -181,7 +182,8 @@ static inline void page_dup_rmap(struct page *page)* Called from mm/vmscan.c to handle paging out */ int page_referenced (struct page *,int is_locked, -struct mem_cgroup *memcg,unsigned long *vm_flags); +struct mem_cgroup *memcg,unsigned long *vm_flags, +int *is_dirty);#define TTU_ACTION (x) ((x) & TTU_ACTION_MASK)@@ -260,9 +262,12 @@ int rmap_walk(struct page *page, struct rmap_walk_control *rwc);static inline int page_referenced (struct page *page,int is_locked,struct mem_cgroup *memcg, -unsigned long *vm_flags) +unsigned long *vm_flags, +int *is_pte_dirty) { *vm_flags =0 ; +if (is_pte_dirty) + *is_pte_dirty =0 ;return 0 ; }include/linux/vm_event_item.h +1
-0@@ -25,6 +25,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,FOR_ALL_ZONES (PGALLOC ),PGFREE ,PGACTIVATE ,PGDEACTIVATE ,PGFAULT ,PGMAJFAULT , +PGLAZYFREED ,FOR_ALL_ZONES (PGREFILL ),FOR_ALL_ZONES (PGSTEAL_KSWAPD ), FOR_ALL_ZONES(PGSTEAL_DIRECT),include/uapi/asm-generic/mman-common.h +1
-0@@ -34,6 +34,7 @@#define MADV_SEQUENTIAL 2/* expect sequential page references */ #define MADV_WILLNEED 3/* will need these pages */ #define MADV_DONTNEED 4/* don't need these pages */ +#define MADV_FREE 5/* free pages only if memory pressure */ /* common parameters: try to keep these consistent across architectures */ #define MADV_REMOVE 9/* remove these pages & resources */ mm/madvise.c +36
-0@@ -19,6 +19,14 @@#include <linux/blkdev.h> #include <linux/swap.h> #include <linux/swapops.h> +#include <linux/mmu_notifier.h> + +#include <asm/tlb.h> + +struct madvise_free_private { +struct vm_area_struct *vma; +struct mmu_gather *tlb; +};/* * Any behaviour which results in changes to the vma->vm_flags needs to @@ -31,6 +39,7 @@ static int madvise_need_mmap_write(int behavior)case MADV_REMOVE :case MADV_WILLNEED :case MADV_DONTNEED : +case MADV_FREE :return 0 ;default :/* be safe, default to 1. list exceptions explicitly */ @@ -251,6 +260,124 @@ static long madvise_willneed(struct vm_area_struct *vma,return 0 ; } +static int madvise_free_pte_range (pmd_t *pmd,unsigned long addr, +unsigned long end,struct mm_walk *walk) + +{ +struct madvise_free_private *fp = walk->private; +struct mmu_gather *tlb = fp->tlb; +struct mm_struct *mm = tlb->mm; +struct vm_area_struct *vma = fp->vma; +spinlock_t *ptl; +pte_t *pte, ptent; +struct page *page; + +split_huge_page_pmd (vma, addr, pmd); +if (pmd_trans_unstable (pmd)) +return 0 ; + + pte =pte_offset_map_lock (mm, pmd, addr, &ptl); +arch_enter_lazy_mmu_mode (); +for (; addr != end; pte++, addr +=PAGE_SIZE ) { + ptent = *pte; + +if (!pte_present (ptent)) +continue ; + + page =vm_normal_page (vma, addr, ptent); +if (!page) +continue ;
Quoted 8 lines
mm/madvise.c static long madvise_willneed(struct vm_area_struct *vma, · line 295
Quoted 6 lines
mm/madvise.c +6
-0+ +if (PageSwapCache (page)) { +if (trylock_page (page)) { +if (try_to_free_swap (page)) +ClearPageDirty (page); +unlock_page (page);'continue' for !try_to_free_swap(page) case?
Good catch.
Quoted 57 lines
Quoted 43 lines
mm/madvise.c +42
-0+ }else +continue ; + } + +/* +* Some of architecture(ex, PPC) don't update TLB +* with set_pte_at and tlb_remove_tlb_entry so for +* the portability, remap the pte with old|clean +* after pte clearing. +*/ + ptent =ptep_get_and_clear_full (mm, addr, pte, + tlb->fullmm); + ptent =pte_mkold (ptent); + ptent =pte_mkclean (ptent); +set_pte_at (mm, addr, pte, ptent); +tlb_remove_tlb_entry (tlb, pte, addr); + } +arch_leave_lazy_mmu_mode (); +pte_unmap_unlock (pte -1 , ptl); +cond_resched (); +return 0 ; +} + +static void madvise_free_page_range (struct mmu_gather *tlb, +struct vm_area_struct *vma, +unsigned long addr,unsigned long end) +{ +struct madvise_free_private fp = { + .vma = vma, + .tlb = tlb, + }; + +struct mm_walk free_walk = { + .pmd_entry = madvise_free_pte_range, + .mm = vma->vm_mm, + .private = &fp, + }; + +BUG_ON (addr >= end); +tlb_start_vma (tlb, vma); +walk_page_range (addr, end, &free_walk); +tlb_end_vma (tlb, vma);mm/madvise.c static long madvise_willneed(struct vm_area_struct *vma, · line 347
Quoted 10 lines
mm/madvise.c +10
-0+} + +static int madvise_free_single_vma (struct vm_area_struct *vma, +unsigned long start_addr,unsigned long end_addr) +{ +unsigned long start, end; +struct mm_struct *mm = vma->vm_mm; +struct mmu_gather tlb; + +if (vma->vm_flags & (VM_LOCKED |VM_HUGETLB |VM_PFNMAP ))THP uses
VM_SPECIAL|VM_HUGETLB|VM_SHARED|VM_MAYSHAREto filter out 'special' VMAs. Looks reasonable here too.
Quoted 3 lines
Otherwise:
Thanks, Kirill!
Quoted 9 lines
Signature · 8 lines
-- Kirill A. Shutemov -- 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>
Signature · 8 lines
Kind regards, Minchan Kim -- 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 v12 2/8 x86: add pmd_[dirty|mkclean] for THP
In reply to Minchan KimMADV_FREE needs pmd_dirty and pmd_mkclean for detecting recent overwrite of the contents since MADV_FREE syscall is called for THP page.
This patch adds pmd_dirty and pmd_mkclean for THP page MADV_FREE support.
--- arch/x86/include/asm/pgtable.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/x86/include/asm/pgtable.h +10 -0
@@ -104,6 +104,11 @@ static inline int pmd_young(pmd_t pmd)return pmd_flags (pmd) & _PAGE_ACCESSED; } +static inline int pmd_dirty (pmd_t pmd) +{ +return pmd_flags (pmd) & _PAGE_DIRTY; +} +static inline int pte_write (pte_t pte) {return pte_flags (pte) & _PAGE_RW;
@@ -267,6 +272,11 @@ static inline pmd_t pmd_mkold(pmd_t pmd)return pmd_clear_flags (pmd, _PAGE_ACCESSED); } +static inline pmd_t pmd_mkclean (pmd_t pmd) +{ +return pmd_clear_flags (pmd, _PAGE_DIRTY); +} +static inline pmd_t pmd_wrprotect (pmd_t pmd) {return pmd_clear_flags (pmd, _PAGE_RW);
Signature · 7 lines
2.0.0 -- 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 v12 3/8 sparc: add pmd_[dirty|mkclean] for THP
In reply to Minchan KimMADV_FREE needs pmd_dirty and pmd_mkclean for detecting recent overwrite of the contents since MADV_FREE syscall is called for THP page.
This patch adds pmd_dirty and pmd_mkclean for THP page MADV_FREE support.
--- arch/sparc/include/asm/pgtable_64.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
arch/sparc/include/asm/pgtable_64.h +16 -0
@@ -666,6 +666,13 @@ static inline unsigned long pmd_young(pmd_t pmd)return pte_young (pte); } +static inline int pmd_dirty (pmd_t pmd) +{ +pte_t pte =__pte (pmd_val (pmd)); + +return pte_dirty (pte); +} +static inline unsigned long pmd_write (pmd_t pmd) {pte_t pte =__pte (pmd_val (pmd));
@@ -723,6 +730,15 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)return __pmd (pte_val (pte)); } +static inline pmd_t pmd_mkclean (pmd_t pmd) +{ +pte_t pte =__pte (pmd_val (pmd)); + + pte =pte_mkclean (pte); + +return __pmd (pte_val (pte)); +} +static inline pmd_t pmd_mkyoung (pmd_t pmd) {pte_t pte =__pte (pmd_val (pmd));
Signature · 7 lines
2.0.0 -- 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 v12 4/8 powerpc: add pmd_[dirty|mkclean] for THP
In reply to Minchan KimMADV_FREE needs pmd_dirty and pmd_mkclean for detecting recent overwrite of the contents since MADV_FREE syscall is called for THP page.
This patch adds pmd_dirty and pmd_mkclean for THP page MADV_FREE support.
--- arch/powerpc/include/asm/pgtable-ppc64.h | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/include/asm/pgtable-ppc64.h +2 -0
@@ -468,9 +468,11 @@ static inline pte_t *pmdp_ptep(pmd_t *pmd)#define pmd_pfn (pmd) pte_pfn(pmd_pte(pmd))#define pmd_young (pmd) pte_young(pmd_pte(pmd)) +#define pmd_dirty (pmd) pte_dirty(pmd_pte(pmd))#define pmd_mkold (pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))#define pmd_wrprotect (pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))#define pmd_mkdirty (pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd))) +#define pmd_mkclean (pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))#define pmd_mkyoung (pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))#define pmd_mkwrite (pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd)))
Signature · 1 line
2.0.0
PATCH v12 5/8 s390: add pmd_[dirty|mkclean] for THP
In reply to Minchan KimMADV_FREE needs pmd_dirty and pmd_mkclean for detecting recent overwrite of the contents since MADV_FREE syscall is called for THP page but for s390 pmds only referenced bit is available because there is no free bit left in the pmd entry for the software dirty bit so this patch adds dumb pmd_dirty which returns always true by suggesting by Martin.
They finally find a solution in future.
http://marc.info/?l=linux-api&m=140440328820808&w=2
--- arch/s390/include/asm/pgtable.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/s390/include/asm/pgtable.h +12 -0
@@ -1586,6 +1586,18 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)return pmd; } +static inline int pmd_dirty (pmd_t pmd) +{ +/* No dirty bit in the segment table entry */ +return 1 ; +} + +static inline pmd_t pmd_mkclean (pmd_t pmd) +{ +/* No dirty bit in the segment table entry */ +return pmd; +} +#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNGstatic inline int pmdp_test_and_clear_young (struct vm_area_struct *vma,unsigned long address,pmd_t *pmdp)
Signature · 7 lines
2.0.0 -- 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 v12 6/8 arm: add pmd_[dirty|mkclean] for THP
In reply to Minchan KimMADV_FREE needs pmd_dirty and pmd_mkclean for detecting recent overwrite of the contents since MADV_FREE syscall is called for THP page.
This patch adds pmd_dirty and pmd_mkclean for THP page MADV_FREE support.
--- arch/arm/include/asm/pgtable-3level.h | 3 +++ 1 file changed, 3 insertions(+)
arch/arm/include/asm/pgtable-3level.h +3 -0
@@ -220,6 +220,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)#define pmd_trans_splitting (pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)#endif +#define pmd_dirty (pmd) (pmd_val(pmd) & PMD_SECT_DIRTY) +#define PMD_BIT_FUNC (fn,op) \ static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
@@ -228,6 +230,7 @@ PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); +PMD_BIT_FUNC(mkclean, &= ~PMD_SECT_DIRTY); PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);#define pmd_mkhuge (pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
Signature · 7 lines
2.0.0 -- 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 v12 7/8 arm64: add pmd_[dirty|mkclean] for THP
In reply to Minchan KimMADV_FREE needs pmd_dirty and pmd_mkclean for detecting recent overwrite of the contents since MADV_FREE syscall is called for THP page.
This patch adds pmd_dirty and pmd_mkclean for THP page MADV_FREE support.
--- arch/arm64/include/asm/pgtable.h | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/include/asm/pgtable.h +2 -0
@@ -240,10 +240,12 @@ static inline pmd_t pte_pmd(pte_t pte)#endif #define pmd_young (pmd) pte_young(pmd_pte(pmd)) +#define pmd_dirty (pmd) pte_dirty(pmd_pte(pmd))#define pmd_wrprotect (pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))#define pmd_mksplitting (pmd) pte_pmd(pte_mkspecial(pmd_pte(pmd)))#define pmd_mkold (pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))#define pmd_mkwrite (pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd))) +#define pmd_mkclean (pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))#define pmd_mkdirty (pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd)))#define pmd_mkyoung (pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))#define pmd_mknotpresent (pmd) (__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
Signature · 7 lines
2.0.0 -- 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>
Re: [PATCH v12 7/8] arm64: add pmd_[dirty|mkclean] for THP
Quoted 7 lines · Minchan Kim
MADV_FREEneedspmd_dirtyandpmd_mkcleanfor detecting recent overwrite of the contents sinceMADV_FREEsyscall is called for THP page.This patch adds
pmd_dirtyandpmd_mkcleanfor THP pageMADV_FREEsupport.
Quoted 6 lines
Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Steve Capper <[email protected]>Cc Russell King <[email protected]>Signed-off-by Minchan Kim <[email protected]>
--
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 v12 8/8 mm: Don't split THP page when syscall is called
In reply to Minchan KimWe don't need to split THP page when MADV_FREE syscall is called. It could be done when VM decide really frees it so we could avoid unnecessary THP split.
--- include/linux/huge_mm.h | 4 ++++ mm/huge_memory.c | 35 +++++++++++++++++++++++++++++++++++ mm/madvise.c | 21 ++++++++++++++++++++- mm/rmap.c | 8 ++++++-- mm/vmscan.c | 28 ++++++++++++++++++---------- 5 files changed, 83 insertions(+), 13 deletions(-)
include/linux/huge_mm.h +4 -0
@@ -19,6 +19,9 @@ extern struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,unsigned long addr, pmd_t *pmd, unsigned int flags); +extern int madvise_free_huge_pmd (struct mmu_gather *tlb, +struct vm_area_struct *vma, +pmd_t *pmd,unsigned long addr);extern int zap_huge_pmd (struct mmu_gather *tlb,struct vm_area_struct *vma,pmd_t *pmd,unsigned long addr);
@@ -56,6 +59,7 @@ extern pmd_t *page_check_address_pmd(struct page *page,unsigned long address, enum page_check_address_pmd_flag flag, spinlock_t **ptl); +extern int pmd_freeable (pmd_t pmd);#define HPAGE_PMD_ORDER (HPAGE_PMD_SHIFT-PAGE_SHIFT)#define HPAGE_PMD_NR (1<<HPAGE_PMD_ORDER)
mm/huge_memory.c +35 -0
@@ -1384,6 +1384,36 @@ out:return 0 ; } +int madvise_free_huge_pmd (struct mmu_gather *tlb,struct vm_area_struct *vma, +pmd_t *pmd,unsigned long addr) + +{ +spinlock_t *ptl; +struct mm_struct *mm = tlb->mm; +int ret =1 ; + +if (pmd_trans_huge_lock (pmd, vma, &ptl) ==1 ) { +struct page *page; +pmd_t orig_pmd; + + orig_pmd =pmdp_get_and_clear (mm, addr, pmd); + +/* No hugepage in swapcache */ + page =pmd_page (orig_pmd); +VM_BUG_ON_PAGE (PageSwapCache (page), page); + + orig_pmd =pmd_mkold (orig_pmd); + orig_pmd =pmd_mkclean (orig_pmd); + +set_pmd_at (mm, addr, pmd, orig_pmd); +tlb_remove_pmd_tlb_entry (tlb, pmd, addr); +spin_unlock (ptl); + ret =0 ; + } + +return ret; +} +int zap_huge_pmd (struct mmu_gather *tlb,struct vm_area_struct *vma,pmd_t *pmd,unsigned long addr) {
@@ -1620,6 +1650,11 @@ unlock:return NULL ; } +int pmd_freeable (pmd_t pmd) +{ +return !pmd_dirty (pmd); +} +static int __split_huge_page_splitting (struct page *page,struct vm_area_struct *vma,unsigned long address)
mm/madvise.c +20 -1
@@ -271,8 +271,26 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,spinlock_t *ptl;pte_t *pte, ptent;struct page *page; +unsigned long next; + + next =pmd_addr_end (addr, end); +if (pmd_trans_huge (*pmd)) { +if (next - addr !=HPAGE_PMD_SIZE ) { +#ifdef CONFIG_DEBUG_VM +if (!rwsem_is_locked (&mm->mmap_sem)) { +pr_err ("%s: mmap_sem is unlocked! addr=0x%lx end=0x%lx vma->vm_start=0x%lx vma->vm_end=0x%lx\n" , + __func__, addr, end, + vma->vm_start, + vma->vm_end); +BUG (); + } +#endif +split_huge_page_pmd (vma, addr, pmd); + }else if (!madvise_free_huge_pmd (tlb, vma, pmd, addr)) + goto next; +/* fall through */ + } -split_huge_page_pmd (vma, addr, pmd);if (pmd_trans_unstable (pmd))return 0 ;
@@ -312,6 +330,7 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr, }arch_leave_lazy_mmu_mode ();pte_unmap_unlock (pte -1 , ptl); +next:cond_resched ();return 0 ; }
mm/rmap.c +6 -2
@@ -704,9 +704,13 @@ static int page_referenced_one(struct page *page, struct vm_area_struct *vma, referenced++;/* -* In this implmentation, MADV_FREE doesn't support THP free +* Use pmd_freeable instead of raw pmd_dirty because in some +* of architecture, pmd_dirty is not defined unless +* CONFIG_TRANSPARNTE_HUGE is enabled */ - dirty++; +if (!pmd_freeable (*pmd)) + dirty++; +spin_unlock (ptl); }else {pte_t *pte;
mm/vmscan.c +18 -10
@@ -971,17 +971,25 @@ static unsigned long shrink_page_list(struct list_head *page_list,* Anonymous process memory has backing store? * Try to allocate it some swap space here. */ -if (PageAnon (page) && !PageSwapCache (page) && !freeable) { -if (!(sc->gfp_mask & __GFP_IO)) - goto keep_locked; -if (!add_to_swap (page, page_list)) - goto activate_locked; - may_enter_fs =1 ; - -/* Adding to swap updated mapping */ - mapping =page_mapping (page); +if (PageAnon (page) && !PageSwapCache (page)) { +if (!freeable) { +if (!(sc->gfp_mask & __GFP_IO)) + goto keep_locked; +if (!add_to_swap (page, page_list)) + goto activate_locked; + may_enter_fs =1 ; +/* Adding to swap updated mapping */ + mapping =page_mapping (page); + }else { +if (likely (!PageTransHuge (page))) + goto unmap; +/* try_to_unmap isn't aware of THP page */ +if (unlikely (split_huge_page_to_list (page, + page_list))) + goto keep_locked; + } } - +unmap:/* * The page is mapped into the page tables of one or more * processes. Try to unmap it here.
Signature · 7 lines
2.0.0 -- 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>
Re: [PATCH v12 8/8] mm: Don't split THP page when syscall is called
Quoted 6 lines · Minchan Kim
We don't need to split THP page when
MADV_FREEsyscall is called. It could be done when VM decide really frees it so we could avoid unnecessary THP split.Cc Andrea Arcangeli <[email protected]>Signed-off-by Minchan Kim <[email protected]>
I would like to free THP without splitting. But good enough for now.
Signature · 7 lines
Kirill A. Shutemov -- 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>
Kirill, Do you have any comment?
Quoted 103 lines · Minchan Kim
This patch enable
MADV_FREEhint for madvise syscall, which have been supported by other OSes. [PATCH 1] includes the details.[1] support
MADVISE_FREEfor !THP page so if VM encounter THP page in syscall context, it splits THP page.
[2-7] is to preparing to call madvise syscall without THP plitting
[8] enable THP page support forMADV_FREE.* From v11
* Fix arm build - Steve
* Separate patch for arm and arm64 - Steve
* Remove unnecessary check - Kirill
* Skip non-vm_normal page - Kirill
* Add Acked-by - Zhang
* Sparc64 build fix
* Pagetable walker THP handling fix* From v10
* Add Acked-by from archstuff(x86, s390)
* Pagewalker based pagetable working - Kirill
* Fixtry_to_unmap_onebroken with hwpoison - Kirill
* UseVM_BUG_ON_PAGEinmadvise_free_pmd- Kirill
* Fixpgtable-3level.hfor arm - Steve* From v9
* Add Acked-by - Rik
* Add THP page support - Kirill* From v8
* Rebased-on v3.16-rc2-mmotm-2014-06-25-16-44* From v7
* Rebased-on next-20140613* From v6
* Remove page from swapcache in syscal time
* Move utility functions frommemory.ctomadvise.c- Johannes
* Rename untilify functtions - Johannes
* Remove unnecessary checks fromvmscan.c- Johannes
* Rebased-on v3.15-rc5-mmotm-2014-05-16-16-56
* Drop Reviewe-by because there was some changes since then.* From v5
* Fix PPC problem which don't flush TLB - Rik
* Remove unnecessarylazyfree_rangestub function - Rik
* Rebased on v3.15-rc5* From v4
* Add Reviewed-by: Zhang Yanfei
* Rebase on v3.15-rc1-mmotm-2014-04-15-16-14* From v3
* Add "how to work part" in description - Zhang
* Addpage_discardableutility function - Zhang
* Clean up* From v2
* Remove forceful dirty marking of swap-readed page - Johannes
* Remove deactivation logic of lazyfreed page
* Rebased on 3.14
* Remove RFC tag* From v1
* Use custom page table walker formadvise_free- Johannes
* RemovePG_lazypageflag - Johannes
* Domadvise_dontneedinstead ofmadvise_freeinswapless systemMinchan Kim (8):
[1] mm: supportmadvise(MADV_FREE)
[2] x86: add pmd_[dirty|mkclean] for THP
[3] sparc: add pmd_[dirty|mkclean] for THP
[4] powerpc: add pmd_[dirty|mkclean] for THP
[5] s390: add pmd_[dirty|mkclean] for THP
[6] arm: add pmd_[dirty|mkclean] for THP
[7] arm64: add pmd_[dirty|mkclean] for THP
[8] mm: Don't split THP page when syscall is calledarch/arm/include/asm/pgtable-3level.h | 3 + arch/arm64/include/asm/pgtable.h | 2 + arch/powerpc/include/asm/pgtable-ppc64.h | 2 + arch/s390/include/asm/pgtable.h | 12 +++ arch/sparc/include/asm/pgtable_64.h | 16 ++++ arch/x86/include/asm/pgtable.h | 10 ++ include/linux/huge_mm.h | 4 + include/linux/rmap.h | 9 +- include/linux/vm_event_item.h | 1 + include/uapi/asm-generic/mman-common.h | 1 + mm/huge_memory.c | 35 +++++++ mm/madvise.c | 155 +++++++++++++++++++++++++++++++ mm/rmap.c | 46 ++++++++- mm/vmscan.c | 64 +++++++++---- mm/vmstat.c | 1 + 15 files changed, 341 insertions(+), 20 deletions(-)Signature · 7 lines
2.0.0 -- 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>
Signature · 8 lines
Kind regards, Minchan Kim -- 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>