Linux Overlay Filesystem development
 help / color / mirror / Atom feed
From: Yuan-Hao Hsu <aa9736195201@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>, Amir Goldstein <amir73il@gmail.com>
Cc: linux-unionfs@vger.kernel.org, linux-kernel@vger.kernel.org,
	Yuan-Hao Hsu <aa9736195201@gmail.com>
Subject: [PATCH] ovl: implement ->get_unmapped_area()
Date: Fri, 28 Aug 2026 01:07:18 +0800	[thread overview]
Message-ID: <20260827170718.497-1-aa9736195201@gmail.com> (raw)

ovl_mmap() passes realfile to the underlying filesystem, so the VMA it
returns is backed by realfile, not by the overlayfs file.

Address selection is not delegated.  __get_unmapped_area() looks at the
overlayfs file's f_op, ovl_file_operations does not implement
->get_unmapped_area(), and the mapping lands wherever
mm_get_unmapped_area() puts it.  ext4, xfs and btrfs all point
->get_unmapped_area() at thp_get_unmapped_area(); none of that is reached.

vaddr - file_offset is then not a multiple of PMD_SIZE,
thp_vma_suitable_order() rejects the VMA, and the PMD-sized folios the
underlying filesystem already has in the page cache are never mapped by
a PMD.

Delegate to the file ovl_mmap() will use.  Calling thp_get_unmapped_area()
here instead would force alignment on filesystems that deliberately do
not implement ->get_unmapped_area(), which commit 34d7cf637c43 ("mm:
don't try THP alignment for FS without get_unmapped_area") avoided.
fs/proc delegates the same way in pde_get_unmapped_area().

Reading a 1025M ext4 file through mmap(NULL, ...), 97% of its page cache
in PMD-sized folios, 15 runs:

                     PMD congruent  minor faults  page tables
  ext4, directly             15/15           764          68K
  overlayfs, before            0/5         16186        2056K
  overlayfs, after           15/15           764          68K

Fault counts had 0 stddev.  Median read time 17.4ms -> 4.80ms, against
4.92ms for the same file on ext4.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Yuan-Hao Hsu <aa9736195201@gmail.com>

---
 fs/overlayfs/file.c |   26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index f3d97eb146e8..0d985025f4c8 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -13,6 +13,7 @@
 #include <linux/security.h>
 #include <linux/fs.h>
 #include <linux/backing-file.h>
+#include <linux/sched/mm.h>
 #include "overlayfs.h"
 
 static char ovl_whatisit(struct inode *inode, struct inode *realinode)
@@ -465,6 +466,30 @@ static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 		return vfs_fsync_range(upperfile, start, end, datasync);
 }
 
+static unsigned long ovl_get_unmapped_area(struct file *file,
+					   unsigned long addr, unsigned long len,
+					   unsigned long pgoff, unsigned long flags)
+{
+	struct ovl_file *of = file->private_data;
+	struct file *realfile = of->realfile;
+
+	/*
+	 * ovl_mmap() hands realfile to the underlying filesystem, so the vma
+	 * ends up backed by realfile.  Let that filesystem pick the address
+	 * too, or one that needs a specific alignment - to allow PMD mappings,
+	 * for example - never gets asked for one.
+	 */
+	if (realfile->f_op->get_unmapped_area)
+		return realfile->f_op->get_unmapped_area(realfile, addr, len,
+							 pgoff, flags);
+
+#ifdef CONFIG_MMU
+	return mm_get_unmapped_area(file, addr, len, pgoff, flags);
+#endif
+
+	return addr;
+}
+
 static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct ovl_file *of = file->private_data;
@@ -654,6 +679,7 @@ const struct file_operations ovl_file_operations = {
 	.write_iter	= ovl_write_iter,
 	.fsync		= ovl_fsync,
 	.mmap		= ovl_mmap,
+	.get_unmapped_area = ovl_get_unmapped_area,
 	.fallocate	= ovl_fallocate,
 	.fadvise	= ovl_fadvise,
 	.flush		= ovl_flush,

base-commit: 26260251022fbc2f248a3d747a9b2b961b18d2d8

             reply	other threads:[~2026-08-27 17:07 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27 17:07 Yuan-Hao Hsu [this message]
2026-08-28 12:23 ` [PATCH] ovl: implement ->get_unmapped_area() Amir Goldstein
2026-08-28 12:41   ` Matthew Wilcox
2026-08-31  8:18     ` Miklos Szeredi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260827170718.497-1-aa9736195201@gmail.com \
    --to=aa9736195201@gmail.com \
    --cc=amir73il@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox