aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-01-06 01:49:08 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-01-06 01:49:08 -0500
commitfa94ddea2b29fdda7640672c8a933dbd901f0278 (patch)
tree4e9204f1438f5ed44bff31e2abee598ad775321d /mm/page_alloc.c
parent6fbfe8d7cd7e71ceb281c5a1b9de6e5e0dfbf1c8 (diff)
parent56d45b62ce622a003da972428fdbba2b42102efb (diff)
Merge branch 'master' into sh/hw-breakpoints
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c68
1 files changed, 57 insertions, 11 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 4e869657cb51..4e9f5cc5fb59 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>
@@ -2401,13 +2402,14 @@ int numa_zonelist_order_handler(ctl_table *table, int write,
2401{ 2402{
2402 char saved_string[NUMA_ZONELIST_ORDER_LEN]; 2403 char saved_string[NUMA_ZONELIST_ORDER_LEN];
2403 int ret; 2404 int ret;
2405 static DEFINE_MUTEX(zl_order_mutex);
2404 2406
2407 mutex_lock(&zl_order_mutex);
2405 if (write) 2408 if (write)
2406 strncpy(saved_string, (char*)table->data, 2409 strcpy(saved_string, (char*)table->data);
2407 NUMA_ZONELIST_ORDER_LEN);
2408 ret = proc_dostring(table, write, buffer, length, ppos); 2410 ret = proc_dostring(table, write, buffer, length, ppos);
2409 if (ret) 2411 if (ret)
2410 return ret; 2412 goto out;
2411 if (write) { 2413 if (write) {
2412 int oldval = user_zonelist_order; 2414 int oldval = user_zonelist_order;
2413 if (__parse_numa_zonelist_order((char*)table->data)) { 2415 if (__parse_numa_zonelist_order((char*)table->data)) {
@@ -2420,7 +2422,9 @@ int numa_zonelist_order_handler(ctl_table *table, int write,
2420 } else if (oldval != user_zonelist_order) 2422 } else if (oldval != user_zonelist_order)
2421 build_all_zonelists(); 2423 build_all_zonelists();
2422 } 2424 }
2423 return 0; 2425out:
2426 mutex_unlock(&zl_order_mutex);
2427 return ret;
2424} 2428}
2425 2429
2426 2430
@@ -5008,23 +5012,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
5008int set_migratetype_isolate(struct page *page) 5012int set_migratetype_isolate(struct page *page)
5009{ 5013{
5010 struct zone *zone; 5014 struct zone *zone;
5011 unsigned long flags; 5015 struct page *curr_page;
5016 unsigned long flags, pfn, iter;
5017 unsigned long immobile = 0;
5018 struct memory_isolate_notify arg;
5019 int notifier_ret;
5012 int ret = -EBUSY; 5020 int ret = -EBUSY;
5013 int zone_idx; 5021 int zone_idx;
5014 5022
5015 zone = page_zone(page); 5023 zone = page_zone(page);
5016 zone_idx = zone_idx(zone); 5024 zone_idx = zone_idx(zone);
5025
5017 spin_lock_irqsave(&zone->lock, flags); 5026 spin_lock_irqsave(&zone->lock, flags);
5027 if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE ||
5028 zone_idx == ZONE_MOVABLE) {
5029 ret = 0;
5030 goto out;
5031 }
5032
5033 pfn = page_to_pfn(page);
5034 arg.start_pfn = pfn;
5035 arg.nr_pages = pageblock_nr_pages;
5036 arg.pages_found = 0;
5037
5018 /* 5038 /*
5019 * In future, more migrate types will be able to be isolation target. 5039 * It may be possible to isolate a pageblock even if the
5040 * migratetype is not MIGRATE_MOVABLE. The memory isolation
5041 * notifier chain is used by balloon drivers to return the
5042 * number of pages in a range that are held by the balloon
5043 * driver to shrink memory. If all the pages are accounted for
5044 * by balloons, are free, or on the LRU, isolation can continue.
5045 * Later, for example, when memory hotplug notifier runs, these
5046 * pages reported as "can be isolated" should be isolated(freed)
5047 * by the balloon driver through the memory notifier chain.
5020 */ 5048 */
5021 if (get_pageblock_migratetype(page) != MIGRATE_MOVABLE && 5049 notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg);
5022 zone_idx != ZONE_MOVABLE) 5050 notifier_ret = notifier_to_errno(notifier_ret);
5051 if (notifier_ret || !arg.pages_found)
5023 goto out; 5052 goto out;
5024 set_pageblock_migratetype(page, MIGRATE_ISOLATE); 5053
5025 move_freepages_block(zone, page, MIGRATE_ISOLATE); 5054 for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) {
5026 ret = 0; 5055 if (!pfn_valid_within(pfn))
5056 continue;
5057
5058 curr_page = pfn_to_page(iter);
5059 if (!page_count(curr_page) || PageLRU(curr_page))
5060 continue;
5061
5062 immobile++;
5063 }
5064
5065 if (arg.pages_found == immobile)
5066 ret = 0;
5067
5027out: 5068out:
5069 if (!ret) {
5070 set_pageblock_migratetype(page, MIGRATE_ISOLATE);
5071 move_freepages_block(zone, page, MIGRATE_ISOLATE);
5072 }
5073
5028 spin_unlock_irqrestore(&zone->lock, flags); 5074 spin_unlock_irqrestore(&zone->lock, flags);
5029 if (!ret) 5075 if (!ret)
5030 drain_all_pages(); 5076 drain_all_pages();