]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image: wait for the main device and all partitions to be known by udev 11144/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 13 Dec 2018 15:39:05 +0000 (16:39 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 17 Dec 2018 12:50:57 +0000 (13:50 +0100)
Fixes #10526.

Even if we waited for the root device to appear, the mount could still fail if
we didn't wait for udev to initalize the device. In particular, the
/dev/block/n:m path used to mount the device is created by udev, and nspawn
would sometimes win the race and the mount would fail with -ENOENT.

The same wait is done for partitions, since if we try to mount them, the same
considerations apply.

Note: I first implemented a version which just does a loop (with a short wait).
In that approach, udev takes on average ~800 µs to initialize the loopback
device. The approach where we set up a monitor and avoid the loop is a bit
nicer. There doesn't seem to be a significant difference in speed.
With 1000 invocations of 'systemd-nspawn -i image.squashfs echo':

loop (previous approach):
real 4m52.625s
user 0m37.094s
sys 2m14.705s

monitor (this patch):
real 4m50.791s
user 0m36.619s
sys 2m14.039s

src/shared/dissect-image.c

index 0e2fb9afbe6f2251e3a1e63ee6e0eb0106fdf4c5..4c2e41c8b8ee16b57d7cab7807b981d6f4273e56 100644 (file)
@@ -40,6 +40,7 @@
 #include "string-util.h"
 #include "strv.h"
 #include "tmpfile-util.h"
+#include "udev-util.h"
 #include "user-util.h"
 #include "xattr-util.h"
 
@@ -165,6 +166,10 @@ static int wait_for_partitions_to_appear(
                 if (device_is_mmc_special_partition(q))
                         continue;
 
+                r = device_wait_for_initialization(q, "block", NULL);
+                if (r < 0)
+                        return r;
+
                 n++;
         }
 
@@ -219,12 +224,17 @@ static int loop_wait_for_partitions_to_appear(
                 sd_device *d,
                 unsigned num_partitions,
                 sd_device_enumerator **ret_enumerator) {
+        _cleanup_(sd_device_unrefp) sd_device *device = NULL;
         int r;
 
         log_debug("Waiting for device (parent + %d partitions) to appear...", num_partitions);
 
+        r = device_wait_for_initialization(d, "block", &device);
+        if (r < 0)
+                return r;
+
         for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
-                r = wait_for_partitions_to_appear(fd, d, num_partitions, ret_enumerator);
+                r = wait_for_partitions_to_appear(fd, device, num_partitions, ret_enumerator);
                 if (r != -EAGAIN)
                         return r;
         }