A backup blockjob needs to be able to notify the parent backup job as
well as track all data to be able to clean up the bitmap and blockdev
used for the backup.
Add the data structure, job allocation function and status XML formatter
and parser.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_blockjob.c | 33 +++++++++++++++++++++++++++++++++
src/qemu/qemu_blockjob.h | 18 ++++++++++++++++++
src/qemu/qemu_domain.c | 21 +++++++++++++++++++++
3 files changed, 72 insertions(+)
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 6d66d75ed7..6f190b3485 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -83,6 +83,11 @@ qemuBlockJobDataDispose(void *obj)
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);
+ }
+
g_free(job->name);
g_free(job->errmsg);
}
@@ -350,6 +355,34 @@ qemuBlockJobDiskNewCopy(virDomainObjPtr vm,
}
+qemuBlockJobDataPtr
+qemuBlockJobDiskNewBackup(virDomainObjPtr vm,
+ virDomainDiskDefPtr disk,
+ virStorageSourcePtr store,
+ const char *bitmap,
+ int jobid)
+{
+ 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.jobid = jobid;
+
+ /* 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
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index 8b28990801..21b07ff884 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -106,6 +106,16 @@ struct _qemuBlockJobCopyData {
};
+typedef struct _qemuBlockJobBackupData qemuBlockJobBackupData;
+typedef qemuBlockJobBackupData *qemuBlockJobDataBackupPtr;
+
+struct _qemuBlockJobBackupData {
+ virStorageSourcePtr store;
+ char *bitmap;
+ int jobid;
+};
+
+
typedef struct _qemuBlockJobData qemuBlockJobData;
typedef qemuBlockJobData *qemuBlockJobDataPtr;
@@ -123,6 +133,7 @@ struct _qemuBlockJobData {
qemuBlockJobCommitData commit;
qemuBlockJobCreateData create;
qemuBlockJobCopyData copy;
+ qemuBlockJobBackupData backup;
} data;
int type; /* qemuBlockJobType */
@@ -181,6 +192,13 @@ qemuBlockJobDiskNewCopy(virDomainObjPtr vm,
bool shallow,
bool reuse);
+qemuBlockJobDataPtr
+qemuBlockJobDiskNewBackup(virDomainObjPtr vm,
+ virDomainDiskDefPtr disk,
+ virStorageSourcePtr store,
+ const char *bitmap,
+ int jobid);
+
qemuBlockJobDataPtr
qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk)
ATTRIBUTE_NONNULL(1);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 738f06bc5b..b649341c9c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2564,6 +2564,16 @@ qemuDomainObjPrivateXMLFormatBlockjobIterator(void *payload,
break;
case QEMU_BLOCKJOB_TYPE_BACKUP:
+ virBufferEscapeString(&childBuf, "<bitmap
name='%s'/>\n", job->data.backup.bitmap);
+ virBufferAsprintf(&childBuf, "<backup
id='%d'/>\n", job->data.backup.jobid);
+ if (job->data.backup.store &&
+ qemuDomainObjPrivateXMLFormatBlockjobFormatSource(&childBuf,
+ "store",
+
job->data.backup.store,
+ data->xmlopt,
+ false) < 0)
+ return -1;
+
case QEMU_BLOCKJOB_TYPE_NONE:
case QEMU_BLOCKJOB_TYPE_INTERNAL:
case QEMU_BLOCKJOB_TYPE_LAST:
@@ -3174,6 +3184,17 @@
qemuDomainObjPrivateXMLParseBlockjobDataSpecific(qemuBlockJobDataPtr job,
break;
case QEMU_BLOCKJOB_TYPE_BACKUP:
+ if (!(job->data.backup.bitmap =
virXPathString("string(./bitmap/@name)", ctxt)))
+ goto broken;
+
+ if (virXPathInt("string(./backup/@id)", ctxt,
&job->data.backup.jobid) < 0)
+ goto broken;
+
+ if (!(tmp = virXPathNode("./store", ctxt)) ||
+ !(job->data.backup.store =
qemuDomainObjPrivateXMLParseBlockjobChain(tmp, ctxt, xmlopt)))
+ goto broken;
+ break;
+
case QEMU_BLOCKJOB_TYPE_NONE:
case QEMU_BLOCKJOB_TYPE_INTERNAL:
case QEMU_BLOCKJOB_TYPE_LAST:
--
2.21.0