aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/memory_hotplug.h4
-rw-r--r--mm/memory_hotplug.c17
-rw-r--r--mm/page_alloc.c87
3 files changed, 72 insertions, 36 deletions
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 864035fb8f8..4307231bd22 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -70,6 +70,10 @@ extern void online_page(struct page *page);
70extern int online_pages(unsigned long, unsigned long); 70extern int online_pages(unsigned long, unsigned long);
71extern void __offline_isolated_pages(unsigned long, unsigned long); 71extern void __offline_isolated_pages(unsigned long, unsigned long);
72 72
73#ifdef CONFIG_MEMORY_HOTREMOVE
74extern bool is_pageblock_removable_nolock(struct page *page);
75#endif /* CONFIG_MEMORY_HOTREMOVE */
76
73/* reasonably generic interface to expand the physical pages in a zone */ 77/* reasonably generic interface to expand the physical pages in a zone */
74extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn, 78extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn,
75 unsigned long nr_pages); 79 unsigned long nr_pages);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 4821338b4e4..b0dc6545297 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -602,27 +602,14 @@ static struct page *next_active_pageblock(struct page *page)
602/* Checks if this range of memory is likely to be hot-removable. */ 602/* Checks if this range of memory is likely to be hot-removable. */
603int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages) 603int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
604{ 604{
605 int type;
606 struct page *page = pfn_to_page(start_pfn); 605 struct page *page = pfn_to_page(start_pfn);
607 struct page *end_page = page + nr_pages; 606 struct page *end_page = page + nr_pages;
608 607
609 /* Check the starting page of each pageblock within the range */ 608 /* Check the starting page of each pageblock within the range */
610 for (; page < end_page; page = next_active_pageblock(page)) { 609 for (; page < end_page; page = next_active_pageblock(page)) {
611 type = get_pageblock_migratetype(page); 610 if (!is_pageblock_removable_nolock(page))
612
613 /*
614 * A pageblock containing MOVABLE or free pages is considered
615 * removable
616 */
617 if (type != MIGRATE_MOVABLE && !pageblock_free(page))
618 return 0;
619
620 /*
621 * A pageblock starting with a PageReserved page is not
622 * considered removable.
623 */
624 if (PageReserved(page))
625 return 0; 611 return 0;
612 cond_resched();
626 } 613 }
627 614
628 /* All pageblocks in the memory block are likely to be hot-removable */ 615 /* All pageblocks in the memory block are likely to be hot-removable */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 099790052bf..6a683f81943 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5297,12 +5297,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
5297 * page allocater never alloc memory from ISOLATE block. 5297 * page allocater never alloc memory from ISOLATE block.
5298 */ 5298 */
5299 5299
5300static int
5301__count_immobile_pages(struct zone *zone, struct page *page, int count)
5302{
5303 unsigned long pfn, iter, found;
5304 /*
5305 * For avoiding noise data, lru_add_drain_all() should be called
5306 * If ZONE_MOVABLE, the zone never contains immobile pages
5307 */
5308 if (zone_idx(zone) == ZONE_MOVABLE)
5309 return true;
5310
5311 if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE)
5312 return true;
5313
5314 pfn = page_to_pfn(page);
5315 for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) {
5316 unsigned long check = pfn + iter;
5317
5318 if (!pfn_valid_within(check)) {
5319 iter++;
5320 continue;
5321 }
5322 page = pfn_to_page(check);
5323 if (!page_count(page)) {
5324 if (PageBuddy(page))
5325 iter += (1 << page_order(page)) - 1;
5326 continue;
5327 }
5328 if (!PageLRU(page))
5329 found++;
5330 /*
5331 * If there are RECLAIMABLE pages, we need to check it.
5332 * But now, memory offline itself doesn't call shrink_slab()
5333 * and it still to be fixed.
5334 */
5335 /*
5336 * If the page is not RAM, page_count()should be 0.
5337 * we don't need more check. This is an _used_ not-movable page.
5338 *
5339 * The problematic thing here is PG_reserved pages. PG_reserved
5340 * is set to both of a memory hole page and a _used_ kernel
5341 * page at boot.
5342 */
5343 if (found > count)
5344 return false;
5345 }
5346 return true;
5347}
5348
5349bool is_pageblock_removable_nolock(struct page *page)
5350{
5351 struct zone *zone = page_zone(page);
5352 return __count_immobile_pages(zone, page, 0);
5353}
5354
5300int set_migratetype_isolate(struct page *page) 5355int set_migratetype_isolate(struct page *page)
5301{ 5356{
5302 struct zone *zone; 5357 struct zone *zone;
5303 struct page *curr_page; 5358 unsigned long flags, pfn;
5304 unsigned long flags, pfn, iter;
5305 unsigned long immobile = 0;
5306 struct memory_isolate_notify arg; 5359 struct memory_isolate_notify arg;
5307 int notifier_ret; 5360 int notifier_ret;
5308 int ret = -EBUSY; 5361 int ret = -EBUSY;
@@ -5312,11 +5365,6 @@ int set_migratetype_isolate(struct page *page)
5312 zone_idx = zone_idx(zone); 5365 zone_idx = zone_idx(zone);
5313 5366
5314 spin_lock_irqsave(&zone->lock, flags); 5367 spin_lock_irqsave(&zone->lock, flags);
5315 if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE ||
5316 zone_idx == ZONE_MOVABLE) {
5317 ret = 0;
5318 goto out;
5319 }
5320 5368
5321 pfn = page_to_pfn(page); 5369 pfn = page_to_pfn(page);
5322 arg.start_pfn = pfn; 5370 arg.start_pfn = pfn;
@@ -5338,21 +5386,18 @@ int set_migratetype_isolate(struct page *page)
5338 notifier_ret = notifier_to_errno(notifier_ret); 5386 notifier_ret = notifier_to_errno(notifier_ret);
5339 if (notifier_ret) 5387 if (notifier_ret)
5340 goto out; 5388 goto out;
5341 5389 /*
5342 for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) { 5390 * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
5343 if (!pfn_valid_within(pfn)) 5391 * We just check MOVABLE pages.
5344 continue; 5392 */
5345 5393 if (__count_immobile_pages(zone, page, arg.pages_found))
5346 curr_page = pfn_to_page(iter);
5347 if (!page_count(curr_page) || PageLRU(curr_page))
5348 continue;
5349
5350 immobile++;
5351 }
5352
5353 if (arg.pages_found == immobile)
5354 ret = 0; 5394 ret = 0;
5355 5395
5396 /*
5397 * immobile means "not-on-lru" paes. If immobile is larger than
5398 * removable-by-driver pages reported by notifier, we'll fail.
5399 */
5400
5356out: 5401out:
5357 if (!ret) { 5402 if (!ret) {
5358 set_pageblock_migratetype(page, MIGRATE_ISOLATE); 5403 set_pageblock_migratetype(page, MIGRATE_ISOLATE);