]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: snapshot: Acquire job earlier on snapshot revert/delete
authorJincheng Miao <jmiao@redhat.com>
Thu, 28 Aug 2014 11:27:04 +0000 (19:27 +0800)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 8 Sep 2014 09:51:33 +0000 (11:51 +0200)
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>
src/qemu/qemu_driver.c

index 90c79eaa82abe3ae9290b97d64b785c71a25837d..8c222cc39133dcc1c78b66cc310505c3f6de9f62 100644 (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;