On Thu, Feb 11, 2010 at 04:40:43PM +0000, Daniel P. Berrange wrote:
Current PCI addresses are allocated at time of VM startup.
To make them truely persistent, it is neccessary to do this
at time of virDomainDefine/virDomainCreate. The code in
qemuStartVMDaemon still remains in order to cope with upgrades
from older libvirt releases
* src/qemu/qemu_driver.c: Rename existing qemuAssignPCIAddresses
to qemuDetectPCIAddresses. Add new qemuAssignPCIAddresses which
does auto-allocation upfront. Call qemuAssignPCIAddresses from
qemuDomainDefine and qemuDomainCreate to assign PCI addresses that
can then be persisted. Don't clear PCI addresses at shutdown if
they are intended to be persistent
---
src/qemu/qemu_driver.c | 84 +++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 79 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 03d0f5f..69187fc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -95,6 +95,7 @@ struct _qemuDomainObjPrivate {
int *vcpupids;
qemuDomainPCIAddressSetPtr pciaddrs;
+ int persistentAddrs;
};
static int qemudShutdown(void);
@@ -857,6 +858,7 @@ qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED,
void *opaq
virDomainObjPtr obj = payload;
struct qemud_driver *driver = opaque;
qemuDomainObjPrivatePtr priv;
+ unsigned long long qemuCmdFlags;
virDomainObjLock(obj);
@@ -872,6 +874,15 @@ qemuReconnectDomain(void *payload, const char *name
ATTRIBUTE_UNUSED, void *opaq
goto error;
}
+ /* XXX we should be persisting the original flags in the XML
+ * not re-detecting them, since the binary may have changed
+ * since launch time */
But where would we store them ? It sounds a bit strange, it's emulator
properties, not really domain ones, and I think we sound only store in
the domain what specific flags might be needed from the emulator, not
the full set (and this could change over time as a domain is being
modified).
+ if (qemudExtractVersionInfo(obj->def->emulator,
+ NULL,
+ &qemuCmdFlags) >= 0 &&
+ (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
+ priv->persistentAddrs = 1;
+
if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(obj->def)))
goto error;
@@ -1976,7 +1987,7 @@ qemuGetPCIWatchdogVendorProduct(virDomainWatchdogDefPtr def,
* some static addrs on CLI. Have to check that...
*/
static int
-qemuAssignPCIAddresses(virDomainObjPtr vm,
+qemuDetectPCIAddresses(virDomainObjPtr vm,
qemuMonitorPCIAddress *addrs,
int naddrs)
{
@@ -2098,7 +2109,7 @@ qemuInitPCIAddresses(struct qemud_driver *driver,
&addrs);
qemuDomainObjExitMonitorWithDriver(driver, vm);
- ret = qemuAssignPCIAddresses(vm, addrs, naddrs);
+ ret = qemuDetectPCIAddresses(vm, addrs, naddrs);
VIR_FREE(addrs);
@@ -2141,6 +2152,44 @@ static int qemudNextFreeVNCPort(struct qemud_driver *driver
ATTRIBUTE_UNUSED) {
return -1;
}
+
+static int
+qemuAssignPCIAddresses(virDomainDefPtr def)
+{
+ int ret = -1;
+ unsigned long long qemuCmdFlags = 0;
+ qemuDomainPCIAddressSetPtr addrs = NULL;
+ struct stat sb;
+
+ if (stat(def->emulator, &sb) < 0) {
+ virReportSystemError(errno,
+ _("Cannot find QEMU binary %s"),
+ def->emulator);
+ goto cleanup;
+ }
do we really need to update that every time ? We can't cache forever
but it's not like the emulator is changing every second. Maybe we need
to put a watch on the emulator at the driver level and keep this in
the driver.
+ if (qemudExtractVersionInfo(def->emulator,
+ NULL,
+ &qemuCmdFlags) < 0)
+ goto cleanup;
+
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+ if (!(addrs = qemuDomainPCIAddressSetCreate(def)))
+ goto cleanup;
+
+ if (qemuAssignDevicePCISlots(def, addrs) < 0)
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ qemuDomainPCIAddressSetFree(addrs);
+
+ return ret;
+}
+
+
static pciDeviceList *
qemuGetPciHostDeviceList(virDomainDefPtr def)
{
@@ -2662,7 +2711,15 @@ static int qemudStartVMDaemon(virConnectPtr conn,
goto cleanup;
}
+ /*
+ * Normally PCI addresses are assigned inhe virDomainCreate
+ * or virDomainDefine methods. We might still need to assign
+ * some here to cope with the question of upgrades. Regardless
+ * we also need to populate the PCi address set cache for later
+ * use in hotplug
+ */
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+ /* Populate cache with current addresses */
if (priv->pciaddrs) {
qemuDomainPCIAddressSetFree(priv->pciaddrs);
priv->pciaddrs = NULL;
@@ -2670,8 +2727,14 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (!(priv->pciaddrs = qemuDomainPCIAddressSetCreate(vm->def)))
goto cleanup;
+
+ /* Assign any remaining addresses */
if (qemuAssignDevicePCISlots(vm->def, priv->pciaddrs) < 0)
goto cleanup;
+
+ priv->persistentAddrs = 1;
+ } else {
+ priv->persistentAddrs = 0;
}
vm->def->id = driver->nextvmid++;
@@ -2903,10 +2966,12 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
VIR_FREE(vm->def->seclabel.imagelabel);
}
- virDomainDefClearPCIAddresses(vm->def);
virDomainDefClearDeviceAliases(vm->def);
- qemuDomainPCIAddressSetFree(priv->pciaddrs);
- priv->pciaddrs = NULL;
+ if (!priv->persistentAddrs) {
+ virDomainDefClearPCIAddresses(vm->def);
+ qemuDomainPCIAddressSetFree(priv->pciaddrs);
+ priv->pciaddrs = NULL;
+ }
qemuDomainReAttachHostDevices(driver, vm->def);
@@ -3352,6 +3417,12 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const
char *xml,
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
goto cleanup;
+ if (qemudCanonicalizeMachine(driver, def) < 0)
+ goto cleanup;
+
+ if (qemuAssignPCIAddresses(def) < 0)
+ goto cleanup;
+
if (!(vm = virDomainAssignDef(driver->caps,
&driver->domains,
def)))
@@ -5049,6 +5120,9 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const
char *xml) {
if (qemudCanonicalizeMachine(driver, def) < 0)
goto cleanup;
+ if (qemuAssignPCIAddresses(def) < 0)
+ goto cleanup;
+
if (!(vm = virDomainAssignDef(driver->caps,
&driver->domains,
def))) {
ACK,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit
http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/