From be9a26d0aa9679590e27aec250c57076dd555860 Mon Sep 17 00:00:00 2001 From: wubijie Date: Mon, 26 Jun 2023 10:30:10 +0800 Subject: [PATCH] Parse the command-line arguments and set the appropriate environment variables --- observation/src/biopattern/biopattern.bpf.c | 61 +++++++++++ observation/src/biopattern/biopattern.c | 111 ++++++++++---------- 2 files changed, 118 insertions(+), 54 deletions(-) create mode 100644 observation/src/biopattern/biopattern.bpf.c diff --git a/observation/src/biopattern/biopattern.bpf.c b/observation/src/biopattern/biopattern.bpf.c new file mode 100644 index 00000000..8ab9567a --- /dev/null +++ b/observation/src/biopattern/biopattern.bpf.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "vmlinux.h" +#include +#include +#include +#include "biopattern.h" +#include "maps.bpf.h" +#include "core_fixes.bpf.h" + +const volatile bool filter_dev = false; +const volatile __u32 target_dev = 0; + +extern __u32 LINUX_KERNEL_VERSION __kconfig; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 64); + __type(key, u32); + __type(value, struct counter); +} counters SEC(".maps"); + +SEC("tracepoint/block/block_rq_complete") +int handle__block_rq_complete(void *args) +{ + struct counter *counterp, zero = {}; + sector_t sector; + u32 nr_sector; + u32 dev; + + if (LINUX_KERNEL_VERSION >= KERNEL_VERSION(5, 18, 0)) { + struct trace_event_raw_block_rq_completion___x *ctx = args; + + sector = BPF_CORE_READ(ctx, sector); + nr_sector = BPF_CORE_READ(ctx, nr_sector); + dev = BPF_CORE_READ(ctx, dev); + } else { + struct trace_event_raw_block_rq_complete___x *ctx = args; + + sector = BPF_CORE_READ(ctx, sector); + nr_sector = BPF_CORE_READ(ctx, nr_sector); + dev = BPF_CORE_READ(ctx, dev); + } + + if (filter_dev && target_dev != dev) + return 0; + + counterp = bpf_map_lookup_or_try_init(&counters, &dev, &zero); + if (!counterp) + return 0; + if (counterp->last_sector) { + if (counterp->last_sector == sector) + __sync_fetch_and_add(&counterp->sequential, 1); + else + __sync_fetch_and_add(&counterp->random, 1); + __sync_fetch_and_add(&counterp->bytes, nr_sector << 9); + } + counterp->last_sector = sector + nr_sector; + return 0; +} + +char LICENSE[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/observation/src/biopattern/biopattern.c b/observation/src/biopattern/biopattern.c index 8ab9567a..eab3c856 100644 --- a/observation/src/biopattern/biopattern.c +++ b/observation/src/biopattern/biopattern.c @@ -1,61 +1,64 @@ -// SPDX-License-Identifier: GPL-2.0 -#include "vmlinux.h" -#include -#include -#include +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +#include "commons.h" #include "biopattern.h" -#include "maps.bpf.h" -#include "core_fixes.bpf.h" +#include "biopattern.skel.h" +#include "btf_helpers.h" +#include "trace_helpers.h" -const volatile bool filter_dev = false; -const volatile __u32 target_dev = 0; +static struct env { + char *disk; + time_t interval; + bool timestamp; + bool verbose; + int times; +} env = { + .interval = 99999999, + .times = 99999999, +}; -extern __u32 LINUX_KERNEL_VERSION __kconfig; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 64); - __type(key, u32); - __type(value, struct counter); -} counters SEC(".maps"); - -SEC("tracepoint/block/block_rq_complete") -int handle__block_rq_complete(void *args) +static error_t parse_arg(int key, char *arg, struct argp_state *state) { - struct counter *counterp, zero = {}; - sector_t sector; - u32 nr_sector; - u32 dev; - - if (LINUX_KERNEL_VERSION >= KERNEL_VERSION(5, 18, 0)) { - struct trace_event_raw_block_rq_completion___x *ctx = args; - - sector = BPF_CORE_READ(ctx, sector); - nr_sector = BPF_CORE_READ(ctx, nr_sector); - dev = BPF_CORE_READ(ctx, dev); - } else { - struct trace_event_raw_block_rq_complete___x *ctx = args; + static int pos_args; - sector = BPF_CORE_READ(ctx, sector); - nr_sector = BPF_CORE_READ(ctx, nr_sector); - dev = BPF_CORE_READ(ctx, dev); + switch (key) { + case 'h': + argp_state_help(state, stderr, ARGP_HELP_STD_HELP); + break; + case 'v': + env.verbose = true; + break; + case 'd': + env.disk = arg; + if (strlen(arg) + 1 > DISK_NAME_LEN) { + warning("Invalid disk name: too long\n"); + argp_usage(state); + } + break; + case 'T': + env.timestamp = true; + break; + case ARGP_KEY_ARG: + errno = 0; + if (pos_args == 0) { + env.interval = strtol(arg, NULL, 10); + if (errno || env.interval <= 0) { + warning("Invalid interval\n"); + argp_usage(state); + } + } else if (pos_args == 1) { + env.times = strtol(arg, NULL, 10); + if (errno || env.times <= 0) { + warning("Invalid times\n"); + argp_usage(state); + } + } else { + warning("Unrecognized positional argument: %s\n", arg); + argp_usage(state); + } + pos_args++; + break; + default: + return ARGP_ERR_UNKNOWN; } - - if (filter_dev && target_dev != dev) - return 0; - - counterp = bpf_map_lookup_or_try_init(&counters, &dev, &zero); - if (!counterp) - return 0; - if (counterp->last_sector) { - if (counterp->last_sector == sector) - __sync_fetch_and_add(&counterp->sequential, 1); - else - __sync_fetch_and_add(&counterp->random, 1); - __sync_fetch_and_add(&counterp->bytes, nr_sector << 9); - } - counterp->last_sector = sector + nr_sector; return 0; -} - -char LICENSE[] SEC("license") = "GPL"; \ No newline at end of file +} \ No newline at end of file -- Gitee