From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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@xxxxxxxxxx> --- src/libvirt_private.syms | 1 + src/lxc/lxc_controller.c | 112 ++----------------------------------- src/util/virfile.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/virfile.h | 3 + 4 files changed, 147 insertions(+), 107 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2fe5068..6625fc6 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 05ca52a..27b51b4 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -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,15 @@ static int virLXCControllerValidateConsoles(virLXCControllerPtr ctrl) } -static int lxcGetLoopFD(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); - } - - 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) +static int virLXCControllerSetupLoopDevice(virDomainFSDefPtr fs) { int lofd = -1; - int fsfd = -1; - struct loop_info64 lo; char *loname = NULL; - int ret = -1; - if ((lofd = lxcGetLoopFD(&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; - } + if ((lofd = virFileLoopDeviceAssociate(fs->src, &loname)) < 0) + return -1; - 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,14 +353,7 @@ 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; + return 0; } @@ -470,7 +368,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 6c69217..8387ae9 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -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__ */ diff --git a/src/util/virfile.h b/src/util/virfile.h index fb8109b..101953a 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 */ -- 1.7.10.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list