After [1] we basically ignore qemu block job event if there is no
correspondent block job object in libvirt. Thus we need to refresh backing
chain after we reconnect block jobs or we can miss events that change backing
chain.
There is also another reason for it. I'm not sure of result if both libvirt is
reading images metadata on refreshing backing chain and qemu is writing
metadata on block job completion.
Reconnection code that depends on backing chain will be moved appropriately in
a different patch.
[1] qemu: add option to process offloaded legacy blockjob event ealier
Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
---
src/qemu/qemu_process.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 46a39ac..0d50db5 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -8193,9 +8193,15 @@ static int
qemuProcessRefreshLegacyBlockjobs(virQEMUDriverPtr driver,
virDomainObjPtr vm)
{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
g_autoptr(GHashTable) blockJobs = NULL;
size_t i;
+ if (priv->reconnectBlockjobs == VIR_TRISTATE_BOOL_NO) {
+ VIR_DEBUG("skipping block job reconnection");
+ return 0;
+ }
+
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
g_autoptr(qemuBlockJobData) job = NULL;
@@ -8221,9 +8227,25 @@ qemuProcessRefreshLegacyBlockjobs(virQEMUDriverPtr driver,
*/
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
- qemuBlockJobDataPtr job = qemuBlockJobDiskGetJob(disk);
+ g_autoptr(qemuBlockJobData) job = qemuBlockJobDiskGetJob(disk);
qemuBlockJobStartupFinalize(vm, job);
+
+ if ((job = qemuBlockJobDiskGetJob(disk)))
+ continue;
+
+ if (!disk->mirror) {
+ /* This should be the only place that calls
+ * qemuDomainDetermineDiskChain with @report_broken == false
+ * to guarantee best-effort domain reconnect */
+ virStorageSourceBackingStoreClear(disk->src);
+ if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL, false) < 0)
+ return -1;
+ }
+ /*
+ * TODO we need code to properly reconnect for mirror blockjobs
+ * that completed while libvirtd was down.
+ */
}
return 0;
@@ -8360,19 +8382,6 @@ qemuProcessReconnect(void *opaque)
if (virDomainDiskTranslateSourcePool(disk) < 0)
goto error;
- /* backing chains need to be refreshed only if they could change */
- if (priv->reconnectBlockjobs != VIR_TRISTATE_BOOL_NO &&
- !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
- /* This should be the only place that calls
- * qemuDomainDetermineDiskChain with @report_broken == false
- * to guarantee best-effort domain reconnect */
- virStorageSourceBackingStoreClear(disk->src);
- if (qemuDomainDetermineDiskChain(driver, obj, disk, NULL, false) < 0)
- goto error;
- } else {
- VIR_DEBUG("skipping backing chain detection for '%s'",
disk->dst);
- }
-
dev.type = VIR_DOMAIN_DEVICE_DISK;
dev.data.disk = disk;
if (qemuAddSharedDevice(driver, &dev, obj->def->name) < 0)
--
1.8.3.1