Skip to content

Commit

Permalink
libbpf-tools: make some minor refactoring
Browse files Browse the repository at this point in the history
Signed-off-by: Wenbo Zhang <[email protected]>
  • Loading branch information
ethercflow authored and yonghong-song committed Oct 1, 2020
1 parent 87792ce commit 73cf23b
Show file tree
Hide file tree
Showing 40 changed files with 319 additions and 262 deletions.
50 changes: 22 additions & 28 deletions libbpf-tools/biolatency.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
#include "biolatency.h"
#include "bits.bpf.h"

#define MAX_ENTRIES 10240
#define MAX_ENTRIES 10240

const volatile char targ_disk[DISK_NAME_LEN] = {};
const volatile bool targ_per_disk = false;
const volatile bool targ_per_flag = false;
const volatile bool targ_queued = false;
const volatile bool targ_ms = false;
const volatile dev_t targ_dev = -1;

struct {
__uint(type, BPF_MAP_TYPE_HASH);
Expand All @@ -33,50 +33,41 @@ struct {
__uint(map_flags, BPF_F_NO_PREALLOC);
} hists SEC(".maps");

static __always_inline bool disk_filtered(const char *disk)
{
int i;

for (i = 0; targ_disk[i] != '\0' && i < DISK_NAME_LEN; i++) {
if (disk[i] != targ_disk[i])
return false;
}
return true;
}

static __always_inline
int trace_rq_start(struct request *rq)
{
u64 ts = bpf_ktime_get_ns();
char disk[DISK_NAME_LEN];

bpf_probe_read_kernel_str(&disk, sizeof(disk), rq->rq_disk->disk_name);
if (!disk_filtered(disk))
return 0;
if (targ_dev != -1) {
struct gendisk *disk = BPF_CORE_READ(rq, rq_disk);
dev_t dev;

dev = disk ? MKDEV(BPF_CORE_READ(disk, major),
BPF_CORE_READ(disk, first_minor)) : 0;
if (targ_dev != dev)
return 0;
}
bpf_map_update_elem(&start, &rq, &ts, 0);
return 0;
}

SEC("tp_btf/block_rq_insert")
int BPF_PROG(tp_btf__block_rq_insert, struct request_queue *q,
struct request *rq)
int BPF_PROG(block_rq_insert, struct request_queue *q, struct request *rq)
{
return trace_rq_start(rq);
}

SEC("tp_btf/block_rq_issue")
int BPF_PROG(tp_btf__block_rq_issue, struct request_queue *q,
struct request *rq)
int BPF_PROG(block_rq_issue, struct request_queue *q, struct request *rq)
{
if (targ_queued && BPF_CORE_READ(q, elevator))
return 0;
return trace_rq_start(rq);
}

SEC("tp_btf/block_rq_complete")
int BPF_PROG(tp_btf__block_rq_complete, struct request *rq, int error,
unsigned int nr_bytes)
int BPF_PROG(block_rq_complete, struct request *rq, int error,
unsigned int nr_bytes)
{
u64 slot, *tsp, ts = bpf_ktime_get_ns();
struct hist_key hkey = {};
Expand All @@ -90,9 +81,12 @@ int BPF_PROG(tp_btf__block_rq_complete, struct request *rq, int error,
if (delta < 0)
goto cleanup;

if (targ_per_disk)
bpf_probe_read_kernel_str(&hkey.disk, sizeof(hkey.disk),
rq->rq_disk->disk_name);
if (targ_per_disk) {
struct gendisk *disk = BPF_CORE_READ(rq, rq_disk);

hkey.dev = disk ? MKDEV(BPF_CORE_READ(disk, major),
BPF_CORE_READ(disk, first_minor)) : 0;
}
if (targ_per_flag)
hkey.cmd_flags = rq->cmd_flags;

Expand All @@ -105,9 +99,9 @@ int BPF_PROG(tp_btf__block_rq_complete, struct request *rq, int error,
}

if (targ_ms)
delta /= 1000000;
delta /= 1000000U;
else
delta /= 1000;
delta /= 1000U;
slot = log2l(delta);
if (slot >= MAX_SLOTS)
slot = MAX_SLOTS - 1;
Expand Down
93 changes: 55 additions & 38 deletions libbpf-tools/biolatency.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

static struct env {
char *disk;
int disk_len;
time_t interval;
int times;
bool timestamp;
Expand All @@ -37,23 +36,22 @@ static struct env {
static volatile bool exiting;

const char *argp_program_version = "biolatency 0.1";
const char *argp_program_bug_address = "<[email protected]>";
const char *argp_program_bug_address = "<[email protected]>";
const char argp_program_doc[] =
"Summarize block device I/O latency as a histogram.\n"
"\n"
"USAGE: biolatency [-h] [-T] [-m] [-Q] [-D] [-F] [-d] [interval] [count]\n"
"\n"
"EXAMPLES:\n"
" biolatency # summarize block I/O latency as a histogram\n"
" biolatency 1 10 # print 1 second summaries, 10 times\n"
" biolatency -mT 1 # 1s summaries, milliseconds, and timestamps\n"
" biolatency -Q # include OS queued time in I/O time\n"
" biolatency -D # show each disk device separately\n"
" biolatency -F # show I/O flags separately\n"
" biolatency -d sdc # Trace sdc only\n";
"Summarize block device I/O latency as a histogram.\n"
"\n"
"USAGE: biolatency [--help] [-T] [-m] [-Q] [-D] [-F] [-d] [interval] [count]\n"
"\n"
"EXAMPLES:\n"
" biolatency # summarize block I/O latency as a histogram\n"
" biolatency 1 10 # print 1 second summaries, 10 times\n"
" biolatency -mT 1 # 1s summaries, milliseconds, and timestamps\n"
" biolatency -Q # include OS queued time in I/O time\n"
" biolatency -D # show each disk device separately\n"
" biolatency -F # show I/O flags separately\n"
" biolatency -d sdc # Trace sdc only\n";

static const struct argp_option opts[] = {
{ NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help" },
{ "timestamp", 'T', NULL, 0, "Include timestamp on output" },
{ "milliseconds", 'm', NULL, 0, "Millisecond histogram" },
{ "queued", 'Q', NULL, 0, "Include OS queued time in I/O time" },
Expand All @@ -72,9 +70,6 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
case 'v':
env.verbose = true;
break;
case 'h':
argp_usage(state);
break;
case 'm':
env.milliseconds = true;
break;
Expand All @@ -87,10 +82,12 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
case 'F':
env.per_flag = true;
break;
case 'T':
env.timestamp = true;
break;
case 'd':
env.disk = arg;
env.disk_len = strlen(arg) + 1;
if (env.disk_len > DISK_NAME_LEN) {
if (strlen(arg) + 1 > DISK_NAME_LEN) {
fprintf(stderr, "invaild disk name: too long\n");
argp_usage(state);
}
Expand Down Expand Up @@ -183,22 +180,27 @@ static void print_cmd_flags(int cmd_flags)
printf("Unknown");
}

static int print_log2_hists(int fd)
static
int print_log2_hists(struct bpf_map *hists, struct partitions *partitions)
{
struct hist_key lookup_key = { .cmd_flags = -1 }, next_key;
char *units = env.milliseconds ? "msecs" : "usecs";
const char *units = env.milliseconds ? "msecs" : "usecs";
const struct partition *partition;
int err, fd = bpf_map__fd(hists);
struct hist hist;
int err;

while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
err = bpf_map_lookup_elem(fd, &next_key, &hist);
if (err < 0) {
fprintf(stderr, "failed to lookup hist: %d\n", err);
return -1;
}
if (env.per_disk)
printf("\ndisk = %s\t", next_key.disk[0] != '\0' ?
next_key.disk : "unnamed");
if (env.per_disk) {
partition = partitions__get_by_dev(partitions,
next_key.dev);
printf("\ndisk = %s\t", partition ? partition->name :
"Unknown");
}
if (env.per_flag)
print_cmd_flags(next_key.cmd_flags);
printf("\n");
Expand All @@ -221,6 +223,8 @@ static int print_log2_hists(int fd)

int main(int argc, char **argv)
{
struct partitions *partitions = NULL;
const struct partition *partition;
static const struct argp argp = {
.options = opts,
.parser = parse_arg,
Expand Down Expand Up @@ -250,9 +254,21 @@ int main(int argc, char **argv)
return 1;
}

partitions = partitions__load();
if (!partitions) {
fprintf(stderr, "failed to load partitions info\n");
goto cleanup;
}

/* initialize global data (filtering options) */
if (env.disk)
strncpy((char*)obj->rodata->targ_disk, env.disk, env.disk_len);
if (env.disk) {
partition = partitions__get_by_name(partitions, env.disk);
if (!partition) {
fprintf(stderr, "invaild partition name: not exist\n");
goto cleanup;
}
obj->rodata->targ_dev = partition->dev;
}
obj->rodata->targ_per_disk = env.per_disk;
obj->rodata->targ_per_flag = env.per_flag;
obj->rodata->targ_ms = env.milliseconds;
Expand All @@ -265,24 +281,24 @@ int main(int argc, char **argv)
}

if (env.queued) {
obj->links.tp_btf__block_rq_insert =
bpf_program__attach(obj->progs.tp_btf__block_rq_insert);
err = libbpf_get_error(obj->links.tp_btf__block_rq_insert);
obj->links.block_rq_insert =
bpf_program__attach(obj->progs.block_rq_insert);
err = libbpf_get_error(obj->links.block_rq_insert);
if (err) {
fprintf(stderr, "failed to attach: %s\n", strerror(-err));
goto cleanup;
}
}
obj->links.tp_btf__block_rq_issue =
bpf_program__attach(obj->progs.tp_btf__block_rq_issue);
err = libbpf_get_error(obj->links.tp_btf__block_rq_issue);
obj->links.block_rq_issue =
bpf_program__attach(obj->progs.block_rq_issue);
err = libbpf_get_error(obj->links.block_rq_issue);
if (err) {
fprintf(stderr, "failed to attach: %s\n", strerror(-err));
goto cleanup;
}
obj->links.tp_btf__block_rq_complete =
bpf_program__attach(obj->progs.tp_btf__block_rq_complete);
err = libbpf_get_error(obj->links.tp_btf__block_rq_complete);
obj->links.block_rq_complete =
bpf_program__attach(obj->progs.block_rq_complete);
err = libbpf_get_error(obj->links.block_rq_complete);
if (err) {
fprintf(stderr, "failed to attach: %s\n", strerror(-err));
goto cleanup;
Expand All @@ -304,7 +320,7 @@ int main(int argc, char **argv)
printf("%-8s\n", ts);
}

err = print_log2_hists(bpf_map__fd(obj->maps.hists));
err = print_log2_hists(obj->maps.hists, partitions);
if (err)
break;

Expand All @@ -314,6 +330,7 @@ int main(int argc, char **argv)

cleanup:
biolatency_bpf__destroy(obj);
partitions__free(partitions);

return err != 0;
}
7 changes: 6 additions & 1 deletion libbpf-tools/biolatency.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
#define DISK_NAME_LEN 32
#define MAX_SLOTS 27

#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)

#define MKDEV(ma, mi) (((ma) << MINORBITS) | (mi))

struct hist_key {
char disk[DISK_NAME_LEN];
__u32 cmd_flags;
__u32 dev;
};

struct hist {
Expand Down
2 changes: 1 addition & 1 deletion libbpf-tools/biopattern.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct {
} counters SEC(".maps");

SEC("tracepoint/block/block_rq_complete")
int tp__block__block_rq_complete(struct trace_event_raw_block_rq_complete *ctx)
int handle__block_rq_complete(struct trace_event_raw_block_rq_complete *ctx)
{
sector_t *last_sectorp, sector = ctx->sector;
struct counter *counterp, zero = {};
Expand Down
Loading

0 comments on commit 73cf23b

Please sign in to comment.