qemu: snapshot: Acquire job earlier on snapshot revert/delete

The code would lookup the snapshot object before acquiring the job. This
could lead to a crash as one thread could delete the snapshot object,
while a second thread already had the reference.

Signed-off-by: Jincheng Miao <jmiao@redhat.com>
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
Jincheng Miao 2014-08-28 19:27:04 +08:00 committed by Peter Krempa
parent b3d2a42e80
commit a4065dc3e7

View File

@ -14010,9 +14010,12 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
goto cleanup;
}
if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
goto endjob;
if (!vm->persistent &&
snap->def->state != VIR_DOMAIN_RUNNING &&
snap->def->state != VIR_DOMAIN_PAUSED &&
@ -14021,13 +14024,13 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("transient domain needs to request run or pause "
"to revert to inactive snapshot"));
goto cleanup;
goto endjob;
}
if (virDomainSnapshotIsExternal(snap)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("revert to external snapshot not supported yet"));
goto cleanup;
goto endjob;
}
if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_FORCE)) {
@ -14035,7 +14038,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY,
_("snapshot '%s' lacks domain '%s' rollback info"),
snap->def->name, vm->def->name);
goto cleanup;
goto endjob;
}
if (virDomainObjIsActive(vm) &&
!(snap->def->state == VIR_DOMAIN_RUNNING
@ -14044,7 +14047,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED))) {
virReportError(VIR_ERR_SNAPSHOT_REVERT_RISKY, "%s",
_("must respawn qemu to start inactive snapshot"));
goto cleanup;
goto endjob;
}
}
@ -14053,7 +14056,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
vm->current_snapshot->def->current = false;
if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
cfg->snapshotDir) < 0)
goto cleanup;
goto endjob;
vm->current_snapshot = NULL;
/* XXX Should we restore vm->current_snapshot after this point
* in the failure cases where we know there was no change? */
@ -14068,12 +14071,9 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
if (snap->def->dom) {
config = virDomainDefCopy(snap->def->dom, caps, driver->xmlopt, true);
if (!config)
goto cleanup;
goto endjob;
}
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
switch ((virDomainState) snap->def->state) {
case VIR_DOMAIN_RUNNING:
case VIR_DOMAIN_PAUSED:
@ -14383,9 +14383,12 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
if (virDomainSnapshotDeleteEnsureACL(snapshot->domain->conn, vm->def) < 0)
goto cleanup;
if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot)))
goto endjob;
if (!metadata_only) {
if (!(flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) &&
virDomainSnapshotIsExternal(snap))
@ -14398,13 +14401,10 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("deletion of %d external disk snapshots not "
"supported yet"), external);
goto cleanup;
goto endjob;
}
}
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
if (flags & (VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY)) {
rem.driver = driver;