]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootchart: don't parse /proc/uptime, use CLOCK_BOOTTIME
authorKarel Zak <kzak@redhat.com>
Thu, 31 Jul 2014 08:15:39 +0000 (10:15 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 3 Aug 2014 05:12:53 +0000 (01:12 -0400)
* systemd-bootchart always parses /proc/uptime, although the
  information is unnecessary when --rel specified

* use /proc/uptime is overkill, since Linux 2.6.39 we have
  clock_gettime(CLOCK_BOOTTIME, ...). The backend on kernel side is
  get_monotonic_boottime() in both cases.

* main() uses "if (graph_start <= 0.0)" to detect that /proc is
  available.

  This is fragile solution as graph_start is always smaller than zero
  on all systems after suspend/resume (e.g. laptops), because in this
  case the system uptime includes suspend time and uptime is always
  greater number than monotonic time. For example right now difference
  between uptime and monotonic time is 37 hours on my laptop.

  Note that main() calls log_uptime() (to parse /proc/uptime) for each
  sample when it believes that /proc is not available. So on my laptop
  systemd-boochars spends all live with /proc/uptime parsing +
  nanosleep(), try

    strace  /usr/lib/systemd/systemd-bootchart

  to see the never ending loop.

  This patch uses access("/proc/vmstat", F_OK) to detect procfs.

man/systemd-bootchart.xml
src/bootchart/bootchart.c
src/bootchart/store.c

index e19bbc11d479be7ae969c6bd44bfe93b0a7f7a7c..150ca48f39b6c669f32f96f64cc4b1358059616e 100644 (file)
                                 not graph the time elapsed since boot
                                 and before systemd-bootchart was
                                 started, as it may result in extremely
-                                large graphs.  </para></listitem>
+                                large graphs. The time elapsed since boot
+                                might also include any time that the system
+                                was suspended.</para></listitem>
                         </varlistentry>
                 </variablelist>
         </refsect1>
index 0ae72c29bbb1571268343f1728a7c0d5995ed940..fc00b4e3f2df888fa1fcf27ffeff770d29f0375d 100644 (file)
@@ -310,6 +310,7 @@ int main(int argc, char *argv[]) {
         time_t t = 0;
         int r;
         struct rlimit rlim;
+        bool has_procfs = false;
 
         parse_conf();
 
@@ -349,6 +350,8 @@ int main(int argc, char *argv[]) {
 
         log_uptime();
 
+        has_procfs = access("/proc/vmstat", F_OK) == 0;
+
         LIST_HEAD_INIT(head);
 
         /* main program loop */
@@ -385,11 +388,11 @@ int main(int argc, char *argv[]) {
                                 parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);
                 }
 
-                /* wait for /proc to become available, discarding samples */
-                if (graph_start <= 0.0)
-                        log_uptime();
-                else
+                if (has_procfs)
                         log_sample(samples, &sampledata);
+                else
+                        /* wait for /proc to become available, discarding samples */
+                        has_procfs = access("/proc/vmstat", F_OK) == 0;
 
                 sample_stop = gettime_ns();
 
index e0719838d5089a6e369ae546715335fc4b4c91c2..cedcba88ed1b8059c03281c75cd2a8fc1c52f992 100644 (file)
@@ -57,27 +57,22 @@ double gettime_ns(void) {
         return (n.tv_sec + (n.tv_nsec / 1000000000.0));
 }
 
-void log_uptime(void) {
-        _cleanup_fclose_ FILE *f = NULL;
-        char str[32];
-        double uptime;
-
-        f = fopen("/proc/uptime", "re");
-
-        if (!f)
-                return;
-        if (!fscanf(f, "%s %*s", str))
-                return;
-
-        uptime = strtod(str, NULL);
+static double gettime_up(void) {
+        struct timespec n;
 
-        log_start = gettime_ns();
+        clock_gettime(CLOCK_BOOTTIME, &n);
+        return (n.tv_sec + (n.tv_nsec / 1000000000.0));
+}
 
-        /* start graph at kernel boot time */
+void log_uptime(void) {
         if (arg_relative)
-                graph_start = log_start;
-        else
+                graph_start = log_start = gettime_ns();
+        else {
+                double uptime = gettime_up();
+
+                log_start = gettime_ns();
                 graph_start = log_start - uptime;
+        }
 }
 
 static char *bufgetline(char *buf) {