diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c index 8eb5548ee..78268ab99 100644 --- a/libdm/libdm-common.c +++ b/libdm/libdm-common.c @@ -381,44 +381,6 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor, return 1; } -static int _rename_dev_node(const char *old_name, const char *new_name) -{ - char oldpath[PATH_MAX]; - char newpath[PATH_MAX]; - struct stat info; - - _build_dev_path(oldpath, sizeof(oldpath), old_name); - _build_dev_path(newpath, sizeof(newpath), new_name); - - if (stat(newpath, &info) == 0) { - if (!S_ISBLK(info.st_mode)) { - log_error("A non-block device file at '%s' " - "is already present", newpath); - return 0; - } - - if (unlink(newpath) < 0) { - if (errno == EPERM) { - /* devfs, entry has already been renamed */ - return 1; - } - log_error("Unable to unlink device node for '%s'", - new_name); - return 0; - } - } - - if (rename(oldpath, newpath) < 0) { - log_error("Unable to rename device node from '%s' to '%s'", - old_name, new_name); - return 0; - } - - log_debug("Renamed %s to %s", oldpath, newpath); - - return 1; -} - static int _rm_dev_node(const char *dev_name) { char path[PATH_MAX]; @@ -442,6 +404,62 @@ static int _rm_dev_node(const char *dev_name) return 1; } +static int _rename_dev_node(const char *old_name, const char *new_name) +{ + char oldpath[PATH_MAX]; + char newpath[PATH_MAX]; + struct stat info; + + _build_dev_path(oldpath, sizeof(oldpath), old_name); + _build_dev_path(newpath, sizeof(newpath), new_name); + + if (stat(newpath, &info) == 0) { + if (!S_ISBLK(info.st_mode)) { + log_error("A non-block device file at '%s' " + "is already present", newpath); + return 0; + } + else if (dm_udev_get_sync_support()) { + if (stat(oldpath, &info) < 0 && + errno == ENOENT) + /* assume udev already deleted this */ + return 1; + else { + log_warn("The node %s should have been renamed to %s " + "by udev but old node is still present. " + "Falling back to direct old node removal.", + oldpath, newpath); + return _rm_dev_node(old_name); + } + } + + if (unlink(newpath) < 0) { + if (errno == EPERM) { + /* devfs, entry has already been renamed */ + return 1; + } + log_error("Unable to unlink device node for '%s'", + new_name); + return 0; + } + } + else if (dm_udev_get_sync_support()) + log_warn("The node %s should have been renamed to %s " + "by udev but new node is not present. " + "Falling back to direct node rename.", + oldpath, newpath); + + if (rename(oldpath, newpath) < 0) { + log_error("Unable to rename device node from '%s' to '%s'", + old_name, new_name); + return 0; + } + + log_debug("Renamed %s to %s", oldpath, newpath); + + return 1; +} + #ifdef linux static int _open_dev_node(const char *dev_name) {