diff options
Diffstat (limited to 'src/analyze')
-rw-r--r-- | src/analyze/analyze.c | 116 |
1 files changed, 73 insertions, 43 deletions
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index aab61e4de3..2d65fdbdb8 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -80,7 +80,7 @@ static usec_t arg_fuzz = 0; static bool arg_no_pager = false; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static const char *arg_host = NULL; -static bool arg_user = false; +static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; static bool arg_man = true; static bool arg_generators = false; @@ -132,10 +132,12 @@ struct host_info { }; static int acquire_bus(bool need_full_bus, sd_bus **bus) { + bool user = arg_scope != UNIT_FILE_SYSTEM; + if (need_full_bus) - return bus_connect_transport(arg_transport, arg_host, arg_user, bus); + return bus_connect_transport(arg_transport, arg_host, user, bus); else - return bus_connect_transport_systemd(arg_transport, arg_host, arg_user, bus); + return bus_connect_transport_systemd(arg_transport, arg_host, user, bus); } static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) { @@ -294,7 +296,12 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) { return -EINPROGRESS; } - if (arg_user) { + if (arg_scope == UNIT_FILE_SYSTEM) { + 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 * (see comment to reverse_offset in struct boot_times). @@ -312,11 +319,6 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) { subtract_timestamp(×.unitsload_start_time, times.reverse_offset); subtract_timestamp(×.unitsload_finish_time, times.reverse_offset); - } else { - if (times.initrd_time) - times.kernel_done_time = times.initrd_time; - else - times.kernel_done_time = times.userspace_time; } cached = true; @@ -439,8 +441,7 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) { return c; fail: - if (unit_times) - free_unit_times(unit_times, (unsigned) c); + free_unit_times(unit_times, (unsigned) c); return r; } @@ -537,11 +538,11 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) { size = sizeof(buf); size = strpcpyf(&ptr, size, "Startup finished in "); - if (t->firmware_time) + if (t->firmware_time > 0) size = strpcpyf(&ptr, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), t->firmware_time - t->loader_time, USEC_PER_MSEC)); - if (t->loader_time) + 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) + if (t->kernel_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)); @@ -550,7 +551,7 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) { if (t->kernel_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)) + 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) size = strpcpyf(&ptr, size, "\n%s was never reached", unit_id); @@ -629,14 +630,14 @@ static int analyze_plot(int argc, char *argv[], void *userdata) { if (boot->firmware_time > boot->loader_time) m++; - if (boot->loader_time) { + if (boot->loader_time > 0) { m++; if (width < 1000.0) width = 1000.0; } - if (boot->initrd_time) + if (boot->initrd_time > 0) m++; - if (boot->kernel_time) + if (boot->kernel_time > 0) m++; for (u = times; u < times + n; u++) { @@ -725,22 +726,22 @@ static int analyze_plot(int argc, char *argv[], void *userdata) { svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time)); svg_graph_box(m, -(double) boot->firmware_time, boot->finish_time); - if (boot->firmware_time) { + if (boot->firmware_time > 0) { svg_bar("firmware", -(double) boot->firmware_time, -(double) boot->loader_time, y); svg_text(true, -(double) boot->firmware_time, y, "firmware"); y++; } - if (boot->loader_time) { + if (boot->loader_time > 0) { svg_bar("loader", -(double) boot->loader_time, 0, y); svg_text(true, -(double) boot->loader_time, y, "loader"); y++; } - if (boot->kernel_time) { + if (boot->kernel_time > 0) { svg_bar("kernel", 0, boot->kernel_done_time, y); svg_text(true, 0, y, "kernel"); y++; } - if (boot->initrd_time) { + if (boot->initrd_time > 0) { svg_bar("initrd", boot->initrd_time, boot->userspace_time, y); svg_text(true, boot->initrd_time, y, "initrd"); y++; @@ -818,7 +819,7 @@ static int list_dependencies_print(const char *name, unsigned int level, unsigne printf("%s", special_glyph(last ? TREE_RIGHT : TREE_BRANCH)); if (times) { - if (times->time) + if (times->time > 0) printf("%s%s @%s +%s%s", ansi_highlight_red(), name, format_timespan(ts, sizeof(ts), times->activating - boot->userspace_time, USEC_PER_MSEC), format_timespan(ts2, sizeof(ts2), times->time, USEC_PER_MSEC), ansi_normal()); @@ -864,6 +865,11 @@ static int list_dependencies_compare(const void *_a, const void *_b) { return usb - usa; } +static bool times_in_range(const struct unit_times *times, const struct boot_times *boot) { + return times && + times->activated > 0 && times->activated <= boot->finish_time; +} + static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int level, char ***units, unsigned int branches) { _cleanup_strv_free_ char **deps = NULL; @@ -889,11 +895,9 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev STRV_FOREACH(c, deps) { times = hashmap_get(unit_times_hashmap, *c); - if (times - && times->activated - && times->activated <= boot->finish_time - && (times->activated >= service_longest - || service_longest == 0)) { + if (times_in_range(times, boot) && + (times->activated >= service_longest + || service_longest == 0)) { service_longest = times->activated; break; } @@ -904,7 +908,8 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev STRV_FOREACH(c, deps) { times = hashmap_get(unit_times_hashmap, *c); - if (times && times->activated && times->activated <= boot->finish_time && (service_longest - times->activated) <= arg_fuzz) + if (times_in_range(times, boot) && + service_longest - times->activated <= arg_fuzz) to_print++; } @@ -913,10 +918,8 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev STRV_FOREACH(c, deps) { times = hashmap_get(unit_times_hashmap, *c); - if (!times - || !times->activated - || times->activated > boot->finish_time - || service_longest - times->activated > arg_fuzz) + if (!times_in_range(times, boot) || + service_longest - times->activated > arg_fuzz) continue; to_print--; @@ -938,7 +941,7 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev if (r < 0) return r; - if (!to_print) + if (to_print == 0) break; } return 0; @@ -1414,6 +1417,21 @@ static int get_or_set_log_target(int argc, char *argv[], void *userdata) { return (argc == 1) ? get_log_target(argc, argv, userdata) : set_log_target(argc, argv, userdata); } +static int dump_unit_paths(int argc, char *argv[], void *userdata) { + _cleanup_lookup_paths_free_ LookupPaths paths = {}; + int r; + char **p; + + r = lookup_paths_init(&paths, arg_scope, 0, NULL); + if (r < 0) + return log_error_errno(r, "lookup_paths_init() failed: %m"); + + STRV_FOREACH(p, paths.search_path) + puts(*p); + + return 0; +} + #if HAVE_SECCOMP static void dump_syscall_filter(const SyscallFilterSet *set) { const char *syscall; @@ -1584,10 +1602,7 @@ static int service_watchdogs(int argc, char *argv[], void *userdata) { } static int do_verify(int argc, char *argv[], void *userdata) { - return verify_units(strv_skip(argv, 1), - arg_user ? UNIT_FILE_USER : UNIT_FILE_SYSTEM, - arg_man, - arg_generators); + return verify_units(strv_skip(argv, 1), arg_scope, arg_man, arg_generators); } static int help(int argc, char *argv[], void *userdata) { @@ -1601,6 +1616,7 @@ static int help(int argc, char *argv[], void *userdata) { " --no-pager Do not pipe output into a pager\n" " --system Operate on system systemd instance\n" " --user Operate on user systemd instance\n" + " --global Operate on global user configuration\n" " -H --host=[USER@]HOST Operate on remote host\n" " -M --machine=CONTAINER Operate on local container\n" " --order Show only order in the graph\n" @@ -1620,6 +1636,7 @@ static int help(int argc, char *argv[], void *userdata) { " log-level [LEVEL] Get/set logging threshold for manager\n" " log-target [TARGET] Get/set logging target for manager\n" " dump Output state serialization of service manager\n" + " unit-paths List load directories for units\n" " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" " verify FILE... Check unit files for correctness\n" " calendar SPEC... Validate repetitive calendar time events\n" @@ -1638,8 +1655,9 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_ORDER, ARG_REQUIRE, - ARG_USER, ARG_SYSTEM, + ARG_USER, + ARG_GLOBAL, ARG_DOT_FROM_PATTERN, ARG_DOT_TO_PATTERN, ARG_FUZZ, @@ -1653,8 +1671,9 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "order", no_argument, NULL, ARG_ORDER }, { "require", no_argument, NULL, ARG_REQUIRE }, - { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, + { "user", no_argument, NULL, ARG_USER }, + { "global", no_argument, NULL, ARG_GLOBAL }, { "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN }, { "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN }, { "fuzz", required_argument, NULL, ARG_FUZZ }, @@ -1680,12 +1699,16 @@ static int parse_argv(int argc, char *argv[]) { case ARG_VERSION: return version(); + case ARG_SYSTEM: + arg_scope = UNIT_FILE_SYSTEM; + break; + case ARG_USER: - arg_user = true; + arg_scope = UNIT_FILE_USER; break; - case ARG_SYSTEM: - arg_user = false; + case ARG_GLOBAL: + arg_scope = UNIT_FILE_GLOBAL; break; case ARG_ORDER: @@ -1763,6 +1786,12 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option code."); } + if (arg_scope == UNIT_FILE_GLOBAL && + !STR_IN_SET(argv[optind] ?: "time", "dot", "unit-paths", "verify")) { + log_error("Option --global only makes sense with verbs dot, unit-paths, verify."); + return -EINVAL; + } + return 1; /* work to do */ } @@ -1783,6 +1812,7 @@ int main(int argc, char *argv[]) { { "set-log-target", 2, 2, 0, set_log_target }, { "get-log-target", VERB_ANY, 1, 0, get_log_target }, { "dump", VERB_ANY, 1, 0, dump }, + { "unit-paths", 1, 1, 0, dump_unit_paths }, { "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters }, { "verify", 2, VERB_ANY, 0, do_verify }, { "calendar", 2, VERB_ANY, 0, test_calendar }, |