Skip to content

Commit 7780d04

Browse files
Hugh Dickinsakpm00
Hugh Dickins
authored andcommitted
mm/pagewalkers: ACTION_AGAIN if pte_offset_map_lock() fails
Simple walk_page_range() users should set ACTION_AGAIN to retry when pte_offset_map_lock() fails. No need to check pmd_trans_unstable(): that was precisely to avoid the possiblity of calling pte_offset_map() on a racily removed or inserted THP entry, but such cases are now safely handled inside it. Likewise there is no need to check pmd_none() or pmd_bad() before calling it. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Hugh Dickins <[email protected]> Reviewed-by: SeongJae Park <[email protected]> for mm/damon part Cc: Alistair Popple <[email protected]> Cc: Anshuman Khandual <[email protected]> Cc: Axel Rasmussen <[email protected]> Cc: Christophe Leroy <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: "Huang, Ying" <[email protected]> Cc: Ira Weiny <[email protected]> Cc: Jason Gunthorpe <[email protected]> Cc: Kirill A. Shutemov <[email protected]> Cc: Lorenzo Stoakes <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Mel Gorman <[email protected]> Cc: Miaohe Lin <[email protected]> Cc: Mike Kravetz <[email protected]> Cc: Mike Rapoport (IBM) <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Naoya Horiguchi <[email protected]> Cc: Pavel Tatashin <[email protected]> Cc: Peter Xu <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Qi Zheng <[email protected]> Cc: Ralph Campbell <[email protected]> Cc: Ryan Roberts <[email protected]> Cc: Song Liu <[email protected]> Cc: Steven Price <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Cc: Thomas Hellström <[email protected]> Cc: Will Deacon <[email protected]> Cc: Yang Shi <[email protected]> Cc: Yu Zhao <[email protected]> Cc: Zack Rusin <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 2798bbe commit 7780d04

File tree

5 files changed

+36
-28
lines changed

5 files changed

+36
-28
lines changed

fs/proc/task_mmu.c

+16-16
Original file line numberDiff line numberDiff line change
@@ -631,14 +631,11 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
631631
goto out;
632632
}
633633

634-
if (pmd_trans_unstable(pmd))
635-
goto out;
636-
/*
637-
* The mmap_lock held all the way back in m_start() is what
638-
* keeps khugepaged out of here and from collapsing things
639-
* in here.
640-
*/
641634
pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
635+
if (!pte) {
636+
walk->action = ACTION_AGAIN;
637+
return 0;
638+
}
642639
for (; addr != end; pte++, addr += PAGE_SIZE)
643640
smaps_pte_entry(pte, addr, walk);
644641
pte_unmap_unlock(pte - 1, ptl);
@@ -1191,10 +1188,11 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
11911188
return 0;
11921189
}
11931190

1194-
if (pmd_trans_unstable(pmd))
1195-
return 0;
1196-
11971191
pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
1192+
if (!pte) {
1193+
walk->action = ACTION_AGAIN;
1194+
return 0;
1195+
}
11981196
for (; addr != end; pte++, addr += PAGE_SIZE) {
11991197
ptent = *pte;
12001198

@@ -1538,16 +1536,17 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,
15381536
spin_unlock(ptl);
15391537
return err;
15401538
}
1541-
1542-
if (pmd_trans_unstable(pmdp))
1543-
return 0;
15441539
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
15451540

15461541
/*
15471542
* We can assume that @vma always points to a valid one and @end never
15481543
* goes beyond vma->vm_end.
15491544
*/
15501545
orig_pte = pte = pte_offset_map_lock(walk->mm, pmdp, addr, &ptl);
1546+
if (!pte) {
1547+
walk->action = ACTION_AGAIN;
1548+
return err;
1549+
}
15511550
for (; addr < end; pte++, addr += PAGE_SIZE) {
15521551
pagemap_entry_t pme;
15531552

@@ -1887,11 +1886,12 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr,
18871886
spin_unlock(ptl);
18881887
return 0;
18891888
}
1890-
1891-
if (pmd_trans_unstable(pmd))
1892-
return 0;
18931889
#endif
18941890
orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
1891+
if (!pte) {
1892+
walk->action = ACTION_AGAIN;
1893+
return 0;
1894+
}
18951895
do {
18961896
struct page *page = can_gather_numa_stats(*pte, vma, addr);
18971897
if (!page)

mm/damon/vaddr.c

+8-4
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,11 @@ static int damon_mkold_pmd_entry(pmd_t *pmd, unsigned long addr,
318318
spin_unlock(ptl);
319319
}
320320

321-
if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
322-
return 0;
323321
pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
322+
if (!pte) {
323+
walk->action = ACTION_AGAIN;
324+
return 0;
325+
}
324326
if (!pte_present(*pte))
325327
goto out;
326328
damon_ptep_mkold(pte, walk->vma, addr);
@@ -464,9 +466,11 @@ static int damon_young_pmd_entry(pmd_t *pmd, unsigned long addr,
464466
regular_page:
465467
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
466468

467-
if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
468-
return -EINVAL;
469469
pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
470+
if (!pte) {
471+
walk->action = ACTION_AGAIN;
472+
return 0;
473+
}
470474
if (!pte_present(*pte))
471475
goto out;
472476
folio = damon_get_folio(pte_pfn(*pte));

mm/mempolicy.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -514,10 +514,11 @@ static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr,
514514
if (ptl)
515515
return queue_folios_pmd(pmd, ptl, addr, end, walk);
516516

517-
if (pmd_trans_unstable(pmd))
518-
return 0;
519-
520517
mapped_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
518+
if (!pte) {
519+
walk->action = ACTION_AGAIN;
520+
return 0;
521+
}
521522
for (; addr != end; pte++, addr += PAGE_SIZE) {
522523
if (!pte_present(*pte))
523524
continue;

mm/mincore.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,11 @@ static int mincore_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
113113
goto out;
114114
}
115115

116-
if (pmd_trans_unstable(pmd)) {
117-
__mincore_unmapped_range(addr, end, vma, vec);
118-
goto out;
119-
}
120-
121116
ptep = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
117+
if (!ptep) {
118+
walk->action = ACTION_AGAIN;
119+
return 0;
120+
}
122121
for (; addr != end; ptep++, addr += PAGE_SIZE) {
123122
pte_t pte = *ptep;
124123

mm/mlock.c

+4
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,10 @@ static int mlock_pte_range(pmd_t *pmd, unsigned long addr,
329329
}
330330

331331
start_pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
332+
if (!start_pte) {
333+
walk->action = ACTION_AGAIN;
334+
return 0;
335+
}
332336
for (pte = start_pte; addr != end; pte++, addr += PAGE_SIZE) {
333337
if (!pte_present(*pte))
334338
continue;

0 commit comments

Comments
 (0)