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; }