提交 2412babe 编写于 作者: M Matthias Bolte

qemu: Reparent children when deleting a snapshot

Shorten qemuDomainSnapshotWriteSnapshotMetadata function name
and make it take a snapshot pointer instead of dealing with
the current snapshot. Update other functions accordingly.

Add a qemuDomainSnapshotReparentChildren hash iterator to
reparent the children of a snapshot that is being deleted. Use
qemuDomainSnapshotWriteMetadata to write updated metadata
to disk.

This fixes a problem where outdated parent information breaks
the snapshot tree and hinders the deletion of child snapshots.

Reported by Philipp Hahn.
上级 3ed3198a
...@@ -2607,10 +2607,10 @@ qemuPrepareMonitorChr(struct qemud_driver *driver, ...@@ -2607,10 +2607,10 @@ qemuPrepareMonitorChr(struct qemud_driver *driver,
return 0; return 0;
} }
static int qemuDomainSnapshotSetActive(virDomainObjPtr vm, static int qemuDomainSnapshotSetCurrentActive(virDomainObjPtr vm,
char *snapshotDir); char *snapshotDir);
static int qemuDomainSnapshotSetInactive(virDomainObjPtr vm, static int qemuDomainSnapshotSetCurrentInactive(virDomainObjPtr vm,
char *snapshotDir); char *snapshotDir);
#define START_POSTFIX ": starting up\n" #define START_POSTFIX ": starting up\n"
...@@ -2807,7 +2807,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, ...@@ -2807,7 +2807,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
vm->current_snapshot, vmop))) vm->current_snapshot, vmop)))
goto cleanup; goto cleanup;
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0) if (qemuDomainSnapshotSetCurrentInactive(vm, driver->snapshotDir) < 0)
goto cleanup; goto cleanup;
/* now that we know it is about to start call the hook if present */ /* now that we know it is about to start call the hook if present */
...@@ -9472,8 +9472,9 @@ static char *qemuFindQemuImgBinary(void) ...@@ -9472,8 +9472,9 @@ static char *qemuFindQemuImgBinary(void)
return ret; return ret;
} }
static int qemuDomainSnapshotWriteSnapshotMetadata(virDomainObjPtr vm, static int qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
char *snapshotDir) virDomainSnapshotObjPtr snapshot,
char *snapshotDir)
{ {
int fd = -1; int fd = -1;
char *newxml = NULL; char *newxml = NULL;
...@@ -9484,7 +9485,7 @@ static int qemuDomainSnapshotWriteSnapshotMetadata(virDomainObjPtr vm, ...@@ -9484,7 +9485,7 @@ static int qemuDomainSnapshotWriteSnapshotMetadata(virDomainObjPtr vm,
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(vm->def->uuid, uuidstr); virUUIDFormat(vm->def->uuid, uuidstr);
newxml = virDomainSnapshotDefFormat(uuidstr, vm->current_snapshot->def, 1); newxml = virDomainSnapshotDefFormat(uuidstr, snapshot->def, 1);
if (newxml == NULL) { if (newxml == NULL) {
virReportOOMError(); virReportOOMError();
return -1; return -1;
...@@ -9501,8 +9502,7 @@ static int qemuDomainSnapshotWriteSnapshotMetadata(virDomainObjPtr vm, ...@@ -9501,8 +9502,7 @@ static int qemuDomainSnapshotWriteSnapshotMetadata(virDomainObjPtr vm,
goto cleanup; goto cleanup;
} }
if (virAsprintf(&snapFile, "%s/%s.xml", snapDir, if (virAsprintf(&snapFile, "%s/%s.xml", snapDir, snapshot->def->name) < 0) {
vm->current_snapshot->def->name) < 0) {
virReportOOMError(); virReportOOMError();
goto cleanup; goto cleanup;
} }
...@@ -9528,25 +9528,27 @@ cleanup: ...@@ -9528,25 +9528,27 @@ cleanup:
return ret; return ret;
} }
static int qemuDomainSnapshotSetActive(virDomainObjPtr vm, static int qemuDomainSnapshotSetCurrentActive(virDomainObjPtr vm,
char *snapshotDir) char *snapshotDir)
{ {
if (vm->current_snapshot) { if (vm->current_snapshot) {
vm->current_snapshot->def->active = 1; vm->current_snapshot->def->active = 1;
return qemuDomainSnapshotWriteSnapshotMetadata(vm, snapshotDir); return qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
snapshotDir);
} }
return 0; return 0;
} }
static int qemuDomainSnapshotSetInactive(virDomainObjPtr vm, static int qemuDomainSnapshotSetCurrentInactive(virDomainObjPtr vm,
char *snapshotDir) char *snapshotDir)
{ {
if (vm->current_snapshot) { if (vm->current_snapshot) {
vm->current_snapshot->def->active = 0; vm->current_snapshot->def->active = 0;
return qemuDomainSnapshotWriteSnapshotMetadata(vm, snapshotDir); return qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
snapshotDir);
} }
return 0; return 0;
...@@ -9686,8 +9688,9 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain, ...@@ -9686,8 +9688,9 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
/* Now we set the new current_snapshot for the domain */ /* Now we set the new current_snapshot for the domain */
vm->current_snapshot = snap; vm->current_snapshot = snap;
if (qemuDomainSnapshotWriteSnapshotMetadata(vm, driver->snapshotDir) < 0) if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
/* qemuDomainSnapshotWriteSnapshotMetadata set the error */ driver->snapshotDir) < 0)
/* qemuDomainSnapshotWriteMetadata set the error */
goto cleanup; goto cleanup;
snapshot = virGetDomainSnapshot(domain, snap->def->name); snapshot = virGetDomainSnapshot(domain, snap->def->name);
...@@ -9941,13 +9944,13 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, ...@@ -9941,13 +9944,13 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
goto endjob; goto endjob;
} }
else { else {
if (qemuDomainSnapshotSetActive(vm, driver->snapshotDir) < 0) if (qemuDomainSnapshotSetCurrentActive(vm, driver->snapshotDir) < 0)
goto endjob; goto endjob;
rc = qemudStartVMDaemon(snapshot->domain->conn, driver, vm, NULL, rc = qemudStartVMDaemon(snapshot->domain->conn, driver, vm, NULL,
false, -1, NULL, VIR_VM_OP_CREATE); false, -1, NULL, VIR_VM_OP_CREATE);
qemuDomainStartAudit(vm, "from-snapshot", rc >= 0); qemuDomainStartAudit(vm, "from-snapshot", rc >= 0);
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0) if (qemuDomainSnapshotSetCurrentInactive(vm, driver->snapshotDir) < 0)
goto endjob; goto endjob;
if (rc < 0) if (rc < 0)
goto endjob; goto endjob;
...@@ -9991,7 +9994,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, ...@@ -9991,7 +9994,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
} }
} }
if (qemuDomainSnapshotSetActive(vm, driver->snapshotDir) < 0) if (qemuDomainSnapshotSetCurrentActive(vm, driver->snapshotDir) < 0)
goto endjob; goto endjob;
} }
...@@ -10128,6 +10131,43 @@ static void qemuDomainSnapshotDiscardChildren(void *payload, ...@@ -10128,6 +10131,43 @@ static void qemuDomainSnapshotDiscardChildren(void *payload,
} }
} }
struct snap_reparent {
struct qemud_driver *driver;
virDomainSnapshotObjPtr snap;
virDomainObjPtr vm;
int err;
};
static void
qemuDomainSnapshotReparentChildren(void *payload,
const char *name ATTRIBUTE_UNUSED,
void *data)
{
virDomainSnapshotObjPtr snap = payload;
struct snap_reparent *rep = data;
if (rep->err < 0) {
return;
}
if (snap->def->parent && STREQ(snap->def->parent, rep->snap->def->name)) {
VIR_FREE(snap->def->parent);
if (rep->snap->def->parent != NULL) {
snap->def->parent = strdup(rep->snap->def->parent);
if (snap->def->parent == NULL) {
virReportOOMError();
rep->err = -1;
return;
}
}
rep->err = qemuDomainSnapshotWriteMetadata(rep->vm, snap,
rep->driver->snapshotDir);
}
}
static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
unsigned int flags) unsigned int flags)
{ {
...@@ -10137,6 +10177,7 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, ...@@ -10137,6 +10177,7 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
virDomainSnapshotObjPtr snap = NULL; virDomainSnapshotObjPtr snap = NULL;
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
struct snap_remove rem; struct snap_remove rem;
struct snap_reparent rep;
virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1); virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1);
...@@ -10169,6 +10210,15 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, ...@@ -10169,6 +10210,15 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
&rem); &rem);
if (rem.err < 0) if (rem.err < 0)
goto endjob; goto endjob;
} else {
rep.driver = driver;
rep.snap = snap;
rep.vm = vm;
rep.err = 0;
virHashForEach(vm->snapshots.objs, qemuDomainSnapshotReparentChildren,
&rep);
if (rep.err < 0)
goto endjob;
} }
ret = qemuDomainSnapshotDiscard(driver, vm, snap); ret = qemuDomainSnapshotDiscard(driver, vm, snap);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册