mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* RFC for 2.6: avoid OOM at bounce buffer storm
@ 2005-06-03 15:47 Martin Wilck
  2005-06-03 23:06 ` Andrew Morton
  0 siblings, 1 reply; 8+ messages in thread
From: Martin Wilck @ 2005-06-03 15:47 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2402 bytes --]

Hello,

I have recently seen massive problems with the bounce buffer allocation 
implementation in 2.6. My system got OOM with an ata_piix controller 
(4GB bounce limit), 2 P4 CPUs and 8GB of RAM with a very simple 
copy-compare test: About 800MB worth of data are copied with cp(1) in 7 
synchronous jobs. Each job does a sync(1) after the copy.

All available ZONE_NORMAL memory is filled with bounce buffers in 
fractions of a second after the sync(1) calls are issued.
The system goes OOM (becomes unusable, OOM killer strikes several times 
against innocent processes).

The attached quick-and-dirty patch gives you an idea of what I figured 
could be a useful workaround for that problem. It follows 2 main ideas:

1 When bounce buffer allocations fail, it is wrong to trigger the page
   reclaim mechanism which is likely to genetate even more bounce buffer
   requests. Thus there should be no wakeup_bdflush() call for the
   page_pool.

2 bounce buffer allocations should not simply use alloc_page() because
   there is no limit for allocations that way. Rather, bounce buffer
   allocations should stop if ZONE_NORMAL is full to a certain degree
   (my patch stops at 51% - chosen arbitrarily).

For the case I described, the system behavior is clearly improved with 
the patch. The system remains usable, and the OOM killer isn't triggered.

(The patch is against an RH enterprise kernel, but it applies against 
almost all recent 2.6.kernels except 2.6.12-rcX).

Idea 1) is already implemented in a recent patch by Nick Piggin which 
went into 2.6.12-rc5. I haven't tested yet if that patch alone fixes my 
problem because I couldn't get 2.6.12-rc5 to run on my system. I doubt 
so, though, because I started with idea 1) alone and it didn't help much.

Here is another idea how the bounce buffer behavior could be enhanced:
Introduce a new memory zone ZONE_4G with memory from 896M-4096M
and allocate bounce buffers preferably in that zone. Advantage: Bounce 
buffers would't interfere with valuable ZONE_NORMAL memory. But that may 
be too much effort just for systems which have too much memory for their 
IO controllers...

Regards
Martin

-- 
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1        mailto:Martin.Wilck@Fujitsu-Siemens.com
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy


[-- Attachment #2: bounce.diff --]
[-- Type: text/x-patch, Size: 4078 bytes --]

diff -rupX /root/diff-exludes linux-2.6.9-6.37.EL-orig/arch/i386/mm/pgtable.c linux-2.6.9-6.37.EL/arch/i386/mm/pgtable.c
--- linux-2.6.9-6.37.EL-orig/arch/i386/mm/pgtable.c	2005-04-11 14:19:03.000000000 +0200
+++ linux-2.6.9-6.37.EL/arch/i386/mm/pgtable.c	2005-05-31 10:27:57.000000000 +0200
@@ -24,6 +24,7 @@
 #include <asm/tlbflush.h>
 #include <asm/atomic_kmap.h>
 
+extern atomic_t n_bounce_pages;
 void show_mem(void)
 {
 	int total = 0, reserved = 0;
@@ -55,6 +56,7 @@ void show_mem(void)
 	printk("%d reserved pages\n",reserved);
 	printk("%d pages shared\n",shared);
 	printk("%d pages swap cached\n",cached);
+	printk("%d bounce buffers used\n",atomic_read(&n_bounce_pages));
 }
 
 EXPORT_SYMBOL_GPL(show_mem);
diff -rupX /root/diff-exludes linux-2.6.9-6.37.EL-orig/Makefile linux-2.6.9-6.37.EL/Makefile
--- linux-2.6.9-6.37.EL-orig/mm/highmem.c	2004-10-18 23:54:37.000000000 +0200
+++ linux-2.6.9-6.37.EL/mm/highmem.c	2005-06-03 15:24:03.000000000 +0200
@@ -28,18 +28,45 @@
 #include <linux/highmem.h>
 #include <asm/tlbflush.h>
 
-static mempool_t *page_pool, *isa_page_pool;
+mempool_t *page_pool, *isa_page_pool;
+atomic_t n_bounce_pages = ATOMIC_INIT(0);
+static unsigned int min_free_pages[MAX_NR_ZONES];
+
+static unsigned int zone_free_pages(int type)
+{
+	pg_data_t *pgdat;
+	unsigned int pages = 0;
+	for_each_pgdat(pgdat)
+		pages += pgdat->node_zones[type].free_pages;
+	return pages;
+}
+
+static int sufficient_lowpages(int gfp)
+{
+	int type = (gfp & __GFP_DMA ? ZONE_DMA : ZONE_NORMAL);
+
+	return (zone_free_pages(type) >= min_free_pages[type]);
+}
 
 static void *page_pool_alloc(int gfp_mask, void *data)
 {
 	int gfp = gfp_mask | (int) (long) data;
+	void *page;
+
+	if (!sufficient_lowpages(gfp))
+		return NULL;
 
-	return alloc_page(gfp);
+	page = alloc_page(gfp);
+
+	if (page)
+		atomic_inc(&n_bounce_pages);
+	return page;
 }
 
 static void page_pool_free(void *page, void *data)
 {
 	__free_page(page);
+	atomic_dec(&n_bounce_pages);
 }
 
 /*
@@ -212,20 +239,25 @@ void fastcall kunmap_high(struct page *p
 EXPORT_SYMBOL(kunmap_high);
 
 #define POOL_SIZE	64
+#define POOL_FRAC(x) ((x)/2)
+#define SMALL_POOL_FRAC(x) ((x)/100)
 
 static __init int init_emergency_pool(void)
 {
+	unsigned int n = zone_free_pages(ZONE_NORMAL);
 	struct sysinfo i;
 	si_meminfo(&i);
 	si_swapinfo(&i);
         
+	min_free_pages[ZONE_NORMAL] = POOL_FRAC(n);
 	if (!i.totalhigh)
 		return 0;
-
-	page_pool = mempool_create(POOL_SIZE, page_pool_alloc, page_pool_free, NULL);
+	n = SMALL_POOL_FRAC(n);
+	n = (n > POOL_SIZE ? n : POOL_SIZE);
+	page_pool = mempool_create(n, page_pool_alloc, page_pool_free, NULL);
 	if (!page_pool)
 		BUG();
-	printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
+	printk("highmem bounce pool size: %d pages, min: %u\n", n, min_free_pages[ZONE_NORMAL]);
 
 	return 0;
 }
@@ -265,11 +297,12 @@ int init_emergency_isa_pool(void)
 	if (isa_page_pool)
 		return 0;
 
+	min_free_pages[ZONE_DMA] = POOL_FRAC(zone_free_pages(ZONE_DMA));
 	isa_page_pool = mempool_create(ISA_POOL_SIZE, page_pool_alloc, page_pool_free, (void *) __GFP_DMA);
 	if (!isa_page_pool)
 		BUG();
 
-	printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE);
+	printk("isa bounce pool size: %d pages, min: %u\n", ISA_POOL_SIZE, min_free_pages[ZONE_DMA]);
 	return 0;
 }
 
diff -rupX /root/diff-exludes linux-2.6.9-6.37.EL-orig/mm/mempool.c linux-2.6.9-6.37.EL/mm/mempool.c
--- linux-2.6.9-6.37.EL-orig/mm/mempool.c	2004-10-18 23:54:37.000000000 +0200
+++ linux-2.6.9-6.37.EL/mm/mempool.c	2005-06-03 15:35:01.000000000 +0200
@@ -15,6 +15,8 @@
 #include <linux/blkdev.h>
 #include <linux/writeback.h>
 
+extern mempool_t *page_pool, *isa_page_pool;
+
 static void add_element(mempool_t *pool, void *element)
 {
 	BUG_ON(pool->curr_nr >= pool->min_nr);
@@ -211,11 +213,12 @@ repeat_alloc:
 		if (likely(element != NULL))
 			return element;
 	}
-
+	
 	/*
 	 * Kick the VM at this point.
 	 */
-	wakeup_bdflush(0);
+	if (pool != page_pool && pool != isa_page_pool)
+		wakeup_bdflush(0);
 
 	spin_lock_irqsave(&pool->lock, flags);
 	if (likely(pool->curr_nr)) {

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: RFC for 2.6: avoid OOM at bounce buffer storm
  2005-06-03 15:47 RFC for 2.6: avoid OOM at bounce buffer storm Martin Wilck
@ 2005-06-03 23:06 ` Andrew Morton
  2005-06-07 14:20   ` Martin Wilck
  0 siblings, 1 reply; 8+ messages in thread
From: Andrew Morton @ 2005-06-03 23:06 UTC (permalink / raw)
  To: Martin Wilck; +Cc: linux-kernel

Martin Wilck <martin.wilck@fujitsu-siemens.com> wrote:
>
> Hello,
> 
> I have recently seen massive problems with the bounce buffer allocation 
> implementation in 2.6. My system got OOM with an ata_piix controller 
> (4GB bounce limit), 2 P4 CPUs and 8GB of RAM with a very simple 
> copy-compare test: About 800MB worth of data are copied with cp(1) in 7 
> synchronous jobs. Each job does a sync(1) after the copy.

Fair enough.

> ...
> 
> The attached quick-and-dirty patch gives you an idea of what I figured 
> could be a useful workaround for that problem. It follows 2 main ideas:
> 
> 1 When bounce buffer allocations fail, it is wrong to trigger the page
>    reclaim mechanism which is likely to genetate even more bounce buffer
>    requests. Thus there should be no wakeup_bdflush() call for the
>    page_pool.
> 
> 2 bounce buffer allocations should not simply use alloc_page() because
>    there is no limit for allocations that way. Rather, bounce buffer
>    allocations should stop if ZONE_NORMAL is full to a certain degree
>    (my patch stops at 51% - chosen arbitrarily).

It might be neater to do this at the mempool level: that way we're adding
general-purpose infrastructure and then just using it, rather than
special-casing the bounce code.

See below a (n untested) patch against the latest devel tree.  It won't be
stunningly scalable on big SMP, but the overhead of bouncing will probably
hide that.


> I couldn't get 2.6.12-rc5 to run on my system.

Ow.  Could you please investigate further?  Any boot messages for us to
see?  it's quite possibly some missing config option..



 include/linux/mempool.h |   17 +++++++++++++++--
 mm/highmem.c            |    4 +++-
 mm/mempool.c            |   17 +++++++++++++----
 3 files changed, 31 insertions(+), 7 deletions(-)

diff -puN include/linux/mempool.h~mempool-bounce-buffer-restriction include/linux/mempool.h
--- 25/include/linux/mempool.h~mempool-bounce-buffer-restriction	Fri Jun  3 16:01:58 2005
+++ 25-akpm/include/linux/mempool.h	Fri Jun  3 16:01:58 2005
@@ -5,6 +5,7 @@
 #define _LINUX_MEMPOOL_H
 
 #include <linux/wait.h>
+#include <asm/semaphore.h>
 
 typedef void * (mempool_alloc_t)(unsigned int __nocast gfp_mask, void *pool_data);
 typedef void (mempool_free_t)(void *element, void *pool_data);
@@ -14,14 +15,26 @@ typedef struct mempool_s {
 	int min_nr;		/* nr of elements at *elements */
 	int curr_nr;		/* Current nr of elements at *elements */
 	void **elements;
+	int limit;
 
 	void *pool_data;
 	mempool_alloc_t *alloc;
 	mempool_free_t *free;
 	wait_queue_head_t wait;
+	struct semaphore limit_sem;
 } mempool_t;
-extern mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
-				 mempool_free_t *free_fn, void *pool_data);
+
+extern mempool_t *mempool_create_restricted(int min_nr,
+	mempool_alloc_t *alloc_fn, mempool_free_t *free_fn,
+	void *pool_data, int limit);
+
+static inline mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
+			mempool_free_t *free_fn, void *pool_data)
+{
+	return mempool_create_restricted(min_nr, alloc_fn, free_fn,
+					pool_data, 0);
+}
+
 extern int mempool_resize(mempool_t *pool, int new_min_nr, unsigned int __nocast gfp_mask);
 extern void mempool_destroy(mempool_t *pool);
 extern void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask);
diff -puN mm/highmem.c~mempool-bounce-buffer-restriction mm/highmem.c
--- 25/mm/highmem.c~mempool-bounce-buffer-restriction	Fri Jun  3 16:01:58 2005
+++ 25-akpm/mm/highmem.c	Fri Jun  3 16:01:58 2005
@@ -224,7 +224,9 @@ static __init int init_emergency_pool(vo
 	if (!i.totalhigh)
 		return 0;
 
-	page_pool = mempool_create(POOL_SIZE, page_pool_alloc, page_pool_free, NULL);
+	page_pool = mempool_create_restricted(POOL_SIZE, page_pool_alloc,
+				page_pool_free, NULL,
+				200 * 1024 * 1024 / PAGE_SIZE);
 	if (!page_pool)
 		BUG();
 	printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
diff -puN mm/mempool.c~mempool-bounce-buffer-restriction mm/mempool.c
--- 25/mm/mempool.c~mempool-bounce-buffer-restriction	Fri Jun  3 16:01:58 2005
+++ 25-akpm/mm/mempool.c	Fri Jun  3 16:01:58 2005
@@ -38,12 +38,13 @@ static void free_pool(mempool_t *pool)
 }
 
 /**
- * mempool_create - create a memory pool
+ * mempool_create_restricted - create a memory pool
  * @min_nr:    the minimum number of elements guaranteed to be
  *             allocated for this pool.
  * @alloc_fn:  user-defined element-allocation function.
  * @free_fn:   user-defined element-freeing function.
  * @pool_data: optional private data available to the user-defined functions.
+ * @limit:     maximum number of in-flight objects
  *
  * this function creates and allocates a guaranteed size, preallocated
  * memory pool. The pool can be used from the mempool_alloc and mempool_free
@@ -51,8 +52,8 @@ static void free_pool(mempool_t *pool)
  * functions might sleep - as long as the mempool_alloc function is not called
  * from IRQ contexts.
  */
-mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
-				mempool_free_t *free_fn, void *pool_data)
+mempool_t *mempool_create_restricted(int min_nr, mempool_alloc_t *alloc_fn,
+			mempool_free_t *free_fn, void *pool_data, int limit)
 {
 	mempool_t *pool;
 
@@ -71,6 +72,8 @@ mempool_t * mempool_create(int min_nr, m
 	init_waitqueue_head(&pool->wait);
 	pool->alloc = alloc_fn;
 	pool->free = free_fn;
+	pool->limit = limit;
+	sema_init(&pool->limit_sem, limit);
 
 	/*
 	 * First pre-allocate the guaranteed number of buffers.
@@ -87,7 +90,7 @@ mempool_t * mempool_create(int min_nr, m
 	}
 	return pool;
 }
-EXPORT_SYMBOL(mempool_create);
+EXPORT_SYMBOL(mempool_create_restricted);
 
 /**
  * mempool_resize - resize an existing memory pool
@@ -208,6 +211,9 @@ void * mempool_alloc(mempool_t *pool, un
 
 	gfp_temp = gfp_mask & ~(__GFP_WAIT|__GFP_IO);
 
+	if (unlikely(pool->limit))
+		down(&pool->limit_sem);
+
 repeat_alloc:
 
 	element = pool->alloc(gfp_temp, pool->pool_data);
@@ -250,6 +256,9 @@ void mempool_free(void *element, mempool
 {
 	unsigned long flags;
 
+	if (unlikely(pool->limit))
+		up(&pool->limit_sem);
+
 	smp_mb();
 	if (pool->curr_nr < pool->min_nr) {
 		spin_lock_irqsave(&pool->lock, flags);
_


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: RFC for 2.6: avoid OOM at bounce buffer storm
  2005-06-03 23:06 ` Andrew Morton
@ 2005-06-07 14:20   ` Martin Wilck
  2005-06-07 19:08     ` Andrew Morton
  0 siblings, 1 reply; 8+ messages in thread
From: Martin Wilck @ 2005-06-07 14:20 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

Andrew Morton wrote:

> It might be neater to do this at the mempool level: that way we're adding
> general-purpose infrastructure and then just using it, rather than
> special-casing the bounce code.
> 
> See below a (n untested) patch against the latest devel tree.  It won't be
> stunningly scalable on big SMP, but the overhead of bouncing will probably
> hide that.

I don't quite understand your patch. You introduce a "limit" field but 
you never actually use it. You also don't count the allocated pages.
Are you using the semaphore for slowing things down on purpose?

(Note that the problem is not in the mempool allocation itself but in 
the "normal" allocation path (page_pool_alloc() -> alloc_page()))

Anyway, I think could figure out your patch but with 2.6.12-rc5-mm2 I 
couldn't reproduce the problem any more. It appears to run much more 
smoothly now, perhaps because wakeup_bdflush() isn't called any more. 
Are you still interested in more data?

>>I couldn't get 2.6.12-rc5 to run on my system.
> 
> Ow.  Could you please investigate further?  Any boot messages for us to
> see?  it's quite possibly some missing config option..

It turned out to be a problem with Red Hat's nash that didn't check the 
returned pid in it's wait4() call and thus ended up insmod'ing mutliple 
modules simultaneously, leading to "Unkown symbol" errors. Yuck, it took 
me a day figure that out.

That bug is fixed in redhat's "mkinitrd" package 4.2.0.3-1 and later, 
but that package is currently only in Fedora's "Development" tree.

Thanks,
Martin

-- 
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1        mailto:Martin.Wilck@Fujitsu-Siemens.com
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: RFC for 2.6: avoid OOM at bounce buffer storm
  2005-06-07 14:20   ` Martin Wilck
@ 2005-06-07 19:08     ` Andrew Morton
  2005-06-08 18:54       ` Martin Wilck
  0 siblings, 1 reply; 8+ messages in thread
From: Andrew Morton @ 2005-06-07 19:08 UTC (permalink / raw)
  To: Martin Wilck; +Cc: linux-kernel

Martin Wilck <martin.wilck@fujitsu-siemens.com> wrote:
>
> > It might be neater to do this at the mempool level: that way we're adding
>  > general-purpose infrastructure and then just using it, rather than
>  > special-casing the bounce code.
>  > 
>  > See below a (n untested) patch against the latest devel tree.  It won't be
>  > stunningly scalable on big SMP, but the overhead of bouncing will probably
>  > hide that.
> 
>  I don't quite understand your patch. You introduce a "limit" field but 
>  you never actually use it. You also don't count the allocated pages.
>  Are you using the semaphore for slowing things down on purpose?

The semaphore is initialised with the limit level, so once it has been
down()ed more than `limit' times, processes will block until someone does
up().

>  (Note that the problem is not in the mempool allocation itself but in 
>  the "normal" allocation path (page_pool_alloc() -> alloc_page()))

yup.  The semaphore will prevent more than `limit' pages being allocated at
any point in time.

>  Anyway, I think could figure out your patch but with 2.6.12-rc5-mm2 I 
>  couldn't reproduce the problem any more.

Oh bugger.

> It appears to run much more 
>  smoothly now, perhaps because wakeup_bdflush() isn't called any more. 
>  Are you still interested in more data?

Perhaps the newer kernel has writeback thresholding fixes so it's not
possible to dirty as much memory with write().

You can probably trigger the same problem if the memory is instead dirtied
with mmap(MAP_SHARED).

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: RFC for 2.6: avoid OOM at bounce buffer storm
  2005-06-07 19:08     ` Andrew Morton
@ 2005-06-08 18:54       ` Martin Wilck
  2005-06-08 21:46         ` Andrew Morton
  0 siblings, 1 reply; 8+ messages in thread
From: Martin Wilck @ 2005-06-08 18:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

Hello Andrew,

> The semaphore is initialised with the limit level, so once it has been
> down()ed more than `limit' times, processes will block until someone does
> up().

Oh - of course. Neat.

>>It appears to run much more 
>> smoothly now, perhaps because wakeup_bdflush() isn't called any more. 
>> Are you still interested in more data?
> 
> Perhaps the newer kernel has writeback thresholding fixes so it's not
> possible to dirty as much memory with write().

I have collected more data and the behavior with 2.6.12-rc5-mm2 is 
flawless, there is a continuous writeback flow close to the maximum rate 
possible, and the bounce buffer usage never gets anywhere near the limit 
where it'd become dangerous. At least not in my test setup. The latest 
fedora kernel 2.6.11-1.27 also behaves ok, although it doesn't adapt to 
changing io load as smoothly as 2.6.12-rc5-mm2 does, and the writeback 
rate is oscillating more strongly.

The kernels where I observe the problem are 2.6.9 kernels from RedHat 
EL4. I have posted this here because I saw that the highmem bounce 
buffer/memory pool implementation was identical between the 2.6.9 kernel 
and all but the very latest development kernels, and I concluded 
prematurely that the behavior under my scenario must also be the same -- 
which it wasn't. I apologize for not having looked more closely.

Many thanks for looking into this anyway. From a theoretical point of 
view, I still think I had a valid point :-/.

Your patch sure looks good to me.

Regards
Martin

-- 
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1        mailto:Martin.Wilck@Fujitsu-Siemens.com
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: RFC for 2.6: avoid OOM at bounce buffer storm
  2005-06-08 18:54       ` Martin Wilck
@ 2005-06-08 21:46         ` Andrew Morton
  2005-06-14 16:22           ` Martin Wilck
  0 siblings, 1 reply; 8+ messages in thread
From: Andrew Morton @ 2005-06-08 21:46 UTC (permalink / raw)
  To: Martin Wilck; +Cc: linux-kernel

Martin Wilck <martin.wilck@fujitsu-siemens.com> wrote:
>
> Hello Andrew,
> 
> > The semaphore is initialised with the limit level, so once it has been
> > down()ed more than `limit' times, processes will block until someone does
> > up().
> 
> Oh - of course. Neat.
> 
> >>It appears to run much more 
> >> smoothly now, perhaps because wakeup_bdflush() isn't called any more. 
> >> Are you still interested in more data?
> > 
> > Perhaps the newer kernel has writeback thresholding fixes so it's not
> > possible to dirty as much memory with write().
> 
> I have collected more data and the behavior with 2.6.12-rc5-mm2 is 
> flawless, there is a continuous writeback flow close to the maximum rate 
> possible, and the bounce buffer usage never gets anywhere near the limit 
> where it'd become dangerous. At least not in my test setup. The latest 
> fedora kernel 2.6.11-1.27 also behaves ok, although it doesn't adapt to 
> changing io load as smoothly as 2.6.12-rc5-mm2 does, and the writeback 
> rate is oscillating more strongly.
> 
> The kernels where I observe the problem are 2.6.9 kernels from RedHat 
> EL4. I have posted this here because I saw that the highmem bounce 
> buffer/memory pool implementation was identical between the 2.6.9 kernel 
> and all but the very latest development kernels, and I concluded 
> prematurely that the behavior under my scenario must also be the same -- 
> which it wasn't. I apologize for not having looked more closely.
> 
> Many thanks for looking into this anyway. From a theoretical point of 
> view, I still think I had a valid point :-/.
> 
> Your patch sure looks good to me.

Well.  As I said, I think what you're seeing here is recent changes to
mm/page-writeback.c which reduce the amount of memory which we'll permit to
be dirtied due to write() calls.  You'll probably find that the bounce
buffer problem is also fixable by reducing /proc/sys/vm/dirty_ratio in
2.6.9, for the same reasons.

What concerns me is that there are other ways of dirtying lots of memory
apart from write(): namely mmap(MAP_SHARED).  If someone dirties 90% of all
memory via mmap() then we might again get into bounce buffer starvation.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: RFC for 2.6: avoid OOM at bounce buffer storm
  2005-06-08 21:46         ` Andrew Morton
@ 2005-06-14 16:22           ` Martin Wilck
  2005-06-14 20:38             ` Andrew Morton
  0 siblings, 1 reply; 8+ messages in thread
From: Martin Wilck @ 2005-06-14 16:22 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

Hi Andrew,

> Well.  As I said, I think what you're seeing here is recent changes to
> mm/page-writeback.c which reduce the amount of memory which we'll permit to
> be dirtied due to write() calls.  You'll probably find that the bounce
> buffer problem is also fixable by reducing /proc/sys/vm/dirty_ratio in
> 2.6.9, for the same reasons.
> 
> What concerns me is that there are other ways of dirtying lots of memory
> apart from write(): namely mmap(MAP_SHARED).  If someone dirties 90% of all
> memory via mmap() then we might again get into bounce buffer starvation.

I have tried the mmap(MAP_SHARED) method now extensively. I haven't been 
able to come anywhere near the catastrophic situations I saw with the 
2.6.9 kernel, even by dirtying the full 8GB in fractions of a second.

There was another strangeness there though: Even with the high memory 
pressure applied, The ZONE_NORMAL free memory would never go below 
~300MB. When the mem pressure got too high, the kernel would rather free 
almost slabs and start swapping than use those remaining 300M. It seems 
to me that the new logic is a bit too conservative with ZONE_NORMAL 
allocations.

Regards
Martin

-- 
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1        mailto:Martin.Wilck@Fujitsu-Siemens.com
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: RFC for 2.6: avoid OOM at bounce buffer storm
  2005-06-14 16:22           ` Martin Wilck
@ 2005-06-14 20:38             ` Andrew Morton
  0 siblings, 0 replies; 8+ messages in thread
From: Andrew Morton @ 2005-06-14 20:38 UTC (permalink / raw)
  To: Martin Wilck; +Cc: linux-kernel

Martin Wilck <martin.wilck@fujitsu-siemens.com> wrote:
>
> Hi Andrew,
> 
> > Well.  As I said, I think what you're seeing here is recent changes to
> > mm/page-writeback.c which reduce the amount of memory which we'll permit to
> > be dirtied due to write() calls.  You'll probably find that the bounce
> > buffer problem is also fixable by reducing /proc/sys/vm/dirty_ratio in
> > 2.6.9, for the same reasons.
> > 
> > What concerns me is that there are other ways of dirtying lots of memory
> > apart from write(): namely mmap(MAP_SHARED).  If someone dirties 90% of all
> > memory via mmap() then we might again get into bounce buffer starvation.
> 
> I have tried the mmap(MAP_SHARED) method now extensively. I haven't been 
> able to come anywhere near the catastrophic situations I saw with the 
> 2.6.9 kernel, even by dirtying the full 8GB in fractions of a second.

OK, thanks.

> There was another strangeness there though: Even with the high memory 
> pressure applied, The ZONE_NORMAL free memory would never go below 
> ~300MB. When the mem pressure got too high, the kernel would rather free 
> almost slabs and start swapping than use those remaining 300M. It seems 
> to me that the new logic is a bit too conservative with ZONE_NORMAL 
> allocations.

Yes, we reserve lots of ZONE_NORMAL memory when performing GFP_HIGHMEM
allocations to avoid a weird corner case in which all of the lowmem memory
is pinned down because some application mlocked a lot of memory.

You can do

	echo 1000 > /proc/sys/vm/lowmem_reserve_ratio 

to get the old behaviour back (I do this all the time).


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2005-06-14 20:39 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-06-03 15:47 RFC for 2.6: avoid OOM at bounce buffer storm Martin Wilck
2005-06-03 23:06 ` Andrew Morton
2005-06-07 14:20   ` Martin Wilck
2005-06-07 19:08     ` Andrew Morton
2005-06-08 18:54       ` Martin Wilck
2005-06-08 21:46         ` Andrew Morton
2005-06-14 16:22           ` Martin Wilck
2005-06-14 20:38             ` Andrew Morton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®