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