Compare commits

...

49 Commits

Author SHA1 Message Date
Cole Robinson 3d90c2f845 Add qemu.conf options for audio workaround
Fix parsing certain USB sysfs files (bz 598272)
Sanitize pool target paths (bz 494005)
Add qemu.conf for clear emulator capabilities
Prevent libvirtd inside a VM from breaking network access (bz 235961)
Mention --all in 'virsh list' docs (bz 575512)
Initscript fixes (bz 565238)
List wireless interfaces via nodedev-list (bz 596928)
2010-06-17 17:42:36 +00:00
Cole Robinson 5c3e8a7ac0 Fix nodedev XML conversion errors (bz 591262)
Fix PCI xml decimal parsing (bz 582752)
Fix CDROM media connect/eject (bz 582005)
Always report qemu startup output on error (bz 581381)
Fix crash from 'virsh dominfo' if secdriver disabled (bz 581166)
2010-05-18 18:49:49 +00:00
Cole Robinson 09a86187e8 Fix slow storage volume allocation (bz 582356) 2010-04-20 19:39:41 +00:00
Cole Robinson a8bac7d647 Fix USB devices by product with security enabled (bz 574136)
Set kernel/initrd in security driver, fixes some URL installs (bz 566425)
2010-03-22 15:09:54 +00:00
Daniel Veillard 74d9fb3860 oops forgot to update sources too, Daniel 2010-03-05 17:11:45 +00:00
Daniel Veillard 1b3b9bf1cc Upstream release of 0.7.7,
Daniel
2010-03-05 16:59:20 +00:00
Adam Jackson 1d1a47ccaf bump to appease cvs 2010-02-17 15:34:59 +00:00
Adam Jackson 14f81abaae all of libvirt_test.la needs -ldl 2010-02-17 15:33:23 +00:00
Jesse Keating 6b3af81b0e Initialize branch F-13 for libvirt 2010-02-17 01:56:25 +00:00
Adam Jackson e24467a8c2 * Tue Feb 16 2010 Adam Jackson <ajax@redhat.com> 0.7.6-2
- libvirt-0.7.6-add-needed.patch: Fix FTBFS from --no-add-needed
- Add BuildRequires: xmlrpc-c-client for libxmlrpc_client.so
2010-02-17 00:11:39 +00:00
Adam Jackson b39c370a76 add the patch 2010-02-16 23:59:23 +00:00
Adam Jackson 62e4e7cde2 * Tue Feb 16 2010 Adam Jackson <ajax@redhat.com> 0.7.6-2
- libvirt-0.7.6-add-needed.patch: Fix FTBFS from --no-add-needed
2010-02-16 23:49:24 +00:00
Daniel Veillard f822179f97 Oops forgot to bump version, Daniel 2010-02-03 17:40:46 +00:00
Daniel Veillard 47e7e1e548 upstream release of 0.7.6
daniel
2010-02-03 17:39:33 +00:00
Chris Weyl e73b75314b * Thu Jan 14 2010 Chris Weyl <cweyl@alumni.drew.edu> 0.7.5-3
- bump for libssh2 rebuild
2010-01-14 16:59:58 +00:00
Daniel P. Berrange 8193a55b4a Rebuild for libparted soname change 2010-01-12 14:10:20 +00:00
Daniel Veillard 6036708fa2 Fix a problem in spec file, Daniel 2009-12-23 15:56:25 +00:00
Daniel Veillard 4717aa0b6d Upstream release of 0.7.5, Daniel 2009-12-23 15:40:21 +00:00
Bill Nottingham 97ae25ea7d Fix typo that causes a failure to update the common directory. (releng #2781) 2009-11-25 23:51:22 +00:00
Daniel Veillard 6470ed033b Upstream release of 0.7.3, Daniel 2009-11-20 18:59:17 +00:00
Daniel Veillard b550f9c1d5 Fix netcf BuildRequire, Daniel 2009-11-20 18:02:51 +00:00
Daniel Veillard ee0273ffc3 Upstream release of libvirt-0.7.3, Daniel 2009-11-20 16:55:47 +00:00
Daniel P. Berrange 50fce74b00 Really fix restore file labelling this time 2009-11-19 12:51:32 +00:00
Daniel P. Berrange e29f71d1c9 Disable numactl on s390[x] 2009-11-11 18:11:49 +00:00
Daniel P. Berrange 427ed20801 Fix QEMU save/restore permissions / labelling 2009-11-11 15:33:52 +00:00
Mark McLoughlin d23e6c285b * Thu Oct 29 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.2-3
- Avoid compressing small log files (#531030)
2009-10-29 17:26:05 +00:00
Mark McLoughlin 2c139b45d8 * Thu Oct 29 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.2-2
- Fix qemu machine types handling
2009-10-29 10:57:55 +00:00
Mark McLoughlin 762435e3b7 * Thu Oct 29 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.2-2
- Make libvirt-devel require libvirt-client, not libvirt
2009-10-29 10:15:23 +00:00
Daniel Veillard 6383d6b056 0.7.2 release, Daniel 2009-10-14 13:03:30 +00:00
Mark McLoughlin 3712441ea6 Add the second patch for #523158 2009-10-13 15:43:47 +00:00
Mark McLoughlin 9d0bc882fa * Tue Oct 13 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-12
- Fix restore of qemu guest using raw save format (#523158)
2009-10-13 15:34:15 +00:00
Mark McLoughlin 90dddf3d3d * Fri Oct 9 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-11
- Fix libvirtd memory leak during error reply sending (#528162)
- Add several PCI hot-unplug typo fixes from upstream
2009-10-09 14:53:48 +00:00
Mark McLoughlin 86abd54d02 * Tue Oct 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-10
- Create /var/log/libvirt/{lxc,uml} dirs for logrotate
- Make libvirt-python dependon on libvirt-client
- Sync misc minor changes from upstream spec
2009-10-06 12:48:58 +00:00
Mark McLoughlin 4ab5ad5425 * Tue Oct 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-9
- Change logrotate config to weekly (#526769)
2009-10-06 09:45:04 +00:00
Mark McLoughlin f9c1b758c3 - Re-label qcow2 backing files (#497131) 2009-10-01 15:17:31 +00:00
Mark McLoughlin 38cf1bd5ba * Thu Oct 1 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-8
- Disable sound backend, even when selinux is disabled (#524499)
2009-10-01 08:35:16 +00:00
Mark McLoughlin aeda455930 * Wed Sep 30 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-7
- Fix USB device passthrough (#522683)
2009-09-30 17:58:52 +00:00
Chris Weyl 288291b795 * Mon Sep 21 2009 Chris Weyl <cweyl@alumni.drew.edu> - 0.7.1-6
- rebuild for libssh2 1.2
2009-09-22 03:52:07 +00:00
Mark McLoughlin 7c2073faca * Mon Sep 21 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-5
- Don't set a bogus error in virDrvSupportsFeature()
- Fix raw save format
2009-09-21 15:32:34 +00:00
Mark McLoughlin 5b528ba717 Fix typo 2009-09-17 14:58:55 +00:00
Mark McLoughlin 4f731a7250 Got the wrong bug number 2009-09-17 14:51:05 +00:00
Mark McLoughlin f1ac0031f5 * Thu Sep 17 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-4%
- A couple of hot-unplug memory handling fixes (#523960)
2009-09-17 14:47:51 +00:00
Daniel Veillard e45b9c9030 Disable numactl on s390[x], Daniel 2009-09-17 13:30:50 +00:00
Daniel Veillard 3cf75c269d Refactoring of spec file by danpb for RHEL 5/6 compat, daniel 2009-09-17 12:32:32 +00:00
Daniel Veillard 585033f372 Release of 0.7.1 upstream, Daniel 2009-09-15 12:50:58 +00:00
Mark McLoughlin 897506e66a * Mon Sep 14 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-0.2.gitfac3f4c
- Update to newer snapshot of 0.7.1
- Stop libvirt using untrusted 'info vcpus' PID data (#520864)
- Support relabelling of USB and PCI devices
- Enable multipath storage support
- Restart libvirtd upon RPM upgrade
2009-09-14 18:30:45 +00:00
Mark McLoughlin e4bf8ffa42 * Sun Sep 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.1-0.1.gitg3ef2e05
- Update to pre-release git snapshot of 0.7.1
- Drop upstreamed patches
2009-09-06 13:46:19 +00:00
Mark McLoughlin 20367a58a6 Add URL to source tag 2009-08-21 10:19:53 +00:00
Mark McLoughlin aa037364ed * Wed Aug 19 2009 Mark McLoughlin <markmc@redhat.com> - 0.7.0-6
- Fix migration completion with newer versions of qemu (#516187)
2009-08-19 17:13:01 +00:00
33 changed files with 2039 additions and 2990 deletions
+6 -2
View File
@@ -9,6 +9,10 @@ libvirt-0.6.2.tar.gz
libvirt-0.6.3.tar.gz
libvirt-0.6.4.tar.gz
libvirt-0.6.5.tar.gz
libvirt-0.7.0-0.1.gitf055724.tar.gz
libvirt-0.7.0-0.6.gite195b43.tar.gz
libvirt-0.7.0.tar.gz
libvirt-0.7.1.tar.gz
libvirt-0.7.2.tar.gz
libvirt-0.7.3.tar.gz
libvirt-0.7.4.tar.gz
libvirt-0.7.5.tar.gz
libvirt-0.7.6.tar.gz
+1 -1
View File
@@ -4,7 +4,7 @@ NAME := libvirt
SPECFILE = $(firstword $(wildcard *.spec))
define find-makefile-common
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
endef
MAKEFILE_COMMON := $(shell $(find-makefile-common))
+1
View File
@@ -0,0 +1 @@
F-13
-51
View File
@@ -1,51 +0,0 @@
From 1e99b2edee0eb3ca1c600e5bd5c55741cb95a29a Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 17 Aug 2009 08:32:08 +0100
Subject: [PATCH] Disable sound cards when running sVirt
Temporary hack till PulseAudio autostart problems are sorted out when
SELinux enforcing (bz 486112)
Fedora-patch: libvirt-0.6.4-svirt-sound.patch
---
src/qemu_conf.c | 17 ++++++++++++++++-
1 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 6b0b404..53186e0 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -1384,6 +1384,20 @@ int qemudBuildCommandLine(virConnectPtr conn,
char uuid[VIR_UUID_STRING_BUFLEN];
char domid[50];
const char *cpu = NULL;
+ int skipSound = 0;
+
+ if (driver->securityDriver &&
+ driver->securityDriver->name &&
+ STREQ(driver->securityDriver->name, "selinux") &&
+ getuid() == 0) {
+ static int soundWarned = 0;
+ skipSound = 1;
+ if (def->nsounds &&
+ !soundWarned) {
+ soundWarned = 1;
+ VIR_WARN0("Sound cards for VMs are disabled while SELinux security model is active");
+ }
+ }
uname_normalize(&ut);
@@ -2015,7 +2029,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
/* Add sound hardware */
- if (def->nsounds) {
+ if (def->nsounds &&
+ !skipSound) {
int size = 100;
char *modstr;
if (VIR_ALLOC_N(modstr, size+1) < 0)
--
1.6.2.5
@@ -1,79 +0,0 @@
From 541cfdf5465ac3bba2c0c0901950547bc6638e47 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Thu, 6 Aug 2009 15:14:19 +0100
Subject: [PATCH] chown kernel/initrd before spawning qemu
If we're running qemu unprivileged, we need to chown any supplied kernel
or initrd before spawning it.
* src/qemu_driver.c: rename qemuDomainSetDiskOwnership() to
qemuDomainSetFileOwnership(), pass it a path string instead of a disk
definition and use it for chowning the kernel/initrd in
qemuDomainSetAllDeviceOwnership()
(cherry picked from commit c42b39784534930791d1feb3de859d85a7848168)
Fedora-patch: libvirt-0.7.0-chown-kernel-initrd-before-spawning-qemu.patch
---
src/qemu_driver.c | 20 ++++++++++++--------
1 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 412b68d..bd58435 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1684,18 +1684,18 @@ static int qemuDomainSetHostdevOwnership(virConnectPtr conn,
}
-static int qemuDomainSetDiskOwnership(virConnectPtr conn,
- virDomainDiskDefPtr def,
+static int qemuDomainSetFileOwnership(virConnectPtr conn,
+ const char *path,
uid_t uid, gid_t gid)
{
- if (!def->src)
+ if (!path)
return 0;
- VIR_DEBUG("Setting ownership on %s to %d:%d", def->src, uid, gid);
- if (chown(def->src, uid, gid) < 0) {
+ VIR_DEBUG("Setting ownership on %s to %d:%d", path, uid, gid);
+ if (chown(path, uid, gid) < 0) {
virReportSystemError(conn, errno, _("cannot set ownership on %s"),
- def->src);
+ path);
return -1;
}
return 0;
@@ -1725,7 +1725,7 @@ static int qemuDomainSetDeviceOwnership(virConnectPtr conn,
(def->data.disk->readonly || def->data.disk->shared))
return 0;
- return qemuDomainSetDiskOwnership(conn, def->data.disk, uid, gid);
+ return qemuDomainSetFileOwnership(conn, def->data.disk->src, uid, gid);
case VIR_DOMAIN_DEVICE_HOSTDEV:
return qemuDomainSetHostdevOwnership(conn, def->data.hostdev, uid, gid);
@@ -1753,12 +1753,16 @@ static int qemuDomainSetAllDeviceOwnership(virConnectPtr conn,
uid = restore ? 0 : driver->user;
gid = restore ? 0 : driver->group;
+ if (qemuDomainSetFileOwnership(conn, def->os.kernel, uid, gid) < 0 ||
+ qemuDomainSetFileOwnership(conn, def->os.initrd, uid, gid) < 0)
+ return -1;
+
for (i = 0 ; i < def->ndisks ; i++) {
if (restore &&
(def->disks[i]->readonly || def->disks[i]->shared))
continue;
- if (qemuDomainSetDiskOwnership(conn, def->disks[i], uid, gid) < 0)
+ if (qemuDomainSetFileOwnership(conn, def->disks[i]->src, uid, gid) < 0)
return -1;
}
--
1.6.2.5
@@ -1,45 +0,0 @@
From ddf0a7cb04debe60825d11186e68cc6de6fd1dd2 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Mon, 10 Aug 2009 11:16:37 +0100
Subject: [PATCH] Handle kernels with no ipv6 support
If the ipv6 kernel module is not loaded, then we get this when starting
a virtual network:
libvir: Network Config error :
cannot enable /proc/sys/net/ipv6/conf/virbr0/disable_ipv6:
No such file or directory
If disable_ipv6 is not present, we should just merrily continue on our
way.
* src/network_driver.c: make networkDisableIPV6() not fail if the kernel
has no ipv6 support
(cherry picked from commit f5a8f969dd92ec2744e1eec5d35288d5fbcded22)
Fedora-patch: libvirt-0.7.0-handle-kernels-with-no-ipv6-support.patch
---
src/network_driver.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/src/network_driver.c b/src/network_driver.c
index eaea454..84910ab 100644
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -801,6 +801,12 @@ static int networkDisableIPV6(virConnectPtr conn,
goto cleanup;
}
+ if (access(field, W_OK) < 0 && errno == ENOENT) {
+ VIR_DEBUG("ipv6 appears to already be disabled on %s", network->def->bridge);
+ ret = 0;
+ goto cleanup;
+ }
+
if (virFileWriteStr(field, "1") < 0) {
virReportSystemError(conn, errno,
_("cannot enable %s"), field);
--
1.6.2.5
-96
View File
@@ -1,96 +0,0 @@
From 663bf081dc6737c7fcc68a7ca1169aca60fbf8e5 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Thu, 13 Aug 2009 11:56:31 +0100
Subject: [PATCH] Make LXC / UML drivers robust against NUMA topology brokenness
Some kernel versions expose broken NUMA topology for some machines.
This causes the LXC/UML drivers to fail to start. QEMU driver was
already fixed for this problem
* src/lxc_conf.c: Log and ignore failure to populate NUMA info
* src/uml_conf.c: Log and ignore failure to populate NUMA info
* src/capabilities.c: Reset nnumaCell to 0 after freeing
(cherry picked from commit 19bac57b26c2d46ac8a7601158f210f34acdceac)
Fedora-patch: libvirt-0.7.0-numa-ignore-fail.patch
---
src/capabilities.c | 1 +
src/lxc_conf.c | 12 ++++++++++--
src/uml_conf.c | 11 +++++++++--
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/src/capabilities.c b/src/capabilities.c
index c6766b6..193a9fe 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -139,6 +139,7 @@ virCapabilitiesFreeNUMAInfo(virCapsPtr caps)
for (i = 0 ; i < caps->host.nnumaCell ; i++)
virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
VIR_FREE(caps->host.numaCell);
+ caps->host.nnumaCell = 0;
}
/**
diff --git a/src/lxc_conf.c b/src/lxc_conf.c
index d06a024..fef60ba 100644
--- a/src/lxc_conf.c
+++ b/src/lxc_conf.c
@@ -30,6 +30,8 @@
#include "lxc_conf.h"
#include "nodeinfo.h"
#include "virterror_internal.h"
+#include "logging.h"
+
#define VIR_FROM_THIS VIR_FROM_LXC
@@ -46,8 +48,14 @@ virCapsPtr lxcCapsInit(void)
0, 0)) == NULL)
goto no_memory;
- if (nodeCapsInitNUMA(caps) < 0)
- goto no_memory;
+ /* Some machines have problematic NUMA toplogy causing
+ * unexpected failures. We don't want to break the QEMU
+ * driver in this scenario, so log errors & carry on
+ */
+ if (nodeCapsInitNUMA(caps) < 0) {
+ virCapabilitiesFreeNUMAInfo(caps);
+ VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
+ }
/* XXX shouldn't 'borrow' KVM's prefix */
virCapabilitiesSetMacPrefix(caps, (unsigned char []){ 0x52, 0x54, 0x00 });
diff --git a/src/uml_conf.c b/src/uml_conf.c
index 48e05a8..4f756d4 100644
--- a/src/uml_conf.c
+++ b/src/uml_conf.c
@@ -45,6 +45,7 @@
#include "nodeinfo.h"
#include "verify.h"
#include "bridge.h"
+#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_UML
@@ -63,8 +64,14 @@ virCapsPtr umlCapsInit(void) {
0, 0)) == NULL)
goto no_memory;
- if (nodeCapsInitNUMA(caps) < 0)
- goto no_memory;
+ /* Some machines have problematic NUMA toplogy causing
+ * unexpected failures. We don't want to break the QEMU
+ * driver in this scenario, so log errors & carry on
+ */
+ if (nodeCapsInitNUMA(caps) < 0) {
+ virCapabilitiesFreeNUMAInfo(caps);
+ VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
+ }
if ((guest = virCapabilitiesAddGuest(caps,
"uml",
--
1.6.2.5
-505
View File
@@ -1,505 +0,0 @@
From d54fc5008d465d192101a0cb78fd02c437dff736 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 17 Aug 2009 08:32:08 +0100
Subject: [PATCH] Policykit rewrite (bug #499970)
Fedora-patch: libvirt-0.7.0-policy-kit-rewrite.patch
---
configure.in | 73 ++++++++++++++++++++++++++++--------------
qemud/Makefile.am | 11 +++++-
qemud/libvirtd.policy | 42 ------------------------
qemud/libvirtd.policy-0 | 42 ++++++++++++++++++++++++
qemud/libvirtd.policy-1 | 42 ++++++++++++++++++++++++
qemud/qemud.c | 4 +-
qemud/qemud.h | 4 +-
qemud/remote.c | 81 ++++++++++++++++++++++++++++++++++++++++++++--
src/remote_internal.c | 7 ++++
9 files changed, 230 insertions(+), 76 deletions(-)
delete mode 100644 qemud/libvirtd.policy
create mode 100644 qemud/libvirtd.policy-0
create mode 100644 qemud/libvirtd.policy-1
diff --git a/configure.in b/configure.in
index 45fa9ed..d28c44a 100644
--- a/configure.in
+++ b/configure.in
@@ -641,40 +641,61 @@ AC_SUBST([SASL_LIBS])
dnl PolicyKit library
POLKIT_CFLAGS=
POLKIT_LIBS=
+PKCHECK_PATH=
AC_ARG_WITH([polkit],
[ --with-polkit use PolicyKit for UNIX socket access checks],
[],
[with_polkit=check])
+with_polkit0=no
+with_polkit1=no
if test "x$with_polkit" = "xyes" -o "x$with_polkit" = "xcheck"; then
- PKG_CHECK_MODULES(POLKIT, polkit-dbus >= $POLKIT_REQUIRED,
- [with_polkit=yes], [
- if test "x$with_polkit" = "xcheck" ; then
- with_polkit=no
- else
- AC_MSG_ERROR(
- [You must install PolicyKit >= $POLKIT_REQUIRED to compile libvirt])
- fi
- ])
- if test "x$with_polkit" = "xyes" ; then
+ dnl Check for new polkit first - just a binary
+ AC_PATH_PROG([PKCHECK_PATH],[pkcheck], [], [/usr/sbin:$PATH])
+ if test "x$PKCHECK_PATH" != "x" ; then
+ AC_DEFINE_UNQUOTED([PKCHECK_PATH],["$PKCHECK_PATH"],[Location of pkcheck program])
AC_DEFINE_UNQUOTED([HAVE_POLKIT], 1,
- [use PolicyKit for UNIX socket access checks])
-
- old_CFLAGS=$CFLAGS
- old_LDFLAGS=$LDFLAGS
- CFLAGS="$CFLAGS $POLKIT_CFLAGS"
- LDFLAGS="$LDFLAGS $POLKIT_LIBS"
- AC_CHECK_FUNCS([polkit_context_is_caller_authorized])
- CFLAGS="$old_CFLAGS"
- LDFLAGS="$old_LDFLAGS"
-
- AC_PATH_PROG([POLKIT_AUTH], [polkit-auth])
- if test "x$POLKIT_AUTH" != "x"; then
- AC_DEFINE_UNQUOTED([POLKIT_AUTH],["$POLKIT_AUTH"],[Location of polkit-auth program])
+ [use PolicyKit for UNIX socket access checks])
+ AC_DEFINE_UNQUOTED([HAVE_POLKIT1], 1,
+ [use PolicyKit for UNIX socket access checks])
+ with_polkit="yes"
+ with_polkit1="yes"
+ else
+ dnl Check for old polkit second - library + binary
+ PKG_CHECK_MODULES(POLKIT, polkit-dbus >= $POLKIT_REQUIRED,
+ [with_polkit=yes], [
+ if test "x$with_polkit" = "xcheck" ; then
+ with_polkit=no
+ else
+ AC_MSG_ERROR(
+ [You must install PolicyKit >= $POLKIT_REQUIRED to compile libvirt])
+ fi
+ ])
+ if test "x$with_polkit" = "xyes" ; then
+ AC_DEFINE_UNQUOTED([HAVE_POLKIT], 1,
+ [use PolicyKit for UNIX socket access checks])
+ AC_DEFINE_UNQUOTED([HAVE_POLKIT0], 1,
+ [use PolicyKit for UNIX socket access checks])
+
+ old_CFLAGS=$CFLAGS
+ old_LDFLAGS=$LDFLAGS
+ CFLAGS="$CFLAGS $POLKIT_CFLAGS"
+ LDFLAGS="$LDFLAGS $POLKIT_LIBS"
+ AC_CHECK_FUNCS([polkit_context_is_caller_authorized])
+ CFLAGS="$old_CFLAGS"
+ LDFLAGS="$old_LDFLAGS"
+
+ AC_PATH_PROG([POLKIT_AUTH], [polkit-auth])
+ if test "x$POLKIT_AUTH" != "x"; then
+ AC_DEFINE_UNQUOTED([POLKIT_AUTH],["$POLKIT_AUTH"],[Location of polkit-auth program])
+ fi
+ with_polkit0="yes"
fi
fi
fi
AM_CONDITIONAL([HAVE_POLKIT], [test "x$with_polkit" = "xyes"])
+AM_CONDITIONAL([HAVE_POLKIT0], [test "x$with_polkit0" = "xyes"])
+AM_CONDITIONAL([HAVE_POLKIT1], [test "x$with_polkit1" = "xyes"])
AC_SUBST([POLKIT_CFLAGS])
AC_SUBST([POLKIT_LIBS])
@@ -1695,7 +1716,11 @@ else
AC_MSG_NOTICE([ avahi: no])
fi
if test "$with_polkit" = "yes" ; then
-AC_MSG_NOTICE([ polkit: $POLKIT_CFLAGS $POLKIT_LIBS])
+if test "$with_polkit0" = "yes" ; then
+AC_MSG_NOTICE([ polkit: $POLKIT_CFLAGS $POLKIT_LIBS (version 0)])
+else
+AC_MSG_NOTICE([ polkit: $PKCHECK_PATH (version 1)])
+fi
else
AC_MSG_NOTICE([ polkit: no])
fi
diff --git a/qemud/Makefile.am b/qemud/Makefile.am
index 959ff88..3d143da 100644
--- a/qemud/Makefile.am
+++ b/qemud/Makefile.am
@@ -21,7 +21,8 @@ EXTRA_DIST = \
remote_protocol.x \
libvirtd.conf \
libvirtd.init.in \
- libvirtd.policy \
+ libvirtd.policy-0 \
+ libvirtd.policy-1 \
libvirtd.sasl \
libvirtd.sysconf \
libvirtd.aug \
@@ -147,7 +148,13 @@ endif
libvirtd_LDADD += ../src/libvirt.la
if HAVE_POLKIT
+if HAVE_POLKIT0
policydir = $(datadir)/PolicyKit/policy
+policyfile = libvirtd.policy-0
+else
+policydir = $(datadir)/polkit-1/actions
+policyfile = libvirtd.policy-1
+endif
endif
if HAVE_AVAHI
@@ -197,7 +204,7 @@ endif
if HAVE_POLKIT
install-data-polkit:: install-init
mkdir -p $(DESTDIR)$(policydir)
- $(INSTALL_DATA) $(srcdir)/libvirtd.policy $(DESTDIR)$(policydir)/org.libvirt.unix.policy
+ $(INSTALL_DATA) $(srcdir)/$(policyfile) $(DESTDIR)$(policydir)/org.libvirt.unix.policy
uninstall-data-polkit:: install-init
rm -f $(DESTDIR)$(policydir)/org.libvirt.unix.policy
else
diff --git a/qemud/libvirtd.policy b/qemud/libvirtd.policy
deleted file mode 100644
index b6da946..0000000
--- a/qemud/libvirtd.policy
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
-
-<!--
-Policy definitions for libvirt daemon
-
-Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
-
-libvirt is licensed to you under the GNU Lesser General Public License
-version 2. See COPYING for details.
-
-NOTE: If you make changes to this file, make sure to validate the file
-using the polkit-policy-file-validate(1) tool. Changes made to this
-file are instantly applied.
--->
-
-<policyconfig>
- <action id="org.libvirt.unix.monitor">
- <description>Monitor local virtualized systems</description>
- <message>System policy prevents monitoring of local virtualized systems</message>
- <defaults>
- <!-- Any program can use libvirt in read-only mode for monitoring,
- even if not part of a session -->
- <allow_any>yes</allow_any>
- <allow_inactive>yes</allow_inactive>
- <allow_active>yes</allow_active>
- </defaults>
- </action>
-
- <action id="org.libvirt.unix.manage">
- <description>Manage local virtualized systems</description>
- <message>System policy prevents management of local virtualized systems</message>
- <defaults>
- <!-- Only a program in the active host session can use libvirt in
- read-write mode for management, and we require user password -->
- <allow_any>no</allow_any>
- <allow_inactive>no</allow_inactive>
- <allow_active>auth_admin_keep_session</allow_active>
- </defaults>
- </action>
-</policyconfig>
diff --git a/qemud/libvirtd.policy-0 b/qemud/libvirtd.policy-0
new file mode 100644
index 0000000..b6da946
--- /dev/null
+++ b/qemud/libvirtd.policy-0
@@ -0,0 +1,42 @@
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<!--
+Policy definitions for libvirt daemon
+
+Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
+
+libvirt is licensed to you under the GNU Lesser General Public License
+version 2. See COPYING for details.
+
+NOTE: If you make changes to this file, make sure to validate the file
+using the polkit-policy-file-validate(1) tool. Changes made to this
+file are instantly applied.
+-->
+
+<policyconfig>
+ <action id="org.libvirt.unix.monitor">
+ <description>Monitor local virtualized systems</description>
+ <message>System policy prevents monitoring of local virtualized systems</message>
+ <defaults>
+ <!-- Any program can use libvirt in read-only mode for monitoring,
+ even if not part of a session -->
+ <allow_any>yes</allow_any>
+ <allow_inactive>yes</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.libvirt.unix.manage">
+ <description>Manage local virtualized systems</description>
+ <message>System policy prevents management of local virtualized systems</message>
+ <defaults>
+ <!-- Only a program in the active host session can use libvirt in
+ read-write mode for management, and we require user password -->
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep_session</allow_active>
+ </defaults>
+ </action>
+</policyconfig>
diff --git a/qemud/libvirtd.policy-1 b/qemud/libvirtd.policy-1
new file mode 100644
index 0000000..6fa3a5e
--- /dev/null
+++ b/qemud/libvirtd.policy-1
@@ -0,0 +1,42 @@
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<!--
+Policy definitions for libvirt daemon
+
+Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
+
+libvirt is licensed to you under the GNU Lesser General Public License
+version 2. See COPYING for details.
+
+NOTE: If you make changes to this file, make sure to validate the file
+using the polkit-policy-file-validate(1) tool. Changes made to this
+file are instantly applied.
+-->
+
+<policyconfig>
+ <action id="org.libvirt.unix.monitor">
+ <description>Monitor local virtualized systems</description>
+ <message>System policy prevents monitoring of local virtualized systems</message>
+ <defaults>
+ <!-- Any program can use libvirt in read-only mode for monitoring,
+ even if not part of a session -->
+ <allow_any>yes</allow_any>
+ <allow_inactive>yes</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.libvirt.unix.manage">
+ <description>Manage local virtualized systems</description>
+ <message>System policy prevents management of local virtualized systems</message>
+ <defaults>
+ <!-- Only a program in the active host session can use libvirt in
+ read-write mode for management, and we require user password -->
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+</policyconfig>
diff --git a/qemud/qemud.c b/qemud/qemud.c
index 3e551ca..50b0cdd 100644
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -895,7 +895,7 @@ static struct qemud_server *qemudNetworkInit(struct qemud_server *server) {
}
#endif
-#ifdef HAVE_POLKIT
+#if HAVE_POLKIT0
if (auth_unix_rw == REMOTE_AUTH_POLKIT ||
auth_unix_ro == REMOTE_AUTH_POLKIT) {
DBusError derr;
@@ -982,7 +982,7 @@ static struct qemud_server *qemudNetworkInit(struct qemud_server *server) {
sock = sock->next;
}
-#ifdef HAVE_POLKIT
+#if HAVE_POLKIT0
if (server->sysbus)
dbus_connection_unref(server->sysbus);
#endif
diff --git a/qemud/qemud.h b/qemud/qemud.h
index 254db44..e8ce209 100644
--- a/qemud/qemud.h
+++ b/qemud/qemud.h
@@ -34,7 +34,7 @@
#include <sasl/sasl.h>
#endif
-#ifdef HAVE_POLKIT
+#if HAVE_POLKIT0
#include <dbus/dbus.h>
#endif
@@ -253,7 +253,7 @@ struct qemud_server {
#if HAVE_SASL
char **saslUsernameWhitelist;
#endif
-#if HAVE_POLKIT
+#if HAVE_POLKIT0
DBusConnection *sysbus;
#endif
};
diff --git a/qemud/remote.c b/qemud/remote.c
index d32d513..490a807 100644
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -43,7 +43,7 @@
#include <fnmatch.h>
#include "virterror_internal.h"
-#ifdef HAVE_POLKIT
+#if HAVE_POLKIT0
#include <polkit/polkit.h>
#include <polkit-dbus/polkit-dbus.h>
#endif
@@ -3106,7 +3106,80 @@ remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
#endif /* HAVE_SASL */
-#if HAVE_POLKIT
+#if HAVE_POLKIT1
+static int
+remoteDispatchAuthPolkit (struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ void *args ATTRIBUTE_UNUSED,
+ remote_auth_polkit_ret *ret)
+{
+ pid_t callerPid;
+ uid_t callerUid;
+ const char *action;
+ int status = -1;
+ char pidbuf[50];
+ int rv;
+
+ virMutexLock(&server->lock);
+ virMutexLock(&client->lock);
+ virMutexUnlock(&server->lock);
+
+ action = client->readonly ?
+ "org.libvirt.unix.monitor" :
+ "org.libvirt.unix.manage";
+
+ const char * const pkcheck [] = {
+ PKCHECK_PATH,
+ "--action-id", action,
+ "--process", pidbuf,
+ "--allow-user-interaction",
+ NULL
+ };
+
+ REMOTE_DEBUG("Start PolicyKit auth %d", client->fd);
+ if (client->auth != REMOTE_AUTH_POLKIT) {
+ VIR_ERROR0(_("client tried invalid PolicyKit init request"));
+ goto authfail;
+ }
+
+ if (qemudGetSocketIdentity(client->fd, &callerUid, &callerPid) < 0) {
+ VIR_ERROR0(_("cannot get peer socket identity"));
+ goto authfail;
+ }
+
+ VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
+
+ rv = snprintf(pidbuf, sizeof pidbuf, "%d", callerPid);
+ if (rv < 0 || rv >= sizeof pidbuf) {
+ VIR_ERROR(_("Caller PID was too large %d"), callerPid);
+ goto authfail;
+ }
+
+ if (virRun(NULL, pkcheck, &status) < 0) {
+ VIR_ERROR(_("Cannot invoke %s"), PKCHECK_PATH);
+ goto authfail;
+ }
+ if (status != 0) {
+ VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %d\n"),
+ action, callerPid, callerUid, status);
+ goto authfail;
+ }
+ VIR_INFO(_("Policy allowed action %s from pid %d, uid %d"),
+ action, callerPid, callerUid);
+ ret->complete = 1;
+ client->auth = REMOTE_AUTH_NONE;
+
+ virMutexUnlock(&client->lock);
+ return 0;
+
+authfail:
+ remoteDispatchAuthError(rerr);
+ virMutexUnlock(&client->lock);
+ return -1;
+}
+#elif HAVE_POLKIT0
static int
remoteDispatchAuthPolkit (struct qemud_server *server,
struct qemud_client *client,
@@ -3217,7 +3290,7 @@ authfail:
return -1;
}
-#else /* HAVE_POLKIT */
+#else /* !HAVE_POLKIT0 & !HAVE_POLKIT1*/
static int
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
@@ -3231,7 +3304,7 @@ remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
remoteDispatchAuthError(rerr);
return -1;
}
-#endif /* HAVE_POLKIT */
+#endif /* HAVE_POLKIT1 */
/***************************************************************
diff --git a/src/remote_internal.c b/src/remote_internal.c
index a58b768..e98c99b 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -6201,6 +6201,7 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
virConnectAuthPtr auth)
{
remote_auth_polkit_ret ret;
+#if HAVE_POLKIT0
int i, allowcb = 0;
virConnectCredential cred = {
VIR_CRED_EXTERNAL,
@@ -6210,8 +6211,10 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
NULL,
0,
};
+#endif
DEBUG0("Client initialize PolicyKit authentication");
+#if HAVE_POLKIT0
if (auth && auth->cb) {
/* Check if the necessary credential type for PolicyKit is supported */
for (i = 0 ; i < auth->ncredtype ; i++) {
@@ -6220,6 +6223,7 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
}
if (allowcb) {
+ DEBUG0("Client run callback for PolicyKit authentication");
/* Run the authentication callback */
if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
@@ -6233,6 +6237,9 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
} else {
DEBUG0("No auth callback provided");
}
+#else
+ DEBUG0("No auth callback required for PolicyKit-1");
+#endif
memset (&ret, 0, sizeof ret);
if (call (conn, priv, in_open, REMOTE_PROC_AUTH_POLKIT,
--
1.6.2.5
+163
View File
@@ -0,0 +1,163 @@
commit 377bc412ce10845930346744e30fe9c4790e5e63
Author: Cole Robinson <crobinso@redhat.com>
Date: Wed May 19 16:03:52 2010 -0400
daemon: Export SDL audio environment variables
/etc/sysconfig/libvirtd has a few environment variables for configuring
libvirt SDL audio. The libvirtd process doesn't see these, however, because
they are never exported. Let's export the variables after sourcing the
sysconfig script.
There is another problem here that the commented out values in the
sysconfig script are not neccessarily the actual defaults, we are qemus
mercy here. Not sure how to solve that.
diff --git a/daemon/libvirtd.init.in b/daemon/libvirtd.init.in
index 809433e..aa7870c 100644
--- a/daemon/libvirtd.init.in
+++ b/daemon/libvirtd.init.in
@@ -45,6 +45,9 @@ KRB5_KTNAME=/etc/libvirt/krb5.tab
test -f @sysconfdir@/sysconfig/libvirtd && . @sysconfdir@/sysconfig/libvirtd
+export QEMU_AUDIO_DRV
+export SDL_AUDIODRIVER
+
LIBVIRTD_CONFIG_ARGS=
if [ -n "$LIBVIRTD_CONFIG" ]
then
commit 7f44743c524faa493d05eaf026f1e90a807e502b
Author: Cole Robinson <crobinso@redhat.com>
Date: Wed May 26 10:51:36 2010 -0400
daemon: sysconf: Update comment about VNC audio
diff --git a/daemon/libvirtd.sysconf b/daemon/libvirtd.sysconf
index 28080a0..b730c5e 100644
--- a/daemon/libvirtd.sysconf
+++ b/daemon/libvirtd.sysconf
@@ -11,7 +11,8 @@
# Override the QEMU/SDL default audio driver probing when
# starting virtual machines using SDL graphics
#
-# NB these have no effect for VMs using VNC
+# NB these have no effect for VMs using VNC, unless vnc_allow_host_audio
+# is enabled in /etc/libvirt/qemu.conf
#QEMU_AUDIO_DRV=sdl
#
#SDL_AUDIODRIVER=pulse
commit fb3ebd0397980ae035e66f0008b09e13377ef80f
Author: Cole Robinson <crobinso@redhat.com>
Date: Wed May 19 16:41:01 2010 -0400
qemu: Allow using regular audio backends with VNC
Currently all host audio backends are disabled if a VM is using VNC, in
favor of the QEMU VNC audio extension. Unfortunately no released VNC
client supports this extension, so users have no way of getting audio
to work if using VNC.
Add a new config option in qemu.conf which allows changing libvirt's
behavior, but keep the default intact.
v2: Fix doc typos, change name to vnc_allow_host_audio
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 5bd60b3..551cc20 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -38,6 +38,7 @@ module Libvirtd_qemu =
| str_entry "save_image_format"
| str_entry "hugetlbfs_mount"
| bool_entry "relaxed_acs_check"
+ | bool_entry "vnc_allow_host_audio"
(* Each enty in the config is one of the following three ... *)
let entry = vnc_entry
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 3da332f..98a1176 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -168,3 +168,13 @@
# be assigned to guests.
#
# relaxed_acs_check = 1
+
+
+# QEMU implements an extension for providing audio over a VNC connection,
+# though if your VNC client does not support it, your only chance for getting
+# sound output is through regular audio backends. By default, libvirt will
+# disable all QEMU sound backends if using VNC, since they can cause
+# permissions issues. Enabling this option will make libvirtd honor the
+# QEMU_AUDIO_DRV environment variable when using VNC.
+#
+# vnc_allow_host_audio = 0
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 2755545..b4d8e74 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -351,6 +351,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
CHECK_TYPE ("relaxed_acs_check", VIR_CONF_LONG);
if (p) driver->relaxedACS = p->l;
+ p = virConfGetValue (conf, "vnc_allow_host_audio");
+ CHECK_TYPE ("vnc_allow_host_audio", VIR_CONF_LONG);
+ if (p) driver->vncAllowHostAudio = p->l;
+
virConfFree (conf);
return 0;
}
@@ -4399,12 +4403,15 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT(def->graphics[0]->data.vnc.keymap);
}
- /* QEMU implements a VNC extension for providing audio, so we
- * set the audio backend to none, to prevent it opening the
- * host OS audio devices since that causes security issues
- * and is non-sensical when using VNC.
+ /* Unless user requested it, set the audio backend to none, to
+ * prevent it opening the host OS audio devices, since that causes
+ * security issues and might not work when using VNC.
*/
- ADD_ENV_LIT("QEMU_AUDIO_DRV=none");
+ if (driver->vncAllowHostAudio) {
+ ADD_ENV_COPY("QEMU_AUDIO_DRV");
+ } else {
+ ADD_ENV_LIT("QEMU_AUDIO_DRV=none");
+ }
} else if ((def->ngraphics == 1) &&
def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
char *xauth = NULL;
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 8fd8d79..7fb4de5 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -138,6 +138,8 @@ struct qemud_driver {
unsigned int relaxedACS : 1;
+ unsigned int vncAllowHostAudio : 1;
+
virCapsPtr caps;
/* An array of callbacks */
diff --git a/src/qemu/test_libvirtd_qemu.aug b/src/qemu/test_libvirtd_qemu.aug
index 2feedc0..a048ae5 100644
--- a/src/qemu/test_libvirtd_qemu.aug
+++ b/src/qemu/test_libvirtd_qemu.aug
@@ -97,6 +97,8 @@ save_image_format = \"gzip\"
hugetlbfs_mount = \"/dev/hugepages\"
relaxed_acs_check = 1
+
+vnc_allow_host_audio = 1
"
test Libvirtd_qemu.lns get conf =
@@ -204,3 +206,5 @@ relaxed_acs_check = 1
{ "hugetlbfs_mount" = "/dev/hugepages" }
{ "#empty" }
{ "relaxed_acs_check" = "1" }
+{ "#empty" }
+{ "vnc_allow_host_audio" = "1" }
+110
View File
@@ -0,0 +1,110 @@
diff -rup libvirt-0.7.7/src/qemu/libvirtd_qemu.aug new/src/qemu/libvirtd_qemu.aug
--- libvirt-0.7.7/src/qemu/libvirtd_qemu.aug 2010-06-17 12:38:52.998946000 -0400
+++ new/src/qemu/libvirtd_qemu.aug 2010-06-17 12:39:28.504148000 -0400
@@ -39,6 +39,7 @@ module Libvirtd_qemu =
| str_entry "hugetlbfs_mount"
| bool_entry "relaxed_acs_check"
| bool_entry "vnc_allow_host_audio"
+ | bool_entry "clear_emulator_capabilities"
(* Each enty in the config is one of the following three ... *)
let entry = vnc_entry
diff -rup libvirt-0.7.7/src/qemu/qemu.conf new/src/qemu/qemu.conf
--- libvirt-0.7.7/src/qemu/qemu.conf 2010-06-17 12:38:53.001953000 -0400
+++ new/src/qemu/qemu.conf 2010-06-17 12:39:28.508149000 -0400
@@ -178,3 +178,12 @@
# QEMU_AUDIO_DRV environment variable when using VNC.
#
# vnc_allow_host_audio = 0
+
+# If clear_emulator_capabilities is enabled, libvirt will drop all
+# privileged capabilities of the QEmu/KVM emulator. This is enabled by
+# default.
+#
+# Warning: Disabling this option means that a compromised guest can
+# exploit the privileges and possibly do damage to the host.
+#
+# clear_emulator_capabilities = 1
diff -rup libvirt-0.7.7/src/qemu/qemu_conf.c new/src/qemu/qemu_conf.c
--- libvirt-0.7.7/src/qemu/qemu_conf.c 2010-06-17 12:38:53.010946000 -0400
+++ new/src/qemu/qemu_conf.c 2010-06-17 12:39:28.526151000 -0400
@@ -103,6 +103,7 @@ int qemudLoadDriverConfig(struct qemud_d
/* Setup critical defaults */
driver->dynamicOwnership = 1;
+ driver->clearEmulatorCapabilities = 1;
if (!(driver->vncListen = strdup("127.0.0.1"))) {
virReportOOMError();
@@ -354,6 +355,10 @@ int qemudLoadDriverConfig(struct qemud_d
CHECK_TYPE ("vnc_allow_host_audio", VIR_CONF_LONG);
if (p) driver->vncAllowHostAudio = p->l;
+ p = virConfGetValue (conf, "clear_emulator_capabilities");
+ CHECK_TYPE ("clear_emulator_capabilities", VIR_CONF_LONG);
+ if (p) driver->clearEmulatorCapabilities = p->l;
+
virConfFree (conf);
return 0;
}
diff -rup libvirt-0.7.7/src/qemu/qemu_conf.h new/src/qemu/qemu_conf.h
--- libvirt-0.7.7/src/qemu/qemu_conf.h 2010-06-17 12:38:53.015945000 -0400
+++ new/src/qemu/qemu_conf.h 2010-06-17 12:39:28.531146000 -0400
@@ -129,8 +129,8 @@ struct qemud_driver {
ebtablesContext *ebtables;
unsigned int relaxedACS : 1;
-
unsigned int vncAllowHostAudio : 1;
+ unsigned int clearEmulatorCapabilities : 1;
virCapsPtr caps;
diff -rup libvirt-0.7.7/src/qemu/qemu_driver.c new/src/qemu/qemu_driver.c
--- libvirt-0.7.7/src/qemu/qemu_driver.c 2010-06-17 12:38:52.988953000 -0400
+++ new/src/qemu/qemu_driver.c 2010-06-17 12:39:28.542147000 -0400
@@ -2699,7 +2699,7 @@ static int qemudStartVMDaemon(virConnect
int stdin_fd) {
const char **argv = NULL, **tmp;
const char **progenv = NULL;
- int i, ret;
+ int i, ret, runflags;
struct stat sb;
int *tapfds = NULL;
int ntapfds = 0;
@@ -2893,9 +2893,16 @@ static int qemudStartVMDaemon(virConnect
for (i = 0 ; i < ntapfds ; i++)
FD_SET(tapfds[i], &keepfd);
+ VIR_DEBUG("Clear emulator capabilities: %d",
+ driver->clearEmulatorCapabilities);
+ runflags = VIR_EXEC_NONBLOCK;
+ if (driver->clearEmulatorCapabilities) {
+ runflags |= VIR_EXEC_CLEAR_CAPS;
+ }
+
ret = virExecDaemonize(argv, progenv, &keepfd, &child,
stdin_fd, &logfile, &logfile,
- VIR_EXEC_NONBLOCK | VIR_EXEC_CLEAR_CAPS,
+ runflags,
qemudSecurityHook, &hookData,
pidfile);
VIR_FREE(pidfile);
diff -rup libvirt-0.7.7/src/qemu/test_libvirtd_qemu.aug new/src/qemu/test_libvirtd_qemu.aug
--- libvirt-0.7.7/src/qemu/test_libvirtd_qemu.aug 2010-06-17 12:38:53.018948000 -0400
+++ new/src/qemu/test_libvirtd_qemu.aug 2010-06-17 12:39:28.546145000 -0400
@@ -99,6 +99,8 @@ hugetlbfs_mount = \"/dev/hugepages\"
relaxed_acs_check = 1
vnc_allow_host_audio = 1
+
+clear_emulator_capabilities = 0
"
test Libvirtd_qemu.lns get conf =
@@ -208,3 +210,5 @@ vnc_allow_host_audio = 1
{ "relaxed_acs_check" = "1" }
{ "#empty" }
{ "vnc_allow_host_audio" = "1" }
+{ "#empty" }
+{ "clear_emulator_capabilities" = "0" }
+132
View File
@@ -0,0 +1,132 @@
commit c4896d378b921ba6471562d7b17641be121c19d6
Author: Daniel P. Berrange <berrange@redhat.com>
Date: Thu Apr 15 11:35:07 2010 +0100
Fix CDROM media change for QEMU when using -device syntax
Disk devices in QEMU have two parts, the guest device and the host
backend driver. Historically these two parts have had the same
"unique" name. With the switch to using -device though, they now
have separate names. Thus when changing CDROM media, for guests
using -device syntax, we need to prepend the QEMU_DRIVE_HOST_PREFIX
constant
* src/qemu/qemu_conf.c, src/qemu/qemu_conf.h: Add helper function
qemuDeviceDriveHostAlias() for building a host backend alias
* src/qemu/qemu_driver.c: Use qemuDeviceDriveHostAlias() to determine
the host backend alias for performing eject/change commands in the
monitor
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 1a8b4aa..0cbedf2 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1699,6 +1699,26 @@ static int qemuAssignDeviceDiskAliasLegacy(virDomainDiskDefPtr disk)
}
+char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
+ unsigned long long qemudCmdFlags)
+{
+ char *ret;
+
+ if (qemudCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+ if (virAsprintf(&ret, "%s%s", QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+ } else {
+ if (!(ret = strdup(disk->info.alias))) {
+ virReportOOMError();
+ return NULL;
+ }
+ }
+ return ret;
+}
+
+
/* Names used before -drive supported the id= option */
static int qemuAssignDeviceDiskAliasFixed(virDomainDiskDefPtr disk)
{
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 574709e..b2820f0 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -220,6 +220,9 @@ char * qemuBuildNicStr(virDomainNetDefPtr net,
char * qemuBuildNicDevStr(virDomainNetDefPtr net,
int vlan);
+char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
+ unsigned long long qemudCmdFlags);
+
/* Both legacy & current support */
char *qemuBuildDriveStr(virDomainDiskDefPtr disk,
int bootable,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0189dcf..7d2f3ef 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6552,11 +6552,13 @@ cleanup:
static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
virDomainObjPtr vm,
- virDomainDiskDefPtr disk)
+ virDomainDiskDefPtr disk,
+ unsigned long long qemuCmdFlags)
{
virDomainDiskDefPtr origdisk = NULL;
int i;
int ret;
+ char *driveAlias = NULL;
origdisk = NULL;
for (i = 0 ; i < vm->def->ndisks ; i++) {
@@ -6594,6 +6596,9 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
driver->securityDriver->domainSetSecurityImageLabel(vm, disk) < 0)
return -1;
+ if (!(driveAlias = qemuDeviceDriveHostAlias(origdisk, qemuCmdFlags)))
+ goto error;
+
qemuDomainObjPrivatePtr priv = vm->privateData;
qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (disk->src) {
@@ -6605,10 +6610,10 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
format = origdisk->driverType;
}
ret = qemuMonitorChangeMedia(priv->mon,
- origdisk->info.alias,
+ driveAlias,
disk->src, format);
} else {
- ret = qemuMonitorEjectMedia(priv->mon, origdisk->info.alias);
+ ret = qemuMonitorEjectMedia(priv->mon, driveAlias);
}
qemuDomainObjExitMonitorWithDriver(driver, vm);
@@ -6625,11 +6630,14 @@ static int qemudDomainChangeEjectableMedia(struct qemud_driver *driver,
disk->src = NULL;
origdisk->type = disk->type;
+ VIR_FREE(driveAlias);
+
virDomainDiskDefFree(disk);
return ret;
error:
+ VIR_FREE(driveAlias);
if (driver->securityDriver &&
driver->securityDriver->domainRestoreSecurityImageLabel &&
driver->securityDriver->domainRestoreSecurityImageLabel(vm, disk) < 0)
@@ -7434,7 +7442,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
- ret = qemudDomainChangeEjectableMedia(driver, vm, dev->data.disk);
+ ret = qemudDomainChangeEjectableMedia(driver, vm,
+ dev->data.disk,
+ qemuCmdFlags);
if (ret == 0)
dev->data.disk = NULL;
break;
+41
View File
@@ -0,0 +1,41 @@
From e3c36a2575bc88a16d776693dc39ea01c780b406 Mon Sep 17 00:00:00 2001
From: Jiri Denemark <jdenemar@redhat.com>
Date: Tue, 16 Mar 2010 16:03:59 +0100
Subject: [PATCH] Use fsync() at the end of file allocation instead of O_DSYNC
Instead of opening storage file with O_DSYNC, make sure data are written
to a disk only before we claim allocation has finished.
---
src/storage/storage_backend.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index ec9fc43..7294a00 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -331,6 +331,13 @@ static int createRawFileOpHook(int fd, void *data) {
goto cleanup;
}
}
+
+ if (fsync(fd) < 0) {
+ ret = errno;
+ virReportSystemError(errno, _("cannot sync data to file '%s'"),
+ hdata->vol->target.path);
+ goto cleanup;
+ }
}
cleanup:
@@ -359,7 +366,7 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
gid_t gid = (vol->target.perms.gid == -1) ? getgid() : vol->target.perms.gid;
if ((createstat = virFileOperation(vol->target.path,
- O_RDWR | O_CREAT | O_EXCL | O_DSYNC,
+ O_RDWR | O_CREAT | O_EXCL,
vol->target.perms.mode, uid, gid,
createRawFileOpHook, &hdata,
VIR_FILE_OP_FORCE_PERMS |
--
1.6.6.1
+12
View File
@@ -0,0 +1,12 @@
diff -rup libvirt-0.7.1/src/util/hostusb.c new/src/hostusb.c
--- libvirt-0.7.1/src/util/hostusb.c 2010-06-03 13:51:14.392459000 -0400
+++ new/src/util/hostusb.c 2010-06-03 14:49:11.763379000 -0400
@@ -123,7 +123,7 @@ static int usbFindBusByVendor(virConnect
char *tmpstr = de->d_name;
unsigned found_bus, found_addr;
- if (STREQ(de->d_name, "usb"))
+ if (STRPREFIX(de->d_name, "usb"))
tmpstr += 3;
if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
+233
View File
@@ -0,0 +1,233 @@
From 3a441522017aa9c1b8b54d2ce4569d0f0d96fa72 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Fri, 12 Mar 2010 12:36:56 -0500
Subject: [PATCH] qemu: Add some debugging at domain startup
---
src/qemu/qemu_driver.c | 24 +++++++++++++++++++++++-
1 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f8ab545..040d645 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2695,6 +2695,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
FD_ZERO(&keepfd);
+ DEBUG0("Beginning VM startup process");
+
if (virDomainObjIsActive(vm)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("VM is already active"));
@@ -2703,22 +2705,27 @@ static int qemudStartVMDaemon(virConnectPtr conn,
/* If you are using a SecurityDriver with dynamic labelling,
then generate a security label for isolation */
+ DEBUG0("Generating domain security label (if required)");
if (driver->securityDriver &&
driver->securityDriver->domainGenSecurityLabel &&
driver->securityDriver->domainGenSecurityLabel(vm) < 0)
return -1;
+ DEBUG0("Generating setting domain security labels (if required)");
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityAllLabel &&
driver->securityDriver->domainSetSecurityAllLabel(vm) < 0)
goto cleanup;
- /* Ensure no historical cgroup for this VM is lieing around bogus settings */
+ /* Ensure no historical cgroup for this VM is lying around bogus
+ * settings */
+ DEBUG0("Ensuring no historical cgroup is lying around");
qemuRemoveCgroup(driver, vm, 1);
if ((vm->def->ngraphics == 1) &&
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics[0]->data.vnc.autoport) {
+ DEBUG0("Determining VNC port");
int port = qemudNextFreeVNCPort(driver);
if (port < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -2735,6 +2742,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
goto cleanup;
}
+ DEBUG0("Creating domain log file");
if ((logfile = qemudLogFD(driver, vm->def->name)) < 0)
goto cleanup;
@@ -2751,14 +2759,17 @@ static int qemudStartVMDaemon(virConnectPtr conn,
goto cleanup;
}
+ DEBUG0("Determing emulator version");
if (qemudExtractVersionInfo(emulator,
NULL,
&qemuCmdFlags) < 0)
goto cleanup;
+ DEBUG0("Setting up domain cgroup (if required)");
if (qemuSetupCgroup(driver, vm) < 0)
goto cleanup;
+ DEBUG0("Preparing host devices");
if (qemuPrepareHostDevices(driver, vm->def) < 0)
goto cleanup;
@@ -2767,6 +2778,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
goto cleanup;
}
+ DEBUG0("Preparing monitor state");
if (qemuPrepareMonitorChr(driver, priv->monConfig, vm->def->name) < 0)
goto cleanup;
@@ -2798,6 +2810,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
* use in hotplug
*/
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+ DEBUG0("Assigning domain PCI addresses");
/* Populate cache with current addresses */
if (priv->pciaddrs) {
qemuDomainPCIAddressSetFree(priv->pciaddrs);
@@ -2816,6 +2829,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
priv->persistentAddrs = 0;
}
+ DEBUG0("Building emulator command line");
vm->def->id = driver->nextvmid++;
if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
priv->monJSON, qemuCmdFlags, &argv, &progenv,
@@ -2899,25 +2913,31 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (ret == -1) /* The VM failed to start */
goto cleanup;
+ DEBUG0("Waiting for monitor to show up");
if (qemudWaitForMonitor(driver, vm, pos) < 0)
goto abort;
+ DEBUG0("Detecting VCPU PIDs");
if (qemuDetectVcpuPIDs(driver, vm) < 0)
goto abort;
+ DEBUG0("Setting CPU affinity");
if (qemudInitCpuAffinity(vm) < 0)
goto abort;
+ DEBUG0("Setting any required VM passwords");
if (qemuInitPasswords(conn, driver, vm, qemuCmdFlags) < 0)
goto abort;
/* If we have -device, then addresses are assigned explicitly.
* If not, then we have to detect dynamic ones here */
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+ DEBUG0("Determining domain device PCI addresses");
if (qemuInitPCIAddresses(driver, vm) < 0)
goto abort;
}
+ DEBUG0("Setting initial memory amount");
qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (qemuMonitorSetBalloon(priv->mon, vm->def->memory) < 0) {
qemuDomainObjExitMonitorWithDriver(driver, vm);
@@ -2925,6 +2945,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
}
if (migrateFrom == NULL) {
+ DEBUG0("Starting domain CPUs");
/* Allow the CPUS to start executing */
if (qemuMonitorStartCPUs(priv->mon, conn) < 0) {
if (virGetLastError() == NULL)
@@ -2937,6 +2958,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
qemuDomainObjExitMonitorWithDriver(driver, vm);
+ DEBUG0("Writing domain status to disk");
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
goto abort;
--
1.6.6.1
From 6d5c8a8f51db8ce97ab35ab6022dd5c94ab016b4 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Fri, 12 Mar 2010 12:37:52 -0500
Subject: [PATCH] qemu: Fix USB by product with security enabled
We need to call PrepareHostdevs to determine the USB device path before
any security calls. PrepareHostUSBDevices was also incorrectly skipping
all USB devices.
---
src/qemu/qemu_driver.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 040d645..b17d26d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2360,7 +2360,7 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver ATTRIBUTE_UNUSED,
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
continue;
/* Resolve a vendor/product to bus/device */
@@ -2703,6 +2703,11 @@ static int qemudStartVMDaemon(virConnectPtr conn,
return -1;
}
+ /* Must be run before security labelling */
+ DEBUG0("Preparing host devices");
+ if (qemuPrepareHostDevices(driver, vm->def) < 0)
+ goto cleanup;
+
/* If you are using a SecurityDriver with dynamic labelling,
then generate a security label for isolation */
DEBUG0("Generating domain security label (if required)");
@@ -2769,10 +2774,6 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (qemuSetupCgroup(driver, vm) < 0)
goto cleanup;
- DEBUG0("Preparing host devices");
- if (qemuPrepareHostDevices(driver, vm->def) < 0)
- goto cleanup;
-
if (VIR_ALLOC(priv->monConfig) < 0) {
virReportOOMError();
goto cleanup;
--
1.6.6.1
From 65e97240e6e4606820dd1c42ac172319e0af4d8d Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Mon, 22 Mar 2010 10:45:36 -0400
Subject: [PATCH] security: selinux: Fix crash when releasing non-existent label
This can be triggered by the qemuStartVMDaemon cleanup path if a
VM references a non-existent USB device (by product) in the XML.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
src/security/security_selinux.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 975b315..6680e2d 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -632,7 +632,8 @@ SELinuxReleaseSecurityLabel(virDomainObjPtr vm)
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
- if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
+ if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC ||
+ secdef->label == NULL)
return 0;
context_t con = context_new(secdef->label);
--
1.6.6.1
+35
View File
@@ -0,0 +1,35 @@
commit 9d0adf249827dde9e1c0d1c19513cf6018ceb34e
Author: Cole Robinson <crobinso@redhat.com>
Date: Wed May 19 15:57:56 2010 -0400
daemon: A few initscript corrections
Fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=565238
- Avahi service is called 'avahi-daemon'
- chkconfig descriptions must use \ for line continuations
diff --git a/daemon/libvirtd.init.in b/daemon/libvirtd.init.in
index d4dc98b..809433e 100644
--- a/daemon/libvirtd.init.in
+++ b/daemon/libvirtd.init.in
@@ -9,7 +9,7 @@
# Should-Start: $named
# Should-Start: xend
# Should-Start: hal
-# Should-Start: avahi
+# Should-Start: avahi-daemon
# Required-Stop: $network messagebus
# Should-Stop: $named
# Default-Start: 3 4 5
@@ -24,8 +24,8 @@
# libvirtd: guest and virtual network management daemon
#
# chkconfig: 345 97 03
-# description: This is a daemon for managing guest instances
-# and libvirt virtual networks
+# description: This is a daemon for managing guest instances \
+# and libvirt virtual networks \
# See http://libvirt.org
#
# processname: libvirtd
+65
View File
@@ -0,0 +1,65 @@
commit e5f31f461f63bbad211e84b810d6ba43a705f9dd
Author: Justin Clift <justin@salasaga.org>
Date: Sun May 30 13:28:42 2010 +1000
Trivial virsh.pod additions --all for "list" command and similar
This is just a trivial patch to virsh.pod (from git master). It adds the
following pieces to the virsh man page:
+ Shows the --inactive and --all optional parameters for the list
command.
Closes Bugzilla #575512, reported by Renich Bon Ciric
https://bugzilla.redhat.com/show_bug.cgi?id=575512
+ Corrects the existing description of the list command, to now say
that only running domains are listed if no domains are specified.
The man page up until this point has said all domains are listed if
no domains are specified, which is incorrect.
+ Adds the "shut off" state to the list of states for the list
command.
+ Adds a missing =back around line 755, that pod2man was complaining
was missing.
diff --git a/tools/virsh.pod b/tools/virsh.pod
index cf7585d..495bb46 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -156,10 +156,10 @@ description see:
L<http://libvirt.org/formatcaps.html>
The XML also show the NUMA topology information if available.
-=item B<list>
+=item B<list> optional I<--inactive> I<--all>
Prints information about one or more domains. If no domains are
-specified it prints out information about all domains.
+specified it prints out information about running domains.
An example format for the list is as follows:
@@ -177,7 +177,7 @@ State is the run state (see below).
B<STATES>
-The State field lists 6 states for a domain, and which ones the
+The State field lists 7 states for a domain, and which ones the
current domain is in.
=over 4
@@ -205,6 +205,11 @@ The domain is in the process of shutting down, i.e. the guest operating system
has been notified and should be in the process of stopping its operations
gracefully.
+=item B<shut off>
+
+The domain is not running. Usually this indicates the domain has been
+shut down completely, or has not been started.
+
=item B<crashed>
The domain has crashed, which is always a violent ending. Usually
+169
View File
@@ -0,0 +1,169 @@
commit a83fe2c23efad190a1e00e448f607fe032650fd6
Author: Cole Robinson <crobinso@redhat.com>
Date: Thu May 20 19:31:16 2010 -0400
network: bridge: Don't start network if it collides with host routing
Fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=235961
If using the default virtual network, an easy way to lose guest network
connectivity is to install libvirt inside the VM. The autostarted
default network inside the guest collides with host virtual network
routing. This is a long standing issue that has caused users quite a
bit of pain and confusion.
On network startup, parse /proc/net/route and compare the requested
IP+netmask against host routing destinations: if any matches are found,
refuse to start the network.
v2: Drop sscanf, fix a comment typo, comment that function could use
libnl instead of /proc
v3: Consider route netmask. Compare binary data rather than convert to
string.
v4: Return to using sscanf, drop inet functions in favor of virSocket,
parsing safety checks. Don't make parse failures fatal, in case
expected format changes.
v5: Try and continue if we receive unexpected. Delimit parsed lines to
prevent scanning past newline
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 5d7ef19..7ab3f3e 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -57,6 +57,7 @@
#include "iptables.h"
#include "bridge.h"
#include "logging.h"
+#include "util/network.h"
#define NETWORK_PID_DIR LOCAL_STATE_DIR "/run/libvirt/network"
#define NETWORK_STATE_DIR LOCAL_STATE_DIR "/lib/libvirt/network"
@@ -908,6 +909,114 @@ cleanup:
return ret;
}
+#define PROC_NET_ROUTE "/proc/net/route"
+
+/* XXX: This function can be a lot more exhaustive, there are certainly
+ * other scenarios where we can ruin host network connectivity.
+ * XXX: Using a proper library is preferred over parsing /proc
+ */
+static int networkCheckRouteCollision(virNetworkObjPtr network)
+{
+ int ret = -1, len;
+ unsigned int net_dest;
+ char *cur, *buf = NULL;
+ enum {MAX_ROUTE_SIZE = 1024*64};
+ virSocketAddr inaddress, innetmask;
+
+ if (!network->def->ipAddress || !network->def->netmask)
+ return 0;
+
+ if (virSocketParseAddr(network->def->ipAddress, &inaddress, 0) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse IP address '%s'"),
+ network->def->ipAddress);
+ goto error;
+ }
+
+ if (virSocketParseAddr(network->def->netmask, &innetmask, 0) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse netmask '%s'"),
+ network->def->netmask);
+ goto error;
+ }
+
+ if (inaddress.stor.ss_family != AF_INET ||
+ innetmask.stor.ss_family != AF_INET) {
+ /* Only support collision check for IPv4 */
+ goto out;
+ }
+
+ net_dest = (inaddress.inet4.sin_addr.s_addr &
+ innetmask.inet4.sin_addr.s_addr);
+
+ /* Read whole routing table into memory */
+ if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
+ goto error;
+
+ /* Dropping the last character shouldn't hurt */
+ if (len > 0)
+ buf[len-1] = '\0';
+
+ VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
+
+ if (!STRPREFIX (buf, "Iface"))
+ goto out;
+
+ /* First line is just headings, skip it */
+ cur = strchr(buf, '\n');
+ if (cur)
+ cur++;
+
+ while (cur) {
+ char iface[17], dest[128], mask[128];
+ unsigned int addr_val, mask_val;
+ int num;
+
+ /* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
+ char *nl = strchr(cur, '\n');
+ if (nl) {
+ *nl++ = '\0';
+ }
+
+ num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
+ iface, dest, mask);
+ cur = nl;
+
+ if (num != 3) {
+ VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
+ continue;
+ }
+
+ if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
+ VIR_DEBUG("Failed to convert network address %s to uint", dest);
+ continue;
+ }
+
+ if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
+ VIR_DEBUG("Failed to convert network mask %s to uint", mask);
+ continue;
+ }
+
+ addr_val &= mask_val;
+
+ if ((net_dest == addr_val) &&
+ (innetmask.inet4.sin_addr.s_addr == mask_val)) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Network %s/%s is already in use by "
+ "interface %s"),
+ network->def->ipAddress,
+ network->def->netmask, iface);
+ goto error;
+ }
+ }
+
+out:
+ ret = 0;
+error:
+ VIR_FREE(buf);
+ return ret;
+}
+
static int networkStartNetworkDaemon(struct network_driver *driver,
virNetworkObjPtr network)
{
@@ -919,6 +1028,10 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
return -1;
}
+ /* Check to see if network collides with an existing route */
+ if (networkCheckRouteCollision(network) < 0)
+ return -1;
+
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
virReportSystemError(err,
_("cannot create bridge '%s'"),
+26
View File
@@ -0,0 +1,26 @@
commit b7a7b3365145f6e9e434a3265a58666cd2e6d8dd
Author: Guido Günther <agx@sigxcpu.org>
Date: Wed Mar 17 21:04:11 2010 +0100
Don't crash without a security driver
"virsh dominfo <vm>" crashes if there's no primary security driver set
since we only intialize the secmodel.model and secmodel.doi if we have
one. Attached patch checks for securityPrimaryDriver instead of
securityDriver since the later is always set in qemudSecurityInit().
Closes: http://bugs.debian.org/574359
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1f2b11d..257f914 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4979,7 +4979,7 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn,
int ret = 0;
qemuDriverLock(driver);
- if (!driver->securityDriver) {
+ if (!driver->securityPrimaryDriver) {
memset(secmodel, 0, sizeof (*secmodel));
goto cleanup;
}
+77
View File
@@ -0,0 +1,77 @@
commit 74c7a3463d18a530d6d749d0199061b5d3f17faa
Author: Cole Robinson <crobinso@redhat.com>
Date: Tue May 11 14:44:34 2010 -0400
node_device: udev: Fix PCI product/vendor swappage
Product and vendor values were swapped in the XML, which made virt-manager
PCI device listing kinda useless.
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index bcfe991..4a9d65f 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -382,8 +382,8 @@ static int udevTranslatePCIIds(unsigned int vendor,
/* pci_get_strings returns void */
pci_get_strings(&m,
- &vendor_name,
&device_name,
+ &vendor_name,
NULL,
NULL);
commit 75d88455f54088f88bc7a503da0a4cd413ef7b95
Author: Klaus Ethgen <Klaus@Ethgen.de>
Date: Tue Apr 27 09:20:47 2010 +0200
The base used for conversion of USB values should be 16 not 10.
Signed-off-by: Guido Günther <agx@sigxcpu.org>
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index b12a49e..3a5a7e2 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -548,8 +548,6 @@ out:
}
-/* XXX Is 10 the correct base for the Number/Class/SubClass/Protocol
- * conversions? */
static int udevProcessUSBInterface(struct udev_device *device,
virNodeDeviceDefPtr def)
{
@@ -559,28 +557,28 @@ static int udevProcessUSBInterface(struct udev_device *device,
if (udevGetUintSysfsAttr(device,
"bInterfaceNumber",
&data->usb_if.number,
- 10) == PROPERTY_ERROR) {
+ 16) == PROPERTY_ERROR) {
goto out;
}
if (udevGetUintSysfsAttr(device,
"bInterfaceClass",
&data->usb_if._class,
- 10) == PROPERTY_ERROR) {
+ 16) == PROPERTY_ERROR) {
goto out;
}
if (udevGetUintSysfsAttr(device,
"bInterfaceSubClass",
&data->usb_if.subclass,
- 10) == PROPERTY_ERROR) {
+ 16) == PROPERTY_ERROR) {
goto out;
}
if (udevGetUintSysfsAttr(device,
"bInterfaceProtocol",
&data->usb_if.protocol,
- 10) == PROPERTY_ERROR) {
+ 16) == PROPERTY_ERROR) {
goto out;
}
+50
View File
@@ -0,0 +1,50 @@
commit e984019688509605966c03cd77f4591d2cc222d3
Author: Cole Robinson <crobinso@redhat.com>
Date: Fri Apr 30 18:14:35 2010 +0200
domain: Fix PCI address decimal parsing regression
<hostdev> address parsing previously attempted to detect the number
base: currently it is hardcoded to base 16, which can break PCI
assignment via virt-manager. Revert to the previous behavior.
* src/conf/domain_conf.c: virDomainDevicePCIAddressParseXML, switch to
virStrToLong_ui(bus, NULL, 0, ...) to autodetect base
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 1607e8b..546ddf2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1079,28 +1079,28 @@ virDomainDevicePCIAddressParseXML(xmlNodePtr node,
function = virXMLPropString(node, "function");
if (domain &&
- virStrToLong_ui(domain, NULL, 16, &addr->domain) < 0) {
+ virStrToLong_ui(domain, NULL, 0, &addr->domain) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <address> 'domain' attribute"));
goto cleanup;
}
if (bus &&
- virStrToLong_ui(bus, NULL, 16, &addr->bus) < 0) {
+ virStrToLong_ui(bus, NULL, 0, &addr->bus) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <address> 'bus' attribute"));
goto cleanup;
}
if (slot &&
- virStrToLong_ui(slot, NULL, 16, &addr->slot) < 0) {
+ virStrToLong_ui(slot, NULL, 0, &addr->slot) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <address> 'slot' attribute"));
goto cleanup;
}
if (function &&
- virStrToLong_ui(function, NULL, 16, &addr->function) < 0) {
+ virStrToLong_ui(function, NULL, 0, &addr->function) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot parse <address> 'function' attribute"));
goto cleanup;
+108
View File
@@ -0,0 +1,108 @@
commit 83be64034a0b530c904ceb4fd1ed1c10b5cdf4bf
Author: Cole Robinson <crobinso@redhat.com>
Date: Mon May 17 10:15:53 2010 -0400
qemu: Report cmdline output if VM dies early
qemuReadLogOutput early VM death detection is racy and won't always work.
Startup then errors when connecting to the VM monitor. This won't report
the emulator cmdline output which is typically the most useful diagnostic.
Check if the VM has died at the very end of the monitor connection step,
and if so, report the cmdline output.
See also: https://bugzilla.redhat.com/show_bug.cgi?id=581381
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ab6bec8..582fdee 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2034,39 +2034,47 @@ static void qemudFreePtyPath(void *payload, const char *name ATTRIBUTE_UNUSED)
VIR_FREE(payload);
}
+static void
+qemuReadLogFD(int logfd, char *buf, int maxlen, int off)
+{
+ int ret;
+ char *tmpbuf = buf + off;
+
+ ret = saferead(logfd, tmpbuf, maxlen - off - 1);
+ if (ret < 0) {
+ ret = 0;
+ }
+
+ tmpbuf[ret] = '\0';
+}
+
static int
qemudWaitForMonitor(struct qemud_driver* driver,
virDomainObjPtr vm, off_t pos)
{
- char buf[4096]; /* Plenty of space to get startup greeting */
+ char buf[4096] = ""; /* Plenty of space to get startup greeting */
int logfd;
int ret = -1;
+ virHashTablePtr paths = NULL;
- if ((logfd = qemudLogReadFD(driver->logDir, vm->def->name, pos))
- < 0)
+ if ((logfd = qemudLogReadFD(driver->logDir, vm->def->name, pos)) < 0)
return -1;
- ret = qemudReadLogOutput(vm, logfd, buf, sizeof(buf),
- qemudFindCharDevicePTYs,
- "console", 30);
- if (close(logfd) < 0) {
- char ebuf[4096];
- VIR_WARN(_("Unable to close logfile: %s"),
- virStrerror(errno, ebuf, sizeof ebuf));
- }
-
- if (ret < 0)
- return -1;
+ if (qemudReadLogOutput(vm, logfd, buf, sizeof(buf),
+ qemudFindCharDevicePTYs,
+ "console", 30) < 0)
+ goto closelog;
VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
- if (qemuConnectMonitor(driver, vm) < 0)
- return -1;
+ if (qemuConnectMonitor(driver, vm) < 0) {
+ goto cleanup;
+ }
/* Try to get the pty path mappings again via the monitor. This is much more
* reliable if it's available.
* Note that the monitor itself can be on a pty, so we still need to try the
* log output method. */
- virHashTablePtr paths = virHashCreate(0);
+ paths = virHashCreate(0);
if (paths == NULL) {
virReportOOMError();
goto cleanup;
@@ -2087,6 +2095,23 @@ cleanup:
virHashFree(paths, qemudFreePtyPath);
}
+ if (kill(vm->pid, 0) == -1 && errno == ESRCH) {
+ /* VM is dead, any other error raised in the interim is probably
+ * not as important as the qemu cmdline output */
+ qemuReadLogFD(logfd, buf, sizeof(buf), strlen(buf));
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("process exited while connecting to monitor: %s"),
+ buf);
+ ret = -1;
+ }
+
+closelog:
+ if (close(logfd) < 0) {
+ char ebuf[4096];
+ VIR_WARN(_("Unable to close logfile: %s"),
+ virStrerror(errno, ebuf, sizeof ebuf));
+ }
+
return ret;
}
+155
View File
@@ -0,0 +1,155 @@
diff -rup libvirt-0.7.7/src/conf/storage_conf.c new/src/conf/storage_conf.c
--- libvirt-0.7.7/src/conf/storage_conf.c 2010-03-05 09:46:29.000000000 -0500
+++ new/src/conf/storage_conf.c 2010-06-17 12:28:44.319588000 -0400
@@ -601,6 +601,7 @@ virStoragePoolDefParseXML(xmlXPathContex
xmlNodePtr source_node;
char *type = NULL;
char *uuid = NULL;
+ char *tmppath;
if (VIR_ALLOC(ret) < 0) {
virReportOOMError();
@@ -698,11 +699,16 @@ virStoragePoolDefParseXML(xmlXPathContex
}
}
- if ((ret->target.path = virXPathString("string(./target/path)", ctxt)) == NULL) {
+ if ((tmppath = virXPathString("string(./target/path)", ctxt)) == NULL) {
virStorageReportError(VIR_ERR_XML_ERROR,
"%s", _("missing storage pool target path"));
goto cleanup;
}
+ ret->target.path = virFileSanitizePath(tmppath);
+ VIR_FREE(tmppath);
+ if (!ret->target.path)
+ goto cleanup;
+
if (virStorageDefParsePerms(ctxt, &ret->target.perms,
"./target/permissions", 0700) < 0)
diff -rup libvirt-0.7.7/src/libvirt_private.syms new/src/libvirt_private.syms
--- libvirt-0.7.7/src/libvirt_private.syms 2010-03-05 10:45:23.000000000 -0500
+++ new/src/libvirt_private.syms 2010-06-17 12:28:44.334585000 -0400
@@ -582,6 +582,7 @@ virFileReadLimFD;
virFilePid;
virFileReadPid;
virFileLinkPointsTo;
+virFileSanitizePath;
virParseNumber;
virAsprintf;
virRun;
diff -rup libvirt-0.7.7/src/storage/storage_driver.c new/src/storage/storage_driver.c
--- libvirt-0.7.7/src/storage/storage_driver.c 2010-03-05 09:46:29.000000000 -0500
+++ new/src/storage/storage_driver.c 2010-06-17 12:28:44.346586000 -0400
@@ -1200,6 +1200,11 @@ storageVolumeLookupByPath(virConnectPtr
virStorageDriverStatePtr driver = conn->storagePrivateData;
unsigned int i;
virStorageVolPtr ret = NULL;
+ char *cleanpath;
+
+ cleanpath = virFileSanitizePath(path);
+ if (!cleanpath)
+ return NULL;
storageDriverLock(driver);
for (i = 0 ; i < driver->pools.count && !ret ; i++) {
@@ -1209,7 +1214,7 @@ storageVolumeLookupByPath(virConnectPtr
const char *stable_path;
stable_path = virStorageBackendStablePath(driver->pools.objs[i],
- path);
+ cleanpath);
/*
* virStorageBackendStablePath already does
* virStorageReportError if it fails; we just need to keep
@@ -1238,6 +1243,7 @@ storageVolumeLookupByPath(virConnectPtr
"%s", _("no storage vol with matching path"));
cleanup:
+ VIR_FREE(cleanpath);
storageDriverUnlock(driver);
return ret;
}
diff -rup libvirt-0.7.7/src/util/util.c new/src/util/util.c
--- libvirt-0.7.7/src/util/util.c 2010-03-03 05:48:25.000000000 -0500
+++ new/src/util/util.c 2010-06-17 12:28:44.357588000 -0400
@@ -1867,6 +1867,55 @@ int virFileAbsPath(const char *path, cha
return 0;
}
+/* Remove spurious / characters from a path. The result must be freed */
+char *
+virFileSanitizePath(const char *path)
+{
+ const char *cur = path;
+ char *cleanpath;
+ int idx = 0;
+
+ cleanpath = strdup(path);
+ if (!cleanpath) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ /* Need to sanitize:
+ * // -> //
+ * /// -> /
+ * /../foo -> /../foo
+ * /foo///bar/ -> /foo/bar
+ */
+
+ /* Starting with // is valid posix, but ///foo == /foo */
+ if (cur[0] == '/' && cur[1] == '/' && cur[2] != '/') {
+ idx = 2;
+ cur += 2;
+ }
+
+ /* Sanitize path in place */
+ while (*cur != '\0') {
+ if (*cur != '/') {
+ cleanpath[idx++] = *cur++;
+ continue;
+ }
+
+ /* Skip all extra / */
+ while (*++cur == '/')
+ continue;
+
+ /* Don't add a trailing / */
+ if (idx != 0 && *cur == '\0')
+ break;
+
+ cleanpath[idx++] = '/';
+ }
+ cleanpath[idx] = '\0';
+
+ return cleanpath;
+}
+
/* Like strtol, but produce an "int" result, and check more carefully.
Return 0 upon success; return -1 to indicate failure.
When END_PTR is NULL, the byte after the final valid digit must be NUL.
diff -rup libvirt-0.7.7/src/util/util.h new/src/util/util.h
--- libvirt-0.7.7/src/util/util.h 2010-02-19 12:14:07.000000000 -0500
+++ new/src/util/util.h 2010-06-17 12:28:44.364585000 -0400
@@ -109,6 +109,8 @@ char *virFindFileInPath(const char *file
int virFileExists(const char *path);
+char *virFileSanitizePath(const char *path);
+
enum {
VIR_FILE_OP_NONE = 0,
VIR_FILE_OP_AS_UID = (1 << 0),
diff -rup libvirt-0.7.7/tests/storagepoolxml2xmlin/pool-dir.xml new/tests/storagepoolxml2xmlin/pool-dir.xml
--- libvirt-0.7.7/tests/storagepoolxml2xmlin/pool-dir.xml 2009-12-22 04:37:57.000000000 -0500
+++ new/tests/storagepoolxml2xmlin/pool-dir.xml 2010-06-17 12:28:44.367585000 -0400
@@ -7,7 +7,7 @@
<source>
</source>
<target>
- <path>/var/lib/libvirt/images</path>
+ <path>///var/////lib/libvirt/images//</path>
<permissions>
<mode>0700</mode>
<owner>0</owner>
+87
View File
@@ -0,0 +1,87 @@
From 3f1aa08af6580c215d973bc6bf57f505dbf8b926 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Fri, 12 Mar 2010 13:38:39 -0500
Subject: [PATCH] security: Set permissions for kernel/initrd
Fixes URL installs when running virt-install as root on Fedora.
---
src/qemu/qemu_security_dac.c | 21 +++++++++++++++++++++
src/security/security_selinux.c | 16 ++++++++++++++++
2 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
index 6911f48..1883fbe 100644
--- a/src/qemu/qemu_security_dac.c
+++ b/src/qemu/qemu_security_dac.c
@@ -332,6 +332,15 @@ qemuSecurityDACRestoreSecurityAllLabel(virDomainObjPtr vm)
vm->def->disks[i]) < 0)
rc = -1;
}
+
+ if (vm->def->os.kernel &&
+ qemuSecurityDACRestoreSecurityFileLabel(vm->def->os.kernel) < 0)
+ rc = -1;
+
+ if (vm->def->os.initrd &&
+ qemuSecurityDACRestoreSecurityFileLabel(vm->def->os.initrd) < 0)
+ rc = -1;
+
return rc;
}
@@ -356,6 +365,18 @@ qemuSecurityDACSetSecurityAllLabel(virDomainObjPtr vm)
return -1;
}
+ if (vm->def->os.kernel &&
+ qemuSecurityDACSetOwnership(vm->def->os.kernel,
+ driver->user,
+ driver->group) < 0)
+ return -1;
+
+ if (vm->def->os.initrd &&
+ qemuSecurityDACSetOwnership(vm->def->os.initrd,
+ driver->user,
+ driver->group) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index b2c8581..975b315 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -616,6 +616,14 @@ SELinuxRestoreSecurityAllLabel(virDomainObjPtr vm)
rc = -1;
}
+ if (vm->def->os.kernel &&
+ SELinuxRestoreSecurityFileLabel(vm->def->os.kernel) < 0)
+ rc = -1;
+
+ if (vm->def->os.initrd &&
+ SELinuxRestoreSecurityFileLabel(vm->def->os.initrd) < 0)
+ rc = -1;
+
return rc;
}
@@ -736,6 +744,14 @@ SELinuxSetSecurityAllLabel(virDomainObjPtr vm)
return -1;
}
+ if (vm->def->os.kernel &&
+ SELinuxSetFilecon(vm->def->os.kernel, default_content_context) < 0)
+ return -1;
+
+ if (vm->def->os.initrd &&
+ SELinuxSetFilecon(vm->def->os.initrd, default_content_context) < 0)
+ return -1;
+
return 0;
}
--
1.6.6.1
+66
View File
@@ -0,0 +1,66 @@
commit 07f6c3a95f1caca368c8723b5b0a25ae2faa1ffe
Author: David Allan <dallan@redhat.com>
Date: Thu May 27 10:44:02 2010 -0400
v2 of Cole's wlan support
* Incorporated Jim's feedback (v1 & v2)
* Moved case of DEVTYPE == "wlan" up as it's definitive that we have a network interface.
* Made comment more detailed about the wired case to explain better
how it differentiates between wired network interfaces and USB
devices.
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index f0485f1..c437861 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -597,8 +597,15 @@ static int udevProcessNetworkInterface(struct udev_device *device,
virNodeDeviceDefPtr def)
{
int ret = -1;
+ const char *devtype = udev_device_get_devtype(device);
union _virNodeDevCapData *data = &def->caps->data;
+ if (devtype && STREQ(devtype, "wlan")) {
+ data->net.subtype = VIR_NODE_DEV_CAP_NET_80211;
+ } else {
+ data->net.subtype = VIR_NODE_DEV_CAP_NET_80203;
+ }
+
if (udevGetStringProperty(device,
"INTERFACE",
&data->net.ifname) == PROPERTY_ERROR) {
@@ -1074,6 +1081,8 @@ static int udevGetDeviceType(struct udev_device *device,
int ret = 0;
devtype = udev_device_get_devtype(device);
+ VIR_DEBUG("Found device type '%s' for device '%s'",
+ NULLSTR(devtype), udev_device_get_sysname(device));
if (devtype != NULL && STREQ(devtype, "usb_device")) {
*type = VIR_NODE_DEV_CAP_USB_DEV;
@@ -1105,13 +1114,20 @@ static int udevGetDeviceType(struct udev_device *device,
goto out;
}
+ if (devtype != NULL && STREQ(devtype, "wlan")) {
+ *type = VIR_NODE_DEV_CAP_NET;
+ goto out;
+ }
+
if (udevGetUintProperty(device, "PCI_CLASS", &tmp, 16) == PROPERTY_FOUND) {
*type = VIR_NODE_DEV_CAP_PCI_DEV;
goto out;
}
- /* It does not appear that network interfaces set the device type
- * property. */
+ /* It does not appear that wired network interfaces set the
+ * DEVTYPE property. USB devices also have an INTERFACE property,
+ * but they do set DEVTYPE, so if devtype is NULL and the
+ * INTERFACE property exists, we have a network device. */
if (devtype == NULL &&
udevGetStringProperty(device,
"INTERFACE",
@@ -1,465 +0,0 @@
From 332979bb680d833529ab9cecac6828c6ce54d731 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 14 Aug 2009 08:31:10 +0100
Subject: [PATCH] Add host PCI device hotplug support
Attaching a host PCI device to a qemu guest is done with a
straightforward 'pci_add pci_addr auto host host=XX:XX.X' command.
Like with NIC and disk hotplug, we need to retain the guest PCI address
assigned by qemu so that we can use it for hot-unplug.
Identifying a device for detach is done using the host PCI address.
Managed mode is handled by detaching/resetting the device before
attaching it to the guest and re-attaching it after detaching it from
the guest.
(cherry picked from commit 7636ef4630fc15c3d559eceb5b5c4fb1524b7c5a)
(cherry picked from commit 0c5b7b93a3cdb197c55d79c2605e9e19e3af43f5)
(cherry picked from commit 60ff07585ca8f7e639fed477e2e2cf79ce1c5c21)
(cherry picked from commit 4e12af5623e4a962a6bb911af06fa29aa85befba)
(cherry picked from commit 4dbecff9fbd5b5d1154bc7a41a5d4dd00533b359)
(cherry picked from commit 12edef9a6aca5bd9a2ea18b73ca862f615684d84)
(cherry picked from commit 457e05062863a35c7efb35470886b9b83a49d04d)
(cherry picked from commit e8ad33931296c67de0538e78d12e21706a826d37)
Fedora-patch: libvirt-add-pci-hostdev-hotplug-support.patch
---
src/domain_conf.c | 33 +++++-
src/domain_conf.h | 13 +++
src/libvirt_private.syms | 2 +
src/qemu_driver.c | 266 ++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 300 insertions(+), 14 deletions(-)
diff --git a/src/domain_conf.c b/src/domain_conf.c
index 2301a96..bad53f7 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -1977,7 +1977,8 @@ out:
static int
virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
const xmlNodePtr node,
- virDomainHostdevDefPtr def) {
+ virDomainHostdevDefPtr def,
+ int flags) {
int ret = -1;
xmlNodePtr cur;
@@ -2049,6 +2050,20 @@ virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
_("pci address needs function id"));
goto out;
}
+ } else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
+ xmlStrEqual(cur->name, BAD_CAST "state")) {
+ char *devaddr = virXMLPropString(cur, "devaddr");
+ if (devaddr &&
+ sscanf(devaddr, "%x:%x:%x",
+ &def->source.subsys.u.pci.guest_addr.domain,
+ &def->source.subsys.u.pci.guest_addr.bus,
+ &def->source.subsys.u.pci.guest_addr.slot) < 3) {
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Unable to parse devaddr parameter '%s'"),
+ devaddr);
+ VIR_FREE(devaddr);
+ goto out;
+ }
} else {
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
_("unknown pci source type '%s'"),
@@ -2123,7 +2138,7 @@ virDomainHostdevDefParseXML(virConnectPtr conn,
}
if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
- if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def) < 0)
+ if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def, flags) < 0)
goto error;
}
} else {
@@ -3937,7 +3952,8 @@ virDomainGraphicsDefFormat(virConnectPtr conn,
static int
virDomainHostdevDefFormat(virConnectPtr conn,
virBufferPtr buf,
- virDomainHostdevDefPtr def)
+ virDomainHostdevDefPtr def,
+ int flags)
{
const char *mode = virDomainHostdevModeTypeToString(def->mode);
const char *type;
@@ -3978,6 +3994,15 @@ virDomainHostdevDefFormat(virConnectPtr conn,
def->source.subsys.u.pci.bus,
def->source.subsys.u.pci.slot,
def->source.subsys.u.pci.function);
+ if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS) {
+ virBufferAddLit(buf, " <state");
+ if (virHostdevHasValidGuestAddr(def))
+ virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'",
+ def->source.subsys.u.pci.guest_addr.domain,
+ def->source.subsys.u.pci.guest_addr.bus,
+ def->source.subsys.u.pci.guest_addr.slot);
+ virBufferAddLit(buf, "/>\n");
+ }
}
virBufferAddLit(buf, " </source>\n");
@@ -4192,7 +4217,7 @@ char *virDomainDefFormat(virConnectPtr conn,
goto cleanup;
for (n = 0 ; n < def->nhostdevs ; n++)
- if (virDomainHostdevDefFormat(conn, &buf, def->hostdevs[n]) < 0)
+ if (virDomainHostdevDefFormat(conn, &buf, def->hostdevs[n], flags) < 0)
goto cleanup;
virBufferAddLit(&buf, " </devices>\n");
diff --git a/src/domain_conf.h b/src/domain_conf.h
index 63fca76..44302be 100644
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -391,6 +391,11 @@ struct _virDomainHostdevDef {
unsigned bus;
unsigned slot;
unsigned function;
+ struct {
+ unsigned domain;
+ unsigned bus;
+ unsigned slot;
+ } guest_addr;
} pci;
} u;
} subsys;
@@ -404,6 +409,14 @@ struct _virDomainHostdevDef {
char* target;
};
+static inline int
+virHostdevHasValidGuestAddr(virDomainHostdevDefPtr def)
+{
+ return def->source.subsys.u.pci.guest_addr.domain ||
+ def->source.subsys.u.pci.guest_addr.bus ||
+ def->source.subsys.u.pci.guest_addr.slot;
+}
+
/* Flags for the 'type' field in next struct */
enum virDomainDeviceType {
VIR_DOMAIN_DEVICE_DISK,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4f1b01f..22131c4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -88,6 +88,8 @@ virDomainGetRootFilesystem;
virDomainGraphicsTypeFromString;
virDomainGraphicsDefFree;
virDomainHostdevDefFree;
+virDomainHostdevModeTypeToString;
+virDomainHostdevSubsysTypeToString;
virDomainInputDefFree;
virDomainLifecycleTypeFromString;
virDomainLifecycleTypeToString;
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index cbc27c4..99dac52 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -5258,9 +5258,91 @@ cleanup:
return -1;
}
-static int qemudDomainAttachHostDevice(virConnectPtr conn,
- virDomainObjPtr vm,
- virDomainDeviceDefPtr dev)
+static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainDeviceDefPtr dev)
+{
+ virDomainHostdevDefPtr hostdev = dev->data.hostdev;
+ char *cmd, *reply;
+ unsigned domain, bus, slot;
+ pciDevice *pci;
+
+ if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
+ virReportOOMError(conn);
+ return -1;
+ }
+
+ pci = pciGetDevice(conn,
+ hostdev->source.subsys.u.pci.domain,
+ hostdev->source.subsys.u.pci.bus,
+ hostdev->source.subsys.u.pci.slot,
+ hostdev->source.subsys.u.pci.function);
+ if (!dev)
+ return -1;
+
+ if ((hostdev->managed && pciDettachDevice(conn, pci) < 0) ||
+ pciResetDevice(conn, pci, driver->activePciHostdevs) < 0) {
+ pciFreeDevice(conn, pci);
+ return -1;
+ }
+
+ if (pciDeviceListAdd(conn, driver->activePciHostdevs, pci) < 0) {
+ pciFreeDevice(conn, pci);
+ return -1;
+ }
+
+ cmd = reply = NULL;
+
+ if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x",
+ hostdev->source.subsys.u.pci.bus,
+ hostdev->source.subsys.u.pci.slot,
+ hostdev->source.subsys.u.pci.function) < 0) {
+ virReportOOMError(conn);
+ goto error;
+ }
+
+ if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
+ qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("cannot attach host pci device"));
+ goto error;
+ }
+
+ if (strstr(reply, "invalid type: host")) {
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
+ _("PCI device assignment is not supported by this version of qemu"));
+ goto error;
+ }
+
+ if (qemudParsePciAddReply(vm, reply, &domain, &bus, &slot) < 0) {
+ qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ _("parsing pci_add reply failed: %s"), reply);
+ goto error;
+ }
+
+ hostdev->source.subsys.u.pci.guest_addr.domain = domain;
+ hostdev->source.subsys.u.pci.guest_addr.bus = bus;
+ hostdev->source.subsys.u.pci.guest_addr.slot = slot;
+
+ vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
+
+ VIR_FREE(reply);
+ VIR_FREE(cmd);
+
+ return 0;
+
+error:
+ pciDeviceListDel(conn, driver->activePciHostdevs, pci);
+
+ VIR_FREE(reply);
+ VIR_FREE(cmd);
+
+ return -1;
+}
+
+static int qemudDomainAttachHostUsbDevice(virConnectPtr conn,
+ virDomainObjPtr vm,
+ virDomainDeviceDefPtr dev)
{
int ret;
char *cmd, *reply;
@@ -5310,6 +5392,36 @@ static int qemudDomainAttachHostDevice(virConnectPtr conn,
return 0;
}
+static int qemudDomainAttachHostDevice(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainDeviceDefPtr dev)
+{
+ virDomainHostdevDefPtr hostdev = dev->data.hostdev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+ _("hostdev mode '%s' not supported"),
+ virDomainHostdevModeTypeToString(hostdev->mode));
+ return -1;
+ }
+
+ if (qemuDomainSetDeviceOwnership(conn, driver, dev, 0) < 0)
+ return -1;
+
+ switch (hostdev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ return qemudDomainAttachHostPciDevice(conn, driver, vm, dev);
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ return qemudDomainAttachHostUsbDevice(conn, vm, dev);
+ default:
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+ _("hostdev subsys type '%s' not supported"),
+ virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
+ return -1;
+ }
+}
+
static int qemudDomainAttachDevice(virDomainPtr dom,
const char *xml) {
struct qemud_driver *driver = dom->conn->privateData;
@@ -5411,13 +5523,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
}
} else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
ret = qemudDomainAttachNetDevice(dom->conn, driver, vm, dev, qemuCmdFlags);
- } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
- dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
- dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
- if (qemuDomainSetDeviceOwnership(dom->conn, driver, dev, 0) < 0)
- goto cleanup;
-
- ret = qemudDomainAttachHostDevice(dom->conn, vm, dev);
+ } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
+ ret = qemudDomainAttachHostDevice(dom->conn, driver, vm, dev);
} else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
_("device type '%s' cannot be attached"),
@@ -5630,6 +5737,143 @@ cleanup:
return ret;
}
+static int qemudDomainDetachHostPciDevice(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainDeviceDefPtr dev)
+{
+ virDomainHostdevDefPtr detach;
+ char *cmd, *reply;
+ int i, ret;
+ pciDevice *pci;
+
+ for (i = 0 ; i < vm->def->nhostdevs ; i++) {
+ unsigned domain = vm->def->hostdevs[i]->source.subsys.u.pci.domain;
+ unsigned bus = vm->def->hostdevs[i]->source.subsys.u.pci.bus;
+ unsigned slot = vm->def->hostdevs[i]->source.subsys.u.pci.slot;
+ unsigned function = vm->def->hostdevs[i]->source.subsys.u.pci.function;
+
+ if (dev->data.hostdev->source.subsys.u.pci.domain == domain &&
+ dev->data.hostdev->source.subsys.u.pci.bus == bus &&
+ dev->data.hostdev->source.subsys.u.pci.slot == slot &&
+ dev->data.hostdev->source.subsys.u.pci.function == function) {
+ detach = vm->def->hostdevs[i];
+ break;
+ }
+ }
+
+ if (!detach) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("host pci device %.4x:%.2x:%.2x.%.1x not found"),
+ dev->data.hostdev->source.subsys.u.pci.domain,
+ dev->data.hostdev->source.subsys.u.pci.bus,
+ dev->data.hostdev->source.subsys.u.pci.slot,
+ dev->data.hostdev->source.subsys.u.pci.function);
+ return -1;
+ }
+
+ if (!virHostdevHasValidGuestAddr(detach)) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("hostdev cannot be detached - device state missing"));
+ return -1;
+ }
+
+ if (virAsprintf(&cmd, "pci_del pci_addr=%.4x:%.2x:%.2x",
+ detach->source.subsys.u.pci.guest_addr.domain,
+ detach->source.subsys.u.pci.guest_addr.bus,
+ detach->source.subsys.u.pci.guest_addr.slot) < 0) {
+ virReportOOMError(conn);
+ return -1;
+ }
+
+ if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
+ qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("cannot detach host pci device"));
+ VIR_FREE(cmd);
+ return -1;
+ }
+
+ DEBUG("%s: pci_del reply: %s", vm->def->name, reply);
+
+ /* If the command fails due to a wrong PCI address qemu prints
+ * 'invalid pci address'; nothing is printed on success */
+ if (strstr(reply, "Invalid pci address")) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("failed to detach host pci device: invalid PCI address %.4x:%.2x:%.2x: %s"),
+ detach->source.subsys.u.pci.guest_addr.domain,
+ detach->source.subsys.u.pci.guest_addr.bus,
+ detach->source.subsys.u.pci.guest_addr.slot,
+ reply);
+ VIR_FREE(reply);
+ VIR_FREE(cmd);
+ return -1;
+ }
+
+ VIR_FREE(reply);
+ VIR_FREE(cmd);
+
+ ret = 0;
+
+ pci = pciGetDevice(conn,
+ detach->source.subsys.u.pci.domain,
+ detach->source.subsys.u.pci.bus,
+ detach->source.subsys.u.pci.slot,
+ detach->source.subsys.u.pci.function);
+ if (!pci)
+ ret = -1;
+ else {
+ pciDeviceListDel(conn, driver->activePciHostdevs, pci);
+ if (pciResetDevice(conn, pci, driver->activePciHostdevs) < 0)
+ ret = -1;
+ if (detach->managed && pciReAttachDevice(conn, pci) < 0)
+ ret = -1;
+ pciFreeDevice(conn, pci);
+ }
+
+ if (i != --vm->def->nhostdevs)
+ memmove(&vm->def->hostdevs[i],
+ &vm->def->hostdevs[i+1],
+ sizeof(*vm->def->hostdevs) * (vm->def->nhostdevs-i));
+ if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs) < 0) {
+ virReportOOMError(conn);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int qemudDomainDetachHostDevice(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainDeviceDefPtr dev)
+{
+ virDomainHostdevDefPtr hostdev = dev->data.hostdev;
+ int ret;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+ _("hostdev mode '%s' not supported"),
+ virDomainHostdevModeTypeToString(hostdev->mode));
+ return -1;
+ }
+
+ switch (hostdev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ ret = qemudDomainDetachHostPciDevice(conn, driver, vm, dev);
+ break;
+ default:
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
+ _("hostdev subsys type '%s' not supported"),
+ virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
+ return -1;
+ }
+
+ if (qemuDomainSetDeviceOwnership(conn, driver, dev, 1) < 0)
+ VIR_WARN0("Fail to restore disk device ownership");
+
+ return ret;
+}
+
static int qemudDomainDetachDevice(virDomainPtr dom,
const char *xml) {
struct qemud_driver *driver = dom->conn->privateData;
@@ -5670,6 +5914,8 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
VIR_WARN0("Fail to restore disk device ownership");
} else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
ret = qemudDomainDetachNetDevice(dom->conn, vm, dev);
+ } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
+ ret = qemudDomainDetachHostDevice(dom->conn, driver, vm, dev);
} else
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("only SCSI or virtio disk device can be detached dynamically"));
--
1.6.2.5
@@ -1,43 +0,0 @@
From 100eb35a80932cd9a162c38ecd2ab8b01894fb61 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Mon, 17 Aug 2009 15:05:22 +0100
Subject: [PATCH] Cosmetic change to 'virsh nodedev-list --tree' output
Maybe it's just me, but I try to select an item from the tree using
double-click and get annoyed when "+-" gets included in the selection.
* src/virsh.c: add a space between "+-" and the node device name
in 'virsh nodedev-list --tree'
(cherry picked from commit 097c818bf00b3777778ffc32fea3a6ed1e741e2b)
Fedora-patch: libvirt-add-space-to-nodedev-list-tree.patch
---
src/virsh.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/src/virsh.c b/src/virsh.c
index 94c3c4e..2d0cf81 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -5370,6 +5370,8 @@ cmdNodeListDevicesPrint(vshControl *ctl,
if (depth && depth < MAX_DEPTH) {
indentBuf[indentIdx] = '+';
indentBuf[indentIdx+1] = '-';
+ indentBuf[indentIdx+2] = ' ';
+ indentBuf[indentIdx+3] = '\0';
}
/* Print this device */
@@ -5398,7 +5400,7 @@ cmdNodeListDevicesPrint(vshControl *ctl,
/* If there is a child device, then print another blank line */
if (nextlastdev != -1) {
vshPrint(ctl, "%s", indentBuf);
- vshPrint(ctl, " |\n");
+ vshPrint(ctl, " |\n");
}
/* Finally print all children */
--
1.6.2.5
@@ -1,812 +0,0 @@
From 89eefbd116ae74c3a5cfcfc74a31a40b83c726c3 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Mon, 17 Aug 2009 15:05:23 +0100
Subject: [PATCH] Maintain a list of active PCI hostdevs and use it in pciResetDevice()
https://bugzilla.redhat.com/499678
First we add a pciDeviceList type and add a qemuGetPciHostDeviceList()
function to build a list from a domain definition. Use this in
prepare/re-attach to simplify things and eliminate the multiple
pciGetDevice() calls.
Then, as we start/shutdown guests we can add or delete devices as
appropriate from a list of active devices.
Finally, in pciReset(), we can use this to determine whether its safe to
reset a device as a side effect of resetting another device.
(cherry picked from commit 78675b228b76a83f83d64856bfb63b9e14c103a0)
(cherry picked from commit e8ad33931296c67de0538e78d12e21706a826d37)
Fedora-patch: libvirt-allow-pci-hostdev-reset-to-reset-other-devices.patch
---
src/libvirt_private.syms | 7 +-
src/pci.c | 211 +++++++++++++++++++++++++++++++++--------
src/pci.h | 23 +++++-
src/qemu_conf.h | 3 +
src/qemu_driver.c | 237 +++++++++++++++++++++++++++-------------------
src/xen_unified.c | 2 +-
6 files changed, 339 insertions(+), 144 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index bd63692..4f1b01f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -278,7 +278,12 @@ pciFreeDevice;
pciDettachDevice;
pciReAttachDevice;
pciResetDevice;
-
+pciDeviceSetManaged;
+pciDeviceGetManaged;
+pciDeviceListNew;
+pciDeviceListFree;
+pciDeviceListAdd;
+pciDeviceListDel;
# qparams.h
qparam_get_query;
diff --git a/src/pci.c b/src/pci.c
index 74f7ef0..96e5d6d 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -63,6 +63,7 @@ struct _pciDevice {
unsigned pci_pm_cap_pos;
unsigned has_flr : 1;
unsigned has_pm_reset : 1;
+ unsigned managed : 1;
};
/* For virReportOOMError() and virReportSystemError() */
@@ -225,7 +226,7 @@ pciWrite32(pciDevice *dev, unsigned pos, uint32_t val)
pciWrite(dev, pos, &buf[0], sizeof(buf));
}
-typedef int (*pciIterPredicate)(pciDevice *, pciDevice *);
+typedef int (*pciIterPredicate)(pciDevice *, pciDevice *, void *);
/* Iterate over available PCI devices calling @predicate
* to compare each one to @dev.
@@ -236,7 +237,8 @@ static int
pciIterDevices(virConnectPtr conn,
pciIterPredicate predicate,
pciDevice *dev,
- pciDevice **matched)
+ pciDevice **matched,
+ void *data)
{
DIR *dir;
struct dirent *entry;
@@ -254,7 +256,7 @@ pciIterDevices(virConnectPtr conn,
while ((entry = readdir(dir))) {
unsigned domain, bus, slot, function;
- pciDevice *try;
+ pciDevice *check;
/* Ignore '.' and '..' */
if (entry->d_name[0] == '.')
@@ -266,18 +268,18 @@ pciIterDevices(virConnectPtr conn,
continue;
}
- try = pciGetDevice(conn, domain, bus, slot, function);
- if (!try) {
+ check = pciGetDevice(conn, domain, bus, slot, function);
+ if (!check) {
ret = -1;
break;
}
- if (predicate(try, dev)) {
- VIR_DEBUG("%s %s: iter matched on %s", dev->id, dev->name, try->name);
- *matched = try;
+ if (predicate(dev, check, data)) {
+ VIR_DEBUG("%s %s: iter matched on %s", dev->id, dev->name, check->name);
+ *matched = check;
break;
}
- pciFreeDevice(conn, try);
+ pciFreeDevice(conn, check);
}
closedir(dir);
return ret;
@@ -379,63 +381,70 @@ pciDetectPowerManagementReset(pciDevice *dev)
return 0;
}
-/* Any devices other than the one supplied on the same domain/bus ? */
+/* Any active devices other than the one supplied on the same domain/bus ? */
static int
-pciSharesBus(pciDevice *a, pciDevice *b)
+pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
{
- return
- a->domain == b->domain &&
- a->bus == b->bus &&
- (a->slot != b->slot ||
- a->function != b->function);
-}
+ pciDeviceList *activeDevs = data;
-static int
-pciBusContainsOtherDevices(virConnectPtr conn, pciDevice *dev)
-{
- pciDevice *matched = NULL;
- if (pciIterDevices(conn, pciSharesBus, dev, &matched) < 0)
- return 1;
- if (!matched)
+ if (dev->domain != check->domain ||
+ dev->bus != check->bus ||
+ (check->slot == check->slot &&
+ check->function == check->function))
+ return 0;
+
+ if (activeDevs && !pciDeviceListFind(activeDevs, check))
return 0;
- pciFreeDevice(conn, matched);
+
return 1;
}
-/* Is @a the parent of @b ? */
+static pciDevice *
+pciBusContainsActiveDevices(virConnectPtr conn,
+ pciDevice *dev,
+ pciDeviceList *activeDevs)
+{
+ pciDevice *active = NULL;
+ if (pciIterDevices(conn, pciSharesBusWithActive,
+ dev, &active, activeDevs) < 0)
+ return NULL;
+ return active;
+}
+
+/* Is @check the parent of @dev ? */
static int
-pciIsParent(pciDevice *a, pciDevice *b)
+pciIsParent(pciDevice *dev, pciDevice *check, void *data ATTRIBUTE_UNUSED)
{
uint16_t device_class;
uint8_t header_type, secondary, subordinate;
- if (a->domain != b->domain)
+ if (dev->domain != check->domain)
return 0;
/* Is it a bridge? */
- device_class = pciRead16(a, PCI_CLASS_DEVICE);
+ device_class = pciRead16(check, PCI_CLASS_DEVICE);
if (device_class != PCI_CLASS_BRIDGE_PCI)
return 0;
/* Is it a plane? */
- header_type = pciRead8(a, PCI_HEADER_TYPE);
+ header_type = pciRead8(check, PCI_HEADER_TYPE);
if ((header_type & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_BRIDGE)
return 0;
- secondary = pciRead8(a, PCI_SECONDARY_BUS);
- subordinate = pciRead8(a, PCI_SUBORDINATE_BUS);
+ secondary = pciRead8(check, PCI_SECONDARY_BUS);
+ subordinate = pciRead8(check, PCI_SUBORDINATE_BUS);
- VIR_DEBUG("%s %s: found parent device %s\n", b->id, b->name, a->name);
+ VIR_DEBUG("%s %s: found parent device %s\n", dev->id, dev->name, check->name);
/* No, it's superman! */
- return (b->bus >= secondary && b->bus <= subordinate);
+ return (dev->bus >= secondary && dev->bus <= subordinate);
}
static pciDevice *
pciGetParentDevice(virConnectPtr conn, pciDevice *dev)
{
pciDevice *parent = NULL;
- pciIterDevices(conn, pciIsParent, dev, &parent);
+ pciIterDevices(conn, pciIsParent, dev, &parent, NULL);
return parent;
}
@@ -443,9 +452,11 @@ pciGetParentDevice(virConnectPtr conn, pciDevice *dev)
* devices behind a bus.
*/
static int
-pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
+pciTrySecondaryBusReset(virConnectPtr conn,
+ pciDevice *dev,
+ pciDeviceList *activeDevs)
{
- pciDevice *parent;
+ pciDevice *parent, *conflict;
uint8_t config_space[PCI_CONF_LEN];
uint16_t ctl;
int ret = -1;
@@ -455,10 +466,10 @@ pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
* In future, we could allow it so long as those devices
* are not in use by the host or other guests.
*/
- if (pciBusContainsOtherDevices(conn, dev)) {
+ if ((conflict = pciBusContainsActiveDevices(conn, dev, activeDevs))) {
pciReportError(conn, VIR_ERR_NO_SUPPORT,
- _("Other devices on bus with %s, not doing bus reset"),
- dev->name);
+ _("Active %s devices on bus with %s, not doing bus reset"),
+ conflict->name, dev->name);
return -1;
}
@@ -572,10 +583,18 @@ pciInitDevice(virConnectPtr conn, pciDevice *dev)
}
int
-pciResetDevice(virConnectPtr conn, pciDevice *dev)
+pciResetDevice(virConnectPtr conn,
+ pciDevice *dev,
+ pciDeviceList *activeDevs)
{
int ret = -1;
+ if (activeDevs && pciDeviceListFind(activeDevs, dev)) {
+ pciReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Not resetting active device %s"), dev->name);
+ return -1;
+ }
+
if (!dev->initted && pciInitDevice(conn, dev) < 0)
return -1;
@@ -594,7 +613,7 @@ pciResetDevice(virConnectPtr conn, pciDevice *dev)
/* Bus reset is not an option with the root bus */
if (ret < 0 && dev->bus != 0)
- ret = pciTrySecondaryBusReset(conn, dev);
+ ret = pciTrySecondaryBusReset(conn, dev, activeDevs);
if (ret < 0) {
virErrorPtr err = virGetLastError();
@@ -890,8 +909,116 @@ pciGetDevice(virConnectPtr conn,
void
pciFreeDevice(virConnectPtr conn ATTRIBUTE_UNUSED, pciDevice *dev)
{
+ if (!dev)
+ return;
VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
if (dev->fd >= 0)
close(dev->fd);
VIR_FREE(dev);
}
+
+void pciDeviceSetManaged(pciDevice *dev, unsigned managed)
+{
+ dev->managed = !!managed;
+}
+
+unsigned pciDeviceGetManaged(pciDevice *dev)
+{
+ return dev->managed;
+}
+
+pciDeviceList *
+pciDeviceListNew(virConnectPtr conn)
+{
+ pciDeviceList *list;
+
+ if (VIR_ALLOC(list) < 0) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+
+ return list;
+}
+
+void
+pciDeviceListFree(virConnectPtr conn,
+ pciDeviceList *list)
+{
+ int i;
+
+ if (!list)
+ return;
+
+ for (i = 0; i < list->count; i++) {
+ pciFreeDevice(conn, list->devs[i]);
+ list->devs[i] = NULL;
+ }
+
+ list->count = 0;
+ VIR_FREE(list->devs);
+ VIR_FREE(list);
+}
+
+int
+pciDeviceListAdd(virConnectPtr conn,
+ pciDeviceList *list,
+ pciDevice *dev)
+{
+ if (pciDeviceListFind(list, dev)) {
+ pciReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Device %s is already in use"), dev->name);
+ return -1;
+ }
+
+ if (VIR_REALLOC_N(list->devs, list->count+1) < 0) {
+ virReportOOMError(conn);
+ return -1;
+ }
+
+ list->devs[list->count++] = dev;
+
+ return 0;
+}
+
+void
+pciDeviceListDel(virConnectPtr conn ATTRIBUTE_UNUSED,
+ pciDeviceList *list,
+ pciDevice *dev)
+{
+ int i;
+
+ for (i = 0; i < list->count; i++) {
+ if (list->devs[i]->domain != dev->domain ||
+ list->devs[i]->bus != dev->bus ||
+ list->devs[i]->slot != dev->slot ||
+ list->devs[i]->function != dev->function)
+ continue;
+
+ pciFreeDevice(conn, list->devs[i]);
+
+ if (i != --list->count)
+ memmove(&list->devs[i],
+ &list->devs[i+1],
+ sizeof(*list->devs) * (list->count-i));
+
+ if (VIR_REALLOC_N(list->devs, list->count) < 0) {
+ ; /* not fatal */
+ }
+
+ break;
+ }
+}
+
+pciDevice *
+pciDeviceListFind(pciDeviceList *list, pciDevice *dev)
+{
+ int i;
+
+ for (i = 0; i < list->count; i++)
+ if (list->devs[i]->domain == dev->domain &&
+ list->devs[i]->bus == dev->bus &&
+ list->devs[i]->slot == dev->slot &&
+ list->devs[i]->function == dev->function)
+ return list->devs[i];
+ return NULL;
+}
diff --git a/src/pci.h b/src/pci.h
index 47882ef..685b0af 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -27,6 +27,11 @@
typedef struct _pciDevice pciDevice;
+typedef struct {
+ unsigned count;
+ pciDevice **devs;
+} pciDeviceList;
+
pciDevice *pciGetDevice (virConnectPtr conn,
unsigned domain,
unsigned bus,
@@ -39,6 +44,22 @@ int pciDettachDevice (virConnectPtr conn,
int pciReAttachDevice (virConnectPtr conn,
pciDevice *dev);
int pciResetDevice (virConnectPtr conn,
- pciDevice *dev);
+ pciDevice *dev,
+ pciDeviceList *activeDevs);
+void pciDeviceSetManaged(pciDevice *dev,
+ unsigned managed);
+unsigned pciDeviceGetManaged(pciDevice *dev);
+
+pciDeviceList *pciDeviceListNew (virConnectPtr conn);
+void pciDeviceListFree (virConnectPtr conn,
+ pciDeviceList *list);
+int pciDeviceListAdd (virConnectPtr conn,
+ pciDeviceList *list,
+ pciDevice *dev);
+void pciDeviceListDel (virConnectPtr conn,
+ pciDeviceList *list,
+ pciDevice *dev);
+pciDevice * pciDeviceListFind (pciDeviceList *list,
+ pciDevice *dev);
#endif /* __VIR_PCI_H__ */
diff --git a/src/qemu_conf.h b/src/qemu_conf.h
index 517626a..ab9d5e1 100644
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -35,6 +35,7 @@
#include "threads.h"
#include "security.h"
#include "cgroup.h"
+#include "pci.h"
#define qemudDebug(fmt, ...) do {} while(0)
@@ -107,6 +108,8 @@ struct qemud_driver {
char *securityDriverName;
virSecurityDriverPtr securityDriver;
+
+ pciDeviceList *activePciHostdevs;
};
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index fd39fc2..cbc27c4 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -128,6 +128,9 @@ static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
static int qemudDetectVcpuPIDs(virConnectPtr conn,
virDomainObjPtr vm);
+static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
+ virDomainDefPtr def);
+
static struct qemud_driver *qemu_driver = NULL;
static int qemuCgroupControllerActive(struct qemud_driver *driver,
@@ -320,6 +323,10 @@ qemuReconnectDomain(struct qemud_driver *driver,
goto error;
}
+ if (qemuUpdateActivePciHostdevs(driver, obj->def) < 0) {
+ goto error;
+ }
+
if (obj->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
driver->securityDriver &&
driver->securityDriver->domainReserveSecurityLabel &&
@@ -524,6 +531,9 @@ qemudStartup(int privileged) {
if ((qemu_driver->caps = qemudCapsInit(NULL)) == NULL)
goto out_of_memory;
+ if ((qemu_driver->activePciHostdevs = pciDeviceListNew(NULL)) == NULL)
+ goto error;
+
if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
goto error;
}
@@ -648,6 +658,7 @@ qemudShutdown(void) {
return -1;
qemuDriverLock(qemu_driver);
+ pciDeviceListFree(NULL, qemu_driver->activePciHostdevs);
virCapabilitiesFree(qemu_driver->caps);
virDomainObjListFree(&qemu_driver->domains);
@@ -1329,48 +1340,16 @@ static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
return -1;
}
-static int qemuPrepareHostDevices(virConnectPtr conn,
- virDomainDefPtr def) {
+static pciDeviceList *
+qemuGetPciHostDeviceList(virConnectPtr conn,
+ virDomainDefPtr def)
+{
+ pciDeviceList *list;
int i;
- /* We have to use 2 loops here. *All* devices must
- * be detached before we reset any of them, because
- * in some cases you have to reset the whole PCI,
- * which impacts all devices on it
- */
-
- for (i = 0 ; i < def->nhostdevs ; i++) {
- virDomainHostdevDefPtr hostdev = def->hostdevs[i];
-
- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
- continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- continue;
-
- if (hostdev->managed) {
- pciDevice *dev = pciGetDevice(conn,
- hostdev->source.subsys.u.pci.domain,
- hostdev->source.subsys.u.pci.bus,
- hostdev->source.subsys.u.pci.slot,
- hostdev->source.subsys.u.pci.function);
- if (!dev)
- goto error;
-
- if (pciDettachDevice(conn, dev) < 0) {
- pciFreeDevice(conn, dev);
- goto error;
- }
-
- pciFreeDevice(conn, dev);
- } /* else {
- XXX validate that non-managed device isn't in use, eg
- by checking that device is either un-bound, or bound
- to pci-stub.ko
- } */
- }
+ if (!(list = pciDeviceListNew(conn)))
+ return NULL;
- /* Now that all the PCI hostdevs have be dettached, we can safely
- * reset them */
for (i = 0 ; i < def->nhostdevs ; i++) {
virDomainHostdevDefPtr hostdev = def->hostdevs[i];
pciDevice *dev;
@@ -1385,95 +1364,151 @@ static int qemuPrepareHostDevices(virConnectPtr conn,
hostdev->source.subsys.u.pci.bus,
hostdev->source.subsys.u.pci.slot,
hostdev->source.subsys.u.pci.function);
- if (!dev)
- goto error;
+ if (!dev) {
+ pciDeviceListFree(conn, list);
+ return NULL;
+ }
- if (pciResetDevice(conn, dev) < 0) {
+ if (pciDeviceListAdd(conn, list, dev) < 0) {
pciFreeDevice(conn, dev);
- goto error;
+ pciDeviceListFree(conn, list);
+ return NULL;
}
- pciFreeDevice(conn, dev);
+ pciDeviceSetManaged(dev, hostdev->managed);
}
- return 0;
+ return list;
+}
-error:
- return -1;
+static int
+qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
+ virDomainDefPtr def)
+{
+ pciDeviceList *pcidevs;
+ int i, ret;
+
+ if (!def->nhostdevs)
+ return 0;
+
+ if (!(pcidevs = qemuGetPciHostDeviceList(NULL, def)))
+ return -1;
+
+ ret = 0;
+
+ for (i = 0; i < pcidevs->count; i++) {
+ if (pciDeviceListAdd(NULL,
+ driver->activePciHostdevs,
+ pcidevs->devs[i]) < 0) {
+ ret = -1;
+ break;
+ }
+ pcidevs->devs[i] = NULL;
+ }
+
+ pciDeviceListFree(NULL, pcidevs);
+ return ret;
}
-static void
-qemuDomainReAttachHostDevices(virConnectPtr conn, virDomainDefPtr def)
+static int
+qemuPrepareHostDevices(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainDefPtr def)
{
+ pciDeviceList *pcidevs;
int i;
- /* Again 2 loops; reset all the devices before re-attach */
+ if (!def->nhostdevs)
+ return 0;
- for (i = 0 ; i < def->nhostdevs ; i++) {
- virDomainHostdevDefPtr hostdev = def->hostdevs[i];
- pciDevice *dev;
+ if (!(pcidevs = qemuGetPciHostDeviceList(conn, def)))
+ return -1;
- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
- continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- continue;
+ /* We have to use 3 loops here. *All* devices must
+ * be detached before we reset any of them, because
+ * in some cases you have to reset the whole PCI,
+ * which impacts all devices on it. Also, all devices
+ * must be reset before being marked as active.
+ */
- dev = pciGetDevice(conn,
- hostdev->source.subsys.u.pci.domain,
- hostdev->source.subsys.u.pci.bus,
- hostdev->source.subsys.u.pci.slot,
- hostdev->source.subsys.u.pci.function);
- if (!dev) {
- virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
- err ? err->message : "");
- virResetError(err);
- continue;
- }
+ /* XXX validate that non-managed device isn't in use, eg
+ * by checking that device is either un-bound, or bound
+ * to pci-stub.ko
+ */
- if (pciResetDevice(conn, dev) < 0) {
- virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to reset PCI device: %s\n"),
- err ? err->message : "");
- virResetError(err);
- }
+ for (i = 0; i < pcidevs->count; i++)
+ if (pciDeviceGetManaged(pcidevs->devs[i]) &&
+ pciDettachDevice(conn, pcidevs->devs[i]) < 0)
+ goto error;
+
+ /* Now that all the PCI hostdevs have be dettached, we can safely
+ * reset them */
+ for (i = 0; i < pcidevs->count; i++)
+ if (pciResetDevice(conn, pcidevs->devs[i],
+ driver->activePciHostdevs) < 0)
+ goto error;
- pciFreeDevice(conn, dev);
+ /* Now mark all the devices as active */
+ for (i = 0; i < pcidevs->count; i++) {
+ if (pciDeviceListAdd(conn,
+ driver->activePciHostdevs,
+ pcidevs->devs[i]) < 0)
+ goto error;
+ pcidevs->devs[i] = NULL;
}
- for (i = 0 ; i < def->nhostdevs ; i++) {
- virDomainHostdevDefPtr hostdev = def->hostdevs[i];
- pciDevice *dev;
+ pciDeviceListFree(conn, pcidevs);
+ return 0;
- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
- continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- continue;
- if (!hostdev->managed)
- continue;
+error:
+ pciDeviceListFree(conn, pcidevs);
+ return -1;
+}
- dev = pciGetDevice(conn,
- hostdev->source.subsys.u.pci.domain,
- hostdev->source.subsys.u.pci.bus,
- hostdev->source.subsys.u.pci.slot,
- hostdev->source.subsys.u.pci.function);
- if (!dev) {
+static void
+qemuDomainReAttachHostDevices(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainDefPtr def)
+{
+ pciDeviceList *pcidevs;
+ int i;
+
+ if (!def->nhostdevs)
+ return;
+
+ if (!(pcidevs = qemuGetPciHostDeviceList(conn, def))) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to allocate pciDeviceList: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ return;
+ }
+
+ /* Again 3 loops; mark all devices as inactive before reset
+ * them and reset all the devices before re-attach */
+
+ for (i = 0; i < pcidevs->count; i++)
+ pciDeviceListDel(conn, driver->activePciHostdevs, pcidevs->devs[i]);
+
+ for (i = 0; i < pcidevs->count; i++)
+ if (pciResetDevice(conn, pcidevs->devs[i],
+ driver->activePciHostdevs) < 0) {
virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
+ VIR_ERROR(_("Failed to reset PCI device: %s\n"),
err ? err->message : "");
virResetError(err);
- continue;
}
- if (pciReAttachDevice(conn, dev) < 0) {
+ for (i = 0; i < pcidevs->count; i++)
+ if (pciDeviceGetManaged(pcidevs->devs[i]) &&
+ pciReAttachDevice(conn, pcidevs->devs[i]) < 0) {
virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to re-attach PCI device: %s\n"),
err ? err->message : "");
virResetError(err);
}
- pciFreeDevice(conn, dev);
- }
+ pciDeviceListFree(conn, pcidevs);
}
static const char *const defaultDeviceACL[] = {
@@ -2001,7 +2036,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (qemuSetupCgroup(conn, driver, vm) < 0)
goto cleanup;
- if (qemuPrepareHostDevices(conn, vm->def) < 0)
+ if (qemuPrepareHostDevices(conn, driver, vm->def) < 0)
goto cleanup;
if (VIR_ALLOC(vm->monitor_chr) < 0) {
@@ -2183,7 +2218,7 @@ static void qemudShutdownVMDaemon(virConnectPtr conn,
VIR_WARN("Failed to restore all device ownership for %s",
vm->def->name);
- qemuDomainReAttachHostDevices(conn, vm->def);
+ qemuDomainReAttachHostDevices(conn, driver, vm->def);
retry:
if ((ret = qemuRemoveCgroup(conn, driver, vm)) < 0) {
@@ -6791,6 +6826,7 @@ out:
static int
qemudNodeDeviceReset (virNodeDevicePtr dev)
{
+ struct qemud_driver *driver = dev->conn->privateData;
pciDevice *pci;
unsigned domain, bus, slot, function;
int ret = -1;
@@ -6802,11 +6838,14 @@ qemudNodeDeviceReset (virNodeDevicePtr dev)
if (!pci)
return -1;
- if (pciResetDevice(dev->conn, pci) < 0)
+ qemuDriverLock(driver);
+
+ if (pciResetDevice(dev->conn, pci, driver->activePciHostdevs) < 0)
goto out;
ret = 0;
out:
+ qemuDriverUnlock(driver);
pciFreeDevice(dev->conn, pci);
return ret;
}
diff --git a/src/xen_unified.c b/src/xen_unified.c
index f2ffc25..dfa9ca5 100644
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -1641,7 +1641,7 @@ xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
if (!pci)
return -1;
- if (pciResetDevice(dev->conn, pci) < 0)
+ if (pciResetDevice(dev->conn, pci, NULL) < 0)
goto out;
ret = 0;
--
1.6.2.5
@@ -1,121 +0,0 @@
From 5aad00b08cadc4d9da8bffd3d255ffaac98d36dd Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 14 Aug 2009 08:31:11 +0100
Subject: [PATCH] Allow PM reset on multi-function PCI devices
https://bugzilla.redhat.com/515689
It turns out that a PCI Power Management reset only affects individual
functions, and not the whole device.
The PCI Power Management spec talks about resetting the 'device' rather
than the 'function', but Intel's Dexuan Cui informs me that it is
actually a per-function reset.
Also, Yu Zhao has added pci_pm_reset() to the kernel, and it doesn't
reject multi-function devices, so it must be true! :-)
(A side issue is that we could defer the PM reset to the kernel if we
could detect that the kernel has PM reset support, but barring version
number checks we don't have a way to detect that support)
* src/pci.c: remove the pciDeviceContainsOtherFunctions() check from
pciTryPowerManagementReset() and prefer PM reset over bus reset
where both are available
Cc: Cui, Dexuan <dexuan.cui@intel.com>
Cc: Yu Zhao <yu.zhao@intel.com>
(cherry picked from commit 64a6682b93a2a8aa38067a43979c9eaf993d2b41)
Fedora-patch: libvirt-allow-pm-reset-on-multi-function-pci-devices.patch
---
src/pci.c | 48 +++++++++---------------------------------------
1 files changed, 9 insertions(+), 39 deletions(-)
diff --git a/src/pci.c b/src/pci.c
index 2dc2e1c..11b3e8b 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -402,29 +402,6 @@ pciBusContainsOtherDevices(virConnectPtr conn, pciDevice *dev)
return 1;
}
-/* Any other functions on this device ? */
-static int
-pciSharesDevice(pciDevice *a, pciDevice *b)
-{
- return
- a->domain == b->domain &&
- a->bus == b->bus &&
- a->slot == b->slot &&
- a->function != b->function;
-}
-
-static int
-pciDeviceContainsOtherFunctions(virConnectPtr conn, pciDevice *dev)
-{
- pciDevice *matched = NULL;
- if (pciIterDevices(conn, pciSharesDevice, dev, &matched) < 0)
- return 1;
- if (!matched)
- return 0;
- pciFreeDevice(conn, matched);
- return 1;
-}
-
/* Is @a the parent of @b ? */
static int
pciIsParent(pciDevice *a, pciDevice *b)
@@ -529,7 +506,7 @@ out:
* above we require the device supports a full internal reset.
*/
static int
-pciTryPowerManagementReset(virConnectPtr conn, pciDevice *dev)
+pciTryPowerManagementReset(virConnectPtr conn ATTRIBUTE_UNUSED, pciDevice *dev)
{
uint8_t config_space[PCI_CONF_LEN];
uint32_t ctl;
@@ -537,16 +514,6 @@ pciTryPowerManagementReset(virConnectPtr conn, pciDevice *dev)
if (!dev->pci_pm_cap_pos)
return -1;
- /* For now, we just refuse to do a power management reset
- * if there are other functions on this device.
- * In future, we could allow it so long as those functions
- * are not in use by the host or other guests.
- */
- if (pciDeviceContainsOtherFunctions(conn, dev)) {
- VIR_WARN("%s contains other functions, not resetting", dev->name);
- return -1;
- }
-
/* Save and restore the device's config space. */
if (pciRead(dev, 0, &config_space[0], PCI_CONF_LEN) < 0) {
VIR_WARN("Failed to save PCI config space for %s", dev->name);
@@ -604,14 +571,17 @@ pciResetDevice(virConnectPtr conn, pciDevice *dev)
if (dev->has_flr)
return 0;
+ /* If the device supports PCI power management reset,
+ * that's the next best thing because it only resets
+ * the function, not the whole device.
+ */
+ if (dev->has_pm_reset)
+ ret = pciTryPowerManagementReset(conn, dev);
+
/* Bus reset is not an option with the root bus */
- if (dev->bus != 0)
+ if (ret < 0 && dev->bus != 0)
ret = pciTrySecondaryBusReset(conn, dev);
- /* Next best option is a PCI power management reset */
- if (ret < 0 && dev->has_pm_reset)
- ret = pciTryPowerManagementReset(conn, dev);
-
if (ret < 0)
pciReportError(conn, VIR_ERR_NO_SUPPORT,
_("No PCI reset capability available for %s"),
--
1.6.2.5
@@ -1,79 +0,0 @@
From 165fb333c9d954fec636dc0f1917ba50417478c0 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Sat, 15 Aug 2009 19:38:15 +0100
Subject: [PATCH] Fix list updating after disk/network hot-unplug
The current code makes a poor effort at updating the device arrays after
hot-unplug. Fix that and combine the two code paths into one.
* src/qemu_driver.c: fix list updating in qemudDomainDetachNetDevice() and
qemudDomainDetachPciDiskDevice()
(cherry picked from commit 4e12af5623e4a962a6bb911af06fa29aa85befba)
Fedora-patch: libvirt-fix-device-list-update-after-detach.patch
---
src/qemu_driver.c | 38 ++++++++++++++++++--------------------
1 files changed, 18 insertions(+), 20 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index bd58435..2c4fd6f 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -5404,18 +5404,17 @@ try_command:
goto cleanup;
}
- if (vm->def->ndisks > 1) {
- vm->def->disks[i] = vm->def->disks[--vm->def->ndisks];
- if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) {
- virReportOOMError(conn);
- goto cleanup;
- }
- qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
- virDomainDiskQSort);
- } else {
- VIR_FREE(vm->def->disks[0]);
- vm->def->ndisks = 0;
+ if (i != --vm->def->ndisks)
+ memmove(&vm->def->disks[i],
+ &vm->def->disks[i+1],
+ sizeof(*vm->def->disks) * (vm->def->ndisks-i));
+ if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
}
+ qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
+ virDomainDiskQSort);
+
ret = 0;
cleanup:
@@ -5503,16 +5502,15 @@ qemudDomainDetachNetDevice(virConnectPtr conn,
DEBUG("%s: host_net_remove reply: %s", vm->def->name, reply);
- if (vm->def->nnets > 1) {
- vm->def->nets[i] = vm->def->nets[--vm->def->nnets];
- if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets) < 0) {
- virReportOOMError(conn);
- goto cleanup;
- }
- } else {
- VIR_FREE(vm->def->nets[0]);
- vm->def->nnets = 0;
+ if (i != --vm->def->nnets)
+ memmove(&vm->def->nets[i],
+ &vm->def->nets[i+1],
+ sizeof(*vm->def->nets) * (vm->def->nnets-i));
+ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
}
+
ret = 0;
cleanup:
--
1.6.2.5
@@ -1,141 +0,0 @@
From c8a9dbe131713de83bdc67c563c4ab149e32c489 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 14 Aug 2009 08:31:11 +0100
Subject: [PATCH] Improve PCI host device reset error message
https://bugzilla.redhat.com/499678
Currently, if we are unable to reset a PCI device we return a fairly
generic 'No PCI reset capability available' error message.
Fix that by returning an error from the individual reset messages and
using that error to construct the higher level error mesage.
* src/pci.c: set errors in pciTryPowerManagementReset() and
pciTrySecondaryBusReset() on failure; use those error messages
in pciResetDevice(), or explain that no reset support is available
(cherry picked from commit ebea34185612c3b96d7d3bbd8b7c2ce6c9f4fe6f)
Fedora-patch: libvirt-improve-pci-hostdev-reset-error-message.patch
---
src/pci.c | 44 +++++++++++++++++++++++++++++++-------------
src/qemu_driver.c | 4 ++--
2 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/src/pci.c b/src/pci.c
index 11b3e8b..74f7ef0 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -456,15 +456,18 @@ pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
* are not in use by the host or other guests.
*/
if (pciBusContainsOtherDevices(conn, dev)) {
- VIR_WARN("Other devices on bus with %s, not doing bus reset",
- dev->name);
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Other devices on bus with %s, not doing bus reset"),
+ dev->name);
return -1;
}
/* Find the parent bus */
parent = pciGetParentDevice(conn, dev);
if (!parent) {
- VIR_WARN("Failed to find parent device for %s", dev->name);
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to find parent device for %s"),
+ dev->name);
return -1;
}
@@ -475,7 +478,9 @@ pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
* are multiple devices/functions
*/
if (pciRead(dev, 0, config_space, PCI_CONF_LEN) < 0) {
- VIR_WARN("Failed to save PCI config space for %s", dev->name);
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to save PCI config space for %s"),
+ dev->name);
goto out;
}
@@ -492,9 +497,12 @@ pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
usleep(200 * 1000); /* sleep 200ms */
- if (pciWrite(dev, 0, config_space, PCI_CONF_LEN) < 0)
- VIR_WARN("Failed to restore PCI config space for %s", dev->name);
-
+ if (pciWrite(dev, 0, config_space, PCI_CONF_LEN) < 0) {
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to restore PCI config space for %s"),
+ dev->name);
+ goto out;
+ }
ret = 0;
out:
pciFreeDevice(conn, parent);
@@ -516,7 +524,9 @@ pciTryPowerManagementReset(virConnectPtr conn ATTRIBUTE_UNUSED, pciDevice *dev)
/* Save and restore the device's config space. */
if (pciRead(dev, 0, &config_space[0], PCI_CONF_LEN) < 0) {
- VIR_WARN("Failed to save PCI config space for %s", dev->name);
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to save PCI config space for %s"),
+ dev->name);
return -1;
}
@@ -533,8 +543,12 @@ pciTryPowerManagementReset(virConnectPtr conn ATTRIBUTE_UNUSED, pciDevice *dev)
usleep(10 * 1000); /* sleep 10ms */
- if (pciWrite(dev, 0, &config_space[0], PCI_CONF_LEN) < 0)
- VIR_WARN("Failed to restore PCI config space for %s", dev->name);
+ if (pciWrite(dev, 0, &config_space[0], PCI_CONF_LEN) < 0) {
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to restore PCI config space for %s"),
+ dev->name);
+ return -1;
+ }
return 0;
}
@@ -582,10 +596,14 @@ pciResetDevice(virConnectPtr conn, pciDevice *dev)
if (ret < 0 && dev->bus != 0)
ret = pciTrySecondaryBusReset(conn, dev);
- if (ret < 0)
+ if (ret < 0) {
+ virErrorPtr err = virGetLastError();
pciReportError(conn, VIR_ERR_NO_SUPPORT,
- _("No PCI reset capability available for %s"),
- dev->name);
+ _("Unable to reset PCI device %s: %s"),
+ dev->name,
+ err ? err->message : _("no FLR, PM reset or bus reset available"));
+ }
+
return ret;
}
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 4ce7a54..fd39fc2 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1465,9 +1465,9 @@ qemuDomainReAttachHostDevices(virConnectPtr conn, virDomainDefPtr def)
continue;
}
- if (pciDettachDevice(conn, dev) < 0) {
+ if (pciReAttachDevice(conn, dev) < 0) {
virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to reset PCI device: %s\n"),
+ VIR_ERROR(_("Failed to re-attach PCI device: %s\n"),
err ? err->message : "");
virResetError(err);
}
--
1.6.2.5
@@ -1,124 +0,0 @@
From 8f26acc66ca90eea67fd5e84be5a76e3b8aa7fbf Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 14 Aug 2009 08:31:11 +0100
Subject: [PATCH] Reset and re-attach PCI host devices on guest shutdown
https://bugzilla.redhat.com/499561
When the guest shuts down, we should attempt to restore all PCI host
devices to a sane state.
In the case of managed hostdevs, we should reset and re-attach the
devices. In the case of unmanaged hostdevs, we should just reset them.
Note, KVM will already reset assigned devices when the guest shuts
down using whatever means it can, so we are only doing it to cover the
cases the kernel can't handle.
* src/qemu_driver.c: add qemuDomainReAttachHostDevices() and call
it from qemudShutdownVMDaemon()
(cherry picked from commit 4035152a8767e72fd4e26a91cb4d5afa75b72e61)
Fedora-patch: libvirt-reattach-pci-hostdevs-after-guest-shutdown.patch
---
src/qemu_driver.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 2c4fd6f..4ce7a54 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1402,6 +1402,80 @@ error:
return -1;
}
+static void
+qemuDomainReAttachHostDevices(virConnectPtr conn, virDomainDefPtr def)
+{
+ int i;
+
+ /* Again 2 loops; reset all the devices before re-attach */
+
+ for (i = 0 ; i < def->nhostdevs ; i++) {
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
+ pciDevice *dev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ continue;
+
+ dev = pciGetDevice(conn,
+ hostdev->source.subsys.u.pci.domain,
+ hostdev->source.subsys.u.pci.bus,
+ hostdev->source.subsys.u.pci.slot,
+ hostdev->source.subsys.u.pci.function);
+ if (!dev) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ continue;
+ }
+
+ if (pciResetDevice(conn, dev) < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to reset PCI device: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ }
+
+ pciFreeDevice(conn, dev);
+ }
+
+ for (i = 0 ; i < def->nhostdevs ; i++) {
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
+ pciDevice *dev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ continue;
+ if (!hostdev->managed)
+ continue;
+
+ dev = pciGetDevice(conn,
+ hostdev->source.subsys.u.pci.domain,
+ hostdev->source.subsys.u.pci.bus,
+ hostdev->source.subsys.u.pci.slot,
+ hostdev->source.subsys.u.pci.function);
+ if (!dev) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ continue;
+ }
+
+ if (pciDettachDevice(conn, dev) < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to reset PCI device: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ }
+
+ pciFreeDevice(conn, dev);
+ }
+}
+
static const char *const defaultDeviceACL[] = {
"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom",
@@ -2109,6 +2183,8 @@ static void qemudShutdownVMDaemon(virConnectPtr conn,
VIR_WARN("Failed to restore all device ownership for %s",
vm->def->name);
+ qemuDomainReAttachHostDevices(conn, vm->def);
+
retry:
if ((ret = qemuRemoveCgroup(conn, driver, vm)) < 0) {
if (ret == -EBUSY && (retries++ < 5)) {
--
1.6.2.5
+501 -425
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
8c2c14a7695c9c661004bcfc6468d62d libvirt-0.7.0.tar.gz
5f315b0bf20e3964f7657ba1e630cd67 libvirt-0.7.7.tar.gz