lc->has_info = 0;
lc->info_failed = 0;
*lc->device = '\0';
- memset(&lc->info, 0, sizeof(lc->info));
+ memset(&lc->config, 0, sizeof(lc->config));
/* set new */
if (device) {
}
errno = 0;
if (lc->has_info)
- return &lc->info;
+ return &lc->config.info;
fd = loopcxt_get_fd(lc);
if (fd < 0)
return NULL;
- if (ioctl(fd, LOOP_GET_STATUS64, &lc->info) == 0) {
+ if (ioctl(fd, LOOP_GET_STATUS64, &lc->config.info) == 0) {
lc->has_info = 1;
lc->info_failed = 0;
DBG(CXT, ul_debugobj(lc, "reading loop_info64 OK"));
- return &lc->info;
+ return &lc->config.info;
}
lc->info_failed = 1;
{
if (!lc)
return -EINVAL;
- lc->info.lo_offset = offset;
+ lc->config.info.lo_offset = offset;
DBG(CXT, ul_debugobj(lc, "set offset=%jd", offset));
return 0;
{
if (!lc)
return -EINVAL;
- lc->info.lo_sizelimit = sizelimit;
+ lc->config.info.lo_sizelimit = sizelimit;
DBG(CXT, ul_debugobj(lc, "set sizelimit=%jd", sizelimit));
return 0;
{
if (!lc)
return -EINVAL;
- lc->info.lo_flags = flags;
+ lc->config.info.lo_flags = flags;
DBG(CXT, ul_debugobj(lc, "set flags=%u", (unsigned) flags));
return 0;
if (!lc->filename)
return -errno;
- xstrncpy((char *)lc->info.lo_file_name, lc->filename, LO_NAME_SIZE);
+ xstrncpy((char *)lc->config.info.lo_file_name, lc->filename, LO_NAME_SIZE);
- DBG(CXT, ul_debugobj(lc, "set backing file=%s", lc->info.lo_file_name));
+ DBG(CXT, ul_debugobj(lc, "set backing file=%s", lc->config.info.lo_file_name));
return 0;
}
int dev_fd;
struct stat st;
- if (!lc->info.lo_offset && !lc->info.lo_sizelimit)
+ if (!lc->config.info.lo_offset && !lc->config.info.lo_sizelimit)
return 0;
if (fstat(file_fd, &st)) {
} else
expected_size = st.st_size;
- if (expected_size == 0 || expected_size <= lc->info.lo_offset) {
+ if (expected_size == 0 || expected_size <= lc->config.info.lo_offset) {
DBG(CXT, ul_debugobj(lc, "failed to determine expected size"));
return 0; /* ignore this error */
}
- if (lc->info.lo_offset > 0)
- expected_size -= lc->info.lo_offset;
+ if (lc->config.info.lo_offset > 0)
+ expected_size -= lc->config.info.lo_offset;
- if (lc->info.lo_sizelimit > 0 && lc->info.lo_sizelimit < expected_size)
- expected_size = lc->info.lo_sizelimit;
+ if (lc->config.info.lo_sizelimit > 0 && lc->config.info.lo_sizelimit < expected_size)
+ expected_size = lc->config.info.lo_sizelimit;
dev_fd = loopcxt_get_fd(lc);
if (dev_fd < 0) {
{
int file_fd, dev_fd, mode = O_RDWR, rc = -1, cnt = 0, err, again;
int errsv = 0;
+ int fallback = 0;
if (!lc || !*lc->device || !lc->filename)
return -EINVAL;
/*
* Open backing file and device
*/
- if (lc->info.lo_flags & LO_FLAGS_READ_ONLY)
+ if (lc->config.info.lo_flags & LO_FLAGS_READ_ONLY)
mode = O_RDONLY;
if ((file_fd = open(lc->filename, mode | O_CLOEXEC)) < 0) {
if (mode == O_RDONLY) {
lc->flags |= LOOPDEV_FL_RDONLY; /* open() mode */
- lc->info.lo_flags |= LO_FLAGS_READ_ONLY; /* kernel loopdev mode */
+ lc->config.info.lo_flags |= LO_FLAGS_READ_ONLY; /* kernel loopdev mode */
} else {
lc->flags |= LOOPDEV_FL_RDWR; /* open() mode */
- lc->info.lo_flags &= ~LO_FLAGS_READ_ONLY;
+ lc->config.info.lo_flags &= ~LO_FLAGS_READ_ONLY;
lc->flags &= ~LOOPDEV_FL_RDONLY;
}
DBG(SETUP, ul_debugobj(lc, "device open: OK"));
- /*
- * Set FD
- */
- if (ioctl(dev_fd, LOOP_SET_FD, file_fd) < 0) {
+ lc->config.fd = file_fd;
+ if (ioctl(dev_fd, LOOP_CONFIGURE, &lc->config) < 0) {
rc = -errno;
errsv = errno;
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_FD failed: %m"));
- goto err;
+ if (errno != EINVAL)
+ {
+ DBG(SETUP, ul_debugobj(lc, "LOOP_CONFIGURE failed: %m"));
+ goto err;
+ }
+ fallback = 1;
}
+ else
+ {
+ if (lc->blocksize > 0
+ && (rc = loopcxt_ioctl_blocksize(lc, lc->blocksize)) < 0) {
+ errsv = -rc;
+ goto err;
+ }
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_FD: OK"));
-
- if (lc->blocksize > 0
- && (rc = loopcxt_ioctl_blocksize(lc, lc->blocksize)) < 0) {
- errsv = -rc;
- goto err;
+ DBG(SETUP, ul_debugobj(lc, "LOOP_CONFIGURE: OK"));
}
- do {
- err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info);
- again = err && errno == EAGAIN;
- if (again)
- xusleep(250000);
- } while (again);
- if (err) {
- rc = -errno;
- errsv = errno;
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64 failed: %m"));
- goto err;
- }
+ if (fallback) {
+ /*
+ * Set FD
+ */
+ if (ioctl(dev_fd, LOOP_SET_FD, file_fd) < 0) {
+ rc = -errno;
+ errsv = errno;
+ DBG(SETUP, ul_debugobj(lc, "LOOP_SET_FD failed: %m"));
+ goto err;
+ }
- DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64: OK"));
+ DBG(SETUP, ul_debugobj(lc, "LOOP_SET_FD: OK"));
+
+ if (lc->blocksize > 0
+ && (rc = loopcxt_ioctl_blocksize(lc, lc->blocksize)) < 0) {
+ errsv = -rc;
+ goto err;
+ }
+
+ do {
+ err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->config.info);
+ again = err && errno == EAGAIN;
+ if (again)
+ xusleep(250000);
+ } while (again);
+ if (err) {
+ rc = -errno;
+ errsv = errno;
+ DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64 failed: %m"));
+ goto err;
+ }
+
+ DBG(SETUP, ul_debugobj(lc, "LOOP_SET_STATUS64: OK"));
+ }
if ((rc = loopcxt_check_size(lc, file_fd)))
goto err;
close(file_fd);
- memset(&lc->info, 0, sizeof(lc->info));
+ memset(&lc->config, 0, sizeof(lc->config));
lc->has_info = 0;
lc->info_failed = 0;
DBG(SETUP, ul_debugobj(lc, "device open: OK"));
do {
- err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info);
+ err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->config.info);
again = err && errno == EAGAIN;
if (again)
xusleep(250000);