diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2e6635993558..6a29ed8e6e60 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -218,6 +218,11 @@ EXPORT_SYMBOL(nr_online_nodes); | |||
218 | 218 | ||
219 | int page_group_by_mobility_disabled __read_mostly; | 219 | int page_group_by_mobility_disabled __read_mostly; |
220 | 220 | ||
221 | /* | ||
222 | * NOTE: | ||
223 | * Don't use set_pageblock_migratetype(page, MIGRATE_ISOLATE) directly. | ||
224 | * Instead, use {un}set_pageblock_isolate. | ||
225 | */ | ||
221 | void set_pageblock_migratetype(struct page *page, int migratetype) | 226 | void set_pageblock_migratetype(struct page *page, int migratetype) |
222 | { | 227 | { |
223 | 228 | ||
@@ -1619,6 +1624,20 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, | |||
1619 | return true; | 1624 | return true; |
1620 | } | 1625 | } |
1621 | 1626 | ||
1627 | #ifdef CONFIG_MEMORY_ISOLATION | ||
1628 | static inline unsigned long nr_zone_isolate_freepages(struct zone *zone) | ||
1629 | { | ||
1630 | if (unlikely(zone->nr_pageblock_isolate)) | ||
1631 | return zone->nr_pageblock_isolate * pageblock_nr_pages; | ||
1632 | return 0; | ||
1633 | } | ||
1634 | #else | ||
1635 | static inline unsigned long nr_zone_isolate_freepages(struct zone *zone) | ||
1636 | { | ||
1637 | return 0; | ||
1638 | } | ||
1639 | #endif | ||
1640 | |||
1622 | bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, | 1641 | bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, |
1623 | int classzone_idx, int alloc_flags) | 1642 | int classzone_idx, int alloc_flags) |
1624 | { | 1643 | { |
@@ -1634,6 +1653,14 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, | |||
1634 | if (z->percpu_drift_mark && free_pages < z->percpu_drift_mark) | 1653 | if (z->percpu_drift_mark && free_pages < z->percpu_drift_mark) |
1635 | free_pages = zone_page_state_snapshot(z, NR_FREE_PAGES); | 1654 | free_pages = zone_page_state_snapshot(z, NR_FREE_PAGES); |
1636 | 1655 | ||
1656 | /* | ||
1657 | * If the zone has MIGRATE_ISOLATE type free pages, we should consider | ||
1658 | * it. nr_zone_isolate_freepages is never accurate so kswapd might not | ||
1659 | * sleep although it could do so. But this is more desirable for memory | ||
1660 | * hotplug than sleeping which can cause a livelock in the direct | ||
1661 | * reclaim path. | ||
1662 | */ | ||
1663 | free_pages -= nr_zone_isolate_freepages(z); | ||
1637 | return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, | 1664 | return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, |
1638 | free_pages); | 1665 | free_pages); |
1639 | } | 1666 | } |
@@ -4398,6 +4425,9 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, | |||
4398 | lruvec_init(&zone->lruvec, zone); | 4425 | lruvec_init(&zone->lruvec, zone); |
4399 | zap_zone_vm_stats(zone); | 4426 | zap_zone_vm_stats(zone); |
4400 | zone->flags = 0; | 4427 | zone->flags = 0; |
4428 | #ifdef CONFIG_MEMORY_ISOLATION | ||
4429 | zone->nr_pageblock_isolate = 0; | ||
4430 | #endif | ||
4401 | if (!size) | 4431 | if (!size) |
4402 | continue; | 4432 | continue; |
4403 | 4433 | ||