mm: improve large folio readahead and alignment for exec memory
Subsystems (7)
Usama Arif
reviewerv2 cover mm: improve large folio readahead and alignment for exec memory
v2 takes a different approach from v1 trying to move away from exec_folio_order() and comeup with a generic arch independent solution which is what I think David was suggesting in [1].
I thought I would send it as code rather than try and discuss it in v1 as its easier :)
v1 -> v2: https://lore.kernel.org/all/[email protected]/
- disable mmap_miss logic for VM_EXEC (Jan Kara)
- Align in elf only when segment VA and file offset are already aligned (Rui)
- preferred_exec_order() for VM_EXEC sync mmap_readahead which takes into account zone high watermarks (as an approximation of memory pressure) (David, or atleast my approach to what David suggested in [1] :))
- Extend max alignment to mapping_max_folio_size() instead of exec_folio_order()
Motiviation
===========exec_folio_order() was introduced [2] to request readahead at an arch-preferred folio order for executable memory, enabling hardware PTE coalescing (e.g. arm64 contpte) and PMD mappings on the fault path.
However, several things prevent this from working optimally:
1. The mmap_miss heuristic in do_sync_mmap_readahead() silently disables exec readahead after 100 page faults. The mmap_miss counter tracks whether readahead is useful for mmap'd file access:
- Incremented by 1 in do_sync_mmap_readahead() on every page cache miss (page needed IO).
- Decremented by N in filemap_map_pages() for N pages successfully mapped via fault-around (pages found in cache without faulting, evidence that readahead was useful). Only non-workingset pages count and recently evicted and re-read pages don't count as hits.
- Decremented by 1 in do_async_mmap_readahead() when a PG_readahead marker page is found (indicates sequential consumption of readahead pages).
When mmap_miss exceeds MMAP_LOTSAMISS (100), all readahead is disabled. On arm64 with 64K pages, both decrement paths are inactive:
- filemap_map_pages() is never called because fault_around_pages (65536 >> PAGE_SHIFT = 1) disables should_fault_around(), which requires fault_around_pages > 1. With only 1 page in the fault-around window, there is nothing "around" to map.
- do_async_mmap_readahead() never fires for exec mappings because exec readahead sets async_size = 0, so no PG_readahead markers are placed.
With no decrements, mmap_miss monotonically increases past MMAP_LOTSAMISS after 100 faults, disabling exec readahead for the remainder of the mapping. Patch 1 fixes this by excluding VM_EXEC VMAs from the mmap_miss logic, similar to how VM_SEQ_READ is already excluded.
2. exec_folio_order() is an arch-specific hook that returns a static order (ilog2(SZ_64K >> PAGE_SHIFT)), which is suboptimal for non-4K page sizes and doesn't adapt to runtime conditions. Patch 2 replaces it with a generic preferred_exec_order() that targets min(PMD_ORDER, 2M), which naturally gives the right answer across architectures and different page sizes: contpte on arm64 (2M for all page sizes), PMD mapping on x86 (2M), and smaller PMDs like s390 (1M). The 2M cap also avoids requesting excessively large folios on configurations where PMD_ORDER is much larger (32M on arm64 16K pages, 512M on arm64 64K pages), which would cause unnecessary memory pressure. The function adapts at runtime based on VMA size and memory pressure (zone watermarks), stepping down the order when memory is tight.
3. Even with correct folio order and readahead, hardware PTE coalescing (e.g. contpte) and PMD mapping require the virtual address to be aligned to the folio size. The readahead path aligns file offsets and the buddy allocator aligns physical memory, but the virtual address depends on the VMA start. For PIE binaries, ASLR randomizes the load address at PAGE_SIZE granularity, so on arm64 with 64K pages only 1/32 of load addresses are 2M-aligned. When misaligned, contpte cannot be used for any folio in the VMA.
Patch 3 fixes this for the main binary by extending maximum_alignment() in the ELF loader to consider mapping_max_folio_size(), aligning load_bias to the largest folio the filesystem will allocate.
Patch 4 fixes this for shared libraries by adding a folio-size alignment fallback in thp_get_unmapped_area_vmflags(). The existing PMD_SIZE alignment (512M on arm64 64K pages) is too large for typical shared libraries, so this smaller fallback succeeds where PMD fails.
I created a benchmark that mmaps a large executable file and calls RET-stub functions at PAGE_SIZE offsets across it. "Cold" measures fault + readahead cost. "Random" first faults in all pages with a sequential sweep (not measured), then measures time for calling random offsets, isolating iTLB miss cost for scattered execution.
The benchmark results on Neoverse V2 (Grace), arm64 with 64K base pages, 512MB executable file on ext4, averaged over 3 runs:
Phase | Baseline | Patched | Improvement -----------|--------------|--------------|------------------ Cold fault | 83.4 ms | 41.3 ms | 50% faster Random | 76.0 ms | 58.3 ms | 23% faster
[1] https://lore.kernel.org/all/[email protected]/
[2] https://lore.kernel.org/all/[email protected]/
Usama Arif (4):
mm: bypass mmap_miss heuristic for VM_EXEC readahead
mm: replace exec_folio_order() with generic preferred_exec_order()
elf: align ET_DYN base to max folio size for PTE coalescing
mm: align file-backed mmap to max folio order in thp_get_unmapped_area
arch/arm64/include/asm/pgtable.h | 8 ----- fs/binfmt_elf.c | 38 ++++++++++++++++++-- include/linux/pgtable.h | 11 ------ mm/filemap.c | 59 ++++++++++++++++++++++++++++---- mm/huge_memory.c | 14 ++++++++ 5 files changed, 102 insertions(+), 28 deletions(-)
Signature · 1 line
2.52.0
Usama Arif
reviewerPATCH v2 1/4 mm: bypass mmap_miss heuristic for VM_EXEC readahead
The mmap_miss counter in do_sync_mmap_readahead() tracks whether readahead is useful for mmap'd file access. It is incremented by 1 on every page cache miss in do_sync_mmap_readahead(), and decremented in two places:
- filemap_map_pages(): decremented by N for each of N pages successfully mapped via fault-around (pages found already in cache, evidence readahead was useful). Only pages not in the workingset count as hits.
- do_async_mmap_readahead(): decremented by 1 when a page with PG_readahead is found in cache.
When the counter exceeds MMAP_LOTSAMISS (100), all readahead is disabled, including the targeted VM_EXEC readahead [1] that requests large folio orders for contpte mapping.
On arm64 with 64K base pages, both decrement paths are inactive:
1. filemap_map_pages() is never called because fault_around_pages (65536 >> PAGE_SHIFT = 1) disables should_fault_around(), which requires fault_around_pages > 1. With only 1 page in the fault-around window, there is nothing "around" to map.
2. do_async_mmap_readahead() never fires for exec mappings because exec readahead sets async_size = 0, so no PG_readahead markers are placed.
With no decrements, mmap_miss monotonically increases past MMAP_LOTSAMISS after 100 page faults, disabling all subsequent exec readahead.
Fix this by excluding VM_EXEC VMAs from the mmap_miss logic, similar to how VM_SEQ_READ is already excluded. The exec readahead path is targeted (one folio at the fault location, async_size=0), not speculative prefetch, so the mmap_miss heuristic designed to throttle wasteful speculative readahead should not apply to it.
[1] https://lore.kernel.org/all/[email protected]/
--- mm/filemap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/filemap.c +1 -1
@@ -3331,7 +3331,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) } } -if (!(vm_flags &VM_SEQ_READ )) { +if (!(vm_flags & (VM_SEQ_READ |VM_EXEC ))) {/* Avoid banging the cache line if not needed */ mmap_miss =READ_ONCE (ra->mmap_miss);if (mmap_miss <MMAP_LOTSAMISS *10 )
Signature · 1 line
2.52.0
Re: [PATCH v2 1/4] mm: bypass mmap_miss heuristic for VM_EXEC readahead
Quoted 38 lines · Usama Arif
The
mmap_misscounter indo_sync_mmap_readahead()tracks whether readahead is useful for mmap'd file access. It is incremented by 1 on every page cache miss indo_sync_mmap_readahead(), and decremented in two places:-
filemap_map_pages(): decremented by N for each of N pages successfully mapped via fault-around (pages found already in cache, evidence readahead was useful). Only pages not in the workingset count as hits.-
do_async_mmap_readahead(): decremented by 1 when a page withPG_readaheadis found in cache.When the counter exceeds
MMAP_LOTSAMISS(100), all readahead is disabled, including the targetedVM_EXECreadahead [1] that requests large folio orders for contpte mapping.On arm64 with 64K base pages, both decrement paths are inactive:
1.
filemap_map_pages()is never called becausefault_around_pages(65536 >>PAGE_SHIFT= 1) disablesshould_fault_around(), which requiresfault_around_pages> 1. With only 1 page in the fault-around window, there is nothing "around" to map.2.
do_async_mmap_readahead()never fires for exec mappings because exec readahead setsasync_size= 0, so noPG_readaheadmarkers are placed.With no decrements,
mmap_missmonotonically increases pastMMAP_LOTSAMISSafter 100 page faults, disabling all subsequent exec readahead.Fix this by excluding
VM_EXECVMAs from themmap_misslogic, similar to howVM_SEQ_READis already excluded. The exec readahead path is targeted (one folio at the fault location, async_size=0), not speculative prefetch, so themmap_missheuristic designed to throttle wasteful speculative readahead should not apply to it.
Quoted 3 lines
[1] https://lore.kernel.org/all/[email protected]/
Signed-off-by Usama Arif <[email protected]>
Looks good to me. Feel free to add:
Honza
Quoted 20 lines
--- mm/filemap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/filemap.c +1
-1@@ -3331,7 +3331,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) } } -if (!(vm_flags &VM_SEQ_READ )) { +if (!(vm_flags & (VM_SEQ_READ |VM_EXEC ))) {/* Avoid banging the cache line if not needed */ mmap_miss =READ_ONCE (ra->mmap_miss);if (mmap_miss <MMAP_LOTSAMISS *10 )Signature · 1 line
2.52.0
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Re: [PATCH v2 1/4] mm: bypass mmap_miss heuristic for VM_EXEC readahead
In reply to Usama Arifmm/filemap.c static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) · line 3334
Quoted 10 lines · Usama Arif
mm/filemap.c +1
-1@@ -3331,7 +3331,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) } } -if (!(vm_flags &VM_SEQ_READ )) { +if (!(vm_flags & (VM_SEQ_READ |VM_EXEC ))) {
Strictly speaking the fact that the file mapped as executable doesn't mean we are serving instruction fetch page fault.
FAULT_FLAG_INSTRUCTION would be the signal, but it is only provided by handful of architectures.
VM_EXEC is good enough proxy.
Signature · 1 line
Kiryl Shutsemau / Kirill A. Shutemov
Usama Arif
reviewerPATCH v2 2/4 mm: replace exec_folio_order() with generic preferred_exec_order()
In reply to Usama ArifReplace the arch-specific exec_folio_order() hook with a generic preferred_exec_order() that dynamically computes the readahead folio order for executable memory. It targets min(PMD_ORDER, 2M) as the maximum, which optimally gives the right answer for contpte (arm64), PMD mapping (x86, arm64 4K), and architectures with smaller PMDs (s390 1M). It adapts at runtime based on:
- VMA size: caps the order so folios fit within the mapping
- Memory pressure: steps down the order when the local node's free memory is below the high watermark for the requested order
This avoids over-allocating on memory-constrained systems while still requesting the optimal order when memory is plentiful.
Since exec_folio_order() is no longer needed, remove the arm64 definition and the generic default from pgtable.h.
--- arch/arm64/include/asm/pgtable.h | 8 ----- include/linux/pgtable.h | 11 ------ mm/filemap.c | 57 ++++++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 25 deletions(-)
arch/arm64/include/asm/pgtable.h +0 -8
@@ -1599,14 +1599,6 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,*/ #define arch_wants_old_prefaulted_pte cpu_has_hw_af -/* -* Request exec memory is read into pagecache in at least 64K folios. This size -* can be contpte-mapped when 4K base pages are in use (16 pages into 1 iTLB -* entry), and HPA can coalesce it (4 pages into 1 TLB entry) when 16K base -* pages are in use. -*/ -#define exec_folio_order () ilog2(SZ_64K >> PAGE_SHIFT) -static inline bool pud_sect_supported (void ) {return PAGE_SIZE ==SZ_4K ;
include/linux/pgtable.h +0 -11
@@ -577,17 +577,6 @@ static inline bool arch_has_hw_pte_young(void) }#endif -#ifndef exec_folio_order -/* -* Returns preferred minimum folio order for executable file-backed memory. Must -* be in range [0, PMD_ORDER). Default to order-0. -*/ -static inline unsigned int exec_folio_order (void ) -{ -return 0 ; -} -#endif -#ifndef arch_check_zapped_ptestatic inline void arch_check_zapped_pte (struct vm_area_struct *vma,pte_t pte)
mm/filemap.c +51 -6
75 lines not on this page · raw message
Signature · 1 line
2.52.0
Kiryl Shutsemau
reviewerRe: [PATCH v2 2/4] mm: replace exec_folio_order() with generic preferred_exec_order()
Quoted 18 lines · Usama Arif
+ * allocations when memory is tight.
+ */mm/filemap.c +16
-0+static unsigned int preferred_exec_order (struct vm_area_struct *vma) +{ +int order; +unsigned long vma_len =vma_pages (vma); +struct zone *zone; +gfp_t gfp; + +if (!IS_ENABLED (CONFIG_TRANSPARENT_HUGEPAGE )) +return 0 ; + +/* Cap at min(PMD_ORDER, 2M) */ + order =min (HPAGE_PMD_ORDER ,ilog2 (SZ_2M >>PAGE_SHIFT )); + +/* Don't request folios larger than the VMA */ + order =min (order,ilog2 (vma_len)); +
mm/filemap.c static int lock_folio_maybe_drop_mmap(struct vm_fault *vmf, struct folio *folio, · line 3334
Quoted 10 lines
mm/filemap.c +10
-0+/* Step down under memory pressure */ + gfp =mapping_gfp_mask (vma->vm_file->f_mapping); + zone =first_zones_zonelist (node_zonelist (numa_node_id (), gfp), +gfp_zone (gfp),NULL )->zone; +if (zone) { +while (order >0 && + !zone_watermark_ok (zone, order, +high_wmark_pages (zone),0 ,0 )) + order--; + }
Eww. That's overkill and layering violation.
If we need something like this, it has to be do within page allocator:
an allocation interface that takes a range (or mask) of acceptable order.
Signature · 1 line
Kiryl Shutsemau / Kirill A. Shutemov
Jan Kara
maintainerRe: [PATCH v2 2/4] mm: replace exec_folio_order() with generic preferred_exec_order()
In reply to Usama ArifQuoted 18 lines · Usama Arif
Replace the arch-specific
exec_folio_order()hook with a genericpreferred_exec_order()that dynamically computes the readahead folio order for executable memory. It targetsmin(PMD_ORDER, 2M)as the maximum, which optimally gives the right answer for contpte (arm64), PMD mapping (x86, arm64 4K), and architectures with smaller PMDs (s390 1M). It adapts at runtime based on:- VMA size: caps the order so folios fit within the mapping
- Memory pressure: steps down the order when the local node's free memory is below the high watermark for the requested orderThis avoids over-allocating on memory-constrained systems while still requesting the optimal order when memory is plentiful.
Since
exec_folio_order()is no longer needed, remove the arm64 definition and the generic default frompgtable.h.Signed-off-by Usama Arif <[email protected]>
...
Quoted 5 lines
mm/filemap.c +5
-0+static unsigned int preferred_exec_order (struct vm_area_struct *vma) +{ +int order; +unsigned long vma_len =vma_pages (vma); +struct zone *zone;
mm/filemap.c static int lock_folio_maybe_drop_mmap(struct vm_fault *vmf, struct folio *folio, · line 3323
Quoted 10 lines
mm/filemap.c +10
-0+gfp_t gfp; + +if (!IS_ENABLED (CONFIG_TRANSPARENT_HUGEPAGE )) +return 0 ; + +/* Cap at min(PMD_ORDER, 2M) */ + order =min (HPAGE_PMD_ORDER ,ilog2 (SZ_2M >>PAGE_SHIFT )); + +/* Don't request folios larger than the VMA */ + order =min (order,ilog2 (vma_len));
Hum, as far as I'm checking page_cache_ra_order() used in do_sync_mmap_readahead(), ra->order is the preferred order but it will be trimmed down to fit both within the file and within ra->size. And ra->size is set for the readahead to fit within the vma so I don't think any order trimming based on vma length is needed in this place?
mm/filemap.c static int lock_folio_maybe_drop_mmap(struct vm_fault *vmf, struct folio *folio, · line 3334
Quoted 10 lines
mm/filemap.c +10
-0+/* Step down under memory pressure */ + gfp =mapping_gfp_mask (vma->vm_file->f_mapping); + zone =first_zones_zonelist (node_zonelist (numa_node_id (), gfp), +gfp_zone (gfp),NULL )->zone; +if (zone) { +while (order >0 && + !zone_watermark_ok (zone, order, +high_wmark_pages (zone),0 ,0 )) + order--; + }
It looks wrong for this logic to be here. Trimming order based on memory pressure makes sense (and we've already got reports that on memory limited devices large order folios in the page cache have too big memory overhead so we'll likely need to handle that for page cache allocations in general) but IMHO it belongs to page_cache_ra_order() or some other common place like that.
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Usama Arif
reviewerRe: [PATCH v2 2/4] mm: replace exec_folio_order() with generic preferred_exec_order()
Quoted 20 lines · Jan Kara
Quoted 18 lines · Usama Arif
Replace the arch-specific
exec_folio_order()hook with a genericpreferred_exec_order()that dynamically computes the readahead folio order for executable memory. It targetsmin(PMD_ORDER, 2M)as the maximum, which optimally gives the right answer for contpte (arm64), PMD mapping (x86, arm64 4K), and architectures with smaller PMDs (s390 1M). It adapts at runtime based on:- VMA size: caps the order so folios fit within the mapping
- Memory pressure: steps down the order when the local node's free memory is below the high watermark for the requested orderThis avoids over-allocating on memory-constrained systems while still requesting the optimal order when memory is plentiful.
Since
exec_folio_order()is no longer needed, remove the arm64 definition and the generic default frompgtable.h.Signed-off-by Usama Arif <[email protected]>...
Quoted 16 lines
Quoted 5 lines
mm/filemap.c +5
-0+static unsigned int preferred_exec_order (struct vm_area_struct *vma) +{ +int order; +unsigned long vma_len =vma_pages (vma); +struct zone *zone;mm/filemap.c static int lock_folio_maybe_drop_mmap(struct vm_fault *vmf, struct folio *folio, · line 3323
Quoted 10 lines
mm/filemap.c +10
-0+gfp_t gfp; + +if (!IS_ENABLED (CONFIG_TRANSPARENT_HUGEPAGE )) +return 0 ; + +/* Cap at min(PMD_ORDER, 2M) */ + order =min (HPAGE_PMD_ORDER ,ilog2 (SZ_2M >>PAGE_SHIFT )); + +/* Don't request folios larger than the VMA */ + order =min (order,ilog2 (vma_len));
Hi Jan,
Thanks for the feedback and sorry for the late reply! I was travelling during the week.
Quoted 5 lines
Hum, as far as I'm checking
page_cache_ra_order()used indo_sync_mmap_readahead(),ra->orderis the preferred order but it will be trimmed down to fit both within the file and withinra->size. Andra->sizeis set for the readahead to fit within the vma so I don't think any order trimming based on vma length is needed in this place?
Ack, yes makes sense.
Quoted 19 lines
mm/filemap.c static int lock_folio_maybe_drop_mmap(struct vm_fault *vmf, struct folio *folio, · line 3334
Quoted 11 lines
mm/filemap.c +10
-0+/* Step down under memory pressure */ + gfp =mapping_gfp_mask (vma->vm_file->f_mapping); + zone =first_zones_zonelist (node_zonelist (numa_node_id (), gfp), +gfp_zone (gfp),NULL )->zone; +if (zone) { +while (order >0 && + !zone_watermark_ok (zone, order, +high_wmark_pages (zone),0 ,0 )) + order--; + }It looks wrong for this logic to be here. Trimming order based on memory pressure makes sense (and we've already got reports that on memory limited devices large order folios in the page cache have too big memory overhead so we'll likely need to handle that for page cache allocations in general) but IMHO it belongs to
page_cache_ra_order()or some other common place like that.
Quoted 1 line
Honza
So I have been thinking about this. readahead_gfp_mask() already sets __GFP_NORETRY, so we wont try aggressive reclaim/compaction to satisfy the allocation. page_cache_ra_order() falls through to the fallback path faulting in order 0 page when allocation is not satsified.
So the allocator already naturally steps down under memory pressure, the explicit zone_watermark_ok() loop might be redundant?
What are your thoughts on just settingra->order = min(HPAGE_PMD_ORDER, ilog2(SZ_2M >> PAGE_SHIFT))? We can do the higher orlder allocation with gfp &= ~__GFP_RECLAIM for the VM_EXEC case.
Jan Kara
maintainerRe: [PATCH v2 2/4] mm: replace exec_folio_order() with generic preferred_exec_order()
Quoted 21 lines · Usama Arif
Quoted 18 lines · Jan Kara
mm/filemap.c static int lock_folio_maybe_drop_mmap(struct vm_fault *vmf, struct folio *folio, · line 3334
Quoted 10 lines
mm/filemap.c +10
-0+/* Step down under memory pressure */ + gfp =mapping_gfp_mask (vma->vm_file->f_mapping); + zone =first_zones_zonelist (node_zonelist (numa_node_id (), gfp), +gfp_zone (gfp),NULL )->zone; +if (zone) { +while (order >0 && + !zone_watermark_ok (zone, order, +high_wmark_pages (zone),0 ,0 )) + order--; + }It looks wrong for this logic to be here. Trimming order based on memory pressure makes sense (and we've already got reports that on memory limited devices large order folios in the page cache have too big memory overhead so we'll likely need to handle that for page cache allocations in general) but IMHO it belongs to
page_cache_ra_order()or some other common place like that.Quoted 1 line
Honza
Quoted 7 lines
So I have been thinking about this.
readahead_gfp_mask()already sets__GFP_NORETRY, so we wont try aggressive reclaim/compaction to satisfy the allocation.page_cache_ra_order()falls through to the fallback path faulting in order 0 page when allocation is not satsified.So the allocator already naturally steps down under memory pressure, the explicit
zone_watermark_ok()loop might be redundant?
Probably yes. I still think we'll have to somehow better tweak the used order based on expected size of the page cache (2M folios seem unreasonably large for a machine that has e.g. 1G of memory in total, even if it has enough free memory at this point in time - we'll benefit from smaller folios and thus finer grained folio activity tracking for such cases). But that's not for this patch set.
Quoted 4 lines
What are your thoughts on just setting
ra->order=min(HPAGE_PMD_ORDER, ilog2(SZ_2M >> PAGE_SHIFT))? We can do the higher orlder allocation with gfp &= ~__GFP_RECLAIM for theVM_EXECcase.
Yes, it's simple and it makes sense to me so if others are fine with it...
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Usama Arif
reviewerPATCH v2 3/4 elf: align ET_DYN base to max folio size for PTE coalescing
In reply to Usama ArifFor PIE binaries (ET_DYN), the load address is randomized at PAGE_SIZE granularity via arch_mmap_rnd(). On arm64 with 64K base pages, this means the binary is 64K-aligned, but contpte mapping requires 2M (CONT_PTE_SIZE) alignment.
Without proper virtual address alignment, readahead patches that allocate 2M folios with 2M-aligned file offsets and physical addresses cannot benefit from contpte mapping, as the contpte fold check in contpte_set_ptes() requires the virtual address to be CONT_PTE_SIZE- aligned.
Fix this by extending maximum_alignment() to consider the maximum folio size supported by the page cache (via mapping_max_folio_size()). For each PT_LOAD segment, the alignment is bumped to the largest power-of-2 that fits within the segment size, capped by the max folio size the filesystem will allocate, if:
- Both p_vaddr and p_offset are aligned to that size
- The segment is large enough (p_filesz >= size)
This ensures load_bias is folio-aligned so that file-offset-aligned folios map to properly aligned virtual addresses, enabling hardware PTE coalescing (e.g. arm64 contpte) and PMD mappings for large folios.
The segment size check avoids reducing ASLR entropy for small binaries that cannot benefit from large folio alignment.
--- fs/binfmt_elf.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-)
fs/binfmt_elf.c +36 -2
@@ -49,6 +49,7 @@#include <uapi/linux/rseq.h> #include <asm/param.h> #include <asm/page.h> +#include <linux/pagemap.h> #ifndef ELF_COMPAT #define ELF_COMPAT 0
@@ -488,19 +489,51 @@ static int elf_read(struct file *file, void *buf, size_t len, loff_t pos)return 0 ; } -static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr) +static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr, +struct file *filp) {unsigned long alignment =0 ; +unsigned long max_folio_size =PAGE_SIZE ;int i; +if (filp && filp->f_mapping) + max_folio_size =mapping_max_folio_size (filp->f_mapping); +for (i =0 ; i < nr; i++) {if (cmds[i].p_type ==PT_LOAD ) {unsigned long p_align = cmds[i].p_align; +unsigned long size;/* skip non-power of two alignments as invalid */ if (!is_power_of_2 (p_align))continue ; alignment =max (alignment, p_align); + +/* +* Try to align the binary to the largest folio +* size that the page cache supports, so the +* hardware can coalesce PTEs (e.g. arm64 +* contpte) or use PMD mappings for large folios. +* +* Use the largest power-of-2 that fits within +* the segment size, capped by what the page +* cache will allocate. Only align when the +* segment's virtual address and file offset are +* already aligned to the folio size, as +* misalignment would prevent coalescing anyway. +* +* The segment size check avoids reducing ASLR +* entropy for small binaries that cannot +* benefit. +*/ +if (!cmds[i].p_filesz) +continue ; + size =rounddown_pow_of_two (cmds[i].p_filesz); + size =min (size, max_folio_size); +if (size >PAGE_SIZE && +IS_ALIGNED (cmds[i].p_vaddr, size) && +IS_ALIGNED (cmds[i].p_offset, size)) + alignment =max (alignment, size); } }
@@ -1104,7 +1137,8 @@ static int load_elf_binary(struct linux_binprm *bprm) }/* Calculate any requested alignment. */ - alignment =maximum_alignment (elf_phdata, elf_ex->e_phnum); + alignment =maximum_alignment (elf_phdata, elf_ex->e_phnum, + bprm->file);/** * DOC: PIE handling
Signature · 1 line
2.52.0
Re: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
Quoted 20 lines · Usama Arif
For PIE binaries (
ET_DYN), the load address is randomized atPAGE_SIZEgranularity viaarch_mmap_rnd(). On arm64 with 64K base pages, this means the binary is 64K-aligned, but contpte mapping requires 2M (CONT_PTE_SIZE) alignment.Without proper virtual address alignment, readahead patches that allocate 2M folios with 2M-aligned file offsets and physical addresses cannot benefit from contpte mapping, as the contpte fold check in
contpte_set_ptes()requires the virtual address to be CONT_PTE_SIZE- aligned.Fix this by extending
maximum_alignment()to consider the maximum folio size supported by the page cache (viamapping_max_folio_size()). For eachPT_LOADsegment, the alignment is bumped to the largest power-of-2 that fits within the segment size, capped by the max folio size the filesystem will allocate, if:- Both
p_vaddrandp_offsetare aligned to that size
- The segment is large enough (p_filesz>= size)
Quoted 8 lines
This ensures
load_biasis folio-aligned so that file-offset-aligned folios map to properly aligned virtual addresses, enabling hardware PTE coalescing (e.g. arm64 contpte) and PMD mappings for large folios.The segment size check avoids reducing ASLR entropy for small binaries that cannot benefit from large folio alignment.
Signed-off-by Usama Arif <[email protected]>
Signature · 1 line
Kiryl Shutsemau / Kirill A. Shutemov
Matthew Wilcox
maintainerRe: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
In reply to Usama Ariffs/binfmt_elf.c static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) · line 500
Quoted 10 lines · Usama Arif
fs/binfmt_elf.c +5
-1-static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr) +static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr, +struct file *filp) {unsigned long alignment =0 ; +unsigned long max_folio_size =PAGE_SIZE ;int i; +if (filp && filp->f_mapping) + max_folio_size =mapping_max_folio_size (filp->f_mapping);
Under what circumstances can bprm->file be NULL?
Also we tend to prefer the name "file" rather than "filp" for new code (yes, there's a lot of old code out there).
Quoted 16 lines
fs/binfmt_elf.c +16
-0+ +/* +* Try to align the binary to the largest folio +* size that the page cache supports, so the +* hardware can coalesce PTEs (e.g. arm64 +* contpte) or use PMD mappings for large folios. +* +* Use the largest power-of-2 that fits within +* the segment size, capped by what the page +* cache will allocate. Only align when the +* segment's virtual address and file offset are +* already aligned to the folio size, as +* misalignment would prevent coalescing anyway. +* +* The segment size check avoids reducing ASLR +* entropy for small binaries that cannot
fs/binfmt_elf.c static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) · line 536
Quoted 10 lines
fs/binfmt_elf.c +10
-0+* benefit. +*/ +if (!cmds[i].p_filesz) +continue ; + size =rounddown_pow_of_two (cmds[i].p_filesz); + size =min (size, max_folio_size); +if (size >PAGE_SIZE && +IS_ALIGNED (cmds[i].p_vaddr, size) && +IS_ALIGNED (cmds[i].p_offset, size)) + alignment =max (alignment, size);
Can this not all be factored out into a different function? Also, I think it was done a bit better here:
https://lore.kernel.org/linux-fsdevel/[email protected]/
+ if (!IS_ALIGNED(cmd->p_vaddr | cmd->p_offset, PMD_SIZE))
+ return false;
Usama Arif
reviewerRe: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
Quoted 9 lines · Matthew Wilcox
Quoted 8 lines · Usama Arif
fs/binfmt_elf.c +3
-1-static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr) +static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr, +struct file *filp) {unsigned long alignment =0 ; +unsigned long max_folio_size =PAGE_SIZE ;int i;
Quoted 4 lines
fs/binfmt_elf.c static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) · line 500
Quoted 2 lines
fs/binfmt_elf.c +2
-0+if (filp && filp->f_mapping) + max_folio_size =mapping_max_folio_size (filp->f_mapping);Under what circumstances can
bprm->filebe NULL?
Yeah its unnecessary here. Its used in other places and this is never checked, so we can remove it.
Quoted 4 lines
Also we tend to prefer the name "file" rather than "filp" for new code (yes, there's a lot of old code out there).
ack. will change in next revision.
Quoted 32 lines
Quoted 16 lines
fs/binfmt_elf.c +16
-0+ +/* +* Try to align the binary to the largest folio +* size that the page cache supports, so the +* hardware can coalesce PTEs (e.g. arm64 +* contpte) or use PMD mappings for large folios. +* +* Use the largest power-of-2 that fits within +* the segment size, capped by what the page +* cache will allocate. Only align when the +* segment's virtual address and file offset are +* already aligned to the folio size, as +* misalignment would prevent coalescing anyway. +* +* The segment size check avoids reducing ASLR +* entropy for small binaries that cannot fs/binfmt_elf.c static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) · line 536
Quoted 10 lines
fs/binfmt_elf.c +10
-0+* benefit. +*/ +if (!cmds[i].p_filesz) +continue ; + size =rounddown_pow_of_two (cmds[i].p_filesz); + size =min (size, max_folio_size); +if (size >PAGE_SIZE && +IS_ALIGNED (cmds[i].p_vaddr, size) && +IS_ALIGNED (cmds[i].p_offset, size)) + alignment =max (alignment, size);Can this not all be factored out into a different function? Also, I think it was done a bit better here:
https://lore.kernel.org/linux-fsdevel/[email protected]/
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (!IS_ALIGNED(cmd->p_vaddr | cmd->p_offset, PMD_SIZE)) + return false;
ack, will try and address this accordingly.
Thanks for the reviews!!
Re: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
In reply to Usama ArifHi Usama,
Quoted 16 lines · Usama Arif
fs/binfmt_elf.c +1
-0@@ -49,6 +49,7 @@#include <uapi/linux/rseq.h> #include <asm/param.h> #include <asm/page.h> +#include <linux/pagemap.h> #ifndef ELF_COMPAT #define ELF_COMPAT 0@@ -488,19 +489,51 @@ static int elf_read(struct file *file, void *buf, size_t len, loff_t pos)return 0 ; }
fs/binfmt_elf.c static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) · line 500
Quoted 10 lines
fs/binfmt_elf.c +5
-1-static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr) +static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr, +struct file *filp) {unsigned long alignment =0 ; +unsigned long max_folio_size =PAGE_SIZE ;int i; +if (filp && filp->f_mapping) + max_folio_size =mapping_max_folio_size (filp->f_mapping);
From experiments (with 16K base pages), mapping_max_folio_size() appears to depend on the filesystem. It returns 8M on ext4, while on btrfs it always falls back to PAGE_SIZE (it seems CONFIG_BTRFS_EXPERIMENTAL=y may change this). This looks overly conservative and ends up missing practical optimization opportunities.
Quoted 26 lines
fs/binfmt_elf.c +18
-0+for (i =0 ; i < nr; i++) {if (cmds[i].p_type ==PT_LOAD ) {unsigned long p_align = cmds[i].p_align; +unsigned long size;/* skip non-power of two alignments as invalid */ if (!is_power_of_2 (p_align))continue ; alignment =max (alignment, p_align); + +/* +* Try to align the binary to the largest folio +* size that the page cache supports, so the +* hardware can coalesce PTEs (e.g. arm64 +* contpte) or use PMD mappings for large folios. +* +* Use the largest power-of-2 that fits within +* the segment size, capped by what the page +* cache will allocate. Only align when the +* segment's virtual address and file offset are +* already aligned to the folio size, as +* misalignment would prevent coalescing anyway. +* +* The segment size check avoids reducing ASLR +* entropy for small binaries that cannot
fs/binfmt_elf.c static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) · line 536
Quoted 10 lines
fs/binfmt_elf.c +10
-0+* benefit. +*/ +if (!cmds[i].p_filesz) +continue ; + size =rounddown_pow_of_two (cmds[i].p_filesz); + size =min (size, max_folio_size); +if (size >PAGE_SIZE && +IS_ALIGNED (cmds[i].p_vaddr, size) && +IS_ALIGNED (cmds[i].p_offset, size)) + alignment =max (alignment, size);
In my patch [1], by aligning eligible segments to PMD_SIZE, THP can quickly collapse them into large mappings with minimal warmup. That doesn’t happen with the current behavior. I think allowing a reasonably sized PMD (say <= 32M) is worth considering. All we really need here is to ensure virtual address alignment. The rest can be left to THP under always, which can decide whether to collapse or not based on memory pressure and other factors.
Quoted 14 lines
fs/binfmt_elf.c +2
-2} }@@ -1104,7 +1137,8 @@ static int load_elf_binary(struct linux_binprm *bprm) }/* Calculate any requested alignment. */ - alignment =maximum_alignment (elf_phdata, elf_ex->e_phnum); + alignment =maximum_alignment (elf_phdata, elf_ex->e_phnum, + bprm->file);/** * DOC: PIE handling --
Quoted 2 lines
2.52.0
Thanks,
Rui
Matthew Wilcox
maintainerRe: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
Quoted 5 lines · WANG Rui
Quoted 1 line
From experiments (with 16K base pages),
mapping_max_folio_size()appears todepend on the filesystem. It returns 8M on ext4, while on btrfs it always falls back to
PAGE_SIZE(it seemsCONFIG_BTRFS_EXPERIMENTAL=ymay change this). This looks overly conservative and ends up missing practical optimization opportunities.
btrfs only supports large folios with CONFIG_BTRFS_EXPERIMENTAL. I mean, it's only been five years since it was added to XFS, can't rush these things.
Usama Arif
reviewerRe: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
In reply to WANG RuiQuoted 27 lines · WANG Rui
Hi Usama,
Quoted 24 lines · Usama Arif
fs/binfmt_elf.c +4
-1@@ -49,6 +49,7 @@#include <uapi/linux/rseq.h> #include <asm/param.h> #include <asm/page.h> +#include <linux/pagemap.h> #ifndef ELF_COMPAT #define ELF_COMPAT 0@@ -488,19 +489,51 @@ static int elf_read(struct file *file, void *buf, size_t len, loff_t pos)return 0 ; } -static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr) +static unsigned long maximum_alignment (struct elf_phdr *cmds,int nr, +struct file *filp) {unsigned long alignment =0 ; +unsigned long max_folio_size =PAGE_SIZE ;int i;
Quoted 8 lines
fs/binfmt_elf.c static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) · line 500
Quoted 2 lines
fs/binfmt_elf.c +2
-0+if (filp && filp->f_mapping) + max_folio_size =mapping_max_folio_size (filp->f_mapping);From experiments (with 16K base pages),
mapping_max_folio_size()appears to depend on the filesystem. It returns 8M on ext4, while on btrfs it always falls back toPAGE_SIZE(it seemsCONFIG_BTRFS_EXPERIMENTAL=ymay change this). This looks overly conservative and ends up missing practical optimization opportunities.
mapping_max_folio_size() reflects what the page cache will actually allocate for a given filesystem, since readahead caps folio allocation at mapping_max_folio_order() (in page_cache_ra_order()). If btrfs reports PAGE_SIZE, readahead won't allocate large folios for it, so there are no large folios to coalesce PTEs for, aligning the binary beyond that would only reduce ASLR entropy for no benefit.
I don't think we should over-align binaries on filesystems that can't take advantage of it.
Quoted 66 lines
Quoted 27 lines
fs/binfmt_elf.c +18
-0+for (i =0 ; i < nr; i++) {if (cmds[i].p_type ==PT_LOAD ) {unsigned long p_align = cmds[i].p_align; +unsigned long size;/* skip non-power of two alignments as invalid */ if (!is_power_of_2 (p_align))continue ; alignment =max (alignment, p_align); + +/* +* Try to align the binary to the largest folio +* size that the page cache supports, so the +* hardware can coalesce PTEs (e.g. arm64 +* contpte) or use PMD mappings for large folios. +* +* Use the largest power-of-2 that fits within +* the segment size, capped by what the page +* cache will allocate. Only align when the +* segment's virtual address and file offset are +* already aligned to the folio size, as +* misalignment would prevent coalescing anyway. +* +* The segment size check avoids reducing ASLR +* entropy for small binaries that cannot fs/binfmt_elf.c static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) · line 536
Quoted 10 lines
fs/binfmt_elf.c +10
-0+* benefit. +*/ +if (!cmds[i].p_filesz) +continue ; + size =rounddown_pow_of_two (cmds[i].p_filesz); + size =min (size, max_folio_size); +if (size >PAGE_SIZE && +IS_ALIGNED (cmds[i].p_vaddr, size) && +IS_ALIGNED (cmds[i].p_offset, size)) + alignment =max (alignment, size);In my patch [1], by aligning eligible segments to
PMD_SIZE, THP can quickly collapse them into large mappings with minimal warmup. That doesn’t happen with the current behavior. I think allowing a reasonably sized PMD (say <= 32M) is worth considering. All we really need here is to ensure virtual address alignment. The rest can be left to THP under always, which can decide whether to collapse or not based on memory pressure and other factors.Quoted 14 lines
fs/binfmt_elf.c +2
-2} }@@ -1104,7 +1137,8 @@ static int load_elf_binary(struct linux_binprm *bprm) }/* Calculate any requested alignment. */ - alignment =maximum_alignment (elf_phdata, elf_ex->e_phnum); + alignment =maximum_alignment (elf_phdata, elf_ex->e_phnum, + bprm->file);/** * DOC: PIE handling -- Quoted 2 lines
2.52.0
Thanks,
Rui
Re: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
Quoted 9 lines
mapping_max_folio_size()reflects what the page cache will actually allocate for a given filesystem, since readahead caps folio allocation atmapping_max_folio_order()(inpage_cache_ra_order()). If btrfs reportsPAGE_SIZE, readahead won't allocate large folios for it, so there are no large folios to coalesce PTEs for, aligning the binary beyond that would only reduce ASLR entropy for no benefit.I don't think we should over-align binaries on filesystems that can't take advantage of it.
Ah, it looks like this might be overlooking another path that can create huge page mappings for read-only code segments: even when the filesystem (e.g. btrfs without experimental) didn't support large folios, READ_ONLY_THP_FOR_FS still allowed read-only file-backed code segments to be collapsed into huge page mappings via khugepaged.
As Wilcox pointed out, it may take quite some time for many filesystems to gain full large folio support? So what I'm trying to clarify is that using mapping_max_folio_size() on this path is not favorable for khugepaged-based optimizations.
Thanks,
Rui
Matthew Wilcox
maintainerRe: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
Quoted 16 lines · WANG Rui
Quoted 9 lines
mapping_max_folio_size()reflects what the page cache will actually allocate for a given filesystem, since readahead caps folio allocation atmapping_max_folio_order()(inpage_cache_ra_order()). If btrfs reportsPAGE_SIZE, readahead won't allocate large folios for it, so there are no large folios to coalesce PTEs for, aligning the binary beyond that would only reduce ASLR entropy for no benefit.I don't think we should over-align binaries on filesystems that can't take advantage of it.
Ah, it looks like this might be overlooking another path that can create huge page mappings for read-only code segments: even when the filesystem (e.g. btrfs without experimental) didn't support large folios,
READ_ONLY_THP_FOR_FSstill allowed read-only file-backed code segments to be collapsed into huge page mappings via khugepaged.
Quoted 4 lines
As Wilcox pointed out, it may take quite some time for many filesystems to gain full large folio support? So what I'm trying to clarify is that using
mapping_max_folio_size()on this path is not favorable for khugepaged-based optimizations.
Nono, that's not what I'm pointing out! btrfs is simply not putting in the effort to support large folios, and that needs to change. READ_ONLY_THP_FOR_FS unnecessaily burdens the rest of the kernel. It was a great hack for its time and paved the path for a lot of what we have today, but it's time to remove it.
Usama Arif
reviewerRe: [PATCH v2 3/4] elf: align ET_DYN base to max folio size for PTE coalescing
Quoted 8 lines · Matthew Wilcox
Quoted 7 lines · WANG Rui
Quoted 7 lines
mapping_max_folio_size()reflects what the page cache will actually allocate for a given filesystem, since readahead caps folio allocation atmapping_max_folio_order()(inpage_cache_ra_order()). If btrfs reportsPAGE_SIZE, readahead won't allocate large folios for it, so there are no large folios to coalesce PTEs for, aligning the binary beyond that would only reduce ASLR entropy for no benefit.
Quoted 8 lines
Quoted 8 lines
Quoted 2 lines
I don't think we should over-align binaries on filesystems that can't take advantage of it.
Ah, it looks like this might be overlooking another path that can create huge page mappings for read-only code segments: even when the filesystem (e.g. btrfs without experimental) didn't support large folios,
READ_ONLY_THP_FOR_FSstill allowed read-only file-backed code segments to be collapsed into huge page mappings via khugepaged.
ah yes, Thank you for pointing this out!
Maybe we should rename mapping_max_folio_size() to mapping_fault_max_folio_size().
Quoted 5 lines
Quoted 5 lines
As Wilcox pointed out, it may take quite some time for many filesystems to gain full large folio support? So what I'm trying to clarify is that using
mapping_max_folio_size()on this path is not favorable for khugepaged-based optimizations.
ack
I am worried that 32M is too large and we lose out on a lot of ASLR bits. Instead of PMD_ORDER, should we do max(SZ_2M, PMD_ORDER)?
Quoted 5 lines
Nono, that's not what I'm pointing out! btrfs is simply not putting in the effort to support large folios, and that needs to change.
READ_ONLY_THP_FOR_FSunnecessaily burdens the rest of the kernel. It was a great hack for its time and paved the path for a lot of what we have today, but it's time to remove it.
Usama Arif
reviewerPATCH v2 4/4 mm: align file-backed mmap to max folio order in thp_get_unmapped_area
In reply to Usama Arifthp_get_unmapped_area() is the get_unmapped_area callback for filesystems like ext4, xfs, and btrfs. It attempts to align the virtual address for PMD_SIZE THP mappings, but on arm64 with 64K base pages PMD_SIZE is 512M, which is too large for typical shared library mappings, so the alignment always fails and falls back to PAGE_SIZE.
This means shared libraries loaded by ld.so via mmap() get 64K-aligned virtual addresses, preventing contpte mapping even when 2M folios are allocated with properly aligned file offsets and physical addresses.
Add a fallback in thp_get_unmapped_area_vmflags() that uses the filesystem's mapping_max_folio_size() to determine alignment, capped to the mapping length via rounddown_pow_of_two(len). This aligns mappings to the largest folio the page cache will actually allocate, without over-aligning small mappings.
The fallback is naturally a no-op for filesystems that don't support large folios and skips the retry when the alignment would equal PMD_SIZE (already attempted above).
--- mm/huge_memory.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
mm/huge_memory.c +14 -0
@@ -1242,6 +1242,20 @@ unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long addif (ret)return ret; +if (filp && filp->f_mapping) { +unsigned long max_folio_size = +mapping_max_folio_size (filp->f_mapping); +unsigned long size =rounddown_pow_of_two (len); + + size =min (size, max_folio_size); +if (size >PAGE_SIZE && size !=PMD_SIZE ) { + ret =__thp_get_unmapped_area (filp, addr, len, off, + flags, size, vm_flags); +if (ret) +return ret; + } + } +return mm_get_unmapped_area_vmflags (filp, addr, len, pgoff, flags, vm_flags); }
Signature · 1 line
2.52.0
Kiryl Shutsemau
reviewerRe: [PATCH v2 4/4] mm: align file-backed mmap to max folio order in thp_get_unmapped_area
Quoted 32 lines · Usama Arif
thp_get_unmapped_area()is theget_unmapped_areacallback for filesystems like ext4, xfs, and btrfs. It attempts to align the virtual address forPMD_SIZETHP mappings, but on arm64 with 64K base pagesPMD_SIZEis 512M, which is too large for typical shared library mappings, so the alignment always fails and falls back toPAGE_SIZE.This means shared libraries loaded by ld.so via
mmap()get 64K-aligned virtual addresses, preventing contpte mapping even when 2M folios are allocated with properly aligned file offsets and physical addresses.Add a fallback in
thp_get_unmapped_area_vmflags()that uses the filesystem'smapping_max_folio_size()to determine alignment, capped to the mapping length viarounddown_pow_of_two(len). This aligns mappings to the largest folio the page cache will actually allocate, without over-aligning small mappings.The fallback is naturally a no-op for filesystems that don't support large folios and skips the retry when the alignment would equal
PMD_SIZE(already attempted above).Signed-off-by Usama Arif <[email protected]>--- mm/huge_memory.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)mm/huge_memory.c +0
-0@@ -1242,6 +1242,20 @@ unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long addif (ret)return ret;
mm/huge_memory.c unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long add · line 1253
Quoted 10 lines
mm/huge_memory.c +9
-0+if (filp && filp->f_mapping) { +unsigned long max_folio_size = +mapping_max_folio_size (filp->f_mapping); +unsigned long size =rounddown_pow_of_two (len); + + size =min (size, max_folio_size); +if (size >PAGE_SIZE && size !=PMD_SIZE ) { + ret =__thp_get_unmapped_area (filp, addr, len, off, + flags, size, vm_flags);
Have you considered to integrate inside __thp_get_unmapped_area?
Like, start with PMD_SIZE alignment, then lower to mapping_max_folio_size if needed and then lower further based on mapping size.
Signature · 1 line
Kiryl Shutsemau / Kirill A. Shutemov