From a8040b6d0ad43e5cb7168fd3b739c8c68aaa61b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 13 Dec 2018 16:39:05 +0100 Subject: [PATCH] dissect-image: wait for the main device and all partitions to be known by udev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 0e2fb9afbe..4c2e41c8b8 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -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; }