summaryrefslogtreecommitdiffstats
path: root/lib/loopdev.c
diff options
context:
space:
mode:
authorKarel Zak2014-01-24 13:58:40 +0100
committerKarel Zak2014-01-24 13:58:40 +0100
commit663bf040611240d164f2464b4d892ecd2b02fa6f (patch)
tree35dcd9192bb4ecd16e668d39fdcd1f61d71c3e75 /lib/loopdev.c
parentinclude/c.h: prefer nanosleep() over usleep() (diff)
downloadkernel-qcow2-util-linux-663bf040611240d164f2464b4d892ecd2b02fa6f.tar.gz
kernel-qcow2-util-linux-663bf040611240d164f2464b4d892ecd2b02fa6f.tar.xz
kernel-qcow2-util-linux-663bf040611240d164f2464b4d892ecd2b02fa6f.zip
losetup: wait for udev
On system with /dev/lop-control the udevd creates /dev/loopN nodes. It seems better to wait a moment after unsuccessful open(/dev/loopN) and try it to open again. The problem is pretty visible on systems where udevd also modifies permission for loopN devices, then open() fails with EACCES when losetup executed by non-root user (but user who is in "disk" group). Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1045432 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib/loopdev.c')
-rw-r--r--lib/loopdev.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/lib/loopdev.c b/lib/loopdev.c
index a636a89c8..5153eaa80 100644
--- a/lib/loopdev.c
+++ b/lib/loopdev.c
@@ -291,9 +291,8 @@ int loopcxt_get_fd(struct loopdev_cxt *lc)
if (lc->fd < 0) {
lc->mode = lc->flags & LOOPDEV_FL_RDWR ? O_RDWR : O_RDONLY;
lc->fd = open(lc->device, lc->mode | O_CLOEXEC);
- DBG(lc, loopdev_debug("open %s [%s]: %s", lc->device,
- lc->flags & LOOPDEV_FL_RDWR ? "rw" : "ro",
- lc->fd < 0 ? "failed" : "ok"));
+ DBG(lc, loopdev_debug("open %s [%s]: %m", lc->device,
+ lc->flags & LOOPDEV_FL_RDWR ? "rw" : "ro"));
}
return lc->fd;
}
@@ -1182,7 +1181,7 @@ static int loopcxt_check_size(struct loopdev_cxt *lc, int file_fd)
*/
int loopcxt_setup_device(struct loopdev_cxt *lc)
{
- int file_fd, dev_fd, mode = O_RDWR, rc = -1;
+ int file_fd, dev_fd, mode = O_RDWR, rc = -1, cnt = 0;
if (!lc || !*lc->device || !lc->filename)
return -EINVAL;
@@ -1222,7 +1221,19 @@ int loopcxt_setup_device(struct loopdev_cxt *lc)
lc->flags &= ~LOOPDEV_FL_RDONLY;
}
- dev_fd = loopcxt_get_fd(lc);
+ do {
+ errno = 0;
+ dev_fd = loopcxt_get_fd(lc);
+ if (dev_fd >= 0 || lc->control_ok == 0)
+ break;
+ if (errno != EACCES && errno != ENOENT)
+ break;
+ /* We have permissions to open /dev/loop-control, but open
+ * /dev/loopN failed with EACCES, it's probably because udevd
+ * does not applied chown yet. Let's wait a moment. */
+ xusleep(25000);
+ } while (cnt++ < 16);
+
if (dev_fd < 0) {
rc = -errno;
goto err;
@@ -1328,6 +1339,7 @@ int loopcxt_add_device(struct loopdev_cxt *lc)
rc = ioctl(ctl, LOOP_CTL_ADD, nr);
close(ctl);
}
+ lc->control_ok = rc >= 0 ? 1 : 0;
done:
DBG(lc, loopdev_debug("add_device done [rc=%d]", rc));
return rc;
@@ -1356,6 +1368,7 @@ int loopcxt_find_unused(struct loopdev_cxt *lc)
rc = loopiter_set_device(lc, name);
}
+ lc->control_ok = ctl >= 0 && rc == 0 ? 1 : 0;
if (ctl >= 0)
close(ctl);
DBG(lc, loopdev_debug("find_unused by loop-control [rc=%d]", rc));