From f81b3e90e46a4a5fc0be57fe67934f23f3bb959b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 31 Aug 2022 22:30:17 +0900 Subject: [PATCH 1/5] udev-util: replace device_new_from_dev_path() with sd_device_new_from_devname() --- src/shared/udev-util.c | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 3c1a674f57..e47c44f7a8 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -123,29 +123,6 @@ int udev_parse_config_full( return 0; } -/* Note that if -ENOENT is returned, it will be logged at debug level rather than error, - * because it's an expected, common occurrence that the caller will handle with a fallback */ -static int device_new_from_dev_path(const char *devlink, sd_device **ret_device) { - struct stat st; - int r; - - assert(devlink); - - if (stat(devlink, &st) < 0) - return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, - "Failed to stat() %s: %m", devlink); - - if (!S_ISBLK(st.st_mode)) - return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), - "%s does not point to a block device: %m", devlink); - - r = sd_device_new_from_stat_rdev(ret_device, &st); - if (r < 0) - return log_error_errno(r, "Failed to initialize device from %s: %m", devlink); - - return 0; -} - struct DeviceMonitorData { const char *sysname; const char *devlink; @@ -225,9 +202,9 @@ static int device_wait_for_initialization_internal( /* Devlink might already exist, if it does get the device to use the sysname filtering */ if (!device && devlink) { - r = device_new_from_dev_path(devlink, &device); - if (r < 0 && r != -ENOENT) - return r; + r = sd_device_new_from_devname(&device, devlink); + if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r)) + return log_error_errno(r, "Failed to create sd-device object from %s: %m", devlink); } if (device) { @@ -282,9 +259,9 @@ static int device_wait_for_initialization_internal( /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized * yet. */ if (!device && devlink) { - r = device_new_from_dev_path(devlink, &device); - if (r < 0 && r != -ENOENT) - return r; + r = sd_device_new_from_devname(&device, devlink); + if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r)) + return log_error_errno(r, "Failed to create sd-device object from %s: %m", devlink); } if (device && sd_device_get_is_initialized(device) > 0) { if (ret) From 4f89ce0c91efc49948ecc3601649fec4d7a36298 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 31 Aug 2022 22:17:12 +0900 Subject: [PATCH 2/5] udev-util: make device_wait_for_initialization() take relative timeout Also make the timer event source floating. --- src/shared/dissect-image.c | 2 +- src/shared/udev-util.c | 22 ++++++++++------------ src/shared/udev-util.h | 4 ++-- src/udev/udevadm-info.c | 2 +- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 87712abfb3..30a10f9239 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -2057,7 +2057,7 @@ static int verity_partition( if (r == 0) { /* devmapper might say that the device exists, but the devlink might not yet have been * created. Check and wait for the udev event in that case. */ - r = device_wait_for_devlink(node, "block", usec_add(now(CLOCK_MONOTONIC), 100 * USEC_PER_MSEC), NULL); + r = device_wait_for_devlink(node, "block", 100 * USEC_PER_MSEC, NULL); /* Fallback to activation with a unique device if it's taking too long */ if (r == -ETIMEDOUT) break; diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index e47c44f7a8..db3161b5ce 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -185,11 +185,10 @@ static int device_wait_for_initialization_internal( sd_device *_device, const char *devlink, const char *subsystem, - usec_t deadline, + usec_t timeout_usec, sd_device **ret) { _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; - _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; /* Ensure that if !_device && devlink, device gets unrefd on errors since it will be new */ _cleanup_(sd_device_unrefp) sd_device *device = sd_device_ref(_device); @@ -247,17 +246,16 @@ static int device_wait_for_initialization_internal( if (r < 0) return log_error_errno(r, "Failed to start device monitor: %m"); - if (deadline != USEC_INFINITY) { - r = sd_event_add_time( - event, &timeout_source, - CLOCK_MONOTONIC, deadline, 0, + if (timeout_usec != USEC_INFINITY) { + r = sd_event_add_time_relative( + event, NULL, + CLOCK_MONOTONIC, timeout_usec, 0, NULL, INT_TO_PTR(-ETIMEDOUT)); if (r < 0) return log_error_errno(r, "Failed to add timeout event source: %m"); } - /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized - * yet. */ + /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized yet. */ if (!device && devlink) { r = sd_device_new_from_devname(&device, devlink); if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r)) @@ -278,12 +276,12 @@ static int device_wait_for_initialization_internal( return 0; } -int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t deadline, sd_device **ret) { - return device_wait_for_initialization_internal(device, NULL, subsystem, deadline, ret); +int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout_usec, sd_device **ret) { + return device_wait_for_initialization_internal(device, NULL, subsystem, timeout_usec, ret); } -int device_wait_for_devlink(const char *devlink, const char *subsystem, usec_t deadline, sd_device **ret) { - return device_wait_for_initialization_internal(NULL, devlink, subsystem, deadline, ret); +int device_wait_for_devlink(const char *devlink, const char *subsystem, usec_t timeout_usec, sd_device **ret) { + return device_wait_for_initialization_internal(NULL, devlink, subsystem, timeout_usec, ret); } int device_is_renaming(sd_device *dev) { diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index 43a1b846f4..c3c3dbe842 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -36,8 +36,8 @@ static inline int udev_parse_config(void) { return udev_parse_config_full(NULL, NULL, NULL, NULL, NULL); } -int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t deadline, sd_device **ret); -int device_wait_for_devlink(const char *path, const char *subsystem, usec_t deadline, sd_device **ret); +int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout_usec, sd_device **ret); +int device_wait_for_devlink(const char *path, const char *subsystem, usec_t timeout_usec, sd_device **ret); int device_is_renaming(sd_device *dev); bool device_for_action(sd_device *dev, sd_device_action_t action); diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c index 04baed2e0c..fccc967a47 100644 --- a/src/udev/udevadm-info.c +++ b/src/udev/udevadm-info.c @@ -846,7 +846,7 @@ int info_main(int argc, char *argv[], void *userdata) { r = device_wait_for_initialization( device, NULL, - usec_add(now(CLOCK_MONOTONIC), arg_wait_for_initialization_timeout), + arg_wait_for_initialization_timeout, &d); if (r < 0) return r; From 2b6605102d0a34665778c41f99ed7301950c096b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 31 Aug 2022 22:43:50 +0900 Subject: [PATCH 3/5] dissect-image: add environment variable to control timeout for waiting devlink to be configured --- docs/ENVIRONMENT.md | 3 +++ src/shared/dissect-image.c | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index e5afafbe10..62e064e12b 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -384,6 +384,9 @@ disk images with `--image=` or similar: directories in `/usr/lib/`, `/run`, …) or passed to the kernel for validation against its built-in certificates. +* `$SYSTEMD_DISSECT_VERITY_TIMEOUT_SEC=sec` — takes a timespan, which controls + the timeout waiting for the image to be configured. Defaults to 100 msec. + * `$SYSTEMD_LOOP_DIRECT_IO` – takes a boolean, which controls whether to enable LO_FLAGS_DIRECT_IO (i.e. direct IO + asynchronous IO) on loopback block devices when opening them. Defaults to on, set this to "0" to disable this diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 30a10f9239..4782330a0c 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -2055,9 +2055,28 @@ static int verity_partition( if (!IN_SET(r, 0, -ENODEV, -ENOENT, -EBUSY)) return log_debug_errno(r, "Checking whether existing verity device %s can be reused failed: %m", node); if (r == 0) { + usec_t timeout_usec = 100 * USEC_PER_MSEC; + const char *e; + + /* On slower machines, like non-KVM vm, setting up device may take a long time. + * Let's make the timeout configurable. */ + e = getenv("SYSTEMD_DISSECT_VERITY_TIMEOUT_SEC"); + if (e) { + usec_t t; + + r = parse_sec(e, &t); + if (r < 0) + log_debug_errno(r, + "Failed to parse timeout specified in $SYSTEMD_DISSECT_VERITY_TIMEOUT_SEC, " + "using the default timeout (%s).", + FORMAT_TIMESPAN(timeout_usec, USEC_PER_MSEC)); + else + timeout_usec = t; + } + /* devmapper might say that the device exists, but the devlink might not yet have been * created. Check and wait for the udev event in that case. */ - r = device_wait_for_devlink(node, "block", 100 * USEC_PER_MSEC, NULL); + r = device_wait_for_devlink(node, "block", timeout_usec, NULL); /* Fallback to activation with a unique device if it's taking too long */ if (r == -ETIMEDOUT) break; From 9fff8e1fdd222f8f05b9ecf170814a9059acfc78 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 31 Aug 2022 23:10:43 +0900 Subject: [PATCH 4/5] test-29-portable: extend timeout for slower environment --- test/units/testsuite-29.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/units/testsuite-29.sh b/test/units/testsuite-29.sh index 3b1395619a..e56dad991e 100755 --- a/test/units/testsuite-29.sh +++ b/test/units/testsuite-29.sh @@ -5,6 +5,17 @@ set -eux set -o pipefail +# Set longer timeout for slower machines, e.g. non-KVM vm. +mkdir -p /run/systemd/system.conf.d +cat >/run/systemd/system.conf.d/10-timeout.conf < Date: Wed, 31 Aug 2022 23:12:26 +0900 Subject: [PATCH 5/5] test-29-portable: enable debugging logs of udevd --- test/units/testsuite-29.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/units/testsuite-29.sh b/test/units/testsuite-29.sh index e56dad991e..cc10d4ad57 100755 --- a/test/units/testsuite-29.sh +++ b/test/units/testsuite-29.sh @@ -16,6 +16,8 @@ systemctl daemon-reexec export SYSTEMD_DISSECT_VERITY_TIMEOUT_SEC=30 +udevadm control --log-level debug + ARGS=() state_directory=/var/lib/private/ if [[ -v ASAN_OPTIONS || -v UBSAN_OPTIONS ]]; then