diff options
author | Konstantin Khlebnikov <khlebnikov@openvz.org> | 2011-05-24 20:12:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-25 11:39:23 -0400 |
commit | 0c917313a8d84fcc0c376db3f7edb7c06f06f920 (patch) | |
tree | de95ed4a300d1034b1abae2eb8c7e509c9dfb341 /mm | |
parent | bd486285f24ac2fd1ff64688fb0729712c5712c4 (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')
-rw-r--r-- | mm/vmscan.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index d303b60f4c2..890f54184d9 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); |