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

Gao feng gaofeng at cn.fujitsu.com
Thu Jul 12 01:33:14 UTC 2012


于 2012年07月11日 17:30, Daniel P. Berrange 写道:
> 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.
> 

Get it,thanks for explaining this to me.

>> +#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)
> 

Yes,will read it,thanks

>> +
>> +    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)
> 

Get it

Thanks!
Gao





More information about the libvir-list mailing list