mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: Andrew Morton <akpm@linux-foundation.org>,
	 David Hildenbrand <david@kernel.org>,
	 "Liam R. Howlett" <liam@infradead.org>,
	Vlastimil Babka <vbabka@kernel.org>,
	 Mike Rapoport <rppt@kernel.org>,
	Suren Baghdasaryan <surenb@google.com>,
	 Michal Hocko <mhocko@suse.com>, Jann Horn <jannh@google.com>,
	 Pedro Falcato <pfalcato@suse.de>,
	 "Matthew Wilcox (Oracle)" <willy@infradead.org>,
	Jan Kara <jack@suse.cz>,  Miaohe Lin <linmiaohe@huawei.com>,
	 Naoya Horiguchi <nao.horiguchi@gmail.com>,
	Rik van Riel <riel@surriel.com>,  Harry Yoo <harry@kernel.org>,
	Lance Yang <lance.yang@linux.dev>,  Kees Cook <kees@kernel.org>,
	Zi Yan <ziy@nvidia.com>,
	 Baolin Wang <baolin.wang@linux.alibaba.com>,
	Nico Pache <npache@redhat.com>,
	 Ryan Roberts <ryan.roberts@arm.com>, Dev Jain <dev.jain@arm.com>,
	 Barry Song <baohua@kernel.org>,
	Usama Arif <usama.arif@linux.dev>,
	 Matthew Brost <matthew.brost@intel.com>,
	 Joshua Hahn <joshua.hahnjy@gmail.com>,
	Rakie Kim <rakie.kim@sk.com>,  Byungchul Park <byungchul@sk.com>,
	Gregory Price <gourry@gourry.net>,
	 Ying Huang <ying.huang@linux.alibaba.com>,
	 Alistair Popple <apopple@nvidia.com>,
	Peter Xu <peterx@redhat.com>,  Xu Xin <xu.xin16@zte.com.cn>,
	Chengming Zhou <chengming.zhou@linux.dev>,
	 Arnd Bergmann <arnd@arndb.de>,
	 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>,
	linux-mm@kvack.org,  linux-kernel@vger.kernel.org,
	linux-fsdevel@vger.kernel.org,  linux-kselftest@vger.kernel.org
Subject: [PATCH v3 01/15] mm/vma: introduce VMA anon page offset field and add helpers
Date: Wed, 29 Jul 2026 17:48:36 +0100	[thread overview]
Message-ID: <20260729-b4-scalable-cow-virt-pgoff-v3-1-e8ecfefea812@kernel.org> (raw)
In-Reply-To: <20260729-b4-scalable-cow-virt-pgoff-v3-0-e8ecfefea812@kernel.org>

This patch establishes fields within the vm_area_struct type to store the
anonymous page offset of VMAs.

The anonymous page offset of a VMA is equal to vma->vm_start >> PAGE_SHIFT
if they are unfaulted or were not remapped, otherwise it is equal to this
value at the point of first fault.

Currently, anonymous folios belonging to CoW'd MAP_PRIVATE-mapped
file-backed VMAs are tracked by their file offset. By adding anonymous
offset as a property of VMAs, we can now track them by their anonymous page
offset instead.

By tracking this, we provide the means by which to eliminate this
inconsistency, and more importantly lay the foundations for future work for
the scalable CoW anonymous rmap rework.

This patch simply adds the fields and some simple helpers. Subsequent
patches will update mm code to make use of these fields correctly.

The fields chosen are packed in the VMA such that, for 64-bit kernel
builds, no additional space is taken up.

The first field is present on cacheline 0 containing key VMA fields, and
the second on cacheline 3, which contains file-backed reverse mapping
fields.

Given the relative time spent accessing reverse mapping fields as well as
updating them, there shouldn't be any performance impact here from false
sharing.

Update the VMA userland tests to account for this change.

No callsites are updated yet, so no functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
 include/linux/mm.h              | 59 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mm_types.h        | 12 +++++++++
 mm/vma.h                        | 14 ++++++++++
 mm/vma_init.c                   |  1 +
 tools/testing/vma/include/dup.h | 26 ++++++++++++++++++
 5 files changed, 112 insertions(+)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 87feaa5a2b78..df78847f5f07 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4393,6 +4393,65 @@ static inline pgoff_t vma_last_pgoff(const struct vm_area_struct *vma)
 	return vma_end_pgoff(vma) - 1;
 }
 
+/**
+ * vma_start_anon_pgoff() - Get the anonymous page offset of the start of @vma
+ * @vma: The VMA whose anonymous page offset is required.
+ *
+ * If unfaulted, then this is vma->vm_start >> PAGE_SHIFT, if faulted then the
+ * anonymous page offset at the time of first fault.
+ *
+ * If the VMA is anonymous, this returns the same value as vma_start_pgoff().
+ *
+ * This value is used for tracking MAP_PRIVATE file-backed mappings by their
+ * anonymous page offset.
+ *
+ * Returns: The anonymous page offset of the start of @vma.
+ */
+static inline pgoff_t vma_start_anon_pgoff(const struct vm_area_struct *vma)
+{
+	pgoff_t pgoff = 0;
+
+#ifdef CONFIG_64BIT
+	pgoff += vma->__vm_anon_pgoff_hi;
+	pgoff <<= 32;
+#endif
+	pgoff += vma->__vm_anon_pgoff_lo;
+	return pgoff;
+}
+
+/**
+ * vma_end_anon_pgoff() - Get the anonymous page offset of the exclusive end of
+ * @vma.
+ * @vma: The VMA whose end anonymous page offset is required.
+ *
+ * This returns the anonymous exclusive end page offset of @vma, which is useful
+ * for expressing page offset ranges.
+ *
+ * See the description of vma_start_anon_pgoff() for a description of VMA
+ * anonymous page offsets.
+ *
+ * Returns: The exclusive end anonymous page offset of @vma.
+ */
+static inline pgoff_t vma_end_anon_pgoff(const struct vm_area_struct *vma)
+{
+	return vma_start_anon_pgoff(vma) + vma_pages(vma);
+}
+
+/**
+ * vma_last_anon_pgoff() - Get the anonymous page offset of the last page in
+ * @vma.
+ * @vma: The VMA whose last anonymous page offset is required.
+ *
+ * See the description of vma_start_anon_pgoff() for a description of VMA
+ * anonymous page offsets.
+ *
+ * Returns: The last anonymous page offset of @vma.
+ */
+static inline pgoff_t vma_last_anon_pgoff(const struct vm_area_struct *vma)
+{
+	return vma_end_anon_pgoff(vma) - 1;
+}
+
 static inline unsigned long vma_desc_size(const struct vm_area_desc *desc)
 {
 	return desc->end - desc->start;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 939b5ea8c9e0..ebf0d912be7d 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -967,6 +967,11 @@ struct vm_area_struct {
 	 */
 	unsigned int vm_lock_seq;
 #endif
+	/*
+	 * Low 32-bits of anonymous page offset.
+	 * See vma_start_anon_pgoff() comment for details.
+	 */
+	unsigned int __vm_anon_pgoff_lo;
 	/*
 	 * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
 	 * list, after a COW of one of the file pages.	A MAP_SHARED vma
@@ -1041,6 +1046,13 @@ struct vm_area_struct {
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map vmlock_dep_map;
 #endif
+#endif
+#ifdef CONFIG_64BIT
+	/*
+	 * High 32-bits of anonymous page offset.
+	 * See vma_start_anon_pgoff() comment for details.
+	 */
+	unsigned int __vm_anon_pgoff_hi;
 #endif
 	/*
 	 * For areas with an address space and backing store,
diff --git a/mm/vma.h b/mm/vma.h
index 0bc7d521e976..54ed7c744e3b 100644
--- a/mm/vma.h
+++ b/mm/vma.h
@@ -283,6 +283,20 @@ static inline void vma_set_pgoff(struct vm_area_struct *vma, pgoff_t pgoff)
 	vma->vm_pgoff = pgoff;
 }
 
+static inline void __vma_set_anon_pgoff(struct vm_area_struct *vma, pgoff_t pgoff)
+{
+#ifdef CONFIG_64BIT
+	vma->__vm_anon_pgoff_hi = pgoff >> 32;
+#endif
+	vma->__vm_anon_pgoff_lo = pgoff & GENMASK(31, 0);
+}
+
+static inline void vma_set_anon_pgoff(struct vm_area_struct *vma, pgoff_t pgoff)
+{
+	vma_assert_can_modify(vma);
+	__vma_set_anon_pgoff(vma, pgoff);
+}
+
 static inline void vma_add_pgoff(struct vm_area_struct *vma, pgoff_t delta)
 {
 	vma_assert_can_modify(vma);
diff --git a/mm/vma_init.c b/mm/vma_init.c
index 715feee283f0..baa7e82f47e3 100644
--- a/mm/vma_init.c
+++ b/mm/vma_init.c
@@ -51,6 +51,7 @@ static void vm_area_init_from(const struct vm_area_struct *src,
 	dest->vm_end = src->vm_end;
 	dest->anon_vma = src->anon_vma;
 	dest->vm_pgoff = vma_start_pgoff(src);
+	__vma_set_anon_pgoff(dest, vma_start_anon_pgoff(src));
 	dest->vm_file = src->vm_file;
 	dest->vm_private_data = src->vm_private_data;
 	vm_flags_init(dest, src->vm_flags);
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index c52b23773cd2..26d9210b1e8b 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -577,6 +577,7 @@ struct vm_area_struct {
 	 */
 	unsigned int vm_lock_seq;
 #endif
+	unsigned int __vm_anon_pgoff_lo;
 
 	/*
 	 * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
@@ -612,6 +613,9 @@ struct vm_area_struct {
 #ifdef CONFIG_PER_VMA_LOCK
 	/* Unstable RCU readers are allowed to read this. */
 	refcount_t vm_refcnt;
+#endif
+#ifdef CONFIG_64BIT
+	unsigned int __vm_anon_pgoff_hi;
 #endif
 	/*
 	 * For areas with an address space and backing store,
@@ -1320,6 +1324,28 @@ static inline pgoff_t vma_end_pgoff(const struct vm_area_struct *vma)
 	return vma_start_pgoff(vma) + vma_pages(vma);
 }
 
+static inline pgoff_t vma_start_anon_pgoff(const struct vm_area_struct *vma)
+{
+	pgoff_t pgoff = 0;
+
+#ifdef CONFIG_64BIT
+	pgoff += vma->__vm_anon_pgoff_hi;
+	pgoff <<= 32;
+#endif
+	pgoff += vma->__vm_anon_pgoff_lo;
+	return pgoff;
+}
+
+static inline pgoff_t vma_end_anon_pgoff(const struct vm_area_struct *vma)
+{
+	return vma_start_anon_pgoff(vma) + vma_pages(vma);
+}
+
+static inline pgoff_t vma_last_anon_pgoff(const struct vm_area_struct *vma)
+{
+	return vma_end_anon_pgoff(vma) - 1;
+}
+
 static inline int vfs_mmap_prepare(struct file *file, struct vm_area_desc *desc)
 {
 	return file->f_op->mmap_prepare(desc);

-- 
2.55.0


  reply	other threads:[~2026-07-29 16:49 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-29 16:48 [PATCH v3 00/15] mm/rmap: index MAP_PRIVATE file-backed folios by anonymous pgoff Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` Lorenzo Stoakes (ARM) [this message]
2026-07-29 17:11   ` [PATCH v3 01/15] mm/vma: introduce VMA anon page offset field and add helpers Lorenzo Stoakes (ARM)
2026-07-30  3:32   ` Gregory Price
2026-08-03  9:28   ` David Hildenbrand (Arm)
2026-08-03  9:46     ` Lorenzo Stoakes (ARM)
2026-08-03  9:58       ` David Hildenbrand (Arm)
2026-08-03 10:13         ` Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 02/15] mm: introduce linear_anon_page_index() Lorenzo Stoakes (ARM)
2026-07-30  6:28   ` Gregory Price
2026-08-03  9:34   ` David Hildenbrand (Arm)
2026-08-03 10:10     ` Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 03/15] mm: abstract vma_address() and introduce vma_anon_address() Lorenzo Stoakes (ARM)
2026-07-30  4:58   ` Gregory Price
2026-07-30  6:39     ` Gregory Price
2026-07-30 10:16       ` Lorenzo Stoakes (ARM)
2026-08-03  9:37   ` David Hildenbrand (Arm)
2026-07-29 16:48 ` [PATCH v3 04/15] mm: update print_bad_page_map() to show anonymous page index Lorenzo Stoakes (ARM)
2026-07-30  6:32   ` Gregory Price
2026-08-03  9:39     ` David Hildenbrand (Arm)
2026-08-03 10:19       ` Lorenzo Stoakes (ARM)
2026-08-05  8:30         ` Gregory Price
2026-08-05  9:01           ` Lorenzo Stoakes (ARM)
2026-08-06 15:14             ` Lorenzo Stoakes (ARM)
2026-08-06 16:54             ` Matthew Wilcox
2026-08-06 17:18               ` Lorenzo Stoakes (ARM)
2026-08-03  9:39   ` David Hildenbrand (Arm)
2026-07-29 16:48 ` [PATCH v3 05/15] mm: introduce and use vma_filebacked_address() Lorenzo Stoakes (ARM)
2026-08-03  9:54   ` David Hildenbrand (Arm)
2026-08-03 10:15     ` Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 06/15] mm: propagate VMA anonymous page offset on map, remap, split + merge Lorenzo Stoakes (ARM)
2026-08-03 10:52   ` David Hildenbrand (Arm)
2026-08-03 13:46     ` Lorenzo Stoakes (ARM)
2026-08-05  7:35       ` David Hildenbrand (Arm)
2026-08-05  8:59         ` Lorenzo Stoakes (ARM)
2026-08-05  9:19           ` David Hildenbrand (Arm)
2026-08-05  9:29             ` Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 07/15] mm/rmap: track whether the page VMA mapped pgoff is anonymous Lorenzo Stoakes (ARM)
2026-08-03 10:57   ` David Hildenbrand (Arm)
2026-08-03 13:51     ` Lorenzo Stoakes (ARM)
2026-08-03 14:02       ` David Hildenbrand (Arm)
2026-08-03 14:32         ` Lorenzo Stoakes (ARM)
2026-08-05  7:17           ` David Hildenbrand (Arm)
2026-08-05  7:25             ` Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 08/15] mm: introduce and use linear_folio_page_index() Lorenzo Stoakes (ARM)
2026-08-03 11:27   ` David Hildenbrand (Arm)
2026-08-03 14:30     ` Lorenzo Stoakes (ARM)
2026-08-05  7:26       ` David Hildenbrand (Arm)
2026-08-05  9:02         ` Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 09/15] mm/rmap: use anon pgoff to track MAP_PRIVATE file-backed anon folios Lorenzo Stoakes (ARM)
2026-08-03 11:32   ` David Hildenbrand (Arm)
2026-08-03 14:30     ` Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 10/15] tools/testing/vma: expand VMA merge tests to assert anon pgoff Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 11/15] tools/testing/selftests/mm: test anonymous page offset merge behaviour Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 12/15] mm/vma: only permit MAP_PRIVATE /dev/zero to be mapped anonymous Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 13/15] mm/vma: make MAP_PRIVATE-mapped /dev/zero mappings truly anonymous Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 14/15] tools/testing/vma: add test to assert MAP_PRIVATE-/dev/zero is anon Lorenzo Stoakes (ARM)
2026-07-29 16:48 ` [PATCH v3 15/15] tools/testing/selftests/mm: add MAP_PRIVATE-/dev/zero merge tests Lorenzo Stoakes (ARM)

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=20260729-b4-scalable-cow-virt-pgoff-v3-1-e8ecfefea812@kernel.org \
    --to=ljs@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=apopple@nvidia.com \
    --cc=arnd@arndb.de \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=byungchul@sk.com \
    --cc=chengming.zhou@linux.dev \
    --cc=david@kernel.org \
    --cc=dev.jain@arm.com \
    --cc=gourry@gourry.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=harry@kernel.org \
    --cc=jack@suse.cz \
    --cc=jannh@google.com \
    --cc=joshua.hahnjy@gmail.com \
    --cc=kees@kernel.org \
    --cc=lance.yang@linux.dev \
    --cc=liam@infradead.org \
    --cc=linmiaohe@huawei.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=matthew.brost@intel.com \
    --cc=mhocko@suse.com \
    --cc=nao.horiguchi@gmail.com \
    --cc=npache@redhat.com \
    --cc=peterx@redhat.com \
    --cc=pfalcato@suse.de \
    --cc=rakie.kim@sk.com \
    --cc=riel@surriel.com \
    --cc=rppt@kernel.org \
    --cc=ryan.roberts@arm.com \
    --cc=surenb@google.com \
    --cc=usama.arif@linux.dev \
    --cc=vbabka@kernel.org \
    --cc=willy@infradead.org \
    --cc=xu.xin16@zte.com.cn \
    --cc=ying.huang@linux.alibaba.com \
    --cc=ziy@nvidia.com \
    /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

all inboxes | Powered by JetHome®