]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
timer: add new feature FixedRandomDelay= 17497/head
authorKristijan Gjoshev <crypter@mail.com>
Sat, 1 Feb 2020 17:27:08 +0000 (18:27 +0100)
committerAnita Zhang <the.anitazha@gmail.com>
Thu, 5 Nov 2020 18:59:33 +0000 (10:59 -0800)
FixedRandomDelay=yes will use
`siphash24(sd_id128_get_machine() || MANAGER_IS_SYSTEM(m) || getuid() || u->id)`,
where || is concatenation, instead of a random number to choose a value between
0 and RandomizedDelaySec= as the timer delay.
This essentially sets up a fixed, but seemingly random, offset for each timer
iteration rather than having a random offset recalculated each time it fires.

Closes #10355

Co-author: Anita Zhang <the.anitazha@gmail.com>

docs/TRANSIENT-SETTINGS.md
man/org.freedesktop.systemd1.xml
man/systemd.timer.xml
src/core/dbus-timer.c
src/core/load-fragment-gperf.gperf.m4
src/core/timer.c
src/core/timer.h
src/shared/bus-unit-util.c
test/fuzz/fuzz-unit-file/directives.service
test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer

index f0dc2ee20ffb88cc6ee5301ae88f27dc8d26351c..50b9a42fa11d00d7a426debf53d9d0a7778c4509 100644 (file)
@@ -374,6 +374,7 @@ Most timer unit settings are available to transient units.
 ✓ RemainAfterElapse=
 ✓ AccuracySec=
 ✓ RandomizedDelaySec=
+✓ FixedRandomDelay=
   Unit=
 ```
 
index c0e0f385b41e9e54aa8a7c584dd2fbf15c1adc60..1f6bbc1a6ec968fd85e9dc1b5b16a8dfca650673 100644 (file)
@@ -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"/>
index 24c6dd50f89cd9a458cb3b675f9cb7f8d0a0bc69..c4698bf4dc95f372d5d4dd48d22b481256fe292b 100644 (file)
         <varname>AccuracySec=1us</varname>.</para></listitem>
       </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>
index da35fa867862ea64d5fc65e61fbda42aa3e8800a..ee54ba87720f73977ef8ec5d816988dc190e2880 100644 (file)
@@ -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);
 
index 063d8ba6b62fe801fe0a6c65ef09c23dfcfaa38d..946862c398a06b51fcd398be7e668683e93c3542 100644 (file)
@@ -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
index 94388f0727ffbe4ebd201e2e462b43ed3edbd0b7..46669b6b1417d85444805953554ce70e2c4083c8 100644 (file)
@@ -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 */
index ab66a201adc23c6b48028bbea4ebfb09e22c4d26..ce4046a21067f4ccef677fedd070a3bdfe062c75 100644 (file)
@@ -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;
 };
index 79c2e0cf1991257b3d568dd9c72b6bdf83b17c88..d1dc9e2e02266eed71d834a975098a73c33d9daa 100644 (file)
@@ -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",
index eebc89f5c2391c296625eff7c038c6d2ebcbdca7..30ce98687a4a132d5a1d71568c5029246f6c036f 100644 (file)
@@ -175,6 +175,7 @@ PipeSize=
 Priority=
 PropagatesReloadTo=
 RandomizedDelaySec=
+FixedRandomDelay=
 RebootArgument=
 ReceiveBuffer=
 RefuseManualStart=
index 7db361cd69b74bad928f47850297f713865196a9..64b8808adc3f8135bd106c6d5427d83b8215e05a 100644 (file)
@@ -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