summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-11-10 13:29:04 +0100
committerGitHub <noreply@github.com>2020-11-10 13:29:04 +0100
commit394131d5be587858d67764bee65198f4a7fe7442 (patch)
tree0bcbdc07fcd1990e78183e0d25c719d9f94bafd6
parentAdd Logitech G403 Prodigy Gaming Mouse to hwdb. (#17537) (diff)
parenttimer: add new feature FixedRandomDelay= (diff)
downloadsystemd-394131d5be587858d67764bee65198f4a7fe7442.tar.xz
systemd-394131d5be587858d67764bee65198f4a7fe7442.zip
Merge pull request #17497 from anitazha/randomizeonce
timer: add new feature FixedRandomDelay=
-rw-r--r--docs/TRANSIENT-SETTINGS.md1
-rw-r--r--man/org.freedesktop.systemd1.xml6
-rw-r--r--man/systemd.timer.xml20
-rw-r--r--src/core/dbus-timer.c4
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/timer.c34
-rw-r--r--src/core/timer.h1
-rw-r--r--src/shared/bus-unit-util.c3
-rw-r--r--test/fuzz/fuzz-unit-file/directives.service1
-rw-r--r--test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer1
10 files changed, 66 insertions, 6 deletions
diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md
index f0dc2ee20ff..50b9a42fa11 100644
--- a/docs/TRANSIENT-SETTINGS.md
+++ b/docs/TRANSIENT-SETTINGS.md
@@ -374,6 +374,7 @@ Most timer unit settings are available to transient units.
✓ RemainAfterElapse=
✓ AccuracySec=
✓ RandomizedDelaySec=
+✓ FixedRandomDelay=
Unit=
```
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
index c231b3c9618..78fd0b3378d 100644
--- a/man/org.freedesktop.systemd1.xml
+++ b/man/org.freedesktop.systemd1.xml
@@ -7211,6 +7211,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RandomizedDelayUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly b FixedRandomDelay = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Persistent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b WakeSystem = ...;
@@ -7236,6 +7238,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
<!--property RandomizedDelayUSec is not documented!-->
+ <!--property FixedRandomDelay is not documented!-->
+
<!--property Persistent is not documented!-->
<!--property WakeSystem is not documented!-->
@@ -7276,6 +7280,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
<variablelist class="dbus-property" generated="True" extra-ref="RandomizedDelayUSec"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="FixedRandomDelay"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="Persistent"/>
<variablelist class="dbus-property" generated="True" extra-ref="WakeSystem"/>
diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml
index 701c44c475b..7c1a4917e56 100644
--- a/man/systemd.timer.xml
+++ b/man/systemd.timer.xml
@@ -269,6 +269,18 @@
</varlistentry>
<varlistentry>
+ <term><varname>FixedRandomDelay=</varname></term>
+
+ <listitem><para>Takes a boolean argument. If true, some amount of time between 0 and
+ <varname>RandomizedDelaySec=</varname> is chosen and added as the delay for each timer iteration. As this
+ delay will not be recalculated on each run, this effectively creates a fixed offset for each iteration.
+ The distribution between 0 and <varname>RandomizedDelaySec=</varname> is deterministic and based on
+ a combination of the machine ID, whether the timer is run by the user/system manager, the service manager's
+ user ID, and the timer's unit name. Has no effect if
+ <varname>RandomizedDelaySec=</varname> is set to 0. Defaults to <option>false</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>OnClockChange=</varname></term>
<term><varname>OnTimezoneChange=</varname></term>
@@ -276,7 +288,7 @@
when the system clock (<constant>CLOCK_REALTIME</constant>) jumps relative to the monotonic clock
(<constant>CLOCK_MONOTONIC</constant>), or when the local system timezone is modified. These options
can be used alone or in combination with other timer expressions (see above) within the same timer
- unit. These options default to false.</para></listitem>
+ unit. These options default to <option>false</option>.</para></listitem>
</varlistentry>
<varlistentry>
@@ -301,7 +313,7 @@
is nonetheless subject to the delay imposed by <varname>RandomizedDelaySec=</varname>.
This is useful to catch up on missed runs of the service when the system was powered down. Note that
this setting only has an effect on timers configured with <varname>OnCalendar=</varname>. Defaults to
- <varname>false</varname>.</para>
+ <option>false</option>.</para>
<para>Use <command>systemctl clean --what=state …</command> on the timer unit to remove the timestamp
file maintained by this option from disk. In particular, use this command before uninstalling a timer
@@ -317,7 +329,7 @@
from suspend, should it be suspended and if the system supports this. Note that this option will only
make sure the system resumes on the appropriate times, it will not take care of suspending it again
after any work that is to be done is finished. Defaults to
- <varname>false</varname>.</para>
+ <option>false</option>.</para>
<para>Note that this functionality requires privileges and is thus generally only available in the
system service manager.</para>
@@ -343,7 +355,7 @@
<varname>RemainAfterElapse=</varname> is on, starting the timer a second time has no effect. However,
if <varname>RemainAfterElapse=</varname> is off and the timer unit was already unloaded, it can be
started again, and thus the service can be triggered multiple times. Defaults to
- <varname>yes</varname>.</para></listitem>
+ <option>true</option>.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index 9720237140c..8e69c173270 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -131,6 +131,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
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("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("FixedRandomDelay", "b", bus_property_get_bool, offsetof(Timer, fixed_random_delay), 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_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -232,6 +233,9 @@ static int bus_timer_set_transient_property(
if (streq(name, "RandomizedDelayUSec"))
return bus_set_transient_usec(u, name, &t->random_usec, message, flags, error);
+ if (streq(name, "FixedRandomDelay"))
+ return bus_set_transient_bool(u, name, &t->fixed_random_delay, message, flags, error);
+
if (streq(name, "WakeSystem"))
return bus_set_transient_bool(u, name, &t->wake_system, message, flags, error);
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 063d8ba6b62..946862c398a 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -481,6 +481,7 @@ Timer.OnTimezoneChange, config_parse_bool,
Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent)
Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse)
+Timer.FixedRandomDelay, config_parse_bool, 0, offsetof(Timer, fixed_random_delay)
Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec)
Timer.Unit, config_parse_trigger_unit, 0, 0
diff --git a/src/core/timer.c b/src/core/timer.c
index 886655a78e9..651f18b5a85 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -169,6 +169,36 @@ static int timer_setup_persistent(Timer *t) {
return 0;
}
+static uint64_t timer_get_fixed_delay_hash(Timer *t) {
+ static const uint8_t hash_key[] = {
+ 0x51, 0x0a, 0xdb, 0x76, 0x29, 0x51, 0x42, 0xc2,
+ 0x80, 0x35, 0xea, 0xe6, 0x8e, 0x3a, 0x37, 0xbd
+ };
+
+ struct siphash state;
+ sd_id128_t machine_id;
+ uid_t uid;
+ int r;
+
+ assert(t);
+
+ uid = getuid();
+ r = sd_id128_get_machine(&machine_id);
+ if (r < 0) {
+ log_unit_debug_errno(UNIT(t), r,
+ "Failed to get machine ID for the fixed delay calculation, proceeding with 0: %m");
+ machine_id = SD_ID128_NULL;
+ }
+
+ siphash24_init(&state, hash_key);
+ siphash24_compress(&machine_id, sizeof(sd_id128_t), &state);
+ siphash24_compress_boolean(MANAGER_IS_SYSTEM(UNIT(t)->manager), &state);
+ siphash24_compress(&uid, sizeof(uid_t), &state);
+ siphash24_compress_string(UNIT(t)->id, &state);
+
+ return siphash24_finalize(&state);
+}
+
static int timer_load(Unit *u) {
Timer *t = TIMER(u);
int r;
@@ -215,6 +245,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {
"%sWakeSystem: %s\n"
"%sAccuracy: %s\n"
"%sRemainAfterElapse: %s\n"
+ "%sFixedRandomDelay: %s\n"
"%sOnClockChange: %s\n"
"%sOnTimeZoneChange: %s\n",
prefix, timer_state_to_string(t->state),
@@ -224,6 +255,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(t->wake_system),
prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1),
prefix, yes_no(t->remain_after_elapse),
+ prefix, yes_no(t->fixed_random_delay),
prefix, yes_no(t->on_clock_change),
prefix, yes_no(t->on_timezone_change));
@@ -332,7 +364,7 @@ static void add_random(Timer *t, usec_t *v) {
if (*v == USEC_INFINITY)
return;
- add = random_u64() % t->random_usec;
+ add = (t->fixed_random_delay ? timer_get_fixed_delay_hash(t) : random_u64()) % t->random_usec;
if (*v + add < *v) /* overflow */
*v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
diff --git a/src/core/timer.h b/src/core/timer.h
index 46d9b9b2622..14fa317064e 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -59,6 +59,7 @@ struct Timer {
bool remain_after_elapse;
bool on_clock_change;
bool on_timezone_change;
+ bool fixed_random_delay;
char *stamp_path;
};
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index fe3a41f4387..2bab2299fbe 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -2074,7 +2074,8 @@ static int bus_append_timer_property(sd_bus_message *m, const char *field, const
"RemainAfterElapse",
"Persistent",
"OnTimezoneChange",
- "OnClockChange"))
+ "OnClockChange",
+ "FixedRandomDelay"))
return bus_append_parse_boolean(m, field, eq);
if (STR_IN_SET(field, "AccuracySec",
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
index eebc89f5c23..30ce98687a4 100644
--- a/test/fuzz/fuzz-unit-file/directives.service
+++ b/test/fuzz/fuzz-unit-file/directives.service
@@ -175,6 +175,7 @@ PipeSize=
Priority=
PropagatesReloadTo=
RandomizedDelaySec=
+FixedRandomDelay=
RebootArgument=
ReceiveBuffer=
RefuseManualStart=
diff --git a/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer
index d3d17dc5355..5bf91b9f4cd 100644
--- a/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer
+++ b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer
@@ -32,6 +32,7 @@ OnCalendar=Fri 2012-11-23 11:12:13
Persistent=true
AccuracySec=24h
RandomizedDelaySec=234234234
+FixedRandomDelay=true
Persistent=no
Unit=foo.service