diff options
Diffstat (limited to 'mm/compaction.c')
-rw-r--r-- | mm/compaction.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index 206847d35978..613c59e928cb 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -1318,6 +1318,17 @@ static enum compact_result __compact_finished(struct zone *zone, | |||
1318 | if (is_via_compact_memory(cc->order)) | 1318 | if (is_via_compact_memory(cc->order)) |
1319 | return COMPACT_CONTINUE; | 1319 | return COMPACT_CONTINUE; |
1320 | 1320 | ||
1321 | if (cc->finishing_block) { | ||
1322 | /* | ||
1323 | * We have finished the pageblock, but better check again that | ||
1324 | * we really succeeded. | ||
1325 | */ | ||
1326 | if (IS_ALIGNED(cc->migrate_pfn, pageblock_nr_pages)) | ||
1327 | cc->finishing_block = false; | ||
1328 | else | ||
1329 | return COMPACT_CONTINUE; | ||
1330 | } | ||
1331 | |||
1321 | /* Direct compactor: Is a suitable page free? */ | 1332 | /* Direct compactor: Is a suitable page free? */ |
1322 | for (order = cc->order; order < MAX_ORDER; order++) { | 1333 | for (order = cc->order; order < MAX_ORDER; order++) { |
1323 | struct free_area *area = &zone->free_area[order]; | 1334 | struct free_area *area = &zone->free_area[order]; |
@@ -1338,8 +1349,29 @@ static enum compact_result __compact_finished(struct zone *zone, | |||
1338 | * other migratetype buddy lists. | 1349 | * other migratetype buddy lists. |
1339 | */ | 1350 | */ |
1340 | if (find_suitable_fallback(area, order, migratetype, | 1351 | if (find_suitable_fallback(area, order, migratetype, |
1341 | true, &can_steal) != -1) | 1352 | true, &can_steal) != -1) { |
1342 | return COMPACT_SUCCESS; | 1353 | |
1354 | /* movable pages are OK in any pageblock */ | ||
1355 | if (migratetype == MIGRATE_MOVABLE) | ||
1356 | return COMPACT_SUCCESS; | ||
1357 | |||
1358 | /* | ||
1359 | * We are stealing for a non-movable allocation. Make | ||
1360 | * sure we finish compacting the current pageblock | ||
1361 | * first so it is as free as possible and we won't | ||
1362 | * have to steal another one soon. This only applies | ||
1363 | * to sync compaction, as async compaction operates | ||
1364 | * on pageblocks of the same migratetype. | ||
1365 | */ | ||
1366 | if (cc->mode == MIGRATE_ASYNC || | ||
1367 | IS_ALIGNED(cc->migrate_pfn, | ||
1368 | pageblock_nr_pages)) { | ||
1369 | return COMPACT_SUCCESS; | ||
1370 | } | ||
1371 | |||
1372 | cc->finishing_block = true; | ||
1373 | return COMPACT_CONTINUE; | ||
1374 | } | ||
1343 | } | 1375 | } |
1344 | 1376 | ||
1345 | return COMPACT_NO_SUITABLE_PAGE; | 1377 | return COMPACT_NO_SUITABLE_PAGE; |