Subject: kern/14781: genfs_getpages reads-ahead too many pages on small pagesize system
To: None <gnats-bugs@gnats.netbsd.org>
From: None <fredette@netbsd.org>
List: netbsd-bugs
Date: 11/29/2001 21:48:00
>Number:         14781
>Category:       kern
>Synopsis:       genfs_getpages reads-ahead too many pages on small pagesize system
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Nov 29 18:49:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Matthew Fredette
>Release:        NetBSD-current updated 20011128
>Organization:
	Self
>Environment:
System: NetBSD still-remains.home 1.5Y NetBSD 1.5Y (FOURMEG) #1: Thu Nov 29 21:01:07 EST 2001 root@the-gates-of-delirium.home:/data/union-sun2-elf/src/sys/arch/sun2/compile/FOURMEG sun2

>Description:
	genfs_getpages reads-ahead 64k at a time, i.e., 1 << (16 - PAGE_SHIFT)
	pages.  See genfs_vnops.c revision 1.40, line 852.

	On a system where PAGE_SHIFT is 11, this means 32 pages.  This
	eventually causes the panic "too many pages" in a recursive call 
	to the same function, which has a limit of 16 pages.  The panic
	is at line 479 of the same file.
>How-To-Repeat:
	Inspection.
>Fix:
	I was able to work around the problem with the following patch,
	which reads-ahead at most 16 pages at a time:
[snip]
Index: genfs_vnops.c
===================================================================
RCS file: /cvsroot/syssrc/sys/miscfs/genfs/genfs_vnops.c,v
retrieving revision 1.40
diff -u -r1.40 genfs_vnops.c
--- genfs_vnops.c	2001/11/10 13:33:41	1.40
+++ genfs_vnops.c	2001/11/30 02:40:56
@@ -851,15 +851,19 @@
 raout:
 	if (!error && !async && !write && ((int)raoffset & 0xffff) == 0 &&
 	    PAGE_SHIFT <= 16) {
+		off_t rasize;
 		int racount;
 
-		racount = 1 << (16 - PAGE_SHIFT);
+		/* XXXUBC temp limit, from above */
+		racount = MIN(1 << (16 - PAGE_SHIFT), 16);
+		rasize = racount << PAGE_SHIFT;
 		(void) VOP_GETPAGES(vp, raoffset, NULL, &racount, 0,
 				    VM_PROT_READ, 0, 0);
 		simple_lock(&uobj->vmobjlock);
 
-		racount = 1 << (16 - PAGE_SHIFT);
-		(void) VOP_GETPAGES(vp, raoffset + 0x10000, NULL, &racount, 0,
+		/* XXXUBC temp limit, from above */
+		racount = MIN(1 << (16 - PAGE_SHIFT), 16);
+		(void) VOP_GETPAGES(vp, raoffset + rasize, NULL, &racount, 0,
 				    VM_PROT_READ, 0, 0);
 		simple_lock(&uobj->vmobjlock);
 	}
[snip]
>Release-Note:
>Audit-Trail:
>Unformatted: