[PATCH RFC 04/13] fs/proc/task_mmu: remove CONFIG_PAGE_MAPCOUNT handling for PM_MMAP_EXCLUSIVE

David Hildenbrand (Arm)
2026-04-12T19:00:27Z

In preparation for removing CONFIG_PAGE_MAPCOUNT, let's always use a
folio_maybe_mapped_shared() to detect possible page sharing, like we do
with CONFIG_NO_PAGE_MAPCOUNT.

Update the doc to state that this behavior no longer depends on the
kernel config, and simplify the doc a bit to mention less details that
are hard to follow.

For small folios and for large folios that were never mapped in multiple
processes at the same time, there is no change at all. For large folios,
there might be a change if

(1) The folio was once mapped at the same time into more than two
address space, and now is only mapped in a single address space. We
might detect it as shared.
(2) A folio page is only mapped into a single address space, but folio
pages mapped into other address spaces. We will detect it as
shared.
(3) A folio page is mapped multiple times into the same address space. We
will detect it as exclusive.

We can now remove __folio_page_mapped_exclusively().

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
Documentation/admin-guide/mm/pagemap.rst | 17 +++++++----------
fs/proc/task_mmu.c | 12 ++----------
2 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/Documentation/admin-guide/mm/pagemap.rst b/Documentation/admin-guide/mm/pagemap.rst
index f9478bcbb6a9..67eb04b1e246 100644
--- a/Documentation/admin-guide/mm/pagemap.rst
+++ b/Documentation/admin-guide/mm/pagemap.rst
@@ -38,16 +38,13 @@ There are four components to pagemap:
precisely which pages are mapped (or in swap) and comparing mapped
pages between processes.

- Traditionally, bit 56 indicates that a page is mapped exactly once and bit
- 56 is clear when a page is mapped multiple times, even when mapped in the
- same process multiple times. In some kernel configurations, the semantics
- for pages part of a larger allocation (e.g., THP) can differ: bit 56 is set
- if all pages part of the corresponding large allocation are *certainly*
- mapped in the same process, even if the page is mapped multiple times in that
- process. Bit 56 is clear when any page page of the larger allocation
- is *maybe* mapped in a different process. In some cases, a large allocation
- might be treated as "maybe mapped by multiple processes" even though this
- is no longer the case.
+ Bit 56 set indicates that the page is currently *certainly* exclusively
+ mapped in this process, and bit 56 clear indicates that the page *might be*
+ mapped into multiple processes ("shared"). Note that in the past, the bit
+ precisely indicated that a page was mapped exactly once, and the bit was
+ clear also if mapped multiple times in the same process. As this precise
+ information is not available for pages that are part of large allocations
+ (e.g., THP), the semantics have been slightly adjusted.

Efficient users of this interface will use ``/proc/pid/maps`` to
determine which areas of memory are actually mapped and llseek to
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index ad0989d101ab..1e1572849fed 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1884,13 +1884,6 @@ static int add_to_pagemap(pagemap_entry_t *pme, struct pagemapread *pm)
return 0;
}

-static bool __folio_page_mapped_exclusively(struct folio *folio, struct page *page)
-{
- if (IS_ENABLED(CONFIG_PAGE_MAPCOUNT))
- return folio_precise_page_mapcount(folio, page) == 1;
- return !folio_maybe_mapped_shared(folio);
-}
-
static int pagemap_pte_hole(unsigned long start, unsigned long end,
__always_unused int depth, struct mm_walk *walk)
{
@@ -1985,8 +1978,7 @@ static pagemap_entry_t pte_to_pagemap_entry(struct pagemapread *pm,
folio = page_folio(page);
if (!folio_test_anon(folio))
flags |= PM_FILE;
- if ((flags & PM_PRESENT) &&
- __folio_page_mapped_exclusively(folio, page))
+ if ((flags & PM_PRESENT) && !folio_maybe_mapped_shared(folio))
flags |= PM_MMAP_EXCLUSIVE;
}

@@ -2058,7 +2050,7 @@ static int pagemap_pmd_range_thp(pmd_t *pmdp, unsigned long addr,
pagemap_entry_t pme;

if (folio && (flags & PM_PRESENT) &&
- __folio_page_mapped_exclusively(folio, page))
+ !folio_maybe_mapped_shared(folio))
cur_flags |= PM_MMAP_EXCLUSIVE;

pme = make_pme(frame, cur_flags);

--
2.43.0