On Wed, Jul 11, 2012 at 03:58:20PM +0800, Gao feng wrote:
this patch addes fuse support for libvirt lxc.
we can use fuse filesystem to generate sysinfo dynamically,
So we can isolate /proc/meminfo,cpuinfo and so on through
fuse filesystem.
we mount fuse filesystem for every container.the mount name
is Lxc-lxcname-fuse.
Signed-off-by: Gao feng <gaofeng(a)cn.fujitsu.com>
---
src/Makefile.am | 9 ++-
src/lxc/lxc_controller.c | 15 +++++
src/lxc/lxc_driver.c | 2 +
src/lxc/lxc_fuse.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++
src/lxc/lxc_fuse.h | 38 +++++++++++
5 files changed, 217 insertions(+), 2 deletions(-)
create mode 100644 src/lxc/lxc_fuse.c
create mode 100644 src/lxc/lxc_fuse.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 6c3eaa7..b01b2df 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -349,11 +349,13 @@ endif
LXC_DRIVER_SOURCES = \
lxc/lxc_conf.c lxc/lxc_conf.h \
+ lxc/lxc_fuse.c lxc/lxc_fuse.h \
lxc/lxc_container.c lxc/lxc_container.h \
lxc/lxc_driver.c lxc/lxc_driver.h
LXC_CONTROLLER_SOURCES = \
lxc/lxc_conf.c lxc/lxc_conf.h \
+ lxc/lxc_fuse.c lxc/lxc_fuse.h \
lxc/lxc_container.c lxc/lxc_container.h \
lxc/lxc_controller.c
@@ -819,8 +821,9 @@ endif
libvirt_driver_lxc_impl_la_CFLAGS = \
$(LIBNL_CFLAGS) \
+ $(FUSE_CFLAGS) \
-I$(top_srcdir)/src/conf $(AM_CFLAGS)
-libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS)
+libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(FUSE_LIBS)
if HAVE_LIBBLKID
libvirt_driver_lxc_impl_la_CFLAGS += $(BLKID_CFLAGS)
libvirt_driver_lxc_impl_la_LIBADD += $(BLKID_LIBS)
@@ -1523,6 +1526,7 @@ libvirt_lxc_SOURCES = \
libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)
libvirt_lxc_LDADD = \
$(NUMACTL_LIBS) \
+ $(FUSE_LIBS) \
libvirt-net-rpc-server.la \
libvirt-net-rpc.la \
libvirt_driver_security.la \
@@ -1540,7 +1544,8 @@ libvirt_lxc_LDADD += $(APPARMOR_LIBS)
endif
libvirt_lxc_CFLAGS = \
-I$(top_srcdir)/src/conf \
- $(AM_CFLAGS)
+ $(AM_CFLAGS) \
+ $(FUSE_CFLAGS)
if HAVE_LIBBLKID
libvirt_lxc_CFLAGS += $(BLKID_CFLAGS)
libvirt_lxc_LDADD += $(BLKID_LIBS)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index a4874ea..44ba07c 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -58,6 +58,7 @@
#include "lxc_conf.h"
#include "lxc_container.h"
+#include "lxc_fuse.h"
#include "virnetdev.h"
#include "virnetdevveth.h"
#include "memory.h"
@@ -1741,6 +1742,20 @@ int main(int argc, char *argv[])
}
}
+ if ((pid = fork()) < 0)
+ goto cleanup;
+
+ if (pid == 0) {
+ if ((pid = fork()) < 0)
+ _exit(-1);
+
+ if (pid > 0)
+ _exit(0);
+
+ lxcRegisterFuse(ctrl->def);
+ _exit(0);
+ }
This is double forking to daemonize, but you never execve()
anywhere. Thus according to POSIX you are mandated to only
use async signal safe functions. This is clearly impossible
given the functionality you need to use with FUSE.
So either you need to make this a separate binary that can
be exec()'d, or instead of fork()ing, run this in a thread
of the libvirt_lxc process. I think you can probably make
do with just using a thread.
+#if HAVE_FUSE
+
+static int lxcProcGetattr(const char *path, struct stat *stbuf)
+{
+ int res = 0;
+
+ memset(stbuf, 0, sizeof(struct stat));
+ if (strcmp(path, "/") == 0) {
strcmp() == 0, is not allowed - use STREQ instead - if you
run 'make syntax-check' it should warn you about this.
+ stbuf->st_mode = S_IFDIR | 0755;
+ stbuf->st_nlink = 2;
+ } else
+ res = -ENOENT;
You need {} around the else clause, if you use {}
around the if clause (see HACKING)
+
+ return res;
+}
+
+static int lxcProcReaddir(const char *path, void *buf,
+ fuse_fill_dir_t filler,
+ off_t offset ATTRIBUTE_UNUSED,
+ struct fuse_file_info *fi ATTRIBUTE_UNUSED)
+{
+ if (strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ filler(buf, ".", NULL, 0);
+ filler(buf, "..", NULL, 0);
+
+ return 0;
+}
+
+static int lxcProcOpen(const char *path ATTRIBUTE_UNUSED,
+ struct fuse_file_info *fi ATTRIBUTE_UNUSED)
+{
+ return -ENOENT;
+}
+
+static int lxcProcRead(const char *path ATTRIBUTE_UNUSED,
+ char *buf ATTRIBUTE_UNUSED,
+ size_t size ATTRIBUTE_UNUSED,
+ off_t offset ATTRIBUTE_UNUSED,
+ struct fuse_file_info *fi ATTRIBUTE_UNUSED)
+{
+ return -ENOENT;
+}
+
+static struct fuse_operations lxcProcOper = {
+ .getattr = lxcProcGetattr,
+ .readdir = lxcProcReaddir,
+ .open = lxcProcOpen,
+ .read = lxcProcRead,
+};
+
+int lxcRegisterFuse(virDomainDefPtr def)
+{
+ int rc = -1;
+ char *path = NULL;
+ char *name = NULL;
+ int argc = 3;
+ char *argv[argc];
+
+ if ((rc = virAsprintf(&name, "Lxc-%s-fuse", def->name)) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if ((rc = virAsprintf(&path, "%s/%s/", LXC_STATE_DIR, def->name))
< 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if ((rc = virFileMakePath(path)) < 0) {
+ virReportSystemError(errno, _("Cannot create %s"), path);
+ goto cleanup;
+ }
+
+ argv[0] = name;
+ argv[1] = path;
+ argv[2] = (char *)"-odirect_io";
+
+ if ((rc = fuse_main(argc, argv, &lxcProcOper, def)) < 0) {
+ virReportSystemError(errno, "%s", _("Cannot start
fuse\n"));
+ goto cleanup;
+ }
+ rc = 0;
+
+cleanup:
+ VIR_FREE(name);
+ VIR_FREE(path);
+ VIR_FREE(argv);
+ return rc;
+}
+
+void lxcUnregisterFuse(virDomainDefPtr def)
+{
+ char *path = NULL;
+ if (virAsprintf(&path, "%s/%s/", LXC_STATE_DIR, def->name) < 0)
{
+ virReportOOMError();
+ return;
+ }
+
+ if (umount(path) < 0)
+ virReportSystemError(errno, "%s", _("umount fuse filesystem
failed\n"));
+
+ VIR_FREE(path);
+}
+
+#else
+int lxcRegisterFuse(virDomainDefPtr def)
+{
+ (void) def;
+ return 0;
+}
+
+void lxcUnregisterFuse(virDomainDefPtr def)
+{
+ (void) def;
+}
+#endif
Use ATTRIBUTE_UNNUSED annotations instead of casting to (void)
Regards,
Daniel
--
|:
http://berrange.com -o-
http://www.flickr.com/photos/dberrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|:
http://entangle-photo.org -o-
http://live.gnome.org/gtk-vnc :|