From f04bdf5368e00bc4ff11f71a0455feda1166ea61 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Thu, 24 Jan 2019 10:35:48 +0100 Subject: [PATCH] qemu: Don't double-free disk->mirror if block commit initialization fails disk->mirror would not be cleared while the local pointer was freed in qemuDomainBlockCommit if qemuDomainObjExitMonitor or qemuBlockJobDiskNew would return a failure. Since block job handling is executed in the separate handler which needs a qemu job, we don't need to pre-set the mirror state prior to starting the job. Similarly the block copy job does not do that. Move the setting of the data after starting the job so that we avoid this problem. Signed-off-by: Peter Krempa Reviewed-by: John Ferlan --- src/qemu/qemu_driver.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index af89f6de3b..f6fba3a6ad 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18175,6 +18175,8 @@ qemuDomainBlockCommit(virDomainPtr dom, disk->dst); goto endjob; } + + jobtype = QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT; } else if (flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) { virReportError(VIR_ERR_INVALID_ARG, _("active commit requested but '%s' is not active"), @@ -18247,22 +18249,16 @@ qemuDomainBlockCommit(virDomainPtr dom, qemuDomainDiskChainElementPrepare(driver, vm, top_parent, false, false) < 0)) goto endjob; + if (!(job = qemuBlockJobDiskNew(disk, jobtype, device))) + goto endjob; + + disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE; + /* Start the commit operation. Pass the user's original spelling, * if any, through to qemu, since qemu may behave differently * depending on whether the input was specified as relative or * absolute (that is, our absolute top_canon may do the wrong - * thing if the user specified a relative name). Be prepared for - * a ready event to occur while locks are dropped. */ - if (mirror) { - disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE; - disk->mirror = mirror; - disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT; - jobtype = QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT; - } - - if (!(job = qemuBlockJobDiskNew(disk, jobtype, device))) - goto endjob; - + * thing if the user specified a relative name). */ qemuDomainObjEnterMonitor(driver, vm); basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src, baseSource); @@ -18272,17 +18268,15 @@ qemuDomainBlockCommit(virDomainPtr dom, ret = qemuMonitorBlockCommit(priv->mon, device, topPath, basePath, backingPath, speed); - if (qemuDomainObjExitMonitor(driver, vm) < 0) { + if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0) { ret = -1; goto endjob; } - if (ret == 0) { - qemuBlockJobStarted(job); - mirror = NULL; - } else { - disk->mirror = NULL; - disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; + qemuBlockJobStarted(job); + if (mirror) { + VIR_STEAL_PTR(disk->mirror, mirror); + disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT; } if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)