[systemd-devel] [PATCH] daemon-reload timestamped: coalesce redundant daemon-reloads

Tom Gundersen teg at jklm.no
Wed Dec 3 18:14:54 PST 2014


On 2 Dec 2014 22:19, "Ken Sedgwick" <ksedgwic at bonsai.com> wrote:
>
> Systems with many units (~10K) take many seconds to perform a
> daemon-reload.  The process of load-balancing these systems requires
> multiple daemon-reloads, many issued concurrently.

Out of curiosity, how does this work? Is there code we can look at?

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


More information about the systemd-devel mailing list