From gemini@geminix.org  Thu Sep 16 13:53:09 2004
Return-Path: <gemini@geminix.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 6651416A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 16 Sep 2004 13:53:09 +0000 (GMT)
Received: from gen129.n001.c02.escapebox.net (gen129.n001.c02.escapebox.net [213.73.91.129])
	by mx1.FreeBSD.org (Postfix) with ESMTP id D548143D49
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 16 Sep 2004 13:53:08 +0000 (GMT)
	(envelope-from gemini@geminix.org)
Received: from gemini by geminix.org with local (Exim 3.36 #1)
	id 1C7wh9-0007PJ-00
	for FreeBSD-gnats-submit@freebsd.org; Thu, 16 Sep 2004 15:53:07 +0200
Message-Id: <E1C7wh9-0007PJ-00@geminix.org>
Date: Thu, 16 Sep 2004 15:53:07 +0200
From: Uwe Doering <gemini@geminix.org>
Reply-To: Uwe Doering <gemini@geminix.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: Wrong/missing 'goto' target label in contigmalloc1()
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         71792
>Category:       kern
>Synopsis:       [vm] [patch] Wrong/missing 'goto' target label in contigmalloc1()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Sep 16 14:00:48 GMT 2004
>Closed-Date:    Fri Nov 23 20:08:25 UTC 2007
>Last-Modified:  Fri Nov 23 20:08:25 UTC 2007
>Originator:     Uwe Doering
>Release:        FreeBSD 4.10-STABLE i386
>Organization:
EscapeBox - Managed On-Demand UNIX Servers
http://www.escapebox.net

>Environment:
System: FreeBSD geminix.org 4.10-STABLE FreeBSD 4.10-STABLE #1: Tue Sep 14 20:12:02 GMT 2004 root@localhost:/RELENG_4_Enhanced i386

>Description:
There are two loops in contigmalloc1() (src/sys/vm/vm_page.c) that
try to make room in the memory arena if there was no page available
on first try that would fit the applying constraints.  The first
loop scans PQ_INACTIVE, the second one PQ_ACTIVE.

Now, the second loop apparently has come into existence by means of
a cut-and-paste operation.  Unfortunately, the author of the code
segment forgot to give that loop its own 'goto' target label, to be
used in start-over situations.  Instead, the 'goto' statements jump
back into the PQ_INACTIVE loop, possibly over and over again.

>How-To-Repeat:
The problem becomes apparent when looking at the relevant source
code.

>Fix:
Give the PQ_ACTIVE loop its own start-over target label.  Please
consider adopting the patch below.

--- vm_page.c.diff begins here ---
--- src/sys/vm/vm_page.c.orig	Wed Jan 28 22:24:01 2004
+++ src/sys/vm/vm_page.c	Sat May  8 20:48:22 2004
@@ -1892,6 +1894,7 @@
 					vm_page_cache(m);
 			}
 
+again2:
 			for (m = TAILQ_FIRST(&vm_page_queues[PQ_ACTIVE].pl);
 				m != NULL;
 				m = next) {
@@ -1901,18 +1904,18 @@
 
 				next = TAILQ_NEXT(m, pageq);
 				if (vm_page_sleep_busy(m, TRUE, "vpctw1"))
-					goto again1;
+					goto again2;
 				vm_page_test_dirty(m);
 				if (m->dirty) {
 					if (m->object->type == OBJT_VNODE) {
 						vn_lock(m->object->handle, LK_EXCLUSIVE | LK_RETRY, curproc);
 						vm_object_page_clean(m->object, 0, 0, OBJPC_SYNC);
 						VOP_UNLOCK(m->object->handle, 0, curproc);
-						goto again1;
+						goto again2;
 					} else if (m->object->type == OBJT_SWAP ||
 								m->object->type == OBJT_DEFAULT) {
 						vm_pageout_flush(&m, 1, 0);
-						goto again1;
+						goto again2;
 					}
 				}
 				if ((m->dirty == 0) && (m->busy == 0) && (m->hold_count == 0))
--- vm_page.c.diff ends here ---
>Release-Note:
>Audit-Trail:

From: Gavin Atkinson <gavin.atkinson@ury.york.ac.uk>
To: bug-followup@FreeBSD.org, gemini@geminix.org
Cc:  
Subject: Re: kern/71792: [vm] [patch] Wrong/missing 'goto' target label in
	contigmalloc1()
Date: Thu, 26 Apr 2007 11:54:38 +0100

 I have no idea if this is actually a bug or not, but note that the code
 has changed significantly since this PR was submitted.  In -HEAD, the
 function in question is in src/sys/vm/vm_contig.c
 
 In revision 1.10, the copied/pasted code was factored out, but retained
 the same "goto" semantics that the submitter believes are wrong:
 http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/vm/vm_contig.c.diff?r1=1.9;r2=1.10
 
 Since then, the code has carried on morphing, and the goto in question
 is around line 234 of -HEAD, and is still effectively the same as it
 always was.
 
 This probably needs looking at by a VM expert (alc?) to determine if the
 original submitter's issues with the code are valid.  I do note that
 DragonFlyBVSD seem to have changed this code in
 http://www.dragonflybsd.org/cvsweb/src/sys/vm/vm_contig.c.diff?r1=1.12&r2=1.13 with a commit message indicating that it did indeed fix a possible endless loop.
 
 
State-Changed-From-To: open->closed 
State-Changed-By: alc 
State-Changed-When: Fri Nov 23 19:57:04 UTC 2007 
State-Changed-Why:  
I am sure that the use of the same label was intentional and 
not accidental.  The reason being that a new page might appear 
in the inactive queue while contigmalloc() slept on an active 
page. 

Also, in the audit trail, there is mention of a fix for an 
endless loop in this code that was applied to DragonflyBSD. 
FreeBSD has had a similar fix since FreeBSD 5.0. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=71792 
>Unformatted:
