diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-10-13 14:37:39 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2020-10-22 14:58:28 +0200 |
commit | b202ec20688cd0abe3f4b2e35cf6002c8bc45189 (patch) | |
tree | 60cbec38307f2eace1d88e6d5c6722484a462634 /src/shared/loop-util.c | |
parent | 786e3a52a24d0317d20d3c8839db59b7bad6d0b7 (diff) | |
download | systemd-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.c | 11 |
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); |