Merge pull request #20715 from yuwata/udev-node-follow-ups
udev-node: several follow-ups
This commit is contained in:
+19
-14
@@ -272,14 +272,14 @@ static int update_timestamp(sd_device *dev, const char *path, struct stat *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 three udev workers (A, B, and C) and all of them calls link_update() for the
|
||||
* same devlink simultaneously.
|
||||
* there exist two udev workers (A and B) and all of them calls link_update() for the same
|
||||
* devlink simultaneously.
|
||||
*
|
||||
* 1. B creates/removes a symlink in the stack directory.
|
||||
* 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. C creates/removes another symlink in the stack directory, so the result of the step 3 is outdated.
|
||||
* 5. B and C finish link_update().
|
||||
* 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().
|
||||
*
|
||||
@@ -334,25 +334,30 @@ static int update_stack_directory(sd_device *dev, const char *dirname, bool add)
|
||||
return log_oom_debug();
|
||||
|
||||
if (!add) {
|
||||
bool unlink_failed = false;
|
||||
int unlink_error = 0, stat_error = 0;
|
||||
|
||||
if (stat(dirname, &st) < 0) {
|
||||
if (errno == ENOENT)
|
||||
return 0; /* The stack directory is already removed. That's OK. */
|
||||
log_device_debug_errno(dev, errno, "Failed to stat %s, ignoring: %m", dirname);
|
||||
stat_error = -errno;
|
||||
}
|
||||
|
||||
if (unlink(filename) < 0) {
|
||||
unlink_failed = true;
|
||||
if (errno != ENOENT)
|
||||
log_device_debug_errno(dev, errno, "Failed to remove %s, ignoring: %m", filename);
|
||||
}
|
||||
if (unlink(filename) < 0)
|
||||
unlink_error = -errno;
|
||||
|
||||
if (rmdir(dirname) >= 0 || errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
if (unlink_failed)
|
||||
return 0; /* If we failed to remove the symlink, there is almost nothing we can do. */
|
||||
if (unlink_error < 0) {
|
||||
if (unlink_error == -ENOENT)
|
||||
return 0;
|
||||
|
||||
/* 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 (stat_error < 0)
|
||||
return log_device_debug_errno(dev, stat_error, "Failed to stat %s: %m", dirname);
|
||||
|
||||
/* The symlink was removed. Check if the timestamp of directory is changed. */
|
||||
r = update_timestamp(dev, dirname, &st);
|
||||
|
||||
Reference in New Issue
Block a user