diff -urN 2.4.10/include/linux/fs.h vm/include/linux/fs.h
--- 2.4.10/include/linux/fs.h Sun Sep 23 21:11:42 2001
+++ vm/include/linux/fs.h Wed Sep 26 15:34:35 2001
@@ -282,7 +282,7 @@
extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long offset);
-#define touch_buffer(bh) SetPageReferenced(bh->b_page)
+#define touch_buffer(bh) mark_page_accessed(bh->b_page)
#include <linux/pipe_fs_i.h>
diff -urN 2.4.10/mm/filemap.c vm/mm/filemap.c
--- 2.4.10/mm/filemap.c Sun Sep 23 21:11:43 2001
+++ vm/mm/filemap.c Wed Sep 26 15:34:35 2001
@@ -1704,7 +1704,7 @@
* and possibly copy it over to another page..
*/
old_page = page;
- mark_page_accessed(page);
+ activate_page(page);
if (no_share) {
struct page *new_page = alloc_page(GFP_HIGHUSER);
diff -urN 2.4.10/mm/swap.c vm/mm/swap.c
--- 2.4.10/mm/swap.c Sun Sep 23 21:11:43 2001
+++ vm/mm/swap.c Wed Sep 26 15:34:35 2001
@@ -54,6 +54,7 @@
del_page_from_active_list(page);
add_page_to_inactive_list(page);
}
+ SetPageReferenced(page);
}
void deactivate_page(struct page * page)
@@ -72,6 +73,7 @@
del_page_from_inactive_list(page);
add_page_to_active_list(page);
}
+ ClearPageReferenced(page);
}
void activate_page(struct page * page)
diff -urN 2.4.10/mm/vmscan.c vm/mm/vmscan.c
--- 2.4.10/mm/vmscan.c Sun Sep 23 21:11:43 2001
+++ vm/mm/vmscan.c Wed Sep 26 15:35:03 2001
@@ -55,6 +55,9 @@
return 0;
}
+ if (PageActive(page) || (PageInactive(page) && PageReferenced(page)))
+ return 0;
+
if (TryLockPage(page))
return 0;
@@ -329,7 +332,6 @@
{
struct list_head * entry;
- spin_lock(&pagemap_lru_lock);
while (max_scan && (entry = inactive_list.prev) != &inactive_list) {
struct page * page;
swp_entry_t swap;
@@ -358,8 +360,10 @@
continue;
/* Racy check to avoid trylocking when not worthwhile */
- if (!page->buffers && page_count(page) != 1)
+ if (!page->buffers && page_count(page) != 1) {
+ activate_page_nolock(page);
continue;
+ }
/*
* The page is locked. IO in progress?
@@ -514,7 +518,6 @@
{
struct list_head * entry;
- spin_lock(&pagemap_lru_lock);
entry = active_list.prev;
while (nr_pages-- && entry != &active_list) {
struct page * page;
@@ -529,23 +532,28 @@
del_page_from_active_list(page);
add_page_to_inactive_list(page);
+ SetPageReferenced(page);
}
- spin_unlock(&pagemap_lru_lock);
}
static int FASTCALL(shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages));
static int shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages)
{
- int max_scan = nr_inactive_pages / priority;
+ int max_scan;
+ int chunk_size = nr_pages;
+ unsigned long ratio;
nr_pages -= kmem_cache_reap(gfp_mask);
if (nr_pages <= 0)
return 0;
- /* Do we want to age the active list? */
- if (nr_inactive_pages < nr_active_pages*2)
- refill_inactive(nr_pages);
+ spin_lock(&pagemap_lru_lock);
+ nr_pages = chunk_size;
+ /* try to keep the active list 2/3 of the size of the cache */
+ ratio = (unsigned long) nr_pages * nr_active_pages / ((nr_inactive_pages + 1) * 2);
+ refill_inactive(ratio);
+ max_scan = nr_inactive_pages / priority;
nr_pages = shrink_cache(nr_pages, max_scan, classzone, gfp_mask);
if (nr_pages <= 0)
return 0;
@@ -558,17 +566,28 @@
int try_to_free_pages(zone_t * classzone, unsigned int gfp_mask, unsigned int order)
{
- int priority = DEF_PRIORITY;
- int ret = 0;
+ int priority, nr_pages, ret = 0;
- do {
- int nr_pages = SWAP_CLUSTER_MAX;
- nr_pages = shrink_caches(priority, classzone, gfp_mask, nr_pages);
- if (nr_pages <= 0)
- return 1;
+ for (;;) {
+ priority = DEF_PRIORITY;
+ nr_pages = SWAP_CLUSTER_MAX;
+
+ do {
+ nr_pages = shrink_caches(priority, classzone, gfp_mask, nr_pages);
+ if (nr_pages <= 0)
+ return 1;
+
+ ret |= swap_out(priority, classzone, gfp_mask, SWAP_CLUSTER_MAX << 2);
+ } while (--priority);
- ret |= swap_out(priority, classzone, gfp_mask, SWAP_CLUSTER_MAX << 2);
- } while (--priority);
+ if (likely(ret))
+ break;
+ if (likely(current->pid != 1))
+ break;
+ current->policy |= SCHED_YIELD;
+ __set_current_state(TASK_RUNNING);
+ schedule();
+ }
return ret;
}