From 05c3c620f72ff17617ae996973b5433048771fe6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 3 Mar 2021 07:34:32 +0900 Subject: [PATCH 1/2] dissect: try to find partition again on timeout Not sure, but at the time the target partition device is created or enumerated, some sysattrs or properties may not be ready. So, let's find partition on timeout. The device may be ready at that time. --- src/shared/dissect-image.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 9dbc0891c5..2c6ae80f20 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -285,6 +285,8 @@ struct wait_data { blkid_partition blkidp; sd_device *found; uint64_t uevent_seqnum_not_before; + usec_t timestamp_not_before; + DissectImageFlags flags; }; static inline void wait_data_done(struct wait_data *d) { @@ -329,6 +331,27 @@ finish: return sd_event_exit(sd_device_monitor_get_event(monitor), r); } +static int timeout_handler(sd_event_source *s, uint64_t usec, void *userdata) { + struct wait_data *w = userdata; + int r; + + assert(w); + + /* Why partition not appeared within the timeout? We may lost some uevent, as some properties + * were not ready when we received uevent... Not sure, but anyway, let's try to find the + * partition again before give up. */ + + r = find_partition(w->parent_device, w->blkidp, w->timestamp_not_before, w->flags, &w->found); + if (r == -ENXIO) + return log_debug_errno(SYNTHETIC_ERRNO(ETIMEDOUT), + "Partition still not appeared after timeout reached."); + if (r < 0) + return log_debug_errno(r, "Failed to find partition: %m"); + + log_debug("Partition appeared after timeout reached."); + return sd_event_exit(sd_event_source_get_event(s), 0); +} + static int wait_for_partition_device( sd_device *parent, blkid_partition pp, @@ -379,6 +402,8 @@ static int wait_for_partition_device( .parent_device = parent, .blkidp = pp, .uevent_seqnum_not_before = uevent_seqnum_not_before, + .timestamp_not_before = timestamp_not_before, + .flags = flags, }; r = sd_device_monitor_start(monitor, device_monitor_handler, &w); @@ -394,7 +419,11 @@ static int wait_for_partition_device( r = sd_event_add_time( event, &timeout_source, CLOCK_MONOTONIC, deadline, 0, - NULL, INT_TO_PTR(-ETIMEDOUT)); + timeout_handler, &w); + if (r < 0) + return r; + + r = sd_event_source_set_exit_on_failure(timeout_source, true); if (r < 0) return r; } From 61730746f77559d6b167311afde42d4e6beb26d4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 3 Mar 2021 08:25:05 +0900 Subject: [PATCH 2/2] dissect: find partition more frequently With the previous commit, the partition may be found after 45 sec. It is too late. Let's find partition more frequently. --- src/shared/dissect-image.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 2c6ae80f20..714baa8572 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -352,6 +352,28 @@ static int timeout_handler(sd_event_source *s, uint64_t usec, void *userdata) { return sd_event_exit(sd_event_source_get_event(s), 0); } +static int retry_handler(sd_event_source *s, uint64_t usec, void *userdata) { + struct wait_data *w = userdata; + int r; + + assert(w); + + r = find_partition(w->parent_device, w->blkidp, w->timestamp_not_before, w->flags, &w->found); + if (r != -ENXIO) { + if (r < 0) + return log_debug_errno(r, "Failed to find partition: %m"); + + log_debug("Partition found by a periodic search."); + return sd_event_exit(sd_event_source_get_event(s), 0); + } + + r = sd_event_source_set_time_relative(s, 500 * USEC_PER_MSEC); + if (r < 0) + return r; + + return sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); +} + static int wait_for_partition_device( sd_device *parent, blkid_partition pp, @@ -361,7 +383,7 @@ static int wait_for_partition_device( DissectImageFlags flags, sd_device **ret) { - _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL, *retry_source = NULL; _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; int r; @@ -428,6 +450,17 @@ static int wait_for_partition_device( return r; } + r = sd_event_add_time_relative( + event, &retry_source, + CLOCK_MONOTONIC, 500 * USEC_PER_MSEC, 0, + retry_handler, &w); + if (r < 0) + return r; + + r = sd_event_source_set_exit_on_failure(retry_source, true); + if (r < 0) + return r; + r = sd_event_loop(event); if (r < 0) return r;