* [RFC PATCH 0/3 V1 resend] mm: add new migrate type and online_movable for hotplug
@ 2012-07-04 8:38 Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 1/3 V1 resend] mm, page_alloc: use __rmqueue_smallest when borrow memory from MIGRATE_CMA Lai Jiangshan
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Lai Jiangshan @ 2012-07-04 8:38 UTC (permalink / raw)
To: Mel Gorman
Cc: Chris Metcalf, Len Brown, Greg Kroah-Hartman, Andi Kleen,
Julia Lawall, David Howells, Lai Jiangshan,
Benjamin Herrenschmidt, Kay Sievers, Ingo Molnar, Paul Gortmaker,
Daniel Kiper, Andrew Morton, Konrad Rzeszutek Wilk, Michal Hocko,
KAMEZAWA Hiroyuki, Minchan Kim, Michal Nazarewicz,
Marek Szyprowski, Rik van Riel, Bjorn Helgaas, Christoph Lameter,
David Rientjes, linux-kernel, linux-acpi, linux-mm
This patchset adds a stable-movable-migrate-type for memory-management,
It is used for anti-fragmentation(hugepage, big-order allocation...),
hot-removal-of-memory(virtualization, power-conserve, move memory between systems
to make better utilities of memories).
it likes ZONE_MOVABLE, but it is more flexible.
o The 1st patch fixes the allocation of CMA and do prepares
for movable-like types.
o The 2nd patch add a new migrate type which stands for the movable types
which pages will not be changed to the other type.
I chose the name MIGRATE_HOTREMOVE from MIGRATE_HOTREMOVE
and MIGRATE_MOVABLE_STABLE, it just because the first usecase of
this new type is for hotremove.
o The 3th path introduces online_movable. When a memoryblock is onlined
by "online_movable", the kernel will not have directly reference to
the page of the memoryblock, thus we can remove that memory any time
when needed.
Different from ZONE_MOVABLE: it can be used for any given memroyblock.
it can be set after boot(ZONE_MOVABLE zones are configured when booting)
Lai Jiangshan (3):
use __rmqueue_smallest when borrow memory from MIGRATE_CMA
add MIGRATE_HOTREMOVE type
add online_movable
arch/tile/mm/init.c | 2 +-
drivers/acpi/acpi_memhotplug.c | 3 +-
drivers/base/memory.c | 24 +++++++----
include/linux/memory.h | 1 +
include/linux/memory_hotplug.h | 4 +-
include/linux/mmzone.h | 37 +++++++++++++++++
include/linux/page-isolation.h | 2 +-
mm/compaction.c | 6 +-
mm/memory-failure.c | 8 +++-
mm/memory_hotplug.c | 36 +++++++++++++---
mm/page_alloc.c | 86 ++++++++++++++++-----------------------
mm/vmstat.c | 3 +
12 files changed, 136 insertions(+), 76 deletions(-)
--
1.7.4.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC PATCH 1/3 V1 resend] mm, page_alloc: use __rmqueue_smallest when borrow memory from MIGRATE_CMA
2012-07-04 8:38 [RFC PATCH 0/3 V1 resend] mm: add new migrate type and online_movable for hotplug Lai Jiangshan
@ 2012-07-04 8:38 ` Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 2/3 V1 resend] mm, page migrate: add MIGRATE_HOTREMOVE type Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 3/3 V1 resend] mm, memory-hotplug: add online_movable Lai Jiangshan
2 siblings, 0 replies; 4+ messages in thread
From: Lai Jiangshan @ 2012-07-04 8:38 UTC (permalink / raw)
To: Mel Gorman
Cc: Chris Metcalf, Len Brown, Greg Kroah-Hartman, Andi Kleen,
Julia Lawall, David Howells, Lai Jiangshan,
Benjamin Herrenschmidt, Kay Sievers, Ingo Molnar, Paul Gortmaker,
Daniel Kiper, Andrew Morton, Konrad Rzeszutek Wilk, Michal Hocko,
KAMEZAWA Hiroyuki, Minchan Kim, Michal Nazarewicz,
Marek Szyprowski, Rik van Riel, Bjorn Helgaas, Christoph Lameter,
David Rientjes, linux-kernel, linux-acpi, linux-mm
The pages of MIGRATE_CMA can't not be changed to the other type,
nor be moved to the other free list.
==>
So when we use __rmqueue_fallback() to borrow memory from MIGRATE_CMA,
one of the highest order page is borrowed and it is split.
But the free pages resulted by splitting can NOT
be moved to MIGRATE_MOVABLE.
==>
So in the next time of allocation, we NEED to borrow again,
another one of the highest order page is borrowed from CMA and it is split.
and results some other new split free pages.
==>
So when __rmqueue_fallback() borrows (highest order)memory from MIGRATE_CMA,
it introduces fragments at the same time and may waste tlb(only one page is used in
a pageblock).
Conclusion:
We should borrows the smallest order memory from MIGRATE_CMA in such case
Result(good):
1) use __rmqueue_smallest when borrow memory from MIGRATE_CMA
2) __rmqueue_fallback() don't handle CMA, it becomes much simpler
Result(bad):
__rmqueue_smallest() can't not be inlined to avoid function call overhead.
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
---
include/linux/mmzone.h | 1 +
mm/page_alloc.c | 63 ++++++++++++++++--------------------------------
2 files changed, 22 insertions(+), 42 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index bf3404e..979c333 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -40,6 +40,7 @@ enum {
MIGRATE_RECLAIMABLE,
MIGRATE_MOVABLE,
MIGRATE_PCPTYPES, /* the number of types on the pcp lists */
+ MIGRATE_PRIME_TYPES = MIGRATE_PCPTYPES,
MIGRATE_RESERVE = MIGRATE_PCPTYPES,
#ifdef CONFIG_CMA
/*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 476ae3e..efc327f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -893,17 +893,10 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
* This array describes the order lists are fallen back to when
* the free lists for the desirable migrate type are depleted
*/
-static int fallbacks[MIGRATE_TYPES][4] = {
- [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
- [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
-#ifdef CONFIG_CMA
- [MIGRATE_MOVABLE] = { MIGRATE_CMA, MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
- [MIGRATE_CMA] = { MIGRATE_RESERVE }, /* Never used */
-#else
- [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
-#endif
- [MIGRATE_RESERVE] = { MIGRATE_RESERVE }, /* Never used */
- [MIGRATE_ISOLATE] = { MIGRATE_RESERVE }, /* Never used */
+static int fallbacks[MIGRATE_PRIME_TYPES][2] = {
+ [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE },
+ [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE },
+ [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE },
};
/*
@@ -995,16 +988,15 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
struct page *page;
int migratetype, i;
+ if (WARN_ON_ONCE(start_migratetype >= MIGRATE_PRIME_TYPES))
+ start_migratetype = MIGRATE_UNMOVABLE;
+
/* Find the largest possible block of pages in the other list */
for (current_order = MAX_ORDER-1; current_order >= order;
--current_order) {
- for (i = 0;; i++) {
+ for (i = 0; i < ARRAY_SIZE(fallbacks[0]); i++) {
migratetype = fallbacks[start_migratetype][i];
- /* MIGRATE_RESERVE handled later if necessary */
- if (migratetype == MIGRATE_RESERVE)
- break;
-
area = &(zone->free_area[current_order]);
if (list_empty(&area->free_list[migratetype]))
continue;
@@ -1018,17 +1010,10 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
* pages to the preferred allocation list. If falling
* back for a reclaimable kernel allocation, be more
* aggressive about taking ownership of free pages
- *
- * On the other hand, never change migration
- * type of MIGRATE_CMA pageblocks nor move CMA
- * pages on different free lists. We don't
- * want unmovable pages to be allocated from
- * MIGRATE_CMA areas.
*/
- if (!is_migrate_cma(migratetype) &&
- (unlikely(current_order >= pageblock_order / 2) ||
- start_migratetype == MIGRATE_RECLAIMABLE ||
- page_group_by_mobility_disabled)) {
+ if (unlikely(current_order >= pageblock_order / 2) ||
+ start_migratetype == MIGRATE_RECLAIMABLE ||
+ page_group_by_mobility_disabled) {
int pages;
pages = move_freepages_block(zone, page,
start_migratetype);
@@ -1047,14 +1032,12 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
rmv_page_order(page);
/* Take ownership for orders >= pageblock_order */
- if (current_order >= pageblock_order &&
- !is_migrate_cma(migratetype))
+ if (current_order >= pageblock_order)
change_pageblock_range(page, current_order,
start_migratetype);
expand(zone, page, order, current_order, area,
- is_migrate_cma(migratetype)
- ? migratetype : start_migratetype);
+ start_migratetype);
trace_mm_page_alloc_extfrag(page, order, current_order,
start_migratetype, migratetype);
@@ -1075,22 +1058,18 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order,
{
struct page *page;
-retry_reserve:
page = __rmqueue_smallest(zone, order, migratetype);
- if (unlikely(!page) && migratetype != MIGRATE_RESERVE) {
+#ifdef CONFIG_CMA
+ if (unlikely(!page) && migratetype == MIGRATE_MOVABLE)
+ page = __rmqueue_smallest(zone, order, MIGRATE_CMA);
+#endif
+
+ if (unlikely(!page))
page = __rmqueue_fallback(zone, order, migratetype);
- /*
- * Use MIGRATE_RESERVE rather than fail an allocation. goto
- * is used because __rmqueue_smallest is an inline function
- * and we want just one call site
- */
- if (!page) {
- migratetype = MIGRATE_RESERVE;
- goto retry_reserve;
- }
- }
+ if (unlikely(!page))
+ page = __rmqueue_smallest(zone, order, MIGRATE_RESERVE);
trace_mm_page_alloc_zone_locked(page, order, migratetype);
return page;
--
1.7.4.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [RFC PATCH 2/3 V1 resend] mm, page migrate: add MIGRATE_HOTREMOVE type
2012-07-04 8:38 [RFC PATCH 0/3 V1 resend] mm: add new migrate type and online_movable for hotplug Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 1/3 V1 resend] mm, page_alloc: use __rmqueue_smallest when borrow memory from MIGRATE_CMA Lai Jiangshan
@ 2012-07-04 8:38 ` Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 3/3 V1 resend] mm, memory-hotplug: add online_movable Lai Jiangshan
2 siblings, 0 replies; 4+ messages in thread
From: Lai Jiangshan @ 2012-07-04 8:38 UTC (permalink / raw)
To: Mel Gorman
Cc: Chris Metcalf, Len Brown, Greg Kroah-Hartman, Andi Kleen,
Julia Lawall, David Howells, Lai Jiangshan,
Benjamin Herrenschmidt, Kay Sievers, Ingo Molnar, Paul Gortmaker,
Daniel Kiper, Andrew Morton, Konrad Rzeszutek Wilk, Michal Hocko,
KAMEZAWA Hiroyuki, Minchan Kim, Michal Nazarewicz,
Marek Szyprowski, Rik van Riel, Bjorn Helgaas, Christoph Lameter,
David Rientjes, linux-kernel, linux-acpi, linux-mm
MIGRATE_HOTREMOVE is a special kind of MIGRATE_MOVABLE, but it is stable:
any page of the type can NOT be changed to the other type nor be moved to
the other free list.
So the pages of MIGRATE_HOTREMOVE are always movable, this ability is
useful for hugepages and hotremove ...etc.
MIGRATE_HOTREMOVE pages is the used as the first candidate when
we allocate movable pages.
1) add small routine is_migrate_movable() for movable-like types
2) add small routine is_migrate_stable() for stable types
3) fix some comments
4) fix get_any_page(). The get_any_page() may change
MIGRATE_CMA/HOTREMOVE types page to MOVABLE which may cause this page
to be changed to UNMOVABLE.
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
---
include/linux/mmzone.h | 34 ++++++++++++++++++++++++++++++++++
include/linux/page-isolation.h | 2 +-
mm/compaction.c | 6 +++---
mm/memory-failure.c | 8 +++++++-
mm/page_alloc.c | 21 +++++++++++++--------
mm/vmstat.c | 3 +++
6 files changed, 61 insertions(+), 13 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 979c333..872f430 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -58,6 +58,15 @@ enum {
*/
MIGRATE_CMA,
#endif
+#ifdef CONFIG_MEMORY_HOTREMOVE
+ /*
+ * MIGRATE_HOTREMOVE migration type is designed to mimic the way
+ * ZONE_MOVABLE works. Only movable pages can be allocated
+ * from MIGRATE_HOTREMOVE pageblocks and page allocator never
+ * implicitly change migration type of MIGRATE_HOTREMOVE pageblock.
+ */
+ MIGRATE_HOTREMOVE,
+#endif
MIGRATE_ISOLATE, /* can't allocate from here */
MIGRATE_TYPES
};
@@ -70,6 +79,31 @@ enum {
# define cma_wmark_pages(zone) 0
#endif
+#ifdef CONFIG_MEMORY_HOTREMOVE
+#define is_migrate_hotremove(migratetype) ((migratetype) == MIGRATE_HOTREMOVE)
+#else
+#define is_migrate_hotremove(migratetype) false
+#endif
+
+/* Is it one of the movable types */
+static inline bool is_migrate_movable(int migratetype)
+{
+ return is_migrate_hotremove(migratetype) ||
+ migratetype == MIGRATE_MOVABLE ||
+ is_migrate_cma(migratetype);
+}
+
+/*
+ * Stable types: any page of the type can NOT be changed to
+ * the other type nor be moved to the other free list.
+ */
+static inline bool is_migrate_stable(int migratetype)
+{
+ return is_migrate_hotremove(migratetype) ||
+ is_migrate_cma(migratetype) ||
+ migratetype == MIGRATE_RESERVE;
+}
+
#define for_each_migratetype_order(order, type) \
for (order = 0; order < MAX_ORDER; order++) \
for (type = 0; type < MIGRATE_TYPES; type++)
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h
index 3bdcab3..b1d6d92 100644
--- a/include/linux/page-isolation.h
+++ b/include/linux/page-isolation.h
@@ -15,7 +15,7 @@ start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
unsigned migratetype);
/*
- * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE.
+ * Changes MIGRATE_ISOLATE to migratetype.
* target range is [start_pfn, end_pfn)
*/
extern int
diff --git a/mm/compaction.c b/mm/compaction.c
index 7ea259d..e8da894 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -47,7 +47,7 @@ static void map_pages(struct list_head *list)
static inline bool migrate_async_suitable(int migratetype)
{
- return is_migrate_cma(migratetype) || migratetype == MIGRATE_MOVABLE;
+ return is_migrate_movable(migratetype);
}
/*
@@ -375,8 +375,8 @@ static bool suitable_migration_target(struct page *page)
if (PageBuddy(page) && page_order(page) >= pageblock_order)
return true;
- /* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */
- if (migrate_async_suitable(migratetype))
+ /* If the block is movable, allow migration */
+ if (is_migrate_movable(migratetype))
return true;
/* Otherwise skip the block */
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index ab1e714..f5e300d 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1367,6 +1367,7 @@ static struct page *new_page(struct page *p, unsigned long private, int **x)
static int get_any_page(struct page *p, unsigned long pfn, int flags)
{
int ret;
+ int mt;
if (flags & MF_COUNT_INCREASED)
return 1;
@@ -1377,6 +1378,11 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags)
*/
lock_memory_hotplug();
+ /* Don't move page of stable type to MIGRATE_MOVABLE */
+ mt = get_pageblock_migratetype(p);
+ if (!is_migrate_stable(mt))
+ mt = MIGRATE_MOVABLE;
+
/*
* Isolate the page, so that it doesn't get reallocated if it
* was free.
@@ -1404,7 +1410,7 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags)
/* Not a free page */
ret = 1;
}
- unset_migratetype_isolate(p, MIGRATE_MOVABLE);
+ unset_migratetype_isolate(p, mt);
unlock_memory_hotplug();
return ret;
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index efc327f..7a4a03b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -667,7 +667,7 @@ static void free_pcppages_bulk(struct zone *zone, int count,
page = list_entry(list->prev, struct page, lru);
/* must delete as __free_one_page list manipulates */
list_del(&page->lru);
- /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
+ /* MIGRATE_MOVABLE list may include other types */
__free_one_page(page, zone, 0, page_private(page));
trace_mm_page_pcpu_drain(page, 0, page_private(page));
} while (--to_free && --batch_free && !list_empty(list));
@@ -1058,6 +1058,14 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order,
{
struct page *page;
+#ifdef CONFIG_MEMORY_HOTREMOVE
+ if (migratetype == MIGRATE_MOVABLE) {
+ page = __rmqueue_smallest(zone, order, MIGRATE_HOTREMOVE);
+ if (likely(page))
+ goto done;
+ }
+#endif
+
page = __rmqueue_smallest(zone, order, migratetype);
#ifdef CONFIG_CMA
@@ -1071,6 +1079,7 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order,
if (unlikely(!page))
page = __rmqueue_smallest(zone, order, MIGRATE_RESERVE);
+done:
trace_mm_page_alloc_zone_locked(page, order, migratetype);
return page;
}
@@ -1105,11 +1114,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
list_add(&page->lru, list);
else
list_add_tail(&page->lru, list);
- if (IS_ENABLED(CONFIG_CMA)) {
- mt = get_pageblock_migratetype(page);
- if (!is_migrate_cma(mt) && mt != MIGRATE_ISOLATE)
- mt = migratetype;
- }
+ mt = get_pageblock_migratetype(page);
set_page_private(page, mt);
list = &page->lru;
}
@@ -1392,7 +1397,7 @@ int split_free_page(struct page *page)
struct page *endpage = page + (1 << order) - 1;
for (; page < endpage; page += pageblock_nr_pages) {
int mt = get_pageblock_migratetype(page);
- if (mt != MIGRATE_ISOLATE && !is_migrate_cma(mt))
+ if (mt != MIGRATE_ISOLATE && !is_migrate_stable(mt))
set_pageblock_migratetype(page,
MIGRATE_MOVABLE);
}
@@ -5465,7 +5470,7 @@ __count_immobile_pages(struct zone *zone, struct page *page, int count)
if (zone_idx(zone) == ZONE_MOVABLE)
return true;
mt = get_pageblock_migratetype(page);
- if (mt == MIGRATE_MOVABLE || is_migrate_cma(mt))
+ if (is_migrate_movable(mt))
return true;
pfn = page_to_pfn(page);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 1bbbbd9..44a3b7f 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -616,6 +616,9 @@ static char * const migratetype_names[MIGRATE_TYPES] = {
#ifdef CONFIG_CMA
"CMA",
#endif
+#ifdef CONFIG_MEMORY_HOTREMOVE
+ "Hotremove",
+#endif
"Isolate",
};
--
1.7.4.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [RFC PATCH 3/3 V1 resend] mm, memory-hotplug: add online_movable
2012-07-04 8:38 [RFC PATCH 0/3 V1 resend] mm: add new migrate type and online_movable for hotplug Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 1/3 V1 resend] mm, page_alloc: use __rmqueue_smallest when borrow memory from MIGRATE_CMA Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 2/3 V1 resend] mm, page migrate: add MIGRATE_HOTREMOVE type Lai Jiangshan
@ 2012-07-04 8:38 ` Lai Jiangshan
2 siblings, 0 replies; 4+ messages in thread
From: Lai Jiangshan @ 2012-07-04 8:38 UTC (permalink / raw)
To: Mel Gorman
Cc: Chris Metcalf, Len Brown, Greg Kroah-Hartman, Andi Kleen,
Julia Lawall, David Howells, Lai Jiangshan,
Benjamin Herrenschmidt, Kay Sievers, Ingo Molnar, Paul Gortmaker,
Daniel Kiper, Andrew Morton, Konrad Rzeszutek Wilk, Michal Hocko,
KAMEZAWA Hiroyuki, Minchan Kim, Michal Nazarewicz,
Marek Szyprowski, Rik van Riel, Bjorn Helgaas, Christoph Lameter,
David Rientjes, linux-kernel, linux-acpi, linux-mm
When a memoryblock is onlined by "online_movable", the kernel will not
have directly reference to the page of the memoryblock,
thus we can remove that memory any time when needed.
It makes things easy when we dynamic hot-add/remove memory, make better
utilities of memories.
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
---
arch/tile/mm/init.c | 2 +-
drivers/acpi/acpi_memhotplug.c | 3 ++-
drivers/base/memory.c | 24 +++++++++++++++---------
include/linux/memory.h | 1 +
include/linux/memory_hotplug.h | 4 ++--
include/linux/mmzone.h | 2 ++
mm/memory_hotplug.c | 36 +++++++++++++++++++++++++++++-------
mm/page_alloc.c | 2 +-
8 files changed, 53 insertions(+), 21 deletions(-)
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c
index 630dd2c..624d397 100644
--- a/arch/tile/mm/init.c
+++ b/arch/tile/mm/init.c
@@ -943,7 +943,7 @@ int arch_add_memory(u64 start, u64 size)
return __add_pages(zone, start_pfn, nr_pages);
}
-int remove_memory(u64 start, u64 size)
+int remove_memory(u64 start, u64 size, int movable)
{
return -EINVAL;
}
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index d985713..8a9c039 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -318,7 +318,8 @@ static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
*/
list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
if (info->enabled) {
- result = remove_memory(info->start_addr, info->length);
+ result = remove_memory(info->start_addr,
+ info->length, 0);
if (result)
return result;
}
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 7dda4f7..cc6c5d2 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -246,7 +246,7 @@ static bool pages_correctly_reserved(unsigned long start_pfn,
* OK to have direct references to sparsemem variables in here.
*/
static int
-memory_block_action(unsigned long phys_index, unsigned long action)
+memory_block_action(unsigned long phys_index, unsigned long action, int movable)
{
unsigned long start_pfn, start_paddr;
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
@@ -262,12 +262,12 @@ memory_block_action(unsigned long phys_index, unsigned long action)
if (!pages_correctly_reserved(start_pfn, nr_pages))
return -EBUSY;
- ret = online_pages(start_pfn, nr_pages);
+ ret = online_pages(start_pfn, nr_pages, movable);
break;
case MEM_OFFLINE:
start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
ret = remove_memory(start_paddr,
- nr_pages << PAGE_SHIFT);
+ nr_pages << PAGE_SHIFT, movable);
break;
default:
WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
@@ -279,7 +279,8 @@ memory_block_action(unsigned long phys_index, unsigned long action)
}
static int memory_block_change_state(struct memory_block *mem,
- unsigned long to_state, unsigned long from_state_req)
+ unsigned long to_state, unsigned long from_state_req,
+ int movable)
{
int ret = 0;
@@ -290,16 +291,19 @@ static int memory_block_change_state(struct memory_block *mem,
goto out;
}
- if (to_state == MEM_OFFLINE)
+ if (to_state == MEM_OFFLINE) {
+ movable = mem->movable;
mem->state = MEM_GOING_OFFLINE;
+ }
- ret = memory_block_action(mem->start_section_nr, to_state);
+ ret = memory_block_action(mem->start_section_nr, to_state, movable);
if (ret) {
mem->state = from_state_req;
goto out;
}
+ mem->movable = movable;
mem->state = to_state;
switch (mem->state) {
case MEM_OFFLINE:
@@ -325,10 +329,12 @@ store_mem_state(struct device *dev,
mem = container_of(dev, struct memory_block, dev);
- if (!strncmp(buf, "online", min((int)count, 6)))
- ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
+ if (!strncmp(buf, "online_movable", min((int)count, 14)))
+ ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE, 1);
+ else if (!strncmp(buf, "online", min((int)count, 6)))
+ ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE, 0);
else if(!strncmp(buf, "offline", min((int)count, 7)))
- ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
+ ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE, 0);
if (ret)
return ret;
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 1ac7f6e..90eae9c 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -26,6 +26,7 @@ struct memory_block {
unsigned long end_section_nr;
unsigned long state;
int section_count;
+ int movable;
/*
* This serializes all state change requests. It isn't
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 910550f..0e6501c 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -70,7 +70,7 @@ extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages);
extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages);
extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
/* VM interface that may be used by firmware interface */
-extern int online_pages(unsigned long, unsigned long);
+extern int online_pages(unsigned long, unsigned long, int);
extern void __offline_isolated_pages(unsigned long, unsigned long);
typedef void (*online_page_callback_t)(struct page *page);
@@ -233,7 +233,7 @@ static inline int is_mem_section_removable(unsigned long pfn,
extern int mem_online_node(int nid);
extern int add_memory(int nid, u64 start, u64 size);
extern int arch_add_memory(int nid, u64 start, u64 size);
-extern int remove_memory(u64 start, u64 size);
+extern int remove_memory(u64 start, u64 size, int);
extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
int nr_pages);
extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms);
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 872f430..458bd0b 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -115,6 +115,8 @@ static inline int get_pageblock_migratetype(struct page *page)
return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
}
+extern void set_pageblock_migratetype(struct page *page, int migratetype);
+
struct free_area {
struct list_head free_list[MIGRATE_TYPES];
unsigned long nr_free;
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 0d7e3ec..cb49893 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -457,7 +457,7 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
}
-int __ref online_pages(unsigned long pfn, unsigned long nr_pages)
+int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int movable)
{
unsigned long onlined_pages = 0;
struct zone *zone;
@@ -466,6 +466,12 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages)
int ret;
struct memory_notify arg;
+ /* at least, alignment against pageblock is necessary */
+ if (!IS_ALIGNED(pfn, pageblock_nr_pages))
+ return -EINVAL;
+ if (!IS_ALIGNED(nr_pages, pageblock_nr_pages))
+ return -EINVAL;
+
lock_memory_hotplug();
arg.start_pfn = pfn;
arg.nr_pages = nr_pages;
@@ -497,6 +503,21 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages)
if (!populated_zone(zone))
need_zonelists_rebuild = 1;
+#ifdef CONFIG_MEMORY_HOTREMOVE
+ if (movable) {
+ unsigned long offset;
+
+ for (offset = 0;
+ offset < nr_pages;
+ offset += pageblock_nr_pages) {
+ spin_lock_irq(&zone->lock);
+ set_pageblock_migratetype(pfn_to_page(pfn + offset),
+ MIGRATE_HOTREMOVE);
+ spin_unlock_irq(&zone->lock);
+ }
+ }
+#endif
+
ret = walk_system_ram_range(pfn, nr_pages, &onlined_pages,
online_pages_range);
if (ret) {
@@ -866,13 +887,14 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
}
static int __ref offline_pages(unsigned long start_pfn,
- unsigned long end_pfn, unsigned long timeout)
+ unsigned long end_pfn, unsigned long timeout, int movable)
{
unsigned long pfn, nr_pages, expire;
long offlined_pages;
int ret, drain, retry_max, node;
struct zone *zone;
struct memory_notify arg;
+ int origin_mt = movable ? MIGRATE_HOTREMOVE : MIGRATE_MOVABLE;
BUG_ON(start_pfn >= end_pfn);
/* at least, alignment against pageblock is necessary */
@@ -892,7 +914,7 @@ static int __ref offline_pages(unsigned long start_pfn,
nr_pages = end_pfn - start_pfn;
/* set above range as isolated */
- ret = start_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
+ ret = start_isolate_page_range(start_pfn, end_pfn, origin_mt);
if (ret)
goto out;
@@ -983,23 +1005,23 @@ failed_removal:
((unsigned long long) end_pfn << PAGE_SHIFT) - 1);
memory_notify(MEM_CANCEL_OFFLINE, &arg);
/* pushback to free area */
- undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
+ undo_isolate_page_range(start_pfn, end_pfn, origin_mt);
out:
unlock_memory_hotplug();
return ret;
}
-int remove_memory(u64 start, u64 size)
+int remove_memory(u64 start, u64 size, int movable)
{
unsigned long start_pfn, end_pfn;
start_pfn = PFN_DOWN(start);
end_pfn = start_pfn + PFN_DOWN(size);
- return offline_pages(start_pfn, end_pfn, 120 * HZ);
+ return offline_pages(start_pfn, end_pfn, 120 * HZ, movable);
}
#else
-int remove_memory(u64 start, u64 size)
+int remove_memory(u64 start, u64 size, int movable)
{
return -EINVAL;
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 7a4a03b..801772c 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -219,7 +219,7 @@ EXPORT_SYMBOL(nr_online_nodes);
int page_group_by_mobility_disabled __read_mostly;
-static void set_pageblock_migratetype(struct page *page, int migratetype)
+void set_pageblock_migratetype(struct page *page, int migratetype)
{
if (unlikely(page_group_by_mobility_disabled))
--
1.7.4.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-07-04 8:38 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-04 8:38 [RFC PATCH 0/3 V1 resend] mm: add new migrate type and online_movable for hotplug Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 1/3 V1 resend] mm, page_alloc: use __rmqueue_smallest when borrow memory from MIGRATE_CMA Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 2/3 V1 resend] mm, page migrate: add MIGRATE_HOTREMOVE type Lai Jiangshan
2012-07-04 8:38 ` [RFC PATCH 3/3 V1 resend] mm, memory-hotplug: add online_movable Lai Jiangshan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).