From: Chethan Suresh Date: Fri, 10 Dec 2021 04:47:59 +0000 (+0530) Subject: Support tracing of processes under cgroup path X-Git-Tag: v0.24.0~47 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=15340c44b98d8ee97a6dce775de614fd268cee13;p=platform%2Fupstream%2Fbcc.git Support tracing of processes under cgroup path - Using bpf_current_task_under_cgroup() we can check whether the probe is being run in the context of a given subset of the cgroup2 hierarchy. - Support cgroup path '-c' args to get the cgroup2 path and filter based on the cgroup2 path fd using bpf_current_task_under_cgroup() Signed-off-by: Chethan Suresh --- diff --git a/libbpf-tools/biolatency.bpf.c b/libbpf-tools/biolatency.bpf.c index 8d8fe584..91e21c3e 100644 --- a/libbpf-tools/biolatency.bpf.c +++ b/libbpf-tools/biolatency.bpf.c @@ -11,12 +11,20 @@ extern int LINUX_KERNEL_VERSION __kconfig; +const volatile bool filter_cg = false; 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_CGROUP_ARRAY); + __type(key, u32); + __type(value, u32); + __uint(max_entries, 1); +} cgroup_map SEC(".maps"); + struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, MAX_ENTRIES); @@ -59,6 +67,9 @@ int trace_rq_start(struct request *rq, int issue) SEC("tp_btf/block_rq_insert") int block_rq_insert(u64 *ctx) { + if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) + return 0; + /** * commit a54895fa (v5.11-rc1) changed tracepoint argument list * from TP_PROTO(struct request_queue *q, struct request *rq) @@ -73,6 +84,9 @@ int block_rq_insert(u64 *ctx) SEC("tp_btf/block_rq_issue") int block_rq_issue(u64 *ctx) { + if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) + return 0; + /** * commit a54895fa (v5.11-rc1) changed tracepoint argument list * from TP_PROTO(struct request_queue *q, struct request *rq) @@ -88,6 +102,9 @@ SEC("tp_btf/block_rq_complete") int BPF_PROG(block_rq_complete, struct request *rq, int error, unsigned int nr_bytes) { + if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) + return 0; + u64 slot, *tsp, ts = bpf_ktime_get_ns(); struct hist_key hkey = {}; struct hist *histp; diff --git a/libbpf-tools/biolatency.c b/libbpf-tools/biolatency.c index a09ebf29..ab309a67 100644 --- a/libbpf-tools/biolatency.c +++ b/libbpf-tools/biolatency.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,8 @@ static struct env { bool per_flag; bool milliseconds; bool verbose; + char *cgroupspath; + bool cg; } env = { .interval = 99999999, .times = 99999999, @@ -41,7 +44,7 @@ const char *argp_program_bug_address = const char argp_program_doc[] = "Summarize block device I/O latency as a histogram.\n" "\n" -"USAGE: biolatency [--help] [-T] [-m] [-Q] [-D] [-F] [-d DISK] [interval] [count]\n" +"USAGE: biolatency [--help] [-T] [-m] [-Q] [-D] [-F] [-d DISK] [-c CG] [interval] [count]\n" "\n" "EXAMPLES:\n" " biolatency # summarize block I/O latency as a histogram\n" @@ -50,7 +53,8 @@ const char argp_program_doc[] = " 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"; +" biolatency -d sdc # Trace sdc only\n" +" biolatency -c CG # Trace process under cgroupsPath CG\n"; static const struct argp_option opts[] = { { "timestamp", 'T', NULL, 0, "Include timestamp on output" }, @@ -60,6 +64,7 @@ static const struct argp_option opts[] = { { "flag", 'F', NULL, 0, "Print a histogram per set of I/O flags" }, { "disk", 'd', "DISK", 0, "Trace this disk only" }, { "verbose", 'v', NULL, 0, "Verbose debug output" }, + { "cgroup", 'c', "/sys/fs/cgroup/unified", 0, "Trace process in cgroup path"}, { NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help" }, {}, }; @@ -90,6 +95,10 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'T': env.timestamp = true; break; + case 'c': + env.cgroupspath = arg; + env.cg = true; + break; case 'd': env.disk = arg; if (strlen(arg) + 1 > DISK_NAME_LEN) { @@ -240,6 +249,8 @@ int main(int argc, char **argv) char ts[32]; time_t t; int err; + int idx, cg_map_fd; + int cgfd = -1; err = argp_parse(&argp, argc, argv, 0, NULL, NULL); if (err) @@ -278,6 +289,7 @@ int main(int argc, char **argv) obj->rodata->targ_per_flag = env.per_flag; obj->rodata->targ_ms = env.milliseconds; obj->rodata->targ_queued = env.queued; + obj->rodata->filter_cg = env.cg; err = biolatency_bpf__load(obj); if (err) { @@ -285,6 +297,21 @@ int main(int argc, char **argv) goto cleanup; } + /* update cgroup path fd to map */ + if (env.cg) { + idx = 0; + cg_map_fd = bpf_map__fd(obj->maps.cgroup_map); + cgfd = open(env.cgroupspath, O_RDONLY); + if (cgfd < 0) { + fprintf(stderr, "Failed opening Cgroup path: %s", env.cgroupspath); + goto cleanup; + } + if (bpf_map_update_elem(cg_map_fd, &idx, &cgfd, BPF_ANY)) { + fprintf(stderr, "Failed adding target cgroup to map"); + goto cleanup; + } + } + if (env.queued) { obj->links.block_rq_insert = bpf_program__attach(obj->progs.block_rq_insert); @@ -336,6 +363,8 @@ int main(int argc, char **argv) cleanup: biolatency_bpf__destroy(obj); partitions__free(partitions); + if (cgfd > 0) + close(cgfd); return err != 0; } diff --git a/libbpf-tools/biosnoop.bpf.c b/libbpf-tools/biosnoop.bpf.c index 1c340357..3fb7403f 100644 --- a/libbpf-tools/biosnoop.bpf.c +++ b/libbpf-tools/biosnoop.bpf.c @@ -8,11 +8,19 @@ #define MAX_ENTRIES 10240 +const volatile bool filter_cg = false; const volatile bool targ_queued = false; const volatile dev_t targ_dev = -1; extern __u32 LINUX_KERNEL_VERSION __kconfig; +struct { + __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY); + __type(key, u32); + __type(value, u32); + __uint(max_entries, 1); +} cgroup_map SEC(".maps"); + struct piddata { char comm[TASK_COMM_LEN]; u32 pid; @@ -60,12 +68,18 @@ int trace_pid(struct request *rq) SEC("fentry/blk_account_io_start") int BPF_PROG(blk_account_io_start, struct request *rq) { + if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) + return 0; + return trace_pid(rq); } SEC("kprobe/blk_account_io_merge_bio") int BPF_KPROBE(blk_account_io_merge_bio, struct request *rq) { + if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) + return 0; + return trace_pid(rq); } @@ -97,6 +111,9 @@ int trace_rq_start(struct request *rq, bool insert) SEC("tp_btf/block_rq_insert") int BPF_PROG(block_rq_insert) { + if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) + return 0; + /** * commit a54895fa (v5.11-rc1) changed tracepoint argument list * from TP_PROTO(struct request_queue *q, struct request *rq) @@ -111,6 +128,9 @@ int BPF_PROG(block_rq_insert) SEC("tp_btf/block_rq_issue") int BPF_PROG(block_rq_issue) { + if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) + return 0; + /** * commit a54895fa (v5.11-rc1) changed tracepoint argument list * from TP_PROTO(struct request_queue *q, struct request *rq) @@ -126,6 +146,9 @@ SEC("tp_btf/block_rq_complete") int BPF_PROG(block_rq_complete, struct request *rq, int error, unsigned int nr_bytes) { + if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) + return 0; + u64 ts = bpf_ktime_get_ns(); struct piddata *piddatap; struct event event = {}; diff --git a/libbpf-tools/biosnoop.c b/libbpf-tools/biosnoop.c index e0f00693..bbca68ce 100644 --- a/libbpf-tools/biosnoop.c +++ b/libbpf-tools/biosnoop.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "blk_types.h" #include "biosnoop.h" #include "biosnoop.skel.h" @@ -27,6 +28,8 @@ static struct env { bool timestamp; bool queued; bool verbose; + char *cgroupspath; + bool cg; } env = {}; static volatile __u64 start_ts; @@ -37,18 +40,20 @@ const char *argp_program_bug_address = const char argp_program_doc[] = "Trace block I/O.\n" "\n" -"USAGE: biosnoop [--help] [-d DISK] [-Q]\n" +"USAGE: biosnoop [--help] [-d DISK] [-c CG] [-Q]\n" "\n" "EXAMPLES:\n" " biosnoop # trace all block I/O\n" " biosnoop -Q # include OS queued time in I/O time\n" " biosnoop 10 # trace for 10 seconds only\n" -" biosnoop -d sdc # trace sdc only\n"; +" biosnoop -d sdc # trace sdc only\n" +" biosnoop -c CG # Trace process under cgroupsPath CG\n"; static const struct argp_option opts[] = { { "queued", 'Q', NULL, 0, "Include OS queued time in I/O time" }, { "disk", 'd', "DISK", 0, "Trace this disk only" }, { "verbose", 'v', NULL, 0, "Verbose debug output" }, + { "cgroup", 'c', "/sys/fs/cgroup/unified/CG", 0, "Trace process in cgroup path"}, { NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help" }, {}, }; @@ -67,6 +72,10 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'Q': env.queued = true; break; + case 'c': + env.cg = true; + env.cgroupspath = arg; + break; case 'd': env.disk = arg; if (strlen(arg) + 1 > DISK_NAME_LEN) { @@ -188,6 +197,8 @@ int main(int argc, char **argv) struct biosnoop_bpf *obj; __u64 time_end = 0; int err; + int idx, cg_map_fd; + int cgfd = -1; err = argp_parse(&argp, argc, argv, 0, NULL, NULL); if (err) @@ -222,6 +233,7 @@ int main(int argc, char **argv) } } obj->rodata->targ_queued = env.queued; + obj->rodata->filter_cg = env.cg; err = biosnoop_bpf__load(obj); if (err) { @@ -229,6 +241,21 @@ int main(int argc, char **argv) goto cleanup; } + /* update cgroup path fd to map */ + if (env.cg) { + idx = 0; + cg_map_fd = bpf_map__fd(obj->maps.cgroup_map); + cgfd = open(env.cgroupspath, O_RDONLY); + if (cgfd < 0) { + fprintf(stderr, "Failed opening Cgroup path: %s\n", env.cgroupspath); + goto cleanup; + } + if (bpf_map_update_elem(cg_map_fd, &idx, &cgfd, BPF_ANY)) { + fprintf(stderr, "Failed adding target cgroup to map\n"); + goto cleanup; + } + } + obj->links.blk_account_io_start = bpf_program__attach(obj->progs.blk_account_io_start); err = libbpf_get_error(obj->links.blk_account_io_start); @@ -325,6 +352,8 @@ cleanup: biosnoop_bpf__destroy(obj); ksyms__free(ksyms); partitions__free(partitions); + if (cgfd > 0) + close(cgfd); return err != 0; }