diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-01-06 01:49:08 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-01-06 01:49:08 -0500 |
commit | fa94ddea2b29fdda7640672c8a933dbd901f0278 (patch) | |
tree | 4e9204f1438f5ed44bff31e2abee598ad775321d /mm/page_alloc.c | |
parent | 6fbfe8d7cd7e71ceb281c5a1b9de6e5e0dfbf1c8 (diff) | |
parent | 56d45b62ce622a003da972428fdbba2b42102efb (diff) |
Merge branch 'master' into sh/hw-breakpoints
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 68 |
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; | 2425 | out: |
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, | |||
5008 | int set_migratetype_isolate(struct page *page) | 5012 | int 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 | |||
5027 | out: | 5068 | out: |
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(); |