bcc/tools: Fix renaming of the state field of task_struct
authorHengqi Chen <chenhengqi@outlook.com>
Sun, 31 Oct 2021 15:20:10 +0000 (23:20 +0800)
committeryonghong-song <ys114321@gmail.com>
Mon, 1 Nov 2021 15:07:53 +0000 (08:07 -0700)
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 <chenhengqi@outlook.com>
tools/offcputime.py
tools/offwaketime.py
tools/runqlat.py
tools/runqslower.py

index 128c6496d3d6ea09cfe70fe993480ba895e279bf..c9b1e6e9dcbc6fe0e23c3b0ad501997c305be6df 100755 (executable)
@@ -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))
index 753eee97fb490bf2b5f4c6de1b2ff43bb8d75ae7..b52d472528803fd35c93e0cb4d27910dc774d622 100755 (executable)
@@ -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))
index a5c261aca3f8c62b982015ff10367e9f2121179c..9edd7bebd8919f17c57dd4ba6034283fbf7a784c 100755 (executable)
@@ -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)
index ef2bf2816c888a870d66cf7a6cff2a650ce5ea1d..6c94d6c6b6bcfb1d71dc05402d8db66e8dc5f03d 100755 (executable)
@@ -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: