[libvirt] [PATCH v5 1/6] add a configure option --with-fuse to prepare introduction of fuse support for libvirt lxc

add a configure option --with-fuse to prepare introduction of fuse support for libvirt lxc. With help from Daniel Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- configure.ac | 36 ++++++++++++++++++++++++++++++++++++ libvirt.spec.in | 9 +++++++++ 2 files changed, 45 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index 8810efd..0cac7fd 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,7 @@ LIBSSH2_REQUIRED="1.0" LIBSSH2_TRANSPORT_REQUIRED="1.3" LIBBLKID_REQUIRED="2.17" DBUS_REQUIRED="1.0.0" +FUSE_REQUIRED="2.8.6" dnl Checks for C compiler. AC_PROG_CC @@ -1857,6 +1858,36 @@ 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 "x$with_fuse" != "xno"; then + PKG_CHECK_MODULES([FUSE], [fuse >= $FUSE_REQUIRED], + [with_fuse=yes], [ + if test "x$with_fuse" = "xcheck" ; then + with_fuse=no + else + AC_MSG_ERROR( + [You must install fuse Library to compile libvirt]) + fi + ]) + if test "x$with_fuse" = "xyes" ; then + FUSE_LIBS="-lfuse" + FUSE_CFLAGS="-D_FILE_OFFSET_BITS=64" + AC_DEFINE_UNQUOTED([HAVE_FUSE], 1, [whether fuse is available for libvirt lxc]) + fi +fi +AM_CONDITIONAL([HAVE_FUSE], [test "x$with_fuse" = "xyes"]) +AC_SUBST([FUSE_CFLAGS]) +AC_SUBST([FUSE_LIBS]) + dnl virsh libraries AC_CHECK_HEADERS([readline/readline.h]) @@ -3161,6 +3192,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 511949e..8fe0d77 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -93,6 +93,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} @@ -503,6 +504,9 @@ BuildRequires: numactl-devel %if %{with_capng} BuildRequires: libcap-ng-devel >= 0.5.0 %endif +%if %{with_fuse} +BuildRequires: fuse-devel >= 2.8.6 +%endif %if %{with_phyp} || %{with_libssh2_transport} %if %{with_libssh2_transport} BuildRequires: libssh2-devel >= 1.3.0 @@ -1186,6 +1190,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 @@ -1289,6 +1297,7 @@ autoreconf -if %{?_without_numactl} \ %{?_without_numad} \ %{?_without_capng} \ + %{?_without_fuse} \ %{?_without_netcf} \ %{?_without_selinux} \ %{?_with_selinux_mount} \ -- 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-containename-fuse,mount point is localstatedir/run/libvirt/lxc/containername. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- po/POTFILES.in | 1 + src/Makefile.am | 9 ++- src/lxc/lxc_cgroup.c | 1 + src/lxc/lxc_container.h | 3 + src/lxc/lxc_controller.c | 26 +++++++ src/lxc/lxc_fuse.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_fuse.h | 40 +++++++++++ src/lxc/lxc_process.c | 1 + 8 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 src/lxc/lxc_fuse.c create mode 100644 src/lxc/lxc_fuse.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 9768528..0199d6f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -50,6 +50,7 @@ src/locking/lock_driver_sanlock.c src/locking/lock_manager.c src/locking/sanlock_helper.c src/lxc/lxc_cgroup.c +src/lxc/lxc_fuse.c src/lxc/lxc_container.c src/lxc/lxc_conf.c src/lxc/lxc_controller.c diff --git a/src/Makefile.am b/src/Makefile.am index 187663f..e7b2bd6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -413,6 +413,7 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_domain.c lxc/lxc_domain.h \ lxc/lxc_monitor.c lxc/lxc_monitor.h \ lxc/lxc_process.c lxc/lxc_process.h \ + lxc/lxc_fuse.c lxc/lxc_fuse.h \ lxc/lxc_driver.c lxc/lxc_driver.h LXC_CONTROLLER_SOURCES = \ @@ -421,6 +422,7 @@ LXC_CONTROLLER_SOURCES = \ lxc/lxc_conf.c lxc/lxc_conf.h \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ + lxc/lxc_fuse.c lxc/lxc_fuse.h \ lxc/lxc_controller.c SECURITY_DRIVER_APPARMOR_HELPER_SOURCES = \ @@ -911,8 +913,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) @@ -1672,6 +1675,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_security_manager.la \ @@ -1690,7 +1694,8 @@ endif libvirt_lxc_CFLAGS = \ -I$(top_srcdir)/src/conf \ $(AM_CFLAGS) \ - $(LIBNL_CFLAGS) + $(LIBNL_CFLAGS) \ + $(FUSE_CFLAGS) if HAVE_LIBBLKID libvirt_lxc_CFLAGS += $(BLKID_CFLAGS) libvirt_lxc_LDADD += $(BLKID_LIBS) diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index bdfaa54..9a5ba1a 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -163,6 +163,7 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM}, {'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_TTY}, {'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX}, + {'c', LXC_DEV_MAJ_FUSE, LXC_DEV_MIN_FUSE}, {0, 0, 0}}; rc = virCgroupDenyAllDevices(cgroup); diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h index b1adacb..c8c70e0 100644 --- a/src/lxc/lxc_container.h +++ b/src/lxc/lxc_container.h @@ -46,6 +46,9 @@ enum { # define LXC_DEV_MAJ_PTY 136 +# define LXC_DEV_MAJ_FUSE 10 +# define LXC_DEV_MIN_FUSE 229 + int lxcContainerSendContinue(int control); int lxcContainerWaitForContinue(int control); diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index a41c903..9c0a10c 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -60,6 +60,7 @@ #include "lxc_container.h" #include "lxc_cgroup.h" #include "lxc_protocol.h" +#include "lxc_fuse.h" #include "virnetdev.h" #include "virnetdevveth.h" #include "memory.h" @@ -1245,6 +1246,28 @@ cleanup: return ret; } +static int +virLXCControllerSetupFuse(virLXCControllerPtr ctrl) +{ + int try = 0; + virThread thread; + if (virThreadCreate(&thread, true, lxcRegisterFuse, + (void *)ctrl->def) < 0) + return -1; + /* + * because libvirt_lxc may use fuse filesystem before fuse being + * mounted by the thread. so wait 3 seconds in libvirt_lxc. if fuse + * is not mounted in 3 seconds, libvirt_lxc will exit. + */ + while (try++ < 2) { + if (lxcRegisterFuseSuccess(ctrl->def)) + return 0; + + sleep(1); + } + + return -1; +} static int virLXCControllerSetupConsoles(virLXCControllerPtr ctrl, @@ -1388,6 +1411,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl) if (virLXCControllerSetupDevPTS(ctrl) < 0) goto cleanup; + if (virLXCControllerSetupFuse(ctrl) < 0) + goto cleanup; + if (virLXCControllerSetupConsoles(ctrl, containerTTYPaths) < 0) goto cleanup; diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c new file mode 100644 index 0000000..f7615a2 --- /dev/null +++ b/src/lxc/lxc_fuse.c @@ -0,0 +1,172 @@ +/* + * 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 <mntent.h> + +#include "lxc_fuse.h" +#include "virterror_internal.h" +#include "logging.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 (STREQ(path, "/")) { + 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 (!STREQ(path, "/")) + 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, +}; + +void lxcRegisterFuse(void *opaque) +{ + int argc = 4; + char *argv[argc]; + char *path = NULL; + char *name = NULL; + virDomainDefPtr DomainDef = (virDomainDefPtr) opaque; + + if (virAsprintf(&name, "Lxc-%s-fuse", DomainDef->name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virAsprintf(&path, "%s/%s/", LXC_STATE_DIR, DomainDef->name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileMakePath(path) < 0) { + virReportSystemError(errno, _("Cannot create %s"), path); + goto cleanup; + } + + argv[0] = name; + argv[1] = path; + argv[2] = (char *)"-odirect_io"; + argv[3] = (char *)"-f"; + + if (fuse_main(argc, argv, &lxcProcOper, DomainDef) < 0) + virReportSystemError(errno, "%s", _("Cannot start fuse")); + +cleanup: + VIR_FREE(name); + VIR_FREE(path); + return; +} + +int lxcRegisterFuseSuccess(virDomainDefPtr def) +{ + FILE *procmnt = NULL; + struct mntent mntent; + char mntbuf[1024]; + char *name = NULL; + int ret = 0; + + if (!(procmnt = setmntent("/proc/mounts", "r"))) { + virReportSystemError(errno, "%s", + _("Failed to read /proc/mounts")); + return ret; + } + + if (virAsprintf(&name, "Lxc-%s-fuse", def->name) < 0) { + virReportOOMError(); + goto cleanup; + } + + while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) { + VIR_DEBUG("Got %s == %s ?\n",mntent.mnt_fsname, name); + if (STRNEQ(mntent.mnt_fsname, name)) + continue; + + ret = 1; + break; + } + +cleanup: + endmntent(procmnt); + VIR_FREE(name); + return ret; +} + +#else +void lxcRegisterFuse(void *opaque ATTRIBUTE_UNUSED) +{ +} + +int lxcRegisterFuseSuccess(virDomainDefPtr def ATTRIBUTE_UNUSED) +{ + return 1; +} +#endif diff --git a/src/lxc/lxc_fuse.h b/src/lxc/lxc_fuse.h new file mode 100644 index 0000000..1937ad8 --- /dev/null +++ b/src/lxc/lxc_fuse.h @@ -0,0 +1,40 @@ +/* + * 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" +#include "util.h" +#include "memory.h" + +extern void lxcRegisterFuse(void *opaque); +extern int lxcRegisterFuseSuccess(virDomainDefPtr def); +#endif diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 079bc3a..a9a0984 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -28,6 +28,7 @@ #include "lxc_process.h" #include "lxc_domain.h" #include "lxc_container.h" +#include "lxc_fuse.h" #include "datatypes.h" #include "virfile.h" #include "virpidfile.h" -- 1.7.7.6

On Thu, Oct 25, 2012 at 06:38:23PM +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-containename-fuse,mount point is localstatedir/run/libvirt/lxc/containername.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- po/POTFILES.in | 1 + src/Makefile.am | 9 ++- src/lxc/lxc_cgroup.c | 1 + src/lxc/lxc_container.h | 3 + src/lxc/lxc_controller.c | 26 +++++++ src/lxc/lxc_fuse.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_fuse.h | 40 +++++++++++ src/lxc/lxc_process.c | 1 + 8 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 src/lxc/lxc_fuse.c create mode 100644 src/lxc/lxc_fuse.h
diff --git a/po/POTFILES.in b/po/POTFILES.in index 9768528..0199d6f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -50,6 +50,7 @@ src/locking/lock_driver_sanlock.c src/locking/lock_manager.c src/locking/sanlock_helper.c src/lxc/lxc_cgroup.c +src/lxc/lxc_fuse.c src/lxc/lxc_container.c src/lxc/lxc_conf.c src/lxc/lxc_controller.c diff --git a/src/Makefile.am b/src/Makefile.am index 187663f..e7b2bd6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -413,6 +413,7 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_domain.c lxc/lxc_domain.h \ lxc/lxc_monitor.c lxc/lxc_monitor.h \ lxc/lxc_process.c lxc/lxc_process.h \ + lxc/lxc_fuse.c lxc/lxc_fuse.h \ lxc/lxc_driver.c lxc/lxc_driver.h
LXC_CONTROLLER_SOURCES = \ @@ -421,6 +422,7 @@ LXC_CONTROLLER_SOURCES = \ lxc/lxc_conf.c lxc/lxc_conf.h \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ + lxc/lxc_fuse.c lxc/lxc_fuse.h \ lxc/lxc_controller.c
SECURITY_DRIVER_APPARMOR_HELPER_SOURCES = \ @@ -911,8 +913,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) @@ -1672,6 +1675,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_security_manager.la \ @@ -1690,7 +1694,8 @@ endif libvirt_lxc_CFLAGS = \ -I$(top_srcdir)/src/conf \ $(AM_CFLAGS) \ - $(LIBNL_CFLAGS) + $(LIBNL_CFLAGS) \ + $(FUSE_CFLAGS) if HAVE_LIBBLKID libvirt_lxc_CFLAGS += $(BLKID_CFLAGS) libvirt_lxc_LDADD += $(BLKID_LIBS) diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index bdfaa54..9a5ba1a 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -163,6 +163,7 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, {'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM}, {'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_TTY}, {'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX}, + {'c', LXC_DEV_MAJ_FUSE, LXC_DEV_MIN_FUSE}, {0, 0, 0}};
rc = virCgroupDenyAllDevices(cgroup); diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h index b1adacb..c8c70e0 100644 --- a/src/lxc/lxc_container.h +++ b/src/lxc/lxc_container.h @@ -46,6 +46,9 @@ enum {
# define LXC_DEV_MAJ_PTY 136
+# define LXC_DEV_MAJ_FUSE 10 +# define LXC_DEV_MIN_FUSE 229 + int lxcContainerSendContinue(int control); int lxcContainerWaitForContinue(int control);
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index a41c903..9c0a10c 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -60,6 +60,7 @@ #include "lxc_container.h" #include "lxc_cgroup.h" #include "lxc_protocol.h" +#include "lxc_fuse.h" #include "virnetdev.h" #include "virnetdevveth.h" #include "memory.h" @@ -1245,6 +1246,28 @@ cleanup: return ret; }
+static int +virLXCControllerSetupFuse(virLXCControllerPtr ctrl) +{ + int try = 0; + virThread thread; + if (virThreadCreate(&thread, true, lxcRegisterFuse, + (void *)ctrl->def) < 0) + return -1; + /* + * because libvirt_lxc may use fuse filesystem before fuse being + * mounted by the thread. so wait 3 seconds in libvirt_lxc. if fuse + * is not mounted in 3 seconds, libvirt_lxc will exit. + */ + while (try++ < 2) { + if (lxcRegisterFuseSuccess(ctrl->def)) + return 0; + + sleep(1); + } + + return -1; +}
static int virLXCControllerSetupConsoles(virLXCControllerPtr ctrl, @@ -1388,6 +1411,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl) if (virLXCControllerSetupDevPTS(ctrl) < 0) goto cleanup;
+ if (virLXCControllerSetupFuse(ctrl) < 0) + goto cleanup; + if (virLXCControllerSetupConsoles(ctrl, containerTTYPaths) < 0) goto cleanup;
diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c new file mode 100644 index 0000000..f7615a2 --- /dev/null +++ b/src/lxc/lxc_fuse.c @@ -0,0 +1,172 @@ +/* + * 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 <mntent.h> + +#include "lxc_fuse.h" +#include "virterror_internal.h" +#include "logging.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 (STREQ(path, "/")) { + 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 (!STREQ(path, "/")) + 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, +}; + +void lxcRegisterFuse(void *opaque) +{ + int argc = 4; + char *argv[argc]; + char *path = NULL; + char *name = NULL; + virDomainDefPtr DomainDef = (virDomainDefPtr) opaque;
It is common practice to just use 'def' as the variable names in this scenario. Also there is never any need to cast from a 'void *' pointer in C (as opposed to C++ which does require casts).
+ + if (virAsprintf(&name, "Lxc-%s-fuse", DomainDef->name) < 0) { + virReportOOMError(); + goto cleanup; + }
I wonder if we should just simplify this and use the fixed name 'libvirt'. Since these mounts are only visible inside the container, I don't think there's a huge need for customized unique names.
+ + if (virAsprintf(&path, "%s/%s/", LXC_STATE_DIR, DomainDef->name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileMakePath(path) < 0) { + virReportSystemError(errno, _("Cannot create %s"), path); + goto cleanup; + } + + argv[0] = name; + argv[1] = path; + argv[2] = (char *)"-odirect_io"; + argv[3] = (char *)"-f"; + + if (fuse_main(argc, argv, &lxcProcOper, DomainDef) < 0) + virReportSystemError(errno, "%s", _("Cannot start fuse")); + +cleanup: + VIR_FREE(name); + VIR_FREE(path); + return; +} + +int lxcRegisterFuseSuccess(virDomainDefPtr def) +{ + FILE *procmnt = NULL; + struct mntent mntent; + char mntbuf[1024]; + char *name = NULL; + int ret = 0; + + if (!(procmnt = setmntent("/proc/mounts", "r"))) { + virReportSystemError(errno, "%s", + _("Failed to read /proc/mounts")); + return ret; + } + + if (virAsprintf(&name, "Lxc-%s-fuse", def->name) < 0) { + virReportOOMError(); + goto cleanup; + }
Likewise here just called it 'libvirt'
+ + while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) { + VIR_DEBUG("Got %s == %s ?\n",mntent.mnt_fsname, name); + if (STRNEQ(mntent.mnt_fsname, name)) + continue; + + ret = 1; + break; + } + +cleanup: + endmntent(procmnt); + VIR_FREE(name); + return ret; +} + +#else +void lxcRegisterFuse(void *opaque ATTRIBUTE_UNUSED) +{ +} + +int lxcRegisterFuseSuccess(virDomainDefPtr def ATTRIBUTE_UNUSED) +{ + return 1; +} +#endif diff --git a/src/lxc/lxc_fuse.h b/src/lxc/lxc_fuse.h new file mode 100644 index 0000000..1937ad8 --- /dev/null +++ b/src/lxc/lxc_fuse.h @@ -0,0 +1,40 @@ +/* + * 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" +#include "util.h" +#include "memory.h"
make syntax-check ought to complain about bogus indentation here in all these macros.
+ +extern void lxcRegisterFuse(void *opaque); +extern int lxcRegisterFuseSuccess(virDomainDefPtr def); +#endif diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 079bc3a..a9a0984 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -28,6 +28,7 @@ #include "lxc_process.h" #include "lxc_domain.h" #include "lxc_container.h" +#include "lxc_fuse.h" #include "datatypes.h" #include "virfile.h" #include "virpidfile.h"
ACK with the minor chanes described 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 :|

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 60f9c7f..5dda1ec 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -97,6 +97,7 @@ virCgroupGetCpuacctUsage; virCgroupGetCpusetCpus; virCgroupGetCpusetMems; virCgroupGetFreezerState; +virCgroupGetMemSwapUsage; virCgroupGetMemSwapHardLimit; virCgroupGetMemoryHardLimit; virCgroupGetMemorySoftLimit; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 3f7b5f7..4aae70d 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -1371,6 +1371,26 @@ int virCgroupGetMemSwapHardLimit(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; +} + +/** * virCgroupSetCpusetMems: * * @group: The cgroup to set cpuset.mems for diff --git a/src/util/cgroup.h b/src/util/cgroup.h index 38fa4b7..0c11eb1 100644 --- a/src/util/cgroup.h +++ b/src/util/cgroup.h @@ -92,6 +92,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

On Thu, Oct 25, 2012 at 06:38:24PM +0800, Gao feng wrote:
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(-)
ACK 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 :|

because libvirt_lxc's cgroup mountpoint is what it shown in /proc/self/cgroup. we can get container's cgroup through virCgroupNew("/", &group), add interface virCgroupGetAppRoot to help container to get it's cgroup. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/libvirt_private.syms | 1 + src/util/cgroup.c | 15 +++++++++++++++ src/util/cgroup.h | 2 ++ 3 files changed, 18 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5dda1ec..0a07c25 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -84,6 +84,7 @@ virCgroupDenyDeviceMajor; virCgroupDenyDevicePath; virCgroupForDomain; virCgroupForDriver; +virCgroupGetAppRoot; virCgroupForEmulator; virCgroupForVcpu; virCgroupFree; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 4aae70d..9777ad5 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -965,6 +965,21 @@ int virCgroupForDriver(const char *name ATTRIBUTE_UNUSED, } #endif +/** +* virCgroupGetAppRoot: +* +* @group: Pointer to returned virCgroupPtr +* +* Returns 0 on success +*/ +int virCgroupGetAppRoot(virCgroupPtr *group) +{ +#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R + return virCgroupNew("/", group); +#else + return -ENXIO; +#endif +} /** * virCgroupForDomain: diff --git a/src/util/cgroup.h b/src/util/cgroup.h index 0c11eb1..e26f65f 100644 --- a/src/util/cgroup.h +++ b/src/util/cgroup.h @@ -47,6 +47,8 @@ int virCgroupForDriver(const char *name, int privileged, int create); +int virCgroupGetAppRoot(virCgroupPtr *group); + int virCgroupForDomain(virCgroupPtr driver, const char *name, virCgroupPtr *group, -- 1.7.7.6

On Thu, Oct 25, 2012 at 06:38:25PM +0800, Gao feng wrote:
because libvirt_lxc's cgroup mountpoint is what it shown in /proc/self/cgroup.
we can get container's cgroup through virCgroupNew("/", &group), add interface virCgroupGetAppRoot to help container to get it's cgroup.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/libvirt_private.syms | 1 + src/util/cgroup.c | 15 +++++++++++++++ src/util/cgroup.h | 2 ++ 3 files changed, 18 insertions(+), 0 deletions(-)
ACK 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 :|

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_cgroup.c | 139 +++++++++++++++++++++++++++++++++++ src/lxc/lxc_cgroup.h | 2 +- src/lxc/lxc_fuse.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++- src/lxc/lxc_fuse.h | 14 ++++ 4 files changed, 349 insertions(+), 4 deletions(-) diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 9a5ba1a..543a7fe 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -23,6 +23,8 @@ #include "lxc_cgroup.h" #include "lxc_container.h" +#include "lxc_fuse.h" +#include "virfile.h" #include "virterror_internal.h" #include "logging.h" #include "memory.h" @@ -137,6 +139,143 @@ cleanup: return ret; } +static int virLXCCgroupGetMemSwapUsage(virCgroupPtr cgroup, + unsigned long long *usage) +{ + return virCgroupGetMemSwapUsage(cgroup, usage); +} + + +static int virLXCCgroupGetMemSwapTotal(virCgroupPtr cgroup, + unsigned long long *total) +{ + return virCgroupGetMemSwapHardLimit(cgroup, total); +} + + +static int virLXCCgroupGetMemUsage(virCgroupPtr cgroup, + unsigned long long *usage) +{ + int ret; + unsigned long memUsage; + + ret = virCgroupGetMemoryUsage(cgroup, &memUsage); + *usage = (unsigned long long) memUsage; + + return ret; +} + + +static int virLXCCgroupGetMemTotal(virCgroupPtr cgroup, + unsigned long long *total) +{ + return virCgroupGetMemoryHardLimit(cgroup, total); +} + + +static int virLXCCgroupGetMemStat(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 = -errno; + 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 (virStrToLong_ull(value + 1, NULL, 10, &stat_value) < 0) { + ret = -EINVAL; + goto out; + } + if (STREQ(line, "cache")) + meminfo[VIR_LXC_FUSE_CACHED] = stat_value >> 10; + else if (STREQ(line, "inactive_anon")) + meminfo[VIR_LXC_FUSE_INACTIVE_ANON] = stat_value >> 10; + else if (STREQ(line, "active_anon")) + meminfo[VIR_LXC_FUSE_ACTIVE_ANON] = stat_value >> 10; + else if (STREQ(line, "inactive_file")) + meminfo[VIR_LXC_FUSE_INACTIVE_FILE] = stat_value >> 10; + else if (STREQ(line, "active_file")) + meminfo[VIR_LXC_FUSE_ACTIVE_FILE] = stat_value >> 10; + else if (STREQ(line, "unevictable")) + meminfo[VIR_LXC_FUSE_UNEVICTABLE] = stat_value >> 10; + } + ret = 0; +out: + VIR_FORCE_FCLOSE(statfd); +out_free: + VIR_FREE(statFile); + return ret; +} + + +int virLXCCgroupGetMeminfo(unsigned long long *meminfo) +{ + int ret; + virCgroupPtr cgroup; + + ret = virCgroupGetAppRoot(&cgroup); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get cgroup for container")); + return ret; + } + + ret = virLXCCgroupGetMemStat(cgroup, meminfo); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat info")); + goto out; + } + + ret = virLXCCgroupGetMemTotal(cgroup, &meminfo[VIR_LXC_FUSE_MEMTOTAL]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup total")); + goto out; + } + + ret = virLXCCgroupGetMemUsage(cgroup, &meminfo[VIR_LXC_FUSE_MEMUSAGE]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat usage")); + goto out; + } + + virLXCCgroupGetMemSwapTotal(cgroup, &meminfo[VIR_LXC_FUSE_SWAPTOTAL]); + virLXCCgroupGetMemSwapUsage(cgroup, &meminfo[VIR_LXC_FUSE_SWAPUSAGE]); + + ret = 0; +out: + virCgroupFree(&cgroup); + + return ret; +} typedef struct _virLXCCgroupDevicePolicy virLXCCgroupDevicePolicy; typedef virLXCCgroupDevicePolicy *virLXCCgroupDevicePolicyPtr; diff --git a/src/lxc/lxc_cgroup.h b/src/lxc/lxc_cgroup.h index 6fc68df..29d0aed 100644 --- a/src/lxc/lxc_cgroup.h +++ b/src/lxc/lxc_cgroup.h @@ -25,5 +25,5 @@ # include "domain_conf.h" int virLXCCgroupSetup(virDomainDefPtr def); - +int virLXCCgroupGetMeminfo(unsigned long long *meminfo); #endif /* __VIR_LXC_CGROUP_H__ */ diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c index f7615a2..b0b148a 100644 --- a/src/lxc/lxc_fuse.c +++ b/src/lxc/lxc_fuse.c @@ -30,26 +30,49 @@ #include <mntent.h> #include "lxc_fuse.h" +#include "lxc_cgroup.h" #include "virterror_internal.h" #include "logging.h" +#include "virfile.h" #define VIR_FROM_THIS VIR_FROM_LXC #if HAVE_FUSE +static const char *fuse_meminfo_path = "/meminfo"; + static int lxcProcGetattr(const char *path, struct stat *stbuf) { - int res = 0; + int res; + char *mempath = NULL; + struct stat sb; memset(stbuf, 0, sizeof(struct stat)); + if (virAsprintf(&mempath, "/proc/%s", path) < 0) { + virReportOOMError(); + return -errno; + } + + res = 0; if (STREQ(path, "/")) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; + } else if (STREQ(path, fuse_meminfo_path)) { + stat(mempath, &sb); + stbuf->st_mode = sb.st_mode; + 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; } @@ -63,6 +86,7 @@ static int lxcProcReaddir(const char *path, void *buf, filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); + filler(buf, fuse_meminfo_path + 1, NULL, 0); return 0; } @@ -70,7 +94,153 @@ static int lxcProcReaddir(const char *path, void *buf, static int lxcProcOpen(const char *path ATTRIBUTE_UNUSED, struct fuse_file_info *fi ATTRIBUTE_UNUSED) { - return -ENOENT; + if (!STREQ(path, fuse_meminfo_path)) + return -ENOENT; + + if ((fi->flags & 3) != O_RDONLY) + return -EACCES; + + return 0; +} + +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; + + if ((res = pread(fd, buf, size, offset)) < 0) + res = -errno; + + VIR_FORCE_CLOSE(fd); + return res; +} + +static int lxcProcReadMeminfo(char *hostpath, virDomainDefPtr def, + char *buf, size_t size, off_t offset) +{ + int copied = 0; + int res; + FILE *fd = NULL; + char line[1024]; + unsigned long long meminfo[VIR_LXC_FUSE_MEMMAX]; + memset(meminfo, 0, sizeof(meminfo)); + + if ((res = virLXCCgroupGetMeminfo(meminfo)) < 0) + return res; + + fd = fopen(hostpath, "r"); + if (fd == NULL) { + virReportSystemError(errno, _("Cannot open %s"), hostpath); + res = errno; + goto out; + } + + fseek(fd, offset, SEEK_SET); + + while (copied < 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 (STREQ(line, "MemTotal") && + (def->mem.hard_limit || def->mem.max_balloon)) { + if (virAsprintf(&new_line, "MemTotal: %8llu KB\n", + meminfo[VIR_LXC_FUSE_MEMTOTAL]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "MemFree") && + (def->mem.hard_limit || def->mem.max_balloon)) { + if (virAsprintf(&new_line, "MemFree: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_MEMTOTAL] - meminfo[VIR_LXC_FUSE_MEMUSAGE])) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Buffers")) { + if (virAsprintf(&new_line, "Buffers: %8d KB\n", 0) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Cached")) { + if (virAsprintf(&new_line, "Cached: %8llu KB\n", + meminfo[VIR_LXC_FUSE_CACHED]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Active")) { + if (virAsprintf(&new_line, "Active: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_ACTIVE_ANON] + meminfo[VIR_LXC_FUSE_ACTIVE_FILE])) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Inactive")) { + if (virAsprintf(&new_line, "Inactive: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_INACTIVE_ANON] + meminfo[VIR_LXC_FUSE_INACTIVE_FILE])) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Active(anon)")) { + if (virAsprintf(&new_line, "Active(anon): %8llu KB\n", + meminfo[VIR_LXC_FUSE_ACTIVE_ANON]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Inactive(anon)")) { + if (virAsprintf(&new_line, "Inactive(anon): %8llu KB\n", + meminfo[VIR_LXC_FUSE_INACTIVE_ANON]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Active(file)")) { + if (virAsprintf(&new_line, "Active(file): %8llu KB\n", + meminfo[VIR_LXC_FUSE_ACTIVE_FILE]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Inactive(file)")) { + if (virAsprintf(&new_line, "Inactive(file): %8llu KB\n", + meminfo[VIR_LXC_FUSE_INACTIVE_FILE]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Unevictable")) { + if (virAsprintf(&new_line, "Unevictable: %8llu KB\n", + meminfo[VIR_LXC_FUSE_UNEVICTABLE]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "SwapTotal") && def->mem.swap_hard_limit) { + if (virAsprintf(&new_line, "SwapTotal: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_SWAPTOTAL] - meminfo[VIR_LXC_FUSE_MEMTOTAL])) < 0) { + goto out_oom; + } + } else if (STREQ(line, "SwapFree") && def->mem.swap_hard_limit) { + if (virAsprintf(&new_line, "SwapFree: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_SWAPTOTAL] - meminfo[VIR_LXC_FUSE_MEMTOTAL] - + meminfo[VIR_LXC_FUSE_SWAPUSAGE] + meminfo[VIR_LXC_FUSE_MEMUSAGE])) < 0) { + goto out_oom; + } + } + *ptr=':'; + } + + len = strlen(new_line); + + if (copied + len > size) + len = size - copied; + + memcpy(buf + copied, new_line, len); + copied += len; + memset(line, 0, sizeof(line)); + if (new_line != line) + VIR_FREE(new_line); + } + res = copied; + +out: + VIR_FORCE_FCLOSE(fd); + return res; + +out_oom: + virReportOOMError(); + res = -errno; + goto out; } static int lxcProcRead(const char *path ATTRIBUTE_UNUSED, @@ -79,7 +249,29 @@ static int lxcProcRead(const char *path ATTRIBUTE_UNUSED, off_t offset ATTRIBUTE_UNUSED, struct fuse_file_info *fi ATTRIBUTE_UNUSED) { - return -ENOENT; + int res = -ENOENT; + char *hostpath = NULL; + struct fuse_context *context = NULL; + virDomainDefPtr def = NULL; + + if (virAsprintf(&hostpath, "/proc/%s", path) < 0) { + virReportOOMError(); + return -errno; + } + + context = fuse_get_context(); + def = (virDomainDefPtr)context->private_data; + + if (STREQ(path, fuse_meminfo_path)) { + if (((res = lxcProcReadMeminfo(hostpath, def, buf, size, offset)) < 0) && + ((res = lxcProcHostRead(hostpath, buf, size, offset)) < 0)) + goto out; + } + +out: + VIR_FREE(hostpath); + return res; + } static struct fuse_operations lxcProcOper = { diff --git a/src/lxc/lxc_fuse.h b/src/lxc/lxc_fuse.h index 1937ad8..dbebe96 100644 --- a/src/lxc/lxc_fuse.h +++ b/src/lxc/lxc_fuse.h @@ -35,6 +35,20 @@ #include "util.h" #include "memory.h" +enum { + VIR_LXC_FUSE_MEMTOTAL, + VIR_LXC_FUSE_MEMUSAGE, + VIR_LXC_FUSE_CACHED, + VIR_LXC_FUSE_ACTIVE_ANON, + VIR_LXC_FUSE_INACTIVE_ANON, + VIR_LXC_FUSE_ACTIVE_FILE, + VIR_LXC_FUSE_INACTIVE_FILE, + VIR_LXC_FUSE_UNEVICTABLE, + VIR_LXC_FUSE_SWAPTOTAL, + VIR_LXC_FUSE_SWAPUSAGE, + VIR_LXC_FUSE_MEMMAX, +}; + extern void lxcRegisterFuse(void *opaque); extern int lxcRegisterFuseSuccess(virDomainDefPtr def); #endif -- 1.7.7.6

On Thu, Oct 25, 2012 at 06:38:26PM +0800, Gao feng wrote:
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_cgroup.c | 139 +++++++++++++++++++++++++++++++++++ src/lxc/lxc_cgroup.h | 2 +- src/lxc/lxc_fuse.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++- src/lxc/lxc_fuse.h | 14 ++++ 4 files changed, 349 insertions(+), 4 deletions(-)
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 9a5ba1a..543a7fe 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -23,6 +23,8 @@
#include "lxc_cgroup.h" #include "lxc_container.h" +#include "lxc_fuse.h" +#include "virfile.h" #include "virterror_internal.h" #include "logging.h" #include "memory.h" @@ -137,6 +139,143 @@ cleanup: return ret; }
+static int virLXCCgroupGetMemSwapUsage(virCgroupPtr cgroup, + unsigned long long *usage) +{ + return virCgroupGetMemSwapUsage(cgroup, usage); +} + + +static int virLXCCgroupGetMemSwapTotal(virCgroupPtr cgroup, + unsigned long long *total) +{ + return virCgroupGetMemSwapHardLimit(cgroup, total); +} + + +static int virLXCCgroupGetMemUsage(virCgroupPtr cgroup, + unsigned long long *usage) +{ + int ret; + unsigned long memUsage; + + ret = virCgroupGetMemoryUsage(cgroup, &memUsage); + *usage = (unsigned long long) memUsage; + + return ret; +} + + +static int virLXCCgroupGetMemTotal(virCgroupPtr cgroup, + unsigned long long *total) +{ + return virCgroupGetMemoryHardLimit(cgroup, total); +} + + +static int virLXCCgroupGetMemStat(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 = -errno; + 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 (virStrToLong_ull(value + 1, NULL, 10, &stat_value) < 0) { + ret = -EINVAL; + goto out; + } + if (STREQ(line, "cache")) + meminfo[VIR_LXC_FUSE_CACHED] = stat_value >> 10; + else if (STREQ(line, "inactive_anon")) + meminfo[VIR_LXC_FUSE_INACTIVE_ANON] = stat_value >> 10; + else if (STREQ(line, "active_anon")) + meminfo[VIR_LXC_FUSE_ACTIVE_ANON] = stat_value >> 10; + else if (STREQ(line, "inactive_file")) + meminfo[VIR_LXC_FUSE_INACTIVE_FILE] = stat_value >> 10; + else if (STREQ(line, "active_file")) + meminfo[VIR_LXC_FUSE_ACTIVE_FILE] = stat_value >> 10; + else if (STREQ(line, "unevictable")) + meminfo[VIR_LXC_FUSE_UNEVICTABLE] = stat_value >> 10; + } + ret = 0; +out: + VIR_FORCE_FCLOSE(statfd); +out_free: + VIR_FREE(statFile);
There is no need for 2 separate labels here. Both of these cleanup calls are safe to invoke unconditionally, assuming the variables are initialized at the start of the method. Also normal naming is to use 'cleanup' not 'out'.
+ return ret; +} + + +int virLXCCgroupGetMeminfo(unsigned long long *meminfo) +{ + int ret; + virCgroupPtr cgroup; + + ret = virCgroupGetAppRoot(&cgroup); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get cgroup for container")); + return ret; + } + + ret = virLXCCgroupGetMemStat(cgroup, meminfo); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat info")); + goto out; + } + + ret = virLXCCgroupGetMemTotal(cgroup, &meminfo[VIR_LXC_FUSE_MEMTOTAL]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup total")); + goto out; + } + + ret = virLXCCgroupGetMemUsage(cgroup, &meminfo[VIR_LXC_FUSE_MEMUSAGE]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat usage")); + goto out; + } + + virLXCCgroupGetMemSwapTotal(cgroup, &meminfo[VIR_LXC_FUSE_SWAPTOTAL]); + virLXCCgroupGetMemSwapUsage(cgroup, &meminfo[VIR_LXC_FUSE_SWAPUSAGE]); + + ret = 0; +out:
Again use 'cleanup' as the name instead of 'out'.
+ virCgroupFree(&cgroup); + + return ret; +}
typedef struct _virLXCCgroupDevicePolicy virLXCCgroupDevicePolicy; typedef virLXCCgroupDevicePolicy *virLXCCgroupDevicePolicyPtr; +static const char *fuse_meminfo_path = "/meminfo"; + static int lxcProcGetattr(const char *path, struct stat *stbuf) { - int res = 0; + int res; + char *mempath = NULL; + struct stat sb;
memset(stbuf, 0, sizeof(struct stat)); + if (virAsprintf(&mempath, "/proc/%s", path) < 0) { + virReportOOMError(); + return -errno; + } + + res = 0;
if (STREQ(path, "/")) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; + } else if (STREQ(path, fuse_meminfo_path)) { + stat(mempath, &sb);
Error checking....
+ stbuf->st_mode = sb.st_mode; + 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; }
@@ -70,7 +94,153 @@ static int lxcProcReaddir(const char *path, void *buf, static int lxcProcOpen(const char *path ATTRIBUTE_UNUSED, struct fuse_file_info *fi ATTRIBUTE_UNUSED)
Remove the ATTRIBUTE_UNUSED annotations when you add the code below.
{ - return -ENOENT; + if (!STREQ(path, fuse_meminfo_path)) + return -ENOENT; + + if ((fi->flags & 3) != O_RDONLY) + return -EACCES; + + return 0; +}
+static int lxcProcReadMeminfo(char *hostpath, virDomainDefPtr def, + char *buf, size_t size, off_t offset) +{ + int copied = 0; + int res; + FILE *fd = NULL; + char line[1024]; + unsigned long long meminfo[VIR_LXC_FUSE_MEMMAX]; + memset(meminfo, 0, sizeof(meminfo)); + + if ((res = virLXCCgroupGetMeminfo(meminfo)) < 0) + return res; + + fd = fopen(hostpath, "r"); + if (fd == NULL) { + virReportSystemError(errno, _("Cannot open %s"), hostpath); + res = errno; + goto out; + } + + fseek(fd, offset, SEEK_SET); + + while (copied < 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 (STREQ(line, "MemTotal") && + (def->mem.hard_limit || def->mem.max_balloon)) { + if (virAsprintf(&new_line, "MemTotal: %8llu KB\n", + meminfo[VIR_LXC_FUSE_MEMTOTAL]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "MemFree") && + (def->mem.hard_limit || def->mem.max_balloon)) { + if (virAsprintf(&new_line, "MemFree: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_MEMTOTAL] - meminfo[VIR_LXC_FUSE_MEMUSAGE])) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Buffers")) { + if (virAsprintf(&new_line, "Buffers: %8d KB\n", 0) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Cached")) { + if (virAsprintf(&new_line, "Cached: %8llu KB\n", + meminfo[VIR_LXC_FUSE_CACHED]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Active")) { + if (virAsprintf(&new_line, "Active: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_ACTIVE_ANON] + meminfo[VIR_LXC_FUSE_ACTIVE_FILE])) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Inactive")) { + if (virAsprintf(&new_line, "Inactive: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_INACTIVE_ANON] + meminfo[VIR_LXC_FUSE_INACTIVE_FILE])) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Active(anon)")) { + if (virAsprintf(&new_line, "Active(anon): %8llu KB\n", + meminfo[VIR_LXC_FUSE_ACTIVE_ANON]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Inactive(anon)")) { + if (virAsprintf(&new_line, "Inactive(anon): %8llu KB\n", + meminfo[VIR_LXC_FUSE_INACTIVE_ANON]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Active(file)")) { + if (virAsprintf(&new_line, "Active(file): %8llu KB\n", + meminfo[VIR_LXC_FUSE_ACTIVE_FILE]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Inactive(file)")) { + if (virAsprintf(&new_line, "Inactive(file): %8llu KB\n", + meminfo[VIR_LXC_FUSE_INACTIVE_FILE]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "Unevictable")) { + if (virAsprintf(&new_line, "Unevictable: %8llu KB\n", + meminfo[VIR_LXC_FUSE_UNEVICTABLE]) < 0) { + goto out_oom; + } + } else if (STREQ(line, "SwapTotal") && def->mem.swap_hard_limit) { + if (virAsprintf(&new_line, "SwapTotal: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_SWAPTOTAL] - meminfo[VIR_LXC_FUSE_MEMTOTAL])) < 0) { + goto out_oom; + } + } else if (STREQ(line, "SwapFree") && def->mem.swap_hard_limit) { + if (virAsprintf(&new_line, "SwapFree: %8llu KB\n", + (meminfo[VIR_LXC_FUSE_SWAPTOTAL] - meminfo[VIR_LXC_FUSE_MEMTOTAL] - + meminfo[VIR_LXC_FUSE_SWAPUSAGE] + meminfo[VIR_LXC_FUSE_MEMUSAGE])) < 0) { + goto out_oom; + }
No need for '{}' around any of the above if() statements since they all have a single line body.
+ } + *ptr=':'; + } + + len = strlen(new_line); + + if (copied + len > size) + len = size - copied; + + memcpy(buf + copied, new_line, len); + copied += len; + memset(line, 0, sizeof(line)); + if (new_line != line) + VIR_FREE(new_line); + } + res = copied; + +out:
s/out/cleanup/
+ VIR_FORCE_FCLOSE(fd); + return res; + +out_oom:
s/out_oom/no_memory/
+ virReportOOMError(); + res = -errno; + goto out; }
static int lxcProcRead(const char *path ATTRIBUTE_UNUSED, @@ -79,7 +249,29 @@ static int lxcProcRead(const char *path ATTRIBUTE_UNUSED, off_t offset ATTRIBUTE_UNUSED, struct fuse_file_info *fi ATTRIBUTE_UNUSED) { - return -ENOENT; + int res = -ENOENT; + char *hostpath = NULL; + struct fuse_context *context = NULL; + virDomainDefPtr def = NULL; + + if (virAsprintf(&hostpath, "/proc/%s", path) < 0) { + virReportOOMError(); + return -errno; + } + + context = fuse_get_context(); + def = (virDomainDefPtr)context->private_data; + + if (STREQ(path, fuse_meminfo_path)) { + if (((res = lxcProcReadMeminfo(hostpath, def, buf, size, offset)) < 0) && + ((res = lxcProcHostRead(hostpath, buf, size, offset)) < 0)) + goto out; + } + +out:
s/out/cleanup/
+ VIR_FREE(hostpath); + return res; + }
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 :|

we already have virtualize meminfo for container through fuse filesystem, add function lxcContainerMountProcFuse to mount this meminfo file to the container's /proc/meminfo. So we can isolate container's /proc/meminfo from host now. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_container.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 2789c17..e8fdb37 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -595,6 +595,36 @@ cleanup: return rc; } +#if HAVE_FUSE +static int lxcContainerMountProcFuse(virDomainDefPtr def, + const char *srcprefix) +{ + int ret = 0; + 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; +} +#else +static int lxcContainerMountProcFuse(virDomainDefPtr def ATTRIBUTE_UNUSED, + const char *srcprefix ATTRIBUTE_UNUSED) +{ + return 0; +} +#endif static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root) { @@ -1550,6 +1580,10 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef, if (lxcContainerMountBasicFS(true, sec_mount_options) < 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, @@ -1640,6 +1674,10 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef, if (lxcContainerMountBasicFS(false, sec_mount_options) < 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, -- 1.7.7.6

On Thu, Oct 25, 2012 at 06:38:27PM +0800, Gao feng wrote:
we already have virtualize meminfo for container through fuse filesystem, add function lxcContainerMountProcFuse to mount this meminfo file to the container's /proc/meminfo.
So we can isolate container's /proc/meminfo from host now.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_container.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 2789c17..e8fdb37 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -595,6 +595,36 @@ cleanup: return rc; }
+#if HAVE_FUSE +static int lxcContainerMountProcFuse(virDomainDefPtr def, + const char *srcprefix) +{ + int ret = 0; + 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; +} +#else +static int lxcContainerMountProcFuse(virDomainDefPtr def ATTRIBUTE_UNUSED, + const char *srcprefix ATTRIBUTE_UNUSED) +{ + return 0; +} +#endif
static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root) { @@ -1550,6 +1580,10 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef, if (lxcContainerMountBasicFS(true, sec_mount_options) < 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, @@ -1640,6 +1674,10 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef, if (lxcContainerMountBasicFS(false, sec_mount_options) < 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,
ACK 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 :|

Hi Daniel Can you review this patch? Any comment is welcomed. Thanks Gao 于 2012年10月25日 18:38, Gao feng 写道:
add a configure option --with-fuse to prepare introduction of fuse support for libvirt lxc.
With help from Daniel
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- configure.ac | 36 ++++++++++++++++++++++++++++++++++++ libvirt.spec.in | 9 +++++++++ 2 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/configure.ac b/configure.ac index 8810efd..0cac7fd 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,7 @@ LIBSSH2_REQUIRED="1.0" LIBSSH2_TRANSPORT_REQUIRED="1.3" LIBBLKID_REQUIRED="2.17" DBUS_REQUIRED="1.0.0" +FUSE_REQUIRED="2.8.6"
dnl Checks for C compiler. AC_PROG_CC @@ -1857,6 +1858,36 @@ 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 "x$with_fuse" != "xno"; then + PKG_CHECK_MODULES([FUSE], [fuse >= $FUSE_REQUIRED], + [with_fuse=yes], [ + if test "x$with_fuse" = "xcheck" ; then + with_fuse=no + else + AC_MSG_ERROR( + [You must install fuse Library to compile libvirt]) + fi + ]) + if test "x$with_fuse" = "xyes" ; then + FUSE_LIBS="-lfuse" + FUSE_CFLAGS="-D_FILE_OFFSET_BITS=64" + AC_DEFINE_UNQUOTED([HAVE_FUSE], 1, [whether fuse is available for libvirt lxc]) + fi +fi +AM_CONDITIONAL([HAVE_FUSE], [test "x$with_fuse" = "xyes"]) +AC_SUBST([FUSE_CFLAGS]) +AC_SUBST([FUSE_LIBS]) +
dnl virsh libraries AC_CHECK_HEADERS([readline/readline.h]) @@ -3161,6 +3192,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 511949e..8fe0d77 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -93,6 +93,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} @@ -503,6 +504,9 @@ BuildRequires: numactl-devel %if %{with_capng} BuildRequires: libcap-ng-devel >= 0.5.0 %endif +%if %{with_fuse} +BuildRequires: fuse-devel >= 2.8.6 +%endif %if %{with_phyp} || %{with_libssh2_transport} %if %{with_libssh2_transport} BuildRequires: libssh2-devel >= 1.3.0 @@ -1186,6 +1190,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 @@ -1289,6 +1297,7 @@ autoreconf -if %{?_without_numactl} \ %{?_without_numad} \ %{?_without_capng} \ + %{?_without_fuse} \ %{?_without_netcf} \ %{?_without_selinux} \ %{?_with_selinux_mount} \

On Wed, Oct 31, 2012 at 06:28:06PM +0800, Gao feng wrote:
Hi Daniel
Can you review this patch? Any comment is welcomed.
It looks pretty good to me. Only a few cleanups required. I've also tested that it works correctly 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年11月02日 22:12, Daniel P. Berrange 写道:
On Wed, Oct 31, 2012 at 06:28:06PM +0800, Gao feng wrote:
Hi Daniel
Can you review this patch? Any comment is welcomed.
It looks pretty good to me. Only a few cleanups required. I've also tested that it works correctly
Thanks for your review. I will fix these cleanups and send v6 patchset. Thanks :)

On Thu, Oct 25, 2012 at 06:38:22PM +0800, Gao feng wrote:
add a configure option --with-fuse to prepare introduction of fuse support for libvirt lxc.
With help from Daniel
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- configure.ac | 36 ++++++++++++++++++++++++++++++++++++ libvirt.spec.in | 9 +++++++++ 2 files changed, 45 insertions(+), 0 deletions(-)
ACK 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 :|
participants (2)
-
Daniel P. Berrange
-
Gao feng