From: Karel Zak Date: Fri, 24 Jan 2014 12:58:40 +0000 (+0100) Subject: losetup: wait for udev X-Git-Tag: v2.25-rc1~624 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=663bf040611240d164f2464b4d892ecd2b02fa6f;p=thirdparty%2Futil-linux.git 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 --- diff --git a/include/loopdev.h b/include/loopdev.h index eb328a080d..793539935f 100644 --- a/include/loopdev.h +++ b/include/loopdev.h @@ -99,6 +99,7 @@ struct loopdev_cxt { unsigned int extra_check:1; /* unusual stuff for iterator */ unsigned int debug:1; /* debug mode ON/OFF */ unsigned int info_failed:1; /* LOOP_GET_STATUS ioctl failed */ + unsigned int control_ok:1; /* /dev/loop-control success */ struct sysfs_cxt sysfs; /* pointer to /sys/dev/block// */ struct loop_info64 info; /* for GET/SET ioctl */ diff --git a/lib/loopdev.c b/lib/loopdev.c index a636a89c8d..5153eaa802 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));