git: ce4ece145cec - stable/15 - vm_page: Fix the error path in vm_page_alloc_contig_domain()

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 01 Oct 2026 15:20:25 UTC
The branch stable/15 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=ce4ece145cec5f38ee0c91f05e82a414eb1aa1ba

commit ce4ece145cec5f38ee0c91f05e82a414eb1aa1ba
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-09-24 15:49:37 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-10-01 13:42:31 +0000

    vm_page: Fix the error path in vm_page_alloc_contig_domain()
    
    If we are inserting a run of pages into a VM object and fail at some
    point due to a memory allocation failure, we have to free all of the
    pages in the run.  We do that by resetting some fields and calling
    vm_page_free_toq() on each page; this removes the page from the object
    and frees it back to the buddy allocator.
    
    If the page is supposed to be wired, we reset the reference count, but
    this was done incorrectly: the VPRC_OBJREF flag must be retained as the
    page still belongs to an object.  Resetting it to zero will cause a
    panic in vm_page_free_prep(): vm_page_free_object_prep() will subtract
    VPRC_OBJREF from the refcount, causing underflow, and
    vm_page_free_prep() subsequently calls panic() if the refcount is
    non-zero.
    
    Reviewed by:    alc, kib
    Fixes:          fee2a2fa3983 ("Change synchonization rules for vm_page reference counting.")
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D59908
    
    (cherry picked from commit 742e58ddc989563f90a1d636cb29793641784ca1)
---
 sys/vm/vm_page.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index ce5748bd5f33..2f47cb7a3104 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -2417,7 +2417,7 @@ vm_page_alloc_contig_domain(vm_object_t object, vm_pindex_t pindex, int domain,
 			for (m = m_ret; m < &m_ret[npages]; m++) {
 				if (m <= mpred &&
 				    (req & VM_ALLOC_WIRED) != 0)
-					m->ref_count = 0;
+					m->ref_count = VPRC_OBJREF;
 				m->oflags = VPO_UNMANAGED;
 				m->busy_lock = VPB_UNBUSIED;
 				/* Don't change PG_ZERO. */