summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorMichal Hocko <mhocko@suse.com>2017-02-22 18:42:00 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 19:41:27 -0500
commitd379f01de09570e06d84b4b09e5f4951821a1dc8 (patch)
tree4f024b1d45b22aab9ae86160e5b4482a36041076 /mm/page_alloc.c
parentaff28015fe5396b7f2bf7f55863949d391eb75fb (diff)
oom, trace: add oom detection tracepoints
should_reclaim_retry is the central decision point for declaring the OOM. It might be really useful to expose data used for this decision making when debugging an unexpected oom situations. Say we have an OOM report: [ 52.264001] mem_eater invoked oom-killer: gfp_mask=0x24280ca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), nodemask=0, order=0, oom_score_adj=0 [ 52.267549] CPU: 3 PID: 3148 Comm: mem_eater Tainted: G W 4.8.0-oomtrace3-00006-gb21338b386d2 #1024 Now we can check the tracepoint data to see how we have ended up in this situation: mem_eater-3148 [003] .... 52.432801: reclaim_retry_zone: node=0 zone=DMA32 order=0 reclaimable=51 available=11134 min_wmark=11084 no_progress_loops=1 wmark_check=1 mem_eater-3148 [003] .... 52.433269: reclaim_retry_zone: node=0 zone=DMA32 order=0 reclaimable=51 available=11103 min_wmark=11084 no_progress_loops=1 wmark_check=1 mem_eater-3148 [003] .... 52.433712: reclaim_retry_zone: node=0 zone=DMA32 order=0 reclaimable=51 available=11100 min_wmark=11084 no_progress_loops=2 wmark_check=1 mem_eater-3148 [003] .... 52.434067: reclaim_retry_zone: node=0 zone=DMA32 order=0 reclaimable=51 available=11097 min_wmark=11084 no_progress_loops=3 wmark_check=1 mem_eater-3148 [003] .... 52.434414: reclaim_retry_zone: node=0 zone=DMA32 order=0 reclaimable=51 available=11094 min_wmark=11084 no_progress_loops=4 wmark_check=1 mem_eater-3148 [003] .... 52.434761: reclaim_retry_zone: node=0 zone=DMA32 order=0 reclaimable=51 available=11091 min_wmark=11084 no_progress_loops=5 wmark_check=1 mem_eater-3148 [003] .... 52.435108: reclaim_retry_zone: node=0 zone=DMA32 order=0 reclaimable=51 available=11087 min_wmark=11084 no_progress_loops=6 wmark_check=1 mem_eater-3148 [003] .... 52.435478: reclaim_retry_zone: node=0 zone=DMA32 order=0 reclaimable=51 available=11084 min_wmark=11084 no_progress_loops=7 wmark_check=0 mem_eater-3148 [003] .... 52.435478: reclaim_retry_zone: node=0 zone=DMA order=0 reclaimable=0 available=1126 min_wmark=179 no_progress_loops=7 wmark_check=0 The above shows that we can quickly deduce that the reclaim stopped making any progress (see no_progress_loops increased in each round) and while there were still some 51 reclaimable pages they couldn't be dropped for some reason (vmscan trace points would tell us more about that part). available will represent reclaimable + free_pages scaled down per no_progress_loops factor. This is essentially an optimistic estimate of how much memory we would have when reclaiming everything. This can be compared to min_wmark to get a rought idea but the wmark_check tells the result of the watermark check which is more precise (includes lowmem reserves, considers the order etc.). As we can see no zone is eligible in the end and that is why we have triggered the oom in this situation. Please note that higher order requests might fail on the wmark_check even when there is much more memory available than min_wmark - e.g. when the memory is fragmented. A follow up tracepoint will help to debug those situations. Link: http://lkml.kernel.org/r/20161220130135.15719-3-mhocko@kernel.org Signed-off-by: Michal Hocko <mhocko@suse.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: David Rientjes <rientjes@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> 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.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index af65c4eedc79..d20f8c3139bb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -55,6 +55,7 @@
55#include <linux/kmemleak.h> 55#include <linux/kmemleak.h>
56#include <linux/compaction.h> 56#include <linux/compaction.h>
57#include <trace/events/kmem.h> 57#include <trace/events/kmem.h>
58#include <trace/events/oom.h>
58#include <linux/prefetch.h> 59#include <linux/prefetch.h>
59#include <linux/mm_inline.h> 60#include <linux/mm_inline.h>
60#include <linux/migrate.h> 61#include <linux/migrate.h>
@@ -3468,6 +3469,8 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
3468 ac->nodemask) { 3469 ac->nodemask) {
3469 unsigned long available; 3470 unsigned long available;
3470 unsigned long reclaimable; 3471 unsigned long reclaimable;
3472 unsigned long min_wmark = min_wmark_pages(zone);
3473 bool wmark;
3471 3474
3472 available = reclaimable = zone_reclaimable_pages(zone); 3475 available = reclaimable = zone_reclaimable_pages(zone);
3473 available -= DIV_ROUND_UP((*no_progress_loops) * available, 3476 available -= DIV_ROUND_UP((*no_progress_loops) * available,
@@ -3478,8 +3481,11 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order,
3478 * Would the allocation succeed if we reclaimed the whole 3481 * Would the allocation succeed if we reclaimed the whole
3479 * available? 3482 * available?
3480 */ 3483 */
3481 if (__zone_watermark_ok(zone, order, min_wmark_pages(zone), 3484 wmark = __zone_watermark_ok(zone, order, min_wmark,
3482 ac_classzone_idx(ac), alloc_flags, available)) { 3485 ac_classzone_idx(ac), alloc_flags, available);
3486 trace_reclaim_retry_zone(z, order, reclaimable,
3487 available, min_wmark, *no_progress_loops, wmark);
3488 if (wmark) {
3483 /* 3489 /*
3484 * If we didn't make any progress and have a lot of 3490 * If we didn't make any progress and have a lot of
3485 * dirty + writeback pages then we should wait for 3491 * dirty + writeback pages then we should wait for