mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
Move loop device setup code into virfile.{c,h}
While it is not currently used elsewhere in libvirt, the code for finding a free loop device & associating a file with it is not LXC specific. Move it into the viffile.{c,h} file where potentially shared code is more commonly kept. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
f547e8768d
commit
9612e4b2e7
@ -1243,6 +1243,7 @@ virDomainListSnapshots;
|
||||
|
||||
|
||||
# virfile.h
|
||||
virFileLoopDeviceAssociate;
|
||||
virFileClose;
|
||||
virFileDirectFdFlag;
|
||||
virFileWrapperFdClose;
|
||||
|
@ -39,8 +39,6 @@
|
||||
#include <getopt.h>
|
||||
#include <sys/mount.h>
|
||||
#include <locale.h>
|
||||
#include <linux/loop.h>
|
||||
#include <dirent.h>
|
||||
#include <grp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
@ -337,108 +335,14 @@ static int virLXCControllerValidateConsoles(virLXCControllerPtr ctrl)
|
||||
}
|
||||
|
||||
|
||||
static int lxcGetLoopFD(char **dev_name)
|
||||
static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs)
|
||||
{
|
||||
int fd = -1;
|
||||
DIR *dh = NULL;
|
||||
struct dirent *de;
|
||||
char *looppath;
|
||||
struct loop_info64 lo;
|
||||
|
||||
VIR_DEBUG("Looking for loop devices in /dev");
|
||||
|
||||
if (!(dh = opendir("/dev"))) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to read /dev"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while ((de = readdir(dh)) != NULL) {
|
||||
if (!STRPREFIX(de->d_name, "loop"))
|
||||
continue;
|
||||
|
||||
if (virAsprintf(&looppath, "/dev/%s", de->d_name) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Checking up on device %s", looppath);
|
||||
if ((fd = open(looppath, O_RDWR)) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to open %s"), looppath);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ioctl(fd, LOOP_GET_STATUS64, &lo) < 0) {
|
||||
/* Got a free device, return the fd */
|
||||
if (errno == ENXIO)
|
||||
goto cleanup;
|
||||
|
||||
VIR_FORCE_CLOSE(fd);
|
||||
virReportSystemError(errno,
|
||||
_("Unable to get loop status on %s"),
|
||||
looppath);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Oh well, try the next device */
|
||||
VIR_FORCE_CLOSE(fd);
|
||||
VIR_FREE(looppath);
|
||||
}
|
||||
|
||||
lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to find a free loop device in /dev"));
|
||||
|
||||
cleanup:
|
||||
if (fd != -1) {
|
||||
VIR_DEBUG("Got free loop device %s %d", looppath, fd);
|
||||
*dev_name = looppath;
|
||||
} else {
|
||||
VIR_DEBUG("No free loop devices available");
|
||||
VIR_FREE(looppath);
|
||||
}
|
||||
if (dh)
|
||||
closedir(dh);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int lxcSetupLoopDevice(virDomainFSDefPtr fs)
|
||||
{
|
||||
int lofd = -1;
|
||||
int fsfd = -1;
|
||||
struct loop_info64 lo;
|
||||
int lofd;
|
||||
char *loname = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if ((lofd = lxcGetLoopFD(&loname)) < 0)
|
||||
if ((lofd = virFileLoopDeviceAssociate(fs->src, &loname)) < 0)
|
||||
return -1;
|
||||
|
||||
memset(&lo, 0, sizeof(lo));
|
||||
lo.lo_flags = LO_FLAGS_AUTOCLEAR;
|
||||
|
||||
if ((fsfd = open(fs->src, O_RDWR)) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to open %s"), fs->src);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ioctl(lofd, LOOP_SET_FD, fsfd) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to attach %s to loop device"),
|
||||
fs->src);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ioctl(lofd, LOOP_SET_STATUS64, &lo) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to mark loop device as autoclear"));
|
||||
|
||||
if (ioctl(lofd, LOOP_CLR_FD, 0) < 0)
|
||||
VIR_WARN("Unable to detach %s from loop device", fs->src);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Attached loop device %s %d to %s", fs->src, lofd, loname);
|
||||
/*
|
||||
* We now change it into a block device type, so that
|
||||
* the rest of container setup 'just works'
|
||||
@ -448,13 +352,6 @@ static int lxcSetupLoopDevice(virDomainFSDefPtr fs)
|
||||
fs->src = loname;
|
||||
loname = NULL;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(loname);
|
||||
VIR_FORCE_CLOSE(fsfd);
|
||||
if (ret == -1)
|
||||
VIR_FORCE_CLOSE(lofd);
|
||||
return lofd;
|
||||
}
|
||||
|
||||
@ -470,7 +367,7 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl)
|
||||
if (ctrl->def->fss[i]->type != VIR_DOMAIN_FS_TYPE_FILE)
|
||||
continue;
|
||||
|
||||
fd = lxcSetupLoopDevice(ctrl->def->fss[i]);
|
||||
fd = virLXCControllerSetupLoopDevice(ctrl->def->fss[i]);
|
||||
if (fd < 0)
|
||||
goto cleanup;
|
||||
|
||||
|
@ -30,6 +30,12 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#ifdef __linux__
|
||||
# include <linux/loop.h>
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "command.h"
|
||||
#include "configmake.h"
|
||||
@ -493,3 +499,135 @@ int virFileUpdatePerm(const char *path,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
static int virFileLoopDeviceOpen(char **dev_name)
|
||||
{
|
||||
int fd = -1;
|
||||
DIR *dh = NULL;
|
||||
struct dirent *de;
|
||||
char *looppath;
|
||||
struct loop_info64 lo;
|
||||
|
||||
VIR_DEBUG("Looking for loop devices in /dev");
|
||||
|
||||
if (!(dh = opendir("/dev"))) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to read /dev"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while ((de = readdir(dh)) != NULL) {
|
||||
if (!STRPREFIX(de->d_name, "loop"))
|
||||
continue;
|
||||
|
||||
if (virAsprintf(&looppath, "/dev/%s", de->d_name) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Checking up on device %s", looppath);
|
||||
if ((fd = open(looppath, O_RDWR)) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to open %s"), looppath);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ioctl(fd, LOOP_GET_STATUS64, &lo) < 0) {
|
||||
/* Got a free device, return the fd */
|
||||
if (errno == ENXIO)
|
||||
goto cleanup;
|
||||
|
||||
VIR_FORCE_CLOSE(fd);
|
||||
virReportSystemError(errno,
|
||||
_("Unable to get loop status on %s"),
|
||||
looppath);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Oh well, try the next device */
|
||||
VIR_FORCE_CLOSE(fd);
|
||||
VIR_FREE(looppath);
|
||||
}
|
||||
|
||||
virFileError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Unable to find a free loop device in /dev"));
|
||||
|
||||
cleanup:
|
||||
if (fd != -1) {
|
||||
VIR_DEBUG("Got free loop device %s %d", looppath, fd);
|
||||
*dev_name = looppath;
|
||||
} else {
|
||||
VIR_DEBUG("No free loop devices available");
|
||||
VIR_FREE(looppath);
|
||||
}
|
||||
if (dh)
|
||||
closedir(dh);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
int virFileLoopDeviceAssociate(const char *file,
|
||||
char **dev)
|
||||
{
|
||||
int lofd = -1;
|
||||
int fsfd = -1;
|
||||
struct loop_info64 lo;
|
||||
char *loname = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if ((lofd = virFileLoopDeviceOpen(&loname)) < 0)
|
||||
return -1;
|
||||
|
||||
memset(&lo, 0, sizeof(lo));
|
||||
lo.lo_flags = LO_FLAGS_AUTOCLEAR;
|
||||
|
||||
if ((fsfd = open(file, O_RDWR)) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to open %s"), file);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ioctl(lofd, LOOP_SET_FD, fsfd) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Unable to attach %s to loop device"),
|
||||
file);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ioctl(lofd, LOOP_SET_STATUS64, &lo) < 0) {
|
||||
virReportSystemError(errno, "%s",
|
||||
_("Unable to mark loop device as autoclear"));
|
||||
|
||||
if (ioctl(lofd, LOOP_CLR_FD, 0) < 0)
|
||||
VIR_WARN("Unable to detach %s from loop device", file);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Attached loop device %s %d to %s", file, lofd, loname);
|
||||
*dev = loname;
|
||||
loname = NULL;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(loname);
|
||||
VIR_FORCE_CLOSE(fsfd);
|
||||
if (ret == -1)
|
||||
VIR_FORCE_CLOSE(lofd);
|
||||
return lofd;
|
||||
}
|
||||
|
||||
#else /* __linux__ */
|
||||
|
||||
int virFileLoopDeviceAssociate(const char *file,
|
||||
char **dev)
|
||||
{
|
||||
virReportSystemError(ENOSYS,
|
||||
_("Unable to associate file %s with loop device"),
|
||||
file);
|
||||
return -1;m
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
@ -105,4 +105,7 @@ int virFileUpdatePerm(const char *path,
|
||||
mode_t mode_remove,
|
||||
mode_t mode_add);
|
||||
|
||||
int virFileLoopDeviceAssociate(const char *file,
|
||||
char **dev);
|
||||
|
||||
#endif /* __VIR_FILES_H */
|
||||
|
Loading…
Reference in New Issue
Block a user