diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/compaction.c | 42 | ||||
| -rw-r--r-- | mm/page_alloc.c | 23 |
2 files changed, 52 insertions, 13 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; |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index dea406a62e3d..089f760ce64a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -2750,10 +2750,9 @@ static inline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) | |||
| 2750 | * one free page of a suitable size. Checking now avoids taking the zone lock | 2750 | * one free page of a suitable size. Checking now avoids taking the zone lock |
| 2751 | * to check in the allocation paths if no pages are free. | 2751 | * to check in the allocation paths if no pages are free. |
| 2752 | */ | 2752 | */ |
| 2753 | static bool __zone_watermark_ok(struct zone *z, unsigned int order, | 2753 | bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, |
| 2754 | unsigned long mark, int classzone_idx, | 2754 | int classzone_idx, unsigned int alloc_flags, |
| 2755 | unsigned int alloc_flags, | 2755 | long free_pages) |
| 2756 | long free_pages) | ||
| 2757 | { | 2756 | { |
| 2758 | long min = mark; | 2757 | long min = mark; |
| 2759 | int o; | 2758 | int o; |
| @@ -3256,8 +3255,8 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, | |||
| 3256 | } | 3255 | } |
| 3257 | 3256 | ||
| 3258 | static inline bool | 3257 | static inline bool |
| 3259 | should_compact_retry(unsigned int order, enum compact_result compact_result, | 3258 | should_compact_retry(struct alloc_context *ac, int order, int alloc_flags, |
| 3260 | enum migrate_mode *migrate_mode, | 3259 | enum compact_result compact_result, enum migrate_mode *migrate_mode, |
| 3261 | int compaction_retries) | 3260 | int compaction_retries) |
| 3262 | { | 3261 | { |
| 3263 | int max_retries = MAX_COMPACT_RETRIES; | 3262 | int max_retries = MAX_COMPACT_RETRIES; |
| @@ -3281,9 +3280,11 @@ should_compact_retry(unsigned int order, enum compact_result compact_result, | |||
| 3281 | /* | 3280 | /* |
| 3282 | * make sure the compaction wasn't deferred or didn't bail out early | 3281 | * make sure the compaction wasn't deferred or didn't bail out early |
| 3283 | * due to locks contention before we declare that we should give up. | 3282 | * due to locks contention before we declare that we should give up. |
| 3283 | * But do not retry if the given zonelist is not suitable for | ||
| 3284 | * compaction. | ||
| 3284 | */ | 3285 | */ |
| 3285 | if (compaction_withdrawn(compact_result)) | 3286 | if (compaction_withdrawn(compact_result)) |
| 3286 | return true; | 3287 | return compaction_zonelist_suitable(ac, order, alloc_flags); |
| 3287 | 3288 | ||
| 3288 | /* | 3289 | /* |
| 3289 | * !costly requests are much more important than __GFP_REPEAT | 3290 | * !costly requests are much more important than __GFP_REPEAT |
| @@ -3311,7 +3312,8 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, | |||
| 3311 | } | 3312 | } |
| 3312 | 3313 | ||
| 3313 | static inline bool | 3314 | static inline bool |
| 3314 | should_compact_retry(unsigned int order, enum compact_result compact_result, | 3315 | should_compact_retry(struct alloc_context *ac, unsigned int order, int alloc_flags, |
| 3316 | enum compact_result compact_result, | ||
| 3315 | enum migrate_mode *migrate_mode, | 3317 | enum migrate_mode *migrate_mode, |
| 3316 | int compaction_retries) | 3318 | int compaction_retries) |
| 3317 | { | 3319 | { |
| @@ -3706,8 +3708,9 @@ retry: | |||
| 3706 | * of free memory (see __compaction_suitable) | 3708 | * of free memory (see __compaction_suitable) |
| 3707 | */ | 3709 | */ |
| 3708 | if (did_some_progress > 0 && | 3710 | if (did_some_progress > 0 && |
| 3709 | should_compact_retry(order, compact_result, | 3711 | should_compact_retry(ac, order, alloc_flags, |
| 3710 | &migration_mode, compaction_retries)) | 3712 | compact_result, &migration_mode, |
| 3713 | compaction_retries)) | ||
| 3711 | goto retry; | 3714 | goto retry; |
| 3712 | 3715 | ||
| 3713 | /* Reclaim has failed us, start killing things */ | 3716 | /* Reclaim has failed us, start killing things */ |
