Merge tag 'mm-hotfixes-stable-2024-04-26-13-30' of git://git.kernel.org/pub/scm/linux...
[sfrench/cifs-2.6.git] / include / linux / page-flags.h
index 652d77805e99dfb2adf31def151a26466eff571c..4bf1c25fd1dc566cccf51742286243bace192dad 100644 (file)
@@ -190,7 +190,6 @@ enum pageflags {
 
        /* At least one page in this folio has the hwpoison flag set */
        PG_has_hwpoisoned = PG_error,
-       PG_hugetlb = PG_active,
        PG_large_rmappable = PG_workingset, /* anon or file-backed */
 };
 
@@ -458,30 +457,51 @@ static __always_inline int TestClearPage##uname(struct page *page)        \
        TESTSETFLAG(uname, lname, policy)                               \
        TESTCLEARFLAG(uname, lname, policy)
 
+#define FOLIO_TEST_FLAG_FALSE(name)                                    \
+static inline bool folio_test_##name(const struct folio *folio)                \
+{ return false; }
+#define FOLIO_SET_FLAG_NOOP(name)                                      \
+static inline void folio_set_##name(struct folio *folio) { }
+#define FOLIO_CLEAR_FLAG_NOOP(name)                                    \
+static inline void folio_clear_##name(struct folio *folio) { }
+#define __FOLIO_SET_FLAG_NOOP(name)                                    \
+static inline void __folio_set_##name(struct folio *folio) { }
+#define __FOLIO_CLEAR_FLAG_NOOP(name)                                  \
+static inline void __folio_clear_##name(struct folio *folio) { }
+#define FOLIO_TEST_SET_FLAG_FALSE(name)                                        \
+static inline bool folio_test_set_##name(struct folio *folio)          \
+{ return false; }
+#define FOLIO_TEST_CLEAR_FLAG_FALSE(name)                              \
+static inline bool folio_test_clear_##name(struct folio *folio)                \
+{ return false; }
+
+#define FOLIO_FLAG_FALSE(name)                                         \
+FOLIO_TEST_FLAG_FALSE(name)                                            \
+FOLIO_SET_FLAG_NOOP(name)                                              \
+FOLIO_CLEAR_FLAG_NOOP(name)
+
 #define TESTPAGEFLAG_FALSE(uname, lname)                               \
-static inline bool folio_test_##lname(const struct folio *folio) { return false; } \
+FOLIO_TEST_FLAG_FALSE(lname)                                           \
 static inline int Page##uname(const struct page *page) { return 0; }
 
 #define SETPAGEFLAG_NOOP(uname, lname)                                 \
-static inline void folio_set_##lname(struct folio *folio) { }          \
+FOLIO_SET_FLAG_NOOP(lname)                                             \
 static inline void SetPage##uname(struct page *page) {  }
 
 #define CLEARPAGEFLAG_NOOP(uname, lname)                               \
-static inline void folio_clear_##lname(struct folio *folio) { }                \
+FOLIO_CLEAR_FLAG_NOOP(lname)                                           \
 static inline void ClearPage##uname(struct page *page) {  }
 
 #define __CLEARPAGEFLAG_NOOP(uname, lname)                             \
-static inline void __folio_clear_##lname(struct folio *folio) { }      \
+__FOLIO_CLEAR_FLAG_NOOP(lname)                                         \
 static inline void __ClearPage##uname(struct page *page) {  }
 
 #define TESTSETFLAG_FALSE(uname, lname)                                        \
-static inline bool folio_test_set_##lname(struct folio *folio)         \
-{ return 0; }                                                          \
+FOLIO_TEST_SET_FLAG_FALSE(lname)                                       \
 static inline int TestSetPage##uname(struct page *page) { return 0; }
 
 #define TESTCLEARFLAG_FALSE(uname, lname)                              \
-static inline bool folio_test_clear_##lname(struct folio *folio)       \
-{ return 0; }                                                          \
+FOLIO_TEST_CLEAR_FLAG_FALSE(lname)                                     \
 static inline int TestClearPage##uname(struct page *page) { return 0; }
 
 #define PAGEFLAG_FALSE(uname, lname) TESTPAGEFLAG_FALSE(uname, lname)  \
@@ -855,29 +875,6 @@ TESTPAGEFLAG_FALSE(LargeRmappable, large_rmappable)
 
 #define PG_head_mask ((1UL << PG_head))
 
-#ifdef CONFIG_HUGETLB_PAGE
-int PageHuge(const struct page *page);
-SETPAGEFLAG(HugeTLB, hugetlb, PF_SECOND)
-CLEARPAGEFLAG(HugeTLB, hugetlb, PF_SECOND)
-
-/**
- * folio_test_hugetlb - Determine if the folio belongs to hugetlbfs
- * @folio: The folio to test.
- *
- * Context: Any context.  Caller should have a reference on the folio to
- * prevent it from being turned into a tail page.
- * Return: True for hugetlbfs folios, false for anon folios or folios
- * belonging to other filesystems.
- */
-static inline bool folio_test_hugetlb(const struct folio *folio)
-{
-       return folio_test_large(folio) &&
-               test_bit(PG_hugetlb, const_folio_flags(folio, 1));
-}
-#else
-TESTPAGEFLAG_FALSE(Huge, hugetlb)
-#endif
-
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 /*
  * PageHuge() only returns true for hugetlbfs pages, but not for
@@ -933,34 +930,23 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
        TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
 #endif
 
-/*
- * Check if a page is currently marked HWPoisoned. Note that this check is
- * best effort only and inherently racy: there is no way to synchronize with
- * failing hardware.
- */
-static inline bool is_page_hwpoison(struct page *page)
-{
-       if (PageHWPoison(page))
-               return true;
-       return PageHuge(page) && PageHWPoison(compound_head(page));
-}
-
 /*
  * For pages that are never mapped to userspace (and aren't PageSlab),
  * page_type may be used.  Because it is initialised to -1, we invert the
  * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and
  * __ClearPageFoo *sets* the bit used for PageFoo.  We reserve a few high and
- * low bits so that an underflow or overflow of page_mapcount() won't be
+ * low bits so that an underflow or overflow of _mapcount won't be
  * mistaken for a page type value.
  */
 
 #define PAGE_TYPE_BASE 0xf0000000
-/* Reserve             0x0000007f to catch underflows of page_mapcount */
+/* 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 PageType(page, flag)                                           \
        ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
@@ -977,35 +963,38 @@ static inline int page_has_type(const struct page *page)
        return page_type_has_type(page->page_type);
 }
 
+#define FOLIO_TYPE_OPS(lname, fname)                                   \
+static __always_inline bool folio_test_##fname(const struct folio *folio)\
+{                                                                      \
+       return folio_test_type(folio, PG_##lname);                      \
+}                                                                      \
+static __always_inline void __folio_set_##fname(struct folio *folio)   \
+{                                                                      \
+       VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio);             \
+       folio->page.page_type &= ~PG_##lname;                           \
+}                                                                      \
+static __always_inline void __folio_clear_##fname(struct folio *folio) \
+{                                                                      \
+       VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio);             \
+       folio->page.page_type |= PG_##lname;                            \
+}
+
 #define PAGE_TYPE_OPS(uname, lname, fname)                             \
+FOLIO_TYPE_OPS(lname, fname)                                           \
 static __always_inline int Page##uname(const struct page *page)                \
 {                                                                      \
        return PageType(page, PG_##lname);                              \
 }                                                                      \
-static __always_inline int folio_test_##fname(const struct folio *folio)\
-{                                                                      \
-       return folio_test_type(folio, PG_##lname);                      \
-}                                                                      \
 static __always_inline void __SetPage##uname(struct page *page)                \
 {                                                                      \
        VM_BUG_ON_PAGE(!PageType(page, 0), page);                       \
        page->page_type &= ~PG_##lname;                                 \
 }                                                                      \
-static __always_inline void __folio_set_##fname(struct folio *folio)   \
-{                                                                      \
-       VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio);             \
-       folio->page.page_type &= ~PG_##lname;                           \
-}                                                                      \
 static __always_inline void __ClearPage##uname(struct page *page)      \
 {                                                                      \
        VM_BUG_ON_PAGE(!Page##uname(page), page);                       \
        page->page_type |= PG_##lname;                                  \
-}                                                                      \
-static __always_inline void __folio_clear_##fname(struct folio *folio) \
-{                                                                      \
-       VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio);             \
-       folio->page.page_type |= PG_##lname;                            \
-}                                                                      \
+}
 
 /*
  * PageBuddy() indicates that the page is free and in the buddy system
@@ -1052,6 +1041,37 @@ PAGE_TYPE_OPS(Table, table, pgtable)
  */
 PAGE_TYPE_OPS(Guard, guard, guard)
 
+#ifdef CONFIG_HUGETLB_PAGE
+FOLIO_TYPE_OPS(hugetlb, hugetlb)
+#else
+FOLIO_TEST_FLAG_FALSE(hugetlb)
+#endif
+
+/**
+ * PageHuge - Determine if the page belongs to hugetlbfs
+ * @page: The page to test.
+ *
+ * Context: Any context.
+ * Return: True for hugetlbfs pages, false for anon pages or pages
+ * belonging to other filesystems.
+ */
+static inline bool PageHuge(const struct page *page)
+{
+       return folio_test_hugetlb(page_folio(page));
+}
+
+/*
+ * Check if a page is currently marked HWPoisoned. Note that this check is
+ * best effort only and inherently racy: there is no way to synchronize with
+ * failing hardware.
+ */
+static inline bool is_page_hwpoison(struct page *page)
+{
+       if (PageHWPoison(page))
+               return true;
+       return PageHuge(page) && PageHWPoison(compound_head(page));
+}
+
 extern bool is_free_buddy_page(struct page *page);
 
 PAGEFLAG(Isolated, isolated, PF_ANY);
@@ -1118,7 +1138,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
  */
 #define PAGE_FLAGS_SECOND                                              \
        (0xffUL /* order */             | 1UL << PG_has_hwpoisoned |    \
-        1UL << PG_hugetlb              | 1UL << PG_large_rmappable)
+        1UL << PG_large_rmappable)
 
 #define PAGE_FLAGS_PRIVATE                             \
        (1UL << PG_private | 1UL << PG_private_2)