tools: filter/display using PID instead of TID
authorHengqi Chen <chenhengqi@outlook.com>
Thu, 20 May 2021 14:49:25 +0000 (22:49 +0800)
committeryonghong-song <ys114321@gmail.com>
Sat, 22 May 2021 00:48:22 +0000 (17:48 -0700)
As mentioned in #3407, several BCC tools misuse bpf_get_current_pid_tgid(),
bpf_get_current_pid_tgid() returns process ID in the upper 32bits, and
thread ID in lower 32 bits (both from userspace's perspective).
In this commit, we return process ID to userspace for display, and use
thread ID as BPF map key so that we can avoid event loss or data corruption.

The following tools are fixed in the commit:
* bashreadline
* cachetop
* dcsnoop
* killsnoop
* llcstat
* mdflush
* mysqld_qslower
* wakeuptime

See also #3411, #3427, #3433 .

Signed-off-by: Hengqi Chen <chenhengqi@outlook.com>
tools/bashreadline.py
tools/cachetop.py
tools/dcsnoop.py
tools/killsnoop.py
tools/llcstat.py
tools/mdflush.py
tools/mysqld_qslower.py
tools/wakeuptime.py

index ad9cfdc0a1dfaf7ba1f7df34043767378b500cea..908a1451bb78a57d16af9df4f265dd6579e23d5d 100755 (executable)
@@ -50,7 +50,7 @@ int printret(struct pt_regs *ctx) {
     u32 pid;
     if (!PT_REGS_RC(ctx))
         return 0;
-    pid = bpf_get_current_pid_tgid();
+    pid = bpf_get_current_pid_tgid() >> 32;
     data.pid = pid;
     bpf_probe_read_user(&data.str, sizeof(data.str), (void *)PT_REGS_RC(ctx));
 
index 803e2a06b8d0a02bda8f67f9f05ee4feb049248d..fe6a9a93f166abd3a517fd525c305f2b8217b6ec 100755 (executable)
@@ -157,8 +157,8 @@ def handle_loop(stdscr, args):
         u32 uid = bpf_get_current_uid_gid();
 
         key.ip = PT_REGS_IP(ctx);
-        key.pid = pid & 0xFFFFFFFF;
-        key.uid = uid & 0xFFFFFFFF;
+        key.pid = pid >> 32;
+        key.uid = uid;
         bpf_get_current_comm(&(key.comm), 16);
 
         counts.increment(key);
index 819d4e66540d346e17196ebd151fd737c7518acf..274eaa5926e2c0eb3b20fe1b69f839a7c191a363 100755 (executable)
@@ -90,7 +90,7 @@ void submit_event(struct pt_regs *ctx, void *name, int type, u32 pid)
 
 int trace_fast(struct pt_regs *ctx, struct nameidata *nd, struct path *path)
 {
-    u32 pid = bpf_get_current_pid_tgid();
+    u32 pid = bpf_get_current_pid_tgid() >> 32;
     submit_event(ctx, (void *)nd->last.name, LOOKUP_REFERENCE, pid);
     return 1;
 }
@@ -98,26 +98,34 @@ int trace_fast(struct pt_regs *ctx, struct nameidata *nd, struct path *path)
 int kprobe__d_lookup(struct pt_regs *ctx, const struct dentry *parent,
     const struct qstr *name)
 {
-    u32 pid = bpf_get_current_pid_tgid();
+    u32 tid = bpf_get_current_pid_tgid();
     struct entry_t entry = {};
     const char *fname = name->name;
     if (fname) {
         bpf_probe_read_kernel(&entry.name, sizeof(entry.name), (void *)fname);
     }
-    entrybypid.update(&pid, &entry);
+    entrybypid.update(&tid, &entry);
     return 0;
 }
 
 int kretprobe__d_lookup(struct pt_regs *ctx)
 {
-    u32 pid = bpf_get_current_pid_tgid();
+    u64 pid_tgid = bpf_get_current_pid_tgid();
+    u32 pid = pid_tgid >> 32;
+    u32 tid = (u32)pid_tgid;
     struct entry_t *ep;
-    ep = entrybypid.lookup(&pid);
-    if (ep == 0 || PT_REGS_RC(ctx) != 0) {
-        return 0;   // missed entry or lookup didn't fail
+
+    ep = entrybypid.lookup(&tid);
+    if (ep == 0) {
+        return 0;   // missed entry
+    }
+    if (PT_REGS_RC(ctx) != 0) {
+        entrybypid.delete(&tid);
+        return 0;   // lookup didn't fail
     }
+
     submit_event(ctx, (void *)ep->name, LOOKUP_MISS, pid);
-    entrybypid.delete(&pid);
+    entrybypid.delete(&tid);
     return 0;
 }
 """
index 2dc5b8af9eeb7292b8661ac0535c3d5dddbc4769..663c8101e871deb7fe1039ba1c16b60f8a70ab8a 100755 (executable)
@@ -65,7 +65,10 @@ BPF_PERF_OUTPUT(events);
 
 int syscall__kill(struct pt_regs *ctx, int tpid, int sig)
 {
-    u32 pid = bpf_get_current_pid_tgid();
+    u64 pid_tgid = bpf_get_current_pid_tgid();
+    u32 pid = pid_tgid >> 32;
+    u32 tid = (u32)pid_tgid;
+
     PID_FILTER
     SIGNAL_FILTER
 
@@ -73,7 +76,7 @@ int syscall__kill(struct pt_regs *ctx, int tpid, int sig)
     if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
         val.tpid = tpid;
         val.sig = sig;
-        infotmp.update(&pid, &val);
+        infotmp.update(&tid, &val);
     }
 
     return 0;
@@ -83,9 +86,11 @@ int do_ret_sys_kill(struct pt_regs *ctx)
 {
     struct data_t data = {};
     struct val_t *valp;
-    u32 pid = bpf_get_current_pid_tgid();
+    u64 pid_tgid = bpf_get_current_pid_tgid();
+    u32 pid = pid_tgid >> 32;
+    u32 tid = (u32)pid_tgid;
 
-    valp = infotmp.lookup(&pid);
+    valp = infotmp.lookup(&tid);
     if (valp == 0) {
         // missed entry
         return 0;
@@ -98,7 +103,7 @@ int do_ret_sys_kill(struct pt_regs *ctx)
     data.sig = valp->sig;
 
     events.perf_submit(ctx, &data, sizeof(data));
-    infotmp.delete(&pid);
+    infotmp.delete(&tid);
 
     return 0;
 }
index 7b7bc47ad023e60dcb7a74349e2e428744296d6e..4f1ba2f9a88ab65d87b885797e75fd6d5d6e965c 100755 (executable)
@@ -50,7 +50,7 @@ BPF_HASH(miss_count, struct key_t);
 
 static inline __attribute__((always_inline)) void get_key(struct key_t* key) {
     key->cpu = bpf_get_smp_processor_id();
-    key->pid = bpf_get_current_pid_tgid();
+    key->pid = bpf_get_current_pid_tgid() >> 32;
     bpf_get_current_comm(&(key->name), sizeof(key->name));
 }
 
index 2abe15cfcd5b8b16d5ed4cb788f0ccd167837447..8a23520b72ccbf48afa17e6567c328e7d4dcc6cd 100755 (executable)
@@ -32,7 +32,7 @@ BPF_PERF_OUTPUT(events);
 int kprobe__md_flush_request(struct pt_regs *ctx, void *mddev, struct bio *bio)
 {
     struct data_t data = {};
-    u32 pid = bpf_get_current_pid_tgid();
+    u32 pid = bpf_get_current_pid_tgid() >> 32;
     data.pid = pid;
     bpf_get_current_comm(&data.comm, sizeof(data.comm));
 /*
index 33ea7ddd1f6e851a2df9b369c66aa7136fea4791..088cd6326ef1c25ce35e525d1678ab11fc47c35d 100755 (executable)
@@ -58,19 +58,21 @@ BPF_HASH(start_tmp, u32, struct start_t);
 BPF_PERF_OUTPUT(events);
 
 int do_start(struct pt_regs *ctx) {
-    u32 pid = bpf_get_current_pid_tgid();
+    u32 tid = bpf_get_current_pid_tgid();
     struct start_t start = {};
     start.ts = bpf_ktime_get_ns();
     bpf_usdt_readarg(1, ctx, &start.query);
-    start_tmp.update(&pid, &start);
+    start_tmp.update(&tid, &start);
     return 0;
 };
 
 int do_done(struct pt_regs *ctx) {
-    u32 pid = bpf_get_current_pid_tgid();
+    u64 pid_tgid = bpf_get_current_pid_tgid();
+    u32 pid = pid_tgid >> 32;
+    u32 tid = (u32)pid_tgid;
     struct start_t *sp;
 
-    sp = start_tmp.lookup(&pid);
+    sp = start_tmp.lookup(&tid);
     if (sp == 0) {
         // missed tracing start
         return 0;
@@ -85,7 +87,7 @@ int do_done(struct pt_regs *ctx) {
         events.perf_submit(ctx, &data, sizeof(data));
     }
 
-    start_tmp.delete(&pid);
+    start_tmp.delete(&tid);
 
     return 0;
 };
index 0723f8af5904eb07cf7350885762468ad82c2411..531030bbe3c896bbec1cefa36ed410d72e337ea5 100755 (executable)
@@ -103,7 +103,9 @@ BPF_HASH(start, u32);
 BPF_STACK_TRACE(stack_traces, STACK_STORAGE_SIZE);
 
 static int offcpu_sched_switch() {
-    u32 pid = bpf_get_current_pid_tgid();
+    u64 pid_tgid = bpf_get_current_pid_tgid();
+    u32 pid = pid_tgid >> 32;
+    u32 tid = (u32)pid_tgid;
     struct task_struct *p = (struct task_struct *) bpf_get_current_task();
     u64 ts;
 
@@ -111,18 +113,19 @@ static int offcpu_sched_switch() {
         return 0;
 
     ts = bpf_ktime_get_ns();
-    start.update(&pid, &ts);
+    start.update(&tid, &ts);
     return 0;
 }
 
 static int wakeup(ARG0, struct task_struct *p) {
-    u32 pid = p->pid;
+    u32 pid = p->tgid;
+    u32 tid = p->pid;
     u64 delta, *tsp, ts;
 
-    tsp = start.lookup(&pid);
+    tsp = start.lookup(&tid);
     if (tsp == 0)
         return 0;        // missed start
-    start.delete(&pid);
+    start.delete(&tid);
 
     if (FILTER)
         return 0;