add mTHP support for anonymous shmem
Subsystems (6)
Baolin Wang
reviewerv3 cover add mTHP support for anonymous shmem
Anonymous pages have already been supported for multi-size (mTHP) allocation through commit 19eaf44954df, that can allow THP to be configured through the sysfs interface located at '/sys/kernel/mm/transparent_hugepage/hugepage-XXkb/enabled'.
However, the anonymous shmem will ignore the anonymous mTHP rule configured through the sysfs interface, and can only use the PMD-mapped THP, that is not reasonable. Many implement anonymous page sharing through mmap(MAP_SHARED | MAP_ANONYMOUS), especially in database usage scenarios, therefore, users expect to apply an unified mTHP strategy for anonymous pages, also including the anonymous shared pages, in order to enjoy the benefits of mTHP. For example, lower latency than PMD-mapped THP, smaller memory bloat than PMD-mapped THP, contiguous PTEs on ARM architecture to reduce TLB miss etc.
The primary strategy is similar to supporting anonymous mTHP. Introduce a new interface '/mm/transparent_hugepage/hugepage-XXkb/shmem_enabled', which can have all the same values as the top-level '/sys/kernel/mm/transparent_hugepage/shmem_enabled', with adding a new additional "inherit" option. By default all sizes will be set to "never" except PMD size, which is set to "inherit". This ensures backward compatibility with the anonymous shmem enabled of the top level, meanwhile also allows independent control of anonymous shmem enabled for each mTHP.
Use the page fault latency tool to measure the performance of 1G anonymous shmem with 32 threads on my machine environment with: ARM64 Architecture, 32 cores, 125G memory:
base: mm-unstable
user-time sys_time faults_per_sec_per_cpu faults_per_sec
0.04s 3.10s 83516.416 2669684.890
mm-unstable + patchset, anon shmem mTHP disabled
user-time sys_time faults_per_sec_per_cpu faults_per_sec
0.02s 3.14s 82936.359 2630746.027
mm-unstable + patchset, anon shmem 64K mTHP enabled
user-time sys_time faults_per_sec_per_cpu faults_per_sec
0.08s 0.31s 678630.231 17082522.495
From the data above, it is observed that the patchset has a minimal impact when mTHP is not enabled (some fluctuations observed during testing). When enabling 64K mTHP, there is a significant improvement of the page fault latency.
Changes from v2:
- Rebased to mm/mm-unstable.
- Remove 'huge' parameter for shmem_alloc_and_add_folio(), per Lance.
Changes from v1:
- Drop the patch that re-arranges the position of highest_order() and next_order(), per Ryan.
- Modify the finish_fault() to fix VA alignment issue, per Ryan and David.
- Fix some building issues, reported by Lance and kernel test robot.
- Update some commit message.
Changes from RFC:
- Rebase the patch set against the new mm-unstable branch, per Lance.
- Add a new patch to export highest_order() and next_order().
- Add a new patch to align mTHP size in shmem_get_unmapped_area().
- Handle the uffd case and the VMA limits case when building mapping for large folio in the finish_fault() function, per Ryan.
- Remove unnecessary 'order' variable in patch 3, per Kefeng.
- Keep the anon shmem counters' name consistency.
- Modify the strategy to support mTHP for anonymous shmem, discussed with Ryan and David.
- Add reviewed tag from Barry.
- Update the commit message.
Baolin Wang (6):
mm: memory: extend finish_fault() to support large folio
mm: shmem: add THP validation for PMD-mapped THP related statistics
mm: shmem: add multi-size THP sysfs interface for anonymous shmem
mm: shmem: add mTHP support for anonymous shmem
mm: shmem: add mTHP size alignment in shmem_get_unmapped_area
mm: shmem: add mTHP counters for anonymous shmem
Documentation/admin-guide/mm/transhuge.rst | 29 ++ include/linux/huge_mm.h | 23 ++ mm/huge_memory.c | 17 +- mm/memory.c | 58 +++- mm/shmem.c | 340 ++++++++++++++++++--- 5 files changed, 406 insertions(+), 61 deletions(-)
Signature · 1 line
2.39.3
Baolin Wang
reviewerPATCH v3 1/6 mm: memory: extend finish_fault() to support large folio
Add large folio mapping establishment support for finish_fault() as a preparation, to support multi-size THP allocation of anonymous shmem pages in the following patches.
--- mm/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-)
mm/memory.c +48 -10
@@ -4831,9 +4831,12 @@ vm_fault_t finish_fault(struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;struct page *page; +struct folio *folio;vm_fault_t ret;bool is_cow = (vmf->flags &FAULT_FLAG_WRITE ) && !(vma->vm_flags &VM_SHARED ); +int type, nr_pages, i; +unsigned long addr = vmf->address;/* Did we COW the page? */ if (is_cow)
@@ -4864,24 +4867,59 @@ vm_fault_t finish_fault(struct vm_fault *vmf)return VM_FAULT_OOM ; } + folio =page_folio (page); + nr_pages =folio_nr_pages (folio); + +/* +* Using per-page fault to maintain the uffd semantics, and same +* approach also applies to non-anonymous-shmem faults to avoid +* inflating the RSS of the process. +*/ +if (!vma_is_anon_shmem (vma) ||unlikely (userfaultfd_armed (vma))) { + nr_pages =1 ; + }else if (nr_pages >1 ) { +pgoff_t idx =folio_page_idx (folio, page); +/* The page offset of vmf->address within the VMA. */ +pgoff_t vma_off = vmf->pgoff - vmf->vma->vm_pgoff; + +/* +* Fallback to per-page fault in case the folio size in page +* cache beyond the VMA limits. +*/ +if (unlikely (vma_off < idx || + vma_off + (nr_pages - idx) >vma_pages (vma))) { + nr_pages =1 ; + }else { +/* Now we can set mappings for the whole large folio. */ + addr = vmf->address - idx *PAGE_SIZE ; + page = &folio->page; + } + } + vmf->pte =pte_offset_map_lock (vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + addr, &vmf->ptl);if (!vmf->pte)return VM_FAULT_NOPAGE ;/* Re-check under ptl */ -if (likely (!vmf_pte_changed (vmf))) { -struct folio *folio =page_folio (page); -int type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); - -set_pte_range (vmf, folio, page,1 , vmf->address); -add_mm_counter (vma->vm_mm, type,1 ); - ret =0 ; - }else { -update_mmu_tlb (vma, vmf->address, vmf->pte); +if (nr_pages ==1 &&unlikely (vmf_pte_changed (vmf))) { +update_mmu_tlb (vma, addr, vmf->pte); ret =VM_FAULT_NOPAGE ; + goto unlock; + }else if (nr_pages >1 && !pte_range_none (vmf->pte, nr_pages)) { +for (i =0 ; i < nr_pages; i++) +update_mmu_tlb (vma, addr +PAGE_SIZE * i, vmf->pte + i); + ret =VM_FAULT_NOPAGE ; + goto unlock; } +folio_ref_add (folio, nr_pages -1 ); +set_pte_range (vmf, folio, page, nr_pages, addr); + type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); +add_mm_counter (vma->vm_mm, type, nr_pages); + ret =0 ; + +unlock:pte_unmap_unlock (vmf->pte, vmf->ptl);return ret; }
Signature · 1 line
2.39.3
Re: [PATCH v3 1/6] mm: memory: extend finish_fault() to support large folio
Quoted 73 lines · Baolin Wang
Add large folio mapping establishment support for
finish_fault()as a preparation, to support multi-size THP allocation of anonymous shmem pages in the following patches.Signed-off-by Baolin Wang <[email protected]>--- mm/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-)mm/memory.c +33
-7@@ -4831,9 +4831,12 @@ vm_fault_t finish_fault(struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;struct page *page; +struct folio *folio;vm_fault_t ret;bool is_cow = (vmf->flags &FAULT_FLAG_WRITE ) && !(vma->vm_flags &VM_SHARED ); +int type, nr_pages, i; +unsigned long addr = vmf->address;/* Did we COW the page? */ if (is_cow)@@ -4864,24 +4867,59 @@ vm_fault_t finish_fault(struct vm_fault *vmf)return VM_FAULT_OOM ; } + folio =page_folio (page); + nr_pages =folio_nr_pages (folio); + +/* +* Using per-page fault to maintain the uffd semantics, and same +* approach also applies to non-anonymous-shmem faults to avoid +* inflating the RSS of the process. +*/ +if (!vma_is_anon_shmem (vma) ||unlikely (userfaultfd_armed (vma))) { + nr_pages =1 ; + }else if (nr_pages >1 ) { +pgoff_t idx =folio_page_idx (folio, page); +/* The page offset of vmf->address within the VMA. */ +pgoff_t vma_off = vmf->pgoff - vmf->vma->vm_pgoff; + +/* +* Fallback to per-page fault in case the folio size in page +* cache beyond the VMA limits. +*/ +if (unlikely (vma_off < idx || + vma_off + (nr_pages - idx) >vma_pages (vma))) { + nr_pages =1 ; + }else { +/* Now we can set mappings for the whole large folio. */ + addr = vmf->address - idx *PAGE_SIZE ; + page = &folio->page; + } + } + vmf->pte =pte_offset_map_lock (vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + addr, &vmf->ptl);if (!vmf->pte)return VM_FAULT_NOPAGE ;/* Re-check under ptl */ -if (likely (!vmf_pte_changed (vmf))) { -struct folio *folio =page_folio (page); -int type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); - -set_pte_range (vmf, folio, page,1 , vmf->address); -add_mm_counter (vma->vm_mm, type,1 );
mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4911
Quoted 10 lines
mm/memory.c +6
-3- ret =0 ; - }else { -update_mmu_tlb (vma, vmf->address, vmf->pte); +if (nr_pages ==1 &&unlikely (vmf_pte_changed (vmf))) { +update_mmu_tlb (vma, addr, vmf->pte); ret =VM_FAULT_NOPAGE ; + goto unlock; + }else if (nr_pages >1 && !pte_range_none (vmf->pte, nr_pages)) { +for (i =0 ; i < nr_pages; i++) +update_mmu_tlb (vma, addr +PAGE_SIZE * i, vmf->pte + i);
Just a friendly reminder: Bang has added the update_mmu_tlb_range()[1] batch function to update TLB in batches, so we can use it instead of the update_mmu_tlb()
loop.
[1] https://lore.kernel.org/linux-mm/[email protected]/
Thanks,
Lance
Quoted 17 lines
mm/memory.c +9
-1+ ret =VM_FAULT_NOPAGE ; + goto unlock; } +folio_ref_add (folio, nr_pages -1 ); +set_pte_range (vmf, folio, page, nr_pages, addr); + type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); +add_mm_counter (vma->vm_mm, type, nr_pages); + ret =0 ; + +unlock:pte_unmap_unlock (vmf->pte, vmf->ptl);return ret; } --2.39.3
Baolin Wang
reviewerRe: [PATCH v3 1/6] mm: memory: extend finish_fault() to support large folio
Quoted 91 lines · Lance Yang
Quoted 73 lines · Baolin Wang
Add large folio mapping establishment support for
finish_fault()as a preparation, to support multi-size THP allocation of anonymous shmem pages in the following patches.Signed-off-by Baolin Wang <[email protected]>--- mm/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-)mm/memory.c +33
-7@@ -4831,9 +4831,12 @@ vm_fault_t finish_fault(struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;struct page *page; +struct folio *folio;vm_fault_t ret;bool is_cow = (vmf->flags &FAULT_FLAG_WRITE ) && !(vma->vm_flags &VM_SHARED ); +int type, nr_pages, i; +unsigned long addr = vmf->address;/* Did we COW the page? */ if (is_cow)@@ -4864,24 +4867,59 @@ vm_fault_t finish_fault(struct vm_fault *vmf)return VM_FAULT_OOM ; } + folio =page_folio (page); + nr_pages =folio_nr_pages (folio); + +/* +* Using per-page fault to maintain the uffd semantics, and same +* approach also applies to non-anonymous-shmem faults to avoid +* inflating the RSS of the process. +*/ +if (!vma_is_anon_shmem (vma) ||unlikely (userfaultfd_armed (vma))) { + nr_pages =1 ; + }else if (nr_pages >1 ) { +pgoff_t idx =folio_page_idx (folio, page); +/* The page offset of vmf->address within the VMA. */ +pgoff_t vma_off = vmf->pgoff - vmf->vma->vm_pgoff; + +/* +* Fallback to per-page fault in case the folio size in page +* cache beyond the VMA limits. +*/ +if (unlikely (vma_off < idx || + vma_off + (nr_pages - idx) >vma_pages (vma))) { + nr_pages =1 ; + }else { +/* Now we can set mappings for the whole large folio. */ + addr = vmf->address - idx *PAGE_SIZE ; + page = &folio->page; + } + } + vmf->pte =pte_offset_map_lock (vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + addr, &vmf->ptl);if (!vmf->pte)return VM_FAULT_NOPAGE ;/* Re-check under ptl */ -if (likely (!vmf_pte_changed (vmf))) { -struct folio *folio =page_folio (page); -int type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); - -set_pte_range (vmf, folio, page,1 , vmf->address); -add_mm_counter (vma->vm_mm, type,1 );mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4911
Quoted 10 lines
mm/memory.c +6
-3- ret =0 ; - }else { -update_mmu_tlb (vma, vmf->address, vmf->pte); +if (nr_pages ==1 &&unlikely (vmf_pte_changed (vmf))) { +update_mmu_tlb (vma, addr, vmf->pte); ret =VM_FAULT_NOPAGE ; + goto unlock; + }else if (nr_pages >1 && !pte_range_none (vmf->pte, nr_pages)) { +for (i =0 ; i < nr_pages; i++) +update_mmu_tlb (vma, addr +PAGE_SIZE * i, vmf->pte + i);Just a friendly reminder: Bang has added the update_mmu_tlb_range()[1] batch function to update TLB in batches, so we can use it instead of the
update_mmu_tlb()
loop.
Quoted 1 line
Good point, I will use the new helper instead.
Re: [PATCH v3 1/6] mm: memory: extend finish_fault() to support large folio
In reply to Baolin WangQuoted 28 lines · Baolin Wang
Add large folio mapping establishment support for
finish_fault()as a preparation, to support multi-size THP allocation of anonymous shmem pages in the following patches.Signed-off-by Baolin Wang <[email protected]>--- mm/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-)mm/memory.c +3
-0@@ -4831,9 +4831,12 @@ vm_fault_t finish_fault(struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;struct page *page; +struct folio *folio;vm_fault_t ret;bool is_cow = (vmf->flags &FAULT_FLAG_WRITE ) && !(vma->vm_flags &VM_SHARED ); +int type, nr_pages, i; +unsigned long addr = vmf->address;/* Did we COW the page? */ if (is_cow)
mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4876
Quoted 10 lines
mm/memory.c +7
-0@@ -4864,24 +4867,59 @@ vm_fault_t finish_fault(struct vm_fault *vmf)return VM_FAULT_OOM ; } + folio =page_folio (page); + nr_pages =folio_nr_pages (folio); + +/* +* Using per-page fault to maintain the uffd semantics, and same +* approach also applies to non-anonymous-shmem faults to avoid +* inflating the RSS of the process.
I don't feel the comment explains the root cause.
For non-shmem, anyway we have allocated the memory? Avoiding inflating RSS seems not so useful as we have occupied the memory. the memory footprint is what we really care about. so we want to rely on read-ahead hints of subpage to determine read-ahead size? that is why we don't map nr_pages for non-shmem files though we can potentially reduce nr_pages - 1 page faults?
Quoted 33 lines
mm/memory.c +23
-5+*/ +if (!vma_is_anon_shmem (vma) ||unlikely (userfaultfd_armed (vma))) { + nr_pages =1 ; + }else if (nr_pages >1 ) { +pgoff_t idx =folio_page_idx (folio, page); +/* The page offset of vmf->address within the VMA. */ +pgoff_t vma_off = vmf->pgoff - vmf->vma->vm_pgoff; + +/* +* Fallback to per-page fault in case the folio size in page +* cache beyond the VMA limits. +*/ +if (unlikely (vma_off < idx || + vma_off + (nr_pages - idx) >vma_pages (vma))) { + nr_pages =1 ; + }else { +/* Now we can set mappings for the whole large folio. */ + addr = vmf->address - idx *PAGE_SIZE ; + page = &folio->page; + } + } + vmf->pte =pte_offset_map_lock (vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + addr, &vmf->ptl);if (!vmf->pte)return VM_FAULT_NOPAGE ;/* Re-check under ptl */ -if (likely (!vmf_pte_changed (vmf))) { -struct folio *folio =page_folio (page); -int type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); -
mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4909
Quoted 10 lines
mm/memory.c +4
-5-set_pte_range (vmf, folio, page,1 , vmf->address); -add_mm_counter (vma->vm_mm, type,1 ); - ret =0 ; - }else { -update_mmu_tlb (vma, vmf->address, vmf->pte); +if (nr_pages ==1 &&unlikely (vmf_pte_changed (vmf))) { +update_mmu_tlb (vma, addr, vmf->pte); ret =VM_FAULT_NOPAGE ; + goto unlock; + }else if (nr_pages >1 && !pte_range_none (vmf->pte, nr_pages)) {
In what case we can't use !pte_range_none(vmf->pte, 1) for nr_pages == 1 then unify the code for nr_pages==1 and nr_pages > 1?
It seems this has been discussed before, but I forget the reason.
Quoted 17 lines
mm/memory.c +11
-1+for (i =0 ; i < nr_pages; i++) +update_mmu_tlb (vma, addr +PAGE_SIZE * i, vmf->pte + i); + ret =VM_FAULT_NOPAGE ; + goto unlock; } +folio_ref_add (folio, nr_pages -1 ); +set_pte_range (vmf, folio, page, nr_pages, addr); + type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); +add_mm_counter (vma->vm_mm, type, nr_pages); + ret =0 ; + +unlock:pte_unmap_unlock (vmf->pte, vmf->ptl);return ret; } --
Quoted 2 lines
2.39.3
Thanks
Barry
Baolin Wang
reviewerRe: [PATCH v3 1/6] mm: memory: extend finish_fault() to support large folio
Quoted 33 lines · Barry Song
Quoted 31 lines · Baolin Wang
Add large folio mapping establishment support for
finish_fault()as a preparation, to support multi-size THP allocation of anonymous shmem pages in the following patches.Signed-off-by Baolin Wang <[email protected]>--- mm/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-)mm/memory.c +3
-0@@ -4831,9 +4831,12 @@ vm_fault_t finish_fault(struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;struct page *page; +struct folio *folio;vm_fault_t ret;bool is_cow = (vmf->flags &FAULT_FLAG_WRITE ) && !(vma->vm_flags &VM_SHARED ); +int type, nr_pages, i; +unsigned long addr = vmf->address;/* Did we COW the page? */ if (is_cow)@@ -4864,24 +4867,59 @@ vm_fault_t finish_fault(struct vm_fault *vmf)return VM_FAULT_OOM ; }
Quoted 11 lines
mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4876
Quoted 7 lines
mm/memory.c +7
-0+ folio =page_folio (page); + nr_pages =folio_nr_pages (folio); + +/* +* Using per-page fault to maintain the uffd semantics, and same +* approach also applies to non-anonymous-shmem faults to avoid +* inflating the RSS of the process. I don't feel the comment explains the root cause.
For non-shmem, anyway we have allocated the memory? Avoiding inflating RSS seems not so useful as we have occupied the memory. the memory footprint
This is also to keep the same behavior as before for non-anon-shmem, and will be discussed in the future.
Quoted 3 lines
is what we really care about. so we want to rely on read-ahead hints of subpage to determine read-ahead size? that is why we don't map
nr_pagesfor non-shmem files though we can potentially reducenr_pages- 1 page faults?
IMHO, there is 2 cases for non-anon-shmem:
(1) read mmap() faults: we can rely on the 'fault_around_bytes' interface to determin what size of mapping to build.
(2) writable mmap() faults: I want to keep the same behavior as before (per-page fault), but we can talk about this when I send new patches to use mTHP to control large folio allocation for writable mmap().
Quoted 47 lines
Quoted 33 lines
mm/memory.c +23
-5+*/ +if (!vma_is_anon_shmem (vma) ||unlikely (userfaultfd_armed (vma))) { + nr_pages =1 ; + }else if (nr_pages >1 ) { +pgoff_t idx =folio_page_idx (folio, page); +/* The page offset of vmf->address within the VMA. */ +pgoff_t vma_off = vmf->pgoff - vmf->vma->vm_pgoff; + +/* +* Fallback to per-page fault in case the folio size in page +* cache beyond the VMA limits. +*/ +if (unlikely (vma_off < idx || + vma_off + (nr_pages - idx) >vma_pages (vma))) { + nr_pages =1 ; + }else { +/* Now we can set mappings for the whole large folio. */ + addr = vmf->address - idx *PAGE_SIZE ; + page = &folio->page; + } + } + vmf->pte =pte_offset_map_lock (vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + addr, &vmf->ptl);if (!vmf->pte)return VM_FAULT_NOPAGE ;/* Re-check under ptl */ -if (likely (!vmf_pte_changed (vmf))) { -struct folio *folio =page_folio (page); -int type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); -mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4909
Quoted 10 lines
mm/memory.c +4
-5-set_pte_range (vmf, folio, page,1 , vmf->address); -add_mm_counter (vma->vm_mm, type,1 ); - ret =0 ; - }else { -update_mmu_tlb (vma, vmf->address, vmf->pte); +if (nr_pages ==1 &&unlikely (vmf_pte_changed (vmf))) { +update_mmu_tlb (vma, addr, vmf->pte); ret =VM_FAULT_NOPAGE ; + goto unlock; + }else if (nr_pages >1 && !pte_range_none (vmf->pte, nr_pages)) {In what case we can't use !pte_range_none(vmf->pte, 1) for
nr_pages== 1 then unify the code for nr_pages==1 andnr_pages> 1?
Quoted 1 line
It seems this has been discussed before, but I forget the reason.
IIUC, this is for uffd case, which is not a none pte entry.
Re: [PATCH v3 1/6] mm: memory: extend finish_fault() to support large folio
Quoted 49 lines · Baolin Wang
Quoted 33 lines · Barry Song
Quoted 31 lines · Baolin Wang
Add large folio mapping establishment support for
finish_fault()as a preparation, to support multi-size THP allocation of anonymous shmem pages in the following patches.Signed-off-by Baolin Wang <[email protected]>--- mm/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-)mm/memory.c +3
-0@@ -4831,9 +4831,12 @@ vm_fault_t finish_fault(struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;struct page *page; +struct folio *folio;vm_fault_t ret;bool is_cow = (vmf->flags &FAULT_FLAG_WRITE ) && !(vma->vm_flags &VM_SHARED ); +int type, nr_pages, i; +unsigned long addr = vmf->address;/* Did we COW the page? */ if (is_cow)@@ -4864,24 +4867,59 @@ vm_fault_t finish_fault(struct vm_fault *vmf)return VM_FAULT_OOM ; }Quoted 11 lines
mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4876
Quoted 7 lines
mm/memory.c +7
-0+ folio =page_folio (page); + nr_pages =folio_nr_pages (folio); + +/* +* Using per-page fault to maintain the uffd semantics, and same +* approach also applies to non-anonymous-shmem faults to avoid +* inflating the RSS of the process. I don't feel the comment explains the root cause.
For non-shmem, anyway we have allocated the memory? Avoiding inflating RSS seems not so useful as we have occupied the memory. the memory footprint
Quoted 2 lines
This is also to keep the same behavior as before for non-anon-shmem, and will be discussed in the future.
OK.
Quoted 11 lines
Quoted 4 lines
is what we really care about. so we want to rely on read-ahead hints of subpage to determine read-ahead size? that is why we don't map
nr_pagesfor non-shmem files though we can potentially reducenr_pages- 1 page faults?IMHO, there is 2 cases for non-anon-shmem:
(1) readmmap()faults: we can rely on the 'fault_around_bytes' interface to determin what size of mapping to build.
(2) writablemmap()faults: I want to keep the same behavior as before (per-page fault), but we can talk about this when I send new patches to use mTHP to control large folio allocation for writablemmap().
OK.
Quoted 48 lines
Quoted 48 lines
Quoted 34 lines
mm/memory.c +23
-5+*/ +if (!vma_is_anon_shmem (vma) ||unlikely (userfaultfd_armed (vma))) { + nr_pages =1 ; + }else if (nr_pages >1 ) { +pgoff_t idx =folio_page_idx (folio, page); +/* The page offset of vmf->address within the VMA. */ +pgoff_t vma_off = vmf->pgoff - vmf->vma->vm_pgoff; + +/* +* Fallback to per-page fault in case the folio size in page +* cache beyond the VMA limits. +*/ +if (unlikely (vma_off < idx || + vma_off + (nr_pages - idx) >vma_pages (vma))) { + nr_pages =1 ; + }else { +/* Now we can set mappings for the whole large folio. */ + addr = vmf->address - idx *PAGE_SIZE ; + page = &folio->page; + } + } + vmf->pte =pte_offset_map_lock (vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + addr, &vmf->ptl);if (!vmf->pte)return VM_FAULT_NOPAGE ;/* Re-check under ptl */ -if (likely (!vmf_pte_changed (vmf))) { -struct folio *folio =page_folio (page); -int type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); -mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4909
Quoted 10 lines
mm/memory.c +4
-5-set_pte_range (vmf, folio, page,1 , vmf->address); -add_mm_counter (vma->vm_mm, type,1 ); - ret =0 ; - }else { -update_mmu_tlb (vma, vmf->address, vmf->pte); +if (nr_pages ==1 &&unlikely (vmf_pte_changed (vmf))) { +update_mmu_tlb (vma, addr, vmf->pte); ret =VM_FAULT_NOPAGE ; + goto unlock; + }else if (nr_pages >1 && !pte_range_none (vmf->pte, nr_pages)) {In what case we can't use !pte_range_none(vmf->pte, 1) for
nr_pages== 1 then unify the code for nr_pages==1 andnr_pages> 1?
Quoted 3 lines
Quoted 1 line
It seems this has been discussed before, but I forget the reason.
IIUC, this is for uffd case, which is not a none pte entry.
Is it possible to have a COW case for shmem? For example, if someone maps a shmem
file as read-only and then writes to it, would that prevent the use of pte_range_none?
Furthermore, if we encounter a large folio in shmem while reading, does it necessarily
mean we can map the entire folio? Is it possible for some processes to only map part
of large folios? For instance, if process A allocates large folios and process B maps
only part of this shmem file or partially unmaps a large folio, how would that be handled?
Apologies for not debugging this thoroughly, but these two corner cases seem worth
considering. If these scenarios have already been addressed, please disregard my comments.
Thanks
Barry
Re: [PATCH v3 1/6] mm: memory: extend finish_fault() to support large folio
Quoted 119 lines · Barry Song
Quoted 49 lines · Baolin Wang
Quoted 33 lines · Barry Song
Quoted 31 lines · Baolin Wang
Add large folio mapping establishment support for
finish_fault()as a preparation, to support multi-size THP allocation of anonymous shmem pages in the following patches.Signed-off-by Baolin Wang <[email protected]>--- mm/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-)mm/memory.c +3
-0@@ -4831,9 +4831,12 @@ vm_fault_t finish_fault(struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;struct page *page; +struct folio *folio;vm_fault_t ret;bool is_cow = (vmf->flags &FAULT_FLAG_WRITE ) && !(vma->vm_flags &VM_SHARED ); +int type, nr_pages, i; +unsigned long addr = vmf->address;/* Did we COW the page? */ if (is_cow)@@ -4864,24 +4867,59 @@ vm_fault_t finish_fault(struct vm_fault *vmf)return VM_FAULT_OOM ; }Quoted 11 lines
mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4876
Quoted 7 lines
mm/memory.c +7
-0+ folio =page_folio (page); + nr_pages =folio_nr_pages (folio); + +/* +* Using per-page fault to maintain the uffd semantics, and same +* approach also applies to non-anonymous-shmem faults to avoid +* inflating the RSS of the process. I don't feel the comment explains the root cause.
For non-shmem, anyway we have allocated the memory? Avoiding inflating RSS seems not so useful as we have occupied the memory. the memory footprintQuoted 2 lines
This is also to keep the same behavior as before for non-anon-shmem, and will be discussed in the future.
OK.
Quoted 11 lines
Quoted 4 lines
is what we really care about. so we want to rely on read-ahead hints of subpage to determine read-ahead size? that is why we don't map
nr_pagesfor non-shmem files though we can potentially reducenr_pages- 1 page faults?IMHO, there is 2 cases for non-anon-shmem:
(1) readmmap()faults: we can rely on the 'fault_around_bytes' interface to determin what size of mapping to build.
(2) writablemmap()faults: I want to keep the same behavior as before (per-page fault), but we can talk about this when I send new patches to use mTHP to control large folio allocation for writablemmap().OK.
Quoted 48 lines
Quoted 48 lines
Quoted 34 lines
mm/memory.c +23
-5+*/ +if (!vma_is_anon_shmem (vma) ||unlikely (userfaultfd_armed (vma))) { + nr_pages =1 ; + }else if (nr_pages >1 ) { +pgoff_t idx =folio_page_idx (folio, page); +/* The page offset of vmf->address within the VMA. */ +pgoff_t vma_off = vmf->pgoff - vmf->vma->vm_pgoff; + +/* +* Fallback to per-page fault in case the folio size in page +* cache beyond the VMA limits. +*/ +if (unlikely (vma_off < idx || + vma_off + (nr_pages - idx) >vma_pages (vma))) { + nr_pages =1 ; + }else { +/* Now we can set mappings for the whole large folio. */ + addr = vmf->address - idx *PAGE_SIZE ; + page = &folio->page; + } + } + vmf->pte =pte_offset_map_lock (vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + addr, &vmf->ptl);if (!vmf->pte)return VM_FAULT_NOPAGE ;/* Re-check under ptl */ -if (likely (!vmf_pte_changed (vmf))) { -struct folio *folio =page_folio (page); -int type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); -mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4909
Quoted 10 lines
mm/memory.c +4
-5-set_pte_range (vmf, folio, page,1 , vmf->address); -add_mm_counter (vma->vm_mm, type,1 ); - ret =0 ; - }else { -update_mmu_tlb (vma, vmf->address, vmf->pte); +if (nr_pages ==1 &&unlikely (vmf_pte_changed (vmf))) { +update_mmu_tlb (vma, addr, vmf->pte); ret =VM_FAULT_NOPAGE ; + goto unlock; + }else if (nr_pages >1 && !pte_range_none (vmf->pte, nr_pages)) {In what case we can't use !pte_range_none(vmf->pte, 1) for
nr_pages== 1 then unify the code for nr_pages==1 andnr_pages> 1?
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
It seems this has been discussed before, but I forget the reason.
IIUC, this is for uffd case, which is not a none pte entry.
Is it possible to have a COW case for shmem? For example, if someone maps a shmem
file as read-only and then writes to it, would that prevent the use ofpte_range_none?
sorry, i mean PRIVATE but not READ-ONLY.
Quoted 17 lines
Furthermore, if we encounter a large folio in shmem while reading, does it necessarily
mean we can map the entire folio? Is it possible for some processes to only map part
of large folios? For instance, if process A allocates large folios and process B maps
only part of this shmem file or partially unmaps a large folio, how would that be handled?Apologies for not debugging this thoroughly, but these two corner cases seem worth
considering. If these scenarios have already been addressed, please disregard my comments.Thanks
Barry
Baolin Wang
reviewerRe: [PATCH v3 1/6] mm: memory: extend finish_fault() to support large folio
Quoted 122 lines · Barry Song
Quoted 121 lines · Barry Song
Quoted 49 lines · Baolin Wang
Quoted 33 lines · Barry Song
Quoted 31 lines · Baolin Wang
Add large folio mapping establishment support for
finish_fault()as a preparation, to support multi-size THP allocation of anonymous shmem pages in the following patches.Signed-off-by Baolin Wang <[email protected]>--- mm/memory.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 10 deletions(-)mm/memory.c +3
-0@@ -4831,9 +4831,12 @@ vm_fault_t finish_fault(struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;struct page *page; +struct folio *folio;vm_fault_t ret;bool is_cow = (vmf->flags &FAULT_FLAG_WRITE ) && !(vma->vm_flags &VM_SHARED ); +int type, nr_pages, i; +unsigned long addr = vmf->address;/* Did we COW the page? */ if (is_cow)@@ -4864,24 +4867,59 @@ vm_fault_t finish_fault(struct vm_fault *vmf)return VM_FAULT_OOM ; }Quoted 11 lines
mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4876
Quoted 7 lines
mm/memory.c +7
-0+ folio =page_folio (page); + nr_pages =folio_nr_pages (folio); + +/* +* Using per-page fault to maintain the uffd semantics, and same +* approach also applies to non-anonymous-shmem faults to avoid +* inflating the RSS of the process. I don't feel the comment explains the root cause.
For non-shmem, anyway we have allocated the memory? Avoiding inflating RSS seems not so useful as we have occupied the memory. the memory footprintQuoted 2 lines
This is also to keep the same behavior as before for non-anon-shmem, and will be discussed in the future.
OK.
Quoted 11 lines
Quoted 4 lines
is what we really care about. so we want to rely on read-ahead hints of subpage to determine read-ahead size? that is why we don't map
nr_pagesfor non-shmem files though we can potentially reducenr_pages- 1 page faults?IMHO, there is 2 cases for non-anon-shmem:
(1) readmmap()faults: we can rely on the 'fault_around_bytes' interface to determin what size of mapping to build.
(2) writablemmap()faults: I want to keep the same behavior as before (per-page fault), but we can talk about this when I send new patches to use mTHP to control large folio allocation for writablemmap().OK.
Quoted 50 lines
Quoted 49 lines
Quoted 34 lines
mm/memory.c +23
-5+*/ +if (!vma_is_anon_shmem (vma) ||unlikely (userfaultfd_armed (vma))) { + nr_pages =1 ; + }else if (nr_pages >1 ) { +pgoff_t idx =folio_page_idx (folio, page); +/* The page offset of vmf->address within the VMA. */ +pgoff_t vma_off = vmf->pgoff - vmf->vma->vm_pgoff; + +/* +* Fallback to per-page fault in case the folio size in page +* cache beyond the VMA limits. +*/ +if (unlikely (vma_off < idx || + vma_off + (nr_pages - idx) >vma_pages (vma))) { + nr_pages =1 ; + }else { +/* Now we can set mappings for the whole large folio. */ + addr = vmf->address - idx *PAGE_SIZE ; + page = &folio->page; + } + } + vmf->pte =pte_offset_map_lock (vma->vm_mm, vmf->pmd, - vmf->address, &vmf->ptl); + addr, &vmf->ptl);if (!vmf->pte)return VM_FAULT_NOPAGE ;/* Re-check under ptl */ -if (likely (!vmf_pte_changed (vmf))) { -struct folio *folio =page_folio (page); -int type = is_cow ?MM_ANONPAGES :mm_counter_file (folio); -mm/memory.c vm_fault_t finish_fault(struct vm_fault *vmf) · line 4909
Quoted 10 lines
mm/memory.c +4
-5-set_pte_range (vmf, folio, page,1 , vmf->address); -add_mm_counter (vma->vm_mm, type,1 ); - ret =0 ; - }else { -update_mmu_tlb (vma, vmf->address, vmf->pte); +if (nr_pages ==1 &&unlikely (vmf_pte_changed (vmf))) { +update_mmu_tlb (vma, addr, vmf->pte); ret =VM_FAULT_NOPAGE ; + goto unlock; + }else if (nr_pages >1 && !pte_range_none (vmf->pte, nr_pages)) {In what case we can't use !pte_range_none(vmf->pte, 1) for
nr_pages== 1 then unify the code for nr_pages==1 andnr_pages> 1?It seems this has been discussed before, but I forget the reason.
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
IIUC, this is for uffd case, which is not a none pte entry.
Is it possible to have a COW case for shmem? For example, if someone maps a shmem
file as read-only and then writes to it, would that prevent the use ofpte_range_none?sorry, i mean PRIVATE but not READ-ONLY.
Yes, I think so. Now CoW case still use per-page fault in do_cow_fault().
Quoted 3 lines
Quoted 3 lines
Furthermore, if we encounter a large folio in shmem while reading, does it necessarily
mean we can map the entire folio? Is it possible for some processes to
Now this will depend on the 'fault_around_bytes' interface.
Quoted 5 lines
Quoted 5 lines
only map part
of large folios? For instance, if process A allocates large folios and process B maps
only part of this shmem file or partially unmaps a large folio, how would that be handled?
This is certainly possible.
For tmpfs:
(1) If 'fault_around_bytes' is enabled, filemap_map_pages() will handle partially mapping of the large folio for process B.
(2) If 'fault_around_bytes' is set to 0, finish_fault() will fallback to per-page fault.
For Anonomous shmem, process B should be the child of process A in your case, then:
(1) If 'fault_around_bytes' is enabled, behavior is same with tmpfs.
(2) If 'fault_around_bytes' is set to 0, finish_fault() will build the whole large folio mapping for process B. Since process B will copy the same shared VMA from parent process A, which means a mTHP mapping to share.
Quoted 4 lines
Quoted 4 lines
Apologies for not debugging this thoroughly, but these two corner cases seem worth
considering. If these scenarios have already been addressed, please disregard my comments.
No worries:) Thanks for your valuable input.
Baolin Wang
reviewerPATCH v3 2/6 mm: shmem: add THP validation for PMD-mapped THP related statistics
In reply to Baolin WangIn order to extend support for mTHP, add THP validation for PMD-mapped THP related statistics to avoid statistical confusion.
--- mm/shmem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
mm/shmem.c +4 -3
@@ -1647,7 +1647,7 @@ static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,return ERR_PTR (-E2BIG ); folio =shmem_alloc_folio (gfp,HPAGE_PMD_ORDER , info, index); -if (!folio) +if (!folio && pages ==HPAGE_PMD_NR )count_vm_event (THP_FILE_FALLBACK ); }else { pages =1 ;
@@ -1665,7 +1665,7 @@ static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,if (xa_find (&mapping->i_pages, &index, index + pages -1 ,XA_PRESENT )) { error = -EEXIST ; - }else if (huge) { + }else if (pages ==HPAGE_PMD_NR ) {count_vm_event (THP_FILE_FALLBACK );count_vm_event (THP_FILE_FALLBACK_CHARGE ); }
@@ -2031,7 +2031,8 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index, folio =shmem_alloc_and_add_folio (huge_gfp, inode, index, fault_mm, true);if (!IS_ERR (folio)) { -count_vm_event (THP_FILE_ALLOC ); +if (folio_test_pmd_mappable (folio)) +count_vm_event (THP_FILE_ALLOC ); goto alloced; }if (PTR_ERR (folio) == -EEXIST )
Signature · 1 line
2.39.3
Baolin Wang
reviewerPATCH v3 3/6 mm: shmem: add multi-size THP sysfs interface for anonymous shmem
In reply to Baolin WangTo support the use of mTHP with anonymous shmem, add a new sysfs interface 'shmem_enabled' in the '/sys/kernel/mm/transparent_hugepage/hugepages-kB/' directory for each mTHP to control whether shmem is enabled for that mTHP, with a value similar to the top level 'shmem_enabled', which can be set to:
"always", "inherit (to inherit the top level setting)", "within_size", "advise", "never", "deny", "force". These values follow the same semantics as the top level, except the 'deny' is equivalent to 'never', and 'force' is equivalent to 'always' to keep compatibility.
By default, PMD-sized hugepages have enabled="inherit" and all other hugepage sizes have enabled="never" for '/sys/kernel/mm/transparent_hugepage/hugepages-xxkB/shmem_enabled'.
In addition, if top level value is 'force', then only PMD-sized hugepages have enabled="inherit", otherwise configuration will be failed and vice versa. That means now we will avoid using non-PMD sized THP to override the global huge allocation.
--- Documentation/admin-guide/mm/transhuge.rst | 29 +++++++ include/linux/huge_mm.h | 10 +++ mm/huge_memory.c | 11 +-- mm/shmem.c | 96 ++++++++++++++++++++++ 4 files changed, 138 insertions(+), 8 deletions(-)
Documentation/admin-guide/mm/transhuge.rst +29 -0
@@ -332,6 +332,35 @@ deny force Force the huge option on for all - very useful for testing; +Anonymous shmem can also use "multi-size THP" (mTHP) by adding a new sysfs knob +to control mTHP allocation: /sys/kernel/mm/transparent_hugepage/hugepages-<size>kB/shmem_enabled. +Its value for each mTHP is essentially consistent with the global setting, except +for the addition of 'inherit' to ensure compatibility with the global settings. +always + Attempt to allocate <size> huge pages every time we need a new page; + +inherit + Inherit the top-level "shmem_enabled" value. By default, PMD-sized hugepages + have enabled="inherit" and all other hugepage sizes have enabled="never"; + +never + Do not allocate <size> huge pages; + +within_size + Only allocate <size> huge page if it will be fully within i_size. + Also respect fadvise()/madvise() hints; + +advise + Only allocate <size> huge pages if requested with fadvise()/madvise(); + +deny + Has the same semantics as 'never', now mTHP allocation policy is only + used for anonymous shmem and no not override tmpfs. + +force + Has the same semantics as 'always', now mTHP allocation policy is only + used for anonymous shmem and no not override tmpfs. + Need of application restart ===========================
include/linux/huge_mm.h +10 -0
@@ -6,6 +6,7 @@#include <linux/mm_types.h> #include <linux/fs.h> /* only for vma_is_dax() */ +#include <linux/kobject.h> vm_fault_t do_huge_pmd_anonymous_page (struct vm_fault *vmf); int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
@@ -63,6 +64,7 @@ ssize_t single_hugepage_flag_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf, enum transparent_hugepage_flag flag);extern struct kobj_attribute shmem_enabled_attr; +extern struct kobj_attribute thpsize_shmem_enabled_attr;/* * Mask of all large folio orders supported for anonymous THP; all orders up to
@@ -265,6 +267,14 @@ unsigned long thp_vma_allowable_orders(struct vm_area_struct *vma,return __thp_vma_allowable_orders (vma, vm_flags, tva_flags, orders); } +struct thpsize { +struct kobject kobj; +struct list_head node; +int order; +}; + +#define to_thpsize (kobj) container_of(kobj, struct thpsize, kobj) +enum mthp_stat_item {MTHP_STAT_ANON_FAULT_ALLOC ,MTHP_STAT_ANON_FAULT_FALLBACK ,
mm/huge_memory.c +3 -8
@@ -449,14 +449,6 @@ static void thpsize_release(struct kobject *kobj);static DEFINE_SPINLOCK (huge_anon_orders_lock);static LIST_HEAD (thpsize_list); -struct thpsize { -struct kobject kobj; -struct list_head node; -int order; -}; - -#define to_thpsize (kobj) container_of(kobj, struct thpsize, kobj) -static ssize_t thpsize_enabled_show (struct kobject *kobj,struct kobj_attribute *attr,char *buf) {
@@ -517,6 +509,9 @@ static struct kobj_attribute thpsize_enabled_attr =static struct attribute *thpsize_attrs[] = { &thpsize_enabled_attr.attr, +#ifdef CONFIG_SHMEM + &thpsize_shmem_enabled_attr.attr, +#endifNULL , };
mm/shmem.c +96 -0
120 lines not on this page · raw message
Signature · 1 line
2.39.3
Re:[PATCH v3 3/6] mm: shmem: add multi-size THP sysfs interface for anonymous shmem
Quoted 53 lines · Baolin Wang
To support the use of mTHP with anonymous shmem, add a new sysfs interface '
shmem_enabled' in the '/sys/kernel/mm/transparent_hugepage/hugepages-kB/' directory for each mTHP to control whether shmem is enabled for that mTHP, with a value similar to the top level 'shmem_enabled', which can be set to:
"always", "inherit (to inherit the top level setting)", "within_size", "advise", "never", "deny", "force". These values follow the same semantics as the top level, except the 'deny' is equivalent to 'never', and 'force' is equivalent to 'always' to keep compatibility.By default, PMD-sized hugepages have enabled="inherit" and all other hugepage sizes have enabled="never" for '
/sys/kernel/mm/transparent_hugepage/hugepages-xxkB/shmem_enabled'.In addition, if top level value is 'force', then only PMD-sized hugepages have enabled="inherit", otherwise configuration will be failed and vice versa. That means now we will avoid using non-PMD sized THP to override the global huge allocation.
Signed-off-by Baolin Wang <[email protected]>---
Documentation/admin-guide/mm/transhuge.rst | 29 +++++++ include/linux/huge_mm.h | 10 +++ mm/huge_memory.c | 11 +-- mm/shmem.c | 96 ++++++++++++++++++++++ 4 files changed, 138 insertions(+), 8 deletions(-)Documentation/admin-guide/mm/transhuge.rst +0
-0@@ -332,6 +332,35 @@ denyforce
Force the huge option on for all - very useful for testing;Documentation/admin-guide/mm/transhuge.rst +20
-0+Anonymous shmem can also use "multi-size THP" (mTHP) by adding a new sysfs knob +to control mTHP allocation: /sys/kernel/mm/transparent_hugepage/hugepages-<size>kB/shmem_enabled. +Its value for each mTHP is essentially consistent with the global setting, except +for the addition of 'inherit' to ensure compatibility with the global settings. +always + Attempt to allocate <size> huge pages every time we need a new page; + +inherit + Inherit the top-level "shmem_enabled" value. By default, PMD-sized hugepages + have enabled="inherit" and all other hugepage sizes have enabled="never"; + +never + Do not allocate <size> huge pages; + +within_size + Only allocate <size> huge page if it will be fully within i_size. + Also respect fadvise()/madvise() hints; + +advise + Only allocate <size> huge pages if requested with fadvise()/madvise();
Documentation/admin-guide/mm/transhuge.rst deny
Quoted 10 lines
Documentation/admin-guide/mm/transhuge.rst +9
-0+ +deny + Has the same semantics as 'never', now mTHP allocation policy is only + used for anonymous shmem and no not override tmpfs. + +force + Has the same semantics as 'always', now mTHP allocation policy is only + used for anonymous shmem and no not override tmpfs. +
I just briefly reviewed the discussion about the value of hugepages-<size>kB/shmem_enabled in V1 [PATCH 5/8]. Is there a conclusion now? Maybe I left out some important information.
Quoted 2 lines
Need of application restart
===========================
Baolin Wang
reviewerRe: [PATCH v3 3/6] mm: shmem: add multi-size THP sysfs interface for anonymous shmem
Quoted 59 lines · wang wei
Quoted 57 lines · Baolin Wang
To support the use of mTHP with anonymous shmem, add a new sysfs interface '
shmem_enabled' in the '/sys/kernel/mm/transparent_hugepage/hugepages-kB/' directory for each mTHP to control whether shmem is enabled for that mTHP, with a value similar to the top level 'shmem_enabled', which can be set to:
"always", "inherit (to inherit the top level setting)", "within_size", "advise", "never", "deny", "force". These values follow the same semantics as the top level, except the 'deny' is equivalent to 'never', and 'force' is equivalent to 'always' to keep compatibility.By default, PMD-sized hugepages have enabled="inherit" and all other hugepage sizes have enabled="never" for '
/sys/kernel/mm/transparent_hugepage/hugepages-xxkB/shmem_enabled'.In addition, if top level value is 'force', then only PMD-sized hugepages have enabled="inherit", otherwise configuration will be failed and vice versa. That means now we will avoid using non-PMD sized THP to override the global huge allocation.
Signed-off-by Baolin Wang <[email protected]>---
Documentation/admin-guide/mm/transhuge.rst | 29 +++++++ include/linux/huge_mm.h | 10 +++ mm/huge_memory.c | 11 +-- mm/shmem.c | 96 ++++++++++++++++++++++ 4 files changed, 138 insertions(+), 8 deletions(-)Documentation/admin-guide/mm/transhuge.rst +0
-0@@ -332,6 +332,35 @@ denyforce
Force the huge option on for all - very useful for testing;Documentation/admin-guide/mm/transhuge.rst +24
-0+Anonymous shmem can also use "multi-size THP" (mTHP) by adding a new sysfs knob +to control mTHP allocation: /sys/kernel/mm/transparent_hugepage/hugepages-<size>kB/shmem_enabled. +Its value for each mTHP is essentially consistent with the global setting, except +for the addition of 'inherit' to ensure compatibility with the global settings. +always + Attempt to allocate <size> huge pages every time we need a new page; + +inherit + Inherit the top-level "shmem_enabled" value. By default, PMD-sized hugepages + have enabled="inherit" and all other hugepage sizes have enabled="never"; + +never + Do not allocate <size> huge pages; + +within_size + Only allocate <size> huge page if it will be fully within i_size. + Also respect fadvise()/madvise() hints; + +advise + Only allocate <size> huge pages if requested with fadvise()/madvise(); + +deny + Has the same semantics as 'never', now mTHP allocation policy is only + used for anonymous shmem and no not override tmpfs.
Quoted 8 lines
Documentation/admin-guide/mm/transhuge.rst deny · line 363
Quoted 5 lines
Documentation/admin-guide/mm/transhuge.rst +5
-0+ +force + Has the same semantics as 'always', now mTHP allocation policy is only + used for anonymous shmem and no not override tmpfs. +I just briefly reviewed the discussion about the value of hugepages-<size>kB/shmem_enabled in V1 [PATCH 5/8]. Is there a conclusion now? Maybe I left out some important information.
You can refer to the this patch's commit message and documentation, which are based on the conclusions of previous discussions.
In addition, you can also read more discussions from the last bi-weekly MM meeting[1], summarized by David.
Baolin Wang
reviewerPATCH v3 4/6 mm: shmem: add mTHP support for anonymous shmem
In reply to Baolin WangCommit 19eaf44954df adds multi-size THP (mTHP) for anonymous pages, that can allow THP to be configured through the sysfs interface located at '/sys/kernel/mm/transparent_hugepage/hugepage-XXkb/enabled'.
However, the anonymous share pages will ignore the anonymous mTHP rule configured through the sysfs interface, and can only use the PMD-mapped THP, that is not reasonable. Users expect to apply the mTHP rule for all anonymous pages, including the anonymous share pages, in order to enjoy the benefits of mTHP. For example, lower latency than PMD-mapped THP, smaller memory bloat than PMD-mapped THP, contiguous PTEs on ARM architecture to reduce TLB miss etc.
The primary strategy is similar to supporting anonymous mTHP. Introduce a new interface '/mm/transparent_hugepage/hugepage-XXkb/shmem_enabled', which can have all the same values as the top-level '/sys/kernel/mm/transparent_hugepage/shmem_enabled', with adding a new additional "inherit" option. By default all sizes will be set to "never" except PMD size, which is set to "inherit". This ensures backward compatibility with the anonymous shmem enabled of the top level, meanwhile also allows independent control of anonymous shmem enabled for each mTHP.
--- include/linux/huge_mm.h | 10 +++ mm/shmem.c | 187 +++++++++++++++++++++++++++++++++------- 2 files changed, 167 insertions(+), 30 deletions(-)
include/linux/huge_mm.h +10 -0
@@ -575,6 +575,16 @@ static inline bool thp_migration_supported(void) {return false; } + +static inline int highest_order (unsigned long orders) +{ +return 0 ; +} + +static inline int next_order (unsigned long *orders,int prev) +{ +return 0 ; +}#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ static inline int split_folio_to_list_to_order(struct folio *folio,
mm/shmem.c +157 -30
242 lines not on this page · raw message
Signature · 1 line
2.39.3
kernel test robot
build botRe: [PATCH v3 4/6] mm: shmem: add mTHP support for anonymous shmem
kernel test robot noticed the following build warnings:
Hi Baolin,
kernel test robot noticed the following build warnings:
[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on next-20240529]
[cannot apply to linus/master v6.10-rc1]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Baolin-Wang/mm-memory-extend-finish_fault-to-support-large-folio/20240530-100805 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/ec35a23026dd016705d211e85163cabe07681516.1717033868.git.baolin.wang%40linux.alibaba.com patch subject: [PATCH v3 4/6] mm: shmem: add mTHP support for anonymous shmem config: riscv-defconfig (https://download.01.org/0day-ci/archive/20240530/[email protected]/config) compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project bafda89a0944d947fc4b3b5663185e07a397ac30) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240530/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All warnings (new ones prefixed by >>):
In file included from mm/shmem.c:28:
In file included from include/linux/ramfs.h:5:
In file included from include/linux/fs_parser.h:11:
In file included from include/linux/fs_context.h:14:
In file included from include/linux/security.h:33:
In file included from include/linux/mm.h:2245:
include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
514 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~
>> mm/shmem.c:1748:14: warning: variable 'suitable_orders' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
1748 | } else if (orders & BIT(HPAGE_PMD_ORDER)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mm/shmem.c:1766:25: note: uninitialized use occurs here
1766 | order = highest_order(suitable_orders);
| ^~~~~~~~~~~~~~~
mm/shmem.c:1748:10: note: remove the 'if' if its condition is always true
1748 | } else if (orders & BIT(HPAGE_PMD_ORDER)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mm/shmem.c:1736:31: note: initialize the variable 'suitable_orders' to silence this warning
1736 | unsigned long suitable_orders;
| ^
| = 02 warnings generated.
vim +1748 mm/shmem.c
1728
1729 static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf,
1730 gfp_t gfp, struct inode *inode, pgoff_t index,
1731 struct mm_struct *fault_mm, unsigned long orders)
1732 {
1733 struct address_space *mapping = inode->i_mapping;
1734 struct shmem_inode_info *info = SHMEM_I(inode);
1735 struct vm_area_struct *vma = vmf ? vmf->vma : NULL;
1736 unsigned long suitable_orders;
1737 struct folio *folio = NULL;
1738 long pages;
1739 int error, order;
1740
1741 if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
1742 orders = 0;
1743
1744 if (orders > 0) {
1745 if (vma && vma_is_anon_shmem(vma)) {
1746 suitable_orders = anon_shmem_suitable_orders(inode, vmf,
1747 mapping, index, orders);
> 1748 } else if (orders & BIT(HPAGE_PMD_ORDER)) { 1749 pages = HPAGE_PMD_NR;
1750 suitable_orders = BIT(HPAGE_PMD_ORDER);
1751 index = round_down(index, HPAGE_PMD_NR);
1752
1753 /*
1754 * Check for conflict before waiting on a huge allocation.
1755 * Conflict might be that a huge page has just been allocated
1756 * and added to page cache by a racing thread, or that there
1757 * is already at least one small page in the huge extent.
1758 * Be careful to retry when appropriate, but not forever!
1759 * Elsewhere -EEXIST would be the right code, but not here.
1760 */
1761 if (xa_find(&mapping->i_pages, &index,
1762 index + HPAGE_PMD_NR - 1, XA_PRESENT))
1763 return ERR_PTR(-E2BIG);
1764 }
1765
1766 order = highest_order(suitable_orders);
1767 while (suitable_orders) {
1768 pages = 1UL << order;
1769 index = round_down(index, pages);
1770 folio = shmem_alloc_folio(gfp, order, info, index);
1771 if (folio)
1772 goto allocated;
1773
1774 if (pages == HPAGE_PMD_NR)
1775 count_vm_event(THP_FILE_FALLBACK);
1776 order = next_order(&suitable_orders, order);
1777 }
1778 } else {
1779 pages = 1;
1780 folio = shmem_alloc_folio(gfp, 0, info, index);
1781 }
1782 if (!folio)
1783 return ERR_PTR(-ENOMEM);
1784
1785 allocated:
1786 __folio_set_locked(folio);
1787 __folio_set_swapbacked(folio);
1788
1789 gfp &= GFP_RECLAIM_MASK;
1790 error = mem_cgroup_charge(folio, fault_mm, gfp);
1791 if (error) {
1792 if (xa_find(&mapping->i_pages, &index,
1793 index + pages - 1, XA_PRESENT)) {
1794 error = -EEXIST;
1795 } else if (pages == HPAGE_PMD_NR) {
1796 count_vm_event(THP_FILE_FALLBACK);
1797 count_vm_event(THP_FILE_FALLBACK_CHARGE);
1798 }
1799 goto unlock;
1800 }
1801
1802 error = shmem_add_to_page_cache(folio, mapping, index, NULL, gfp);
1803 if (error)
1804 goto unlock;
1805
1806 error = shmem_inode_acct_blocks(inode, pages);
1807 if (error) {
1808 struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
1809 long freed;
1810 /*
1811 * Try to reclaim some space by splitting a few
1812 * large folios beyond i_size on the filesystem.
1813 */
1814 shmem_unused_huge_shrink(sbinfo, NULL, 2);
1815 /*
1816 * And do a shmem_recalc_inode() to account for freed pages:
1817 * except our folio is there in cache, so not quite balanced.
1818 */
1819 spin_lock(&info->lock);
1820 freed = pages + info->alloced - info->swapped -
1821 READ_ONCE(mapping->nrpages);
1822 if (freed > 0)
1823 info->alloced -= freed;
1824 spin_unlock(&info->lock);
1825 if (freed > 0)
1826 shmem_inode_unacct_blocks(inode, freed);
1827 error = shmem_inode_acct_blocks(inode, pages);
1828 if (error) {
1829 filemap_remove_folio(folio);
1830 goto unlock;
1831 }
1832 }
1833
1834 shmem_recalc_inode(inode, pages, 0);
1835 folio_add_lru(folio);
1836 return folio;
1837
1838 unlock:
1839 folio_unlock(folio);
1840 folio_put(folio);
1841 return ERR_PTR(error);
1842 }
1843
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Baolin Wang
reviewerRe: [PATCH v3 4/6] mm: shmem: add mTHP support for anonymous shmem
Quoted 36 lines · kernel test robot
Hi Baolin,
kernel test robot noticed the following build warnings:
[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on next-20240529]
[cannot apply to linus/master v6.10-rc1]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]url: https://github.com/intel-lab-lkp/linux/commits/Baolin-Wang/mm-memory-extend-finish_fault-to-support-large-folio/20240530-100805 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/ec35a23026dd016705d211e85163cabe07681516.1717033868.git.baolin.wang%40linux.alibaba.com patch subject: [PATCH v3 4/6] mm: shmem: add mTHP support for anonymous shmem config: riscv-defconfig (https://download.01.org/0day-ci/archive/20240530/[email protected]/config) compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project bafda89a0944d947fc4b3b5663185e07a397ac30) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240530/[email protected]/reproduce)If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/All warnings (new ones prefixed by >>):
In file included from
mm/shmem.c:28:
In file included frominclude/linux/ramfs.h:5:
In file included frominclude/linux/fs_parser.h:11:
In file included frominclude/linux/fs_context.h:14:
In file included frominclude/linux/security.h:33:
In file included frominclude/linux/mm.h:2245:
include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enumnode_stat_item' and 'enumlru_list') [-Wenum-enum-conversion]
514 | returnnode_stat_name(NR_LRU_BASE + lru)+ 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~Quoted 1 line
Quoted 1 line
mm/shmem.c:1748:14: warning: variable 'suitable_orders' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
Quoted 13 lines
1748 | } else if (orders & BIT(HPAGE_PMD_ORDER)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mm/shmem.c:1766:25: note: uninitialized use occurs here
1766 | order = highest_order(suitable_orders);
| ^~~~~~~~~~~~~~~
mm/shmem.c:1748:10: note: remove the 'if' if its condition is always true
1748 | } else if (orders & BIT(HPAGE_PMD_ORDER)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mm/shmem.c:1736:31: note: initialize the variable 'suitable_orders' to silence this warning
1736 | unsigned long suitable_orders;
| ^
| = 0
2 warnings generated.Thanks for reporting. Will fix the warning in next version.
Re: [PATCH v3 4/6] mm: shmem: add mTHP support for anonymous shmem
In reply to Baolin WangHi Baolin,
kernel test robot noticed the following build warnings:
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Baolin-Wang/mm-memory-extend-finish_fault-to-support-large-folio/20240530-100805 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/ec35a23026dd016705d211e85163cabe07681516.1717033868.git.baolin.wang%40linux.alibaba.com patch subject: [PATCH v3 4/6] mm: shmem: add mTHP support for anonymous shmem config: powerpc64-randconfig-r071-20240531 (https://download.01.org/0day-ci/archive/20240602/[email protected]/config) compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project bafda89a0944d947fc4b3b5663185e07a397ac30)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]> | Reported-by: Dan Carpenter <[email protected]> | Closes: https://lore.kernel.org/r/[email protected]/
smatch warnings:mm/shmem.c:1766 shmem_alloc_and_add_folio() error: uninitialized symbol 'suitable_orders'.
vim +/suitable_orders +1766 mm/shmem.c
ededbc2c2f28a1 Baolin Wang 2024-05-30 1729 static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf,
ededbc2c2f28a1 Baolin Wang 2024-05-30 1730 gfp_t gfp, struct inode *inode, pgoff_t index,
ededbc2c2f28a1 Baolin Wang 2024-05-30 1731 struct mm_struct *fault_mm, unsigned long orders)
800d8c63b2e989 Kirill A. Shutemov 2016-07-26 1732 {
3022fd7af9604d Hugh Dickins 2023-09-29 1733 struct address_space *mapping = inode->i_mapping;
0f0796945614b7 Mike Rapoport 2017-09-06 1734 struct shmem_inode_info *info = SHMEM_I(inode);
ededbc2c2f28a1 Baolin Wang 2024-05-30 1735 struct vm_area_struct *vma = vmf ? vmf->vma : NULL;
ededbc2c2f28a1 Baolin Wang 2024-05-30 1736 unsigned long suitable_orders;
ededbc2c2f28a1 Baolin Wang 2024-05-30 1737 struct folio *folio = NULL;
3022fd7af9604d Hugh Dickins 2023-09-29 1738 long pages;
ededbc2c2f28a1 Baolin Wang 2024-05-30 1739 int error, order;
800d8c63b2e989 Kirill A. Shutemov 2016-07-26 1740
396bcc5299c281 Matthew Wilcox (Oracle 2020-04-06 1741) if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
ededbc2c2f28a1 Baolin Wang 2024-05-30 1742 orders = 0;
800d8c63b2e989 Kirill A. Shutemov 2016-07-26 1743
ededbc2c2f28a1 Baolin Wang 2024-05-30 1744 if (orders > 0) {
ededbc2c2f28a1 Baolin Wang 2024-05-30 1745 if (vma && vma_is_anon_shmem(vma)) {
ededbc2c2f28a1 Baolin Wang 2024-05-30 1746 suitable_orders = anon_shmem_suitable_orders(inode, vmf,
ededbc2c2f28a1 Baolin Wang 2024-05-30 1747 mapping, index, orders);
ededbc2c2f28a1 Baolin Wang 2024-05-30 1748 } else if (orders & BIT(HPAGE_PMD_ORDER)) {
3022fd7af9604d Hugh Dickins 2023-09-29 1749 pages = HPAGE_PMD_NR;
ededbc2c2f28a1 Baolin Wang 2024-05-30 1750 suitable_orders = BIT(HPAGE_PMD_ORDER);
3022fd7af9604d Hugh Dickins 2023-09-29 1751 index = round_down(index, HPAGE_PMD_NR);
3022fd7af9604d Hugh Dickins 2023-09-29 1752
3022fd7af9604d Hugh Dickins 2023-09-29 1753 /*
3022fd7af9604d Hugh Dickins 2023-09-29 1754 * Check for conflict before waiting on a huge allocation.
3022fd7af9604d Hugh Dickins 2023-09-29 1755 * Conflict might be that a huge page has just been allocated
3022fd7af9604d Hugh Dickins 2023-09-29 1756 * and added to page cache by a racing thread, or that there
3022fd7af9604d Hugh Dickins 2023-09-29 1757 * is already at least one small page in the huge extent.
3022fd7af9604d Hugh Dickins 2023-09-29 1758 * Be careful to retry when appropriate, but not forever!
3022fd7af9604d Hugh Dickins 2023-09-29 1759 * Elsewhere -EEXIST would be the right code, but not here.
3022fd7af9604d Hugh Dickins 2023-09-29 1760 */
3022fd7af9604d Hugh Dickins 2023-09-29 1761 if (xa_find(&mapping->i_pages, &index,
3022fd7af9604d Hugh Dickins 2023-09-29 1762 index + HPAGE_PMD_NR - 1, XA_PRESENT))
3022fd7af9604d Hugh Dickins 2023-09-29 1763 return ERR_PTR(-E2BIG);
ededbc2c2f28a1 Baolin Wang 2024-05-30 1764 }suitable_orders uninitialized on else path.
52cd3b074050dd Lee Schermerhorn 2008-04-28 1765
ededbc2c2f28a1 Baolin Wang 2024-05-30 @1766 order = highest_order(suitable_orders);
ededbc2c2f28a1 Baolin Wang 2024-05-30 1767 while (suitable_orders) {
ededbc2c2f28a1 Baolin Wang 2024-05-30 1768 pages = 1UL << order;
ededbc2c2f28a1 Baolin Wang 2024-05-30 1769 index = round_down(index, pages);
ededbc2c2f28a1 Baolin Wang 2024-05-30 1770 folio = shmem_alloc_folio(gfp, order, info, index);
ededbc2c2f28a1 Baolin Wang 2024-05-30 1771 if (folio)
ededbc2c2f28a1 Baolin Wang 2024-05-30 1772 goto allocated;
ededbc2c2f28a1 Baolin Wang 2024-05-30 1773
ededbc2c2f28a1 Baolin Wang 2024-05-30 1774 if (pages == HPAGE_PMD_NR)
3022fd7af9604d Hugh Dickins 2023-09-29 1775 count_vm_event(THP_FILE_FALLBACK);
ededbc2c2f28a1 Baolin Wang 2024-05-30 1776 order = next_order(&suitable_orders, order);
ededbc2c2f28a1 Baolin Wang 2024-05-30 1777 }
3022fd7af9604d Hugh Dickins 2023-09-29 1778 } else {
3022fd7af9604d Hugh Dickins 2023-09-29 1779 pages = 1;Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Baolin Wang
reviewerRe: [PATCH v3 4/6] mm: shmem: add mTHP support for anonymous shmem
Quoted 13 lines · Dan Carpenter
Hi Baolin,
kernel test robot noticed the following build warnings:
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Baolin-Wang/mm-memory-extend-finish_fault-to-support-large-folio/20240530-100805 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/ec35a23026dd016705d211e85163cabe07681516.1717033868.git.baolin.wang%40linux.alibaba.com patch subject: [PATCH v3 4/6] mm: shmem: add mTHP support for anonymous shmem config: powerpc64-randconfig-r071-20240531 (https://download.01.org/0day-ci/archive/20240602/[email protected]/config) compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project bafda89a0944d947fc4b3b5663185e07a397ac30)
Quoted 8 lines
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]> | Reported-by: Dan Carpenter <[email protected]> | Closes: https://lore.kernel.org/r/[email protected]/smatch warnings:
mm/shmem.c:1766shmem_alloc_and_add_folio()error: uninitialized symbol 'suitable_orders'.
Thanks Dan. LKP also reported this warning [1]. Will fix it.
Baolin Wang
reviewerPATCH v3 5/6 mm: shmem: add mTHP size alignment in shmem_get_unmapped_area
In reply to Baolin WangAlthough the top-level hugepage allocation can be turned off, anonymous shmem can still use mTHP by configuring the sysfs interface located at '/sys/kernel/mm/transparent_hugepage/hugepage-XXkb/shmem_enabled'. Therefore, add alignment for mTHP size to provide a suitable alignment address in shmem_get_unmapped_area().
--- mm/shmem.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-)
mm/shmem.c +27 -9
@@ -2394,6 +2394,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,unsigned long inflated_len;unsigned long inflated_addr;unsigned long inflated_offset; +unsigned long hpage_size;if (len >TASK_SIZE )return -ENOMEM ;
@@ -2412,8 +2413,6 @@ unsigned long shmem_get_unmapped_area(struct file *file,if (shmem_huge ==SHMEM_HUGE_DENY )return addr; -if (len <HPAGE_PMD_SIZE ) -return addr;if (flags &MAP_FIXED )return addr;/*
@@ -2425,8 +2424,11 @@ unsigned long shmem_get_unmapped_area(struct file *file,if (uaddr == addr)return addr; + hpage_size =HPAGE_PMD_SIZE ;if (shmem_huge !=SHMEM_HUGE_FORCE ) {struct super_block *sb; +unsigned long __maybe_unused hpage_orders; +int order =0 ;if (file) {VM_BUG_ON (file->f_op != &shmem_file_operations);
@@ -2439,18 +2441,34 @@ unsigned long shmem_get_unmapped_area(struct file *file,if (IS_ERR (shm_mnt))return addr; sb = shm_mnt->mnt_sb; + +/* +* Find the highest mTHP order used for anonymous shmem to +* provide a suitable alignment address. +*/ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + hpage_orders =READ_ONCE (huge_anon_shmem_orders_always); + hpage_orders |=READ_ONCE (huge_anon_shmem_orders_within_size); + hpage_orders |=READ_ONCE (huge_anon_shmem_orders_madvise); + hpage_orders |=READ_ONCE (huge_anon_shmem_orders_inherit); + order =highest_order (hpage_orders); + hpage_size =PAGE_SIZE << order; +#endif } -if (SHMEM_SB (sb)->huge ==SHMEM_HUGE_NEVER ) +if (SHMEM_SB (sb)->huge ==SHMEM_HUGE_NEVER && !order)return addr; } - offset = (pgoff <<PAGE_SHIFT ) & (HPAGE_PMD_SIZE -1 ); -if (offset && offset + len <2 *HPAGE_PMD_SIZE ) +if (len < hpage_size) +return addr; + + offset = (pgoff <<PAGE_SHIFT ) & (hpage_size -1 ); +if (offset && offset + len <2 * hpage_size)return addr; -if ((addr & (HPAGE_PMD_SIZE -1 )) == offset) +if ((addr & (hpage_size -1 )) == offset)return addr; - inflated_len = len +HPAGE_PMD_SIZE -PAGE_SIZE ; + inflated_len = len + hpage_size -PAGE_SIZE ;if (inflated_len >TASK_SIZE )return addr;if (inflated_len < len)
@@ -2463,10 +2481,10 @@ unsigned long shmem_get_unmapped_area(struct file *file,if (inflated_addr & ~PAGE_MASK )return addr; - inflated_offset = inflated_addr & (HPAGE_PMD_SIZE -1 ); + inflated_offset = inflated_addr & (hpage_size -1 ); inflated_addr += offset - inflated_offset;if (inflated_offset > offset) - inflated_addr +=HPAGE_PMD_SIZE ; + inflated_addr += hpage_size;if (inflated_addr >TASK_SIZE - len)return addr;
Signature · 1 line
2.39.3
Baolin Wang
reviewerPATCH v3 6/6 mm: shmem: add mTHP counters for anonymous shmem
In reply to Baolin WangAdd mTHP counters for anonymous shmem.
--- include/linux/huge_mm.h | 3 +++ mm/huge_memory.c | 6 ++++++ mm/shmem.c | 18 +++++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-)
include/linux/huge_mm.h +3 -0
@@ -281,6 +281,9 @@ enum mthp_stat_item {MTHP_STAT_ANON_FAULT_FALLBACK_CHARGE ,MTHP_STAT_SWPOUT ,MTHP_STAT_SWPOUT_FALLBACK , +MTHP_STAT_FILE_ALLOC , +MTHP_STAT_FILE_FALLBACK , +MTHP_STAT_FILE_FALLBACK_CHARGE , __MTHP_STAT_COUNT };
mm/huge_memory.c +6 -0
@@ -555,6 +555,9 @@ DEFINE_MTHP_STAT_ATTR(anon_fault_fallback, MTHP_STAT_ANON_FAULT_FALLBACK);DEFINE_MTHP_STAT_ATTR (anon_fault_fallback_charge,MTHP_STAT_ANON_FAULT_FALLBACK_CHARGE );DEFINE_MTHP_STAT_ATTR (swpout,MTHP_STAT_SWPOUT );DEFINE_MTHP_STAT_ATTR (swpout_fallback,MTHP_STAT_SWPOUT_FALLBACK ); +DEFINE_MTHP_STAT_ATTR (file_alloc,MTHP_STAT_FILE_ALLOC ); +DEFINE_MTHP_STAT_ATTR (file_fallback,MTHP_STAT_FILE_FALLBACK ); +DEFINE_MTHP_STAT_ATTR (file_fallback_charge,MTHP_STAT_FILE_FALLBACK_CHARGE );static struct attribute *stats_attrs[] = { &anon_fault_alloc_attr.attr,
@@ -562,6 +565,9 @@ static struct attribute *stats_attrs[] = { &anon_fault_fallback_charge_attr.attr, &swpout_attr.attr, &swpout_fallback_attr.attr, + &file_alloc_attr.attr, + &file_fallback_attr.attr, + &file_fallback_charge_attr.attr, NULL, };
mm/shmem.c +15 -3
@@ -1773,6 +1773,9 @@ static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf,if (pages ==HPAGE_PMD_NR )count_vm_event (THP_FILE_FALLBACK ); +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +count_mthp_stat (order,MTHP_STAT_FILE_FALLBACK ); +#endif order =next_order (&suitable_orders, order); } }else {
@@ -1792,9 +1795,15 @@ static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf,if (xa_find (&mapping->i_pages, &index, index + pages -1 ,XA_PRESENT )) { error = -EEXIST ; - }else if (pages ==HPAGE_PMD_NR ) { -count_vm_event (THP_FILE_FALLBACK ); -count_vm_event (THP_FILE_FALLBACK_CHARGE ); + }else if (pages >1 ) { +if (pages ==HPAGE_PMD_NR ) { +count_vm_event (THP_FILE_FALLBACK ); +count_vm_event (THP_FILE_FALLBACK_CHARGE ); + } +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +count_mthp_stat (folio_order (folio),MTHP_STAT_FILE_FALLBACK ); +count_mthp_stat (folio_order (folio),MTHP_STAT_FILE_FALLBACK_CHARGE ); +#endif } goto unlock; }
@@ -2168,6 +2177,9 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,if (!IS_ERR (folio)) {if (folio_test_pmd_mappable (folio))count_vm_event (THP_FILE_ALLOC ); +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +count_mthp_stat (folio_order (folio),MTHP_STAT_FILE_ALLOC ); +#endif goto alloced; }if (PTR_ERR (folio) == -EEXIST )
Signature · 1 line
2.39.3
Quoted 33 lines · Baolin Wang
Anonymous pages have already been supported for multi-size (mTHP) allocation through commit
19eaf44954df, that can allow THP to be configured through the sysfs interface located at '/sys/kernel/mm/transparent_hugepage/hugepage-XXkb/enabled'.However, the anonymous shmem will ignore the anonymous mTHP rule configured through the sysfs interface, and can only use the PMD-mapped THP, that is not reasonable. Many implement anonymous page sharing through
mmap(MAP_SHARED | MAP_ANONYMOUS), especially in database usage scenarios, therefore, users expect to apply an unified mTHP strategy for anonymous pages, also including the anonymous shared pages, in order to enjoy the benefits of mTHP. For example, lower latency than PMD-mapped THP, smaller memory bloat than PMD-mapped THP, contiguous PTEs on ARM architecture to reduce TLB miss etc.The primary strategy is similar to supporting anonymous mTHP. Introduce a new interface '/mm/transparent_hugepage/hugepage-XXkb/shmem_enabled', which can have all the same values as the top-level '
/sys/kernel/mm/transparent_hugepage/shmem_enabled', with adding a new additional "inherit" option. By default all sizes will be set to "never" except PMD size, which is set to "inherit". This ensures backward compatibility with the anonymous shmem enabled of the top level, meanwhile also allows independent control of anonymous shmem enabled for each mTHP.Use the page fault latency tool to measure the performance of 1G anonymous shmem with 32 threads on my machine environment with: ARM64 Architecture, 32 cores, 125G memory:
base: mm-unstable
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.04s 3.10s 83516.416 2669684.890mm-unstable + patchset, anon shmem mTHP disabled
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.02s 3.14s 82936.359 2630746.027
Quoted 7 lines
mm-unstable + patchset, anon shmem 64K mTHP enabled
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.08s 0.31s 678630.231 17082522.495From the data above, it is observed that the patchset has a minimal impact when
mTHP is not enabled (some fluctuations observed during testing). When enabling 64K mTHP, there is a significant improvement of the page fault latency.
Let me summarize the takeaway from the bi-weekly MM meeting as I understood it, that includes Hugh's feedback on per-block tracking vs. mTHP:
(1) Per-block tracking
Per-block tracking is currently considered unwarranted complexity in shmem.c. We should try to get it done without that. For any test cases that fail, we should consider if they are actually valid for shmem.
To optimize FALLOC_FL_PUNCH_HOLE for the cases where splitting+freeing is not possible at fallcoate() time, detecting zeropages later and retrying to split+free might be an option, without per-block tracking.
(2) mTHP controls
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.
Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that.
(4) force/disable
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
"within_size" might have value, and especially for consistency, we should have them per size.
So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
@Daniel, Pankaj, what are your plans regarding that? It would be great if we could get an understanding on the next steps on !anon shmem.
Signature · 3 lines
Cheers, David / dhildenb
Baolin Wang
reviewerQuoted 38 lines · David Hildenbrand
Quoted 37 lines · Baolin Wang
Anonymous pages have already been supported for multi-size (mTHP) allocation through commit
19eaf44954df, that can allow THP to be configured through the sysfs interface located at '/sys/kernel/mm/transparent_hugepage/hugepage-XXkb/enabled'.However, the anonymous shmem will ignore the anonymous mTHP rule configured through the sysfs interface, and can only use the PMD-mapped THP, that is not reasonable. Many implement anonymous page sharing through
mmap(MAP_SHARED | MAP_ANONYMOUS), especially in database usage scenarios, therefore, users expect to apply an unified mTHP strategy for anonymous pages, also including the anonymous shared pages, in order to enjoy the benefits of mTHP. For example, lower latency than PMD-mapped THP, smaller memory bloat than PMD-mapped THP, contiguous PTEs on ARM architecture to reduce TLB miss etc.The primary strategy is similar to supporting anonymous mTHP. Introduce a new interface '/mm/transparent_hugepage/hugepage-XXkb/shmem_enabled', which can have all the same values as the top-level '
/sys/kernel/mm/transparent_hugepage/shmem_enabled', with adding a new additional "inherit" option. By default all sizes will be set to "never" except PMD size, which is set to "inherit". This ensures backward compatibility with the anonymous shmem enabled of the top level, meanwhile also allows independent control of anonymous shmem enabled for each mTHP.Use the page fault latency tool to measure the performance of 1G anonymous shmem with 32 threads on my machine environment with: ARM64 Architecture, 32 cores, 125G memory:
base: mm-unstable
user-time sys_time faults_per_sec_per_cpufaults_per_sec0.04s 3.10s 83516.416 2669684.890mm-unstable + patchset, anon shmem mTHP disabled user-time sys_time faults_per_sec_per_cpu
faults_per_sec0.02s 3.14s 82936.359 2630746.027mm-unstable + patchset, anon shmem 64K mTHP enabled user-time sys_time faults_per_sec_per_cpu
faults_per_sec0.08s 0.31s 678630.231 17082522.495
Quoted 5 lines
Quoted 3 lines
From the data above, it is observed that the patchset has a minimal impact when mTHP is not enabled (some fluctuations observed during testing). When enabling 64K mTHP, there is a significant improvement of the page fault latency.
Let me summarize the takeaway from the bi-weekly MM meeting as I understood it, that includes Hugh's feedback on per-block tracking vs.
Thanks David for the summarization.
Quoted 10 lines
mTHP:
(1) Per-block tracking
Per-block tracking is currently considered unwarranted complexity in
shmem.c. We should try to get it done without that. For any test cases that fail, we should consider if they are actually valid for shmem.To optimize
FALLOC_FL_PUNCH_HOLEfor the cases where splitting+freeing is not possible atfallcoate()time, detecting zeropages later and retrying to split+free might be an option, without per-block tracking.
Quoted 5 lines
(2) mTHP controls
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Quoted 9 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that. >
(4) force/disableThese settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
Sorry, I missed this. So I thould remove the 'force' and 'deny' option for each mTHP, right?
Quoted 10 lines
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
@Baolin, this series likely does not consider (4) yet. And I suggest we
have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
Sure. I will remove the "anonymous thp" terminology from the documentation, but want to still keep it in the commit message, cause I want to start from the anonymous shmem.
Quoted 4 lines
@Daniel, Pankaj, what are your plans regarding that? It would be great if we could get an understanding on the next steps on !anon shmem.
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
Quoted 13 lines
Quoted 13 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that. >
(4) force/disable
Quoted 6 lines
Quoted 3 lines
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
Sorry, I missed this. So I thould remove the 'force' and 'deny' option for each mTHP, right?
Yes, that's my understanding. But we have to keep them on the top level for any possible user out there.
Quoted 14 lines
Quoted 14 lines
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
Quoted 7 lines
Quoted 3 lines
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
Sure. I will remove the "anonymous thp" terminology from the documentation, but want to still keep it in the commit message, cause I want to start from the anonymous shmem.
For commit message and friends makes sense. The story should be "controls all of shmem/tmpfs, but support will be added iteratively. The first step is anonymous shmem."
Signature · 3 lines
Cheers, David / dhildenb
Baolin Wang
reviewerQuoted 25 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
Quoted 13 lines
Quoted 13 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that. >
(4) force/disable
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
Sorry, I missed this. So I thould remove the 'force' and 'deny' option for each mTHP, right?
Yes, that's my understanding. But we have to keep them on the top level for any possible user out there.
OK.
Quoted 17 lines
Quoted 17 lines
Quoted 16 lines
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
Quoted 5 lines
Quoted 3 lines
Sure. I will remove the "anonymous thp" terminology from the documentation, but want to still keep it in the commit message, cause I want to start from the anonymous shmem.
For commit message and friends makes sense. The story should be "controls all of shmem/tmpfs, but support will be added iteratively. The first step is anonymous shmem."
Sure. Thanks.
Quoted 11 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
I've integrated patches 11 and 12 from the lsf RFC thread [1] on top of Baolin's v3 patches. You may find a version in my integration branch here [2]. I can attach them here if it's preferred.
[1] https://lore.kernel.org/all/[email protected]/
[2] https://gitlab.com/dkruces/linux-next/-/commits/next-20240604-shmem-mthp
The point here is to combine the large folios strategy I proposed with mTHP user controls. Would it make sense to limit the orders to the mapping order calculated based on the size and index?
@@ -1765,6 +1798,10 @@ static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf,
order = highest_order(suitable_orders);
while (suitable_orders) {+ if (order > mapping_order) {
+ order = next_order(&suitable_orders, order);
+ continue;
+ }
pages = 1UL << order;
index = round_down(index, pages);
folio = shmem_alloc_folio(gfp, order, info, index);Note: The branch still need to be adapted to include !anon mm.
Quoted 55 lines
Quoted 14 lines
Quoted 14 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that. >
(4) force/disableQuoted 6 lines
Quoted 3 lines
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
Sorry, I missed this. So I thould remove the 'force' and 'deny' option for each mTHP, right?
Yes, that's my understanding. But we have to keep them on the top level for any possible user out there.
Quoted 14 lines
Quoted 14 lines
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
Quoted 7 lines
Quoted 3 lines
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
Sure. I will remove the "anonymous thp" terminology from the documentation, but want to still keep it in the commit message, cause I want to start from the anonymous shmem.
For commit message and friends makes sense. The story should be "controls all of shmem/tmpfs, but support will be added iteratively. The first step is anonymous shmem."
Signature · 3 lines
Cheers, David / dhildenb
Baolin Wang
reviewerQuoted 17 lines · Daniel Gomez
Quoted 11 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
I've integrated patches 11 and 12 from the lsf RFC thread [1] on top of Baolin's v3 patches. You may find a version in my integration branch here [2]. I can attach them here if it's preferred.
Quoted 6 lines
[1] https://lore.kernel.org/all/[email protected]/
[2] https://gitlab.com/dkruces/linux-next/-/commits/next-20240604-shmem-mthpThe point here is to combine the large folios strategy I proposed with mTHP user controls. Would it make sense to limit the orders to the mapping order calculated based on the size and index?
IMO, for !anon shmem, this change makes sense to me. We should respect the size and mTHP should act as a order filter.
For anon shmem, we should ignore the length, which you always set it to PAGE_SIZE in patch [1].
[1] https://gitlab.com/dkruces/linux-next/-/commit/edf02311fd6d86b355d3aeb74e67c8da6de3c569
Quoted 13 lines
(quoted diff) +4
-0@@ -1765,6 +1798,10 @@ static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf, order = highest_order(suitable_orders); while (suitable_orders) { + if (order > mapping_order) { + order = next_order(&suitable_orders, order); + continue; + } pages = 1UL << order; index = round_down(index, pages); folio = shmem_alloc_folio(gfp, order, info, index);Note: The branch still need to be adapted to include !anon mm.
Quoted 23 lines · Baolin Wang
Quoted 20 lines · Daniel Gomez
Quoted 11 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
I've integrated patches 11 and 12 from the lsf RFC thread [1] on top of Baolin's v3 patches. You may find a version in my integration branch here [2]. I can attach them here if it's preferred.
[1] https://lore.kernel.org/all/[email protected]/
[2] https://protect2.fireeye.com/v1/url?k=a23e7c06-c3b56926-a23ff749-74fe485fb347-371ca2bfd5d9869f&q=1&e=6974304e-a786-4255-93a7-57498540241c&u=https%3A%2F%2Fgitlab.com%2Fdkruces%2Flinux-next%2F-%2Fcommits%2Fnext-20240604-shmem-mthp
Quoted 6 lines
Quoted 3 lines
The point here is to combine the large folios strategy I proposed with mTHP user controls. Would it make sense to limit the orders to the mapping order calculated based on the size and index?
IMO, for !anon shmem, this change makes sense to me. We should respect the size and mTHP should act as a order filter.
What about respecing the size when within_size flag is enabled? Then, 'always' would allocate mTHP enabled folios, regardless of the size. And 'never' would ignore mTHP and size. So, 'never' can be used for this 'safe' boot case mentioned in the discussion.
Quoted 5 lines
For anon shmem, we should ignore the length, which you always set it to
PAGE_SIZEin patch [1].
Since we are ignoring the length, we should ignore any value being passed.
Quoted 14 lines
Quoted 14 lines
(quoted diff) +4
-0@@ -1765,6 +1798,10 @@ static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf, order = highest_order(suitable_orders); while (suitable_orders) { + if (order > mapping_order) { + order = next_order(&suitable_orders, order); + continue; + } pages = 1UL << order; index = round_down(index, pages); folio = shmem_alloc_folio(gfp, order, info, index);Note: The branch still need to be adapted to include !anon mm.
Baolin Wang
reviewerQuoted 28 lines · Daniel Gomez
Quoted 27 lines · Baolin Wang
Quoted 23 lines · Daniel Gomez
Quoted 11 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
I've integrated patches 11 and 12 from the lsf RFC thread [1] on top of Baolin's v3 patches. You may find a version in my integration branch here [2]. I can attach them here if it's preferred.
[1] https://lore.kernel.org/all/[email protected]/
[2] https://protect2.fireeye.com/v1/url?k=a23e7c06-c3b56926-a23ff749-74fe485fb347-371ca2bfd5d9869f&q=1&e=6974304e-a786-4255-93a7-57498540241c&u=https%3A%2F%2Fgitlab.com%2Fdkruces%2Flinux-next%2F-%2Fcommits%2Fnext-20240604-shmem-mthpThe point here is to combine the large folios strategy I proposed with mTHP user controls. Would it make sense to limit the orders to the mapping order calculated based on the size and index?
Quoted 7 lines
Quoted 2 lines
IMO, for !anon shmem, this change makes sense to me. We should respect the size and mTHP should act as a order filter.
What about respecing the size when
within_sizeflag is enabled? Then, 'always' would allocate mTHP enabled folios, regardless of the size. And 'never' would ignore mTHP and size. So, 'never' can be used for this 'safe' boot case mentioned in the discussion.
Looks reasonable to me. What do you think, David?
And what about 'advise' option? Silimar to 'within_size'?
Quoted 21 lines
Quoted 4 lines
For anon shmem, we should ignore the length, which you always set it to
PAGE_SIZEin patch [1].Since we are ignoring the length, we should ignore any value being passed.
Quoted 14 lines
Quoted 14 lines
(quoted diff) +4
-0@@ -1765,6 +1798,10 @@ static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf, order = highest_order(suitable_orders); while (suitable_orders) { + if (order > mapping_order) { + order = next_order(&suitable_orders, order); + continue; + } pages = 1UL << order; index = round_down(index, pages); folio = shmem_alloc_folio(gfp, order, info, index);Note: The branch still need to be adapted to include !anon mm.
Quoted 34 lines · Baolin Wang
Quoted 31 lines · Daniel Gomez
Quoted 29 lines · Baolin Wang
Quoted 17 lines · Daniel Gomez
Quoted 11 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
I've integrated patches 11 and 12 from the lsf RFC thread [1] on top of Baolin's v3 patches. You may find a version in my integration branch here [2]. I can attach them here if it's preferred.
Quoted 6 lines
[1] https://lore.kernel.org/all/[email protected]/
[2] https://protect2.fireeye.com/v1/url?k=a23e7c06-c3b56926-a23ff749-74fe485fb347-371ca2bfd5d9869f&q=1&e=6974304e-a786-4255-93a7-57498540241c&u=https%3A%2F%2Fgitlab.com%2Fdkruces%2Flinux-next%2F-%2Fcommits%2Fnext-20240604-shmem-mthpThe point here is to combine the large folios strategy I proposed with mTHP user controls. Would it make sense to limit the orders to the mapping order calculated based on the size and index?
IMO, for !anon shmem, this change makes sense to me. We should respect the size and mTHP should act as a order filter.
Quoted 7 lines
Quoted 4 lines
What about respecing the size when
within_sizeflag is enabled? Then, 'always' would allocate mTHP enabled folios, regardless of the size. And 'never' would ignore mTHP and size. So, 'never' can be used for this 'safe' boot case mentioned in the discussion.Looks reasonable to me. What do you think, David?
That mimics existing PMD-THP behavior, right?
With "within_size", we must not exceed the size, with "always", we may exceed the size.
Quoted 1 line
And what about 'advise' option? Silimar to '
within_size'?
Good question. What's the behavior of PMD-THP? I would assume it behaves like "within_size", because in the common case we mmap (+advise) only within the size of the file, not exceeding it.
(the always option, as I learned during the meeting, is primarily helpful when writing to tmpfs files in an append-fashion. With mmap()+madvise() that doesn't quite happen)
Signature · 3 lines
Cheers, David / dhildenb
Baolin Wang
reviewerQuoted 40 lines · David Hildenbrand
Quoted 39 lines · Baolin Wang
Quoted 35 lines · Daniel Gomez
Quoted 23 lines · Baolin Wang
Quoted 20 lines · Daniel Gomez
Quoted 11 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
I've integrated patches 11 and 12 from the lsf RFC thread [1] on top of Baolin's v3 patches. You may find a version in my integration branch here [2]. I can attach them here if it's preferred.
[1] https://lore.kernel.org/all/[email protected]/
[2] https://protect2.fireeye.com/v1/url?k=a23e7c06-c3b56926-a23ff749-74fe485fb347-371ca2bfd5d9869f&q=1&e=6974304e-a786-4255-93a7-57498540241c&u=https%3A%2F%2Fgitlab.com%2Fdkruces%2Flinux-next%2F-%2Fcommits%2Fnext-20240604-shmem-mthpQuoted 6 lines
Quoted 3 lines
The point here is to combine the large folios strategy I proposed with mTHP user controls. Would it make sense to limit the orders to the mapping order calculated based on the size and index?
IMO, for !anon shmem, this change makes sense to me. We should respect the size and mTHP should act as a order filter.
What about respecing the size when
within_sizeflag is enabled? Then, 'always' would allocate mTHP enabled folios, regardless of the size. And 'never' would ignore mTHP and size. So, 'never' can be used for this 'safe' boot case mentioned in the discussion.
Quoted 6 lines
Quoted 2 lines
Looks reasonable to me. What do you think, David?
That mimics existing PMD-THP behavior, right?
With "
within_size", we must not exceed the size, with "always", we may exceed the size.
Yes, I think so.
Quoted 3 lines
Quoted 1 line
And what about 'advise' option? Silimar to '
within_size'?Good question. What's the behavior of PMD-THP? I would assume it behaves like "
within_size", because in the common case we mmap (+advise) only within the size of the file, not exceeding it.
Yes, that is also my understanding.
Quoted 2 lines
(the always option, as I learned during the meeting, is primarily helpful when writing to tmpfs files in an append-fashion. With mmap()+madvise() that doesn't quite happen)
Quoted 40 lines · David Hildenbrand
Quoted 39 lines · Baolin Wang
Quoted 35 lines · Daniel Gomez
Quoted 23 lines · Baolin Wang
Quoted 20 lines · Daniel Gomez
Quoted 11 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
I've integrated patches 11 and 12 from the lsf RFC thread [1] on top of Baolin's v3 patches. You may find a version in my integration branch here [2]. I can attach them here if it's preferred.
[1] https://lore.kernel.org/all/[email protected]/
[2] https://protect2.fireeye.com/v1/url?k=a23e7c06-c3b56926-a23ff749-74fe485fb347-371ca2bfd5d9869f&q=1&e=6974304e-a786-4255-93a7-57498540241c&u=https%3A%2F%2Fgitlab.com%2Fdkruces%2Flinux-next%2F-%2Fcommits%2Fnext-20240604-shmem-mthpQuoted 6 lines
Quoted 3 lines
The point here is to combine the large folios strategy I proposed with mTHP user controls. Would it make sense to limit the orders to the mapping order calculated based on the size and index?
IMO, for !anon shmem, this change makes sense to me. We should respect the size and mTHP should act as a order filter.
What about respecing the size when
within_sizeflag is enabled? Then, 'always' would allocate mTHP enabled folios, regardless of the size. And 'never' would ignore mTHP and size. So, 'never' can be used for this 'safe' boot case mentioned in the discussion.
Quoted 7 lines
Quoted 2 lines
Looks reasonable to me. What do you think, David?
That mimics existing PMD-THP behavior, right?
With "
within_size", we must not exceed the size, with "always", we may exceed the size.
But right now we only check the inode size. With large folio support in write_iter() we can have access to the length as well. I think this would solve (paratially?) the cases where we don't have access to the file size and if we perform writes in bigger chunks.
E.g. xfs_io -t -f -c "pwrite -b 2M -S 0x58 0 2M" /mnt/test/file
For 'within_size', the example above would allocate 512 pages instead of one huge page. After patches [1] [2] we can get the size of the write to allocate whatever mTHP/THP makes more sense for the length being passed.
[1] https://lore.kernel.org/all/[email protected]/
[2] https://lore.kernel.org/all/[email protected]/
Here a quick hack for THP:
@@ -561,7 +561,8 @@ bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
case SHMEM_HUGE_WITHIN_SIZE:
index = round_up(index + 1, HPAGE_PMD_NR);
i_size = round_up(i_size_read(inode), PAGE_SIZE);
- if (i_size >> PAGE_SHIFT >= index)
+ if ((i_size >> PAGE_SHIFT >= index) ||
+ (len >> PAGE_SHIFT >= index))
return true;
fallthrough;Quoted 6 lines
Quoted 2 lines
And what about 'advise' option? Silimar to '
within_size'?Good question. What's the behavior of PMD-THP? I would assume it behaves like "
within_size", because in the common case we mmap (+advise) only within the size of the file, not exceeding it.
It allocates a huge page on request when MADV_HUGEPAGE (regardless of the size).
Quoted 4 lines
(the always option, as I learned during the meeting, is primarily helpful when writing to tmpfs files in an append-fashion. With mmap()+madvise() that doesn't quite happen)
Let's benefit of larger writes as well if the chunk matches any of the mTHP/ THP sizes.
Quoted 6 lines
Signature · 4 lines
-- Cheers, David / dhildenb
Quoted 54 lines · Daniel Gomez
Quoted 40 lines · David Hildenbrand
Quoted 39 lines · Baolin Wang
Quoted 35 lines · Daniel Gomez
Quoted 23 lines · Baolin Wang
Quoted 20 lines · Daniel Gomez
Quoted 11 lines · David Hildenbrand
Quoted 9 lines
Quoted 7 lines
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Good, it would be helpful to coordinate with Daniel and Pankaj.
I've integrated patches 11 and 12 from the lsf RFC thread [1] on top of Baolin's v3 patches. You may find a version in my integration branch here [2]. I can attach them here if it's preferred.
[1] https://lore.kernel.org/all/[email protected]/
[2] https://protect2.fireeye.com/v1/url?k=a23e7c06-c3b56926-a23ff749-74fe485fb347-371ca2bfd5d9869f&q=1&e=6974304e-a786-4255-93a7-57498540241c&u=https%3A%2F%2Fgitlab.com%2Fdkruces%2Flinux-next%2F-%2Fcommits%2Fnext-20240604-shmem-mthpQuoted 6 lines
Quoted 3 lines
The point here is to combine the large folios strategy I proposed with mTHP user controls. Would it make sense to limit the orders to the mapping order calculated based on the size and index?
IMO, for !anon shmem, this change makes sense to me. We should respect the size and mTHP should act as a order filter.
What about respecing the size when
within_sizeflag is enabled? Then, 'always' would allocate mTHP enabled folios, regardless of the size. And 'never' would ignore mTHP and size. So, 'never' can be used for this 'safe' boot case mentioned in the discussion.Quoted 7 lines
Quoted 2 lines
Looks reasonable to me. What do you think, David?
That mimics existing PMD-THP behavior, right?
With "
within_size", we must not exceed the size, with "always", we may exceed the size.But right now we only check the inode size. With large folio support in
write_iter()we can have access to the length as well. I think this would solve (paratially?) the cases where we don't have access to the file size and if we perform writes in bigger chunks.
Quoted 6 lines
E.g.
xfs_io-t -f -c "pwrite -b 2M -S0x580 2M"/mnt/test/fileFor '
within_size', the example above would allocate 512 pages instead of one huge page. After patches [1] [2] we can get the size of the write to allocate whatever mTHP/THP makes more sense for the length being passed.
Yes, although this sounds like an optimization/change we should be doing separately I guess.
Quoted 17 lines
[1] https://lore.kernel.org/all/[email protected]/
[2] https://lore.kernel.org/all/[email protected]/Here a quick hack for THP:
(quoted diff) +2
-1@@ -561,7 +561,8 @@ bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force, case SHMEM_HUGE_WITHIN_SIZE: index = round_up(index + 1, HPAGE_PMD_NR); i_size = round_up(i_size_read(inode), PAGE_SIZE); - if (i_size >> PAGE_SHIFT >= index) + if ((i_size >> PAGE_SHIFT >= index) || + (len >> PAGE_SHIFT >= index)) return true; fallthrough;Quoted 2 lines
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
And what about 'advise' option? Silimar to '
within_size'?Good question. What's the behavior of PMD-THP? I would assume it behaves like "
within_size", because in the common case we mmap (+advise) only within the size of the file, not exceeding it.It allocates a huge page on request when
MADV_HUGEPAGE(regardless of the size).
Interesting, so we should do the same. Thanks!
Signature · 3 lines
Cheers, David / dhildenb
Quoted 99 lines · Baolin Wang
Quoted 50 lines · David Hildenbrand
Quoted 49 lines · Baolin Wang
Anonymous pages have already been supported for multi-size (mTHP) allocation
through commit19eaf44954df, that can allow THP to be configured through the
sysfs interface located at '/sys/kernel/mm/transparent_hugepage/hugepage-XXkb/enabled'.However, the anonymous shmem will ignore the anonymous mTHP rule configured
through the sysfs interface, and can only use the PMD-mapped THP, that is not
reasonable. Many implement anonymous page sharing through mmap(MAP_SHARED |MAP_ANONYMOUS), especially in database usage scenarios, therefore, users expect
to apply an unified mTHP strategy for anonymous pages, also including the anonymous shared pages, in order to enjoy the benefits of mTHP. For example,
lower latency than PMD-mapped THP, smaller memory bloat than PMD-mapped THP,
contiguous PTEs on ARM architecture to reduce TLB miss etc.The primary strategy is similar to supporting anonymous mTHP. Introduce a new interface '/mm/transparent_hugepage/hugepage-XXkb/shmem_enabled', which can have all the same values as the top-level '
/sys/kernel/mm/transparent_hugepage/shmem_enabled', with adding a new additional "inherit" option. By default all sizes will be set to "never" except PMD size, which is set to "inherit". This ensures backward compatibility
with the anonymous shmem enabled of the top level, meanwhile also allows independent control of anonymous shmem enabled for each mTHP.Use the page fault latency tool to measure the performance of 1G anonymous shmem
with 32 threads on my machine environment with: ARM64 Architecture, 32 cores,
125G memory:
base: mm-unstable
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.04s 3.10s 83516.416 2669684.890mm-unstable + patchset, anon shmem mTHP disabled
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.02s 3.14s 82936.359 2630746.027mm-unstable + patchset, anon shmem 64K mTHP enabled
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.08s 0.31s 678630.231 17082522.495Quoted 8 lines
Quoted 5 lines
From the data above, it is observed that the patchset has a minimal
impact when
mTHP is not enabled (some fluctuations observed during testing). When enabling 64K
mTHP, there is a significant improvement of the page fault latency.Let me summarize the takeaway from the bi-weekly MM meeting as I understood it, that includes Hugh's feedback on per-block tracking vs.
Thanks David for the summarization.
Quoted 12 lines
mTHP:
(1) Per-block tracking
Per-block tracking is currently considered unwarranted complexity in
shmem.c. We should try to get it done without that. For any test cases that fail, we should consider if they are actually valid for shmem.To optimize
FALLOC_FL_PUNCH_HOLEfor the cases where splitting+freeing is not possible atfallcoate()time, detecting zeropages later and retrying to split+free might be an option, without per-block tracking.Quoted 8 lines
(2) mTHP controls
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
Yes, that's what I thought and in my TODO list.
Quoted 12 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that. >
(4) force/disable
Quoted 7 lines
Quoted 3 lines
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
Sorry, I missed this. So I thould remove the 'force' and 'deny' option for each mTHP, right?
I prefer to this. Perhaps the functionality of "force/deny" is different from that of "always/never" when tmpfs is supported. The user needs to understand the usage of "force" and "deny" again.
Quoted 38 lines · David Hildenbrand
Quoted 37 lines · Baolin Wang
Anonymous pages have already been supported for multi-size (mTHP) allocation through commit
19eaf44954df, that can allow THP to be configured through the sysfs interface located at '/sys/kernel/mm/transparent_hugepage/hugepage-XXkb/enabled'.However, the anonymous shmem will ignore the anonymous mTHP rule configured through the sysfs interface, and can only use the PMD-mapped THP, that is not reasonable. Many implement anonymous page sharing through
mmap(MAP_SHARED | MAP_ANONYMOUS), especially in database usage scenarios, therefore, users expect to apply an unified mTHP strategy for anonymous pages, also including the anonymous shared pages, in order to enjoy the benefits of mTHP. For example, lower latency than PMD-mapped THP, smaller memory bloat than PMD-mapped THP, contiguous PTEs on ARM architecture to reduce TLB miss etc.The primary strategy is similar to supporting anonymous mTHP. Introduce a new interface '/mm/transparent_hugepage/hugepage-XXkb/shmem_enabled', which can have all the same values as the top-level '
/sys/kernel/mm/transparent_hugepage/shmem_enabled', with adding a new additional "inherit" option. By default all sizes will be set to "never" except PMD size, which is set to "inherit". This ensures backward compatibility with the anonymous shmem enabled of the top level, meanwhile also allows independent control of anonymous shmem enabled for each mTHP.Use the page fault latency tool to measure the performance of 1G anonymous shmem with 32 threads on my machine environment with: ARM64 Architecture, 32 cores, 125G memory:
base: mm-unstable
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.04s 3.10s 83516.416 2669684.890mm-unstable + patchset, anon shmem mTHP disabled
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.02s 3.14s 82936.359 2630746.027mm-unstable + patchset, anon shmem 64K mTHP enabled
user-timesys_timefaults_per_sec_per_cpufaults_per_sec
0.08s 0.31s 678630.231 17082522.495
Quoted 6 lines
Quoted 3 lines
From the data above, it is observed that the patchset has a minimal impact when
mTHP is not enabled (some fluctuations observed during testing). When enabling 64K mTHP, there is a significant improvement of the page fault latency.Let me summarize the takeaway from the bi-weekly MM meeting as I understood it, that includes Hugh's feedback on per-block tracking vs. mTHP:
Thanks David for the summary. Please, find below some follow up questions.
I want understand if zeropage scanning overhead is preferred over per-block tracking complexity or if we still need to verify this.
Quoted 6 lines
(1) Per-block tracking
Per-block tracking is currently considered unwarranted complexity in
shmem.c. We should try to get it done without that. For any test cases that fail, we should consider if they are actually valid for shmem.
I agree it was unwarranted complexity but only if this is just to fix lseek() as we can simply make the test pass by checking if holes are reported as data. That would be the minimum required for lseek() to be compliant with the syscall.
How can we use per-block tracking for reclaiming memory and what changes would be needed? Or is per-block really a non-viable option?
Clearly, if per-block is viable option, shmem_fault() bug would required to be fixed first. Any ideas on how to make it reproducible?
The alternatives discussed where sub-page refcounting and zeropage scanning. The first one is not possible (IIUC) because of a refactor years back that simplified the code and also requires extra complexity. The second option would require additional overhead as we would involve scanning.
Quoted 11 lines
To optimize
FALLOC_FL_PUNCH_HOLEfor the cases where splitting+freeing is not possible atfallcoate()time, detecting zeropages later and retrying to split+free might be an option, without per-block tracking.(2) mTHP controls
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.
That was clear for me too. But what is the reason we want to boot in 'safe mode'? What are the implications of not respecing that?
Quoted 3 lines
Further, the mTHP controls should control all of shmem, not only "anonymous shmem".
As I understood from the call, mTHP with sysctl knobs is preferred over optimistic falloc/write allocation? But is still unclear to me why the former is preferred.
Is large folios a non-viable option?
Quoted 28 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that.
(4) force/disable
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
Quoted 6 lines
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
@Daniel, Pankaj, what are your plans regarding that? It would be great if we could get an understanding on the next steps on !anon shmem.
I realize I've raised so many questions, but it's essential for us to grasp the mm concerns and usage scenarios. This understanding will provide clarity on the direction regarding folios for !anon shmem.
Quoted 6 lines
Signature · 4 lines
-- Cheers, David / dhildenb
Daniel
Hi Daniel,
Quoted 15 lines
Quoted 2 lines
Let me summarize the takeaway from the bi-weekly MM meeting as I understood it, that includes Hugh's feedback on per-block tracking vs. mTHP:
Thanks David for the summary. Please, find below some follow up questions.
I want understand if zeropage scanning overhead is preferred over per-block tracking complexity or if we still need to verify this.
Quoted 6 lines
(1) Per-block tracking
Per-block tracking is currently considered unwarranted complexity in
shmem.c. We should try to get it done without that. For any test cases that fail, we should consider if they are actually valid for shmem.
Quoted 6 lines
I agree it was unwarranted complexity but only if this is just to fix
lseek()as we can simply make the test pass by checking if holes are reported as data. That would be the minimum required forlseek()to be compliant with the syscall.How can we use per-block tracking for reclaiming memory and what changes would be needed? Or is per-block really a non-viable option?
The interesting thing is: with mTHP toggles it is opt-in -- like for PMD-sized THP with shmem_enabled -- and we don't have to be that concerned about this problem right now.
Quoted 5 lines
Clearly, if per-block is viable option,
shmem_fault()bug would required to be fixed first. Any ideas on how to make it reproducible?The alternatives discussed where sub-page refcounting and zeropage scanning.
Yeah, I don't think sub-page refcounting is a feasible (and certainly not desired ;) ) option in the folio world.
Quoted 3 lines
The first one is not possible (IIUC) because of a refactor years back that simplified the code and also requires extra complexity. The second option would require additional overhead as we would involve scanning.
We'll likely need something similar (scanning, tracking?) for anonymous memory as well. There was a proposal for a THP shrinker some time ago, that would solve part of the problem.
For example, for shmem you could simply flag folios that failed splitting during fallocate() as reclaim candidates and try to reclaim memory later. So you don't have to scan arbitrary folios (which might also be desired, though).
Quoted 15 lines
Quoted 7 lines
To optimize
FALLOC_FL_PUNCH_HOLEfor the cases where splitting+freeing is not possible atfallcoate()time, detecting zeropages later and retrying to split+free might be an option, without per-block tracking.Quoted 5 lines
(2) mTHP controls
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.That was clear for me too. But what is the reason we want to boot in 'safe mode'? What are the implications of not respecing that?
[...]
Quoted 4 lines
As I understood from the call, mTHP with sysctl knobs is preferred over optimistic falloc/write allocation? But is still unclear to me why the former is preferred.
I think Hugh's point was that this should be an opt-in feature, just like PMD-sized THP started out, and still is, an opt-in feature.
Problematic interaction with khugepaged (that will be fixed) is one thing, interaction with memory reclaim (without any kind of memory reclaim mechanisms in place) might be another one. Controlling and tuning for specific folio sizes might be another one Hugh raised. [summarizing what I recall from the discussion, there might be more].
Quoted 2 lines
Is large folios a non-viable option?
I think you mean "allocating large folios without user space control".
Because mTHP gives user space full control, to the point where you can enable all sizes and obtain the same result.
Quoted 33 lines
Quoted 33 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that.
(4) force/disable
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
Quoted 6 lines
Quoted 2 lines
@Daniel, Pankaj, what are your plans regarding that? It would be great if we could get an understanding on the next steps on !anon shmem.
I realize I've raised so many questions, but it's essential for us to grasp the mm concerns and usage scenarios. This understanding will provide clarity on the direction regarding folios for !anon shmem.
If I understood correctly, Hugh had strong feelings against not respecting mTHP toggles for shmem. Without per-block tracking, I agree with that.
Signature · 3 lines
Cheers, David / dhildenb
Quoted 21 lines · David Hildenbrand
Hi Daniel,
Quoted 19 lines
Quoted 2 lines
Let me summarize the takeaway from the bi-weekly MM meeting as I understood it, that includes Hugh's feedback on per-block tracking vs. mTHP:
Thanks David for the summary. Please, find below some follow up questions.
I want understand if zeropage scanning overhead is preferred over per-block tracking complexity or if we still need to verify this.
Quoted 6 lines
(1) Per-block tracking
Per-block tracking is currently considered unwarranted complexity in
shmem.c. We should try to get it done without that. For any test cases that fail, we should consider if they are actually valid for shmem.I agree it was unwarranted complexity but only if this is just to fix
lseek()as we can simply make the test pass by checking if holes are reported as data. That would be the minimum required forlseek()to be compliant with the syscall.
Quoted 6 lines
Quoted 2 lines
How can we use per-block tracking for reclaiming memory and what changes would be needed? Or is per-block really a non-viable option?
The interesting thing is: with mTHP toggles it is opt-in -- like for PMD-sized THP with
shmem_enabled-- and we don't have to be that concerned about this problem right now.
Without respecting the size when allocating large folios, mTHP toggles would over allocate. My proposal added earlier to this thread is to combine the 2 to avoid that case. Otherwise, shouldn't we try to find a solution for the reclaiming path?
Quoted 10 lines
Quoted 6 lines
Clearly, if per-block is viable option,
shmem_fault()bug would required to be fixed first. Any ideas on how to make it reproducible?The alternatives discussed where sub-page refcounting and zeropage scanning.
Yeah, I don't think sub-page refcounting is a feasible (and certainly not desired ;) ) option in the folio world.
Quoted 7 lines
Quoted 3 lines
The first one is not possible (IIUC) because of a refactor years back that simplified the code and also requires extra complexity. The second option would require additional overhead as we would involve scanning.
We'll likely need something similar (scanning, tracking?) for anonymous memory as well. There was a proposal for a THP shrinker some time ago, that would solve part of the problem.
It's good to know we have the same problem in different places. I'm more inclined to keep the information rather than adding an extra overhead. Unless the complexity is really overwhelming. Considering the concerns here, not sure how much should we try merging with iomap as per Ritesh's suggestion.
The THP shrinker, could you please confirm if it is this following thread?
https://lore.kernel.org/all/[email protected]/
Quoted 5 lines
For example, for shmem you could simply flag folios that failed splitting during
fallocate()as reclaim candidates and try to reclaim memory later. So you don't have to scan arbitrary folios (which might also be desired, though).
Thanks for the suggestion. I'll look into this.
Quoted 20 lines
Quoted 16 lines
Quoted 8 lines
To optimize
FALLOC_FL_PUNCH_HOLEfor the cases where splitting+freeing is not possible atfallcoate()time, detecting zeropages later and retrying to split+free might be an option, without per-block tracking.Quoted 5 lines
(2) mTHP controls
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.That was clear for me too. But what is the reason we want to boot in 'safe mode'? What are the implications of not respecing that?
[...]
Quoted 1 line
Quoted 6 lines
Quoted 3 lines
As I understood from the call, mTHP with sysctl knobs is preferred over optimistic falloc/write allocation? But is still unclear to me why the former is preferred.
I think Hugh's point was that this should be an opt-in feature, just like PMD-sized THP started out, and still is, an opt-in feature.
I'd be keen to understand the use case for this. Even the current THP controls we have in tmpfs. I guess these are just scenarios with no swap involved? Are these use cases the same for both tmpfs and shmem anon mm?
Quoted 11 lines
Problematic interaction with khugepaged (that will be fixed) is one thing, interaction with memory reclaim (without any kind of memory reclaim mechanisms in place) might be another one. Controlling and tuning for specific folio sizes might be another one Hugh raised. [summarizing what I recall from the discussion, there might be more].
Quoted 2 lines
Is large folios a non-viable option?
I think you mean "allocating large folios without user space control".
Yes.
Quoted 3 lines
Because mTHP gives user space full control, to the point where you can enable all sizes and obtain the same result.
Agree.
Quoted 37 lines
Quoted 37 lines
Quoted 36 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that.
(4) force/disable
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
@Daniel, Pankaj, what are your plans regarding that? It would be great if we could get an understanding on the next steps on !anon shmem.
Quoted 6 lines
Quoted 3 lines
I realize I've raised so many questions, but it's essential for us to grasp the mm concerns and usage scenarios. This understanding will provide clarity on the direction regarding folios for !anon shmem.
If I understood correctly, Hugh had strong feelings against not respecting mTHP toggles for shmem. Without per-block tracking, I agree with that.
My understanding was the same. But I have this follow-up question: should we respect mTHP toggles without considering mapping constraints (size and index)? Or perhaps we should use within_size where we can fit this intermediate approach, as long as mTHP granularity is respected?
Daniel
Quoted 6 lines
Signature · 4 lines
-- Cheers, David / dhildenb
[...]
Quoted 11 lines
Quoted 6 lines
Quoted 2 lines
How can we use per-block tracking for reclaiming memory and what changes would be needed? Or is per-block really a non-viable option?
The interesting thing is: with mTHP toggles it is opt-in -- like for PMD-sized THP with
shmem_enabled-- and we don't have to be that concerned about this problem right now.Without respecting the size when allocating large folios, mTHP toggles would over allocate. My proposal added earlier to this thread is to combine the 2 to avoid that case. Otherwise, shouldn't we try to find a solution for the reclaiming path?
I think at some point we'll really have to do a better job at reclaiming (either memory-overallocation, PUNCHHOLE that couldn't split, but maybe also pages that are now all-zero again and could be reclaimed again).
Quoted 15 lines
Quoted 15 lines
Quoted 7 lines
Clearly, if per-block is viable option,
shmem_fault()bug would required to be fixed first. Any ideas on how to make it reproducible?The alternatives discussed where sub-page refcounting and zeropage scanning.
Yeah, I don't think sub-page refcounting is a feasible (and certainly not desired ;) ) option in the folio world.
Quoted 3 lines
The first one is not possible (IIUC) because of a refactor years back that simplified the code and also requires extra complexity. The second option would require additional overhead as we would involve scanning.
Quoted 8 lines
Quoted 3 lines
We'll likely need something similar (scanning, tracking?) for anonymous memory as well. There was a proposal for a THP shrinker some time ago, that would solve part of the problem.
It's good to know we have the same problem in different places. I'm more inclined to keep the information rather than adding an extra overhead. Unless the complexity is really overwhelming. Considering the concerns here, not sure how much should we try merging with iomap as per Ritesh's suggestion.
As raised in the meeting, I do see value in maintaining the information; but I also see why Hugh and Kirill think this might be unwarranted complexity in shmem.c. Meaning: we might be able to achieve something similar without it, and we don't have to solve the problem right now to benefit from large folios.
Quoted 4 lines
The THP shrinker, could you please confirm if it is this following thread?
Yes, although there was no follow up so far. Possibly, because in the current khugepaged approach, there will be a constant back-and-forth between khugepaged collapsing memory (and wasting memory in the default setting), and the THP shrinker reclaiming memory; doesn't sound quite effective :) That needs more thought IMHO.
[...]
Quoted 21 lines
Quoted 21 lines
Quoted 13 lines
Quoted 10 lines
To optimize
FALLOC_FL_PUNCH_HOLEfor the cases where splitting+freeing is not possible atfallcoate()time, detecting zeropages later and retrying to split+free might be an option, without per-block tracking.(2) mTHP controls
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.That was clear for me too. But what is the reason we want to boot in 'safe mode'? What are the implications of not respecing that?
[...]
Quoted 4 lines
As I understood from the call, mTHP with sysctl knobs is preferred over optimistic falloc/write allocation? But is still unclear to me why the former is preferred.
Quoted 6 lines
Quoted 2 lines
I think Hugh's point was that this should be an opt-in feature, just like PMD-sized THP started out, and still is, an opt-in feature.
I'd be keen to understand the use case for this. Even the current THP controls we have in tmpfs. I guess these are just scenarios with no swap involved? Are these use cases the same for both tmpfs and shmem anon mm?
Systems without swap are one case I think. The other reason for a toggle in the past was to be able to disable it to troubleshoot issues (Hugh mentioned in the meeting about unlocking new code paths in shmem.c only with a toggle).
Staring at my Fedora system:
$ cat /sys/kernel/mm/transparent_hugepage/shmem_enabled always within_size advise [never] deny force
Maybe because it uses tmpfs to mount /tmp (interesting article on lwn.net about that) and people are concerned about the side-effects (that can currently waste memory, or result in more reclaim work being required when exceeding file sizes).
For VMs, I know that shmem+THP with memory ballooning is problematic and not really recommended.
[...]
Quoted 40 lines
Quoted 40 lines
Quoted 39 lines
Quoted 29 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that.
(4) force/disable
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
Quoted 6 lines
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
@Daniel, Pankaj, what are your plans regarding that? It would be great if we could get an understanding on the next steps on !anon shmem.
I realize I've raised so many questions, but it's essential for us to grasp the mm concerns and usage scenarios. This understanding will provide clarity on the direction regarding folios for !anon shmem.
Quoted 7 lines
Quoted 2 lines
If I understood correctly, Hugh had strong feelings against not respecting mTHP toggles for shmem. Without per-block tracking, I agree with that.
My understanding was the same. But I have this follow-up question: should we respect mTHP toggles without considering mapping constraints (size and index)? Or perhaps we should use
within_sizewhere we can fit this intermediate approach, as long as mTHP granularity is respected?
Likely we should do exactly the same as we would do with the existing PMD-sized THPs.
I recall in the meeting that we discussed that always vs. within_size seems to have some value, and that we should respect that setting like we did for PMD-sized THP.
Which other mapping constraints could we have?
Signature · 3 lines
Cheers, David / dhildenb
Quoted 99 lines · David Hildenbrand
[...]
Quoted 11 lines
Quoted 6 lines
Quoted 2 lines
How can we use per-block tracking for reclaiming memory and what changes would be needed? Or is per-block really a non-viable option?
The interesting thing is: with mTHP toggles it is opt-in -- like for PMD-sized THP with
shmem_enabled-- and we don't have to be that concerned about this problem right now.Without respecting the size when allocating large folios, mTHP toggles would over allocate. My proposal added earlier to this thread is to combine the 2 to avoid that case. Otherwise, shouldn't we try to find a solution for the reclaiming path?
I think at some point we'll really have to do a better job at reclaiming (either memory-overallocation, PUNCHHOLE that couldn't split, but maybe also pages that are now all-zero again and could be reclaimed again).
Quoted 15 lines
Quoted 15 lines
Quoted 7 lines
Clearly, if per-block is viable option,
shmem_fault()bug would required to be fixed first. Any ideas on how to make it reproducible?The alternatives discussed where sub-page refcounting and zeropage scanning.
Yeah, I don't think sub-page refcounting is a feasible (and certainly not desired ;) ) option in the folio world.
Quoted 3 lines
The first one is not possible (IIUC) because of a refactor years back that simplified the code and also requires extra complexity. The second option would require additional overhead as we would involve scanning.
Quoted 8 lines
Quoted 3 lines
We'll likely need something similar (scanning, tracking?) for anonymous memory as well. There was a proposal for a THP shrinker some time ago, that would solve part of the problem.
It's good to know we have the same problem in different places. I'm more inclined to keep the information rather than adding an extra overhead. Unless the complexity is really overwhelming. Considering the concerns here, not sure how much should we try merging with iomap as per Ritesh's suggestion.
As raised in the meeting, I do see value in maintaining the information; but I also see why Hugh and Kirill think this might be unwarranted complexity in
shmem.c. Meaning: we might be able to achieve something similar without it, and we don't have to solve the problem right now to benefit from large folios.Quoted 4 lines
The THP shrinker, could you please confirm if it is this following thread?
Yes, although there was no follow up so far. Possibly, because in the current khugepaged approach, there will be a constant back-and-forth between khugepaged collapsing memory (and wasting memory in the default setting), and the THP shrinker reclaiming memory; doesn't sound quite effective :) That needs more thought IMHO.
[...]
Quoted 21 lines
Quoted 21 lines
Quoted 13 lines
Quoted 10 lines
To optimize
FALLOC_FL_PUNCH_HOLEfor the cases where splitting+freeing is not possible atfallcoate()time, detecting zeropages later and retrying to split+free might be an option, without per-block tracking.(2) mTHP controls
As a default, we should not be using large folios / mTHP for any shmem, just like we did with THP via
shmem_enabled. This is what this series currently does, and is aprt of the whole mTHP user-space interface design.That was clear for me too. But what is the reason we want to boot in 'safe mode'? What are the implications of not respecing that?
[...]
Quoted 4 lines
As I understood from the call, mTHP with sysctl knobs is preferred over optimistic falloc/write allocation? But is still unclear to me why the former is preferred.
Quoted 6 lines
Quoted 2 lines
I think Hugh's point was that this should be an opt-in feature, just like PMD-sized THP started out, and still is, an opt-in feature.
I'd be keen to understand the use case for this. Even the current THP controls we have in tmpfs. I guess these are just scenarios with no swap involved? Are these use cases the same for both tmpfs and shmem anon mm?
Systems without swap are one case I think. The other reason for a toggle in the past was to be able to disable it to troubleshoot issues (Hugh mentioned in the meeting about unlocking new code paths in
shmem.conly with a toggle).Staring at my Fedora system:
$ cat /sys/kernel/mm/transparent_hugepage/shmem_enabled always within_size advise [never] deny force
Quoted 7 lines
Maybe because it uses tmpfs to mount /tmp (interesting article on lwn.net about that) and people are concerned about the side-effects (that can currently waste memory, or result in more reclaim work being required when exceeding file sizes).
For VMs, I know that shmem+THP with memory ballooning is problematic and not really recommended.
Agree. We cannot PUNCH_HOLES when using THP unless the punch is PMD-size.
Quoted 51 lines
[...]
Quoted 40 lines
Quoted 40 lines
Quoted 39 lines
Quoted 29 lines
Also, we should properly fallback within the configured sizes, and not jump "over" configured sizes. Unless there is a good reason.
(3) khugepaged
khugepaged needs to handle larger folios properly as well. Until fixed, using smaller THP sizes as fallback might prohibit collapsing a PMD-sized THP later. But really, khugepaged needs to be fixed to handle that.
(4) force/disable
These settings are rather testing artifacts from the old ages. We should not add them to the per-size toggles. We might "inherit" it from the global one, though.
"
within_size" might have value, and especially for consistency, we should have them per size.So, this series only tackles anonymous shmem, which is a good starting point. Ideally, we'd get support for other shmem (especially during fault time) soon afterwards, because we won't be adding separate toggles for that from the interface POV, and having inconsistent behavior between kernel versions would be a bit unfortunate.
Quoted 6 lines
@Baolin, this series likely does not consider (4) yet. And I suggest we have to take a lot of the "anonymous thp" terminology out of this series, especially when it comes to documentation.
@Daniel, Pankaj, what are your plans regarding that? It would be great if we could get an understanding on the next steps on !anon shmem.
I realize I've raised so many questions, but it's essential for us to grasp the mm concerns and usage scenarios. This understanding will provide clarity on the direction regarding folios for !anon shmem.
Quoted 7 lines
Quoted 2 lines
If I understood correctly, Hugh had strong feelings against not respecting mTHP toggles for shmem. Without per-block tracking, I agree with that.
My understanding was the same. But I have this follow-up question: should we respect mTHP toggles without considering mapping constraints (size and index)? Or perhaps we should use
within_sizewhere we can fit this intermediate approach, as long as mTHP granularity is respected?
Quoted 8 lines
Likely we should do exactly the same as we would do with the existing PMD-sized THPs.
I recall in the meeting that we discussed that always vs.
within_sizeseems to have some value, and that we should respect that setting like we did for PMD-sized THP.Which other mapping constraints could we have?
Patch 12 in my RFC for LSF [1] adds this shmem_mapping_size_order() (updated to support get_order()) to get the max order 'based on the file size which the mapping currently allows at the given index'. Same check is done here [2] in filemap.c.
[1] https://lore.kernel.org/all/[email protected]/
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/filemap.c?h=v6.10-rc2#n1940
@@ -1726,6 +1726,37 @@ static struct folio *shmem_alloc_folio(gfp_t gfp, int order,
return folio;
}
+/**
+ * shmem_mapping_size_order - Get maximum folio order for the given file size.
+ * @mapping: Target address_space.
+ * @index: The page index.
+ * @size: The suggested size of the folio to create.
+ *
+ * This returns a high order for folios (when supported) based on the file size
+ * which the mapping currently allows at the given index. The index is relevant
+ * due to alignment considerations the mapping might have. The returned order
+ * may be less than the size passed.
+ *
+ * Like __filemap_get_folio order calculation.
+ *
+ * Return: The order.
+ */
+static inline unsigned int
+shmem_mapping_size_order(struct address_space *mapping, pgoff_t index,
+ size_t size)
+{
+ unsigned int order = get_order(max_t(size_t, size, PAGE_SIZE));
+
+ if (!mapping_large_folio_support(mapping))
+ return 0;
+
+ /* If we're not aligned, allocate a smaller folio */
+ if (index & ((1UL << order) - 1))
+ order = __ffs(index);
+
+ return min_t(size_t, order, MAX_PAGECACHE_ORDER);
+}
+
Quoted 6 lines
Signature · 4 lines
-- Cheers, David / dhildenb