From 1edfb2409d159f46af385ef36b2017a4102cf67f Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Sat, 17 Dec 2016 17:57:22 +0200 Subject: [PATCH] flowtop: Move & refactor walk_processes() to proc.c Add proc_find_by_inode() in proc.c which finds pid by inode & gets processe's command line and use it in the flowtop.c instead of walk_processes(). Signed-off-by: Vadim Kochan Signed-off-by: Tobias Klauser --- flowtop.c | 78 ++++++++------------------------------------------------------- proc.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ proc.h | 1 + 3 files changed, 85 insertions(+), 69 deletions(-) diff --git a/flowtop.c b/flowtop.c index 4f8cbcf5..f382d6c9 100644 --- a/flowtop.c +++ b/flowtop.c @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include #include @@ -474,80 +472,22 @@ static void flow_list_destroy(struct flow_list *fl) spinlock_unlock(&flow_list.lock); } -static int walk_process(unsigned int pid, struct flow_entry *n) +static void flow_entry_find_process(struct flow_entry *n) { + char cmdline[512]; + pid_t pid; int ret; - DIR *dir; - struct dirent *ent; - char path[1024]; - if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1) - panic("giant process name! %u\n", pid); - - dir = opendir(path); - if (!dir) - return 0; - - while ((ent = readdir(dir))) { - struct stat statbuf; - - if (snprintf(path, sizeof(path), "/proc/%u/fd/%s", - pid, ent->d_name) < 0) - continue; - - if (stat(path, &statbuf) < 0) - continue; - - if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == statbuf.st_ino) { - char cmdline[256]; - - ret = proc_get_cmdline(pid, cmdline, sizeof(cmdline)); - if (ret < 0) - panic("Failed to get process cmdline: %s\n", strerror(errno)); - - if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0) - n->procname[0] = '\0'; - n->procnum = pid; - closedir(dir); - return 1; - } - } - - closedir(dir); - return 0; -} - -static void walk_processes(struct flow_entry *n) -{ - int ret; - DIR *dir; - struct dirent *ent; - - /* n->inode must be set */ - if (n->inode <= 0) { + ret = proc_find_by_inode(n->inode, cmdline, sizeof(cmdline), &pid); + if (ret <= 0) { n->procname[0] = '\0'; return; } - dir = opendir("/proc"); - if (!dir) - panic("Cannot open /proc: %s\n", strerror(errno)); - - while ((ent = readdir(dir))) { - const char *name = ent->d_name; - char *end; - unsigned int pid = strtoul(name, &end, 10); - - /* not a PID */ - if (pid == 0 && end == name) - continue; - - ret = walk_process(pid, n); - if (ret > 0) - break; - } + if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0) + n->procname[0] = '\0'; - closedir(dir); + n->procnum = pid; } static int get_port_inode(uint16_t port, int proto, bool is_ip6) @@ -810,7 +750,7 @@ static void flow_entry_get_extended(struct flow_entry *n) n->inode = get_port_inode(n->port_src, n->l4_proto, n->l3_proto == AF_INET6); if (n->inode > 0) - walk_processes(n); + flow_entry_find_process(n); } static char *bandw2str(double bytes, char *buf, size_t len) diff --git a/proc.c b/proc.c index 76e3c933..c25396a8 100644 --- a/proc.c +++ b/proc.c @@ -3,11 +3,13 @@ #endif #include #include +#include #include #include #include #include #include +#include #include "proc.h" #include "die.h" @@ -83,6 +85,79 @@ ssize_t proc_get_cmdline(unsigned int pid, char *cmdline, size_t len) return ret; } +static int match_pid_by_inode(pid_t pid, ino_t ino) +{ + struct dirent *ent; + char path[1024]; + DIR *dir; + + if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1) + panic("giant process name! %u\n", pid); + + dir = opendir(path); + if (!dir) + return -1; + + while ((ent = readdir(dir))) { + struct stat statbuf; + + if (snprintf(path, sizeof(path), "/proc/%u/fd/%s", + pid, ent->d_name) < 0) + continue; + + if (stat(path, &statbuf) < 0) + continue; + + if (S_ISSOCK(statbuf.st_mode) && ino == statbuf.st_ino) { + closedir(dir); + return 0; + } + } + + closedir(dir); + return -1; +} + +int proc_find_by_inode(ino_t ino, char *cmdline, size_t len, pid_t *pid) +{ + struct dirent *ent; + DIR *dir; + + if (ino <= 0) { + cmdline[0] = '\0'; + return 0; + } + + dir = opendir("/proc"); + if (!dir) + panic("Cannot open /proc: %s\n", strerror(errno)); + + while ((ent = readdir(dir))) { + int ret; + char *end; + const char *name = ent->d_name; + pid_t cur_pid = strtoul(name, &end, 10); + + /* not a PID */ + if (cur_pid == 0 && end == name) + continue; + + ret = match_pid_by_inode(cur_pid, ino); + if (!ret) { + ret = proc_get_cmdline(cur_pid, cmdline, len); + if (ret < 0) + panic("Failed to get process cmdline: %s\n", strerror(errno)); + + closedir(dir); + *pid = cur_pid; + return ret; + } + } + + closedir(dir); + return -1; +} + int proc_exec(const char *proc, char *const argv[]) { int status; diff --git a/proc.h b/proc.h index 9220b2ad..6e5f3aca 100644 --- a/proc.h +++ b/proc.h @@ -8,5 +8,6 @@ extern int set_proc_prio(int prio); extern int set_sched_status(int policy, int priority); extern ssize_t proc_get_cmdline(unsigned int pid, char *cmdline, size_t len); extern int proc_exec(const char *proc, char *const argv[]); +extern int proc_find_by_inode(ino_t ino, char *cmdline, size_t len, pid_t *pid); #endif /* PROC_H */ -- 2.11.4.GIT