[libvirt] [PATCH 14/15] Move loop device setup code into virfile.{c, h}

Daniel P. Berrange berrange at redhat.com
Tue Jul 3 15:58:53 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

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 at redhat.com>
---
 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




More information about the libvir-list mailing list