bootchart: make bootchart work from within the initrd

With this patch, bootchart can be started from within the initramfs via
the kernel command line "rdinit=/usr/lib/systemd/systemd-bootchart"

see:
    http://harald.fedorapeople.org/downloads/bootchart-20130207-1652.svg
This commit is contained in:
Harald Hoyer 2013-02-12 15:36:29 -08:00 committed by Auke Kok
parent 759c945a43
commit f2f85884ca
2 changed files with 46 additions and 30 deletions

View File

@ -47,7 +47,7 @@ struct cpu_stat_struct cpustat[MAXCPUS];
int pscount;
int cpus;
double interval;
FILE *of;
FILE *of = NULL;
int overrun = 0;
static int exiting = 0;
@ -64,7 +64,7 @@ double scale_x = 100.0; /* 100px = 1sec */
double scale_y = 20.0; /* 16px = 1 process bar */
char init_path[PATH_MAX] = "/sbin/init";
char output_path[PATH_MAX] = "/var/log";
char output_path[PATH_MAX] = "/run/log";
static struct rlimit rlim;
@ -235,6 +235,7 @@ int main(int argc, char *argv[])
execl(init_path, init_path, NULL);
}
}
argv[0][0] = '@';
/* start with empty ps LL */
ps_first = calloc(1, sizeof(struct ps_struct));
@ -264,6 +265,14 @@ int main(int argc, char *argv[])
sampletime[samples] = gettime_ns();
if (!of && (access(output_path, R_OK|W_OK|X_OK) == 0)) {
t = time(NULL);
strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M", localtime(&t));
snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", output_path, datestr);
of = fopen(output_file, "w");
}
/* wait for /proc to become available, discarding samples */
if (!(graph_start > 0.0))
log_uptime();
@ -323,11 +332,13 @@ int main(int argc, char *argv[])
}
closedir(proc);
t = time(NULL);
strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M", localtime(&t));
snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", output_path, datestr);
if (!of) {
t = time(NULL);
strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M", localtime(&t));
snprintf(output_file, PATH_MAX, "%s/bootchart-%s.svg", output_path, datestr);
of = fopen(output_file, "w");
}
of = fopen(output_file, "w");
if (!of) {
perror("open output_file");
exit (EXIT_FAILURE);

View File

@ -43,7 +43,7 @@
*/
static char smaps_buf[4096];
DIR *proc;
int procfd=-1;
double gettime_ns(void)
{
@ -62,6 +62,7 @@ void log_uptime(void)
double uptime;
f = fopen("/proc/uptime", "r");
if (!f)
return;
if (!fscanf(f, "%s %*s", str)) {
@ -113,10 +114,22 @@ void log_sample(int sample)
ssize_t s;
ssize_t n;
struct dirent *ent;
int fd;
/* all the per-process stuff goes here */
if (!proc) {
/* find all processes */
proc = opendir("/proc");
if (!proc)
return;
procfd = dirfd(proc);
} else {
rewinddir(proc);
}
if (!vmstat) {
/* block stuff */
vmstat = open("/proc/vmstat", O_RDONLY);
vmstat = openat(procfd, "vmstat", O_RDONLY);
if (vmstat == -1) {
perror("open /proc/vmstat");
exit (EXIT_FAILURE);
@ -148,7 +161,7 @@ vmstat_next:
if (!schedstat) {
/* overall CPU utilization */
schedstat = open("/proc/schedstat", O_RDONLY);
schedstat = openat(procfd, "schedstat", O_RDONLY);
if (schedstat == -1) {
perror("open /proc/schedstat");
exit (EXIT_FAILURE);
@ -186,7 +199,7 @@ schedstat_next:
if (entropy) {
if (!e_fd) {
e_fd = open("/proc/sys/kernel/random/entropy_avail", O_RDONLY);
e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY);
}
if (e_fd) {
@ -198,16 +211,6 @@ schedstat_next:
}
}
/* all the per-process stuff goes here */
if (!proc) {
/* find all processes */
proc = opendir("/proc");
if (!proc)
return;
} else {
rewinddir(proc);
}
while ((ent = readdir(proc)) != NULL) {
char filename[PATH_MAX];
int pid;
@ -254,8 +257,8 @@ schedstat_next:
/* get name, start time */
if (!ps->sched) {
sprintf(filename, "/proc/%d/sched", pid);
ps->sched = open(filename, O_RDONLY);
sprintf(filename, "%d/sched", pid);
ps->sched = openat(procfd, filename, O_RDONLY);
if (ps->sched == -1)
continue;
}
@ -286,8 +289,9 @@ schedstat_next:
ps->starttime = strtod(t, NULL) / 1000.0;
/* ppid */
sprintf(filename, "/proc/%d/stat", pid);
st = fopen(filename, "r");
sprintf(filename, "%d/stat", pid);
fd = openat(procfd, filename, O_RDONLY);
st = fdopen(fd, "r");
if (!st)
continue;
if (!fscanf(st, "%*s %*s %*s %i", &p)) {
@ -342,8 +346,8 @@ schedstat_next:
/* rt, wt */
if (!ps->schedstat) {
sprintf(filename, "/proc/%d/schedstat", pid);
ps->schedstat = open(filename, O_RDONLY);
sprintf(filename, "%d/schedstat", pid);
ps->schedstat = openat(procfd, filename, O_RDONLY);
if (ps->schedstat == -1)
continue;
}
@ -374,8 +378,9 @@ schedstat_next:
goto catch_rename;
/* Pss */
if (!ps->smaps) {
sprintf(filename, "/proc/%d/smaps", pid);
ps->smaps = fopen(filename, "r");
sprintf(filename, "%d/smaps", pid);
fd = openat(procfd, filename, O_RDONLY);
ps->smaps = fdopen(fd, "r");
if (!ps->smaps)
continue;
setvbuf(ps->smaps, smaps_buf, _IOFBF, sizeof(smaps_buf));
@ -408,8 +413,8 @@ catch_rename:
/* re-fetch name */
/* get name, start time */
if (!ps->sched) {
sprintf(filename, "/proc/%d/sched", pid);
ps->sched = open(filename, O_RDONLY);
sprintf(filename, "%d/sched", pid);
ps->sched = openat(procfd, filename, O_RDONLY);
if (ps->sched == -1)
continue;
}