diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/internal.h | 4 | ||||
-rw-r--r-- | mm/page_alloc.c | 26 | ||||
-rw-r--r-- | mm/vmscan.c | 11 |
3 files changed, 32 insertions, 9 deletions
diff --git a/mm/internal.h b/mm/internal.h index f02c7508068d..f290c4db528b 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
@@ -259,4 +259,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
259 | unsigned long start, int len, int flags, | 259 | unsigned long start, int len, int flags, |
260 | struct page **pages, struct vm_area_struct **vmas); | 260 | struct page **pages, struct vm_area_struct **vmas); |
261 | 261 | ||
262 | #define ZONE_RECLAIM_NOSCAN -2 | ||
263 | #define ZONE_RECLAIM_FULL -1 | ||
264 | #define ZONE_RECLAIM_SOME 0 | ||
265 | #define ZONE_RECLAIM_SUCCESS 1 | ||
262 | #endif | 266 | #endif |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6407cbfccd77..2f457a756d46 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1462,15 +1462,33 @@ zonelist_scan: | |||
1462 | BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); | 1462 | BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); |
1463 | if (!(alloc_flags & ALLOC_NO_WATERMARKS)) { | 1463 | if (!(alloc_flags & ALLOC_NO_WATERMARKS)) { |
1464 | unsigned long mark; | 1464 | unsigned long mark; |
1465 | int ret; | ||
1466 | |||
1465 | mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK]; | 1467 | mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK]; |
1466 | if (!zone_watermark_ok(zone, order, mark, | 1468 | if (zone_watermark_ok(zone, order, mark, |
1467 | classzone_idx, alloc_flags)) { | 1469 | classzone_idx, alloc_flags)) |
1468 | if (!zone_reclaim_mode || | 1470 | goto try_this_zone; |
1469 | !zone_reclaim(zone, gfp_mask, order)) | 1471 | |
1472 | if (zone_reclaim_mode == 0) | ||
1473 | goto this_zone_full; | ||
1474 | |||
1475 | ret = zone_reclaim(zone, gfp_mask, order); | ||
1476 | switch (ret) { | ||
1477 | case ZONE_RECLAIM_NOSCAN: | ||
1478 | /* did not scan */ | ||
1479 | goto try_next_zone; | ||
1480 | case ZONE_RECLAIM_FULL: | ||
1481 | /* scanned but unreclaimable */ | ||
1482 | goto this_zone_full; | ||
1483 | default: | ||
1484 | /* did we reclaim enough */ | ||
1485 | if (!zone_watermark_ok(zone, order, mark, | ||
1486 | classzone_idx, alloc_flags)) | ||
1470 | goto this_zone_full; | 1487 | goto this_zone_full; |
1471 | } | 1488 | } |
1472 | } | 1489 | } |
1473 | 1490 | ||
1491 | try_this_zone: | ||
1474 | page = buffered_rmqueue(preferred_zone, zone, order, | 1492 | page = buffered_rmqueue(preferred_zone, zone, order, |
1475 | gfp_mask, migratetype); | 1493 | gfp_mask, migratetype); |
1476 | if (page) | 1494 | if (page) |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 79a98d98ed33..16c82a868e2b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -2492,16 +2492,16 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) | |||
2492 | */ | 2492 | */ |
2493 | if (zone_pagecache_reclaimable(zone) <= zone->min_unmapped_pages && | 2493 | if (zone_pagecache_reclaimable(zone) <= zone->min_unmapped_pages && |
2494 | zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages) | 2494 | zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages) |
2495 | return 0; | 2495 | return ZONE_RECLAIM_FULL; |
2496 | 2496 | ||
2497 | if (zone_is_all_unreclaimable(zone)) | 2497 | if (zone_is_all_unreclaimable(zone)) |
2498 | return 0; | 2498 | return ZONE_RECLAIM_FULL; |
2499 | 2499 | ||
2500 | /* | 2500 | /* |
2501 | * Do not scan if the allocation should not be delayed. | 2501 | * Do not scan if the allocation should not be delayed. |
2502 | */ | 2502 | */ |
2503 | if (!(gfp_mask & __GFP_WAIT) || (current->flags & PF_MEMALLOC)) | 2503 | if (!(gfp_mask & __GFP_WAIT) || (current->flags & PF_MEMALLOC)) |
2504 | return 0; | 2504 | return ZONE_RECLAIM_NOSCAN; |
2505 | 2505 | ||
2506 | /* | 2506 | /* |
2507 | * Only run zone reclaim on the local zone or on zones that do not | 2507 | * Only run zone reclaim on the local zone or on zones that do not |
@@ -2511,10 +2511,11 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) | |||
2511 | */ | 2511 | */ |
2512 | node_id = zone_to_nid(zone); | 2512 | node_id = zone_to_nid(zone); |
2513 | if (node_state(node_id, N_CPU) && node_id != numa_node_id()) | 2513 | if (node_state(node_id, N_CPU) && node_id != numa_node_id()) |
2514 | return 0; | 2514 | return ZONE_RECLAIM_NOSCAN; |
2515 | 2515 | ||
2516 | if (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED)) | 2516 | if (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED)) |
2517 | return 0; | 2517 | return ZONE_RECLAIM_NOSCAN; |
2518 | |||
2518 | ret = __zone_reclaim(zone, gfp_mask, order); | 2519 | ret = __zone_reclaim(zone, gfp_mask, order); |
2519 | zone_clear_flag(zone, ZONE_RECLAIM_LOCKED); | 2520 | zone_clear_flag(zone, ZONE_RECLAIM_LOCKED); |
2520 | 2521 | ||