Swap cache patch for pre-2.0.31-9

Krzysztof Strasburger (strasbur@chkw386.ch.pwr.wroc.pl)
Wed, 17 Sep 97 09:01


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;