Blame 0040-lib-loopdev-consolidate-ioctls-calls-on-EAGAIN.patch

Karel Zak 0f3035
From 53b543476d271cce71c4f5b66d9d6a28f1a75370 Mon Sep 17 00:00:00 2001
Karel Zak 0f3035
From: Karel Zak <kzak@redhat.com>
Karel Zak 0f3035
Date: Wed, 9 Mar 2022 11:28:07 +0100
Karel Zak 0f3035
Subject: lib/loopdev: consolidate ioctls calls on EAGAIN
Karel Zak 0f3035
Karel Zak 0f3035
Keep all logic to repeat ioctl calls in one macro rather than
Karel Zak 0f3035
duplicate code.
Karel Zak 0f3035
Karel Zak 0f3035
Addresses: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=2117203
Karel Zak 0f3035
Signed-off-by: Karel Zak <kzak@redhat.com>
Karel Zak 0f3035
---
Karel Zak 0f3035
 lib/loopdev.c | 97 ++++++++++++++++++++++++++++-----------------------
Karel Zak 0f3035
 1 file changed, 54 insertions(+), 43 deletions(-)
Karel Zak 0f3035
Karel Zak 0f3035
diff --git a/lib/loopdev.c b/lib/loopdev.c
Karel Zak 0f3035
index fda0e1210..cceab2db1 100644
Karel Zak 0f3035
--- a/lib/loopdev.c
Karel Zak 0f3035
+++ b/lib/loopdev.c
Karel Zak 0f3035
@@ -43,7 +43,6 @@
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
@@ -77,6 +76,24 @@ static void loopdev_init_debug(void)
Karel Zak 0f3035
 #define loopcxt_sysfs_available(_lc)	(!((_lc)->flags & LOOPDEV_FL_NOSYSFS)) \
Karel Zak 0f3035
 					 && !loopcxt_ioctl_enabled(_lc)
Karel Zak 0f3035
 
Karel Zak 0f3035
+/*
Karel Zak 0f3035
+ * Calls @x and repeat on EAGAIN
Karel Zak 0f3035
+ */
Karel Zak 0f3035
+#define repeat_on_eagain(x) __extension__ ({			\
Karel Zak 0f3035
+		int _c = 0, _e;					\
Karel Zak 0f3035
+		do {						\
Karel Zak 0f3035
+			errno = 0;				\
Karel Zak 0f3035
+			_e = x;					\
Karel Zak 0f3035
+			if (_e == 0 || errno != EAGAIN)		\
Karel Zak 0f3035
+				break;				\
Karel Zak 0f3035
+			if (_c >= LOOPDEV_MAX_TRIES)		\
Karel Zak 0f3035
+				break;				\
Karel Zak 0f3035
+			xusleep(250000);			\
Karel Zak 0f3035
+			_c++;					\
Karel Zak 0f3035
+		} while (1);					\
Karel Zak 0f3035
+		_e == 0 ? 0 : errno ? -errno : -1;		\
Karel Zak 0f3035
+	})
Karel Zak 0f3035
+
Karel Zak 0f3035
 /*
Karel Zak 0f3035
  * @lc: context
Karel Zak 0f3035
  * @device: device name, absolute device path or NULL to reset the current setting
Karel Zak 0f3035
@@ -1276,6 +1293,7 @@ static int loopcxt_check_size(struct loopdev_cxt *lc, int file_fd)
Karel Zak 0f3035
 	return 0;
Karel Zak 0f3035
 }
Karel Zak 0f3035
 
Karel Zak 0f3035
+
Karel Zak 0f3035
 /*
Karel Zak 0f3035
  * @lc: context
Karel Zak 0f3035
  *
Karel Zak 0f3035
@@ -1364,8 +1382,9 @@ int loopcxt_setup_device(struct loopdev_cxt *lc)
Karel Zak 0f3035
 	 * -- since Linux v5.8-rc1, commit 3448914e8cc550ba792d4ccc74471d1ca4293aae
Karel Zak 0f3035
 	 */
Karel Zak 0f3035
 	lc->config.fd = file_fd;
Karel Zak 0f3035
-	if (ioctl(dev_fd, LOOP_CONFIGURE, &lc->config) < 0) {
Karel Zak 0f3035
-		rc = -errno;
Karel Zak 0f3035
+
Karel Zak 0f3035
+	rc = repeat_on_eagain( ioctl(dev_fd, LOOP_CONFIGURE, &lc->config) );
Karel Zak 0f3035
+	if (rc != 0) {
Karel Zak 0f3035
 		errsv = errno;
Karel Zak 0f3035
 		if (errno != EINVAL && errno != ENOTTY) {
Karel Zak 0f3035
 			DBG(SETUP, ul_debugobj(lc, "LOOP_CONFIGURE failed: %m"));
Karel Zak 0f3035
@@ -1430,6 +1449,7 @@ err:
Karel Zak 0f3035
 	return rc;
Karel Zak 0f3035
 }
Karel Zak 0f3035
 
Karel Zak 0f3035
+
Karel Zak 0f3035
 /*
Karel Zak 0f3035
  * @lc: context
Karel Zak 0f3035
  *
Karel Zak 0f3035
@@ -1443,28 +1463,18 @@ 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, tries = 0;
Karel Zak 0f3035
+	int dev_fd, rc;
Karel Zak 0f3035
 
Karel Zak 0f3035
 	errno = 0;
Karel Zak 0f3035
 	dev_fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
 
Karel Zak 0f3035
-	if (dev_fd < 0) {
Karel Zak 0f3035
-		rc = -errno;
Karel Zak 0f3035
-		return rc;
Karel Zak 0f3035
-	}
Karel Zak 0f3035
-	DBG(SETUP, ul_debugobj(lc, "device open: OK"));
Karel Zak 0f3035
+	if (dev_fd < 0)
Karel Zak 0f3035
+		return -errno;
Karel Zak 0f3035
 
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
-			xusleep(250000);
Karel Zak 0f3035
-			tries++;
Karel Zak 0f3035
-		}
Karel Zak 0f3035
-	} while (again && tries <= LOOPDEV_MAX_TRIES);
Karel Zak 0f3035
+	DBG(SETUP, ul_debugobj(lc, "calling LOOP_SET_STATUS64"));
Karel Zak 0f3035
 
Karel Zak 0f3035
-	if (err) {
Karel Zak 0f3035
-		rc = -errno;
Karel Zak 0f3035
+	rc = repeat_on_eagain( ioctl(dev_fd, LOOP_SET_STATUS64, &lc->config.info) );
Karel Zak 0f3035
+	if (rc != 0) {
Karel Zak 0f3035
 		DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64 failed: %m"));
Karel Zak 0f3035
 		return rc;
Karel Zak 0f3035
 	}
Karel Zak 0f3035
@@ -1475,14 +1485,16 @@ int loopcxt_ioctl_status(struct loopdev_cxt *lc)
Karel Zak 0f3035
 
Karel Zak 0f3035
 int loopcxt_ioctl_capacity(struct loopdev_cxt *lc)
Karel Zak 0f3035
 {
Karel Zak 0f3035
-	int fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
+	int rc, fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
 
Karel Zak 0f3035
 	if (fd < 0)
Karel Zak 0f3035
 		return -EINVAL;
Karel Zak 0f3035
 
Karel Zak 0f3035
+	DBG(SETUP, ul_debugobj(lc, "calling LOOP_SET_CAPACITY"));
Karel Zak 0f3035
+
Karel Zak 0f3035
 	/* Kernels prior to v2.6.30 don't support this ioctl */
Karel Zak 0f3035
-	if (ioctl(fd, LOOP_SET_CAPACITY, 0) < 0) {
Karel Zak 0f3035
-		int rc = -errno;
Karel Zak 0f3035
+	rc = repeat_on_eagain( ioctl(fd, LOOP_SET_CAPACITY, 0) );
Karel Zak 0f3035
+	if (rc != 0) {
Karel Zak 0f3035
 		DBG(CXT, ul_debugobj(lc, "LOOP_SET_CAPACITY failed: %m"));
Karel Zak 0f3035
 		return rc;
Karel Zak 0f3035
 	}
Karel Zak 0f3035
@@ -1493,14 +1505,16 @@ int loopcxt_ioctl_capacity(struct loopdev_cxt *lc)
Karel Zak 0f3035
 
Karel Zak 0f3035
 int loopcxt_ioctl_dio(struct loopdev_cxt *lc, unsigned long use_dio)
Karel Zak 0f3035
 {
Karel Zak 0f3035
-	int fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
+	int rc, fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
 
Karel Zak 0f3035
 	if (fd < 0)
Karel Zak 0f3035
 		return -EINVAL;
Karel Zak 0f3035
 
Karel Zak 0f3035
+	DBG(SETUP, ul_debugobj(lc, "calling LOOP_SET_DIRECT_IO"));
Karel Zak 0f3035
+
Karel Zak 0f3035
 	/* Kernels prior to v4.4 don't support this ioctl */
Karel Zak 0f3035
-	if (ioctl(fd, LOOP_SET_DIRECT_IO, use_dio) < 0) {
Karel Zak 0f3035
-		int rc = -errno;
Karel Zak 0f3035
+	rc = repeat_on_eagain( ioctl(fd, LOOP_SET_DIRECT_IO, use_dio) );
Karel Zak 0f3035
+	if (rc != 0) {
Karel Zak 0f3035
 		DBG(CXT, ul_debugobj(lc, "LOOP_SET_DIRECT_IO failed: %m"));
Karel Zak 0f3035
 		return rc;
Karel Zak 0f3035
 	}
Karel Zak 0f3035
@@ -1515,25 +1529,19 @@ int loopcxt_ioctl_dio(struct loopdev_cxt *lc, unsigned long use_dio)
Karel Zak 0f3035
  */
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
+	int rc, fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
 
Karel Zak 0f3035
 	if (fd < 0)
Karel Zak 0f3035
 		return -EINVAL;
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
+	DBG(SETUP, ul_debugobj(lc, "calling LOOP_SET_BLOCK_SIZE"));
Karel Zak 0f3035
+
Karel Zak 0f3035
+	rc = repeat_on_eagain(
Karel Zak 0f3035
+		ioctl(fd, LOOP_SET_BLOCK_SIZE, (unsigned long) blocksize) );
Karel Zak 0f3035
+	if (rc != 0) {
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
 
Karel Zak 0f3035
 	DBG(CXT, ul_debugobj(lc, "logical block size set"));
Karel Zak 0f3035
 	return 0;
Karel Zak 0f3035
@@ -1541,14 +1549,17 @@ int loopcxt_ioctl_blocksize(struct loopdev_cxt *lc, uint64_t blocksize)
Karel Zak 0f3035
 
Karel Zak 0f3035
 int loopcxt_delete_device(struct loopdev_cxt *lc)
Karel Zak 0f3035
 {
Karel Zak 0f3035
-	int fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
+	int rc, fd = loopcxt_get_fd(lc);
Karel Zak 0f3035
 
Karel Zak 0f3035
 	if (fd < 0)
Karel Zak 0f3035
 		return -EINVAL;
Karel Zak 0f3035
 
Karel Zak 0f3035
-	if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
Karel Zak 0f3035
+	DBG(SETUP, ul_debugobj(lc, "calling LOOP_SET_CLR_FD"));
Karel Zak 0f3035
+
Karel Zak 0f3035
+	rc = repeat_on_eagain( ioctl(fd, LOOP_CLR_FD, 0) );
Karel Zak 0f3035
+	if (rc != 0) {
Karel Zak 0f3035
 		DBG(CXT, ul_debugobj(lc, "LOOP_CLR_FD failed: %m"));
Karel Zak 0f3035
-		return -errno;
Karel Zak 0f3035
+		return rc;
Karel Zak 0f3035
 	}
Karel Zak 0f3035
 
Karel Zak 0f3035
 	DBG(CXT, ul_debugobj(lc, "device removed"));
Karel Zak 0f3035
-- 
Karel Zak 0f3035
2.37.1
Karel Zak 0f3035