Merge misc fixes from Andrew Morton: "10 patches. Subsystems affected by this patch series: ipc, MAINTAINERS, and mm (vmscan, debug, pagemap, kmemleak, and selftests)" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: kselftest/vm: revert "tools/testing/selftests/vm/userfaultfd.c: use swap() to make code cleaner" MAINTAINERS: update rppt's email mm/kmemleak: avoid scanning potential huge holes ipc/sem: do not sleep with a spin lock held mm/pgtable: define pte_index so that preprocessor could recognize it mm/page_table_check: check entries at pmd levels mm/khugepaged: unify collapse pmd clear, flush and free mm/page_table_check: use unsigned long for page counters and cleanup mm/debug_vm_pgtable: remove pte entry from the page table Revert "mm/page_isolation: unset migratetype directly for non Buddy page"
Unified · Split
| @@ -12399,7 +12399,7 @@ F: include/uapi/linux/membarrier.h · 12398 unmodified lines | ||
| 12399 | 12399 | F: kernel/sched/membarrier.c |
| 12400 | 12400 | |
| 12401 | 12401 | MEMBLOCK |
| 12402 | −M: Mike Rapoport <rppt@linux.ibm.com> | |
| 12402 | +M: Mike Rapoport <rppt@kernel.org> | |
| 12403 | 12403 | L: linux-mm@kvack.org |
| 12404 | 12404 | S: Maintained |
| 12405 | 12405 | F: Documentation/core-api/boot-time-mm.rst |
| @@ -26,6 +26,9 @@ void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr, · 25 unmodified lines | ||
| 26 | 26 | pmd_t *pmdp, pmd_t pmd); |
| 27 | 27 | void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, |
| 28 | 28 | pud_t *pudp, pud_t pud); |
| 29 | +void __page_table_check_pte_clear_range(struct mm_struct *mm, | |
| 30 | + unsigned long addr, | |
| 31 | + pmd_t pmd); | |
| 29 | 32 | |
| 30 | 33 | static inline void page_table_check_alloc(struct page *page, unsigned int order) |
| 31 | 34 | { |
| @@ -100,6 +103,16 @@ static inline void page_table_check_pud_set(struct mm_struct *mm, · 68 unmodified lines | ||
| 100 | 103 | __page_table_check_pud_set(mm, addr, pudp, pud); |
| 101 | 104 | } |
| 102 | 105 | |
| 106 | +static inline void page_table_check_pte_clear_range(struct mm_struct *mm, | |
| 107 | + unsigned long addr, | |
| 108 | + pmd_t pmd) | |
| 109 | +{ | |
| 110 | + if (static_branch_likely(&page_table_check_disabled)) | |
| 111 | + return; | |
| 112 | + | |
| 113 | + __page_table_check_pte_clear_range(mm, addr, pmd); | |
| 114 | +} | |
| 115 | + | |
| 103 | 116 | #else |
| 104 | 117 | |
| 105 | 118 | static inline void page_table_check_alloc(struct page *page, unsigned int order) |
| @@ -143,5 +156,11 @@ static inline void page_table_check_pud_set(struct mm_struct *mm, · 37 unmodified lines | ||
| 143 | 156 | { |
| 144 | 157 | } |
| 145 | 158 | |
| 159 | +static inline void page_table_check_pte_clear_range(struct mm_struct *mm, | |
| 160 | + unsigned long addr, | |
| 161 | + pmd_t pmd) | |
| 162 | +{ | |
| 163 | +} | |
| 164 | + | |
| 146 | 165 | #endif /* CONFIG_PAGE_TABLE_CHECK */ |
| 147 | 166 | #endif /* __LINUX_PAGE_TABLE_CHECK_H */ |
| @@ -62,6 +62,7 @@ static inline unsigned long pte_index(unsigned long address) · 61 unmodified lines | ||
| 62 | 62 | { |
| 63 | 63 | return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); |
| 64 | 64 | } |
| 65 | +#define pte_index pte_index | |
| 65 | 66 | |
| 66 | 67 | #ifndef pmd_index |
| 67 | 68 | static inline unsigned long pmd_index(unsigned long address) |
| @@ -1964,6 +1964,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) · 1963 unmodified lines | ||
| 1964 | 1964 | */ |
| 1965 | 1965 | un = lookup_undo(ulp, semid); |
| 1966 | 1966 | if (un) { |
| 1967 | + spin_unlock(&ulp->lock); | |
| 1967 | 1968 | kvfree(new); |
| 1968 | 1969 | goto success; |
| 1969 | 1970 | } |
| @@ -1976,9 +1977,8 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) · 6 unmodified lines | ||
| 1976 | 1977 | ipc_assert_locked_object(&sma->sem_perm); |
| 1977 | 1978 | list_add(&new->list_id, &sma->list_id); |
| 1978 | 1979 | un = new; |
| 1979 | − | |
| 1980 | −success: | |
| 1981 | 1980 | spin_unlock(&ulp->lock); |
| 1981 | +success: | |
| 1982 | 1982 | sem_unlock(sma, -1); |
| 1983 | 1983 | out: |
| 1984 | 1984 | return un; |
| @@ -171,6 +171,8 @@ static void __init pte_advanced_tests(struct pgtable_debug_args *args) · 170 unmodified lines | ||
| 171 | 171 | ptep_test_and_clear_young(args->vma, args->vaddr, args->ptep); |
| 172 | 172 | pte = ptep_get(args->ptep); |
| 173 | 173 | WARN_ON(pte_young(pte)); |
| 174 | + | |
| 175 | + ptep_get_and_clear_full(args->mm, args->vaddr, args->ptep, 1); | |
| 174 | 176 | } |
| 175 | 177 | |
| 176 | 178 | static void __init pte_savedwrite_tests(struct pgtable_debug_args *args) |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/hashtable.h> |
| 17 | 17 | #include <linux/userfaultfd_k.h> |
| 18 | 18 | #include <linux/page_idle.h> |
| 19 | +#include <linux/page_table_check.h> | |
| 19 | 20 | #include <linux/swapops.h> |
| 20 | 21 | #include <linux/shmem_fs.h> |
| 21 | 22 | |
| @@ -1416,6 +1417,21 @@ static int khugepaged_add_pte_mapped_thp(struct mm_struct *mm, · 1394 unmodified lines | ||
| 1416 | 1417 | return 0; |
| 1417 | 1418 | } |
| 1418 | 1419 | |
| 1420 | +static void collapse_and_free_pmd(struct mm_struct *mm, struct vm_area_struct *vma, | |
| 1421 | + unsigned long addr, pmd_t *pmdp) | |
| 1422 | +{ | |
| 1423 | + spinlock_t *ptl; | |
| 1424 | + pmd_t pmd; | |
| 1425 | + | |
| 1426 | + mmap_assert_write_locked(mm); | |
| 1427 | + ptl = pmd_lock(vma->vm_mm, pmdp); | |
| 1428 | + pmd = pmdp_collapse_flush(vma, addr, pmdp); | |
| 1429 | + spin_unlock(ptl); | |
| 1430 | + mm_dec_nr_ptes(mm); | |
| 1431 | + page_table_check_pte_clear_range(mm, addr, pmd); | |
| 1432 | + pte_free(mm, pmd_pgtable(pmd)); | |
| 1433 | +} | |
| 1434 | + | |
| 1419 | 1435 | /** |
| 1420 | 1436 | * collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at |
| 1421 | 1437 | * address haddr. |
| @@ -1433,7 +1449,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr) · 11 unmodified lines | ||
| 1433 | 1449 | struct vm_area_struct *vma = find_vma(mm, haddr); |
| 1434 | 1450 | struct page *hpage; |
| 1435 | 1451 | pte_t *start_pte, *pte; |
| 1436 | − pmd_t *pmd, _pmd; | |
| 1452 | + pmd_t *pmd; | |
| 1437 | 1453 | spinlock_t *ptl; |
| 1438 | 1454 | int count = 0; |
| 1439 | 1455 | int i; |
| @@ -1509,12 +1525,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr) · 69 unmodified lines | ||
| 1509 | 1525 | } |
| 1510 | 1526 | |
| 1511 | 1527 | /* step 4: collapse pmd */ |
| 1512 | − ptl = pmd_lock(vma->vm_mm, pmd); | |
| 1513 | − _pmd = pmdp_collapse_flush(vma, haddr, pmd); | |
| 1514 | − spin_unlock(ptl); | |
| 1515 | − mm_dec_nr_ptes(mm); | |
| 1516 | − pte_free(mm, pmd_pgtable(_pmd)); | |
| 1517 | − | |
| 1528 | + collapse_and_free_pmd(mm, vma, haddr, pmd); | |
| 1518 | 1529 | drop_hpage: |
| 1519 | 1530 | unlock_page(hpage); |
| 1520 | 1531 | put_page(hpage); |
| @@ -1552,7 +1563,7 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) · 31 unmodified lines | ||
| 1552 | 1563 | struct vm_area_struct *vma; |
| 1553 | 1564 | struct mm_struct *mm; |
| 1554 | 1565 | unsigned long addr; |
| 1555 | − pmd_t *pmd, _pmd; | |
| 1566 | + pmd_t *pmd; | |
| 1556 | 1567 | |
| 1557 | 1568 | i_mmap_lock_write(mapping); |
| 1558 | 1569 | vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) { |
| @@ -1591,14 +1602,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) · 32 unmodified lines | ||
| 1591 | 1602 | * reverse order. Trylock is a way to avoid deadlock. |
| 1592 | 1603 | */ |
| 1593 | 1604 | if (mmap_write_trylock(mm)) { |
| 1594 | − if (!khugepaged_test_exit(mm)) { | |
| 1595 | − spinlock_t *ptl = pmd_lock(mm, pmd); | |
| 1596 | − /* assume page table is clear */ | |
| 1597 | − _pmd = pmdp_collapse_flush(vma, addr, pmd); | |
| 1598 | − spin_unlock(ptl); | |
| 1599 | − mm_dec_nr_ptes(mm); | |
| 1600 | − pte_free(mm, pmd_pgtable(_pmd)); | |
| 1601 | − } | |
| 1605 | + if (!khugepaged_test_exit(mm)) | |
| 1606 | + collapse_and_free_pmd(mm, vma, addr, pmd); | |
| 1602 | 1607 | mmap_write_unlock(mm); |
| 1603 | 1608 | } else { |
| 1604 | 1609 | /* Try again later */ |
| @@ -1410,7 +1410,8 @@ static void kmemleak_scan(void) · 1409 unmodified lines | ||
| 1410 | 1410 | { |
| 1411 | 1411 | unsigned long flags; |
| 1412 | 1412 | struct kmemleak_object *object; |
| 1413 | − int i; | |
| 1413 | + struct zone *zone; | |
| 1414 | + int __maybe_unused i; | |
| 1414 | 1415 | int new_leaks = 0; |
| 1415 | 1416 | |
| 1416 | 1417 | jiffies_last_scan = jiffies; |
| @@ -1450,9 +1451,9 @@ static void kmemleak_scan(void) · 33 unmodified lines | ||
| 1450 | 1451 | * Struct page scanning for each node. |
| 1451 | 1452 | */ |
| 1452 | 1453 | get_online_mems(); |
| 1453 | − for_each_online_node(i) { | |
| 1454 | − unsigned long start_pfn = node_start_pfn(i); | |
| 1455 | − unsigned long end_pfn = node_end_pfn(i); | |
| 1454 | + for_each_populated_zone(zone) { | |
| 1455 | + unsigned long start_pfn = zone->zone_start_pfn; | |
| 1456 | + unsigned long end_pfn = zone_end_pfn(zone); | |
| 1456 | 1457 | unsigned long pfn; |
| 1457 | 1458 | |
| 1458 | 1459 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { |
| @@ -1461,8 +1462,8 @@ static void kmemleak_scan(void) · 2 unmodified lines | ||
| 1461 | 1462 | if (!page) |
| 1462 | 1463 | continue; |
| 1463 | 1464 | |
| 1464 | − /* only scan pages belonging to this node */ | |
| 1465 | − if (page_to_nid(page) != i) | |
| 1465 | + /* only scan pages belonging to this zone */ | |
| 1466 | + if (page_zone(page) != zone) | |
| 1466 | 1467 | continue; |
| 1467 | 1468 | /* only scan if page is in use */ |
| 1468 | 1469 | if (page_count(page) == 0) |
| @@ -115,7 +115,7 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype) · 114 unmodified lines | ||
| 115 | 115 | * onlining - just onlined memory won't immediately be considered for |
| 116 | 116 | * allocation. |
| 117 | 117 | */ |
| 118 | − if (!isolated_page && PageBuddy(page)) { | |
| 118 | + if (!isolated_page) { | |
| 119 | 119 | nr_pages = move_freepages_block(zone, page, migratetype, NULL); |
| 120 | 120 | __mod_zone_freepage_state(zone, nr_pages, migratetype); |
| 121 | 121 | } |
| @@ -86,8 +86,8 @@ static void page_table_check_clear(struct mm_struct *mm, unsigned long addr, · 85 unmodified lines | ||
| 86 | 86 | { |
| 87 | 87 | struct page_ext *page_ext; |
| 88 | 88 | struct page *page; |
| 89 | + unsigned long i; | |
| 89 | 90 | bool anon; |
| 90 | − int i; | |
| 91 | 91 | |
| 92 | 92 | if (!pfn_valid(pfn)) |
| 93 | 93 | return; |
| @@ -121,8 +121,8 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr, · 27 unmodified lines | ||
| 121 | 121 | { |
| 122 | 122 | struct page_ext *page_ext; |
| 123 | 123 | struct page *page; |
| 124 | + unsigned long i; | |
| 124 | 125 | bool anon; |
| 125 | − int i; | |
| 126 | 126 | |
| 127 | 127 | if (!pfn_valid(pfn)) |
| 128 | 128 | return; |
| @@ -152,10 +152,10 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr, · 23 unmodified lines | ||
| 152 | 152 | void __page_table_check_zero(struct page *page, unsigned int order) |
| 153 | 153 | { |
| 154 | 154 | struct page_ext *page_ext = lookup_page_ext(page); |
| 155 | − int i; | |
| 155 | + unsigned long i; | |
| 156 | 156 | |
| 157 | 157 | BUG_ON(!page_ext); |
| 158 | − for (i = 0; i < (1 << order); i++) { | |
| 158 | + for (i = 0; i < (1ul << order); i++) { | |
| 159 | 159 | struct page_table_check *ptc = get_page_table_check(page_ext); |
| 160 | 160 | |
| 161 | 161 | BUG_ON(atomic_read(&ptc->anon_map_count)); |
| @@ -206,17 +206,10 @@ EXPORT_SYMBOL(__page_table_check_pud_clear); · 44 unmodified lines | ||
| 206 | 206 | void __page_table_check_pte_set(struct mm_struct *mm, unsigned long addr, |
| 207 | 207 | pte_t *ptep, pte_t pte) |
| 208 | 208 | { |
| 209 | − pte_t old_pte; | |
| 210 | − | |
| 211 | 209 | if (&init_mm == mm) |
| 212 | 210 | return; |
| 213 | 211 | |
| 214 | − old_pte = *ptep; | |
| 215 | − if (pte_user_accessible_page(old_pte)) { | |
| 216 | − page_table_check_clear(mm, addr, pte_pfn(old_pte), | |
| 217 | − PAGE_SIZE >> PAGE_SHIFT); | |
| 218 | − } | |
| 219 | − | |
| 212 | + __page_table_check_pte_clear(mm, addr, *ptep); | |
| 220 | 213 | if (pte_user_accessible_page(pte)) { |
| 221 | 214 | page_table_check_set(mm, addr, pte_pfn(pte), |
| 222 | 215 | PAGE_SIZE >> PAGE_SHIFT, |
| @@ -228,17 +221,10 @@ EXPORT_SYMBOL(__page_table_check_pte_set); · 5 unmodified lines | ||
| 228 | 221 | void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr, |
| 229 | 222 | pmd_t *pmdp, pmd_t pmd) |
| 230 | 223 | { |
| 231 | − pmd_t old_pmd; | |
| 232 | − | |
| 233 | 224 | if (&init_mm == mm) |
| 234 | 225 | return; |
| 235 | 226 | |
| 236 | − old_pmd = *pmdp; | |
| 237 | − if (pmd_user_accessible_page(old_pmd)) { | |
| 238 | − page_table_check_clear(mm, addr, pmd_pfn(old_pmd), | |
| 239 | − PMD_PAGE_SIZE >> PAGE_SHIFT); | |
| 240 | − } | |
| 241 | − | |
| 227 | + __page_table_check_pmd_clear(mm, addr, *pmdp); | |
| 242 | 228 | if (pmd_user_accessible_page(pmd)) { |
| 243 | 229 | page_table_check_set(mm, addr, pmd_pfn(pmd), |
| 244 | 230 | PMD_PAGE_SIZE >> PAGE_SHIFT, |
| @@ -250,17 +236,10 @@ EXPORT_SYMBOL(__page_table_check_pmd_set); · 5 unmodified lines | ||
| 250 | 236 | void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, |
| 251 | 237 | pud_t *pudp, pud_t pud) |
| 252 | 238 | { |
| 253 | − pud_t old_pud; | |
| 254 | − | |
| 255 | 239 | if (&init_mm == mm) |
| 256 | 240 | return; |
| 257 | 241 | |
| 258 | − old_pud = *pudp; | |
| 259 | − if (pud_user_accessible_page(old_pud)) { | |
| 260 | − page_table_check_clear(mm, addr, pud_pfn(old_pud), | |
| 261 | − PUD_PAGE_SIZE >> PAGE_SHIFT); | |
| 262 | − } | |
| 263 | − | |
| 242 | + __page_table_check_pud_clear(mm, addr, *pudp); | |
| 264 | 243 | if (pud_user_accessible_page(pud)) { |
| 265 | 244 | page_table_check_set(mm, addr, pud_pfn(pud), |
| 266 | 245 | PUD_PAGE_SIZE >> PAGE_SHIFT, |
| @@ -268,3 +247,23 @@ void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr, · 1 unmodified line | ||
| 268 | 247 | } |
| 269 | 248 | } |
| 270 | 249 | EXPORT_SYMBOL(__page_table_check_pud_set); |
| 250 | + | |
| 251 | +void __page_table_check_pte_clear_range(struct mm_struct *mm, | |
| 252 | + unsigned long addr, | |
| 253 | + pmd_t pmd) | |
| 254 | +{ | |
| 255 | + if (&init_mm == mm) | |
| 256 | + return; | |
| 257 | + | |
| 258 | + if (!pmd_bad(pmd) && !pmd_leaf(pmd)) { | |
| 259 | + pte_t *ptep = pte_offset_map(&pmd, addr); | |
| 260 | + unsigned long i; | |
| 261 | + | |
| 262 | + pte_unmap(ptep); | |
| 263 | + for (i = 0; i < PTRS_PER_PTE; i++) { | |
| 264 | + __page_table_check_pte_clear(mm, addr, *ptep); | |
| 265 | + addr += PAGE_SIZE; | |
| 266 | + ptep++; | |
| 267 | + } | |
| 268 | + } | |
| 269 | +} | |
| @@ -1417,6 +1417,7 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize) · 1416 unmodified lines | ||
| 1417 | 1417 | static int userfaultfd_stress(void) |
| 1418 | 1418 | { |
| 1419 | 1419 | void *area; |
| 1420 | + char *tmp_area; | |
| 1420 | 1421 | unsigned long nr; |
| 1421 | 1422 | struct uffdio_register uffdio_register; |
| 1422 | 1423 | struct uffd_stats uffd_stats[nr_cpus]; |
| @@ -1527,9 +1528,13 @@ static int userfaultfd_stress(void) · 104 unmodified lines | ||
| 1527 | 1528 | count_verify[nr], nr); |
| 1528 | 1529 | |
| 1529 | 1530 | /* prepare next bounce */ |
| 1530 | − swap(area_src, area_dst); | |
| 1531 | + tmp_area = area_src; | |
| 1532 | + area_src = area_dst; | |
| 1533 | + area_dst = tmp_area; | |
| 1531 | 1534 | |
| 1532 | − swap(area_src_alias, area_dst_alias); | |
| 1535 | + tmp_area = area_src_alias; | |
| 1536 | + area_src_alias = area_dst_alias; | |
| 1537 | + area_dst_alias = tmp_area; | |
| 1533 | 1538 | |
| 1534 | 1539 | uffd_stats_report(uffd_stats, nr_cpus); |
| 1535 | 1540 | } |