From 97a5abd36eeab4e07a31b27f6a2c2078d42e2e33 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 8 Mar 2022 11:40:58 +0100 Subject: lib/loopdev: retry LOOP_SET_STATUS64 and LOOP_SET_BLOCK_SIZE on EAGAIN Upstream: http://github.com/util-linux/util-linux/commit/0ae7bb11c29aa11c8ef25b1ef2f82ee4701b856d Upstream: http://github.com/util-linux/util-linux/commit/eab90ef8d4f66394285e0cff1dfc0a27242c05aa Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=2058176 Signed-off-by: Karel Zak --- lib/loopdev.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/lib/loopdev.c b/lib/loopdev.c index 54d337ea3..48af82aef 100644 --- a/lib/loopdev.c +++ b/lib/loopdev.c @@ -42,6 +42,8 @@ #include "blkdev.h" #include "debug.h" +#define LOOPDEV_MAX_TRIES 10 + /* * Debug stuff (based on include/debug.h) */ @@ -1260,6 +1262,7 @@ int loopcxt_setup_device(struct loopdev_cxt *lc) { int file_fd, dev_fd, mode = O_RDWR, rc = -1, cnt = 0; int errsv = 0; + int err, again; if (!lc || !*lc->device || !lc->filename) return -EINVAL; @@ -1331,7 +1334,17 @@ int loopcxt_setup_device(struct loopdev_cxt *lc) DBG(SETUP, ul_debugobj(lc, "LOOP_SET_FD: OK")); - if (ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info)) { + cnt = 0; + do { + err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info); + again = err && errno == EAGAIN; + if (again) { + xusleep(250000); + cnt++; + } + } while (again && cnt <= LOOPDEV_MAX_TRIES); + + if (err) { rc = -errno; errsv = errno; DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64 failed: %m")); @@ -1376,7 +1389,7 @@ err: */ int loopcxt_set_status(struct loopdev_cxt *lc) { - int dev_fd, rc = -1; + int dev_fd, rc = -1, err, again, tries = 0; errno = 0; dev_fd = loopcxt_get_fd(lc); @@ -1387,7 +1400,16 @@ int loopcxt_set_status(struct loopdev_cxt *lc) } DBG(SETUP, ul_debugobj(lc, "device open: OK")); - if (ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info)) { + do { + err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info); + again = err && errno == EAGAIN; + if (again) { + xusleep(250000); + tries++; + } + } while (again && tries <= LOOPDEV_MAX_TRIES); + + if (err) { rc = -errno; DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64 failed: %m")); return rc; @@ -1440,12 +1462,22 @@ int loopcxt_set_dio(struct loopdev_cxt *lc, unsigned long use_dio) int loopcxt_set_blocksize(struct loopdev_cxt *lc, uint64_t blocksize) { int fd = loopcxt_get_fd(lc); + int err, again, tries = 0; if (fd < 0) return -EINVAL; - /* Kernels prior to v4.14 don't support this ioctl */ - if (ioctl(fd, LOOP_SET_BLOCK_SIZE, (unsigned long) blocksize) < 0) { + 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++; + } + } while (again && tries <= LOOPDEV_MAX_TRIES); + + if (err) { int rc = -errno; DBG(CXT, ul_debugobj(lc, "LOOP_SET_BLOCK_SIZE failed: %m")); return rc; -- 2.34.1