]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
analyze: extend the dump command to accept patterns
authorFranck Bui <fbui@suse.com>
Tue, 13 Sep 2022 14:13:16 +0000 (16:13 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 12 Oct 2022 22:47:42 +0000 (07:47 +0900)
The new function DumpPatterns() can be used to limit (drastically) the size of
the data returned by PID1. Hence the optimization of serializing data into a
file descriptor should be less relevant than having the possibility to limit
the data when communicating with the service manager remotely.

NB: when passing patterns, the dump command omits the version of the manager as
well as the features and the timestamps.

13 files changed:
man/org.freedesktop.systemd1.xml
man/systemd-analyze.xml
shell-completion/bash/systemd-analyze
src/analyze/analyze-dump.c
src/analyze/analyze.c
src/core/dbus-manager.c
src/core/execute.c
src/core/fuzz-unit-file.c
src/core/manager-dump.c
src/core/manager-dump.h
src/core/manager.c
src/core/org.freedesktop.systemd1.conf
src/test/test-engine.c

index 6127541f8bf96165d189e22dfc6cb4a77058ec53..9fb215a136e1b777da8405ee2f859f29ada6833f 100644 (file)
@@ -162,6 +162,8 @@ node /org/freedesktop/systemd1 {
       Subscribe();
       Unsubscribe();
       Dump(out s output);
+      DumpPatterns(in  as patterns,
+                   out s output);
       DumpByFileDescriptor(out h fd);
       Reload();
       @org.freedesktop.DBus.Method.NoReply("true")
@@ -868,6 +870,8 @@ node /org/freedesktop/systemd1 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="Dump()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="DumpPatterns()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="DumpByFileDescriptor()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="Reload()"/>
@@ -1338,7 +1342,9 @@ node /org/freedesktop/systemd1 {
       string guaranteed, and new fields may be added any time, and old fields removed. The general structure
       may be rearranged drastically between releases. This is exposed by
       <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
-      <command>dump</command> command. The <function>DumpByFileDescriptor()</function> method is identical to
+      <command>dump</command> command. Similarly, <function>DumpPatterns()</function> returns the internal
+      state of units whose names match the glob expressions specified in the <varname>patterns</varname>
+      argument. The <function>DumpByFileDescriptor()</function> method is identical to
       <function>Dump()</function> but returns the data serialized into a file descriptor (the client should
       read the text data from it until hitting EOF). Given the size limits on D-Bus messages and the possibly
       large size of the returned string, <function>DumpByFileDescriptor()</function> is usually the
index 13b881cfc71d67681e22cfd16f9e7b091a5c0b3b..cce08fa121800c7eb6fbcd99fa40766efa31f3a2 100644 (file)
@@ -43,6 +43,7 @@
       <command>systemd-analyze</command>
       <arg choice="opt" rep="repeat">OPTIONS</arg>
       <arg choice="plain">dump</arg>
+      <arg choice="opt" rep="repeat"><replaceable>PATTERN</replaceable></arg>
     </cmdsynopsis>
 
     <cmdsynopsis>
@@ -243,10 +244,12 @@ multi-user.target @47.820s
     </refsect2>
 
     <refsect2>
-      <title><command>systemd-analyze dump</command></title>
+      <title><command>systemd-analyze dump [<replaceable>pattern</replaceable>…]</command></title>
 
-      <para>This command outputs a (usually very long) human-readable serialization of the complete server
-      state. Its format is subject to change without notice and should not be parsed by applications.</para>
+      <para>Without any parameter, this command outputs a (usually very long) human-readable serialization of
+      the complete service manager state. Optional glob pattern may be specified, causing the output to be
+      limited to units whose names match one of the patterns. The output format is subject to change without
+      notice and should not be parsed by applications.</para>
 
       <example>
         <title>Show the internal state of user manager</title>
index 9fe984d87c5ecd57eafd878fa1b9cfbe501767de..fe2c1d122c1ca0ca30da9e6d4a0c9d4b04d2e3ce 100644 (file)
@@ -60,9 +60,10 @@ _systemd_analyze() {
     )
 
     local -A VERBS=(
-        [STANDALONE]='time blame plot dump unit-paths exit-status calendar timestamp timespan'
+        [STANDALONE]='time blame plot unit-paths exit-status calendar timestamp timespan'
         [CRITICAL_CHAIN]='critical-chain'
         [DOT]='dot'
+        [DUMP]='dump'
         [VERIFY]='verify'
         [SECCOMP_FILTER]='syscall-filter'
         [CAT_CONFIG]='cat-config'
@@ -125,6 +126,13 @@ _systemd_analyze() {
             comps='--help --version --system --user --global --from-pattern --to-pattern --order --require'
         fi
 
+    elif __contains_word "$verb" ${VERBS[DUMP]}; then
+        if [[ $cur = -* ]]; then
+            comps='--help --version --system --user --no-pager'
+        else
+            comps=$( __get_units_all )
+        fi
+
     elif __contains_word "$verb" ${VERBS[SECCOMP_FILTER]}; then
         if [[ $cur = -* ]]; then
             comps='--help --version --no-pager'
index 448ce09bd78cffe1752ddc27e69d756469685264..220218e2feaba457c62e906baa1a4fb6b9f4fa73 100644 (file)
@@ -29,6 +29,46 @@ static int dump_fallback(sd_bus *bus) {
         return 0;
 }
 
+static int dump_patterns(sd_bus *bus, char **patterns) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
+        _cleanup_strv_free_ char **mangled = NULL;
+        const char *text;
+        int r;
+
+        r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "DumpPatterns");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        STRV_FOREACH(pattern, patterns) {
+                char *t;
+
+                r = unit_name_mangle_with_suffix(*pattern, NULL, UNIT_NAME_MANGLE_GLOB, ".service", &t);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to mangle name: %m");
+
+                r = strv_consume(&mangled, t);
+                if (r < 0)
+                        return log_oom();
+        }
+
+        r = sd_bus_message_append_strv(m, mangled);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_call(bus, m, 0, &error, &reply);
+        if (r < 0)
+                return log_error_errno(r, "Failed to issue method call DumpPatterns: %s",
+                                       bus_error_message(&error, r));
+
+        r = sd_bus_message_read(reply, "s", &text);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        fputs(text, stdout);
+        return r;
+}
+
 int verb_dump(int argc, char *argv[], void *userdata) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -42,6 +82,9 @@ int verb_dump(int argc, char *argv[], void *userdata) {
 
         pager_open(arg_pager_flags);
 
+        if (argc > 1)
+                return dump_patterns(bus, strv_skip(argv, 1));
+
         if (!sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD))
                 return dump_fallback(bus);
 
index 6215f50faca193ed257b464406b1600e61f96efa..4a276f66ba133f30dbe19925296583567d1b1826 100644 (file)
@@ -190,7 +190,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "  plot                       Output SVG graphic showing service\n"
                "                             initialization\n"
                "  dot [UNIT...]              Output dependency graph in %s format\n"
-               "  dump                       Output state serialization of service\n"
+               "  dump [PATTERN...]          Output state serialization of service\n"
                "                             manager\n"
                "  cat-config                 Show configuration file and drop-ins\n"
                "  unit-files                 List files and symlinks for units\n"
@@ -557,7 +557,7 @@ static int run(int argc, char *argv[]) {
                 { "get-log-target",    VERB_ANY, 1,        0,            verb_log_control       },
                 { "service-watchdogs", VERB_ANY, 2,        0,            verb_service_watchdogs },
                 /* ↑ … until here ↑ */
-                { "dump",              VERB_ANY, 1,        0,            verb_dump              },
+                { "dump",              VERB_ANY, VERB_ANY, 0,            verb_dump              },
                 { "cat-config",        2,        VERB_ANY, 0,            verb_cat_config        },
                 { "unit-files",        VERB_ANY, VERB_ANY, 0,            verb_unit_files        },
                 { "unit-paths",        1,        1,        0,            verb_unit_paths        },
index 473c0bc5abbc8ac68c4b35949a9948c5481a970e..73f739b12dcf6da57bff330110157acfa9bbd5db 100644 (file)
@@ -1344,7 +1344,13 @@ static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_er
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int dump_impl(sd_bus_message *message, void *userdata, sd_bus_error *error, int (*reply)(sd_bus_message *, char *)) {
+static int dump_impl(
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error,
+                char **patterns,
+                int (*reply)(sd_bus_message *, char *)) {
+
         _cleanup_free_ char *dump = NULL;
         Manager *m = ASSERT_PTR(userdata);
         int r;
@@ -1357,7 +1363,7 @@ static int dump_impl(sd_bus_message *message, void *userdata, sd_bus_error *erro
         if (r < 0)
                 return r;
 
-        r = manager_get_dump_string(m, &dump);
+        r = manager_get_dump_string(m, patterns, &dump);
         if (r < 0)
                 return r;
 
@@ -1369,7 +1375,7 @@ static int reply_dump(sd_bus_message *message, char *dump) {
 }
 
 static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return dump_impl(message, userdata, error, reply_dump);
+        return dump_impl(message, userdata, error, NULL, reply_dump);
 }
 
 static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
@@ -1383,7 +1389,18 @@ static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
 }
 
 static int method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return dump_impl(message, userdata, error, reply_dump_by_fd);
+        return dump_impl(message, userdata, error, NULL, reply_dump_by_fd);
+}
+
+static int method_dump_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_strv_free_ char **patterns = NULL;
+        int r;
+
+        r = sd_bus_message_read_strv(message, &patterns);
+        if (r < 0)
+                return r;
+
+        return dump_impl(message, userdata, error, patterns, reply_dump);
 }
 
 static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -3010,6 +3027,11 @@ const sd_bus_vtable bus_manager_vtable[] = {
                                 SD_BUS_RESULT("s", output),
                                 method_dump,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("DumpPatterns",
+                                SD_BUS_ARGS("as", patterns),
+                                SD_BUS_RESULT("s", output),
+                                method_dump_patterns,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("DumpByFileDescriptor",
                                 SD_BUS_NO_ARGS,
                                 SD_BUS_RESULT("h", fd),
index 86d238b57d9bd3331fa54ebfaf163e0514470272..b5b7de6d2a008178b25740b094c6fed73c75486d 100644 (file)
@@ -919,7 +919,7 @@ static int ask_for_confirmation(const ExecContext *context, const char *vc, Unit
                                u->id, u->description, cmdline);
                         continue; /* ask again */
                 case 'j':
-                        manager_dump_jobs(u->manager, stdout, "  ");
+                        manager_dump_jobs(u->manager, stdout, /* patterns= */ NULL, "  ");
                         continue; /* ask again */
                 case 'n':
                         /* 'n' was removed in favor of 'f'. */
index 058be6aa74d65586540a09d9f9d88b11fe1c2729..7b393386ffc1bb105cc6472ffa830255166272ed 100644 (file)
@@ -83,7 +83,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         assert_se(g);
 
         unit_dump(u, g, "");
-        manager_dump(m, g, ">>>");
+        manager_dump(m, g, /* patterns= */ NULL, ">>>");
 
         return 0;
 }
index 61717d8006f76356bcb22997137500003a5278b8..5a92356d487e7124b9026f617350e2b4471d365c 100644 (file)
@@ -7,31 +7,40 @@
 #include "manager-dump.h"
 #include "unit-serialize.h"
 
-void manager_dump_jobs(Manager *s, FILE *f, const char *prefix) {
+void manager_dump_jobs(Manager *s, FILE *f, char **patterns, const char *prefix) {
         Job *j;
 
         assert(s);
         assert(f);
 
-        HASHMAP_FOREACH(j, s->jobs)
+        HASHMAP_FOREACH(j, s->jobs) {
+
+                if (!strv_fnmatch_or_empty(patterns, j->unit->id, FNM_NOESCAPE))
+                        continue;
+
                 job_dump(j, f, prefix);
+        }
 }
 
-void manager_dump_units(Manager *s, FILE *f, const char *prefix) {
+void manager_dump_units(Manager *s, FILE *f, char **patterns, const char *prefix) {
         Unit *u;
         const char *t;
 
         assert(s);
         assert(f);
 
-        HASHMAP_FOREACH_KEY(u, t, s->units)
-                if (u->id == t)
-                        unit_dump(u, f, prefix);
+        HASHMAP_FOREACH_KEY(u, t, s->units) {
+                if (u->id != t)
+                        continue;
+
+                if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
+                        continue;
+
+                unit_dump(u, f, prefix);
+        }
 }
 
-void manager_dump(Manager *m, FILE *f, const char *prefix) {
-        assert(m);
-        assert(f);
+static void manager_dump_header(Manager *m, FILE *f, const char *prefix) {
 
         /* NB: this is a debug interface for developers. It's not supposed to be machine readable or be
          * stable between versions. We take the liberty to restructure it entirely between versions and
@@ -50,12 +59,22 @@ void manager_dump(Manager *m, FILE *f, const char *prefix) {
                                 timestamp_is_set(t->realtime) ? FORMAT_TIMESTAMP(t->realtime) :
                                                                 FORMAT_TIMESPAN(t->monotonic, 1));
         }
+}
+
+void manager_dump(Manager *m, FILE *f, char **patterns, const char *prefix) {
+        assert(m);
+        assert(f);
+
+        /* If no pattern is provided, dump the full manager state including the manager version, features and
+         * so on. Otherwise limit the dump to the units/jobs matching the specified patterns. */
+        if (!patterns)
+                manager_dump_header(m, f, prefix);
 
-        manager_dump_units(m, f, prefix);
-        manager_dump_jobs(m, f, prefix);
+        manager_dump_units(m, f, patterns, prefix);
+        manager_dump_jobs(m, f, patterns, prefix);
 }
 
-int manager_get_dump_string(Manager *m, char **ret) {
+int manager_get_dump_string(Manager *m, char **patterns, char **ret) {
         _cleanup_free_ char *dump = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         size_t size;
@@ -68,7 +87,7 @@ int manager_get_dump_string(Manager *m, char **ret) {
         if (!f)
                 return -errno;
 
-        manager_dump(m, f, NULL);
+        manager_dump(m, f, patterns, NULL);
 
         r = fflush_and_check(f);
         if (r < 0)
@@ -85,8 +104,8 @@ void manager_test_summary(Manager *m) {
         assert(m);
 
         printf("-> By units:\n");
-        manager_dump_units(m, stdout, "\t");
+        manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("-> By jobs:\n");
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 }
index 317a4b641cedc9b0646dedd1d05065a4e0002c58..714a1f0c8ef0d2bd59570c2ee342e49b98ee81d3 100644 (file)
@@ -5,8 +5,8 @@
 
 #include "manager.h"
 
-void manager_dump_jobs(Manager *s, FILE *f, const char *prefix);
-void manager_dump_units(Manager *s, FILE *f, const char *prefix);
-void manager_dump(Manager *s, FILE *f, const char *prefix);
-int manager_get_dump_string(Manager *m, char **ret);
+void manager_dump_jobs(Manager *s, FILE *f, char **patterns, const char *prefix);
+void manager_dump_units(Manager *s, FILE *f, char **patterns, const char *prefix);
+void manager_dump(Manager *s, FILE *f, char **patterns, const char *prefix);
+int manager_get_dump_string(Manager *m, char **patterns, char **ret);
 void manager_test_summary(Manager *m);
index 90e126840a79bb53634b729ecdd44c0ce38652fb..22c79bed17aba4de3ce1ebb753a98228a448e514 100644 (file)
@@ -2823,7 +2823,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
         case SIGUSR2: {
                 _cleanup_free_ char *dump = NULL;
 
-                r = manager_get_dump_string(m, &dump);
+                r = manager_get_dump_string(m, /* patterns= */ NULL, &dump);
                 if (r < 0) {
                         log_warning_errno(errno, "Failed to acquire manager dump: %m");
                         break;
index 4a798c787058117b85b028085aed5ce78da0b085..8aa1b03a33402669fe1ffdadaf60e3e998f3d163 100644 (file)
                        send_interface="org.freedesktop.systemd1.Manager"
                        send_member="DumpByFileDescriptor"/>
 
+                <allow send_destination="org.freedesktop.systemd1"
+                       send_interface="org.freedesktop.systemd1.Manager"
+                       send_member="DumpPatterns"/>
+
                 <allow send_destination="org.freedesktop.systemd1"
                        send_interface="org.freedesktop.systemd1.Manager"
                        send_member="ListUnitFiles"/>
index d430076056f11f75ae05f99422f476b7c7606d5d..600391094c7e1232e0903e2bed8a73de0a40e20c 100644 (file)
@@ -103,86 +103,86 @@ int main(int argc, char *argv[]) {
         assert_se(manager_load_startable_unit_or_warn(m, "a.service", NULL, &a) >= 0);
         assert_se(manager_load_startable_unit_or_warn(m, "b.service", NULL, &b) >= 0);
         assert_se(manager_load_startable_unit_or_warn(m, "c.service", NULL, &c) >= 0);
-        manager_dump_units(m, stdout, "\t");
+        manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test1: (Trivial)\n");
         r = manager_add_job(m, JOB_START, c, JOB_REPLACE, NULL, &err, &j);
         if (sd_bus_error_is_set(&err))
                 log_error("error: %s: %s", err.name, err.message);
         assert_se(r == 0);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Load2:\n");
         manager_clear_jobs(m);
         assert_se(manager_load_startable_unit_or_warn(m, "d.service", NULL, &d) >= 0);
         assert_se(manager_load_startable_unit_or_warn(m, "e.service", NULL, &e) >= 0);
-        manager_dump_units(m, stdout, "\t");
+        manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test2: (Cyclic Order, Unfixable)\n");
         assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, NULL, &j) == -EDEADLK);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n");
         assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, NULL, &j) == 0);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test4: (Identical transaction)\n");
         assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, NULL, &j) == 0);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Load3:\n");
         assert_se(manager_load_startable_unit_or_warn(m, "g.service", NULL, &g) >= 0);
-        manager_dump_units(m, stdout, "\t");
+        manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test5: (Colliding transaction, fail)\n");
         assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, NULL, &j) == -EDEADLK);
 
         printf("Test6: (Colliding transaction, replace)\n");
         assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, NULL, &j) == 0);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test7: (Unmergeable job type, fail)\n");
         assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, NULL, &j) == -EDEADLK);
 
         printf("Test8: (Mergeable job type, fail)\n");
         assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, NULL, &j) == 0);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test9: (Unmergeable job type, replace)\n");
         assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, NULL, &j) == 0);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Load4:\n");
         assert_se(manager_load_startable_unit_or_warn(m, "h.service", NULL, &h) >= 0);
-        manager_dump_units(m, stdout, "\t");
+        manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
         assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, NULL, &j) == 0);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Load5:\n");
         manager_clear_jobs(m);
         assert_se(manager_load_startable_unit_or_warn(m, "i.service", NULL, &i) >= 0);
         SERVICE(a)->state = SERVICE_RUNNING;
         SERVICE(d)->state = SERVICE_RUNNING;
-        manager_dump_units(m, stdout, "\t");
+        manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test11: (Start/stop job ordering, execution cycle)\n");
         assert_se(manager_add_job(m, JOB_START, i, JOB_FAIL, NULL, NULL, &j) == 0);
         assert_se(unit_has_job_type(a, JOB_STOP));
         assert_se(unit_has_job_type(d, JOB_STOP));
         assert_se(unit_has_job_type(b, JOB_START));
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Load6:\n");
         manager_clear_jobs(m);
         assert_se(manager_load_startable_unit_or_warn(m, "a-conj.service", NULL, &a_conj) >= 0);
         SERVICE(a)->state = SERVICE_DEAD;
-        manager_dump_units(m, stdout, "\t");
+        manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
 
         printf("Test12: (Trivial cycle, Unfixable)\n");
         assert_se(manager_add_job(m, JOB_START, a_conj, JOB_REPLACE, NULL, NULL, &j) == -EDEADLK);
-        manager_dump_jobs(m, stdout, "\t");
+        manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
 
         assert_se(!hashmap_get(unit_get_dependencies(a, UNIT_PROPAGATES_RELOAD_TO), b));
         assert_se(!hashmap_get(unit_get_dependencies(b, UNIT_RELOAD_PROPAGATED_FROM), a));