aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/compaction.h6
-rw-r--r--mm/compaction.c53
-rw-r--r--mm/vmscan.c10
3 files changed, 51 insertions, 18 deletions
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index bb2bbdbe5464..7a9323aef4a3 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -23,6 +23,7 @@ extern int fragmentation_index(struct zone *zone, unsigned int order);
23extern unsigned long try_to_compact_pages(struct zonelist *zonelist, 23extern unsigned long try_to_compact_pages(struct zonelist *zonelist,
24 int order, gfp_t gfp_mask, nodemask_t *mask, 24 int order, gfp_t gfp_mask, nodemask_t *mask,
25 bool sync); 25 bool sync);
26extern int compact_pgdat(pg_data_t *pgdat, int order);
26extern unsigned long compaction_suitable(struct zone *zone, int order); 27extern unsigned long compaction_suitable(struct zone *zone, int order);
27 28
28/* Do not skip compaction more than 64 times */ 29/* Do not skip compaction more than 64 times */
@@ -62,6 +63,11 @@ static inline unsigned long try_to_compact_pages(struct zonelist *zonelist,
62 return COMPACT_CONTINUE; 63 return COMPACT_CONTINUE;
63} 64}
64 65
66static inline int compact_pgdat(pg_data_t *pgdat, int order)
67{
68 return COMPACT_CONTINUE;
69}
70
65static inline unsigned long compaction_suitable(struct zone *zone, int order) 71static inline unsigned long compaction_suitable(struct zone *zone, int order)
66{ 72{
67 return COMPACT_SKIPPED; 73 return COMPACT_SKIPPED;
diff --git a/mm/compaction.c b/mm/compaction.c
index d9ebebe1a2aa..36f0f61f4a24 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -675,44 +675,61 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
675 675
676 676
677/* Compact all zones within a node */ 677/* Compact all zones within a node */
678static int compact_node(int nid) 678static int __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc)
679{ 679{
680 int zoneid; 680 int zoneid;
681 pg_data_t *pgdat;
682 struct zone *zone; 681 struct zone *zone;
683 682
684 if (nid < 0 || nid >= nr_node_ids || !node_online(nid))
685 return -EINVAL;
686 pgdat = NODE_DATA(nid);
687
688 /* Flush pending updates to the LRU lists */ 683 /* Flush pending updates to the LRU lists */
689 lru_add_drain_all(); 684 lru_add_drain_all();
690 685
691 for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) { 686 for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
692 struct compact_control cc = {
693 .nr_freepages = 0,
694 .nr_migratepages = 0,
695 .order = -1,
696 .sync = true,
697 };
698 687
699 zone = &pgdat->node_zones[zoneid]; 688 zone = &pgdat->node_zones[zoneid];
700 if (!populated_zone(zone)) 689 if (!populated_zone(zone))
701 continue; 690 continue;
702 691
703 cc.zone = zone; 692 cc->nr_freepages = 0;
704 INIT_LIST_HEAD(&cc.freepages); 693 cc->nr_migratepages = 0;
705 INIT_LIST_HEAD(&cc.migratepages); 694 cc->zone = zone;
695 INIT_LIST_HEAD(&cc->freepages);
696 INIT_LIST_HEAD(&cc->migratepages);
706 697
707 compact_zone(zone, &cc); 698 if (cc->order < 0 || !compaction_deferred(zone))
699 compact_zone(zone, cc);
708 700
709 VM_BUG_ON(!list_empty(&cc.freepages)); 701 VM_BUG_ON(!list_empty(&cc->freepages));
710 VM_BUG_ON(!list_empty(&cc.migratepages)); 702 VM_BUG_ON(!list_empty(&cc->migratepages));
711 } 703 }
712 704
713 return 0; 705 return 0;
714} 706}
715 707
708int compact_pgdat(pg_data_t *pgdat, int order)
709{
710 struct compact_control cc = {
711 .order = order,
712 .sync = false,
713 };
714
715 return __compact_pgdat(pgdat, &cc);
716}
717
718static int compact_node(int nid)
719{
720 pg_data_t *pgdat;
721 struct compact_control cc = {
722 .order = -1,
723 .sync = true,
724 };
725
726 if (nid < 0 || nid >= nr_node_ids || !node_online(nid))
727 return -EINVAL;
728 pgdat = NODE_DATA(nid);
729
730 return __compact_pgdat(pgdat, &cc);
731}
732
716/* Compact all nodes in the system */ 733/* Compact all nodes in the system */
717static int compact_nodes(void) 734static int compact_nodes(void)
718{ 735{
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d7dad2a4e69c..b2b4c4a0ada2 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2919,6 +2919,8 @@ out:
2919 * and it is potentially going to sleep here. 2919 * and it is potentially going to sleep here.
2920 */ 2920 */
2921 if (order) { 2921 if (order) {
2922 int zones_need_compaction = 1;
2923
2922 for (i = 0; i <= end_zone; i++) { 2924 for (i = 0; i <= end_zone; i++) {
2923 struct zone *zone = pgdat->node_zones + i; 2925 struct zone *zone = pgdat->node_zones + i;
2924 2926
@@ -2939,9 +2941,17 @@ out:
2939 goto loop_again; 2941 goto loop_again;
2940 } 2942 }
2941 2943
2944 /* Check if the memory needs to be defragmented. */
2945 if (zone_watermark_ok(zone, order,
2946 low_wmark_pages(zone), *classzone_idx, 0))
2947 zones_need_compaction = 0;
2948
2942 /* If balanced, clear the congested flag */ 2949 /* If balanced, clear the congested flag */
2943 zone_clear_flag(zone, ZONE_CONGESTED); 2950 zone_clear_flag(zone, ZONE_CONGESTED);
2944 } 2951 }
2952
2953 if (zones_need_compaction)
2954 compact_pgdat(pgdat, order);
2945 } 2955 }
2946 2956
2947 /* 2957 /*