From 2a596dac5e00c4fcf750a693fd6174b68188efc3 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Wed, 14 Nov 2012 17:39:04 +0800 Subject: [PATCH] add fuse support for libvirt lxc 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 --- 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 | 20 ++++ src/lxc/lxc_fuse.c | 202 +++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_fuse.h | 51 ++++++++++ src/lxc/lxc_process.c | 1 + 8 files changed, 286 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 1b7640c0a6..ec59efbe51 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -51,6 +51,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 4026a15b69..627dbb5c46 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 = \ @@ -912,8 +914,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) @@ -1679,6 +1682,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 \ @@ -1697,7 +1701,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 912233fa34..1b3a137987 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 b1adacb42e..c8c70e0633 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 16cda9d2f8..5510b9a08c 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" @@ -130,6 +131,8 @@ struct _virLXCController { virNetServerProgramPtr prog; bool inShutdown; int timerShutdown; + + virLXCFusePtr fuse; }; #include "lxc_controller_dispatch.h" @@ -242,6 +245,13 @@ static void virLXCControllerConsoleClose(virLXCControllerConsolePtr console) } +static void +virLXCControllerFreeFuse(virLXCControllerPtr ctrl) +{ + return lxcFreeFuse(&ctrl->fuse); +} + + static void virLXCControllerFree(virLXCControllerPtr ctrl) { size_t i; @@ -272,6 +282,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl) virEventRemoveTimeout(ctrl->timerShutdown); virObjectUnref(ctrl->server); + virLXCControllerFreeFuse(ctrl); VIR_FREE(ctrl); } @@ -1243,6 +1254,12 @@ cleanup: } +static int +virLXCControllerSetupFuse(virLXCControllerPtr ctrl) +{ + return lxcSetupFuse(&ctrl->fuse, ctrl->def); +} + static int virLXCControllerSetupConsoles(virLXCControllerPtr ctrl, char **containerTTYPaths) @@ -1405,6 +1422,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 0000000000..8ed5ea16af --- /dev/null +++ b/src/lxc/lxc_fuse.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2012 Fujitsu Limited. + * + * lxc_fuse.c: fuse filesystem support for libvirt lxc + * + * Authors: + * Gao feng + * + * 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 + * . + */ + +#include +#include +#include +#include +#include +#include +#include + +#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, +}; + +static void lxcFuseDestroy(virLXCFusePtr fuse) +{ + virMutexLock(&fuse->lock); + fuse_unmount(fuse->mountpoint, fuse->ch); + fuse_destroy(fuse->fuse); + fuse->fuse = NULL; + virMutexUnlock(&fuse->lock); +} + +static void lxcFuseRun(void *opaque) +{ + virLXCFusePtr fuse = opaque; + + if (fuse_loop(fuse->fuse) < 0) + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("fuse_loop failed")); + + lxcFuseDestroy(fuse); +} + +int lxcSetupFuse(virLXCFusePtr *f, virDomainDefPtr def) +{ + int ret = -1; + struct fuse_args args = FUSE_ARGS_INIT(0, NULL); + virLXCFusePtr fuse = NULL; + + if (VIR_ALLOC(fuse) < 0) + goto cleanup; + + fuse->def = def; + + if (virMutexInit(&fuse->lock) < 0) + goto cleanup2; + + if (virAsprintf(&fuse->mountpoint, "%s/%s/", LXC_STATE_DIR, + def->name) < 0) { + virReportOOMError(); + goto cleanup1; + } + + if (virFileMakePath(fuse->mountpoint) < 0) { + virReportSystemError(errno, _("Cannot create %s"), + fuse->mountpoint); + goto cleanup1; + } + + /* process name is libvirt_lxc */ + if (fuse_opt_add_arg(&args, "libvirt_lxc") == -1 || + fuse_opt_add_arg(&args, "-odirect_io") == -1 || + fuse_opt_add_arg(&args, "-ofsname=libvirt") == -1) + goto cleanup1; + + fuse->ch = fuse_mount(fuse->mountpoint, &args); + if (fuse->ch == NULL) + goto cleanup1; + + fuse->fuse = fuse_new(fuse->ch, &args, &lxcProcOper, + sizeof(lxcProcOper), fuse->def); + if (fuse->fuse == NULL) { + fuse_unmount(fuse->mountpoint, fuse->ch); + goto cleanup1; + } + + if (virThreadCreate(&fuse->thread, true, lxcFuseRun, + (void *)fuse) < 0) { + lxcFuseDestroy(fuse); + goto cleanup1; + } + + ret = 0; +cleanup: + fuse_opt_free_args(&args); + *f = fuse; + return ret; +cleanup1: + VIR_FREE(fuse->mountpoint); + virMutexDestroy(&fuse->lock); +cleanup2: + VIR_FREE(fuse); + goto cleanup; +} + +void lxcFreeFuse(virLXCFusePtr *f) +{ + virLXCFusePtr fuse = *f; + /* lxcFuseRun thread create success */ + if (fuse) { + /* exit fuse_loop, lxcFuseRun thread may try to destroy + * fuse->fuse at the same time,so add a lock here. */ + virMutexLock(&fuse->lock); + if (fuse->fuse) + fuse_exit(fuse->fuse); + virMutexUnlock(&fuse->lock); + + virThreadJoin(&fuse->thread); + + VIR_FREE(fuse->mountpoint); + VIR_FREE(*f); + } +} +#else +int lxcSetupFuse(virLXCFusePtr *f ATTRIBUTE_UNUSED, + virDomainDefPtr def ATTRIBUTE_UNUSED) +{ + return 0; +} + +void lxcFreeFuse(virLXCFusePtr *f ATTRIBUTE_UNUSED) +{ +} +#endif diff --git a/src/lxc/lxc_fuse.h b/src/lxc/lxc_fuse.h new file mode 100644 index 0000000000..cd94076148 --- /dev/null +++ b/src/lxc/lxc_fuse.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012 Fujitsu Limited. + * + * lxc_fuse.c: fuse filesystem support for libvirt lxc + * + * Authors: + * Gao feng + * + * 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 + * . + */ + +#ifndef LXC_FUSE_H +# define LXC_FUSE_H + +# define FUSE_USE_VERSION 26 + +# include +# if HAVE_FUSE +# include +# endif + +# include "lxc_conf.h" +# include "util.h" +# include "memory.h" + +struct virLXCFuse { + virDomainDefPtr def; + virThread thread; + char *mountpoint; + struct fuse *fuse; + struct fuse_chan *ch; + virMutex lock; +}; +typedef struct virLXCFuse *virLXCFusePtr; + +extern int lxcSetupFuse(virLXCFusePtr *f, virDomainDefPtr def); +extern void lxcFreeFuse(virLXCFusePtr *f); + +#endif /* LXC_FUSE_H */ diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 514ef81f44..8b9d02fb3f 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" -- GitLab