summaryrefslogtreecommitdiff
path: root/src/bootchart
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootchart')
-rw-r--r--src/bootchart/bootchart.c35
-rw-r--r--src/bootchart/bootchart.h1
-rw-r--r--src/bootchart/store.c24
-rw-r--r--src/bootchart/store.h5
-rw-r--r--src/bootchart/svg.c97
-rw-r--r--src/bootchart/svg.h2
6 files changed, 78 insertions, 86 deletions
diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 1024f78fa6..8cb1ee6921 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -67,7 +67,6 @@ double interval;
FILE *of = NULL;
int overrun = 0;
static int exiting = 0;
-int sysfd=-1;
#define DEFAULT_SAMPLES_LEN 500
#define DEFAULT_HZ 25.0
@@ -314,6 +313,8 @@ static void do_journal_append(char *file) {
int main(int argc, char *argv[]) {
_cleanup_free_ char *build = NULL;
+ _cleanup_close_ int sysfd = -1;
+ _cleanup_closedir_ DIR *proc = NULL;
struct sigaction sig = {
.sa_handler = signal_handler,
};
@@ -323,7 +324,6 @@ int main(int argc, char *argv[]) {
time_t t = 0;
int r;
struct rlimit rlim;
- bool has_procfs = false;
parse_conf();
@@ -373,8 +373,6 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- has_procfs = access("/proc/vmstat", F_OK) == 0;
-
LIST_HEAD_INIT(head);
/* main program loop */
@@ -404,13 +402,16 @@ int main(int argc, char *argv[]) {
parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);
}
- if (has_procfs) {
- r = log_sample(samples, &sampledata);
+ if (proc)
+ rewinddir(proc);
+ else
+ proc = opendir("/proc");
+
+ /* wait for /proc to become available, discarding samples */
+ if (proc) {
+ r = log_sample(proc, samples, &sampledata);
if (r < 0)
return EXIT_FAILURE;
- } else {
- /* wait for /proc to become available, discarding samples */
- has_procfs = access("/proc/vmstat", F_OK) == 0;
}
sample_stop = gettime_ns();
@@ -470,23 +471,23 @@ int main(int argc, char *argv[]) {
}
if (!of) {
- fprintf(stderr, "opening output file '%s': %m\n", output_file);
- exit (EXIT_FAILURE);
+ log_error("Error opening output file '%s': %m\n", output_file);
+ return EXIT_FAILURE;
}
- svg_do(strna(build));
+ r = svg_do(strna(build));
+ if (r < 0) {
+ log_error_errno(r, "Error generating svg file: %m\n");
+ return EXIT_FAILURE;
+ }
- fprintf(stderr, "systemd-bootchart wrote %s\n", output_file);
+ log_info("systemd-bootchart wrote %s\n", output_file);
do_journal_append(output_file);
if (of)
fclose(of);
- closedir(proc);
- if (sysfd >= 0)
- close(sysfd);
-
/* nitpic cleanups */
ps = ps_first->next_ps;
while (ps->next_ps) {
diff --git a/src/bootchart/bootchart.h b/src/bootchart/bootchart.h
index e4dbdd921d..6e83a99a2b 100644
--- a/src/bootchart/bootchart.h
+++ b/src/bootchart/bootchart.h
@@ -132,4 +132,3 @@ extern char arg_output_path[PATH_MAX];
extern char arg_init_path[PATH_MAX];
extern FILE *of;
-extern int sysfd;
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index 53b827fe59..6125104084 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -45,8 +45,6 @@
*/
static char smaps_buf[4096];
static int skip = 0;
-DIR *proc;
-int procfd = -1;
double gettime_ns(void) {
struct timespec n;
@@ -86,7 +84,7 @@ static char *bufgetline(char *buf) {
return c;
}
-static int pid_cmdline_strscpy(char *buffer, size_t buf_len, int pid) {
+static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid) {
char filename[PATH_MAX];
_cleanup_close_ int fd=-1;
ssize_t n;
@@ -107,7 +105,7 @@ static int pid_cmdline_strscpy(char *buffer, size_t buf_len, int pid) {
return 0;
}
-int log_sample(int sample, struct list_sample_data **ptr) {
+int log_sample(DIR *proc, int sample, struct list_sample_data **ptr) {
static int vmstat = -1;
static int schedstat = -1;
char buf[4096];
@@ -126,19 +124,13 @@ int log_sample(int sample, struct list_sample_data **ptr) {
int fd;
struct list_sample_data *sampledata;
struct ps_sched_struct *ps_prev = NULL;
+ int procfd;
sampledata = *ptr;
- /* all the per-process stuff goes here */
- if (!proc) {
- /* find all processes */
- proc = opendir("/proc");
- if (!proc)
- return -errno;
- procfd = dirfd(proc);
- } else {
- rewinddir(proc);
- }
+ procfd = dirfd(proc);
+ if (procfd < 0)
+ return -errno;
if (vmstat < 0) {
/* block stuff */
@@ -301,7 +293,7 @@ schedstat_next:
/* cmdline */
if (arg_show_cmdline)
- pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);
+ pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
/* discard line 2 */
m = bufgetline(buf);
@@ -520,7 +512,7 @@ catch_rename:
/* cmdline */
if (arg_show_cmdline)
- pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);
+ pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
}
}
diff --git a/src/bootchart/store.h b/src/bootchart/store.h
index 8cb319275c..bc54f4f631 100644
--- a/src/bootchart/store.h
+++ b/src/bootchart/store.h
@@ -27,9 +27,6 @@
#include <dirent.h>
#include "bootchart.h"
-extern DIR *proc;
-extern int procfd;
-
double gettime_ns(void);
void log_uptime(void);
-int log_sample(int sample, struct list_sample_data **ptr);
+int log_sample(DIR *proc, int sample, struct list_sample_data **ptr);
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index 8c8fab941d..b031090d2f 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -31,6 +31,7 @@
#include <fcntl.h>
#include "util.h"
+#include "fileio.h"
#include "macro.h"
#include "store.h"
#include "svg.h"
@@ -149,54 +150,47 @@ static void svg_header(void) {
svg(" ]]>\n </style>\n</defs>\n\n");
}
-static void svg_title(const char *build) {
- char cmdline[256] = "";
- char filename[PATH_MAX];
- char buf[256];
- char rootbdev[16] = "Unknown";
- char model[256] = "Unknown";
+static int svg_title(const char *build) {
+ _cleanup_free_ char *cmdline = NULL;
+ _cleanup_free_ char *model = NULL;
+ _cleanup_free_ char *buf = NULL;
char date[256] = "Unknown";
- char cpu[256] = "Unknown";
+ char *cpu;
char *c;
- FILE *f;
time_t t;
- int fd, r;
+ int r;
struct utsname uts;
- /* grab /proc/cmdline */
- fd = openat(procfd, "cmdline", O_RDONLY);
- f = fdopen(fd, "r");
- if (f) {
- if (!fgets(cmdline, 255, f))
- sprintf(cmdline, "Unknown");
- fclose(f);
- } else {
- if (fd >= 0)
- close(fd);
+ r = read_one_line_file("/proc/cmdline", &cmdline);
+ if (r < 0) {
+ log_error_errno(r, "Unable to read cmdline: %m\n");
+ return r;
}
/* extract root fs so we can find disk model name in sysfs */
/* FIXME: this works only in the simple case */
c = strstr(cmdline, "root=/dev/");
if (c) {
- strncpy(rootbdev, &c[10], 3);
+ char rootbdev[4];
+ char filename[32];
+
+ strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1);
rootbdev[3] = '\0';
- sprintf(filename, "block/%s/device/model", rootbdev);
- fd = openat(sysfd, filename, O_RDONLY);
- f = fdopen(fd, "r");
- if (f) {
- if (!fgets(model, 255, f))
- log_error("Error reading disk model for %s: %m\n", rootbdev);
- fclose(f);
- } else {
- if (fd >= 0)
- close(fd);
+ snprintf(filename, sizeof(filename), "/sys/block/%s/device/model", rootbdev);
+
+ r = read_one_line_file(filename, &model);
+ if (r < 0) {
+ log_error("Error reading disk model for %s: %m\n", rootbdev);
+ return r;
}
}
/* various utsname parameters */
- if (uname(&uts))
+ r = uname(&uts);
+ if (r < 0) {
log_error("Error getting uname info\n");
+ return -errno;
+ }
/* date */
t = time(NULL);
@@ -204,21 +198,23 @@ static void svg_title(const char *build) {
assert_se(r > 0);
/* CPU type */
- fd = openat(procfd, "cpuinfo", O_RDONLY);
- f = fdopen(fd, "r");
- if (f) {
- while (fgets(buf, 255, f)) {
- if (strstr(buf, "model name")) {
- strncpy(cpu, &buf[13], 255);
- break;
- }
- }
- fclose(f);
- } else {
- if (fd >= 0)
- close(fd);
+ r = read_full_file("/proc/cpuinfo", &buf, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Unable to read cpuinfo: %m\n");
+ return r;
+ }
+
+ cpu = strstr(buf, "model name");
+ if (!cpu) {
+ log_error("Unable to read module name from cpuinfo.\n");
+ return -ENOENT;
}
+ cpu += 13;
+ c = strchr(cpu, '\n');
+ if (c)
+ *c = '\0';
+
svg("<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
uts.nodename, date);
svg("<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
@@ -241,6 +237,8 @@ static void svg_title(const char *build) {
svg("</text>\n");
svg("<text class=\"sec\" x=\"20\" y=\"155\">Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered</text>\n",
arg_hz, arg_samples_len, overrun, pscount, pfiltered);
+
+ return 0;
}
static void svg_graph_box(int height) {
@@ -1273,10 +1271,10 @@ static void svg_top_ten_pss(void) {
top[n]->pid);
}
-void svg_do(const char *build) {
+int svg_do(const char *build) {
struct ps_struct *ps;
double offset = 7;
- int c;
+ int r, c;
memzero(&str, sizeof(str));
@@ -1334,9 +1332,12 @@ void svg_do(const char *build) {
svg("</g>\n\n");
svg("<g transform=\"translate(10, 0)\">\n");
- svg_title(build);
+ r = svg_title(build);
svg("</g>\n\n");
+ if (r < 0)
+ return r;
+
svg("<g transform=\"translate(10,200)\">\n");
svg_top_ten_cpu();
svg("</g>\n\n");
@@ -1359,4 +1360,6 @@ void svg_do(const char *build) {
/* svg footer */
svg("\n</svg>\n");
+
+ return 0;
}
diff --git a/src/bootchart/svg.h b/src/bootchart/svg.h
index df3a7bf8ef..f0fb1a7ce7 100644
--- a/src/bootchart/svg.h
+++ b/src/bootchart/svg.h
@@ -24,4 +24,4 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-void svg_do(const char *build);
+int svg_do(const char *build);