PS Kurt, das ist vor allem fuer Linux Mama gedacht, als dieses Patch
geht wahrscheinlich nicht ins 2.0 Kernel.
Krzysztof Strasburger
diff -u --recursive linux.orig/Documentation/memory-tuning.txt linux/Documentation/memory-tuning.txt
--- linux.orig/Documentation/memory-tuning.txt Tue Aug 19 03:16:47 1997
+++ linux/Documentation/memory-tuning.txt Wed Jan 28 08:43:15 1998
@@ -46,3 +46,24 @@
The other three files in /proc/sys/vm are undocumented, as yet.
Thomas Koenig, ig25@rz.uni-karlsruhe.de
+
+The file /proc/sys/vm/spcache allows changing of the handling of swap cache
+(first number) and the policy of freeing page cache pages in the shrink_mmap
+function (second number).
+The first number (min_swap_pages) controls the minimal number of free swap
+entries. If nr_swap_pages falls below min_swap_pages, swap cache entries
+for accessed pages are freed.
+The second number (page_cache_mode) controls the behavior of the shrink_mmap
+function. If bit 0 is set, page cache pages not present in the page table
+of any process are freed even if the "referenced" bit is set. If bit 1 is set,
+page cache pages present in page tables are aged. Thus, removing of page
+cache pages from memory is preferred to swapping out private pages.
+
+Command "echo 128 3 > /proc/sys/vm/spcache" sets the threshold of free swap
+entries to 128 and enables most aggressive freeing of page cache pages.
+
+I've found that aggressive freeing of page cache pages may be useful
+for low memory machines, although the machinery works anyway much better
+now (2.0.33) than in the times of 2.0.30.
+
+Krzysztof Strasburger, strasbur@chkw386.ch.pwr.wroc.pl
diff -u --recursive linux.orig/include/linux/mm.h linux/include/linux/mm.h
--- linux.orig/include/linux/mm.h Tue Dec 2 22:18:11 1997
+++ linux/include/linux/mm.h Mon Jan 26 08:50:55 1998
@@ -10,6 +10,8 @@
#include <linux/string.h>
extern unsigned long high_memory;
+extern int min_swap_pages;
+extern int page_cache_mode;
#include <asm/page.h>
#include <asm/atomic.h>
diff -u --recursive linux.orig/include/linux/swap.h linux/include/linux/swap.h
--- linux.orig/include/linux/swap.h Mon Jun 3 12:38:37 1996
+++ linux/include/linux/swap.h Mon Jan 26 06:19:01 1998
@@ -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 --recursive linux.orig/include/linux/sysctl.h linux/include/linux/sysctl.h
--- linux.orig/include/linux/sysctl.h Tue Aug 12 21:06:35 1997
+++ linux/include/linux/sysctl.h Mon Jan 26 06:19:01 1998
@@ -67,7 +67,8 @@
#define VM_KSWAPD 2 /* struct: control background pageout */
#define VM_FREEPG 3 /* struct: Set free page thresholds */
#define VM_BDFLUSH 4 /* struct: Control buffer cache flushing */
-#define VM_MAXID 5
+#define VM_SPCACHE 5 /* struct: Control swap and page cache handling */
+#define VM_MAXID 6
/* CTL_NET names: */
#define NET_CORE 1
diff -u --recursive linux.orig/kernel/sysctl.c linux/kernel/sysctl.c
--- linux.orig/kernel/sysctl.c Wed Aug 13 22:02:42 1997
+++ linux/kernel/sysctl.c Mon Jan 26 06:19:02 1998
@@ -161,6 +161,8 @@
{VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&bdflush_min, &bdflush_max},
+ {VM_SPCACHE, "spcache",
+ &min_swap_pages, 2*sizeof(int), 0600, NULL, &proc_dointvec},
{0}
};
diff -u --recursive linux.orig/mm/filemap.c linux/mm/filemap.c
--- linux.orig/mm/filemap.c Thu Dec 11 02:09:44 1997
+++ linux/mm/filemap.c Wed Jan 28 08:53:09 1998
@@ -162,7 +162,8 @@
/* age this page potential used */
if (priority < 4)
age_page(page);
- break;
+ if (!(page->inode && (page_cache_mode & 0x1)))
+ break;
}
/* is it a page cache page? */
@@ -181,6 +182,8 @@
default:
/* more than one users: we can't throw it away */
set_bit(PG_referenced, &page->flags);
+ if (page->inode && (page_cache_mode & 0x2))
+ age_page(page);
/* fall through */
case 0:
/* nothing */
diff -u --recursive linux.orig/mm/mmap.c linux/mm/mmap.c
--- linux.orig/mm/mmap.c Fri Nov 7 17:57:31 1997
+++ linux/mm/mmap.c Mon Jan 26 06:24:35 1998
@@ -59,6 +59,7 @@
freepages >>= 1;
freepages += nr_free_pages;
freepages += nr_swap_pages;
+ freepages += nr_swap_cache_pages;
freepages -= MAP_NR(high_memory) >> 4;
return freepages > pages;
}
diff -u --recursive linux.orig/mm/swap.c linux/mm/swap.c
--- linux.orig/mm/swap.c Mon Jun 3 12:38:37 1996
+++ linux/mm/swap.c Mon Jan 26 06:19:02 1998
@@ -42,6 +42,10 @@
int free_pages_low = 30;
int free_pages_high = 40;
+/* And these two too... */
+int min_swap_pages = 256;
+int page_cache_mode = 0;
+
/* We track the number of pages currently being asynchronously swapped
out, so that we don't try to swap TOO many pages out at once */
atomic_t nr_async_pages = 0;
diff -u --recursive linux.orig/mm/swap_state.c linux/mm/swap_state.c
--- linux.orig/mm/swap_state.c Wed Mar 13 13:17:23 1996
+++ linux/mm/swap_state.c Mon Jan 26 06:19:02 1998
@@ -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 --recursive linux.orig/mm/swapfile.c linux/mm/swapfile.c
--- linux.orig/mm/swapfile.c Mon Mar 31 21:22:37 1997
+++ linux/mm/swapfile.c Mon Jan 26 06:22:26 1998
@@ -570,6 +570,7 @@
++val->totalswap;
}
}
+ val->freeswap += nr_swap_cache_pages;
val->freeswap <<= PAGE_SHIFT;
val->totalswap <<= PAGE_SHIFT;
return;
diff -u --recursive linux.orig/mm/vmscan.c linux/mm/vmscan.c
--- linux.orig/mm/vmscan.c Thu Dec 11 02:09:44 1997
+++ linux/mm/vmscan.c Mon Jan 26 08:25:57 1998
@@ -104,6 +104,8 @@
* is oldest). */
if ((pte_dirty(pte) && delete_from_swap_cache(MAP_NR(page)))
|| pte_young(pte)) {
+ if (pte_young(pte) && nr_swap_pages < min_swap_pages)
+ delete_from_swap_cache(MAP_NR(page));
set_pte(page_table, pte_mkold(pte));
touch_page(page_map);
return 0;