Re: MAJOR memory leak in 2.0.31-pre9

Dr. Werner Fink (werner@suse.de)
Fri, 19 Sep 1997 13:58:41 +0200


> Once upon a time, Michael Meskes wrote
> > I'm not completely sure, but isn't some of the memory info computed as
> > 'memory we would need if we couldn't share some parts'? So just counting and
> > comparing these numbers is quite misleading.
>
> Yeah, but in that case, the sum of the SIZE numbers from ps is bigger
> than the sum of used memory and used swap (not counting buffers). What
> I got was the other way around - the sum of the SIZE numbers from ps was
> 80MB _smaller_ than the sum of used mem and swap as reported by free in
> 2.0.31pre9. Currently, under 2.0.29, the SIZEs add up to 97524, and the
> amount of memory + swap used is only 49440, which is normal.

Have you tried Krzysztof Strasburger "Swap cache patch for pre-2.0.31-9"?
Does this one make a difference?

Werner

Krzysztof's patch:
-------------------------------------------------------------------------
Return-Path: <owner-linux-kernel-outgoing@vger.rutgers.edu>
Date: Wed, 17 Sep 97 09:01
From: strasbur@chkw386.ch.pwr.wroc.pl (Krzysztof Strasburger)
To: linux-kernel@vger.rutgers.edu
Subject: Swap cache patch for pre-2.0.31-9
X-Orcpt: rfc822;linux-kernel@vger.rutgers.edu
Sender: owner-linux-kernel@vger.rutgers.edu
Precedence: bulk

Hi all!
Here is my swap cache patch for pre-2.0.31-9. It was present in pre-1 and
pre-2, but Linus forgot (rejected?) it. I couple it with the page cache patch
no longer, as they fix different things (bug and feature ;-).
And a short summary. There is a structure called swap cache in the kernel.
If the page is read from the swap area, we have its copy still kept there.
If the page must be then swapped out and it is not dirty, we can simply
free it without writing to the swap area (there is an actual copy there).
Problem: pages in the swap cache (occupying the swap area) are not counted
as free. They should be treated as free, because each request for freeing
the page which has its counterpart in the swap cache does not allocate an
additional swap entry. On the other hand, if the page is dirty, the swap
entry is freed.
Effects: let us run a program, which uses 9 MB of memory and we have
8 MB RAM + 8 MB swap (the bug has been found in such circumstances).
The whole swap area is eaten by the swap cache and no new programs can be run.
It doesn't matter that we have still 7 MB of free VM.
Regards
Krzysztof Strasburger

diff -u -r linux.orig/include/linux/swap.h linux/include/linux/swap.h
--- linux.orig/include/linux/swap.h Mon Jun 3 14:38:37 1996
+++ linux/include/linux/swap.h Fri Apr 18 17:11:22 1997
@@ -34,6 +34,7 @@

extern int nr_swap_pages;
extern int nr_free_pages;
+extern int nr_swap_cache_pages;
extern atomic_t nr_async_pages;
extern int min_free_pages;
extern int free_pages_low;
@@ -113,10 +114,12 @@
swap_cache_find_total++;
#endif
entry = xchg(swap_cache + index, 0);
+ if (entry) {
#ifdef SWAP_CACHE_INFO
- if (entry)
swap_cache_find_success++;
#endif
+ nr_swap_cache_pages--;
+ }
return entry;
}

@@ -133,6 +136,7 @@
swap_cache_del_success++;
#endif
swap_free(entry);
+ nr_swap_cache_pages--;
return 1;
}
return 0;
diff -u -r linux.orig/mm/mmap.c linux/mm/mmap.c
--- linux.orig/mm/mmap.c Fri Dec 6 22:09:24 1996
+++ linux/mm/mmap.c Fri Apr 18 17:12:08 1997
@@ -55,9 +55,10 @@
long freepages;
freepages = buffermem >> PAGE_SHIFT;
freepages += page_cache_size;
- freepages >>= 1;
+/* freepages >>= 1; 64 MB used as buffers and you can't run a 50 MB program */
freepages += nr_free_pages;
freepages += nr_swap_pages;
+ freepages += nr_swap_cache_pages;
freepages -= MAP_NR(high_memory) >> 4;
return freepages > pages;
}
diff -u -r linux.orig/mm/swap_state.c linux/mm/swap_state.c
--- linux.orig/mm/swap_state.c Wed Mar 13 14:17:23 1996
+++ linux/mm/swap_state.c Fri Apr 18 17:12:11 1997
@@ -32,6 +32,8 @@
*/
unsigned long *swap_cache;

+int nr_swap_cache_pages = 0;
+
#ifdef SWAP_CACHE_INFO
unsigned long swap_cache_add_total = 0;
unsigned long swap_cache_add_success = 0;
@@ -64,6 +66,7 @@
#ifdef SWAP_CACHE_INFO
swap_cache_add_success++;
#endif
+ nr_swap_cache_pages++;
return 1;
}
return 0;
diff -u -r linux.orig/mm/swapfile.c linux/mm/swapfile.c
--- linux.orig/mm/swapfile.c Thu Apr 10 23:47:14 1997
+++ linux/mm/swapfile.c Fri Apr 18 17:12:12 1997
@@ -570,6 +570,7 @@
++val->totalswap;
}
}
+ val->freeswap += nr_swap_cache_pages;
val->freeswap <<= PAGE_SHIFT;
val->totalswap <<= PAGE_SHIFT;
return;