Skip to content

Commit

Permalink
Merge branch 'akpm' (patches from Andrew)
Browse files Browse the repository at this point in the history
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 <[email protected]>:
  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"
  • Loading branch information
torvalds committed Feb 4, 2022
2 parents cff7f22 + 07d2505 commit f9aaa5b
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 56 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -12399,7 +12399,7 @@ F: include/uapi/linux/membarrier.h
F: kernel/sched/membarrier.c

MEMBLOCK
M: Mike Rapoport <rppt@linux.ibm.com>
M: Mike Rapoport <rppt@kernel.org>
L: [email protected]
S: Maintained
F: Documentation/core-api/boot-time-mm.rst
Expand Down
19 changes: 19 additions & 0 deletions include/linux/page_table_check.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr,
pmd_t *pmdp, pmd_t pmd);
void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr,
pud_t *pudp, pud_t pud);
void __page_table_check_pte_clear_range(struct mm_struct *mm,
unsigned long addr,
pmd_t pmd);

static inline void page_table_check_alloc(struct page *page, unsigned int order)
{
Expand Down Expand Up @@ -100,6 +103,16 @@ static inline void page_table_check_pud_set(struct mm_struct *mm,
__page_table_check_pud_set(mm, addr, pudp, pud);
}

static inline void page_table_check_pte_clear_range(struct mm_struct *mm,
unsigned long addr,
pmd_t pmd)
{
if (static_branch_likely(&page_table_check_disabled))
return;

__page_table_check_pte_clear_range(mm, addr, pmd);
}

#else

static inline void page_table_check_alloc(struct page *page, unsigned int order)
Expand Down Expand Up @@ -143,5 +156,11 @@ static inline void page_table_check_pud_set(struct mm_struct *mm,
{
}

static inline void page_table_check_pte_clear_range(struct mm_struct *mm,
unsigned long addr,
pmd_t pmd)
{
}

#endif /* CONFIG_PAGE_TABLE_CHECK */
#endif /* __LINUX_PAGE_TABLE_CHECK_H */
1 change: 1 addition & 0 deletions include/linux/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ static inline unsigned long pte_index(unsigned long address)
{
return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
}
#define pte_index pte_index

#ifndef pmd_index
static inline unsigned long pmd_index(unsigned long address)
Expand Down
4 changes: 2 additions & 2 deletions ipc/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1964,6 +1964,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
*/
un = lookup_undo(ulp, semid);
if (un) {
spin_unlock(&ulp->lock);
kvfree(new);
goto success;
}
Expand All @@ -1976,9 +1977,8 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
ipc_assert_locked_object(&sma->sem_perm);
list_add(&new->list_id, &sma->list_id);
un = new;

success:
spin_unlock(&ulp->lock);
success:
sem_unlock(sma, -1);
out:
return un;
Expand Down
2 changes: 2 additions & 0 deletions mm/debug_vm_pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ static void __init pte_advanced_tests(struct pgtable_debug_args *args)
ptep_test_and_clear_young(args->vma, args->vaddr, args->ptep);
pte = ptep_get(args->ptep);
WARN_ON(pte_young(pte));

ptep_get_and_clear_full(args->mm, args->vaddr, args->ptep, 1);
}

static void __init pte_savedwrite_tests(struct pgtable_debug_args *args)
Expand Down
37 changes: 21 additions & 16 deletions mm/khugepaged.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/hashtable.h>
#include <linux/userfaultfd_k.h>
#include <linux/page_idle.h>
#include <linux/page_table_check.h>
#include <linux/swapops.h>
#include <linux/shmem_fs.h>

Expand Down Expand Up @@ -1416,6 +1417,21 @@ static int khugepaged_add_pte_mapped_thp(struct mm_struct *mm,
return 0;
}

static void collapse_and_free_pmd(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long addr, pmd_t *pmdp)
{
spinlock_t *ptl;
pmd_t pmd;

mmap_assert_write_locked(mm);
ptl = pmd_lock(vma->vm_mm, pmdp);
pmd = pmdp_collapse_flush(vma, addr, pmdp);
spin_unlock(ptl);
mm_dec_nr_ptes(mm);
page_table_check_pte_clear_range(mm, addr, pmd);
pte_free(mm, pmd_pgtable(pmd));
}

/**
* collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at
* address haddr.
Expand All @@ -1433,7 +1449,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr)
struct vm_area_struct *vma = find_vma(mm, haddr);
struct page *hpage;
pte_t *start_pte, *pte;
pmd_t *pmd, _pmd;
pmd_t *pmd;
spinlock_t *ptl;
int count = 0;
int i;
Expand Down Expand Up @@ -1509,12 +1525,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr)
}

/* step 4: collapse pmd */
ptl = pmd_lock(vma->vm_mm, pmd);
_pmd = pmdp_collapse_flush(vma, haddr, pmd);
spin_unlock(ptl);
mm_dec_nr_ptes(mm);
pte_free(mm, pmd_pgtable(_pmd));

collapse_and_free_pmd(mm, vma, haddr, pmd);
drop_hpage:
unlock_page(hpage);
put_page(hpage);
Expand Down Expand Up @@ -1552,7 +1563,7 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
struct vm_area_struct *vma;
struct mm_struct *mm;
unsigned long addr;
pmd_t *pmd, _pmd;
pmd_t *pmd;

i_mmap_lock_write(mapping);
vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) {
Expand Down Expand Up @@ -1591,14 +1602,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
* reverse order. Trylock is a way to avoid deadlock.
*/
if (mmap_write_trylock(mm)) {
if (!khugepaged_test_exit(mm)) {
spinlock_t *ptl = pmd_lock(mm, pmd);
/* assume page table is clear */
_pmd = pmdp_collapse_flush(vma, addr, pmd);
spin_unlock(ptl);
mm_dec_nr_ptes(mm);
pte_free(mm, pmd_pgtable(_pmd));
}
if (!khugepaged_test_exit(mm))
collapse_and_free_pmd(mm, vma, addr, pmd);
mmap_write_unlock(mm);
} else {
/* Try again later */
Expand Down
13 changes: 7 additions & 6 deletions mm/kmemleak.c
Original file line number Diff line number Diff line change
Expand Up @@ -1410,7 +1410,8 @@ static void kmemleak_scan(void)
{
unsigned long flags;
struct kmemleak_object *object;
int i;
struct zone *zone;
int __maybe_unused i;
int new_leaks = 0;

jiffies_last_scan = jiffies;
Expand Down Expand Up @@ -1450,9 +1451,9 @@ static void kmemleak_scan(void)
* Struct page scanning for each node.
*/
get_online_mems();
for_each_online_node(i) {
unsigned long start_pfn = node_start_pfn(i);
unsigned long end_pfn = node_end_pfn(i);
for_each_populated_zone(zone) {
unsigned long start_pfn = zone->zone_start_pfn;
unsigned long end_pfn = zone_end_pfn(zone);
unsigned long pfn;

for (pfn = start_pfn; pfn < end_pfn; pfn++) {
Expand All @@ -1461,8 +1462,8 @@ static void kmemleak_scan(void)
if (!page)
continue;

/* only scan pages belonging to this node */
if (page_to_nid(page) != i)
/* only scan pages belonging to this zone */
if (page_zone(page) != zone)
continue;
/* only scan if page is in use */
if (page_count(page) == 0)
Expand Down
2 changes: 1 addition & 1 deletion mm/page_isolation.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype)
* onlining - just onlined memory won't immediately be considered for
* allocation.
*/
if (!isolated_page && PageBuddy(page)) {
if (!isolated_page) {
nr_pages = move_freepages_block(zone, page, migratetype, NULL);
__mod_zone_freepage_state(zone, nr_pages, migratetype);
}
Expand Down
55 changes: 27 additions & 28 deletions mm/page_table_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ static void page_table_check_clear(struct mm_struct *mm, unsigned long addr,
{
struct page_ext *page_ext;
struct page *page;
unsigned long i;
bool anon;
int i;

if (!pfn_valid(pfn))
return;
Expand Down Expand Up @@ -121,8 +121,8 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr,
{
struct page_ext *page_ext;
struct page *page;
unsigned long i;
bool anon;
int i;

if (!pfn_valid(pfn))
return;
Expand Down Expand Up @@ -152,10 +152,10 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr,
void __page_table_check_zero(struct page *page, unsigned int order)
{
struct page_ext *page_ext = lookup_page_ext(page);
int i;
unsigned long i;

BUG_ON(!page_ext);
for (i = 0; i < (1 << order); i++) {
for (i = 0; i < (1ul << order); i++) {
struct page_table_check *ptc = get_page_table_check(page_ext);

BUG_ON(atomic_read(&ptc->anon_map_count));
Expand Down Expand Up @@ -206,17 +206,10 @@ EXPORT_SYMBOL(__page_table_check_pud_clear);
void __page_table_check_pte_set(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte)
{
pte_t old_pte;

if (&init_mm == mm)
return;

old_pte = *ptep;
if (pte_user_accessible_page(old_pte)) {
page_table_check_clear(mm, addr, pte_pfn(old_pte),
PAGE_SIZE >> PAGE_SHIFT);
}

__page_table_check_pte_clear(mm, addr, *ptep);
if (pte_user_accessible_page(pte)) {
page_table_check_set(mm, addr, pte_pfn(pte),
PAGE_SIZE >> PAGE_SHIFT,
Expand All @@ -228,17 +221,10 @@ EXPORT_SYMBOL(__page_table_check_pte_set);
void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr,
pmd_t *pmdp, pmd_t pmd)
{
pmd_t old_pmd;

if (&init_mm == mm)
return;

old_pmd = *pmdp;
if (pmd_user_accessible_page(old_pmd)) {
page_table_check_clear(mm, addr, pmd_pfn(old_pmd),
PMD_PAGE_SIZE >> PAGE_SHIFT);
}

__page_table_check_pmd_clear(mm, addr, *pmdp);
if (pmd_user_accessible_page(pmd)) {
page_table_check_set(mm, addr, pmd_pfn(pmd),
PMD_PAGE_SIZE >> PAGE_SHIFT,
Expand All @@ -250,21 +236,34 @@ EXPORT_SYMBOL(__page_table_check_pmd_set);
void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr,
pud_t *pudp, pud_t pud)
{
pud_t old_pud;

if (&init_mm == mm)
return;

old_pud = *pudp;
if (pud_user_accessible_page(old_pud)) {
page_table_check_clear(mm, addr, pud_pfn(old_pud),
PUD_PAGE_SIZE >> PAGE_SHIFT);
}

__page_table_check_pud_clear(mm, addr, *pudp);
if (pud_user_accessible_page(pud)) {
page_table_check_set(mm, addr, pud_pfn(pud),
PUD_PAGE_SIZE >> PAGE_SHIFT,
pud_write(pud));
}
}
EXPORT_SYMBOL(__page_table_check_pud_set);

void __page_table_check_pte_clear_range(struct mm_struct *mm,
unsigned long addr,
pmd_t pmd)
{
if (&init_mm == mm)
return;

if (!pmd_bad(pmd) && !pmd_leaf(pmd)) {
pte_t *ptep = pte_offset_map(&pmd, addr);
unsigned long i;

pte_unmap(ptep);
for (i = 0; i < PTRS_PER_PTE; i++) {
__page_table_check_pte_clear(mm, addr, *ptep);
addr += PAGE_SIZE;
ptep++;
}
}
}
9 changes: 7 additions & 2 deletions tools/testing/selftests/vm/userfaultfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,7 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize)
static int userfaultfd_stress(void)
{
void *area;
char *tmp_area;
unsigned long nr;
struct uffdio_register uffdio_register;
struct uffd_stats uffd_stats[nr_cpus];
Expand Down Expand Up @@ -1527,9 +1528,13 @@ static int userfaultfd_stress(void)
count_verify[nr], nr);

/* prepare next bounce */
swap(area_src, area_dst);
tmp_area = area_src;
area_src = area_dst;
area_dst = tmp_area;

swap(area_src_alias, area_dst_alias);
tmp_area = area_src_alias;
area_src_alias = area_dst_alias;
area_dst_alias = tmp_area;

uffd_stats_report(uffd_stats, nr_cpus);
}
Expand Down

0 comments on commit f9aaa5b

Please sign in to comment.