diff mbox series

[RFC,2/6] mm: allow reuse of the lower 16bit of the page type with an actual type

Message ID 20240522210341.1030552-3-david@redhat.com (mailing list archive)
State New
Headers show
Series mm: page_type, zsmalloc and page_mapcount_reset() | expand

Commit Message

David Hildenbrand May 22, 2024, 9:03 p.m. UTC
As long as the owner sets a page type first, we can allow reuse of the
lower 16bit! Restrict it to the head page.

We'll use that for zsmalloc next, to set a proper type while still
reusing that field to store information that cannot go elsewhere for
now.

Fear of running out of bits for storing the actual type? Actually, we
don't need one bit per type, we could store a single value instead.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 include/linux/mm_types.h   |  5 +++++
 include/linux/page-flags.h | 22 ++++++++++++++--------
 2 files changed, 19 insertions(+), 8 deletions(-)

Comments

David Hildenbrand May 24, 2024, 10:04 a.m. UTC | #1
On 22.05.24 23:03, David Hildenbrand wrote:
> As long as the owner sets a page type first, we can allow reuse of the
> lower 16bit! Restrict it to the head page.
> 
> We'll use that for zsmalloc next, to set a proper type while still
> reusing that field to store information that cannot go elsewhere for
> now.
> 
> Fear of running out of bits for storing the actual type? Actually, we
> don't need one bit per type, we could store a single value instead.
> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---

Likely the following might be better if we want to go down that path:



 From 39f198589039451d94166f3893dc939a919f74c7 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Wed, 22 May 2024 21:57:43 +0200
Subject: [PATCH] mm: allow reuse of the lower 18 bit of the page type with an
  actual type

As long as the owner sets a page type first, we can allow reuse of the
lower 18 bit: sufficient to store an offset into a 256 KiB page, which
is the maximum base page size we support. Restrict it to the head page.

We'll use that for zsmalloc next, to set a proper type while still
reusing that field to store information (offset into a base page) that
cannot go elsewhere for now.

Fear of running out of bits for storing the actual type? Actually, we
don't need one bit per type, we could store a single value instead.
Further, we could likely limit PAGE_TYPE_BASE to a single (highest) bit.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
  include/linux/mm_types.h   |  5 +++++
  include/linux/page-flags.h | 20 ++++++++++++--------
  2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 532a3030405d..437a62bed277 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -168,6 +168,11 @@ struct page {
  		 *
  		 * See page-flags.h for a list of page types which are currently
  		 * stored here.
+		 *
+		 * Owners of typed folios may reuse the lower 18 bit of the
+		 * head page page_type field after setting the page type,
+		 * but must reset these 18 bit to -1 before clearing the
+		 * page type.
  		 */
  		unsigned int page_type;
  	};
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 104078afe0b1..2f49c8b2f411 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -945,14 +945,18 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
   */
  
  #define PAGE_TYPE_BASE	0xf0000000
-/* Reserve		0x0000007f to catch underflows of _mapcount */
-#define PAGE_MAPCOUNT_RESERVE	-128
-#define PG_buddy	0x00000080
-#define PG_offline	0x00000100
-#define PG_table	0x00000200
-#define PG_guard	0x00000400
-#define PG_hugetlb	0x00000800
-#define PG_slab		0x00001000
+/*
+ * Reserve		0x0003ffff to catch underflows of _mapcount and
+ * allow owners that set a type to reuse the lower 18 bit for their own
+ * purposes.
+ */
+#define PAGE_MAPCOUNT_RESERVE	-262144
+#define PG_buddy	0x00040000
+#define PG_offline	0x00080000
+#define PG_table	0x00100000
+#define PG_guard	0x00200000
+#define PG_hugetlb	0x00400800
+#define PG_slab		0x00800000
  
  #define PageType(page, flag)						\
  	((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
diff mbox series

Patch

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 532a3030405d..6dae8e15037b 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -168,6 +168,11 @@  struct page {
 		 *
 		 * See page-flags.h for a list of page types which are currently
 		 * stored here.
+		 *
+		 * Owners of typed folios may reuse the lower 16bit of the
+		 * head page page_type field after setting the page type,
+		 * but must reset these 16 bit to -1 before clearing the
+		 * page type.
 		 */
 		unsigned int page_type;
 	};
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 104078afe0b1..ed9ac4b5233d 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -942,17 +942,23 @@  PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
  * __ClearPageFoo *sets* the bit used for PageFoo.  We reserve a few high and
  * low bits so that an underflow or overflow of _mapcount won't be
  * mistaken for a page type value.
+ *
+ * The highest bit must always be 1, to make page_has_type() work as expected.
  */
 
 #define PAGE_TYPE_BASE	0xf0000000
-/* Reserve		0x0000007f to catch underflows of _mapcount */
-#define PAGE_MAPCOUNT_RESERVE	-128
-#define PG_buddy	0x00000080
-#define PG_offline	0x00000100
-#define PG_table	0x00000200
-#define PG_guard	0x00000400
-#define PG_hugetlb	0x00000800
-#define PG_slab		0x00001000
+/*
+ * Reserve		0x0000ffff to catch underflows of _mapcount and
+ * allow owners that set a type to reuse the lower 16 bit for their own
+ * purposes.
+ */
+#define PAGE_MAPCOUNT_RESERVE	-65536
+#define PG_buddy	0x00010080
+#define PG_offline	0x00020000
+#define PG_table	0x00040000
+#define PG_guard	0x00080000
+#define PG_hugetlb	0x00100800
+#define PG_slab		0x00200000
 
 #define PageType(page, flag)						\
 	((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)