[patch 1/2] vm early reclaim orphaned pages (take 2)

From: Nick Piggin
Date: Mon Jun 20 2005 - 02:24:31 EST


How about this?

--
SUSE Labs, Novell Inc.


We have workloads where orphaned pages build up and appear to slow
the system down when it starts reclaiming memory.

Stripping the referenced bit from orphaned pages and putting them
on the end of the inactive list should help improve reclaim.

Signed-off-by: Nick Piggin <npiggin@xxxxxxx>

Index: linux-2.6/mm/truncate.c
===================================================================
--- linux-2.6.orig/mm/truncate.c 2005-06-01 16:09:34.000000000 +1000
+++ linux-2.6/mm/truncate.c 2005-06-20 17:05:41.011026426 +1000
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/pagevec.h>
+#include <linux/swap.h>
#include <linux/buffer_head.h> /* grr. try_to_release_page,
block_invalidatepage */

@@ -48,9 +49,11 @@
if (page->mapping != mapping)
return;

- if (PagePrivate(page))
- do_invalidatepage(page, 0);
-
+ if (PagePrivate(page)) {
+ if (!(do_invalidatepage(page, 0)))
+ rotate_orphaned_page(page);
+ }
+
clear_page_dirty(page);
ClearPageUptodate(page);
ClearPageMappedToDisk(page);
Index: linux-2.6/include/linux/swap.h
===================================================================
--- linux-2.6.orig/include/linux/swap.h 2005-06-01 16:09:26.000000000 +1000
+++ linux-2.6/include/linux/swap.h 2005-06-20 17:05:01.632921946 +1000
@@ -169,6 +169,7 @@
extern void FASTCALL(mark_page_accessed(struct page *));
extern void lru_add_drain(void);
extern int rotate_reclaimable_page(struct page *page);
+extern void rotate_orphaned_page(struct page *page);
extern void swap_setup(void);

/* linux/mm/vmscan.c */
Index: linux-2.6/mm/swap.c
===================================================================
--- linux-2.6.orig/mm/swap.c 2004-12-25 08:34:31.000000000 +1100
+++ linux-2.6/mm/swap.c 2005-06-20 17:20:28.216728238 +1000
@@ -87,7 +87,7 @@
spin_lock_irqsave(&zone->lru_lock, flags);
if (PageLRU(page) && !PageActive(page)) {
list_del(&page->lru);
- list_add_tail(&page->lru, &zone->inactive_list);
+ list_move_tail(&page->lru, &zone->inactive_list);
inc_page_state(pgrotated);
}
if (!test_clear_page_writeback(page))
@@ -97,6 +97,32 @@
}

/*
+ * A page has been truncated, but is being orphaned on the LRU list due to
+ * a filesystem dependancy.
+ *
+ * Strip the referenced bit from this page, and if it is on the active list
+ * then put it on the head of the inactive list to aid page reclaim.
+ *
+ * We don't put it on the tail of the inactive list because the page is
+ * not able to be immediately freed due to filesystem dependancy (however
+ * in general, putting the page on the tail would probably be a win, but
+ * slightly more prone to introducing a regression).
+ */
+void rotate_orphaned_page(struct page *page)
+{
+ unsigned long flags;
+ struct zone *zone = page_zone(page);
+
+ spin_lock_irqsave(&zone->lru_lock, flags);
+ ClearPageReferenced(page);
+ if (PageLRU(page) && PageActive(page)) {
+ list_move(&page->lru, &zone->inactive_list);
+ ClearPageActive(page);
+ }
+ spin_unlock_irqrestore(&zone->lru_lock, flags);
+}
+
+/*
* FIXME: speed this up?
*/
void fastcall activate_page(struct page *page)