RFE: Please provide option RandomSec= to systemd timer (#1303552)

Resolves: #1303552
This commit is contained in:
Jan Synacek 2016-02-01 14:24:40 +01:00
parent 743659b0b9
commit 66361260e2
3 changed files with 376 additions and 0 deletions

View File

@ -0,0 +1,251 @@
From d2686a718564c0873e2ed7138e7a31471279c1ec Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 18 Nov 2015 13:37:30 +0100
Subject: [PATCH 5/6] core: add new RandomSec= setting for time units
This allows configuration of a random time on top of the elapse events,
in order to spread time events in a network evenly across a range.
(cherry picked from commit 744c7693751830149ae78fdaf95c6c6f99d59f07)
Resolves: #1303552
---
man/systemd.timer.xml | 43 ++++++++++++++++++++++++++++++-----
src/core/dbus-timer.c | 17 ++++++++++++++
src/core/load-fragment-gperf.gperf.m4 | 1 +
src/core/timer.c | 32 +++++++++++++++++++++++++-
src/core/timer.h | 1 +
src/shared/bus-util.c | 31 +++++++++++++++++++++++++
6 files changed, 118 insertions(+), 7 deletions(-)
diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
index 20890f2..bdd14d8 100644
--- a/man/systemd.timer.xml
+++ b/man/systemd.timer.xml
@@ -180,13 +180,12 @@
<varname>OnUnitInactiveSec=</varname> and ending the time
configured with <varname>AccuracySec=</varname> later. Within
this time window, the expiry time will be placed at a
- host-specific, randomized but stable position that is
+ host-specific, randomized, but stable position that is
synchronized between all local timer units. This is done in
- order to distribute the wake-up time in networked
- installations, as well as optimizing power consumption to
- suppress unnecessary CPU wake-ups. To get best accuracy, set
- this option to 1us. Note that the timer is still subject to
- the timer slack configured via
+ order to optimize power consumption to suppress unnecessary
+ CPU wake-ups. To get best accuracy, set this option to
+ 1us. Note that the timer is still subject to the timer slack
+ configured via
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
<varname>TimerSlackNSec=</varname> setting. See
<citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
@@ -194,6 +193,38 @@
this value as high as possible and as low as
necessary.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>RandomSec=</varname></term>
+
+ <listitem><para>Delay the timer by a randomly selected, evenly
+ distributed amount of time between 0 and the specified time
+ value. Defaults to 0, indicating that no randomized delay
+ shall be applied. Each timer unit will determine this delay
+ randomly each time it is started, and the delay will simply be
+ added on top of the next determined elapsing time. This is
+ useful to stretch dispatching of similarly configured timer
+ events over a certain amount time, to avoid that they all fire
+ at the same time, possibly resulting in resource
+ congestion. Note the relation to
+ <varname>AccuracySec=</varname> above: the latter allows the
+ service manager to coalesce timer events within a specified
+ time range in order to minimize wakeups, the former does the
+ opposite: it stretches timer events over a time range, to make
+ it unlikely that they fire simultaneously. If
+ <varname>RandomSec=</varname> and
+ <varname>AccuracySec=</varname> are used in conjunction, first
+ the a randomized time is added, and the result is then
+ possibly shifted further to coalesce it with other timer
+ events possibly happening on the system. As mentioned above
+ <varname>AccuracySec=</varname> defaults to 1min and
+ <varname>RandomSec=</varname> to 0, thus encouraging
+ coalescing of timer events. In order to optimally stretch
+ timer events over a certain range of time, make sure to set
+ <varname>RandomSec=</varname> to a higher value, and
+ <varname>AccuracySec=1us</varname>.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>Unit=</varname></term>
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index 74a9914..7875bf6 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -179,6 +179,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RandomUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END
@@ -282,6 +283,22 @@ static int bus_timer_set_transient_property(
return 1;
+ } else if (streq(name, "RandomUSec")) {
+ usec_t u = 0;
+
+ r = sd_bus_message_read(message, "t", &u);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ char time[FORMAT_TIMESPAN_MAX];
+
+ t->random_usec = u;
+ unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomSec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+ }
+
+ return 1;
+
} else if (streq(name, "WakeSystem")) {
int b;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index aae81c8..270b069 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -335,6 +335,7 @@ Timer.OnUnitInactiveSec, config_parse_timer, 0,
Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent)
Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
+Timer.RandomSec, config_parse_sec, 0, offsetof(Timer, random_usec)
Timer.Unit, config_parse_trigger_unit, 0, 0
m4_dnl
Path.PathExists, config_parse_path_spec, 0, 0
diff --git a/src/core/timer.c b/src/core/timer.c
index 7f4a2eb..cf50f03 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -25,6 +25,7 @@
#include "unit-name.h"
#include "timer.h"
#include "dbus-timer.h"
+#include "random-util.h"
#include "special.h"
#include "bus-util.h"
#include "bus-error.h"
@@ -305,6 +306,28 @@ static usec_t monotonic_to_boottime(usec_t t) {
return 0;
}
+static void add_random(Timer *t, usec_t *v) {
+ char s[FORMAT_TIMESPAN_MAX];
+ usec_t add;
+
+ assert(t);
+ assert(*v);
+
+ if (t->random_usec == 0)
+ return;
+ if (*v == USEC_INFINITY)
+ return;
+
+ add = random_u64() % t->random_usec;
+
+ if (*v + add < *v) /* overflow */
+ *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
+ else
+ *v += add;
+
+ log_unit_info(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
+}
+
static void timer_enter_waiting(Timer *t, bool initial) {
bool found_monotonic = false, found_realtime = false;
usec_t ts_realtime, ts_monotonic;
@@ -420,8 +443,12 @@ static void timer_enter_waiting(Timer *t, bool initial) {
if (found_monotonic) {
char buf[FORMAT_TIMESPAN_MAX];
+ usec_t left;
- log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0, 0));
+ add_random(t, &t->next_elapse_monotonic_or_boottime);
+
+ left = t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0;
+ log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0));
if (t->monotonic_event_source) {
r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
@@ -454,6 +481,9 @@ static void timer_enter_waiting(Timer *t, bool initial) {
if (found_realtime) {
char buf[FORMAT_TIMESTAMP_MAX];
+
+ add_random(t, &t->next_elapse_realtime);
+
log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
if (t->realtime_event_source) {
diff --git a/src/core/timer.h b/src/core/timer.h
index 9d919e4..415a71b 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -68,6 +68,7 @@ struct Timer {
Unit meta;
usec_t accuracy_usec;
+ usec_t random_usec;
LIST_HEAD(TimerValue, values);
usec_t next_elapse_realtime;
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 11350da..b1f598a 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1374,6 +1374,37 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
return bus_log_create_error(r);
return 0;
+
+ } else if (streq(field, "EnvironmentFile")) {
+
+ r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "EnvironmentFiles");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "v", "a(sb)", 1,
+ eq[0] == '-' ? eq + 1 : eq,
+ eq[0] == '-');
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 0;
+
+ } else if (streq(field, "RandomSec")) {
+ usec_t t;
+
+ r = parse_sec(eq, &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse RandomSec= parameter: %s", eq);
+
+ r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomUSec");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "v", "t", t);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 0;
}
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
--
2.5.0

View File

@ -0,0 +1,122 @@
From 631a626cee4f80368fec05f11c4e6cab637256b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Thu, 26 Nov 2015 16:32:41 -0500
Subject: [PATCH 6/6] core: rename Random* to RandomizedDelay*
The name RandomSec is too generic: "Sec" just specifies the default
unit type, and "Random" by itself is not enough. Rename to something
that should give the user general idea what the setting does without
looking at documentation.
(cherry picked from commit 6f5d79986a9c98b9cacc83f865fed957e4e6e4e6)
Related: #1303552
---
man/systemd.timer.xml | 8 ++++----
src/core/dbus-timer.c | 6 +++---
src/core/load-fragment-gperf.gperf.m4 | 2 +-
src/shared/bus-util.c | 6 +++---
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
index bdd14d8..ab83b2c 100644
--- a/man/systemd.timer.xml
+++ b/man/systemd.timer.xml
@@ -195,7 +195,7 @@
</varlistentry>
<varlistentry>
- <term><varname>RandomSec=</varname></term>
+ <term><varname>RandomizedDelaySec=</varname></term>
<listitem><para>Delay the timer by a randomly selected, evenly
distributed amount of time between 0 and the specified time
@@ -212,16 +212,16 @@
time range in order to minimize wakeups, the former does the
opposite: it stretches timer events over a time range, to make
it unlikely that they fire simultaneously. If
- <varname>RandomSec=</varname> and
+ <varname>RandomizedDelaySec=</varname> and
<varname>AccuracySec=</varname> are used in conjunction, first
the a randomized time is added, and the result is then
possibly shifted further to coalesce it with other timer
events possibly happening on the system. As mentioned above
<varname>AccuracySec=</varname> defaults to 1min and
- <varname>RandomSec=</varname> to 0, thus encouraging
+ <varname>RandomizedDelaySec=</varname> to 0, thus encouraging
coalescing of timer events. In order to optimally stretch
timer events over a certain range of time, make sure to set
- <varname>RandomSec=</varname> to a higher value, and
+ <varname>RandomizedDelaySec=</varname> to a higher value, and
<varname>AccuracySec=1us</varname>.</para></listitem>
</varlistentry>
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index 7875bf6..270cd27 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -179,7 +179,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RandomUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END
@@ -283,7 +283,7 @@ static int bus_timer_set_transient_property(
return 1;
- } else if (streq(name, "RandomUSec")) {
+ } else if (streq(name, "RandomizedDelayUSec")) {
usec_t u = 0;
r = sd_bus_message_read(message, "t", &u);
@@ -294,7 +294,7 @@ static int bus_timer_set_transient_property(
char time[FORMAT_TIMESPAN_MAX];
t->random_usec = u;
- unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomSec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+ unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
}
return 1;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 270b069..2b37641 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -335,7 +335,7 @@ Timer.OnUnitInactiveSec, config_parse_timer, 0,
Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent)
Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
-Timer.RandomSec, config_parse_sec, 0, offsetof(Timer, random_usec)
+Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec)
Timer.Unit, config_parse_trigger_unit, 0, 0
m4_dnl
Path.PathExists, config_parse_path_spec, 0, 0
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index b1f598a..f19633a 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1389,14 +1389,14 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
return 0;
- } else if (streq(field, "RandomSec")) {
+ } else if (streq(field, "RandomizedDelaySec")) {
usec_t t;
r = parse_sec(eq, &t);
if (r < 0)
- return log_error_errno(r, "Failed to parse RandomSec= parameter: %s", eq);
+ return log_error_errno(r, "Failed to parse RandomizedDelaySec= parameter: %s", eq);
- r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomUSec");
+ r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomizedDelayUSec");
if (r < 0)
return bus_log_create_error(r);
--
2.5.0

View File

@ -116,6 +116,8 @@ Patch0080: 0080-tests-don-t-abbreviate-function-names-needlessly.patch
Patch0081: 0081-basic-don-t-append-suffixes-to-unit-name-glob-expres.patch
Patch0082: 0082-man-document-that-unit-file-globbing-only-operates-o.patch
Patch0083: 0083-ask-password-api-only-emit-a-star-on-valid-unicode-c.patch
Patch0084: 0084-core-add-new-RandomSec-setting-for-time-units.patch
Patch0085: 0085-core-rename-Random-to-RandomizedDelay.patch
Patch997: 0001-Re-apply-walters-unit-patch-for-F23-systemd-v222.patch
Patch998: 0001-Revert-core-mount-add-dependencies-to-dynamically-mo-v222.patch
@ -859,6 +861,7 @@ getent passwd systemd-journal-upload >/dev/null 2>&1 || useradd -r -l -g systemd
* Mon Feb 1 2016 Jan Synáček <jsynacek@redhat.com> - 222-14
- Stopping services using glob patterns does not work as stated in man page (#1288851)
- systemd asking for password on boot: ask_password_tty() prints multiple asterisks when typing special characters (#1301984)
- RFE: Please provide option RandomSec= to systemd timer (#1303552)
* Mon Jan 25 2016 Jan Synáček <jsynacek@redhat.com> - 222-13
- units: increase watchdog timeout to 3min for all our services