If libvirtd is running unprivileged, it is not able to read devices'
PCI config data from sysfs, and
qemuDomainDeviceCalculatePCIConnectFlags() will need to read the PCI
config data in to positively determine whether or not a device is an
Express device or a legacy PCI device.
In order to avoid creating a parallel "quiet" version of the function
that reads PCI config, this patch passes a virQEMUDriverPtr down
through all the call chains that that initialize the
qemuDomainFillDevicePCIConnectFlagsIterData, and saves the pointer
with the rest of the iterdata so that it can be used by
qemuDomainDeviceCalculatePCIConnectFlags(). This pointer isn't used
yet, but will be used in an upcoming patch (that detects Express vs
legacy PCI for VFIO assigned devices) to examine driver->privileged.
---
src/qemu/qemu_domain.c | 2 +-
src/qemu/qemu_domain_address.c | 33 +++++++++++++++++++++++----------
src/qemu/qemu_domain_address.h | 7 +++++--
src/qemu/qemu_hotplug.c | 19 ++++++++++---------
src/qemu/qemu_process.c | 13 +++++++++----
tests/qemuhotplugtest.c | 4 +++-
6 files changed, 51 insertions(+), 27 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 0f113a7..5642134 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -3123,7 +3123,7 @@ qemuDomainDefAssignAddresses(virDomainDef *def,
goto cleanup;
}
- if (qemuDomainAssignAddresses(def, qemuCaps, NULL, newDomain) < 0)
+ if (qemuDomainAssignAddresses(def, qemuCaps, driver, NULL, newDomain) < 0)
goto cleanup;
ret = 0;
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 15d7c1a..65753c5 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -428,6 +428,7 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
*/
static virDomainPCIConnectFlags
qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
+ virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
virDomainPCIConnectFlags pcieFlags,
virDomainPCIConnectFlags virtioFlags)
{
@@ -666,6 +667,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
typedef struct {
virDomainPCIConnectFlags virtioFlags;
virDomainPCIConnectFlags pcieFlags;
+ virQEMUDriverPtr driver;
} qemuDomainFillDevicePCIConnectFlagsIterData;
@@ -678,8 +680,12 @@ typedef struct {
static void
qemuDomainFillDevicePCIConnectFlagsIterInit(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
+ virQEMUDriverPtr driver,
qemuDomainFillDevicePCIConnectFlagsIterData
*data)
{
+
+ data->driver = driver;
+
if (qemuDomainMachineHasPCIeRoot(def)) {
data->pcieFlags = (VIR_PCI_CONNECT_TYPE_PCIE_DEVICE |
VIR_PCI_CONNECT_HOTPLUGGABLE);
@@ -719,7 +725,8 @@ qemuDomainFillDevicePCIConnectFlagsIter(virDomainDefPtr def
ATTRIBUTE_UNUSED,
qemuDomainFillDevicePCIConnectFlagsIterData *data = opaque;
info->pciConnectFlags
- = qemuDomainDeviceCalculatePCIConnectFlags(dev, data->pcieFlags,
+ = qemuDomainDeviceCalculatePCIConnectFlags(dev, data->driver,
+ data->pcieFlags,
data->virtioFlags);
return 0;
}
@@ -739,11 +746,12 @@ qemuDomainFillDevicePCIConnectFlagsIter(virDomainDefPtr def
ATTRIBUTE_UNUSED,
*/
static int
qemuDomainFillAllPCIConnectFlags(virDomainDefPtr def,
- virQEMUCapsPtr qemuCaps)
+ virQEMUCapsPtr qemuCaps,
+ virQEMUDriverPtr driver)
{
qemuDomainFillDevicePCIConnectFlagsIterData data;
- qemuDomainFillDevicePCIConnectFlagsIterInit(def, qemuCaps, &data);
+ qemuDomainFillDevicePCIConnectFlagsIterInit(def, qemuCaps, driver, &data);
return virDomainDeviceInfoIterate(def,
qemuDomainFillDevicePCIConnectFlagsIter,
@@ -765,7 +773,8 @@ qemuDomainFillAllPCIConnectFlags(virDomainDefPtr def,
static void
qemuDomainFillDevicePCIConnectFlags(virDomainDefPtr def,
virDomainDeviceDefPtr dev,
- virQEMUCapsPtr qemuCaps)
+ virQEMUCapsPtr qemuCaps,
+ virQEMUDriverPtr driver)
{
virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
@@ -781,10 +790,11 @@ qemuDomainFillDevicePCIConnectFlags(virDomainDefPtr def,
*/
qemuDomainFillDevicePCIConnectFlagsIterData data;
- qemuDomainFillDevicePCIConnectFlagsIterInit(def, qemuCaps, &data);
+ qemuDomainFillDevicePCIConnectFlagsIterInit(def, qemuCaps, driver, &data);
info->pciConnectFlags
- = qemuDomainDeviceCalculatePCIConnectFlags(dev, data.pcieFlags,
+ = qemuDomainDeviceCalculatePCIConnectFlags(dev, data.driver,
+ data.pcieFlags,
data.virtioFlags);
}
}
@@ -1851,6 +1861,7 @@ qemuDomainAddressFindNewBusNr(virDomainDefPtr def)
static int
qemuDomainAssignPCIAddresses(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
+ virQEMUDriverPtr driver,
virDomainObjPtr obj)
{
int ret = -1;
@@ -1877,7 +1888,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
* of all devices. This will be used to pick an appropriate
* bus when assigning addresses.
*/
- if (qemuDomainFillAllPCIConnectFlags(def, qemuCaps) < 0)
+ if (qemuDomainFillAllPCIConnectFlags(def, qemuCaps, driver) < 0)
goto cleanup;
if (nbuses > 0 &&
@@ -1991,7 +2002,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
dev.type = VIR_DOMAIN_DEVICE_CONTROLLER;
dev.data.controller = def->controllers[contIndex];
/* set connect flags so it will be properly addressed */
- qemuDomainFillDevicePCIConnectFlags(def, &dev, qemuCaps);
+ qemuDomainFillDevicePCIConnectFlags(def, &dev, qemuCaps, driver);
if (qemuDomainPCIAddressReserveNextSlot(addrs,
&dev.data.controller->info)
< 0)
goto cleanup;
@@ -2273,6 +2284,7 @@ qemuDomainAssignUSBAddresses(virDomainDefPtr def,
int
qemuDomainAssignAddresses(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
+ virQEMUDriverPtr driver,
virDomainObjPtr obj,
bool newDomain)
{
@@ -2287,7 +2299,7 @@ qemuDomainAssignAddresses(virDomainDefPtr def,
qemuDomainAssignARMVirtioMMIOAddresses(def, qemuCaps);
- if (qemuDomainAssignPCIAddresses(def, qemuCaps, obj) < 0)
+ if (qemuDomainAssignPCIAddresses(def, qemuCaps, driver, obj) < 0)
return -1;
if (qemuDomainAssignUSBAddresses(def, obj, newDomain) < 0)
@@ -2313,12 +2325,13 @@ qemuDomainAssignAddresses(virDomainDefPtr def,
*/
int
qemuDomainEnsurePCIAddress(virDomainObjPtr obj,
+ virQEMUDriverPtr driver,
virDomainDeviceDefPtr dev)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
- qemuDomainFillDevicePCIConnectFlags(obj->def, dev, priv->qemuCaps);
+ qemuDomainFillDevicePCIConnectFlags(obj->def, dev, priv->qemuCaps, driver);
return virDomainPCIAddressEnsureAddr(priv->pciaddrs, info,
info->pciConnectFlags);
diff --git a/src/qemu/qemu_domain_address.h b/src/qemu/qemu_domain_address.h
index 800859c..0cdfacb 100644
--- a/src/qemu/qemu_domain_address.h
+++ b/src/qemu/qemu_domain_address.h
@@ -25,6 +25,7 @@
# include "domain_addr.h"
# include "domain_conf.h"
+# include "qemu_conf.h"
# include "qemu_capabilities.h"
int qemuDomainSetSCSIControllerModel(const virDomainDef *def,
@@ -33,13 +34,15 @@ int qemuDomainSetSCSIControllerModel(const virDomainDef *def,
int qemuDomainAssignAddresses(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
+ virQEMUDriverPtr driver,
virDomainObjPtr obj,
bool newDomain)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuDomainEnsurePCIAddress(virDomainObjPtr obj,
+ virQEMUDriverPtr driver,
virDomainDeviceDefPtr dev)
- ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
virDomainDeviceInfoPtr info,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 41731ab..dc424d0 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -345,7 +345,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn,
goto error;
} else if (!disk->info.type ||
disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
- if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
+ if (qemuDomainEnsurePCIAddress(vm, driver, &dev) < 0)
goto error;
}
releaseaddr = true;
@@ -504,7 +504,7 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver,
if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
- if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
+ if (qemuDomainEnsurePCIAddress(vm, driver, &dev) < 0)
goto cleanup;
} else if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
@@ -1135,7 +1135,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("virtio-s390 net device cannot be hotplugged."));
goto cleanup;
- } else if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) {
+ } else if (qemuDomainEnsurePCIAddress(vm, driver, &dev) < 0) {
goto cleanup;
}
@@ -1436,7 +1436,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1)
< 0)
goto error;
- if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
+ if (qemuDomainEnsurePCIAddress(vm, driver, &dev) < 0)
goto error;
releaseaddr = true;
if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO &&
@@ -1767,7 +1767,8 @@ qemuDomainChrRemove(virDomainDefPtr vmdef,
* 0 otherwise
*/
static int
-qemuDomainAttachChrDeviceAssignAddr(virDomainObjPtr vm,
+qemuDomainAttachChrDeviceAssignAddr(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
virDomainChrDefPtr chr)
{
virDomainDefPtr def = vm->def;
@@ -1782,7 +1783,7 @@ qemuDomainAttachChrDeviceAssignAddr(virDomainObjPtr vm,
} else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI) {
- if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
+ if (qemuDomainEnsurePCIAddress(vm, driver, &dev) < 0)
return -1;
return 1;
@@ -1841,7 +1842,7 @@ int qemuDomainAttachChrDevice(virConnectPtr conn,
if (qemuAssignDeviceChrAlias(vmdef, chr, -1) < 0)
goto cleanup;
- if ((rc = qemuDomainAttachChrDeviceAssignAddr(vm, chr)) < 0)
+ if ((rc = qemuDomainAttachChrDeviceAssignAddr(driver, vm, chr)) < 0)
goto cleanup;
if (rc == 1)
need_release = true;
@@ -1981,7 +1982,7 @@ qemuDomainAttachRNGDevice(virConnectPtr conn,
if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
- if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
+ if (qemuDomainEnsurePCIAddress(vm, driver, &dev) < 0)
goto cleanup;
} else if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
@@ -2521,7 +2522,7 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
if ((shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
- (qemuDomainEnsurePCIAddress(vm, &dev) < 0))
+ (qemuDomainEnsurePCIAddress(vm, driver, &dev) < 0))
return -1;
if (!(shmstr = qemuBuildShmemDevStr(vm->def, shmem, priv->qemuCaps)))
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1b67aee..a404471 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3350,8 +3350,10 @@ qemuProcessReconnect(void *opaque)
goto cleanup;
}
- if ((qemuDomainAssignAddresses(obj->def, priv->qemuCaps, obj, false)) < 0)
+ if ((qemuDomainAssignAddresses(obj->def, priv->qemuCaps,
+ driver, obj, false)) < 0) {
goto error;
+ }
/* if domain requests security driver we haven't loaded, report error, but
* do not kill the domain
@@ -5136,9 +5138,10 @@ qemuProcessPrepareDomain(virConnectPtr conn,
* use in hotplug
*/
VIR_DEBUG("Assigning domain PCI addresses");
- if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm,
- !!(flags & VIR_QEMU_PROCESS_START_NEW))) < 0)
+ if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, driver, vm,
+ !!(flags & VIR_QEMU_PROCESS_START_NEW))) < 0)
{
goto cleanup;
+ }
if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
goto cleanup;
@@ -6344,8 +6347,10 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
* use in hotplug
*/
VIR_DEBUG("Assigning domain PCI addresses");
- if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm, false)) < 0)
+ if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps,
+ driver, vm, false)) < 0) {
goto error;
+ }
if ((timestamp = virTimeStringNow()) == NULL)
goto error;
diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
index 89e870c..f0a8453 100644
--- a/tests/qemuhotplugtest.c
+++ b/tests/qemuhotplugtest.c
@@ -90,8 +90,10 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt,
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
goto cleanup;
- if (qemuDomainAssignAddresses((*vm)->def, priv->qemuCaps, *vm, true) < 0)
+ if (qemuDomainAssignAddresses((*vm)->def, priv->qemuCaps,
+ &driver, *vm, true) < 0) {
goto cleanup;
+ }
if (qemuAssignDeviceAliases((*vm)->def, priv->qemuCaps) < 0)
goto cleanup;
--
2.7.4