summaryrefslogtreecommitdiff
path: root/src/analyze
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyze')
-rw-r--r--src/analyze/analyze.c116
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(&times.unitsload_start_time, times.reverse_offset);
subtract_timestamp(&times.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 },