diff --git a/bcc-0.34.0-RHEL-Centos-tools-fix-alignment-in-tp_args-for-bio-t.patch b/bcc-0.34.0-RHEL-Centos-tools-fix-alignment-in-tp_args-for-bio-t.patch deleted file mode 100644 index aa03d05..0000000 --- a/bcc-0.34.0-RHEL-Centos-tools-fix-alignment-in-tp_args-for-bio-t.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 8a9da1d866dfb69ad1ca59bdc50a799ba2da3a0c Mon Sep 17 00:00:00 2001 -From: Jerome Marchand -Date: Thu, 24 Oct 2024 16:56:14 +0200 -Subject: [PATCH] RHEL/Centos: tools: fix alignment in tp_args for bio tools - -The padding in tp_args is wrong on RHEL 9 / c9s kernel because of the -kernel commit 6bc27040eb90 ("sched: Add support for lazy preemption") -which added a common field to tracepoints. - -Now the dev field is at an offset of 12 bytes as shown by -block_io_start/done format file. - -Signed-off-by: Jerome Marchand ---- - tools/biolatency.py | 2 +- - tools/biosnoop.py | 2 +- - tools/biotop.py | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/tools/biolatency.py b/tools/biolatency.py -index 03b48a4c..ac150ea2 100755 ---- a/tools/biolatency.py -+++ b/tools/biolatency.py -@@ -88,7 +88,7 @@ typedef struct ext_val { - } ext_val_t; - - struct tp_args { -- u64 __unused__; -+ u32 __unused__[3]; - dev_t dev; - sector_t sector; - unsigned int nr_sector; -diff --git a/tools/biosnoop.py b/tools/biosnoop.py -index f0fef98b..819e953f 100755 ---- a/tools/biosnoop.py -+++ b/tools/biosnoop.py -@@ -66,7 +66,7 @@ struct val_t { - }; - - struct tp_args { -- u64 __unused__; -+ u32 __unused__[3]; - dev_t dev; - sector_t sector; - unsigned int nr_sector; -diff --git a/tools/biotop.py b/tools/biotop.py -index 879c6b8f..4c3a1c9a 100755 ---- a/tools/biotop.py -+++ b/tools/biotop.py -@@ -91,7 +91,7 @@ struct val_t { - }; - - struct tp_args { -- u64 __unused__; -+ u32 __unused__[3]; - dev_t dev; - sector_t sector; - unsigned int nr_sector; --- -2.47.0 - diff --git a/bcc-0.34.0-tools-biolatency-biosnoop-biotop-use-TRACEPOINT_PROB.patch b/bcc-0.34.0-tools-biolatency-biosnoop-biotop-use-TRACEPOINT_PROB.patch new file mode 100644 index 0000000..87a8398 --- /dev/null +++ b/bcc-0.34.0-tools-biolatency-biosnoop-biotop-use-TRACEPOINT_PROB.patch @@ -0,0 +1,425 @@ +From cdd2ade85acd05c8c7af17b0802163ad6fcb8ec7 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Tue, 15 Jul 2025 02:25:38 +0200 +Subject: [PATCH] tools/{biolatency,biosnoop,biotop}: use TRACEPOINT_PROBE() + for tracepoints (#5366) + +When support for block_io_* tracepoint was added, it used +attach_tracepoint() since it was closer to the existing code that +attached to kprobes. However, that meant we have to rely on a local +prototype of the args structure and the tool can be broken by a +change of the tracepoints format, which is what happens with kernel +commit aa6ff4eb7c10d ("block: Add ioprio to block_rq tracepoint") +which added a new argument to block tracepoints. + +Replace attach_tracepoint() by TRACEPOINT_PROBE() so we don't have to +deal with the tracepoint format changes. + +Signed-off-by: Jerome Marchand +--- + tools/biolatency.py | 102 +++++++++++++++++++++++--------------------- + tools/biosnoop.py | 86 +++++++++++++++++++------------------ + tools/biotop.py | 81 ++++++++++++++++++----------------- + 3 files changed, 141 insertions(+), 128 deletions(-) + +diff --git a/tools/biolatency.py b/tools/biolatency.py +index 3ba1b237..1d3f2d80 100755 +--- a/tools/biolatency.py ++++ b/tools/biolatency.py +@@ -87,17 +87,6 @@ typedef struct ext_val { + 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 @@ int trace_req_start(struct pt_regs *ctx, struct request *req) + 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 @@ int trace_req_done(struct pt_regs *ctx, struct request *req) + + 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 @@ bpf_text = bpf_text.replace("STORE", store_str) + 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 045e1f9d..65df90c3 100755 +--- a/tools/biosnoop.py ++++ b/tools/biosnoop.py +@@ -65,17 +65,6 @@ struct val_t { + 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 @@ int trace_pid_start(struct pt_regs *ctx, struct request *req) + 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 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req) + + 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 @@ int trace_req_completion_tp(struct tp_args *args) + return __trace_req_completion(args, key); + } + """ ++ + if args.queue: + bpf_text = bpf_text.replace('##QUEUE##', '1') + else: +@@ -329,31 +323,41 @@ int trace_req_completion_tp(struct tp_args *args) + 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 480c37a4..4281b742 100755 +--- a/tools/biotop.py ++++ b/tools/biotop.py +@@ -90,17 +90,6 @@ struct val_t { + 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 @@ int trace_pid_start(struct pt_regs *ctx, struct request *req) + 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 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req) + + 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 @@ int trace_req_completion_tp(struct tp_args *args) + 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', +-- +2.50.1 + diff --git a/bcc.spec b/bcc.spec index 7f6240e..0cfd548 100644 --- a/bcc.spec +++ b/bcc.spec @@ -25,15 +25,15 @@ Name: bcc Version: 0.34.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: BPF Compiler Collection (BCC) License: Apache-2.0 URL: https://github.com/iovisor/bcc Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz Patch0: %%{name}-%%{version}-Revert-Fix-bashreadline-4903.patch -Patch1: %%{name}-%%{version}-RHEL-Centos-tools-fix-alignment-in-tp_args-for-bio-t.patch -Patch2: %%{name}-%%{version}-tools-biosnoop-Fix-biosnoop-pattern-option-5304.patch -Patch3: %%{name}-%%{version}-clang-Define-DCONFIG_CC_IS_CLANG-in-KBuildHelper-get.patch +Patch1: %%{name}-%%{version}-tools-biosnoop-Fix-biosnoop-pattern-option-5304.patch +Patch2: %%{name}-%%{version}-clang-Define-DCONFIG_CC_IS_CLANG-in-KBuildHelper-get.patch +Patch3: %%{name}-%%{version}-tools-biolatency-biosnoop-biotop-use-TRACEPOINT_PROB.patch # Arches will be included as upstream support is added and dependencies are # satisfied in the respective arches @@ -266,6 +266,9 @@ cp -a libbpf-tools/tmp-install/bin/* %{buildroot}/%{_sbindir}/ %endif %changelog +* Mon Jul 28 2025 Jerome Marchand - 0.34.0-2 +- Fix bio* tools tracepoints (RHEL-99677) + * Mon May 19 2025 Jerome Marchand - 0.34.0-1 - Rebase to the latest version (RHEL-78921) - Rebuild with LLVM 20 (RHEL-81772)