Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Oct 2002 12:20:49 -0700
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Ben Stuyts <ben@stuyts.nl>
Cc:        Robert Watson <rwatson@freebsd.org>, current@freebsd.org, jeff@freebsd.org
Subject:   [Ugly PATCH] Re: Again: panic kmem_malloc()
Message-ID:  <3DA72490.32A10E8@mindspring.com>
References:  <Pine.NEB.3.96L.1021010175350.39392C-100000@fledge.watson.org> <4.3.2.7.2.20021011100633.03783d58@terminus>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------E6AD74128BB6F64586677DD8
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Ben Stuyts wrote:
> Is there a way to check the free list of the kernel? Maybe I can find out
> what action triggers eating al its memory.

] panic: kmem_malloc(4096): kmem_map too small: 28246016 total allocated.

That's easy: you're calling kmem_malloc() without M_NOWAIT.

That function only operates on the maps kmem_map or mb_map.

It calls vm_map_findspace(), which fails to find space in the
map.

vm_map_findspace() fails to add space to the map, because it
only adds space tot he map if the map is kernel_map; all other
maps fail catastrophically.

The map you are calling it with is kmem_map (if it were mb_map,
you would get an "Out of mbuf clusters" message on your console,
and the allocation would fail, regardless of the value of the
M_NOWAIT flags bit (mbuf allocations do not properly honor the
lack of an M_NOWAIT flags bit).

The panic message occurs becuause you asked it to wait for memory
to be available.

But the code is stupid, and refuses to wait for memory to be
available, in the case that space can not be found in the map,
because it does not properly realize that the freeing of memory
elsewhere can result in freed space in the map.  So it calls
"panic" instead of waiting.

Therefore, it's technically illegal to call kmem_malloc() with
a third argument that does not include the M_NOWAIT bit, even
though the function is documented, and obviously intended, to
permit the use of this flags bit.


In -current, there is exactly one place where kmem_malloc() is
called with the kmem_map as its first argument: in the function
page_alloc() in vm/uma_core.c.


So, you have two bogus things happening:

1)	page_alloc() in uma is using kmem_malloc() without the
	M_NOWAIT flag

2)	kmem_malloc() without the M_NOWAIT flag panics, INSTEAD
	OF FRICKING WAITING, LIKE YOU ARE TELLING IT TO DO.
	:-0_ <- Dr. Evil

Probably, page_alloc should be rewritten to not use kmem_malloc(),
and to use the kmem_alloc_wait() instead.

Please find a (relatively bogus) patch attached, which could cause
things to block for a long time, but will avoid the panic.

Jeffrey Roberson is going to need to fix UMA allocations, per the
comment in this patch, for a more permanent fix.  I've specifically
Cc:'ed him on this message.

-- Terry
--------------E6AD74128BB6F64586677DD8
Content-Type: text/plain; charset=us-ascii;
 name="uma.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="uma.diff"

Index: uma_core.c
===================================================================
RCS file: /cvs/src/sys/vm/uma_core.c,v
retrieving revision 1.38
diff -c -r1.38 uma_core.c
*** uma_core.c	28 Sep 2002 17:15:33 -0000	1.38
--- uma_core.c	11 Oct 2002 15:19:15 -0000
***************
*** 781,787 ****
  	void *p;	/* Returned page */
  
  	*pflag = UMA_SLAB_KMEM;
! 	p = (void *) kmem_malloc(kmem_map, bytes, wait);
    
  	return (p);
  }
--- 781,798 ----
  	void *p;	/* Returned page */
  
  	*pflag = UMA_SLAB_KMEM;
! 	/*
! 	 * XXX Bogus
! 	 * kmem_malloc() can panic if called without M_NOWAIT on kmem_map;
! 	 * work around this by calling kmem_alloc_wait() instead.  This is
! 	 * really bogus, because it can hang indefinitely.  Jeffrey Roberson
! 	 * needs to fix this to do all UMA allocations out of kernel_map,
! 	 * instead, so pmap_growkernel() can be used, instead of hanging.
! 	 */
! 	if (wait & M_NOWAIT)
! 		p = (void *) kmem_malloc(kmem_map, bytes, wait);
! 	else
! 		p = (void *) kmem_alloc_wait(kmem_map, bytes);
    
  	return (p);
  }

--------------E6AD74128BB6F64586677DD8--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3DA72490.32A10E8>