loop-util: take a LOCK_EX BSD file lock on control device while we acquire a loopback device

This commit is contained in:
Lennart Poettering
2022-04-07 18:55:58 +02:00
parent da9ae8ea6c
commit cc53046620
+16
View File
@@ -514,6 +514,17 @@ static int loop_device_make_internal(
for (unsigned n_attempts = 0;;) {
_cleanup_close_ int loop = -1;
/* Let's take a lock on the control device first. On a busy system, where many programs
* attempt to allocate a loopback device at the same time, we might otherwise keep looping
* around relatively heavy operations: asking for a free loopback device, then opening it,
* validating it, attaching something to it. Let's serialize this whole operation, to make
* unnecessary busywork less likely. Note that this is just something we do to optimize our
* own code (and whoever else decides to use LOCK_EX locks for this), taking this lock is not
* necessary, it just means it's less likely we have to iterate through this loop again and
* again if our own code races against our own code. */
if (flock(control, LOCK_EX) < 0)
return -errno;
nr = ioctl(control, LOOP_CTL_GET_FREE);
if (nr < 0)
return -errno;
@@ -542,6 +553,11 @@ static int loop_device_make_internal(
return r;
}
/* OK, this didn't work, let's try again a bit later, but first release the lock on the
* control device */
if (flock(control, LOCK_UN) < 0)
return -errno;
if (++n_attempts >= 64) /* Give up eventually */
return -EBUSY;