[libvirt] [RFC] [PATCH 1/5] add configure option --with-fuse for libvirt

add a configure option --with-fuse to prepare introduction of fuse support for libvirt lxc. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- configure.ac | 45 +++++++++++++++++++++++++++++++++++++++++++++ libvirt.spec.in | 9 +++++++++ 2 files changed, 54 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index d45f4f1..d5cf45f 100644 --- a/configure.ac +++ b/configure.ac @@ -1694,7 +1694,47 @@ AM_CONDITIONAL([HAVE_CAPNG], [test "$with_capng" != "no"]) AC_SUBST([CAPNG_CFLAGS]) AC_SUBST([CAPNG_LIBS]) +dnl libfuse +AC_ARG_WITH([fuse], + AC_HELP_STRING([--with-fuse], [use libfuse to proivde fuse filesystem support for libvirt lxc]), + [], + [with_fuse=check]) +dnl +dnl This check looks for 'fuse' +dnl +FUSE_CFLAGS= +FUSE_LIBS= +if test "$with_fuse" != "no"; then + old_cflags="$CFLAGS" + old_libs="$LIBS" + old_cppflags="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" + if test "$with_fuse" = "check"; then + AC_CHECK_HEADER([fuse.h], [], [with_fuse=no]) + AC_CHECK_LIB([fuse], [fuse_main], [], [with_fuse=no]) + if test "$with_fuse" != "no"; then + with_fuse="yes" + fi + else + fail=0 + AC_CHECK_HEADER([fuse.h], [], [fail=1]) + AC_CHECK_LIB([fuse], [fuse_main], [], [fail=1]) + test $fail = 1 && + AC_MSG_ERROR([You must install the fuse >= 2.9.0 development package in order to compile and run libvirt]) + fi + CFLAGS="$old_cflags" + LIBS="$old_libs" + CPPFLAGS="$old_cppflags" +fi +if test "$with_fuse" = "yes"; then + FUSE_LIBS="-lfuse" + FUSE_CFLAGS="-D_FILE_OFFSET_BITS=64" + AC_DEFINE_UNQUOTED([HAVE_FUSE], 1, [Whether fuse is available for privilege reduction]) +fi +AM_CONDITIONAL([HAVE_FUSE], [test "$with_fuse" != "no"]) +AC_SUBST([FUSE_CFLAGS]) +AC_SUBST([FUSE_LIBS]) dnl virsh libraries AC_CHECK_HEADERS([readline/readline.h]) @@ -2912,6 +2952,11 @@ AC_MSG_NOTICE([ capng: $CAPNG_CFLAGS $CAPNG_LIBS]) else AC_MSG_NOTICE([ capng: no]) fi +if test "$with_fuse" = "yes" ; then +AC_MSG_NOTICE([ fuse: $FUSE_CFLAGS $FUSE_LIBS]) +else +AC_MSG_NOTICE([ fuse: no]) +fi if test "$with_xen" = "yes" ; then AC_MSG_NOTICE([ xen: $XEN_CFLAGS $XEN_LIBS]) else diff --git a/libvirt.spec.in b/libvirt.spec.in index ec2b3b4..8cb2291 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -86,6 +86,7 @@ # A few optional bits off by default, we enable later %define with_polkit 0%{!?_without_polkit:0} %define with_capng 0%{!?_without_capng:0} +%define with_fuse 0%{!?_without_fuse:0} %define with_netcf 0%{!?_without_netcf:0} %define with_udev 0%{!?_without_udev:0} %define with_hal 0%{!?_without_hal:0} @@ -450,6 +451,9 @@ BuildRequires: numactl-devel %if %{with_capng} BuildRequires: libcap-ng-devel >= 0.5.0 %endif +%if %{with_fuse} +BuildRequires: fuse-devel >= 2.9.0 +%endif %if %{with_phyp} BuildRequires: libssh2-devel %endif @@ -1092,6 +1096,10 @@ of recent versions of Linux (and other OSes). %define _without_capng --without-capng %endif +%if ! %{with_fuse} +%define _without_fuse --without-fuse +%endif + %if ! %{with_netcf} %define _without_netcf --without-netcf %endif @@ -1181,6 +1189,7 @@ autoreconf -if %{?_without_numactl} \ %{?_without_numad} \ %{?_without_capng} \ + %{?_without_fuse} \ %{?_without_netcf} \ %{?_without_selinux} \ %{?_without_hal} \ -- 1.7.7.6

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@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); + } + rc = virLXCControllerRun(ctrl); cleanup: diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index b58aeae..3f6838f 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -41,6 +41,7 @@ #include "lxc_conf.h" #include "lxc_container.h" #include "lxc_driver.h" +#include "lxc_fuse.h" #include "memory.h" #include "util.h" #include "virnetdevbridge.h" @@ -1485,6 +1486,7 @@ static int lxcVmTerminate(lxc_driver_t *driver, return -1; } + lxcUnregisterFuse(vm->def); virSecurityManagerRestoreAllLabel(driver->securityManager, vm->def, false); virSecurityManagerReleaseLabel(driver->securityManager, vm->def); diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c new file mode 100644 index 0000000..5fdacab --- /dev/null +++ b/src/lxc/lxc_fuse.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2012 Fujitsu Limited. + * + * lxc_fuse.c: fuse filesystem support for libvirt lxc + * + * Authors: + * Gao feng <gaofeng at cn.fujitsu.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <config.h> +#include <fcntl.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <sys/mount.h> + +#include "virterror_internal.h" +#include "lxc_fuse.h" +#include "util.h" +#include "memory.h" + +#define VIR_FROM_THIS VIR_FROM_LXC + +#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) { + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + } else + res = -ENOENT; + + 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 diff --git a/src/lxc/lxc_fuse.h b/src/lxc/lxc_fuse.h new file mode 100644 index 0000000..f87d848 --- /dev/null +++ b/src/lxc/lxc_fuse.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2012 Fujitsu Limited. + * + * lxc_fuse.c: fuse filesystem support for libvirt lxc + * + * Authors: + * Gao feng <gaofeng at cn.fujitsu.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef LXC_FUSE_H +#define LXC_FUSE_H + +#define FUSE_USE_VERSION 26 + +#include <config.h> +#if HAVE_FUSE +#include <fuse.h> +#endif + +#include "lxc_conf.h" + +extern int lxcRegisterFuse(virDomainDefPtr def); +extern void lxcUnregisterFuse(virDomainDefPtr def); +#endif -- 1.7.7.6

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@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 :|

于 2012年07月11日 17:30, Daniel P. Berrange 写道:
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@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.
Get it,thanks for explaining this to me.
+#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)
Yes,will read it,thanks
+ + 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)
Get it Thanks! Gao

virCgroupGetMemSwapUsage is used to get container's swap usage, with this interface,we can get swap usage in fuse filesystem. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/libvirt_private.syms | 1 + src/util/cgroup.c | 20 ++++++++++++++++++++ src/util/cgroup.h | 1 + 3 files changed, 22 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 6625fc6..5a1f20e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -79,6 +79,7 @@ virCgroupGetCpuacctStat; virCgroupGetCpuacctUsage; virCgroupGetCpusetMems; virCgroupGetFreezerState; +virCgroupGetMemSwapUsage; virCgroupGetMemSwapHardLimit; virCgroupGetMemoryHardLimit; virCgroupGetMemorySoftLimit; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 5b32881..d6fcd61 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -1188,6 +1188,26 @@ int virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb) } /** + * virCgroupGetMemSwapUsage: + * + * @group: The cgroup to get mem+swap usage for + * @kb: The mem+swap amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb) +{ + long long unsigned int usage_in_bytes; + int ret; + ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + "memory.memsw.usage_in_bytes", &usage_in_bytes); + if (ret == 0) + *kb = usage_in_bytes >> 10; + return ret; +} + +/** * virCgroupGetMemSwapHardLimit: * * @group: The cgroup to get mem+swap hard limit for diff --git a/src/util/cgroup.h b/src/util/cgroup.h index 05325ae..caca362 100644 --- a/src/util/cgroup.h +++ b/src/util/cgroup.h @@ -70,6 +70,7 @@ int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb); int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb); int virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb); int virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb); +int virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb); enum { VIR_CGROUP_DEVICE_READ = 1, -- 1.7.7.6

with this patch,container's meminfo will be shown based on containers' mem cgroup. Right now,it's impossible to virtualize all values in meminfo, I collect some values such as MemTotal,MemFree,Cached,Active, Inactive,Active(anon),Inactive(anon),Active(file),Inactive(anon), Active(file),Inactive(file),Unevictable,SwapTotal,SwapFree. if I miss something, please let me know. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_fuse.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 332 insertions(+), 8 deletions(-) diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c index 5fdacab..69b4f2e 100644 --- a/src/lxc/lxc_fuse.c +++ b/src/lxc/lxc_fuse.c @@ -32,22 +32,52 @@ #include "lxc_fuse.h" #include "util.h" #include "memory.h" +#include "virfile.h" #define VIR_FROM_THIS VIR_FROM_LXC #if HAVE_FUSE +enum { + MEMTOTAL, + MEMUSAGE, + CACHED, + ACTIVE_ANON, + INACTIVE_ANON, + ACTIVE_FILE, + INACTIVE_FILE, + UNEVICTABLE, + SWAPTOTAL, + SWAPUSAGE, + MEMMAX, +}; + +static const char *meminfo_path = "/meminfo"; static int lxcProcGetattr(const char *path, struct stat *stbuf) { int res = 0; + char *mempath = NULL; + struct stat sb; + virAsprintf(&mempath, "/proc/%s",path); memset(stbuf, 0, sizeof(struct stat)); if (strcmp(path, "/") == 0) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; + } else if (strcmp(path, meminfo_path) == 0) { + stat(mempath, &sb); + stbuf->st_mode = S_IFREG | 0444; + stbuf->st_nlink = 1; + stbuf->st_blksize = sb.st_blksize; + stbuf->st_blocks = sb.st_blocks; + stbuf->st_size = sb.st_size; + stbuf->st_atime = sb.st_atime; + stbuf->st_ctime = sb.st_ctime; + stbuf->st_mtime = sb.st_mtime; } else res = -ENOENT; + VIR_FREE(mempath); return res; } @@ -61,23 +91,317 @@ static int lxcProcReaddir(const char *path, void *buf, filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); + filler(buf, meminfo_path + 1, NULL, 0); return 0; } -static int lxcProcOpen(const char *path ATTRIBUTE_UNUSED, - struct fuse_file_info *fi ATTRIBUTE_UNUSED) +static int lxcProcOpen(const char *path, + struct fuse_file_info *fi) +{ + if (strcmp(path, meminfo_path) != 0) + return -ENOENT; + + if ((fi->flags & 3) != O_RDONLY) + return -EACCES; + + return 0; +} + +static int lxcGetMemCgroupSwapUsage(virCgroupPtr cgroup, unsigned long long *usage) +{ + return virCgroupGetMemSwapUsage(cgroup, usage); +} + +static int lxcGetMemCgroupSwapTotal(virCgroupPtr cgroup, unsigned long long *total) +{ + return virCgroupGetMemSwapHardLimit(cgroup, total); +} + +static int lxcGetMemCgroupMemUsage(virCgroupPtr cgroup, unsigned long long *usage) +{ + int ret; + unsigned long memUsage; + + ret = virCgroupGetMemoryUsage(cgroup, &memUsage); + *usage = (unsigned long long) memUsage; + + return ret; +} + +static int lxcGetMemCgroupMemTotal(virCgroupPtr cgroup, unsigned long long *total) { - return -ENOENT; + return virCgroupGetMemoryHardLimit(cgroup, total); } -static int lxcProcRead(const char *path ATTRIBUTE_UNUSED, - char *buf ATTRIBUTE_UNUSED, - size_t size ATTRIBUTE_UNUSED, - off_t offset ATTRIBUTE_UNUSED, +static int lxcGetMemCgroupStat(virCgroupPtr cgroup, unsigned long long *meminfo) +{ + int ret = 0; + FILE *statfd = NULL; + char *statFile = NULL; + char line[1024]; + + ret = virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_MEMORY, + "memory.stat", &statFile); + if (ret < 0 ) { + virReportSystemError(-ret, "%s", + _("cannot get the path of MEMORY cgroup controller")); + return ret; + } + + statfd = fopen(statFile, "r"); + if (statfd == NULL) { + ret = -ENOENT; + goto out_free; + } + + while (fgets(line, sizeof(line), statfd) != NULL) { + char *value = strchr(line, ' '); + char *nl = value ? strchr(line, '\n') : NULL; + unsigned long long stat_value; + + if (!value) + continue; + + if (nl) + *nl = '\0'; + + *value = '\0'; + if (strcmp(line, "cache") == 0) { + if ((ret = virStrToLong_ull(value + 1, NULL, 10, &stat_value)) < 0) + goto out; + meminfo[CACHED] = stat_value >> 10; + } else if (strcmp(line, "inactive_anon") == 0) { + if ((ret = virStrToLong_ull(value + 1, NULL, 10, &stat_value)) < 0) + goto out; + meminfo[INACTIVE_ANON] = stat_value >> 10; + } else if (strcmp(line, "active_anon") == 0) { + if ((ret = virStrToLong_ull(value + 1, NULL, 10, &stat_value)) < 0) + goto out; + meminfo[ACTIVE_ANON] = stat_value >> 10; + } else if (strcmp(line, "inactive_file") == 0) { + if ((ret = virStrToLong_ull(value + 1, NULL, 10, &stat_value)) < 0) + goto out; + meminfo[INACTIVE_FILE] = stat_value >> 10; + } else if (strcmp(line, "active_file") == 0) { + if ((ret = virStrToLong_ull(value + 1, NULL, 10, &stat_value)) < 0) + goto out; + meminfo[ACTIVE_FILE] = stat_value >> 10; + } else if (strcmp(line, "unevictable") == 0) { + if ((ret = virStrToLong_ull(value + 1, NULL, 10, &stat_value)) < 0) + goto out; + meminfo[UNEVICTABLE] = stat_value >> 10; + } + } + ret = 0; +out: + pclose(statfd); +out_free: + VIR_FREE(statFile); + return ret; +} + +static int lxcGetMeminfo(virDomainDefPtr def, unsigned long long *meminfo) +{ + int ret; + virCgroupPtr driver; + virCgroupPtr cgroup; + + ret = virCgroupForDriver("lxc", &driver, 1, 0); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get cgroup for driver")); + return ret; + } + + ret = virCgroupForDomain(driver, def->name, &cgroup, 0); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get cgroup for domain")); + goto out_driver; + } + + ret = lxcGetMemCgroupStat(cgroup, meminfo); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat info\n")); + goto out; + } + + ret = lxcGetMemCgroupMemTotal(cgroup, &meminfo[MEMTOTAL]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup total\n")); + goto out; + } + + ret = lxcGetMemCgroupMemUsage(cgroup, &meminfo[MEMUSAGE]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat usage\n")); + goto out; + } + + ret = lxcGetMemCgroupSwapTotal(cgroup, &meminfo[SWAPTOTAL]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat swaptotal\n")); + goto out; + } + + ret = lxcGetMemCgroupSwapUsage(cgroup, &meminfo[SWAPUSAGE]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat swapusage\n")); + goto out; + } + + ret = 0; +out: + virCgroupFree(&cgroup); + +out_driver: + virCgroupFree(&driver); + + return ret; +} + +static int lxcProcReadMeminfo(char *hostpath, virDomainDefPtr def, + char *buf, size_t size, off_t offset) +{ + int res; + FILE *fd = NULL; + char line[1024]; + unsigned long long meminfo[MEMMAX]; + + if ((res = lxcGetMeminfo(def, meminfo)) < 0) { + virReportSystemError(errno, "%s", _("Get Memory Cgroup info failed\n")); + return res; + } + + fd = fopen(hostpath, "r"); + if (fd == NULL) { + virReportSystemError(errno, "Cannot fopen %s\n", hostpath); + res = -errno; + goto out; + } + + fseek(fd, offset, SEEK_SET); + + while (res < size && fgets(line, sizeof(line), fd) != NULL) { + int len = 0; + char *new_line = NULL; + char *ptr = strchr(line, ':'); + if (ptr) { + *ptr = '\0'; + new_line = line; + + if (strcmp(line, "MemTotal") == 0 && + (def->mem.hard_limit || def->mem.max_balloon)) { + virAsprintf(&new_line, "MemTotal: %8llu KB\n", + meminfo[MEMTOTAL]); + } else if (strcmp(line, "MemFree") == 0 && + (def->mem.hard_limit || def->mem.max_balloon)) { + virAsprintf(&new_line, "MemFree: %8llu KB\n", + (meminfo[MEMTOTAL] - meminfo[MEMUSAGE])); + } else if (strcmp(line, "Buffers") == 0) { + virAsprintf(&new_line, "Buffers: %8d KB\n", 0); + } else if (strcmp(line, "Cached") == 0 && meminfo[CACHED]) { + virAsprintf(&new_line, "Cached: %8llu KB\n", + meminfo[CACHED]); + } else if (strcmp(line, "Active") == 0 && meminfo[ACTIVE_ANON]) { + virAsprintf(&new_line, "Active: %8llu KB\n", + (meminfo[ACTIVE_ANON] + meminfo[ACTIVE_FILE])); + } else if (strcmp(line, "Inactive") == 0 && meminfo[INACTIVE_ANON]) { + virAsprintf(&new_line, "Inactive: %8llu KB\n", + (meminfo[INACTIVE_ANON] + meminfo[INACTIVE_FILE])); + } else if (strcmp(line, "Active(anon)") == 0 && meminfo[ACTIVE_ANON]) { + virAsprintf(&new_line, "Active(anon): %8llu KB\n", + meminfo[ACTIVE_ANON]); + } else if (strcmp(line, "Inactive(anon)") == 0 && meminfo[INACTIVE_ANON]) { + virAsprintf(&new_line, "Inactive(anon): %8llu KB\n", + meminfo[INACTIVE_ANON]); + } else if (strcmp(line, "Active(file)") == 0 && meminfo[ACTIVE_FILE]) { + virAsprintf(&new_line, "Active(file): %8llu KB\n", + meminfo[ACTIVE_FILE]); + } else if (strcmp(line, "Inactive(file)") == 0 && meminfo[INACTIVE_FILE]) { + virAsprintf(&new_line, "Inactive(file): %8llu KB\n", + meminfo[INACTIVE_FILE]); + } else if (strcmp(line, "Unevictable") == 0 && meminfo[UNEVICTABLE]) { + virAsprintf(&new_line, "Unevictable: %8llu KB\n", + meminfo[UNEVICTABLE]); + } else if (strcmp(line, "SwapTotal") == 0 && def->mem.swap_hard_limit) { + virAsprintf(&new_line, "SwapTotal: %8llu KB\n", + (meminfo[SWAPTOTAL] - meminfo[MEMTOTAL])); + } else if (strcmp(line, "SwapFree") == 0 && def->mem.swap_hard_limit) { + virAsprintf(&new_line, "SwapFree: %8llu KB\n", + (meminfo[SWAPTOTAL] - meminfo[MEMTOTAL] + - meminfo[SWAPUSAGE] + meminfo[MEMUSAGE])); + } + *ptr=':'; + } + + len = strlen(new_line); + + if (res + len > size) + len = size - res; + + memcpy(buf + res, new_line, len); + res += len; + memset(line, 0, sizeof(line)); + if (new_line != line) + VIR_FREE(new_line); + } +out: + VIR_FORCE_FCLOSE(fd); + return res; +} + +static int lxcProcHostRead(char *path, char *buf, size_t size, off_t offset) +{ + int fd; + int res; + fd = open(path, O_RDONLY); + if (fd == -1) + return -errno; + + res = pread(fd, buf, size, offset); + if (res == -1) + res = -errno; + close(fd); + return res; +} + +static int lxcProcRead(const char *path, + char *buf, + size_t size, + off_t offset, struct fuse_file_info *fi ATTRIBUTE_UNUSED) { - return -ENOENT; + int res = 0; + char *hostpath = NULL; + struct fuse_context *context = NULL; + virDomainDefPtr def = NULL; + + if ((res = virAsprintf(&hostpath, "/proc/%s", path)) < 0) { + virReportSystemError(errno, "%s", _("Cannot get host path\n")); + return res; + } + + context = fuse_get_context(); + def = (virDomainDefPtr)context->private_data; + + if (strcmp(path, meminfo_path) == 0) { + res = lxcProcReadMeminfo(hostpath, def, buf, size, offset); + } else + return -ENOENT; + + if (res < 0) { + if((res = lxcProcHostRead(hostpath, buf, size, offset)) < 0) + virReportSystemError(errno, "%s", _("failed to show host's meminfo\n")); + } + VIR_FREE(hostpath); + return res; } static struct fuse_operations lxcProcOper = { -- 1.7.7.6

we already have virtualize meminfo for container in fuse filesystem, add function lxcContainerMountProcFuse to mount this meminfo file to the container's /proc/meminfo. So we isolate container's /proc/meminfo now. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_container.c | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 145accb..5e0cf06 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -520,6 +520,27 @@ cleanup: return rc; } +static int lxcContainerMountProcFuse(virDomainDefPtr def, + const char *srcprefix) +{ + int ret; + char *meminfo_path = NULL; + + if ((ret = virAsprintf(&meminfo_path, + "%s/%s/%s/meminfo", + srcprefix, LXC_STATE_DIR, + def->name)) < 0) + return ret; + + if ((ret = mount(meminfo_path, "/proc/meminfo", + NULL, MS_BIND, NULL)) < 0) { + virReportSystemError(errno, + _("Failed to mount %s on /proc/meminfo"), + meminfo_path); + } + VIR_FREE(meminfo_path); + return ret; +} static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root) { @@ -1430,6 +1451,10 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef, if (lxcContainerMountBasicFS(vmDef, true, securityDriver) < 0) goto cleanup; + /* Mounts /proc/meminfo etc sysinfo */ + if (lxcContainerMountProcFuse(vmDef, "/.oldroot") < 0) + goto cleanup; + /* Now we can re-mount the cgroups controllers in the * same configuration as before */ if (lxcContainerMountCGroups(mounts, nmounts) < 0) @@ -1509,6 +1534,10 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef, if (lxcContainerMountBasicFS(vmDef, false, securityDriver) < 0) goto cleanup; + /* Mounts /proc/meminfo etc sysinfo */ + if (lxcContainerMountProcFuse(vmDef, "/.oldroot") < 0) + goto cleanup; + /* Now we can re-mount the cgroups controllers in the * same configuration as before */ if (lxcContainerMountCGroups(mounts, nmounts) < 0) -- 1.7.7.6

On Wed, Jul 11, 2012 at 03:58:19PM +0800, Gao feng wrote:
add a configure option --with-fuse to prepare introduction of fuse support for libvirt lxc.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- configure.ac | 45 +++++++++++++++++++++++++++++++++++++++++++++ libvirt.spec.in | 9 +++++++++ 2 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/configure.ac b/configure.ac index d45f4f1..d5cf45f 100644 --- a/configure.ac +++ b/configure.ac @@ -1694,7 +1694,47 @@ AM_CONDITIONAL([HAVE_CAPNG], [test "$with_capng" != "no"]) AC_SUBST([CAPNG_CFLAGS]) AC_SUBST([CAPNG_LIBS])
+dnl libfuse +AC_ARG_WITH([fuse], + AC_HELP_STRING([--with-fuse], [use libfuse to proivde fuse filesystem support for libvirt lxc]), + [], + [with_fuse=check])
+dnl +dnl This check looks for 'fuse' +dnl +FUSE_CFLAGS= +FUSE_LIBS= +if test "$with_fuse" != "no"; then + old_cflags="$CFLAGS" + old_libs="$LIBS" + old_cppflags="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" + if test "$with_fuse" = "check"; then + AC_CHECK_HEADER([fuse.h], [], [with_fuse=no]) + AC_CHECK_LIB([fuse], [fuse_main], [], [with_fuse=no]) + if test "$with_fuse" != "no"; then + with_fuse="yes" + fi + else + fail=0 + AC_CHECK_HEADER([fuse.h], [], [fail=1]) + AC_CHECK_LIB([fuse], [fuse_main], [], [fail=1]) + test $fail = 1 && + AC_MSG_ERROR([You must install the fuse >= 2.9.0 development package in order to compile and run libvirt]) + fi + CFLAGS="$old_cflags" + LIBS="$old_libs" + CPPFLAGS="$old_cppflags" +fi +if test "$with_fuse" = "yes"; then + FUSE_LIBS="-lfuse" + FUSE_CFLAGS="-D_FILE_OFFSET_BITS=64" + AC_DEFINE_UNQUOTED([HAVE_FUSE], 1, [Whether fuse is available for privilege reduction]) +fi +AM_CONDITIONAL([HAVE_FUSE], [test "$with_fuse" != "no"]) +AC_SUBST([FUSE_CFLAGS]) +AC_SUBST([FUSE_LIBS])
FUSE includes a pkg-config file, so you can remove almost all of this code here and just use PKG_CONFIG_CHECK 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 :|

于 2012年07月11日 17:24, Daniel P. Berrange 写道:
On Wed, Jul 11, 2012 at 03:58:19PM +0800, Gao feng wrote:
add a configure option --with-fuse to prepare introduction of fuse support for libvirt lxc.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- configure.ac | 45 +++++++++++++++++++++++++++++++++++++++++++++ libvirt.spec.in | 9 +++++++++ 2 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/configure.ac b/configure.ac index d45f4f1..d5cf45f 100644 --- a/configure.ac +++ b/configure.ac @@ -1694,7 +1694,47 @@ AM_CONDITIONAL([HAVE_CAPNG], [test "$with_capng" != "no"]) AC_SUBST([CAPNG_CFLAGS]) AC_SUBST([CAPNG_LIBS])
+dnl libfuse +AC_ARG_WITH([fuse], + AC_HELP_STRING([--with-fuse], [use libfuse to proivde fuse filesystem support for libvirt lxc]), + [], + [with_fuse=check])
+dnl +dnl This check looks for 'fuse' +dnl +FUSE_CFLAGS= +FUSE_LIBS= +if test "$with_fuse" != "no"; then + old_cflags="$CFLAGS" + old_libs="$LIBS" + old_cppflags="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" + if test "$with_fuse" = "check"; then + AC_CHECK_HEADER([fuse.h], [], [with_fuse=no]) + AC_CHECK_LIB([fuse], [fuse_main], [], [with_fuse=no]) + if test "$with_fuse" != "no"; then + with_fuse="yes" + fi + else + fail=0 + AC_CHECK_HEADER([fuse.h], [], [fail=1]) + AC_CHECK_LIB([fuse], [fuse_main], [], [fail=1]) + test $fail = 1 && + AC_MSG_ERROR([You must install the fuse >= 2.9.0 development package in order to compile and run libvirt]) + fi + CFLAGS="$old_cflags" + LIBS="$old_libs" + CPPFLAGS="$old_cppflags" +fi +if test "$with_fuse" = "yes"; then + FUSE_LIBS="-lfuse" + FUSE_CFLAGS="-D_FILE_OFFSET_BITS=64" + AC_DEFINE_UNQUOTED([HAVE_FUSE], 1, [Whether fuse is available for privilege reduction]) +fi +AM_CONDITIONAL([HAVE_FUSE], [test "$with_fuse" != "no"]) +AC_SUBST([FUSE_CFLAGS]) +AC_SUBST([FUSE_LIBS])
FUSE includes a pkg-config file, so you can remove almost all of this code here and just use PKG_CONFIG_CHECK
I see,I will change this in next version. Thanks!
participants (2)
-
Daniel P. Berrange
-
Gao feng