#include "alloc-util.h"
#include "chase-symlinks.h"
+#include "device-monitor-private.h"
#include "device-util.h"
#include "errno-util.h"
#include "event-util.h"
return 0;
}
-static int setup_monitor(sd_event *event, sd_device_monitor **ret) {
+static int setup_monitor(sd_event *event, MonitorNetlinkGroup group, const char *description, sd_device_monitor **ret) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
int r;
assert(event);
assert(ret);
- r = sd_device_monitor_new(&monitor);
+ r = device_monitor_new_full(&monitor, group, /* fd = */ -1);
if (r < 0)
return r;
if (r < 0)
return r;
- r = sd_device_monitor_start(monitor, device_monitor_handler, NULL);
+ r = sd_device_monitor_set_description(monitor, description);
if (r < 0)
return r;
- r = sd_event_source_set_description(sd_device_monitor_get_event_source(monitor),
- "device-monitor-event-source");
+ r = sd_device_monitor_start(monitor, device_monitor_handler, NULL);
if (r < 0)
return r;
}
int wait_main(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
+ _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *udev_monitor = NULL, *kernel_monitor = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
int r;
if (r < 0)
return log_error_errno(r, "Failed to set up inotify: %m");
- r = setup_monitor(event, &monitor);
+ r = setup_monitor(event, MONITOR_GROUP_UDEV, "udev-uevent-monitor-event-source", &udev_monitor);
if (r < 0)
- return log_error_errno(r, "Failed to set up device monitor: %m");
+ return log_error_errno(r, "Failed to set up udev uevent monitor: %m");
if (arg_wait_until == WAIT_UNTIL_ADDED) {
/* If --initialized=no is specified, it is not necessary to wait uevents for the specified
- * devices to be processed by udevd. Let's periodically check the devices. Then, we may be
- * able to finish this program earlier when udevd is very busy.
- *
- * This is useful for working around issues #24360 and #24450.
+ * devices to be processed by udevd. Hence, let's listen on the kernel's uevent stream. Then,
+ * we may be able to finish this program earlier when udevd is very busy.
+ * Note, we still need to also setup udev monitor, as this may be invoked with a devlink
+ * (e.g. /dev/disk/by-id/foo). In that case, the devlink may not exist when we received a
+ * uevent from kernel, as the udevd may not finish to process the uevent yet. Hence, we need
+ * to wait until the event is processed by udevd. */
+ r = setup_monitor(event, MONITOR_GROUP_KERNEL, "kernel-uevent-monitor-event-source", &kernel_monitor);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set up kernel uevent monitor: %m");
+
+ /* This is a workaround for issues #24360 and #24450.
* For some reasons, the kernel sometimes does not emit uevents for loop block device on
* attach. Hence, without the periodic timer, no event source for this program will be
* triggered, and this will be timed out.