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
Unified · Split
| @@ -67,7 +67,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf, · 66 unmodified lines | |||
| 67 | */ | 67 | */ |
| 68 | ppage = pfn_to_online_page(pfn); | 68 | ppage = pfn_to_online_page(pfn); |
| 69 | 69 | ||
| 70 | if (!ppage || PageSlab(ppage) || page_has_type(ppage)) | 70 | if (!ppage) |
| 71 | pcount = 0; | 71 | pcount = 0; |
| 72 | else | 72 | else |
| 73 | pcount = page_mapcount(ppage); | 73 | pcount = page_mapcount(ppage); |
| @@ -124,11 +124,8 @@ u64 stable_page_flags(struct page *page) · 50 unmodified lines | |||
| 124 | 124 | ||
| 125 | /* | 125 | /* |
| 126 | * pseudo flags for the well known (anonymous) memory mapped pages | 126 | * pseudo flags for the well known (anonymous) memory mapped pages |
| 127 | * | ||
| 128 | * Note that page->_mapcount is overloaded in SLAB, so the | ||
| 129 | * simple test in page_mapped() is not enough. | ||
| 130 | */ | 127 | */ |
| 131 | if (!PageSlab(page) && page_mapped(page)) | 128 | if (page_mapped(page)) |
| 132 | u |= 1 << KPF_MMAP; | 129 | u |= 1 << KPF_MMAP; |
| 133 | if (PageAnon(page)) | 130 | if (PageAnon(page)) |
| 134 | u |= 1 << KPF_ANON; | 131 | u |= 1 << KPF_ANON; |
| @@ -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) |
| @@ -135,6 +135,7 @@ IF_HAVE_PG_ARCH_X(arch_3) · 134 unmodified lines | |||
| 135 | #define DEF_PAGETYPE_NAME(_name) { PG_##_name, __stringify(_name) } | 135 | #define DEF_PAGETYPE_NAME(_name) { PG_##_name, __stringify(_name) } |
| 136 | 136 | ||
| 137 | #define __def_pagetype_names \ | 137 | #define __def_pagetype_names \ |
| 138 | DEF_PAGETYPE_NAME(hugetlb), \ | ||
| 138 | DEF_PAGETYPE_NAME(offline), \ | 139 | DEF_PAGETYPE_NAME(offline), \ |
| 139 | DEF_PAGETYPE_NAME(guard), \ | 140 | DEF_PAGETYPE_NAME(guard), \ |
| 140 | DEF_PAGETYPE_NAME(table), \ | 141 | DEF_PAGETYPE_NAME(table), \ |
| @@ -205,11 +205,10 @@ static int __init crash_save_vmcoreinfo_init(void) · 204 unmodified lines | |||
| 205 | VMCOREINFO_NUMBER(PG_head_mask); | 205 | VMCOREINFO_NUMBER(PG_head_mask); |
| 206 | #define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy) | 206 | #define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy) |
| 207 | VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); | 207 | VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); |
| 208 | #ifdef CONFIG_HUGETLB_PAGE | 208 | #define PAGE_HUGETLB_MAPCOUNT_VALUE (~PG_hugetlb) |
| 209 | VMCOREINFO_NUMBER(PG_hugetlb); | 209 | VMCOREINFO_NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE); |
| 210 | #define PAGE_OFFLINE_MAPCOUNT_VALUE (~PG_offline) | 210 | #define PAGE_OFFLINE_MAPCOUNT_VALUE (~PG_offline) |
| 211 | VMCOREINFO_NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE); | 211 | VMCOREINFO_NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE); |
| 212 | #endif | ||
| 213 | 212 | ||
| 214 | #ifdef CONFIG_KALLSYMS | 213 | #ifdef CONFIG_KALLSYMS |
| 215 | VMCOREINFO_SYMBOL(kallsyms_names); | 214 | VMCOREINFO_SYMBOL(kallsyms_names); |
| @@ -627,10 +627,10 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries, · 626 unmodified lines | |||
| 627 | /* | 627 | /* |
| 628 | * Zero out zone modifiers, as we don't have specific zone | 628 | * Zero out zone modifiers, as we don't have specific zone |
| 629 | * requirements. Keep the flags related to allocation in atomic | 629 | * requirements. Keep the flags related to allocation in atomic |
| 630 | * contexts and I/O. | 630 | * contexts, I/O, nolockdep. |
| 631 | */ | 631 | */ |
| 632 | alloc_flags &= ~GFP_ZONEMASK; | 632 | alloc_flags &= ~GFP_ZONEMASK; |
| 633 | alloc_flags &= (GFP_ATOMIC | GFP_KERNEL); | 633 | alloc_flags &= (GFP_ATOMIC | GFP_KERNEL | __GFP_NOLOCKDEP); |
| 634 | alloc_flags |= __GFP_NOWARN; | 634 | alloc_flags |= __GFP_NOWARN; |
| 635 | page = alloc_pages(alloc_flags, DEPOT_POOL_ORDER); | 635 | page = alloc_pages(alloc_flags, DEPOT_POOL_ORDER); |
| 636 | if (page) | 636 | if (page) |
| @@ -1624,7 +1624,7 @@ static inline void __clear_hugetlb_destructor(struct hstate *h, · 1623 unmodified lines | |||
| 1624 | { | 1624 | { |
| 1625 | lockdep_assert_held(&hugetlb_lock); | 1625 | lockdep_assert_held(&hugetlb_lock); |
| 1626 | 1626 | ||
| 1627 | folio_clear_hugetlb(folio); | 1627 | __folio_clear_hugetlb(folio); |
| 1628 | } | 1628 | } |
| 1629 | 1629 | ||
| 1630 | /* | 1630 | /* |
| @@ -1711,7 +1711,7 @@ static void add_hugetlb_folio(struct hstate *h, struct folio *folio, · 80 unmodified lines | |||
| 1711 | h->surplus_huge_pages_node[nid]++; | 1711 | h->surplus_huge_pages_node[nid]++; |
| 1712 | } | 1712 | } |
| 1713 | 1713 | ||
| 1714 | folio_set_hugetlb(folio); | 1714 | __folio_set_hugetlb(folio); |
| 1715 | folio_change_private(folio, NULL); | 1715 | folio_change_private(folio, NULL); |
| 1716 | /* | 1716 | /* |
| 1717 | * We have to set hugetlb_vmemmap_optimized again as above | 1717 | * We have to set hugetlb_vmemmap_optimized again as above |
| @@ -1781,7 +1781,7 @@ static void __update_and_free_hugetlb_folio(struct hstate *h, · 63 unmodified lines | |||
| 1781 | * If vmemmap pages were allocated above, then we need to clear the | 1781 | * If vmemmap pages were allocated above, then we need to clear the |
| 1782 | * hugetlb destructor under the hugetlb lock. | 1782 | * hugetlb destructor under the hugetlb lock. |
| 1783 | */ | 1783 | */ |
| 1784 | if (clear_dtor) { | 1784 | if (folio_test_hugetlb(folio)) { |
| 1785 | spin_lock_irq(&hugetlb_lock); | 1785 | spin_lock_irq(&hugetlb_lock); |
| 1786 | __clear_hugetlb_destructor(h, folio); | 1786 | __clear_hugetlb_destructor(h, folio); |
| 1787 | spin_unlock_irq(&hugetlb_lock); | 1787 | spin_unlock_irq(&hugetlb_lock); |
| @@ -2049,7 +2049,7 @@ static void __prep_account_new_huge_page(struct hstate *h, int nid) · 261 unmodified lines | |||
| 2049 | 2049 | ||
| 2050 | static void init_new_hugetlb_folio(struct hstate *h, struct folio *folio) | 2050 | static void init_new_hugetlb_folio(struct hstate *h, struct folio *folio) |
| 2051 | { | 2051 | { |
| 2052 | folio_set_hugetlb(folio); | 2052 | __folio_set_hugetlb(folio); |
| 2053 | INIT_LIST_HEAD(&folio->lru); | 2053 | INIT_LIST_HEAD(&folio->lru); |
| 2054 | hugetlb_set_folio_subpool(folio, NULL); | 2054 | hugetlb_set_folio_subpool(folio, NULL); |
| 2055 | set_hugetlb_cgroup(folio, NULL); | 2055 | set_hugetlb_cgroup(folio, NULL); |
| @@ -2159,22 +2159,6 @@ static bool prep_compound_gigantic_folio_for_demote(struct folio *folio, · 103 unmodified lines | |||
| 2159 | return __prep_compound_gigantic_folio(folio, order, true); | 2159 | return __prep_compound_gigantic_folio(folio, order, true); |
| 2160 | } | 2160 | } |
| 2161 | 2161 | ||
| 2162 | /* | ||
| 2163 | * PageHuge() only returns true for hugetlbfs pages, but not for normal or | ||
| 2164 | * transparent huge pages. See the PageTransHuge() documentation for more | ||
| 2165 | * details. | ||
| 2166 | */ | ||
| 2167 | int PageHuge(const struct page *page) | ||
| 2168 | { | ||
| 2169 | const struct folio *folio; | ||
| 2170 | |||
| 2171 | if (!PageCompound(page)) | ||
| 2172 | return 0; | ||
| 2173 | folio = page_folio(page); | ||
| 2174 | return folio_test_hugetlb(folio); | ||
| 2175 | } | ||
| 2176 | EXPORT_SYMBOL_GPL(PageHuge); | ||
| 2177 | |||
| 2178 | /* | 2162 | /* |
| 2179 | * Find and lock address space (mapping) in write mode. | 2163 | * Find and lock address space (mapping) in write mode. |
| 2180 | * | 2164 | * |
| @@ -3268,9 +3252,12 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma, · 1087 unmodified lines | |||
| 3268 | 3252 | ||
| 3269 | rsv_adjust = hugepage_subpool_put_pages(spool, 1); | 3253 | rsv_adjust = hugepage_subpool_put_pages(spool, 1); |
| 3270 | hugetlb_acct_memory(h, -rsv_adjust); | 3254 | hugetlb_acct_memory(h, -rsv_adjust); |
| 3271 | if (deferred_reserve) | 3255 | if (deferred_reserve) { |
| 3256 | spin_lock_irq(&hugetlb_lock); | ||
| 3272 | hugetlb_cgroup_uncharge_folio_rsvd(hstate_index(h), | 3257 | hugetlb_cgroup_uncharge_folio_rsvd(hstate_index(h), |
| 3273 | pages_per_huge_page(h), folio); | 3258 | pages_per_huge_page(h), folio); |
| 3259 | spin_unlock_irq(&hugetlb_lock); | ||
| 3260 | } | ||
| 3274 | } | 3261 | } |
| 3275 | 3262 | ||
| 3276 | if (!memcg_charge_ret) | 3263 | if (!memcg_charge_ret) |
| @@ -6274,6 +6261,12 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm, · 2997 unmodified lines | |||
| 6274 | VM_UFFD_MISSING); | 6261 | VM_UFFD_MISSING); |
| 6275 | } | 6262 | } |
| 6276 | 6263 | ||
| 6264 | if (!(vma->vm_flags & VM_MAYSHARE)) { | ||
| 6265 | ret = vmf_anon_prepare(vmf); | ||
| 6266 | if (unlikely(ret)) | ||
| 6267 | goto out; | ||
| 6268 | } | ||
| 6269 | |||
| 6277 | folio = alloc_hugetlb_folio(vma, haddr, 0); | 6270 | folio = alloc_hugetlb_folio(vma, haddr, 0); |
| 6278 | if (IS_ERR(folio)) { | 6271 | if (IS_ERR(folio)) { |
| 6279 | /* | 6272 | /* |
| @@ -6310,15 +6303,12 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm, · 30 unmodified lines | |||
| 6310 | */ | 6303 | */ |
| 6311 | restore_reserve_on_error(h, vma, haddr, folio); | 6304 | restore_reserve_on_error(h, vma, haddr, folio); |
| 6312 | folio_put(folio); | 6305 | folio_put(folio); |
| 6306 | ret = VM_FAULT_SIGBUS; | ||
| 6313 | goto out; | 6307 | goto out; |
| 6314 | } | 6308 | } |
| 6315 | new_pagecache_folio = true; | 6309 | new_pagecache_folio = true; |
| 6316 | } else { | 6310 | } else { |
| 6317 | folio_lock(folio); | 6311 | folio_lock(folio); |
| 6318 | |||
| 6319 | ret = vmf_anon_prepare(vmf); | ||
| 6320 | if (unlikely(ret)) | ||
| 6321 | goto backout_unlocked; | ||
| 6322 | anon_rmap = 1; | 6312 | anon_rmap = 1; |
| 6323 | } | 6313 | } |
| 6324 | } else { | 6314 | } else { |
| @@ -1331,15 +1331,22 @@ static unsigned long zswap_shrinker_count(struct shrinker *shrinker, · 1330 unmodified lines | |||
| 1331 | if (!gfp_has_io_fs(sc->gfp_mask)) | 1331 | if (!gfp_has_io_fs(sc->gfp_mask)) |
| 1332 | return 0; | 1332 | return 0; |
| 1333 | 1333 | ||
| 1334 | #ifdef CONFIG_MEMCG_KMEM | 1334 | /* |
| 1335 | mem_cgroup_flush_stats(memcg); | 1335 | * For memcg, use the cgroup-wide ZSWAP stats since we don't |
| 1336 | nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT; | 1336 | * have them per-node and thus per-lruvec. Careful if memcg is |
| 1337 | nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED); | 1337 | * runtime-disabled: we can get sc->memcg == NULL, which is ok |
| 1338 | #else | 1338 | * for the lruvec, but not for memcg_page_state(). |
| 1339 | /* use pool stats instead of memcg stats */ | 1339 | * |
| 1340 | nr_backing = zswap_pool_total_size >> PAGE_SHIFT; | 1340 | * Without memcg, use the zswap pool-wide metrics. |
| 1341 | nr_stored = atomic_read(&zswap_nr_stored); | 1341 | */ |
| 1342 | #endif | 1342 | if (!mem_cgroup_disabled()) { |
| 1343 | mem_cgroup_flush_stats(memcg); | ||
| 1344 | nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT; | ||
| 1345 | nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED); | ||
| 1346 | } else { | ||
| 1347 | nr_backing = zswap_pool_total_size >> PAGE_SHIFT; | ||
| 1348 | nr_stored = atomic_read(&zswap_nr_stored); | ||
| 1349 | } | ||
| 1343 | 1350 | ||
| 1344 | if (!nr_stored) | 1351 | if (!nr_stored) |
| 1345 | return 0; | 1352 | return 0; |
| @@ -56,7 +56,6 @@ · 55 unmodified lines | |||
| 56 | #include <asm/types.h> | 56 | #include <asm/types.h> |
| 57 | #include <ctype.h> | 57 | #include <ctype.h> |
| 58 | #include <errno.h> | 58 | #include <errno.h> |
| 59 | #include <limits.h> | ||
| 60 | #include <stdbool.h> | 59 | #include <stdbool.h> |
| 61 | #include <stdint.h> | 60 | #include <stdint.h> |
| 62 | #include <stdio.h> | 61 | #include <stdio.h> |
| @@ -1159,7 +1158,7 @@ void __run_test(struct __fixture_metadata *f, · 1096 unmodified lines | |||
| 1159 | struct __test_metadata *t) | 1158 | struct __test_metadata *t) |
| 1160 | { | 1159 | { |
| 1161 | struct __test_xfail *xfail; | 1160 | struct __test_xfail *xfail; |
| 1162 | char test_name[LINE_MAX]; | 1161 | char *test_name; |
| 1163 | const char *diagnostic; | 1162 | const char *diagnostic; |
| 1164 | 1163 | ||
| 1165 | /* reset test struct */ | 1164 | /* reset test struct */ |
| @@ -1167,8 +1166,12 @@ void __run_test(struct __fixture_metadata *f, · 1 unmodified line | |||
| 1167 | t->trigger = 0; | 1166 | t->trigger = 0; |
| 1168 | memset(t->results->reason, 0, sizeof(t->results->reason)); | 1167 | memset(t->results->reason, 0, sizeof(t->results->reason)); |
| 1169 | 1168 | ||
| 1170 | snprintf(test_name, sizeof(test_name), "%s%s%s.%s", | 1169 | if (asprintf(&test_name, "%s%s%s.%s", f->name, |
| 1171 | f->name, variant->name[0] ? "." : "", variant->name, t->name); | 1170 | variant->name[0] ? "." : "", variant->name, t->name) == -1) { |
| 1171 | ksft_print_msg("ERROR ALLOCATING MEMORY\n"); | ||
| 1172 | t->exit_code = KSFT_FAIL; | ||
| 1173 | _exit(t->exit_code); | ||
| 1174 | } | ||
| 1172 | 1175 | ||
| 1173 | ksft_print_msg(" RUN %s ...\n", test_name); | 1176 | ksft_print_msg(" RUN %s ...\n", test_name); |
| 1174 | 1177 | ||
| @@ -1206,6 +1209,7 @@ void __run_test(struct __fixture_metadata *f, · 31 unmodified lines | |||
| 1206 | 1209 | ||
| 1207 | ksft_test_result_code(t->exit_code, test_name, | 1210 | ksft_test_result_code(t->exit_code, test_name, |
| 1208 | diagnostic ? "%s" : NULL, diagnostic); | 1211 | diagnostic ? "%s" : NULL, diagnostic); |
| 1212 | free(test_name); | ||
| 1209 | } | 1213 | } |
| 1210 | 1214 | ||
| 1211 | static int test_harness_run(int argc, char **argv) | 1215 | static int test_harness_run(int argc, char **argv) |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/mman.h> | 7 | #include <linux/mman.h> |
| 8 | #include <linux/prctl.h> | 8 | #include <linux/prctl.h> |
| 9 | 9 | ||
| 10 | #define _GNU_SOURCE | ||
| 10 | #include <stdio.h> | 11 | #include <stdio.h> |
| 11 | #include <stdlib.h> | 12 | #include <stdlib.h> |
| 12 | #include <sys/auxv.h> | 13 | #include <sys/auxv.h> |
| @@ -54,7 +54,6 @@ int test_nr; · 53 unmodified lines | |||
| 54 | u64 shadow_pkey_reg; | 54 | u64 shadow_pkey_reg; |
| 55 | int dprint_in_signal; | 55 | int dprint_in_signal; |
| 56 | char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE]; | 56 | char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE]; |
| 57 | char buf[256]; | ||
| 58 | 57 | ||
| 59 | void cat_into_file(char *str, char *file) | 58 | void cat_into_file(char *str, char *file) |
| 60 | { | 59 | { |
| @@ -1745,42 +1744,6 @@ void pkey_setup_shadow(void) · 1684 unmodified lines | |||
| 1745 | shadow_pkey_reg = __read_pkey_reg(); | 1744 | shadow_pkey_reg = __read_pkey_reg(); |
| 1746 | } | 1745 | } |
| 1747 | 1746 | ||
| 1748 | pid_t parent_pid; | ||
| 1749 | |||
| 1750 | void restore_settings_atexit(void) | ||
| 1751 | { | ||
| 1752 | if (parent_pid == getpid()) | ||
| 1753 | cat_into_file(buf, "/proc/sys/vm/nr_hugepages"); | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | void save_settings(void) | ||
| 1757 | { | ||
| 1758 | int fd; | ||
| 1759 | int err; | ||
| 1760 | |||
| 1761 | if (geteuid()) | ||
| 1762 | return; | ||
| 1763 | |||
| 1764 | fd = open("/proc/sys/vm/nr_hugepages", O_RDONLY); | ||
| 1765 | if (fd < 0) { | ||
| 1766 | fprintf(stderr, "error opening\n"); | ||
| 1767 | perror("error: "); | ||
| 1768 | exit(__LINE__); | ||
| 1769 | } | ||
| 1770 | |||
| 1771 | /* -1 to guarantee leaving the trailing \0 */ | ||
| 1772 | err = read(fd, buf, sizeof(buf)-1); | ||
| 1773 | if (err < 0) { | ||
| 1774 | fprintf(stderr, "error reading\n"); | ||
| 1775 | perror("error: "); | ||
| 1776 | exit(__LINE__); | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | parent_pid = getpid(); | ||
| 1780 | atexit(restore_settings_atexit); | ||
| 1781 | close(fd); | ||
| 1782 | } | ||
| 1783 | |||
| 1784 | int main(void) | 1747 | int main(void) |
| 1785 | { | 1748 | { |
| 1786 | int nr_iterations = 22; | 1749 | int nr_iterations = 22; |
| @@ -1788,7 +1751,6 @@ int main(void) · 1 unmodified line | |||
| 1788 | 1751 | ||
| 1789 | srand((unsigned int)time(NULL)); | 1752 | srand((unsigned int)time(NULL)); |
| 1790 | 1753 | ||
| 1791 | save_settings(); | ||
| 1792 | setup_handlers(); | 1754 | setup_handlers(); |
| 1793 | 1755 | ||
| 1794 | printf("has pkeys: %d\n", pkeys_supported); | 1756 | printf("has pkeys: %d\n", pkeys_supported); |
| @@ -385,6 +385,7 @@ CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 0 · 384 unmodified lines | |||
| 385 | CATEGORY="ksm" run_test ./ksm_functional_tests | 385 | CATEGORY="ksm" run_test ./ksm_functional_tests |
| 386 | 386 | ||
| 387 | # protection_keys tests | 387 | # protection_keys tests |
| 388 | nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages) | ||
| 388 | if [ -x ./protection_keys_32 ] | 389 | if [ -x ./protection_keys_32 ] |
| 389 | then | 390 | then |
| 390 | CATEGORY="pkey" run_test ./protection_keys_32 | 391 | CATEGORY="pkey" run_test ./protection_keys_32 |
| @@ -394,6 +395,7 @@ if [ -x ./protection_keys_64 ] · 3 unmodified lines | |||
| 394 | then | 395 | then |
| 395 | CATEGORY="pkey" run_test ./protection_keys_64 | 396 | CATEGORY="pkey" run_test ./protection_keys_64 |
| 396 | fi | 397 | fi |
| 398 | echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages | ||
| 397 | 399 | ||
| 398 | if [ -x ./soft-dirty ] | 400 | if [ -x ./soft-dirty ] |
| 399 | then | 401 | then |
| @@ -300,7 +300,7 @@ int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd, · 299 unmodified lines | |||
| 300 | char **addr) | 300 | char **addr) |
| 301 | { | 301 | { |
| 302 | size_t i; | 302 | size_t i; |
| 303 | int dummy; | 303 | int __attribute__((unused)) dummy = 0; |
| 304 | 304 | ||
| 305 | srand(time(NULL)); | 305 | srand(time(NULL)); |
| 306 | 306 | ||