Pull misc fixes from Andrew Morton: "11 hotfixes. 8 are cc:stable and the remaining 3 (nice ratio!) address post-6.8 issues or aren't considered suitable for backporting. All except one of these are for MM. I see no particular theme - it's singletons all over" * tag 'mm-hotfixes-stable-2024-04-26-13-30' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: mm/hugetlb: fix DEBUG_LOCKS_WARN_ON(1) when dissolve_free_hugetlb_folio() selftests: mm: protection_keys: save/restore nr_hugepages value from launch script stackdepot: respect __GFP_NOLOCKDEP allocation flag hugetlb: check for anon_vma prior to folio allocation mm: zswap: fix shrinker NULL crash with cgroup_disable=memory mm: turn folio_test_hugetlb into a PageType mm: support page_mapcount() on page_has_type() pages mm: create FOLIO_FLAG_FALSE and FOLIO_TYPE_OPS macros mm/hugetlb: fix missing hugetlb_lock for resv uncharge selftests: mm: fix unused and uninitialized variable warning selftests/harness: remove use of LINE_MAX
Showing the changes to include/linux (2 of 13 files). Show all
Unified · Split
| @@ -1223,14 +1223,16 @@ static inline void page_mapcount_reset(struct page *page) · 1222 unmodified lines | ||
| 1223 | 1223 | * a large folio, it includes the number of times this page is mapped |
| 1224 | 1224 | * as part of that folio. |
| 1225 | 1225 | * |
| 1226 | − * The result is undefined for pages which cannot be mapped into userspace. | |
| 1227 | − * For example SLAB or special types of pages. See function page_has_type(). | |
| 1228 | − * They use this field in struct page differently. | |
| 1226 | + * Will report 0 for pages which cannot be mapped into userspace, eg | |
| 1227 | + * slab, page tables and similar. | |
| 1229 | 1228 | */ |
| 1230 | 1229 | static inline int page_mapcount(struct page *page) |
| 1231 | 1230 | { |
| 1232 | 1231 | int mapcount = atomic_read(&page->_mapcount) + 1; |
| 1233 | 1232 | |
| 1233 | + /* Handle page_has_type() pages */ | |
| 1234 | + if (mapcount < 0) | |
| 1235 | + mapcount = 0; | |
| 1234 | 1236 | if (unlikely(PageCompound(page))) |
| 1235 | 1237 | mapcount += folio_entire_mapcount(page_folio(page)); |
| 1236 | 1238 | |
| @@ -190,7 +190,6 @@ enum pageflags { · 189 unmodified lines | ||
| 190 | 190 | |
| 191 | 191 | /* At least one page in this folio has the hwpoison flag set */ |
| 192 | 192 | PG_has_hwpoisoned = PG_error, |
| 193 | − PG_hugetlb = PG_active, | |
| 194 | 193 | PG_large_rmappable = PG_workingset, /* anon or file-backed */ |
| 195 | 194 | }; |
| 196 | 195 | |
| @@ -458,30 +457,51 @@ static __always_inline int TestClearPage##uname(struct page *page) \ · 261 unmodified lines | ||
| 458 | 457 | TESTSETFLAG(uname, lname, policy) \ |
| 459 | 458 | TESTCLEARFLAG(uname, lname, policy) |
| 460 | 459 | |
| 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 | + | |
| 461 | 483 | #define TESTPAGEFLAG_FALSE(uname, lname) \ |
| 462 | −static inline bool folio_test_##lname(const struct folio *folio) { return false; } \ | |
| 484 | +FOLIO_TEST_FLAG_FALSE(lname) \ | |
| 463 | 485 | static inline int Page##uname(const struct page *page) { return 0; } |
| 464 | 486 | |
| 465 | 487 | #define SETPAGEFLAG_NOOP(uname, lname) \ |
| 466 | −static inline void folio_set_##lname(struct folio *folio) { } \ | |
| 488 | +FOLIO_SET_FLAG_NOOP(lname) \ | |
| 467 | 489 | static inline void SetPage##uname(struct page *page) { } |
| 468 | 490 | |
| 469 | 491 | #define CLEARPAGEFLAG_NOOP(uname, lname) \ |
| 470 | −static inline void folio_clear_##lname(struct folio *folio) { } \ | |
| 492 | +FOLIO_CLEAR_FLAG_NOOP(lname) \ | |
| 471 | 493 | static inline void ClearPage##uname(struct page *page) { } |
| 472 | 494 | |
| 473 | 495 | #define __CLEARPAGEFLAG_NOOP(uname, lname) \ |
| 474 | −static inline void __folio_clear_##lname(struct folio *folio) { } \ | |
| 496 | +__FOLIO_CLEAR_FLAG_NOOP(lname) \ | |
| 475 | 497 | static inline void __ClearPage##uname(struct page *page) { } |
| 476 | 498 | |
| 477 | 499 | #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) \ | |
| 480 | 501 | static inline int TestSetPage##uname(struct page *page) { return 0; } |
| 481 | 502 | |
| 482 | 503 | #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) \ | |
| 485 | 505 | static inline int TestClearPage##uname(struct page *page) { return 0; } |
| 486 | 506 | |
| 487 | 507 | #define PAGEFLAG_FALSE(uname, lname) TESTPAGEFLAG_FALSE(uname, lname) \ |
| @@ -855,29 +875,6 @@ TESTPAGEFLAG_FALSE(LargeRmappable, large_rmappable) · 367 unmodified lines | ||
| 855 | 875 | |
| 856 | 876 | #define PG_head_mask ((1UL << PG_head)) |
| 857 | 877 | |
| 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 | − | |
| 881 | 878 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 882 | 879 | /* |
| 883 | 880 | * PageHuge() only returns true for hugetlbfs pages, but not for |
| @@ -933,34 +930,23 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned) · 49 unmodified lines | ||
| 933 | 930 | TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned) |
| 934 | 931 | #endif |
| 935 | 932 | |
| 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 | − | |
| 948 | 933 | /* |
| 949 | 934 | * For pages that are never mapped to userspace (and aren't PageSlab), |
| 950 | 935 | * page_type may be used. Because it is initialised to -1, we invert the |
| 951 | 936 | * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and |
| 952 | 937 | * __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 | |
| 954 | 939 | * mistaken for a page type value. |
| 955 | 940 | */ |
| 956 | 941 | |
| 957 | 942 | #define PAGE_TYPE_BASE 0xf0000000 |
| 958 | −/* Reserve 0x0000007f to catch underflows of page_mapcount */ | |
| 943 | +/* Reserve 0x0000007f to catch underflows of _mapcount */ | |
| 959 | 944 | #define PAGE_MAPCOUNT_RESERVE -128 |
| 960 | 945 | #define PG_buddy 0x00000080 |
| 961 | 946 | #define PG_offline 0x00000100 |
| 962 | 947 | #define PG_table 0x00000200 |
| 963 | 948 | #define PG_guard 0x00000400 |
| 949 | +#define PG_hugetlb 0x00000800 | |
| 964 | 950 | |
| 965 | 951 | #define PageType(page, flag) \ |
| 966 | 952 | ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE) |
| @@ -977,35 +963,38 @@ static inline int page_has_type(const struct page *page) · 10 unmodified lines | ||
| 977 | 963 | return page_type_has_type(page->page_type); |
| 978 | 964 | } |
| 979 | 965 | |
| 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 | + | |
| 980 | 982 | #define PAGE_TYPE_OPS(uname, lname, fname) \ |
| 983 | +FOLIO_TYPE_OPS(lname, fname) \ | |
| 981 | 984 | static __always_inline int Page##uname(const struct page *page) \ |
| 982 | 985 | { \ |
| 983 | 986 | return PageType(page, PG_##lname); \ |
| 984 | 987 | } \ |
| 985 | −static __always_inline int folio_test_##fname(const struct folio *folio)\ | |
| 986 | −{ \ | |
| 987 | − return folio_test_type(folio, PG_##lname); \ | |
| 988 | −} \ | |
| 989 | 988 | static __always_inline void __SetPage##uname(struct page *page) \ |
| 990 | 989 | { \ |
| 991 | 990 | VM_BUG_ON_PAGE(!PageType(page, 0), page); \ |
| 992 | 991 | page->page_type &= ~PG_##lname; \ |
| 993 | 992 | } \ |
| 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 | −} \ | |
| 999 | 993 | static __always_inline void __ClearPage##uname(struct page *page) \ |
| 1000 | 994 | { \ |
| 1001 | 995 | VM_BUG_ON_PAGE(!Page##uname(page), page); \ |
| 1002 | 996 | 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 | +} | |
| 1009 | 998 | |
| 1010 | 999 | /* |
| 1011 | 1000 | * PageBuddy() indicates that the page is free and in the buddy system |
| @@ -1052,6 +1041,37 @@ PAGE_TYPE_OPS(Table, table, pgtable) · 40 unmodified lines | ||
| 1052 | 1041 | */ |
| 1053 | 1042 | PAGE_TYPE_OPS(Guard, guard, guard) |
| 1054 | 1043 | |
| 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 | + | |
| 1055 | 1075 | extern bool is_free_buddy_page(struct page *page); |
| 1056 | 1076 | |
| 1057 | 1077 | PAGEFLAG(Isolated, isolated, PF_ANY); |
| @@ -1118,7 +1138,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page) · 60 unmodified lines | ||
| 1118 | 1138 | */ |
| 1119 | 1139 | #define PAGE_FLAGS_SECOND \ |
| 1120 | 1140 | (0xffUL /* order */ | 1UL << PG_has_hwpoisoned | \ |
| 1121 | − 1UL << PG_hugetlb | 1UL << PG_large_rmappable) | |
| 1141 | + 1UL << PG_large_rmappable) | |
| 1122 | 1142 | |
| 1123 | 1143 | #define PAGE_FLAGS_PRIVATE \ |
| 1124 | 1144 | (1UL << PG_private | 1UL << PG_private_2) |