From 6ecccf60d2497895a7665b70a0471da53f4dafb3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Aug 2022 00:33:15 +0900 Subject: [PATCH 1/6] udevadm-settle: emit deprecated warning earlier --- src/udev/udevadm-settle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index df9fefc8d0..2404442fd7 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -172,6 +172,8 @@ int settle_main(int argc, char *argv[], void *userdata) { return 0; } + (void) emit_deprecation_warning(); + deadline = now(CLOCK_MONOTONIC) + arg_timeout; /* guarantee that the udev daemon isn't pre-processing */ @@ -197,8 +199,6 @@ int settle_main(int argc, char *argv[], void *userdata) { return 0; } - (void) emit_deprecation_warning(); - for (;;) { if (arg_exists && access(arg_exists, F_OK) >= 0) return 0; From f9786884027129d4de4463208f5c2bd1b97d540c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Aug 2022 00:31:13 +0900 Subject: [PATCH 2/6] udevadm-settle: make failure in udev_ctrl_new() critical It should not fail in general. --- src/udev/udevadm-settle.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index 2404442fd7..50972847f2 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -176,21 +176,24 @@ int settle_main(int argc, char *argv[], void *userdata) { deadline = now(CLOCK_MONOTONIC) + arg_timeout; - /* guarantee that the udev daemon isn't pre-processing */ if (getuid() == 0) { _cleanup_(udev_ctrl_unrefp) UdevCtrl *uctrl = NULL; - if (udev_ctrl_new(&uctrl) >= 0) { - r = udev_ctrl_send_ping(uctrl); - if (r < 0) { - log_debug_errno(r, "Failed to connect to udev daemon: %m"); - return 0; - } + /* guarantee that the udev daemon isn't pre-processing */ - r = udev_ctrl_wait(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout)); - if (r < 0) - return log_error_errno(r, "Failed to wait for daemon to reply: %m"); + r = udev_ctrl_new(&uctrl); + if (r < 0) + return log_error_errno(r, "Failed to create control socket for udev daemon: %m"); + + r = udev_ctrl_send_ping(uctrl); + if (r < 0) { + log_debug_errno(r, "Failed to connect to udev daemon, ignoring: %m"); + return 0; } + + r = udev_ctrl_wait(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout)); + if (r < 0) + return log_error_errno(r, "Failed to wait for daemon to reply: %m"); } fd = udev_queue_init(); From 23b11e0b7ce3ece40606edeed43ff998c3fe03ee Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Aug 2022 00:45:21 +0900 Subject: [PATCH 3/6] udevadm-settle: check if udevd is running --- src/udev/udevadm-settle.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index 50972847f2..1bb047f442 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -194,6 +194,10 @@ int settle_main(int argc, char *argv[], void *userdata) { r = udev_ctrl_wait(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout)); if (r < 0) return log_error_errno(r, "Failed to wait for daemon to reply: %m"); + } else { + /* For non-privileged users, at least check if udevd is running. */ + if (access("/run/udev/control", F_OK) < 0) + return log_error_errno(errno, "udevd is not running."); } fd = udev_queue_init(); From d0dfd9fd325001e27aed1828b8ae0e03193b56bd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Aug 2022 01:04:56 +0900 Subject: [PATCH 4/6] udevadm-settle: rename arg_timeout -> arg_timeout_usec --- src/udev/udevadm-settle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index 1bb047f442..b61875a6e7 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -29,7 +29,7 @@ #include "util.h" #include "virt.h" -static usec_t arg_timeout = 120 * USEC_PER_SEC; +static usec_t arg_timeout_usec = 120 * USEC_PER_SEC; static const char *arg_exists = NULL; static int help(void) { @@ -61,7 +61,7 @@ static int parse_argv(int argc, char *argv[]) { while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) { switch (c) { case 't': - r = parse_sec(optarg, &arg_timeout); + r = parse_sec(optarg, &arg_timeout_usec); if (r < 0) return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg); break; @@ -174,7 +174,7 @@ int settle_main(int argc, char *argv[], void *userdata) { (void) emit_deprecation_warning(); - deadline = now(CLOCK_MONOTONIC) + arg_timeout; + deadline = now(CLOCK_MONOTONIC) + arg_timeout_usec; if (getuid() == 0) { _cleanup_(udev_ctrl_unrefp) UdevCtrl *uctrl = NULL; @@ -191,7 +191,7 @@ int settle_main(int argc, char *argv[], void *userdata) { return 0; } - r = udev_ctrl_wait(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout)); + r = udev_ctrl_wait(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout_usec)); if (r < 0) return log_error_errno(r, "Failed to wait for daemon to reply: %m"); } else { From 9668c1a5d32264b2f782e854764ef2efe7f70c1a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Aug 2022 01:06:08 +0900 Subject: [PATCH 5/6] udevadm-settle: use sd-event --- src/udev/udevadm-settle.c | 93 ++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index b61875a6e7..477e9d735e 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -4,29 +4,21 @@ * Copyright © 2009 Scott James Remnant */ -#include #include -#include -#include -#include -#include #include #include "sd-bus.h" +#include "sd-event.h" #include "sd-login.h" #include "sd-messages.h" #include "bus-util.h" -#include "fd-util.h" -#include "io-util.h" -#include "string-util.h" #include "strv.h" #include "time-util.h" #include "udev-ctrl.h" #include "udev-util.h" #include "udevadm.h" #include "unit-def.h" -#include "util.h" #include "virt.h" static usec_t arg_timeout_usec = 120 * USEC_PER_SEC; @@ -158,9 +150,36 @@ static int emit_deprecation_warning(void) { return 0; } +static bool check(void) { + int r; + + if (arg_exists) { + if (access(arg_exists, F_OK) >= 0) + return true; + + if (errno != ENOENT) + log_warning_errno(errno, "Failed to check the existence of \"%s\", ignoring: %m", arg_exists); + } + + /* exit if queue is empty */ + r = udev_queue_is_empty(); + if (r < 0) + log_warning_errno(r, "Failed to check if udev queue is empty, ignoring: %m"); + + return r > 0; +} + +static int on_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata) { + assert(s); + + if (check()) + return sd_event_exit(sd_event_source_get_event(s), 0); + + return 0; +} + int settle_main(int argc, char *argv[], void *userdata) { - _cleanup_close_ int fd = -1; - usec_t deadline; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; int r; r = parse_argv(argc, argv); @@ -174,8 +193,6 @@ int settle_main(int argc, char *argv[], void *userdata) { (void) emit_deprecation_warning(); - deadline = now(CLOCK_MONOTONIC) + arg_timeout_usec; - if (getuid() == 0) { _cleanup_(udev_ctrl_unrefp) UdevCtrl *uctrl = NULL; @@ -200,34 +217,30 @@ int settle_main(int argc, char *argv[], void *userdata) { return log_error_errno(errno, "udevd is not running."); } - fd = udev_queue_init(); - if (fd < 0) { - log_debug_errno(fd, "Queue is empty, nothing to watch: %m"); + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get default sd-event object: %m"); + + r = sd_event_add_inotify(event, NULL, "/run/udev" , IN_DELETE, on_inotify, NULL); + if (r < 0) + return log_error_errno(r, "Failed to add inotify watch for /run/udev: %m"); + + if (arg_timeout_usec != USEC_INFINITY) { + r = sd_event_add_time_relative(event, NULL, CLOCK_BOOTTIME, arg_timeout_usec, 0, + NULL, INT_TO_PTR(-ETIMEDOUT)); + if (r < 0) + return log_error_errno(r, "Failed to add timer event source: %m"); + } + + /* Check before entering the event loop, as the udev queue may be already empty. */ + if (check()) return 0; - } - for (;;) { - if (arg_exists && access(arg_exists, F_OK) >= 0) - return 0; + r = sd_event_loop(event); + if (r == -ETIMEDOUT) + return log_error_errno(r, "Timed out for waiting the udev queue being empty."); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); - /* exit if queue is empty */ - r = udev_queue_is_empty(); - if (r < 0) - return log_error_errno(r, "Failed to check queue is empty: %m"); - if (r > 0) - return 0; - - if (now(CLOCK_MONOTONIC) >= deadline) - return -ETIMEDOUT; - - /* wake up when queue becomes empty */ - r = fd_wait_for_event(fd, POLLIN, MSEC_PER_SEC); - if (r < 0) - return r; - if (r & POLLIN) { - r = flush_fd(fd); - if (r < 0) - return log_error_errno(r, "Failed to flush queue: %m"); - } - } + return 0; } From 5b61c9b2bb9dcddcabb34a45d74454ed0eeed346 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Aug 2022 01:11:47 +0900 Subject: [PATCH 6/6] udevadm-settle: check validity of specified path --- src/udev/udevadm-settle.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index 477e9d735e..9de25ae678 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -13,6 +13,7 @@ #include "sd-messages.h" #include "bus-util.h" +#include "path-util.h" #include "strv.h" #include "time-util.h" #include "udev-ctrl.h" @@ -58,6 +59,9 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg); break; case 'E': + if (!path_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid path: %s", optarg); + arg_exists = optarg; break; case 'V':