Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libbpf-tools/offcputime: Allow offcputime to run on old kernels #4334

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 21 additions & 11 deletions libbpf-tools/offcputime.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,50 +44,49 @@ struct {

static bool allow_record(struct task_struct *t)
{
if (targ_tgid != -1 && targ_tgid != t->tgid)
if (targ_tgid != -1 && targ_tgid != BPF_CORE_READ(t, tgid))
return false;
if (targ_pid != -1 && targ_pid != t->pid)
if (targ_pid != -1 && targ_pid != BPF_CORE_READ(t, pid))
return false;
if (user_threads_only && t->flags & PF_KTHREAD)
if (user_threads_only && BPF_CORE_READ(t, flags) & PF_KTHREAD)
return false;
else if (kernel_threads_only && !(t->flags & PF_KTHREAD))
else if (kernel_threads_only && !(BPF_CORE_READ(t, flags) & PF_KTHREAD))
return false;
if (state != -1 && get_task_state(t) != state)
return false;
return true;
}

SEC("tp_btf/sched_switch")
int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_struct *next)
static int handle_switch(u64 *ctx, struct task_struct *prev)
{
struct internal_key *i_keyp, i_key;
struct val_t *valp, val;
s64 delta;
u32 pid;

if (allow_record(prev)) {
pid = prev->pid;
pid = BPF_CORE_READ(prev, pid);
/* To distinguish idle threads of different cores */
if (!pid)
pid = bpf_get_smp_processor_id();
i_key.key.pid = pid;
i_key.key.tgid = prev->tgid;
i_key.key.tgid = BPF_CORE_READ(prev, tgid);
i_key.start_ts = bpf_ktime_get_ns();

if (prev->flags & PF_KTHREAD)
if (BPF_CORE_READ(prev, flags) & PF_KTHREAD)
i_key.key.user_stack_id = -1;
else
i_key.key.user_stack_id =
bpf_get_stackid(ctx, &stackmap,
BPF_F_USER_STACK);
i_key.key.kern_stack_id = bpf_get_stackid(ctx, &stackmap, 0);
bpf_map_update_elem(&start, &pid, &i_key, 0);
bpf_probe_read_kernel_str(&val.comm, sizeof(prev->comm), prev->comm);
BPF_CORE_READ_STR_INTO(&val.comm, prev, comm);
val.delta = 0;
bpf_map_update_elem(&info, &i_key.key, &val, BPF_NOEXIST);
}

pid = next->pid;
pid = bpf_get_current_pid_tgid();
i_keyp = bpf_map_lookup_elem(&start, &pid);
if (!i_keyp)
return 0;
Expand All @@ -107,4 +106,15 @@ int BPF_PROG(sched_switch, bool preempt, struct task_struct *prev, struct task_s
return 0;
}

SEC("tp_btf/sched_switch")
int BPF_PROG(sched_switch_btf, bool preempt, struct task_struct *prev, struct task_struct *next) {
return handle_switch(ctx, prev);
}

SEC("kprobe/finish_task_switch")
int BPF_PROG(sched_switch_tp) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's fallback to raw tracepoint instead. See #4217.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for replay, but on my test env, the "raw_tp/sched_switch" won't work:

libbpf: sched_switch is not found in vmlinux BTF                                                                                                               
    entries_lock                                                                                                                                               
failed to get syms                                                                                                                                             
    -                 (0)                                                                                                                                      
        51                                                                                                                                                     
                                                                                                                                                               
    entries_lock                                                                                                                                               
failed to get syms
    -                 (0)
        4811

    entries_lock        

The comm is empty and PID is always 0, I think the prev is not correctly taken. Do you have any suggest?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's fallback to raw tracepoint instead. See #4217.

I tried to make it work and succeed, but the call stacks still seem always belong to the tracepoint raw_tp/sched_switch.

Changed code:

SEC("raw_tp/sched_switch")
int BPF_PROG(sched_switch_tp) {
	struct task_struct *prev = (struct task_struct *)((struct bpf_raw_tracepoint_args *)ctx)->args[1];
	return handle_switch(ctx, prev);
}

Output example:

    entries_lock                                                                                                                                    [250/15106]
    -                kworker/2:2 (2704182)                                                                                                                     
        9                                                                                                                                                      
                                                                                                                                                                       

    entries_lock                       
    wait4                              
    -                bash (2708107)
        13                             

    entries_lock                       
    -                ksoftirqd/0 (10)
        1                              

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does #4217 work for you ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does #4217 work for you ?

Everything works fine except the callstacks, so close this pr until I find the reason and solutions。

struct task_struct *prev = (struct task_struct *)PT_REGS_PARM1_CORE((struct pt_regs *)ctx);
return handle_switch(ctx, prev);
}

char LICENSE[] SEC("license") = "GPL";
6 changes: 6 additions & 0 deletions libbpf-tools/offcputime.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ int main(int argc, char **argv)
return 1;
}

if (probe_tp_btf("sched_switch")) {
bpf_program__set_autoload(obj->progs.sched_switch_tp, false);
} else {
bpf_program__set_autoload(obj->progs.sched_switch_btf, false);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are following kernel code style guide, so drop the surrounding {}.


/* initialize global data (filtering options) */
obj->rodata->targ_tgid = env.pid;
obj->rodata->targ_pid = env.tid;
Expand Down