mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-11-03 20:01:16 +00:00
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 <gaofeng@cn.fujitsu.com>
This commit is contained in:
parent
b6c37e5fb5
commit
2a596dac5e
@ -51,6 +51,7 @@ src/locking/lock_driver_sanlock.c
|
|||||||
src/locking/lock_manager.c
|
src/locking/lock_manager.c
|
||||||
src/locking/sanlock_helper.c
|
src/locking/sanlock_helper.c
|
||||||
src/lxc/lxc_cgroup.c
|
src/lxc/lxc_cgroup.c
|
||||||
|
src/lxc/lxc_fuse.c
|
||||||
src/lxc/lxc_container.c
|
src/lxc/lxc_container.c
|
||||||
src/lxc/lxc_conf.c
|
src/lxc/lxc_conf.c
|
||||||
src/lxc/lxc_controller.c
|
src/lxc/lxc_controller.c
|
||||||
|
@ -413,6 +413,7 @@ LXC_DRIVER_SOURCES = \
|
|||||||
lxc/lxc_domain.c lxc/lxc_domain.h \
|
lxc/lxc_domain.c lxc/lxc_domain.h \
|
||||||
lxc/lxc_monitor.c lxc/lxc_monitor.h \
|
lxc/lxc_monitor.c lxc/lxc_monitor.h \
|
||||||
lxc/lxc_process.c lxc/lxc_process.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/lxc_driver.c lxc/lxc_driver.h
|
||||||
|
|
||||||
LXC_CONTROLLER_SOURCES = \
|
LXC_CONTROLLER_SOURCES = \
|
||||||
@ -421,6 +422,7 @@ LXC_CONTROLLER_SOURCES = \
|
|||||||
lxc/lxc_conf.c lxc/lxc_conf.h \
|
lxc/lxc_conf.c lxc/lxc_conf.h \
|
||||||
lxc/lxc_container.c lxc/lxc_container.h \
|
lxc/lxc_container.c lxc/lxc_container.h \
|
||||||
lxc/lxc_cgroup.c lxc/lxc_cgroup.h \
|
lxc/lxc_cgroup.c lxc/lxc_cgroup.h \
|
||||||
|
lxc/lxc_fuse.c lxc/lxc_fuse.h \
|
||||||
lxc/lxc_controller.c
|
lxc/lxc_controller.c
|
||||||
|
|
||||||
SECURITY_DRIVER_APPARMOR_HELPER_SOURCES = \
|
SECURITY_DRIVER_APPARMOR_HELPER_SOURCES = \
|
||||||
@ -912,8 +914,9 @@ endif
|
|||||||
|
|
||||||
libvirt_driver_lxc_impl_la_CFLAGS = \
|
libvirt_driver_lxc_impl_la_CFLAGS = \
|
||||||
$(LIBNL_CFLAGS) \
|
$(LIBNL_CFLAGS) \
|
||||||
|
$(FUSE_CFLAGS) \
|
||||||
-I$(top_srcdir)/src/conf $(AM_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
|
if HAVE_LIBBLKID
|
||||||
libvirt_driver_lxc_impl_la_CFLAGS += $(BLKID_CFLAGS)
|
libvirt_driver_lxc_impl_la_CFLAGS += $(BLKID_CFLAGS)
|
||||||
libvirt_driver_lxc_impl_la_LIBADD += $(BLKID_LIBS)
|
libvirt_driver_lxc_impl_la_LIBADD += $(BLKID_LIBS)
|
||||||
@ -1679,6 +1682,7 @@ libvirt_lxc_SOURCES = \
|
|||||||
libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)
|
libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(AM_LDFLAGS)
|
||||||
libvirt_lxc_LDADD = \
|
libvirt_lxc_LDADD = \
|
||||||
$(NUMACTL_LIBS) \
|
$(NUMACTL_LIBS) \
|
||||||
|
$(FUSE_LIBS) \
|
||||||
libvirt-net-rpc-server.la \
|
libvirt-net-rpc-server.la \
|
||||||
libvirt-net-rpc.la \
|
libvirt-net-rpc.la \
|
||||||
libvirt_security_manager.la \
|
libvirt_security_manager.la \
|
||||||
@ -1697,7 +1701,8 @@ endif
|
|||||||
libvirt_lxc_CFLAGS = \
|
libvirt_lxc_CFLAGS = \
|
||||||
-I$(top_srcdir)/src/conf \
|
-I$(top_srcdir)/src/conf \
|
||||||
$(AM_CFLAGS) \
|
$(AM_CFLAGS) \
|
||||||
$(LIBNL_CFLAGS)
|
$(LIBNL_CFLAGS) \
|
||||||
|
$(FUSE_CFLAGS)
|
||||||
if HAVE_LIBBLKID
|
if HAVE_LIBBLKID
|
||||||
libvirt_lxc_CFLAGS += $(BLKID_CFLAGS)
|
libvirt_lxc_CFLAGS += $(BLKID_CFLAGS)
|
||||||
libvirt_lxc_LDADD += $(BLKID_LIBS)
|
libvirt_lxc_LDADD += $(BLKID_LIBS)
|
||||||
|
@ -163,6 +163,7 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
|
|||||||
{'c', LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM},
|
{'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_TTY},
|
||||||
{'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX},
|
{'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX},
|
||||||
|
{'c', LXC_DEV_MAJ_FUSE, LXC_DEV_MIN_FUSE},
|
||||||
{0, 0, 0}};
|
{0, 0, 0}};
|
||||||
|
|
||||||
rc = virCgroupDenyAllDevices(cgroup);
|
rc = virCgroupDenyAllDevices(cgroup);
|
||||||
|
@ -46,6 +46,9 @@ enum {
|
|||||||
|
|
||||||
# define LXC_DEV_MAJ_PTY 136
|
# define LXC_DEV_MAJ_PTY 136
|
||||||
|
|
||||||
|
# define LXC_DEV_MAJ_FUSE 10
|
||||||
|
# define LXC_DEV_MIN_FUSE 229
|
||||||
|
|
||||||
int lxcContainerSendContinue(int control);
|
int lxcContainerSendContinue(int control);
|
||||||
int lxcContainerWaitForContinue(int control);
|
int lxcContainerWaitForContinue(int control);
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include "lxc_container.h"
|
#include "lxc_container.h"
|
||||||
#include "lxc_cgroup.h"
|
#include "lxc_cgroup.h"
|
||||||
#include "lxc_protocol.h"
|
#include "lxc_protocol.h"
|
||||||
|
#include "lxc_fuse.h"
|
||||||
#include "virnetdev.h"
|
#include "virnetdev.h"
|
||||||
#include "virnetdevveth.h"
|
#include "virnetdevveth.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@ -130,6 +131,8 @@ struct _virLXCController {
|
|||||||
virNetServerProgramPtr prog;
|
virNetServerProgramPtr prog;
|
||||||
bool inShutdown;
|
bool inShutdown;
|
||||||
int timerShutdown;
|
int timerShutdown;
|
||||||
|
|
||||||
|
virLXCFusePtr fuse;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "lxc_controller_dispatch.h"
|
#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)
|
static void virLXCControllerFree(virLXCControllerPtr ctrl)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -272,6 +282,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl)
|
|||||||
virEventRemoveTimeout(ctrl->timerShutdown);
|
virEventRemoveTimeout(ctrl->timerShutdown);
|
||||||
|
|
||||||
virObjectUnref(ctrl->server);
|
virObjectUnref(ctrl->server);
|
||||||
|
virLXCControllerFreeFuse(ctrl);
|
||||||
|
|
||||||
VIR_FREE(ctrl);
|
VIR_FREE(ctrl);
|
||||||
}
|
}
|
||||||
@ -1243,6 +1254,12 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virLXCControllerSetupFuse(virLXCControllerPtr ctrl)
|
||||||
|
{
|
||||||
|
return lxcSetupFuse(&ctrl->fuse, ctrl->def);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virLXCControllerSetupConsoles(virLXCControllerPtr ctrl,
|
virLXCControllerSetupConsoles(virLXCControllerPtr ctrl,
|
||||||
char **containerTTYPaths)
|
char **containerTTYPaths)
|
||||||
@ -1405,6 +1422,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
|
|||||||
if (virLXCControllerSetupDevPTS(ctrl) < 0)
|
if (virLXCControllerSetupDevPTS(ctrl) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virLXCControllerSetupFuse(ctrl) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (virLXCControllerSetupConsoles(ctrl, containerTTYPaths) < 0)
|
if (virLXCControllerSetupConsoles(ctrl, containerTTYPaths) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
202
src/lxc/lxc_fuse.c
Normal file
202
src/lxc/lxc_fuse.c
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
51
src/lxc/lxc_fuse.h
Normal file
51
src/lxc/lxc_fuse.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
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 */
|
@ -28,6 +28,7 @@
|
|||||||
#include "lxc_process.h"
|
#include "lxc_process.h"
|
||||||
#include "lxc_domain.h"
|
#include "lxc_domain.h"
|
||||||
#include "lxc_container.h"
|
#include "lxc_container.h"
|
||||||
|
#include "lxc_fuse.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "virfile.h"
|
#include "virfile.h"
|
||||||
#include "virpidfile.h"
|
#include "virpidfile.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user