diff --git a/tools/biolatency.py b/tools/biolatency.py index 3ba1b237dd5d..1d3f2d8032c5 100755 --- a/tools/biolatency.py +++ b/tools/biolatency.py @@ -87,17 +87,6 @@ u64 count; } ext_val_t; -struct tp_args { - u64 __unused__; - dev_t dev; - sector_t sector; - unsigned int nr_sector; - unsigned int bytes; - char rwbs[8]; - char comm[16]; - char cmd[]; -}; - struct start_key { dev_t dev; u32 _pad; @@ -134,16 +123,6 @@ return __trace_req_start(key); } -int trace_req_start_tp(struct tp_args *args) -{ - struct start_key key = { - .dev = args->dev, - .sector = args->sector - }; - - return __trace_req_start(key); -} - // output static int __trace_req_done(struct start_key key) { @@ -176,8 +155,22 @@ return __trace_req_done(key); } +""" + +tp_start_text = """ +TRACEPOINT_PROBE(block, START_TP) +{ + struct start_key key = { + .dev = args->dev, + .sector = args->sector + }; + + return __trace_req_start(key); +} +""" -int trace_req_done_tp(struct tp_args *args) +tp_done_text = """ +TRACEPOINT_PROBE(block, DONE_TP) { struct start_key key = { .dev = args->dev, @@ -266,41 +259,54 @@ if args.ebpf: exit() -# load BPF program -b = BPF(text=bpf_text) +# Which kprobe/tracepoint to attach to. +# We can attach to two IO start kprobes but only one of the other types. +kprobe_start = set() +tp_start = None +kprobe_done = None +tp_done = None + if args.queued: - if BPF.tracepoint_exists("block", "block_io_start"): - b.attach_tracepoint(tp="block:block_io_start", fn_name="trace_req_start_tp") - elif BPF.get_kprobe_functions(b'__blk_account_io_start'): - b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_req_start") + if BPF.get_kprobe_functions(b'__blk_account_io_start'): + kprobe_start.add("__blk_account_io_start") elif BPF.get_kprobe_functions(b'blk_account_io_start'): - b.attach_kprobe(event="blk_account_io_start", fn_name="trace_req_start") + kprobe_start.add("blk_account_io_start") + elif BPF.tracepoint_exists("block", "block_io_start"): + tp_start = "block_io_start" elif BPF.tracepoint_exists("block", "block_bio_queue"): - b.attach_tracepoint(tp="block:block_bio_queue", fn_name="trace_req_start_tp") - else: - if args.flags: - # Some flags are accessible in the rwbs field (RAHEAD, SYNC and META) - # but other aren't. Disable the -F option for tracepoint for now. - print("ERROR: blk_account_io_start probe not available. Can't use -F.") - exit() + tp_start = "block_bio_queue" + else: if BPF.get_kprobe_functions(b'blk_start_request'): - b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start") - b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start") + kprobe_start.add("blk_start_request") + kprobe_start.add("blk_mq_start_request") -if BPF.tracepoint_exists("block", "block_io_done"): - b.attach_tracepoint(tp="block:block_io_done", fn_name="trace_req_done_tp") -elif BPF.get_kprobe_functions(b'__blk_account_io_done'): - b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_done") +if BPF.get_kprobe_functions(b'__blk_account_io_done'): + kprobe_done = "__blk_account_io_done" elif BPF.get_kprobe_functions(b'blk_account_io_done'): - b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_done") + kprobe_done = "blk_account_io_done" +elif BPF.tracepoint_exists("block", "block_io_done"): + tp_done = "block_io_done" elif BPF.tracepoint_exists("block", "block_rq_complete"): - b.attach_tracepoint(tp="block:block_rq_complete", fn_name="trace_req_done_tp") -else: - if args.flags: - print("ERROR: blk_account_io_done probe not available. Can't use -F.") - exit() + tp_done = "block_rq_complete" + +if args.flags and (tp_start or tp_done): + # Some flags are accessible in the rwbs field (RAHEAD, SYNC and META) + # but other aren't. Disable the -F option for tracepoint for now. + print("ERROR: blk_account_io_start/done probes not available. Can't use -F.") + exit() + +if tp_start: + bpf_text += tp_start_text.replace("START_TP", tp_start) +if tp_done: + bpf_text += tp_done_text.replace("DONE_TP", tp_done) +# load BPF program +b = BPF(text=bpf_text) +for i in kprobe_start: + b.attach_kprobe(event=i, fn_name="trace_req_start") +if kprobe_done: + b.attach_kprobe(event=kprobe_done, fn_name="trace_req_done") if not args.json: print("Tracing block device I/O... Hit Ctrl-C to end.") diff --git a/tools/biosnoop.py b/tools/biosnoop.py index 045e1f9da58b..65df90c39d7d 100755 --- a/tools/biosnoop.py +++ b/tools/biosnoop.py @@ -65,17 +65,6 @@ char name[TASK_COMM_LEN]; }; -struct tp_args { - u64 __unused__; - dev_t dev; - sector_t sector; - unsigned int nr_sector; - unsigned int bytes; - char rwbs[8]; - char comm[16]; - char cmd[]; -}; - struct hash_key { dev_t dev; u32 rwflag; @@ -182,17 +171,6 @@ return __trace_pid_start(key); } -int trace_pid_start_tp(struct tp_args *args) -{ - struct hash_key key = { - .dev = args->dev, - .rwflag = get_rwflag_tp(args->rwbs), - .sector = args->sector - }; - - return __trace_pid_start(key); -} - // time block I/O int trace_req_start(struct pt_regs *ctx, struct request *req) { @@ -284,8 +262,23 @@ return __trace_req_completion(ctx, key); } +""" -int trace_req_completion_tp(struct tp_args *args) +tp_start_text = """ +TRACEPOINT_PROBE(block, block_io_start) +{ + struct hash_key key = { + .dev = args->dev, + .rwflag = get_rwflag_tp(args->rwbs), + .sector = args->sector + }; + + return __trace_pid_start(key); +} +""" + +tp_done_text = """ +TRACEPOINT_PROBE(block, block_io_done) { struct hash_key key = { .dev = args->dev, @@ -296,6 +289,7 @@ return __trace_req_completion(args, key); } """ + if args.queue: bpf_text = bpf_text.replace('##QUEUE##', '1') else: @@ -329,31 +323,41 @@ if args.ebpf: exit() -# initialize BPF -b = BPF(text=bpf_text) if BPF.tracepoint_exists("block", "block_io_start"): - b.attach_tracepoint(tp="block:block_io_start", fn_name="trace_pid_start_tp") -elif BPF.get_kprobe_functions(b'__blk_account_io_start'): - b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start") -elif BPF.get_kprobe_functions(b'blk_account_io_start'): - b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start") + bpf_text += tp_start_text + tp_start = True +else: + tp_start = False + +if BPF.tracepoint_exists("block", "block_io_done"): + bpf_text += tp_done_text + tp_done = True else: - print("ERROR: No found any block io start probe/tp.") - exit() + tp_done = False + +# initialize BPF +b = BPF(text=bpf_text) +if not tp_start: + if BPF.get_kprobe_functions(b'__blk_account_io_start'): + b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start") + elif BPF.get_kprobe_functions(b'blk_account_io_start'): + b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start") + else: + print("ERROR: No found any block io start probe/tp.") + exit() if BPF.get_kprobe_functions(b'blk_start_request'): b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start") b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start") -if BPF.tracepoint_exists("block", "block_io_done"): - b.attach_tracepoint(tp="block:block_io_done", fn_name="trace_req_completion_tp") -elif BPF.get_kprobe_functions(b'__blk_account_io_done'): - b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion") -elif BPF.get_kprobe_functions(b'blk_account_io_done'): - b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion") -else: - print("ERROR: No found any block io done probe/tp.") - exit() +if not tp_done: + if BPF.get_kprobe_functions(b'__blk_account_io_done'): + b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion") + elif BPF.get_kprobe_functions(b'blk_account_io_done'): + b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion") + else: + print("ERROR: No found any block io done probe/tp.") + exit() # header diff --git a/tools/biotop.py b/tools/biotop.py index 480c37a4a981..4281b7424396 100755 --- a/tools/biotop.py +++ b/tools/biotop.py @@ -90,17 +90,6 @@ u32 io; }; -struct tp_args { - u64 __unused__; - dev_t dev; - sector_t sector; - unsigned int nr_sector; - unsigned int bytes; - char rwbs[8]; - char comm[16]; - char cmd[]; -}; - struct hash_key { dev_t dev; u32 _pad; @@ -143,16 +132,6 @@ return __trace_pid_start(key); } -int trace_pid_start_tp(struct tp_args *args) -{ - struct hash_key key = { - .dev = args->dev, - .sector = args->sector - }; - - return __trace_pid_start(key); -} - // time block I/O int trace_req_start(struct pt_regs *ctx, struct request *req) { @@ -246,8 +225,22 @@ return __trace_req_completion(key); } +""" + +tp_start_text = """ +TRACEPOINT_PROBE(block, block_io_start) +{ + struct hash_key key = { + .dev = args->dev, + .sector = args->sector + }; + + return __trace_pid_start(key); +} +""" -int trace_req_completion_tp(struct tp_args *args) +tp_done_text = """ +TRACEPOINT_PROBE(block, block_io_done) { struct hash_key key = { .dev = args->dev, @@ -272,30 +265,40 @@ else: bpf_text = bpf_text.replace('FILTER_PID', '0') -b = BPF(text=bpf_text) if BPF.tracepoint_exists("block", "block_io_start"): - b.attach_tracepoint(tp="block:block_io_start", fn_name="trace_pid_start_tp") -elif BPF.get_kprobe_functions(b'__blk_account_io_start'): - b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start") -elif BPF.get_kprobe_functions(b'blk_account_io_start'): - b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start") + bpf_text += tp_start_text + tp_start = True else: - print("ERROR: No found any block io start probe/tp.") - exit() + tp_start = False + +if BPF.tracepoint_exists("block", "block_io_done"): + bpf_text += tp_done_text + tp_done = True +else: + tp_done = False + +b = BPF(text=bpf_text) +if not tp_start: + if BPF.get_kprobe_functions(b'__blk_account_io_start'): + b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start") + elif BPF.get_kprobe_functions(b'blk_account_io_start'): + b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start") + else: + print("ERROR: No found any block io start probe/tp.") + exit() if BPF.get_kprobe_functions(b'blk_start_request'): b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start") b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start") -if BPF.tracepoint_exists("block", "block_io_done"): - b.attach_tracepoint(tp="block:block_io_done", fn_name="trace_req_completion_tp") -elif BPF.get_kprobe_functions(b'__blk_account_io_done'): - b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion") -elif BPF.get_kprobe_functions(b'blk_account_io_done'): - b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion") -else: - print("ERROR: No found any block io done probe/tp.") - exit() +if not tp_done: + if BPF.get_kprobe_functions(b'__blk_account_io_done'): + b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion") + elif BPF.get_kprobe_functions(b'blk_account_io_done'): + b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion") + else: + print("ERROR: No found any block io done probe/tp.") + exit() # check whether hash table batch ops is supported htab_batch_ops = True if BPF.kernel_struct_has_field(b'bpf_map_ops',