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 | * a large folio, it includes the number of times this page is mapped | 1223 | * a large folio, it includes the number of times this page is mapped |
| 1224 | * as part of that folio. | 1224 | * as part of that folio. |
| 1225 | * | 1225 | * |
| 1226 | * The result is undefined for pages which cannot be mapped into userspace. | 1226 | * Will report 0 for pages which cannot be mapped into userspace, eg |
| 1227 | * For example SLAB or special types of pages. See function page_has_type(). | 1227 | * slab, page tables and similar. |
| 1228 | * They use this field in struct page differently. | ||
| 1229 | */ | 1228 | */ |
| 1230 | static inline int page_mapcount(struct page *page) | 1229 | static inline int page_mapcount(struct page *page) |
| 1231 | { | 1230 | { |
| 1232 | int mapcount = atomic_read(&page->_mapcount) + 1; | 1231 | int mapcount = atomic_read(&page->_mapcount) + 1; |
| 1233 | 1232 | ||
| 1233 | /* Handle page_has_type() pages */ | ||
| 1234 | if (mapcount < 0) | ||
| 1235 | mapcount = 0; | ||
| 1234 | if (unlikely(PageCompound(page))) | 1236 | if (unlikely(PageCompound(page))) |
| 1235 | mapcount += folio_entire_mapcount(page_folio(page)); | 1237 | mapcount += folio_entire_mapcount(page_folio(page)); |
| 1236 | 1238 | ||
| @@ -190,7 +190,6 @@ enum pageflags { · 189 unmodified lines | |||
| 190 | 190 | ||
| 191 | /* At least one page in this folio has the hwpoison flag set */ | 191 | /* At least one page in this folio has the hwpoison flag set */ |
| 192 | PG_has_hwpoisoned = PG_error, | 192 | PG_has_hwpoisoned = PG_error, |
| 193 | PG_hugetlb = PG_active, | ||
| 194 | PG_large_rmappable = PG_workingset, /* anon or file-backed */ | 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 | TESTSETFLAG(uname, lname, policy) \ | 457 | TESTSETFLAG(uname, lname, policy) \ |
| 459 | TESTCLEARFLAG(uname, lname, policy) | 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 | #define TESTPAGEFLAG_FALSE(uname, lname) \ | 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 | static inline int Page##uname(const struct page *page) { return 0; } | 485 | static inline int Page##uname(const struct page *page) { return 0; } |
| 464 | 486 | ||
| 465 | #define SETPAGEFLAG_NOOP(uname, lname) \ | 487 | #define SETPAGEFLAG_NOOP(uname, lname) \ |
| 466 | static inline void folio_set_##lname(struct folio *folio) { } \ | 488 | FOLIO_SET_FLAG_NOOP(lname) \ |
| 467 | static inline void SetPage##uname(struct page *page) { } | 489 | static inline void SetPage##uname(struct page *page) { } |
| 468 | 490 | ||
| 469 | #define CLEARPAGEFLAG_NOOP(uname, lname) \ | 491 | #define CLEARPAGEFLAG_NOOP(uname, lname) \ |
| 470 | static inline void folio_clear_##lname(struct folio *folio) { } \ | 492 | FOLIO_CLEAR_FLAG_NOOP(lname) \ |
| 471 | static inline void ClearPage##uname(struct page *page) { } | 493 | static inline void ClearPage##uname(struct page *page) { } |
| 472 | 494 | ||
| 473 | #define __CLEARPAGEFLAG_NOOP(uname, lname) \ | 495 | #define __CLEARPAGEFLAG_NOOP(uname, lname) \ |
| 474 | static inline void __folio_clear_##lname(struct folio *folio) { } \ | 496 | __FOLIO_CLEAR_FLAG_NOOP(lname) \ |
| 475 | static inline void __ClearPage##uname(struct page *page) { } | 497 | static inline void __ClearPage##uname(struct page *page) { } |
| 476 | 498 | ||
| 477 | #define TESTSETFLAG_FALSE(uname, lname) \ | 499 | #define TESTSETFLAG_FALSE(uname, lname) \ |
| 478 | static inline bool folio_test_set_##lname(struct folio *folio) \ | 500 | FOLIO_TEST_SET_FLAG_FALSE(lname) \ |
| 479 | { return 0; } \ | ||
| 480 | static inline int TestSetPage##uname(struct page *page) { return 0; } | 501 | static inline int TestSetPage##uname(struct page *page) { return 0; } |
| 481 | 502 | ||
| 482 | #define TESTCLEARFLAG_FALSE(uname, lname) \ | 503 | #define TESTCLEARFLAG_FALSE(uname, lname) \ |
| 483 | static inline bool folio_test_clear_##lname(struct folio *folio) \ | 504 | FOLIO_TEST_CLEAR_FLAG_FALSE(lname) \ |
| 484 | { return 0; } \ | ||
| 485 | static inline int TestClearPage##uname(struct page *page) { return 0; } | 505 | static inline int TestClearPage##uname(struct page *page) { return 0; } |
| 486 | 506 | ||
| 487 | #define PAGEFLAG_FALSE(uname, lname) TESTPAGEFLAG_FALSE(uname, lname) \ | 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 | #define PG_head_mask ((1UL << PG_head)) | 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 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 878 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 882 | /* | 879 | /* |
| 883 | * PageHuge() only returns true for hugetlbfs pages, but not for | 880 | * PageHuge() only returns true for hugetlbfs pages, but not for |
| @@ -933,34 +930,23 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned) · 49 unmodified lines | |||
| 933 | TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned) | 930 | TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned) |
| 934 | #endif | 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 | * For pages that are never mapped to userspace (and aren't PageSlab), | 934 | * For pages that are never mapped to userspace (and aren't PageSlab), |
| 950 | * page_type may be used. Because it is initialised to -1, we invert the | 935 | * page_type may be used. Because it is initialised to -1, we invert the |
| 951 | * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and | 936 | * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and |
| 952 | * __ClearPageFoo *sets* the bit used for PageFoo. We reserve a few high and | 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 | * mistaken for a page type value. | 939 | * mistaken for a page type value. |
| 955 | */ | 940 | */ |
| 956 | 941 | ||
| 957 | #define PAGE_TYPE_BASE 0xf0000000 | 942 | #define PAGE_TYPE_BASE 0xf0000000 |
| 958 | /* Reserve 0x0000007f to catch underflows of page_mapcount */ | 943 | /* Reserve 0x0000007f to catch underflows of _mapcount */ |
| 959 | #define PAGE_MAPCOUNT_RESERVE -128 | 944 | #define PAGE_MAPCOUNT_RESERVE -128 |
| 960 | #define PG_buddy 0x00000080 | 945 | #define PG_buddy 0x00000080 |
| 961 | #define PG_offline 0x00000100 | 946 | #define PG_offline 0x00000100 |
| 962 | #define PG_table 0x00000200 | 947 | #define PG_table 0x00000200 |
| 963 | #define PG_guard 0x00000400 | 948 | #define PG_guard 0x00000400 |
| 949 | #define PG_hugetlb 0x00000800 | ||
| 964 | 950 | ||
| 965 | #define PageType(page, flag) \ | 951 | #define PageType(page, flag) \ |
| 966 | ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE) | 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 | return page_type_has_type(page->page_type); | 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 | #define PAGE_TYPE_OPS(uname, lname, fname) \ | 982 | #define PAGE_TYPE_OPS(uname, lname, fname) \ |
| 983 | FOLIO_TYPE_OPS(lname, fname) \ | ||
| 981 | static __always_inline int Page##uname(const struct page *page) \ | 984 | static __always_inline int Page##uname(const struct page *page) \ |
| 982 | { \ | 985 | { \ |
| 983 | return PageType(page, PG_##lname); \ | 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 | static __always_inline void __SetPage##uname(struct page *page) \ | 988 | static __always_inline void __SetPage##uname(struct page *page) \ |
| 990 | { \ | 989 | { \ |
| 991 | VM_BUG_ON_PAGE(!PageType(page, 0), page); \ | 990 | VM_BUG_ON_PAGE(!PageType(page, 0), page); \ |
| 992 | page->page_type &= ~PG_##lname; \ | 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 | static __always_inline void __ClearPage##uname(struct page *page) \ | 993 | static __always_inline void __ClearPage##uname(struct page *page) \ |
| 1000 | { \ | 994 | { \ |
| 1001 | VM_BUG_ON_PAGE(!Page##uname(page), page); \ | 995 | VM_BUG_ON_PAGE(!Page##uname(page), page); \ |
| 1002 | page->page_type |= PG_##lname; \ | 996 | page->page_type |= PG_##lname; \ |
| 1003 | } \ | 997 | } |
| 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 | } \ | ||
| 1009 | 998 | ||
| 1010 | /* | 999 | /* |
| 1011 | * PageBuddy() indicates that the page is free and in the buddy system | 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 | PAGE_TYPE_OPS(Guard, guard, guard) | 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 | extern bool is_free_buddy_page(struct page *page); | 1075 | extern bool is_free_buddy_page(struct page *page); |
| 1056 | 1076 | ||
| 1057 | PAGEFLAG(Isolated, isolated, PF_ANY); | 1077 | PAGEFLAG(Isolated, isolated, PF_ANY); |
| @@ -1118,7 +1138,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page) · 60 unmodified lines | |||
| 1118 | */ | 1138 | */ |
| 1119 | #define PAGE_FLAGS_SECOND \ | 1139 | #define PAGE_FLAGS_SECOND \ |
| 1120 | (0xffUL /* order */ | 1UL << PG_has_hwpoisoned | \ | 1140 | (0xffUL /* order */ | 1UL << PG_has_hwpoisoned | \ |
| 1121 | 1UL << PG_hugetlb | 1UL << PG_large_rmappable) | 1141 | 1UL << PG_large_rmappable) |
| 1122 | 1142 | ||
| 1123 | #define PAGE_FLAGS_PRIVATE \ | 1143 | #define PAGE_FLAGS_PRIVATE \ |
| 1124 | (1UL << PG_private | 1UL << PG_private_2) | 1144 | (1UL << PG_private | 1UL << PG_private_2) |