aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2006-03-22 03:07:58 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-22 10:53:56 -0500
commit46453a6e194a8c55fe6cf3dc8e1c4f24e2abc013 (patch)
treee407665e6c8cdf33814007750c49fdbea0a21e0e /mm/vmscan.c
parent2492ecc1a16b8ccf679d2999dca4f1b48aef07ee (diff)
[PATCH] mm: never ClearPageLRU released pages
If vmscan finds a zero refcount page on the lru list, never ClearPageLRU it. This means the release code need not hold ->lru_lock to stabilise PageLRU, so that lock may be skipped entirely when releasing !PageLRU pages (because we know PageLRU won't have been temporarily cleared by vmscan, which was previously guaranteed by holding the lock to synchronise against vmscan). Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 4fe7e3aa02e2..acb7611cd525 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1085,21 +1085,25 @@ static int isolate_lru_pages(int nr_to_scan, struct list_head *src,
1085 page = lru_to_page(src); 1085 page = lru_to_page(src);
1086 prefetchw_prev_lru_page(page, src, flags); 1086 prefetchw_prev_lru_page(page, src, flags);
1087 1087
1088 if (!TestClearPageLRU(page))
1089 BUG();
1090 list_del(&page->lru); 1088 list_del(&page->lru);
1091 if (get_page_testone(page)) { 1089 if (unlikely(get_page_testone(page))) {
1092 /* 1090 /*
1093 * It is being freed elsewhere 1091 * It is being freed elsewhere
1094 */ 1092 */
1095 __put_page(page); 1093 __put_page(page);
1096 SetPageLRU(page);
1097 list_add(&page->lru, src); 1094 list_add(&page->lru, src);
1098 continue; 1095 continue;
1099 } else {
1100 list_add(&page->lru, dst);
1101 nr_taken++;
1102 } 1096 }
1097
1098 /*
1099 * Be careful not to clear PageLRU until after we're sure
1100 * the page is not being freed elsewhere -- the page release
1101 * code relies on it.
1102 */
1103 if (!TestClearPageLRU(page))
1104 BUG();
1105 list_add(&page->lru, dst);
1106 nr_taken++;
1103 } 1107 }
1104 1108
1105 *scanned = scan; 1109 *scanned = scan;