Karel Zak 0f3035
From a24905f03e90fb2f418bd5b8816378a99bb535b2 Mon Sep 17 00:00:00 2001
Karel Zak 0f3035
From: Karel Zak <kzak@redhat.com>
Karel Zak 0f3035
Date: Tue, 1 Mar 2022 12:07:07 +0100
Karel Zak 0f3035
Subject: loopdev: add retries on EAGAIN
Karel Zak 0f3035
Karel Zak 0f3035
* add limit to number of attempts for LOOP_SET_STATUS64
Karel Zak 0f3035
Karel Zak 0f3035
* use the same for LOOP_SET_BLOCK_SIZE ioctl
Karel Zak 0f3035
Karel Zak 0f3035
Addresses: https://github.com/util-linux/util-linux/issues/1582
Karel Zak 0f3035
Signed-off-by: Karel Zak <kzak@redhat.com>
Karel Zak 0f3035
---
Karel Zak 0f3035
 lib/loopdev.c | 32 +++++++++++++++++++++++---------
Karel Zak 0f3035
 1 file changed, 23 insertions(+), 9 deletions(-)
Karel Zak 0f3035
Karel Zak 0f3035
diff --git a/lib/loopdev.c b/lib/loopdev.c
Karel Zak 0f3035
index 511f8a0d6..e8ccf6ae6 100644
Karel Zak 0f3035
--- a/lib/loopdev.c
Karel Zak 0f3035
+++ b/lib/loopdev.c
Karel Zak 0f3035
@@ -43,6 +43,9 @@
Karel Zak 0f3035
 #include "debug.h"
Karel Zak 0f3035
 #include "fileutils.h"
Karel Zak 0f3035
 
Karel Zak 0f3035
+
Karel Zak 0f3035
+#define LOOPDEV_MAX_TRIES	10
Karel Zak 0f3035
+
Karel Zak 0f3035
 /*
Karel Zak 0f3035
  * Debug stuff (based on include/debug.h)
Karel Zak 0f3035
  */
Karel Zak 0f3035
@@ -1450,7 +1453,7 @@ err:
Karel Zak 0f3035
  */
Karel Zak 0f3035
 int loopcxt_ioctl_status(struct loopdev_cxt *lc)
Karel Zak 0f3035
 {
Karel Zak 0f3035
-	int dev_fd, rc = -1, err, again;
Karel Zak 0f3035
+	int dev_fd, rc = -1, err, again, tries = 0;
Karel Zak 0f3035
 
Karel Zak 0f3035
 	errno = 0;
Karel Zak 0f3035
 	dev_fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
@@ -1464,9 +1467,12 @@ int loopcxt_ioctl_status(struct loopdev_cxt *lc)
Karel Zak 0f3035
 	do {
Karel Zak 0f3035
 		err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->config.info);
Karel Zak 0f3035
 		again = err && errno == EAGAIN;
Karel Zak 0f3035
-		if (again)
Karel Zak 0f3035
+		if (again) {
Karel Zak 0f3035
 			xusleep(250000);
Karel Zak 0f3035
-	} while (again);
Karel Zak 0f3035
+			tries++;
Karel Zak 0f3035
+		}
Karel Zak 0f3035
+	} while (again && tries <= LOOPDEV_MAX_TRIES);
Karel Zak 0f3035
+
Karel Zak 0f3035
 	if (err) {
Karel Zak 0f3035
 		rc = -errno;
Karel Zak 0f3035
 		DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64 failed: %m"));
Karel Zak 0f3035
@@ -1520,16 +1526,24 @@ int loopcxt_ioctl_dio(struct loopdev_cxt *lc, unsigned long use_dio)
Karel Zak 0f3035
 int loopcxt_ioctl_blocksize(struct loopdev_cxt *lc, uint64_t blocksize)
Karel Zak 0f3035
 {
Karel Zak 0f3035
 	int fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
+	int err, again, tries = 0;
Karel Zak 0f3035
 
Karel Zak 0f3035
 	if (fd < 0)
Karel Zak 0f3035
 		return -EINVAL;
Karel Zak 0f3035
 
Karel Zak 0f3035
-	/* Kernels prior to v4.14 don't support this ioctl */
Karel Zak 0f3035
-	if (ioctl(fd, LOOP_SET_BLOCK_SIZE, (unsigned long) blocksize) < 0) {
Karel Zak 0f3035
-		int rc = -errno;
Karel Zak 0f3035
-		DBG(CXT, ul_debugobj(lc, "LOOP_SET_BLOCK_SIZE failed: %m"));
Karel Zak 0f3035
-		return rc;
Karel Zak 0f3035
-	}
Karel Zak 0f3035
+	do {
Karel Zak 0f3035
+		/* Kernels prior to v4.14 don't support this ioctl */
Karel Zak 0f3035
+		err = ioctl(fd, LOOP_SET_BLOCK_SIZE, (unsigned long) blocksize);
Karel Zak 0f3035
+		again = err && errno == EAGAIN;
Karel Zak 0f3035
+		if (again) {
Karel Zak 0f3035
+			xusleep(250000);
Karel Zak 0f3035
+			tries++;
Karel Zak 0f3035
+		} else if (err) {
Karel Zak 0f3035
+			int rc = -errno;
Karel Zak 0f3035
+			DBG(CXT, ul_debugobj(lc, "LOOP_SET_BLOCK_SIZE failed: %m"));
Karel Zak 0f3035
+			return rc;
Karel Zak 0f3035
+		}
Karel Zak 0f3035
+	} while (again && tries <= LOOPDEV_MAX_TRIES);
Karel Zak 0f3035
 
Karel Zak 0f3035
 	DBG(CXT, ul_debugobj(lc, "logical block size set"));
Karel Zak 0f3035
 	return 0;
Karel Zak 0f3035
-- 
Karel Zak 0f3035
2.37.1
Karel Zak 0f3035