X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbootchart%2Flog.c;h=ccec03f12cb18c6b85c49dcdc888df50d5d5ba07;hb=0eff0f3bce1d0826765f6e84ff046b10fe5a1a12;hp=c697121814e7d6e848f01c5a6aaf0bf820f7c5dd;hpb=53f5329f7aa321d72847cd7f8f28da9a7db80331;p=elogind.git diff --git a/src/bootchart/log.c b/src/bootchart/log.c index c69712181..ccec03f12 100644 --- a/src/bootchart/log.c +++ b/src/bootchart/log.c @@ -1,16 +1,24 @@ -/* - * log.c - * - * Copyright (C) 2009-2012 Intel Coproration - * - * Authors: - * Auke Kok - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 - * of the License. - */ +/*** + log.c - This file is part of systemd-bootchart + + Copyright (C) 2009-2013 Intel Coproration + + Authors: + Auke Kok + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . + ***/ #define _GNU_SOURCE 1 #include @@ -35,32 +43,31 @@ */ static char smaps_buf[4096]; DIR *proc; - +int procfd=-1; double gettime_ns(void) { - struct timespec now; + struct timespec n; - clock_gettime(CLOCK_MONOTONIC, &now); + clock_gettime(CLOCK_MONOTONIC, &n); - return (now.tv_sec + (now.tv_nsec / 1000000000.0)); + return (n.tv_sec + (n.tv_nsec / 1000000000.0)); } void log_uptime(void) { - FILE *f; + FILE _cleanup_fclose_ *f = NULL; char str[32]; double uptime; f = fopen("/proc/uptime", "r"); + if (!f) return; - if (!fscanf(f, "%s %*s", str)) { - fclose(f); + if (!fscanf(f, "%s %*s", str)) return; - } - fclose(f); + uptime = strtod(str, NULL); log_start = gettime_ns(); @@ -86,12 +93,31 @@ static char *bufgetline(char *buf) return c; } +static int pid_cmdline_strncpy(char *buffer, int pid, size_t buf_len) { + char filename[PATH_MAX]; + int _cleanup_close_ fd=-1; + ssize_t n; + + sprintf(filename, "%d/cmdline", pid); + fd = openat(procfd, filename, O_RDONLY); + if (fd < 0) + return -errno; + + n = read(fd, buffer, buf_len-1); + if (n > 0) { + int i; + for (i = 0; i < n; i++) + if (buffer[i] == '\0') + buffer[i] = ' '; + buffer[n] = '\0'; + } + return 0; +} void log_sample(int sample) { static int vmstat; static int schedstat; - FILE *st; char buf[4095]; char key[256]; char val[256]; @@ -105,10 +131,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); @@ -140,7 +178,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); @@ -178,7 +216,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) { @@ -190,16 +228,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; @@ -222,24 +250,23 @@ schedstat_next: /* end of our LL? then append a new record */ if (ps->pid != pid) { + FILE _cleanup_fclose_ *st = NULL; char t[32]; struct ps_struct *parent; - ps->next_ps = malloc(sizeof(struct ps_struct)); + ps->next_ps = calloc(1, sizeof(struct ps_struct)); if (!ps->next_ps) { - perror("malloc(ps_struct)"); + perror("calloc(ps_struct)"); exit (EXIT_FAILURE); } - memset(ps->next_ps, 0, sizeof(struct ps_struct)); ps = ps->next_ps; ps->pid = pid; - ps->sample = malloc(sizeof(struct ps_sched_struct) * (len + 1)); + ps->sample = calloc(samples_len + 1, sizeof(struct ps_sched_struct)); if (!ps->sample) { - perror("malloc(ps_struct)"); + perror("calloc(ps_struct)"); exit (EXIT_FAILURE); } - memset(ps->sample, 0, sizeof(struct ps_sched_struct) * (len + 1)); pscount++; @@ -248,8 +275,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; } @@ -264,7 +291,12 @@ schedstat_next: if (!sscanf(buf, "%s %*s %*s", key)) continue; - strncpy(ps->name, key, 16); + strncpy(ps->name, key, 256); + + /* cmdline */ + if (show_cmdline) + pid_cmdline_strncpy(ps->name, pid, 256); + /* discard line 2 */ m = bufgetline(buf); if (!m) @@ -280,15 +312,14 @@ 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)) { - fclose(st); continue; } - fclose(st); ps->ppid = p; /* @@ -336,8 +367,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; } @@ -368,8 +399,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)); @@ -402,8 +434,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; } @@ -422,7 +454,11 @@ catch_rename: if (!sscanf(buf, "%s %*s %*s", key)) continue; - strncpy(ps->name, key, 16); + strncpy(ps->name, key, 256); + + /* cmdline */ + if (show_cmdline) + pid_cmdline_strncpy(ps->name, pid, 256); } } }