[libvirt] [PATCH v6 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 libvirt,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 | 157 ++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_fuse.h | 40 ++++++++++++ src/lxc/lxc_process.c | 1 + 8 files changed, 236 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..f0d28f8 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()) + 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..42107d7 --- /dev/null +++ b/src/lxc/lxc_fuse.c @@ -0,0 +1,157 @@ +/* + * 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, see + * <http://www.gnu.org/licenses/>. + */ + +#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; + virDomainDefPtr def = opaque; + + if (virAsprintf(&path, "%s/%s/", LXC_STATE_DIR, def->name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileMakePath(path) < 0) { + virReportSystemError(errno, _("Cannot create %s"), path); + goto cleanup; + } + + argv[0] = (char *)"libvirt"; + argv[1] = path; + argv[2] = (char *)"-odirect_io"; + argv[3] = (char *)"-f"; + + if (fuse_main(argc, argv, &lxcProcOper, def) < 0) + virReportSystemError(errno, "%s", _("Cannot start fuse")); + +cleanup: + VIR_FREE(path); + return; +} + +int lxcRegisterFuseSuccess(void) +{ + FILE *procmnt = NULL; + struct mntent mntent; + char mntbuf[1024]; + int ret = 0; + + if (!(procmnt = setmntent("/proc/mounts", "r"))) { + virReportSystemError(errno, "%s", + _("Failed to read /proc/mounts")); + return ret; + } + + while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) { + VIR_DEBUG("Got %s\n",mntent.mnt_fsname); + if (STRNEQ(mntent.mnt_fsname, "libvirt")) + continue; + + ret = 1; + break; + } + + endmntent(procmnt); + return ret; +} + +#else +void lxcRegisterFuse(void *opaque ATTRIBUTE_UNUSED) +{ +} + +int lxcRegisterFuseSuccess(void) +{ + return 1; +} +#endif diff --git a/src/lxc/lxc_fuse.h b/src/lxc/lxc_fuse.h new file mode 100644 index 0000000..5b3689e --- /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, see + * <http://www.gnu.org/licenses/>. + */ + +#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(void); +#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

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

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

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 | 190 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/lxc/lxc_fuse.h | 14 ++++ 4 files changed, 339 insertions(+), 6 deletions(-) diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 9a5ba1a..debbb38 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 cleanup; + } + + 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 cleanup; + } + 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; + +cleanup: + VIR_FREE(statFile); + VIR_FORCE_FCLOSE(statfd); + 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 cleanup; + } + + ret = virLXCCgroupGetMemTotal(cgroup, &meminfo[VIR_LXC_FUSE_MEMTOTAL]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup total")); + goto cleanup; + } + + ret = virLXCCgroupGetMemUsage(cgroup, &meminfo[VIR_LXC_FUSE_MEMUSAGE]); + if (ret < 0) { + virReportSystemError(-ret, "%s", + _("Unable to get memory cgroup stat usage")); + goto cleanup; + } + + virLXCCgroupGetMemSwapTotal(cgroup, &meminfo[VIR_LXC_FUSE_SWAPTOTAL]); + virLXCCgroupGetMemSwapUsage(cgroup, &meminfo[VIR_LXC_FUSE_SWAPUSAGE]); + + ret = 0; +cleanup: + 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 42107d7..ebebb32 100644 --- a/src/lxc/lxc_fuse.c +++ b/src/lxc/lxc_fuse.c @@ -30,26 +30,54 @@ #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)) { + if (stat(mempath, &sb) < 0) { + res = -errno; + goto cleanup; + } + + 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; } +cleanup: + VIR_FREE(mempath); return res; } @@ -63,14 +91,147 @@ 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; } -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 (!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) { - return -ENOENT; + 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 cleanup; + } + + 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 no_memory; + } 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 no_memory; + } else if (STREQ(line, "Buffers")) { + if (virAsprintf(&new_line, "Buffers: %8d KB\n", 0) < 0) + goto no_memory; + } else if (STREQ(line, "Cached")) { + if (virAsprintf(&new_line, "Cached: %8llu KB\n", + meminfo[VIR_LXC_FUSE_CACHED]) < 0) + goto no_memory; + } 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 no_memory; + } 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 no_memory; + } else if (STREQ(line, "Active(anon)")) { + if (virAsprintf(&new_line, "Active(anon): %8llu KB\n", + meminfo[VIR_LXC_FUSE_ACTIVE_ANON]) < 0) + goto no_memory; + } else if (STREQ(line, "Inactive(anon)")) { + if (virAsprintf(&new_line, "Inactive(anon): %8llu KB\n", + meminfo[VIR_LXC_FUSE_INACTIVE_ANON]) < 0) + goto no_memory; + } else if (STREQ(line, "Active(file)")) { + if (virAsprintf(&new_line, "Active(file): %8llu KB\n", + meminfo[VIR_LXC_FUSE_ACTIVE_FILE]) < 0) + goto no_memory; + } else if (STREQ(line, "Inactive(file)")) { + if (virAsprintf(&new_line, "Inactive(file): %8llu KB\n", + meminfo[VIR_LXC_FUSE_INACTIVE_FILE]) < 0) + goto no_memory; + } else if (STREQ(line, "Unevictable")) { + if (virAsprintf(&new_line, "Unevictable: %8llu KB\n", + meminfo[VIR_LXC_FUSE_UNEVICTABLE]) < 0) + goto no_memory; + } 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 no_memory; + } 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 no_memory; + } + *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; + +cleanup: + VIR_FORCE_FCLOSE(fd); + return res; + +no_memory: + virReportOOMError(); + res = -errno; + goto cleanup; } static int lxcProcRead(const char *path ATTRIBUTE_UNUSED, @@ -79,7 +240,26 @@ 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); + } + + 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 5b3689e..813ae06 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(void); #endif -- 1.7.7.6

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 Mon, Nov 05, 2012 at 01:23:51PM +0800, Gao feng wrote:
+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]) +
For comparison, here is how we test for fuse in libguestfs: dnl FUSE is optional to build the FUSE module. AC_ARG_ENABLE([fuse], AS_HELP_STRING([--disable-fuse], [disable FUSE (guestmount) support]), [], [enable_fuse=yes]) AS_IF([test "x$enable_fuse" != "xno"], [PKG_CHECK_MODULES([FUSE],[fuse], [AC_SUBST([FUSE_CFLAGS]) AC_SUBST([FUSE_LIBS]) AC_DEFINE([HAVE_FUSE],[1],[Define to 1 if you have FUSE.]) old_LIBS="$LIBS" LIBS="$FUSE_LIBS $LIBS" AC_CHECK_FUNCS([fuse_opt_add_opt_escaped]) LIBS="$old_LIBS" ], [enable_fuse=no AC_MSG_WARN([FUSE library and headers are missing, so optional FUSE module won't be built]) ]) ]) AM_CONDITIONAL([HAVE_FUSE],[test "x$enable_fuse" != "xno"]) [ https://github.com/libguestfs/libguestfs/blob/master/configure.ac#L744 ] Is there any reason not to use PKG_CHECK_MODULES? Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org

On Mon, Nov 05, 2012 at 10:11:17AM +0000, Richard W.M. Jones wrote:
On Mon, Nov 05, 2012 at 01:23:51PM +0800, Gao feng wrote:
+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"
As per Rich's comments, these 2 lines are bogus. The PKG_CHECK_MODULES macro should already be setting FUSE_LIBS and FUSE_CFLAGS to the correct values defined in the pkg-config file for FUSE.
+ 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]) +
For comparison, here is how we test for fuse in libguestfs:
dnl FUSE is optional to build the FUSE module. AC_ARG_ENABLE([fuse], AS_HELP_STRING([--disable-fuse], [disable FUSE (guestmount) support]), [], [enable_fuse=yes]) AS_IF([test "x$enable_fuse" != "xno"], [PKG_CHECK_MODULES([FUSE],[fuse], [AC_SUBST([FUSE_CFLAGS]) AC_SUBST([FUSE_LIBS]) AC_DEFINE([HAVE_FUSE],[1],[Define to 1 if you have FUSE.]) old_LIBS="$LIBS" LIBS="$FUSE_LIBS $LIBS" AC_CHECK_FUNCS([fuse_opt_add_opt_escaped]) LIBS="$old_LIBS" ], [enable_fuse=no AC_MSG_WARN([FUSE library and headers are missing, so optional FUSE module won't be built]) ]) ]) AM_CONDITIONAL([HAVE_FUSE],[test "x$enable_fuse" != "xno"])
[ https://github.com/libguestfs/libguestfs/blob/master/configure.ac#L744 ]
Is there any reason not to use PKG_CHECK_MODULES?
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月05日 18:30, Daniel P. Berrange 写道:
On Mon, Nov 05, 2012 at 10:11:17AM +0000, Richard W.M. Jones wrote:
On Mon, Nov 05, 2012 at 01:23:51PM +0800, Gao feng wrote:
+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"
As per Rich's comments, these 2 lines are bogus. The PKG_CHECK_MODULES macro should already be setting FUSE_LIBS and FUSE_CFLAGS to the correct values defined in the pkg-config file for FUSE.
+ 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]) +
For comparison, here is how we test for fuse in libguestfs:
dnl FUSE is optional to build the FUSE module. AC_ARG_ENABLE([fuse], AS_HELP_STRING([--disable-fuse], [disable FUSE (guestmount) support]), [], [enable_fuse=yes]) AS_IF([test "x$enable_fuse" != "xno"], [PKG_CHECK_MODULES([FUSE],[fuse], [AC_SUBST([FUSE_CFLAGS]) AC_SUBST([FUSE_LIBS]) AC_DEFINE([HAVE_FUSE],[1],[Define to 1 if you have FUSE.]) old_LIBS="$LIBS" LIBS="$FUSE_LIBS $LIBS" AC_CHECK_FUNCS([fuse_opt_add_opt_escaped]) LIBS="$old_LIBS" ], [enable_fuse=no AC_MSG_WARN([FUSE library and headers are missing, so optional FUSE module won't be built]) ]) ]) AM_CONDITIONAL([HAVE_FUSE],[test "x$enable_fuse" != "xno"])
[ https://github.com/libguestfs/libguestfs/blob/master/configure.ac#L744 ]
Is there any reason not to use PKG_CHECK_MODULES?
Is this ok? I'm not familiar with this :( 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 AS_IF([test "x$with_fuse" != "xno"], [PKG_CHECK_MODULES([FUSE], [fuse >= $FUSE_REQUIRED], [with_fuse=yes AC_SUBST([FUSE_CFLAGS]) AC_SUBST([FUSE_LIBS]) AC_DEFINE([HAVE_FUSE], [1], [whether fuse is available for libvirt lxc]) ], [with_fuse=no AC_MSG_ERROR([You must install fuse Library to compile libvirt]) ]) ]) AM_CONDITIONAL([HAVE_FUSE], [test "x$with_fuse" = "xyes"]) Thanks! Gao

On Mon, Nov 05, 2012 at 08:10:26PM +0800, Gao feng wrote:
于 2012年11月05日 18:30, Daniel P. Berrange 写道:
On Mon, Nov 05, 2012 at 10:11:17AM +0000, Richard W.M. Jones wrote:
On Mon, Nov 05, 2012 at 01:23:51PM +0800, Gao feng wrote:
+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"
As per Rich's comments, these 2 lines are bogus. The PKG_CHECK_MODULES macro should already be setting FUSE_LIBS and FUSE_CFLAGS to the correct values defined in the pkg-config file for FUSE.
+ 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]) +
For comparison, here is how we test for fuse in libguestfs:
dnl FUSE is optional to build the FUSE module. AC_ARG_ENABLE([fuse], AS_HELP_STRING([--disable-fuse], [disable FUSE (guestmount) support]), [], [enable_fuse=yes]) AS_IF([test "x$enable_fuse" != "xno"], [PKG_CHECK_MODULES([FUSE],[fuse], [AC_SUBST([FUSE_CFLAGS]) AC_SUBST([FUSE_LIBS]) AC_DEFINE([HAVE_FUSE],[1],[Define to 1 if you have FUSE.]) old_LIBS="$LIBS" LIBS="$FUSE_LIBS $LIBS" AC_CHECK_FUNCS([fuse_opt_add_opt_escaped]) LIBS="$old_LIBS" ], [enable_fuse=no AC_MSG_WARN([FUSE library and headers are missing, so optional FUSE module won't be built]) ]) ]) AM_CONDITIONAL([HAVE_FUSE],[test "x$enable_fuse" != "xno"])
[ https://github.com/libguestfs/libguestfs/blob/master/configure.ac#L744 ]
Is there any reason not to use PKG_CHECK_MODULES?
Is this ok? I'm not familiar with this :(
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 AS_IF([test "x$with_fuse" != "xno"], [PKG_CHECK_MODULES([FUSE], [fuse >= $FUSE_REQUIRED], [with_fuse=yes AC_SUBST([FUSE_CFLAGS]) AC_SUBST([FUSE_LIBS]) AC_DEFINE([HAVE_FUSE], [1], [whether fuse is available for libvirt lxc]) ], [with_fuse=no AC_MSG_ERROR([You must install fuse Library to compile libvirt]) ]) ]) AM_CONDITIONAL([HAVE_FUSE], [test "x$with_fuse" = "xyes"])
It looks OK, but you need to try all four combinations: with and without fuse-devel installed, and --with-fuse and --without-fuse. As written, --with-fuse=check and --with-fuse=yes both do the same thing (check for FUSE), which is probably OK but may not be what you meant to write. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top

于 2012年11月05日 20:14, Richard W.M. Jones 写道:
On Mon, Nov 05, 2012 at 08:10:26PM +0800, Gao feng wrote:
于 2012年11月05日 18:30, Daniel P. Berrange 写道:
On Mon, Nov 05, 2012 at 10:11:17AM +0000, Richard W.M. Jones wrote:
On Mon, Nov 05, 2012 at 01:23:51PM +0800, Gao feng wrote:
+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"
As per Rich's comments, these 2 lines are bogus. The PKG_CHECK_MODULES macro should already be setting FUSE_LIBS and FUSE_CFLAGS to the correct values defined in the pkg-config file for FUSE.
+ 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]) +
For comparison, here is how we test for fuse in libguestfs:
dnl FUSE is optional to build the FUSE module. AC_ARG_ENABLE([fuse], AS_HELP_STRING([--disable-fuse], [disable FUSE (guestmount) support]), [], [enable_fuse=yes]) AS_IF([test "x$enable_fuse" != "xno"], [PKG_CHECK_MODULES([FUSE],[fuse], [AC_SUBST([FUSE_CFLAGS]) AC_SUBST([FUSE_LIBS]) AC_DEFINE([HAVE_FUSE],[1],[Define to 1 if you have FUSE.]) old_LIBS="$LIBS" LIBS="$FUSE_LIBS $LIBS" AC_CHECK_FUNCS([fuse_opt_add_opt_escaped]) LIBS="$old_LIBS" ], [enable_fuse=no AC_MSG_WARN([FUSE library and headers are missing, so optional FUSE module won't be built]) ]) ]) AM_CONDITIONAL([HAVE_FUSE],[test "x$enable_fuse" != "xno"])
[ https://github.com/libguestfs/libguestfs/blob/master/configure.ac#L744 ]
Is there any reason not to use PKG_CHECK_MODULES?
Is this ok? I'm not familiar with this :(
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 AS_IF([test "x$with_fuse" != "xno"], [PKG_CHECK_MODULES([FUSE], [fuse >= $FUSE_REQUIRED], [with_fuse=yes AC_SUBST([FUSE_CFLAGS]) AC_SUBST([FUSE_LIBS]) AC_DEFINE([HAVE_FUSE], [1], [whether fuse is available for libvirt lxc]) ], [with_fuse=no AC_MSG_ERROR([You must install fuse Library to compile libvirt]) ]) ]) AM_CONDITIONAL([HAVE_FUSE], [test "x$with_fuse" = "xyes"])
It looks OK, but you need to try all four combinations: with and without fuse-devel installed, and --with-fuse and --without-fuse.
As written, --with-fuse=check and --with-fuse=yes both do the same thing (check for FUSE), which is probably OK but may not be what you meant to write.
Get it,will test and fix this small problem. Thanks again :)
participants (3)
-
Daniel P. Berrange
-
Gao feng
-
Richard W.M. Jones