2.0.33 - swap and page cache - last trial

Krzysztof Strasburger (strasbur@chkw386.ch.pwr.wroc.pl)
Fri, 30 Jan 98 08:54


Hi all!
Here is the latest version of the swap and page cache patch. Previous
version should go to /dev/null. I finally understood how the referenced
bit works.
This patch contains a partial solution of the problem pointed out
by Stephen - possible memory overcommit while page cache entries are
locked by frequently accessed pages.

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;