dcavalca / rpms / util-linux

Forked from rpms/util-linux 2 years ago
Clone

Blame SOURCES/1001-losetup-avoid-infinite-busy-loop.patch

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