From e04ef376c3ee89b52a5befa82f1fe768cfd08cf1 Mon Sep 17 00:00:00 2001 From: Luis Gerhorst <privat@luisgerhorst.de> Date: Sat, 10 Jul 2021 11:08:13 +0200 Subject: [PATCH] task_find: Optimize, avoid open on regular files Using perf record it was determined that most time in both find task_find.bpf.c is spent in openat, therefore this has to be avoided. --- src/task_find.bpf.c | 30 +++++++++++++++++------------- src/task_lib.bpf.h | 11 +++++++++++ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/task_find.bpf.c b/src/task_find.bpf.c index 13352a1..cbac40d 100644 --- a/src/task_find.bpf.c +++ b/src/task_find.bpf.c @@ -28,7 +28,7 @@ void *u_newline; void *u_iterdents64_buf; size_t root_namelen; -static long iter_dir(size_t namelen, bool print) { +static long iter_dir(uint32_t d_type, size_t namelen, bool print) { long err = 0; if (namelen + 1 > PATHLEN) { @@ -37,12 +37,6 @@ static long iter_dir(size_t namelen, bool print) { goto end; } - int *prog_fd = bpf_map_lookup_elem(&state_map, &PDPF_KEY); - if (!prog_fd) { - bpf_printk("Error: !bpf_map_lookup_elem(&state_map, &PDPF_KEY)"); - goto end; - } - int *curr_depth_p = bpf_map_lookup_elem(&state_map, &CURR_DEPTH_KEY); if (!curr_depth_p) { bpf_printk("Error: bpf_map_lookup_elem(&state_map, &CURR_DEPTH_KEY)"); @@ -56,6 +50,13 @@ static long iter_dir(size_t namelen, bool print) { } void *name_user = u_iterdents64_buf + depth * PATHLEN; + if (d_type != DT_DIR) { + if (print) { + write(STDOUT_FILENO, name_user, namelen); + write(STDOUT_FILENO, u_newline, 1); + } + goto end; + } int *parent_dfd = bpf_map_lookup_elem(&dfd_map, &depth); if (!parent_dfd) { @@ -65,10 +66,7 @@ static long iter_dir(size_t namelen, bool print) { int dfd = openat(*parent_dfd, name_user, O_RDONLY | O_DIRECTORY, 0777); if (dfd < 0) { - if (print) { - write(STDOUT_FILENO, name_user, namelen); - write(STDOUT_FILENO, u_newline, 1); - } + bpf_printk("Warning: openat failed, is someone modifying the tree?"); /* Not a directory, no need to iterate. */ goto end; } @@ -90,6 +88,12 @@ static long iter_dir(size_t namelen, bool print) { goto reset_depth; } + int *prog_fd = bpf_map_lookup_elem(&state_map, &PDPF_KEY); + if (!prog_fd) { + bpf_printk("Error: !bpf_map_lookup_elem(&state_map, &PDPF_KEY)"); + goto end; + } + err = bpf_task_iterdents64(dfd, *prog_fd, child_name_user, PATHLEN); if (err) { bpf_printk("Error: iterdents64(%d, %d) = %d", dfd, *prog_fd, err); @@ -116,7 +120,7 @@ int entry(void *ctx) { long err = 0; - err = iter_dir(root_namelen, false); + err = iter_dir(DT_DIR, root_namelen, false); if (err) { goto end; } @@ -143,7 +147,7 @@ int process_dirent(struct bpf_dirent64 *d) { } } - err = iter_dir(d->namelen, match); + err = iter_dir(d->d_type, d->namelen, match); if (err) { goto end; } diff --git a/src/task_lib.bpf.h b/src/task_lib.bpf.h index 84c7af2..7545e82 100644 --- a/src/task_lib.bpf.h +++ b/src/task_lib.bpf.h @@ -65,6 +65,17 @@ typedef off64_t off_t; #define SEEK_DATA 3 /* Seek to next data. */ #define SEEK_HOLE 4 /* Seek to next hole. */ +/* these are defined by POSIX and also present in glibc's dirent.h */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + /* Copied from man getdents64(2). */ struct linux_dirent64 { ino64_t d_ino; /* 64-bit inode number */ -- GitLab