chiark / gitweb /
manager: parse RD_TIMESTAMP passed from initrd
authorLennart Poettering <lennart@poettering.net>
Mon, 8 Nov 2010 05:31:09 +0000 (00:31 -0500)
committerLennart Poettering <lennart@poettering.net>
Wed, 10 Nov 2010 21:38:44 +0000 (22:38 +0100)
.gitignore
Makefile.am
src/dbus-manager.c
src/main.c
src/manager.c
src/manager.h
src/timestamp.c [new file with mode: 0644]
src/util.c
src/util.h

index 4223788..a99cd17 100644 (file)
@@ -1,3 +1,4 @@
+systemd-timestamp
 systemd-cryptsetup
 systemd-cryptsetup-generator
 systemd-tty-ask-password-agent
index 3371c59..52bd13f 100644 (file)
@@ -115,7 +115,8 @@ rootlibexec_PROGRAMS = \
        systemd-fsck \
        systemd-quotacheck \
        systemd-cryptsetup \
-       systemd-cryptsetup-generator
+       systemd-cryptsetup-generator \
+       systemd-timestamp
 
 noinst_PROGRAMS = \
        test-engine \
@@ -714,6 +715,15 @@ systemd_quotacheck_CFLAGS = \
 systemd_quotacheck_LDADD = \
        libsystemd-basic.la
 
+systemd_timestamp_SOURCES = \
+       src/timestamp.c
+
+systemd_timestamp_CFLAGS = \
+       $(AM_CFLAGS)
+
+systemd_timestamp_LDADD = \
+       libsystemd-basic.la
+
 systemd_cryptsetup_SOURCES = \
        src/cryptsetup.c
 
index c195031..769035f 100644 (file)
 #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL                        \
         "  <property name=\"Version\" type=\"s\" access=\"read\"/>\n"   \
         "  <property name=\"RunningAs\" type=\"s\" access=\"read\"/>\n" \
+        "  <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"LogLevel\" type=\"s\" access=\"read\"/>\n"  \
         "  <property name=\"LogTarget\" type=\"s\" access=\"read\"/>\n" \
         "  <property name=\"NNames\" type=\"u\" access=\"read\"/>\n"    \
@@ -300,6 +302,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
         const BusProperty properties[] = {
                 { "org.freedesktop.systemd1.Manager", "Version",       bus_property_append_string,    "s",  PACKAGE_STRING     },
                 { "org.freedesktop.systemd1.Manager", "RunningAs",     bus_manager_append_running_as, "s",  &m->running_as     },
+                { "org.freedesktop.systemd1.Manager", "InitRDTimestamp", bus_property_append_uint64,  "t",  &m->initrd_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "StartupTimestamp", bus_property_append_uint64, "t",  &m->startup_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "FinishTimestamp", bus_property_append_uint64,  "t",  &m->finish_timestamp.realtime },
                 { "org.freedesktop.systemd1.Manager", "LogLevel",      bus_manager_append_log_level,  "s",  NULL               },
index f7d76a2..cd73ee2 100644 (file)
@@ -871,12 +871,31 @@ fail:
         return r;
 }
 
+static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
+        const char *e;
+        unsigned long long a, b;
+
+        assert(t);
+
+        if (!(e = getenv("RD_TIMESTAMP")))
+                return NULL;
+
+        if (sscanf(e, "%llu %llu", &a, &b) != 2)
+                return NULL;
+
+        t->realtime = (usec_t) a;
+        t->monotonic = (usec_t) b;
+
+        return t;
+}
+
 int main(int argc, char *argv[]) {
         Manager *m = NULL;
         int r, retval = EXIT_FAILURE;
         FDSet *fds = NULL;
         bool reexecute = false;
         const char *shutdown_verb = NULL;
+        dual_timestamp initrd_timestamp = { 0ULL, 0ULL };
 
         if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
                 /* This is compatbility support for SysV, where
@@ -965,9 +984,13 @@ int main(int argc, char *argv[]) {
                "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                arg_running_as == MANAGER_SYSTEM);
 
-        /* Unset some environment variables passed in from the kernel
-         * that don't really make sense for us. */
         if (arg_running_as == MANAGER_SYSTEM) {
+                /* Parse the data passed to us by the initrd and unset it */
+                parse_initrd_timestamp(&initrd_timestamp);
+                filter_environ("RD_");
+
+                /* Unset some environment variables passed in from the
+                 * kernel that don't really make sense for us. */
                 unsetenv("HOME");
                 unsetenv("TERM");
         }
@@ -1030,6 +1053,9 @@ int main(int argc, char *argv[]) {
         m->mount_auto = arg_mount_auto;
         m->swap_auto = arg_swap_auto;
 
+        if (dual_timestamp_is_set(&initrd_timestamp))
+                m->initrd_timestamp = initrd_timestamp;
+
         if (arg_console)
                 manager_set_console(m, arg_console);
 
index c7de1ea..d690a0f 100644 (file)
@@ -2501,6 +2501,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
+        dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
         dual_timestamp_serialize(f, "startup-timestamp", &m->startup_timestamp);
         dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
 
@@ -2555,7 +2556,9 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                 if (l[0] == 0)
                         break;
 
-                if (startswith(l, "startup-timestamp="))
+                if (startswith(l, "initrd-timestamp="))
+                        dual_timestamp_deserialize(l+17, &m->initrd_timestamp);
+                else if (startswith(l, "startup-timestamp="))
                         dual_timestamp_deserialize(l+18, &m->startup_timestamp);
                 else if (startswith(l, "finish-timestamp="))
                         dual_timestamp_deserialize(l+17, &m->finish_timestamp);
@@ -2715,7 +2718,7 @@ bool manager_unit_pending_inactive(Manager *m, const char *name) {
 }
 
 void manager_check_finished(Manager *m) {
-        char userspace[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
+        char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
 
         assert(m);
 
@@ -2727,15 +2730,26 @@ void manager_check_finished(Manager *m) {
 
         dual_timestamp_get(&m->finish_timestamp);
 
-        if (m->running_as == MANAGER_SYSTEM)
-                log_info("Startup finished in %s (kernel) + %s (userspace) = %s.",
-                         format_timespan(kernel, sizeof(kernel),
-                                         m->startup_timestamp.monotonic),
-                         format_timespan(userspace, sizeof(userspace),
-                                         m->finish_timestamp.monotonic - m->startup_timestamp.monotonic),
-                         format_timespan(sum, sizeof(sum),
-                                         m->finish_timestamp.monotonic));
-        else
+        if (m->running_as == MANAGER_SYSTEM) {
+                if (dual_timestamp_is_set(&m->initrd_timestamp)) {
+                        log_info("Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
+                                 format_timespan(kernel, sizeof(kernel),
+                                                 m->initrd_timestamp.monotonic),
+                                 format_timespan(initrd, sizeof(initrd),
+                                                 m->startup_timestamp.monotonic - m->initrd_timestamp.monotonic),
+                                 format_timespan(userspace, sizeof(userspace),
+                                                 m->finish_timestamp.monotonic - m->startup_timestamp.monotonic),
+                                 format_timespan(sum, sizeof(sum),
+                                                 m->finish_timestamp.monotonic));
+                } else
+                        log_info("Startup finished in %s (kernel) + %s (userspace) = %s.",
+                                 format_timespan(kernel, sizeof(kernel),
+                                                 m->startup_timestamp.monotonic),
+                                 format_timespan(userspace, sizeof(userspace),
+                                                 m->finish_timestamp.monotonic - m->startup_timestamp.monotonic),
+                                 format_timespan(sum, sizeof(sum),
+                                                 m->finish_timestamp.monotonic));
+        } else
                 log_debug("Startup finished in %s.",
                           format_timespan(userspace, sizeof(userspace),
                                           m->finish_timestamp.monotonic - m->startup_timestamp.monotonic));
index 8a64750..ab7f263 100644 (file)
@@ -143,6 +143,7 @@ struct Manager {
 
         char **environment;
 
+        dual_timestamp initrd_timestamp;
         dual_timestamp startup_timestamp;
         dual_timestamp finish_timestamp;
 
diff --git a/src/timestamp.c b/src/timestamp.c
new file mode 100644 (file)
index 0000000..ce51429
--- /dev/null
@@ -0,0 +1,39 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd 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; either version 2 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
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[]) {
+        struct dual_timestamp t;
+
+        /* This is mostly useful for stuff like init ram disk scripts
+         * which want to take a proper timestamp to do minimal bootup
+         * profiling. */
+
+        dual_timestamp_get(&t);
+        printf("%llu %llu\n",
+               (unsigned long long) t.realtime,
+               (unsigned long long) t.monotonic);
+
+        return 0;
+}
index 6f9399b..f41861b 100644 (file)
@@ -3566,7 +3566,6 @@ void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
         }
 }
 
-
 char *fstab_node_to_udev_node(const char *p) {
         char *dn, *t, *u;
         int r;
@@ -3617,6 +3616,24 @@ char *fstab_node_to_udev_node(const char *p) {
         return strdup(p);
 }
 
+void filter_environ(const char *prefix) {
+        int i, j;
+        assert(prefix);
+
+        if (!environ)
+                return;
+
+        for (i = 0, j = 0; environ[i]; i++) {
+
+                if (startswith(environ[i], prefix))
+                        continue;
+
+                environ[j++] = environ[i];
+        }
+
+        environ[j] = NULL;
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
index b7ef51e..5567da8 100644 (file)
@@ -372,6 +372,8 @@ void dual_timestamp_deserialize(const char *value, dual_timestamp *t);
 
 char *fstab_node_to_udev_node(const char *p);
 
+void filter_environ(const char *prefix);
+
 #define NULSTR_FOREACH(i, l)                                    \
         for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)