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 | 68 | ppage = pfn_to_online_page(pfn); |
| 69 | 69 | |
| 70 | − if (!ppage || PageSlab(ppage) || page_has_type(ppage)) | |
| 70 | + if (!ppage) | |
| 71 | 71 | pcount = 0; |
| 72 | 72 | else |
| 73 | 73 | pcount = page_mapcount(ppage); |
| @@ -124,11 +124,8 @@ u64 stable_page_flags(struct page *page) · 50 unmodified lines | ||
| 124 | 124 | |
| 125 | 125 | /* |
| 126 | 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 | 129 | u |= 1 << KPF_MMAP; |
| 133 | 130 | if (PageAnon(page)) |
| 134 | 131 | u |= 1 << KPF_ANON; |
| @@ -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) |
| @@ -135,6 +135,7 @@ IF_HAVE_PG_ARCH_X(arch_3) · 134 unmodified lines | ||
| 135 | 135 | #define DEF_PAGETYPE_NAME(_name) { PG_##_name, __stringify(_name) } |
| 136 | 136 | |
| 137 | 137 | #define __def_pagetype_names \ |
| 138 | + DEF_PAGETYPE_NAME(hugetlb), \ | |
| 138 | 139 | DEF_PAGETYPE_NAME(offline), \ |
| 139 | 140 | DEF_PAGETYPE_NAME(guard), \ |
| 140 | 141 | DEF_PAGETYPE_NAME(table), \ |
| @@ -205,11 +205,10 @@ static int __init crash_save_vmcoreinfo_init(void) · 204 unmodified lines | ||
| 205 | 205 | VMCOREINFO_NUMBER(PG_head_mask); |
| 206 | 206 | #define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy) |
| 207 | 207 | VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); |
| 208 | −#ifdef CONFIG_HUGETLB_PAGE | |
| 209 | − VMCOREINFO_NUMBER(PG_hugetlb); | |
| 208 | +#define PAGE_HUGETLB_MAPCOUNT_VALUE (~PG_hugetlb) | |
| 209 | + VMCOREINFO_NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE); | |
| 210 | 210 | #define PAGE_OFFLINE_MAPCOUNT_VALUE (~PG_offline) |
| 211 | 211 | VMCOREINFO_NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE); |
| 212 | −#endif | |
| 213 | 212 | |
| 214 | 213 | #ifdef CONFIG_KALLSYMS |
| 215 | 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 | 628 | * Zero out zone modifiers, as we don't have specific zone |
| 629 | 629 | * requirements. Keep the flags related to allocation in atomic |
| 630 | − * contexts and I/O. | |
| 630 | + * contexts, I/O, nolockdep. | |
| 631 | 631 | */ |
| 632 | 632 | alloc_flags &= ~GFP_ZONEMASK; |
| 633 | − alloc_flags &= (GFP_ATOMIC | GFP_KERNEL); | |
| 633 | + alloc_flags &= (GFP_ATOMIC | GFP_KERNEL | __GFP_NOLOCKDEP); | |
| 634 | 634 | alloc_flags |= __GFP_NOWARN; |
| 635 | 635 | page = alloc_pages(alloc_flags, DEPOT_POOL_ORDER); |
| 636 | 636 | if (page) |
| @@ -1624,7 +1624,7 @@ static inline void __clear_hugetlb_destructor(struct hstate *h, · 1623 unmodified lines | ||
| 1624 | 1624 | { |
| 1625 | 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 | 1711 | h->surplus_huge_pages_node[nid]++; |
| 1712 | 1712 | } |
| 1713 | 1713 | |
| 1714 | − folio_set_hugetlb(folio); | |
| 1714 | + __folio_set_hugetlb(folio); | |
| 1715 | 1715 | folio_change_private(folio, NULL); |
| 1716 | 1716 | /* |
| 1717 | 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 | 1781 | * If vmemmap pages were allocated above, then we need to clear the |
| 1782 | 1782 | * hugetlb destructor under the hugetlb lock. |
| 1783 | 1783 | */ |
| 1784 | − if (clear_dtor) { | |
| 1784 | + if (folio_test_hugetlb(folio)) { | |
| 1785 | 1785 | spin_lock_irq(&hugetlb_lock); |
| 1786 | 1786 | __clear_hugetlb_destructor(h, folio); |
| 1787 | 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 | 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 | 2053 | INIT_LIST_HEAD(&folio->lru); |
| 2054 | 2054 | hugetlb_set_folio_subpool(folio, NULL); |
| 2055 | 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 | 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 | 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 | 3253 | rsv_adjust = hugepage_subpool_put_pages(spool, 1); |
| 3270 | 3254 | hugetlb_acct_memory(h, -rsv_adjust); |
| 3271 | − if (deferred_reserve) | |
| 3255 | + if (deferred_reserve) { | |
| 3256 | + spin_lock_irq(&hugetlb_lock); | |
| 3272 | 3257 | hugetlb_cgroup_uncharge_folio_rsvd(hstate_index(h), |
| 3273 | 3258 | pages_per_huge_page(h), folio); |
| 3259 | + spin_unlock_irq(&hugetlb_lock); | |
| 3260 | + } | |
| 3274 | 3261 | } |
| 3275 | 3262 | |
| 3276 | 3263 | if (!memcg_charge_ret) |
| @@ -6274,6 +6261,12 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm, · 2997 unmodified lines | ||
| 6274 | 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 | 6270 | folio = alloc_hugetlb_folio(vma, haddr, 0); |
| 6278 | 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 | 6304 | restore_reserve_on_error(h, vma, haddr, folio); |
| 6312 | 6305 | folio_put(folio); |
| 6306 | + ret = VM_FAULT_SIGBUS; | |
| 6313 | 6307 | goto out; |
| 6314 | 6308 | } |
| 6315 | 6309 | new_pagecache_folio = true; |
| 6316 | 6310 | } else { |
| 6317 | 6311 | folio_lock(folio); |
| 6318 | − | |
| 6319 | − ret = vmf_anon_prepare(vmf); | |
| 6320 | − if (unlikely(ret)) | |
| 6321 | − goto backout_unlocked; | |
| 6322 | 6312 | anon_rmap = 1; |
| 6323 | 6313 | } |
| 6324 | 6314 | } else { |
| @@ -1331,15 +1331,22 @@ static unsigned long zswap_shrinker_count(struct shrinker *shrinker, · 1330 unmodified lines | ||
| 1331 | 1331 | if (!gfp_has_io_fs(sc->gfp_mask)) |
| 1332 | 1332 | return 0; |
| 1333 | 1333 | |
| 1334 | −#ifdef CONFIG_MEMCG_KMEM | |
| 1335 | − mem_cgroup_flush_stats(memcg); | |
| 1336 | − nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT; | |
| 1337 | − nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED); | |
| 1338 | −#else | |
| 1339 | − /* use pool stats instead of memcg stats */ | |
| 1340 | − nr_backing = zswap_pool_total_size >> PAGE_SHIFT; | |
| 1341 | − nr_stored = atomic_read(&zswap_nr_stored); | |
| 1342 | −#endif | |
| 1334 | + /* | |
| 1335 | + * For memcg, use the cgroup-wide ZSWAP stats since we don't | |
| 1336 | + * have them per-node and thus per-lruvec. Careful if memcg is | |
| 1337 | + * runtime-disabled: we can get sc->memcg == NULL, which is ok | |
| 1338 | + * for the lruvec, but not for memcg_page_state(). | |
| 1339 | + * | |
| 1340 | + * Without memcg, use the zswap pool-wide metrics. | |
| 1341 | + */ | |
| 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 | 1351 | if (!nr_stored) |
| 1345 | 1352 | return 0; |
| @@ -56,7 +56,6 @@ · 55 unmodified lines | ||
| 56 | 56 | #include <asm/types.h> |
| 57 | 57 | #include <ctype.h> |
| 58 | 58 | #include <errno.h> |
| 59 | −#include <limits.h> | |
| 60 | 59 | #include <stdbool.h> |
| 61 | 60 | #include <stdint.h> |
| 62 | 61 | #include <stdio.h> |
| @@ -1159,7 +1158,7 @@ void __run_test(struct __fixture_metadata *f, · 1096 unmodified lines | ||
| 1159 | 1158 | struct __test_metadata *t) |
| 1160 | 1159 | { |
| 1161 | 1160 | struct __test_xfail *xfail; |
| 1162 | − char test_name[LINE_MAX]; | |
| 1161 | + char *test_name; | |
| 1163 | 1162 | const char *diagnostic; |
| 1164 | 1163 | |
| 1165 | 1164 | /* reset test struct */ |
| @@ -1167,8 +1166,12 @@ void __run_test(struct __fixture_metadata *f, · 1 unmodified line | ||
| 1167 | 1166 | t->trigger = 0; |
| 1168 | 1167 | memset(t->results->reason, 0, sizeof(t->results->reason)); |
| 1169 | 1168 | |
| 1170 | − snprintf(test_name, sizeof(test_name), "%s%s%s.%s", | |
| 1171 | − f->name, variant->name[0] ? "." : "", variant->name, t->name); | |
| 1169 | + if (asprintf(&test_name, "%s%s%s.%s", f->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 | 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 | 1210 | ksft_test_result_code(t->exit_code, test_name, |
| 1208 | 1211 | diagnostic ? "%s" : NULL, diagnostic); |
| 1212 | + free(test_name); | |
| 1209 | 1213 | } |
| 1210 | 1214 | |
| 1211 | 1215 | static int test_harness_run(int argc, char **argv) |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/mman.h> |
| 8 | 8 | #include <linux/prctl.h> |
| 9 | 9 | |
| 10 | +#define _GNU_SOURCE | |
| 10 | 11 | #include <stdio.h> |
| 11 | 12 | #include <stdlib.h> |
| 12 | 13 | #include <sys/auxv.h> |
| @@ -54,7 +54,6 @@ int test_nr; · 53 unmodified lines | ||
| 54 | 54 | u64 shadow_pkey_reg; |
| 55 | 55 | int dprint_in_signal; |
| 56 | 56 | char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE]; |
| 57 | −char buf[256]; | |
| 58 | 57 | |
| 59 | 58 | void cat_into_file(char *str, char *file) |
| 60 | 59 | { |
| @@ -1745,42 +1744,6 @@ void pkey_setup_shadow(void) · 1684 unmodified lines | ||
| 1745 | 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 | 1747 | int main(void) |
| 1785 | 1748 | { |
| 1786 | 1749 | int nr_iterations = 22; |
| @@ -1788,7 +1751,6 @@ int main(void) · 1 unmodified line | ||
| 1788 | 1751 | |
| 1789 | 1752 | srand((unsigned int)time(NULL)); |
| 1790 | 1753 | |
| 1791 | − save_settings(); | |
| 1792 | 1754 | setup_handlers(); |
| 1793 | 1755 | |
| 1794 | 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 | 385 | CATEGORY="ksm" run_test ./ksm_functional_tests |
| 386 | 386 | |
| 387 | 387 | # protection_keys tests |
| 388 | +nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages) | |
| 388 | 389 | if [ -x ./protection_keys_32 ] |
| 389 | 390 | then |
| 390 | 391 | CATEGORY="pkey" run_test ./protection_keys_32 |
| @@ -394,6 +395,7 @@ if [ -x ./protection_keys_64 ] · 3 unmodified lines | ||
| 394 | 395 | then |
| 395 | 396 | CATEGORY="pkey" run_test ./protection_keys_64 |
| 396 | 397 | fi |
| 398 | +echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages | |
| 397 | 399 | |
| 398 | 400 | if [ -x ./soft-dirty ] |
| 399 | 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 | 300 | char **addr) |
| 301 | 301 | { |
| 302 | 302 | size_t i; |
| 303 | − int dummy; | |
| 303 | + int __attribute__((unused)) dummy = 0; | |
| 304 | 304 | |
| 305 | 305 | srand(time(NULL)); |
| 306 | 306 | |