mm: make folio_mapcount() return 0 for small typed folios
authorDavid Hildenbrand <david@redhat.com>
Tue, 9 Apr 2024 19:22:49 +0000 (21:22 +0200)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 6 May 2024 00:53:29 +0000 (17:53 -0700)
We already handle it properly for large folios.  Let's also return "0" for
small typed folios, like page_mapcount() currently would.

Consequently, folio_mapcount() will never return negative values for typed
folios, but may return negative values for underflows.

[david@redhat.com: make folio_mapcount() slightly more efficient]
Link: https://lkml.kernel.org/r/c30fcda1-ed87-46f5-8297-cdedbddac009@redhat.com
Link: https://lkml.kernel.org/r/20240409192301.907377-7-david@redhat.com
Signed-off-by: David Hildenbrand <david@redhat.com>
Cc: Chris Zankel <chris@zankel.net>
Cc: Hugh Dickins <hughd@google.com>
Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Richard Chang <richardycc@google.com>
Cc: Rich Felker <dalias@libc.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Yang Shi <shy828301@gmail.com>
Cc: Yin Fengwei <fengwei.yin@intel.com>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/mm.h

index c7470da5797f137a41c6faa2b815578831f0602e..78e583b50e421be86db95a54461a8454b3f5cd4c 100644 (file)
@@ -1261,12 +1261,22 @@ static inline int folio_large_mapcount(const struct folio *folio)
  * references the entire folio counts exactly once, even when such special
  * page table entries are comprised of multiple ordinary page table entries.
  *
+ * Will report 0 for pages which cannot be mapped into userspace, such as
+ * slab, page tables and similar.
+ *
  * Return: The number of times this folio is mapped.
  */
 static inline int folio_mapcount(const struct folio *folio)
 {
-       if (likely(!folio_test_large(folio)))
-               return atomic_read(&folio->_mapcount) + 1;
+       int mapcount;
+
+       if (likely(!folio_test_large(folio))) {
+               mapcount = atomic_read(&folio->_mapcount) + 1;
+               /* Handle page_has_type() pages */
+               if (mapcount < PAGE_MAPCOUNT_RESERVE + 1)
+                       mapcount = 0;
+               return mapcount;
+       }
        return folio_large_mapcount(folio);
 }