4eda52
From 1561b9e2c9ea779ab611f52fd8b4eef616896e09 Mon Sep 17 00:00:00 2001
4295f9
From: Yu Watanabe <watanabe.yu+github@gmail.com>
4295f9
Date: Wed, 1 Sep 2021 02:20:33 +0900
4295f9
Subject: [PATCH] udev-node: always atomically create symlink to device node
4295f9
4295f9
By the previous commit, it is not necessary to distinguish if the devlink
4295f9
already exists. Also, I cannot find any significant advantages of the
4295f9
previous complecated logic, that is, first try to create directly, and then
4295f9
fallback to atomically creation. Moreover, such logic increases the chance
4295f9
of conflicts between multiple udev workers.
4295f9
4295f9
This makes devlinks always created atomically. Hopefully, this reduces the
4295f9
conflicts between the workers.
4295f9
4295f9
(cherry picked from commit 242d39ebc1391f4734f6e63ff13764de92bc5f70)
4295f9
4eda52
Related: #2005024
4295f9
---
4295f9
 src/udev/udev-node.c | 42 +++++++++---------------------------------
4295f9
 1 file changed, 9 insertions(+), 33 deletions(-)
4295f9
4295f9
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
4295f9
index 1a34ea8128..46c04fe00b 100644
4295f9
--- a/src/udev/udev-node.c
4295f9
+++ b/src/udev/udev-node.c
4295f9
@@ -71,6 +71,13 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
4295f9
         assert(node);
4295f9
         assert(slink);
4295f9
 
4295f9
+        if (lstat(slink, &stats) >= 0) {
4295f9
+                if (!S_ISLNK(stats.st_mode))
4295f9
+                        return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
4295f9
+                                                      "Conflicting inode '%s' found, link to '%s' will not be created.", slink, node);
4295f9
+        } else if (errno != ENOENT)
4295f9
+                return log_device_debug_errno(dev, errno, "Failed to lstat() '%s': %m", slink);
4295f9
+
4295f9
         r = path_extract_directory(slink, &slink_dirname);
4295f9
         if (r < 0)
4295f9
                 return log_device_debug_errno(dev, r, "Failed to get parent directory of '%s': %m", slink);
4295f9
@@ -80,41 +87,11 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
4295f9
         if (r < 0)
4295f9
                 return log_device_debug_errno(dev, r, "Failed to get relative path from '%s' to '%s': %m", slink, node);
4295f9
 
4295f9
-        if (lstat(slink, &stats) >= 0) {
4295f9
-                _cleanup_free_ char *buf = NULL;
4295f9
-
4295f9
-                if (!S_ISLNK(stats.st_mode))
4295f9
-                        return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
4295f9
-                                                      "Conflicting inode '%s' found, link to '%s' will not be created.", slink, node);
4295f9
-
4295f9
-                if (readlink_malloc(slink, &buf) >= 0 &&
4295f9
-                    path_equal(target, buf)) {
4295f9
-                        /* preserve link with correct target, do not replace node of other device */
4295f9
-                        log_device_debug(dev, "Preserve already existing symlink '%s' to '%s'", slink, target);
4295f9
-
4295f9
-                        (void) label_fix(slink, LABEL_IGNORE_ENOENT);
4295f9
-                        (void) utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW);
4295f9
-
4295f9
-                        return 0;
4295f9
-                }
4295f9
-        } else if (errno == ENOENT) {
4295f9
-                log_device_debug(dev, "Creating symlink '%s' to '%s'", slink, target);
4295f9
-
4295f9
-                r = create_symlink(target, slink);
4295f9
-                if (r >= 0)
4295f9
-                        return 0;
4295f9
-
4295f9
-                log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s', trying to replace '%s': %m", slink, target, slink);
4295f9
-        } else
4295f9
-                return log_device_debug_errno(dev, errno, "Failed to lstat() '%s': %m", slink);
4295f9
-
4295f9
-        log_device_debug(dev, "Atomically replace '%s'", slink);
4295f9
-
4295f9
         r = device_get_device_id(dev, &id;;
4295f9
         if (r < 0)
4295f9
                 return log_device_debug_errno(dev, r, "Failed to get device id: %m");
4295f9
-        slink_tmp = strjoina(slink, ".tmp-", id);
4295f9
 
4295f9
+        slink_tmp = strjoina(slink, ".tmp-", id);
4295f9
         (void) unlink(slink_tmp);
4295f9
 
4295f9
         r = create_symlink(target, slink_tmp);
4295f9
@@ -127,8 +104,7 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
4295f9
                 return r;
4295f9
         }
4295f9
 
4295f9
-        /* Tell caller that we replaced already existing symlink. */
4295f9
-        return 1;
4295f9
+        return 0;
4295f9
 }
4295f9
 
4295f9
 static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir, char **ret) {