From 08765a9a0ba8dc9c38ec7dff05fa1734cf43866f Mon Sep 17 00:00:00 2001 From: Hengqi Chen Date: Sun, 31 Oct 2021 23:20:10 +0800 Subject: [PATCH] bcc/tools: Fix renaming of the state field of task_struct Kernel commit 2f064a59a1 ("sched: Change task_struct::state") changes the name of task_struct::state to task_struct::__state, which breaks several bcc tools. Fix this issue by checking field existence in vmlinux BTF. Since this change was intruduce in kernel v5.14, we should have BTF support. Closes #3658 . Signed-off-by: Hengqi Chen --- tools/offcputime.py | 12 ++++++++---- tools/offwaketime.py | 20 ++++++++++++-------- tools/runqlat.py | 8 ++++++-- tools/runqslower.py | 8 ++++++-- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/tools/offcputime.py b/tools/offcputime.py index 128c6496..c9b1e6e9 100755 --- a/tools/offcputime.py +++ b/tools/offcputime.py @@ -116,8 +116,8 @@ bpf_text = """ #define MAXBLOCK_US MAXBLOCK_US_VALUEULL struct key_t { - u32 pid; - u32 tgid; + u64 pid; + u64 tgid; int user_stack_id; int kernel_stack_id; char name[TASK_COMM_LEN]; @@ -205,14 +205,18 @@ else: thread_context = "all threads" thread_filter = '1' if args.state == 0: - state_filter = 'prev->state == 0' + state_filter = 'prev->STATE_FIELD == 0' elif args.state: # these states are sometimes bitmask checked - state_filter = 'prev->state & %d' % args.state + state_filter = 'prev->STATE_FIELD & %d' % args.state else: state_filter = '1' bpf_text = bpf_text.replace('THREAD_FILTER', thread_filter) bpf_text = bpf_text.replace('STATE_FILTER', state_filter) +if BPF.kernel_struct_has_field(b'task_struct', b'__state') == 1: + bpf_text = bpf_text.replace('STATE_FIELD', '__state') +else: + bpf_text = bpf_text.replace('STATE_FIELD', 'state') # set stack storage size bpf_text = bpf_text.replace('STACK_STORAGE_SIZE', str(args.stack_storage_size)) diff --git a/tools/offwaketime.py b/tools/offwaketime.py index 753eee97..b52d4725 100755 --- a/tools/offwaketime.py +++ b/tools/offwaketime.py @@ -139,12 +139,12 @@ bpf_text = """ struct key_t { char waker[TASK_COMM_LEN]; char target[TASK_COMM_LEN]; - int w_k_stack_id; - int w_u_stack_id; - int t_k_stack_id; - int t_u_stack_id; - u32 t_pid; - u32 t_tgid; + s64 w_k_stack_id; + s64 w_u_stack_id; + s64 t_k_stack_id; + s64 t_u_stack_id; + u64 t_pid; + u64 t_tgid; u32 w_pid; u32 w_tgid; }; @@ -254,14 +254,18 @@ elif args.kernel_threads_only: else: thread_filter = '1' if args.state == 0: - state_filter = 'p->state == 0' + state_filter = 'p->STATE_FIELD == 0' elif args.state: # these states are sometimes bitmask checked - state_filter = 'p->state & %d' % args.state + state_filter = 'p->STATE_FIELD & %d' % args.state else: state_filter = '1' bpf_text = bpf_text.replace('THREAD_FILTER', thread_filter) bpf_text = bpf_text.replace('STATE_FILTER', state_filter) +if BPF.kernel_struct_has_field(b'task_struct', b'__state') == 1: + bpf_text = bpf_text.replace('STATE_FIELD', '__state') +else: + bpf_text = bpf_text.replace('STATE_FIELD', 'state') # set stack storage size bpf_text = bpf_text.replace('STACK_STORAGE_SIZE', str(args.stack_storage_size)) diff --git a/tools/runqlat.py b/tools/runqlat.py index a5c261ac..9edd7beb 100755 --- a/tools/runqlat.py +++ b/tools/runqlat.py @@ -156,7 +156,7 @@ int trace_run(struct pt_regs *ctx, struct task_struct *prev) u32 pid, tgid; // ivcsw: treat like an enqueue event and store timestamp - if (prev->state == TASK_RUNNING) { + if (prev->STATE_FIELD == TASK_RUNNING) { tgid = prev->tgid; pid = prev->pid; if (!(FILTER || pid == 0)) { @@ -210,7 +210,7 @@ RAW_TRACEPOINT_PROBE(sched_switch) u32 pid, tgid; // ivcsw: treat like an enqueue event and store timestamp - if (prev->state == TASK_RUNNING) { + if (prev->STATE_FIELD == TASK_RUNNING) { tgid = prev->tgid; pid = prev->pid; if (!(FILTER || pid == 0)) { @@ -248,6 +248,10 @@ else: bpf_text += bpf_text_kprobe # code substitutions +if BPF.kernel_struct_has_field(b'task_struct', b'__state') == 1: + bpf_text = bpf_text.replace('STATE_FIELD', '__state') +else: + bpf_text = bpf_text.replace('STATE_FIELD', 'state') if args.pid: # pid from userspace point of view is thread group from kernel pov bpf_text = bpf_text.replace('FILTER', 'tgid != %s' % args.pid) diff --git a/tools/runqslower.py b/tools/runqslower.py index ef2bf281..6c94d6c6 100755 --- a/tools/runqslower.py +++ b/tools/runqslower.py @@ -118,7 +118,7 @@ int trace_run(struct pt_regs *ctx, struct task_struct *prev) // ivcsw: treat like an enqueue event and store timestamp prev_pid = prev->pid; - if (prev->state == TASK_RUNNING) { + if (prev->STATE_FIELD == TASK_RUNNING) { tgid = prev->tgid; u64 ts = bpf_ktime_get_ns(); if (prev_pid != 0) { @@ -185,7 +185,7 @@ RAW_TRACEPOINT_PROBE(sched_switch) long state; // ivcsw: treat like an enqueue event and store timestamp - bpf_probe_read_kernel(&state, sizeof(long), (const void *)&prev->state); + bpf_probe_read_kernel(&state, sizeof(long), (const void *)&prev->STATE_FIELD); bpf_probe_read_kernel(&prev_pid, sizeof(prev->pid), &prev->pid); if (state == TASK_RUNNING) { bpf_probe_read_kernel(&tgid, sizeof(prev->tgid), &prev->tgid); @@ -234,6 +234,10 @@ else: bpf_text += bpf_text_kprobe # code substitutions +if BPF.kernel_struct_has_field(b'task_struct', b'__state') == 1: + bpf_text = bpf_text.replace('STATE_FIELD', '__state') +else: + bpf_text = bpf_text.replace('STATE_FIELD', 'state') if min_us == 0: bpf_text = bpf_text.replace('FILTER_US', '0') else: -- 2.34.1