diff options
Diffstat (limited to 'mm/compaction.c')
-rw-r--r-- | mm/compaction.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index 4af1577adb5c..d8a20fcf8678 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -1318,7 +1318,8 @@ static enum compact_result compact_finished(struct zone *zone, | |||
1318 | */ | 1318 | */ |
1319 | static enum compact_result __compaction_suitable(struct zone *zone, int order, | 1319 | static enum compact_result __compaction_suitable(struct zone *zone, int order, |
1320 | unsigned int alloc_flags, | 1320 | unsigned int alloc_flags, |
1321 | int classzone_idx) | 1321 | int classzone_idx, |
1322 | unsigned long wmark_target) | ||
1322 | { | 1323 | { |
1323 | int fragindex; | 1324 | int fragindex; |
1324 | unsigned long watermark; | 1325 | unsigned long watermark; |
@@ -1341,7 +1342,8 @@ static enum compact_result __compaction_suitable(struct zone *zone, int order, | |||
1341 | * allocated and for a short time, the footprint is higher | 1342 | * allocated and for a short time, the footprint is higher |
1342 | */ | 1343 | */ |
1343 | watermark += (2UL << order); | 1344 | watermark += (2UL << order); |
1344 | if (!zone_watermark_ok(zone, 0, watermark, classzone_idx, alloc_flags)) | 1345 | if (!__zone_watermark_ok(zone, 0, watermark, classzone_idx, |
1346 | alloc_flags, wmark_target)) | ||
1345 | return COMPACT_SKIPPED; | 1347 | return COMPACT_SKIPPED; |
1346 | 1348 | ||
1347 | /* | 1349 | /* |
@@ -1368,7 +1370,8 @@ enum compact_result compaction_suitable(struct zone *zone, int order, | |||
1368 | { | 1370 | { |
1369 | enum compact_result ret; | 1371 | enum compact_result ret; |
1370 | 1372 | ||
1371 | ret = __compaction_suitable(zone, order, alloc_flags, classzone_idx); | 1373 | ret = __compaction_suitable(zone, order, alloc_flags, classzone_idx, |
1374 | zone_page_state(zone, NR_FREE_PAGES)); | ||
1372 | trace_mm_compaction_suitable(zone, order, ret); | 1375 | trace_mm_compaction_suitable(zone, order, ret); |
1373 | if (ret == COMPACT_NOT_SUITABLE_ZONE) | 1376 | if (ret == COMPACT_NOT_SUITABLE_ZONE) |
1374 | ret = COMPACT_SKIPPED; | 1377 | ret = COMPACT_SKIPPED; |
@@ -1376,6 +1379,39 @@ enum compact_result compaction_suitable(struct zone *zone, int order, | |||
1376 | return ret; | 1379 | return ret; |
1377 | } | 1380 | } |
1378 | 1381 | ||
1382 | bool compaction_zonelist_suitable(struct alloc_context *ac, int order, | ||
1383 | int alloc_flags) | ||
1384 | { | ||
1385 | struct zone *zone; | ||
1386 | struct zoneref *z; | ||
1387 | |||
1388 | /* | ||
1389 | * Make sure at least one zone would pass __compaction_suitable if we continue | ||
1390 | * retrying the reclaim. | ||
1391 | */ | ||
1392 | for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx, | ||
1393 | ac->nodemask) { | ||
1394 | unsigned long available; | ||
1395 | enum compact_result compact_result; | ||
1396 | |||
1397 | /* | ||
1398 | * Do not consider all the reclaimable memory because we do not | ||
1399 | * want to trash just for a single high order allocation which | ||
1400 | * is even not guaranteed to appear even if __compaction_suitable | ||
1401 | * is happy about the watermark check. | ||
1402 | */ | ||
1403 | available = zone_reclaimable_pages(zone) / order; | ||
1404 | available += zone_page_state_snapshot(zone, NR_FREE_PAGES); | ||
1405 | compact_result = __compaction_suitable(zone, order, alloc_flags, | ||
1406 | ac_classzone_idx(ac), available); | ||
1407 | if (compact_result != COMPACT_SKIPPED && | ||
1408 | compact_result != COMPACT_NOT_SUITABLE_ZONE) | ||
1409 | return true; | ||
1410 | } | ||
1411 | |||
1412 | return false; | ||
1413 | } | ||
1414 | |||
1379 | static enum compact_result compact_zone(struct zone *zone, struct compact_control *cc) | 1415 | static enum compact_result compact_zone(struct zone *zone, struct compact_control *cc) |
1380 | { | 1416 | { |
1381 | enum compact_result ret; | 1417 | enum compact_result ret; |