Re: [linux-next:master] [mm] 7b32f64bc5: pts.svt-av1.Preset13.Bosphorus4K.frames_per_second 45.8% regression

Bo Zhang <[email protected]> Thu, 23 Jul 2026 10:45:27 +0800
Newsgroups dev.linux.lists.oe-lkp,org.kernel.vger.linux-fsdevel,org.kvack.linux-mm
Message-ID <[email protected]>
From: zhangbo56 <[email protected]>

On Thu 18-06-26 16:00:42, kernel test robot wrote:
> kernel test robot noticed a 45.8% regression of
> pts.svt-av1.Preset13.Bosphorus4K.frames_per_second on:
>
> commit: 7b32f64bc512b40b268776c5ac4d354b325b3197
> ("mm: limit filemap_fault readahead to VMA boundaries")
>
>     169.95 +/- 6%     -45.8%      92.15 +/- 10%  pts.svt-av1.Preset13.Bosphorus4K.frames_per_second
>     220.57 +/- 3%    +870.9%       2141        pts.time.major_page_faults

Hi Oliver,

Could you help test if the below patch fixes the regression?

The 870% increase in major faults suggests that readahead is being cut
short too aggressively. The current approach unconditionally sets
_max_index on every fault, which likely prevents readahead from
prefetching ahead effectively for sequential access patterns.

The fix: only limit readahead when the fault is close to the VMA end --
if there are fewer pages remaining in the VMA than ra_pages, set
_max_index. Otherwise, do nothing.

For a 4MB VMA with ra_pages=32, only faults in the last 32 pages (128KB)
trigger the limit. The other 99.9% of faults see no change at all.

Similarly, only clamp the read-around start when the fault is near the
VMA beginning.

This applies on top of 7b32f64bc512 and can be applied with git am.

Reported-by: kernel test robot <[email protected]>
Signed-off-by: Bo Zhang <[email protected]>
---
 mm/filemap.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 97772a05a18e..9f1e1c9ea6df 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -3313,8 +3313,11 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf)
 	vm_flags_t vm_flags = vmf->vma->vm_flags;
 	bool force_thp_readahead = false;
 	unsigned short mmap_miss;
+	unsigned long vma_end_pgoff = vmf->vma->vm_pgoff + vma_pages(vmf->vma);
+	unsigned long vma_pages_left = vma_end_pgoff - vmf->pgoff;
 
-	ractl._max_index = vmf->vma->vm_pgoff + vma_pages(vmf->vma) - 1;
+	if (vma_pages_left < ra->ra_pages)
+		ractl._max_index = vma_end_pgoff - 1;
 
 	/* Use the readahead code, even if readahead is disabled */
 	if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
@@ -3398,7 +3401,8 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf)
 		 * mmap read-around
 		 */
 		ra->start = max_t(long, 0, vmf->pgoff - ra->ra_pages / 2);
-		ra->start = max(ra->start, vmf->vma->vm_pgoff);
+		if (vmf->pgoff - vmf->vma->vm_pgoff < ra->ra_pages / 2)
+			ra->start = max(ra->start, vmf->vma->vm_pgoff);
 		ra->size = ra->ra_pages;
 		ra->async_size = ra->ra_pages / 4;
 		ra->order = 0;
@@ -3441,7 +3445,12 @@ static struct file *do_async_mmap_readahead(struct vm_fault *vmf,
 	}
 
 	if (folio_test_readahead(folio)) {
-		ractl._max_index = vmf->vma->vm_pgoff + vma_pages(vmf->vma) - 1;
+		unsigned long vma_end_pgoff = vmf->vma->vm_pgoff +
+					     vma_pages(vmf->vma);
+		unsigned long vma_pages_left = vma_end_pgoff - vmf->pgoff;
+
+		if (vma_pages_left < ra->ra_pages)
+			ractl._max_index = vma_end_pgoff - 1;
 		fpin = maybe_unlock_mmap_for_io(vmf, fpin);
 		page_cache_async_ra(&ractl, folio, ra->ra_pages);
 	}
-- 
2.34.1