|
|
4295f9 |
From 323f687e53737ccf7687482c31690374da90d8e7 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 |
|
|
|
4295f9 |
Related: #1977994
|
|
|
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) {
|