From: Michal Nazarewicz <m.nazarewicz@samsung.com>
To: mina86@mina86.com
Cc: Andrew Morton <akpm@linux-foundation.org>,
Ankita Garg <ankita@in.ibm.com>,
Bryan Huntsman <bryanh@codeaurora.org>,
Daniel Walker <dwalker@codeaurora.org>,
FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>,
Hans Verkuil <hverkuil@xs4all.nl>,
Johan Mossberg <johan.xx.mossberg@stericsson.com>,
Jonathan Corbet <corbet@lwn.net>,
KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>,
Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
Marcus LORENTZON <marcus.xm.lorentzon@stericsson.com>,
Marek Szyprowski <m.szyprowski@samsung.com>,
Mark Brown <broonie@opensource.wolfsonmicro.com>,
Mel Gorman <mel@csn.ul.ie>, Pawel Osciak <pawel@osciak.com>,
Russell King <linux@arm.linux.org.uk>,
Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>,
Zach Pfeffer <zpfeffer@codeaurora.org>,
dipankar@in.ibm.com, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-media@vger.kernel.org,
linux-mm@kvack.org
Subject: [RFCv6 10/13] mm: MIGRATE_CMA migration type added
Date: Fri, 19 Nov 2010 16:58:08 +0100 [thread overview]
Message-ID: <3ce957fd990a221ee9e9e3047bb564d2ed11eebf.1290172312.git.m.nazarewicz@samsung.com> (raw)
In-Reply-To: <cover.1290172312.git.m.nazarewicz@samsung.com>
The MIGRATE_CMA migration type has two main characteristics:
(i) only movable and reclaimable pages can be allocated from
MIGRATE_CMA page blocks and (ii) page allocator will never
change migration type of MIGRATE_CMA page blocks.
This guarantees that page in a MIGRATE_CMA page block can
always be freed (by reclaiming it or moving somewhere else).
It is designed to be used with Contiguous Memory Allocator
(CMA) for allocating big chunks (eg. 10MiB) of physically
contiguous memory. Once driver requests contiguous memory,
CMA will migrate or reclaim pages from MIGRATE_CMA page block.
To minimise number of migrations, MIGRATE_CMA migration type
is the last type tried when page allocator falls back to other
migration types then requested.
To use this new migration type one can use
__free_pageblock_cma() function which moves frees a whole page
block to a buddy allocator marking it (and thus all pages in
it) as MIGRATE_CMA.
Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
include/linux/mmzone.h | 30 +++++++++++++----
mm/Kconfig | 9 +++++
mm/compaction.c | 10 ++++++
mm/internal.h | 3 ++
mm/page_alloc.c | 83 +++++++++++++++++++++++++++++++++++++++---------
5 files changed, 113 insertions(+), 22 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 39c24eb..317da6b 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -35,13 +35,24 @@
*/
#define PAGE_ALLOC_COSTLY_ORDER 3
-#define MIGRATE_UNMOVABLE 0
-#define MIGRATE_RECLAIMABLE 1
-#define MIGRATE_MOVABLE 2
-#define MIGRATE_PCPTYPES 3 /* the number of types on the pcp lists */
-#define MIGRATE_RESERVE 3
-#define MIGRATE_ISOLATE 4 /* can't allocate from here */
-#define MIGRATE_TYPES 5
+enum {
+ MIGRATE_UNMOVABLE,
+ MIGRATE_RECLAIMABLE,
+ MIGRATE_MOVABLE,
+ MIGRATE_PCPTYPES, /* the number of types on the pcp lists */
+ MIGRATE_RESERVE = MIGRATE_PCPTYPES,
+ MIGRATE_ISOLATE, /* can't allocate from here */
+#ifdef CONFIG_MIGRATE_CMA
+ MIGRATE_CMA, /* only movable & reclaimable */
+#endif
+ MIGRATE_TYPES
+};
+
+#ifdef CONFIG_MIGRATE_CMA
+# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
+#else
+# define is_migrate_cma(migratetype) false
+#endif
#define for_each_migratetype_order(order, type) \
for (order = 0; order < MAX_ORDER; order++) \
@@ -54,6 +65,11 @@ static inline int get_pageblock_migratetype(struct page *page)
return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
}
+static inline bool is_pageblock_cma(struct page *page)
+{
+ return is_migrate_cma(get_pageblock_migratetype(page));
+}
+
struct free_area {
struct list_head free_list[MIGRATE_TYPES];
unsigned long nr_free;
diff --git a/mm/Kconfig b/mm/Kconfig
index 5ad2471..4aee3c5 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -1,3 +1,12 @@
+config MIGRATE_CMA
+ bool
+ help
+ This option should be selected by code that requires MIGRATE_CMA
+ migration type to be present. Once a page block has this
+ migration type, only movable and reclaimable pages can be
+ allocated from it and the page block never changes it's
+ migration type.
+
config SELECT_MEMORY_MODEL
def_bool y
depends on EXPERIMENTAL || ARCH_SELECT_MEMORY_MODEL
diff --git a/mm/compaction.c b/mm/compaction.c
index 4d709ee..c5e404b 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -113,6 +113,16 @@ static bool suitable_migration_target(struct page *page)
if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE)
return false;
+ /* Keep MIGRATE_CMA alone as well. */
+ /*
+ * XXX Revisit. We currently cannot let compaction touch CMA
+ * pages since compaction insists on changing their migration
+ * type to MIGRATE_MOVABLE (see split_free_page() called from
+ * isolate_freepages_block() above).
+ */
+ if (is_migrate_cma(migratetype))
+ return false;
+
/* If the page is a large free page, then allow migration */
if (PageBuddy(page) && page_order(page) >= pageblock_order)
return true;
diff --git a/mm/internal.h b/mm/internal.h
index dedb0af..cc24e74 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -49,6 +49,9 @@ extern void putback_lru_page(struct page *page);
* in mm/page_alloc.c
*/
extern void __free_pages_bootmem(struct page *page, unsigned int order);
+#ifdef CONFIG_MIGRATE_CMA
+extern void __free_pageblock_cma(struct page *page);
+#endif
extern void prep_compound_page(struct page *page, unsigned long order);
#ifdef CONFIG_MEMORY_FAILURE
extern bool is_free_buddy_page(struct page *page);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 6dd2854..91daf22 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -712,6 +712,30 @@ void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
}
}
+#ifdef CONFIG_MIGRATE_CMA
+
+/*
+ * Free whole pageblock and set it's migration type to MIGRATE_CMA.
+ */
+void __init __free_pageblock_cma(struct page *page)
+{
+ struct page *p = page;
+ unsigned i = pageblock_nr_pages;
+
+ prefetchw(p);
+ do {
+ if (--i)
+ prefetchw(p + 1);
+ __ClearPageReserved(p);
+ set_page_count(p, 0);
+ } while (++p, i);
+
+ set_page_refcounted(page);
+ set_pageblock_migratetype(page, MIGRATE_CMA);
+ __free_pages(page, pageblock_order);
+}
+
+#endif
/*
* The order of subdivision here is critical for the IO subsystem.
@@ -819,11 +843,16 @@ 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][MIGRATE_TYPES-1] = {
+static int fallbacks[MIGRATE_TYPES][4] = {
[MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
+#ifdef CONFIG_MIGRATE_CMA
+ [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_CMA , MIGRATE_RESERVE },
+ [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_CMA , MIGRATE_RESERVE },
+#else
[MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
[MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
- [MIGRATE_RESERVE] = { MIGRATE_RESERVE, MIGRATE_RESERVE, MIGRATE_RESERVE }, /* Never used */
+#endif
+ [MIGRATE_RESERVE] = { MIGRATE_RESERVE }, /* Never used */
};
/*
@@ -919,12 +948,12 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
/* 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 < MIGRATE_TYPES - 1; 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)
- continue;
+ break;
area = &(zone->free_area[current_order]);
if (list_empty(&area->free_list[migratetype]))
@@ -941,17 +970,28 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
* agressive about taking ownership of free pages
*/
if (unlikely(current_order >= (pageblock_order >> 1)) ||
- start_migratetype == MIGRATE_RECLAIMABLE ||
- page_group_by_mobility_disabled) {
- unsigned long pages;
+ start_migratetype == MIGRATE_RECLAIMABLE ||
+ page_group_by_mobility_disabled) {
+ int pages;
pages = move_freepages_block(zone, page,
- start_migratetype);
+ start_migratetype);
- /* Claim the whole block if over half of it is free */
- if (pages >= (1 << (pageblock_order-1)) ||
- page_group_by_mobility_disabled)
+ /*
+ * Claim the whole block if over half
+ * of it is free
+ *
+ * On the other hand, never change
+ * migration type of MIGRATE_CMA
+ * pageblockss. We don't want
+ * unmovable or unreclaimable pages to
+ * be allocated from MIGRATE_CMA
+ * areas.
+ */
+ if (!is_pageblock_cma(page) &&
+ (pages >= (1 << (pageblock_order-1)) ||
+ page_group_by_mobility_disabled))
set_pageblock_migratetype(page,
- start_migratetype);
+ start_migratetype);
migratetype = start_migratetype;
}
@@ -961,7 +1001,8 @@ __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)
+ if (current_order >= pageblock_order &&
+ !is_pageblock_cma(page))
change_pageblock_range(page, current_order,
start_migratetype);
@@ -1176,9 +1217,16 @@ void free_hot_cold_page(struct page *page, int cold)
* offlined but treat RESERVE as movable pages so we can get those
* areas back if necessary. Otherwise, we may have to free
* excessively into the page allocator
+ *
+ * Still, do not change migration type of MIGRATE_CMA pages (if
+ * they'd be recorded as MIGRATE_MOVABLE an unmovable page could
+ * be allocated from MIGRATE_CMA block and we don't want to allow
+ * that). In this respect, treat MIGRATE_CMA like
+ * MIGRATE_ISOLATE.
*/
if (migratetype >= MIGRATE_PCPTYPES) {
- if (unlikely(migratetype == MIGRATE_ISOLATE)) {
+ if (unlikely(migratetype == MIGRATE_ISOLATE
+ || is_migrate_cma(migratetype))) {
free_one_page(zone, page, 0, migratetype);
goto out;
}
@@ -1267,7 +1315,8 @@ int split_free_page(struct page *page)
if (order >= pageblock_order - 1) {
struct page *endpage = page + (1 << order) - 1;
for (; page < endpage; page += pageblock_nr_pages)
- set_pageblock_migratetype(page, MIGRATE_MOVABLE);
+ if (!is_pageblock_cma(page))
+ set_pageblock_migratetype(page, MIGRATE_MOVABLE);
}
return 1 << order;
@@ -5365,6 +5414,10 @@ int set_migratetype_isolate(struct page *page)
zone_idx = zone_idx(zone);
spin_lock_irqsave(&zone->lock, flags);
+ if (is_pageblock_cma(page)) {
+ ret = 0;
+ goto out;
+ }
pfn = page_to_pfn(page);
arg.start_pfn = pfn;
--
1.7.2.3
--
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/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2010-11-19 15:58 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-19 15:57 [RFCv6 00/13] The Contiguous Memory Allocator framework Michal Nazarewicz
2010-11-19 15:57 ` [RFCv6 01/13] lib: rbtree: rb_root_init() function added Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 02/13] lib: bitmap: Added alignment offset for bitmap_find_next_zero_area() Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 03/13] lib: genalloc: Generic allocator improvements Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 04/13] mm: cma: Contiguous Memory Allocator added Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 05/13] mm: cma: debugfs support added Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 06/13] mm: cma: Best-fit algorithm added Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 07/13] mm: cma: Test device and application added Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 08/13] mm: move some functions to page_isolation.c Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 09/13] mm: alloc_contig_free_pages() added Michal Nazarewicz
2010-11-19 15:58 ` Michal Nazarewicz [this message]
2010-11-19 15:58 ` [RFCv6 11/13] mm: MIGRATE_CMA isolation functions added Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 12/13] mm: cma: Migration support added [wip] Michal Nazarewicz
2010-11-19 15:58 ` [RFCv6 13/13] ARM: cma: Added CMA to Aquila, Goni and c210 universal boards Michal Nazarewicz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3ce957fd990a221ee9e9e3047bb564d2ed11eebf.1290172312.git.m.nazarewicz@samsung.com \
--to=m.nazarewicz@samsung.com \
--cc=akpm@linux-foundation.org \
--cc=ankita@in.ibm.com \
--cc=broonie@opensource.wolfsonmicro.com \
--cc=bryanh@codeaurora.org \
--cc=corbet@lwn.net \
--cc=dipankar@in.ibm.com \
--cc=dwalker@codeaurora.org \
--cc=fujita.tomonori@lab.ntt.co.jp \
--cc=hverkuil@xs4all.nl \
--cc=johan.xx.mossberg@stericsson.com \
--cc=kamezawa.hiroyu@jp.fujitsu.com \
--cc=konrad.wilk@oracle.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux@arm.linux.org.uk \
--cc=m.szyprowski@samsung.com \
--cc=marcus.xm.lorentzon@stericsson.com \
--cc=mel@csn.ul.ie \
--cc=mina86@mina86.com \
--cc=pawel@osciak.com \
--cc=svaidy@linux.vnet.ibm.com \
--cc=zpfeffer@codeaurora.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox