kern/101668: [patch] Some failed calls to contigmalloc(9) cause
panic
Michael Plass
mfp49_freebsd at plass-family.net
Tue Aug 8 18:40:19 UTC 2006
>Number: 101668
>Category: kern
>Synopsis: [patch] Some failed calls to contigmalloc(9) cause panic
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Aug 08 18:40:14 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: Michael Plass
>Release: 6.1-RELEASE
>Organization:
>Environment:
FreeBSD froghorn 6.1-RELEASE FreeBSD 6.1-RELEASE #0: Sun May 7 04:42:56 UTC 2006 root at opus.cse.buffalo.edu:/usr/obj/usr/src/sys/SMP i386
>Description:
When contigmalloc(9) is used to request a contiguous physical memory area, a panic can result. This is most likely to happen in the case of a failed request.
>How-To-Repeat:
A call to contigmalloc that asks for more physical memory than the machine has will cause this panic. Calls of considerably smaller size can also provoke the problem.
>Fix:
The bug is in vm_page_alloc_contig; the retry logic allows the start value to go negative, so the test (i == -1) in line 437 is incorrect. The test should be (i < 0):
63 __FBSDID("$FreeBSD: src/sys/vm/vm_contig.c,v 1.43.2.3.2.1 2006/04/25 15:29:50 scottl Exp $");
390
391 vm_page_t
392 vm_page_alloc_contig(vm_pindex_t npages, vm_paddr_t low, vm_paddr_t high,
393 vm_offset_t alignment, vm_offset_t boundary)
394 {
395 vm_object_t object;
396 vm_offset_t size;
397 vm_paddr_t phys;
398 vm_page_t pga = vm_page_array;
399 int i, pass, pqtype, start;
400
401 size = npages << PAGE_SHIFT;
402 if (size == 0)
403 panic("vm_page_alloc_contig: size must not be 0");
404 if ((alignment & (alignment - 1)) != 0)
405 panic("vm_page_alloc_contig: alignment must be a power of 2");
406 if ((boundary & (boundary - 1)) != 0)
407 panic("vm_page_alloc_contig: boundary must be a power of 2");
408
409 for (pass = 0; pass < 2; pass++) {
410 if (atop(high) < vm_page_array_size)
411 start = atop(high) - npages + 1;
412 else
413 start = vm_page_array_size - npages + 1;
414 vm_page_lock_queues();
415 retry:
416 start--;
417 /*
418 * Find last page in array that is free, within range,
419 * aligned, and such that the boundary won't be crossed.
420 */
421 for (i = start; i >= 0; i--) {
422 phys = VM_PAGE_TO_PHYS(&pga[i]);
423 pqtype = pga[i].queue - pga[i].pc;
424 if (pass == 0) {
425 if (pqtype != PQ_FREE && pqtype != PQ_CACHE)
426 continue;
427 } else if (pqtype != PQ_FREE && pqtype != PQ_CACHE &&
428 pga[i].queue != PQ_ACTIVE &&
429 pga[i].queue != PQ_INACTIVE)
430 continue;
431 if (phys >= low && phys + size <= high &&
432 ((phys & (alignment - 1)) == 0) &&
433 ((phys ^ (phys + size - 1)) & ~(boundary - 1)) == 0)
434 break;
435 }
436 /* There are no candidates at all. */
****437 if (i < 0) {
438 vm_page_unlock_queues();
439 continue;
440 }
441 start = i;
Here is a patch against -CURRENT:
Index: vm_contig.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/vm_contig.c,v
retrieving revision 1.51
diff -u -r1.51 vm_contig.c
--- vm_contig.c 8 Mar 2006 00:51:00 -0000 1.51
+++ vm_contig.c 8 Aug 2006 18:10:33 -0000
@@ -447,7 +447,7 @@
break;
}
/* There are no candidates at all. */
- if (i == -1) {
+ if (i < 0) {
vm_page_unlock_queues();
continue;
}
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list