From: Josef Bacik should_reclaim_retry() walks a zonelist and passes the zoneref pointer to the reclaim_retry_zone tracepoint, which loads the zone from the entry again to find the node. Memory hotplug rebuilds the zonelists in place while allocations are under way. When a zone in front of the zoneref entry has become empty, the entries move up, and this one can be the end marker by the time the tracepoint looks at it. zonelist_node_idx() then dereferences a NULL zone. Short of that, the event can name another zone than the one its numbers belong to. Pass the zone pointer instead of the zoneref pointer. Fixes: d379f01de095 ("oom, trace: add oom detection tracepoints") Cc: Assisted-by: LLM Signed-off-by: Josef Bacik Signed-off-by: David Hildenbrand (Arm) Signed-off-by: Vlastimil Babka (SUSE) --- include/trace/events/oom.h | 8 ++++---- mm/page_alloc.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/trace/events/oom.h b/include/trace/events/oom.h index 9f0a5d1482c4..cbcf6fe4cc61 100644 --- a/include/trace/events/oom.h +++ b/include/trace/events/oom.h @@ -33,7 +33,7 @@ TRACE_EVENT(oom_score_adj_update, TRACE_EVENT(reclaim_retry_zone, - TP_PROTO(struct zoneref *zoneref, + TP_PROTO(struct zone *zone, int order, unsigned long reclaimable, unsigned long available, @@ -41,7 +41,7 @@ TRACE_EVENT(reclaim_retry_zone, int no_progress_loops, bool wmark_check), - TP_ARGS(zoneref, order, reclaimable, available, min_wmark, no_progress_loops, wmark_check), + TP_ARGS(zone, order, reclaimable, available, min_wmark, no_progress_loops, wmark_check), TP_STRUCT__entry( __field( int, node) @@ -55,8 +55,8 @@ TRACE_EVENT(reclaim_retry_zone, ), TP_fast_assign( - __entry->node = zonelist_node_idx(zoneref); - __entry->zone_idx = zonelist_zone_idx(zoneref); + __entry->node = zone_to_nid(zone); + __entry->zone_idx = zone_idx(zone); __entry->order = order; __entry->reclaimable = reclaimable; __entry->available = available; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 13211b8caada..8f8885165045 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4675,7 +4675,7 @@ should_reclaim_retry(gfp_t gfp_mask, unsigned order, */ wmark = __zone_watermark_ok(zone, order, min_wmark, ac->highest_zoneidx, alloc_flags, available); - trace_reclaim_retry_zone(z, order, reclaimable, + trace_reclaim_retry_zone(zone, order, reclaimable, available, min_wmark, *no_progress_loops, wmark); if (wmark) { ret = true; -- 2.56.0