提交 9612e4b2 编写于 作者: D Daniel P. Berrange

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: NDaniel P. Berrange <berrange@redhat.com>
上级 f547e876
...@@ -1243,6 +1243,7 @@ virDomainListSnapshots; ...@@ -1243,6 +1243,7 @@ virDomainListSnapshots;
# virfile.h # virfile.h
virFileLoopDeviceAssociate;
virFileClose; virFileClose;
virFileDirectFdFlag; virFileDirectFdFlag;
virFileWrapperFdClose; virFileWrapperFdClose;
......
...@@ -39,8 +39,6 @@ ...@@ -39,8 +39,6 @@
#include <getopt.h> #include <getopt.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <locale.h> #include <locale.h>
#include <linux/loop.h>
#include <dirent.h>
#include <grp.h> #include <grp.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <time.h> #include <time.h>
...@@ -337,108 +335,14 @@ static int virLXCControllerValidateConsoles(virLXCControllerPtr ctrl) ...@@ -337,108 +335,14 @@ static int virLXCControllerValidateConsoles(virLXCControllerPtr ctrl)
} }
static int lxcGetLoopFD(char **dev_name) static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs)
{ {
int fd = -1; int lofd;
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;
char *loname = NULL; char *loname = NULL;
int ret = -1;
if ((lofd = lxcGetLoopFD(&loname)) < 0) if ((lofd = virFileLoopDeviceAssociate(fs->src, &loname)) < 0)
return -1; 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 * We now change it into a block device type, so that
* the rest of container setup 'just works' * the rest of container setup 'just works'
...@@ -448,13 +352,6 @@ static int lxcSetupLoopDevice(virDomainFSDefPtr fs) ...@@ -448,13 +352,6 @@ static int lxcSetupLoopDevice(virDomainFSDefPtr fs)
fs->src = loname; fs->src = loname;
loname = NULL; loname = NULL;
ret = 0;
cleanup:
VIR_FREE(loname);
VIR_FORCE_CLOSE(fsfd);
if (ret == -1)
VIR_FORCE_CLOSE(lofd);
return lofd; return lofd;
} }
...@@ -470,7 +367,7 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl) ...@@ -470,7 +367,7 @@ static int virLXCControllerSetupLoopDevices(virLXCControllerPtr ctrl)
if (ctrl->def->fss[i]->type != VIR_DOMAIN_FS_TYPE_FILE) if (ctrl->def->fss[i]->type != VIR_DOMAIN_FS_TYPE_FILE)
continue; continue;
fd = lxcSetupLoopDevice(ctrl->def->fss[i]); fd = virLXCControllerSetupLoopDevice(ctrl->def->fss[i]);
if (fd < 0) if (fd < 0)
goto cleanup; goto cleanup;
......
...@@ -30,6 +30,12 @@ ...@@ -30,6 +30,12 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <dirent.h>
#ifdef __linux__
# include <linux/loop.h>
# include <sys/ioctl.h>
#endif
#include "command.h" #include "command.h"
#include "configmake.h" #include "configmake.h"
...@@ -493,3 +499,135 @@ int virFileUpdatePerm(const char *path, ...@@ -493,3 +499,135 @@ int virFileUpdatePerm(const char *path,
return 0; 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, ...@@ -105,4 +105,7 @@ int virFileUpdatePerm(const char *path,
mode_t mode_remove, mode_t mode_remove,
mode_t mode_add); mode_t mode_add);
int virFileLoopDeviceAssociate(const char *file,
char **dev);
#endif /* __VIR_FILES_H */ #endif /* __VIR_FILES_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册