[libvirt] [RFC] [PATCH 2/5] add fuse support for libvirt lxc

Daniel P. Berrange berrange at redhat.com
Wed Jul 11 09:30:09 UTC 2012


On Wed, Jul 11, 2012 at 03:58:20PM +0800, Gao feng wrote:
> this patch addes fuse support for libvirt lxc.
> we can use fuse filesystem to generate sysinfo dynamically,
> So we can isolate /proc/meminfo,cpuinfo and so on through
> fuse filesystem.
> 
> we mount fuse filesystem for every container.the mount name
> is Lxc-lxcname-fuse.
> 
> Signed-off-by: Gao feng <gaofeng at cn.fujitsu.com>
> ---
>  src/Makefile.am          |    9 ++-
>  src/lxc/lxc_controller.c |   15 +++++
>  src/lxc/lxc_driver.c     |    2 +
>  src/lxc/lxc_fuse.c       |  155 ++++++++++++++++++++++++++++++++++++++++++++++
>  src/lxc/lxc_fuse.h       |   38 +++++++++++
>  5 files changed, 217 insertions(+), 2 deletions(-)
>  create mode 100644 src/lxc/lxc_fuse.c
>  create mode 100644 src/lxc/lxc_fuse.h
> 
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 6c3eaa7..b01b2df 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -349,11 +349,13 @@ endif
>  
>  LXC_DRIVER_SOURCES =						\
>  		lxc/lxc_conf.c lxc/lxc_conf.h			\
> +		lxc/lxc_fuse.c lxc/lxc_fuse.h			\
>  		lxc/lxc_container.c lxc/lxc_container.h		\
>  		lxc/lxc_driver.c lxc/lxc_driver.h
>  
>  LXC_CONTROLLER_SOURCES =					\
>  		lxc/lxc_conf.c lxc/lxc_conf.h			\
> +		lxc/lxc_fuse.c lxc/lxc_fuse.h			\
>  		lxc/lxc_container.c lxc/lxc_container.h		\
>  		lxc/lxc_controller.c
>  
> @@ -819,8 +821,9 @@ endif
>  
>  libvirt_driver_lxc_impl_la_CFLAGS = \
>  		$(LIBNL_CFLAGS) \
> +		$(FUSE_CFLAGS) \
>  		-I$(top_srcdir)/src/conf $(AM_CFLAGS)
> -libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS)
> +libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(FUSE_LIBS)
>  if HAVE_LIBBLKID
>  libvirt_driver_lxc_impl_la_CFLAGS += $(BLKID_CFLAGS)
>  libvirt_driver_lxc_impl_la_LIBADD += $(BLKID_LIBS)
> @@ -1523,6 +1526,7 @@ libvirt_lxc_SOURCES =						\
>  libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)
>  libvirt_lxc_LDADD =			\
>  		$(NUMACTL_LIBS) \
> +		$(FUSE_LIBS) \
>  		libvirt-net-rpc-server.la \
>  		libvirt-net-rpc.la \
>  		libvirt_driver_security.la \
> @@ -1540,7 +1544,8 @@ libvirt_lxc_LDADD += $(APPARMOR_LIBS)
>  endif
>  libvirt_lxc_CFLAGS =				\
>  		-I$(top_srcdir)/src/conf	\
> -		$(AM_CFLAGS)
> +		$(AM_CFLAGS)			\
> +		$(FUSE_CFLAGS)
>  if HAVE_LIBBLKID
>  libvirt_lxc_CFLAGS += $(BLKID_CFLAGS)
>  libvirt_lxc_LDADD += $(BLKID_LIBS)
> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
> index a4874ea..44ba07c 100644
> --- a/src/lxc/lxc_controller.c
> +++ b/src/lxc/lxc_controller.c
> @@ -58,6 +58,7 @@
>  
>  #include "lxc_conf.h"
>  #include "lxc_container.h"
> +#include "lxc_fuse.h"
>  #include "virnetdev.h"
>  #include "virnetdevveth.h"
>  #include "memory.h"
> @@ -1741,6 +1742,20 @@ int main(int argc, char *argv[])
>          }
>      }
>  
> +    if ((pid = fork()) < 0)
> +        goto cleanup;
> +
> +    if (pid == 0) {
> +        if ((pid = fork()) < 0)
> +            _exit(-1);
> +
> +        if (pid > 0)
> +           _exit(0);
> +
> +        lxcRegisterFuse(ctrl->def);
> +        _exit(0);
> +    }


This is double forking to daemonize, but you never execve()
anywhere. Thus according to POSIX you are mandated to only
use async signal safe functions. This is clearly impossible
given the functionality you need to use with FUSE.

So either you need to make this a separate binary that can
be exec()'d, or instead of fork()ing, run this in a thread
of the libvirt_lxc process.  I think you can probably make
do with just using a thread.

> +#if HAVE_FUSE
> +
> +static int lxcProcGetattr(const char *path, struct stat *stbuf)
> +{
> +    int res = 0;
> +
> +    memset(stbuf, 0, sizeof(struct stat));
> +    if (strcmp(path, "/") == 0) {

strcmp() == 0, is not allowed - use STREQ instead - if you
run 'make syntax-check' it should warn you about this.

> +        stbuf->st_mode = S_IFDIR | 0755;
> +        stbuf->st_nlink = 2;
> +    } else
> +        res = -ENOENT;

You need {} around the else clause, if you use {}
around the if clause (see HACKING)

> +
> +    return res;
> +}
> +
> +static int lxcProcReaddir(const char *path, void *buf,
> +                          fuse_fill_dir_t filler,
> +                          off_t offset ATTRIBUTE_UNUSED,
> +                          struct fuse_file_info *fi ATTRIBUTE_UNUSED)
> +{
> +    if (strcmp(path, "/") != 0)
> +        return -ENOENT;
> +
> +    filler(buf, ".", NULL, 0);
> +    filler(buf, "..", NULL, 0);
> +
> +    return 0;
> +}
> +
> +static int lxcProcOpen(const char *path ATTRIBUTE_UNUSED,
> +                       struct fuse_file_info *fi ATTRIBUTE_UNUSED)
> +{
> +    return -ENOENT;
> +}
> +
> +static int lxcProcRead(const char *path ATTRIBUTE_UNUSED,
> +                       char *buf ATTRIBUTE_UNUSED,
> +                       size_t size ATTRIBUTE_UNUSED,
> +                       off_t offset ATTRIBUTE_UNUSED,
> +                       struct fuse_file_info *fi ATTRIBUTE_UNUSED)
> +{
> +    return -ENOENT;
> +}
> +
> +static struct fuse_operations lxcProcOper = {
> +    .getattr = lxcProcGetattr,
> +    .readdir = lxcProcReaddir,
> +    .open    = lxcProcOpen,
> +    .read    = lxcProcRead,
> +};
> +
> +int lxcRegisterFuse(virDomainDefPtr def)
> +{
> +    int rc = -1;
> +    char *path = NULL;
> +    char *name = NULL;
> +    int argc = 3;
> +    char *argv[argc];
> +
> +    if ((rc = virAsprintf(&name, "Lxc-%s-fuse", def->name)) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    if ((rc = virAsprintf(&path, "%s/%s/", LXC_STATE_DIR, def->name)) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    if ((rc = virFileMakePath(path)) < 0) {
> +        virReportSystemError(errno, _("Cannot create %s"), path);
> +        goto cleanup;
> +    }
> +
> +    argv[0] = name;
> +    argv[1] = path;
> +    argv[2] = (char *)"-odirect_io";
> +
> +    if ((rc = fuse_main(argc, argv, &lxcProcOper, def)) < 0) {
> +        virReportSystemError(errno, "%s", _("Cannot start fuse\n"));
> +        goto cleanup;
> +    }
> +    rc = 0;
> +
> +cleanup:
> +    VIR_FREE(name);
> +    VIR_FREE(path);
> +    VIR_FREE(argv);
> +    return rc;
> +}
> +
> +void lxcUnregisterFuse(virDomainDefPtr def)
> +{
> +    char *path = NULL;
> +    if (virAsprintf(&path, "%s/%s/", LXC_STATE_DIR, def->name) < 0) {
> +        virReportOOMError();
> +        return;
> +    }
> +
> +    if (umount(path) < 0)
> +         virReportSystemError(errno, "%s", _("umount fuse filesystem failed\n"));
> +
> +    VIR_FREE(path);
> +}
> +
> +#else
> +int lxcRegisterFuse(virDomainDefPtr def)
> +{
> +    (void) def;
> +    return 0;
> +}
> +
> +void lxcUnregisterFuse(virDomainDefPtr def)
> +{
> +    (void) def;
> +}
> +#endif

Use ATTRIBUTE_UNNUSED annotations instead of casting to (void)


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list