($INBOX_DIR/description missing)
 help / color / mirror / Atom feed
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 --]

      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).