|
@@ -1080,12 +1080,10 @@ static void free_pcppages_bulk(struct zone *zone, int count,
|
|
int migratetype = 0;
|
|
int migratetype = 0;
|
|
int batch_free = 0;
|
|
int batch_free = 0;
|
|
bool isolated_pageblocks;
|
|
bool isolated_pageblocks;
|
|
-
|
|
|
|
- spin_lock(&zone->lock);
|
|
|
|
- isolated_pageblocks = has_isolate_pageblock(zone);
|
|
|
|
|
|
+ struct page *page, *tmp;
|
|
|
|
+ LIST_HEAD(head);
|
|
|
|
|
|
while (count) {
|
|
while (count) {
|
|
- struct page *page;
|
|
|
|
struct list_head *list;
|
|
struct list_head *list;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1107,27 +1105,36 @@ static void free_pcppages_bulk(struct zone *zone, int count,
|
|
batch_free = count;
|
|
batch_free = count;
|
|
|
|
|
|
do {
|
|
do {
|
|
- int mt; /* migratetype of the to-be-freed page */
|
|
|
|
-
|
|
|
|
page = list_last_entry(list, struct page, lru);
|
|
page = list_last_entry(list, struct page, lru);
|
|
- /* must delete as __free_one_page list manipulates */
|
|
|
|
|
|
+ /* must delete to avoid corrupting pcp list */
|
|
list_del(&page->lru);
|
|
list_del(&page->lru);
|
|
pcp->count--;
|
|
pcp->count--;
|
|
|
|
|
|
- mt = get_pcppage_migratetype(page);
|
|
|
|
- /* MIGRATE_ISOLATE page should not go to pcplists */
|
|
|
|
- VM_BUG_ON_PAGE(is_migrate_isolate(mt), page);
|
|
|
|
- /* Pageblock could have been isolated meanwhile */
|
|
|
|
- if (unlikely(isolated_pageblocks))
|
|
|
|
- mt = get_pageblock_migratetype(page);
|
|
|
|
-
|
|
|
|
if (bulkfree_pcp_prepare(page))
|
|
if (bulkfree_pcp_prepare(page))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- __free_one_page(page, page_to_pfn(page), zone, 0, mt);
|
|
|
|
- trace_mm_page_pcpu_drain(page, 0, mt);
|
|
|
|
|
|
+ list_add_tail(&page->lru, &head);
|
|
} while (--count && --batch_free && !list_empty(list));
|
|
} while (--count && --batch_free && !list_empty(list));
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ spin_lock(&zone->lock);
|
|
|
|
+ isolated_pageblocks = has_isolate_pageblock(zone);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Use safe version since after __free_one_page(),
|
|
|
|
+ * page->lru.next will not point to original list.
|
|
|
|
+ */
|
|
|
|
+ list_for_each_entry_safe(page, tmp, &head, lru) {
|
|
|
|
+ int mt = get_pcppage_migratetype(page);
|
|
|
|
+ /* MIGRATE_ISOLATE page should not go to pcplists */
|
|
|
|
+ VM_BUG_ON_PAGE(is_migrate_isolate(mt), page);
|
|
|
|
+ /* Pageblock could have been isolated meanwhile */
|
|
|
|
+ if (unlikely(isolated_pageblocks))
|
|
|
|
+ mt = get_pageblock_migratetype(page);
|
|
|
|
+
|
|
|
|
+ __free_one_page(page, page_to_pfn(page), zone, 0, mt);
|
|
|
|
+ trace_mm_page_pcpu_drain(page, 0, mt);
|
|
|
|
+ }
|
|
spin_unlock(&zone->lock);
|
|
spin_unlock(&zone->lock);
|
|
}
|
|
}
|
|
|
|
|