From: Alexander Kanavin <alex.kanavin@gmail.com>
To: ranjitsinhrathod1991@gmail.com
Cc: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>,
openembedded-core@lists.openembedded.org
Subject: Re: [OE-Core][kirkstone][PATCH] systemd: Add patches to fix systemd-udev delay during initialization
Date: Sat, 11 May 2024 07:07:13 +0200 [thread overview]
Message-ID: <CANNYZj-dC-nuL8gCbzYOkM9zATJNbGngLCB_asai7cs2=zpuQg@mail.gmail.com> (raw)
In-Reply-To: <20240511040811.336618-1-ranjitsinhrathod1991@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 68208 bytes --]
Perhaps it’s better to provide a newer systemd including these patches via
a mixin layer? It’s an invasive backport and not really suitable for lts.
Alex
On Sat 11. May 2024 at 6.08, Ranjitsinh Rathod via lists.openembedded.org
<ranjitsinhrathod1991=gmail.com@lists.openembedded.org> wrote:
> From: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
>
> Below upstream systemd PR fixes overall delay in systemd-udev in
> initialization by removing multiple for loops along with delays in those
> loops
> By applying these patches from the PR improves almost 800 - 900 ms in
> the initialization
> By this system boots up fasts and also avoids some issues related to
> this delay
>
> PR link: https://github.com/systemd/systemd/pull/23043
>
> Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> Signed-off-by: Ranjitsinh Rathod <ranjitsinhrathod1991@gmail.com>
> ---
> ...0001-udev-move-udev_node_escape_path.patch | 120 ++++++++
> ...update-and-introduce-stack_directory.patch | 90 ++++++
> ...ve-stack-directory-even-if-it-is-emp.patch | 267 +++++++++++++++++
> ...-introduce-path_make_relative_parent.patch | 99 +++++++
> .../0005-udev-use-readlinkat_malloc.patch | 74 +++++
> ...-link_find_prioritized-and-variables.patch | 190 ++++++++++++
> ...7-udev-use-path_make_relative_parent.patch | 43 +++
> ...ake-node_symlink-accept-NULL-devname.patch | 75 +++++
> ...k-when-updating-device-node-symlinks.patch | 277 ++++++++++++++++++
> ...ck-directory-run-udev-links-when-all.patch | 130 ++++++++
> meta/recipes-core/systemd/systemd_250.5.bb | 10 +
> 11 files changed, 1375 insertions(+)
> create mode 100644
> meta/recipes-core/systemd/systemd/0001-udev-move-udev_node_escape_path.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0002-udev-split-link_update-and-introduce-stack_directory.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0003-udev-do-not-remove-stack-directory-even-if-it-is-emp.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0004-path-util-introduce-path_make_relative_parent.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0005-udev-use-readlinkat_malloc.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0006-udev-rename-link_find_prioritized-and-variables.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0007-udev-use-path_make_relative_parent.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0008-udev-make-node_symlink-accept-NULL-devname.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0009-udev-use-flock-when-updating-device-node-symlinks.patch
> create mode 100644
> meta/recipes-core/systemd/systemd/0010-udev-cleanup-stack-directory-run-udev-links-when-all.patch
>
> diff --git
> a/meta/recipes-core/systemd/systemd/0001-udev-move-udev_node_escape_path.patch
> b/meta/recipes-core/systemd/systemd/0001-udev-move-udev_node_escape_path.patch
> new file mode 100644
> index 0000000000..900ca81170
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0001-udev-move-udev_node_escape_path.patch
> @@ -0,0 +1,120 @@
> +From b9168275c39a190441fee73ba1c8a64515fd3b0e Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 11:25:37 +0900
> +Subject: [PATCH 01/10] udev: move udev_node_escape_path()
> +
> +No functionality is changed.
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/b9168275c39a190441fee73ba1c8a64515fd3b0e
> ]
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 84 ++++++++++++++++++++++----------------------
> + 1 file changed, 42 insertions(+), 42 deletions(-)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index bb34977d97..79d050cce6 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -222,48 +222,6 @@ static int link_find_prioritized(sd_device *dev,
> bool add, const char *stackdir,
> + return !!*ret;
> + }
> +
> +-size_t udev_node_escape_path(const char *src, char *dest, size_t size) {
> +- size_t i, j;
> +- uint64_t h;
> +-
> +- assert(src);
> +- assert(dest);
> +- assert(size >= 12);
> +-
> +- for (i = 0, j = 0; src[i] != '\0'; i++) {
> +- if (src[i] == '/') {
> +- if (j+4 >= size - 12 + 1)
> +- goto toolong;
> +- memcpy(&dest[j], "\\x2f", 4);
> +- j += 4;
> +- } else if (src[i] == '\\') {
> +- if (j+4 >= size - 12 + 1)
> +- goto toolong;
> +- memcpy(&dest[j], "\\x5c", 4);
> +- j += 4;
> +- } else {
> +- if (j+1 >= size - 12 + 1)
> +- goto toolong;
> +- dest[j] = src[i];
> +- j++;
> +- }
> +- }
> +- dest[j] = '\0';
> +- return j;
> +-
> +-toolong:
> +- /* If the input path is too long to encode as a filename, then
> let's suffix with a string
> +- * generated from the hash of the path. */
> +-
> +- h = siphash24_string(src, UDEV_NODE_HASH_KEY.bytes);
> +-
> +- for (unsigned k = 0; k <= 10; k++)
> +- dest[size - k - 2] = urlsafe_base64char((h >> (k * 6)) &
> 63);
> +-
> +- dest[size - 1] = '\0';
> +- return size - 1;
> +-}
> +-
> + static int update_timestamp(sd_device *dev, const char *path, struct
> stat *prev) {
> + assert(path);
> + assert(prev);
> +@@ -414,6 +372,48 @@ static int update_stack_directory(sd_device *dev,
> const char *dirname, bool add)
> + return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ELOOP),
> "Failed to create symbolic link %s: %m", filename);
> + }
> +
> ++size_t udev_node_escape_path(const char *src, char *dest, size_t size) {
> ++ size_t i, j;
> ++ uint64_t h;
> ++
> ++ assert(src);
> ++ assert(dest);
> ++ assert(size >= 12);
> ++
> ++ for (i = 0, j = 0; src[i] != '\0'; i++) {
> ++ if (src[i] == '/') {
> ++ if (j+4 >= size - 12 + 1)
> ++ goto toolong;
> ++ memcpy(&dest[j], "\\x2f", 4);
> ++ j += 4;
> ++ } else if (src[i] == '\\') {
> ++ if (j+4 >= size - 12 + 1)
> ++ goto toolong;
> ++ memcpy(&dest[j], "\\x5c", 4);
> ++ j += 4;
> ++ } else {
> ++ if (j+1 >= size - 12 + 1)
> ++ goto toolong;
> ++ dest[j] = src[i];
> ++ j++;
> ++ }
> ++ }
> ++ dest[j] = '\0';
> ++ return j;
> ++
> ++toolong:
> ++ /* If the input path is too long to encode as a filename, then
> let's suffix with a string
> ++ * generated from the hash of the path. */
> ++
> ++ h = siphash24_string(src, UDEV_NODE_HASH_KEY.bytes);
> ++
> ++ for (unsigned k = 0; k <= 10; k++)
> ++ dest[size - k - 2] = urlsafe_base64char((h >> (k * 6)) &
> 63);
> ++
> ++ dest[size - 1] = '\0';
> ++ return size - 1;
> ++}
> ++
> + /* manage "stack of names" with possibly specified device priorities */
> + static int link_update(sd_device *dev, const char *slink_in, bool add) {
> + _cleanup_free_ char *slink = NULL, *dirname = NULL;
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0002-udev-split-link_update-and-introduce-stack_directory.patch
> b/meta/recipes-core/systemd/systemd/0002-udev-split-link_update-and-introduce-stack_directory.patch
> new file mode 100644
> index 0000000000..edc7ab5b38
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0002-udev-split-link_update-and-introduce-stack_directory.patch
> @@ -0,0 +1,90 @@
> +From 7e7c36fbbb396364c386bf1edbe9b25179a134c6 Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 11:26:08 +0900
> +Subject: [PATCH 02/10] udev: split link_update() and introduce
> + stack_directory_get_name()
> +
> +No functionality is changed.
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/7e7c36fbbb396364c386bf1edbe9b25179a134c6
> ]
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 52 ++++++++++++++++++++++++++++----------------
> + 1 file changed, 33 insertions(+), 19 deletions(-)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index 79d050cce6..b4b865c021 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -414,33 +414,47 @@ toolong:
> + return size - 1;
> + }
> +
> +-/* manage "stack of names" with possibly specified device priorities */
> +-static int link_update(sd_device *dev, const char *slink_in, bool add) {
> +- _cleanup_free_ char *slink = NULL, *dirname = NULL;
> +- const char *slink_name;
> ++static int stack_directory_get_name(const char *slink, char **ret) {
> ++ _cleanup_free_ char *s = NULL, *dirname = NULL;
> + char name_enc[NAME_MAX+1];
> +- int r;
> ++ const char *name;
> +
> +- assert(dev);
> +- assert(slink_in);
> ++ assert(slink);
> ++ assert(ret);
> +
> +- slink = strdup(slink_in);
> +- if (!slink)
> +- return log_oom_debug();
> ++ s = strdup(slink);
> ++ if (!s)
> ++ return -ENOMEM;
> +
> +- path_simplify(slink);
> ++ path_simplify(s);
> +
> +- slink_name = path_startswith(slink, "/dev");
> +- if (!slink_name ||
> +- empty_or_root(slink_name) ||
> +- !path_is_normalized(slink_name))
> +- return log_device_debug_errno(dev,
> SYNTHETIC_ERRNO(EINVAL),
> +- "Invalid symbolic link of
> device node: %s", slink);
> ++ if (!path_is_normalized(s))
> ++ return -EINVAL;
> ++
> ++ name = path_startswith(s, "/dev");
> ++ if (empty_or_root(name))
> ++ return -EINVAL;
> ++
> ++ udev_node_escape_path(name, name_enc, sizeof(name_enc));
> +
> +- (void) udev_node_escape_path(slink_name, name_enc,
> sizeof(name_enc));
> + dirname = path_join("/run/udev/links", name_enc);
> + if (!dirname)
> +- return log_oom_debug();
> ++ return -ENOMEM;
> ++
> ++ *ret = TAKE_PTR(dirname);
> ++ return 0;
> ++}
> ++
> ++static int link_update(sd_device *dev, const char *slink, bool add) {
> ++ _cleanup_free_ char *dirname = NULL;
> ++ int r;
> ++
> ++ assert(dev);
> ++ assert(slink);
> ++
> ++ r = stack_directory_get_name(slink, &dirname);
> ++ if (r < 0)
> ++ return log_device_debug_errno(dev, r, "Failed to build
> stack directory name for '%s': %m", slink);
> +
> + r = update_stack_directory(dev, dirname, add);
> + if (r < 0)
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0003-udev-do-not-remove-stack-directory-even-if-it-is-emp.patch
> b/meta/recipes-core/systemd/systemd/0003-udev-do-not-remove-stack-directory-even-if-it-is-emp.patch
> new file mode 100644
> index 0000000000..6d2b178bd4
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0003-udev-do-not-remove-stack-directory-even-if-it-is-emp.patch
> @@ -0,0 +1,267 @@
> +From a28d67a90374a9d11bd5635f81961f72e5a8b33e Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 11:47:20 +0900
> +Subject: [PATCH 03/10] udev: do not remove stack directory even if it is
> empty
> +
> +Then, we can always assume the directory exists, and the code become
> +slightly simpler.
> +
> +Note, unused directories are removed by the main udevd process in a
> +later commit.
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/a28d67a90374a9d11bd5635f81961f72e5a8b33e
> ]
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 158 +++++++++++++++++--------------------------
> + 1 file changed, 61 insertions(+), 97 deletions(-)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index b4b865c021..6ead839a5f 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -35,7 +35,6 @@
> +
> + #define CREATE_LINK_MAX_RETRIES 128
> + #define LINK_UPDATE_MAX_RETRIES 128
> +-#define CREATE_STACK_LINK_MAX_RETRIES 128
> + #define UPDATE_TIMESTAMP_MAX_RETRIES 128
> + #define MAX_RANDOM_DELAY (250 * USEC_PER_MSEC)
> + #define MIN_RANDOM_DELAY ( 50 * USEC_PER_MSEC)
> +@@ -140,15 +139,8 @@ static int link_find_prioritized(sd_device *dev,
> bool add, const char *stackdir,
> + }
> +
> + dir = opendir(stackdir);
> +- if (!dir) {
> +- if (add) /* The stack directory must exist. */
> +- return -errno;
> +- if (errno != ENOENT)
> +- return -errno;
> +-
> +- *ret = NULL;
> +- return 0;
> +- }
> ++ if (!dir)
> ++ return -errno;
> +
> + r = device_get_device_id(dev, &id);
> + if (r < 0)
> +@@ -222,8 +214,8 @@ static int link_find_prioritized(sd_device *dev, bool
> add, const char *stackdir,
> + return !!*ret;
> + }
> +
> +-static int update_timestamp(sd_device *dev, const char *path, struct
> stat *prev) {
> +- assert(path);
> ++static int update_timestamp(sd_device *dev, int fd, struct stat *prev) {
> ++ assert(fd >= 0);
> + assert(prev);
> +
> + /* Even if a symlink in the stack directory is created/removed,
> the mtime of the directory may
> +@@ -247,129 +239,96 @@ static int update_timestamp(sd_device *dev, const
> char *path, struct stat *prev)
> + * timestamp of the stack directory is always increased at least
> in the above step 5, so A can
> + * detect the update. */
> +
> +- if ((prev->st_mode & S_IFMT) == 0)
> +- return 0; /* Does not exist, or previous stat() failed.
> */
> +-
> + for (unsigned i = 0; i < UPDATE_TIMESTAMP_MAX_RETRIES; i++) {
> + struct stat st;
> +
> +- if (stat(path, &st) < 0)
> ++ if (fstat(fd, &st) < 0)
> + return -errno;
> +
> + if (!stat_inode_unmodified(prev, &st))
> + return 0;
> +
> + log_device_debug(dev,
> +- "%s is modified, but its timestamp is
> not changed, "
> +- "updating timestamp after 10ms.",
> +- path);
> ++ "Stack directory is modified, but its
> timestamp is not changed, "
> ++ "updating timestamp after 10ms.");
> +
> + (void) usleep(10 * USEC_PER_MSEC);
> +- if (utimensat(AT_FDCWD, path, NULL, 0) < 0)
> ++ if (futimens(fd, NULL) < 0)
> + return -errno;
> + }
> +
> + return -ELOOP;
> + }
> +
> +-static int update_stack_directory(sd_device *dev, const char *dirname,
> bool add) {
> +- _cleanup_free_ char *filename = NULL, *data = NULL, *buf = NULL;
> +- const char *devname, *id;
> +- struct stat st = {};
> +- int priority, r;
> ++static int stack_directory_update(sd_device *dev, int fd, bool add) {
> ++ struct stat st;
> ++ const char *id;
> ++ int r;
> +
> + assert(dev);
> +- assert(dirname);
> ++ assert(fd >= 0);
> +
> + r = device_get_device_id(dev, &id);
> + if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to get
> device id: %m");
> +-
> +- filename = path_join(dirname, id);
> +- if (!filename)
> +- return log_oom_debug();
> ++ return r;
> +
> +- if (!add) {
> +- int unlink_error = 0, stat_error = 0;
> ++ if (fstat(fd, &st) < 0)
> ++ return -errno;
> +
> +- if (stat(dirname, &st) < 0) {
> +- if (errno == ENOENT)
> +- return 0; /* The stack directory is
> already removed. That's OK. */
> +- stat_error = -errno;
> +- }
> ++ if (add) {
> ++ _cleanup_free_ char *data = NULL, *buf = NULL;
> ++ const char *devname;
> ++ int priority;
> +
> +- if (unlink(filename) < 0)
> +- unlink_error = -errno;
> ++ r = sd_device_get_devname(dev, &devname);
> ++ if (r < 0)
> ++ return r;
> +
> +- if (rmdir(dirname) >= 0 || errno == ENOENT)
> +- return 0;
> ++ r = device_get_devlink_priority(dev, &priority);
> ++ if (r < 0)
> ++ return r;
> +
> +- if (unlink_error < 0) {
> +- if (unlink_error == -ENOENT)
> +- return 0;
> ++ if (asprintf(&data, "%i:%s", priority, devname) < 0)
> ++ return -ENOMEM;
> +
> +- /* If we failed to remove the symlink, then
> there is almost nothing we can do. */
> +- return log_device_debug_errno(dev, unlink_error,
> "Failed to remove %s: %m", filename);
> +- }
> ++ if (readlinkat_malloc(fd, id, &buf) >= 0 && streq(buf,
> data))
> ++ return 0; /* Unchanged. */
> +
> +- if (stat_error < 0)
> +- return log_device_debug_errno(dev, stat_error,
> "Failed to stat %s: %m", dirname);
> ++ (void) unlinkat(fd, id, 0);
> +
> +- /* The symlink was removed. Check if the timestamp of
> directory is changed. */
> +- r = update_timestamp(dev, dirname, &st);
> +- if (r < 0 && r != -ENOENT)
> +- return log_device_debug_errno(dev, r, "Failed to
> update timestamp of %s: %m", dirname);
> ++ if (symlinkat(data, fd, id) < 0)
> ++ return -errno;
> +
> +- return 0;
> ++ } else {
> ++ if (unlinkat(fd, id, 0) < 0) {
> ++ if (errno == ENOENT)
> ++ return 0; /* Unchanged. */
> ++ return -errno;
> ++ }
> + }
> +
> +- r = sd_device_get_devname(dev, &devname);
> ++ r = update_timestamp(dev, fd, &st);
> + if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to get
> device node: %m");
> +-
> +- r = device_get_devlink_priority(dev, &priority);
> +- if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to get
> priority of device node symlink: %m");
> +-
> +- if (asprintf(&data, "%i:%s", priority, devname) < 0)
> +- return log_oom_debug();
> +-
> +- if (readlink_malloc(filename, &buf) >= 0 && streq(buf, data))
> +- return 0;
> +-
> +- if (unlink(filename) < 0 && errno != ENOENT)
> +- log_device_debug_errno(dev, errno, "Failed to remove %s,
> ignoring: %m", filename);
> ++ return r;
> +
> +- for (unsigned j = 0; j < CREATE_STACK_LINK_MAX_RETRIES; j++) {
> +- /* This may fail with -ENOENT when the parent directory
> is removed during
> +- * creating the file by another udevd worker. */
> +- r = mkdir_p(dirname, 0755);
> +- if (r == -ENOENT)
> +- continue;
> +- if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to
> create directory %s: %m", dirname);
> ++ return 0;
> ++}
> +
> +- if (stat(dirname, &st) < 0) {
> +- if (errno == ENOENT)
> +- continue;
> +- return log_device_debug_errno(dev, errno,
> "Failed to stat %s: %m", dirname);
> +- }
> ++static int stack_directory_open(const char *dirname) {
> ++ _cleanup_close_ int fd = -1;
> ++ int r;
> +
> +- if (symlink(data, filename) < 0) {
> +- if (errno == ENOENT)
> +- continue;
> +- return log_device_debug_errno(dev, errno,
> "Failed to create symbolic link %s: %m", filename);
> +- }
> ++ assert(dirname);
> +
> +- /* The symlink was created. Check if the timestamp of
> directory is changed. */
> +- r = update_timestamp(dev, dirname, &st);
> +- if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to
> update timestamp of %s: %m", dirname);
> ++ r = mkdir_parents(dirname, 0755);
> ++ if (r < 0)
> ++ return r;
> +
> +- return 0;
> +- }
> ++ fd = open_mkdir_at(AT_FDCWD, dirname, O_CLOEXEC | O_DIRECTORY |
> O_NOFOLLOW | O_RDONLY, 0755);
> ++ if (fd < 0)
> ++ return fd;
> +
> +- return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ELOOP),
> "Failed to create symbolic link %s: %m", filename);
> ++ return TAKE_FD(fd);
> + }
> +
> + size_t udev_node_escape_path(const char *src, char *dest, size_t size) {
> +@@ -447,6 +406,7 @@ static int stack_directory_get_name(const char
> *slink, char **ret) {
> +
> + static int link_update(sd_device *dev, const char *slink, bool add) {
> + _cleanup_free_ char *dirname = NULL;
> ++ _cleanup_close_ int dirfd = -1;
> + int r;
> +
> + assert(dev);
> +@@ -456,9 +416,13 @@ static int link_update(sd_device *dev, const char
> *slink, bool add) {
> + if (r < 0)
> + return log_device_debug_errno(dev, r, "Failed to build
> stack directory name for '%s': %m", slink);
> +
> +- r = update_stack_directory(dev, dirname, add);
> ++ dirfd = stack_directory_open(dirname);
> ++ if (dirfd < 0)
> ++ return log_device_debug_errno(dev, dirfd, "Failed to
> open stack directory '%s': %m", dirname);
> ++
> ++ r = stack_directory_update(dev, dirfd, add);
> + if (r < 0)
> +- return r;
> ++ return log_device_debug_errno(dev, r, "Failed to update
> stack directory '%s': %m", dirname);
> +
> + for (unsigned i = 0; i < LINK_UPDATE_MAX_RETRIES; i++) {
> + _cleanup_free_ char *target = NULL;
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0004-path-util-introduce-path_make_relative_parent.patch
> b/meta/recipes-core/systemd/systemd/0004-path-util-introduce-path_make_relative_parent.patch
> new file mode 100644
> index 0000000000..dfc9fc9886
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0004-path-util-introduce-path_make_relative_parent.patch
> @@ -0,0 +1,99 @@
> +From d4f60bdc11d8e6275922ca5c7f80b130ebbb3d5f Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 07:01:59 +0900
> +Subject: [PATCH 04/10] path-util: introduce path_make_relative_parent()
> +
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/d4f60bdc11d8e6275922ca5c7f80b130ebbb3d5f
> ]
> +Comments: Refreshed first two hunks to apply patch cleanly without
> patch-fuzz
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/basic/path-util.c | 18 ++++++++++++++++++
> + src/basic/path-util.h | 1 +
> + src/test/test-path-util.c | 27 +++++++++++++++++++++++++++
> + 3 files changed, 46 insertions(+)
> +
> +diff --git a/src/basic/path-util.c b/src/basic/path-util.c
> +index 338377d918..41e0d4d753 100644
> +--- a/src/basic/path-util.c
> ++++ b/src/basic/path-util.c
> +@@ -201,6 +201,24 @@ int path_make_relative(const char *from,
> + return 0;
> + }
> +
> ++int path_make_relative_parent(const char *from_child, const char *to,
> char **ret) {
> ++ _cleanup_free_ char *from = NULL;
> ++ int r;
> ++
> ++ assert(from_child);
> ++ assert(to);
> ++ assert(ret);
> ++
> ++ /* Similar to path_make_relative(), but provides the relative
> path from the parent directory of
> ++ * 'from_child'. This may be useful when creating relative
> symlink. */
> ++
> ++ r = path_extract_directory(from_child, &from);
> ++ if (r < 0)
> ++ return r;
> ++
> ++ return path_make_relative(from, to, ret);
> ++}
> ++
> + char* path_startswith_strv(const char *p, char **set) {
> + char **s, *t;
> +
> +diff --git a/src/basic/path-util.h b/src/basic/path-util.h
> +index 41bbc7bb86..8cd7f512a6 100644
> +--- a/src/basic/path-util.h
> ++++ b/src/basic/path-util.h
> +@@ -57,6 +57,7 @@ char* path_make_absolute(const char *p,
> + int safe_getcwd(char **ret);
> + int path_make_absolute_cwd(const char *p, char **ret);
> + int path_make_relative(const char *from, const char *to, char **ret);
> ++int path_make_relative_parent(const char *from_child, const char *to,
> char **ret);
> + char *path_startswith_full(const char *path, const char *prefix, bool
> accept_dot_dot) _pure_;
> + static inline char* path_startswith(const char *path, const char
> *prefix) {
> + return path_startswith_full(path, prefix, true);
> +diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
> +index e0583cfbab..a26e351233 100644
> +--- a/src/test/test-path-util.c
> ++++ b/src/test/test-path-util.c
> +@@ -477,6 +477,33 @@ TEST(path_make_relative) {
> +
> test_path_make_relative_one("//extra.//.//./.slashes//./won't////fo.ol///anybody//",
> "/././/extra././/.slashes////ar.e/.just/././.fine///",
> "../../../ar.e/.just/.fine");
> + }
> +
> ++static void test_path_make_relative_parent_one(const char *from, const
> char *to, const char *expected) {
> ++ _cleanup_free_ char *z = NULL;
> ++ int r;
> ++
> ++ log_info("/* %s(%s, %s) */", __func__, from, to);
> ++
> ++ r = path_make_relative_parent(from, to, &z);
> ++ assert_se((r >= 0) == !!expected);
> ++ assert_se(streq_ptr(z, expected));
> ++}
> ++
> ++TEST(path_make_relative_parent) {
> ++ test_path_make_relative_parent_one("some/relative/path/hoge",
> "/some/path", NULL);
> ++ test_path_make_relative_parent_one("/some/path/hoge",
> "some/relative/path", NULL);
> ++ test_path_make_relative_parent_one("/some/dotdot/../path/hoge",
> "/some/path", NULL);
> ++ test_path_make_relative_parent_one("/", "/aaa", NULL);
> ++
> ++ test_path_make_relative_parent_one("/hoge", "/", ".");
> ++ test_path_make_relative_parent_one("/hoge", "/some/path",
> "some/path");
> ++ test_path_make_relative_parent_one("/some/path/hoge",
> "/some/path", ".");
> ++ test_path_make_relative_parent_one("/some/path/hoge",
> "/some/path/in/subdir", "in/subdir");
> ++ test_path_make_relative_parent_one("/some/path/hoge", "/",
> "../..");
> ++ test_path_make_relative_parent_one("/some/path/hoge",
> "/some/other/path", "../other/path");
> ++ test_path_make_relative_parent_one("/some/path/./dot/hoge",
> "/some/further/path", "../../further/path");
> ++
> test_path_make_relative_parent_one("//extra.//.//./.slashes//./won't////fo.ol///anybody//hoge",
> "/././/extra././/.slashes////ar.e/.just/././.fine///",
> "../../../ar.e/.just/.fine");
> ++}
> ++
> + TEST(path_strv_resolve) {
> + char tmp_dir[] = "/tmp/test-path-util-XXXXXX";
> + _cleanup_strv_free_ char **search_dirs = NULL;
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0005-udev-use-readlinkat_malloc.patch
> b/meta/recipes-core/systemd/systemd/0005-udev-use-readlinkat_malloc.patch
> new file mode 100644
> index 0000000000..42179f2031
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0005-udev-use-readlinkat_malloc.patch
> @@ -0,0 +1,74 @@
> +From faadf97500dc8e76350a409c127f3f0fed116f9a Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 03:29:07 +0900
> +Subject: [PATCH 05/10] udev: use readlinkat_malloc()
> +
> +And try to read it only when the file is symlink.
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/faadf97500dc8e76350a409c127f3f0fed116f9a
> ]
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 20 ++++++++++++--------
> + 1 file changed, 12 insertions(+), 8 deletions(-)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index 6ead839a5f..0320f2d041 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -147,7 +147,6 @@ static int link_find_prioritized(sd_device *dev, bool
> add, const char *stackdir,
> + return r;
> +
> + FOREACH_DIRENT_ALL(de, dir, break) {
> +- _cleanup_free_ char *path = NULL, *buf = NULL;
> + int tmp_prio;
> +
> + if (de->d_name[0] == '.')
> +@@ -157,15 +156,18 @@ static int link_find_prioritized(sd_device *dev,
> bool add, const char *stackdir,
> + if (streq(de->d_name, id))
> + continue;
> +
> +- path = path_join(stackdir, de->d_name);
> +- if (!path)
> +- return -ENOMEM;
> +-
> +- if (readlink_malloc(path, &buf) >= 0) {
> ++ if (de->d_type == DT_LNK) {
> ++ _cleanup_free_ char *buf = NULL;
> + char *devnode;
> +
> + /* New format. The devnode and priority can be
> obtained from symlink. */
> +
> ++ r = readlinkat_malloc(dirfd(dir), de->d_name,
> &buf);
> ++ if (r < 0) {
> ++ log_device_debug_errno(dev, r, "Failed
> to read symlink %s, ignoring: %m", de->d_name);
> ++ continue;
> ++ }
> ++
> + devnode = strchr(buf, ':');
> + if (!devnode || devnode == buf)
> + continue;
> +@@ -183,7 +185,8 @@ static int link_find_prioritized(sd_device *dev, bool
> add, const char *stackdir,
> + r = free_and_strdup(&target, devnode);
> + if (r < 0)
> + return r;
> +- } else {
> ++
> ++ } else if (de->d_type == DT_REG) {
> + _cleanup_(sd_device_unrefp) sd_device *tmp_dev =
> NULL;
> + const char *devnode;
> +
> +@@ -205,7 +208,8 @@ static int link_find_prioritized(sd_device *dev, bool
> add, const char *stackdir,
> + r = free_and_strdup(&target, devnode);
> + if (r < 0)
> + return r;
> +- }
> ++ } else
> ++ continue;
> +
> + priority = tmp_prio;
> + }
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0006-udev-rename-link_find_prioritized-and-variables.patch
> b/meta/recipes-core/systemd/systemd/0006-udev-rename-link_find_prioritized-and-variables.patch
> new file mode 100644
> index 0000000000..8fe4c9281c
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0006-udev-rename-link_find_prioritized-and-variables.patch
> @@ -0,0 +1,190 @@
> +From 6b01e2905c387002a20b0a38f4b7670c8eb82cb8 Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 11:56:52 +0900
> +Subject: [PATCH 06/10] udev: rename link_find_prioritized() and variables
> +
> +Also shorten code a bit.
> +
> +Just for consistency with other part and readability of the code.
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/6b01e2905c387002a20b0a38f4b7670c8eb82cb8
> ]
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 62 ++++++++++++++++++++++----------------------
> + 1 file changed, 31 insertions(+), 31 deletions(-)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index 0320f2d041..f358564b41 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -63,20 +63,21 @@ static int create_symlink(const char *target, const
> char *slink) {
> + return r;
> + }
> +
> +-static int node_symlink(sd_device *dev, const char *node, const char
> *slink) {
> ++static int node_symlink(sd_device *dev, const char *devnode, const char
> *slink) {
> + _cleanup_free_ char *slink_dirname = NULL, *target = NULL;
> + const char *id, *slink_tmp;
> +- struct stat stats;
> ++ struct stat st;
> + int r;
> +
> + assert(dev);
> +- assert(node);
> ++ assert(devnode);
> + assert(slink);
> +
> +- if (lstat(slink, &stats) >= 0) {
> +- if (!S_ISLNK(stats.st_mode))
> ++ if (lstat(slink, &st) >= 0) {
> ++ if (!S_ISLNK(st.st_mode))
> + return log_device_debug_errno(dev,
> SYNTHETIC_ERRNO(EEXIST),
> +- "Conflicting inode
> '%s' found, link to '%s' will not be created.", slink, node);
> ++ "Conflicting inode
> '%s' found, link to '%s' will not be created.",
> ++ slink, devnode);
> + } else if (errno != ENOENT)
> + return log_device_debug_errno(dev, errno, "Failed to
> lstat() '%s': %m", slink);
> +
> +@@ -85,9 +86,9 @@ static int node_symlink(sd_device *dev, const char
> *node, const char *slink) {
> + return log_device_debug_errno(dev, r, "Failed to get
> parent directory of '%s': %m", slink);
> +
> + /* use relative link */
> +- r = path_make_relative(slink_dirname, node, &target);
> ++ r = path_make_relative(slink_dirname, devnode, &target);
> + if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to get
> relative path from '%s' to '%s': %m", slink, node);
> ++ return log_device_debug_errno(dev, r, "Failed to get
> relative path from '%s' to '%s': %m", slink, devnode);
> +
> + r = device_get_device_id(dev, &id);
> + if (r < 0)
> +@@ -109,36 +110,36 @@ static int node_symlink(sd_device *dev, const char
> *node, const char *slink) {
> + return 0;
> + }
> +
> +-static int link_find_prioritized(sd_device *dev, bool add, const char
> *stackdir, char **ret) {
> ++static int stack_directory_find_prioritized_devnode(sd_device *dev,
> const char *dirname, bool add, char **ret) {
> + _cleanup_closedir_ DIR *dir = NULL;
> +- _cleanup_free_ char *target = NULL;
> ++ _cleanup_free_ char *devnode = NULL;
> + int r, priority = 0;
> + const char *id;
> +
> + assert(dev);
> +- assert(stackdir);
> ++ assert(dirname);
> + assert(ret);
> +
> + /* Find device node of device with highest priority. This
> returns 1 if a device found, 0 if no
> +- * device found, or a negative errno. */
> ++ * device found, or a negative errno on error. */
> +
> + if (add) {
> +- const char *devnode;
> ++ const char *n;
> +
> + r = device_get_devlink_priority(dev, &priority);
> + if (r < 0)
> + return r;
> +
> +- r = sd_device_get_devname(dev, &devnode);
> ++ r = sd_device_get_devname(dev, &n);
> + if (r < 0)
> + return r;
> +
> +- target = strdup(devnode);
> +- if (!target)
> ++ devnode = strdup(n);
> ++ if (!devnode)
> + return -ENOMEM;
> + }
> +
> +- dir = opendir(stackdir);
> ++ dir = opendir(dirname);
> + if (!dir)
> + return -errno;
> +
> +@@ -158,7 +159,7 @@ static int link_find_prioritized(sd_device *dev, bool
> add, const char *stackdir,
> +
> + if (de->d_type == DT_LNK) {
> + _cleanup_free_ char *buf = NULL;
> +- char *devnode;
> ++ char *colon;
> +
> + /* New format. The devnode and priority can be
> obtained from symlink. */
> +
> +@@ -168,27 +169,25 @@ static int link_find_prioritized(sd_device *dev,
> bool add, const char *stackdir,
> + continue;
> + }
> +
> +- devnode = strchr(buf, ':');
> +- if (!devnode || devnode == buf)
> ++ colon = strchr(buf, ':');
> ++ if (!colon || colon == buf)
> + continue;
> +
> +- *(devnode++) = '\0';
> +- if (!path_startswith(devnode, "/dev"))
> +- continue;
> ++ *colon = '\0';
> +
> + if (safe_atoi(buf, &tmp_prio) < 0)
> + continue;
> +
> +- if (target && tmp_prio <= priority)
> ++ if (devnode && tmp_prio <= priority)
> + continue;
> +
> +- r = free_and_strdup(&target, devnode);
> ++ r = free_and_strdup(&devnode, colon + 1);
> + if (r < 0)
> + return r;
> +
> + } else if (de->d_type == DT_REG) {
> + _cleanup_(sd_device_unrefp) sd_device *tmp_dev =
> NULL;
> +- const char *devnode;
> ++ const char *val;
> +
> + /* Old format. The devnode and priority must be
> obtained from uevent and
> + * udev database files. */
> +@@ -199,22 +198,23 @@ static int link_find_prioritized(sd_device *dev,
> bool add, const char *stackdir,
> + if (device_get_devlink_priority(tmp_dev,
> &tmp_prio) < 0)
> + continue;
> +
> +- if (target && tmp_prio <= priority)
> ++ if (devnode && tmp_prio <= priority)
> + continue;
> +
> +- if (sd_device_get_devname(tmp_dev, &devnode) < 0)
> ++ if (sd_device_get_devname(tmp_dev, &val) < 0)
> + continue;
> +
> +- r = free_and_strdup(&target, devnode);
> ++ r = free_and_strdup(&devnode, val);
> + if (r < 0)
> + return r;
> ++
> + } else
> + continue;
> +
> + priority = tmp_prio;
> + }
> +
> +- *ret = TAKE_PTR(target);
> ++ *ret = TAKE_PTR(devnode);
> + return !!*ret;
> + }
> +
> +@@ -443,7 +443,7 @@ static int link_update(sd_device *dev, const char
> *slink, bool add) {
> + if (stat(dirname, &st1) < 0 && errno != ENOENT)
> + return log_device_debug_errno(dev, errno,
> "Failed to stat %s: %m", dirname);
> +
> +- r = link_find_prioritized(dev, add, dirname, &target);
> ++ r = stack_directory_find_prioritized_devnode(dev,
> dirname, add, &target);
> + if (r < 0)
> + return log_device_debug_errno(dev, r, "Failed to
> determine device node with the highest priority for '%s': %m", slink);
> + if (r == 0) {
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0007-udev-use-path_make_relative_parent.patch
> b/meta/recipes-core/systemd/systemd/0007-udev-use-path_make_relative_parent.patch
> new file mode 100644
> index 0000000000..6a0ea22672
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0007-udev-use-path_make_relative_parent.patch
> @@ -0,0 +1,43 @@
> +From d6595c5ced636d44dc40adfb0b7cfc929bcac7a3 Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 12:05:36 +0900
> +Subject: [PATCH 07/10] udev: use path_make_relative_parent()
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/d6595c5ced636d44dc40adfb0b7cfc929bcac7a3
> ]
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 8 ++------
> + 1 file changed, 2 insertions(+), 6 deletions(-)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index f358564b41..5a011cf86b 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -64,7 +64,7 @@ static int create_symlink(const char *target, const
> char *slink) {
> + }
> +
> + static int node_symlink(sd_device *dev, const char *devnode, const char
> *slink) {
> +- _cleanup_free_ char *slink_dirname = NULL, *target = NULL;
> ++ _cleanup_free_ char *target = NULL;
> + const char *id, *slink_tmp;
> + struct stat st;
> + int r;
> +@@ -81,12 +81,8 @@ static int node_symlink(sd_device *dev, const char
> *devnode, const char *slink)
> + } else if (errno != ENOENT)
> + return log_device_debug_errno(dev, errno, "Failed to
> lstat() '%s': %m", slink);
> +
> +- r = path_extract_directory(slink, &slink_dirname);
> +- if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to get
> parent directory of '%s': %m", slink);
> +-
> + /* use relative link */
> +- r = path_make_relative(slink_dirname, devnode, &target);
> ++ r = path_make_relative_parent(slink, devnode, &target);
> + if (r < 0)
> + return log_device_debug_errno(dev, r, "Failed to get
> relative path from '%s' to '%s': %m", slink, devnode);
> +
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0008-udev-make-node_symlink-accept-NULL-devname.patch
> b/meta/recipes-core/systemd/systemd/0008-udev-make-node_symlink-accept-NULL-devname.patch
> new file mode 100644
> index 0000000000..cb29367f4d
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0008-udev-make-node_symlink-accept-NULL-devname.patch
> @@ -0,0 +1,75 @@
> +From 541a463fd5aad912c07c88d84e5a1c597c810956 Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 12:08:06 +0900
> +Subject: [PATCH 08/10] udev: make node_symlink() accept NULL devname
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/541a463fd5aad912c07c88d84e5a1c597c810956
> ]
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 24 +++++++++---------------
> + 1 file changed, 9 insertions(+), 15 deletions(-)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index 5a011cf86b..8e78546e18 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -70,13 +70,18 @@ static int node_symlink(sd_device *dev, const char
> *devnode, const char *slink)
> + int r;
> +
> + assert(dev);
> +- assert(devnode);
> + assert(slink);
> +
> ++ if (!devnode) {
> ++ r = sd_device_get_devname(dev, &devnode);
> ++ if (r < 0)
> ++ return log_device_debug_errno(dev, r, "Failed to
> get device node: %m");
> ++ }
> ++
> + if (lstat(slink, &st) >= 0) {
> + if (!S_ISLNK(st.st_mode))
> + return log_device_debug_errno(dev,
> SYNTHETIC_ERRNO(EEXIST),
> +- "Conflicting inode
> '%s' found, link to '%s' will not be created.",
> ++ "Conflicting inode
> '%s' found, symlink to '%s' will not be created.",
> + slink, devnode);
> + } else if (errno != ENOENT)
> + return log_device_debug_errno(dev, errno, "Failed to
> lstat() '%s': %m", slink);
> +@@ -488,23 +493,12 @@ static int device_get_devpath_by_devnum(sd_device
> *dev, char **ret) {
> +
> + int udev_node_update(sd_device *dev, sd_device *dev_old) {
> + _cleanup_free_ char *filename = NULL;
> +- const char *devnode, *devlink;
> ++ const char *devlink;
> + int r;
> +
> + assert(dev);
> + assert(dev_old);
> +
> +- r = sd_device_get_devname(dev, &devnode);
> +- if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to get
> devnode: %m");
> +-
> +- if (DEBUG_LOGGING) {
> +- const char *id = NULL;
> +-
> +- (void) device_get_device_id(dev, &id);
> +- log_device_debug(dev, "Handling device node '%s',
> devnum=%s", devnode, strna(id));
> +- }
> +-
> + /* update possible left-over symlinks */
> + FOREACH_DEVICE_DEVLINK(dev_old, devlink) {
> + /* check if old link name still belongs to this device */
> +@@ -536,7 +530,7 @@ int udev_node_update(sd_device *dev, sd_device
> *dev_old) {
> + return log_device_debug_errno(dev, r, "Failed to get
> device path: %m");
> +
> + /* always add /dev/{block,char}/$major:$minor */
> +- r = node_symlink(dev, devnode, filename);
> ++ r = node_symlink(dev, NULL, filename);
> + if (r < 0)
> + return log_device_warning_errno(dev, r, "Failed to
> create device symlink '%s': %m", filename);
> +
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0009-udev-use-flock-when-updating-device-node-symlinks.patch
> b/meta/recipes-core/systemd/systemd/0009-udev-use-flock-when-updating-device-node-symlinks.patch
> new file mode 100644
> index 0000000000..96ce076378
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0009-udev-use-flock-when-updating-device-node-symlinks.patch
> @@ -0,0 +1,277 @@
> +From 57a272902aa821f9598dd0d74eab98d287473a63 Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 12:17:23 +0900
> +Subject: [PATCH 09/10] udev: use flock() when updating device node
> symlinks
> +
> +By locking the stack directory, we can safely determine the device node
> +with the highest priority for a symlink. So, the multiple try-and-wait
> +loops can be dropped, and the code becomes quite simple.
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/57a272902aa821f9598dd0d74eab98d287473a63
> ]
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 173 ++++++++++---------------------------------
> + 1 file changed, 40 insertions(+), 133 deletions(-)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index 8e78546e18..42efaaa028 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -1,11 +1,6 @@
> + /* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +-#include <errno.h>
> +-#include <fcntl.h>
> +-#include <stdbool.h>
> +-#include <stddef.h>
> +-#include <sys/stat.h>
> +-#include <unistd.h>
> ++#include <sys/file.h>
> +
> + #include "sd-id128.h"
> +
> +@@ -22,47 +17,15 @@
> + #include "mkdir-label.h"
> + #include "parse-util.h"
> + #include "path-util.h"
> +-#include "random-util.h"
> + #include "selinux-util.h"
> + #include "smack-util.h"
> + #include "stat-util.h"
> +-#include "stdio-util.h"
> + #include "string-util.h"
> +-#include "strxcpyx.h"
> +-#include "time-util.h"
> + #include "udev-node.h"
> + #include "user-util.h"
> +
> +-#define CREATE_LINK_MAX_RETRIES 128
> +-#define LINK_UPDATE_MAX_RETRIES 128
> +-#define UPDATE_TIMESTAMP_MAX_RETRIES 128
> +-#define MAX_RANDOM_DELAY (250 * USEC_PER_MSEC)
> +-#define MIN_RANDOM_DELAY ( 50 * USEC_PER_MSEC)
> + #define UDEV_NODE_HASH_KEY
> SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f)
> +
> +-static int create_symlink(const char *target, const char *slink) {
> +- int r;
> +-
> +- assert(target);
> +- assert(slink);
> +-
> +- for (unsigned i = 0; i < CREATE_LINK_MAX_RETRIES; i++) {
> +- r = mkdir_parents_label(slink, 0755);
> +- if (r == -ENOENT)
> +- continue;
> +- if (r < 0)
> +- return r;
> +-
> +- mac_selinux_create_file_prepare(slink, S_IFLNK);
> +- r = RET_NERRNO(symlink(target, slink));
> +- mac_selinux_create_file_clear();
> +- if (r != -ENOENT)
> +- return r;
> +- }
> +-
> +- return r;
> +-}
> +-
> + static int node_symlink(sd_device *dev, const char *devnode, const char
> *slink) {
> + _cleanup_free_ char *target = NULL;
> + const char *id, *slink_tmp;
> +@@ -98,7 +61,13 @@ static int node_symlink(sd_device *dev, const char
> *devnode, const char *slink)
> + slink_tmp = strjoina(slink, ".tmp-", id);
> + (void) unlink(slink_tmp);
> +
> +- r = create_symlink(target, slink_tmp);
> ++ r = mkdir_parents_label(slink_tmp, 0755);
> ++ if (r < 0)
> ++ return log_device_debug_errno(dev, r, "Failed to create
> parent directory of '%s': %m", slink_tmp);
> ++
> ++ mac_selinux_create_file_prepare(slink_tmp, S_IFLNK);
> ++ r = RET_NERRNO(symlink(target, slink_tmp));
> ++ mac_selinux_create_file_clear();
> + if (r < 0)
> + return log_device_debug_errno(dev, r, "Failed to create
> symlink '%s' to '%s': %m", slink_tmp, target);
> +
> +@@ -219,54 +188,7 @@ static int
> stack_directory_find_prioritized_devnode(sd_device *dev, const char *
> + return !!*ret;
> + }
> +
> +-static int update_timestamp(sd_device *dev, int fd, struct stat *prev) {
> +- assert(fd >= 0);
> +- assert(prev);
> +-
> +- /* Even if a symlink in the stack directory is created/removed,
> the mtime of the directory may
> +- * not be changed. Why? Let's consider the following situation.
> For simplicity, let's assume
> +- * there exist two udev workers (A and B) and all of them calls
> link_update() for the same
> +- * devlink simultaneously.
> +- *
> +- * 1. A creates/removes a symlink in the stack directory.
> +- * 2. A calls the first stat() in the loop of link_update().
> +- * 3. A calls link_find_prioritized().
> +- * 4. B creates/removes another symlink in the stack directory,
> so the result of the step 3 is outdated.
> +- * 5. B finishes link_update().
> +- * 6. A creates/removes devlink according to the outdated result
> in the step 3.
> +- * 7. A calls the second stat() in the loop of link_update().
> +- *
> +- * If these 7 steps are processed in this order within a short
> time period that kernel's timer
> +- * does not increase, then even if the contents in the stack
> directory is changed, the results
> +- * of two stat() called by A shows the same timestamp, and A
> cannot detect the change.
> +- *
> +- * By calling this function after creating/removing symlinks in
> the stack directory, the
> +- * timestamp of the stack directory is always increased at least
> in the above step 5, so A can
> +- * detect the update. */
> +-
> +- for (unsigned i = 0; i < UPDATE_TIMESTAMP_MAX_RETRIES; i++) {
> +- struct stat st;
> +-
> +- if (fstat(fd, &st) < 0)
> +- return -errno;
> +-
> +- if (!stat_inode_unmodified(prev, &st))
> +- return 0;
> +-
> +- log_device_debug(dev,
> +- "Stack directory is modified, but its
> timestamp is not changed, "
> +- "updating timestamp after 10ms.");
> +-
> +- (void) usleep(10 * USEC_PER_MSEC);
> +- if (futimens(fd, NULL) < 0)
> +- return -errno;
> +- }
> +-
> +- return -ELOOP;
> +-}
> +-
> + static int stack_directory_update(sd_device *dev, int fd, bool add) {
> +- struct stat st;
> + const char *id;
> + int r;
> +
> +@@ -277,9 +199,6 @@ static int stack_directory_update(sd_device *dev, int
> fd, bool add) {
> + if (r < 0)
> + return r;
> +
> +- if (fstat(fd, &st) < 0)
> +- return -errno;
> +-
> + if (add) {
> + _cleanup_free_ char *data = NULL, *buf = NULL;
> + const char *devname;
> +@@ -312,11 +231,7 @@ static int stack_directory_update(sd_device *dev,
> int fd, bool add) {
> + }
> + }
> +
> +- r = update_timestamp(dev, fd, &st);
> +- if (r < 0)
> +- return r;
> +-
> +- return 0;
> ++ return 1; /* Updated. */
> + }
> +
> + static int stack_directory_open(const char *dirname) {
> +@@ -336,6 +251,21 @@ static int stack_directory_open(const char *dirname)
> {
> + return TAKE_FD(fd);
> + }
> +
> ++static int stack_directory_lock(int dirfd) {
> ++ _cleanup_close_ int fd = -1;
> ++
> ++ assert(dirfd >= 0);
> ++
> ++ fd = openat(dirfd, ".lock", O_CLOEXEC | O_NOFOLLOW | O_RDONLY |
> O_CREAT, 0600);
> ++ if (fd < 0)
> ++ return -errno;
> ++
> ++ if (flock(fd, LOCK_EX) < 0)
> ++ return -errno;
> ++
> ++ return TAKE_FD(fd);
> ++}
> ++
> + size_t udev_node_escape_path(const char *src, char *dest, size_t size) {
> + size_t i, j;
> + uint64_t h;
> +@@ -410,8 +340,8 @@ static int stack_directory_get_name(const char
> *slink, char **ret) {
> + }
> +
> + static int link_update(sd_device *dev, const char *slink, bool add) {
> +- _cleanup_free_ char *dirname = NULL;
> +- _cleanup_close_ int dirfd = -1;
> ++ _cleanup_free_ char *dirname = NULL, *devnode = NULL;
> ++ _cleanup_close_ int dirfd = -1, lockfd = -1;
> + int r;
> +
> + assert(dev);
> +@@ -425,51 +355,28 @@ static int link_update(sd_device *dev, const char
> *slink, bool add) {
> + if (dirfd < 0)
> + return log_device_debug_errno(dev, dirfd, "Failed to
> open stack directory '%s': %m", dirname);
> +
> ++ lockfd = stack_directory_lock(dirfd);
> ++ if (lockfd < 0)
> ++ return log_device_debug_errno(dev, lockfd, "Failed to
> lock stack directory '%s': %m", dirname);
> ++
> + r = stack_directory_update(dev, dirfd, add);
> + if (r < 0)
> + return log_device_debug_errno(dev, r, "Failed to update
> stack directory '%s': %m", dirname);
> +
> +- for (unsigned i = 0; i < LINK_UPDATE_MAX_RETRIES; i++) {
> +- _cleanup_free_ char *target = NULL;
> +- struct stat st1 = {}, st2 = {};
> +-
> +- if (i > 0) {
> +- usec_t delay = MIN_RANDOM_DELAY +
> random_u64_range(MAX_RANDOM_DELAY - MIN_RANDOM_DELAY);
> +-
> +- log_device_debug(dev, "Directory %s was updated,
> retrying to update devlink %s after %s.",
> +- dirname, slink,
> FORMAT_TIMESPAN(delay, USEC_PER_MSEC));
> +- (void) usleep(delay);
> +- }
> +-
> +- if (stat(dirname, &st1) < 0 && errno != ENOENT)
> +- return log_device_debug_errno(dev, errno,
> "Failed to stat %s: %m", dirname);
> +-
> +- r = stack_directory_find_prioritized_devnode(dev,
> dirname, add, &target);
> +- if (r < 0)
> +- return log_device_debug_errno(dev, r, "Failed to
> determine device node with the highest priority for '%s': %m", slink);
> +- if (r == 0) {
> +- log_device_debug(dev, "No reference left for
> '%s', removing", slink);
> +-
> +- if (unlink(slink) < 0 && errno != ENOENT)
> +- log_device_debug_errno(dev, errno,
> "Failed to remove '%s', ignoring: %m", slink);
> ++ r = stack_directory_find_prioritized_devnode(dev, dirname, add,
> &devnode);
> ++ if (r < 0)
> ++ return log_device_debug_errno(dev, r, "Failed to
> determine device node with the highest priority for '%s': %m", slink);
> ++ if (r > 0)
> ++ return node_symlink(dev, devnode, slink);
> +
> +- (void) rmdir_parents(slink, "/dev");
> +- return 0;
> +- }
> ++ log_device_debug(dev, "No reference left for '%s', removing",
> slink);
> +
> +- r = node_symlink(dev, target, slink);
> +- if (r < 0)
> +- return r;
> ++ if (unlink(slink) < 0 && errno != ENOENT)
> ++ log_device_debug_errno(dev, errno, "Failed to remove
> '%s', ignoring: %m", slink);
> +
> +- if (stat(dirname, &st2) < 0 && errno != ENOENT)
> +- return log_device_debug_errno(dev, errno,
> "Failed to stat %s: %m", dirname);
> ++ (void) rmdir_parents(slink, "/dev");
> +
> +- if (((st1.st_mode & S_IFMT) == 0 && (st2.st_mode &
> S_IFMT) == 0) ||
> +- stat_inode_unmodified(&st1, &st2))
> +- return 0;
> +- }
> +-
> +- return -ELOOP;
> ++ return 0;
> + }
> +
> + static int device_get_devpath_by_devnum(sd_device *dev, char **ret) {
> +--
> +2.25.1
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0010-udev-cleanup-stack-directory-run-udev-links-when-all.patch
> b/meta/recipes-core/systemd/systemd/0010-udev-cleanup-stack-directory-run-udev-links-when-all.patch
> new file mode 100644
> index 0000000000..7a6f614db7
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0010-udev-cleanup-stack-directory-run-udev-links-when-all.patch
> @@ -0,0 +1,130 @@
> +From 1055172804e660df2e1c498dafa998ffd65e0c88 Mon Sep 17 00:00:00 2001
> +From: Yu Watanabe <watanabe.yu+github@gmail.com>
> +Date: Mon, 11 Apr 2022 21:52:49 +0900
> +Subject: [PATCH 10/10] udev: cleanup stack directory /run/udev/links when
> all
> + workers exited
> +
> +By the previous commit, the stack directories are not removed even if
> +it is empty. To reduce the inode usage of /run, let's cleanup the
> +directories.
> +
> +PR - https://github.com/systemd/systemd/pull/23043
> +Upstream-Status: Backport [
> https://github.com/systemd/systemd/pull/23043/commits/1055172804e660df2e1c498dafa998ffd65e0c88
> ]
> +Comments: Refreshed all hunks to apply patch cleanly without patch-fuzz
> +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
> +
> +---
> + src/udev/udev-node.c | 42 ++++++++++++++++++++++++++++++++++++++++++
> + src/udev/udev-node.h | 1 +
> + src/udev/udevd.c | 10 ++++++++++
> + 3 files changed, 53 insertions(+)
> +
> +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
> +index 42efaaa028..4e7dca06de 100644
> +--- a/src/udev/udev-node.c
> ++++ b/src/udev/udev-node.c
> +@@ -24,6 +24,48 @@
> +
> + #define UDEV_NODE_HASH_KEY
> SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f)
> +
> ++int udev_node_cleanup(void) {
> ++ _cleanup_closedir_ DIR *dir = NULL;
> ++
> ++ /* This must not be called when any workers exist. It would
> cause a race between mkdir() called
> ++ * by stack_directory_lock() and unlinkat() called by this. */
> ++
> ++ dir = opendir("/run/udev/links");
> ++ if (!dir) {
> ++ if (errno == ENOENT)
> ++ return 0;
> ++
> ++ return log_debug_errno(errno, "Failed to open directory
> '/run/udev/links', ignoring: %m");
> ++ }
> ++
> ++ FOREACH_DIRENT_ALL(de, dir, break) {
> ++ _cleanup_free_ char *lockfile = NULL;
> ++
> ++ if (de->d_name[0] == '.')
> ++ continue;
> ++
> ++ if (de->d_type != DT_DIR)
> ++ continue;
> ++
> ++ /* As commented in the above, this is called when no
> worker exists, hence the file is not
> ++ * locked. On a later uevent, the lock file will be
> created if necessary. So, we can safely
> ++ * remove the file now. */
> ++ lockfile = path_join(de->d_name, ".lock");
> ++ if (!lockfile)
> ++ return log_oom_debug();
> ++
> ++ if (unlinkat(dirfd(dir), lockfile, 0) < 0 && errno !=
> ENOENT) {
> ++ log_debug_errno(errno, "Failed to remove
> '/run/udev/links/%s', ignoring: %m", lockfile);
> ++ continue;
> ++ }
> ++
> ++ if (unlinkat(dirfd(dir), de->d_name, AT_REMOVEDIR) < 0
> && errno != ENOTEMPTY)
> ++ log_debug_errno(errno, "Failed to remove
> '/run/udev/links/%s', ignoring: %m", de->d_name);
> ++ }
> ++
> ++ return 0;
> ++}
> ++
> + static int node_symlink(sd_device *dev, const char *devnode, const char
> *slink) {
> + _cleanup_free_ char *target = NULL;
> + const char *id, *slink_tmp;
> +diff --git a/src/udev/udev-node.h b/src/udev/udev-node.h
> +index 86a829545a..0c545e4a0f 100644
> +--- a/src/udev/udev-node.h
> ++++ b/src/udev/udev-node.h
> +@@ -17,5 +17,6 @@ int udev_node_apply_permissions(
> + OrderedHashmap *seclabel_list);
> + int udev_node_remove(sd_device *dev);
> + int udev_node_update(sd_device *dev, sd_device *dev_old);
> ++int udev_node_cleanup(void);
> +
> + size_t udev_node_escape_path(const char *src, char *dest, size_t size);
> +diff --git a/src/udev/udevd.c b/src/udev/udevd.c
> +index b179dfac37..c519e19897 100644
> +--- a/src/udev/udevd.c
> ++++ b/src/udev/udevd.c
> +@@ -62,6 +62,7 @@
> + #include "udev-builtin.h"
> + #include "udev-ctrl.h"
> + #include "udev-event.h"
> ++#include "udev-node.h"
> + #include "udev-util.h"
> + #include "udev-watch.h"
> + #include "user-util.h"
> +@@ -106,6 +107,7 @@ typedef struct Manager {
> +
> + usec_t last_usec;
> +
> ++ bool udev_node_needs_cleanup;
> + bool stop_exec_queue;
> + bool exit;
> + } Manager;
> +@@ -933,6 +935,9 @@ static int event_queue_start(Manager *ma
> + manager->last_usec = usec;
> + }
> +
> ++ /* To make the stack directory /run/udev/links cleaned up later.
> */
> ++ manager->udev_node_needs_cleanup = true;
> ++
> + r = event_source_disable(manager->kill_workers_event);
> + if (r < 0)
> + log_warning_errno(r, "Failed to disable event source for
> cleaning up idle workers, ignoring: %m");
> +@@ -1487,6 +1492,11 @@ static int on_post(sd_event_source *s, v
> +
> + /* There are no idle workers. */
> +
> ++ if (manager->udev_node_needs_cleanup) {
> ++ (void) udev_node_cleanup();
> ++ manager->udev_node_needs_cleanup = false;
> ++ }
> ++
> + if (manager->exit)
> + return sd_event_exit(manager->event, 0);
> +
> +--
> +2.25.1
> +
> diff --git a/meta/recipes-core/systemd/systemd_250.5.bb
> b/meta/recipes-core/systemd/systemd_250.5.bb
> index 4d520c85f3..22ebc0a229 100644
> --- a/meta/recipes-core/systemd/systemd_250.5.bb
> +++ b/meta/recipes-core/systemd/systemd_250.5.bb
> @@ -34,6 +34,16 @@ SRC_URI += "file://touchscreen.rules \
>
> file://0001-nspawn-make-sure-host-root-can-write-to-the-uidmappe.patch \
> file://CVE-2023-7008.patch \
> file://fix-vlan-qos-mapping.patch \
> + file://0001-udev-move-udev_node_escape_path.patch \
> +
> file://0002-udev-split-link_update-and-introduce-stack_directory.patch \
> +
> file://0003-udev-do-not-remove-stack-directory-even-if-it-is-emp.patch \
> +
> file://0004-path-util-introduce-path_make_relative_parent.patch \
> + file://0005-udev-use-readlinkat_malloc.patch \
> +
> file://0006-udev-rename-link_find_prioritized-and-variables.patch \
> + file://0007-udev-use-path_make_relative_parent.patch \
> + file://0008-udev-make-node_symlink-accept-NULL-devname.patch \
> +
> file://0009-udev-use-flock-when-updating-device-node-symlinks.patch \
> +
> file://0010-udev-cleanup-stack-directory-run-udev-links-when-all.patch \
> "
>
> # patches needed by musl
> --
> 2.25.1
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#199203):
> https://lists.openembedded.org/g/openembedded-core/message/199203
> Mute This Topic: https://lists.openembedded.org/mt/106034797/1686489
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [
> alex.kanavin@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
>
[-- Attachment #2: Type: text/html, Size: 84531 bytes --]
prev parent reply other threads:[~2024-05-11 5:07 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-11 4:08 [OE-Core][kirkstone][PATCH] systemd: Add patches to fix systemd-udev delay during initialization Ranjitsinh Rathod
2024-05-11 5:07 ` Alexander Kanavin [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CANNYZj-dC-nuL8gCbzYOkM9zATJNbGngLCB_asai7cs2=zpuQg@mail.gmail.com' \
--to=alex.kanavin@gmail.com \
--cc=openembedded-core@lists.openembedded.org \
--cc=ranjitsinh.rathod@kpit.com \
--cc=ranjitsinhrathod1991@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).