The PowerPC radix path takes one reference for every PTE that maps the shared tail page. Unlike the generic path, get_page() lets the counter continue after it becomes non-positive and eventually cycle to zero.
Use try_get_page() so vmemmap population fails before the shared page reference count can cycle, matching the generic implementation. Signed-off-by: Muchun Song <[email protected]> --- arch/powerpc/mm/book3s64/radix_pgtable.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index 9ca28e4a610a..a3332f32ffb2 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -1042,13 +1042,17 @@ static pte_t * __meminit radix__vmemmap_pte_populate(pmd_t *pmdp, unsigned long /* * When a PTE/PMD entry is freed from the init_mm * there's a free_pages() call to this page allocated - * above. Thus this get_page() is paired with the + * above. Thus this try_get_page() is paired with the * put_page_testzero() on the freeing path. * This can only called by certain ZONE_DEVICE path, * and through vmemmap_populate_compound_pages() when * slab is available. + * + * Use try_get_page() to prevent the shared page refcount + * from overflowing. */ - get_page(reuse); + if (!try_get_page(reuse)) + return NULL; p = page_to_virt(reuse); pr_debug("Tail page reuse vmemmap mapping\n"); } -- 2.54.0
