From 9612e4b2e7dfa0de89405075fca32718e1d66203 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 3 Jul 2012 15:06:27 +0100 Subject: [PATCH] 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 --- src/libvirt_private.syms | 1 + src/lxc/lxc_controller.c | 111 ++----------------------------- src/util/virfile.c | 138 +++++++++++++++++++++++++++++++++++++++ src/util/virfile.h | 3 + 4 files changed, 146 insertions(+), 107 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2fe5068784..6625fc6525 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1243,6 +1243,7 @@ virDomainListSnapshots; # virfile.h +virFileLoopDeviceAssociate; virFileClose; virFileDirectFdFlag; virFileWrapperFdClose; diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index b083d5292f..c35ac45b4f 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -39,8 +39,6 @@ #include #include #include -#include -#include #include #include #include @@ -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; diff --git a/src/util/virfile.c b/src/util/virfile.c index 6c6921704f..8387ae9528 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -30,6 +30,12 @@ #include #include #include +#include + +#ifdef __linux__ +# include +# include +#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__ */ diff --git a/src/util/virfile.h b/src/util/virfile.h index fb8109bfbd..101953ae1a 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -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 */ -- GitLab