From aagero@aage.aage.priv.no  Sun Dec 17 22:58:23 1995
Received: from birk04.studby.uio.no (root@birk04.studby.uio.no [129.240.214.13])
          by freefall.freebsd.org (8.7.3/8.7.3) with ESMTP id WAA07581
          for <FreeBSD-gnats-submit@freebsd.org>; Sun, 17 Dec 1995 22:58:21 -0800 (PST)
Received: (from aagero@localhost) by birk04.studby.uio.no (8.7.3/FreeBSD1.0) id HAA12860; Mon, 18 Dec 1995 07:58:18 +0100 (MET)
Message-Id: <199512180658.HAA12860@birk04.studby.uio.no>
Date: Mon, 18 Dec 1995 07:58:18 +0100 (MET)
From: aagero@aage.aage.priv.no
Reply-To: aagero@aage.aage.priv.no
To: FreeBSD-gnats-submit@freebsd.org
Subject: busy pages get free'd by vm_page_free
X-Send-Pr-Version: 3.2

>Number:         901
>Category:       kern
>Synopsis:       vm_page_free frees wrong pages in vfs_bio.c
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Dec 17 23:00:01 PST 1995
>Closed-Date:    Sat Jan 6 15:25:09 PST 1996
>Last-Modified:  Sat Jan  6 15:29:15 PST 1996
>Originator:     ge Rbekk
>Release:        FreeBSD 2.2-CURRENT i386
>Organization:
>Environment:

FreeBSD-CURRENT 14. dec. sources.

>Description:

vm_page_free() in vfs_bio.c has an incorrent index of the free(?) pages. When
vm_hold_free_pages() calls vm_page_free() it points to the wrong page due to
the index being a signed datatype.

>How-To-Repeat:

Do a lot of activity, in order to get the paging moving. Usually ls -lR / has
been sufficient.

>Fix:

Apply the included patch.
	
--- kern/vfs_bio.c      Sun Dec 17 02:51:17 1995
+++ kern/vfs_bio.c~     Sun Dec 17 02:51:04 1995
@@ -1634,7 +1634,7 @@
        vm_offset_t to = round_page(toa);
 
        for (pg = from; pg < to; pg += PAGE_SIZE) {
-               int index = ((caddr_t) pg - bp->b_data) >> PAGE_SHIFT;
+               unsigned int index = ((caddr_t) pg - bp->b_data) >> PAGE_SHIFT;
                p = bp->b_pages[index];
                bp->b_pages[index] = 0;
                pmap_kremove(pg);

>Release-Note:
>Audit-Trail:

From: David Greenman <davidg@Root.COM>
To: aagero@aage.aage.priv.no
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/901: busy pages get free'd by vm_page_free 
Date: Sun, 17 Dec 1995 23:37:12 -0800

 >>Description:
 >
 >vm_page_free() in vfs_bio.c has an incorrent index of the free(?) pages. When
 >vm_hold_free_pages() calls vm_page_free() it points to the wrong page due to
 >the index being a signed datatype.
 >
 >>How-To-Repeat:
 >
 >Do a lot of activity, in order to get the paging moving. Usually ls -lR / has
 >been sufficient.
 >
 >>Fix:
 >
 >Apply the included patch.
 >	
 >--- kern/vfs_bio.c      Sun Dec 17 02:51:17 1995
 >+++ kern/vfs_bio.c~     Sun Dec 17 02:51:04 1995
 >@@ -1634,7 +1634,7 @@
 >        vm_offset_t to = round_page(toa);
 > 
 >        for (pg = from; pg < to; pg += PAGE_SIZE) {
 >-               int index = ((caddr_t) pg - bp->b_data) >> PAGE_SHIFT;
 >+               unsigned int index = ((caddr_t) pg - bp->b_data) >> PAGE_SHIFT;
 >                p = bp->b_pages[index];
 >                bp->b_pages[index] = 0;
 >                pmap_kremove(pg);
 
    I must be really missing something. The index that is calculated should
 always be between 0 and 1 (or some small number). I don't understand why
 making index unsigned would make any difference since it should always be
 positive. If it's ever negative, well then that's quite another problem.
 
 -DG
State-Changed-From-To: open->feedback 
State-Changed-By: phk 
State-Changed-When: Sat Jan 6 13:54:21 PST 1996 
State-Changed-Why:  

It actually looks like you're right, if  
((caddr_t) pg - bp->b_data)  
is bigger than 0x7f000000 
then trouble abounds. 

Could you try this patch instead ? 

Index: vfs_bio.c 
=================================================================== 
RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v 
retrieving revision 1.81 
diff -u -r1.81 vfs_bio.c 
--- vfs_bio.c	1996/01/05 20:12:33	1.81 
+++ vfs_bio.c	1996/01/06 21:58:17 
@@ -1637,9 +1637,9 @@ 
vm_page_t p; 
vm_offset_t from = round_page(froma); 
vm_offset_t to = round_page(toa); 
+	unsigned int index = ((caddr_t) from - bp->b_data) >> PAGE_SHIFT; 

-	for (pg = from; pg < to; pg += PAGE_SIZE) { 
-		int index = ((caddr_t) pg - bp->b_data) >> PAGE_SHIFT; 
+	for (pg = from; pg < to; pg += PAGE_SIZE, index++) { 
p = bp->b_pages[index]; 
bp->b_pages[index] = 0; 
pmap_kremove(pg); 


Poul-Henning Kamp 
State-Changed-From-To: feedback->closed 
State-Changed-By: davidg 
State-Changed-When: Sat Jan 6 15:25:09 PST 1996 
State-Changed-Why:  
This should be fixed in rev 1.82 of vfs_bio.c. The problem appears to 
be that "from" is already aligned at the buffer base, but bp->b_data 
was not. bp->b_data needs to first be page-truncated before the 
subtraction. I've rewritten the routines in rev 1.82 and the new version 
should fix the problem. 
>Unformatted:
