Re: [PATCH v2 1/4] mm: bypass mmap_miss heuristic for VM_EXEC readahead

Jan Kara
2026-03-20T14:18:51Z

On Fri 20-03-26 06:58:51, Usama Arif wrote:
> 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/20250430145920.3748738-6-ryan.roberts@arm.com/
>
> Signed-off-by: Usama Arif <usama.arif@linux.dev>

Looks good to me. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

Honza

> ---
> mm/filemap.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 6cd7974d4adab..7d89c6b384cc4 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -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)
> --
> 2.52.0
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR