@@ -190,7 +190,6 @@ enum pageflags {
190190
191191 /* At least one page in this folio has the hwpoison flag set */
192192 PG_has_hwpoisoned = PG_error ,
193- PG_hugetlb = PG_active ,
194193 PG_large_rmappable = PG_workingset , /* anon or file-backed */
195194};
196195
@@ -458,30 +457,51 @@ static __always_inline int TestClearPage##uname(struct page *page) \
458457 TESTSETFLAG(uname, lname, policy) \
459458 TESTCLEARFLAG(uname, lname, policy)
460459
460+ #define FOLIO_TEST_FLAG_FALSE (name ) \
461+ static inline bool folio_test_##name(const struct folio *folio) \
462+ { return false; }
463+ #define FOLIO_SET_FLAG_NOOP (name ) \
464+ static inline void folio_set_##name(struct folio *folio) { }
465+ #define FOLIO_CLEAR_FLAG_NOOP (name ) \
466+ static inline void folio_clear_##name(struct folio *folio) { }
467+ #define __FOLIO_SET_FLAG_NOOP (name ) \
468+ static inline void __folio_set_##name(struct folio *folio) { }
469+ #define __FOLIO_CLEAR_FLAG_NOOP (name ) \
470+ static inline void __folio_clear_##name(struct folio *folio) { }
471+ #define FOLIO_TEST_SET_FLAG_FALSE (name ) \
472+ static inline bool folio_test_set_##name(struct folio *folio) \
473+ { return false; }
474+ #define FOLIO_TEST_CLEAR_FLAG_FALSE (name ) \
475+ static inline bool folio_test_clear_##name(struct folio *folio) \
476+ { return false; }
477+
478+ #define FOLIO_FLAG_FALSE (name ) \
479+ FOLIO_TEST_FLAG_FALSE(name) \
480+ FOLIO_SET_FLAG_NOOP(name) \
481+ FOLIO_CLEAR_FLAG_NOOP(name)
482+
461483#define TESTPAGEFLAG_FALSE (uname , lname ) \
462- static inline bool folio_test_##lname(const struct folio *folio) { return false; } \
484+ FOLIO_TEST_FLAG_FALSE(lname) \
463485static inline int Page##uname(const struct page *page) { return 0; }
464486
465487#define SETPAGEFLAG_NOOP (uname , lname ) \
466- static inline void folio_set_##lname(struct folio *folio) { } \
488+ FOLIO_SET_FLAG_NOOP(lname) \
467489static inline void SetPage##uname(struct page *page) { }
468490
469491#define CLEARPAGEFLAG_NOOP (uname , lname ) \
470- static inline void folio_clear_##lname(struct folio *folio) { } \
492+ FOLIO_CLEAR_FLAG_NOOP(lname) \
471493static inline void ClearPage##uname(struct page *page) { }
472494
473495#define __CLEARPAGEFLAG_NOOP (uname , lname ) \
474- static inline void __folio_clear_##lname(struct folio *folio) { } \
496+ __FOLIO_CLEAR_FLAG_NOOP(lname) \
475497static inline void __ClearPage##uname(struct page *page) { }
476498
477499#define TESTSETFLAG_FALSE (uname , lname ) \
478- static inline bool folio_test_set_##lname(struct folio *folio) \
479- { return 0; } \
500+ FOLIO_TEST_SET_FLAG_FALSE(lname) \
480501static inline int TestSetPage##uname(struct page *page) { return 0; }
481502
482503#define TESTCLEARFLAG_FALSE (uname , lname ) \
483- static inline bool folio_test_clear_##lname(struct folio *folio) \
484- { return 0; } \
504+ FOLIO_TEST_CLEAR_FLAG_FALSE(lname) \
485505static inline int TestClearPage##uname(struct page *page) { return 0; }
486506
487507#define PAGEFLAG_FALSE (uname , lname ) TESTPAGEFLAG_FALSE(uname, lname) \
@@ -855,29 +875,6 @@ TESTPAGEFLAG_FALSE(LargeRmappable, large_rmappable)
855875
856876#define PG_head_mask ((1UL << PG_head))
857877
858- #ifdef CONFIG_HUGETLB_PAGE
859- int PageHuge (const struct page * page );
860- SETPAGEFLAG (HugeTLB , hugetlb , PF_SECOND )
861- CLEARPAGEFLAG (HugeTLB , hugetlb , PF_SECOND )
862-
863- /**
864- * folio_test_hugetlb - Determine if the folio belongs to hugetlbfs
865- * @folio: The folio to test.
866- *
867- * Context: Any context. Caller should have a reference on the folio to
868- * prevent it from being turned into a tail page.
869- * Return: True for hugetlbfs folios, false for anon folios or folios
870- * belonging to other filesystems.
871- */
872- static inline bool folio_test_hugetlb (const struct folio * folio )
873- {
874- return folio_test_large (folio ) &&
875- test_bit (PG_hugetlb , const_folio_flags (folio , 1 ));
876- }
877- #else
878- TESTPAGEFLAG_FALSE (Huge , hugetlb )
879- #endif
880-
881878#ifdef CONFIG_TRANSPARENT_HUGEPAGE
882879/*
883880 * PageHuge() only returns true for hugetlbfs pages, but not for
@@ -933,34 +930,23 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
933930 TESTSCFLAG_FALSE (HasHWPoisoned , has_hwpoisoned )
934931#endif
935932
936- /*
937- * Check if a page is currently marked HWPoisoned. Note that this check is
938- * best effort only and inherently racy: there is no way to synchronize with
939- * failing hardware.
940- */
941- static inline bool is_page_hwpoison (struct page * page )
942- {
943- if (PageHWPoison (page ))
944- return true;
945- return PageHuge (page ) && PageHWPoison (compound_head (page ));
946- }
947-
948933/*
949934 * For pages that are never mapped to userspace (and aren't PageSlab),
950935 * page_type may be used. Because it is initialised to -1, we invert the
951936 * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and
952937 * __ClearPageFoo *sets* the bit used for PageFoo. We reserve a few high and
953- * low bits so that an underflow or overflow of page_mapcount() won't be
938+ * low bits so that an underflow or overflow of _mapcount won't be
954939 * mistaken for a page type value.
955940 */
956941
957942#define PAGE_TYPE_BASE 0xf0000000
958- /* Reserve 0x0000007f to catch underflows of page_mapcount */
943+ /* Reserve 0x0000007f to catch underflows of _mapcount */
959944#define PAGE_MAPCOUNT_RESERVE -128
960945#define PG_buddy 0x00000080
961946#define PG_offline 0x00000100
962947#define PG_table 0x00000200
963948#define PG_guard 0x00000400
949+ #define PG_hugetlb 0x00000800
964950
965951#define PageType (page , flag ) \
966952 ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
@@ -977,35 +963,38 @@ static inline int page_has_type(const struct page *page)
977963 return page_type_has_type (page -> page_type );
978964}
979965
966+ #define FOLIO_TYPE_OPS (lname , fname ) \
967+ static __always_inline bool folio_test_##fname(const struct folio *folio)\
968+ { \
969+ return folio_test_type(folio, PG_##lname); \
970+ } \
971+ static __always_inline void __folio_set_##fname(struct folio *folio) \
972+ { \
973+ VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio); \
974+ folio->page.page_type &= ~PG_##lname; \
975+ } \
976+ static __always_inline void __folio_clear_##fname(struct folio *folio) \
977+ { \
978+ VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio); \
979+ folio->page.page_type |= PG_##lname; \
980+ }
981+
980982#define PAGE_TYPE_OPS (uname , lname , fname ) \
983+ FOLIO_TYPE_OPS(lname, fname) \
981984static __always_inline int Page##uname(const struct page *page) \
982985{ \
983986 return PageType(page, PG_##lname); \
984987} \
985- static __always_inline int folio_test_##fname(const struct folio *folio)\
986- { \
987- return folio_test_type(folio, PG_##lname); \
988- } \
989988static __always_inline void __SetPage##uname(struct page *page) \
990989{ \
991990 VM_BUG_ON_PAGE(!PageType(page, 0), page); \
992991 page->page_type &= ~PG_##lname; \
993992} \
994- static __always_inline void __folio_set_##fname(struct folio *folio) \
995- { \
996- VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio); \
997- folio->page.page_type &= ~PG_##lname; \
998- } \
999993static __always_inline void __ClearPage##uname(struct page *page) \
1000994{ \
1001995 VM_BUG_ON_PAGE(!Page##uname(page), page); \
1002996 page->page_type |= PG_##lname; \
1003- } \
1004- static __always_inline void __folio_clear_##fname(struct folio *folio) \
1005- { \
1006- VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio); \
1007- folio->page.page_type |= PG_##lname; \
1008- } \
997+ }
1009998
1010999/*
10111000 * PageBuddy() indicates that the page is free and in the buddy system
@@ -1052,6 +1041,37 @@ PAGE_TYPE_OPS(Table, table, pgtable)
10521041 */
10531042PAGE_TYPE_OPS (Guard , guard , guard )
10541043
1044+ #ifdef CONFIG_HUGETLB_PAGE
1045+ FOLIO_TYPE_OPS (hugetlb , hugetlb )
1046+ #else
1047+ FOLIO_TEST_FLAG_FALSE (hugetlb )
1048+ #endif
1049+
1050+ /**
1051+ * PageHuge - Determine if the page belongs to hugetlbfs
1052+ * @page: The page to test.
1053+ *
1054+ * Context: Any context.
1055+ * Return: True for hugetlbfs pages, false for anon pages or pages
1056+ * belonging to other filesystems.
1057+ */
1058+ static inline bool PageHuge (const struct page * page )
1059+ {
1060+ return folio_test_hugetlb (page_folio (page ));
1061+ }
1062+
1063+ /*
1064+ * Check if a page is currently marked HWPoisoned. Note that this check is
1065+ * best effort only and inherently racy: there is no way to synchronize with
1066+ * failing hardware.
1067+ */
1068+ static inline bool is_page_hwpoison (struct page * page )
1069+ {
1070+ if (PageHWPoison (page ))
1071+ return true;
1072+ return PageHuge (page ) && PageHWPoison (compound_head (page ));
1073+ }
1074+
10551075extern bool is_free_buddy_page (struct page * page );
10561076
10571077PAGEFLAG (Isolated , isolated , PF_ANY );
@@ -1118,7 +1138,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
11181138 */
11191139#define PAGE_FLAGS_SECOND \
11201140 (0xffUL /* order */ | 1UL << PG_has_hwpoisoned | \
1121- 1UL << PG_hugetlb | 1UL << PG_large_rmappable)
1141+ 1UL << PG_large_rmappable)
11221142
11231143#define PAGE_FLAGS_PRIVATE \
11241144 (1UL << PG_private | 1UL << PG_private_2)
0 commit comments