diff --git a/backport-path-util-introduce-path_glob_can_match.patch b/backport-path-util-introduce-path_glob_can_match.patch new file mode 100644 index 0000000000000000000000000000000000000000..0a5c6d9e4703915ffa700a798972256fe34ccdfb --- /dev/null +++ b/backport-path-util-introduce-path_glob_can_match.patch @@ -0,0 +1,99 @@ +From 3b703fe269a4a34f1b5ad1c3ce219c8c407e6fe1 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 17 Aug 2022 06:43:37 +0900 +Subject: [PATCH] path-util: introduce path_glob_can_match() + +--- + src/basic/path-util.c | 61 +++++++++++++++++++++++++++++++++++++++++++ + src/basic/path-util.h | 2 ++ + 2 files changed, 63 insertions(+) + +diff --git a/src/basic/path-util.c b/src/basic/path-util.c +index 13d71ed..bec930f 100644 +--- a/src/basic/path-util.c ++++ b/src/basic/path-util.c +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: LGPL-2.1-or-later */ + + #include ++#include + #include + #include + #include +@@ -1395,3 +1396,63 @@ bool prefixed_path_strv_contains(char **l, const char *path) { + + return false; + } ++ ++int path_glob_can_match(const char *pattern, const char *prefix, char **ret) { ++ assert(pattern); ++ assert(prefix); ++ ++ for (const char *a = pattern, *b = prefix;;) { ++ _cleanup_free_ char *g = NULL, *h = NULL; ++ const char *p, *q; ++ int r, s; ++ ++ r = path_find_first_component(&a, /* accept_dot_dot = */ false, &p); ++ if (r < 0) ++ return r; ++ ++ s = path_find_first_component(&b, /* accept_dot_dot = */ false, &q); ++ if (s < 0) ++ return s; ++ ++ if (s == 0) { ++ /* The pattern matches the prefix. */ ++ if (ret) { ++ char *t; ++ ++ t = path_join(prefix, p); ++ if (!t) ++ return -ENOMEM; ++ ++ *ret = t; ++ } ++ return true; ++ } ++ ++ if (r == 0) ++ break; ++ ++ if (r == s && strneq(p, q, r)) ++ continue; /* common component. Check next. */ ++ ++ g = strndup(p, r); ++ if (!g) ++ return -ENOMEM; ++ ++ if (!string_is_glob(g)) ++ break; ++ ++ /* We found a glob component. Check if the glob pattern matches the prefix component. */ ++ ++ h = strndup(q, s); ++ if (!h) ++ return -ENOMEM; ++ ++ if (fnmatch(g, h, 0) != 0) ++ break; ++ } ++ ++ /* The pattern does not match the prefix. */ ++ if (ret) ++ *ret = NULL; ++ return false; ++} +diff --git a/src/basic/path-util.h b/src/basic/path-util.h +index 26e7362..c374a77 100644 +--- a/src/basic/path-util.h ++++ b/src/basic/path-util.h +@@ -202,3 +202,5 @@ static inline const char *empty_to_root(const char *path) { + + bool path_strv_contains(char **l, const char *path); + bool prefixed_path_strv_contains(char **l, const char *path); ++ ++int path_glob_can_match(const char *pattern, const char *prefix, char **ret); +-- +2.33.0 + diff --git a/backport-sysctl-apply-prefix-before-calling-glob.patch b/backport-sysctl-apply-prefix-before-calling-glob.patch new file mode 100644 index 0000000000000000000000000000000000000000..19b31b92b2cf9e2ad5eac94a7e21a2ed549dbbb6 --- /dev/null +++ b/backport-sysctl-apply-prefix-before-calling-glob.patch @@ -0,0 +1,121 @@ +From 9ec8c82b8c836f7632ba0a075c296e6ddc53f643 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 17 Aug 2022 04:54:06 +0900 +Subject: [PATCH] sysctl: apply prefix before calling glob() + +Otherwise, if there exist million of network interfaces, +calling glob() for network properties takes much time. + +Fixes #24031. +--- + src/sysctl/sysctl.c | 61 +++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 53 insertions(+), 8 deletions(-) + +diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c +index fc13529..499ddde 100644 +--- a/src/sysctl/sysctl.c ++++ b/src/sysctl/sysctl.c +@@ -86,7 +86,7 @@ static Option *option_new( + return TAKE_PTR(o); + } + +-static int sysctl_write_or_warn(const char *key, const char *value, bool ignore_failure) { ++static int sysctl_write_or_warn(const char *key, const char *value, bool ignore_failure, bool ignore_enoent) { + int r; + + r = sysctl_write(key, value); +@@ -106,7 +106,7 @@ static int sysctl_write_or_warn(const char *key, const char *value, bool ignore_ + return 0; + } + +-static int apply_glob_option(OrderedHashmap *sysctl_options, Option *option) { ++static int apply_glob_option_with_prefix(OrderedHashmap *sysctl_options, Option *option, const char *prefix) { + _cleanup_strv_free_ char **paths = NULL; + _cleanup_free_ char *pattern = NULL; + int r, k; +@@ -115,7 +115,35 @@ static int apply_glob_option(OrderedHashmap *sysctl_options, Option *option) { + assert(sysctl_options); + assert(option); + +- pattern = path_join("/proc/sys", option->key); ++ if (prefix) { ++ _cleanup_free_ char *key = NULL; ++ ++ r = path_glob_can_match(option->key, prefix, &key); ++ if (r < 0) ++ return log_error_errno(r, "Failed to check if the glob '%s' matches prefix '%s': %m", ++ option->key, prefix); ++ if (r == 0) { ++ log_debug("The glob '%s' does not match prefix '%s'.", option->key, prefix); ++ return 0; ++ } ++ ++ log_debug("The glob '%s' is prefixed with '%s': '%s'", option->key, prefix, key); ++ ++ if (!string_is_glob(key)) { ++ /* The prefixed pattern is not glob anymore. Let's skip to call glob(). */ ++ if (ordered_hashmap_contains(sysctl_options, key)) { ++ log_debug("Not setting %s (explicit setting exists).", key); ++ return 0; ++ } ++ ++ return sysctl_write_or_warn(key, option->value, ++ /* ignore_failure = */ option->ignore_failure, ++ /* ignore_enoent = */ true); ++ } ++ ++ pattern = path_join("/proc/sys", key); ++ } else ++ pattern = path_join("/proc/sys", option->key); + if (!pattern) + return log_oom(); + +@@ -137,15 +165,30 @@ static int apply_glob_option(OrderedHashmap *sysctl_options, Option *option) { + + assert_se(key = path_startswith(*s, "/proc/sys")); + +- if (!test_prefix(key)) +- continue; +- + if (ordered_hashmap_contains(sysctl_options, key)) { + log_debug("Not setting %s (explicit setting exists).", key); + continue; + } + +- k = sysctl_write_or_warn(key, option->value, option->ignore_failure); ++ k = sysctl_write_or_warn(key, option->value, ++ /* ignore_failure = */ option->ignore_failure, ++ /* ignore_enoent = */ false); ++ if (k < 0 && r >= 0) ++ r = k; ++ } ++ ++ return r; ++} ++ ++static int apply_glob_option(OrderedHashmap *sysctl_options, Option *option) { ++ int r = 0, k; ++ char **i; ++ ++ if (strv_isempty(arg_prefixes)) ++ return apply_glob_option_with_prefix(sysctl_options, option, NULL); ++ ++ STRV_FOREACH(i, arg_prefixes) { ++ k = apply_glob_option_with_prefix(sysctl_options, option, *i); + if (k < 0 && r >= 0) + r = k; + } +@@ -167,7 +210,9 @@ static int apply_all(OrderedHashmap *sysctl_options) { + if (string_is_glob(option->key)) + k = apply_glob_option(sysctl_options, option); + else +- k = sysctl_write_or_warn(option->key, option->value, option->ignore_failure); ++ k = sysctl_write_or_warn(option->key, option->value, ++ /* ignore_failure = */ option->ignore_failure, ++ /* ignore_enoent = */ false); + if (k < 0 && r >= 0) + r = k; + } +-- +2.33.0 + diff --git a/backport-sysctl-drop-proc-sys-in-prefix.patch b/backport-sysctl-drop-proc-sys-in-prefix.patch new file mode 100644 index 0000000000000000000000000000000000000000..64acac668c51cad2921ba921df2ff4b5e4b6a384 --- /dev/null +++ b/backport-sysctl-drop-proc-sys-in-prefix.patch @@ -0,0 +1,57 @@ +From c01404fdf100b03dafa8a366d07f74f3c30d5330 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 17 Aug 2022 03:11:00 +0900 +Subject: [PATCH] sysctl: drop /proc/sys/ in prefix + +--- + src/sysctl/sysctl.c | 20 ++++---------------- + 1 file changed, 4 insertions(+), 16 deletions(-) + +diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c +index dda112f45..ae079b7a7 100644 +--- a/src/sysctl/sysctl.c ++++ b/src/sysctl/sysctl.c +@@ -56,18 +56,7 @@ static bool test_prefix(const char *p) { + if (strv_isempty(arg_prefixes)) + return true; + +- STRV_FOREACH(i, arg_prefixes) { +- const char *t; +- +- t = path_startswith(*i, "/proc/sys/"); +- if (!t) +- t = *i; +- +- if (path_startswith(p, t)) +- return true; +- } +- +- return false; ++ return path_startswith_strv(p, arg_prefixes); + } + + static Option *option_new( +@@ -360,6 +349,7 @@ static int parse_argv(int argc, char *argv[]) { + break; + + case ARG_PREFIX: { ++ const char *s; + char *p; + + /* We used to require people to specify absolute paths +@@ -368,10 +358,8 @@ static int parse_argv(int argc, char *argv[]) { + * sysctl name available. */ + sysctl_normalize(optarg); + +- if (path_startswith(optarg, "/proc/sys")) +- p = strdup(optarg); +- else +- p = path_join("/proc/sys", optarg); ++ s = path_startswith(optarg, "/proc/sys"); ++ p = strdup(s ?: optarg); + if (!p) + return log_oom(); + +-- +2.33.0 + diff --git a/backport-sysctl-split-out-code-for-applying-glob-option.patch b/backport-sysctl-split-out-code-for-applying-glob-option.patch new file mode 100644 index 0000000000000000000000000000000000000000..648cbb52fac3e1c4285d848c939eaee14e76cab3 --- /dev/null +++ b/backport-sysctl-split-out-code-for-applying-glob-option.patch @@ -0,0 +1,132 @@ +From 7177ac45723a2d716d34b66fb5d8691df5f2c6c8 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 17 Aug 2022 04:10:30 +0900 +Subject: [PATCH] sysctl: split out code for applying glob option + +--- + src/sysctl/sysctl.c | 96 ++++++++++++++++++++++++--------------------- + 1 file changed, 51 insertions(+), 45 deletions(-) + +diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c +index 642535b..df02771 100644 +--- a/src/sysctl/sysctl.c ++++ b/src/sysctl/sysctl.c +@@ -106,64 +106,70 @@ static int sysctl_write_or_warn(const char *key, const char *value, bool ignore_ + return 0; + } + +-static int apply_all(OrderedHashmap *sysctl_options) { +- Option *option; +- int r = 0; ++static int apply_glob_option(OrderedHashmap *sysctl_options, Option *option) { ++ _cleanup_strv_free_ char **paths = NULL; ++ _cleanup_free_ char *pattern = NULL; ++ int r, k; ++ char **s; + +- ORDERED_HASHMAP_FOREACH(option, sysctl_options) { +- int k; ++ assert(sysctl_options); ++ assert(option); + +- /* Ignore "negative match" options, they are there only to exclude stuff from globs. */ +- if (!option->value) +- continue; ++ pattern = path_join("/proc/sys", option->key); ++ if (!pattern) ++ return log_oom(); + +- if (string_is_glob(option->key)) { +- _cleanup_strv_free_ char **paths = NULL; +- _cleanup_free_ char *pattern = NULL; +- char **s; ++ r = glob_extend(&paths, pattern, GLOB_NOCHECK); ++ if (r < 0) { ++ if (r == -ENOENT) { ++ log_debug("No match for glob: %s", option->key); ++ return 0; ++ } ++ if (option->ignore_failure || ERRNO_IS_PRIVILEGE(r)) { ++ log_debug_errno(r, "Failed to resolve glob '%s', ignoring: %m", option->key); ++ return 0; ++ } else ++ return log_error_errno(r, "Couldn't resolve glob '%s': %m", option->key); ++ } + +- pattern = path_join("/proc/sys", option->key); +- if (!pattern) +- return log_oom(); ++ STRV_FOREACH(s, paths) { ++ const char *key; + +- k = glob_extend(&paths, pattern, GLOB_NOCHECK); +- if (k < 0) { +- if (option->ignore_failure || ERRNO_IS_PRIVILEGE(k)) +- log_debug_errno(k, "Failed to resolve glob '%s', ignoring: %m", +- option->key); +- else { +- log_error_errno(k, "Couldn't resolve glob '%s': %m", +- option->key); +- if (r == 0) +- r = k; +- } ++ assert_se(key = path_startswith(*s, "/proc/sys")); + +- } else if (strv_isempty(paths)) +- log_debug("No match for glob: %s", option->key); ++ if (!test_prefix(key)) ++ continue; + +- STRV_FOREACH(s, paths) { +- const char *key; ++ if (ordered_hashmap_contains(sysctl_options, key)) { ++ log_debug("Not setting %s (explicit setting exists).", key); ++ continue; ++ } + +- assert_se(key = path_startswith(*s, "/proc/sys")); ++ k = sysctl_write_or_warn(key, option->value, option->ignore_failure); ++ if (k < 0 && r >= 0) ++ r = k; ++ } + +- if (!test_prefix(key)) +- continue; ++ return r; ++} + +- if (ordered_hashmap_contains(sysctl_options, key)) { +- log_debug("Not setting %s (explicit setting exists).", key); +- continue; +- } ++static int apply_all(OrderedHashmap *sysctl_options) { ++ Option *option; ++ int r = 0; + +- k = sysctl_write_or_warn(key, option->value, option->ignore_failure); +- if (r == 0) +- r = k; +- } ++ ORDERED_HASHMAP_FOREACH(option, sysctl_options) { ++ int k; + +- } else { ++ /* Ignore "negative match" options, they are there only to exclude stuff from globs. */ ++ if (!option->value) ++ continue; ++ ++ if (string_is_glob(option->key)) ++ k = apply_glob_option(sysctl_options, option); ++ else + k = sysctl_write_or_warn(option->key, option->value, option->ignore_failure); +- if (r == 0) +- r = k; +- } ++ if (k < 0 && r >= 0) ++ r = k; + } + + return r; +-- +2.33.0 + diff --git a/backport-sysctl-use-ordered_hashmap_ensure_put.patch b/backport-sysctl-use-ordered_hashmap_ensure_put.patch new file mode 100644 index 0000000000000000000000000000000000000000..1bd584f74d21e04d41c9cc741c0a3868bec12a89 --- /dev/null +++ b/backport-sysctl-use-ordered_hashmap_ensure_put.patch @@ -0,0 +1,35 @@ +From 350ffa9749f2ce5d62e4b66cc7418e25e6829963 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 17 Aug 2022 14:29:26 +0900 +Subject: [PATCH] sysctl: use ordered_hashmap_ensure_put() + +--- + src/sysctl/sysctl.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c +index de0e03ec9..dda112f45 100644 +--- a/src/sysctl/sysctl.c ++++ b/src/sysctl/sysctl.c +@@ -254,9 +254,6 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig + !test_prefix(p)) + continue; + +- if (ordered_hashmap_ensure_allocated(sysctl_options, &option_hash_ops) < 0) +- return log_oom(); +- + existing = ordered_hashmap_get(*sysctl_options, p); + if (existing) { + if (streq_ptr(value, existing->value)) { +@@ -272,7 +269,7 @@ static int parse_file(OrderedHashmap **sysctl_options, const char *path, bool ig + if (!new_option) + return log_oom(); + +- k = ordered_hashmap_put(*sysctl_options, new_option->key, new_option); ++ k = ordered_hashmap_ensure_put(sysctl_options, &option_hash_ops, new_option->key, new_option); + if (k < 0) + return log_error_errno(k, "Failed to add sysctl variable %s to hashmap: %m", p); + +-- +2.33.0 + diff --git a/systemd.spec b/systemd.spec index 31a19f37ba118a34a679bb3d006022c96584c07f..e4251b58d46eafa3359f22e541864d0ff4e6a2b6 100644 --- a/systemd.spec +++ b/systemd.spec @@ -25,7 +25,7 @@ Name: systemd Url: https://systemd.io/ Version: 249 -Release: 100 +Release: 101 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -731,6 +731,11 @@ Patch6678: backport-manager-improve-message-about-Reload-Reexec-requests.pa Patch6679: backport-core-fix-null-in-output.patch Patch6680: backport-core-Bump-log-level-of-reexecute-request-to-notice.patch Patch6681: backport-core-Log-in-more-scenarios-about-which-process-initi.patch +Patch6682: backport-sysctl-use-ordered_hashmap_ensure_put.patch +Patch6683: backport-sysctl-drop-proc-sys-in-prefix.patch +Patch6684: backport-sysctl-split-out-code-for-applying-glob-option.patch +Patch6685: backport-path-util-introduce-path_glob_can_match.patch +Patch6686: backport-sysctl-apply-prefix-before-calling-glob.patch Patch9001: update-rtc-with-system-clock-when-shutdown.patch Patch9002: udev-add-actions-while-rename-netif-failed.patch @@ -2247,6 +2252,9 @@ grep -q -E '^KEYMAP="?fi-latin[19]"?' /etc/vconsole.conf 2>/dev/null && /usr/bin/systemd-cryptenroll %changelog +* Mon Feb 17 2025 zhangyao - 249-101 +- sysctl: improve performance for applying glob pattern + * Tue Dec 24 2024 xujing - 249-100 - add DefaultEnableMemswLimit support