mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #9801 from yuwata/analyze-cleanups
analyze: several improvements
This commit is contained in:
commit
a9e241dcb3
@ -221,106 +221,48 @@ static void subtract_timestamp(usec_t *a, usec_t b) {
|
||||
}
|
||||
|
||||
static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
|
||||
static const struct bus_properties_map property_map[] = {
|
||||
{ "FirmwareTimestampMonotonic", "t", NULL, offsetof(struct boot_times, firmware_time) },
|
||||
{ "LoaderTimestampMonotonic", "t", NULL, offsetof(struct boot_times, loader_time) },
|
||||
{ "KernelTimestamp", "t", NULL, offsetof(struct boot_times, kernel_time) },
|
||||
{ "InitRDTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_time) },
|
||||
{ "UserspaceTimestampMonotonic", "t", NULL, offsetof(struct boot_times, userspace_time) },
|
||||
{ "FinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, finish_time) },
|
||||
{ "SecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_start_time) },
|
||||
{ "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_finish_time) },
|
||||
{ "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_start_time) },
|
||||
{ "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_finish_time) },
|
||||
{ "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_start_time) },
|
||||
{ "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_finish_time) },
|
||||
{ "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_start_time) },
|
||||
{ "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_finish_time) },
|
||||
{ "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_start_time) },
|
||||
{ "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_finish_time) },
|
||||
{ "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_start_time) },
|
||||
{ "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_finish_time) },
|
||||
{},
|
||||
};
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
static struct boot_times times;
|
||||
static bool cached = false;
|
||||
int r;
|
||||
|
||||
if (cached)
|
||||
goto finish;
|
||||
|
||||
assert_cc(sizeof(usec_t) == sizeof(uint64_t));
|
||||
|
||||
if (bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"FirmwareTimestampMonotonic",
|
||||
×.firmware_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"LoaderTimestampMonotonic",
|
||||
×.loader_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"KernelTimestamp",
|
||||
×.kernel_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"InitRDTimestampMonotonic",
|
||||
×.initrd_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"UserspaceTimestampMonotonic",
|
||||
×.userspace_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"FinishTimestampMonotonic",
|
||||
×.finish_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"SecurityStartTimestampMonotonic",
|
||||
×.security_start_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"SecurityFinishTimestampMonotonic",
|
||||
×.security_finish_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"GeneratorsStartTimestampMonotonic",
|
||||
×.generators_start_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"GeneratorsFinishTimestampMonotonic",
|
||||
×.generators_finish_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"UnitsLoadStartTimestampMonotonic",
|
||||
×.unitsload_start_time) < 0 ||
|
||||
bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"UnitsLoadFinishTimestampMonotonic",
|
||||
×.unitsload_finish_time) < 0)
|
||||
return -EIO;
|
||||
|
||||
(void) bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"InitRDSecurityStartTimestampMonotonic",
|
||||
×.initrd_security_start_time);
|
||||
(void) bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"InitRDSecurityFinishTimestampMonotonic",
|
||||
×.initrd_security_finish_time);
|
||||
(void) bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"InitRDGeneratorsStartTimestampMonotonic",
|
||||
×.initrd_generators_start_time);
|
||||
(void) bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"InitRDGeneratorsFinishTimestampMonotonic",
|
||||
×.initrd_generators_finish_time);
|
||||
(void) bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"InitRDUnitsLoadStartTimestampMonotonic",
|
||||
×.initrd_unitsload_start_time);
|
||||
(void) bus_get_uint64_property(bus,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"InitRDUnitsLoadFinishTimestampMonotonic",
|
||||
×.initrd_unitsload_finish_time);
|
||||
r = bus_map_all_properties(
|
||||
bus,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
property_map,
|
||||
BUS_MAP_STRDUP,
|
||||
&error,
|
||||
NULL,
|
||||
×);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get timestamp properties: %s", bus_error_message(&error, r));
|
||||
|
||||
if (times.finish_time <= 0) {
|
||||
log_error("Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n"
|
||||
@ -331,23 +273,23 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
if (arg_scope == UNIT_FILE_SYSTEM) {
|
||||
if (arg_scope == UNIT_FILE_SYSTEM && times.security_start_time > 0) {
|
||||
/* security_start_time is set when systemd is not running under container environment. */
|
||||
if (times.initrd_time > 0)
|
||||
times.kernel_done_time = times.initrd_time;
|
||||
else
|
||||
times.kernel_done_time = times.userspace_time;
|
||||
} else {
|
||||
/*
|
||||
* User-instance-specific timestamps processing
|
||||
* User-instance-specific or container-system-specific timestamps processing
|
||||
* (see comment to reverse_offset in struct boot_times).
|
||||
*/
|
||||
times.reverse_offset = times.userspace_time;
|
||||
|
||||
times.firmware_time = times.loader_time = times.kernel_time = times.initrd_time = times.userspace_time = 0;
|
||||
subtract_timestamp(×.finish_time, times.reverse_offset);
|
||||
times.firmware_time = times.loader_time = times.kernel_time = times.initrd_time = times.userspace_time =
|
||||
times.security_start_time = times.security_finish_time = 0;
|
||||
|
||||
subtract_timestamp(×.security_start_time, times.reverse_offset);
|
||||
subtract_timestamp(×.security_finish_time, times.reverse_offset);
|
||||
subtract_timestamp(×.finish_time, times.reverse_offset);
|
||||
|
||||
subtract_timestamp(×.generators_start_time, times.reverse_offset);
|
||||
subtract_timestamp(×.generators_finish_time, times.reverse_offset);
|
||||
@ -381,13 +323,20 @@ static void free_host_info(struct host_info *hi) {
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct host_info*, free_host_info);
|
||||
|
||||
static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
|
||||
static const struct bus_properties_map property_map[] = {
|
||||
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activating) },
|
||||
{ "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activated) },
|
||||
{ "ActiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivating) },
|
||||
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivated) },
|
||||
{},
|
||||
};
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r, c = 0;
|
||||
struct boot_times *boot_times = NULL;
|
||||
_cleanup_(unit_times_freep) struct unit_times *unit_times = NULL;
|
||||
size_t size = 0;
|
||||
struct boot_times *boot_times = NULL;
|
||||
size_t allocated = 0, c = 0;
|
||||
UnitInfo u;
|
||||
int r;
|
||||
|
||||
r = acquire_boot_times(bus, &boot_times);
|
||||
if (r < 0)
|
||||
@ -411,7 +360,7 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
|
||||
while ((r = bus_parse_unit_info(reply, &u)) > 0) {
|
||||
struct unit_times *t;
|
||||
|
||||
if (!GREEDY_REALLOC(unit_times, size, c+2))
|
||||
if (!GREEDY_REALLOC(unit_times, allocated, c+2))
|
||||
return log_oom();
|
||||
|
||||
unit_times[c+1].has_data = false;
|
||||
@ -420,23 +369,17 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
|
||||
|
||||
assert_cc(sizeof(usec_t) == sizeof(uint64_t));
|
||||
|
||||
if (bus_get_uint64_property(bus, u.unit_path,
|
||||
"org.freedesktop.systemd1.Unit",
|
||||
"InactiveExitTimestampMonotonic",
|
||||
&t->activating) < 0 ||
|
||||
bus_get_uint64_property(bus, u.unit_path,
|
||||
"org.freedesktop.systemd1.Unit",
|
||||
"ActiveEnterTimestampMonotonic",
|
||||
&t->activated) < 0 ||
|
||||
bus_get_uint64_property(bus, u.unit_path,
|
||||
"org.freedesktop.systemd1.Unit",
|
||||
"ActiveExitTimestampMonotonic",
|
||||
&t->deactivating) < 0 ||
|
||||
bus_get_uint64_property(bus, u.unit_path,
|
||||
"org.freedesktop.systemd1.Unit",
|
||||
"InactiveEnterTimestampMonotonic",
|
||||
&t->deactivated) < 0)
|
||||
return -EIO;
|
||||
r = bus_map_all_properties(
|
||||
bus,
|
||||
"org.freedesktop.systemd1",
|
||||
u.unit_path,
|
||||
property_map,
|
||||
BUS_MAP_STRDUP,
|
||||
&error,
|
||||
NULL,
|
||||
t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get timestamp properties of unit %s: %s", u.id, bus_error_message(&error, r));
|
||||
|
||||
subtract_timestamp(&t->activating, boot_times->reverse_offset);
|
||||
subtract_timestamp(&t->activated, boot_times->reverse_offset);
|
||||
@ -579,18 +522,21 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) {
|
||||
size = strpcpyf(&ptr, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), t->firmware_time - t->loader_time, USEC_PER_MSEC));
|
||||
if (t->loader_time > 0)
|
||||
size = strpcpyf(&ptr, size, "%s (loader) + ", format_timespan(ts, sizeof(ts), t->loader_time, USEC_PER_MSEC));
|
||||
if (t->kernel_time > 0)
|
||||
if (t->kernel_done_time > 0)
|
||||
size = strpcpyf(&ptr, size, "%s (kernel) + ", format_timespan(ts, sizeof(ts), t->kernel_done_time, USEC_PER_MSEC));
|
||||
if (t->initrd_time > 0)
|
||||
size = strpcpyf(&ptr, size, "%s (initrd) + ", format_timespan(ts, sizeof(ts), t->userspace_time - t->initrd_time, USEC_PER_MSEC));
|
||||
|
||||
size = strpcpyf(&ptr, size, "%s (userspace) ", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC));
|
||||
if (t->kernel_time > 0)
|
||||
if (t->kernel_done_time > 0)
|
||||
strpcpyf(&ptr, size, "= %s ", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC));
|
||||
|
||||
if (unit_id && activated_time > 0 && activated_time != USEC_INFINITY)
|
||||
size = strpcpyf(&ptr, size, "\n%s reached after %s in userspace", unit_id, format_timespan(ts, sizeof(ts), activated_time - t->userspace_time, USEC_PER_MSEC));
|
||||
else if (unit_id && activated_time == 0)
|
||||
if (unit_id && activated_time > 0 && activated_time != USEC_INFINITY) {
|
||||
if (t->userspace_time > 0)
|
||||
size = strpcpyf(&ptr, size, "\n%s reached after %s in userspace", unit_id, format_timespan(ts, sizeof(ts), activated_time - t->userspace_time, USEC_PER_MSEC));
|
||||
else
|
||||
size = strpcpyf(&ptr, size, "\n%s reached after %s in userspace", unit_id, format_timespan(ts, sizeof(ts), activated_time - t->reverse_offset, USEC_PER_MSEC));
|
||||
} else if (unit_id && activated_time == 0)
|
||||
size = strpcpyf(&ptr, size, "\n%s was never reached", unit_id);
|
||||
else if (unit_id && activated_time == USEC_INFINITY)
|
||||
size = strpcpyf(&ptr, size, "\nCould not get time to reach %s.", unit_id);
|
||||
@ -698,7 +644,7 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
if (boot->initrd_time > 0)
|
||||
m++;
|
||||
if (boot->kernel_time > 0)
|
||||
if (boot->kernel_done_time > 0)
|
||||
m++;
|
||||
|
||||
for (u = times; u->has_data; u++) {
|
||||
@ -798,7 +744,7 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
|
||||
svg_text(true, -(double) boot->loader_time, y, "loader");
|
||||
y++;
|
||||
}
|
||||
if (boot->kernel_time > 0) {
|
||||
if (boot->kernel_done_time > 0) {
|
||||
svg_bar("kernel", 0, boot->kernel_done_time, y);
|
||||
svg_text(true, 0, y, "kernel");
|
||||
y++;
|
||||
@ -823,7 +769,8 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
|
||||
svg_bar("active", boot->userspace_time, boot->finish_time, y);
|
||||
svg_bar("security", boot->security_start_time, boot->security_finish_time, y);
|
||||
if (boot->security_start_time > 0)
|
||||
svg_bar("security", boot->security_start_time, boot->security_finish_time, y);
|
||||
svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
|
||||
svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
|
||||
svg_text(true, boot->userspace_time, y, "systemd");
|
||||
@ -846,9 +793,11 @@ static int analyze_plot(int argc, char *argv[], void *userdata) {
|
||||
svg_bar("deactivating", 0, 300000, y);
|
||||
svg_text(true, 400000, y, "Deactivating");
|
||||
y++;
|
||||
svg_bar("security", 0, 300000, y);
|
||||
svg_text(true, 400000, y, "Setting up security module");
|
||||
y++;
|
||||
if (boot->security_start_time > 0) {
|
||||
svg_bar("security", 0, 300000, y);
|
||||
svg_text(true, 400000, y, "Setting up security module");
|
||||
y++;
|
||||
}
|
||||
svg_bar("generators", 0, 300000, y);
|
||||
svg_text(true, 400000, y, "Generators");
|
||||
y++;
|
||||
|
@ -53,6 +53,27 @@ typedef enum StatusType {
|
||||
STATUS_TYPE_EMERGENCY,
|
||||
} StatusType;
|
||||
|
||||
/* Notes:
|
||||
* 1. TIMESTAMP_FIRMWARE, TIMESTAMP_LOADER, TIMESTAMP_KERNEL, TIMESTAMP_INITRD,
|
||||
* TIMESTAMP_SECURITY_START, and TIMESTAMP_SECURITY_FINISH are set only when
|
||||
* the manager is system and not running under container environment.
|
||||
*
|
||||
* 2. The monotonic timestamp of TIMESTAMP_KERNEL is always zero.
|
||||
*
|
||||
* 3. The realtime timestamp of TIMESTAMP_KERNEL will be unset if the system does not
|
||||
* have RTC.
|
||||
*
|
||||
* 4. TIMESTAMP_FIRMWARE and TIMESTAMP_LOADER will be unset if the system does not
|
||||
* have RTC, or systemd is built without EFI support.
|
||||
*
|
||||
* 5. The monotonic timestamps of TIMESTAMP_FIRMWARE and TIMESTAMP_LOADER are stored as
|
||||
* negative of the actual value.
|
||||
*
|
||||
* 6. TIMESTAMP_USERSPACE is the timestamp of when the manager was started.
|
||||
*
|
||||
* 7. TIMESTAMP_INITRD_* are set only when the system is booted with an initrd.
|
||||
*/
|
||||
|
||||
typedef enum ManagerTimestamp {
|
||||
MANAGER_TIMESTAMP_FIRMWARE,
|
||||
MANAGER_TIMESTAMP_LOADER,
|
||||
|
Loading…
Reference in New Issue
Block a user