initctl: fix %CPU listing bug and use hash table for faster lookup

Two major bugs: `if (!cg)` and missing `strdup(path)`.

Also convert to use std hash table for lookup of previous cpu load value
for a given cgroup path.  The hash table is sized after the current num.
rows on the screen -- resize currently not supported.  The value given
to hcreate() should be 25% greater than the estimated num of entries,
but we take a wild guess just to make sure we don't run out of space at
runtime.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2021-03-15 13:43:37 +01:00
1 parent 230c64927b
commit 08144df5ea
1 file changed
+27 -20
+27 -20
View File
@@ -29,8 +29,10 @@
#include <dirent.h> #include <dirent.h>
#include <getopt.h> #include <getopt.h>
#include <paths.h> #include <paths.h>
#include <search.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <inttypes.h>
#include <time.h> #include <time.h>
#include <utmp.h> #include <utmp.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@@ -784,6 +786,7 @@ static struct cg *append(char *path)
{ {
struct cg *cg; struct cg *cg;
char fn[256]; char fn[256];
ENTRY item;
snprintf(fn, sizeof(fn), "%s/cpuacct.usage", path); snprintf(fn, sizeof(fn), "%s/cpuacct.usage", path);
if (access(fn, F_OK)) { if (access(fn, F_OK)) {
@@ -795,30 +798,26 @@ static struct cg *append(char *path)
if (!cg) if (!cg)
err(1, "failed allocating struct cg"); err(1, "failed allocating struct cg");
cg->cg_path = path; cg->cg_path = strdup(path);
if (!list) if (list)
list = cg; cg->cg_next = list;
else { list = cg;
struct cg *tmp = list;
while (tmp->cg_next) item.key = cg->cg_path;
tmp = tmp->cg_next; item.data = cg;
tmp->cg_next = cg; if (!hsearch(item, ENTER))
} err(1, "failed adding to hash table");
return cg; return cg;
} }
static struct cg *find(char *path) static struct cg *find(char *path)
{ {
struct cg *cg; ENTRY *ep, item = { path, NULL };
for (cg = list; cg; cg = cg->cg_next) { ep = hsearch(item, FIND);
if (strcmp(cg->cg_path, path)) if (ep)
continue; return ep->data;
return cg;
}
return append(path); return append(path);
} }
@@ -831,7 +830,7 @@ static float cgroup_cpuload(char *path)
FILE *fp; FILE *fp;
cg = find(path); cg = find(path);
if (cg) if (!cg)
return 0.0; return 0.0;
snprintf(fn, sizeof(fn), "%s/cpuacct.usage", cg->cg_path); snprintf(fn, sizeof(fn), "%s/cpuacct.usage", cg->cg_path);
@@ -850,7 +849,6 @@ static float cgroup_cpuload(char *path)
cg->cg_load = (float)(diff / 1000000); cg->cg_load = (float)(diff / 1000000);
cg->cg_load /= 10.0; cg->cg_load /= 10.0;
} }
cg->cg_prev = curr; cg->cg_prev = curr;
} }
@@ -888,6 +886,9 @@ static int dump_cgroup(char *path, char *pfx, int top)
int i, n; int i, n;
int num; int num;
if (top >= screen_rows)
return 0;
if (-1 == lstat(path, &st)) if (-1 == lstat(path, &st))
return 1; return 1;
@@ -932,7 +933,7 @@ static int dump_cgroup(char *path, char *pfx, int top)
} }
printf("%s/ [cpu.shares: %d]\n", nm, cgroup_shares(buf)); printf("%s/ [cpu.shares: %d]\n", nm, cgroup_shares(buf));
rc += dump_cgroup(buf, prefix, top); rc += dump_cgroup(buf, prefix, top + i);
free(namelist[i]); free(namelist[i]);
} }
@@ -952,13 +953,16 @@ static int dump_cgroup(char *path, char *pfx, int top)
if (pid <= 0) if (pid <= 0)
continue; continue;
/* skip kernel threads for now */ /* skip kernel threads for now (no cmdline) */
pid_comm(pid, comm, sizeof(comm)); pid_comm(pid, comm, sizeof(comm));
if (pid_cmdline(pid, buf, sizeof(buf))) if (pid_cmdline(pid, buf, sizeof(buf)))
printf("%s%s%s %s%d %s %s%s\n", printf("%s%s%s %s%d %s %s%s\n",
top ? " " : "", top ? " " : "",
pfx, ++i == num ? END : FORK, pfx, ++i == num ? END : FORK,
CDIM, pid, comm, buf, CRST); CDIM, pid, comm, buf, CRST);
top += i;
if (top >= screen_rows)
break;
} }
return fclose(fp); return fclose(fp);
@@ -994,6 +998,9 @@ static int show_cgtop(char *arg)
arg = path; arg = path;
} }
if (!hcreate(screen_rows + 25))
err(1, "failed creating hash table");
while (1) { while (1) {
fputs("\e[2J\e[1;1H", stdout); fputs("\e[2J\e[1;1H", stdout);
if (heading) if (heading)