]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect: use DISKSEQ when waiting for block devices 20257/head
authorLuca Boccassi <luca.boccassi@microsoft.com>
Tue, 20 Jul 2021 14:26:56 +0000 (15:26 +0100)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Wed, 28 Jul 2021 19:07:01 +0000 (20:07 +0100)
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.

src/core/namespace.c
src/dissect/dissect.c
src/gpt-auto-generator/gpt-auto-generator.c
src/nspawn/nspawn.c
src/portable/portable.c
src/shared/discover-image.c
src/shared/dissect-image.c
src/shared/dissect-image.h
src/sysext/sysext.c
src/test/test-loop-block.c

index 982aeeac1915b002cbc93badaf3020dab267ffb2..6b939e65e44b63354b3157998308a0b7ea40b64f 100644 (file)
@@ -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,
index 88bb3de40f776e14cd8c8f29870a97d0a80f9eee..f0d5da8d18b71cb3234fe4116b97eb917bf139b3 100644 (file)
@@ -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,
index f5346f49ad1ad91ed1553db54b9b3c53ec9dabfd..4d0364fceebaa9f83555faf420df4e1122dd555d 100644 (file)
@@ -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|
index 99a325621976e75409dc933a1a91c6b0929c3d11..98b0b0486b16c57fbf9b76a0bec96c5f2281ffd6 100644 (file)
@@ -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,
index 5afb008bb8f2737d5dcad8902a213a9a7739606a..899a74073d6d43eeac32f7e92ab40fdddf80d67e 100644 (file)
@@ -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 |
index 521264ec29b3b194a8f636fe76157004746b6c5e..1711dd647afdf71450d53cf07148d908340cc33b 100644 (file)
@@ -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 |
index 27b9ac9569e7674e094b2cbcffc8fc85e15219b3..1df1bdc3cd0ba30c10ab7a14a48e225a50fe9e54 100644 (file)
@@ -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,
index 1ce14e915e29495f452e0e9b9aa840b1a264d274..cad52f2184c59a31b1ccf0f7d771e6ca7aff0a55 100644 (file)
@@ -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);
index 572e4007fe27ff0072157520c70c823fbf337790..0d1f1c5218a5a5242e75d77fa3598eba42b32307 100644 (file)
@@ -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,
index 57f3279b676b692ebf12ab703c03d6d7dad8174d..1642f82e40ddf1fe38a739eacf8e2a1d05a5121a 100644 (file)
@@ -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);