diff --git a/SOURCES/libvirt-nodedev-Expose-PCI-header-type.patch b/SOURCES/libvirt-nodedev-Expose-PCI-header-type.patch new file mode 100644 index 0000000..b1812d2 --- /dev/null +++ b/SOURCES/libvirt-nodedev-Expose-PCI-header-type.patch @@ -0,0 +1,343 @@ +From 00d879937512b24db576a39fc94c78b427f8916d Mon Sep 17 00:00:00 2001 +Message-Id: <00d879937512b24db576a39fc94c78b427f8916d@dist-git> +From: Martin Kletzander +Date: Mon, 23 May 2016 18:10:04 +0200 +Subject: [PATCH] nodedev: Expose PCI header type + +RHEL-7.2.z: https://bugzilla.redhat.com/show_bug.cgi?id=1331328 +Upstream: https://bugzilla.redhat.com/show_bug.cgi?id=1317531 + +If we expose this information, which is one byte in every PCI config +file, we let all mgmt apps know whether the device itself is an endpoint +or not so it's easier for them to decide whether such device can be +passed through into a VM (endpoint) or not (*-bridge). + +Signed-off-by: Martin Kletzander +(cherry picked from commit d77ffb6876e87a5c6f4c74c49cf0d89ade4f8326) +Signed-off-by: Michal Privoznik +--- + docs/formatnode.html.in | 36 ++++++++++++++-------- + docs/schemas/nodedev.rng | 11 +++++++ + src/conf/node_device_conf.c | 20 ++++++++++++ + src/conf/node_device_conf.h | 1 + + src/libvirt_private.syms | 3 ++ + src/node_device/node_device_udev.c | 3 ++ + src/util/virpci.c | 33 ++++++++++++++++++++ + src/util/virpci.h | 12 ++++++++ + .../pci_0000_00_02_0_header_type.xml | 15 +++++++++ + .../pci_0000_00_1c_0_header_type.xml | 20 ++++++++++++ + tests/nodedevxml2xmltest.c | 2 ++ + 11 files changed, 144 insertions(+), 12 deletions(-) + create mode 100644 tests/nodedevschemadata/pci_0000_00_02_0_header_type.xml + create mode 100644 tests/nodedevschemadata/pci_0000_00_1c_0_header_type.xml + +diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in +index 3ff1bef..a14bcfd 100644 +--- a/docs/formatnode.html.in ++++ b/docs/formatnode.html.in +@@ -97,18 +97,30 @@ +
+ This optional element can occur multiple times. If it + exists, it has a mandatory type attribute +- which will be set to +- either physical_function +- or virtual_functions. If the type +- is physical_function, there will be a +- single address subelement which contains +- the PCI address of the SRIOV Physical Function (PF) +- that is the parent of this device (and this device is, +- by implication, an SRIOV Virtual Function (VF)). If +- the type is virtual_functions, then this +- device is an SRIOV PF, and the capability element will +- have a list of address subelements, one +- for each VF on this PF. ++ which will be set to: ++
++
physical_function
++
++ That means there will be a single address ++ subelement which contains the PCI address of the SRIOV ++ Physical Function (PF) that is the parent of this device ++ (and this device is, by implication, an SRIOV Virtual ++ Function (VF)). ++
++
virtual_function
++
++ In this case this device is an SRIOV PF, and the capability ++ element will have a list of address ++ subelements, one for each VF on this PF. ++
++
pci-bridge or cardbus-bridge
++
++ This shows merely that the lower 7 bits of PCI header type ++ have either value of 1 or 2 respectively. Usually this ++ means such device cannot be used for PCI passthrough. ++ Since 1.3.3 ++
++
+
+
numa
+
+diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng +index 744dccd..949811c 100644 +--- a/docs/schemas/nodedev.rng ++++ b/docs/schemas/nodedev.rng +@@ -169,6 +169,17 @@ + + + ++ ++ ++ ++ pci-bridge ++ cardbus-bridge ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c +index e6f3f27..feefb9a 100644 +--- a/src/conf/node_device_conf.c ++++ b/src/conf/node_device_conf.c +@@ -394,6 +394,12 @@ char *virNodeDeviceDefFormat(const virNodeDeviceDef *def) + if (data->pci_dev.numa_node >= 0) + virBufferAsprintf(&buf, "\n", + data->pci_dev.numa_node); ++ ++ if (data->pci_dev.hdrType) { ++ virBufferAsprintf(&buf, "\n", ++ virPCIHeaderTypeToString(data->pci_dev.hdrType)); ++ } ++ + if (data->pci_dev.flags & VIR_NODE_DEV_CAP_FLAG_PCIE) + virPCIEDeviceInfoFormat(&buf, data->pci_dev.pci_express); + break; +@@ -1264,6 +1270,7 @@ virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt, + xmlNodePtr orignode, iommuGroupNode, pciExpress; + int ret = -1; + virPCIEDeviceInfoPtr pci_express = NULL; ++ char *tmp = NULL; + + orignode = ctxt->node; + ctxt->node = node; +@@ -1321,6 +1328,18 @@ virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt, + _("invalid NUMA node ID supplied for '%s'")) < 0) + goto out; + ++ if ((tmp = virXPathString("string(./capability[1]/@type)", ctxt))) { ++ int hdrType = virPCIHeaderTypeFromString(tmp); ++ ++ if (hdrType <= 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unknown PCI header type '%s'"), tmp); ++ goto out; ++ } ++ ++ data->pci_dev.hdrType = hdrType; ++ } ++ + if ((pciExpress = virXPathNode("./pci-express[1]", ctxt))) { + if (VIR_ALLOC(pci_express) < 0) + goto out; +@@ -1335,6 +1354,7 @@ virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt, + + ret = 0; + out: ++ VIR_FREE(tmp); + virPCIEDeviceInfoFree(pci_express); + ctxt->node = orignode; + return ret; +diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h +index 7dd39ca..73d2a7f 100644 +--- a/src/conf/node_device_conf.h ++++ b/src/conf/node_device_conf.h +@@ -118,6 +118,7 @@ typedef struct _virNodeDevCapData { + unsigned int iommuGroupNumber; + int numa_node; + virPCIEDeviceInfoPtr pci_express; ++ int hdrType; /* enum virPCIHeaderType or -1 */ + } pci_dev; + struct { + unsigned int bus; +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 86909c1..0db30be 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1976,11 +1976,14 @@ virPCIDeviceSetUsedBy; + virPCIDeviceUnbind; + virPCIDeviceWaitForCleanup; + virPCIEDeviceInfoFree; ++virPCIGetHeaderType; + virPCIGetNetName; + virPCIGetPhysicalFunction; + virPCIGetVirtualFunctionIndex; + virPCIGetVirtualFunctionInfo; + virPCIGetVirtualFunctions; ++virPCIHeaderTypeFromString; ++virPCIHeaderTypeToString; + virPCIIsVirtualFunction; + + +diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c +index aaee0e5..6bff5ba 100644 +--- a/src/node_device/node_device_udev.c ++++ b/src/node_device/node_device_udev.c +@@ -506,6 +506,9 @@ static int udevProcessPCI(struct udev_device *device, + + /* We need to be root to read PCI device configs */ + if (priv->privileged) { ++ if (virPCIGetHeaderType(pciDev, &data->pci_dev.hdrType) < 0) ++ goto out; ++ + if (virPCIDeviceIsPCIExpress(pciDev) > 0) { + if (VIR_ALLOC(pci_express) < 0) + goto out; +diff --git a/src/util/virpci.c b/src/util/virpci.c +index 35b1459..d98db3f 100644 +--- a/src/util/virpci.c ++++ b/src/util/virpci.c +@@ -55,6 +55,12 @@ VIR_LOG_INIT("util.pci"); + VIR_ENUM_IMPL(virPCIELinkSpeed, VIR_PCIE_LINK_SPEED_LAST, + "", "2.5", "5", "8") + ++VIR_ENUM_IMPL(virPCIHeader, VIR_PCI_HEADER_LAST, ++ "endpoint", ++ "pci-bridge", ++ "cardbus-bridge", ++); ++ + struct _virPCIDevice { + unsigned int domain; + unsigned int bus; +@@ -2872,6 +2878,33 @@ virPCIDeviceGetLinkCapSta(virPCIDevicePtr dev, + } + + ++int virPCIGetHeaderType(virPCIDevicePtr dev, int *hdrType) ++{ ++ int fd; ++ uint8_t type; ++ ++ *hdrType = -1; ++ ++ if ((fd = virPCIDeviceConfigOpen(dev, true)) < 0) ++ return -1; ++ ++ type = virPCIDeviceRead8(dev, fd, PCI_HEADER_TYPE); ++ ++ virPCIDeviceConfigClose(dev, fd); ++ ++ type &= PCI_HEADER_TYPE_MASK; ++ if (type >= VIR_PCI_HEADER_LAST) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unknown PCI header type '%d'"), type); ++ return -1; ++ } ++ ++ *hdrType = type; ++ ++ return 0; ++} ++ ++ + void + virPCIEDeviceInfoFree(virPCIEDeviceInfoPtr dev) + { +diff --git a/src/util/virpci.h b/src/util/virpci.h +index 64b9e96..1ed59dd 100644 +--- a/src/util/virpci.h ++++ b/src/util/virpci.h +@@ -52,6 +52,16 @@ typedef enum { + + VIR_ENUM_DECL(virPCIELinkSpeed) + ++typedef enum { ++ VIR_PCI_HEADER_ENDPOINT = 0, ++ VIR_PCI_HEADER_PCI_BRIDGE, ++ VIR_PCI_HEADER_CARDBUS_BRIDGE, ++ ++ VIR_PCI_HEADER_LAST ++} virPCIHeaderType; ++ ++VIR_ENUM_DECL(virPCIHeader) ++ + typedef struct _virPCIELink virPCIELink; + typedef virPCIELink *virPCIELinkPtr; + struct _virPCIELink { +@@ -214,6 +224,8 @@ int virPCIDeviceGetLinkCapSta(virPCIDevicePtr dev, + unsigned int *sta_speed, + unsigned int *sta_width); + ++int virPCIGetHeaderType(virPCIDevicePtr dev, int *hdrType); ++ + void virPCIEDeviceInfoFree(virPCIEDeviceInfoPtr dev); + + #endif /* __VIR_PCI_H__ */ +diff --git a/tests/nodedevschemadata/pci_0000_00_02_0_header_type.xml b/tests/nodedevschemadata/pci_0000_00_02_0_header_type.xml +new file mode 100644 +index 0000000..5150fd1 +--- /dev/null ++++ b/tests/nodedevschemadata/pci_0000_00_02_0_header_type.xml +@@ -0,0 +1,15 @@ ++ ++ pci_0000_00_02_0 ++ computer ++ ++ 0 ++ 0 ++ 2 ++ 0 ++ 4th Gen Core Processor Integrated Graphics Controller ++ Intel Corporation ++ ++
++ ++ ++ +diff --git a/tests/nodedevschemadata/pci_0000_00_1c_0_header_type.xml b/tests/nodedevschemadata/pci_0000_00_1c_0_header_type.xml +new file mode 100644 +index 0000000..dea5f05 +--- /dev/null ++++ b/tests/nodedevschemadata/pci_0000_00_1c_0_header_type.xml +@@ -0,0 +1,20 @@ ++ ++ pci_0000_00_1c_0 ++ computer ++ ++ 0 ++ 0 ++ 28 ++ 0 ++ 8 Series/C220 Series Chipset Family PCI Express Root Port #1 ++ Intel Corporation ++ ++
++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c +index a37d729..d2cd444 100644 +--- a/tests/nodedevxml2xmltest.c ++++ b/tests/nodedevxml2xmltest.c +@@ -91,6 +91,8 @@ mymain(void) + DO_TEST("usb_device_1d6b_1_0000_00_1d_0"); + DO_TEST("pci_8086_4238_pcie_wireless"); + DO_TEST("pci_8086_0c0c_snd_hda_intel"); ++ DO_TEST("pci_0000_00_02_0_header_type"); ++ DO_TEST("pci_0000_00_1c_0_header_type"); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + } +-- +2.8.3 + diff --git a/SOURCES/libvirt-nodedev-Fix-parsing-of-generated-XMLs.patch b/SOURCES/libvirt-nodedev-Fix-parsing-of-generated-XMLs.patch new file mode 100644 index 0000000..77d3c79 --- /dev/null +++ b/SOURCES/libvirt-nodedev-Fix-parsing-of-generated-XMLs.patch @@ -0,0 +1,67 @@ +From f583c2a22e7ce86586aa30f3ee66b6a830778550 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Martin Kletzander +Date: Mon, 23 May 2016 18:10:05 +0200 +Subject: [PATCH] nodedev: Fix parsing of generated XMLs + +RHEL-7.2.z: https://bugzilla.redhat.com/show_bug.cgi?id=1331328 + +Commit d77ffb6876 added not only reporting of the PCI header type, but +also parsing of that information. However, because there was no parsing +done for the other sub-PCI capabilities, if there was any other +capability then a valid header type name (like phys_function or +virt_functions) the parsing would fail. This prevented passing node +device XMLs that we generated into our own functions when dealing with, +e.g. with SRIOV cards. + +Instead of reworking the whole parsing, just fix this one occurence and +remove a test for it for the time being. Future patches will deal with +the rest. + +Signed-off-by: Martin Kletzander +(cherry picked from commit 17a94ba70fc11c21f8ea70ff92131d0868f4cde1) +Signed-off-by: Michal Privoznik +--- + src/conf/node_device_conf.c | 12 ------------ + tests/nodedevxml2xmltest.c | 2 -- + 2 files changed, 14 deletions(-) + +diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c +index feefb9a..fdea79e 100644 +--- a/src/conf/node_device_conf.c ++++ b/src/conf/node_device_conf.c +@@ -1328,18 +1328,6 @@ virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt, + _("invalid NUMA node ID supplied for '%s'")) < 0) + goto out; + +- if ((tmp = virXPathString("string(./capability[1]/@type)", ctxt))) { +- int hdrType = virPCIHeaderTypeFromString(tmp); +- +- if (hdrType <= 0) { +- virReportError(VIR_ERR_INTERNAL_ERROR, +- _("Unknown PCI header type '%s'"), tmp); +- goto out; +- } +- +- data->pci_dev.hdrType = hdrType; +- } +- + if ((pciExpress = virXPathNode("./pci-express[1]", ctxt))) { + if (VIR_ALLOC(pci_express) < 0) + goto out; +diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c +index d2cd444..a37d729 100644 +--- a/tests/nodedevxml2xmltest.c ++++ b/tests/nodedevxml2xmltest.c +@@ -91,8 +91,6 @@ mymain(void) + DO_TEST("usb_device_1d6b_1_0000_00_1d_0"); + DO_TEST("pci_8086_4238_pcie_wireless"); + DO_TEST("pci_8086_0c0c_snd_hda_intel"); +- DO_TEST("pci_0000_00_02_0_header_type"); +- DO_TEST("pci_0000_00_1c_0_header_type"); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + } +-- +2.8.3 + diff --git a/SOURCES/libvirt-nodedev-Indent-PCI-express-for-future-fix.patch b/SOURCES/libvirt-nodedev-Indent-PCI-express-for-future-fix.patch new file mode 100644 index 0000000..e327a86 --- /dev/null +++ b/SOURCES/libvirt-nodedev-Indent-PCI-express-for-future-fix.patch @@ -0,0 +1,74 @@ +From 3b9712c09ff6ac00d5d371f3e1e71391037eb5bf Mon Sep 17 00:00:00 2001 +Message-Id: <3b9712c09ff6ac00d5d371f3e1e71391037eb5bf@dist-git> +From: Martin Kletzander +Date: Mon, 23 May 2016 18:10:03 +0200 +Subject: [PATCH] nodedev: Indent PCI express for future fix + +RHEL-7.2.z: https://bugzilla.redhat.com/show_bug.cgi?id=1331328 + +Best viewed with '-w' as this is just an adjustment for future patch to +be readable without that. + +Signed-off-by: Martin Kletzander +(cherry picked from commit 0d8f45246a74b627e62eccef2bb19068690312e2) +Signed-off-by: Michal Privoznik +--- + src/node_device/node_device_udev.c | 38 ++++++++++++++++++++------------------ + 1 file changed, 20 insertions(+), 18 deletions(-) + +diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c +index 100b44d..aaee0e5 100644 +--- a/src/node_device/node_device_udev.c ++++ b/src/node_device/node_device_udev.c +@@ -505,28 +505,30 @@ static int udevProcessPCI(struct udev_device *device, + goto out; + + /* We need to be root to read PCI device configs */ +- if (priv->privileged && virPCIDeviceIsPCIExpress(pciDev) > 0) { +- if (VIR_ALLOC(pci_express) < 0) +- goto out; +- +- if (virPCIDeviceHasPCIExpressLink(pciDev) > 0) { +- if (VIR_ALLOC(pci_express->link_cap) < 0 || +- VIR_ALLOC(pci_express->link_sta) < 0) ++ if (priv->privileged) { ++ if (virPCIDeviceIsPCIExpress(pciDev) > 0) { ++ if (VIR_ALLOC(pci_express) < 0) + goto out; + +- if (virPCIDeviceGetLinkCapSta(pciDev, +- &pci_express->link_cap->port, +- &pci_express->link_cap->speed, +- &pci_express->link_cap->width, +- &pci_express->link_sta->speed, +- &pci_express->link_sta->width) < 0) +- goto out; ++ if (virPCIDeviceHasPCIExpressLink(pciDev) > 0) { ++ if (VIR_ALLOC(pci_express->link_cap) < 0 || ++ VIR_ALLOC(pci_express->link_sta) < 0) ++ goto out; ++ ++ if (virPCIDeviceGetLinkCapSta(pciDev, ++ &pci_express->link_cap->port, ++ &pci_express->link_cap->speed, ++ &pci_express->link_cap->width, ++ &pci_express->link_sta->speed, ++ &pci_express->link_sta->width) < 0) ++ goto out; + +- pci_express->link_sta->port = -1; /* PCIe can't negotiate port. Yet :) */ ++ pci_express->link_sta->port = -1; /* PCIe can't negotiate port. Yet :) */ ++ } ++ data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCIE; ++ data->pci_dev.pci_express = pci_express; ++ pci_express = NULL; + } +- data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCIE; +- data->pci_dev.pci_express = pci_express; +- pci_express = NULL; + } + + ret = 0; +-- +2.8.3 + diff --git a/SOURCES/libvirt-qemu-bulk-stats-Don-t-access-possibly-blocked-storage.patch b/SOURCES/libvirt-qemu-bulk-stats-Don-t-access-possibly-blocked-storage.patch new file mode 100644 index 0000000..ed7b0c8 --- /dev/null +++ b/SOURCES/libvirt-qemu-bulk-stats-Don-t-access-possibly-blocked-storage.patch @@ -0,0 +1,57 @@ +From a3176697f2d1288d3e30ca6aac0d2c5891a6b135 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Thu, 26 May 2016 12:54:54 +0200 +Subject: [PATCH] qemu: bulk stats: Don't access possibly blocked storage + +https://bugzilla.redhat.com/show_bug.cgi?id=1339963 + +If the stats for a block device can't be acquired from qemu we've +fallen back to loading them from the file on the disk in libvirt. + +If qemu is not cooperating due to being stuck on an inaccessible NFS +share we would then attempt to read the files and get stuck too with +the VM object locked. All other APIs would eventually get stuck waiting +on the VM lock. + +Avoid this problem by skipping the block stats if the VM is online but +the monitor did not provide any stats. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1337073 +(cherry picked from commit 71d2c172edb997bae1e883b2e1bafa97d9f953a1) +--- + src/qemu/qemu_driver.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 1075237..5e28b21 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -19392,13 +19392,22 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver, + QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, block_idx, "backingIndex", + backing_idx); + +- /* use fallback path if data is not available */ +- if (!stats || !alias || !(entry = virHashLookup(stats, alias))) { ++ /* the VM is offline so we have to go and load the stast from the disk by ++ * ourselves */ ++ if (!virDomainObjIsActive(dom)) { + ret = qemuDomainGetStatsOneBlockFallback(driver, cfg, dom, record, + maxparams, src, block_idx); + goto cleanup; + } + ++ /* In case where qemu didn't provide the stats we stop here rather than ++ * trying to refresh the stats from the disk. Inability to provide stats is ++ * usually caused by blocked storage so this would make libvirtd hang */ ++ if (!stats || !alias || !(entry = virHashLookup(stats, alias))) { ++ ret = 0; ++ goto cleanup; ++ } ++ + QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, block_idx, + "rd.reqs", entry->rd_req); + QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, block_idx, +-- +2.8.3 + diff --git a/SOURCES/libvirt-qemu-driver-Remove-unnecessary-flag-in-qemuDomainGetStatsBlock.patch b/SOURCES/libvirt-qemu-driver-Remove-unnecessary-flag-in-qemuDomainGetStatsBlock.patch new file mode 100644 index 0000000..3be0f70 --- /dev/null +++ b/SOURCES/libvirt-qemu-driver-Remove-unnecessary-flag-in-qemuDomainGetStatsBlock.patch @@ -0,0 +1,79 @@ +From 992d8fee540fcdeba1a8b1cb9568fb981d210b08 Mon Sep 17 00:00:00 2001 +Message-Id: <992d8fee540fcdeba1a8b1cb9568fb981d210b08@dist-git> +From: Peter Krempa +Date: Thu, 26 May 2016 12:54:52 +0200 +Subject: [PATCH] qemu: driver: Remove unnecessary flag in + qemuDomainGetStatsBlock + +https://bugzilla.redhat.com/show_bug.cgi?id=1339963 + +'abbreviated' was true if 'stats' were NULL + +(cherry picked from commit 5d2b0e6f12b4e57d75ed1047ab1c36443b7a54b3) +--- + src/qemu/qemu_driver.c | 15 +++++---------- + 1 file changed, 5 insertions(+), 10 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index bdebf13..e403103 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -19340,7 +19340,6 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver, + virStorageSourcePtr src, + size_t block_idx, + unsigned int backing_idx, +- bool abbreviated, + virHashTablePtr stats) + { + qemuBlockStats *entry; +@@ -19359,7 +19358,7 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver, + QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, block_idx, "backingIndex", + backing_idx); + +- if (abbreviated || !alias || !(entry = virHashLookup(stats, alias))) { ++ if (!stats || !alias || !(entry = virHashLookup(stats, alias))) { + if (virStorageSourceIsEmpty(src)) { + ret = 0; + goto cleanup; +@@ -19436,15 +19435,12 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver, + int rc; + virHashTablePtr stats = NULL; + qemuDomainObjPrivatePtr priv = dom->privateData; +- bool abbreviated = false; + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + int count_index = -1; + size_t visited = 0; + bool visitBacking = !!(privflags & QEMU_DOMAIN_STATS_BACKING); + +- if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom)) { +- abbreviated = true; /* it's ok, just go ahead silently */ +- } else { ++ if (HAVE_JOB(privflags) && virDomainObjIsActive(dom)) { + qemuDomainObjEnterMonitor(driver, dom); + rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats, + visitBacking); +@@ -19454,10 +19450,9 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver, + if (qemuDomainObjExitMonitor(driver, dom) < 0) + goto cleanup; + +- if (rc < 0) { ++ /* failure to retrieve stats is fine at this point */ ++ if (rc < 0) + virResetLastError(); +- abbreviated = true; /* still ok, again go ahead silently */ +- } + } + + /* When listing backing chains, it's easier to fix up the count +@@ -19474,7 +19469,7 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver, + while (src && (backing_idx == 0 || visitBacking)) { + if (qemuDomainGetStatsOneBlock(driver, cfg, dom, record, maxparams, + disk, src, visited, backing_idx, +- abbreviated, stats) < 0) ++ stats) < 0) + goto cleanup; + visited++; + backing_idx++; +-- +2.8.3 + diff --git a/SOURCES/libvirt-qemu-driver-Separate-bulk-stats-worker-for-block-devices.patch b/SOURCES/libvirt-qemu-driver-Separate-bulk-stats-worker-for-block-devices.patch new file mode 100644 index 0000000..ad7ec25 --- /dev/null +++ b/SOURCES/libvirt-qemu-driver-Separate-bulk-stats-worker-for-block-devices.patch @@ -0,0 +1,96 @@ +From fdf02246eb2837e144b1929887af94aa9ce9a77e Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Thu, 26 May 2016 12:54:53 +0200 +Subject: [PATCH] qemu: driver: Separate bulk stats worker for block devices + +https://bugzilla.redhat.com/show_bug.cgi?id=1339963 + +Extract the fallback path that reloads the stats from disk into a +separate function. + +(cherry picked from commit 3aa5d51a9530a8737ca584b393c29297dd9bbc37) +--- + src/qemu/qemu_driver.c | 58 ++++++++++++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 21 deletions(-) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index e403103..1075237 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -19329,6 +19329,40 @@ do { \ + goto cleanup; \ + } while (0) + ++/* refresh information by opening images on the disk */ ++static int ++qemuDomainGetStatsOneBlockFallback(virQEMUDriverPtr driver, ++ virQEMUDriverConfigPtr cfg, ++ virDomainObjPtr dom, ++ virDomainStatsRecordPtr record, ++ int *maxparams, ++ virStorageSourcePtr src, ++ size_t block_idx) ++{ ++ int ret = -1; ++ ++ if (virStorageSourceIsEmpty(src)) ++ return 0; ++ ++ if (qemuStorageLimitsRefresh(driver, cfg, dom, src) < 0) { ++ virResetLastError(); ++ return 0; ++ } ++ ++ if (src->allocation) ++ QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, ++ "allocation", src->allocation); ++ if (src->capacity) ++ QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, ++ "capacity", src->capacity); ++ if (src->physical) ++ QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, ++ "physical", src->physical); ++ ret = 0; ++ cleanup: ++ return ret; ++} ++ + + static int + qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver, +@@ -19358,28 +19392,10 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver, + QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, block_idx, "backingIndex", + backing_idx); + ++ /* use fallback path if data is not available */ + if (!stats || !alias || !(entry = virHashLookup(stats, alias))) { +- if (virStorageSourceIsEmpty(src)) { +- ret = 0; +- goto cleanup; +- } +- +- if (qemuStorageLimitsRefresh(driver, cfg, dom, src) < 0) { +- virResetLastError(); +- ret = 0; +- goto cleanup; +- } +- +- if (src->allocation) +- QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, +- "allocation", src->allocation); +- if (src->capacity) +- QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, +- "capacity", src->capacity); +- if (src->physical) +- QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, +- "physical", src->physical); +- ret = 0; ++ ret = qemuDomainGetStatsOneBlockFallback(driver, cfg, dom, record, ++ maxparams, src, block_idx); + goto cleanup; + } + +-- +2.8.3 + diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec index 6043680..f0ce48e 100644 --- a/SPECS/libvirt.spec +++ b/SPECS/libvirt.spec @@ -382,7 +382,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 1.2.17 -Release: 13%{?dist}.4%{?extra_release} +Release: 13%{?dist}.5%{?extra_release} License: LGPLv2+ Group: Development/Libraries BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -655,6 +655,12 @@ Patch259: libvirt-virSystemdGetMachineNameByPID-Initialize-reply.patch Patch260: libvirt-util-Fix-virCgroupNewMachine-ATTRIBUTE_NONNULL-args.patch Patch261: libvirt-dbus-Don-t-unref-NULL-messages.patch Patch262: libvirt-vmx-Expose-datacenter-path-in-domain-XML.patch +Patch263: libvirt-nodedev-Indent-PCI-express-for-future-fix.patch +Patch264: libvirt-nodedev-Expose-PCI-header-type.patch +Patch265: libvirt-nodedev-Fix-parsing-of-generated-XMLs.patch +Patch266: libvirt-qemu-driver-Remove-unnecessary-flag-in-qemuDomainGetStatsBlock.patch +Patch267: libvirt-qemu-driver-Separate-bulk-stats-worker-for-block-devices.patch +Patch268: libvirt-qemu-bulk-stats-Don-t-access-possibly-blocked-storage.patch %if %{with_libvirtd} @@ -2606,6 +2612,14 @@ exit 0 %doc examples/systemtap %changelog +* Thu May 26 2016 Jiri Denemark - 1.2.17-13.el7_2.5 +- nodedev: Indent PCI express for future fix (rhbz#1331328) +- nodedev: Expose PCI header type (rhbz#1331328) +- nodedev: Fix parsing of generated XMLs (rhbz#1331328) +- qemu: driver: Remove unnecessary flag in qemuDomainGetStatsBlock (rhbz#1339963) +- qemu: driver: Separate bulk stats worker for block devices (rhbz#1339963) +- qemu: bulk stats: Don't access possibly blocked storage (rhbz#1339963) + * Wed Mar 2 2016 Jiri Denemark - 1.2.17-13.el7_2.4 - systemd: Escape machine name for machined (rhbz#1308494) - systemd: Add virSystemdGetMachineNameByPID (rhbz#1308494)