Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

page_pool: add tracepoints for page_pool with details need by XDP

The xdp tracepoints for mem id disconnect don't carry information about, why
it was not safe_to_remove. The tracepoint page_pool:page_pool_inflight in
this patch can be used for extract this info for further debugging.

This patchset also adds tracepoint for the pages_state_* release/hold
transitions, including a pointer to the page. This can be used for stats
about in-flight pages, or used to debug page leakage via keeping track of
page pointer and combining this with kprobe for __put_page().

Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jesper Dangaard Brouer and committed by
David S. Miller
32c28f7e f033b688

+99 -1
+87
include/trace/events/page_pool.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #undef TRACE_SYSTEM 3 + #define TRACE_SYSTEM page_pool 4 + 5 + #if !defined(_TRACE_PAGE_POOL_H) || defined(TRACE_HEADER_MULTI_READ) 6 + #define _TRACE_PAGE_POOL_H 7 + 8 + #include <linux/types.h> 9 + #include <linux/tracepoint.h> 10 + 11 + #include <net/page_pool.h> 12 + 13 + TRACE_EVENT(page_pool_inflight, 14 + 15 + TP_PROTO(const struct page_pool *pool, 16 + s32 inflight, u32 hold, u32 release), 17 + 18 + TP_ARGS(pool, inflight, hold, release), 19 + 20 + TP_STRUCT__entry( 21 + __field(const struct page_pool *, pool) 22 + __field(s32, inflight) 23 + __field(u32, hold) 24 + __field(u32, release) 25 + ), 26 + 27 + TP_fast_assign( 28 + __entry->pool = pool; 29 + __entry->inflight = inflight; 30 + __entry->hold = hold; 31 + __entry->release = release; 32 + ), 33 + 34 + TP_printk("page_pool=%p inflight=%d hold=%u release=%u", 35 + __entry->pool, __entry->inflight, __entry->hold, __entry->release) 36 + ); 37 + 38 + TRACE_EVENT(page_pool_state_release, 39 + 40 + TP_PROTO(const struct page_pool *pool, 41 + const struct page *page, u32 release), 42 + 43 + TP_ARGS(pool, page, release), 44 + 45 + TP_STRUCT__entry( 46 + __field(const struct page_pool *, pool) 47 + __field(const struct page *, page) 48 + __field(u32, release) 49 + ), 50 + 51 + TP_fast_assign( 52 + __entry->pool = pool; 53 + __entry->page = page; 54 + __entry->release = release; 55 + ), 56 + 57 + TP_printk("page_pool=%p page=%p release=%u", 58 + __entry->pool, __entry->page, __entry->release) 59 + ); 60 + 61 + TRACE_EVENT(page_pool_state_hold, 62 + 63 + TP_PROTO(const struct page_pool *pool, 64 + const struct page *page, u32 hold), 65 + 66 + TP_ARGS(pool, page, hold), 67 + 68 + TP_STRUCT__entry( 69 + __field(const struct page_pool *, pool) 70 + __field(const struct page *, page) 71 + __field(u32, hold) 72 + ), 73 + 74 + TP_fast_assign( 75 + __entry->pool = pool; 76 + __entry->page = page; 77 + __entry->hold = hold; 78 + ), 79 + 80 + TP_printk("page_pool=%p page=%p hold=%u", 81 + __entry->pool, __entry->page, __entry->hold) 82 + ); 83 + 84 + #endif /* _TRACE_PAGE_POOL_H */ 85 + 86 + /* This part must be outside protection */ 87 + #include <trace/define_trace.h>
+4
net/core/net-traces.c
··· 43 43 EXPORT_TRACEPOINT_SYMBOL_GPL(br_fdb_update); 44 44 #endif 45 45 46 + #if IS_ENABLED(CONFIG_PAGE_POOL) 47 + #include <trace/events/page_pool.h> 48 + #endif 49 + 46 50 #include <trace/events/neigh.h> 47 51 EXPORT_TRACEPOINT_SYMBOL_GPL(neigh_update); 48 52 EXPORT_TRACEPOINT_SYMBOL_GPL(neigh_update_done);
+8 -1
net/core/page_pool.c
··· 4 4 * Author: Jesper Dangaard Brouer <netoptimizer@brouer.com> 5 5 * Copyright (C) 2016 Red Hat, Inc. 6 6 */ 7 + 7 8 #include <linux/types.h> 8 9 #include <linux/kernel.h> 9 10 #include <linux/slab.h> ··· 14 13 #include <linux/dma-mapping.h> 15 14 #include <linux/page-flags.h> 16 15 #include <linux/mm.h> /* for __put_page() */ 16 + 17 + #include <trace/events/page_pool.h> 17 18 18 19 static int page_pool_init(struct page_pool *pool, 19 20 const struct page_pool_params *params) ··· 159 156 /* Track how many pages are held 'in-flight' */ 160 157 pool->pages_state_hold_cnt++; 161 158 159 + trace_page_pool_state_hold(pool, page, pool->pages_state_hold_cnt); 160 + 162 161 /* When page just alloc'ed is should/must have refcnt 1. */ 163 162 return page; 164 163 } ··· 196 191 197 192 distance = _distance(hold_cnt, release_cnt); 198 193 199 - /* TODO: Add tracepoint here */ 194 + trace_page_pool_inflight(pool, distance, hold_cnt, release_cnt); 200 195 return distance; 201 196 } 202 197 ··· 227 222 page->dma_addr = 0; 228 223 skip_dma_unmap: 229 224 atomic_inc(&pool->pages_state_release_cnt); 225 + trace_page_pool_state_release(pool, page, 226 + atomic_read(&pool->pages_state_release_cnt)); 230 227 } 231 228 232 229 /* unmap the page and clean our state */