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:
Dominique Leuenberger 2016-08-09 20:14:55 +00:00 committed by Git OBS Bridge
commit d79d3fda35
7 changed files with 346 additions and 350 deletions

View 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

View 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;

View File

@ -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

View File

@ -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

View File

@ -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;

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

View File

@ -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 {