From 5c5d01915a6d8dae559757146a64ee04eb2e84ba Mon Sep 17 00:00:00 2001 From: Yue Tao Date: Thu, 23 Sep 2021 14:20:06 +0800 Subject: [PATCH] Add debian package for systemd Porting 851/909/910/913/919/920/922/923/924/925/926/927 patches to debian, other patches are confirmed in debian version. Story: 2009221 Task: 43416 Signed-off-by: Yue Tao Change-Id: I5af677c90342bae7c30991bf465e0db79c71667d --- ...-Update-symbols-file-for-libsystemd0.patch | 52 ++ base/systemd/debian/deb_patches/series | 1 + base/systemd/debian/meta_data.yaml | 4 + .../851-inject-millisec-in-syslog-date.patch | 88 ++ ...lock-data-allocation-out-of-sd_event.patch | 79 ++ ...ut-code-to-add-remove-timer-event-so.patch | 120 +++ ...earliest_index-latest_index-into-com.patch | 110 +++ ...d-ability-to-ratelimit-event-sources.patch | 835 ++++++++++++++++++ ...xcessive-proc-self-mountinfo-parsing.patch | 37 + ...ordering-of-pending-ratelimited-even.patch | 100 +++ .../923-sd-event-drop-unnecessary-else.patch | 35 + .../patches/924-sd-event-use-CMP-macro.patch | 98 ++ .../patches/925-sd-event-use-usec_add.patch | 35 + ...ent_source_time_prioq_reshuffle-acce.patch | 48 + ...reshuffle-time-prioq-on-changing-onl.patch | 101 +++ base/systemd/debian/patches/series | 26 + .../debian/patches/skip-some-testcases.patch | 30 + 17 files changed, 1799 insertions(+) create mode 100644 base/systemd/debian/deb_patches/0001-Update-symbols-file-for-libsystemd0.patch create mode 100644 base/systemd/debian/deb_patches/series create mode 100644 base/systemd/debian/meta_data.yaml create mode 100644 base/systemd/debian/patches/851-inject-millisec-in-syslog-date.patch create mode 100644 base/systemd/debian/patches/909-sd-event-split-clock-data-allocation-out-of-sd_event.patch create mode 100644 base/systemd/debian/patches/910-sd-event-split-out-code-to-add-remove-timer-event-so.patch create mode 100644 base/systemd/debian/patches/913-sd-event-remove-earliest_index-latest_index-into-com.patch create mode 100644 base/systemd/debian/patches/919-sd-event-add-ability-to-ratelimit-event-sources.patch create mode 100644 base/systemd/debian/patches/920-core-prevent-excessive-proc-self-mountinfo-parsing.patch create mode 100644 base/systemd/debian/patches/922-sd-event-change-ordering-of-pending-ratelimited-even.patch create mode 100644 base/systemd/debian/patches/923-sd-event-drop-unnecessary-else.patch create mode 100644 base/systemd/debian/patches/924-sd-event-use-CMP-macro.patch create mode 100644 base/systemd/debian/patches/925-sd-event-use-usec_add.patch create mode 100644 base/systemd/debian/patches/926-sd-event-make-event_source_time_prioq_reshuffle-acce.patch create mode 100644 base/systemd/debian/patches/927-sd-event-always-reshuffle-time-prioq-on-changing-onl.patch create mode 100644 base/systemd/debian/patches/series create mode 100644 base/systemd/debian/patches/skip-some-testcases.patch diff --git a/base/systemd/debian/deb_patches/0001-Update-symbols-file-for-libsystemd0.patch b/base/systemd/debian/deb_patches/0001-Update-symbols-file-for-libsystemd0.patch new file mode 100644 index 000000000..2e43aefb6 --- /dev/null +++ b/base/systemd/debian/deb_patches/0001-Update-symbols-file-for-libsystemd0.patch @@ -0,0 +1,52 @@ +From 2818847c832ad5e11c501b9cb7110aec5e534582 Mon Sep 17 00:00:00 2001 +From: Yue Tao +Date: Tue, 9 Nov 2021 23:19:48 -0800 +Subject: [PATCH] Update symbols file for libsystemd0 + +Introduce 3 new functions by porting upstream commit +b6d5481b3d9f7c9b1198ab54b54326ec73e855bf. + +See source patch 919-sd-event-add-ability-to-ratelimit-event-sources.patch + +Signed-off-by: Yue Tao +--- + debian/libsystemd0.symbols | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/debian/libsystemd0.symbols b/debian/libsystemd0.symbols +index fdd6adebb1..9bd312e355 100644 +--- a/debian/libsystemd0.symbols ++++ b/debian/libsystemd0.symbols +@@ -28,6 +28,7 @@ libsystemd.so.0 libsystemd0 #MINVER# + LIBSYSTEMD_245@LIBSYSTEMD_245 245 + LIBSYSTEMD_246@LIBSYSTEMD_246 246 + LIBSYSTEMD_247@LIBSYSTEMD_247 247 ++ LIBSYSTEMD_248@LIBSYSTEMD_248 248 + sd_booted@LIBSYSTEMD_209 0 + sd_bus_add_fallback@LIBSYSTEMD_221 221 + sd_bus_add_fallback_vtable@LIBSYSTEMD_221 221 +@@ -434,11 +435,13 @@ libsystemd.so.0 libsystemd0 #MINVER# + sd_event_source_get_io_revents@LIBSYSTEMD_221 221 + sd_event_source_get_pending@LIBSYSTEMD_221 221 + sd_event_source_get_priority@LIBSYSTEMD_221 221 ++ sd_event_source_get_ratelimit@LIBSYSTEMD_248 248 + sd_event_source_get_signal@LIBSYSTEMD_221 221 + sd_event_source_get_time@LIBSYSTEMD_221 221 + sd_event_source_get_time_accuracy@LIBSYSTEMD_221 221 + sd_event_source_get_time_clock@LIBSYSTEMD_221 221 + sd_event_source_get_userdata@LIBSYSTEMD_221 221 ++ sd_event_source_is_ratelimited@LIBSYSTEMD_248 248 + sd_event_source_ref@LIBSYSTEMD_221 221 + sd_event_source_send_child_signal@LIBSYSTEMD_245 245 + sd_event_source_set_child_pidfd_own@LIBSYSTEMD_245 245 +@@ -453,6 +456,7 @@ libsystemd.so.0 libsystemd0 #MINVER# + sd_event_source_set_io_fd_own@LIBSYSTEMD_237 237 + sd_event_source_set_prepare@LIBSYSTEMD_221 221 + sd_event_source_set_priority@LIBSYSTEMD_221 221 ++ sd_event_source_set_ratelimit@LIBSYSTEMD_248 248 + sd_event_source_set_time@LIBSYSTEMD_221 221 + sd_event_source_set_time_accuracy@LIBSYSTEMD_221 221 + sd_event_source_set_time_relative@LIBSYSTEMD_247 247 +-- +2.31.1 + diff --git a/base/systemd/debian/deb_patches/series b/base/systemd/debian/deb_patches/series new file mode 100644 index 000000000..18d1298b6 --- /dev/null +++ b/base/systemd/debian/deb_patches/series @@ -0,0 +1 @@ +0001-Update-symbols-file-for-libsystemd0.patch diff --git a/base/systemd/debian/meta_data.yaml b/base/systemd/debian/meta_data.yaml new file mode 100644 index 000000000..8df52c80f --- /dev/null +++ b/base/systemd/debian/meta_data.yaml @@ -0,0 +1,4 @@ +debver: 247.3-6 +revision: + dist: $STX_DIST + PKG_GITREVCOUNT: true diff --git a/base/systemd/debian/patches/851-inject-millisec-in-syslog-date.patch b/base/systemd/debian/patches/851-inject-millisec-in-syslog-date.patch new file mode 100644 index 000000000..85593c85c --- /dev/null +++ b/base/systemd/debian/patches/851-inject-millisec-in-syslog-date.patch @@ -0,0 +1,88 @@ +From 8b63ddb68a39d48ebb621d76a2b1f07f5ff67ac7 Mon Sep 17 00:00:00 2001 +Message-Id: <8b63ddb68a39d48ebb621d76a2b1f07f5ff67ac7.1574264572.git.Jim.Somerville@windriver.com> +From: systemd team +Date: Tue, 8 Nov 2016 17:06:01 -0500 +Subject: [PATCH 1/3] inject millisec in syslog date + +Signed-off-by: Jim Somerville +--- + src/journal/journald-syslog.c | 48 +++++++++++++++++++++++++++++++++++++------ + 1 file changed, 42 insertions(+), 6 deletions(-) + +diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c +index 1a9db59..36288cb 100644 +--- a/src/journal/journald-syslog.c ++++ b/src/journal/journald-syslog.c +@@ -25,6 +25,43 @@ + /* Warn once every 30s if we missed syslog message */ + #define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC) + ++/* internal function that builds a formatted time str of the ++ * tv parameter into the passed buffer. (ie Nov 7 16:28:38.109) ++ * If tv is NULL, then the clock function is used to build the formatted time ++ * returns (same as snprintf) - number of characters written to buffer. ++ */ ++static int formatSyslogDate(char * buffer, int bufLen, const struct timeval *tv) { ++ struct timeval tv_tmp; ++ long int millisec; ++ char tmpbuf[64]; ++ struct tm tm; ++ time_t t; ++ ++ if (!tv) { ++ // no timeval input so get time data from clock ++ usec_t now_usec = now(CLOCK_REALTIME); ++ time_t now_sec = ((time_t) now_usec / USEC_PER_SEC); ++ long int now_fraction_secs = now_usec % USEC_PER_SEC; ++ tv_tmp.tv_sec = now_sec; ++ tv_tmp.tv_usec = now_fraction_secs; ++ tv = &tv_tmp; ++ } ++ ++ t = tv->tv_sec; ++ if (!localtime_r(&t, &tm)) ++ return 0; ++ ++ // format time to the second granularity - ie Nov 7 16:28:38 ++ if (strftime(tmpbuf,sizeof(tmpbuf),"%h %e %T", &tm) <= 0) ++ return 0; ++ ++ millisec = tv->tv_usec / 1000; ++ // now append millisecond granularity (ie Nov 7 16:28:38.109) to ++ // the formatted string. ++ return snprintf(buffer, bufLen, "%s.%03lu", tmpbuf, millisec); ++} ++ ++ + static void forward_syslog_iovec( + Server *s, + const struct iovec *iovec, +@@ -125,8 +162,6 @@ void server_forward_syslog(Server *s, in + char header_priority[DECIMAL_STR_MAX(priority) + 3], header_time[64], + header_pid[STRLEN("[]: ") + DECIMAL_STR_MAX(pid_t) + 1]; + int n = 0; +- time_t t; +- struct tm tm; + _cleanup_free_ char *ident_buf = NULL; + + assert(s); +@@ -141,12 +176,11 @@ void server_forward_syslog(Server *s, in + xsprintf(header_priority, "<%i>", priority); + iovec[n++] = IOVEC_MAKE_STRING(header_priority); + ++ + /* Second: timestamp */ +- t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC)); +- if (!localtime_r(&t, &tm)) +- return; +- if (strftime(header_time, sizeof(header_time), "%h %e %T ", &tm) <= 0) +- return; ++ if (formatSyslogDate(header_time, sizeof(header_time), tv) <=0 ) ++ return; ++ + iovec[n++] = IOVEC_MAKE_STRING(header_time); + + /* Third: identifier and PID */ +-- +1.8.3.1 + diff --git a/base/systemd/debian/patches/909-sd-event-split-clock-data-allocation-out-of-sd_event.patch b/base/systemd/debian/patches/909-sd-event-split-clock-data-allocation-out-of-sd_event.patch new file mode 100644 index 000000000..4e0114122 --- /dev/null +++ b/base/systemd/debian/patches/909-sd-event-split-clock-data-allocation-out-of-sd_event.patch @@ -0,0 +1,79 @@ +From 77b772bce846db28dc447420fd380a51eadcde15 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Nov 2020 11:40:24 +0100 +Subject: [PATCH 09/20] sd-event: split clock data allocation out of + sd_event_add_time() + +Just some simple refactoring, that will make things easier for us later. +But it looks better this way even without the later function reuse. + +(cherry picked from commit 41c63f36c3352af8bebf03b6181f5d866431d0af) + +Related: #1819868 + +[commit 6cc0022115afbac9ac66c456b140601d90271687 from +https://github.com/systemd-rhel/rhel-8/] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 34 ++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 11 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 7074520..8e6536f 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -1065,6 +1065,28 @@ static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); + } + ++static int setup_clock_data(sd_event *e, struct clock_data *d, clockid_t clock) { ++ int r; ++ ++ assert(d); ++ ++ if (d->fd < 0) { ++ r = event_setup_timer_fd(e, d, clock); ++ if (r < 0) ++ return r; ++ } ++ ++ r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); ++ if (r < 0) ++ return r; ++ ++ r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); ++ if (r < 0) ++ return r; ++ ++ return 0; ++} ++ + _public_ int sd_event_add_time( + sd_event *e, + sd_event_source **ret, +@@ -1094,20 +1116,10 @@ _public_ int sd_event_add_time( + d = event_get_clock_data(e, type); + assert(d); + +- r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); +- if (r < 0) +- return r; +- +- r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); ++ r = setup_clock_data(e, d, clock); + if (r < 0) + return r; + +- if (d->fd < 0) { +- r = event_setup_timer_fd(e, d, clock); +- if (r < 0) +- return r; +- } +- + s = source_new(e, !ret, type); + if (!s) + return -ENOMEM; +-- +2.17.1 + diff --git a/base/systemd/debian/patches/910-sd-event-split-out-code-to-add-remove-timer-event-so.patch b/base/systemd/debian/patches/910-sd-event-split-out-code-to-add-remove-timer-event-so.patch new file mode 100644 index 000000000..8c5f6505b --- /dev/null +++ b/base/systemd/debian/patches/910-sd-event-split-out-code-to-add-remove-timer-event-so.patch @@ -0,0 +1,120 @@ +From dad1d000b493f98f4f5eaf4bfa34c8617f41970f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Nov 2020 15:25:35 +0100 +Subject: [PATCH 10/20] sd-event: split out code to add/remove timer event + sources to earliest/latest prioq + +Just some refactoring that makes code prettier, and will come handy +later, because we can reuse these functions at more places. + +(cherry picked from commit 1e45e3fecc303e7ae9946220c742f69675e99c34) + +Related: #1819868 + +[commit 88b2618e4de850060a1c5c22b049e6de0578fbb5 from +https://github.com/systemd-rhel/rhel-8/] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 57 +++++++++++++++++++++--------- + 1 file changed, 41 insertions(+), 16 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 8e6536f..e0e0eaa 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -723,6 +723,19 @@ static void event_source_time_prioq_resh + d->needs_rearm = true; + } + ++static void event_source_time_prioq_remove( ++ sd_event_source *s, ++ struct clock_data *d) { ++ ++ assert(s); ++ assert(d); ++ ++ prioq_remove(d->earliest, s, &s->time.earliest_index); ++ prioq_remove(d->latest, s, &s->time.latest_index); ++ s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL; ++ d->needs_rearm = true; ++} ++ + static void source_disconnect(sd_event_source *s) { + sd_event *event; + +@@ -747,13 +760,8 @@ static void source_disconnect(sd_event_s + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; +- +- d = event_get_clock_data(s->event, s->type); +- assert(d); +- +- prioq_remove(d->earliest, s, &s->time.earliest_index); +- prioq_remove(d->latest, s, &s->time.latest_index); +- d->needs_rearm = true; ++ assert_se(d = event_get_clock_data(s->event, s->type)); ++ event_source_time_prioq_remove(s, d); + break; + } + +@@ -1110,6 +1118,30 @@ static int setup_clock_data(sd_event *e, + return 0; + } + ++static int event_source_time_prioq_put( ++ sd_event_source *s, ++ struct clock_data *d) { ++ ++ int r; ++ ++ assert(s); ++ assert(d); ++ ++ r = prioq_put(d->earliest, s, &s->time.earliest_index); ++ if (r < 0) ++ return r; ++ ++ r = prioq_put(d->latest, s, &s->time.latest_index); ++ if (r < 0) { ++ assert_se(prioq_remove(d->earliest, s, &s->time.earliest_index) > 0); ++ s->time.earliest_index = PRIOQ_IDX_NULL; ++ return r; ++ } ++ ++ d->needs_rearm = true; ++ return 0; ++} ++ + _public_ int sd_event_add_time( + sd_event *e, + sd_event_source **ret, +@@ -1140,8 +1172,7 @@ _public_ int sd_event_add_time( + if (!callback) + callback = time_exit_callback; + +- d = event_get_clock_data(e, type); +- assert(d); ++ assert_se(d = event_get_clock_data(e, type)); + + r = setup_clock_data(e, d, clock); + if (r < 0) +@@ -1158,13 +1189,7 @@ _public_ int sd_event_add_time( + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + +- d->needs_rearm = true; +- +- r = prioq_put(d->earliest, s, &s->time.earliest_index); +- if (r < 0) +- return r; +- +- r = prioq_put(d->latest, s, &s->time.latest_index); ++ r = event_source_time_prioq_put(s, d); + if (r < 0) + return r; + +-- +2.17.1 + diff --git a/base/systemd/debian/patches/913-sd-event-remove-earliest_index-latest_index-into-com.patch b/base/systemd/debian/patches/913-sd-event-remove-earliest_index-latest_index-into-com.patch new file mode 100644 index 000000000..528422992 --- /dev/null +++ b/base/systemd/debian/patches/913-sd-event-remove-earliest_index-latest_index-into-com.patch @@ -0,0 +1,110 @@ +From f72ca8a711fc406dc52f18c7dbc3bfc5397b26ea Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Nov 2020 17:49:27 +0100 +Subject: [PATCH 13/20] sd-event: remove earliest_index/latest_index into + common part of event source objects + +So far we used these fields to organize the earliest/latest timer event +priority queue. In a follow-up commit we want to introduce ratelimiting +to event sources, at which point we want any kind of event source to be +able to trigger time wakeups, and hence they all need to be included in +the earliest/latest prioqs. Thus, in preparation let's make this +generic. + +No change in behaviour, just some shifting around of struct members from +the type-specific to the generic part. + +(cherry picked from commit f41315fceb5208c496145cda2d6c865a5458ce44) + +Related: #1819868 + +[commit 97f599bf57fdaee688ae5750e9b2b2587e2b597a from +https://github.com/systemd-rhel/rhel-8/] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/src/libsystemd/sd-event/event-source.h b/src/libsystemd/sd-event/event-source.h +index 62d07187a2..189d3b48df 100644 +--- a/src/libsystemd/sd-event/event-source.h ++++ b/src/libsystemd/sd-event/event-source.h +@@ -72,6 +72,9 @@ struct sd_event_source { + + LIST_FIELDS(sd_event_source, sources); + ++ unsigned earliest_index; ++ unsigned latest_index; ++ + union { + struct { + sd_event_io_handler_t callback; +@@ -84,8 +87,6 @@ struct sd_event_source { + struct { + sd_event_time_handler_t callback; + usec_t next, accuracy; +- unsigned earliest_index; +- unsigned latest_index; + } time; + struct { + sd_event_signal_handler_t callback; +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index a2f7868..82cb9ad 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -718,8 +718,8 @@ static void event_source_time_prioq_resh + /* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy, + * pending, enable state. Makes sure the two prioq's are ordered properly again. */ + assert_se(d = event_get_clock_data(s->event, s->type)); +- prioq_reshuffle(d->earliest, s, &s->time.earliest_index); +- prioq_reshuffle(d->latest, s, &s->time.latest_index); ++ prioq_reshuffle(d->earliest, s, &s->earliest_index); ++ prioq_reshuffle(d->latest, s, &s->latest_index); + d->needs_rearm = true; + } + +@@ -730,9 +730,9 @@ static void event_source_time_prioq_remo + assert(s); + assert(d); + +- prioq_remove(d->earliest, s, &s->time.earliest_index); +- prioq_remove(d->latest, s, &s->time.latest_index); +- s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL; ++ prioq_remove(d->earliest, s, &s->earliest_index); ++ prioq_remove(d->latest, s, &s->latest_index); ++ s->earliest_index = s->latest_index = PRIOQ_IDX_NULL; + d->needs_rearm = true; + } + +@@ -1105,14 +1105,14 @@ static int event_source_time_prioq_put( + assert(s); + assert(d); + +- r = prioq_put(d->earliest, s, &s->time.earliest_index); ++ r = prioq_put(d->earliest, s, &s->earliest_index); + if (r < 0) + return r; + +- r = prioq_put(d->latest, s, &s->time.latest_index); ++ r = prioq_put(d->latest, s, &s->latest_index); + if (r < 0) { +- assert_se(prioq_remove(d->earliest, s, &s->time.earliest_index) > 0); +- s->time.earliest_index = PRIOQ_IDX_NULL; ++ assert_se(prioq_remove(d->earliest, s, &s->earliest_index) > 0); ++ s->earliest_index = PRIOQ_IDX_NULL; + return r; + } + +@@ -1173,7 +1173,7 @@ _public_ int sd_event_add_time( + s->time.next = usec; + s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy; + s->time.callback = callback; +- s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL; ++ s->earliest_index = s->latest_index = PRIOQ_IDX_NULL; + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + +-- +2.17.1 + diff --git a/base/systemd/debian/patches/919-sd-event-add-ability-to-ratelimit-event-sources.patch b/base/systemd/debian/patches/919-sd-event-add-ability-to-ratelimit-event-sources.patch new file mode 100644 index 000000000..62710f6ba --- /dev/null +++ b/base/systemd/debian/patches/919-sd-event-add-ability-to-ratelimit-event-sources.patch @@ -0,0 +1,835 @@ +From 69266c451910d2b57313b2fe7561e07cd5400d27 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Nov 2020 18:02:40 +0100 +Subject: [PATCH 19/20] sd-event: add ability to ratelimit event sources + +Let's a concept of "rate limiting" to event sources: if specific event +sources fire too often in some time interval temporarily take them +offline, and take them back online once the interval passed. + +This is a simple scheme of avoiding starvation of event sources if some +event source fires too often. + +This introduces the new conceptual states of "offline" and "online" for +event sources: an event source is "online" only when enabled *and* not +ratelimited, and offline in all other cases. An event source that is +online hence has its fds registered in the epoll, its signals in the +signalfd and so on. + +(cherry picked from commit b6d5481b3d9f7c9b1198ab54b54326ec73e855bf) + +Related: #1819868 + +[commit 395eb7753a9772f505102fbbe3ba3261b57abbe9 from +https://github.com/systemd-rhel/rhel-8/ + +LZ: Moved the changes in libsystemd.sym to libsystemd.sym.m4 from the +file changing history; patch ratelimit.h in its old path; dropped +SOURCE_INOTIFY related parts in sd-event.c because it hasn't been +added in this systemd version.] + +Signed-off-by: Li Zhou +--- + src/libsystemd/libsystemd.sym | 7 + + src/libsystemd/sd-event/event-source.h | 6 + + src/libsystemd/sd-event/sd-event.c | 396 +++++++++++++++++++++---- + src/systemd/sd-event.h | 3 + + 4 files changed, 350 insertions(+), 62 deletions(-) + +diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym +index f83b364c96..b03bcd952f 100644 +--- a/src/libsystemd/libsystemd.sym ++++ b/src/libsystemd/libsystemd.sym +@@ -736,3 +736,10 @@ global: + sd_device_has_current_tag; + sd_device_set_sysattr_valuef; + } LIBSYSTEMD_246; ++ ++LIBSYSTEMD_248 { ++global: ++ sd_event_source_set_ratelimit; ++ sd_event_source_get_ratelimit; ++ sd_event_source_is_ratelimited; ++} LIBSYSTEMD_246; +diff --git a/src/libsystemd/sd-event/event-source.h b/src/libsystemd/sd-event/event-source.h +index 189d3b48df..f0d2a1b9e6 100644 +--- a/src/libsystemd/sd-event/event-source.h ++++ b/src/libsystemd/sd-event/event-source.h +@@ -11,6 +11,7 @@ + #include "hashmap.h" + #include "list.h" + #include "prioq.h" ++#include "ratelimit.h" + + typedef enum EventSourceType { + SOURCE_IO, +@@ -61,6 +62,7 @@ struct sd_event_source { + bool dispatching:1; + bool floating:1; + bool exit_on_failure:1; ++ bool ratelimited:1; + + int64_t priority; + unsigned pending_index; +@@ -72,6 +74,10 @@ struct sd_event_source { + + LIST_FIELDS(sd_event_source, sources); + ++ RateLimit rate_limit; ++ ++ /* These are primarily fields relevant for time event sources, but since any event source can ++ * effectively become one when rate-limited, this is part of the common fields. */ + unsigned earliest_index; + unsigned latest_index; + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 39f13cb409..3f1a6776fe 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -37,6 +37,16 @@ static bool EVENT_SOURCE_WATCH_PIDFD(sd_event_source *s) { + s->child.options == WEXITED; + } + ++static bool event_source_is_online(sd_event_source *s) { ++ assert(s); ++ return s->enabled != SD_EVENT_OFF && !s->ratelimited; ++} ++ ++static bool event_source_is_offline(sd_event_source *s) { ++ assert(s); ++ return s->enabled == SD_EVENT_OFF || s->ratelimited; ++} ++ + static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = { + [SOURCE_IO] = "io", + [SOURCE_TIME_REALTIME] = "realtime", +@@ -55,7 +65,25 @@ static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] + + DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int); + +-#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM) ++#define EVENT_SOURCE_IS_TIME(t) \ ++ IN_SET((t), \ ++ SOURCE_TIME_REALTIME, \ ++ SOURCE_TIME_BOOTTIME, \ ++ SOURCE_TIME_MONOTONIC, \ ++ SOURCE_TIME_REALTIME_ALARM, \ ++ SOURCE_TIME_BOOTTIME_ALARM) ++ ++#define EVENT_SOURCE_CAN_RATE_LIMIT(t) \ ++ IN_SET((t), \ ++ SOURCE_IO, \ ++ SOURCE_TIME_REALTIME, \ ++ SOURCE_TIME_BOOTTIME, \ ++ SOURCE_TIME_MONOTONIC, \ ++ SOURCE_TIME_REALTIME_ALARM, \ ++ SOURCE_TIME_BOOTTIME_ALARM, \ ++ SOURCE_SIGNAL, \ ++ SOURCE_DEFER, \ ++ SOURCE_INOTIFY) + + struct sd_event { + unsigned n_ref; +@@ -81,7 +109,7 @@ struct sd_event { + Hashmap *signal_data; /* indexed by priority */ + + Hashmap *child_sources; +- unsigned n_enabled_child_sources; ++ unsigned n_online_child_sources; + + Set *post_sources; + +@@ -146,6 +174,11 @@ static int pending_prioq_compare(const void *a, const void *b) { + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + ++ /* Non rate-limited ones first. */ ++ r = CMP(!!x->ratelimited, !!y->ratelimited); ++ if (r != 0) ++ return r; ++ + /* Lower priority values first */ + r = CMP(x->priority, y->priority); + if (r != 0) +@@ -168,6 +201,11 @@ static int prepare_prioq_compare(const void *a, const void *b) { + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + ++ /* Non rate-limited ones first. */ ++ r = CMP(!!x->ratelimited, !!y->ratelimited); ++ if (r != 0) ++ return r; ++ + /* Move most recently prepared ones last, so that we can stop + * preparing as soon as we hit one that has already been + * prepared in the current iteration */ +@@ -179,12 +217,30 @@ static int prepare_prioq_compare(const void *a, const void *b) { + return CMP(x->priority, y->priority); + } + ++static usec_t time_event_source_next(const sd_event_source *s) { ++ assert(s); ++ ++ /* We have two kinds of event sources that have elapsation times associated with them: the actual ++ * time based ones and the ones for which a ratelimit can be in effect (where we want to be notified ++ * once the ratelimit time window ends). Let's return the next elapsing time depending on what we are ++ * looking at here. */ ++ ++ if (s->ratelimited) { /* If rate-limited the next elapsation is when the ratelimit time window ends */ ++ assert(s->rate_limit.begin != 0); ++ assert(s->rate_limit.interval != 0); ++ return usec_add(s->rate_limit.begin, s->rate_limit.interval); ++ } ++ ++ /* Otherwise this must be a time event source, if not ratelimited */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ return s->time.next; ++ ++ return USEC_INFINITY; ++} ++ + static int earliest_time_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + +- assert(EVENT_SOURCE_IS_TIME(x->type)); +- assert(x->type == y->type); +- + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; +@@ -198,19 +254,30 @@ static int earliest_time_prioq_compare(const void *a, const void *b) { + return 1; + + /* Order by time */ +- return CMP(x->time.next, y->time.next); ++ return CMP(time_event_source_next(x), time_event_source_next(y)); + } + + static usec_t time_event_source_latest(const sd_event_source *s) { +- return usec_add(s->time.next, s->time.accuracy); ++ assert(s); ++ ++ if (s->ratelimited) { /* For ratelimited stuff the earliest and the latest time shall actually be the ++ * same, as we should avoid adding additional inaccuracy on an inaccuracy time ++ * window */ ++ assert(s->rate_limit.begin != 0); ++ assert(s->rate_limit.interval != 0); ++ return usec_add(s->rate_limit.begin, s->rate_limit.interval); ++ } ++ ++ /* Must be a time event source, if not ratelimited */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ return usec_add(s->time.next, s->time.accuracy); ++ ++ return USEC_INFINITY; + } + + static int latest_time_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + +- assert(EVENT_SOURCE_IS_TIME(x->type)); +- assert(x->type == y->type); +- + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; +@@ -661,12 +728,12 @@ static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) + * and possibly drop the signalfd for it. */ + + if (sig == SIGCHLD && +- e->n_enabled_child_sources > 0) ++ e->n_online_child_sources > 0) + return; + + if (e->signal_sources && + e->signal_sources[sig] && +- e->signal_sources[sig]->enabled != SD_EVENT_OFF) ++ event_source_is_online(e->signal_sources[sig])) + return; + + /* +@@ -713,11 +780,17 @@ static void event_source_time_prioq_reshuffle(sd_event_source *s) { + struct clock_data *d; + + assert(s); +- assert(EVENT_SOURCE_IS_TIME(s->type)); + + /* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy, + * pending, enable state. Makes sure the two prioq's are ordered properly again. */ +- assert_se(d = event_get_clock_data(s->event, s->type)); ++ ++ if (s->ratelimited) ++ d = &s->event->monotonic; ++ else { ++ assert(EVENT_SOURCE_IS_TIME(s->type)); ++ assert_se(d = event_get_clock_data(s->event, s->type)); ++ } ++ + prioq_reshuffle(d->earliest, s, &s->earliest_index); + prioq_reshuffle(d->latest, s, &s->latest_index); + d->needs_rearm = true; +@@ -758,12 +831,18 @@ static void source_disconnect(sd_event_source *s) { + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: +- case SOURCE_TIME_BOOTTIME_ALARM: { +- struct clock_data *d; +- assert_se(d = event_get_clock_data(s->event, s->type)); +- event_source_time_prioq_remove(s, d); ++ case SOURCE_TIME_BOOTTIME_ALARM: ++ /* Only remove this event source from the time event source here if it is not ratelimited. If ++ * it is ratelimited, we'll remove it below, separately. Why? Because the clock used might ++ * differ: ratelimiting always uses CLOCK_MONOTONIC, but timer events might use any clock */ ++ ++ if (!s->ratelimited) { ++ struct clock_data *d; ++ assert_se(d = event_get_clock_data(s->event, s->type)); ++ event_source_time_prioq_remove(s, d); ++ } ++ + break; +- } + + case SOURCE_SIGNAL: + if (s->signal.sig > 0) { +@@ -778,9 +857,9 @@ static void source_disconnect(sd_event_source *s) { + + case SOURCE_CHILD: + if (s->child.pid > 0) { +- if (s->enabled != SD_EVENT_OFF) { +- assert(s->event->n_enabled_child_sources > 0); +- s->event->n_enabled_child_sources--; ++ if (event_source_is_online(s)) { ++ assert(s->event->n_online_child_sources > 0); ++ s->event->n_online_child_sources--; + } + + (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid)); +@@ -850,6 +929,9 @@ static void source_disconnect(sd_event_source *s) { + if (s->prepare) + prioq_remove(s->event->prepare, s, &s->prepare_index); + ++ if (s->ratelimited) ++ event_source_time_prioq_remove(s, &s->event->monotonic); ++ + event = TAKE_PTR(s->event); + LIST_REMOVE(sources, event->sources, s); + event->n_sources--; +@@ -1322,7 +1404,7 @@ _public_ int sd_event_add_child( + if (!callback) + callback = child_exit_callback; + +- if (e->n_enabled_child_sources == 0) { ++ if (e->n_online_child_sources == 0) { + /* Caller must block SIGCHLD before using us to watch children, even if pidfd is available, + * for compatibility with pre-pidfd and because we don't want the reap the child processes + * ourselves, i.e. call waitid(), and don't want Linux' default internal logic for that to +@@ -1387,7 +1469,7 @@ _public_ int sd_event_add_child( + e->need_process_child = true; + } + +- e->n_enabled_child_sources++; ++ e->n_online_child_sources++; + + if (ret) + *ret = s; +@@ -1419,7 +1501,7 @@ _public_ int sd_event_add_child_pidfd( + if (!callback) + callback = child_exit_callback; + +- if (e->n_enabled_child_sources == 0) { ++ if (e->n_online_child_sources == 0) { + r = signal_is_blocked(SIGCHLD); + if (r < 0) + return r; +@@ -1469,7 +1551,7 @@ _public_ int sd_event_add_child_pidfd( + e->need_process_child = true; + } + +- e->n_enabled_child_sources++; ++ e->n_online_child_sources++; + + if (ret) + *ret = s; +@@ -2055,7 +2137,7 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { + if (s->io.fd == fd) + return 0; + +- if (s->enabled == SD_EVENT_OFF) { ++ if (event_source_is_offline(s)) { + s->io.fd = fd; + s->io.registered = false; + } else { +@@ -2122,7 +2204,7 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) + if (r < 0) + return r; + +- if (s->enabled != SD_EVENT_OFF) { ++ if (event_source_is_online(s)) { + r = source_io_register(s, s->enabled, events); + if (r < 0) + return r; +@@ -2225,7 +2307,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) + + event_gc_inode_data(s->event, old_inode_data); + +- } else if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) { ++ } else if (s->type == SOURCE_SIGNAL && event_source_is_online(s)) { + struct signal_data *old, *d; + + /* Move us from the signalfd belonging to the old +@@ -2272,20 +2354,29 @@ _public_ int sd_event_source_get_enabled(sd_event_source *s, int *ret) { + return s->enabled != SD_EVENT_OFF; + } + +-static int event_source_disable(sd_event_source *s) { ++static int event_source_offline( ++ sd_event_source *s, ++ int enabled, ++ bool ratelimited) { ++ ++ bool was_offline; + int r; + + assert(s); +- assert(s->enabled != SD_EVENT_OFF); ++ assert(enabled == SD_EVENT_OFF || ratelimited); + + /* Unset the pending flag when this event source is disabled */ +- if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { ++ if (s->enabled != SD_EVENT_OFF && ++ enabled == SD_EVENT_OFF && ++ !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) + return r; + } + +- s->enabled = SD_EVENT_OFF; ++ was_offline = event_source_is_offline(s); ++ s->enabled = enabled; ++ s->ratelimited = ratelimited; + + switch (s->type) { + +@@ -2306,8 +2397,10 @@ static int event_source_disable(sd_event_source *s) { + break; + + case SOURCE_CHILD: +- assert(s->event->n_enabled_child_sources > 0); +- s->event->n_enabled_child_sources--; ++ if (!was_offline) { ++ assert(s->event->n_online_child_sources > 0); ++ s->event->n_online_child_sources--; ++ } + + if (EVENT_SOURCE_WATCH_PIDFD(s)) + source_child_pidfd_unregister(s); +@@ -2328,26 +2421,42 @@ static int event_source_disable(sd_event_source *s) { + assert_not_reached("Wut? I shouldn't exist."); + } + +- return 0; ++ return 1; + } + +-static int event_source_enable(sd_event_source *s, int enable) { ++static int event_source_online( ++ sd_event_source *s, ++ int enabled, ++ bool ratelimited) { ++ ++ bool was_online; + int r; + + assert(s); +- assert(IN_SET(enable, SD_EVENT_ON, SD_EVENT_ONESHOT)); +- assert(s->enabled == SD_EVENT_OFF); ++ assert(enabled != SD_EVENT_OFF || !ratelimited); + + /* Unset the pending flag when this event source is enabled */ +- if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { ++ if (s->enabled == SD_EVENT_OFF && ++ enabled != SD_EVENT_OFF && ++ !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) + return r; + } + ++ /* Are we really ready for onlining? */ ++ if (enabled == SD_EVENT_OFF || ratelimited) { ++ /* Nope, we are not ready for onlining, then just update the precise state and exit */ ++ s->enabled = enabled; ++ s->ratelimited = ratelimited; ++ return 0; ++ } ++ ++ was_online = event_source_is_online(s); ++ + switch (s->type) { + case SOURCE_IO: +- r = source_io_register(s, enable, s->io.events); ++ r = source_io_register(s, enabled, s->io.events); + if (r < 0) + return r; + break; +@@ -2365,7 +2474,7 @@ static int event_source_enable(sd_event_source *s, int enable) { + if (EVENT_SOURCE_WATCH_PIDFD(s)) { + /* yes, we have pidfd */ + +- r = source_child_pidfd_register(s, enable); ++ r = source_child_pidfd_register(s, enabled); + if (r < 0) + return r; + } else { +@@ -2378,8 +2487,8 @@ static int event_source_enable(sd_event_source *s, int enable) { + } + } + +- s->event->n_enabled_child_sources++; +- ++ if (!was_online) ++ s->event->n_online_child_sources++; + break; + + case SOURCE_TIME_REALTIME: +@@ -2397,7 +2506,8 @@ static int event_source_enable(sd_event_source *s, int enable) { + assert_not_reached("Wut? I shouldn't exist."); + } + +- s->enabled = enable; ++ s->enabled = enabled; ++ s->ratelimited = ratelimited; + + /* Non-failing operations below */ + switch (s->type) { +@@ -2417,7 +2527,7 @@ static int event_source_enable(sd_event_source *s, int enable) { + break; + } + +- return 0; ++ return 1; + } + + _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { +@@ -2435,7 +2545,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { + return 0; + + if (m == SD_EVENT_OFF) +- r = event_source_disable(s); ++ r = event_source_offline(s, m, s->ratelimited); + else { + if (s->enabled != SD_EVENT_OFF) { + /* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the +@@ -2444,7 +2554,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { + return 0; + } + +- r = event_source_enable(s, m); ++ r = event_source_online(s, m, s->ratelimited); + } + if (r < 0) + return r; +@@ -2701,6 +2811,96 @@ _public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) + return ret; + } + ++static int event_source_enter_ratelimited(sd_event_source *s) { ++ int r; ++ ++ assert(s); ++ ++ /* When an event source becomes ratelimited, we place it in the CLOCK_MONOTONIC priority queue, with ++ * the end of the rate limit time window, much as if it was a timer event source. */ ++ ++ if (s->ratelimited) ++ return 0; /* Already ratelimited, this is a NOP hence */ ++ ++ /* Make sure we can install a CLOCK_MONOTONIC event further down. */ ++ r = setup_clock_data(s->event, &s->event->monotonic, CLOCK_MONOTONIC); ++ if (r < 0) ++ return r; ++ ++ /* Timer event sources are already using the earliest/latest queues for the timer scheduling. Let's ++ * first remove them from the prioq appropriate for their own clock, so that we can use the prioq ++ * fields of the event source then for adding it to the CLOCK_MONOTONIC prioq instead. */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ event_source_time_prioq_remove(s, event_get_clock_data(s->event, s->type)); ++ ++ /* Now, let's add the event source to the monotonic clock instead */ ++ r = event_source_time_prioq_put(s, &s->event->monotonic); ++ if (r < 0) ++ goto fail; ++ ++ /* And let's take the event source officially offline */ ++ r = event_source_offline(s, s->enabled, /* ratelimited= */ true); ++ if (r < 0) { ++ event_source_time_prioq_remove(s, &s->event->monotonic); ++ goto fail; ++ } ++ ++ event_source_pp_prioq_reshuffle(s); ++ ++ log_debug("Event source %p (%s) entered rate limit state.", s, strna(s->description)); ++ return 0; ++ ++fail: ++ /* Reinstall time event sources in the priority queue as before. This shouldn't fail, since the queue ++ * space for it should already be allocated. */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ assert_se(event_source_time_prioq_put(s, event_get_clock_data(s->event, s->type)) >= 0); ++ ++ return r; ++} ++ ++static int event_source_leave_ratelimit(sd_event_source *s) { ++ int r; ++ ++ assert(s); ++ ++ if (!s->ratelimited) ++ return 0; ++ ++ /* Let's take the event source out of the monotonic prioq first. */ ++ event_source_time_prioq_remove(s, &s->event->monotonic); ++ ++ /* Let's then add the event source to its native clock prioq again — if this is a timer event source */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) { ++ r = event_source_time_prioq_put(s, event_get_clock_data(s->event, s->type)); ++ if (r < 0) ++ goto fail; ++ } ++ ++ /* Let's try to take it online again. */ ++ r = event_source_online(s, s->enabled, /* ratelimited= */ false); ++ if (r < 0) { ++ /* Do something roughly sensible when this failed: undo the two prioq ops above */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ event_source_time_prioq_remove(s, event_get_clock_data(s->event, s->type)); ++ ++ goto fail; ++ } ++ ++ event_source_pp_prioq_reshuffle(s); ++ ratelimit_reset(&s->rate_limit); ++ ++ log_debug("Event source %p (%s) left rate limit state.", s, strna(s->description)); ++ return 0; ++ ++fail: ++ /* Do something somewhat reasonable when we cannot move an event sources out of ratelimited mode: ++ * simply put it back in it, maybe we can then process it more successfully next iteration. */ ++ assert_se(event_source_time_prioq_put(s, &s->event->monotonic) >= 0); ++ ++ return r; ++} ++ + static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { + usec_t c; + assert(e); +@@ -2798,7 +2998,7 @@ static int event_arm_timer( + d->needs_rearm = false; + + a = prioq_peek(d->earliest); +- if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) { ++ if (!a || a->enabled == SD_EVENT_OFF || time_event_source_next(a) == USEC_INFINITY) { + + if (d->fd < 0) + return 0; +@@ -2817,7 +3017,7 @@ static int event_arm_timer( + b = prioq_peek(d->latest); + assert_se(b && b->enabled != SD_EVENT_OFF); + +- t = sleep_between(e, a->time.next, time_event_source_latest(b)); ++ t = sleep_between(e, time_event_source_next(a), time_event_source_latest(b)); + if (d->next == t) + return 0; + +@@ -2895,10 +3095,22 @@ static int process_timer( + + for (;;) { + s = prioq_peek(d->earliest); +- if (!s || +- s->time.next > n || +- s->enabled == SD_EVENT_OFF || +- s->pending) ++ if (!s || time_event_source_next(s) > n) ++ break; ++ ++ if (s->ratelimited) { ++ /* This is an event sources whose ratelimit window has ended. Let's turn it on ++ * again. */ ++ assert(s->ratelimited); ++ ++ r = event_source_leave_ratelimit(s); ++ if (r < 0) ++ return r; ++ ++ continue; ++ } ++ ++ if (s->enabled == SD_EVENT_OFF || s->pending) + break; + + r = source_set_pending(s, true); +@@ -2943,7 +3155,7 @@ static int process_child(sd_event *e) { + if (s->pending) + continue; + +- if (s->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(s)) + continue; + + if (s->child.exited) +@@ -2990,7 +3202,7 @@ static int process_pidfd(sd_event *e, sd_event_source *s, uint32_t revents) { + if (s->pending) + return 0; + +- if (s->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(s)) + return 0; + + if (!EVENT_SOURCE_WATCH_PIDFD(s)) +@@ -3150,7 +3362,7 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { + + LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { + +- if (s->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(s)) + continue; + + r = source_set_pending(s, true); +@@ -3186,7 +3398,7 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { + * sources if IN_IGNORED or IN_UNMOUNT is set. */ + LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { + +- if (s->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(s)) + continue; + + if ((d->buffer.ev.mask & (IN_IGNORED|IN_UNMOUNT)) == 0 && +@@ -3240,6 +3452,16 @@ static int source_dispatch(sd_event_source *s) { + * callback might have invalidated/disconnected the event source. */ + saved_event = sd_event_ref(s->event); + ++ /* Check if we hit the ratelimit for this event source, if so, let's disable it. */ ++ assert(!s->ratelimited); ++ if (!ratelimit_below(&s->rate_limit)) { ++ r = event_source_enter_ratelimited(s); ++ if (r < 0) ++ return r; ++ ++ return 1; ++ } ++ + if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) +@@ -3253,7 +3475,7 @@ static int source_dispatch(sd_event_source *s) { + * post sources as pending */ + + SET_FOREACH(z, s->event->post_sources) { +- if (z->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(z)) + continue; + + r = source_set_pending(z, true); +@@ -3373,7 +3595,7 @@ static int event_prepare(sd_event *e) { + sd_event_source *s; + + s = prioq_peek(e->prepare); +- if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF) ++ if (!s || s->prepare_iteration == e->iteration || event_source_is_offline(s)) + break; + + s->prepare_iteration = e->iteration; +@@ -3413,7 +3635,7 @@ static int dispatch_exit(sd_event *e) { + assert(e); + + p = prioq_peek(e->exit); +- if (!p || p->enabled == SD_EVENT_OFF) { ++ if (!p || event_source_is_offline(p)) { + e->state = SD_EVENT_FINISHED; + return 0; + } +@@ -3435,7 +3657,7 @@ static sd_event_source* event_next_pending(sd_event *e) { + if (!p) + return NULL; + +- if (p->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(p)) + return NULL; + + return p; +@@ -4049,3 +4271,53 @@ _public_ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b) { + s->exit_on_failure = b; + return 1; + } ++ ++_public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval, unsigned burst) { ++ int r; ++ ++ assert_return(s, -EINVAL); ++ ++ /* Turning on ratelimiting on event source types that don't support it, is a loggable offense. Doing ++ * so is a programming error. */ ++ assert_return(EVENT_SOURCE_CAN_RATE_LIMIT(s->type), -EDOM); ++ ++ /* When ratelimiting is configured we'll always reset the rate limit state first and start fresh, ++ * non-ratelimited. */ ++ r = event_source_leave_ratelimit(s); ++ if (r < 0) ++ return r; ++ ++ s->rate_limit = (RateLimit) { interval, burst }; ++ return 0; ++} ++ ++_public_ int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval, unsigned *ret_burst) { ++ assert_return(s, -EINVAL); ++ ++ /* Querying whether an event source has ratelimiting configured is not a loggable offsense, hence ++ * don't use assert_return(). Unlike turning on ratelimiting it's not really a programming error */ ++ if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type)) ++ return -EDOM; ++ ++ if (!ratelimit_configured(&s->rate_limit)) ++ return -ENOEXEC; ++ ++ if (ret_interval) ++ *ret_interval = s->rate_limit.interval; ++ if (ret_burst) ++ *ret_burst = s->rate_limit.burst; ++ ++ return 0; ++} ++ ++_public_ int sd_event_source_is_ratelimited(sd_event_source *s) { ++ assert_return(s, -EINVAL); ++ ++ if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type)) ++ return false; ++ ++ if (!ratelimit_configured(&s->rate_limit)) ++ return false; ++ ++ return s->ratelimited; ++} +diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h +index 937c9bd460..2ae2a0da48 100644 +--- a/src/systemd/sd-event.h ++++ b/src/systemd/sd-event.h +@@ -162,6 +162,9 @@ int sd_event_source_get_floating(sd_event_source *s); + int sd_event_source_set_floating(sd_event_source *s, int b); + int sd_event_source_get_exit_on_failure(sd_event_source *s); + int sd_event_source_set_exit_on_failure(sd_event_source *s, int b); ++int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval_usec, unsigned burst); ++int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval_usec, unsigned *ret_burst); ++int sd_event_source_is_ratelimited(sd_event_source *s); + + /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); +-- +2.17.1 + diff --git a/base/systemd/debian/patches/920-core-prevent-excessive-proc-self-mountinfo-parsing.patch b/base/systemd/debian/patches/920-core-prevent-excessive-proc-self-mountinfo-parsing.patch new file mode 100644 index 000000000..f3162d1a1 --- /dev/null +++ b/base/systemd/debian/patches/920-core-prevent-excessive-proc-self-mountinfo-parsing.patch @@ -0,0 +1,37 @@ +From dc3e079395816ce251c4794992f1816a61c1215d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Thu, 9 Jul 2020 18:16:44 +0200 +Subject: [PATCH 20/20] core: prevent excessive /proc/self/mountinfo parsing + +(cherry picked from commit d586f642fd90e3bb378f7b6d3e3a64a753e51756) + +Resolves: #1819868 + +[commit 51737206afaa10d902c86ec9b5ec97cf425039c2 from +https://github.com/systemd-rhel/rhel-8/] + +Signed-off-by: Li Zhou +--- + src/core/mount.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/core/mount.c b/src/core/mount.c +index c7aed23..48427b7 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1861,6 +1861,12 @@ static void mount_enumerate(Manager *m) + goto fail; + } + ++ r = sd_event_source_set_ratelimit(m->mount_event_source, 1 * USEC_PER_SEC, 5); ++ if (r < 0) { ++ log_error_errno(r, "Failed to enable rate limit for mount events: %m"); ++ goto fail; ++ } ++ + (void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch"); + } + +-- +2.17.1 + diff --git a/base/systemd/debian/patches/922-sd-event-change-ordering-of-pending-ratelimited-even.patch b/base/systemd/debian/patches/922-sd-event-change-ordering-of-pending-ratelimited-even.patch new file mode 100644 index 000000000..5aef7609a --- /dev/null +++ b/base/systemd/debian/patches/922-sd-event-change-ordering-of-pending-ratelimited-even.patch @@ -0,0 +1,100 @@ +From 762ba1d9cd3571f294965cb86525999e81fdec5d Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 8 Jun 2021 00:07:51 -0700 +Subject: [PATCH 1/6] sd-event: change ordering of pending/ratelimited events + +Instead of ordering non-pending before pending we should order +"non-pending OR ratelimited" before "pending AND not-ratelimited". +This fixes a bug where ratelimited events were ordered at the end of the +priority queue and could be stuck there for an indeterminate amount of +time. + +(cherry picked from commit 81107b8419c39f726fd2805517a5b9faab204e59) + +Related: #1984406 + +[commit 93de7820843c175f4c9661dbfcb312e8ee09fbd3 from +https://github.com/systemd-rhel/rhel-8/ (branch rhel-8.4.0)] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 48 +++++++++++++----------------- + 1 file changed, 20 insertions(+), 28 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 282b38f..fcf333e 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -237,25 +237,6 @@ static usec_t time_event_source_next(const sd_event_source *s) { + return USEC_INFINITY; + } + +-static int earliest_time_prioq_compare(const void *a, const void *b) { +- const sd_event_source *x = a, *y = b; +- +- /* Enabled ones first */ +- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) +- return -1; +- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) +- return 1; +- +- /* Move the pending ones to the end */ +- if (!x->pending && y->pending) +- return -1; +- if (x->pending && !y->pending) +- return 1; +- +- /* Order by time */ +- return CMP(time_event_source_next(x), time_event_source_next(y)); +-} +- + static usec_t time_event_source_latest(const sd_event_source *s) { + assert(s); + +@@ -274,7 +255,15 @@ static usec_t time_event_source_latest(const sd_event_source *s) { + return USEC_INFINITY; + } + +-static int latest_time_prioq_compare(const void *a, const void *b) { ++static bool event_source_timer_candidate(const sd_event_source *s) { ++ assert(s); ++ ++ /* Returns true for event sources that either are not pending yet (i.e. where it's worth to mark them pending) ++ * or which are currently ratelimited (i.e. where it's worth leaving the ratelimited state) */ ++ return !s->pending || s->ratelimited; ++} ++ ++static int time_prioq_compare(const void *a, const void *b, usec_t (*time_func)(const sd_event_source *s)) { + const sd_event_source *x = a, *y = b; + + /* Enabled ones first */ +@@ -283,14 +272,22 @@ static int latest_time_prioq_compare(const void *a, const void *b) { + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + +- /* Move the pending ones to the end */ +- if (!x->pending && y->pending) ++ /* Order "non-pending OR ratelimited" before "pending AND not-ratelimited" */ ++ if (event_source_timer_candidate(x) && !event_source_timer_candidate(y)) + return -1; +- if (x->pending && !y->pending) ++ if (!event_source_timer_candidate(x) && event_source_timer_candidate(y)) + return 1; + + /* Order by time */ +- return CMP(time_event_source_latest(x), time_event_source_latest(y)); ++ return CMP(time_func(x), time_func(y)); ++} ++ ++static int earliest_time_prioq_compare(const void *a, const void *b) { ++ return time_prioq_compare(a, b, time_event_source_next); ++} ++ ++static int latest_time_prioq_compare(const void *a, const void *b) { ++ return time_prioq_compare(a, b, time_event_source_latest); + } + + static int exit_prioq_compare(const void *a, const void *b) { +-- +2.17.1 + diff --git a/base/systemd/debian/patches/923-sd-event-drop-unnecessary-else.patch b/base/systemd/debian/patches/923-sd-event-drop-unnecessary-else.patch new file mode 100644 index 000000000..d3b5f3c0b --- /dev/null +++ b/base/systemd/debian/patches/923-sd-event-drop-unnecessary-else.patch @@ -0,0 +1,35 @@ +From 9824f4e131b5ffea0be23dd25b24b953314f1a79 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 15 Jun 2021 00:44:04 +0900 +Subject: [PATCH 2/6] sd-event: drop unnecessary "else" + +(cherry picked from commit 7e2bf71ca3638e36ee33215ceee386ba8013da6d) + +Related: #1984406 + +[commit 3e7e54c63236c65aa01bb332fd5135a13e51b992 from +https://github.com/systemd-rhel/rhel-8/ (branch rhel-8.4.0)] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index fcf333e..9b6d2f0 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -2199,8 +2199,8 @@ static int event_arm_timer( + + if (!d->needs_rearm) + return 0; +- else +- d->needs_rearm = false; ++ ++ d->needs_rearm = false; + + a = prioq_peek(d->earliest); + if (!a || a->enabled == SD_EVENT_OFF || time_event_source_next(a) == USEC_INFINITY) { +-- +2.17.1 + diff --git a/base/systemd/debian/patches/924-sd-event-use-CMP-macro.patch b/base/systemd/debian/patches/924-sd-event-use-CMP-macro.patch new file mode 100644 index 000000000..7e2840682 --- /dev/null +++ b/base/systemd/debian/patches/924-sd-event-use-CMP-macro.patch @@ -0,0 +1,98 @@ +From 766177b0afd897e43504c1228fe46ea03833df29 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 15 Jun 2021 00:51:33 +0900 +Subject: [PATCH 3/6] sd-event: use CMP() macro + +(cherry picked from commit 06e131477d82b83c5d516e66d6e413affd7c774a) + +Related: #1984406 + +[commit eaab8d57d9db0d98d7e618ba634983c34cdb9c06 from +https://github.com/systemd-rhel/rhel-8/ (branch rhel-8.4.0)] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 37 ++++++++++++++---------------- + 1 file changed, 17 insertions(+), 20 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 9b6d2f0..84a874d 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -168,10 +168,9 @@ static int pending_prioq_compare(const void *a, const void *b) { + assert(y->pending); + + /* Enabled ones first */ +- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) +- return -1; +- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) +- return 1; ++ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF); ++ if (r != 0) ++ return r; + + /* Non rate-limited ones first. */ + r = CMP(!!x->ratelimited, !!y->ratelimited); +@@ -195,10 +194,9 @@ static int prepare_prioq_compare(const void *a, const void *b) { + assert(y->prepare); + + /* Enabled ones first */ +- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) +- return -1; +- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) +- return 1; ++ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF); ++ if (r != 0) ++ return r; + + /* Non rate-limited ones first. */ + r = CMP(!!x->ratelimited, !!y->ratelimited); +@@ -265,18 +263,17 @@ static bool event_source_timer_candidate(const sd_event_source *s) { + + static int time_prioq_compare(const void *a, const void *b, usec_t (*time_func)(const sd_event_source *s)) { + const sd_event_source *x = a, *y = b; ++ int r; + + /* Enabled ones first */ +- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) +- return -1; +- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) +- return 1; ++ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF); ++ if (r != 0) ++ return r; + + /* Order "non-pending OR ratelimited" before "pending AND not-ratelimited" */ +- if (event_source_timer_candidate(x) && !event_source_timer_candidate(y)) +- return -1; +- if (!event_source_timer_candidate(x) && event_source_timer_candidate(y)) +- return 1; ++ r = CMP(!event_source_timer_candidate(x), !event_source_timer_candidate(y)); ++ if (r != 0) ++ return r; + + /* Order by time */ + return CMP(time_func(x), time_func(y)); +@@ -292,15 +289,15 @@ static int latest_time_prioq_compare(const void *a, const void *b) { + + static int exit_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; ++ int r; + + assert(x->type == SOURCE_EXIT); + assert(y->type == SOURCE_EXIT); + + /* Enabled ones first */ +- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) +- return -1; +- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) +- return 1; ++ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF); ++ if (r != 0) ++ return r; + + /* Lower priority values first */ + return CMP(x->priority, y->priority); +-- +2.17.1 + diff --git a/base/systemd/debian/patches/925-sd-event-use-usec_add.patch b/base/systemd/debian/patches/925-sd-event-use-usec_add.patch new file mode 100644 index 000000000..8e49ed067 --- /dev/null +++ b/base/systemd/debian/patches/925-sd-event-use-usec_add.patch @@ -0,0 +1,35 @@ +From e2088e9fd7dd09c542d8c456b62dbd2d21ee9e51 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 15 Jun 2021 01:01:48 +0900 +Subject: [PATCH 4/6] sd-event: use usec_add() + +(cherry picked from commit a595fb5ca9c69c589e758e9ebe3b70ac90450ba3) + +Related: #1984406 + +[commit b8732d647162b50ce9b34de2ad7ae11a53f6e7ba from +https://github.com/systemd-rhel/rhel-8/ (branch rhel-8.4.0)] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 84a874d..1cf1c41 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -3677,8 +3677,8 @@ static int arm_watchdog(sd_event *e) { + assert(e->watchdog_fd >= 0); + + t = sleep_between(e, +- e->watchdog_last + (e->watchdog_period / 2), +- e->watchdog_last + (e->watchdog_period * 3 / 4)); ++ usec_add(e->watchdog_last, (e->watchdog_period / 2)), ++ usec_add(e->watchdog_last, (e->watchdog_period * 3 / 4))); + + timespec_store(&its.it_value, t); + +-- +2.17.1 + diff --git a/base/systemd/debian/patches/926-sd-event-make-event_source_time_prioq_reshuffle-acce.patch b/base/systemd/debian/patches/926-sd-event-make-event_source_time_prioq_reshuffle-acce.patch new file mode 100644 index 000000000..ab465fe28 --- /dev/null +++ b/base/systemd/debian/patches/926-sd-event-make-event_source_time_prioq_reshuffle-acce.patch @@ -0,0 +1,48 @@ +From 9a3a48fde35fd02981b44ff6b2e184f33377d36c Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 15 Jun 2021 02:03:02 +0900 +Subject: [PATCH 5/6] sd-event: make event_source_time_prioq_reshuffle() accept + all event source type + +But it does nothing for an event source which is neither a timer nor +ratelimited. + +(cherry picked from commit 5c08c7ab23dbf02aaf4e4bbae8e08a195da230a4) + +Related: #1984406 + +[commit 9f044118dbc6a0f04b3820ffaa9d4c7807ae48a7 +https://github.com/systemd-rhel/rhel-8/ (branch rhel-8.4.0)] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 1cf1c41..6215bac 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -771,14 +771,15 @@ static void event_source_time_prioq_reshuffle(sd_event_source *s) { + assert(s); + + /* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy, +- * pending, enable state. Makes sure the two prioq's are ordered properly again. */ ++ * pending, enable state, and ratelimiting state. Makes sure the two prioq's are ordered ++ * properly again. */ + + if (s->ratelimited) + d = &s->event->monotonic; +- else { +- assert(EVENT_SOURCE_IS_TIME(s->type)); ++ else if (EVENT_SOURCE_IS_TIME(s->type)) + assert_se(d = event_get_clock_data(s->event, s->type)); +- } ++ else ++ return; /* no-op for an event source which is neither a timer nor ratelimited. */ + + prioq_reshuffle(d->earliest, s, &s->earliest_index); + prioq_reshuffle(d->latest, s, &s->latest_index); +-- +2.17.1 + diff --git a/base/systemd/debian/patches/927-sd-event-always-reshuffle-time-prioq-on-changing-onl.patch b/base/systemd/debian/patches/927-sd-event-always-reshuffle-time-prioq-on-changing-onl.patch new file mode 100644 index 000000000..c1f58b8af --- /dev/null +++ b/base/systemd/debian/patches/927-sd-event-always-reshuffle-time-prioq-on-changing-onl.patch @@ -0,0 +1,101 @@ +From 71552a073ed08beb227b9b007fb9818f08923baa Mon Sep 17 00:00:00 2001 +From: Li Zhou +Date: Tue, 26 Oct 2021 11:46:48 +0800 +Subject: [PATCH 6/6] sd-event: always reshuffle time prioq on changing + online/offline state + +Before 81107b8419c39f726fd2805517a5b9faab204e59, the compare functions +for the latest or earliest prioq did not handle ratelimited flag. +So, it was ok to not reshuffle the time prioq when changing the flag. + +But now, those two compare functions also compare the source is +ratelimited or not. So, it is necessary to reshuffle the time prioq +after changing the ratelimited flag. + +Hopefully fixes #19903. + +(cherry picked from commit 2115b9b6629eeba7bc9f42f757f38205febb1cb7) + +Related: #1984406 + +[commit f5611a22d4a65ef440352792085774ce898adb0f from +https://github.com/systemd-rhel/rhel-8/ (branch rhel-8.4.0) + +LZ: Adapt the patch for context changes and no real change on the +patch.] + +Signed-off-by: Li Zhou +--- + src/libsystemd/sd-event/sd-event.c | 33 ++++++++++-------------------- + 1 file changed, 11 insertions(+), 22 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 6215bac..c17b368 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -2370,14 +2370,6 @@ static int event_source_offline( + source_io_unregister(s); + break; + +- case SOURCE_TIME_REALTIME: +- case SOURCE_TIME_BOOTTIME: +- case SOURCE_TIME_MONOTONIC: +- case SOURCE_TIME_REALTIME_ALARM: +- case SOURCE_TIME_BOOTTIME_ALARM: +- event_source_time_prioq_reshuffle(s); +- break; +- + case SOURCE_SIGNAL: + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + break; +@@ -2398,6 +2390,11 @@ static int event_source_offline( + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + break; + ++ case SOURCE_TIME_REALTIME: ++ case SOURCE_TIME_BOOTTIME: ++ case SOURCE_TIME_MONOTONIC: ++ case SOURCE_TIME_REALTIME_ALARM: ++ case SOURCE_TIME_BOOTTIME_ALARM: + case SOURCE_DEFER: + case SOURCE_POST: + case SOURCE_INOTIFY: +@@ -2407,6 +2404,9 @@ static int event_source_offline( + assert_not_reached("Wut? I shouldn't exist."); + } + ++ /* Always reshuffle time prioq, as the ratelimited flag may be changed. */ ++ event_source_time_prioq_reshuffle(s); ++ + return 1; + } + +@@ -2496,22 +2496,11 @@ static int event_source_online( + s->ratelimited = ratelimited; + + /* Non-failing operations below */ +- switch (s->type) { +- case SOURCE_TIME_REALTIME: +- case SOURCE_TIME_BOOTTIME: +- case SOURCE_TIME_MONOTONIC: +- case SOURCE_TIME_REALTIME_ALARM: +- case SOURCE_TIME_BOOTTIME_ALARM: +- event_source_time_prioq_reshuffle(s); +- break; +- +- case SOURCE_EXIT: ++ if (s->type == SOURCE_EXIT) + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); +- break; + +- default: +- break; +- } ++ /* Always reshuffle time prioq, as the ratelimited flag may be changed. */ ++ event_source_time_prioq_reshuffle(s); + + return 1; + } +-- +2.17.1 + diff --git a/base/systemd/debian/patches/series b/base/systemd/debian/patches/series new file mode 100644 index 000000000..87e3b961b --- /dev/null +++ b/base/systemd/debian/patches/series @@ -0,0 +1,26 @@ +# STX Patches +851-inject-millisec-in-syslog-date.patch + +# This cluster of patches relates to fixing redhat bug #1819868 +# "systemd excessively reads mountinfo and udev in dense container environments" + +# Patch (3) for solving #1819868 +909-sd-event-split-clock-data-allocation-out-of-sd_event.patch +# Patch (4) for solving #1819868 +910-sd-event-split-out-code-to-add-remove-timer-event-so.patch +# Patch (6) for solving #1819868 +913-sd-event-remove-earliest_index-latest_index-into-com.patch +# Patch (9) for solving #1819868 +919-sd-event-add-ability-to-ratelimit-event-sources.patch +# Patch (10) for solving #1819868 +920-core-prevent-excessive-proc-self-mountinfo-parsing.patch +skip-some-testcases.patch + +# This cluster of patches relates to fixing redhat bug #1968528 +# "fix rate-limiting of mount events" +922-sd-event-change-ordering-of-pending-ratelimited-even.patch +923-sd-event-drop-unnecessary-else.patch +924-sd-event-use-CMP-macro.patch +925-sd-event-use-usec_add.patch +926-sd-event-make-event_source_time_prioq_reshuffle-acce.patch +927-sd-event-always-reshuffle-time-prioq-on-changing-onl.patch diff --git a/base/systemd/debian/patches/skip-some-testcases.patch b/base/systemd/debian/patches/skip-some-testcases.patch new file mode 100644 index 000000000..d26bc2069 --- /dev/null +++ b/base/systemd/debian/patches/skip-some-testcases.patch @@ -0,0 +1,30 @@ +--- a/src/test/meson.build ++++ b/src/test/meson.build +@@ -224,9 +224,9 @@ tests += [ + [], + []], + +- [['src/test/test-util.c'], +- [], +- []], ++# [['src/test/test-util.c'], ++# [], ++# []], + + [['src/test/test-json.c'], + [], +@@ -1103,10 +1103,10 @@ tests += [ + libsystemd_network], + []], + +- [['src/libsystemd-network/test-dhcp-server.c'], +- [libshared, +- libsystemd_network], +- []], ++# [['src/libsystemd-network/test-dhcp-server.c'], ++# [libshared, ++# libsystemd_network], ++# []], + + [['src/libsystemd-network/test-ipv4ll.c', + 'src/libsystemd-network/arp-util.h',