[libvirt] [PATCH 0/6] parallels: get rid of cached domains list in driver
by Dmitry Guryanov
The goal of this patch series is to get rid of cached domains
list.
Someone can create several connections to libvirt or change
something (start VM or change parameters) using native tools.
In such case first connection will not get any info about those
changes.
There is no way to check, if the cache valid, so remove it and
always query needed data using prlctl command.
Dmitry Guryanov (6):
parallels: return a new list of domains from parallelsLoadDomains
parallels: rename uuidstr to __uuidstr in macro
parallels: return up-to-date info about domains
parallels: don't track domain state in global domains list
parallels: don't use stored domains list in parallelsDomainDefineXML
parallels: remove domains list from _parallelsConn structure
src/parallels/parallels_driver.c | 423 ++++++++++++++++++--------------------
src/parallels/parallels_utils.h | 1 -
2 files changed, 195 insertions(+), 229 deletions(-)
12 years, 3 months
[libvirt] [PATCH] remove dnsmasq command line parameter "--filterwin2k"
by Gene Czarcinski
This patch removed the "--filterwin2k" dnsmasq command line
parameter which was unnecessary for domain specification,
possibly blocked some usage, and was command line clutter.
Gene Czarcinski <gene(a)czarc.net>
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 53eebed..808c843 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -543,7 +543,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
/* need to specify local even if no domain specified */
virCommandAddArgFormat(cmd, "--local=/%s/",
network->def->domain ? network->def->domain
: "");
- virCommandAddArgList(cmd, "--domain-needed", "--filterwin2k", NULL);
+ virCommandAddArg(cmd, "--domain-needed");
if (pidfile)
virCommandAddArgPair(cmd, "--pid-file", pidfile);
diff --git a/tests/networkxml2argvdata/isolated-network.argv
b/tests/networkxml2argvdata/isolated-network.argv
index 276f42a..048c72b 100644
--- a/tests/networkxml2argvdata/isolated-network.argv
+++ b/tests/networkxml2argvdata/isolated-network.argv
@@ -1,5 +1,5 @@
@DNSMASQ@ --strict-order --bind-interfaces \
---local=// --domain-needed --filterwin2k --conf-file= \
+--local=// --domain-needed --conf-file= \
--except-interface lo --dhcp-option=3 --no-resolv \
--listen-address 192.168.152.1 \
--dhcp-range 192.168.152.2,192.168.152.254 \
diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.argv
b/tests/networkxml2argvdata/nat-network-dns-hosts.argv
index 8040e2a..03a0676 100644
--- a/tests/networkxml2argvdata/nat-network-dns-hosts.argv
+++ b/tests/networkxml2argvdata/nat-network-dns-hosts.argv
@@ -1,4 +1,4 @@
@DNSMASQ@ --strict-order --bind-interfaces --domain=example.com \
---local=/example.com/ --domain-needed --filterwin2k \
+--local=/example.com/ --domain-needed \
--conf-file= --except-interface lo --listen-address 192.168.122.1 \
--expand-hosts --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\
diff --git
a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
index bb50fd6..a1e4200 100644
--- a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
+++ b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
@@ -1,7 +1,7 @@
@DNSMASQ@ \
--strict-order \
--bind-interfaces \
---local=// --domain-needed --filterwin2k --conf-file= \
+--local=// --domain-needed --conf-file= \
--except-interface lo \
--srv-host=name.tcp.,,,, \
--listen-address 192.168.122.1 \
diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
index 36498f2..8af38c4 100644
--- a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
+++ b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
@@ -1,7 +1,7 @@
@DNSMASQ@ \
--strict-order \
--bind-interfaces \
---local=// --domain-needed --filterwin2k --conf-file= \
+--local=// --domain-needed --conf-file= \
--except-interface lo \
--srv-host=name.tcp.test-domain-name,.,1024,10,10 \
--listen-address 192.168.122.1 \
diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv
b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv
index 2a6c799..404b56a 100644
--- a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv
+++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv
@@ -1,5 +1,5 @@
@DNSMASQ@ --strict-order --bind-interfaces \
---local=// --domain-needed --filterwin2k --conf-file= \
+--local=// --domain-needed --conf-file= \
--except-interface lo '--txt-record=example,example value' \
--listen-address 192.168.122.1 --listen-address 192.168.123.1 \
--listen-address 2001:db8:ac10:fe01::1 \
diff --git a/tests/networkxml2argvdata/nat-network.argv
b/tests/networkxml2argvdata/nat-network.argv
index 265b931..1dc8f73 100644
--- a/tests/networkxml2argvdata/nat-network.argv
+++ b/tests/networkxml2argvdata/nat-network.argv
@@ -1,5 +1,5 @@
@DNSMASQ@ --strict-order --bind-interfaces \
---local=// --domain-needed --filterwin2k --conf-file= \
+--local=// --domain-needed --conf-file= \
--except-interface lo --listen-address 192.168.122.1 \
--listen-address 192.168.123.1 --listen-address 2001:db8:ac10:fe01::1 \
--listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 \
diff --git a/tests/networkxml2argvdata/netboot-network.argv
b/tests/networkxml2argvdata/netboot-network.argv
index 4f998d5..5a85ec2 100644
--- a/tests/networkxml2argvdata/netboot-network.argv
+++ b/tests/networkxml2argvdata/netboot-network.argv
@@ -1,5 +1,5 @@
@DNSMASQ@ --strict-order --bind-interfaces --domain=example.com \
---local=/example.com/ --domain-needed --filterwin2k --conf-file= \
+--local=/example.com/ --domain-needed --conf-file= \
--except-interface lo --listen-address 192.168.122.1 \
--dhcp-range 192.168.122.2,192.168.122.254 \
--dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases \
diff --git a/tests/networkxml2argvdata/netboot-proxy-network.argv
b/tests/networkxml2argvdata/netboot-proxy-network.argv
index 89319ef..36836b0 100644
--- a/tests/networkxml2argvdata/netboot-proxy-network.argv
+++ b/tests/networkxml2argvdata/netboot-proxy-network.argv
@@ -1,5 +1,5 @@
@DNSMASQ@ --strict-order --bind-interfaces --domain=example.com \
---local=/example.com/ --domain-needed --filterwin2k --conf-file= \
+--local=/example.com/ --domain-needed --conf-file= \
--except-interface lo --listen-address 192.168.122.1 \
--dhcp-range 192.168.122.2,192.168.122.254 \
--dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases \
diff --git a/tests/networkxml2argvdata/routed-network.argv
b/tests/networkxml2argvdata/routed-network.argv
index ac43991..77e802f 100644
--- a/tests/networkxml2argvdata/routed-network.argv
+++ b/tests/networkxml2argvdata/routed-network.argv
@@ -1,3 +1,3 @@
@DNSMASQ@ --strict-order --bind-interfaces \
---local=// --domain-needed --filterwin2k --conf-file= \
+--local=// --domain-needed --conf-file= \
--except-interface lo --listen-address 192.168.122.1\
12 years, 3 months
[libvirt] [PATCH v0] qemu: Add sandbox support.
by Ján Tomko
QEMU (since 1.2-rc0) supports setting up a syscall whitelist through
libseccomp on linux kernel from 3.5-rc1. This is enabled by specifying
-sandbox on on qemu command line.
This patch detects this capability by searching for -sandbox in qemu
help output and runs qemu with -sandbox on if sandbox is set to non-zero
in qemu.conf.
---
Should this option be in qemu.conf, or would it be better to set it
per-domain in the XML?
---
src/qemu/qemu.conf | 6 ++++++
src/qemu/qemu_capabilities.c | 3 +++
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 3 +++
src/qemu/qemu_conf.c | 5 +++++
src/qemu/qemu_conf.h | 1 +
6 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index d3175fa..47e510e 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -375,3 +375,9 @@
#
#keepalive_interval = 5
#keepalive_count = 5
+
+
+
+# Enable this to use seccomp syscall whitelisting in QEMU.
+#
+#sandbox = 1
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2ba7956..b0728e8 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -176,6 +176,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"disable-s3",
"disable-s4", /* 105 */
+ "sandbox"
);
struct qemu_feature_flags {
@@ -1139,6 +1140,8 @@ qemuCapsComputeCmdFlags(const char *help,
}
if (strstr(help, "-smbios type"))
qemuCapsSet(flags, QEMU_CAPS_SMBIOS_TYPE);
+ if (strstr(help, "-sandbox"))
+ qemuCapsSet(flags, QEMU_CAPS_SANDBOX);
if ((netdev = strstr(help, "-netdev"))) {
/* Disable -netdev on 0.12 since although it exists,
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index a7b3a06..0066901 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -141,6 +141,7 @@ enum qemuCapsFlags {
QEMU_CAPS_IOLIMITS = 103, /* -device ...logical_block_size & co */
QEMU_CAPS_DISABLE_S3 = 104, /* S3 BIOS Advertisement on/off */
QEMU_CAPS_DISABLE_S4 = 105, /* S4 BIOS Advertisement on/off */
+ QEMU_CAPS_SANDBOX = 106, /* -sandbox */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index e739f34..737d4d9 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6462,6 +6462,9 @@ qemuBuildCommandLine(virConnectPtr conn,
? qemucmd->env_value[i] : "");
}
+ if (driver->sandbox && qemuCapsGet(qemuCaps, QEMU_CAPS_SANDBOX))
+ virCommandAddArgList(cmd, "-sandbox", "on", NULL);
+
return cmd;
no_memory:
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index e9e15c5..a367fcd 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -129,6 +129,7 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
driver->keepAliveInterval = 5;
driver->keepAliveCount = 5;
+ driver->sandbox = false;
/* Just check the file is readable before opening it, otherwise
* libvirt emits an error.
@@ -570,6 +571,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
CHECK_TYPE("keepalive_count", VIR_CONF_LONG);
if (p) driver->keepAliveCount = p->l;
+ p = virConfGetValue(conf, "sandbox");
+ CHECK_TYPE("sandbox", VIR_CONF_LONG);
+ if (p) driver->sandbox = p->l;
+
virConfFree (conf);
return 0;
}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index ac285f6..f1b6465 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -152,6 +152,7 @@ struct qemud_driver {
int keepAliveInterval;
unsigned int keepAliveCount;
+ bool sandbox;
};
typedef struct _qemuDomainCmdlineDef qemuDomainCmdlineDef;
--
1.7.8.6
12 years, 3 months
[libvirt] [PATCH V3] Add proxy FS support to libvirt
by M. Mohan Kumar
From: "M. Mohan Kumar" <mohan(a)in.ibm.com>
A new FS driver type 'proxy' is added to QEMU 9p server. This patch adds
support for using proxy FS driver from libvirt.
QEMU proxy FS driver uses socket for communicating between helper and qemu
proxy FS driver. Proxy helper (a stand alone binary part of qemu) is invoked
with one of the descriptors created using socketpair call and the share path.
Similarly QEMU is invoked with another descriptor created using the same
socketpair system call and with other required FS driver parameters.
Need for proxy FS driver
========================
Pass through security model in QEMU 9p server has following issues:
1) TOCTTOU vulnerability: Following symbolic links in the server could
provide access to files beyond 9p export path.
2) Running QEMU with root privilege could be a security issue (pass
through security model needs root privilege).
Proxy FS driver is implemented to solve these issues.
Proxy FS uses chroot + socket combination for securing the vulnerability
known with following symbolic links. Intention of adding a new filesystem
type is to allow qemu to run in non-root mode, but doing privileged
operations in a chroot environment using socket IO.
Proxy helper is invoked with root privileges and chroots into 9p export path.
QEMU proxy fs driver sends filesystem request to proxy helper and receives the
response from it.
Proxy helper is designed such a way that it needs only few capabilities related
to filesystem operations (such as CAP_DAC_OVERRIDE, CAP_FOWNER, etc) and all
other capabilities are dropped (CAP_SYS_CHROOT, etc)
Proxy patches
http://permalink.gmane.org/gmane.comp.emulators.qemu/128735
Signed-off-by: M. Mohan Kumar <mohan(a)in.ibm.com>
---
Changes from previous version V3
* Addressed Daniel's review comments
Changes from previous version V2
* Rebased on top of current libvirt git level
Changes from previous version
* Remove the xml node for specifying the virtfs-proxy-helper path, now it is
determined from qemu binary path.
docs/formatdomain.html.in | 2 +
src/conf/domain_conf.c | 3 +-
src/conf/domain_conf.h | 2 +-
src/qemu/qemu_capabilities.c | 5 ++-
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 83 ++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_command.h | 3 +-
tests/qemuhelptest.c | 7 +++-
8 files changed, 96 insertions(+), 10 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 2c5c456..bf74ed8 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1621,6 +1621,8 @@
while the value <code>immediate</code> means that a host writeback
is immediately triggered for all pages touched during a guest file
write operation <span class="since">(since 0.9.10)</span>.
+ or <code>type='proxy'</code> <span class="since">(since
+ 1.0)</span>.
</dd>
<dt><code>type='template'</code></dt>
<dd>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 851284a..79ca2b7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -268,7 +268,8 @@ VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
VIR_ENUM_IMPL(virDomainFSDriverType, VIR_DOMAIN_FS_DRIVER_TYPE_LAST,
"default",
"path",
- "handle")
+ "handle",
+ "proxy")
VIR_ENUM_IMPL(virDomainFSAccessMode, VIR_DOMAIN_FS_ACCESSMODE_LAST,
"passthrough",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index fd0e89e..a296f49 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -660,6 +660,7 @@ enum virDomainFSDriverType {
VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT = 0,
VIR_DOMAIN_FS_DRIVER_TYPE_PATH,
VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE,
+ VIR_DOMAIN_FS_DRIVER_TYPE_PROXY,
VIR_DOMAIN_FS_DRIVER_TYPE_LAST
};
@@ -698,7 +699,6 @@ struct _virDomainFSDef {
unsigned long long space_soft_limit; /* in bytes */
};
-
/* 5 different types of networking config */
enum virDomainNetType {
VIR_DOMAIN_NET_TYPE_USER,
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 5472267..88b7e87 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -144,7 +144,6 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"ich9-ahci",
"no-acpi",
"fsdev-readonly",
-
"virtio-blk-pci.scsi", /* 80 */
"blk-sg-io",
"drive-copy-on-read",
@@ -172,7 +171,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"bridge", /* 100 */
"lsi",
"virtio-scsi-pci",
-
+ "fsdev-proxy",
);
struct qemu_feature_flags {
@@ -1133,6 +1132,8 @@ qemuCapsComputeCmdFlags(const char *help,
qemuCapsSet(flags, QEMU_CAPS_FSDEV_READONLY);
if (strstr(fsdev, "writeout"))
qemuCapsSet(flags, QEMU_CAPS_FSDEV_WRITEOUT);
+ if (strstr(fsdev, "sock_fd"))
+ qemuCapsSet(flags, QEMU_CAPS_FSDEV_PROXY);
}
if (strstr(help, "-smbios type"))
qemuCapsSet(flags, QEMU_CAPS_SMBIOS_TYPE);
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index d606890..073a1cd 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -138,6 +138,7 @@ enum qemuCapsFlags {
QEMU_CAPS_NETDEV_BRIDGE = 100, /* bridge helper support */
QEMU_CAPS_SCSI_LSI = 101, /* -device lsi */
QEMU_CAPS_VIRTIO_SCSI_PCI = 102, /* -device virtio-scsi-pci */
+ QEMU_CAPS_FSDEV_PROXY = 103, /* -fsdev proxy supported */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4ca3047..3f78635 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -46,6 +46,7 @@
#include <sys/utsname.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <libgen.h>
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -116,7 +117,8 @@ VIR_ENUM_DECL(qemuDomainFSDriver)
VIR_ENUM_IMPL(qemuDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST,
"local",
"local",
- "handle");
+ "handle",
+ "proxy");
static void
@@ -2632,9 +2634,59 @@ error:
return NULL;
}
+/*
+ * Invokes the Proxy Helper with one of the socketpair as its parameter
+ *
+ */
+static int qemuInvokeProxyHelper(const char *emulator, int sock, const char *path)
+{
+#define HELPER "virtfs-proxy-helper"
+ int ret_val, status;
+ virCommandPtr cmd;
+ char *helper, *dname, *dp;
+
+ dp = strdup(emulator);
+ if (!dp) {
+ virReportOOMError();
+ return -1;
+ }
+ dname = strrchr(dp, '/');
+ if (!dname) {
+ VIR_FREE(dp);
+ VIR_FORCE_CLOSE(sock);
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to get path details from %s"), dp);
+ return -1;
+ }
+ *dname = '\0';
+ if (virAsprintf(&helper, "%s/%s", dp, HELPER) < 0) {
+ VIR_FREE(dp);
+ VIR_FORCE_CLOSE(sock);
+ virReportOOMError();
+ return -1;
+ }
+
+ cmd = virCommandNewArgList(helper, NULL);
+ virCommandAddArg(cmd, "-f");
+ virCommandAddArgFormat(cmd, "%d", sock);
+ virCommandAddArg(cmd, "-p");
+ virCommandAddArgFormat(cmd, "%s", path);
+ virCommandTransferFD(cmd, sock);
+ virCommandDaemonize(cmd);
+ ret_val = virCommandRun(cmd, &status);
+ if (ret_val < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("%s can't execute"), helper);
+ VIR_FORCE_CLOSE(sock);
+ }
+ virCommandFree(cmd);
+ VIR_FREE(helper);
+ VIR_FREE(dp);
+ return ret_val;
+}
char *qemuBuildFSStr(virDomainFSDefPtr fs,
- virBitmapPtr qemuCaps ATTRIBUTE_UNUSED)
+ virBitmapPtr qemuCaps ATTRIBUTE_UNUSED, int qemuSocket)
{
virBuffer opt = VIR_BUFFER_INITIALIZER;
const char *driver = qemuDomainFSDriverTypeToString(fs->fsdriver);
@@ -2683,6 +2735,10 @@ char *qemuBuildFSStr(virDomainFSDefPtr fs,
}
virBufferAsprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
+
+ if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_PROXY)
+ virBufferAsprintf(&opt, ",sock_fd=%d", qemuSocket);
+
virBufferAsprintf(&opt, ",path=%s", fs->src);
if (fs->readonly) {
@@ -5153,10 +5209,31 @@ qemuBuildCommandLine(virConnectPtr conn,
if (qemuCapsGet(qemuCaps, QEMU_CAPS_FSDEV)) {
for (i = 0 ; i < def->nfss ; i++) {
char *optstr;
+ int sockets[2] = {-1, -1};
virDomainFSDefPtr fs = def->fss[i];
+ /*
+ * If its a proxy FS, we need to create a socket pair
+ * and invoke proxy_helper
+ */
+ if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_PROXY) {
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_FSDEV_PROXY) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("proxy helper not supported"));
+ goto error;
+ }
+ /* create a socket pair */
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
+ virReportSystemError(errno, _("socketpair %s"), "failed");
+ goto error;
+ }
+ virCommandTransferFD(cmd, sockets[1]);
+ if (qemuInvokeProxyHelper(def->emulator, sockets[0],
+ fs->src) < 0)
+ goto error;
+ }
virCommandAddArg(cmd, "-fsdev");
- if (!(optstr = qemuBuildFSStr(fs, qemuCaps)))
+ if (!(optstr = qemuBuildFSStr(fs, qemuCaps, sockets[1])))
goto error;
virCommandAddArg(cmd, optstr);
VIR_FREE(optstr);
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index e999bc7..2da5ad0 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -89,7 +89,8 @@ char *qemuBuildDriveStr(virConnectPtr conn,
bool bootable,
virBitmapPtr qemuCaps);
char *qemuBuildFSStr(virDomainFSDefPtr fs,
- virBitmapPtr qemuCaps);
+ virBitmapPtr qemuCaps,
+ int qemuSocket);
/* Current, best practice */
char * qemuBuildDriveDevStr(virDomainDefPtr def,
diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c
index 2d15c94..6af2e68 100644
--- a/tests/qemuhelptest.c
+++ b/tests/qemuhelptest.c
@@ -679,7 +679,9 @@ mymain(void)
QEMU_CAPS_SCSI_BLOCK,
QEMU_CAPS_SCSI_CD,
QEMU_CAPS_IDE_CD,
- QEMU_CAPS_SCSI_LSI);
+ QEMU_CAPS_SCSI_LSI,
+ QEMU_CAPS_FSDEV_PROXY);
+
DO_TEST("qemu-1.1.0", 1001000, 0, 0,
QEMU_CAPS_VNC_COLON,
QEMU_CAPS_NO_REBOOT,
@@ -759,7 +761,8 @@ mymain(void)
QEMU_CAPS_NEC_USB_XHCI,
QEMU_CAPS_NETDEV_BRIDGE,
QEMU_CAPS_SCSI_LSI,
- QEMU_CAPS_VIRTIO_SCSI_PCI);
+ QEMU_CAPS_VIRTIO_SCSI_PCI,
+ QEMU_CAPS_FSDEV_PROXY);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
1.7.7.6
12 years, 3 months
[libvirt] [PATCH] events: Fix domain event race on client disconnect
by Christophe Fergeau
GNOME Boxes sometimes stops getting domain events from libvirtd, even
after restarting it. Further investigation in libvirtd shows that
events are properly queued with virDomainEventStateQueue, but the
timer virDomainEventTimer which flushes the events and sends them to
the clients never gets called. Looking at the event queue in gdb
shows that it's non-empty and that its size increases with each new
events.
virDomainEventTimer is set up in virDomainEventStateRegister[ID]
when going from 0 client connecte to 1 client connected, but is
initially disabled. The timer is removed in
virDomainEventStateRegister[ID] when the last client is disconnected
(going from 1 client connected to 0).
This timer (which handles sending the events to the clients) is
enabled in virDomainEventStateQueue when queueing an event on an
empty queue (queue containing 0 events). It's disabled in
virDomainEventStateFlush after flushing the queue (ie removing all
the elements from it). This way, no extra work is done when the queue
is empty, and when the next event comes up, the timer will get
reenabled because the queue will go from 0 event to 1 event, which
triggers enabling the timer.
However, with this Boxes bug, we have a client connected (Boxes), a
non-empty queue (there are events waiting to be sent), but a disabled
timer, so something went wrong.
When Boxes connects (it's the only client connecting to the libvirtd
instance I used for debugging), the event timer is not set as expected
(state->timer == -1 when virDomainEventStateRegisterID is called),
but at the same time the event queue is not empty. In other words,
we had no clients connected, but pending events. This also explains
why the timer never gets enabled as this is only done when an event
is queued on an empty queue.
I think this can happen if an event gets queued using
virDomainEventStateQueue and the client disconnection happens before
the event timer virDomainEventTimer gets a chance to run and flush
the event. In this situation, virDomainEventStateDeregister[ID] will
get called with a non-empty event queue, the timer will be destroyed
if this was the only client connected. Then, when other clients connect
at a later time, they will never get notified about domain events as
the event timer will never get enabled because the timer is only
enabled if the event queue is empty when virDomainEventStateRegister[ID]
gets called, which will is no longer the case.
To avoid this issue, this commit makes sure to remove all events from
the event queue when the last client in unregistered. As there is
no longer anyone interested in receiving these events, these events
are stale so there is no need to keep them around. A client connecting
later will have no interest in getting events that happened before it
got connected.
---
src/conf/domain_event.c | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index 43ecdcf..7ab973b 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -525,13 +525,13 @@ void virDomainEventFree(virDomainEventPtr event)
}
/**
- * virDomainEventQueueFree:
+ * virDomainEventQueueClear:
* @queue: pointer to the queue
*
- * Free the memory in the queue. We process this like a list here
+ * Removes all elements from the queue
*/
static void
-virDomainEventQueueFree(virDomainEventQueuePtr queue)
+virDomainEventQueueClear(virDomainEventQueuePtr queue)
{
int i;
if (!queue)
@@ -541,6 +541,22 @@ virDomainEventQueueFree(virDomainEventQueuePtr queue)
virDomainEventFree(queue->events[i]);
}
VIR_FREE(queue->events);
+ queue->count = 0;
+}
+
+/**
+ * virDomainEventQueueFree:
+ * @queue: pointer to the queue
+ *
+ * Free the memory in the queue. We process this like a list here
+ */
+static void
+virDomainEventQueueFree(virDomainEventQueuePtr queue)
+{
+ if (!queue)
+ return;
+
+ virDomainEventQueueClear(queue);
VIR_FREE(queue);
}
@@ -1559,6 +1575,7 @@ virDomainEventStateDeregister(virConnectPtr conn,
state->timer != -1) {
virEventRemoveTimeout(state->timer);
state->timer = -1;
+ virDomainEventQueueClear(state->queue);
}
virDomainEventStateUnlock(state);
@@ -1596,6 +1613,7 @@ virDomainEventStateDeregisterID(virConnectPtr conn,
state->timer != -1) {
virEventRemoveTimeout(state->timer);
state->timer = -1;
+ virDomainEventQueueClear(state->queue);
}
virDomainEventStateUnlock(state);
--
1.7.11.4
12 years, 3 months
[libvirt] [RFC PATCH v1 0/2] Qemu/Gluster support in Libvirt
by Harsh Prateek Bora
This patchset provides support for Gluster protocol based network disks.
It is based on the proposed gluster support in Qemu on qemu-devel:
http://lists.gnu.org/archive/html/qemu-devel/2012-08/msg01539.html
TODO:
- Add support for IPv6 format based server addr
- Support for transport types other than socket.
Harsh Prateek Bora (2):
Qemu/Gluster: Add Gluster protocol as supported network disk formats.
tests: Add tests for gluster protocol based network disks support
docs/schemas/domaincommon.rng | 8 ++
src/conf/domain_conf.c | 14 ++-
src/conf/domain_conf.h | 3 +-
src/qemu/qemu_command.c | 123 +++++++++++++++++++++
tests/qemuargv2xmltest.c | 1 +
.../qemuxml2argv-disk-drive-network-gluster.args | 1 +
.../qemuxml2argv-disk-drive-network-gluster.xml | 33 ++++++
tests/qemuxml2argvtest.c | 2 +
8 files changed, 182 insertions(+), 3 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-gluster.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-gluster.xml
--
1.7.11.2
12 years, 3 months
[libvirt] [PATCH V4] implement offline migration
by liguang
allow migration even domain isn't active by
inserting some stubs to tunnel migration path.
Signed-off-by: liguang <lig.fnst(a)cn.fujitsu.com>
---
src/qemu/qemu_driver.c | 2 +-
src/qemu/qemu_migration.c | 181
+++++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_migration.h | 3 +-
3 files changed, 178 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d74bf52..00ca211 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9779,7 +9779,7 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr
dconn,
virCheckFlags(QEMU_MIGRATION_FLAGS, -1);
- if (!dom_xml) {
+ if (!dom_xml && !(flags & VIR_MIGRATE_OFFLINE)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("no domain XML passed"));
goto cleanup;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1b21ef6..991bcc5 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -70,6 +70,7 @@ enum qemuMigrationCookieFlags {
QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT,
+ QEMU_MIGRATION_COOKIE_FLAG_OFFLINE,
QEMU_MIGRATION_COOKIE_FLAG_LAST
};
@@ -77,12 +78,13 @@ enum qemuMigrationCookieFlags {
VIR_ENUM_DECL(qemuMigrationCookieFlag);
VIR_ENUM_IMPL(qemuMigrationCookieFlag,
QEMU_MIGRATION_COOKIE_FLAG_LAST,
- "graphics", "lockstate", "persistent");
+ "graphics", "lockstate", "persistent", "offline");
enum qemuMigrationCookieFeatures {
QEMU_MIGRATION_COOKIE_GRAPHICS = (1 <<
QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS),
QEMU_MIGRATION_COOKIE_LOCKSTATE = (1 <<
QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE),
QEMU_MIGRATION_COOKIE_PERSISTENT = (1 <<
QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT),
+ QEMU_MIGRATION_COOKIE_OFFLINE = (1 <<
QEMU_MIGRATION_COOKIE_FLAG_OFFLINE),
};
typedef struct _qemuMigrationCookieGraphics
qemuMigrationCookieGraphics;
@@ -101,6 +103,10 @@ struct _qemuMigrationCookie {
unsigned int flags;
unsigned int flagsMandatory;
+ /*offline migration flag*/
+ int offline;
+ char *mig_file;
+
/* Host properties */
unsigned char localHostuuid[VIR_UUID_BUFLEN];
unsigned char remoteHostuuid[VIR_UUID_BUFLEN];
@@ -139,6 +145,8 @@ static void
qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
if (mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS)
qemuMigrationCookieGraphicsFree(mig->graphics);
+ if (mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS)
+ VIR_FREE(mig->mig_file);
VIR_FREE(mig->localHostname);
VIR_FREE(mig->remoteHostname);
@@ -439,6 +447,12 @@ qemuMigrationCookieXMLFormat(struct qemud_driver
*driver,
virBufferAdjustIndent(buf, -2);
}
+ if (mig->flags & QEMU_MIGRATION_COOKIE_OFFLINE) {
+ virBufferAsprintf(buf, " <offline mig_ol='%d' mig_file='%
s'>\n",
+ mig->offline, mig->mig_file);
+ virBufferAddLit(buf, " </offline>\n");
+ }
+
virBufferAddLit(buf, "</qemu-migration>\n");
return 0;
}
@@ -662,6 +676,18 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr
mig,
VIR_FREE(nodes);
}
+ if ((flags & QEMU_MIGRATION_COOKIE_OFFLINE) &&
+ virXPathBoolean("count(./offline) > 0", ctxt)) {
+ if (virXPathInt("string(./offline/@mig_ol)", ctxt,
&mig->offline) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing mig_ol attribute in
migration data"));
+ goto error;
+ }
+ mig->mig_file = virXPathString("string(./offline/@mig_file)",
ctxt);
+ if (mig->mig_file && STREQ(mig->mig_file, ""))
+ VIR_FREE(mig->mig_file);
+ }
+
return 0;
error:
@@ -721,6 +747,12 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
qemuMigrationCookieAddPersistent(mig, dom) < 0)
return -1;
+ if (flags & QEMU_MIGRATION_COOKIE_OFFLINE) {
+ mig->flags |= QEMU_MIGRATION_COOKIE_OFFLINE;
+ mig->offline = 1;
+ }
+
+
if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
return -1;
@@ -1307,6 +1339,27 @@ qemuMigrationPrepareAny(struct qemud_driver
*driver,
/* Domain starts inactive, even if the domain XML had an id field.
*/
vm->def->id = -1;
+ if (tunnel) {
+ if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein,
cookieinlen,
+
QEMU_MIGRATION_COOKIE_OFFLINE)))
+ return ret;
+ else if (mig->offline) {
+ char *file, *str, *tmp = NULL;
+ ret = 0;
+ for (str = mig->mig_file; ; str = NULL) {
+ file = strtok_r(str, " ", &tmp);
+ if (file == NULL)
+ break;
+ if (virFDStreamCreateFile(st, file, 0, 0, O_WRONLY, 0)
< 0) {
+ virReportSystemError(errno, "%s",
+ _("cannot setup stream for
tunnelled migration\n"));
+ ret = -1;
+ }
+ }
+ goto endjob;
+ }
+ }
+
if (tunnel &&
(pipe(dataFD) < 0 || virSetCloseExec(dataFD[1]) < 0)) {
virReportSystemError(errno, "%s",
@@ -2303,6 +2356,117 @@ cleanup:
return ret;
}
+static int
+doReadFile(virStreamPtr st ATTRIBUTE_UNUSED,
+ char *buf, size_t nbytes, void *opaque)
+{
+ int *fd = opaque;
+
+ return saferead(*fd, buf, nbytes);
+}
+
+
+/*
+ * do offline migration
+ */
+static int doMigrateOffline(struct qemud_driver *driver,
+ virConnectPtr dconn,
+ virDomainObjPtr vm,
+ const char *cookiein,
+ int cookieinlen,
+ char **cookieout,
+ int *cookieoutlen,
+ unsigned long flags,
+ const char *dom_xml,
+ const char *dname,
+ virStreamPtr st,
+ unsigned long resource)
+{
+ xmlDocPtr xml = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlNodePtr *disks = NULL;
+ qemuMigrationCookiePtr mig = NULL;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ int i = 0, cn = 0, fd = -1, ret = -1;
+ char *src[] = {NULL}, *files = NULL;
+
+ VIR_DEBUG("driver=%p, vm=%p, st=%p, cookiein=%s, cookieinlen=%d, "
+ "cookieout=%p, cookieoutlen=%p, dom_xml=%s,"
+ "dname=%s, flags=%lx, resource=%lu",
+ driver, vm, st, NULLSTR(cookiein), cookieinlen,
+ cookieout, cookieoutlen, dom_xml, dname, flags,
resource);
+
+ xml = virXMLParseStringCtxt(dom_xml, _("(domain_definition)"),
&ctxt);
+ if (!xml) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("can't parse dom_xml for offline migration
\n"));
+ goto cleanup;
+ }
+ cn = virXPathNodeSet("./devices/disk", ctxt, &disks);
+ if (cn < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Fail to get disk node\n"));
+ goto cleanup;
+ }
+ cn = 1;
+
+ for (i = 0 ; i < cn ; i++) {
+ ctxt->node = disks[i];
+ src[i] = virXPathString("string(./source/@file"
+ "|./source/@dir"
+ "|./source/@name)", ctxt);
+ virBufferAsprintf(&buf, "%s ", src[i]);
+ }
+
+ files = virBufferContentAndReset(&buf);
+
+ if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0)))
+ goto cleanup;
+
+ mig->mig_file = files;
+
+ if (qemuMigrationBakeCookie(mig, driver, vm,
+ cookieout, cookieoutlen,
+ QEMU_MIGRATION_COOKIE_OFFLINE) < 0)
+ goto cleanup;
+
+ cookiein = *cookieout;
+ cookieinlen = *cookieoutlen;
+ cookieout = NULL;
+ cookieoutlen = 0;
+
+ qemuDomainObjEnterRemoteWithDriver(driver, vm);
+ ret = dconn->driver->domainMigratePrepareTunnel3
+ (dconn, st, cookiein, cookieinlen,
+ cookieout, cookieoutlen,
+ flags, dname, resource, dom_xml);
+ qemuDomainObjExitRemoteWithDriver(driver, vm);
+ if (ret == -1)
+ goto cleanup;
+
+ for (i = 0; i < cn; i++) {
+ if ((fd = open(src[i], O_RDONLY)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s %s",
+ _("Fail to open file for offline migration
\n"), src[i]);
+ goto cleanup;
+ }
+ if (virStreamSendAll(st, doReadFile, &fd) < 0)
+ goto cleanup;
+ if (VIR_CLOSE(fd) < 0)
+ goto cleanup;
+ }
+
+ if (virStreamFinish(st) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(files);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xml);
+ return ret;
+}
/* This is essentially a re-impl of virDomainMigrateVersion3
* from libvirt.c, but running in source libvirtd context,
@@ -2357,7 +2521,13 @@ static int doPeer2PeerMigrate3(struct
qemud_driver *driver,
if (flags & VIR_MIGRATE_TUNNELLED) {
if (!(st = virStreamNew(dconn, 0)))
goto cleanup;
-
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ if (doMigrateOffline(driver, dconn, vm, cookiein,
cookieinlen,
+ &cookieout, &cookieoutlen, flags,
dom_xml,
+ dname, st, resource) != -1)
+ ret = 0;
+ goto cleanup;
+ }
qemuDomainObjEnterRemoteWithDriver(driver, vm);
ret = dconn->driver->domainMigratePrepareTunnel3
(dconn, st, cookiein, cookieinlen,
@@ -2477,7 +2647,7 @@ finish:
vm->def->name);
cleanup:
- if (ddomain) {
+ if (ddomain || (flags & VIR_MIGRATE_OFFLINE)) {
virObjectUnref(ddomain);
ret = 0;
} else {
@@ -2557,7 +2727,7 @@ static int doPeer2PeerMigrate(struct qemud_driver
*driver,
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest unexpectedly quit"));
- goto cleanup;
+ flags |= VIR_MIGRATE_OFFLINE;
}
/* Change protection is only required on the source side (us), and
@@ -2573,7 +2743,6 @@ static int doPeer2PeerMigrate(struct qemud_driver
*driver,
else
ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm,
dconnuri, flags, dname, resource);
-
cleanup:
orig_err = virSaveLastError();
qemuDomainObjEnterRemoteWithDriver(driver, vm);
@@ -2620,7 +2789,7 @@ qemuMigrationPerformJob(struct qemud_driver
*driver,
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
- goto endjob;
+ flags |= VIR_MIGRATE_OFFLINE;
}
if (!qemuMigrationIsAllowed(driver, vm, NULL))
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index 1740204..2bcaea0 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -36,7 +36,8 @@
VIR_MIGRATE_NON_SHARED_DISK | \
VIR_MIGRATE_NON_SHARED_INC | \
VIR_MIGRATE_CHANGE_PROTECTION | \
- VIR_MIGRATE_UNSAFE)
+ VIR_MIGRATE_UNSAFE | \
+ VIR_MIGRATE_OFFLINE)
enum qemuMigrationJobPhase {
QEMU_MIGRATION_PHASE_NONE = 0,
--
1.7.2.5
12 years, 3 months
Re: [libvirt] Memory free in libvirt JNA
by Benjamin Wang (gendwang)
Hi,
Overview Part of JNA API describes as following:
1. Description1:
If the native method returns char* and actually allocates memory, a return type of Pointer should be used to avoid leaking the memory. It is then up to you to take the necessary steps to free the allocated memory.
2. Description2:
Declare the method as returning a Structure of the appropriate type, then invoke Structure.toArray(int) to convert to an array of initialized structures of the appropriate size. Note that your Structure class must have a no-args constructor, and you are responsible for freeing the returned memory if applicable in whatever way is appropriate for the called function.
And the example code shows as following:
// Original C code
struct Display* get_displays(int* pcount);
void free_displays(struct Display* displays);
// Equivalent JNA mapping
Display get_displays(IntByReference pcount);
void free_displays(Display[] displays);
...
IntByReference pcount = new IntByReference();
Display d = lib.get_displays(pcount);
Display[] displays = (Display[])d.toArray(pcount.getValue());
...
lib.free_displays(displays);
That's to say. All the memory allocated by native code must be freed explicitly in JNA part. We must add some free memory methods to support the memory-freeing.
Any comments?
B.R.
Benjamin Wang
-----Original Message-----
From: Daniel Veillard [mailto:veillard@redhat.com]
Sent: 2012年8月20日 14:25
To: Benjamin Wang (gendwang)
Cc: stoty(a)tvnet.hu; Daniel.Schwager(a)dtnet.de
Subject: Re: Memory free in libvirt JNA
On Mon, Aug 20, 2012 at 05:15:45AM +0000, Benjamin Wang (gendwang) wrote:
> Hi Veillard,
> Thanks for your reply. I checked the current Libvirt-JNA
> implementation. I find that a method named "free" defined in Domain
> class which is used to free the domain object. If this is mandatory, that's to say, we should a lot of methods into the current Libvirt-jna implementation to free the memory which is allocated by libvirt API. Please correct me!
As far as I understat free() is aliased as finalize() on that object so the java runtime will call free() automatically on garbage collection. I'm not a java expert, check some Java litterature for more details about how this is done and the cases where
free() might be better called directly.
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
12 years, 3 months
[libvirt] [PATCH] Fix location of SELinux mount during RPM builds
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
When building RPMs the host kernel cannot be assumed to match
the target OS kernel. Thus auto-detecting /selinux vs
/sys/fs/selinux based on the host kernel can result in the
wrong choice (eg F18 builds on a RHEL6 host kernel)
---
libvirt.spec.in | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 044b00f..fb35934 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1222,6 +1222,15 @@ of recent versions of Linux (and other OSes).
%if 0%{?enable_autotools}
autoreconf -if
%endif
+
+%if %{with_selinux}
+%if %{?fedora} >= 17 || %{?rhel} >= 7
+%define with_selinux_mount --with-selinux-mount="/sys/fs/cgroup"
+%else
+%define with_selinux_mount --with-selinux-mount="/selinux"
+%endif
+%endif
+
%configure %{?_without_xen} \
%{?_without_qemu} \
%{?_without_openvz} \
@@ -1254,6 +1263,7 @@ autoreconf -if
%{?_without_capng} \
%{?_without_netcf} \
%{?_without_selinux} \
+ %{?_with_selinux_mount} \
%{?_without_hal} \
%{?_without_udev} \
%{?_without_yajl} \
--
1.7.11.2
12 years, 3 months