summaryrefslogtreecommitdiff
path: root/src/shared/loop-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-10-13 14:37:39 +0200
committerLennart Poettering <lennart@poettering.net>2020-10-22 14:58:28 +0200
commitb202ec20688cd0abe3f4b2e35cf6002c8bc45189 (patch)
tree60cbec38307f2eace1d88e6d5c6722484a462634 /src/shared/loop-util.c
parent786e3a52a24d0317d20d3c8839db59b7bad6d0b7 (diff)
downloadsystemd-b202ec20688cd0abe3f4b2e35cf6002c8bc45189.tar.gz
loop-util: wait a random time before trying again
Let's try to make collisions when multiple clients want to use the same device less likely, by sleeping a random time on collision. The loop device allocation protocol is inherently collision prone: first, a program asks which is the next free loop device, then it tries to acquire it, in a separate, unsynchronized setp. If many peers do this all at the same time, they'll likely all collide when trying to acquire the device, so that they need to ask for a free device again and again. Let's make this a little less prone to collisions, reducing the number of failing attempts: whenever we notice a collision we'll now wait short and randomized time, making it more likely another peer succeeds. (This also adds a similar logic when retrying LOOP_SET_STATUS64, but with a slightly altered calculation, since there we definitely want to wait a bit, under all cases)
Diffstat (limited to 'src/shared/loop-util.c')
-rw-r--r--src/shared/loop-util.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c
index 091a304755..1c92fdbf5f 100644
--- a/src/shared/loop-util.c
+++ b/src/shared/loop-util.c
@@ -24,6 +24,7 @@
#include "loop-util.h"
#include "missing_loop.h"
#include "parse-util.h"
+#include "random-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -248,7 +249,10 @@ static int loop_configure(
goto fail;
}
- (void) usleep(50 * USEC_PER_MSEC);
+ /* Sleep some random time, but at least 10ms, at most 250ms. Increase the delay the more
+ * failed attempts we see */
+ (void) usleep(UINT64_C(10) * USEC_PER_MSEC +
+ random_u64() % (UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
}
return 0;
@@ -414,6 +418,11 @@ int loop_device_make(
return -EBUSY;
loopdev = mfree(loopdev);
+
+ /* Wait some random time, to make collision less likely. Let's pick a random time in the
+ * range 0ms…250ms, linearly scaled by the number of failed attempts. */
+ (void) usleep(random_u64() % (UINT64_C(10) * USEC_PER_MSEC +
+ UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
}
d = new(LoopDevice, 1);