On 2 Dec 2014 22:19, "Ken Sedgwick" <ksedg...@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel
_______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel