aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace/postprocess/trace-vmscan-postprocess.pl4
-rw-r--r--include/linux/mmzone.h3
-rw-r--r--include/trace/events/vmscan.h17
-rw-r--r--mm/page_alloc.c14
-rw-r--r--mm/vmscan.c32
5 files changed, 45 insertions, 25 deletions
diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
index ba976805853a..66bfd8396877 100644
--- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
+++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
@@ -111,7 +111,7 @@ my $regex_direct_begin_default = 'order=([0-9]*) may_writepage=([0-9]*) gfp_flag
111my $regex_direct_end_default = 'nr_reclaimed=([0-9]*)'; 111my $regex_direct_end_default = 'nr_reclaimed=([0-9]*)';
112my $regex_kswapd_wake_default = 'nid=([0-9]*) order=([0-9]*)'; 112my $regex_kswapd_wake_default = 'nid=([0-9]*) order=([0-9]*)';
113my $regex_kswapd_sleep_default = 'nid=([0-9]*)'; 113my $regex_kswapd_sleep_default = 'nid=([0-9]*)';
114my $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*)'; 114my $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*) gfp_flags=([A-Z_|]*)';
115my $regex_lru_isolate_default = 'isolate_mode=([0-9]*) classzone_idx=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_skipped=([0-9]*) nr_taken=([0-9]*) lru=([a-z_]*)'; 115my $regex_lru_isolate_default = 'isolate_mode=([0-9]*) classzone_idx=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_skipped=([0-9]*) nr_taken=([0-9]*) lru=([a-z_]*)';
116my $regex_lru_shrink_inactive_default = 'nid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) nr_dirty=([0-9]*) nr_writeback=([0-9]*) nr_congested=([0-9]*) nr_immediate=([0-9]*) nr_activate=([0-9]*) nr_ref_keep=([0-9]*) nr_unmap_fail=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)'; 116my $regex_lru_shrink_inactive_default = 'nid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) nr_dirty=([0-9]*) nr_writeback=([0-9]*) nr_congested=([0-9]*) nr_immediate=([0-9]*) nr_activate=([0-9]*) nr_ref_keep=([0-9]*) nr_unmap_fail=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)';
117my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)'; 117my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)';
@@ -201,7 +201,7 @@ $regex_kswapd_sleep = generate_traceevent_regex(
201$regex_wakeup_kswapd = generate_traceevent_regex( 201$regex_wakeup_kswapd = generate_traceevent_regex(
202 "vmscan/mm_vmscan_wakeup_kswapd", 202 "vmscan/mm_vmscan_wakeup_kswapd",
203 $regex_wakeup_kswapd_default, 203 $regex_wakeup_kswapd_default,
204 "nid", "zid", "order"); 204 "nid", "zid", "order", "gfp_flags");
205$regex_lru_isolate = generate_traceevent_regex( 205$regex_lru_isolate = generate_traceevent_regex(
206 "vmscan/mm_vmscan_lru_isolate", 206 "vmscan/mm_vmscan_lru_isolate",
207 $regex_lru_isolate_default, 207 $regex_lru_isolate_default,
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 5d935411d3c4..f11ae29005f1 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -776,7 +776,8 @@ static inline bool is_dev_zone(const struct zone *zone)
776#include <linux/memory_hotplug.h> 776#include <linux/memory_hotplug.h>
777 777
778void build_all_zonelists(pg_data_t *pgdat); 778void build_all_zonelists(pg_data_t *pgdat);
779void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx); 779void wakeup_kswapd(struct zone *zone, gfp_t gfp_mask, int order,
780 enum zone_type classzone_idx);
780bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, 781bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
781 int classzone_idx, unsigned int alloc_flags, 782 int classzone_idx, unsigned int alloc_flags,
782 long free_pages); 783 long free_pages);
diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h
index e0b8b9173e1c..6570c5b45ba1 100644
--- a/include/trace/events/vmscan.h
+++ b/include/trace/events/vmscan.h
@@ -78,26 +78,29 @@ TRACE_EVENT(mm_vmscan_kswapd_wake,
78 78
79TRACE_EVENT(mm_vmscan_wakeup_kswapd, 79TRACE_EVENT(mm_vmscan_wakeup_kswapd,
80 80
81 TP_PROTO(int nid, int zid, int order), 81 TP_PROTO(int nid, int zid, int order, gfp_t gfp_flags),
82 82
83 TP_ARGS(nid, zid, order), 83 TP_ARGS(nid, zid, order, gfp_flags),
84 84
85 TP_STRUCT__entry( 85 TP_STRUCT__entry(
86 __field( int, nid ) 86 __field( int, nid )
87 __field( int, zid ) 87 __field( int, zid )
88 __field( int, order ) 88 __field( int, order )
89 __field( gfp_t, gfp_flags )
89 ), 90 ),
90 91
91 TP_fast_assign( 92 TP_fast_assign(
92 __entry->nid = nid; 93 __entry->nid = nid;
93 __entry->zid = zid; 94 __entry->zid = zid;
94 __entry->order = order; 95 __entry->order = order;
96 __entry->gfp_flags = gfp_flags;
95 ), 97 ),
96 98
97 TP_printk("nid=%d zid=%d order=%d", 99 TP_printk("nid=%d zid=%d order=%d gfp_flags=%s",
98 __entry->nid, 100 __entry->nid,
99 __entry->zid, 101 __entry->zid,
100 __entry->order) 102 __entry->order,
103 show_gfp_flags(__entry->gfp_flags))
101); 104);
102 105
103DECLARE_EVENT_CLASS(mm_vmscan_direct_reclaim_begin_template, 106DECLARE_EVENT_CLASS(mm_vmscan_direct_reclaim_begin_template,
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index f6005b7c3446..02c1a60d7937 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3805,16 +3805,18 @@ retry:
3805 return page; 3805 return page;
3806} 3806}
3807 3807
3808static void wake_all_kswapds(unsigned int order, const struct alloc_context *ac) 3808static void wake_all_kswapds(unsigned int order, gfp_t gfp_mask,
3809 const struct alloc_context *ac)
3809{ 3810{
3810 struct zoneref *z; 3811 struct zoneref *z;
3811 struct zone *zone; 3812 struct zone *zone;
3812 pg_data_t *last_pgdat = NULL; 3813 pg_data_t *last_pgdat = NULL;
3814 enum zone_type high_zoneidx = ac->high_zoneidx;
3813 3815
3814 for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, 3816 for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, high_zoneidx,
3815 ac->high_zoneidx, ac->nodemask) { 3817 ac->nodemask) {
3816 if (last_pgdat != zone->zone_pgdat) 3818 if (last_pgdat != zone->zone_pgdat)
3817 wakeup_kswapd(zone, order, ac->high_zoneidx); 3819 wakeup_kswapd(zone, gfp_mask, order, high_zoneidx);
3818 last_pgdat = zone->zone_pgdat; 3820 last_pgdat = zone->zone_pgdat;
3819 } 3821 }
3820} 3822}
@@ -4093,7 +4095,7 @@ retry_cpuset:
4093 goto nopage; 4095 goto nopage;
4094 4096
4095 if (gfp_mask & __GFP_KSWAPD_RECLAIM) 4097 if (gfp_mask & __GFP_KSWAPD_RECLAIM)
4096 wake_all_kswapds(order, ac); 4098 wake_all_kswapds(order, gfp_mask, ac);
4097 4099
4098 /* 4100 /*
4099 * The adjusted alloc_flags might result in immediate success, so try 4101 * The adjusted alloc_flags might result in immediate success, so try
@@ -4151,7 +4153,7 @@ retry_cpuset:
4151retry: 4153retry:
4152 /* Ensure kswapd doesn't accidentally go to sleep as long as we loop */ 4154 /* Ensure kswapd doesn't accidentally go to sleep as long as we loop */
4153 if (gfp_mask & __GFP_KSWAPD_RECLAIM) 4155 if (gfp_mask & __GFP_KSWAPD_RECLAIM)
4154 wake_all_kswapds(order, ac); 4156 wake_all_kswapds(order, gfp_mask, ac);
4155 4157
4156 reserve_flags = __gfp_pfmemalloc_flags(gfp_mask); 4158 reserve_flags = __gfp_pfmemalloc_flags(gfp_mask);
4157 if (reserve_flags) 4159 if (reserve_flags)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 976be140a8ce..4390a8d5be41 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3539,16 +3539,21 @@ kswapd_try_sleep:
3539} 3539}
3540 3540
3541/* 3541/*
3542 * A zone is low on free memory, so wake its kswapd task to service it. 3542 * A zone is low on free memory or too fragmented for high-order memory. If
3543 * kswapd should reclaim (direct reclaim is deferred), wake it up for the zone's
3544 * pgdat. It will wake up kcompactd after reclaiming memory. If kswapd reclaim
3545 * has failed or is not needed, still wake up kcompactd if only compaction is
3546 * needed.
3543 */ 3547 */
3544void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx) 3548void wakeup_kswapd(struct zone *zone, gfp_t gfp_flags, int order,
3549 enum zone_type classzone_idx)
3545{ 3550{
3546 pg_data_t *pgdat; 3551 pg_data_t *pgdat;
3547 3552
3548 if (!managed_zone(zone)) 3553 if (!managed_zone(zone))
3549 return; 3554 return;
3550 3555
3551 if (!cpuset_zone_allowed(zone, GFP_KERNEL | __GFP_HARDWALL)) 3556 if (!cpuset_zone_allowed(zone, gfp_flags))
3552 return; 3557 return;
3553 pgdat = zone->zone_pgdat; 3558 pgdat = zone->zone_pgdat;
3554 pgdat->kswapd_classzone_idx = kswapd_classzone_idx(pgdat, 3559 pgdat->kswapd_classzone_idx = kswapd_classzone_idx(pgdat,
@@ -3557,14 +3562,23 @@ void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx)
3557 if (!waitqueue_active(&pgdat->kswapd_wait)) 3562 if (!waitqueue_active(&pgdat->kswapd_wait))
3558 return; 3563 return;
3559 3564
3560 /* Hopeless node, leave it to direct reclaim */ 3565 /* Hopeless node, leave it to direct reclaim if possible */
3561 if (pgdat->kswapd_failures >= MAX_RECLAIM_RETRIES) 3566 if (pgdat->kswapd_failures >= MAX_RECLAIM_RETRIES ||
3562 return; 3567 pgdat_balanced(pgdat, order, classzone_idx)) {
3563 3568 /*
3564 if (pgdat_balanced(pgdat, order, classzone_idx)) 3569 * There may be plenty of free memory available, but it's too
3570 * fragmented for high-order allocations. Wake up kcompactd
3571 * and rely on compaction_suitable() to determine if it's
3572 * needed. If it fails, it will defer subsequent attempts to
3573 * ratelimit its work.
3574 */
3575 if (!(gfp_flags & __GFP_DIRECT_RECLAIM))
3576 wakeup_kcompactd(pgdat, order, classzone_idx);
3565 return; 3577 return;
3578 }
3566 3579
3567 trace_mm_vmscan_wakeup_kswapd(pgdat->node_id, classzone_idx, order); 3580 trace_mm_vmscan_wakeup_kswapd(pgdat->node_id, classzone_idx, order,
3581 gfp_flags);
3568 wake_up_interruptible(&pgdat->kswapd_wait); 3582 wake_up_interruptible(&pgdat->kswapd_wait);
3569} 3583}
3570 3584