{
if (job->type == QEMU_BLOCKJOB_TYPE_CREATE)
virObjectUnref(job->data.create.src);
+
+ if (job->type == QEMU_BLOCKJOB_TYPE_BACKUP) {
+ virObjectUnref(job->data.backup.store);
+ g_free(job->data.backup.bitmap);
+ }
}
}
+qemuBlockJobDataPtr
+qemuBlockJobDiskNewBackup(virDomainObjPtr vm,
+ virDomainDiskDefPtr disk,
+ virStorageSourcePtr store,
+ bool deleteStore,
+ const char *bitmap)
+{
+ g_autoptr(qemuBlockJobData) job = NULL;
+ g_autofree char *jobname = NULL;
+
+ jobname = g_strdup_printf("backup-%s-%s", disk->dst, disk->src->nodeformat);
+
+ if (!(job = qemuBlockJobDataNew(QEMU_BLOCKJOB_TYPE_BACKUP, jobname)))
+ return NULL;
+
+ job->data.backup.bitmap = g_strdup(bitmap);
+ job->data.backup.store = virObjectRef(store);
+ job->data.backup.deleteStore = deleteStore;
+
+ /* backup jobs are usually started in bulk by transaction so the caller
+ * shall save the status XML */
+ if (qemuBlockJobRegister(job, vm, disk, false) < 0)
+ return NULL;
+
+ return g_steal_pointer(&job);
+}
+
+
/**
* qemuBlockJobDiskGetJob:
* @disk: disk definition
};
+typedef struct _qemuBlockJobBackupData qemuBlockJobBackupData;
+typedef qemuBlockJobBackupData *qemuBlockJobDataBackupPtr;
+
+struct _qemuBlockJobBackupData {
+ virStorageSourcePtr store;
+ bool deleteStore;
+ char *bitmap;
+};
+
+
typedef struct _qemuBlockJobData qemuBlockJobData;
typedef qemuBlockJobData *qemuBlockJobDataPtr;
qemuBlockJobCommitData commit;
qemuBlockJobCreateData create;
qemuBlockJobCopyData copy;
+ qemuBlockJobBackupData backup;
} data;
int type; /* qemuBlockJobType */
bool shallow,
bool reuse);
+qemuBlockJobDataPtr
+qemuBlockJobDiskNewBackup(virDomainObjPtr vm,
+ virDomainDiskDefPtr disk,
+ virStorageSourcePtr store,
+ bool deleteStore,
+ const char *bitmap);
+
qemuBlockJobDataPtr
qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk)
ATTRIBUTE_NONNULL(1);
break;
case QEMU_BLOCKJOB_TYPE_BACKUP:
+ virBufferEscapeString(&childBuf, "<bitmap name='%s'/>\n", job->data.backup.bitmap);
+ if (job->data.backup.store) {
+ if (qemuDomainObjPrivateXMLFormatBlockjobFormatSource(&childBuf,
+ "store",
+ job->data.backup.store,
+ data->xmlopt,
+ false) < 0)
+ return -1;
+
+ if (job->data.backup.deleteStore)
+ virBufferAddLit(&childBuf, "<deleteStore/>\n");
+ }
break;
case QEMU_BLOCKJOB_TYPE_BROKEN:
break;
case QEMU_BLOCKJOB_TYPE_BACKUP:
+ job->data.backup.bitmap = virXPathString("string(./bitmap/@name)", ctxt);
+
+ if (!(tmp = virXPathNode("./store", ctxt)) ||
+ !(job->data.backup.store = qemuDomainObjPrivateXMLParseBlockjobChain(tmp, ctxt, xmlopt)))
+ goto broken;
+
+ if (virXPathNode("./deleteStore", ctxt))
+ job->data.backup.deleteStore = true;
+
break;
case QEMU_BLOCKJOB_TYPE_BROKEN: