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