mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
libdm: fix races with udev
On modern systems udev manages nodes in /dev/mapper directory. It creates, deletes and renames the nodes according to the state of the kernel driver. When the dmsetup is compiled without udev support (--enable-udev_sync) and runs on the system with running udevd it tries to manage nodes in /dev/mapper too, so it can race with udev. dmsetup checks if the node was created/deleted/renamed with the stat syscall, and skips the operation if it was. However, if udev creates/deletes/renames the node after the stat syscall and before the mknod/unlink/rename syscall, dmsetup reports an error. Since in the system everything happened as expected, skip reporting error for such case. These races can be easily provoked by inserting sleep at appropriate places. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
This commit is contained in:
parent
3ac7f927e1
commit
ed30145f4a
@ -1,5 +1,6 @@
|
||||
Version 1.02.83
|
||||
==================================
|
||||
Skip race errors when non-udev dmsetup build runs on udev-enabled system.
|
||||
Skip error message when holders are not present in sysfs.
|
||||
Use __linux__ instead of linux define to make libdevmapper.h C compliant.
|
||||
|
||||
|
@ -966,7 +966,9 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
|
||||
(void) dm_prepare_selinux_context(path, S_IFBLK);
|
||||
old_mask = umask(0);
|
||||
if (mknod(path, S_IFBLK | mode, dev) < 0) {
|
||||
|
||||
/* The node may already have been created by udev. So ignore EEXIST. */
|
||||
if (mknod(path, S_IFBLK | mode, dev) < 0 && errno != EEXIST) {
|
||||
log_error("%s: mknod for %s failed: %s", path, dev_name, strerror(errno));
|
||||
umask(old_mask);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
@ -998,7 +1000,8 @@ static int _rm_dev_node(const char *dev_name, int warn_if_udev_failed)
|
||||
log_warn("Node %s was not removed by udev. "
|
||||
"Falling back to direct node removal.", path);
|
||||
|
||||
if (unlink(path) < 0) {
|
||||
/* udev may already have deleted the node. Ignore ENOENT. */
|
||||
if (unlink(path) < 0 && errno != ENOENT) {
|
||||
log_error("Unable to unlink device node for '%s'", dev_name);
|
||||
return 0;
|
||||
}
|
||||
@ -1054,7 +1057,8 @@ static int _rename_dev_node(const char *old_name, const char *new_name,
|
||||
"Falling back to direct node rename.",
|
||||
oldpath, newpath);
|
||||
|
||||
if (rename(oldpath, newpath) < 0) {
|
||||
/* udev may already have renamed the node. Ignore ENOENT. */
|
||||
if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
|
||||
log_error("Unable to rename device node from '%s' to '%s'",
|
||||
old_name, new_name);
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user