public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements
@ 2006-02-27 18:26 Rafael J. Wysocki
  2006-02-27 18:28 ` [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant Rafael J. Wysocki
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Rafael J. Wysocki @ 2006-02-27 18:26 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Andrew Morton, LKML

Hi,

The following two patches are designed to improve the shrink_all_memory()
function used by swsusp and other pm functions.

The first patch makes shrink_all_memory() overflow-resistant.  The problem is
that, AFAICT, balance_pgdat(pgdat, nr_to_free, 0) may free more than nr_to_free
pages, in which case nr_to_free, being unsigned, will overflow (and obviously
it cannot be less than 0).  Also if the argument is too big, strange things may
happen.

The first patch adds a workaround of the problem that shrink_all_memory() may
return 0 even if there still are some pages to free.  WIth this patch applied
it sometimes frees 2 times as many pages as without it on my box.

Please have a look and comment.

Greetings,
Rafael


-- 
Beer is proof that God loves us and wants us to be happy - Benjamin Franklin


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

* [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant
  2006-02-27 18:26 [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements Rafael J. Wysocki
@ 2006-02-27 18:28 ` Rafael J. Wysocki
  2006-02-27 18:53   ` Jesper Juhl
  2006-02-28  3:16   ` Andrew Morton
  2006-02-27 18:30 ` [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder Rafael J. Wysocki
  2006-02-27 18:33 ` [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements Pavel Machek
  2 siblings, 2 replies; 14+ messages in thread
From: Rafael J. Wysocki @ 2006-02-27 18:28 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Andrew Morton, LKML

Make shrink_all_memory() overflow-resistant.


Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 include/linux/swap.h |    2 +-
 mm/vmscan.c          |    9 +++++----
 2 files changed, 6 insertions(+), 5 deletions(-)

Index: linux-2.6.16-rc4-mm2/mm/vmscan.c
===================================================================
--- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
+++ linux-2.6.16-rc4-mm2/mm/vmscan.c
@@ -1785,18 +1785,19 @@ void wakeup_kswapd(struct zone *zone, in
  * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
  * pages.
  */
-int shrink_all_memory(unsigned long nr_pages)
+unsigned long shrink_all_memory(unsigned int nr_pages)
 {
 	pg_data_t *pgdat;
-	unsigned long nr_to_free = nr_pages;
-	int ret = 0;
+	long long nr_to_free = nr_pages;
+	unsigned long ret = 0;
 	struct reclaim_state reclaim_state = {
 		.reclaimed_slab = 0,
 	};
 
 	current->reclaim_state = &reclaim_state;
 	for_each_pgdat(pgdat) {
-		int freed;
+		unsigned long freed;
+
 		freed = balance_pgdat(pgdat, nr_to_free, 0);
 		ret += freed;
 		nr_to_free -= freed;
Index: linux-2.6.16-rc4-mm2/include/linux/swap.h
===================================================================
--- linux-2.6.16-rc4-mm2.orig/include/linux/swap.h
+++ linux-2.6.16-rc4-mm2/include/linux/swap.h
@@ -173,7 +173,7 @@ extern void swap_setup(void);
 
 /* linux/mm/vmscan.c */
 extern unsigned long try_to_free_pages(struct zone **, gfp_t);
-extern int shrink_all_memory(unsigned long nr_pages);
+extern unsigned long shrink_all_memory(unsigned int nr_pages);
 extern int vm_swappiness;
 
 #ifdef CONFIG_NUMA


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

* [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder
  2006-02-27 18:26 [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements Rafael J. Wysocki
  2006-02-27 18:28 ` [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant Rafael J. Wysocki
@ 2006-02-27 18:30 ` Rafael J. Wysocki
  2006-02-28  3:25   ` Andrew Morton
  2006-02-27 18:33 ` [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements Pavel Machek
  2 siblings, 1 reply; 14+ messages in thread
From: Rafael J. Wysocki @ 2006-02-27 18:30 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Andrew Morton, LKML

Make shrink_all_memory() repeat the attempts to free more memory if there
seems to be no pages to free.


Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 mm/vmscan.c |   22 +++++++++++++++-------
 1 files changed, 15 insertions(+), 7 deletions(-)

Index: linux-2.6.16-rc4-mm2/mm/vmscan.c
===================================================================
--- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
+++ linux-2.6.16-rc4-mm2/mm/vmscan.c
@@ -33,6 +33,7 @@
 #include <linux/cpuset.h>
 #include <linux/notifier.h>
 #include <linux/rwsem.h>
+#include <linux/delay.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -1793,17 +1794,24 @@ unsigned long shrink_all_memory(unsigned
 	struct reclaim_state reclaim_state = {
 		.reclaimed_slab = 0,
 	};
+	int retry = 2;
 
 	current->reclaim_state = &reclaim_state;
-	for_each_pgdat(pgdat) {
-		unsigned long freed;
+	do {
+		for_each_pgdat(pgdat) {
+			unsigned long freed;
 
-		freed = balance_pgdat(pgdat, nr_to_free, 0);
-		ret += freed;
-		nr_to_free -= freed;
-		if (nr_to_free <= 0)
+			freed = balance_pgdat(pgdat, nr_to_free, 0);
+			ret += freed;
+			nr_to_free -= freed;
+			if (nr_to_free <= 0)
+				break;
+		}
+		if (ret > 0)
 			break;
-	}
+		if (retry)
+			msleep_interruptible(100);
+	} while (retry--);
 	current->reclaim_state = NULL;
 	return ret;
 }

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

* Re: [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements
  2006-02-27 18:26 [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements Rafael J. Wysocki
  2006-02-27 18:28 ` [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant Rafael J. Wysocki
  2006-02-27 18:30 ` [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder Rafael J. Wysocki
@ 2006-02-27 18:33 ` Pavel Machek
  2 siblings, 0 replies; 14+ messages in thread
From: Pavel Machek @ 2006-02-27 18:33 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Andrew Morton, LKML

Hi!

> The following two patches are designed to improve the shrink_all_memory()
> function used by swsusp and other pm functions.
> 
> The first patch makes shrink_all_memory() overflow-resistant.  The problem is
> that, AFAICT, balance_pgdat(pgdat, nr_to_free, 0) may free more than nr_to_free
> pages, in which case nr_to_free, being unsigned, will overflow (and obviously
> it cannot be less than 0).  Also if the argument is too big, strange things may
> happen.
> 
> The first patch adds a workaround of the problem that shrink_all_memory() may
> return 0 even if there still are some pages to free.  WIth this patch applied
> it sometimes frees 2 times as many pages as without it on my box.
> 
> Please have a look and comment.

ACK on the first one, Andrew, please suggest how to do the second one
better.
								Pavel
-- 
Web maintainer for suspend.sf.net (www.sf.net/projects/suspend) wanted...

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

* Re: [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant
  2006-02-27 18:28 ` [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant Rafael J. Wysocki
@ 2006-02-27 18:53   ` Jesper Juhl
  2006-02-27 19:02     ` Pavel Machek
  2006-02-27 23:15     ` Rafael J. Wysocki
  2006-02-28  3:16   ` Andrew Morton
  1 sibling, 2 replies; 14+ messages in thread
From: Jesper Juhl @ 2006-02-27 18:53 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Pavel Machek, Andrew Morton, LKML

On 2/27/06, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> Make shrink_all_memory() overflow-resistant.
>
>
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
>  include/linux/swap.h |    2 +-
>  mm/vmscan.c          |    9 +++++----
>  2 files changed, 6 insertions(+), 5 deletions(-)
>
> Index: linux-2.6.16-rc4-mm2/mm/vmscan.c
> ===================================================================
> --- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
> +++ linux-2.6.16-rc4-mm2/mm/vmscan.c
> @@ -1785,18 +1785,19 @@ void wakeup_kswapd(struct zone *zone, in
>   * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
>   * pages.
>   */
> -int shrink_all_memory(unsigned long nr_pages)
> +unsigned long shrink_all_memory(unsigned int nr_pages)

What about the callers of shrink_all_memory() who currently expect it
to return an int, have you checked how they will react to you changing
the return type (and signedness) ?

>  {
>         pg_data_t *pgdat;
> -       unsigned long nr_to_free = nr_pages;
> -       int ret = 0;
> +       long long nr_to_free = nr_pages;

'nr_pages' passed to the function is an unsigned int, why this change?
also, nr_to_free is later passed to balance_pgdat() as the second
argument and balance_pgdat() expects to be passed an int.


> +       unsigned long ret = 0;
>         struct reclaim_state reclaim_state = {
>                 .reclaimed_slab = 0,
>         };
>
>         current->reclaim_state = &reclaim_state;
>         for_each_pgdat(pgdat) {
> -               int freed;
> +               unsigned long freed;

balance_pgdat() returns a plain int, so what's the point of making
'freed' an unsigned long?


> +
>                 freed = balance_pgdat(pgdat, nr_to_free, 0);
>                 ret += freed;
>                 nr_to_free -= freed;
> Index: linux-2.6.16-rc4-mm2/include/linux/swap.h
> ===================================================================
> --- linux-2.6.16-rc4-mm2.orig/include/linux/swap.h
> +++ linux-2.6.16-rc4-mm2/include/linux/swap.h
> @@ -173,7 +173,7 @@ extern void swap_setup(void);
>
>  /* linux/mm/vmscan.c */
>  extern unsigned long try_to_free_pages(struct zone **, gfp_t);
> -extern int shrink_all_memory(unsigned long nr_pages);
> +extern unsigned long shrink_all_memory(unsigned int nr_pages);
>  extern int vm_swappiness;
>
>  #ifdef CONFIG_NUMA
>


This patch may be correct or it may be wrong, I've not spend enough
time staring at it and follow the code it calls and gets called by to
say which, but I for one would like an explanation of why these
changes are made and why they are correct.
There's a distinct lack of a changelog/explanation with this patch.
Or maybe I'm just dense and can't see the obvious correctness, but if
that's the case I'd still like to be enlightened :)


--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post  http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please      http://www.expita.com/nomime.html

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

* Re: [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant
  2006-02-27 18:53   ` Jesper Juhl
@ 2006-02-27 19:02     ` Pavel Machek
  2006-02-27 19:06       ` Jesper Juhl
  2006-02-27 23:15     ` Rafael J. Wysocki
  1 sibling, 1 reply; 14+ messages in thread
From: Pavel Machek @ 2006-02-27 19:02 UTC (permalink / raw)
  To: Jesper Juhl; +Cc: Rafael J. Wysocki, Andrew Morton, LKML

On Po 27-02-06 19:53:47, Jesper Juhl wrote:
> On 2/27/06, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > Make shrink_all_memory() overflow-resistant.
> >
> >
> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> > ---
> >  include/linux/swap.h |    2 +-
> >  mm/vmscan.c          |    9 +++++----
> >  2 files changed, 6 insertions(+), 5 deletions(-)
> >
> > Index: linux-2.6.16-rc4-mm2/mm/vmscan.c
> > ===================================================================
> > --- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
> > +++ linux-2.6.16-rc4-mm2/mm/vmscan.c
> > @@ -1785,18 +1785,19 @@ void wakeup_kswapd(struct zone *zone, in
> >   * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
> >   * pages.
> >   */
> > -int shrink_all_memory(unsigned long nr_pages)
> > +unsigned long shrink_all_memory(unsigned int nr_pages)
> 
> What about the callers of shrink_all_memory() who currently expect it
> to return an int, have you checked how they will react to you changing
> the return type (and signedness) ?

That's okay, we checked all 3 callers :-).
									Pavel
-- 
Web maintainer for suspend.sf.net (www.sf.net/projects/suspend) wanted...

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

* Re: [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant
  2006-02-27 19:02     ` Pavel Machek
@ 2006-02-27 19:06       ` Jesper Juhl
  0 siblings, 0 replies; 14+ messages in thread
From: Jesper Juhl @ 2006-02-27 19:06 UTC (permalink / raw)
  To: Pavel Machek; +Cc: Rafael J. Wysocki, Andrew Morton, LKML

On 2/27/06, Pavel Machek <pavel@suse.cz> wrote:
> On Po 27-02-06 19:53:47, Jesper Juhl wrote:
> > On 2/27/06, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > > Make shrink_all_memory() overflow-resistant.
> > >
> > >
> > > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> > > ---
> > >  include/linux/swap.h |    2 +-
> > >  mm/vmscan.c          |    9 +++++----
> > >  2 files changed, 6 insertions(+), 5 deletions(-)
> > >
> > > Index: linux-2.6.16-rc4-mm2/mm/vmscan.c
> > > ===================================================================
> > > --- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
> > > +++ linux-2.6.16-rc4-mm2/mm/vmscan.c
> > > @@ -1785,18 +1785,19 @@ void wakeup_kswapd(struct zone *zone, in
> > >   * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
> > >   * pages.
> > >   */
> > > -int shrink_all_memory(unsigned long nr_pages)
> > > +unsigned long shrink_all_memory(unsigned int nr_pages)
> >
> > What about the callers of shrink_all_memory() who currently expect it
> > to return an int, have you checked how they will react to you changing
> > the return type (and signedness) ?
>
> That's okay, we checked all 3 callers :-).

I'm sure you did, I'm not saying you didn't.
All I'm asking for is a short explanation of why the changes the patch
makes are correct since that's not obvious to me, and I'd like to
understand the patch.

--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post  http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please      http://www.expita.com/nomime.html

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

* Re: [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant
  2006-02-27 18:53   ` Jesper Juhl
  2006-02-27 19:02     ` Pavel Machek
@ 2006-02-27 23:15     ` Rafael J. Wysocki
  1 sibling, 0 replies; 14+ messages in thread
From: Rafael J. Wysocki @ 2006-02-27 23:15 UTC (permalink / raw)
  To: Jesper Juhl; +Cc: Pavel Machek, Andrew Morton, LKML

Hi,

On Monday 27 February 2006 19:53, Jesper Juhl wrote:
> On 2/27/06, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > Make shrink_all_memory() overflow-resistant.
> >
> >
> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> > ---
> >  include/linux/swap.h |    2 +-
> >  mm/vmscan.c          |    9 +++++----
> >  2 files changed, 6 insertions(+), 5 deletions(-)
> >
> > Index: linux-2.6.16-rc4-mm2/mm/vmscan.c
> > ===================================================================
> > --- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
> > +++ linux-2.6.16-rc4-mm2/mm/vmscan.c
> > @@ -1785,18 +1785,19 @@ void wakeup_kswapd(struct zone *zone, in
> >   * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
> >   * pages.
> >   */
> > -int shrink_all_memory(unsigned long nr_pages)
> > +unsigned long shrink_all_memory(unsigned int nr_pages)
> 
> What about the callers of shrink_all_memory() who currently expect it
> to return an int, have you checked how they will react to you changing
> the return type (and signedness) ?

AFAICT, there are not any.

> >  {
> >         pg_data_t *pgdat;
> > -       unsigned long nr_to_free = nr_pages;
> > -       int ret = 0;
> > +       long long nr_to_free = nr_pages;
> 
> 'nr_pages' passed to the function is an unsigned int, why this change?
> also, nr_to_free is later passed to balance_pgdat() as the second
> argument and balance_pgdat() expects to be passed an int.

First, the balance_pgdat() in the current -mm expects to be passed
unsigned long here.

Second, say you pass 100 and balance_pgdat() returns 110.  Then if
nr_to_free is unsigned, it will become a huge positive number instead of
a negative number, as it should be.  Thus it has to be signed IMO.

It could be long, but on i386 long is the same as int.

> > +       unsigned long ret = 0;
> >         struct reclaim_state reclaim_state = {
> >                 .reclaimed_slab = 0,
> >         };
> >
> >         current->reclaim_state = &reclaim_state;
> >         for_each_pgdat(pgdat) {
> > -               int freed;
> > +               unsigned long freed;
> 
> balance_pgdat() returns a plain int, so what's the point of making
> 'freed' an unsigned long?

Well, at least the balance_pgdat() I'm looking at now returns
unsigned long.

> > +
> >                 freed = balance_pgdat(pgdat, nr_to_free, 0);
> >                 ret += freed;
> >                 nr_to_free -= freed;
> > Index: linux-2.6.16-rc4-mm2/include/linux/swap.h
> > ===================================================================
> > --- linux-2.6.16-rc4-mm2.orig/include/linux/swap.h
> > +++ linux-2.6.16-rc4-mm2/include/linux/swap.h
> > @@ -173,7 +173,7 @@ extern void swap_setup(void);
> >
> >  /* linux/mm/vmscan.c */
> >  extern unsigned long try_to_free_pages(struct zone **, gfp_t);
> > -extern int shrink_all_memory(unsigned long nr_pages);
> > +extern unsigned long shrink_all_memory(unsigned int nr_pages);
> >  extern int vm_swappiness;
> >
> >  #ifdef CONFIG_NUMA
> >
> 
> 
> This patch may be correct or it may be wrong, I've not spend enough
> time staring at it and follow the code it calls and gets called by to
> say which, but I for one would like an explanation of why these
> changes are made and why they are correct.
> There's a distinct lack of a changelog/explanation with this patch.
> Or maybe I'm just dense and can't see the obvious correctness, but if
> that's the case I'd still like to be enlightened :)

Perhaps I should have explained it in a more detailed way in the
changelog.

The problem is that, AFAICT, balance_pgdat(pgdat, nr_to_free, 0) may free
more than nr_to_free pages, in which case nr_to_free, being unsigned, will
overflow (and obviously it cannot be less than 0).  Also if nr_pages is
too big, strange things may happen (without the patch, that is).

Greetings,
Rafael

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

* Re: [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant
  2006-02-27 18:28 ` [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant Rafael J. Wysocki
  2006-02-27 18:53   ` Jesper Juhl
@ 2006-02-28  3:16   ` Andrew Morton
  2006-02-28 17:28     ` Rafael J. Wysocki
  1 sibling, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2006-02-28  3:16 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: pavel, linux-kernel

"Rafael J. Wysocki" <rjw@sisk.pl> wrote:
>
> Make shrink_all_memory() overflow-resistant.
> 

As you've probably noticed, I'm moving toward making all the scalars which
hold counts of pages in the VM toward unsigned long.  For uniformity, and
because there is a small risk that a huge machine with 4k pages could
actually overflow a 32-bit counter.

> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
>  include/linux/swap.h |    2 +-
>  mm/vmscan.c          |    9 +++++----
>  2 files changed, 6 insertions(+), 5 deletions(-)
> 
> Index: linux-2.6.16-rc4-mm2/mm/vmscan.c
> ===================================================================
> --- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
> +++ linux-2.6.16-rc4-mm2/mm/vmscan.c
> @@ -1785,18 +1785,19 @@ void wakeup_kswapd(struct zone *zone, in
>   * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
>   * pages.
>   */
> -int shrink_all_memory(unsigned long nr_pages)
> +unsigned long shrink_all_memory(unsigned int nr_pages)

So nr_pages should remain unsigned long.

> +	long long nr_to_free = nr_pages;

As should nr_to_free.

The actual bug is the (unsigned <= 0) thing.   So how's about this?

--- devel/include/linux/swap.h~vmscan-use-unsigned-longs-shrink_all_memory-fix	2006-02-27 19:13:30.000000000 -0800
+++ devel-akpm/include/linux/swap.h	2006-02-27 19:13:30.000000000 -0800
@@ -173,7 +173,7 @@ extern void swap_setup(void);
 
 /* linux/mm/vmscan.c */
 extern unsigned long try_to_free_pages(struct zone **, gfp_t);
-extern int shrink_all_memory(unsigned long nr_pages);
+extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
 
 #ifdef CONFIG_NUMA
--- devel/mm/vmscan.c~vmscan-use-unsigned-longs-shrink_all_memory-fix	2006-02-27 19:13:30.000000000 -0800
+++ devel-akpm/mm/vmscan.c	2006-02-27 19:13:30.000000000 -0800
@@ -1779,22 +1779,23 @@ void wakeup_kswapd(struct zone *zone, in
  * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
  * pages.
  */
-int shrink_all_memory(unsigned long nr_pages)
+unsigned long shrink_all_memory(unsigned long nr_pages)
 {
 	pg_data_t *pgdat;
 	unsigned long nr_to_free = nr_pages;
-	int ret = 0;
+	unsigned long ret = 0;
 	struct reclaim_state reclaim_state = {
 		.reclaimed_slab = 0,
 	};
 
 	current->reclaim_state = &reclaim_state;
 	for_each_pgdat(pgdat) {
-		int freed;
+		unsigned long freed;
+
 		freed = balance_pgdat(pgdat, nr_to_free, 0);
 		ret += freed;
 		nr_to_free -= freed;
-		if (nr_to_free <= 0)
+		if ((long)nr_to_free <= 0)
 			break;
 	}
 	current->reclaim_state = NULL;
_


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

* Re: [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder
  2006-02-27 18:30 ` [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder Rafael J. Wysocki
@ 2006-02-28  3:25   ` Andrew Morton
  2006-02-28 17:25     ` Rafael J. Wysocki
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2006-02-28  3:25 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: pavel, linux-kernel

"Rafael J. Wysocki" <rjw@sisk.pl> wrote:
>
> Make shrink_all_memory() repeat the attempts to free more memory if there
> seems to be no pages to free.
> 

This description doesn't describe what the problem is, not how the patch
fixes it.  So I'm kinda left guessing.

> ===================================================================
> --- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
> +++ linux-2.6.16-rc4-mm2/mm/vmscan.c
> @@ -33,6 +33,7 @@
>  #include <linux/cpuset.h>
>  #include <linux/notifier.h>
>  #include <linux/rwsem.h>
> +#include <linux/delay.h>
>  
>  #include <asm/tlbflush.h>
>  #include <asm/div64.h>
> @@ -1793,17 +1794,24 @@ unsigned long shrink_all_memory(unsigned
>  	struct reclaim_state reclaim_state = {
>  		.reclaimed_slab = 0,
>  	};
> +	int retry = 2;
>  
>  	current->reclaim_state = &reclaim_state;
> -	for_each_pgdat(pgdat) {
> -		unsigned long freed;
> +	do {
> +		for_each_pgdat(pgdat) {
> +			unsigned long freed;
>  
> -		freed = balance_pgdat(pgdat, nr_to_free, 0);
> -		ret += freed;
> -		nr_to_free -= freed;
> -		if (nr_to_free <= 0)
> +			freed = balance_pgdat(pgdat, nr_to_free, 0);
> +			ret += freed;
> +			nr_to_free -= freed;
> +			if (nr_to_free <= 0)
> +				break;
> +		}
> +		if (ret > 0)
>  			break;
> -	}
> +		if (retry)
> +			msleep_interruptible(100);

TASK_INTERRUPTIBLE sleeps won't do anything if someone has sent this
process a signal.    They should be used with caution.


Something like the below, I guess.  But it's hard to fix something when you
don't know what you're fixing.

swsusp should call drop_pagecache() and then drop_slab() before trying to
use shrink_all_memory(), btw.


diff -puN mm/vmscan.c~mm-make-shrink_all_memory-try-harder mm/vmscan.c
--- devel/mm/vmscan.c~mm-make-shrink_all_memory-try-harder	2006-02-27 19:17:29.000000000 -0800
+++ devel-akpm/mm/vmscan.c	2006-02-27 19:21:08.000000000 -0800
@@ -33,6 +33,7 @@
 #include <linux/cpuset.h>
 #include <linux/notifier.h>
 #include <linux/rwsem.h>
+#include <linux/delay.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -1783,11 +1784,13 @@ unsigned long shrink_all_memory(unsigned
 	pg_data_t *pgdat;
 	unsigned long nr_to_free = nr_pages;
 	unsigned long ret = 0;
+	unsigned retry = 2;
 	struct reclaim_state reclaim_state = {
 		.reclaimed_slab = 0,
 	};
 
 	current->reclaim_state = &reclaim_state;
+repeat:
 	for_each_pgdat(pgdat) {
 		unsigned long freed;
 
@@ -1797,6 +1800,10 @@ unsigned long shrink_all_memory(unsigned
 		if ((long)nr_to_free <= 0)
 			break;
 	}
+	if (retry-- && ret < nr_pages) {
+		blk_congestion_wait(WRITE, HZ/5);
+		goto repeat;
+	}
 	current->reclaim_state = NULL;
 	return ret;
 }
_

But then, the above could be implemented by the caller, so I don't know
what's going on..


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

* Re: [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder
  2006-02-28  3:25   ` Andrew Morton
@ 2006-02-28 17:25     ` Rafael J. Wysocki
  2006-02-28 18:46       ` Andrew Morton
  0 siblings, 1 reply; 14+ messages in thread
From: Rafael J. Wysocki @ 2006-02-28 17:25 UTC (permalink / raw)
  To: Andrew Morton; +Cc: pavel, linux-kernel

On Tuesday 28 February 2006 04:25, Andrew Morton wrote:
> "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> >
> > Make shrink_all_memory() repeat the attempts to free more memory if there
> > seems to be no pages to free.
> > 
> 
> This description doesn't describe what the problem is, not how the patch
> fixes it.  So I'm kinda left guessing.

I have described it in the 0/0 message, but I should have repeated that in the
changelog, sorry.

The probelm is that shrink_all_memory() sometimes returns 0 when there are
some freeable pages left.  In swsusp we stop freeing memory when
shrink_all_memory() returns 0, so this is a problem to us.

> > ===================================================================
> > --- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
> > +++ linux-2.6.16-rc4-mm2/mm/vmscan.c
> > @@ -33,6 +33,7 @@
> >  #include <linux/cpuset.h>
> >  #include <linux/notifier.h>
> >  #include <linux/rwsem.h>
> > +#include <linux/delay.h>
> >  
> >  #include <asm/tlbflush.h>
> >  #include <asm/div64.h>
> > @@ -1793,17 +1794,24 @@ unsigned long shrink_all_memory(unsigned
> >  	struct reclaim_state reclaim_state = {
> >  		.reclaimed_slab = 0,
> >  	};
> > +	int retry = 2;
> >  
> >  	current->reclaim_state = &reclaim_state;
> > -	for_each_pgdat(pgdat) {
> > -		unsigned long freed;
> > +	do {
> > +		for_each_pgdat(pgdat) {
> > +			unsigned long freed;
> >  
> > -		freed = balance_pgdat(pgdat, nr_to_free, 0);
> > -		ret += freed;
> > -		nr_to_free -= freed;
> > -		if (nr_to_free <= 0)
> > +			freed = balance_pgdat(pgdat, nr_to_free, 0);
> > +			ret += freed;
> > +			nr_to_free -= freed;
> > +			if (nr_to_free <= 0)
> > +				break;
> > +		}
> > +		if (ret > 0)
> >  			break;
> > -	}
> > +		if (retry)
> > +			msleep_interruptible(100);
> 
> TASK_INTERRUPTIBLE sleeps won't do anything if someone has sent this
> process a signal.    They should be used with caution.
> 
> 
> Something like the below, I guess.  But it's hard to fix something when you
> don't know what you're fixing.

Sorry again.

> swsusp should call drop_pagecache() and then drop_slab() before trying to
> use shrink_all_memory(), btw.

Well, sometimes we don't need to free a lot of memory.

> diff -puN mm/vmscan.c~mm-make-shrink_all_memory-try-harder mm/vmscan.c
> --- devel/mm/vmscan.c~mm-make-shrink_all_memory-try-harder	2006-02-27 19:17:29.000000000 -0800
> +++ devel-akpm/mm/vmscan.c	2006-02-27 19:21:08.000000000 -0800
> @@ -33,6 +33,7 @@
>  #include <linux/cpuset.h>
>  #include <linux/notifier.h>
>  #include <linux/rwsem.h>
> +#include <linux/delay.h>
>  
>  #include <asm/tlbflush.h>
>  #include <asm/div64.h>
> @@ -1783,11 +1784,13 @@ unsigned long shrink_all_memory(unsigned
>  	pg_data_t *pgdat;
>  	unsigned long nr_to_free = nr_pages;
>  	unsigned long ret = 0;
> +	unsigned retry = 2;
>  	struct reclaim_state reclaim_state = {
>  		.reclaimed_slab = 0,
>  	};
>  
>  	current->reclaim_state = &reclaim_state;
> +repeat:
>  	for_each_pgdat(pgdat) {
>  		unsigned long freed;
>  
> @@ -1797,6 +1800,10 @@ unsigned long shrink_all_memory(unsigned
>  		if ((long)nr_to_free <= 0)
>  			break;
>  	}
> +	if (retry-- && ret < nr_pages) {
> +		blk_congestion_wait(WRITE, HZ/5);
> +		goto repeat;
> +	}

I'd like to do this only if ret is 0.

>  	current->reclaim_state = NULL;
>  	return ret;
>  }
> _
> 
> But then, the above could be implemented by the caller, so I don't know
> what's going on..

If 0 is returned, the caller assumes there are no more freeable pages.


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

* Re: [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant
  2006-02-28  3:16   ` Andrew Morton
@ 2006-02-28 17:28     ` Rafael J. Wysocki
  0 siblings, 0 replies; 14+ messages in thread
From: Rafael J. Wysocki @ 2006-02-28 17:28 UTC (permalink / raw)
  To: Andrew Morton; +Cc: pavel, linux-kernel

On Tuesday 28 February 2006 04:16, Andrew Morton wrote:
> "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> >
> > Make shrink_all_memory() overflow-resistant.
> > 
> 
> As you've probably noticed, I'm moving toward making all the scalars which
> hold counts of pages in the VM toward unsigned long.  For uniformity, and
> because there is a small risk that a huge machine with 4k pages could
> actually overflow a 32-bit counter.
> 
> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> > ---
> >  include/linux/swap.h |    2 +-
> >  mm/vmscan.c          |    9 +++++----
> >  2 files changed, 6 insertions(+), 5 deletions(-)
> > 
> > Index: linux-2.6.16-rc4-mm2/mm/vmscan.c
> > ===================================================================
> > --- linux-2.6.16-rc4-mm2.orig/mm/vmscan.c
> > +++ linux-2.6.16-rc4-mm2/mm/vmscan.c
> > @@ -1785,18 +1785,19 @@ void wakeup_kswapd(struct zone *zone, in
> >   * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
> >   * pages.
> >   */
> > -int shrink_all_memory(unsigned long nr_pages)
> > +unsigned long shrink_all_memory(unsigned int nr_pages)
> 
> So nr_pages should remain unsigned long.
> 
> > +	long long nr_to_free = nr_pages;
> 
> As should nr_to_free.

OK

> The actual bug is the (unsigned <= 0) thing.   So how's about this?

I like it (if my opinion matters here ;-)).  Thanks a lot.


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

* Re: [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder
  2006-02-28 17:25     ` Rafael J. Wysocki
@ 2006-02-28 18:46       ` Andrew Morton
  2006-02-28 23:04         ` Rafael J. Wysocki
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2006-02-28 18:46 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: pavel, linux-kernel

"Rafael J. Wysocki" <rjw@sisk.pl> wrote:
>
> On Tuesday 28 February 2006 04:25, Andrew Morton wrote:
> > "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> > >
> > > Make shrink_all_memory() repeat the attempts to free more memory if there
> > > seems to be no pages to free.
> > > 
> > 
> > This description doesn't describe what the problem is, not how the patch
> > fixes it.  So I'm kinda left guessing.
> 
> I have described it in the 0/0 message, but I should have repeated that in the
> changelog, sorry.

Actually these [patch 0/n] emails are a nuisance - some poor schmuck just
has to copy-n-paste that text into the fist patch's changelog anwyay.

> > swsusp should call drop_pagecache() and then drop_slab() before trying to
> > use shrink_all_memory(), btw.
> 
> Well, sometimes we don't need to free a lot of memory.

OK.  But if clean pagecache and reclaimable slabs are left in memory,
they'll have to be written to swap, won't they?

It could well be more efficent to restore them from swap.  Slower suspend,
faster resume.

> > +	if (retry-- && ret < nr_pages) {
> > +		blk_congestion_wait(WRITE, HZ/5);
> > +		goto repeat;
> > +	}
> 
> I'd like to do this only if ret is 0.

Well I figured that this was a more general approach: we were _asked_ to
free that many pages.  If we haven't done that yet, keep trying.  Can you
test that code please?


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

* Re: [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder
  2006-02-28 18:46       ` Andrew Morton
@ 2006-02-28 23:04         ` Rafael J. Wysocki
  0 siblings, 0 replies; 14+ messages in thread
From: Rafael J. Wysocki @ 2006-02-28 23:04 UTC (permalink / raw)
  To: Andrew Morton; +Cc: pavel, linux-kernel

On Tuesday 28 February 2006 19:46, Andrew Morton wrote:
> "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> >
> > On Tuesday 28 February 2006 04:25, Andrew Morton wrote:
> > > "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> > > >
> > > > Make shrink_all_memory() repeat the attempts to free more memory if there
> > > > seems to be no pages to free.
> > > > 
> > > 
> > > This description doesn't describe what the problem is, not how the patch
> > > fixes it.  So I'm kinda left guessing.
> > 
> > I have described it in the 0/0 message, but I should have repeated that in the
> > changelog, sorry.
> 
> Actually these [patch 0/n] emails are a nuisance - some poor schmuck just
> has to copy-n-paste that text into the fist patch's changelog anwyay.
> 
> > > swsusp should call drop_pagecache() and then drop_slab() before trying to
> > > use shrink_all_memory(), btw.
> > 
> > Well, sometimes we don't need to free a lot of memory.
> 
> OK.  But if clean pagecache and reclaimable slabs are left in memory,
> they'll have to be written to swap, won't they?

Yes, but then we write them more or less linearly and we can also compress
them. :-)
 
> It could well be more efficent to restore them from swap.  Slower suspend,
> faster resume.
> 
> > > +	if (retry-- && ret < nr_pages) {
> > > +		blk_congestion_wait(WRITE, HZ/5);
> > > +		goto repeat;
> > > +	}
> > 
> > I'd like to do this only if ret is 0.
> 
> Well I figured that this was a more general approach: we were _asked_ to
> free that many pages.  If we haven't done that yet, keep trying.  Can you
> test that code please?

So far, it works just fine.  Thanks.

[Tested on 2.6.16-rc4-mm2, because -rc5-mm1 crashes on my system in a
spectacular way (already reported separately).]

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

end of thread, other threads:[~2006-02-28 23:04 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-27 18:26 [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements Rafael J. Wysocki
2006-02-27 18:28 ` [RFC][PATCH -mm 1/2] mm: make shrink_all_memory overflow-resistant Rafael J. Wysocki
2006-02-27 18:53   ` Jesper Juhl
2006-02-27 19:02     ` Pavel Machek
2006-02-27 19:06       ` Jesper Juhl
2006-02-27 23:15     ` Rafael J. Wysocki
2006-02-28  3:16   ` Andrew Morton
2006-02-28 17:28     ` Rafael J. Wysocki
2006-02-27 18:30 ` [RFC][PATCH -mm 2/2] mm: make shrink_all_memory try harder Rafael J. Wysocki
2006-02-28  3:25   ` Andrew Morton
2006-02-28 17:25     ` Rafael J. Wysocki
2006-02-28 18:46       ` Andrew Morton
2006-02-28 23:04         ` Rafael J. Wysocki
2006-02-27 18:33 ` [RFC][PATCH -mm 0/2] mm: shrink_all_memory improvements Pavel Machek

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