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@xxxxxxxxxxxxxx> > --- > 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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list