Accepting request 417209 from Virtualization
Another bug fix for Factory found during SLE12 SP2 testing. - cpu_x86: fix libvirtd segfault when host cpu is 'qemu64' cpumodel-vendor-crash-fix.patch bsc#992425 - bsc#988279. Move the qemu-bridge-helper apparmor profile from the qemu abstraction to the usr.sbin.libvirtd profile. apparmor-qemu-bridge-helper.patch - spec: minor improvements to logic enabling numactl and numad support and fix nested if indentation FATE#319979 - 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 - spec: enable numactl and numad support for aarch64 FATE#319979, bsc#991377 OBS-URL: https://build.opensuse.org/request/show/417209 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libvirt?expand=0&rev=212
This commit is contained in:
commit
d79d3fda35
69
apparmor-qemu-bridge-helper.patch
Normal file
69
apparmor-qemu-bridge-helper.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From 430cd5a72cf1f5c3e56cf1b4b40385812477aef3 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
|
||||
Date: Fri, 5 Aug 2016 09:32:54 +0200
|
||||
Subject: [PATCH] apparmor: move qemu-bridge-helper to libvirtd profile
|
||||
|
||||
qemu-bridge-helper is only called from libvirtd, it has to be moved
|
||||
from the qemu domain abstraction to the usr.sbin.libvirtd profile.
|
||||
---
|
||||
examples/apparmor/libvirt-qemu | 19 -------------------
|
||||
examples/apparmor/usr.sbin.libvirtd | 18 ++++++++++++++++++
|
||||
2 files changed, 18 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/examples/apparmor/libvirt-qemu b/examples/apparmor/libvirt-qemu
|
||||
index efb4873..11381d4 100644
|
||||
--- a/examples/apparmor/libvirt-qemu
|
||||
+++ b/examples/apparmor/libvirt-qemu
|
||||
@@ -148,22 +148,3 @@
|
||||
/etc/udev/udev.conf r,
|
||||
/sys/bus/ r,
|
||||
/sys/class/ r,
|
||||
-
|
||||
- /usr/{lib,libexec}/qemu-bridge-helper Cx -> qemu_bridge_helper,
|
||||
- # child profile for bridge helper process
|
||||
- profile qemu_bridge_helper {
|
||||
- #include <abstractions/base>
|
||||
-
|
||||
- capability setuid,
|
||||
- capability setgid,
|
||||
- capability setpcap,
|
||||
- capability net_admin,
|
||||
-
|
||||
- network inet stream,
|
||||
-
|
||||
- /dev/net/tun rw,
|
||||
- /etc/qemu/** r,
|
||||
- owner @{PROC}/*/status r,
|
||||
-
|
||||
- /usr/{lib,libexec}/qemu-bridge-helper rmix,
|
||||
- }
|
||||
diff --git a/examples/apparmor/usr.sbin.libvirtd b/examples/apparmor/usr.sbin.libvirtd
|
||||
index 23f70f5..48651b2 100644
|
||||
--- a/examples/apparmor/usr.sbin.libvirtd
|
||||
+++ b/examples/apparmor/usr.sbin.libvirtd
|
||||
@@ -67,4 +67,22 @@
|
||||
# allow changing to our UUID-based named profiles
|
||||
change_profile -> @{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
|
||||
|
||||
+ /usr/{lib,libexec}/qemu-bridge-helper Cx -> qemu_bridge_helper,
|
||||
+ # child profile for bridge helper process
|
||||
+ profile qemu_bridge_helper {
|
||||
+ #include <abstractions/base>
|
||||
+
|
||||
+ capability setuid,
|
||||
+ capability setgid,
|
||||
+ capability setpcap,
|
||||
+ capability net_admin,
|
||||
+
|
||||
+ network inet stream,
|
||||
+
|
||||
+ /dev/net/tun rw,
|
||||
+ /etc/qemu/** r,
|
||||
+ owner @{PROC}/*/status r,
|
||||
+
|
||||
+ /usr/{lib,libexec}/qemu-bridge-helper rmix,
|
||||
+ }
|
||||
}
|
||||
--
|
||||
2.6.6
|
||||
|
56
cpumodel-vendor-crash-fix.patch
Normal file
56
cpumodel-vendor-crash-fix.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From 341445ce85d91a105f8183f22226d9d90853b27b Mon Sep 17 00:00:00 2001
|
||||
From: Jim Fehlig <jfehlig@suse.com>
|
||||
Date: Fri, 5 Aug 2016 15:23:47 -0600
|
||||
Subject: [PATCH] cpu_x86: fix libvirtd crash when host cpu is 'qemu64'
|
||||
|
||||
When starting an L2 nested VM with <cpu mode="host-model"> on an
|
||||
L1 VM with cpu 'qemu64', libvirtd crashes with
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0x00007ffff739bf33 in x86DataCpuid (cpuid=0x8, cpuid=0x8,
|
||||
data=data@entry=0x7fffb800ee78) at cpu/cpu_x86.c:287
|
||||
287 for (i = 0; i < data->len; i++) {
|
||||
(gdb) bt
|
||||
f0 0x00007ffff739bf33 in x86DataCpuid (cpuid=0x8, cpuid=0x8,
|
||||
data=data@entry=0x7fffb800ee78) at cpu/cpu_x86.c:287
|
||||
f1 virCPUx86DataAddCPUID (data=data@entry=0x7fffb800ee78, cpuid=0x8)
|
||||
at cpu/cpu_x86.c:355
|
||||
f2 0x00007ffff739ef47 in x86Compute (host=<optimized out>, cpu=0x7fffb8000cc0,
|
||||
guest=0x7fffecca7348, message=<optimized out>) at cpu/cpu_x86.c:1580
|
||||
f3 0x00007fffd2b38e53 in qemuBuildCpuModelArgStr (migrating=false,
|
||||
hasHwVirt=<synthetic pointer>, qemuCaps=0x7fffb8001040, buf=0x7fffecca7360,
|
||||
def=0x7fffc400ce20, driver=0x1c) at qemu/qemu_command.c:6283
|
||||
f4 qemuBuildCpuCommandLine (cmd=cmd@entry=0x7fffb8002f60,
|
||||
driver=driver@entry=0x7fffc80882c0, def=def@entry=0x7fffc400ce20,
|
||||
qemuCaps=qemuCaps@entry=0x7fffb8001040, migrating=<optimized out>)
|
||||
at qemu/qemu_command.c:6445
|
||||
|
||||
In frame 2, &host_model->vendor->cpuid is passed to virCPUx86DataAddCPUID(),
|
||||
but
|
||||
|
||||
(gdb) p *host_model
|
||||
$23 = {name = 0x7fffb800ec50 "qemu64", vendor = 0x0, signature = 0, data = {
|
||||
len = 2, data = 0x7fffb800e720}}
|
||||
|
||||
With vendor = 0x0, &host_model->vendor->cpuid evaluates to 8, which
|
||||
is not a nice value to pass to virCPUx86DataAddCPUID(). Check for a
|
||||
non-null host_model->vendor before calling virCPUx86DataAddCPUID().
|
||||
|
||||
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
|
||||
---
|
||||
src/cpu/cpu_x86.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
Index: libvirt-2.0.0/src/cpu/cpu_x86.c
|
||||
===================================================================
|
||||
--- libvirt-2.0.0.orig/src/cpu/cpu_x86.c
|
||||
+++ libvirt-2.0.0/src/cpu/cpu_x86.c
|
||||
@@ -1576,7 +1576,7 @@ x86Compute(virCPUDefPtr host,
|
||||
if (!(guest_model = x86ModelCopy(host_model)))
|
||||
goto error;
|
||||
|
||||
- if (cpu->vendor &&
|
||||
+ if (cpu->vendor && host_model->vendor &&
|
||||
virCPUx86DataAddCPUID(&guest_model->data,
|
||||
&host_model->vendor->cpuid) < 0)
|
||||
goto error;
|
@ -1,3 +1,39 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Aug 5 22:27:44 UTC 2016 - jfehlig@suse.com
|
||||
|
||||
- cpu_x86: fix libvirtd segfault when host cpu is 'qemu64'
|
||||
cpumodel-vendor-crash-fix.patch
|
||||
bsc#992425
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Aug 5 08:05:39 UTC 2016 - cbosdonnat@suse.com
|
||||
|
||||
- bsc#988279. Move the qemu-bridge-helper apparmor profile from the
|
||||
qemu abstraction to the usr.sbin.libvirtd profile.
|
||||
apparmor-qemu-bridge-helper.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Aug 3 19:31:11 UTC 2016 - jfehlig@suse.com
|
||||
|
||||
- spec: minor improvements to logic enabling numactl and numad
|
||||
support and fix nested if indentation
|
||||
FATE#319979
|
||||
|
||||
-------------------------------------------------------------------
|
||||
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
|
||||
|
||||
|
63
libvirt.spec
63
libvirt.spec
@ -41,10 +41,9 @@
|
||||
%define with_hyperv 0%{!?_without_hyperv:0}
|
||||
|
||||
# Then the secondary host drivers, which run inside libvirtd
|
||||
%define with_storage_rbd 0
|
||||
%define with_storage_rbd 0%{!?_without_storage_rbd:0}
|
||||
%define with_storage_sheepdog 0
|
||||
%define with_storage_gluster 0
|
||||
%define with_numactl 0%{!?_without_numactl:1}
|
||||
%define with_apparmor 0%{!?_without_apparmor:1}
|
||||
|
||||
# Optional bits on by default
|
||||
@ -54,6 +53,7 @@
|
||||
# A few optional bits off by default, we enable later
|
||||
%define with_cgconfig 0%{!?_without_cgconfig:0}
|
||||
%define with_systemd 0%{!?_without_systemd:0}
|
||||
%define with_numactl 0%{!?_without_numactl:0}
|
||||
%define with_numad 0%{!?_without_numad:0}
|
||||
%define with_firewalld 0%{!?_without_firewalld:0}
|
||||
%define with_wireshark 0%{!?_without_wireshark:0}
|
||||
@ -77,10 +77,17 @@
|
||||
%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
|
||||
%define with_numactl 0
|
||||
# Enable numactl for most architectures. Handle aarch64 separately
|
||||
%ifnarch s390 s390x %arm %ix86 aarch64
|
||||
%define with_numactl 0%{!?_without_numactl:1}
|
||||
%endif
|
||||
|
||||
# For aarch64, numactl is only available on newer than 1320, or SLE12
|
||||
# family newer than 120100
|
||||
%ifarch aarch64
|
||||
%if 0%{?suse_version} > 1320 || ( 0%{?suse_version} == 1315 && ( 0%{?sle_version} > 120100 ) )
|
||||
%define with_numactl 0%{!?_without_numactl:1}
|
||||
%endif
|
||||
%endif
|
||||
|
||||
# vbox is available only on i386 x86_64
|
||||
@ -106,26 +113,26 @@
|
||||
%ifarch x86_64
|
||||
# enable on anything newer than 1320, or SLE12 family newer than 120100
|
||||
# use librbd-devel as build dependency
|
||||
%if 0%{?suse_version} > 1320 || ( 0%{?suse_version} == 1315 && ( 0%{?sle_version} > 120100 ) )
|
||||
%define with_storage_rbd 1
|
||||
%define with_rbd_lib librbd-devel
|
||||
%endif
|
||||
# enable for SLE12 family <= 120100 (SLE12ga/sp1, Leap 42.1)
|
||||
%if 0%{?suse_version} > 1320 || ( 0%{?suse_version} == 1315 && ( 0%{?sle_version} > 120100 ) )
|
||||
%define with_storage_rbd 0%{!?_without_storage_rbd:1}
|
||||
%define with_rbd_lib librbd-devel
|
||||
%endif
|
||||
# enable for SLE12 family <= 120100 (SLE12GA/SP1, Leap 42.1)
|
||||
# use ceph-devel as build dependency
|
||||
%if 0%{?suse_version} == 1315 && 0%{?sle_version} <= 120100
|
||||
%define with_storage_rbd 1
|
||||
%define with_rbd_lib ceph-devel
|
||||
%endif
|
||||
%if 0%{?suse_version} == 1315 && 0%{?sle_version} <= 120100
|
||||
%define with_storage_rbd 0%{!?_without_storage_rbd:1}
|
||||
%define with_rbd_lib ceph-devel
|
||||
%endif
|
||||
%endif
|
||||
|
||||
# For arm
|
||||
%ifarch aarch64
|
||||
# enable on anything newer than 1320, or SLE12 family newer than 120100
|
||||
# use librbd-devel as build dependency
|
||||
%if 0%{?suse_version} > 1320 || ( 0%{?is_opensuse} == 0 && 0%{?sle_version} > 120100 )
|
||||
%define with_storage_rbd 1
|
||||
%define with_rbd_lib librbd-devel
|
||||
%endif
|
||||
%if 0%{?suse_version} > 1320 || ( 0%{?is_opensuse} == 0 && 0%{?sle_version} > 120100 )
|
||||
%define with_storage_rbd 0%{!?_without_storage_rbd:1}
|
||||
%define with_rbd_lib librbd-devel
|
||||
%endif
|
||||
%endif
|
||||
|
||||
# Support systemd on 12.1 and later
|
||||
@ -139,11 +146,19 @@
|
||||
%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
|
||||
%if %{with_qemu} || %{with_lxc} || %{with_uml}
|
||||
%ifarch x86_64
|
||||
# Enable numad for most architectures. Handle aarch64 separately
|
||||
%ifnarch s390 s390x %arm %ix86 aarch64
|
||||
%define with_numad 0%{!?_without_numad:1}
|
||||
%endif
|
||||
# For aarch64, enable on anything newer than 1320, or SLE12 family newer
|
||||
# than 120100
|
||||
%ifarch aarch64
|
||||
%if 0%{?suse_version} > 1320 || ( 0%{?suse_version} == 1315 && 0%{?sle_version} > 120100 )
|
||||
%define with_numad 0%{!?_without_numad:1}
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
|
||||
# Force QEMU to run as qemu:qemu
|
||||
@ -301,8 +316,8 @@ 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
|
||||
Patch102: cpumodel-vendor-crash-fix.patch
|
||||
# Need to go upstream
|
||||
Patch150: xen-pv-cdrom.patch
|
||||
Patch151: blockcopy-check-dst-identical-device.patch
|
||||
@ -311,6 +326,7 @@ Patch153: ppc64le-canonical-name.patch
|
||||
Patch154: libxl-set-migration-constraints.patch
|
||||
Patch155: libxl-set-cach-mode.patch
|
||||
Patch156: apparmor-fixes.patch
|
||||
Patch157: apparmor-qemu-bridge-helper.patch
|
||||
# Our patches
|
||||
Patch200: libvirtd-defaults.patch
|
||||
Patch201: libvirtd-init-script.patch
|
||||
@ -763,6 +779,7 @@ libvirt plugin for NSS for translating domain names into IP addresses.
|
||||
%patch154 -p1
|
||||
%patch155 -p1
|
||||
%patch156 -p1
|
||||
%patch157 -p1
|
||||
%patch200 -p1
|
||||
%patch201 -p1
|
||||
%patch202 -p1
|
||||
|
@ -1,118 +0,0 @@
|
||||
commit caba00f00fb18d8ffc388f4fc8b82527ef98d3b0
|
||||
Author: Jim Fehlig <jfehlig@suse.com>
|
||||
Date: Wed Jul 6 14:06:37 2016 -0600
|
||||
|
||||
virpci: simplify virPCIDeviceBindToStub
|
||||
|
||||
Early in virPCIDeviceBindToStub, there is a check to see if the
|
||||
stub is already bound to the device, returning success with no
|
||||
further actions if that is the case.
|
||||
|
||||
The same condition is unnecessarily checked later in the function.
|
||||
Remove the unneeded checks to simplify the logic a bit.
|
||||
|
||||
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
|
||||
|
||||
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
|
||||
@@ -1196,7 +1196,6 @@ static int
|
||||
virPCIDeviceBindToStub(virPCIDevicePtr dev)
|
||||
{
|
||||
int result = -1;
|
||||
- bool reprobe = false;
|
||||
char *stubDriverPath = NULL;
|
||||
char *driverLink = NULL;
|
||||
char *path = NULL; /* reused for different purposes */
|
||||
@@ -1225,10 +1224,16 @@ virPCIDeviceBindToStub(virPCIDevicePtr d
|
||||
/* 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;
|
||||
}
|
||||
- reprobe = true;
|
||||
+ /*
|
||||
+ * 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;
|
||||
@@ -1249,51 +1254,34 @@ virPCIDeviceBindToStub(virPCIDevicePtr d
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- /* check whether the device is bound to pci-stub when we write dev->id to
|
||||
- * ${stubDriver}/new_id.
|
||||
- */
|
||||
- if (virFileLinkPointsTo(driverLink, stubDriverPath)) {
|
||||
- dev->unbind_from_stub = true;
|
||||
- dev->remove_slot = true;
|
||||
- result = 0;
|
||||
+ if (virPCIDeviceUnbind(dev) < 0)
|
||||
goto remove_id;
|
||||
- }
|
||||
|
||||
- if (virPCIDeviceUnbind(dev) < 0)
|
||||
+ /* Xen's pciback.ko wants you to use new_slot first */
|
||||
+ VIR_FREE(path);
|
||||
+ if (!(path = virPCIDriverFile(stubDriverName, "new_slot")))
|
||||
goto remove_id;
|
||||
|
||||
- /* If the device was bound to a driver we'll need to reprobe later */
|
||||
- dev->reprobe = reprobe;
|
||||
+ 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 remove_id;
|
||||
+ }
|
||||
+ dev->remove_slot = true;
|
||||
|
||||
- /* If the device isn't already bound to pci-stub, try binding it now.
|
||||
- */
|
||||
- if (!virFileLinkPointsTo(driverLink, stubDriverPath)) {
|
||||
- /* Xen's pciback.ko wants you to use new_slot first */
|
||||
- VIR_FREE(path);
|
||||
- if (!(path = virPCIDriverFile(stubDriverName, "new_slot")))
|
||||
- goto remove_id;
|
||||
-
|
||||
- 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 remove_id;
|
||||
- }
|
||||
- dev->remove_slot = true;
|
||||
+ VIR_FREE(path);
|
||||
+ if (!(path = virPCIDriverFile(stubDriverName, "bind")))
|
||||
+ goto remove_id;
|
||||
|
||||
- VIR_FREE(path);
|
||||
- if (!(path = virPCIDriverFile(stubDriverName, "bind")))
|
||||
- goto remove_id;
|
||||
-
|
||||
- if (virFileWriteStr(path, dev->name, 0) < 0) {
|
||||
- virReportSystemError(errno,
|
||||
- _("Failed to bind PCI device '%s' to %s"),
|
||||
- dev->name, stubDriverName);
|
||||
- goto remove_id;
|
||||
- }
|
||||
- dev->unbind_from_stub = true;
|
||||
+ if (virFileWriteStr(path, dev->name, 0) < 0) {
|
||||
+ virReportSystemError(errno,
|
||||
+ _("Failed to bind PCI device '%s' to %s"),
|
||||
+ dev->name, stubDriverName);
|
||||
+ goto remove_id;
|
||||
}
|
||||
+ dev->unbind_from_stub = true;
|
||||
|
||||
result = 0;
|
||||
|
@ -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
|
||||
|
@ -2,13 +2,10 @@ Index: libvirt-2.0.0/examples/apparmor/libvirt-qemu
|
||||
===================================================================
|
||||
--- libvirt-2.0.0.orig/examples/apparmor/libvirt-qemu
|
||||
+++ libvirt-2.0.0/examples/apparmor/libvirt-qemu
|
||||
@@ -152,6 +152,9 @@
|
||||
@@ -151,3 +151,6 @@
|
||||
/etc/udev/udev.conf r,
|
||||
/sys/bus/ r,
|
||||
/sys/class/ r,
|
||||
|
||||
+
|
||||
+ # Temporary screendump rule -- See bsc#904426
|
||||
+ /var/cache/libvirt/qemu/qemu.screendump.* rw,
|
||||
+
|
||||
/usr/{lib,libexec}/qemu-bridge-helper Cx -> qemu_bridge_helper,
|
||||
# child profile for bridge helper process
|
||||
profile qemu_bridge_helper {
|
||||
|
Loading…
Reference in New Issue
Block a user