mirror of
https://github.com/systemd/systemd.git
synced 2025-02-07 05:57:46 +03:00
dissect: use DISKSEQ when waiting for block devices
DISKSEQ is a reliable way to find out if we missed a uevent or not, as it's monotonically increasing. If we parse an event with a smaller or no sequence number, we know we need to wait longer. If we parse an event with a greater sequence number, we know we missed it and the device was reused.
This commit is contained in:
parent
bcef1743a5
commit
a36429971a
@ -1905,6 +1905,7 @@ int setup_namespace(
|
||||
loop_device->fd,
|
||||
&verity,
|
||||
root_image_options,
|
||||
loop_device->diskseq,
|
||||
loop_device->uevent_seqnum_not_before,
|
||||
loop_device->timestamp_not_before,
|
||||
dissect_image_flags,
|
||||
|
@ -795,6 +795,7 @@ static int run(int argc, char *argv[]) {
|
||||
arg_image,
|
||||
&arg_verity_settings,
|
||||
NULL,
|
||||
d->diskseq,
|
||||
d->uevent_seqnum_not_before,
|
||||
d->timestamp_not_before,
|
||||
arg_flags,
|
||||
|
@ -699,6 +699,7 @@ static int enumerate_partitions(dev_t devnum) {
|
||||
r = dissect_image(
|
||||
fd,
|
||||
NULL, NULL,
|
||||
/* diskseq= */ 0,
|
||||
UINT64_MAX,
|
||||
USEC_INFINITY,
|
||||
DISSECT_IMAGE_GPT_ONLY|
|
||||
|
@ -5700,6 +5700,7 @@ static int run(int argc, char *argv[]) {
|
||||
arg_image,
|
||||
&arg_verity_settings,
|
||||
NULL,
|
||||
loop->diskseq,
|
||||
loop->uevent_seqnum_not_before,
|
||||
loop->timestamp_not_before,
|
||||
dissect_image_flags,
|
||||
|
@ -393,6 +393,7 @@ static int portable_extract_by_path(
|
||||
r = dissect_image(
|
||||
d->fd,
|
||||
NULL, NULL,
|
||||
d->diskseq,
|
||||
d->uevent_seqnum_not_before,
|
||||
d->timestamp_not_before,
|
||||
DISSECT_IMAGE_READ_ONLY |
|
||||
|
@ -1203,6 +1203,7 @@ int image_read_metadata(Image *i) {
|
||||
r = dissect_image(
|
||||
d->fd,
|
||||
NULL, NULL,
|
||||
d->diskseq,
|
||||
d->uevent_seqnum_not_before,
|
||||
d->timestamp_not_before,
|
||||
DISSECT_IMAGE_GENERIC_ROOT |
|
||||
|
@ -284,6 +284,7 @@ struct wait_data {
|
||||
sd_device *parent_device;
|
||||
blkid_partition blkidp;
|
||||
sd_device *found;
|
||||
uint64_t diskseq;
|
||||
uint64_t uevent_seqnum_not_before;
|
||||
usec_t timestamp_not_before;
|
||||
DissectImageFlags flags;
|
||||
@ -302,7 +303,25 @@ static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device,
|
||||
if (device_for_action(device, SD_DEVICE_REMOVE))
|
||||
return 0;
|
||||
|
||||
if (w->uevent_seqnum_not_before != UINT64_MAX) {
|
||||
if (w->diskseq != 0) {
|
||||
uint64_t diskseq;
|
||||
|
||||
/* If w->diskseq is non-zero, then we must have a disk seqnum */
|
||||
r = sd_device_get_diskseq(device, &diskseq);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Dropping event because it has no diskseq, but waiting for %" PRIu64, w->diskseq);
|
||||
return 0;
|
||||
}
|
||||
if (diskseq < w->diskseq) {
|
||||
log_debug("Dropping event because diskseq too old (%" PRIu64 " < %" PRIu64 ")",
|
||||
diskseq, w->diskseq);
|
||||
return 0;
|
||||
}
|
||||
if (diskseq > w->diskseq) {
|
||||
r = -EBUSY;
|
||||
goto finish; /* Newer than what we were expecting, so we missed it, stop waiting */
|
||||
}
|
||||
} else if (w->uevent_seqnum_not_before != UINT64_MAX) {
|
||||
uint64_t seqnum;
|
||||
|
||||
r = sd_device_get_seqnum(device, &seqnum);
|
||||
@ -378,6 +397,7 @@ static int wait_for_partition_device(
|
||||
sd_device *parent,
|
||||
blkid_partition pp,
|
||||
usec_t deadline,
|
||||
uint64_t diskseq,
|
||||
uint64_t uevent_seqnum_not_before,
|
||||
usec_t timestamp_not_before,
|
||||
DissectImageFlags flags,
|
||||
@ -423,6 +443,7 @@ static int wait_for_partition_device(
|
||||
_cleanup_(wait_data_done) struct wait_data w = {
|
||||
.parent_device = parent,
|
||||
.blkidp = pp,
|
||||
.diskseq = diskseq,
|
||||
.uevent_seqnum_not_before = uevent_seqnum_not_before,
|
||||
.timestamp_not_before = timestamp_not_before,
|
||||
.flags = flags,
|
||||
@ -450,16 +471,21 @@ 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;
|
||||
/* If we don't have a disk sequence number then we cannot do exact matching,
|
||||
* and we cannot know if we missed it or if it has not been sent yet, so set
|
||||
* up additional retries to increase the chances of receiving the event. */
|
||||
if (diskseq == 0) {
|
||||
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_source_set_exit_on_failure(retry_source, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_event_loop(event);
|
||||
if (r < 0)
|
||||
@ -583,6 +609,7 @@ int dissect_image(
|
||||
int fd,
|
||||
const VeritySettings *verity,
|
||||
const MountOptions *mount_options,
|
||||
uint64_t diskseq,
|
||||
uint64_t uevent_seqnum_not_before,
|
||||
usec_t timestamp_not_before,
|
||||
DissectImageFlags flags,
|
||||
@ -838,7 +865,7 @@ int dissect_image(
|
||||
if (!pp)
|
||||
return errno_or_else(EIO);
|
||||
|
||||
r = wait_for_partition_device(d, pp, deadline, uevent_seqnum_not_before, timestamp_not_before, flags, &q);
|
||||
r = wait_for_partition_device(d, pp, deadline, diskseq, uevent_seqnum_not_before, timestamp_not_before, flags, &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -2750,6 +2777,7 @@ int dissect_image_and_warn(
|
||||
const char *name,
|
||||
const VeritySettings *verity,
|
||||
const MountOptions *mount_options,
|
||||
uint64_t diskseq,
|
||||
uint64_t uevent_seqnum_not_before,
|
||||
usec_t timestamp_not_before,
|
||||
DissectImageFlags flags,
|
||||
@ -2766,7 +2794,7 @@ int dissect_image_and_warn(
|
||||
name = buffer;
|
||||
}
|
||||
|
||||
r = dissect_image(fd, verity, mount_options, uevent_seqnum_not_before, timestamp_not_before, flags, ret);
|
||||
r = dissect_image(fd, verity, mount_options, diskseq, uevent_seqnum_not_before, timestamp_not_before, flags, ret);
|
||||
switch (r) {
|
||||
|
||||
case -EOPNOTSUPP:
|
||||
@ -2874,7 +2902,7 @@ int mount_image_privately_interactively(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up loopback device for %s: %m", image);
|
||||
|
||||
r = dissect_image_and_warn(d->fd, image, &verity, NULL, d->uevent_seqnum_not_before, d->timestamp_not_before, flags, &dissected_image);
|
||||
r = dissect_image_and_warn(d->fd, image, &verity, NULL, d->diskseq, d->uevent_seqnum_not_before, d->timestamp_not_before, flags, &dissected_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -2965,6 +2993,7 @@ int verity_dissect_and_mount(
|
||||
loop_device->fd,
|
||||
&verity,
|
||||
options,
|
||||
loop_device->diskseq,
|
||||
loop_device->uevent_seqnum_not_before,
|
||||
loop_device->timestamp_not_before,
|
||||
dissect_image_flags,
|
||||
@ -2975,6 +3004,7 @@ int verity_dissect_and_mount(
|
||||
loop_device->fd,
|
||||
&verity,
|
||||
options,
|
||||
loop_device->diskseq,
|
||||
loop_device->uevent_seqnum_not_before,
|
||||
loop_device->timestamp_not_before,
|
||||
dissect_image_flags | DISSECT_IMAGE_NO_PARTITION_TABLE,
|
||||
|
@ -162,8 +162,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
|
||||
const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
|
||||
|
||||
int probe_filesystem(const char *node, char **ret_fstype);
|
||||
int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, uint64_t diskseq, uint64_t uevent_seqnum_not_before, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, uint64_t diskseq, uint64_t uevent_seqnum_not_before, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
|
||||
|
||||
DissectedImage* dissected_image_unref(DissectedImage *m);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
|
||||
|
@ -532,6 +532,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
|
||||
img->path,
|
||||
&verity_settings,
|
||||
NULL,
|
||||
d->diskseq,
|
||||
d->uevent_seqnum_not_before,
|
||||
d->timestamp_not_before,
|
||||
flags,
|
||||
|
@ -51,7 +51,7 @@ static void* thread_func(void *ptr) {
|
||||
|
||||
log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);
|
||||
|
||||
r = dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, DISSECT_IMAGE_READ_ONLY, &dissected);
|
||||
r = dissect_image(loop->fd, NULL, NULL, loop->diskseq, loop->uevent_seqnum_not_before, loop->timestamp_not_before, DISSECT_IMAGE_READ_ONLY, &dissected);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed dissect loopback device %s: %m", loop->node);
|
||||
assert_se(r >= 0);
|
||||
@ -188,7 +188,7 @@ int main(int argc, char *argv[]) {
|
||||
sfdisk = NULL;
|
||||
|
||||
assert_se(loop_device_make(fd, O_RDWR, 0, UINT64_MAX, LO_FLAGS_PARTSCAN, &loop) >= 0);
|
||||
assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
|
||||
assert_se(dissect_image(loop->fd, NULL, NULL, loop->diskseq, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
|
||||
|
||||
assert_se(dissected->partitions[PARTITION_ESP].found);
|
||||
assert_se(dissected->partitions[PARTITION_ESP].node);
|
||||
@ -212,7 +212,7 @@ int main(int argc, char *argv[]) {
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", id, true) >= 0);
|
||||
|
||||
dissected = dissected_image_unref(dissected);
|
||||
assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
|
||||
assert_se(dissect_image(loop->fd, NULL, NULL, loop->diskseq, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
|
||||
|
||||
assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user