!839 [sync] PR-838: sysctl: improve performance for applying glob pattern

From: @openeuler-sync-bot 
Reviewed-by: @xujing99 
Signed-off-by: @xujing99
This commit is contained in:
openeuler-ci-bot 2025-02-24 02:35:07 +00:00 committed by Gitee
commit e8599f6a86
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
6 changed files with 453 additions and 1 deletions

View File

@ -0,0 +1,99 @@
From 3b703fe269a4a34f1b5ad1c3ce219c8c407e6fe1 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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 <errno.h>
+#include <fnmatch.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -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

View File

@ -0,0 +1,121 @@
From 9ec8c82b8c836f7632ba0a075c296e6ddc53f643 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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

View File

@ -0,0 +1,57 @@
From c01404fdf100b03dafa8a366d07f74f3c30d5330 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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

View File

@ -0,0 +1,132 @@
From 7177ac45723a2d716d34b66fb5d8691df5f2c6c8 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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

View File

@ -0,0 +1,35 @@
From 350ffa9749f2ce5d62e4b66cc7418e25e6829963 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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

View File

@ -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 <zhangyao108@huawei.com> - 249-101
- sysctl: improve performance for applying glob pattern
* Tue Dec 24 2024 xujing <xujing125@huawei.com> - 249-100
- add DefaultEnableMemswLimit support