From: "Daniel P. Berrange" <berrange(a)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@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