summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorMichal Hocko <mhocko@suse.com>2017-02-22 18:41:45 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 19:41:27 -0500
commitaa187507ef8bb3178a3312d851e8485bd81913c9 (patch)
tree3b6c8f0d140fc3242c077819c82ece7ed0398d2b /mm/page_alloc.c
parentf8005451d75f4879a93b12c14b162dd60f81ec56 (diff)
mm: throttle show_mem() from warn_alloc()
Tetsuo has been stressing OOM killer path with many parallel allocation requests when he has noticed that it is not all that hard to swamp kernel logs with warn_alloc messages caused by allocation stalls. Even though the allocation stall message is triggered only once in 10s there might be many different tasks hitting it roughly around the same time. A big part of the output is show_mem() which can generate a lot of output even on a small machines. There is no reason to show the state of memory counter for each allocation stall, especially when multiple of them are reported in a short time period. Chances are that not much has changed since the last report. This patch simply rate limits show_mem called from warn_alloc to only dump something once per second. This should be enough to give us a clue why an allocation might be stalling while burst of warnings will not swamp log with too much data. While we are at it, extract all the show_mem related handling (filters) into a separate function warn_alloc_show_mem. This will make the code cleaner and as a bonus point we can distinguish which part of warn_alloc got throttled due to rate limiting as ___ratelimit dumps the caller. [akpm@linux-foundation.org: reduce scope of the ratelimit_states] Link: http://lkml.kernel.org/r/20161215101510.9030-1-mhocko@kernel.org Signed-off-by: Michal Hocko <mhocko@suse.com> Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index f3e0c69a97b7..3c790ae4cb52 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3007,18 +3007,12 @@ static inline bool should_suppress_show_mem(void)
3007 return ret; 3007 return ret;
3008} 3008}
3009 3009
3010static DEFINE_RATELIMIT_STATE(nopage_rs, 3010static void warn_alloc_show_mem(gfp_t gfp_mask)
3011 DEFAULT_RATELIMIT_INTERVAL,
3012 DEFAULT_RATELIMIT_BURST);
3013
3014void warn_alloc(gfp_t gfp_mask, const char *fmt, ...)
3015{ 3011{
3016 unsigned int filter = SHOW_MEM_FILTER_NODES; 3012 unsigned int filter = SHOW_MEM_FILTER_NODES;
3017 struct va_format vaf; 3013 static DEFINE_RATELIMIT_STATE(show_mem_rs, HZ, 1);
3018 va_list args;
3019 3014
3020 if ((gfp_mask & __GFP_NOWARN) || !__ratelimit(&nopage_rs) || 3015 if (should_suppress_show_mem() || !__ratelimit(&show_mem_rs))
3021 debug_guardpage_minorder() > 0)
3022 return; 3016 return;
3023 3017
3024 /* 3018 /*
@@ -3033,6 +3027,20 @@ void warn_alloc(gfp_t gfp_mask, const char *fmt, ...)
3033 if (in_interrupt() || !(gfp_mask & __GFP_DIRECT_RECLAIM)) 3027 if (in_interrupt() || !(gfp_mask & __GFP_DIRECT_RECLAIM))
3034 filter &= ~SHOW_MEM_FILTER_NODES; 3028 filter &= ~SHOW_MEM_FILTER_NODES;
3035 3029
3030 show_mem(filter);
3031}
3032
3033void warn_alloc(gfp_t gfp_mask, const char *fmt, ...)
3034{
3035 struct va_format vaf;
3036 va_list args;
3037 static DEFINE_RATELIMIT_STATE(nopage_rs, DEFAULT_RATELIMIT_INTERVAL,
3038 DEFAULT_RATELIMIT_BURST);
3039
3040 if ((gfp_mask & __GFP_NOWARN) || !__ratelimit(&nopage_rs) ||
3041 debug_guardpage_minorder() > 0)
3042 return;
3043
3036 pr_warn("%s: ", current->comm); 3044 pr_warn("%s: ", current->comm);
3037 3045
3038 va_start(args, fmt); 3046 va_start(args, fmt);
@@ -3044,8 +3052,7 @@ void warn_alloc(gfp_t gfp_mask, const char *fmt, ...)
3044 pr_cont(", mode:%#x(%pGg)\n", gfp_mask, &gfp_mask); 3052 pr_cont(", mode:%#x(%pGg)\n", gfp_mask, &gfp_mask);
3045 3053
3046 dump_stack(); 3054 dump_stack();
3047 if (!should_suppress_show_mem()) 3055 warn_alloc_show_mem(gfp_mask);
3048 show_mem(filter);
3049} 3056}
3050 3057
3051static inline struct page * 3058static inline struct page *