]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/loop-util: use longer delay when waiting for loop device
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 29 May 2023 22:20:30 +0000 (00:20 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 30 May 2023 11:41:56 +0000 (13:41 +0200)
The kernel may be syncing a file system or doing something else that requires
more time. So make the delay a bit longer, but provide some feedback and also
grow the delay exponentially (though with a long exponent). If the kernel is
doing something else, no need to repeat so often. With 38 attempts, we get a
total of slightly above 5000 ms.

I wrote this when I thought that the the delay is not long enough. It turned
out that we were blocking the file system on the loop device, so waiting longer
wasn't helpful. But I think it's nicer to do it this way anyway.

src/shared/loop-util.c

index a85cff09142b2dcdbd758c8b02f3283a6d5c89d8..5418871093def6ebff8088a6b5fb5e58d8409c01 100644 (file)
@@ -817,16 +817,24 @@ static LoopDevice* loop_device_free(LoopDevice *d) {
         }
 
         /* Now that the block device is released, let's also try to remove it */
-        if (control >= 0)
-                for (unsigned n_attempts = 0;;) {
+        if (control >= 0) {
+                useconds_t delay = 5 * USEC_PER_MSEC;
+
+                for (unsigned attempt = 1;; attempt++) {
                         if (ioctl(control, LOOP_CTL_REMOVE, d->nr) >= 0)
                                 break;
-                        if (errno != EBUSY || ++n_attempts >= 64) {
+                        if (errno != EBUSY || attempt > 38) {
                                 log_debug_errno(errno, "Failed to remove device %s: %m", strna(d->node));
                                 break;
                         }
-                        (void) usleep(50 * USEC_PER_MSEC);
+                        if (attempt % 5 == 0) {
+                                log_debug("Device is still busy after %u attempts…", attempt);
+                                delay *= 2;
+                        }
+
+                        (void) usleep(delay);
                 }
+        }
 
         free(d->node);
         sd_device_unref(d->dev);