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/<maj:min>/ */
struct loop_info64 info; /* for GET/SET ioctl */
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;
}
*/
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;
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;
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;
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));