From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: Arnd Bergmann <arnd@arndb.de>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Andrew Morton <akpm@linux-foundation.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Jann Horn <jannh@google.com>, Pedro Falcato <pfalcato@suse.de>,
David Hildenbrand <david@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, Hugh Dickins <hughd@google.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
"Matthew Wilcox (Oracle)" <willy@infradead.org>,
Jan Kara <jack@suse.cz>
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-fsdevel@vger.kernel.org, linux-kselftest@vger.kernel.org,
"Lorenzo Stoakes (ARM)" <ljs@kernel.org>
Subject: [PATCH v3 6/6] tools/testing/selftests/mm: add MAP_PRIVATE-/dev/zero merge tests
Date: Sat, 26 Sep 2026 11:41:11 +0100 [thread overview]
Message-ID: <20260926-map-private-dev-zero-v3-6-d4781e84ccfc@kernel.org> (raw)
In-Reply-To: <20260926-map-private-dev-zero-v3-0-d4781e84ccfc@kernel.org>
Assert that MAP_PRIVATE-mapped /dev/zero mappings behave like they are
anonymous.
Test both unfaulted and faulted/unfaulted merges with page offset 0 which
would not merge if the mappings were treated as if they were file-backed.
With the recent change that makes them behave as pure anonymous mappings,
the merges should succeed as their page offsets are equal to their
anonymous page offsets.
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
---
tools/testing/selftests/mm/merge.c | 95 ++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/tools/testing/selftests/mm/merge.c b/tools/testing/selftests/mm/merge.c
index 52b8727b6628..7dd2933417c1 100644
--- a/tools/testing/selftests/mm/merge.c
+++ b/tools/testing/selftests/mm/merge.c
@@ -1362,6 +1362,101 @@ TEST_F(merge, anon_and_page_offset_mismatch_memfd)
ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr + 5 * page_size);
}
+TEST_F(merge, merge_map_private_dev_zero_unfaulted)
+{
+ struct procmap_fd *procmap = &self->procmap;
+ unsigned int page_size = self->page_size;
+ char *carveout = self->carveout;
+ char *ptr, *ptr2;
+ int fd_zero;
+
+ if (access("/dev/zero", F_OK))
+ SKIP(return, "No /dev/zero.");
+ fd_zero = open("/dev/zero", O_RDWR);
+ ASSERT_NE(fd_zero, -1);
+
+ /*
+ * Map two MAP_PRIVATE-/dev/zero VMAs next to one another with offset 0
+ * each.
+ *
+ * With these being made truly anonymous upon mapping, they will
+ * merge. If they were file-backed VMAs the page offsets would prevent
+ * the merge:
+ *
+ * |-----||------| |-------------|
+ * | ptr || ptr2 | -> | ptr |
+ * |-----||------| |-------------|
+ */
+ ptr = mmap(carveout, 5 * page_size, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE, fd_zero, 0);
+ ptr2 = mmap(&carveout[5 * page_size], 5 * page_size,
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, fd_zero, 0);
+ close(fd_zero);
+ ASSERT_NE(ptr, MAP_FAILED);
+ ASSERT_NE(ptr2, MAP_FAILED);
+
+ /* Assert that they merged. */
+ ASSERT_TRUE(find_vma_procmap(procmap, ptr));
+ ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr);
+ ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr + 10 * page_size);
+}
+
+TEST_F(merge, merge_map_private_dev_zero_faulted_unfaulted)
+{
+ struct procmap_fd *procmap = &self->procmap;
+ unsigned int page_size = self->page_size;
+ char *carveout = self->carveout;
+ char *ptr, *ptr2;
+ int fd_zero;
+
+ if (access("/dev/zero", F_OK))
+ SKIP(return, "No /dev/zero.");
+ fd_zero = open("/dev/zero", O_RDWR);
+ ASSERT_NE(fd_zero, -1);
+
+ /*
+ * Map a MAP_PRIVATE mapping of /dev/zero with page offset 0, then fault
+ * it in:
+ *
+ * |-------------------------------|
+ * | faulted |
+ * |-------------------------------|
+ */
+ ptr = mmap(carveout, 15 * page_size, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE, fd_zero, 0);
+ ASSERT_NE(ptr, MAP_FAILED);
+ memset(ptr, 'x', 15 * page_size);
+
+ /*
+ * Unmap the middle:
+ *
+ * |---------| |---------|
+ * | faulted | | faulted |
+ * |---------| |---------|
+ */
+ ASSERT_EQ(munmap(&ptr[5 * page_size], 5 * page_size), 0);
+
+ /*
+ * Map in a new unfaulted mapping in the middle with page offset 0 -
+ * this should merge and would not if it were treated as a file rather
+ * than pure anon:
+ *
+ * |---------|-----------|---------|
+ * | faulted | unfaulted | faulted |
+ * |---------|-----------|---------|
+ */
+ ptr2 = mmap(&carveout[5 * page_size], 5 * page_size,
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE,
+ fd_zero, 0);
+ close(fd_zero);
+ ASSERT_NE(ptr2, MAP_FAILED);
+
+ /* Assert that they merged. */
+ ASSERT_TRUE(find_vma_procmap(procmap, ptr));
+ ASSERT_EQ(procmap->query.vma_start, (unsigned long)ptr);
+ ASSERT_EQ(procmap->query.vma_end, (unsigned long)ptr + 15 * page_size);
+}
+
TEST_F(merge_with_fork, mremap_faulted_to_unfaulted_prev)
{
struct procmap_fd *procmap = &self->procmap;
--
2.55.0
next prev parent reply other threads:[~2026-09-26 10:41 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-26 10:41 [PATCH v3 0/6] mm: make MAP_PRIVATE-/dev/zero mappings truly anonymous Lorenzo Stoakes (ARM)
2026-09-26 10:41 ` [PATCH v3 1/6] mm: move drivers/char/mem.c to mm/char-mem.c Lorenzo Stoakes (ARM)
2026-09-26 10:41 ` [PATCH v3 2/6] mm: implement file_is_dev_zero() to uniquely identify /dev/zero Lorenzo Stoakes (ARM)
2026-09-26 10:41 ` [PATCH v3 3/6] mm/vma: only permit MAP_PRIVATE /dev/zero to be mapped anonymous Lorenzo Stoakes (ARM)
2026-09-26 10:41 ` [PATCH v3 4/6] mm/vma: make MAP_PRIVATE-mapped /dev/zero mappings truly anonymous Lorenzo Stoakes (ARM)
2026-09-26 10:41 ` [PATCH v3 5/6] tools/testing/vma: add test to assert MAP_PRIVATE-/dev/zero is anon Lorenzo Stoakes (ARM)
2026-09-26 10:41 ` Lorenzo Stoakes (ARM) [this message]
2026-09-28 23:39 ` [PATCH v3 0/6] mm: make MAP_PRIVATE-/dev/zero mappings truly anonymous Andrew Morton
2026-09-29 8:29 ` 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=20260926-map-private-dev-zero-v3-6-d4781e84ccfc@kernel.org \
--to=ljs@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=arnd@arndb.de \
--cc=baolin.wang@linux.alibaba.com \
--cc=david@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=hughd@google.com \
--cc=jack@suse.cz \
--cc=jannh@google.com \
--cc=liam@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@suse.com \
--cc=pfalcato@suse.de \
--cc=rppt@kernel.org \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=willy@infradead.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.