|
@@ -2611,24 +2611,26 @@ void mark_free_pages(struct zone *zone)
|
|
|
}
|
|
|
#endif /* CONFIG_PM */
|
|
|
|
|
|
-/*
|
|
|
- * Free a 0-order page
|
|
|
- * cold == true ? free a cold page : free a hot page
|
|
|
- */
|
|
|
-void free_hot_cold_page(struct page *page, bool cold)
|
|
|
+static bool free_hot_cold_page_prepare(struct page *page, unsigned long pfn)
|
|
|
{
|
|
|
- struct zone *zone = page_zone(page);
|
|
|
- struct per_cpu_pages *pcp;
|
|
|
- unsigned long flags;
|
|
|
- unsigned long pfn = page_to_pfn(page);
|
|
|
int migratetype;
|
|
|
|
|
|
if (!free_pcp_prepare(page))
|
|
|
- return;
|
|
|
+ return false;
|
|
|
|
|
|
migratetype = get_pfnblock_migratetype(page, pfn);
|
|
|
set_pcppage_migratetype(page, migratetype);
|
|
|
- local_irq_save(flags);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+static void free_hot_cold_page_commit(struct page *page, unsigned long pfn,
|
|
|
+ bool cold)
|
|
|
+{
|
|
|
+ struct zone *zone = page_zone(page);
|
|
|
+ struct per_cpu_pages *pcp;
|
|
|
+ int migratetype;
|
|
|
+
|
|
|
+ migratetype = get_pcppage_migratetype(page);
|
|
|
__count_vm_event(PGFREE);
|
|
|
|
|
|
/*
|
|
@@ -2641,7 +2643,7 @@ void free_hot_cold_page(struct page *page, bool cold)
|
|
|
if (migratetype >= MIGRATE_PCPTYPES) {
|
|
|
if (unlikely(is_migrate_isolate(migratetype))) {
|
|
|
free_one_page(zone, page, pfn, 0, migratetype);
|
|
|
- goto out;
|
|
|
+ return;
|
|
|
}
|
|
|
migratetype = MIGRATE_MOVABLE;
|
|
|
}
|
|
@@ -2657,8 +2659,22 @@ void free_hot_cold_page(struct page *page, bool cold)
|
|
|
free_pcppages_bulk(zone, batch, pcp);
|
|
|
pcp->count -= batch;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
-out:
|
|
|
+/*
|
|
|
+ * Free a 0-order page
|
|
|
+ * cold == true ? free a cold page : free a hot page
|
|
|
+ */
|
|
|
+void free_hot_cold_page(struct page *page, bool cold)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+ unsigned long pfn = page_to_pfn(page);
|
|
|
+
|
|
|
+ if (!free_hot_cold_page_prepare(page, pfn))
|
|
|
+ return;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+ free_hot_cold_page_commit(page, pfn, cold);
|
|
|
local_irq_restore(flags);
|
|
|
}
|
|
|
|
|
@@ -2668,11 +2684,25 @@ out:
|
|
|
void free_hot_cold_page_list(struct list_head *list, bool cold)
|
|
|
{
|
|
|
struct page *page, *next;
|
|
|
+ unsigned long flags, pfn;
|
|
|
+
|
|
|
+ /* Prepare pages for freeing */
|
|
|
+ list_for_each_entry_safe(page, next, list, lru) {
|
|
|
+ pfn = page_to_pfn(page);
|
|
|
+ if (!free_hot_cold_page_prepare(page, pfn))
|
|
|
+ list_del(&page->lru);
|
|
|
+ set_page_private(page, pfn);
|
|
|
+ }
|
|
|
|
|
|
+ local_irq_save(flags);
|
|
|
list_for_each_entry_safe(page, next, list, lru) {
|
|
|
+ unsigned long pfn = page_private(page);
|
|
|
+
|
|
|
+ set_page_private(page, 0);
|
|
|
trace_mm_page_free_batched(page, cold);
|
|
|
- free_hot_cold_page(page, cold);
|
|
|
+ free_hot_cold_page_commit(page, pfn, cold);
|
|
|
}
|
|
|
+ local_irq_restore(flags);
|
|
|
}
|
|
|
|
|
|
/*
|