Add some SLE12 SP2 bug fixes

OBS-URL: https://build.opensuse.org/package/show/Virtualization/libvirt?expand=0&rev=554
This commit is contained in:
James Fehlig 2016-08-02 17:40:29 +00:00 committed by Git OBS Bridge
parent 7e6534702e
commit f0336af2de
3 changed files with 162 additions and 211 deletions

View File

@ -1,3 +1,18 @@
-------------------------------------------------------------------
Tue Aug 2 17:17:25 UTC 2016 - jfehlig@suse.com
- Update patches providing support for driver_override sysfs
interface with latest upstream variant. Dropped
pci-simplify-stub.patch and updated
pci-use-driver-override-sysfs.patch
bsc#986718
-------------------------------------------------------------------
Sat Jul 30 17:25:38 UTC 2016 - jfehlig@suse.com
- spec: enable numactl and numad support for aarch64
FATE#319979, bsc#991377
-------------------------------------------------------------------
Fri Jul 15 14:57:40 UTC 2016 - jfehlig@suse.com

View File

@ -77,9 +77,8 @@
%endif
%endif
# numactl package has "ExclusiveArch: ia64 x86_64 ppc64 ppc64le ppc %sparc"
# We'll only use it on x86_64 ppc64 ppc64le
%ifnarch x86_64 ppc64 ppc64le
# numactl has 'ExcludeArch s390 s390x'
%ifarch s390 s390x
%define with_numactl 0
%endif
@ -139,9 +138,9 @@
%define with_wireshark 0
# numad is used to manage the CPU and memory placement dynamically for
# qemu, lxc, and uml drivers. We'll only use in on x86_64
# qemu, lxc, and uml drivers. We'll only use it on aarch64 and x86_64
%if %{with_qemu} || %{with_lxc} || %{with_uml}
%ifarch x86_64
%ifarch aarch64 x86_64
%define with_numad 0%{!?_without_numad:1}
%endif
%endif
@ -301,8 +300,7 @@ Source100: %{name}-rpmlintrc
Patch0: c8f08e48-systemd-notify-fix.patch
# Patches pending upstream review
Patch100: libxl-dom-reset.patch
Patch101: pci-simplify-stub.patch
Patch102: pci-use-driver-override-sysfs.patch
Patch101: pci-use-driver-override-sysfs.patch
# Need to go upstream
Patch150: xen-pv-cdrom.patch
Patch151: blockcopy-check-dst-identical-device.patch
@ -755,7 +753,6 @@ libvirt plugin for NSS for translating domain names into IP addresses.
%patch0 -p1
%patch100 -p1
%patch101 -p1
%patch102 -p1
%patch150 -p1
%patch151 -p1
%patch152 -p1

View File

@ -1,191 +1,81 @@
commit 1de627810eaba897705cf32c9f025023e34ce73a
Author: Jim Fehlig <jfehlig@suse.com>
Date: Fri Jul 8 16:25:03 2016 -0600
From 9bd9a05b8b64489598ca4e0d241247cb99406d20 Mon Sep 17 00:00:00 2001
From: Jim Fehlig <jfehlig@suse.com>
Date: Mon, 1 Aug 2016 21:16:43 -0600
Subject: [PATCH] virpci: support driver_override sysfs interface
virpci: support driver_override sysfs interface
Currently, libvirt uses the new_id PCI sysfs interface to bind a PCI
stub driver to a PCI device. The new_id interface is known to be
buggy and racey, hence a more deterministic interface was introduced
in the 3.12 kernel - driver_override. For more details see
https://www.redhat.com/archives/libvir-list/2016-June/msg02124.html
This patch changes the stub binding/unbinding code to use the
driver_override interface if present. If not present, the new_id
interface will be used to provide compatibility with older kernels
lacking driver_override.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
libvirt uses the new_id PCI sysfs interface to bind a PCI stub driver
to a PCI device. The new_id interface is known to be buggy and racey,
hence a more deterministic interface was introduced in the 3.12 kernel:
driver_override. For more details see
https://www.redhat.com/archives/libvir-list/2016-June/msg02124.html
This patch adds support for the driver_override interface by
- adding new virPCIDevice{BindTo,UnbindFrom}StubWithOverride functions
that use the driver_override interface
- renames the existing virPCIDevice{BindTo,UnbindFrom}Stub functions
to virPCIDevice{BindTo,UnbindFrom}StubWithNewid to perserve existing
behavior on new_id interface
- changes virPCIDevice{BindTo,UnbindFrom}Stub function to call one of
the above depending on availability of driver_override
The patch includes a bit of duplicate code, but allows for easily
dropping the new_id code once support for older kernels is no
longer desired.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
---
src/util/virpci.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 149 insertions(+), 2 deletions(-)
Index: libvirt-2.0.0/src/util/virpci.c
===================================================================
--- libvirt-2.0.0.orig/src/util/virpci.c
+++ libvirt-2.0.0/src/util/virpci.c
@@ -1158,6 +1158,19 @@ virPCIDeviceUnbindFromStub(virPCIDeviceP
VIR_DEBUG("Reprobing for PCI device %s", dev->name);
+ /* Remove driver_override if it exists */
+ VIR_FREE(path);
+ if (!(path = virPCIFile(dev->name, "driver_override")))
+ goto cleanup;
+
+ if (virFileExists(path) && virFileWriteStr(path, "\n", 0) < 0) {
+ virReportSystemError(errno,
+ _("Failed to remove stub driver from "
+ "driver_override interface of PCI device '%s'"),
+ dev->name);
+ goto cleanup;
+ }
+
/* Trigger a re-probe of the device is not in the stub's dynamic
* ID table. If the stub is available, but 'remove_id' isn't
* available, then re-probing would just cause the device to be
@@ -1193,49 +1206,13 @@ virPCIDeviceUnbindFromStub(virPCIDeviceP
@@ -1089,8 +1089,54 @@ virPCIDeviceUnbind(virPCIDevicePtr dev)
return ret;
}
+/*
+ * Bind a PCI device to a driver using driver_override sysfs interface.
+ * E.g.
+ *
+ * echo driver-name > /sys/bus/pci/devices/0000:03:00.0/driver_override
+ * echo 0000:03:00.0 > /sys/bus/pci/devices/0000:03:00.0/driver/unbind
+ * echo 0000:03:00.0 > /sys/bus/pci/drivers_probe
+ *
+ * An empty driverName will cause the device to be bound to its
+ * preferred driver.
+ */
static int
-virPCIDeviceBindToStub(virPCIDevicePtr dev)
+virPCIDeviceBindToStubWithNewid(virPCIDevicePtr dev,
+ const char *stubDriverName)
{
- int result = -1;
- char *stubDriverPath = NULL;
- char *driverLink = NULL;
- char *path = NULL; /* reused for different purposes */
- const char *stubDriverName = NULL;
+ int ret = -1;
+ char *path = NULL;
virErrorPtr err = NULL;
- /* Check the device is configured to use one of the known stub drivers */
- if (dev->stubDriver == VIR_PCI_STUB_DRIVER_NONE) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("No stub driver configured for PCI device %s"),
- dev->name);
- return -1;
- } else if (!(stubDriverName = virPCIStubDriverTypeToString(dev->stubDriver))) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unknown stub driver configured for PCI device %s"),
- dev->name);
- return -1;
- }
-
- if (!(stubDriverPath = virPCIDriverDir(stubDriverName)) ||
- !(driverLink = virPCIFile(dev->name, "driver")))
- goto cleanup;
-
- if (virFileExists(driverLink)) {
- if (virFileLinkPointsTo(driverLink, stubDriverPath)) {
- /* The device is already bound to the correct driver */
- VIR_DEBUG("Device %s is already bound to %s",
- dev->name, stubDriverName);
- dev->unbind_from_stub = true;
- dev->remove_slot = true;
- result = 0;
- goto cleanup;
- }
- /*
- * If the device is bound to a driver that is not the stub, we'll
- * need to reprobe later
- */
- dev->reprobe = true;
- }
-
/* Add the PCI device ID to the stub's dynamic ID table;
* this is needed to allow us to bind the device to the stub.
* Note: if the device is not currently bound to any driver,
@@ -1283,7 +1260,7 @@ virPCIDeviceBindToStub(virPCIDevicePtr d
}
dev->unbind_from_stub = true;
- result = 0;
+ ret = 0;
remove_id:
err = virSaveLastError();
@@ -1299,7 +1276,7 @@ virPCIDeviceBindToStub(virPCIDevicePtr d
"cannot be probed again.", dev->id, stubDriverName);
}
dev->reprobe = false;
- result = -1;
+ ret = -1;
goto cleanup;
}
@@ -1314,10 +1291,142 @@ virPCIDeviceBindToStub(virPCIDevicePtr d
"cannot be probed again.", dev->id, stubDriverName);
}
dev->reprobe = false;
- result = -1;
+ ret = -1;
+ goto cleanup;
+ }
+
+ cleanup:
+ VIR_FREE(path);
+
+ if (err)
+ virSetError(err);
+ virFreeError(err);
+
+ return ret;
+}
+
+
+static int
+virPCIDeviceBindToStubWithOverride(virPCIDevicePtr dev,
+ const char *stubDriverName)
-virPCIDeviceUnbindFromStub(virPCIDevicePtr dev)
+virPCIDeviceBindWithDriverOverride(virPCIDevicePtr dev,
+ const char *driverName)
+{
+ int ret = -1;
+ char *path = NULL;
+ char *path;
+
+ /*
+ * Add stub to the device's driver_override, falling back to
+ * adding the device ID to the stub's dynamic ID table.
+ */
+ if (!(path = virPCIFile(dev->name, "driver_override")))
+ return -1;
+
+ if (virFileWriteStr(path, stubDriverName, 0) < 0) {
+ if (virFileWriteStr(path, driverName, 0) < 0) {
+ virReportSystemError(errno,
+ _("Failed to add stub driver '%s' to "
+ "driver_override interface of PCI device '%s'"),
+ stubDriverName, dev->name);
+ _("Failed to add driver '%s' to driver_override "
+ " interface of PCI device '%s'"),
+ driverName, dev->name);
+ goto cleanup;
+ }
+
+ if (virPCIDeviceUnbind(dev) < 0)
+ goto cleanup;
+
+ /* Xen's pciback.ko wants you to use new_slot first */
+ VIR_FREE(path);
+ if (!(path = virPCIDriverFile(stubDriverName, "new_slot")))
+ goto cleanup;
+
+ if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) {
+ virReportSystemError(errno,
+ _("Failed to add slot for "
+ "PCI device '%s' to %s"),
+ dev->name, stubDriverName);
+ goto cleanup;
+ }
+ dev->remove_slot = true;
+
+ if (virFileWriteStr(PCI_SYSFS "drivers_probe", dev->name, 0) < 0) {
+ virReportSystemError(errno,
+ _("Failed to trigger a re-probe for PCI device '%s'"),
+ _("Failed to trigger a probe for PCI device '%s'"),
+ dev->name);
goto cleanup;
}
+ /*
+ * Device is now bound to the stub. Set reprobe so it will be re-bound
+ * when unbinding from the stub.
+ */
+ dev->reprobe = true;
+ dev->unbind_from_stub = true;
+ goto cleanup;
+ }
+
+ ret = 0;
+
@ -194,15 +84,65 @@ Index: libvirt-2.0.0/src/util/virpci.c
+ return ret;
+}
+
+static int
+virPCIDeviceUnbindFromStubWithNewid(virPCIDevicePtr dev)
{
int result = -1;
char *drvdir = NULL;
@@ -1191,9 +1237,41 @@ virPCIDeviceUnbindFromStub(virPCIDeviceP
return result;
}
+static int
+virPCIDeviceUnbindFromStubWithOverride(virPCIDevicePtr dev)
+{
+ if (!dev->unbind_from_stub) {
+ VIR_DEBUG("Unbind from stub skipped for PCI device %s", dev->name);
+ return 0;
+ }
+
+ return virPCIDeviceBindWithDriverOverride(dev, "\n");
+}
+
+static int
+virPCIDeviceBindToStub(virPCIDevicePtr dev)
+virPCIDeviceUnbindFromStub(virPCIDevicePtr dev)
+{
+ int result = -1;
+ int ret;
+ char *path;
+
+ /*
+ * Prefer using the device's driver_override interface, falling back
+ * to the unpleasant new_id interface.
+ */
+ if (!(path = virPCIFile(dev->name, "driver_override")))
+ return -1;
+
+ if (virFileExists(path))
+ ret = virPCIDeviceUnbindFromStubWithOverride(dev);
+ else
+ ret = virPCIDeviceUnbindFromStubWithNewid(dev);
+
+ VIR_FREE(path);
+ return ret;
+}
static int
-virPCIDeviceBindToStub(virPCIDevicePtr dev)
+virPCIDeviceBindToStubWithNewid(virPCIDevicePtr dev)
{
int result = -1;
bool reprobe = false;
@@ -1345,6 +1423,75 @@ virPCIDeviceBindToStub(virPCIDevicePtr d
return result;
}
+static int
+virPCIDeviceBindToStubWithOverride(virPCIDevicePtr dev)
+{
+ int ret = -1;
+ const char *stubDriverName;
+ char *stubDriverPath = NULL;
+ char *driverLink = NULL;
+ char *path = NULL; /* reused for different purposes */
+ const char *stubDriverName = NULL;
+
+ /* Check the device is configured to use one of the known stub drivers */
+ if (dev->stubDriver == VIR_PCI_STUB_DRIVER_NONE) {
@ -226,46 +166,45 @@ Index: libvirt-2.0.0/src/util/virpci.c
+ /* The device is already bound to the correct driver */
+ VIR_DEBUG("Device %s is already bound to %s",
+ dev->name, stubDriverName);
+ dev->unbind_from_stub = true;
+ dev->remove_slot = true;
+ result = 0;
+ ret = 0;
+ goto cleanup;
+ }
+ /*
+ * If the device is bound to a driver that is not the stub, we'll
+ * need to reprobe later
+ */
+ dev->reprobe = true;
+ }
+
+ /*
+ * Add stub to the device's driver_override, falling back to
+ * adding the device ID to the stub's dynamic ID table.
+ */
+ if (!(path = virPCIFile(dev->name, "driver_override")))
+ if (virPCIDeviceBindWithDriverOverride(dev, stubDriverName) < 0)
+ goto cleanup;
+
+ if (virFileExists(path)) {
+ if (virPCIDeviceBindToStubWithOverride(dev, stubDriverName) < 0)
+ goto cleanup;
+ } else {
+ if (virPCIDeviceBindToStubWithNewid(dev, stubDriverName) < 0)
+ goto cleanup;
+ }
+ dev->unbind_from_stub = true;
+ ret = 0;
+
+ result = 0;
+ cleanup:
+ VIR_FREE(stubDriverPath);
+ VIR_FREE(driverLink);
+ return ret;
+}
+
cleanup:
VIR_FREE(stubDriverPath);
VIR_FREE(driverLink);
@@ -1326,10 +1435,6 @@ virPCIDeviceBindToStub(virPCIDevicePtr d
if (result < 0)
virPCIDeviceUnbindFromStub(dev);
- if (err)
- virSetError(err);
- virFreeError(err);
-
return result;
}
+static int
+virPCIDeviceBindToStub(virPCIDevicePtr dev)
+{
+ int ret;
+ char *path;
+
+ /*
+ * Prefer using the device's driver_override interface, falling back
+ * to the unpleasant new_id interface.
+ */
+ if (!(path = virPCIFile(dev->name, "driver_override")))
+ return -1;
+
+ if (virFileExists(path))
+ ret = virPCIDeviceBindToStubWithOverride(dev);
+ else
+ ret = virPCIDeviceBindToStubWithNewid(dev);
+
+ VIR_FREE(path);
+ return ret;
+}
+
/* virPCIDeviceDetach:
*
* Detach this device from the host driver, attach it to the stub