From e9ddabc246ced239cbce436e16792dc4c3d1b52d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 8 Nov 2010 00:31:09 -0500 Subject: [PATCH] manager: parse RD_TIMESTAMP passed from initrd --- .gitignore | 1 + Makefile.am | 12 +++++++++++- src/dbus-manager.c | 3 +++ src/main.c | 30 ++++++++++++++++++++++++++++-- src/manager.c | 36 +++++++++++++++++++++++++----------- src/manager.h | 1 + src/timestamp.c | 39 +++++++++++++++++++++++++++++++++++++++ src/util.c | 19 ++++++++++++++++++- src/util.h | 2 ++ 9 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 src/timestamp.c diff --git a/.gitignore b/.gitignore index 42237888..a99cd174 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +systemd-timestamp systemd-cryptsetup systemd-cryptsetup-generator systemd-tty-ask-password-agent diff --git a/Makefile.am b/Makefile.am index 3371c597..52bd13fe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/src/dbus-manager.c b/src/dbus-manager.c index c1950319..769035f6 100644 --- a/src/dbus-manager.c +++ b/src/dbus-manager.c @@ -150,7 +150,9 @@ #define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \ " \n" \ " \n" \ + " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \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 }, diff --git a/src/main.c b/src/main.c index f7d76a29..cd73ee2c 100644 --- a/src/main.c +++ b/src/main.c @@ -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); diff --git a/src/manager.c b/src/manager.c index c7de1ea9..d690a0f1 100644 --- a/src/manager.c +++ b/src/manager.c @@ -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)); diff --git a/src/manager.h b/src/manager.h index 8a647505..ab7f2636 100644 --- a/src/manager.h +++ b/src/manager.h @@ -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 index 00000000..ce514294 --- /dev/null +++ b/src/timestamp.c @@ -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 . +***/ + +#include + +#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; +} diff --git a/src/util.c b/src/util.c index 6f9399b4..f41861b6 100644 --- a/src/util.c +++ b/src/util.c @@ -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", diff --git a/src/util.h b/src/util.h index b7ef51e2..5567da85 100644 --- a/src/util.h +++ b/src/util.h @@ -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) -- 2.39.5