Blame SOURCES/0621-systemd-analyze-make-dump-work-for-large-of-units.patch

17b0f1
From 6772555b226a116bff07b7d8af28b16032273866 Mon Sep 17 00:00:00 2001
17b0f1
From: David Tardon <dtardon@redhat.com>
17b0f1
Date: Wed, 9 May 2018 09:35:52 +0200
17b0f1
Subject: [PATCH] systemd-analyze: make dump work for large # of units
17b0f1
17b0f1
If there is a large number of units, the size of the generated dump
17b0f1
string can overstep DBus message size limit. So let's pass that string
17b0f1
via a fd.
17b0f1
17b0f1
(cherry picked from commit c0a1bfacfea9c65ea79fd07682a5b60b5d711a33)
17b0f1
17b0f1
Resolves: #1446095
17b0f1
---
17b0f1
 src/analyze/analyze.c                  | 57 ++++++++++++++++++++++----
17b0f1
 src/core/dbus-manager.c                | 26 +++++++++++-
17b0f1
 src/core/org.freedesktop.systemd1.conf |  4 ++
17b0f1
 3 files changed, 76 insertions(+), 11 deletions(-)
17b0f1
17b0f1
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
17b0f1
index ff84f6894f..7116aaa88d 100644
17b0f1
--- a/src/analyze/analyze.c
17b0f1
+++ b/src/analyze/analyze.c
17b0f1
@@ -29,6 +29,7 @@
17b0f1
 #include "sd-bus.h"
17b0f1
 #include "bus-util.h"
17b0f1
 #include "bus-error.h"
17b0f1
+#include "copy.h"
17b0f1
 #include "install.h"
17b0f1
 #include "log.h"
17b0f1
 #include "build.h"
17b0f1
@@ -1096,12 +1097,42 @@ static int dot(sd_bus *bus, char* patterns[]) {
17b0f1
         return 0;
17b0f1
 }
17b0f1
 
17b0f1
-static int dump(sd_bus *bus, char **args) {
17b0f1
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
17b0f1
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
17b0f1
+static int dump_fallback(sd_bus *bus) {
17b0f1
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
17b0f1
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
17b0f1
         const char *text = NULL;
17b0f1
         int r;
17b0f1
 
17b0f1
+        assert(bus);
17b0f1
+
17b0f1
+        r = sd_bus_call_method(
17b0f1
+                        bus,
17b0f1
+                        "org.freedesktop.systemd1",
17b0f1
+                        "/org/freedesktop/systemd1",
17b0f1
+                        "org.freedesktop.systemd1.Manager",
17b0f1
+                        "Dump",
17b0f1
+                        &error,
17b0f1
+                        &reply,
17b0f1
+                        "");
17b0f1
+        if (r < 0) {
17b0f1
+                log_error("Failed to issue method call Dump: %s", bus_error_message(&error, -r));
17b0f1
+                return r;
17b0f1
+        }
17b0f1
+
17b0f1
+        r = sd_bus_message_read(reply, "s", &text);
17b0f1
+        if (r < 0)
17b0f1
+                return bus_log_parse_error(r);
17b0f1
+
17b0f1
+        fputs(text, stdout);
17b0f1
+        return 0;
17b0f1
+}
17b0f1
+
17b0f1
+static int dump(sd_bus *bus, char **args) {
17b0f1
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
17b0f1
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
17b0f1
+        int fd = -1;
17b0f1
+        int r;
17b0f1
+
17b0f1
         if (!strv_isempty(args)) {
17b0f1
                 log_error("Too many arguments.");
17b0f1
                 return -E2BIG;
17b0f1
@@ -1109,26 +1140,34 @@ static int dump(sd_bus *bus, char **args) {
17b0f1
 
17b0f1
         pager_open_if_enabled();
17b0f1
 
17b0f1
+        if (!sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD))
17b0f1
+                return dump_fallback(bus);
17b0f1
+
17b0f1
         r = sd_bus_call_method(
17b0f1
                         bus,
17b0f1
                        "org.freedesktop.systemd1",
17b0f1
                        "/org/freedesktop/systemd1",
17b0f1
                        "org.freedesktop.systemd1.Manager",
17b0f1
-                       "Dump",
17b0f1
+                       "DumpByFileDescriptor",
17b0f1
                        &error,
17b0f1
                        &reply,
17b0f1
                        "");
17b0f1
         if (r < 0) {
17b0f1
-                log_error("Failed issue method call: %s", bus_error_message(&error, -r));
17b0f1
-                return r;
17b0f1
+                /* fall back to Dump if DumpByFileDescriptor is not supported */
17b0f1
+                if (!IN_SET(r, -EACCES, -EBADR)) {
17b0f1
+                        log_error("Failed to issue method call DumpByFileDescriptor: %s", bus_error_message(&error, -r));
17b0f1
+                        return r;
17b0f1
+                }
17b0f1
+
17b0f1
+                return dump_fallback(bus);
17b0f1
         }
17b0f1
 
17b0f1
-        r = sd_bus_message_read(reply, "s", &text);
17b0f1
+        r = sd_bus_message_read(reply, "h", &fd;;
17b0f1
         if (r < 0)
17b0f1
                 return bus_log_parse_error(r);
17b0f1
 
17b0f1
-        fputs(text, stdout);
17b0f1
-        return 0;
17b0f1
+        fflush(stdout);
17b0f1
+        return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0);
17b0f1
 }
17b0f1
 
17b0f1
 static int set_log_level(sd_bus *bus, char **args) {
17b0f1
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
17b0f1
index d34ed042f6..1766163b33 100644
17b0f1
--- a/src/core/dbus-manager.c
17b0f1
+++ b/src/core/dbus-manager.c
17b0f1
@@ -1064,7 +1064,7 @@ static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userda
17b0f1
         return sd_bus_reply_method_return(message, NULL);
17b0f1
 }
17b0f1
 
17b0f1
-static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
17b0f1
+static int dump_impl(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error, int (*reply)(sd_bus_message *, char *)) {
17b0f1
         _cleanup_free_ char *dump = NULL;
17b0f1
         _cleanup_fclose_ FILE *f = NULL;
17b0f1
         Manager *m = userdata;
17b0f1
@@ -1089,13 +1089,34 @@ static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
17b0f1
         manager_dump_jobs(m, f, NULL);
17b0f1
 
17b0f1
         fflush(f);
17b0f1
-
17b0f1
         if (ferror(f))
17b0f1
                 return -ENOMEM;
17b0f1
 
17b0f1
+        return reply(message, dump);
17b0f1
+}
17b0f1
+
17b0f1
+static int reply_dump(sd_bus_message *message, char *dump) {
17b0f1
         return sd_bus_reply_method_return(message, "s", dump);
17b0f1
 }
17b0f1
 
17b0f1
+static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
17b0f1
+        return dump_impl(bus, message, userdata, error, reply_dump);
17b0f1
+}
17b0f1
+
17b0f1
+static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
17b0f1
+        _cleanup_close_ int fd = -1;
17b0f1
+
17b0f1
+        fd = acquire_data_fd(dump, strlen(dump), 0);
17b0f1
+        if (fd < 0)
17b0f1
+                return fd;
17b0f1
+
17b0f1
+        return sd_bus_reply_method_return(message, "h", fd);
17b0f1
+}
17b0f1
+
17b0f1
+static int method_dump_by_fd(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
17b0f1
+        return dump_impl(bus, message, userdata, error, reply_dump_by_fd);
17b0f1
+}
17b0f1
+
17b0f1
 static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
17b0f1
         _cleanup_free_ char *path = NULL;
17b0f1
         Manager *m = userdata;
17b0f1
@@ -2092,6 +2113,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
17b0f1
         SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
17b0f1
         SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
17b0f1
         SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
17b0f1
+        SD_BUS_METHOD("DumpByFileDescriptor", NULL, "h", method_dump_by_fd, SD_BUS_VTABLE_UNPRIVILEGED),
17b0f1
         SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
17b0f1
         SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
17b0f1
         SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
17b0f1
diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf
17b0f1
index 3997dd0b4e..8187cf1731 100644
17b0f1
--- a/src/core/org.freedesktop.systemd1.conf
17b0f1
+++ b/src/core/org.freedesktop.systemd1.conf
17b0f1
@@ -96,6 +96,10 @@
17b0f1
                        send_interface="org.freedesktop.systemd1.Manager"
17b0f1
                        send_member="Dump"/>
17b0f1
 
17b0f1
+                
17b0f1
+                       send_interface="org.freedesktop.systemd1.Manager"
17b0f1
+                       send_member="DumpByFileDescriptor"/>
17b0f1
+
17b0f1
                 
17b0f1
                        send_interface="org.freedesktop.systemd1.Manager"
17b0f1
                        send_member="GetDefaultTarget"/>