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


Reply via email to