<p dir="ltr"><br>
On 2 Dec 2014 22:19, "Ken Sedgwick" <<a href="mailto:ksedgwic@bonsai.com">ksedgwic@bonsai.com</a>> wrote:<br>
><br>
> Systems with many units (~10K) take many seconds to perform a<br>
> daemon-reload.  The process of load-balancing these systems requires<br>
> multiple daemon-reloads, many issued concurrently.</p>
<p dir="ltr">Out of curiosity, how does this work? Is there code we can look at?</p>
<p dir="ltr">> Currently many of<br>
> these redundant daemon-reloads timeout and fail.<br>
><br>
> This patch adds a new systemd method ReloadTimestamped which contains<br>
> the monotonic timestamp of the daemon-reload issuance.  When a<br>
> ReloadTimestamped message is handled it's timestamp is compared to<br>
> the timestamp of the most recent successful daemon reload.  If the<br>
> message is redundant it is returns with success immediately.<br>
><br>
> The original Reload method is preserved to support compatibility with<br>
> older systemctl versions.<br>
><br>
> If a new systemctl receives a SD_BUS_ERROR_UNKNOWN_METHOD error in<br>
> response to ReloadTimestamped it retries with the original Reload<br>
> method.<br>
> ---<br>
>  src/core/dbus-manager.c   | 47 +++++++++++++++++++++++++++++++++++++++++++++++<br>
>  src/core/manager.c        |  8 ++++++++<br>
>  src/core/manager.h        |  3 +++<br>
>  src/systemctl/systemctl.c | 19 ++++++++++++++++++-<br>
>  4 files changed, 76 insertions(+), 1 deletion(-)<br>
><br>
> diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c<br>
> index 0994d7b..6a42456 100644<br>
> --- a/src/core/dbus-manager.c<br>
> +++ b/src/core/dbus-manager.c<br>
> @@ -1100,6 +1100,52 @@ static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, s<br>
>          return 1;<br>
>  }<br>
><br>
> +static int method_reload_timestamped(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {<br>
> +        Manager *m = userdata;<br>
> +        int r;<br>
> +        usec_t requested_time;<br>
> +<br>
> +        assert(bus);<br>
> +        assert(message);<br>
> +        assert(m);<br>
> +<br>
> +        r = bus_verify_reload_daemon_async(m, message, error);<br>
> +        if (r < 0)<br>
> +                return r;<br>
> +        if (r == 0)<br>
> +                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */<br>
> +<br>
> +        r = mac_selinux_access_check(message, "reload", error);<br>
> +        if (r < 0)<br>
> +                return r;<br>
> +<br>
> +        r = sd_bus_message_read(message, "t", &requested_time);<br>
> +        if (r < 0)<br>
> +                return r;<br>
> +<br>
> +        /* Is this reload needed?  If a completed reload was started<br>
> +         * after this reload was requested we can coalesce it and<br>
> +         * return immediate success. */<br>
> +<br>
> +        if (requested_time < m->last_reload_time)<br>
> +                return sd_bus_reply_method_return(message, NULL);<br>
> +<br>
> +        /* Instead of sending the reply back right away, we just<br>
> +         * remember that we need to and then send it after the reload<br>
> +         * is finished. That way the caller knows when the reload<br>
> +         * finished. */<br>
> +<br>
> +        assert(!m->queued_message);<br>
> +        r = sd_bus_message_new_method_return(message, &m->queued_message);<br>
> +        if (r < 0)<br>
> +                return r;<br>
> +<br>
> +        m->queued_message_bus = sd_bus_ref(bus);<br>
> +        m->exit_code = MANAGER_RELOAD;<br>
> +<br>
> +        return 1;<br>
> +}<br>
> +<br>
>  static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {<br>
>          Manager *m = userdata;<br>
>          int r;<br>
> @@ -1917,6 +1963,7 @@ const sd_bus_vtable bus_manager_vtable[] = {<br>
>          SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),<br>
>          SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),<br>
>          SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),<br>
> +        SD_BUS_METHOD("ReloadTimestamped", "t", NULL, method_reload_timestamped, SD_BUS_VTABLE_UNPRIVILEGED),<br>
>          SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),<br>
>          SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),<br>
>          SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),<br>
> diff --git a/src/core/manager.c b/src/core/manager.c<br>
> index cff24fa..4619ce3 100644<br>
> --- a/src/core/manager.c<br>
> +++ b/src/core/manager.c<br>
> @@ -616,6 +616,8 @@ int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {<br>
><br>
>          m->taint_usr = dir_is_empty("/usr") > 0;<br>
><br>
> +        m->last_reload_time = 0ULL;<br>
> +<br>
>          *_m = m;<br>
>          return 0;<br>
><br>
> @@ -2444,9 +2446,12 @@ int manager_reload(Manager *m) {<br>
>          int r, q;<br>
>          _cleanup_fclose_ FILE *f = NULL;<br>
>          _cleanup_fdset_free_ FDSet *fds = NULL;<br>
> +        usec_t this_reload_time;<br>
><br>
>          assert(m);<br>
><br>
> +        this_reload_time = now(CLOCK_MONOTONIC);<br>
> +<br>
>          r = manager_open_serialization(m, &f);<br>
>          if (r < 0)<br>
>                  return r;<br>
> @@ -2518,6 +2523,9 @@ int manager_reload(Manager *m) {<br>
><br>
>          m->send_reloading_done = true;<br>
><br>
> +        if (r >= 0)<br>
> +                m->last_reload_time = this_reload_time;<br>
> +<br>
>          return r;<br>
>  }<br>
><br>
> diff --git a/src/core/manager.h b/src/core/manager.h<br>
> index ab75f90..7790127 100644<br>
> --- a/src/core/manager.h<br>
> +++ b/src/core/manager.h<br>
> @@ -295,6 +295,9 @@ struct Manager {<br>
><br>
>          /* Used for processing polkit authorization responses */<br>
>          Hashmap *polkit_registry;<br>
> +<br>
> +        /* Used to coalesce redundant reloads */<br>
> +        usec_t last_reload_time;<br>
>  };<br>
><br>
>  int manager_new(SystemdRunningAs running_as, bool test_run, Manager **m);<br>
> diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c<br>
> index 74af772..3a50c75 100644<br>
> --- a/src/systemctl/systemctl.c<br>
> +++ b/src/systemctl/systemctl.c<br>
> @@ -142,6 +142,8 @@ static bool arg_plain = false;<br>
><br>
>  static bool original_stdout_is_tty;<br>
><br>
> +static bool legacy_daemon_reload = false;<br>
> +<br>
>  static int daemon_reload(sd_bus *bus, char **args);<br>
>  static int halt_now(enum action a);<br>
>  static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);<br>
> @@ -4860,6 +4862,9 @@ static int daemon_reload(sd_bus *bus, char **args) {<br>
>                                      /* "daemon-reload" */ "Reload";<br>
>          }<br>
><br>
> +        if (streq(method, "Reload") && !legacy_daemon_reload)<br>
> +                method = "ReloadTimestamped";<br>
> +<br>
>          r = sd_bus_message_new_method_call(<br>
>                          bus,<br>
>                          &m,<br>
> @@ -4870,12 +4875,24 @@ static int daemon_reload(sd_bus *bus, char **args) {<br>
>          if (r < 0)<br>
>                  return bus_log_create_error(r);<br>
><br>
> +        if (streq(method, "ReloadTimestamped")) {<br>
> +                r = sd_bus_message_append(m, "t", now(CLOCK_MONOTONIC));<br>
> +                if (r < 0)<br>
> +                        return bus_log_create_error(r);<br>
> +        }<br>
> +<br>
>          r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);<br>
>          if (r < 0)<br>
>                  return bus_log_create_error(r);<br>
><br>
>          r = sd_bus_call(bus, m, 0, &error, NULL);<br>
> -        if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)<br>
> +        if (r == -EBADR && streq(method, "ReloadTimestamped") && streq(<a href="http://error.name">error.name</a>, SD_BUS_ERROR_UNKNOWN_METHOD)) {<br>
> +                /* The ReloadTimestamped method wasn't available, retry<br>
> +                 * with legacy Reload instead. */<br>
> +                legacy_daemon_reload = true;<br>
> +                return daemon_reload(bus, args);<br>
> +        }<br>
> +        else if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)<br>
>                  /* There's always a fallback possible for<br>
>                   * legacy actions. */<br>
>                  r = -EADDRNOTAVAIL;<br>
> --<br>
> 1.9.3<br>
><br>
> _______________________________________________<br>
> systemd-devel mailing list<br>
> <a href="mailto:systemd-devel@lists.freedesktop.org">systemd-devel@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/systemd-devel">http://lists.freedesktop.org/mailman/listinfo/systemd-devel</a><br>
</p>