Skip to contentSkip to conversation

inactive_clean

RFC PATCH In review Peter Zijlstra 3 participants 14 messages Jun 19, 2006

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 inactive_clean

Another (complementary) approach to avoiding the VM deadlock.

Nick's comment on that anonymous pages could be clean was of course correct, and I smacked my head for not realising it sooner.

My previous efforts at tracking dirty pages focused on shared pages. But shared pages are not all and, quite often even a small part of the problem. Most 'normal' workloads are dominated by anonymous pages.

So, in order to guarantee easily freeable pages we also have to look at anonymous memory. Thinking about it I arrived at something Rik invented long ago: the inactive_clean list - a third LRU list consisting of clean pages.

The thing I like least about the current impl. is that all clean pages are unmapped; I'd like to have them mapped but read-only and trap the write faults (next step?).

Also, setting the clean watermarks needs more thought.

Comments?

NOTE: this patch alone also makes my mad shared mmap write program finish to completion.

---
 include/linux/mm_inline.h  |   23 +++++++++
 include/linux/mmzone.h     |    3 +
 include/linux/page-flags.h |    6 ++
 include/linux/swap.h       |    1 
 mm/page_alloc.c            |   27 ++++++++++-
 mm/swap.c                  |   44 ++++++++++--------
 mm/swapfile.c              |    4 -
 mm/vmscan.c                |  108 ++++++++++++++++++++++++++++++++++++++-------
 8 files changed, 176 insertions(+), 40 deletions(-)
include/linux/swap.h +0 -1
Index: linux-2.6/include/linux/swap.h
===================================================================
@@ -165,7 +165,6 @@ extern unsigned int nr_free_pagecache_pa
 /* linux/mm/swap.c */
 extern void FASTCALL(lru_cache_add(struct page *));
 extern void FASTCALL(lru_cache_add_active(struct page *));
-extern void FASTCALL(activate_page(struct page *));
 extern void FASTCALL(mark_page_accessed(struct page *));
 extern void lru_add_drain(void);
 extern int lru_add_drain_all(void);
mm/swapfile.c +2 -2
Index: linux-2.6/mm/swapfile.c
===================================================================
@@ -496,7 +496,7 @@ static void unuse_pte(struct vm_area_str
 	 * Move the page to the active list so it is not
 	 * immediately swapped out again after swapon.
 	 */
-	activate_page(page);
+	mark_page_accessed(page);
 }
 
 static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
@@ -598,7 +598,7 @@ static int unuse_mm(struct mm_struct *mm
 		 * Activate page so shrink_cache is unlikely to unmap its
 		 * ptes while lock is dropped, so swapoff can make progress.
 		 */
-		activate_page(page);
+		mark_page_accessed(page);
 		unlock_page(page);
 		down_read(&mm->mmap_sem);
 		lock_page(page);
mm/swap.c +26 -18

63 lines not on this page · raw message

include/linux/mm_inline.h +23 -0
Index: linux-2.6/include/linux/mm_inline.h
===================================================================
@@ -14,6 +14,13 @@ add_page_to_inactive_list(struct zone *z
 }
 
 static inline void
+add_page_to_clean_list(struct zone *zone, struct page *page)
+{
+	list_add(&page->lru, &zone->clean_list);
+	zone->nr_clean++;
+}
+
+static inline void
 del_page_from_active_list(struct zone *zone, struct page *page)
 {
 	list_del(&page->lru);
@@ -27,6 +34,17 @@ del_page_from_inactive_list(struct zone 
 	zone->nr_inactive--;
 }
 
+void wakeup_kswapd(struct zone *zone, int order);
+
+static inline void
+del_page_from_clean_list(struct zone *zone, struct page *page)
+{
+	list_del(&page->lru);
+	zone->nr_clean--;
+	if (zone->nr_clean + zone->free_pages < zone->clean_low)
+		wakeup_kswapd(zone, 0);
+}
+
 static inline void
 del_page_from_lru(struct zone *zone, struct page *page)
 {
@@ -34,6 +52,11 @@ del_page_from_lru(struct zone *zone, str
 	if (PageActive(page)) {
 		__ClearPageActive(page);
 		zone->nr_active--;
+	} else if (PageClean(page)) {
+		__ClearPageClean(page);
+		zone->nr_clean--;
+		if (zone->nr_clean + zone->free_pages < zone->clean_low)
+			wakeup_kswapd(zone, 0);
 	} else {
 		zone->nr_inactive--;
 	}
include/linux/mmzone.h +3 -0
Index: linux-2.6/include/linux/mmzone.h
===================================================================
@@ -156,10 +156,13 @@ struct zone {
 	spinlock_t		lru_lock;	
 	struct list_head	active_list;
 	struct list_head	inactive_list;
+	struct list_head	clean_list;
 	unsigned long		nr_scan_active;
 	unsigned long		nr_scan_inactive;
 	unsigned long		nr_active;
 	unsigned long		nr_inactive;
+	unsigned long		nr_clean;
+	unsigned long		clean_low, clean_high;
 	unsigned long		pages_scanned;	   /* since last reclaim */
 	int			all_unreclaimable; /* All pages pinned */
 
include/linux/page-flags.h +6 -0
Index: linux-2.6/include/linux/page-flags.h
===================================================================
@@ -89,6 +89,7 @@
 #define PG_buddy		19	/* Page is free, on buddy lists */
 
 #define PG_uncached		20	/* Page has been mapped as uncached */
+#define PG_clean		21	/* Page is on the clean list */
 
 /*
  * Global page accounting.  One instance per CPU.  Only unsigned longs are
@@ -360,6 +361,11 @@ extern void __mod_page_state_offset(unsi
 #define SetPageUncached(page)	set_bit(PG_uncached, &(page)->flags)
 #define ClearPageUncached(page)	clear_bit(PG_uncached, &(page)->flags)
 
+#define PageClean(page)		test_bit(PG_clean, &(page)->flags)
+#define SetPageClean(page)	set_bit(PG_clean, &(page)->flags)
+#define ClearPageClean(page)	clear_bit(PG_clean, &(page)->flags)
+#define __ClearPageClean(page)	__clear_bit(PG_clean, &(page)->flags)
+
 struct page;	/* forward declaration */
 
 int test_clear_page_dirty(struct page *page);
mm/page_alloc.c +24 -3
Index: linux-2.6/mm/page_alloc.c
===================================================================
@@ -154,7 +154,8 @@ static void bad_page(struct page *page)
 			1 << PG_slab    |
 			1 << PG_swapcache |
 			1 << PG_writeback |
-			1 << PG_buddy );
+			1 << PG_buddy |
+		        1 << PG_clean );
 	set_page_count(page, 0);
 	reset_page_mapcount(page);
 	page->mapping = NULL;
@@ -384,7 +385,8 @@ static inline int free_pages_check(struc
 			1 << PG_swapcache |
 			1 << PG_writeback |
 			1 << PG_reserved |
-			1 << PG_buddy ))))
+			1 << PG_buddy |
+			1 << PG_clean ))))
 		bad_page(page);
 	if (PageDirty(page))
 		__ClearPageDirty(page);
@@ -533,7 +535,8 @@ static int prep_new_page(struct page *pa
 			1 << PG_swapcache |
 			1 << PG_writeback |
 			1 << PG_reserved |
-			1 << PG_buddy ))))
+			1 << PG_buddy |
+			1 << PG_clean ))))
 		bad_page(page);
 
 	/*
@@ -1461,6 +1464,9 @@ void show_free_areas(void)
 			" min:%lukB"
 			" low:%lukB"
 			" high:%lukB"
+			" clean: %lukB"
+			" low: %lukB"
+			" high: %lukB"
 			" active:%lukB"
 			" inactive:%lukB"
 			" present:%lukB"
@@ -1472,6 +1478,9 @@ void show_free_areas(void)
 			K(zone->pages_min),
 			K(zone->pages_low),
 			K(zone->pages_high),
+			K(zone->nr_clean),
+			K(zone->clean_low),
+			K(zone->clean_high),
 			K(zone->nr_active),
 			K(zone->nr_inactive),
 			K(zone->present_pages),
@@ -2102,10 +2111,12 @@ static void __init free_area_init_core(s
 		zone_pcp_init(zone);
 		INIT_LIST_HEAD(&zone->active_list);
 		INIT_LIST_HEAD(&zone->inactive_list);
+		INIT_LIST_HEAD(&zone->clean_list);
 		zone->nr_scan_active = 0;
 		zone->nr_scan_inactive = 0;
 		zone->nr_active = 0;
 		zone->nr_inactive = 0;
+		zone->nr_clean = 0;
 		atomic_set(&zone->reclaim_in_progress, 0);
 		if (!size)
 			continue;
@@ -2261,6 +2272,9 @@ static int zoneinfo_show(struct seq_file
 			   "\n        min      %lu"
 			   "\n        low      %lu"
 			   "\n        high     %lu"
+			   "\n        clean    %lu"
+			   "\n        low      %lu"
+			   "\n        high     %lu"
 			   "\n        active   %lu"
 			   "\n        inactive %lu"
 			   "\n        scanned  %lu (a: %lu i: %lu)"
@@ -2270,6 +2284,9 @@ static int zoneinfo_show(struct seq_file
 			   zone->pages_min,
 			   zone->pages_low,
 			   zone->pages_high,
+			   zone->nr_clean,
+			   zone->clean_low,
+			   zone->clean_high,
 			   zone->nr_active,
 			   zone->nr_inactive,
 			   zone->pages_scanned,
@@ -2609,6 +2626,10 @@ void setup_per_zone_pages_min(void)
 
 		zone->pages_low   = zone->pages_min + (tmp >> 2);
 		zone->pages_high  = zone->pages_min + (tmp >> 1);
+
+		zone->clean_low   = zone->pages_low  << 3;
+		zone->clean_high  = zone->pages_high << 3;
+
 		spin_unlock_irqrestore(&zone->lru_lock, flags);
 	}
 
mm/vmscan.c +92 -16

184 lines not on this page · raw message

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw
Quoted 3 lines · Peter Zijlstra

My previous efforts at tracking dirty pages focused on shared pages. But shared pages are not all and, quite often even a small part of the problem. Most 'normal' workloads are dominated by anonymous pages.

Shared pages are the major problem because we have no way of tracking their dirty state. Shared file mapped pages are a problem because they require writeout which will not occur if we are not aware of them. The dirty state of anonymous pages typically does not matter because these pages are thrown away when a process terminates.

Quoted 4 lines

So, in order to guarantee easily freeable pages we also have to look at anonymous memory. Thinking about it I arrived at something Rik invented long ago: the inactive_clean list - a third LRU list consisting of clean pages.

I fail to see the point. What is the problem with anonymous memory? Swap?

Quoted 3 lines

The thing I like least about the current impl. is that all clean pages are unmapped; I'd like to have them mapped but read-only and trap the write faults (next step?).

This is some sort of swap problem?

Quoted 3 lines

Also, setting the clean watermarks needs more thought.

Comments?

I am not clear what issue you are trying to solve. Seem that this is something entirely different.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#2 lore raw
Quoted 12 lines · Christoph Lameter
Quoted 3 lines · Peter Zijlstra

My previous efforts at tracking dirty pages focused on shared pages. But shared pages are not all and, quite often even a small part of the problem. Most 'normal' workloads are dominated by anonymous pages.

Shared pages are the major problem because we have no way of tracking their dirty state. Shared file mapped pages are a problem because they require writeout which will not occur if we are not aware of them. The dirty state of anonymous pages typically does not matter because these pages are thrown away when a process terminates.

Quoted 6 lines
Quoted 4 lines

So, in order to guarantee easily freeable pages we also have to look at anonymous memory. Thinking about it I arrived at something Rik invented long ago: the inactive_clean list - a third LRU list consisting of clean page

I fail to see the point. What is the problem with anonymous memory? Swap?

http://linux-mm.org/NetworkStorageDeadlock

Basically, we want to free memory, but freeing costs more memory than we currently have available.

This patch creates a pool of pages that can be evicted without IO, but can also be taken back into service, again without IO - hence not 'wasting' memory being free.

The problem is currently being circumvented on several levels with local mempools, these fragment the available free memory and require extra complexity to manage.

Yes, raising the number of free pages will have the same effect, however it wastes memory from another point of view.

Neither of these approaches will really solve the 'Network' problem, because it does not come with a finite bound of memory. Any networked storage can require inf. amount of memory for a single writeback. Usually things are not that bad, esp. with dedicated storage networks that avoid too much protocols stacks.

The only solution for the networked problem is in dropping non-critical packets when we start to run low.

Also this does give more leeway to make things like cluster pageout:
http://linuxhacker.ru/~nikita/patches/2.6.15-rc1/05-cluster-pageout.patch
work.

In the end, I want to be able to run a diskless system, with networked swap and, have stuff like cluster pageout working without the machine going funny on me.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw
Quoted 4 lines · Peter Zijlstra

http://linux-mm.org/NetworkStorageDeadlock

Basically, we want to free memory, but freeing costs more memory than we currently have available.

Freeing of anonymous memory does not cost anythin when the process terminates. You mean free through swapping? The problem is the swap via the network?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw
Quoted 10 lines · Christoph Lameter
Quoted 4 lines · Peter Zijlstra

http://linux-mm.org/NetworkStorageDeadlock

Basically, we want to free memory, but freeing costs more memory than we currently have available.

Freeing of anonymous memory does not cost anythin when the process terminates. You mean free through swapping? The problem is the swap via the network?

Not only swap. Writable MAP_SHARED mmap has the same problem...

Signature · 7 lines
All Rights Reversed

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#5 lore raw
Quoted 1 line · Rik van Riel

Not only swap. Writable MAP_SHARED mmap has the same problem...

Writable MAP_SHARED is throttled by Peter Z. other patchset on page dirtying. So the problem should have been solved at that level.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#6 lore raw
Quoted 6 lines · Christoph Lameter
Quoted 1 line · Rik van Riel

Not only swap. Writable MAP_SHARED mmap has the same problem...

Writable MAP_SHARED is throttled by Peter Z. other patchset on page dirtying. So the problem should have been solved at that level.

This new patch throttles both. It might even make the other
one less needed - not sure...

Signature · 7 lines
All Rights Reversed

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#7 lore raw
Quoted 10 lines · Rik van Riel
Quoted 6 lines · Christoph Lameter
Quoted 1 line · Rik van Riel

Not only swap. Writable MAP_SHARED mmap has the same problem...

Writable MAP_SHARED is throttled by Peter Z. other patchset on page dirtying. So the problem should have been solved at that level.

This new patch throttles both. It might even make the other
one less needed - not sure...

Hmmm.. My counter patches add NR_ANON to count the number of anonymous pages. These are all potentially dirty. If you throttle on NR_DIRTY + NR_ANON then we may have the effect without this patch.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw
Quoted 10 lines · Christoph Lameter
Quoted 8 lines · Rik van Riel
Quoted 6 lines · Christoph Lameter
Quoted 1 line · Rik van Riel

Not only swap. Writable MAP_SHARED mmap has the same problem...

Writable MAP_SHARED is throttled by Peter Z. other patchset on page dirtying. So the problem should have been solved at that level.

Quoted 6 lines
Quoted 2 lines

This new patch throttles both. It might even make the other
one less needed - not sure...

Hmmm.. My counter patches add NR_ANON to count the number of anonymous pages. These are all potentially dirty. If you throttle on NR_DIRTY + NR_ANON then we may have the effect without this patch.

Sure, but what do you do to reach you threshold if there are not enough mapped pages around to clean?

At that point the only thing left is to make sure some anonymous pages become clean, that is write them out to swap and have them sit around in the swap cache.

The next question is: 'which pages do I write out?', and there page reclaim comes in; however are you only going to write out anonymous pages and violate page order for file backed pages?

This train of thougth led to the proposed patch.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw
Quoted 6 lines · Peter Zijlstra
Quoted 3 lines

Hmmm.. My counter patches add NR_ANON to count the number of anonymous pages. These are all potentially dirty. If you throttle on NR_DIRTY + NR_ANON then we may have the effect without this patch.

Sure, but what do you do to reach you threshold if there are not enough mapped pages around to clean?

You reach the threshold and the writeout happens. So there are enough clean pages available.

Quoted 3 lines

At that point the only thing left is to make sure some anonymous pages become clean, that is write them out to swap and have them sit around in the swap cache.

Thats fine. The threshold just insures that you can write out the anonymous pages.

Quoted 3 lines

The next question is: 'which pages do I write out?', and there page reclaim comes in; however are you only going to write out anonymous pages and violate page order for file backed pages?

I would think that one would first write out dirty file backed pages.

What page order are you talking about?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw
Quoted 11 lines · Christoph Lameter
Quoted 6 lines · Peter Zijlstra
Quoted 3 lines

Hmmm.. My counter patches add NR_ANON to count the number of anonymous pages. These are all potentially dirty. If you throttle on NR_DIRTY + NR_ANON then we may have the effect without this patch.

Sure, but what do you do to reach you threshold if there are not enough mapped pages around to clean?

You reach the threshold and the writeout happens. So there are enough clean pages available.

I think we look at the threshold from differ sides, what I meant was:
we want nr_clean > nr_wanted_clean, where nr_clean = nr_clean_anon + nr_clean_mapped. Now nr_clean_mapped = nr_mapped - nr_dirty_mapped, what if nr_mapped < nr_wanted_clean?

You need to increase nr_clean_anon to reach nr_wanted_clean.

Quoted 6 lines
Quoted 3 lines

At that point the only thing left is to make sure some anonymous pages become clean, that is write them out to swap and have them sit around in the swap cache.

Thats fine. The threshold just insures that you can write out the anonymous pages.

But you need slightly more than just writeout, you need to create a clean anonymous page, so you need to keep it around.

Quoted 7 lines
Quoted 3 lines

The next question is: 'which pages do I write out?', and there page reclaim comes in; however are you only going to write out anonymous pages and violate page order for file backed pages?

I would think that one would first write out dirty file backed pages.

What page order are you talking about?

LRU page order, and having a preference for file-backed pages breaks it.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#11 lore raw
Quoted 1 line · Peter Zijlstra

You need to increase nr_clean_anon to reach nr_wanted_clean.

nr_clean_anon? Anonymous pages are always dirty! They may appear to be clean for a process but fundamentally a clean anonymous page is full of zeros. We use a special page for that.

Quoted 2 lines

But you need slightly more than just writeout, you need to create a clean anonymous page, so you need to keep it around.

Still boogling on the clean anonymous pages. Maybe with swap you can get there. You mean the anonymous page is clean when it was written to swap? We are dealing with a special case here when the performance already sucks and now we add more logic to make the case when performance was not bad worse?

If an anonymus page gains a reference to swap then it is fundamentally no longer a pure anonymous page.

Quoted 1 line

LRU page order, and having a preference for file-backed pages breaks it.

zone_reclaim already does not observe that order but goes for the easily reclaimable unmapped pages.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#12 lore raw
In reply to Christoph Lameter
Quoted 3 lines · Christoph Lameter

Hmmm.. My counter patches add NR_ANON to count the number of anonymous pages. These are all potentially dirty. If you throttle on NR_DIRTY + NR_ANON then we may have the effect without this patch.

I bet you can, but how many more things do you need to measure to achieve the same thing peterz's patch achieves with one counter and list ?

Signature · 7 lines
All Rights Reversed

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#13 lore raw
Quoted 9 lines · Rik van Riel
Quoted 3 lines · Christoph Lameter

Hmmm.. My counter patches add NR_ANON to count the number of anonymous pages. These are all potentially dirty. If you throttle on NR_DIRTY + NR_ANON then we may have the effect without this patch.

I bet you can, but how many more things do you need to measure to achieve the same thing peterz's patch achieves with one counter and list ?

We need this counter anyways in order to get to the unmapped pages per zone.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>