summaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
authorMichal Nazarewicz <mina86@xxxxxxxxxx>2011-12-20 08:53:33 +0800
committerAndy Green <andy.green@linaro.org>2011-12-26 15:09:42 +0800
commitcff293c606578cfbbbea6092db71d89763741b8e (patch)
treeeb49c37aa42148d4bb6d5a7169c50a7f2256bf72 /mm
parent9661604073fad76e64ef5aae52193b78e8bb4779 (diff)
If page is on PCP list while pageblock it belongs to gets isolated,
the page's private still holds the old migrate type. This means that free_pcppages_bulk() will put the page on a freelist of the old migrate type instead of MIGRATE_ISOLATE. This commit changes that by explicitly checking whether page's pageblock's migrate type is MIGRATE_ISOLATE and if it is, overwrites page's private data. Signed-off-by: Michal Nazarewicz <mina86@xxxxxxxxxx> Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2b8ba3aebf6..7cfd08448bc 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -628,6 +628,18 @@ 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);
+
+ /*
+ * When page is isolated in set_migratetype_isolate()
+ * function it's page_private is not changed since the
+ * function has no way of knowing if it can touch it.
+ * This means that when a page is on PCP list, it's
+ * page_private no longer matches the desired migrate
+ * type.
+ */
+ if (get_pageblock_migratetype(page) == MIGRATE_ISOLATE)
+ set_page_private(page, MIGRATE_ISOLATE);
+
/* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
__free_one_page(page, zone, 0, page_private(page));
trace_mm_page_pcpu_drain(page, 0, page_private(page));