1 /* SPDX-License-Identifier: GPL-2.0-or-later */
8 #include "alloc-util.h"
10 #include "device-monitor-private.h"
11 #include "device-util.h"
12 #include "errno-util.h"
13 #include "event-util.h"
16 #include "inotify-util.h"
17 #include "parse-util.h"
18 #include "path-util.h"
19 #include "static-destruct.h"
20 #include "string-table.h"
22 #include "udev-util.h"
25 typedef enum WaitUntil
{
26 WAIT_UNTIL_INITIALIZED
,
30 _WAIT_UNTIL_INVALID
= -EINVAL
,
33 static WaitUntil arg_wait_until
= WAIT_UNTIL_INITIALIZED
;
34 static usec_t arg_timeout_usec
= USEC_INFINITY
;
35 static bool arg_settle
= false;
36 static char **arg_devices
= NULL
;
38 STATIC_DESTRUCTOR_REGISTER(arg_devices
, strv_freep
);
40 static const char * const wait_until_table
[_WAIT_UNTIL_MAX
] = {
41 [WAIT_UNTIL_INITIALIZED
] = "initialized",
42 [WAIT_UNTIL_ADDED
] = "added",
43 [WAIT_UNTIL_REMOVED
] = "removed",
46 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wait_until
, WaitUntil
);
48 static int check_device(const char *path
) {
49 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
54 if (arg_wait_until
== WAIT_UNTIL_REMOVED
) {
55 r
= laccess(path
, F_OK
);
63 r
= sd_device_new_from_path(&dev
, path
);
69 if (arg_wait_until
== WAIT_UNTIL_INITIALIZED
)
70 return sd_device_get_is_initialized(dev
);
75 static bool check(void) {
79 r
= udev_queue_is_empty();
83 log_warning_errno(r
, "Failed to check if udev queue is empty, assuming empty: %m");
86 STRV_FOREACH(p
, arg_devices
) {
90 log_warning_errno(r
, "Failed to check if device \"%s\" is %s, assuming not %s: %m",
92 wait_until_to_string(arg_wait_until
),
93 wait_until_to_string(arg_wait_until
));
101 static int check_and_exit(sd_event
*event
) {
107 r
= sd_event_exit(event
, 0);
117 static int device_monitor_handler(sd_device_monitor
*monitor
, sd_device
*device
, void *userdata
) {
124 if (device_for_action(device
, SD_DEVICE_REMOVE
) != (arg_wait_until
== WAIT_UNTIL_REMOVED
))
127 if (arg_wait_until
== WAIT_UNTIL_REMOVED
)
128 /* On removed event, the received device may not contain enough information.
129 * Let's unconditionally check all requested devices are removed. */
130 return check_and_exit(sd_device_monitor_get_event(monitor
));
132 /* For other events, at first check if the received device matches with the requested devices,
133 * to avoid calling check() so many times within a short time. */
135 r
= sd_device_get_sysname(device
, &name
);
137 log_device_warning_errno(device
, r
, "Failed to get sysname of received device, ignoring: %m");
141 STRV_FOREACH(p
, arg_devices
) {
144 if (!path_startswith(*p
, "/sys"))
147 r
= path_find_last_component(*p
, false, NULL
, &s
);
149 log_warning_errno(r
, "Failed to extract filename from \"%s\", ignoring: %m", *p
);
155 if (strneq(s
, name
, r
))
156 return check_and_exit(sd_device_monitor_get_event(monitor
));
159 r
= sd_device_get_devname(device
, &name
);
162 log_device_warning_errno(device
, r
, "Failed to get devname of received device, ignoring: %m");
166 if (path_strv_contains(arg_devices
, name
))
167 return check_and_exit(sd_device_monitor_get_event(monitor
));
169 FOREACH_DEVICE_DEVLINK(device
, link
)
170 if (path_strv_contains(arg_devices
, link
))
171 return check_and_exit(sd_device_monitor_get_event(monitor
));
176 static int setup_monitor(sd_event
*event
, MonitorNetlinkGroup group
, const char *description
, sd_device_monitor
**ret
) {
177 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*monitor
= NULL
;
183 r
= device_monitor_new_full(&monitor
, group
, /* fd = */ -1);
187 (void) sd_device_monitor_set_receive_buffer_size(monitor
, 128*1024*1024);
189 r
= sd_device_monitor_attach_event(monitor
, event
);
193 r
= sd_device_monitor_set_description(monitor
, description
);
197 r
= sd_device_monitor_start(monitor
, device_monitor_handler
, NULL
);
201 *ret
= TAKE_PTR(monitor
);
205 static int on_inotify(sd_event_source
*s
, const struct inotify_event
*event
, void *userdata
) {
206 return check_and_exit(sd_event_source_get_event(s
));
209 static int setup_inotify(sd_event
*event
) {
210 _cleanup_(sd_event_source_unrefp
) sd_event_source
*s
= NULL
;
218 r
= sd_event_add_inotify(event
, &s
, "/run/udev" , IN_CREATE
| IN_DELETE
, on_inotify
, NULL
);
222 r
= sd_event_source_set_description(s
, "inotify-event-source");
226 return sd_event_source_set_floating(s
, true);
229 static int setup_timer(sd_event
*event
) {
230 _cleanup_(sd_event_source_unrefp
) sd_event_source
*s
= NULL
;
235 if (arg_timeout_usec
== USEC_INFINITY
)
238 r
= sd_event_add_time_relative(event
, &s
, CLOCK_BOOTTIME
, arg_timeout_usec
, 0,
239 NULL
, INT_TO_PTR(-ETIMEDOUT
));
243 r
= sd_event_source_set_description(s
, "timeout-event-source");
247 return sd_event_source_set_floating(s
, true);
250 static int reset_timer(sd_event
*e
, sd_event_source
**s
);
252 static int on_periodic_timer(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
253 static unsigned counter
= 0;
259 e
= sd_event_source_get_event(s
);
261 /* Even if all devices exists, we try to wait for uevents to be emitted from kernel. */
268 log_debug("All requested devices popped up without receiving kernel uevents.");
269 return sd_event_exit(e
, 0);
272 r
= reset_timer(e
, &s
);
274 log_warning_errno(r
, "Failed to reset periodic timer event source, ignoring: %m");
279 static int reset_timer(sd_event
*e
, sd_event_source
**s
) {
280 return event_reset_time_relative(e
, s
, CLOCK_BOOTTIME
, 250 * USEC_PER_MSEC
, 0,
281 on_periodic_timer
, NULL
, 0, "periodic-timer-event-source", false);
284 static int setup_periodic_timer(sd_event
*event
) {
285 _cleanup_(sd_event_source_unrefp
) sd_event_source
*s
= NULL
;
290 r
= reset_timer(event
, &s
);
294 /* Set the lower priority than device monitor, to make uevents always dispatched first. */
295 r
= sd_event_source_set_priority(s
, SD_EVENT_PRIORITY_NORMAL
+ 1);
299 return sd_event_source_set_floating(s
, true);
302 static int help(void) {
303 printf("%s wait [OPTIONS] DEVICE [DEVICEā¦]\n\n"
304 "Wait for devices or device symlinks being created.\n\n"
305 " -h --help Print this message\n"
306 " -V --version Print version of the program\n"
307 " -t --timeout=SEC Maximum time to wait for the device\n"
308 " --initialized=BOOL Wait for devices being initialized by systemd-udevd\n"
309 " --removed Wait for devices being removed\n"
310 " --settle Also wait for all queued events being processed\n",
311 program_invocation_short_name
);
316 static int parse_argv(int argc
, char *argv
[]) {
318 ARG_INITIALIZED
= 0x100,
323 static const struct option options
[] = {
324 { "timeout", required_argument
, NULL
, 't' },
325 { "initialized", required_argument
, NULL
, ARG_INITIALIZED
},
326 { "removed", no_argument
, NULL
, ARG_REMOVED
},
327 { "settle", no_argument
, NULL
, ARG_SETTLE
},
328 { "help", no_argument
, NULL
, 'h' },
329 { "version", no_argument
, NULL
, 'V' },
335 while ((c
= getopt_long(argc
, argv
, "t:hV", options
, NULL
)) >= 0)
338 r
= parse_sec(optarg
, &arg_timeout_usec
);
340 return log_error_errno(r
, "Failed to parse -t/--timeout= parameter: %s", optarg
);
343 case ARG_INITIALIZED
:
344 r
= parse_boolean(optarg
);
346 return log_error_errno(r
, "Failed to parse --initialized= parameter: %s", optarg
);
347 arg_wait_until
= r
? WAIT_UNTIL_INITIALIZED
: WAIT_UNTIL_ADDED
;
351 arg_wait_until
= WAIT_UNTIL_REMOVED
;
359 return print_version();
368 assert_not_reached();
372 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
373 "Too few arguments, expected at least one device path or device symlink.");
375 arg_devices
= strv_copy(argv
+ optind
);
379 return 1; /* work to do */
382 int wait_main(int argc
, char *argv
[], void *userdata
) {
383 _cleanup_(sd_device_monitor_unrefp
) sd_device_monitor
*udev_monitor
= NULL
, *kernel_monitor
= NULL
;
384 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
387 r
= parse_argv(argc
, argv
);
391 STRV_FOREACH(p
, arg_devices
) {
394 if (!path_is_safe(*p
))
395 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
396 "Device path cannot contain \"..\".");
398 if (!is_device_path(*p
))
399 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
400 "Specified path \"%s\" does not start with \"/dev/\" or \"/sys/\".", *p
);
403 /* Check before configuring event sources, as devices may be already initialized. */
407 r
= sd_event_default(&event
);
409 return log_error_errno(r
, "Failed to initialize sd-event: %m");
411 r
= setup_timer(event
);
413 return log_error_errno(r
, "Failed to set up timeout: %m");
415 r
= setup_inotify(event
);
417 return log_error_errno(r
, "Failed to set up inotify: %m");
419 r
= setup_monitor(event
, MONITOR_GROUP_UDEV
, "udev-uevent-monitor-event-source", &udev_monitor
);
421 return log_error_errno(r
, "Failed to set up udev uevent monitor: %m");
423 if (arg_wait_until
== WAIT_UNTIL_ADDED
) {
424 /* If --initialized=no is specified, it is not necessary to wait uevents for the specified
425 * devices to be processed by udevd. Hence, let's listen on the kernel's uevent stream. Then,
426 * we may be able to finish this program earlier when udevd is very busy.
427 * Note, we still need to also setup udev monitor, as this may be invoked with a devlink
428 * (e.g. /dev/disk/by-id/foo). In that case, the devlink may not exist when we received a
429 * uevent from kernel, as the udevd may not finish to process the uevent yet. Hence, we need
430 * to wait until the event is processed by udevd. */
431 r
= setup_monitor(event
, MONITOR_GROUP_KERNEL
, "kernel-uevent-monitor-event-source", &kernel_monitor
);
433 return log_error_errno(r
, "Failed to set up kernel uevent monitor: %m");
435 /* This is a workaround for issues #24360 and #24450.
436 * For some reasons, the kernel sometimes does not emit uevents for loop block device on
437 * attach. Hence, without the periodic timer, no event source for this program will be
438 * triggered, and this will be timed out.
439 * Theoretically, inotify watch may be better, but this program typically expected to run in
440 * a short time. Hence, let's use the simpler periodic timer event source here. */
441 r
= setup_periodic_timer(event
);
443 return log_error_errno(r
, "Failed to set up periodic timer: %m");
446 /* Check before entering the event loop, as devices may be initialized during setting up event sources. */
450 r
= sd_event_loop(event
);
452 return log_error_errno(r
, "Timed out for waiting devices being %s.",
453 wait_until_to_string(arg_wait_until
));
455 return log_error_errno(r
, "Event loop failed: %m");