diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index f22088db57..19bf01abc7 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -340,7 +340,7 @@ _public_ int sd_device_new_from_subsystem_sysname( assert_return(path_is_normalized(sysname), -EINVAL); if (streq(subsystem, "subsystem")) { - FOREACH_STRING(s, "/sys/subsystem/", "/sys/bus/", "/sys/class/") { + FOREACH_STRING(s, "/sys/bus/", "/sys/class/") { r = device_strjoin_new(s, sysname, NULL, NULL, ret); if (r < 0) return r; @@ -364,13 +364,11 @@ _public_ int sd_device_new_from_subsystem_sysname( const char *subsys = memdupa_suffix0(sysname, sep - sysname); sep++; - FOREACH_STRING(s, "/sys/subsystem/", "/sys/bus/") { - r = device_strjoin_new(s, subsys, "/drivers/", sep, ret); - if (r < 0) - return r; - if (r > 0) - return 0; - } + r = device_strjoin_new("/sys/bus/", subsys, "/drivers/", sep, ret); + if (r < 0) + return r; + if (r > 0) + return 0; } } @@ -380,13 +378,11 @@ _public_ int sd_device_new_from_subsystem_sysname( if (name[i] == '/') name[i] = '!'; - FOREACH_STRING(s, "/sys/subsystem/", "/sys/bus/") { - r = device_strjoin_new(s, subsystem, "/devices/", name, ret); - if (r < 0) - return r; - if (r > 0) - return 0; - } + r = device_strjoin_new("/sys/bus/", subsystem, "/devices/", name, ret); + if (r < 0) + return r; + if (r > 0) + return 0; r = device_strjoin_new("/sys/class/", subsystem, "/", name, ret); if (r < 0) @@ -739,7 +735,7 @@ _public_ int sd_device_get_syspath(sd_device *device, const char **ret) { static int device_new_from_child(sd_device **ret, sd_device *child) { _cleanup_free_ char *path = NULL; - const char *subdir, *syspath; + const char *syspath; int r; assert(ret); @@ -749,35 +745,35 @@ static int device_new_from_child(sd_device **ret, sd_device *child) { if (r < 0) return r; - path = strdup(syspath); - if (!path) - return -ENOMEM; - subdir = path + STRLEN("/sys"); - for (;;) { - char *pos; + _cleanup_free_ char *p = NULL; - pos = strrchr(subdir, '/'); - if (!pos || pos < subdir + 2) + r = path_extract_directory(path ?: syspath, &p); + if (r < 0) + return r; + + if (path_equal(p, "/sys")) return -ENODEV; - *pos = '\0'; + r = sd_device_new_from_syspath(ret, p); + if (r != -ENODEV) + return r; - r = sd_device_new_from_syspath(ret, path); - if (r < 0) - continue; - - return 0; + free_and_replace(path, p); } } _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) { + int r; + assert_return(child, -EINVAL); if (!child->parent_set) { - child->parent_set = true; + r = device_new_from_child(&child->parent, child); + if (r < 0 && r != -ENODEV) + return r; - (void) device_new_from_child(&child->parent, child); + child->parent_set = true; } if (!child->parent) @@ -869,9 +865,7 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) { r = device_set_subsystem(device, "module"); else if (strstr(syspath, "/drivers/")) r = device_set_drivers_subsystem(device); - else if (PATH_STARTSWITH_SET(device->devpath, "/subsystem/", - "/class/", - "/bus/")) + else if (PATH_STARTSWITH_SET(device->devpath, "/class/", "/bus/")) r = device_set_subsystem(device, "subsystem"); else { device->subsystem_set = true; @@ -1144,8 +1138,14 @@ _public_ int sd_device_get_seqnum(sd_device *device, uint64_t *ret) { } _public_ int sd_device_get_diskseq(sd_device *device, uint64_t *ret) { + int r; + assert_return(device, -EINVAL); + r = device_read_uevent_file(device); + if (r < 0) + return r; + if (device->diskseq == 0) return -ENOENT; diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 1cde6b9c9c..424ecfc2cf 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -422,7 +422,7 @@ static int worker_send_result(Manager *manager, int result) { return loop_write(manager->worker_watch[WRITE_END], &result, sizeof(result), false); } -static int device_get_block_device(sd_device *dev, const char **ret) { +static int device_get_whole_disk(sd_device *dev, const char **ret) { const char *val; int r; @@ -451,6 +451,8 @@ static int device_get_block_device(sd_device *dev, const char **ret) { return log_device_debug_errno(dev, r, "Failed to get devtype: %m"); if (r >= 0 && streq(val, "partition")) { r = sd_device_get_parent(dev, &dev); + if (r == -ENOENT) /* The device may be already removed. */ + goto irrelevant; if (r < 0) return log_device_debug_errno(dev, r, "Failed to get parent device: %m"); } @@ -469,7 +471,7 @@ irrelevant: return 0; } -static int worker_lock_block_device(sd_device *dev, int *ret_fd) { +static int worker_lock_whole_disk(sd_device *dev, int *ret_fd) { _cleanup_close_ int fd = -1; const char *val; int r; @@ -482,7 +484,7 @@ static int worker_lock_block_device(sd_device *dev, int *ret_fd) { * event handling; in the case udev acquired the lock, the external process can block until udev has * finished its event handling. */ - r = device_get_block_device(dev, &val); + r = device_get_whole_disk(dev, &val); if (r < 0) return r; if (r == 0) @@ -579,7 +581,7 @@ static int worker_process_device(Manager *manager, sd_device *dev) { * Instead of processing the event, we requeue the event and will try again after a delay. * * The user-facing side of this: https://systemd.io/BLOCK_DEVICE_LOCKING */ - r = worker_lock_block_device(dev, &fd_lock); + r = worker_lock_whole_disk(dev, &fd_lock); if (r == -EAGAIN) return EVENT_RESULT_TRY_AGAIN; if (r < 0) @@ -1091,7 +1093,7 @@ static int event_queue_assume_block_device_unlocked(Manager *manager, sd_device * device is not locked anymore. The assumption may not be true, but that should not cause any * issues, as in that case events will be requeued soon. */ - r = device_get_block_device(dev, &devname); + r = device_get_whole_disk(dev, &devname); if (r <= 0) return r; @@ -1104,7 +1106,7 @@ static int event_queue_assume_block_device_unlocked(Manager *manager, sd_device if (event->retry_again_next_usec == 0) continue; - if (device_get_block_device(event->dev, &event_devname) <= 0) + if (device_get_whole_disk(event->dev, &event_devname) <= 0) continue; if (!streq(devname, event_devname))