[libvirt] [PATCH 0/2] schemas: Remove useless definition
by Martin Kletzander
Let's save 21 lines just because I've found out a way how to convince
xmllint to do something we thought it can't. The first patch is the
brains of this operation, the second one is just a cleaner guy; best
served with '-w'.
Martin Kletzander (2):
schema: Remove unnecessary interface-options
schema: Indent interface properly
docs/schemas/domaincommon.rng | 787 ++++++++++++++++++++----------------------
1 file changed, 383 insertions(+), 404 deletions(-)
--
2.2.2
9 years, 9 months
[libvirt] [PATCH] xend: Don't crash in virDomainXMLDevID
by Michal Privoznik
The function is called from all {Attach,Update,Detach}Device APIs to
create config strings that are later passed to the xend to perform the
desired action. The function is intended to handle all supported
devices. However, as of 5b05358abacb1029fa0d61f72decacf0d4fd8ffb we
are trying to get disk driver of the device without checking if the
device really is a disk. This leads to an segmentation fault:
#0 0x00007ffff7571815 in virDomainDiskGetDriver () from /usr/lib/libvirt.so.0
#1 0x00007fffeb9ad471 in ?? () from /usr/lib/libvirt/connection-driver/libvirt_driver_xen.so
#2 0x00007fffeb9b1062 in xenDaemonAttachDeviceFlags () from /usr/lib/libvirt/connection-driver/libvirt_driver_xen.so
#3 0x00007fffeb9a8a86 in ?? () from /usr/lib/libvirt/connection-driver/libvirt_driver_xen.so
#4 0x00007ffff7609266 in virDomainAttachDevice () from /usr/lib/libvirt.so.0
#5 0x0000555555593c9d in ?? ()
#6 0x00007ffff76743c9 in virNetServerProgramDispatch () from /usr/lib/libvirt.so.0
#7 0x00005555555a678d in ?? ()
#8 0x00007ffff755460e in ?? () from /usr/lib/libvirt.so.0
#9 0x00007ffff7553b06 in ?? () from /usr/lib/libvirt.so.0
#10 0x00007ffff4998b50 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#11 0x00007ffff46e30ed in clone () from /lib/x86_64-linux-gnu/libc.so.6
#12 0x0000000000000000 in ?? ()
Reported-by: Xiaolin Su <linxxnil(a)126.com>
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/xen/xend_internal.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index a51cb20..c2b9098 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -3329,9 +3329,10 @@ virDomainXMLDevID(virConnectPtr conn,
xenUnifiedPrivatePtr priv = conn->privateData;
char *xref;
char *tmp;
- const char *driver = virDomainDiskGetDriver(dev->data.disk);
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+ const char *driver = virDomainDiskGetDriver(dev->data.disk);
+
if (STREQ_NULLABLE(driver, "tap") || STREQ_NULLABLE(driver, "tap2"))
strcpy(class, driver);
else
--
2.0.5
9 years, 9 months
[libvirt] [PATCH v3 1/2] util: Functions for getting/setting device options
by akrowiak@linux.vnet.ibm.com
From: Tony Krowiak <akrowiak(a)linux.vnet.ibm.com>
This patch provides the utility functions needed to synchronize
the rxfilter changes made to a guest domain with the corresponding
macvtap devices on the host:
* Get/set PROMISC flag
* Get/set ALLMULTI, MULTICAST
Signed-off-by: Tony Krowiak <akrowiak(a)linux.vnet.ibm.com>
---
Changes for v3:
* Fixed a syntax-check error in virNetDevGetRxFilter function
src/libvirt_private.syms | 8 ++-
src/util/virnetdev.c | 186 +++++++++++++++++++++++++++++++++++++++-------
src/util/virnetdev.h | 24 ++++++-
3 files changed, 190 insertions(+), 28 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a2eec83..8d76f9b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1639,13 +1639,16 @@ virNetDevGetIPv4Address;
virNetDevGetLinkInfo;
virNetDevGetMAC;
virNetDevGetMTU;
+virNetDevGetOnline;
virNetDevGetPhysicalFunction;
+virNetDevGetPromiscuous;
+virNetDevGetRcvAllMulti;
+virNetDevGetRcvMulti;
virNetDevGetRxFilter;
virNetDevGetVirtualFunctionIndex;
virNetDevGetVirtualFunctionInfo;
virNetDevGetVirtualFunctions;
virNetDevGetVLanID;
-virNetDevIsOnline;
virNetDevIsVirtualFunction;
virNetDevLinkDump;
virNetDevReplaceMacAddress;
@@ -1663,6 +1666,9 @@ virNetDevSetMTUFromDevice;
virNetDevSetName;
virNetDevSetNamespace;
virNetDevSetOnline;
+virNetDevSetPromiscuous;
+virNetDevSetRcvAllMulti;
+virNetDevSetRcvMulti;
virNetDevSetupControl;
virNetDevValidateConfig;
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index ef96b2b..5d330ce 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -610,17 +610,7 @@ int virNetDevSetName(const char* ifname, const char *newifname)
#if defined(SIOCSIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
-/**
- * virNetDevSetOnline:
- * @ifname: the interface name
- * @online: true for up, false for down
- *
- * Function to control if an interface is activated (up, true) or not (down, false)
- *
- * Returns 0 in case of success or -1 on error.
- */
-int virNetDevSetOnline(const char *ifname,
- bool online)
+int virNetDevSetIFFlag(const char *ifname, int flag, bool val)
{
int fd = -1;
int ret = -1;
@@ -637,10 +627,10 @@ int virNetDevSetOnline(const char *ifname,
goto cleanup;
}
- if (online)
- ifflags = ifr.ifr_flags | IFF_UP;
+ if (val)
+ ifflags = ifr.ifr_flags | flag;
else
- ifflags = ifr.ifr_flags & ~IFF_UP;
+ ifflags = ifr.ifr_flags & ~flag;
if (ifr.ifr_flags != ifflags) {
ifr.ifr_flags = ifflags;
@@ -659,8 +649,9 @@ int virNetDevSetOnline(const char *ifname,
return ret;
}
#else
-int virNetDevSetOnline(const char *ifname,
- bool online ATTRIBUTE_UNUSED)
+int virNetDevSetIFFlag(const char *ifname,
+ int flag ATTRIBUTE_UNUSED,
+ bool val ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS,
_("Cannot set interface flags on '%s'"),
@@ -670,18 +661,77 @@ int virNetDevSetOnline(const char *ifname,
#endif
-#if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
+
/**
- * virNetDevIsOnline:
+ * virNetDevSetOnline:
* @ifname: the interface name
- * @online: where to store the status
+ * @online: true for up, false for down
*
- * Function to query if an interface is activated (true) or not (false)
+ * Function to control if an interface is activated (up, true) or not (down, false)
*
- * Returns 0 in case of success or an errno code in case of failure.
+ * Returns 0 in case of success or -1 on error.
*/
-int virNetDevIsOnline(const char *ifname,
- bool *online)
+int virNetDevSetOnline(const char *ifname,
+ bool online)
+{
+
+ return virNetDevSetIFFlag(ifname, IFF_UP, online);
+}
+
+/**
+ * virNetDevSetPromiscuous:
+ * @ifname: the interface name
+ * @promiscuous: true for receive all packets, false for do not receive
+ * all packets
+ *
+ * Function to control if an interface is to receive all
+ * packets (receive all, true) or not (do not receive all, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetPromiscuous(const char *ifname,
+ bool promiscuous)
+{
+ return virNetDevSetIFFlag(ifname, IFF_PROMISC, promiscuous);
+}
+
+/**
+ * virNetDevSetRcvMulti:
+ * @ifname: the interface name
+ * @:receive true for receive multicast packets, false for do not receive
+ * multicast packets
+ *
+ * Function to control if an interface is to receive multicast
+ * packets in which it is interested (receive, true)
+ * or not (do not receive, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetRcvMulti(const char *ifname,
+ bool receive)
+{
+ return virNetDevSetIFFlag(ifname, IFF_MULTICAST, receive);
+}
+
+/**
+ * virNetDevSetRcvAllMulti:
+ * @ifname: the interface name
+ * @:receive true for receive all packets, false for do not receive all packets
+ *
+ * Function to control if an interface is to receive all multicast
+ * packets (receive, true) or not (do not receive, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetRcvAllMulti(const char *ifname,
+ bool receive)
+{
+ return virNetDevSetIFFlag(ifname, IFF_ALLMULTI, receive);
+}
+
+
+#if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
+int virNetDevGetIFFlag(const char *ifname, int flag, bool *val)
{
int fd = -1;
int ret = -1;
@@ -697,7 +747,7 @@ int virNetDevIsOnline(const char *ifname,
goto cleanup;
}
- *online = (ifr.ifr_flags & IFF_UP) ? true : false;
+ *val = (ifr.ifr_flags & flag) ? true : false;
ret = 0;
cleanup:
@@ -705,8 +755,9 @@ int virNetDevIsOnline(const char *ifname,
return ret;
}
#else
-int virNetDevIsOnline(const char *ifname,
- bool *online ATTRIBUTE_UNUSED)
+int virNetDevGetIFFlag(const char *ifname,
+ int flag ATTRIBUTE_UNUSED,
+ bool *val ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS,
_("Cannot get interface flags on '%s'"),
@@ -717,6 +768,70 @@ int virNetDevIsOnline(const char *ifname,
/**
+ * virNetDevGetOnline:
+ * @ifname: the interface name
+ * @online: where to store the status
+ *
+ * Function to query if an interface is activated (true) or not (false)
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+int virNetDevGetOnline(const char *ifname,
+ bool *online)
+{
+ return virNetDevGetIFFlag(ifname, IFF_UP, online);
+}
+
+/**
+ * virNetDevIsPromiscuous:
+ * @ifname: the interface name
+ * @promiscuous: where to store the status
+ *
+ * Function to query if an interface is receiving all packets (true) or
+ * not (false)
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+int virNetDevGetPromiscuous(const char *ifname,
+ bool *promiscuous)
+{
+ return virNetDevGetIFFlag(ifname, IFF_PROMISC, promiscuous);
+}
+
+/**
+ * virNetDevIsRcvMulti:
+ * @ifname: the interface name
+ * @receive where to store the status
+ *
+ * Function to query whether an interface is receiving multicast packets (true)
+ * in which it is interested, or not (false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevGetRcvMulti(const char *ifname,
+ bool *receive)
+{
+ return virNetDevGetIFFlag(ifname, IFF_MULTICAST, receive);
+}
+
+/**
+ * virNetDevIsRcvAllMulti:
+ * @ifname: the interface name
+ * @:receive where to store the status
+ *
+ * Function to query whether an interface is receiving all multicast
+ * packets (receiving, true) or not (is not receiving, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevGetRcvAllMulti(const char *ifname,
+ bool *receive)
+{
+ return virNetDevGetIFFlag(ifname, IFF_ALLMULTI, receive);
+}
+
+
+/**
* virNetDevGetIndex:
* @ifname : Name of the interface whose index is to be found
* @ifindex: Pointer to int where the index will be written into
@@ -2549,6 +2664,7 @@ int virNetDevGetRxFilter(const char *ifname,
virNetDevRxFilterPtr *filter)
{
int ret = -1;
+ bool receive;
virNetDevRxFilterPtr fil = virNetDevRxFilterNew();
if (!fil)
@@ -2560,6 +2676,24 @@ int virNetDevGetRxFilter(const char *ifname,
if (virNetDevGetMulticastTable(ifname, fil))
goto cleanup;
+ if (virNetDevGetPromiscuous(ifname, &fil->promiscuous))
+ goto cleanup;
+
+ if (virNetDevGetRcvAllMulti(ifname, &receive))
+ goto cleanup;
+
+ if (receive) {
+ fil->multicast.mode = VIR_NETDEV_RX_FILTER_MODE_ALL;
+ } else {
+ if (virNetDevGetRcvMulti(ifname, &receive))
+ goto cleanup;
+
+ if (receive)
+ fil->multicast.mode = VIR_NETDEV_RX_FILTER_MODE_NORMAL;
+ else
+ fil->multicast.mode = VIR_NETDEV_RX_FILTER_MODE_NONE;
+ }
+
ret = 0;
cleanup:
if (ret < 0) {
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index fb7988f..8d03459 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -83,7 +83,7 @@ int virNetDevExists(const char *brname)
int virNetDevSetOnline(const char *ifname,
bool online)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-int virNetDevIsOnline(const char *ifname,
+int virNetDevGetOnline(const char *ifname,
bool *online)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
@@ -200,4 +200,26 @@ int virNetDevDelMulti(const char *ifname,
virMacAddrPtr macaddr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevSetIFFlag(const char *ifname, int flag, bool val)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevGetIFFlag(const char *ifname, int flag, bool *val)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevSetPromiscuous(const char *ifname, bool promiscuous)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevGetPromiscuous(const char *ifname, bool *promiscuous)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevSetRcvMulti(const char *ifname, bool receive)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevGetRcvMulti(const char *ifname, bool *receive)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevSetRcvAllMulti(const char *ifname, bool receive)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevGetRcvAllMulti(const char *ifname, bool *receive)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
#endif /* __VIR_NETDEV_H__ */
--
1.7.1
9 years, 9 months
[libvirt] [PATCH v3] conf: Don't mangle vcpu placement randomly
by Michal Privoznik
https://bugzilla.redhat.com/show_bug.cgi?id=1170492
In one of our previous commits (dc8b7ce7) we've done a functional
change even though it was intended as pure refactor. The problem is,
that the following XML:
<vcpu placement='static' current='2'>6</vcpu>
<cputune>
<emulatorpin cpuset='1-3'/>
</cputune>
<numatune>
<memory mode='strict' placement='auto'/>
</numatune>
gets translated into this one:
<vcpu placement='auto' current='2'>6</vcpu>
<cputune>
<emulatorpin cpuset='1-3'/>
</cputune>
<numatune>
<memory mode='strict' placement='auto'/>
</numatune>
We should not change the vcpu placement mode. Moreover, we're doing
something similar in case of emulatorpin and iothreadpin. If they were
set, but vcpu placement was auto, we've mistakenly removed them from
the domain XML even though we are able to set them independently on
vcpus.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
diff to v2:
-Martin's review worked in
src/conf/domain_conf.c | 84 +++++++++-------------
.../qemuxml2argv-cputune-numatune.xml | 35 +++++++++
tests/qemuxml2xmltest.c | 1 +
3 files changed, 70 insertions(+), 50 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cputune-numatune.xml
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d562e1a..706e5d2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13084,28 +13084,20 @@ virDomainDefParseXML(xmlDocPtr xml,
goto error;
}
- /* Ignore emulatorpin if <vcpu> placement is "auto", they
- * conflicts with each other, and <vcpu> placement can't be
- * simply ignored, as <numatune>'s placement defaults to it.
- */
if (n) {
- if (def->placement_mode != VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
- if (n > 1) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("only one emulatorpin is supported"));
- VIR_FREE(nodes);
- goto error;
- }
-
- def->cputune.emulatorpin = virDomainVcpuPinDefParseXML(nodes[0],
- ctxt, 0,
- true, false);
-
- if (!def->cputune.emulatorpin)
- goto error;
- } else {
- VIR_WARN("Ignore emulatorpin for <vcpu> placement is 'auto'");
+ if (n > 1) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("only one emulatorpin is supported"));
+ VIR_FREE(nodes);
+ goto error;
}
+
+ def->cputune.emulatorpin = virDomainVcpuPinDefParseXML(nodes[0],
+ ctxt, 0,
+ true, false);
+
+ if (!def->cputune.emulatorpin)
+ goto error;
}
VIR_FREE(nodes);
@@ -13116,38 +13108,28 @@ virDomainDefParseXML(xmlDocPtr xml,
goto error;
}
- /* Ignore iothreadpin if <vcpu> placement is "auto", they
- * conflict with each other, and <vcpu> placement can't be
- * simply ignored, as <numatune>'s placement defaults to it.
- */
- if (n) {
- if (def->placement_mode != VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
- if (VIR_ALLOC_N(def->cputune.iothreadspin, n) < 0)
- goto error;
+ if (n && VIR_ALLOC_N(def->cputune.iothreadspin, n) < 0)
+ goto error;
- for (i = 0; i < n; i++) {
- virDomainVcpuPinDefPtr iothreadpin = NULL;
- iothreadpin = virDomainVcpuPinDefParseXML(nodes[i], ctxt,
- def->iothreads,
- false, true);
- if (!iothreadpin)
- goto error;
+ for (i = 0; i < n; i++) {
+ virDomainVcpuPinDefPtr iothreadpin = NULL;
+ iothreadpin = virDomainVcpuPinDefParseXML(nodes[i], ctxt,
+ def->iothreads,
+ false, true);
+ if (!iothreadpin)
+ goto error;
- if (virDomainVcpuPinIsDuplicate(def->cputune.iothreadspin,
- def->cputune.niothreadspin,
- iothreadpin->vcpuid)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("duplicate iothreadpin for same iothread"));
- virDomainVcpuPinDefFree(iothreadpin);
- goto error;
- }
-
- def->cputune.iothreadspin[def->cputune.niothreadspin++] =
- iothreadpin;
- }
- } else {
- VIR_WARN("Ignore iothreadpin for <vcpu> placement is 'auto'");
+ if (virDomainVcpuPinIsDuplicate(def->cputune.iothreadspin,
+ def->cputune.niothreadspin,
+ iothreadpin->vcpuid)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("duplicate iothreadpin for same iothread"));
+ virDomainVcpuPinDefFree(iothreadpin);
+ goto error;
}
+
+ def->cputune.iothreadspin[def->cputune.niothreadspin++] =
+ iothreadpin;
}
VIR_FREE(nodes);
@@ -13185,7 +13167,9 @@ virDomainDefParseXML(xmlDocPtr xml,
ctxt) < 0)
goto error;
- if (virDomainNumatuneHasPlacementAuto(def->numatune) && !def->cpumask)
+ if (virDomainNumatuneHasPlacementAuto(def->numatune) &&
+ !def->cpumask && !def->cputune.vcpupin &&
+ !def->cputune.emulatorpin && !def->cputune.iothreadspin)
def->placement_mode = VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO;
if ((n = virXPathNodeSet("./resource", ctxt, &nodes)) < 0) {
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cputune-numatune.xml b/tests/qemuxml2argvdata/qemuxml2argv-cputune-numatune.xml
new file mode 100644
index 0000000..9759b48
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-cputune-numatune.xml
@@ -0,0 +1,35 @@
+<domain type='kvm'>
+ <name>dummy2</name>
+ <uuid>4d92ec27-9ebf-400b-ae91-20c71c647c19</uuid>
+ <memory unit='KiB'>131072</memory>
+ <currentMemory unit='KiB'>65536</currentMemory>
+ <vcpu placement='auto' current='2'>6</vcpu>
+ <cputune>
+ <emulatorpin cpuset='1-3'/>
+ </cputune>
+ <numatune>
+ <memory mode='strict' placement='auto'/>
+ </numatune>
+ <os>
+ <type arch='x86_64' machine='pc-q35-2.3'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <controller type='sata' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pcie-root'/>
+ <controller type='pci' index='1' model='dmi-to-pci-bridge'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/>
+ </controller>
+ <controller type='pci' index='2' model='pci-bridge'>
+ <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/>
+ </controller>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 4abb303..285538a 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -310,6 +310,7 @@ mymain(void)
DO_TEST("blkiotune-device");
DO_TEST("cputune");
DO_TEST("cputune-zero-shares");
+ DO_TEST("cputune-numatune");
DO_TEST("smp");
DO_TEST("iothreads");
--
2.0.5
9 years, 9 months
[libvirt] Bug fixing of libvirt -- attach-interface using xen driver
by linxxnil
Dear:
I think there was a bug, when attach-interface using xen driver.
when I use xen driver to attach interface for domain, the libvirtd will crash.
the info with GDB:
#0 0x00007ffff7571815 in virDomainDiskGetDriver () from /usr/lib/libvirt.so.0
#1 0x00007fffeb9ad471 in ?? () from /usr/lib/libvirt/connection-driver/libvirt_driver_xen.so
#2 0x00007fffeb9b1062 in xenDaemonAttachDeviceFlags () from /usr/lib/libvirt/connection-driver/libvirt_driver_xen.so
#3 0x00007fffeb9a8a86 in ?? () from /usr/lib/libvirt/connection-driver/libvirt_driver_xen.so
#4 0x00007ffff7609266 in virDomainAttachDevice () from /usr/lib/libvirt.so.0
#5 0x0000555555593c9d in ?? ()
#6 0x00007ffff76743c9 in virNetServerProgramDispatch () from /usr/lib/libvirt.so.0
#7 0x00005555555a678d in ?? ()
#8 0x00007ffff755460e in ?? () from /usr/lib/libvirt.so.0
#9 0x00007ffff7553b06 in ?? () from /usr/lib/libvirt.so.0
#10 0x00007ffff4998b50 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#11 0x00007ffff46e30ed in clone () from /lib/x86_64-linux-gnu/libc.so.6
#12 0x0000000000000000 in ?? ()
And I think the bug is at the function virDomainXMLDevID(), file path: src/xen/xend_internal.c
--------------------------------------------------
static int
virDomainXMLDevID(virConnectPtr conn, virDomainDefPtr def, virDomainDeviceDefPtr dev, char *class, char *ref, int ref_len)
{
xenUnifiedPrivatePtr priv = conn->privateData;
char *xref;
char *tmp;
const char *driver = virDomainDiskGetDriver(dev->data.disk);
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
if (STREQ_NULLABLE(driver, "tap") || STREQ_NULLABLE(driver, "tap2"))
strcpy(class, driver);
else
strcpy(class, "vbd");
-----------------------------------------------------------------
the follow line:
const char *driver = virDomainDiskGetDriver(dev->data.disk);
if the dev->data.disk not initialize before, the libvirt will crash.
And I changed it like this :
--------------------------------------------------------------
static int
virDomainXMLDevID(virConnectPtr conn, virDomainDefPtr def, virDomainDeviceDefPtr dev, char *class, char *ref, int ref_len)
{
xenUnifiedPrivatePtr priv = conn->privateData;
char *xref;
char *tmp;
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
const char *driver = virDomainDiskGetDriver(dev->data.disk);
if (STREQ_NULLABLE(driver, "tap") || STREQ_NULLABLE(driver, "tap2"))
strcpy(class, driver);
else
strcpy(class, "vbd");
-------------------------------------------------------------
It works fine
Would some confirm and fix it?
Xiaolin.Su
9 years, 9 months
[libvirt] [PATCH] Add ability to set rlimits at container boot
by Ryan Cleere
---
docs/formatdomain.html.in | 49 +++++++++++++++++++++++
docs/schemas/domaincommon.rng | 89
+++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.c | 92
+++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 33 ++++++++++++++++
src/libvirt_private.syms | 1 +
src/lxc/lxc_controller.c | 32 +++++++++++++++
src/util/virprocess.c | 4 +-
src/util/virprocess.h | 2 +
8 files changed, 300 insertions(+), 2 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f8d5f89..5aec51c 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -348,6 +348,55 @@
</pre>
+ <p>
+ If you want to set an rlimit of the containter init process instead
of
+ inheriting from the host init, set the <code>rlimits</code> element.
You
+ are able to set any of the rlimits that setrlimits is able to set
using
+ any of the following sub-elements:
+ </p>
+
+ <dl>
+ <dt><code>as</code></dt>
+ <dd>Used to set RLIMIT_AS.</dd>
+ <dt><code>core</code></dt>
+ <dd>Used to set RLIMIT_CORE.</dd>
+ <dt><code>cpu</code></dt>
+ <dd>Used to set RLIMIT_CPU.</dd>
+ <dt><code>data</code></dt>
+ <dd>Used to set RLIMIT_DATA.</dd>
+ <dt><code>fsize</code></dt>
+ <dd>Used to set RLIMIT_FSIZE.</dd>
+ <dt><code>locks</code></dt>
+ <dd>Used to set RLIMIT_LOCKS.</dd>
+ <dt><code>memlock</code></dt>
+ <dd>Used to set RLIMIT_MEMLOCK.</dd>
+ <dt><code>msgqueue</code></dt>
+ <dd>Used to set RLIMIT_MSGQUEUE.</dd>
+ <dt><code>nice</code></dt>
+ <dd>Used to set RLIMIT_NICE.</dd>
+ <dt><code>nofile</code></dt>
+ <dd>Used to set RLIMIT_NOFILE.</dd>
+ <dt><code>nproc</code></dt>
+ <dd>Used to set RLIMIT_NPROC.</dd>
+ <dt><code>rss</code></dt>
+ <dd>Used to set RLIMIT_RSS.</dd>
+ <dt><code>rtprio</code></dt>
+ <dd>Used to set RLIMIT_RTPRIO.</dd>
+ <dt><code>rttime</code></dt>
+ <dd>Used to set RLIMIT_RTTIME.</dd>
+ <dt><code>sigpending</code></dt>
+ <dd>Used to set RLIMIT_SIGPENDING.</dd>
+ <dt><code>stack</code></dt>
+ <dd>Used to set RLIMIT_STACK.</dd>
+ </dl>
+
+ <pre>
+ <rlimits>
+ <nofile>10240</nofile>
+ </rlimits>
+ </pre>
+
+
<h3><a name="elementsSysinfo">SMBIOS System Information</a></h3>
<p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index d467dce..b98f8d5 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -59,6 +59,9 @@
<ref name="idmap"/>
</optional>
<optional>
+ <ref name="rlimits"/>
+ </optional>
+ <optional>
<ref name="devices"/>
</optional>
<zeroOrMore>
@@ -570,6 +573,92 @@
</interleave>
</element>
</define>
+ <define name="rlimits">
+ <element name="rlimits">
+ <interleave>
+ <optional>
+ <element name="cpu">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="fsize">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="data">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="stack">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="core">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="rss">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="nproc">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="nofile">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="memlock">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="as">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="locks">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="sigpending">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="msgqueue">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="nice">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="rtprio">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ <optional>
+ <element name="rttime">
+ <ref name='scaledInteger'/>
+ </element>
+ </optional>
+ </interleave>
+ </element>
+ </define>
<!--
Resources usage defines the amount of memory (maximum and possibly
current usage) and number of virtual CPUs used by that domain.
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d562e1a..399976e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -772,6 +772,24 @@ VIR_ENUM_IMPL(virDomainLoader,
"rom",
"pflash")
+VIR_ENUM_IMPL(virDomainRLimit, VIR_DOMAIN_RLIMIT_LAST,
+ "cpu",
+ "fsize",
+ "data",
+ "stack",
+ "core",
+ "rss",
+ "nproc",
+ "nofile",
+ "memlock",
+ "as",
+ "locks",
+ "sigpending",
+ "msgqueue",
+ "nice",
+ "rtprio",
+ "rttime")
+
/* Internal mapping: subset of block job types that can be present in
* <mirror> XML (remaining types are not two-phase). */
VIR_ENUM_DECL(virDomainBlockJob)
@@ -979,7 +997,40 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,
return -1;
}
+static virDomainRLimitsPtr
+virDomainRLimitParseXML(xmlNodePtr node)
+{
+ char *c = NULL;
+ long long val;
+ virDomainRLimitsPtr def;
+
+ if (VIR_ALLOC(def) < 0)
+ return NULL;
+ if (node->type == XML_ELEMENT_NODE) {
+ c = (char *)xmlNodeGetContent(node);
+ if (virStrToLong_ll(c, NULL, 10, &val) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse rlimit value of %s"),
+ c);
+ goto error;
+ }
+ VIR_FREE(c);
+
+ def->limit = val;
+ if ((def->resource = virDomainRLimitTypeFromString((const char
*)node->name)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not determine resource type of '%s'"),
+ node->name);
+ goto error;
+ }
+ }
+ return def;
+ error:
+ VIR_FREE(c);
+ VIR_FREE(def);
+ return NULL;
+}
static void
virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
@@ -14423,6 +14474,34 @@ virDomainDefParseXML(xmlDocPtr xml,
virHashFree(bootHash);
+ if ((node = virXPathNode("./rlimits[1]", ctxt)) != NULL && (n =
virXMLChildElementCount(node)) > 0) {
+ xmlNodePtr cur = node->children;
+ if (n && VIR_ALLOC_N(def->rlimits, n) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ if (!(def->rlimits[i] = virDomainRLimitParseXML(cur))) {
+ for (j = 0; j < i; j++)
+ VIR_FREE(def->rlimits[j]);
+ VIR_FREE(def->rlimits);
+ goto error;
+ }
+ def->nrlimits++;
+ for (j = 0; j < i; j++) {
+ if (def->rlimits[j]->resource ==
def->rlimits[i]->resource) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("duplicate rlimit resources '%s'"),
+ virDomainRLimitTypeToString(def->rlimits[j]->resource));
+ for (int k = 0; k < i; k++)
+ VIR_FREE(def->rlimits[k]);
+ VIR_FREE(def->rlimits);
+ goto error;
+ }
+ }
+ cur = cur->next;
+ }
+ }
+
return def;
error:
@@ -20048,6 +20127,19 @@ virDomainDefFormatInternal(virDomainDefPtr def,
goto error;
}
+ if (def->nrlimits > 0) {
+ virBufferAddLit(buf, "<rlimits>\n");
+ virBufferAdjustIndent(buf, 2);
+ for (n = 0; n < def->nrlimits; n++) {
+ virBufferAsprintf(buf, "<%s>%lld</%s>\n",
+ virDomainRLimitTypeToString(def->rlimits[n]->resource),
+ def->rlimits[n]->limit,
+ virDomainRLimitTypeToString(def->rlimits[n]->resource));
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</rlimits>\n");
+ }
+
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</domain>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 93f2314..b032202 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1851,6 +1851,27 @@ typedef enum {
VIR_DOMAIN_CLOCK_BASIS_LAST
} virDomainClockBasis;
+typedef enum {
+ VIR_DOMAIN_RLIMIT_CPU,
+ VIR_DOMAIN_RLIMIT_FSIZE,
+ VIR_DOMAIN_RLIMIT_DATA,
+ VIR_DOMAIN_RLIMIT_STACK,
+ VIR_DOMAIN_RLIMIT_CORE,
+ VIR_DOMAIN_RLIMIT_RSS,
+ VIR_DOMAIN_RLIMIT_NPROC,
+ VIR_DOMAIN_RLIMIT_NOFILE,
+ VIR_DOMAIN_RLIMIT_MEMLOCK,
+ VIR_DOMAIN_RLIMIT_AS,
+ VIR_DOMAIN_RLIMIT_LOCKS,
+ VIR_DOMAIN_RLIMIT_SIGPENDING,
+ VIR_DOMAIN_RLIMIT_MSGQUEUE,
+ VIR_DOMAIN_RLIMIT_NICE,
+ VIR_DOMAIN_RLIMIT_RTPRIO,
+ VIR_DOMAIN_RLIMIT_RTTIME,
+
+ VIR_DOMAIN_RLIMIT_LAST
+} virDomainRLimit;
+
typedef struct _virDomainClockDef virDomainClockDef;
typedef virDomainClockDef *virDomainClockDefPtr;
struct _virDomainClockDef {
@@ -2039,6 +2060,14 @@ struct _virDomainPowerManagement {
int s4;
};
+typedef struct _virDomainRLimits virDomainRLimits;
+typedef virDomainRLimits *virDomainRLimitsPtr;
+
+struct _virDomainRLimits {
+ int resource;
+ long long limit;
+};
+
/*
* Guest VM main configuration
*
@@ -2156,6 +2185,9 @@ struct _virDomainDef {
size_t nshmems;
virDomainShmemDefPtr *shmems;
+ size_t nrlimits;
+ virDomainRLimitsPtr *rlimits;
+
/* Only 1 */
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
@@ -2844,6 +2876,7 @@ VIR_ENUM_DECL(virDomainRNGModel)
VIR_ENUM_DECL(virDomainRNGBackend)
VIR_ENUM_DECL(virDomainTPMModel)
VIR_ENUM_DECL(virDomainTPMBackend)
+VIR_ENUM_DECL(virDomainRLimit)
/* from libvirt.h */
VIR_ENUM_DECL(virDomainState)
VIR_ENUM_DECL(virDomainNostateReason)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index bd7870f..7b71ff1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1896,6 +1896,7 @@ virProcessGetNamespaces;
virProcessGetStartTime;
virProcessKill;
virProcessKillPainfully;
+virProcessPrLimit;
virProcessRunInMountNamespace;
virProcessSetAffinity;
virProcessSetMaxFiles;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 8a7c7e8..5c63a1b 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -798,6 +798,35 @@ static int
virLXCControllerSetupCgroupLimits(virLXCControllerPtr ctrl)
return ret;
}
+static int virLXCControllerSetupRLimits(virLXCControllerPtr ctrl)
+{
+ int i, ret = -1;
+ struct rlimit rlim;
+
+ VIR_DEBUG("Setting up rlimits");
+
+ VIR_DEBUG("nrlimits = %d", (int)ctrl->def->nrlimits);
+ VIR_DEBUG("setting limits on process %d", ctrl->initpid);
+ if (ctrl->def->nrlimits > 0) {
+ for (i = 0; i < ctrl->def->nrlimits; i++) {
+ rlim.rlim_max = rlim.rlim_cur = ctrl->def->rlimits[i]->limit;
+ VIR_DEBUG("Setting rlimit %s(%d) on pid %d to %lld",
+
virDomainRLimitTypeToString(ctrl->def->rlimits[i]->resource),
+ ctrl->def->rlimits[i]->resource,
+ ctrl->initpid,
+ ctrl->def->rlimits[i]->limit);
+ if (virProcessPrLimit(ctrl->initpid,
ctrl->def->rlimits[i]->resource, &rlim) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to set rlimit"));
+ goto cleanup;
+ }
+ }
+ }
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
static void virLXCControllerClientCloseHook(virNetServerClientPtr client)
{
@@ -2318,6 +2347,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
if (virLXCControllerSetupCgroupLimits(ctrl) < 0)
goto cleanup;
+ if (virLXCControllerSetupRLimits(ctrl) < 0)
+ goto cleanup;
+
if (virLXCControllerSetupUserns(ctrl) < 0)
goto cleanup;
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index d0a1500..d83ae28 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -676,13 +676,13 @@ int virProcessSetNamespaces(size_t nfdlist,
}
#if HAVE_PRLIMIT
-static int
+int
virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim)
{
return prlimit(pid, resource, rlim, NULL);
}
#elif HAVE_SETRLIMIT
-static int
+int
virProcessPrLimit(pid_t pid ATTRIBUTE_UNUSED,
int resource ATTRIBUTE_UNUSED,
struct rlimit *rlim ATTRIBUTE_UNUSED)
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index bcaede5..c40b41a 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -22,6 +22,7 @@
#ifndef __VIR_PROCESS_H__
# define __VIR_PROCESS_H__
+# include <sys/resource.h>
# include <sys/types.h>
# include "internal.h"
@@ -73,4 +74,5 @@ typedef int (*virProcessNamespaceCallback)(pid_t pid,
void *opaque);
int virProcessRunInMountNamespace(pid_t pid,
virProcessNamespaceCallback cb,
void *opaque);
+int virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim);
#endif /* __VIR_PROCESS_H__ */
9 years, 9 months
[libvirt] [PATCH 00/12] memory hotplug: Preliminary fixes and cleanups
by Peter Krempa
This series was split out from my memory hotplug series that is not quite ready
yet. The aim of this series is to refactor the code that creates commandline
for the memory-backend-* qemu object so that it can be later reused for hotplug
via monitor. Additionally this series also fixes a bug in NUMA memory
initialisation where qemu doesn't support a combination of old and new approach.
Peter Krempa (12):
conf: numatune: Extract code for requesting memory nodeset from
formatting
test: utils: Add helpers for automatic numbering of test cases
util: json: make value object creator universal by supporting adding
util: json: Add functions to convert JSON arrays from/to virBitmaps
util: json: add helper to iterate JSON object key=value pairs
qemu: command: Add helper to format -object strings from JSON
representation
qemu: Extract code to setup memory backing objects
qemu: command: Shuffle around formating of alias for memory backend
objs
qemu: command: Unify values for boolean values when formating memory
backends
qemu: command: Switch to bytes when formatting size for memory
backends
qemu: command: Refactor NUMA backend object formatting to use JSON
objs
qemu: command: Don't combine old and modern NUMA node creation
src/conf/numatune_conf.c | 33 +-
src/conf/numatune_conf.h | 5 +
src/libvirt_private.syms | 6 +
src/qemu/qemu_command.c | 547 +++++++++++++++------
src/qemu/qemu_command.h | 4 +
src/util/virjson.c | 220 ++++++++-
src/util/virjson.h | 17 +
tests/Makefile.am | 13 +-
tests/qemucommandutiltest.c | 118 +++++
.../qemuxml2argv-hugepages-pages.args | 20 +-
.../qemuxml2argv-hugepages-pages2.args | 8 +-
.../qemuxml2argv-hugepages-pages3.args | 7 +-
.../qemuxml2argv-hugepages-shared.args | 20 +-
.../qemuxml2argv-numatune-memnode-no-memory.args | 6 +-
.../qemuxml2argv-numatune-memnode.args | 8 +-
tests/testutils.c | 46 ++
tests/testutils.h | 3 +
17 files changed, 871 insertions(+), 210 deletions(-)
create mode 100644 tests/qemucommandutiltest.c
--
2.2.2
9 years, 9 months
[libvirt] [PATCH] cpu: add Freescale ppc64 CPU models
by Olivia Yin
Signed-off-by: Olivia Yin <hong-hua.yin(a)freescale.com>
---
src/cpu/cpu_map.xml | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
index bd9b056..c34874e 100644
--- a/src/cpu/cpu_map.xml
+++ b/src/cpu/cpu_map.xml
@@ -1,4 +1,4 @@
-<cpus>
+n<cpus>
<arch name='x86'>
<!-- vendor definitions -->
<vendor name='Intel' string='GenuineIntel'/>
@@ -600,6 +600,7 @@
<arch name='ppc64'>
<!-- vendor definitions -->
<vendor name='IBM'/>
+ <vendor name='Freescale'/>
<!-- IBM-based CPU models -->
<model name='POWER7'>
@@ -657,5 +658,40 @@
<pvr value='0x004d0000'/>
</model>
+<!-- Freescale-based CPU models -->
+ <model name='POWERPC_e5500_v10'>
+ <vendor name='Freescale'/>
+ <pvr value='0x80240010'/>
+ </model>
+
+ <model name='POWERPC_e5500_v11'>
+ <vendor name='Freescale'/>
+ <pvr value='0x80240011'/>
+ </model>
+
+ <model name='POWERPC_e5500_v12'>
+ <vendor name='Freescale'/>
+ <pvr value='0x80240012'/>
+ </model>
+
+ <model name='POWERPC_e5500_v1020'>
+ <vendor name='Freescale'/>
+ <pvr value='0x80241020'/>
+ </model>
+
+ <model name='POWERPC_e6500_v10'>
+ <vendor name='Freescale'/>
+ <pvr value='0x80400010'/>
+ </model>
+
+ <model name='POWERPC_e6500_v20'>
+ <vendor name='Freescale'/>
+ <pvr value='0x80400020'/>
+ </model>
+
+ <model name='POWERPC_e6500_v120'>
+ <vendor name='Freescale'/>
+ <pvr value='0x80400120'/>
+ </model>
</arch>
</cpus>
--
2.1.0.27.g96db324
9 years, 9 months
[libvirt] [PATCH] schemas: Allow all generic elements and attributes for all interfaces
by Michal Privoznik
There are some interface types (notably 'server' and 'client')
which instead of allowing the default set of elements and
attributes (like the rest do), try to enumerate only the elements
they know of. This way it's, however, easy to miss something. For
instance, the <address/> element was not mentioned at all. This
resulted in a strange behavior: when such interface was added
into XML, the address was automatically generated by parsing
code. Later, the formatted XML hasn't passed the RNG schema. This
became more visible once we've turned on the XML validation on
domain XML changes: appending an empty line at the end of
formatted XML (to trick virsh think the XML had changed) made
libvirt to refuse the very same XML it formatted.
Instead of trying to find each element and attribute we are
missing in the schema, lets just allow all the elements and
attributes like we're doing that for the rest of types. It's no
harm if the schema is wider than our parser allows.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
docs/schemas/domaincommon.rng | 28 +---
.../qemuxml2argv-interface-server.xml | 157 +++++++++++++++++++++
2 files changed, 159 insertions(+), 26 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-interface-server.xml
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9d6c1ee..d467dce 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2173,14 +2173,7 @@
</attribute>
<empty/>
</element>
- <optional>
- <element name="mac">
- <attribute name="address">
- <ref name="uniMacAddr"/>
- </attribute>
- <empty/>
- </element>
- </optional>
+ <ref name="interface-options"/>
</interleave>
</group>
<group>
@@ -2199,24 +2192,7 @@
</attribute>
<empty/>
</element>
- <optional>
- <element name="mac">
- <attribute name="address">
- <ref name="uniMacAddr"/>
- </attribute>
- <empty/>
- </element>
- </optional>
- <optional>
- <element name="model">
- <attribute name="type">
- <data type="string">
- <param name='pattern'>[a-zA-Z0-9\-_]+</param>
- </data>
- </attribute>
- <empty/>
- </element>
- </optional>
+ <ref name="interface-options"/>
</interleave>
</group>
<group>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-interface-server.xml b/tests/qemuxml2argvdata/qemuxml2argv-interface-server.xml
new file mode 100644
index 0000000..9edf773
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-interface-server.xml
@@ -0,0 +1,157 @@
+<domain type='kvm'>
+ <name>gentoo</name>
+ <uuid>a75aca4b-a02f-2bcb-4a91-c93cd848c34b</uuid>
+ <memory unit='KiB'>4194304</memory>
+ <currentMemory unit='KiB'>4194304</currentMemory>
+ <memoryBacking>
+ <hugepages>
+ <page size='1048576' unit='KiB' nodeset='0-3'/>
+ </hugepages>
+ </memoryBacking>
+ <vcpu placement='static'>4</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-i440fx-1.4'>hvm</type>
+ <boot dev='hd'/>
+ <boot dev='cdrom'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <cpu mode='custom' match='exact'>
+ <model fallback='allow'>Haswell</model>
+ <vendor>Intel</vendor>
+ <feature policy='require' name='tm2'/>
+ <feature policy='require' name='est'/>
+ <feature policy='require' name='vmx'/>
+ <feature policy='require' name='osxsave'/>
+ <feature policy='require' name='smx'/>
+ <feature policy='require' name='ss'/>
+ <feature policy='require' name='ds'/>
+ <feature policy='require' name='vme'/>
+ <feature policy='require' name='dtes64'/>
+ <feature policy='require' name='abm'/>
+ <feature policy='require' name='ht'/>
+ <feature policy='require' name='acpi'/>
+ <feature policy='require' name='pbe'/>
+ <feature policy='require' name='tm'/>
+ <feature policy='require' name='pdcm'/>
+ <feature policy='require' name='pdpe1gb'/>
+ <feature policy='require' name='ds_cpl'/>
+ <feature policy='require' name='rdrand'/>
+ <feature policy='require' name='f16c'/>
+ <feature policy='require' name='xtpr'/>
+ <feature policy='require' name='monitor'/>
+ <numa>
+ <cell id='0' cpus='0' memory='1048576' unit='KiB'/>
+ <cell id='1' cpus='1' memory='1048576' unit='KiB'/>
+ <cell id='2' cpus='2' memory='1048576' unit='KiB'/>
+ <cell id='3' cpus='3' memory='1048576' unit='KiB'/>
+ </numa>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <pm>
+ <suspend-to-mem enabled='yes'/>
+ <suspend-to-disk enabled='yes'/>
+ </pm>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='file' device='floppy'>
+ <driver name='qemu' type='raw' cache='none'/>
+ <source file='/var/lib/libvirt/images/fd.img'/>
+ <target dev='fda' bus='fdc'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/var/lib/libvirt/images/gentoo.qcow2'/>
+ <target dev='vda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/var/lib/libvirt/images/OtherDemo.img'/>
+ <target dev='vdb' bus='virtio'/>
+ <encryption format='qcow'>
+ <secret type='passphrase' uuid='e78d4b51-a2af-485f-b0f5-afca709a80f4'/>
+ </encryption>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <driver name='qemu' type='raw' cache='none'/>
+ <source file='/home/zippy/tmp/install-amd64-minimal-20140619.iso'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <shareable/>
+ <address type='drive' controller='0' bus='1' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='virtio-serial' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
+ </controller>
+ <controller type='fdc' index='0'/>
+ <interface type='network'>
+ <mac address='52:54:00:d6:c0:0b'/>
+ <source network='default'/>
+ <bandwidth>
+ <inbound average='100'/>
+ <outbound average='100'/>
+ </bandwidth>
+ <model type='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </interface>
+ <interface type='server'>
+ <mac address='52:54:00:22:c9:42'/>
+ <source address='127.0.0.1' port='1234'/>
+ <bandwidth>
+ <inbound average='1234'/>
+ <outbound average='5678'/>
+ </bandwidth>
+ <model type='rtl8139'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
+ </interface>
+ <interface type='client'>
+ <mac address='52:54:00:8c:b1:f8'/>
+ <source address='127.0.0.1' port='1234'/>
+ <model type='rtl8139'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <serial type='pty'>
+ <target port='1'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <channel type='unix'>
+ <source mode='bind' path='/var/lib/libvirt/qemu/channel/target/gentoo.org.qemu.guest_agent.0'/>
+ <target type='virtio' name='org.qemu.guest_agent.0'/>
+ <address type='virtio-serial' controller='0' bus='0' port='1'/>
+ </channel>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes'/>
+ <sound model='ich6'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </sound>
+ <video>
+ <model type='cirrus' vram='16384' heads='1'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+ </video>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
--
2.0.5
9 years, 9 months
[libvirt] [PATCH] Add rlimits to lxc
by Ryan Cleere
---
src/conf/domain_conf.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 12 +++++
src/lxc/lxc_controller.c | 12 +++++
src/util/virprocess.c | 4 +-
src/util/virprocess.h | 3 ++
5 files changed, 144 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2d81c37..a673dc2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -26,6 +26,7 @@
#include <dirent.h>
#include <fcntl.h>
#include <strings.h>
+#include <sys/resource.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -1003,7 +1004,86 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,
return -1;
}
+static virDomainRLimitsPtr
+virDomainRLimitsNew(void)
+{
+ virDomainRLimitsPtr def = NULL;
+
+ if (VIR_ALLOC(def) < 0)
+ return NULL;
+
+ return def;
+}
+
+static virDomainRLimitsPtr
+virDomainRLimitParseXML(xmlNodePtr node)
+{
+ char *c = NULL;
+ long long val;
+ virDomainRLimitsPtr def;
+ if (!(def = virDomainRLimitsNew()))
+ return NULL;
+
+ if (node->type == XML_ELEMENT_NODE) {
+ c = (char *)xmlNodeGetContent(node);
+ if (virStrToLong_ll(c, NULL, 10, &val) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse rlimit value of %s"),
+ c);
+ goto error;
+ }
+ VIR_FREE(c);
+
+ def->limit = val;
+ if (VIR_STRDUP(def->name, (char *)node->name) < 0)
+ goto error;
+
+ if (xmlStrEqual(node->name, BAD_CAST "as")) {
+ def->resource = RLIMIT_AS;
+ } else if (xmlStrEqual(node->name, BAD_CAST "core")) {
+ def->resource = RLIMIT_CORE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "cpu")) {
+ def->resource = RLIMIT_CPU;
+ } else if (xmlStrEqual(node->name, BAD_CAST "data")) {
+ def->resource = RLIMIT_DATA;
+ } else if (xmlStrEqual(node->name, BAD_CAST "fsize")) {
+ def->resource = RLIMIT_FSIZE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "locks")) {
+ def->resource = RLIMIT_LOCKS;
+ } else if (xmlStrEqual(node->name, BAD_CAST "memlock")) {
+ def->resource = RLIMIT_MEMLOCK;
+ } else if (xmlStrEqual(node->name, BAD_CAST "msgqueue")) {
+ def->resource = RLIMIT_MSGQUEUE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "nice")) {
+ def->resource = RLIMIT_NICE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "nofile")) {
+ def->resource = RLIMIT_NOFILE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "nproc")) {
+ def->resource = RLIMIT_NPROC;
+ } else if (xmlStrEqual(node->name, BAD_CAST "rss")) {
+ def->resource = RLIMIT_RSS;
+ } else if (xmlStrEqual(node->name, BAD_CAST "rtprio")) {
+ def->resource = RLIMIT_RTPRIO;
+ } else if (xmlStrEqual(node->name, BAD_CAST "sigpending")) {
+ def->resource = RLIMIT_SIGPENDING;
+ } else if (xmlStrEqual(node->name, BAD_CAST "stack")) {
+ def->resource = RLIMIT_STACK;
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not determine resource type of '%s'"),
+ node->name);
+ goto error;
+ }
+ }
+
+ return def;
+
+ error:
+ VIR_FREE(c);
+ VIR_FREE(def);
+ return NULL;
+}
static void
virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
@@ -14180,6 +14260,28 @@ virDomainDefParseXML(xmlDocPtr xml,
virHashFree(bootHash);
+ if ((node = virXPathNode("./rlimits[1]", ctxt)) != NULL && (n = virXMLChildElementCount(node)) > 0) {
+ xmlNodePtr cur = node->children;
+ if (n && VIR_ALLOC_N(def->rlimits, n) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ if (!(def->rlimits[i] = virDomainRLimitParseXML(cur)))
+ goto error;
+ def->nrlimits++;
+ for (j = 0; j < i; j++) {
+ if (def->rlimits[j]->resource == def->rlimits[i]->resource) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("duplicate rlimit resources '%s'"),
+ def->rlimits[j]->name);
+ goto error;
+ }
+ }
+ cur = cur->next;
+ }
+ }
+ VIR_FREE(node);
+
return def;
error:
@@ -19759,6 +19861,19 @@ virDomainDefFormatInternal(virDomainDefPtr def,
goto error;
}
+ if (def->nrlimits > 0) {
+ virBufferAddLit(buf, "<rlimits>\n");
+ virBufferAdjustIndent(buf, 2);
+ for (n = 0; n < def->nrlimits; n++) {
+ virBufferAsprintf(buf, "<%s>%lld</%s>\n",
+ def->rlimits[n]->name,
+ def->rlimits[n]->limit,
+ def->rlimits[n]->name);
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</rlimits>\n");
+ }
+
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</domain>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 439f3c0..abad30e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2021,6 +2021,15 @@ struct _virDomainPowerManagement {
int s4;
};
+typedef struct _virDomainRLimits virDomainRLimits;
+typedef virDomainRLimits *virDomainRLimitsPtr;
+
+struct _virDomainRLimits {
+ char *name;
+ int resource;
+ long long limit;
+};
+
/*
* Guest VM main configuration
*
@@ -2138,6 +2147,9 @@ struct _virDomainDef {
size_t nshmems;
virDomainShmemDefPtr *shmems;
+ size_t nrlimits;
+ virDomainRLimitsPtr *rlimits;
+
/* Only 1 */
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 53a2c8d..ef5551e 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -2490,6 +2490,18 @@ int main(int argc, char *argv[])
}
}
+ VIR_INFO("nrlimits = %d", (int)ctrl->def->nrlimits);
+ if (ctrl->def->nrlimits > 0) {
+ struct rlimit rlim;
+ int n;
+ for (i = 0; i < ctrl->def->nrlimits; i++) {
+ rlim.rlim_max = rlim.rlim_cur = ctrl->def->rlimits[i]->limit;
+ n = virProcessPrLimit(0, ctrl->def->rlimits[i]->resource, &rlim);
+ if (n < 0)
+ goto cleanup;
+ }
+ }
+
rc = virLXCControllerRun(ctrl);
cleanup:
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 0c8a32f..9bb5370 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -675,13 +675,13 @@ int virProcessSetNamespaces(size_t nfdlist,
}
#if HAVE_PRLIMIT
-static int
+int
virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim)
{
return prlimit(pid, resource, rlim, NULL);
}
#elif HAVE_SETRLIMIT
-static int
+int
virProcessPrLimit(pid_t pid ATTRIBUTE_UNUSED,
int resource ATTRIBUTE_UNUSED,
struct rlimit *rlim ATTRIBUTE_UNUSED)
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index bcaede5..045f8d4 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -22,6 +22,7 @@
#ifndef __VIR_PROCESS_H__
# define __VIR_PROCESS_H__
+# include <sys/resource.h>
# include <sys/types.h>
# include "internal.h"
@@ -73,4 +74,6 @@ typedef int (*virProcessNamespaceCallback)(pid_t pid, void *opaque);
int virProcessRunInMountNamespace(pid_t pid,
virProcessNamespaceCallback cb,
void *opaque);
+
+int virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim);
#endif /* __VIR_PROCESS_H__ */
--
1.9.3 (Apple Git-50)
9 years, 9 months