[libvirt] [PATCH] Add support for probing filesystem with libblkid

Daniel P. Berrange berrange at redhat.com
Tue Nov 1 15:02:37 UTC 2011


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

The LXC code for mounting container filesystems from block devices
tries all filesystems in /etc/filesystems and possibly those in
/proc/filesystems. The regular mount binary, however, first tries
using libblkid to detect the format. Add support for doing the same
in libvirt, since Fedora's /etc/filesystems is missing many formats,
most notably ext4 which is the default filesystem Fedora uses!

* src/Makefile.am: Link libvirt_lxc to libblkid
* src/lxc/lxc_container.c: Probe filesystem format with liblkid
---
 src/Makefile.am         |    4 ++
 src/lxc/lxc_container.c |  102 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 105 insertions(+), 1 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index c36664b..bf26b19 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1495,6 +1495,10 @@ libvirt_lxc_CFLAGS =				\
 		$(AUDIT_CFLAGS)			\
 		-I at top_srcdir@/src/conf		\
 		$(AM_CFLAGS)
+if HAVE_LIBBLKID
+libvirt_lxc_CFLAGS += $(BLKID_CFLAGS)
+libvirt_lxc_LDADD += $(BLKID_LIBS)
+endif
 endif
 endif
 EXTRA_DIST += $(LXC_CONTROLLER_SOURCES)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 36ac3a9..647aaea 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -47,6 +47,10 @@
 # include <cap-ng.h>
 #endif
 
+#if HAVE_LIBBLKID
+# include <blkid/blkid.h>
+#endif
+
 #include "virterror_internal.h"
 #include "logging.h"
 #include "lxc_container.h"
@@ -627,6 +631,86 @@ cleanup:
 }
 
 
+#ifdef HAVE_LIBBLKID
+static int
+lxcContainerMountDetectFilesystem(const char *src, char **type)
+{
+    int fd;
+    int ret = -1;
+    int rc;
+    const char *data = NULL;
+    blkid_probe blkid = NULL;
+
+    *type = NULL;
+
+    if ((fd = open(src, O_RDONLY)) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to open filesystem %s"), src);
+        return -1;
+    }
+
+    if (!(blkid = blkid_new_probe())) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to create blkid library handle"));
+        goto cleanup;
+    }
+    if (blkid_probe_set_device(blkid, fd, 0, 0) < 0) {
+        virReportSystemError(EINVAL,
+                             _("Unable to associated device %s with blkid library"),
+                             src);
+        goto cleanup;
+    }
+
+    blkid_probe_enable_superblocks(blkid, 1);
+
+    blkid_probe_set_superblocks_flags(blkid, BLKID_SUBLKS_TYPE);
+
+    rc = blkid_do_safeprobe(blkid);
+    if (rc != 0) {
+        if (rc == 1) /* Nothing found, return success with *type == NULL */
+            goto done;
+
+        if (rc == -2) {
+            virReportSystemError(EINVAL,
+                                 _("Too many filesystems detected for %s"),
+                                 src);
+        } else {
+            virReportSystemError(errno,
+                                 _("Unable to detect filesystem for %s"),
+                                 src);
+        }
+        goto cleanup;
+    }
+
+    if (blkid_probe_lookup_value(blkid, "TYPE", &data, NULL) < 0) {
+        virReportSystemError(ENOENT,
+                             _("Unable to find filesystem type for %s"),
+                             src);
+        goto cleanup;
+    }
+
+    if (!(*type = strdup(data))) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+done:
+    ret = 0;
+cleanup:
+    VIR_FORCE_CLOSE(fd);
+    blkid_free_probe(blkid);
+    return ret;
+}
+#else /* ! HAVE_LIBBLKID */
+static int
+lxcContainerMountDetectFilesystem(const char *src ATTRIBUTE_UNUSED,
+                                  char **type)
+{
+    /* No libblkid, so just return success with no detected type */
+    *type = NULL;
+    return 0;
+}
+#endif /* ! HAVE_LIBBLKID */
 
 /*
  * This functions attempts to do automatic detection of filesystem
@@ -771,6 +855,8 @@ static int lxcContainerMountFSBlockHelper(virDomainFSDefPtr fs,
 {
     int fsflags = 0;
     int ret = -1;
+    char *format = NULL;
+
     if (fs->readonly)
         fsflags |= MS_RDONLY;
 
@@ -781,7 +867,21 @@ static int lxcContainerMountFSBlockHelper(virDomainFSDefPtr fs,
         goto cleanup;
     }
 
-    ret = lxcContainerMountFSBlockAuto(fs, fsflags, src, srcprefix);
+    if (lxcContainerMountDetectFilesystem(src, &format) < 0)
+        goto cleanup;
+
+    if (format) {
+        VIR_DEBUG("Mount %s with detected format %s", src, format);
+        if (mount(src, fs->dst, format, fsflags, NULL) < 0) {
+            virReportSystemError(errno,
+                                 _("Failed to mount device %s to %s as %s"),
+                                 src, fs->dst, format);
+            goto cleanup;
+        }
+        ret = 0;
+    } else {
+        ret = lxcContainerMountFSBlockAuto(fs, fsflags, src, srcprefix);
+    }
 
 cleanup:
     return ret;
-- 
1.7.6.4




More information about the libvir-list mailing list