Blob Blame History Raw
diff -Naur a/sys-utils/losetup.8 b/sys-utils/losetup.8
--- a/sys-utils/losetup.8	2021-10-20 15:23:28.983136437 -0700
+++ b/sys-utils/losetup.8	2021-10-20 15:23:54.314264432 -0700
@@ -68,6 +68,13 @@
 file.
 .B This setup may be dangerous, can cause data loss, corruption and overwrites.
 Use \fB\-\-nooverlap\fR with \fB\-\-find\fR during setup to avoid this problem.
+.sp
+The loop device setup is not an atomic operation when used with \fB\-\-find\fP, and
+.B losetup
+does not protect this operation by any lock.  The number of attempts is
+internally restricted to a maximum of 16.  It is recommended to use for example
+.BR flock (1)
+to avoid a collision in heavily parallel use cases.
 
 .SH OPTIONS
 The \fIsize\fR and \fIoffset\fR
@@ -170,6 +177,11 @@
 displays the status of a loop device, it returns 1 if the device
 is not configured and 2 if an error occurred which prevented
 determining the status of the device.
+.SH NOTES
+Since version 2.37
+.B losetup
+uses LOOP_CONFIGURE ioctl to setup a new loop device by one ioctl call.  The
+old versions use LOOP_SET_FD and LOOP_SET_STATUS64 ioctls to do the same.
 
 .SH FILES
 .TP
diff -Naur a/sys-utils/losetup.c b/sys-utils/losetup.c
--- a/sys-utils/losetup.c	2021-10-20 15:23:28.902136028 -0700
+++ b/sys-utils/losetup.c	2021-10-20 15:23:54.315264437 -0700
@@ -463,7 +463,7 @@
 		       const char *file, uint64_t offset, uint64_t sizelimit)
 {
 	int hasdev = loopcxt_has_device(lc);
-	int rc = 0;
+	int rc = 0, ntries = 0;
 
 	/* losetup --find --noverlap file.img */
 	if (!hasdev && nooverlap) {
@@ -556,8 +556,12 @@
 		rc = loopcxt_setup_device(lc);
 		if (rc == 0)
 			break;			/* success */
-		if (errno == EBUSY && !hasdev)
+
+		if (errno == EBUSY && !hasdev && ntries < 16) {
+			xusleep(200000);
+			ntries++;
 			continue;
+		}
 
 		/* errors */
 		errpre = hasdev && loopcxt_get_fd(lc) < 0 ?