}
-/**
- * qemuCheckpointFindActiveDiskInParent:
- * @vm: domain object
- * @from: starting moment object
- * @diskname: name (target) of the disk to find
- *
- * Find the first checkpoint starting from @from continuing through parents
- * of the checkpoint which describes disk @diskname. Return the pointer to the
- * definition of the disk.
- */
-static virDomainCheckpointDiskDef *
-qemuCheckpointFindActiveDiskInParent(virDomainObjPtr vm,
- virDomainMomentObjPtr from,
- const char *diskname)
-{
- virDomainMomentObjPtr parent = from;
- virDomainCheckpointDefPtr parentdef = NULL;
- size_t i;
-
- while (parent) {
- parentdef = virDomainCheckpointObjGetDef(parent);
-
- for (i = 0; i < parentdef->ndisks; i++) {
- virDomainCheckpointDiskDef *chkdisk = &parentdef->disks[i];
-
- if (STRNEQ(chkdisk->name, diskname))
- continue;
-
- /* currently inspected checkpoint doesn't describe the disk,
- * continue into parent checkpoint */
- if (chkdisk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
- break;
-
- return chkdisk;
- }
-
- parent = virDomainCheckpointFindByName(vm->checkpoints,
- parentdef->parent.parent_name);
- }
-
- return NULL;
-}
-
-
int
qemuCheckpointDiscardDiskBitmaps(virStorageSourcePtr src,
virHashTablePtr blockNamedNodeData,
const char *delbitmap,
- const char *parentbitmap,
virJSONValuePtr actions,
const char *diskdst,
GSList **reopenimages)
{
- virStorageSourcePtr n = src;
+ virStorageSourcePtr n;
+ bool found = false;
/* find the backing chain entry with bitmap named '@delbitmap' */
- while (n) {
- qemuBlockNamedNodeDataBitmapPtr tmp;
-
- if ((tmp = qemuBlockNamedNodeDataGetBitmapByName(blockNamedNodeData,
- n, delbitmap))) {
- break;
- }
-
- n = n->backingStore;
- }
-
- if (!n) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("bitmap '%s' not found in backing chain of '%s'"),
- delbitmap, diskdst);
- return -1;
- }
-
- while (n) {
- qemuBlockNamedNodeDataBitmapPtr srcbitmap;
-
- if (!(srcbitmap = qemuBlockNamedNodeDataGetBitmapByName(blockNamedNodeData,
- n, delbitmap)))
- break;
-
- /* For the actual checkpoint deletion we will merge any bitmap into the
- * bitmap of the parent checkpoint (@parentbitmap) or for any image
- * where the parent checkpoint bitmap is not present we must rename
- * the bitmap of the deleted checkpoint into the bitmap of the parent
- * checkpoint as qemu can't currently take the allocation map and turn
- * it into a bitmap and thus we wouldn't be able to do a backup. */
- if (parentbitmap) {
- qemuBlockNamedNodeDataBitmapPtr dstbitmap;
- g_autoptr(virJSONValue) arr = NULL;
-
- dstbitmap = qemuBlockNamedNodeDataGetBitmapByName(blockNamedNodeData,
- n, parentbitmap);
-
- if (dstbitmap) {
- if (srcbitmap->recording && !dstbitmap->recording) {
- if (qemuMonitorTransactionBitmapEnable(actions,
- n->nodeformat,
- dstbitmap->name) < 0)
- return -1;
- }
-
- } else {
- if (qemuMonitorTransactionBitmapAdd(actions,
- n->nodeformat,
- parentbitmap,
- true,
- !srcbitmap->recording,
- srcbitmap->granularity) < 0)
- return -1;
- }
+ for (n = src; virStorageSourceIsBacking(n); n = n->backingStore) {
+ qemuBlockNamedNodeDataBitmapPtr bitmapdata;
- arr = virJSONValueNewArray();
-
- if (qemuMonitorTransactionBitmapMergeSourceAddBitmap(arr,
- n->nodeformat,
- srcbitmap->name) < 0)
- return -1;
+ if (!(bitmapdata = qemuBlockNamedNodeDataGetBitmapByName(blockNamedNodeData,
+ n, delbitmap)))
+ continue;
- if (qemuMonitorTransactionBitmapMerge(actions,
- n->nodeformat,
- parentbitmap, &arr) < 0)
- return -1;
- }
+ found = true;
if (qemuMonitorTransactionBitmapRemove(actions,
n->nodeformat,
- srcbitmap->name) < 0)
+ bitmapdata->name) < 0)
return -1;
if (n != src)
*reopenimages = g_slist_prepend(*reopenimages, n);
+ }
- n = n->backingStore;
+ if (!found) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("bitmap '%s' not found in backing chain of '%s'"),
+ delbitmap, diskdst);
+ return -1;
}
return 0;
static int
qemuCheckpointDiscardBitmaps(virDomainObjPtr vm,
- virDomainCheckpointDefPtr chkdef,
- virDomainMomentObjPtr parent)
+ virDomainCheckpointDefPtr chkdef)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverPtr driver = priv->driver;
for (i = 0; i < chkdef->ndisks; i++) {
virDomainCheckpointDiskDef *chkdisk = &chkdef->disks[i];
virDomainDiskDefPtr domdisk = virDomainDiskByTarget(vm->def, chkdisk->name);
- virDomainCheckpointDiskDef *parentchkdisk = NULL;
- const char *parentbitmap = NULL;
/* domdisk can be missing e.g. when it was unplugged */
if (!domdisk)
if (chkdisk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
continue;
- /* If any ancestor checkpoint has a bitmap for the same
- * disk, then this bitmap must be merged to the
- * ancestor. */
- if ((parentchkdisk = qemuCheckpointFindActiveDiskInParent(vm, parent,
- chkdisk->name)))
- parentbitmap = parentchkdisk->bitmap;
-
if (qemuCheckpointDiscardDiskBitmaps(domdisk->src, blockNamedNodeData,
- chkdisk->bitmap, parentbitmap,
+ chkdisk->bitmap,
actions, domdisk->dst,
&reopenimages) < 0)
return -1;
bool update_parent,
bool metadata_only)
{
- virDomainMomentObjPtr parent = NULL;
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
g_autofree char *chkFile = NULL;
bool chkcurrent = chk == virDomainCheckpointGetCurrent(vm->checkpoints);
if (!metadata_only) {
virDomainCheckpointDefPtr chkdef = virDomainCheckpointObjGetDef(chk);
- parent = virDomainCheckpointFindByName(vm->checkpoints,
- chk->def->parent_name);
- if (qemuCheckpointDiscardBitmaps(vm, chkdef, parent) < 0)
+ if (qemuCheckpointDiscardBitmaps(vm, chkdef) < 0)
return -1;
}
if (chkcurrent) {
+ virDomainMomentObjPtr parent = NULL;
+
virDomainCheckpointSetCurrent(vm->checkpoints, NULL);
+ parent = virDomainCheckpointFindByName(vm->checkpoints,
+ chk->def->parent_name);
+
if (update_parent && parent) {
virDomainCheckpointSetCurrent(vm->checkpoints, parent);
if (qemuCheckpointWriteMetadata(vm, parent,
const char *name;
virStorageSourcePtr chain;
const char *deletebitmap;
- const char *parentbitmap;
const char *nodedatafile;
};
if (qemuCheckpointDiscardDiskBitmaps(data->chain,
nodedata,
data->deletebitmap,
- data->parentbitmap,
actions,
"testdisk",
&reopenimages) >= 0) {
TEST_BACKUP_BITMAP_CALCULATE("empty", bitmapSourceChain, "a", "empty");
-#define TEST_CHECKPOINT_DELETE_MERGE(testname, delbmp, parbmp, named) \
+#define TEST_CHECKPOINT_DELETE_MERGE(testname, delbmp, named) \
do { \
checkpointdeletedata.name = testname; \
checkpointdeletedata.chain = bitmapSourceChain; \
checkpointdeletedata.deletebitmap = delbmp; \
- checkpointdeletedata.parentbitmap = parbmp; \
checkpointdeletedata.nodedatafile = named; \
if (virTestRun("checkpoint delete " testname, \
testQemuCheckpointDeleteMerge, &checkpointdeletedata) < 0) \
ret = -1; \
} while (0)
- TEST_CHECKPOINT_DELETE_MERGE("empty", "a", NULL, "empty");
+ TEST_CHECKPOINT_DELETE_MERGE("empty", "a", "empty");
#define TEST_BITMAP_VALIDATE(testname, bitmap, rc) \
do { \