aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorRobert Jennings <rcj@linux.vnet.ibm.com>2009-12-17 09:44:38 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-17 22:53:36 -0500
commit925cc71e512a29e2594bcc17dc58d0a0e9c4d524 (patch)
tree7240ccf6ba713cc180d388a28f00c1a43293bc14 /mm/page_alloc.c
parent55639353a0035052d9ea6cfe4dde0ac7fcbb2c9f (diff)
mm: Add notifier in pageblock isolation for balloon drivers
Memory balloon drivers can allocate a large amount of memory which is not movable but could be freed to accomodate memory hotplug remove. Prior to calling the memory hotplug notifier chain the memory in the pageblock is isolated. Currently, if the migrate type is not MIGRATE_MOVABLE the isolation will not proceed, causing the memory removal for that page range to fail. Rather than failing pageblock isolation if the migrateteype is not MIGRATE_MOVABLE, this patch checks if all of the pages in the pageblock, and not on the LRU, are owned by a registered balloon driver (or other entity) using a notifier chain. If all of the non-movable pages are owned by a balloon, they can be freed later through the memory notifier chain and the range can still be isolated in set_migratetype_isolate(). Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Ingo Molnar <mingo@elte.hu> Cc: Brian King <brking@linux.vnet.ibm.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Gerald Schaefer <geralds@linux.vnet.ibm.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c57
1 files changed, 50 insertions, 7 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 74af449b1f1d..998eacc1e4c3 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -48,6 +48,7 @@
48#include <linux/page_cgroup.h> 48#include <linux/page_cgroup.h>
49#include <linux/debugobjects.h> 49#include <linux/debugobjects.h>
50#include <linux/kmemleak.h> 50#include <linux/kmemleak.h>
51#include <linux/memory.h>
51#include <trace/events/kmem.h> 52#include <trace/events/kmem.h>
52 53
53#include <asm/tlbflush.h> 54#include <asm/tlbflush.h>
@@ -5008,23 +5009,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
5008int set_migratetype_isolate(struct page *page) 5009int set_migratetype_isolate(struct page *page)
5009{ 5010{
5010 struct zone *zone; 5011 struct zone *zone;
5011 unsigned long flags; 5012 struct page *curr_page;
5013 unsigned long flags, pfn, iter;
5014 unsigned long immobile = 0;
5015 struct memory_isolate_notify arg;
5016 int notifier_ret;
5012 int ret = -EBUSY; 5017 int ret = -EBUSY;
5013 int zone_idx; 5018 int zone_idx;
5014 5019
5015 zone = page_zone(page); 5020 zone = page_zone(page);
5016 zone_idx = zone_idx(zone); 5021 zone_idx = zone_idx(zone);
5022
5017 spin_lock_irqsave(&zone->lock, flags); 5023 spin_lock_irqsave(&zone->lock, flags);
5024 if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE ||
5025 zone_idx == ZONE_MOVABLE) {
5026 ret = 0;
5027 goto out;
5028 }
5029
5030 pfn = page_to_pfn(page);
5031 arg.start_pfn = pfn;
5032 arg.nr_pages = pageblock_nr_pages;
5033 arg.pages_found = 0;
5034
5018 /* 5035 /*
5019 * In future, more migrate types will be able to be isolation target. 5036 * It may be possible to isolate a pageblock even if the
5037 * migratetype is not MIGRATE_MOVABLE. The memory isolation
5038 * notifier chain is used by balloon drivers to return the
5039 * number of pages in a range that are held by the balloon
5040 * driver to shrink memory. If all the pages are accounted for
5041 * by balloons, are free, or on the LRU, isolation can continue.
5042 * Later, for example, when memory hotplug notifier runs, these
5043 * pages reported as "can be isolated" should be isolated(freed)
5044 * by the balloon driver through the memory notifier chain.
5020 */ 5045 */
5021 if (get_pageblock_migratetype(page) != MIGRATE_MOVABLE && 5046 notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg);
5022 zone_idx != ZONE_MOVABLE) 5047 notifier_ret = notifier_to_errno(notifier_ret);
5048 if (notifier_ret || !arg.pages_found)
5023 goto out; 5049 goto out;
5024 set_pageblock_migratetype(page, MIGRATE_ISOLATE); 5050
5025 move_freepages_block(zone, page, MIGRATE_ISOLATE); 5051 for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) {
5026 ret = 0; 5052 if (!pfn_valid_within(pfn))
5053 continue;
5054
5055 curr_page = pfn_to_page(iter);
5056 if (!page_count(curr_page) || PageLRU(curr_page))
5057 continue;
5058
5059 immobile++;
5060 }
5061
5062 if (arg.pages_found == immobile)
5063 ret = 0;
5064
5027out: 5065out:
5066 if (!ret) {
5067 set_pageblock_migratetype(page, MIGRATE_ISOLATE);
5068 move_freepages_block(zone, page, MIGRATE_ISOLATE);
5069 }
5070
5028 spin_unlock_irqrestore(&zone->lock, flags); 5071 spin_unlock_irqrestore(&zone->lock, flags);
5029 if (!ret) 5072 if (!ret)
5030 drain_all_pages(); 5073 drain_all_pages();