<div dir="ltr"><br><div><br></div><div>thumbs up from me, thanks for sending this.</div><div><br></div><div>Auke</div><div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Jul 31, 2014 at 1:15 AM, Karel Zak <span dir="ltr"><<a href="mailto:kzak@redhat.com" target="_blank">kzak@redhat.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">* systemd-bootchart always parses /proc/uptime, although the<br>
  information is unnecessary when --rel specified<br>
<br>
* use /proc/uptime is overkill, since Linux 2.6.39 we have<br>
  clock_gettime(CLOCK_BOOTTIME, ...). The backend on kernel side is<br>
  get_monotonic_boottime() in both cases.<br>
<br>
* main() uses "if (graph_start <= 0.0)" to detect that /proc is<br>
  available.<br>
<br>
  This is fragile solution as graph_start is always smaller than zero<br>
  on all systems after suspend/resume (e.g. laptops), because in this<br>
  case the system uptime includes suspend time and uptime is always<br>
  greater number than monotonic time. For example right now difference<br>
  between uptime and monotonic time is 37 hours on my laptop.<br>
<br>
  Note that main() calls log_uptime() (to parse /proc/uptime) for each<br>
  sample when it believes that /proc is not available. So on my laptop<br>
  systemd-boochars spends all live with /proc/uptime parsing +<br>
  nanosleep(), try<br>
<br>
    strace  /usr/lib/systemd/systemd-bootchart<br>
<br>
  to see the never ending loop.<br>
<br>
  This patch uses access("/proc/vmstat", F_OK) to detect procfs.<br>
---<br>
 man/systemd-bootchart.xml |  4 +++-<br>
 src/bootchart/bootchart.c | 11 +++++++----<br>
 src/bootchart/store.c     | 29 ++++++++++++-----------------<br>
 3 files changed, 22 insertions(+), 22 deletions(-)<br>
<br>
diff --git a/man/systemd-bootchart.xml b/man/systemd-bootchart.xml<br>
index e19bbc1..150ca48 100644<br>
--- a/man/systemd-bootchart.xml<br>
+++ b/man/systemd-bootchart.xml<br>
@@ -131,7 +131,9 @@<br>
                                 not graph the time elapsed since boot<br>
                                 and before systemd-bootchart was<br>
                                 started, as it may result in extremely<br>
-                                large graphs.  </para></listitem><br>
+                                large graphs. The time elapsed since boot<br>
+                                might also include any time that the system<br>
+                                was suspended.</para></listitem><br>
                         </varlistentry><br>
                 </variablelist><br>
         </refsect1><br>
diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c<br>
index cbfc28d..909ef46 100644<br>
--- a/src/bootchart/bootchart.c<br>
+++ b/src/bootchart/bootchart.c<br>
@@ -310,6 +310,7 @@ int main(int argc, char *argv[]) {<br>
         time_t t = 0;<br>
         int r;<br>
         struct rlimit rlim;<br>
+        bool has_procfs = false;<br>
<br>
         parse_conf();<br>
<br>
@@ -349,6 +350,8 @@ int main(int argc, char *argv[]) {<br>
<br>
         log_uptime();<br>
<br>
+        has_procfs = access("/proc/vmstat", F_OK) == 0;<br>
+<br>
         LIST_HEAD_INIT(head);<br>
<br>
         /* main program loop */<br>
@@ -385,11 +388,11 @@ int main(int argc, char *argv[]) {<br>
                                 parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);<br>
                 }<br>
<br>
-                /* wait for /proc to become available, discarding samples */<br>
-                if (graph_start <= 0.0)<br>
-                        log_uptime();<br>
-                else<br>
+                if (has_procfs)<br>
                         log_sample(samples, &sampledata);<br>
+                else<br>
+                        /* wait for /proc to become available, discarding samples */<br>
+                        has_procfs = access("/proc/vmstat", F_OK) == 0;<br>
<br>
                 sample_stop = gettime_ns();<br>
<br>
diff --git a/src/bootchart/store.c b/src/bootchart/store.c<br>
index e071983..cedcba8 100644<br>
--- a/src/bootchart/store.c<br>
+++ b/src/bootchart/store.c<br>
@@ -57,27 +57,22 @@ double gettime_ns(void) {<br>
         return (n.tv_sec + (n.tv_nsec / 1000000000.0));<br>
 }<br>
<br>
-void log_uptime(void) {<br>
-        _cleanup_fclose_ FILE *f = NULL;<br>
-        char str[32];<br>
-        double uptime;<br>
-<br>
-        f = fopen("/proc/uptime", "re");<br>
-<br>
-        if (!f)<br>
-                return;<br>
-        if (!fscanf(f, "%s %*s", str))<br>
-                return;<br>
-<br>
-        uptime = strtod(str, NULL);<br>
+static double gettime_up(void) {<br>
+        struct timespec n;<br>
<br>
-        log_start = gettime_ns();<br>
+        clock_gettime(CLOCK_BOOTTIME, &n);<br>
+        return (n.tv_sec + (n.tv_nsec / 1000000000.0));<br>
+}<br>
<br>
-        /* start graph at kernel boot time */<br>
+void log_uptime(void) {<br>
         if (arg_relative)<br>
-                graph_start = log_start;<br>
-        else<br>
+                graph_start = log_start = gettime_ns();<br>
+        else {<br>
+                double uptime = gettime_up();<br>
+<br>
+                log_start = gettime_ns();<br>
                 graph_start = log_start - uptime;<br>
+        }<br>
 }<br>
<br>
 static char *bufgetline(char *buf) {<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.9.3<br>
<br>
_______________________________________________<br>
systemd-devel mailing list<br>
<a href="mailto:systemd-devel@lists.freedesktop.org">systemd-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/systemd-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/systemd-devel</a><br>
</font></span></blockquote></div><br></div>