From ee5f823ae535a699f8326e4d55e2071ca62915cb Mon Sep 17 00:00:00 2001 From: mcaleavya Date: Fri, 12 Feb 2016 20:06:38 +0000 Subject: [PATCH] added new files for biosnoop and bashreadline --- tools/bashreadline.py | 40 +++++++++++++----- tools/biosnoop.py | 109 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 104 insertions(+), 45 deletions(-) diff --git a/tools/bashreadline.py b/tools/bashreadline.py index 464dfda..984970a 100755 --- a/tools/bashreadline.py +++ b/tools/bashreadline.py @@ -9,35 +9,55 @@ # Licensed under the Apache License, Version 2.0 (the "License") # # 28-Jan-2016 Brendan Gregg Created this. +# 12-Feb-2016 Allan McAleavy migrated to BPF_PERF_OUTPUT from __future__ import print_function from bcc import BPF from time import strftime +import ctypes as ct # load BPF program bpf_text = """ #include + +struct str_t { + u64 pid; + char str[80]; +}; + +BPF_PERF_OUTPUT(events); + int printret(struct pt_regs *ctx) { + struct str_t data = {}; + u32 pid; if (!ctx->ax) return 0; - - char str[80] = {}; - bpf_probe_read(&str, sizeof(str), (void *)ctx->ax); - bpf_trace_printk("%s\\n", &str); + pid = bpf_get_current_pid_tgid(); + data.pid = pid; + bpf_probe_read(&data.str, sizeof(data.str), (void *)ctx->ax); + events.perf_submit(ctx,&data,sizeof(data)); return 0; }; """ +STR_DATA = 80 + +class Data(ct.Structure): + _fields_ = [ + ("pid", ct.c_ulonglong), + ("str", ct.c_char * STR_DATA) + ] + b = BPF(text=bpf_text) b.attach_uretprobe(name="/bin/bash", sym="readline", fn_name="printret") # header print("%-9s %-6s %s" % ("TIME", "PID", "COMMAND")) -# format output +def print_event(cpu, data, size): + event = ct.cast(data, ct.POINTER(Data)).contents + print("%-9s %-6d %s" % (strftime("%H:%M:%S"), event.pid, event.str)) + +b["events"].open_perf_buffer(print_event) while 1: - try: - (task, pid, cpu, flags, ts, msg) = b.trace_fields() - except ValueError: - continue - print("%-9s %-6d %s" % (strftime("%H:%M:%S"), pid, msg)) + b.kprobe_poll() diff --git a/tools/biosnoop.py b/tools/biosnoop.py index 37ee3f9..21f74c5 100755 --- a/tools/biosnoop.py +++ b/tools/biosnoop.py @@ -11,9 +11,13 @@ # Licensed under the Apache License, Version 2.0 (the "License") # # 16-Sep-2015 Brendan Gregg Created this. +# 11-Feb-2016 Allan McAleavy updated for BPF_PERF_OUTPUT + from __future__ import print_function from bcc import BPF +import ctypes as ct +import re # load BPF program b = BPF(text=""" @@ -25,8 +29,21 @@ struct val_t { char name[TASK_COMM_LEN]; }; +struct key_t { + u32 pid; + u64 rwflag; + u64 delta; + u64 sector; + u64 len; + u64 ts; + char disk_name[DISK_NAME_LEN]; + char name[TASK_COMM_LEN]; +}; + + BPF_HASH(start, struct request *); BPF_HASH(infobyreq, struct request *, struct val_t); +BPF_PERF_OUTPUT(events); // cache PID and comm by-req int trace_pid_start(struct pt_regs *ctx, struct request *req) @@ -37,7 +54,6 @@ int trace_pid_start(struct pt_regs *ctx, struct request *req) val.pid = bpf_get_current_pid_tgid(); infobyreq.update(&req, &val); } - return 0; } @@ -58,6 +74,8 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req) u64 *tsp, delta; u32 *pidp = 0; struct val_t *valp; + struct key_t key ={}; + u64 ts; // fetch timestamp and calculate delta tsp = start.lookup(&req); @@ -65,30 +83,29 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req) // missed tracing issue return 0; } - delta = bpf_ktime_get_ns() - *tsp; + ts = bpf_ktime_get_ns(); + key.delta = ts - *tsp; + key.ts = ts / 1000; - // - // Fetch and output issuing pid and comm. - // As bpf_trace_prink() is limited to a maximum of 1 string and 2 - // integers, we'll use more than one to output the data. - // valp = infobyreq.lookup(&req); if (valp == 0) { - bpf_trace_printk("0 0 ? %d\\n", req->__data_len); + key.len = req->__data_len; + strcpy(key.name,"?"); } else { - bpf_trace_printk("0 %d %s %d\\n", valp->pid, valp->name, - req->__data_len); + key.pid = valp->pid; + key.len = req->__data_len; + key.sector = req->__sector; + bpf_probe_read(&key.name, sizeof(key.name), valp->name); + bpf_probe_read(&key.disk_name, sizeof(key.disk_name), + req->rq_disk->disk_name); } - // output remaining details if (req->cmd_flags & REQ_WRITE) { - bpf_trace_printk("1 W %s %d %d ?\\n", req->rq_disk->disk_name, - req->__sector, delta / 1000); + key.rwflag=1; } else { - bpf_trace_printk("1 R %s %d %d ?\\n", req->rq_disk->disk_name, - req->__sector, delta / 1000); + key.rwflag=0; } - + events.perf_submit(ctx,&key,sizeof(key)); start.delete(&req); infobyreq.delete(&req); @@ -101,29 +118,51 @@ b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start") b.attach_kprobe(event="blk_account_io_completion", fn_name="trace_req_completion") + +TASK_COMM_LEN = 16 # linux/sched.h +DISK_NAME_LEN = 32 # linux/genhd.h + +class Data(ct.Structure): + _fields_ = [ + ("pid", ct.c_ulonglong), + ("rwflag", ct.c_ulonglong), + ("delta", ct.c_ulonglong), + ("sector", ct.c_ulonglong), + ("len", ct.c_ulonglong), + ("ts", ct.c_ulonglong), + ("disk_name", ct.c_char * DISK_NAME_LEN), + ("name", ct.c_char * TASK_COMM_LEN) + ] # header print("%-14s %-14s %-6s %-7s %-2s %-9s %-7s %7s" % ("TIME(s)", "COMM", "PID", "DISK", "T", "SECTOR", "BYTES", "LAT(ms)")) +rwflg = "" start_ts = 0 - -# format output -while 1: - (task, pid, cpu, flags, ts, msg) = b.trace_fields() - args = msg.split(" ") - +prev_ts = 0 +delta = 0 +# process event +def print_event(cpu, data, size): + event = ct.cast(data, ct.POINTER(Data)).contents + val = -1 + global start_ts + global prev_ts + global delta + if event.rwflag == 1: + rwflg = "W" + if event.rwflag == 0: + rwflg = "R" + if not re.match('\?', event.name): + val = event.sector if start_ts == 0: - start_ts = ts - - if args[0] == "0": - (real_pid, real_comm, bytes_s) = (args[1], args[2], args[3]) - continue - else: - (type_s, disk_s, sector_s, us_s) = (args[1], args[2], args[3], - args[4]) - - ms = float(int(us_s, 10)) / 1000 - + prev_ts = start_ts + if start_ts == 1: + delta = float(delta) + (event.ts - prev_ts) print("%-14.9f %-14.14s %-6s %-7s %-2s %-9s %-7s %7.2f" % ( - ts - start_ts, real_comm, real_pid, disk_s, type_s, sector_s, - bytes_s, ms)) + delta / 1000000, event.name, event.pid, event.disk_name, rwflg, val, + event.len, float(event.delta) / 1000000)) + prev_ts = event.ts + start_ts = 1 +b["events"].open_perf_buffer(print_event) +while 1: + b.kprobe_poll() -- 2.7.4