bpftool, musl compat: Replace nftw with FTW_ACTIONRETVAL
musl nftw implementation does not support FTW_ACTIONRETVAL. There have been multiple attempts at pushing the feature in musl upstream, but it has been refused or ignored all the times: https://www.openwall.com/lists/musl/2021/03/26/1 https://www.openwall.com/lists/musl/2022/01/22/1 In this case we only care about /proc/<pid>/fd/<fd>, so it's not too difficult to reimplement directly instead, and the new implementation makes 'bpftool perf' slightly faster because it doesn't needlessly stat/readdir unneeded directories (54ms -> 13ms on my machine). Signed-off-by: Dominique Martinet <asmadeus@codewreck.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Quentin Monnet <quentin@isovalent.com> Link: https://lore.kernel.org/bpf/20220424051022.2619648-4-asmadeus@codewreck.org
This commit is contained in:
Родитель
003fed595c
Коммит
93bc2e9e94
|
@ -11,7 +11,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ftw.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
#include <bpf/bpf.h>
|
#include <bpf/bpf.h>
|
||||||
|
|
||||||
|
@ -147,81 +147,83 @@ static void print_perf_plain(int pid, int fd, __u32 prog_id, __u32 fd_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int show_proc(const char *fpath, const struct stat *sb,
|
static int show_proc(void)
|
||||||
int tflag, struct FTW *ftwbuf)
|
|
||||||
{
|
{
|
||||||
|
struct dirent *proc_de, *pid_fd_de;
|
||||||
__u64 probe_offset, probe_addr;
|
__u64 probe_offset, probe_addr;
|
||||||
__u32 len, prog_id, fd_type;
|
__u32 len, prog_id, fd_type;
|
||||||
int err, pid = 0, fd = 0;
|
DIR *proc, *pid_fd;
|
||||||
|
int err, pid, fd;
|
||||||
const char *pch;
|
const char *pch;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
|
||||||
/* prefix always /proc */
|
proc = opendir("/proc");
|
||||||
pch = fpath + 5;
|
if (!proc)
|
||||||
if (*pch == '\0')
|
return -1;
|
||||||
return 0;
|
|
||||||
|
while ((proc_de = readdir(proc))) {
|
||||||
|
pid = 0;
|
||||||
|
pch = proc_de->d_name;
|
||||||
|
|
||||||
/* pid should be all numbers */
|
/* pid should be all numbers */
|
||||||
pch++;
|
|
||||||
while (isdigit(*pch)) {
|
while (isdigit(*pch)) {
|
||||||
pid = pid * 10 + *pch - '0';
|
pid = pid * 10 + *pch - '0';
|
||||||
pch++;
|
pch++;
|
||||||
}
|
}
|
||||||
if (*pch == '\0')
|
if (*pch != '\0')
|
||||||
return 0;
|
continue;
|
||||||
if (*pch != '/')
|
|
||||||
return FTW_SKIP_SUBTREE;
|
|
||||||
|
|
||||||
/* check /proc/<pid>/fd directory */
|
err = snprintf(buf, sizeof(buf), "/proc/%s/fd", proc_de->d_name);
|
||||||
pch++;
|
if (err < 0 || err >= (int)sizeof(buf))
|
||||||
if (strncmp(pch, "fd", 2))
|
continue;
|
||||||
return FTW_SKIP_SUBTREE;
|
|
||||||
pch += 2;
|
|
||||||
if (*pch == '\0')
|
|
||||||
return 0;
|
|
||||||
if (*pch != '/')
|
|
||||||
return FTW_SKIP_SUBTREE;
|
|
||||||
|
|
||||||
/* check /proc/<pid>/fd/<fd_num> */
|
pid_fd = opendir(buf);
|
||||||
pch++;
|
if (!pid_fd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
while ((pid_fd_de = readdir(pid_fd))) {
|
||||||
|
fd = 0;
|
||||||
|
pch = pid_fd_de->d_name;
|
||||||
|
|
||||||
|
/* fd should be all numbers */
|
||||||
while (isdigit(*pch)) {
|
while (isdigit(*pch)) {
|
||||||
fd = fd * 10 + *pch - '0';
|
fd = fd * 10 + *pch - '0';
|
||||||
pch++;
|
pch++;
|
||||||
}
|
}
|
||||||
if (*pch != '\0')
|
if (*pch != '\0')
|
||||||
return FTW_SKIP_SUBTREE;
|
continue;
|
||||||
|
|
||||||
/* query (pid, fd) for potential perf events */
|
/* query (pid, fd) for potential perf events */
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
err = bpf_task_fd_query(pid, fd, 0, buf, &len, &prog_id, &fd_type,
|
err = bpf_task_fd_query(pid, fd, 0, buf, &len,
|
||||||
|
&prog_id, &fd_type,
|
||||||
&probe_offset, &probe_addr);
|
&probe_offset, &probe_addr);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return 0;
|
continue;
|
||||||
|
|
||||||
if (json_output)
|
if (json_output)
|
||||||
print_perf_json(pid, fd, prog_id, fd_type, buf, probe_offset,
|
print_perf_json(pid, fd, prog_id, fd_type, buf,
|
||||||
probe_addr);
|
probe_offset, probe_addr);
|
||||||
else
|
else
|
||||||
print_perf_plain(pid, fd, prog_id, fd_type, buf, probe_offset,
|
print_perf_plain(pid, fd, prog_id, fd_type, buf,
|
||||||
probe_addr);
|
probe_offset, probe_addr);
|
||||||
|
}
|
||||||
|
closedir(pid_fd);
|
||||||
|
}
|
||||||
|
closedir(proc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_show(int argc, char **argv)
|
static int do_show(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int flags = FTW_ACTIONRETVAL | FTW_PHYS;
|
int err;
|
||||||
int err = 0, nopenfd = 16;
|
|
||||||
|
|
||||||
if (!has_perf_query_support())
|
if (!has_perf_query_support())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (json_output)
|
if (json_output)
|
||||||
jsonw_start_array(json_wtr);
|
jsonw_start_array(json_wtr);
|
||||||
if (nftw("/proc", show_proc, nopenfd, flags) == -1) {
|
err = show_proc();
|
||||||
p_err("%s", strerror(errno));
|
|
||||||
err = -1;
|
|
||||||
}
|
|
||||||
if (json_output)
|
if (json_output)
|
||||||
jsonw_end_array(json_wtr);
|
jsonw_end_array(json_wtr);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче