Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
102 changes: 54 additions & 48 deletions tools/biolatency.py
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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.")
Expand Down
86 changes: 45 additions & 41 deletions tools/biosnoop.py
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand All @@ -296,6 +289,7 @@
return __trace_req_completion(args, key);
}
"""

if args.queue:
bpf_text = bpf_text.replace('##QUEUE##', '1')
else:
Expand Down Expand Up @@ -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
Expand Down
81 changes: 42 additions & 39 deletions tools/biotop.py
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand All @@ -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',
Expand Down
Loading