From jelal.hb.north.de!saturn.hb.north.de!nox@deceased.hb.north.de  Sun May 12 17:07:37 1996
Received: from deceased.hb.north.de (deceased.hb.north.de [194.94.232.249])
          by freefall.freebsd.org (8.7.3/8.7.3) with SMTP id RAA24580
          for <FreeBSD-gnats-submit@freebsd.org>; Sun, 12 May 1996 17:07:34 -0700 (PDT)
Received: from jelal.hb.north.de by deceased.hb.north.de with uucp
	(Smail3.1.29.1) id m0uIl5W-0016I5C; Mon, 13 May 96 02:02 MET DST
Received: by jelal.hb.north.de (SMail-ST 0.95gcc/2.5+)
	id AA00373; Mon, 13 May 1996 01:08:06 +0100 (CET)
Received: (from nox@localhost) by saturn.hb.north.de (8.7.5/8.7.3) id AAA02946; Mon, 13 May 1996 00:20:55 +0200 (MET DST)
Message-Id: <199605122220.AAA02946@saturn.hb.north.de>
Date: Mon, 13 May 1996 00:20:55 +0200 (MET DST)
From: nox@jelal.hb.north.de
Reply-To: nox@jelal.hb.north.de
To: FreeBSD-gnats-submit@freebsd.org
Subject: vm_page_unhold: hold count < 0!!!
X-Send-Pr-Version: 3.2

>Number:         1195
>Category:       kern
>Synopsis:       stable with DIAGNOSTIC panics `vm_page_unhold: hold count < 0'
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    dyson
>State:          closed
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun May 12 17:10:02 PDT 1996
>Closed-Date:    Wed Jun 19 18:56:06 PDT 1996
>Last-Modified:  Wed Jun 19 18:57:34 PDT 1996
>Originator:     Juergen Lock
>Release:        FreeBSD 2.1-STABLE i386
>Organization:
orga-what?
>Environment:

	-stable as of ~a week old, but problem seen since, uh, 2.0?

>Description:

	Every time i make a DIAGNOSTIC kernel and then dump more than
a few MB to tape using afio, i get this.  Then i disable the panic
and everything is well again.  So this itself is not critical but...

>How-To-Repeat:

	(boot DIAGNOSTIC kernel, install afio, mount scratch monk.. errm, tape)

	find /usr/src | afio -G 2 -o -v -f -b 5120 -c 1000 -s 100000x -Z /dev/nrst0

>Fix:
	
	As all the problematic calls seem to come out of vunmapbuf,

Index: i386/i386/vm_machdep.c
@@ -783,8 +783,20 @@
 	/*
 	 * release the data page
 	 */
+#ifdef DIAGNOSTIC
+		vm_page_t foo;
+		pa = pmap_kextract((vm_offset_t) addr);
+		foo = PHYS_TO_VM_PAGE(pa);
+		if (foo->hold_count <= 0) {
+			/* panic in vm_page_unhold -> printf */
+			printf("vunmapbuf: vm_page_unhold: hold count %d <= 0!!!\n", foo->hold_count);
+			foo->hold_count = 1;
+		}
+		vm_page_unhold(foo);
+#else
 		pa = pmap_kextract((vm_offset_t) addr);
 		vm_page_unhold(PHYS_TO_VM_PAGE(pa));
+#endif
 	}
 }
 
now try the write again and you get a console full of these printfs.

 hope it helps...
	Juergen
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->dyson 
Responsible-Changed-By: scrappy 
Responsible-Changed-When: Mon May 27 14:35:36 PDT 1996 
Responsible-Changed-Why:  
more "possibly fixed" PRs due to Mega Commit 

From: David Greenman <davidg@Root.COM>
To: nox@jelal.hb.north.de
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: kern/1195: stable with DIAGNOSTIC panics `vm_page_unhold: hold count < 0'
Date: Tue, 18 Jun 1996 20:54:57 -0700

 >>Description:
 >
 >	Every time i make a DIAGNOSTIC kernel and then dump more than
 >a few MB to tape using afio, i get this.  Then i disable the panic
 >and everything is well again.  So this itself is not critical but...
 >
 >>How-To-Repeat:
 >
 >	(boot DIAGNOSTIC kernel, install afio, mount scratch monk.. errm, tape)
 >
 >	find /usr/src | afio -G 2 -o -v -f -b 5120 -c 1000 -s 100000x -Z /dev/nrst0
 
 
    Please try out the attached patch and see if the problem is fixed.
    Thanks.
 
 -DG
 
 David Greenman
 Core-team/Principal Architect, The FreeBSD Project
 
 Index: vm_machdep.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/i386/i386/vm_machdep.c,v
 retrieving revision 1.39.4.2
 diff -c -r1.39.4.2 vm_machdep.c
 *** vm_machdep.c	1996/01/30 12:56:30	1.39.4.2
 --- vm_machdep.c	1996/06/19 03:35:38
 ***************
 *** 687,710 ****
   vmapbuf(bp)
   	register struct buf *bp;
   {
 ! 	register int npf;
 ! 	register caddr_t addr;
 ! 	int off;
 ! 	vm_offset_t kva;
 ! 	vm_offset_t pa, v;
   
   	if ((bp->b_flags & B_PHYS) == 0)
   		panic("vmapbuf");
   
 ! 	/*
 ! 	 * this is the kva that is to be used for
 ! 	 * the temporary kernel mapping
 ! 	 */
 ! 	kva = (vm_offset_t) bp->b_saveaddr;
 ! 
 ! 	for (addr = (caddr_t)trunc_page(bp->b_data);
   		addr < bp->b_data + bp->b_bufsize;
 ! 		addr += PAGE_SIZE) {
   
   /*
    * do the vm_fault if needed, do the copy-on-write thing when
 --- 687,701 ----
   vmapbuf(bp)
   	register struct buf *bp;
   {
 ! 	register caddr_t addr, v, kva;
 ! 	vm_offset_t pa;
   
   	if ((bp->b_flags & B_PHYS) == 0)
   		panic("vmapbuf");
   
 ! 	for (v = bp->b_saveaddr, addr = bp->b_data;
   		addr < bp->b_data + bp->b_bufsize;
 ! 		addr += PAGE_SIZE, v += PAGE_SIZE) {
   
   /*
    * do the vm_fault if needed, do the copy-on-write thing when
 ***************
 *** 712,742 ****
    */
   		vm_fault_quick(addr,
   			(bp->b_flags&B_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ);
 ! 		pa = pmap_kextract((vm_offset_t) addr);
   		if (pa == 0)
   			panic("vmapbuf: page not present");
 - /*
 -  * hold the data page
 -  */
 - #ifdef DIAGNOSTIC
 - 		if( VM_PAGE_TO_PHYS(PHYS_TO_VM_PAGE(pa)) != pa)
 - 			panic("vmapbuf: confused PHYS_TO_VM_PAGE mapping");
 - #endif
   		vm_page_hold(PHYS_TO_VM_PAGE(pa));
   	}
   
 ! 	addr = bp->b_saveaddr = bp->b_data;
 ! 	off = (int)addr & PGOFSET;
 ! 	npf = btoc(round_page(bp->b_bufsize + off));
 ! 	bp->b_data = (caddr_t) (kva + off);
 ! 	while (npf--) {
 ! 		pa = pmap_kextract((vm_offset_t)addr);
 ! 		if (pa == 0)
 ! 			panic("vmapbuf: null page frame");
 ! 		pmap_kenter(kva, trunc_page(pa));
 ! 		addr += PAGE_SIZE;
 ! 		kva += PAGE_SIZE;
 ! 	}
   }
   
   /*
 --- 703,718 ----
    */
   		vm_fault_quick(addr,
   			(bp->b_flags&B_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ);
 ! 		pa = trunc_page(pmap_kextract((vm_offset_t) addr));
   		if (pa == 0)
   			panic("vmapbuf: page not present");
   		vm_page_hold(PHYS_TO_VM_PAGE(pa));
 + 		pmap_kenter((vm_offset_t) v, pa);
   	}
   
 ! 	kva = bp->b_saveaddr;
 ! 	bp->b_saveaddr = bp->b_data;
 ! 	bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK);
   }
   
   /*
 ***************
 *** 748,778 ****
   	register struct buf *bp;
   {
   	register caddr_t addr;
 ! 	vm_offset_t v,pa;
   
   	if ((bp->b_flags & B_PHYS) == 0)
   		panic("vunmapbuf");
   
 ! 	for (addr = (caddr_t)trunc_page((vm_offset_t) bp->b_data);
 ! 		addr < bp->b_data + bp->b_bufsize;
 ! 		addr += NBPG)
   		pmap_kremove((vm_offset_t) addr);
 - 
 - 	bp->b_data = bp->b_saveaddr;
 - 	bp->b_saveaddr = NULL;
 - 
 - /*
 -  * unhold the pde, and data pages
 -  */
 - 	for (addr = (caddr_t)trunc_page((vm_offset_t) bp->b_data);
 - 		addr < bp->b_data + bp->b_bufsize;
 - 		addr += NBPG) {
 - 	/*
 - 	 * release the data page
 - 	 */
 - 		pa = pmap_kextract((vm_offset_t) addr);
   		vm_page_unhold(PHYS_TO_VM_PAGE(pa));
   	}
   }
   
   /*
 --- 724,742 ----
   	register struct buf *bp;
   {
   	register caddr_t addr;
 ! 	vm_offset_t pa;
   
   	if ((bp->b_flags & B_PHYS) == 0)
   		panic("vunmapbuf");
   
 ! 	for (addr = bp->b_data; addr < bp->b_data + bp->b_bufsize;
 ! 		addr += PAGE_SIZE) {
 ! 		pa = trunc_page(pmap_kextract((vm_offset_t) addr));
   		pmap_kremove((vm_offset_t) addr);
   		vm_page_unhold(PHYS_TO_VM_PAGE(pa));
   	}
 + 
 + 	bp->b_data = bp->b_saveaddr;
   }
   
   /*

From: Juergen Lock <nox@jelal.hb.north.de>
To: davidg@Root.COM
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: kern/1195: stable with DIAGNOSTIC panics `vm_page_unhold: hold count < 0'
Date: Wed, 19 Jun 1996 08:57:14 +0200 (MET DST)

 David Greenman writes:
 > 
 > >>Description:
 > >
 > >	Every time i make a DIAGNOSTIC kernel and then dump more than
 > >a few MB to tape using afio, i get this.  Then i disable the panic
 > >and everything is well again.  So this itself is not critical but...
 > >
 > >>How-To-Repeat:
 > >
 > >	(boot DIAGNOSTIC kernel, install afio, mount scratch monk.. errm, tape)
 > >
 > >	find /usr/src | afio -G 2 -o -v -f -b 5120 -c 1000 -s 100000x -Z /dev/nrst0
 > 
 > 
 >    Please try out the attached patch and see if the problem is fixed.
 >    Thanks.
 > 
 > -DG
 > 
 > David Greenman
 > Core-team/Principal Architect, The FreeBSD Project
 > 
 > Index: vm_machdep.c
 > ===================================================================
 > RCS file: /home/ncvs/src/sys/i386/i386/vm_machdep.c,v
 > retrieving revision 1.39.4.2
 > diff -c -r1.39.4.2 vm_machdep.c
 > *** vm_machdep.c	1996/01/30 12:56:30	1.39.4.2
 > --- vm_machdep.c	1996/06/19 03:35:38
 
 Yeah :)
 
  look good so far, it has just written usr/obj without incident.
 i have now started usr/src, if anything happens i'll mail again.
 
  hows that for a good news...
 	Juergen
State-Changed-From-To: open->closed 
State-Changed-By: davidg 
State-Changed-When: Wed Jun 19 18:56:06 PDT 1996 
State-Changed-Why:  
Bug was fixed in rev 1.39.4.3 of vm_machdep.c. It was caused 
by a rounding/off-by-one bug in vmapbuf/vunmapbuf(). 
>Unformatted:
