|
@@ -790,23 +790,32 @@ static struct page *compaction_alloc(struct page *migratepage,
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * We cannot control nr_migratepages and nr_freepages fully when migration is
|
|
|
- * running as migrate_pages() has no knowledge of compact_control. When
|
|
|
- * migration is complete, we count the number of pages on the lists by hand.
|
|
|
+ * This is a migrate-callback that "frees" freepages back to the isolated
|
|
|
+ * freelist. All pages on the freelist are from the same zone, so there is no
|
|
|
+ * special handling needed for NUMA.
|
|
|
+ */
|
|
|
+static void compaction_free(struct page *page, unsigned long data)
|
|
|
+{
|
|
|
+ struct compact_control *cc = (struct compact_control *)data;
|
|
|
+
|
|
|
+ list_add(&page->lru, &cc->freepages);
|
|
|
+ cc->nr_freepages++;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * We cannot control nr_migratepages fully when migration is running as
|
|
|
+ * migrate_pages() has no knowledge of of compact_control. When migration is
|
|
|
+ * complete, we count the number of pages on the list by hand.
|
|
|
*/
|
|
|
static void update_nr_listpages(struct compact_control *cc)
|
|
|
{
|
|
|
int nr_migratepages = 0;
|
|
|
- int nr_freepages = 0;
|
|
|
struct page *page;
|
|
|
|
|
|
list_for_each_entry(page, &cc->migratepages, lru)
|
|
|
nr_migratepages++;
|
|
|
- list_for_each_entry(page, &cc->freepages, lru)
|
|
|
- nr_freepages++;
|
|
|
|
|
|
cc->nr_migratepages = nr_migratepages;
|
|
|
- cc->nr_freepages = nr_freepages;
|
|
|
}
|
|
|
|
|
|
/* possible outcome of isolate_migratepages */
|
|
@@ -1016,8 +1025,8 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
|
|
|
}
|
|
|
|
|
|
nr_migrate = cc->nr_migratepages;
|
|
|
- err = migrate_pages(&cc->migratepages, compaction_alloc, NULL,
|
|
|
- (unsigned long)cc,
|
|
|
+ err = migrate_pages(&cc->migratepages, compaction_alloc,
|
|
|
+ compaction_free, (unsigned long)cc,
|
|
|
cc->sync ? MIGRATE_SYNC_LIGHT : MIGRATE_ASYNC,
|
|
|
MR_COMPACTION);
|
|
|
update_nr_listpages(cc);
|