aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
authorKonstantin Khlebnikov <khlebnikov@openvz.org>2011-05-24 20:12:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-25 11:39:23 -0400
commit0c917313a8d84fcc0c376db3f7edb7c06f06f920 (patch)
treede95ed4a300d1034b1abae2eb8c7e509c9dfb341 /mm/vmscan.c
parentbd486285f24ac2fd1ff64688fb0729712c5712c4 (diff)
mm: strictly require elevated page refcount in isolate_lru_page()
isolate_lru_page() must be called only with stable reference to the page, this is what is written in the comment above it, this is reasonable. current isolate_lru_page() users and its page extra reference sources: mm/huge_memory.c: __collapse_huge_page_isolate() - reference from pte mm/memcontrol.c: mem_cgroup_move_parent() - get_page_unless_zero() mem_cgroup_move_charge_pte_range() - reference from pte mm/memory-failure.c: soft_offline_page() - fixed, reference from get_any_page() delete_from_lru_cache() - reference from caller or get_page_unless_zero() [ seems like there bug, because __memory_failure() can call page_action() for hpages tail, but it is ok for isolate_lru_page(), tail getted and not in lru] mm/memory_hotplug.c: do_migrate_range() - fixed, get_page_unless_zero() mm/mempolicy.c: migrate_page_add() - reference from pte mm/migrate.c: do_move_page_to_node_array() - reference from follow_page() mlock.c: - various external references mm/vmscan.c: putback_lru_page() - reference from isolate_lru_page() It seems that all isolate_lru_page() users are ready now for this restriction. So, let's replace redundant get_page_unless_zero() with get_page() and add page initial reference count check with VM_BUG_ON() Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org> Cc: Andi Kleen <andi@firstfloor.org> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Lee Schermerhorn <lee.schermerhorn@hp.com> Cc: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d303b60f4c2a..890f54184d9a 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1207,13 +1207,16 @@ int isolate_lru_page(struct page *page)
1207{ 1207{
1208 int ret = -EBUSY; 1208 int ret = -EBUSY;
1209 1209
1210 VM_BUG_ON(!page_count(page));
1211
1210 if (PageLRU(page)) { 1212 if (PageLRU(page)) {
1211 struct zone *zone = page_zone(page); 1213 struct zone *zone = page_zone(page);
1212 1214
1213 spin_lock_irq(&zone->lru_lock); 1215 spin_lock_irq(&zone->lru_lock);
1214 if (PageLRU(page) && get_page_unless_zero(page)) { 1216 if (PageLRU(page)) {
1215 int lru = page_lru(page); 1217 int lru = page_lru(page);
1216 ret = 0; 1218 ret = 0;
1219 get_page(page);
1217 ClearPageLRU(page); 1220 ClearPageLRU(page);
1218 1221
1219 del_page_from_lru_list(zone, page, lru); 1222 del_page_from_lru_list(zone, page, lru);