From 6220694c52a5a04102b48109e4f24e958b559bd3 Mon Sep 17 00:00:00 2001 From: Hou Tao Date: Sat, 20 Dec 2025 12:04:34 +0800 Subject: [PATCH 1/3] PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails When vm_insert_page() fails in p2pmem_alloc_mmap(), p2pmem_alloc_mmap() doesn't invoke percpu_ref_put() to free the per-CPU ref of pgmap acquired after gen_pool_alloc_owner(), and memunmap_pages() will hang forever when trying to remove the PCI device. Fix it by adding the missed percpu_ref_put(). Fixes: 7e9c7ef83d78 ("PCI/P2PDMA: Allow userspace VMA allocations through sysfs") Signed-off-by: Hou Tao Signed-off-by: Bjorn Helgaas Reviewed-by: Logan Gunthorpe Reviewed-by: Alistair Popple Link: https://patch.msgid.link/20251220040446.274991-2-houtao@huaweicloud.com --- drivers/pci/p2pdma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index 4a2fc7ab42c3..218c1f5252b6 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -152,6 +152,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj, ret = vm_insert_page(vma, vaddr, page); if (ret) { gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len); + percpu_ref_put(ref); return ret; } percpu_ref_get(ref); From cb500023a75246f60b79af9f7321d6e75330c5b5 Mon Sep 17 00:00:00 2001 From: Hou Tao Date: Sat, 20 Dec 2025 12:04:35 +0800 Subject: [PATCH 2/3] PCI/P2PDMA: Fix p2pmem_alloc_mmap() warning condition Commit b7e282378773 has already changed the initial page refcount of p2pdma page from one to zero, however, in p2pmem_alloc_mmap() it uses "VM_WARN_ON_ONCE_PAGE(!page_ref_count(page))" to assert the initial page refcount should not be zero and the following will be reported when CONFIG_DEBUG_VM is enabled: page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x380400000 flags: 0x20000000002000(reserved|node=0|zone=4) raw: 0020000000002000 ff1100015e3ab440 0000000000000000 0000000000000000 raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: VM_WARN_ON_ONCE_PAGE(!page_ref_count(page)) ------------[ cut here ]------------ WARNING: CPU: 5 PID: 449 at drivers/pci/p2pdma.c:240 p2pmem_alloc_mmap+0x83a/0xa60 Fix by using "page_ref_count(page)" as the assertion condition. Fixes: b7e282378773 ("mm/mm_init: move p2pdma page refcount initialisation to p2pdma") Signed-off-by: Hou Tao Signed-off-by: Bjorn Helgaas Reviewed-by: Logan Gunthorpe Reviewed-by: Alistair Popple Link: https://patch.msgid.link/20251220040446.274991-3-houtao@huaweicloud.com --- drivers/pci/p2pdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index 218c1f5252b6..dd64ec830fdd 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -147,7 +147,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj, * we have just allocated the page no one else should be * using it. */ - VM_WARN_ON_ONCE_PAGE(!page_ref_count(page), page); + VM_WARN_ON_ONCE_PAGE(page_ref_count(page), page); set_page_count(page, 1); ret = vm_insert_page(vma, vaddr, page); if (ret) { From 83014d82a1100abc89f7712ad67c3e5accaddc43 Mon Sep 17 00:00:00 2001 From: Alistair Popple Date: Mon, 12 Jan 2026 11:54:40 +1100 Subject: [PATCH 3/3] PCI/P2PDMA: Reset page reference count when page mapping fails When mapping a p2pdma page the page reference count is initialised to 1 prior to calling vm_insert_page(). This is to avoid vm_insert_page() warning if the page refcount is zero. Prior to setting the page count there is a check to ensure the page is currently free (ie. has a zero reference count). However vm_insert_page() can fail. In this case the pages are freed back to the genalloc pool, but that does not reset the page refcount. So a future allocation of the same page will see the elevated page refcount from the previous set_page_count() call triggering the VM_WARN_ON_ONCE_PAGE checking that the page is free. Fix this by resetting the page refcount to zero using set_page_count(). Note that put_page() is not used because that would result in freeing the page twice due to implicitly calling p2pdma_folio_free(). Fixes: b7e282378773 ("mm/mm_init: move p2pdma page refcount initialisation to p2pdma") Signed-off-by: Alistair Popple Signed-off-by: Bjorn Helgaas Reviewed-by: Logan Gunthorpe Acked-by: Balbir Singh Link: https://patch.msgid.link/20260112005440.998543-1-apopple@nvidia.com --- drivers/pci/p2pdma.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index dd64ec830fdd..79a414fd6623 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -152,6 +152,13 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj, ret = vm_insert_page(vma, vaddr, page); if (ret) { gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len); + + /* + * Reset the page count. We don't use put_page() + * because we don't want to trigger the + * p2pdma_folio_free() path. + */ + set_page_count(page, 0); percpu_ref_put(ref); return ret; }