diff options
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 61d3a9a0d96f..e176bd3936da 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -1904,6 +1904,24 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
1904 | } | 1904 | } |
1905 | #endif | 1905 | #endif |
1906 | 1906 | ||
1907 | /* is kswapd sleeping prematurely? */ | ||
1908 | static int sleeping_prematurely(int order, long remaining) | ||
1909 | { | ||
1910 | struct zone *zone; | ||
1911 | |||
1912 | /* If a direct reclaimer woke kswapd within HZ/10, it's premature */ | ||
1913 | if (remaining) | ||
1914 | return 1; | ||
1915 | |||
1916 | /* If after HZ/10, a zone is below the high mark, it's premature */ | ||
1917 | for_each_populated_zone(zone) | ||
1918 | if (!zone_watermark_ok(zone, order, high_wmark_pages(zone), | ||
1919 | 0, 0)) | ||
1920 | return 1; | ||
1921 | |||
1922 | return 0; | ||
1923 | } | ||
1924 | |||
1907 | /* | 1925 | /* |
1908 | * For kswapd, balance_pgdat() will work across all this node's zones until | 1926 | * For kswapd, balance_pgdat() will work across all this node's zones until |
1909 | * they are all at high_wmark_pages(zone). | 1927 | * they are all at high_wmark_pages(zone). |
@@ -2185,8 +2203,30 @@ static int kswapd(void *p) | |||
2185 | */ | 2203 | */ |
2186 | order = new_order; | 2204 | order = new_order; |
2187 | } else { | 2205 | } else { |
2188 | if (!freezing(current) && !kthread_should_stop()) | 2206 | if (!freezing(current) && !kthread_should_stop()) { |
2189 | schedule(); | 2207 | long remaining = 0; |
2208 | |||
2209 | /* Try to sleep for a short interval */ | ||
2210 | if (!sleeping_prematurely(order, remaining)) { | ||
2211 | remaining = schedule_timeout(HZ/10); | ||
2212 | finish_wait(&pgdat->kswapd_wait, &wait); | ||
2213 | prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); | ||
2214 | } | ||
2215 | |||
2216 | /* | ||
2217 | * After a short sleep, check if it was a | ||
2218 | * premature sleep. If not, then go fully | ||
2219 | * to sleep until explicitly woken up | ||
2220 | */ | ||
2221 | if (!sleeping_prematurely(order, remaining)) | ||
2222 | schedule(); | ||
2223 | else { | ||
2224 | if (remaining) | ||
2225 | count_vm_event(KSWAPD_PREMATURE_FAST); | ||
2226 | else | ||
2227 | count_vm_event(KSWAPD_PREMATURE_SLOW); | ||
2228 | } | ||
2229 | } | ||
2190 | 2230 | ||
2191 | order = pgdat->kswapd_max_order; | 2231 | order = pgdat->kswapd_max_order; |
2192 | } | 2232 | } |