diff options
Diffstat (limited to 'mm/compaction.c')
-rw-r--r-- | mm/compaction.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index 223464227299..949198d01260 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -818,6 +818,13 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, | |||
818 | page_count(page) > page_mapcount(page)) | 818 | page_count(page) > page_mapcount(page)) |
819 | goto isolate_fail; | 819 | goto isolate_fail; |
820 | 820 | ||
821 | /* | ||
822 | * Only allow to migrate anonymous pages in GFP_NOFS context | ||
823 | * because those do not depend on fs locks. | ||
824 | */ | ||
825 | if (!(cc->gfp_mask & __GFP_FS) && page_mapping(page)) | ||
826 | goto isolate_fail; | ||
827 | |||
821 | /* If we already hold the lock, we can skip some rechecking */ | 828 | /* If we already hold the lock, we can skip some rechecking */ |
822 | if (!locked) { | 829 | if (!locked) { |
823 | locked = compact_trylock_irqsave(zone_lru_lock(zone), | 830 | locked = compact_trylock_irqsave(zone_lru_lock(zone), |
@@ -1677,14 +1684,16 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order, | |||
1677 | unsigned int alloc_flags, const struct alloc_context *ac, | 1684 | unsigned int alloc_flags, const struct alloc_context *ac, |
1678 | enum compact_priority prio) | 1685 | enum compact_priority prio) |
1679 | { | 1686 | { |
1680 | int may_enter_fs = gfp_mask & __GFP_FS; | ||
1681 | int may_perform_io = gfp_mask & __GFP_IO; | 1687 | int may_perform_io = gfp_mask & __GFP_IO; |
1682 | struct zoneref *z; | 1688 | struct zoneref *z; |
1683 | struct zone *zone; | 1689 | struct zone *zone; |
1684 | enum compact_result rc = COMPACT_SKIPPED; | 1690 | enum compact_result rc = COMPACT_SKIPPED; |
1685 | 1691 | ||
1686 | /* Check if the GFP flags allow compaction */ | 1692 | /* |
1687 | if (!may_enter_fs || !may_perform_io) | 1693 | * Check if the GFP flags allow compaction - GFP_NOIO is really |
1694 | * tricky context because the migration might require IO | ||
1695 | */ | ||
1696 | if (!may_perform_io) | ||
1688 | return COMPACT_SKIPPED; | 1697 | return COMPACT_SKIPPED; |
1689 | 1698 | ||
1690 | trace_mm_compaction_try_to_compact_pages(order, gfp_mask, prio); | 1699 | trace_mm_compaction_try_to_compact_pages(order, gfp_mask, prio); |
@@ -1751,6 +1760,7 @@ static void compact_node(int nid) | |||
1751 | .mode = MIGRATE_SYNC, | 1760 | .mode = MIGRATE_SYNC, |
1752 | .ignore_skip_hint = true, | 1761 | .ignore_skip_hint = true, |
1753 | .whole_zone = true, | 1762 | .whole_zone = true, |
1763 | .gfp_mask = GFP_KERNEL, | ||
1754 | }; | 1764 | }; |
1755 | 1765 | ||
1756 | 1766 | ||
@@ -1876,6 +1886,7 @@ static void kcompactd_do_work(pg_data_t *pgdat) | |||
1876 | .classzone_idx = pgdat->kcompactd_classzone_idx, | 1886 | .classzone_idx = pgdat->kcompactd_classzone_idx, |
1877 | .mode = MIGRATE_SYNC_LIGHT, | 1887 | .mode = MIGRATE_SYNC_LIGHT, |
1878 | .ignore_skip_hint = true, | 1888 | .ignore_skip_hint = true, |
1889 | .gfp_mask = GFP_KERNEL, | ||
1879 | 1890 | ||
1880 | }; | 1891 | }; |
1881 | trace_mm_compaction_kcompactd_wake(pgdat->node_id, cc.order, | 1892 | trace_mm_compaction_kcompactd_wake(pgdat->node_id, cc.order, |