2 minutes
Adding Tracepoints in Ftrace
Ftrace comes with many static tracepoints out of the box but sometime we may want tracepoint which doesn’t exist and we need to enable dynamic tracepoints. Since using dyamic tracepoints is not a portable aproach as function name may change for different kernel version therefore it is preferred to only tracepoints visible in ftrace i.e static tracepoints. The tracepoint can be added in ftrace source in kernel and patch can be submitted to add those to the mainstream to make them static.
For example to add mm_page_swap_in/mm_page_swap_out
.
mm_page_swap_in: Called whenever page is swapped in from swap area. The “ret” value can be used to compare if page was added from swap cache(minor fault) or from lower level swap area(major fault), which can be useful in profiling the performance degradation due to swapping
mm_page_swap_out: Called whenever page is swapped out to swap area
It requires 2 steps:
-
Declaring the tracepoint: Since these are memory related events and some of the memory related events are already available in
/sys/kernel/debug/tracing/events/kmem
let’s addmm_page_swap_in
in the same directory i.e kmem.Before declaring tracepoint, we need to look into the function where this tracepoint will be inserted to see what fields are visible in the function which can be passed to the tracepoint and captured. For eg: here we can pass struct page *, int to the tracepoint.
/include/trace/events/kmem.h
holds the declaration of events related to kmem. Let’s addmm_page_swap_in/mm_page_swap_out
to the same. The declaration format is:TRACE_EVENT(mm_page_swap_out, // Tracepoint name TP_PROTO(struct page *page, int ret), // args this tracepoint will accept TP_ARGS(page, ret), TP_STRUCT__entry( __field( unsigned long, pfn ) // tracepoint specific structure, same as __field( int, ret ) // format structure in event's format file. ), TP_fast_assign( __entry->pfn = page_to_pfn(page); // assigning value to the tracepoint struct __entry->ret = ret; ), TP_printk("page=%p pfn=%lu ret=%d", // Print function called pfn_to_page(__entry->pfn), __entry->pfn, __entry->ret) );
This will create the function
trace_mm_page_fault(struct page*, int)
, which can be inserted wherever we want to put our tracepoint. -
Putting that tracepoint in appropriate place required:
add_to_swap(struct page *page, struct list_head *list)
is the function called when page is added to the swap area. So to put the declared tracepoint :int add_to_swap(struct page *page, struct list_head *list) { ..... trace_mm_page_swap_out(page,ret) }
Now, after recompiling the kernel and mounting debugfs, we can see our tracepoint in ftrace:
/sys/kernel/debug/tracing/events/kmem/mm_page_swap_out /sys/kernel/debug/tracing/events/kmem/mm_page_swap_out/id /sys/kernel/debug/tracing/events/kmem/mm_page_swap_out/format /sys/kernel/debug/tracing/events/kmem/mm_page_swap_out/filter /sys/kernel/debug/tracing/events/kmem/mm_page_swap_out/enable
Similarly, we can add tracepoint for
mm_page_swap_in
which can be added in functionstatic int do_swap_page(...)
inmm/memory.c
.