[GSoC][PATCH v4 0/4] removal of qemu_domainjob dependencies

The following series of patches work on isolating the qemu_domainjob from its dependency on other files such as `qemu_migration_params`, `qemu_monitor`, etc. This is done by the introduction of a `privateData` structure, which is further handled by a structure of callback functions. Previous version of this patch can be found here[1]. This new version improves the previous patches in accordance with the review by Michal. Both domainJob and domainJobInfo now passes the callback structure, instead of assigning each variable manually. [1]: https://www.redhat.com/archives/libvir-list/2020-July/msg00423.html Prathamesh Chavan (4): qemu_domain: remove passing `qemuDomainObjPrivatePtr` as param qemu_domainjob: moved PrivateXML parse-job and format-job qemu_domainjob: introduce `privateData` for `qemuDomainJob` qemu_domainjob: introduce `privateData` for `qemuDomainJobInfo` src/qemu/qemu_backup.c | 15 +- src/qemu/qemu_domain.c | 254 +----------------- src/qemu/qemu_domain.h | 28 ++ src/qemu/qemu_domainjob.c | 425 ++++++++++++++++++++++++++++--- src/qemu/qemu_domainjob.h | 83 ++++-- src/qemu/qemu_driver.c | 21 +- src/qemu/qemu_migration.c | 42 ++- src/qemu/qemu_migration_cookie.c | 7 +- src/qemu/qemu_migration_params.c | 9 +- src/qemu/qemu_process.c | 26 +- 10 files changed, 566 insertions(+), 344 deletions(-) -- 2.25.1

`qemuDomainObjPrivatePtr` parameter was avoided being passed as a paramter in functions `qemuDomainObjPrivateXMLParseJob` and `qemuDomainObjPrivateXMLFormatJob`, as we already pass `virDomainObjPtr`, which can be used to get `privateData` pointer. Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- src/qemu/qemu_domain.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 2d9d8226d6..b448c89417 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2224,11 +2224,11 @@ qemuDomainObjPrivateXMLFormatNBDMigration(virBufferPtr buf, static int qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, - virDomainObjPtr vm, - qemuDomainObjPrivatePtr priv) + virDomainObjPtr vm) { g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); + qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainJob job = priv->job.active; if (!qemuDomainTrackJob(job)) @@ -2399,7 +2399,7 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, if (priv->lockState) virBufferAsprintf(buf, "<lockstate>%s</lockstate>\n", priv->lockState); - if (qemuDomainObjPrivateXMLFormatJob(buf, vm, priv) < 0) + if (qemuDomainObjPrivateXMLFormatJob(buf, vm) < 0) return -1; if (priv->fakeReboot) @@ -2948,9 +2948,9 @@ qemuDomainObjPrivateXMLParseJobNBDSource(xmlNodePtr node, static int qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm, - qemuDomainObjPrivatePtr priv, xmlXPathContextPtr ctxt) { + qemuDomainObjPrivatePtr priv = vm->privateData; g_autofree xmlNodePtr *nodes = NULL; size_t i; int n; @@ -2986,9 +2986,9 @@ qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm, static int qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, - qemuDomainObjPrivatePtr priv, xmlXPathContextPtr ctxt) { + qemuDomainObjPrivatePtr priv = vm->privateData; VIR_XPATH_NODE_AUTORESTORE(ctxt); g_autofree char *tmp = NULL; @@ -3034,7 +3034,7 @@ qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, return -1; } - if (qemuDomainObjPrivateXMLParseJobNBD(vm, priv, ctxt) < 0) + if (qemuDomainObjPrivateXMLParseJobNBD(vm, ctxt) < 0) return -1; if (qemuMigrationParamsParse(ctxt, &priv->job.migParams) < 0) @@ -3203,7 +3203,7 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, priv->lockState = virXPathString("string(./lockstate)", ctxt); - if (qemuDomainObjPrivateXMLParseJob(vm, priv, ctxt) < 0) + if (qemuDomainObjPrivateXMLParseJob(vm, ctxt) < 0) goto error; priv->fakeReboot = virXPathBoolean("boolean(./fakereboot)", ctxt) == 1; -- 2.25.1

On 7/13/20 8:03 PM, Prathamesh Chavan wrote:
`qemuDomainObjPrivatePtr` parameter was avoided being passed as a paramter in functions `qemuDomainObjPrivateXMLParseJob` and `qemuDomainObjPrivateXMLFormatJob`, as we already pass `virDomainObjPtr`, which can be used to get `privateData` pointer.
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- src/qemu/qemu_domain.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal

Functions `qemuDomainObjPrivateXMLParseJob` and `qemuDomainObjPrivateXMLFormatJob` moved from `qemu_domain` to `qemu_domainjob`. Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- src/qemu/qemu_domain.c | 241 -------------------------------------- src/qemu/qemu_domainjob.c | 241 ++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domainjob.h | 8 ++ 3 files changed, 249 insertions(+), 241 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b448c89417..10d2033db1 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2168,102 +2168,6 @@ qemuDomainObjPrivateXMLFormatPR(virBufferPtr buf, } -static int -qemuDomainObjPrivateXMLFormatNBDMigrationSource(virBufferPtr buf, - virStorageSourcePtr src, - virDomainXMLOptionPtr xmlopt) -{ - g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; - g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); - - virBufferAsprintf(&attrBuf, " type='%s' format='%s'", - virStorageTypeToString(src->type), - virStorageFileFormatTypeToString(src->format)); - - if (virDomainDiskSourceFormat(&childBuf, src, "source", 0, false, - VIR_DOMAIN_DEF_FORMAT_STATUS, - false, false, xmlopt) < 0) - return -1; - - virXMLFormatElement(buf, "migrationSource", &attrBuf, &childBuf); - - return 0; -} - - -static int -qemuDomainObjPrivateXMLFormatNBDMigration(virBufferPtr buf, - virDomainObjPtr vm) -{ - qemuDomainObjPrivatePtr priv = vm->privateData; - size_t i; - virDomainDiskDefPtr disk; - qemuDomainDiskPrivatePtr diskPriv; - - for (i = 0; i < vm->def->ndisks; i++) { - g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; - g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); - disk = vm->def->disks[i]; - diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - - virBufferAsprintf(&attrBuf, " dev='%s' migrating='%s'", - disk->dst, diskPriv->migrating ? "yes" : "no"); - - if (diskPriv->migrSource && - qemuDomainObjPrivateXMLFormatNBDMigrationSource(&childBuf, - diskPriv->migrSource, - priv->driver->xmlopt) < 0) - return -1; - - virXMLFormatElement(buf, "disk", &attrBuf, &childBuf); - } - - return 0; -} - - -static int -qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, - virDomainObjPtr vm) -{ - g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; - g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); - qemuDomainObjPrivatePtr priv = vm->privateData; - qemuDomainJob job = priv->job.active; - - if (!qemuDomainTrackJob(job)) - job = QEMU_JOB_NONE; - - if (job == QEMU_JOB_NONE && - priv->job.asyncJob == QEMU_ASYNC_JOB_NONE) - return 0; - - virBufferAsprintf(&attrBuf, " type='%s' async='%s'", - qemuDomainJobTypeToString(job), - qemuDomainAsyncJobTypeToString(priv->job.asyncJob)); - - if (priv->job.phase) { - virBufferAsprintf(&attrBuf, " phase='%s'", - qemuDomainAsyncJobPhaseToString(priv->job.asyncJob, - priv->job.phase)); - } - - if (priv->job.asyncJob != QEMU_ASYNC_JOB_NONE) - virBufferAsprintf(&attrBuf, " flags='0x%lx'", priv->job.apiFlags); - - if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT && - qemuDomainObjPrivateXMLFormatNBDMigration(&childBuf, vm) < 0) - return -1; - - if (priv->job.migParams) - qemuMigrationParamsFormat(&childBuf, priv->job.migParams); - - virXMLFormatElement(buf, "job", &attrBuf, &childBuf); - - return 0; -} - - static bool qemuDomainHasSlirp(virDomainObjPtr vm) { @@ -2899,151 +2803,6 @@ qemuDomainObjPrivateXMLParsePR(xmlXPathContextPtr ctxt, } -static int -qemuDomainObjPrivateXMLParseJobNBDSource(xmlNodePtr node, - xmlXPathContextPtr ctxt, - virDomainDiskDefPtr disk, - virDomainXMLOptionPtr xmlopt) -{ - VIR_XPATH_NODE_AUTORESTORE(ctxt); - qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - g_autofree char *format = NULL; - g_autofree char *type = NULL; - g_autoptr(virStorageSource) migrSource = NULL; - xmlNodePtr sourceNode; - - ctxt->node = node; - - if (!(ctxt->node = virXPathNode("./migrationSource", ctxt))) - return 0; - - if (!(type = virXMLPropString(ctxt->node, "type"))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("missing storage source type")); - return -1; - } - - if (!(format = virXMLPropString(ctxt->node, "format"))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("missing storage source format")); - return -1; - } - - if (!(migrSource = virDomainStorageSourceParseBase(type, format, NULL))) - return -1; - - /* newer libvirt uses the <source> subelement instead of formatting the - * source directly into <migrationSource> */ - if ((sourceNode = virXPathNode("./source", ctxt))) - ctxt->node = sourceNode; - - if (virDomainStorageSourceParse(ctxt->node, ctxt, migrSource, - VIR_DOMAIN_DEF_PARSE_STATUS, xmlopt) < 0) - return -1; - - diskPriv->migrSource = g_steal_pointer(&migrSource); - return 0; -} - - -static int -qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm, - xmlXPathContextPtr ctxt) -{ - qemuDomainObjPrivatePtr priv = vm->privateData; - g_autofree xmlNodePtr *nodes = NULL; - size_t i; - int n; - - if ((n = virXPathNodeSet("./disk[@migrating='yes']", ctxt, &nodes)) < 0) - return -1; - - if (n > 0) { - if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) { - VIR_WARN("Found disks marked for migration but we were not " - "migrating"); - n = 0; - } - for (i = 0; i < n; i++) { - virDomainDiskDefPtr disk; - g_autofree char *dst = NULL; - - if ((dst = virXMLPropString(nodes[i], "dev")) && - (disk = virDomainDiskByTarget(vm->def, dst))) { - QEMU_DOMAIN_DISK_PRIVATE(disk)->migrating = true; - - if (qemuDomainObjPrivateXMLParseJobNBDSource(nodes[i], ctxt, - disk, - priv->driver->xmlopt) < 0) - return -1; - } - } - } - - return 0; -} - - -static int -qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, - xmlXPathContextPtr ctxt) -{ - qemuDomainObjPrivatePtr priv = vm->privateData; - VIR_XPATH_NODE_AUTORESTORE(ctxt); - g_autofree char *tmp = NULL; - - if (!(ctxt->node = virXPathNode("./job[1]", ctxt))) - return 0; - - if ((tmp = virXPathString("string(@type)", ctxt))) { - int type; - - if ((type = qemuDomainJobTypeFromString(tmp)) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unknown job type %s"), tmp); - return -1; - } - VIR_FREE(tmp); - priv->job.active = type; - } - - if ((tmp = virXPathString("string(@async)", ctxt))) { - int async; - - if ((async = qemuDomainAsyncJobTypeFromString(tmp)) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unknown async job type %s"), tmp); - return -1; - } - VIR_FREE(tmp); - priv->job.asyncJob = async; - - if ((tmp = virXPathString("string(@phase)", ctxt))) { - priv->job.phase = qemuDomainAsyncJobPhaseFromString(async, tmp); - if (priv->job.phase < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unknown job phase %s"), tmp); - return -1; - } - VIR_FREE(tmp); - } - } - - if (virXPathULongHex("string(@flags)", ctxt, &priv->job.apiFlags) == -2) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid job flags")); - return -1; - } - - if (qemuDomainObjPrivateXMLParseJobNBD(vm, ctxt) < 0) - return -1; - - if (qemuMigrationParamsParse(ctxt, &priv->job.migParams) < 0) - return -1; - - return 0; -} - - static int qemuDomainObjPrivateXMLParseSlirpFeatures(xmlNodePtr featuresNode, xmlXPathContextPtr ctxt, diff --git a/src/qemu/qemu_domainjob.c b/src/qemu/qemu_domainjob.c index 654f1c4f90..d96d5334a3 100644 --- a/src/qemu/qemu_domainjob.c +++ b/src/qemu/qemu_domainjob.c @@ -1184,3 +1184,244 @@ qemuDomainObjAbortAsyncJob(virDomainObjPtr obj) priv->job.abortJob = true; virDomainObjBroadcast(obj); } + + +static int +qemuDomainObjPrivateXMLFormatNBDMigrationSource(virBufferPtr buf, + virStorageSourcePtr src, + virDomainXMLOptionPtr xmlopt) +{ + g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); + + virBufferAsprintf(&attrBuf, " type='%s' format='%s'", + virStorageTypeToString(src->type), + virStorageFileFormatTypeToString(src->format)); + + if (virDomainDiskSourceFormat(&childBuf, src, "source", 0, false, + VIR_DOMAIN_DEF_FORMAT_STATUS, + false, false, xmlopt) < 0) + return -1; + + virXMLFormatElement(buf, "migrationSource", &attrBuf, &childBuf); + + return 0; +} + + +static int +qemuDomainObjPrivateXMLFormatNBDMigration(virBufferPtr buf, + virDomainObjPtr vm) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + size_t i; + virDomainDiskDefPtr disk; + qemuDomainDiskPrivatePtr diskPriv; + + for (i = 0; i < vm->def->ndisks; i++) { + g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); + disk = vm->def->disks[i]; + diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + + virBufferAsprintf(&attrBuf, " dev='%s' migrating='%s'", + disk->dst, diskPriv->migrating ? "yes" : "no"); + + if (diskPriv->migrSource && + qemuDomainObjPrivateXMLFormatNBDMigrationSource(&childBuf, + diskPriv->migrSource, + priv->driver->xmlopt) < 0) + return -1; + + virXMLFormatElement(buf, "disk", &attrBuf, &childBuf); + } + + return 0; +} + + +int +qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, + virDomainObjPtr vm) +{ + g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); + qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJob job = priv->job.active; + + if (!qemuDomainTrackJob(job)) + job = QEMU_JOB_NONE; + + if (job == QEMU_JOB_NONE && + priv->job.asyncJob == QEMU_ASYNC_JOB_NONE) + return 0; + + virBufferAsprintf(&attrBuf, " type='%s' async='%s'", + qemuDomainJobTypeToString(job), + qemuDomainAsyncJobTypeToString(priv->job.asyncJob)); + + if (priv->job.phase) { + virBufferAsprintf(&attrBuf, " phase='%s'", + qemuDomainAsyncJobPhaseToString(priv->job.asyncJob, + priv->job.phase)); + } + + if (priv->job.asyncJob != QEMU_ASYNC_JOB_NONE) + virBufferAsprintf(&attrBuf, " flags='0x%lx'", priv->job.apiFlags); + + if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT && + qemuDomainObjPrivateXMLFormatNBDMigration(&childBuf, vm) < 0) + return -1; + + if (priv->job.migParams) + qemuMigrationParamsFormat(&childBuf, priv->job.migParams); + + virXMLFormatElement(buf, "job", &attrBuf, &childBuf); + + return 0; +} + + +static int +qemuDomainObjPrivateXMLParseJobNBDSource(xmlNodePtr node, + xmlXPathContextPtr ctxt, + virDomainDiskDefPtr disk, + virDomainXMLOptionPtr xmlopt) +{ + VIR_XPATH_NODE_AUTORESTORE(ctxt); + qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + g_autofree char *format = NULL; + g_autofree char *type = NULL; + g_autoptr(virStorageSource) migrSource = NULL; + xmlNodePtr sourceNode; + + ctxt->node = node; + + if (!(ctxt->node = virXPathNode("./migrationSource", ctxt))) + return 0; + + if (!(type = virXMLPropString(ctxt->node, "type"))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing storage source type")); + return -1; + } + + if (!(format = virXMLPropString(ctxt->node, "format"))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing storage source format")); + return -1; + } + + if (!(migrSource = virDomainStorageSourceParseBase(type, format, NULL))) + return -1; + + /* newer libvirt uses the <source> subelement instead of formatting the + * source directly into <migrationSource> */ + if ((sourceNode = virXPathNode("./source", ctxt))) + ctxt->node = sourceNode; + + if (virDomainStorageSourceParse(ctxt->node, ctxt, migrSource, + VIR_DOMAIN_DEF_PARSE_STATUS, xmlopt) < 0) + return -1; + + diskPriv->migrSource = g_steal_pointer(&migrSource); + return 0; +} + + +static int +qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm, + xmlXPathContextPtr ctxt) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + g_autofree xmlNodePtr *nodes = NULL; + size_t i; + int n; + + if ((n = virXPathNodeSet("./disk[@migrating='yes']", ctxt, &nodes)) < 0) + return -1; + + if (n > 0) { + if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) { + VIR_WARN("Found disks marked for migration but we were not " + "migrating"); + n = 0; + } + for (i = 0; i < n; i++) { + virDomainDiskDefPtr disk; + g_autofree char *dst = NULL; + + if ((dst = virXMLPropString(nodes[i], "dev")) && + (disk = virDomainDiskByTarget(vm->def, dst))) { + QEMU_DOMAIN_DISK_PRIVATE(disk)->migrating = true; + + if (qemuDomainObjPrivateXMLParseJobNBDSource(nodes[i], ctxt, + disk, + priv->driver->xmlopt) < 0) + return -1; + } + } + } + + return 0; +} + + +int +qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, + xmlXPathContextPtr ctxt) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + VIR_XPATH_NODE_AUTORESTORE(ctxt); + g_autofree char *tmp = NULL; + + if (!(ctxt->node = virXPathNode("./job[1]", ctxt))) + return 0; + + if ((tmp = virXPathString("string(@type)", ctxt))) { + int type; + + if ((type = qemuDomainJobTypeFromString(tmp)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown job type %s"), tmp); + return -1; + } + VIR_FREE(tmp); + priv->job.active = type; + } + + if ((tmp = virXPathString("string(@async)", ctxt))) { + int async; + + if ((async = qemuDomainAsyncJobTypeFromString(tmp)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown async job type %s"), tmp); + return -1; + } + VIR_FREE(tmp); + priv->job.asyncJob = async; + + if ((tmp = virXPathString("string(@phase)", ctxt))) { + priv->job.phase = qemuDomainAsyncJobPhaseFromString(async, tmp); + if (priv->job.phase < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown job phase %s"), tmp); + return -1; + } + VIR_FREE(tmp); + } + } + + if (virXPathULongHex("string(@flags)", ctxt, &priv->job.apiFlags) == -2) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid job flags")); + return -1; + } + + if (qemuDomainObjPrivateXMLParseJobNBD(vm, ctxt) < 0) + return -1; + + if (qemuMigrationParamsParse(ctxt, &priv->job.migParams) < 0) + return -1; + + return 0; +} diff --git a/src/qemu/qemu_domainjob.h b/src/qemu/qemu_domainjob.h index 124664354d..9d2ee14584 100644 --- a/src/qemu/qemu_domainjob.h +++ b/src/qemu/qemu_domainjob.h @@ -267,3 +267,11 @@ void qemuDomainObjFreeJob(qemuDomainJobObjPtr job); int qemuDomainObjInitJob(qemuDomainJobObjPtr job); bool qemuDomainJobAllowed(qemuDomainJobObjPtr jobs, qemuDomainJob newJob); + +int +qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, + virDomainObjPtr vm); + +int +qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, + xmlXPathContextPtr ctxt); -- 2.25.1

On 7/13/20 8:03 PM, Prathamesh Chavan wrote:
Functions `qemuDomainObjPrivateXMLParseJob` and `qemuDomainObjPrivateXMLFormatJob` moved from `qemu_domain` to `qemu_domainjob`.
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- src/qemu/qemu_domain.c | 241 -------------------------------------- src/qemu/qemu_domainjob.c | 241 ++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domainjob.h | 8 ++ 3 files changed, 249 insertions(+), 241 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal

To remove dependecy of `qemuDomainJob` on job specific paramters, a `privateData` pointer is introduced. To handle it, structure of callback functions is also introduced. Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- The static callback functions structure was declared in `qemu_domain.c` Due to this, all callback functions (present in `qemu_domainobj.c`) were exposed using the .h file to allow their access by the `qemu_domain.c` file. src/qemu/qemu_domain.c | 9 ++- src/qemu/qemu_domain.h | 10 ++++ src/qemu/qemu_domainjob.c | 94 ++++++++++++++++++++++++-------- src/qemu/qemu_domainjob.h | 44 ++++++++++++--- src/qemu/qemu_driver.c | 3 +- src/qemu/qemu_migration.c | 28 +++++++--- src/qemu/qemu_migration_params.c | 9 ++- src/qemu/qemu_process.c | 15 +++-- 8 files changed, 165 insertions(+), 47 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 10d2033db1..a02865dc59 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -88,6 +88,13 @@ VIR_ENUM_IMPL(qemuDomainNamespace, "mount", ); +static qemuDomainObjPrivateJobCallbacks qemuPrivateJobCallbacks = { + .allocJobPrivate = &qemuJobAllocPrivate, + .freeJobPrivate = &qemuJobFreePrivate, + .formatJob = &qemuDomainFormatJobPrivate, + .parseJob = &qemuDomainParseJobPrivate, +}; + /** * qemuDomainObjFromDomain: * @domain: Domain pointer that has to be looked up @@ -1585,7 +1592,7 @@ qemuDomainObjPrivateAlloc(void *opaque) if (VIR_ALLOC(priv) < 0) return NULL; - if (qemuDomainObjInitJob(&priv->job) < 0) { + if (qemuDomainObjInitJob(&priv->job, &qemuPrivateJobCallbacks) < 0) { virReportSystemError(errno, "%s", _("Unable to init qemu driver mutexes")); goto error; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index e524fd0002..bb9b414a46 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -492,6 +492,16 @@ struct _qemuDomainXmlNsDef { char **capsdel; }; +typedef struct _qemuDomainJobPrivate qemuDomainJobPrivate; +typedef qemuDomainJobPrivate *qemuDomainJobPrivatePtr; +struct _qemuDomainJobPrivate { + bool spiceMigration; /* we asked for spice migration and we + * should wait for it to finish */ + bool spiceMigrated; /* spice migration completed */ + bool dumpCompleted; /* dump completed */ + qemuMigrationParamsPtr migParams; +}; + int qemuDomainObjStartWorker(virDomainObjPtr dom); void qemuDomainObjStopWorker(virDomainObjPtr dom); diff --git a/src/qemu/qemu_domainjob.c b/src/qemu/qemu_domainjob.c index d96d5334a3..fe160afe79 100644 --- a/src/qemu/qemu_domainjob.c +++ b/src/qemu/qemu_domainjob.c @@ -159,23 +159,32 @@ qemuDomainEventEmitJobCompleted(virQEMUDriverPtr driver, virObjectEventStateQueue(driver->domainEventState, event); } - -int -qemuDomainObjInitJob(qemuDomainJobObjPtr job) +void * +qemuJobAllocPrivate(void) { - memset(job, 0, sizeof(*job)); - - if (virCondInit(&job->cond) < 0) - return -1; + qemuDomainJobPrivatePtr priv; + if (VIR_ALLOC(priv) < 0) + return NULL; + return (void *)priv; +} - if (virCondInit(&job->asyncCond) < 0) { - virCondDestroy(&job->cond); - return -1; - } - return 0; +static void +qemuJobFreePrivateData(qemuDomainJobPrivatePtr priv) +{ + priv->spiceMigration = false; + priv->spiceMigrated = false; + priv->dumpCompleted = false; + qemuMigrationParamsFree(priv->migParams); + priv->migParams = NULL; } +void +qemuJobFreePrivate(void *opaque) +{ + qemuDomainJobObjPtr job = (qemuDomainJobObjPtr) opaque; + qemuJobFreePrivateData(job->privateData); +} static void qemuDomainObjResetJob(qemuDomainJobObjPtr job) @@ -207,14 +216,11 @@ qemuDomainObjResetAsyncJob(qemuDomainJobObjPtr job) job->phase = 0; job->mask = QEMU_JOB_DEFAULT_MASK; job->abortJob = false; - job->spiceMigration = false; - job->spiceMigrated = false; - job->dumpCompleted = false; VIR_FREE(job->error); g_clear_pointer(&job->current, qemuDomainJobInfoFree); - qemuMigrationParamsFree(job->migParams); - job->migParams = NULL; + job->cb->freeJobPrivate(job); job->apiFlags = 0; + job->cb = NULL; } void @@ -229,7 +235,7 @@ qemuDomainObjRestoreJob(virDomainObjPtr obj, job->asyncJob = priv->job.asyncJob; job->asyncOwner = priv->job.asyncOwner; job->phase = priv->job.phase; - job->migParams = g_steal_pointer(&priv->job.migParams); + job->privateData = g_steal_pointer(&priv->job.privateData); job->apiFlags = priv->job.apiFlags; qemuDomainObjResetJob(&priv->job); @@ -1239,14 +1245,24 @@ qemuDomainObjPrivateXMLFormatNBDMigration(virBufferPtr buf, return 0; } +int +qemuDomainFormatJobPrivate(virBufferPtr buf, + qemuDomainJobObjPtr job) +{ + qemuDomainJobPrivatePtr priv = job->privateData; + if (priv->migParams) + qemuMigrationParamsFormat(buf, priv->migParams); + return 0; +} int qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, virDomainObjPtr vm) { + qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobObjPtr jobObj = &priv->job; g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); - qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainJob job = priv->job.active; if (!qemuDomainTrackJob(job)) @@ -1273,8 +1289,8 @@ qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, qemuDomainObjPrivateXMLFormatNBDMigration(&childBuf, vm) < 0) return -1; - if (priv->job.migParams) - qemuMigrationParamsFormat(&childBuf, priv->job.migParams); + if (jobObj->cb->formatJob(&childBuf, jobObj) < 0) + return -1; virXMLFormatElement(buf, "job", &attrBuf, &childBuf); @@ -1366,12 +1382,22 @@ qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm, return 0; } +int +qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, + qemuDomainJobObjPtr job) +{ + qemuDomainJobPrivatePtr jobPriv = job->privateData; + if (qemuMigrationParamsParse(ctxt, &jobPriv->migParams) < 0) + return -1; + return 0; +} int qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, xmlXPathContextPtr ctxt) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobObjPtr job = &priv->job; VIR_XPATH_NODE_AUTORESTORE(ctxt); g_autofree char *tmp = NULL; @@ -1420,8 +1446,32 @@ qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, if (qemuDomainObjPrivateXMLParseJobNBD(vm, ctxt) < 0) return -1; - if (qemuMigrationParamsParse(ctxt, &priv->job.migParams) < 0) + if (job->cb->parseJob(ctxt, job) < 0) + return -1; + + return 0; +} + + +int +qemuDomainObjInitJob(qemuDomainJobObjPtr job, + qemuDomainObjPrivateJobCallbacksPtr cb) +{ + memset(job, 0, sizeof(*job)); + job->cb = cb; + + if (!(job->privateData = job->cb->allocJobPrivate())) { + qemuDomainObjFreeJob(job); + return -1; + } + + if (virCondInit(&job->cond) < 0) + return -1; + + if (virCondInit(&job->asyncCond) < 0) { + virCondDestroy(&job->cond); return -1; + } return 0; } diff --git a/src/qemu/qemu_domainjob.h b/src/qemu/qemu_domainjob.h index 9d2ee14584..b0e840adc8 100644 --- a/src/qemu/qemu_domainjob.h +++ b/src/qemu/qemu_domainjob.h @@ -156,6 +156,23 @@ qemuDomainJobInfoCopy(qemuDomainJobInfoPtr info); typedef struct _qemuDomainJobObj qemuDomainJobObj; typedef qemuDomainJobObj *qemuDomainJobObjPtr; + +typedef void *(*qemuDomainObjPrivateJobAlloc)(void); +typedef void (*qemuDomainObjPrivateJobFree)(void *); +typedef int (*qemuDomainObjPrivateJobFormat)(virBufferPtr, + qemuDomainJobObjPtr); +typedef int (*qemuDomainObjPrivateJobParse)(xmlXPathContextPtr, + qemuDomainJobObjPtr); + +typedef struct _qemuDomainObjPrivateJobCallbacks qemuDomainObjPrivateJobCallbacks; +typedef qemuDomainObjPrivateJobCallbacks *qemuDomainObjPrivateJobCallbacksPtr; +struct _qemuDomainObjPrivateJobCallbacks { + qemuDomainObjPrivateJobAlloc allocJobPrivate; + qemuDomainObjPrivateJobFree freeJobPrivate; + qemuDomainObjPrivateJobFormat formatJob; + qemuDomainObjPrivateJobParse parseJob; +}; + struct _qemuDomainJobObj { virCond cond; /* Use to coordinate jobs */ @@ -182,14 +199,11 @@ struct _qemuDomainJobObj { qemuDomainJobInfoPtr current; /* async job progress data */ qemuDomainJobInfoPtr completed; /* statistics data of a recently completed job */ bool abortJob; /* abort of the job requested */ - bool spiceMigration; /* we asked for spice migration and we - * should wait for it to finish */ - bool spiceMigrated; /* spice migration completed */ char *error; /* job event completion error */ - bool dumpCompleted; /* dump completed */ - - qemuMigrationParamsPtr migParams; unsigned long apiFlags; /* flags passed to the API which started the async job */ + + void *privateData; /* job specific collection of data */ + qemuDomainObjPrivateJobCallbacksPtr cb; }; const char *qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job, @@ -264,7 +278,9 @@ bool qemuDomainTrackJob(qemuDomainJob job); void qemuDomainObjFreeJob(qemuDomainJobObjPtr job); -int qemuDomainObjInitJob(qemuDomainJobObjPtr job); +int +qemuDomainObjInitJob(qemuDomainJobObjPtr job, + qemuDomainObjPrivateJobCallbacksPtr cb); bool qemuDomainJobAllowed(qemuDomainJobObjPtr jobs, qemuDomainJob newJob); @@ -275,3 +291,17 @@ qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, int qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, xmlXPathContextPtr ctxt); + +void * +qemuJobAllocPrivate(void); + +void +qemuJobFreePrivate(void *opaque); + +int +qemuDomainFormatJobPrivate(virBufferPtr buf, + qemuDomainJobObjPtr job); + +int +qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, + qemuDomainJobObjPtr job); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d185666ed8..d9c5f21f21 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3701,9 +3701,10 @@ static int qemuDumpWaitForCompletion(virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; VIR_DEBUG("Waiting for dump completion"); - while (!priv->job.dumpCompleted && !priv->job.abortJob) { + while (!jobPriv->dumpCompleted && !priv->job.abortJob) { if (virDomainObjWait(vm) < 0) return -1; } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 78e64344f6..2c7bf349c3 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1422,12 +1422,13 @@ static int qemuMigrationSrcWaitForSpice(virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; - if (!priv->job.spiceMigration) + if (!jobPriv->spiceMigration) return 0; VIR_DEBUG("Waiting for SPICE to finish migration"); - while (!priv->job.spiceMigrated && !priv->job.abortJob) { + while (!jobPriv->spiceMigrated && !priv->job.abortJob) { if (virDomainObjWait(vm) < 0) return -1; } @@ -1856,9 +1857,11 @@ qemuMigrationSrcGraphicsRelocate(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) { + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; + ret = qemuMonitorGraphicsRelocate(priv->mon, type, listenAddress, port, tlsPort, tlsSubject); - priv->job.spiceMigration = !ret; + jobPriv->spiceMigration = !ret; if (qemuDomainObjExitMonitor(driver, vm) < 0) ret = -1; } @@ -1993,6 +1996,7 @@ qemuMigrationSrcCleanup(virDomainObjPtr vm, { virQEMUDriverPtr driver = opaque; qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; VIR_DEBUG("vm=%s, conn=%p, asyncJob=%s, phase=%s", vm->def->name, conn, @@ -2018,7 +2022,7 @@ qemuMigrationSrcCleanup(virDomainObjPtr vm, " domain was successfully started on destination or not", vm->def->name); qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, - priv->job.migParams, priv->job.apiFlags); + jobPriv->migParams, priv->job.apiFlags); /* clear the job and let higher levels decide what to do */ qemuDomainObjDiscardAsyncJob(driver, vm); break; @@ -2382,6 +2386,7 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver, int dataFD[2] = { -1, -1 }; qemuDomainObjPrivatePtr priv = NULL; qemuMigrationCookiePtr mig = NULL; + qemuDomainJobPrivatePtr jobPriv = NULL; bool tunnel = !!st; g_autofree char *xmlout = NULL; unsigned int cookieFlags; @@ -2505,6 +2510,7 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver, *def = NULL; priv = vm->privateData; + jobPriv = priv->job.privateData; priv->origname = g_strdup(origname); if (taint_hook) { @@ -2710,7 +2716,7 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver, stopjob: qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN, - priv->job.migParams, priv->job.apiFlags); + jobPriv->migParams, priv->job.apiFlags); if (stopProcess) { unsigned int stopFlags = VIR_QEMU_PROCESS_STOP_MIGRATED; @@ -2979,6 +2985,7 @@ qemuMigrationSrcConfirmPhase(virQEMUDriverPtr driver, virObjectEventPtr event; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; qemuDomainJobInfoPtr jobInfo = NULL; VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, " @@ -3064,7 +3071,7 @@ qemuMigrationSrcConfirmPhase(virQEMUDriverPtr driver, qemuMigrationSrcRestoreDomainState(driver, vm); qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, - priv->job.migParams, priv->job.apiFlags); + jobPriv->migParams, priv->job.apiFlags); if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0) VIR_WARN("Failed to save status on vm %s", vm->def->name); @@ -4642,6 +4649,7 @@ qemuMigrationSrcPerformJob(virQEMUDriverPtr driver, virErrorPtr orig_err = NULL; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, flags) < 0) @@ -4699,7 +4707,7 @@ qemuMigrationSrcPerformJob(virQEMUDriverPtr driver, */ if (!v3proto && ret < 0) qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, - priv->job.migParams, priv->job.apiFlags); + jobPriv->migParams, priv->job.apiFlags); qemuMigrationSrcRestoreDomainState(driver, vm); @@ -4740,6 +4748,7 @@ qemuMigrationSrcPerformPhase(virQEMUDriverPtr driver, unsigned long resource) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; int ret = -1; /* If we didn't start the job in the begin phase, start it now. */ @@ -4774,7 +4783,7 @@ qemuMigrationSrcPerformPhase(virQEMUDriverPtr driver, endjob: if (ret < 0) { qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, - priv->job.migParams, priv->job.apiFlags); + jobPriv->migParams, priv->job.apiFlags); qemuMigrationJobFinish(driver, vm); } else { qemuMigrationJobContinue(vm); @@ -4973,6 +4982,7 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver, virErrorPtr orig_err = NULL; int cookie_flags = 0; qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); unsigned short port; unsigned long long timeReceived = 0; @@ -5226,7 +5236,7 @@ qemuMigrationDstFinish(virQEMUDriverPtr driver, } qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN, - priv->job.migParams, priv->job.apiFlags); + jobPriv->migParams, priv->job.apiFlags); qemuMigrationJobFinish(driver, vm); if (!virDomainObjIsActive(vm)) diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index aea17b1ac8..fc282960da 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -950,6 +950,7 @@ qemuMigrationParamsEnableTLS(virQEMUDriverPtr driver, qemuMigrationParamsPtr migParams) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; g_autoptr(virJSONValue) tlsProps = NULL; g_autoptr(virJSONValue) secProps = NULL; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); @@ -961,7 +962,7 @@ qemuMigrationParamsEnableTLS(virQEMUDriverPtr driver, return -1; } - if (!priv->job.migParams->params[QEMU_MIGRATION_PARAM_TLS_CREDS].set) { + if (!jobPriv->migParams->params[QEMU_MIGRATION_PARAM_TLS_CREDS].set) { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", _("TLS migration is not supported with this " "QEMU binary")); @@ -1025,8 +1026,9 @@ qemuMigrationParamsDisableTLS(virDomainObjPtr vm, qemuMigrationParamsPtr migParams) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; - if (!priv->job.migParams->params[QEMU_MIGRATION_PARAM_TLS_CREDS].set) + if (!jobPriv->migParams->params[QEMU_MIGRATION_PARAM_TLS_CREDS].set) return 0; if (qemuMigrationParamsSetString(migParams, @@ -1150,6 +1152,7 @@ qemuMigrationParamsCheck(virQEMUDriverPtr driver, virBitmapPtr remoteCaps) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; qemuMigrationCapability cap; qemuMigrationParty party; size_t i; @@ -1203,7 +1206,7 @@ qemuMigrationParamsCheck(virQEMUDriverPtr driver, * to ask QEMU for their current settings. */ - return qemuMigrationParamsFetch(driver, vm, asyncJob, &priv->job.migParams); + return qemuMigrationParamsFetch(driver, vm, asyncJob, &jobPriv->migParams); } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 70fc24b993..af060b3180 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1608,6 +1608,7 @@ qemuProcessHandleSpiceMigrated(qemuMonitorPtr mon G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { qemuDomainObjPrivatePtr priv; + qemuDomainJobPrivatePtr jobPriv; virObjectLock(vm); @@ -1615,12 +1616,13 @@ qemuProcessHandleSpiceMigrated(qemuMonitorPtr mon G_GNUC_UNUSED, vm, vm->def->name); priv = vm->privateData; + jobPriv = priv->job.privateData; if (priv->job.asyncJob != QEMU_ASYNC_JOB_MIGRATION_OUT) { VIR_DEBUG("got SPICE_MIGRATE_COMPLETED event without a migration job"); goto cleanup; } - priv->job.spiceMigrated = true; + jobPriv->spiceMigrated = true; virDomainObjBroadcast(vm); cleanup: @@ -1720,6 +1722,7 @@ qemuProcessHandleDumpCompleted(qemuMonitorPtr mon G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { qemuDomainObjPrivatePtr priv; + qemuDomainJobPrivatePtr jobPriv; virObjectLock(vm); @@ -1727,11 +1730,12 @@ qemuProcessHandleDumpCompleted(qemuMonitorPtr mon G_GNUC_UNUSED, vm, vm->def->name, stats, NULLSTR(error)); priv = vm->privateData; + jobPriv = priv->job.privateData; if (priv->job.asyncJob == QEMU_ASYNC_JOB_NONE) { VIR_DEBUG("got DUMP_COMPLETED event without a dump_completed job"); goto cleanup; } - priv->job.dumpCompleted = true; + jobPriv->dumpCompleted = true; priv->job.current->stats.dump = *stats; priv->job.error = g_strdup(error); @@ -3411,6 +3415,8 @@ qemuProcessRecoverMigrationIn(virQEMUDriverPtr driver, virDomainState state, int reason) { + + qemuDomainJobPrivatePtr jobPriv = job->privateData; bool postcopy = (state == VIR_DOMAIN_PAUSED && reason == VIR_DOMAIN_PAUSED_POSTCOPY_FAILED) || (state == VIR_DOMAIN_RUNNING && @@ -3459,7 +3465,7 @@ qemuProcessRecoverMigrationIn(virQEMUDriverPtr driver, } qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_NONE, - job->migParams, job->apiFlags); + jobPriv->migParams, job->apiFlags); return 0; } @@ -3471,6 +3477,7 @@ qemuProcessRecoverMigrationOut(virQEMUDriverPtr driver, int reason, unsigned int *stopFlags) { + qemuDomainJobPrivatePtr jobPriv = job->privateData; bool postcopy = state == VIR_DOMAIN_PAUSED && (reason == VIR_DOMAIN_PAUSED_POSTCOPY || reason == VIR_DOMAIN_PAUSED_POSTCOPY_FAILED); @@ -3554,7 +3561,7 @@ qemuProcessRecoverMigrationOut(virQEMUDriverPtr driver, } qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_NONE, - job->migParams, job->apiFlags); + jobPriv->migParams, job->apiFlags); return 0; } -- 2.25.1

On Mon, Jul 13, 2020 at 11:33:40PM +0530, Prathamesh Chavan wrote:
To remove dependecy of `qemuDomainJob` on job specific paramters, a `privateData` pointer is introduced. To handle it, structure of callback functions is also introduced.
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- The static callback functions structure was declared in `qemu_domain.c` Due to this, all callback functions (present in `qemu_domainobj.c`) were exposed using the .h file to allow their access by the `qemu_domain.c` file.
src/qemu/qemu_domain.c | 9 ++- src/qemu/qemu_domain.h | 10 ++++ src/qemu/qemu_domainjob.c | 94 ++++++++++++++++++++++++-------- src/qemu/qemu_domainjob.h | 44 ++++++++++++--- src/qemu/qemu_driver.c | 3 +- src/qemu/qemu_migration.c | 28 +++++++--- src/qemu/qemu_migration_params.c | 9 ++- src/qemu/qemu_process.c | 15 +++-- 8 files changed, 165 insertions(+), 47 deletions(-)
So the biggest issue I have with this is that it is impossible to see which of these functions are going to end up in `src/hypervisor/virjob.c` and which of them will stay qemu-specific in `src/qemu/qemu_domainjob.c`. I would suggest either: 1) marking them as such in some understandable way or 2) leaving qemu-specific code in `qemu_driver.c` 3) creating yet another file for what is going to become `virjob.c` Otherwise I'm getting confused with some of the things, why are they there etc.
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 10d2033db1..a02865dc59 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -88,6 +88,13 @@ VIR_ENUM_IMPL(qemuDomainNamespace, "mount", );
+static qemuDomainObjPrivateJobCallbacks qemuPrivateJobCallbacks = { + .allocJobPrivate = &qemuJobAllocPrivate, + .freeJobPrivate = &qemuJobFreePrivate, + .formatJob = &qemuDomainFormatJobPrivate, + .parseJob = &qemuDomainParseJobPrivate, +}; + /** * qemuDomainObjFromDomain: * @domain: Domain pointer that has to be looked up @@ -1585,7 +1592,7 @@ qemuDomainObjPrivateAlloc(void *opaque) if (VIR_ALLOC(priv) < 0) return NULL;
- if (qemuDomainObjInitJob(&priv->job) < 0) { + if (qemuDomainObjInitJob(&priv->job, &qemuPrivateJobCallbacks) < 0) { virReportSystemError(errno, "%s", _("Unable to init qemu driver mutexes")); goto error; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index e524fd0002..bb9b414a46 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -492,6 +492,16 @@ struct _qemuDomainXmlNsDef { char **capsdel; };
+typedef struct _qemuDomainJobPrivate qemuDomainJobPrivate; +typedef qemuDomainJobPrivate *qemuDomainJobPrivatePtr; +struct _qemuDomainJobPrivate { + bool spiceMigration; /* we asked for spice migration and we + * should wait for it to finish */ + bool spiceMigrated; /* spice migration completed */ + bool dumpCompleted; /* dump completed */ + qemuMigrationParamsPtr migParams; +}; + int qemuDomainObjStartWorker(virDomainObjPtr dom); void qemuDomainObjStopWorker(virDomainObjPtr dom);
diff --git a/src/qemu/qemu_domainjob.c b/src/qemu/qemu_domainjob.c index d96d5334a3..fe160afe79 100644 --- a/src/qemu/qemu_domainjob.c +++ b/src/qemu/qemu_domainjob.c @@ -159,23 +159,32 @@ qemuDomainEventEmitJobCompleted(virQEMUDriverPtr driver, virObjectEventStateQueue(driver->domainEventState, event); }
- -int -qemuDomainObjInitJob(qemuDomainJobObjPtr job) +void * +qemuJobAllocPrivate(void) { - memset(job, 0, sizeof(*job)); - - if (virCondInit(&job->cond) < 0) - return -1; + qemuDomainJobPrivatePtr priv; + if (VIR_ALLOC(priv) < 0) + return NULL; + return (void *)priv; +}
- if (virCondInit(&job->asyncCond) < 0) { - virCondDestroy(&job->cond); - return -1; - }
- return 0; +static void +qemuJobFreePrivateData(qemuDomainJobPrivatePtr priv) +{ + priv->spiceMigration = false; + priv->spiceMigrated = false; + priv->dumpCompleted = false; + qemuMigrationParamsFree(priv->migParams); + priv->migParams = NULL; }
+void +qemuJobFreePrivate(void *opaque) +{ + qemuDomainJobObjPtr job = (qemuDomainJobObjPtr) opaque; + qemuJobFreePrivateData(job->privateData); +}
static void qemuDomainObjResetJob(qemuDomainJobObjPtr job) @@ -207,14 +216,11 @@ qemuDomainObjResetAsyncJob(qemuDomainJobObjPtr job) job->phase = 0; job->mask = QEMU_JOB_DEFAULT_MASK; job->abortJob = false; - job->spiceMigration = false; - job->spiceMigrated = false; - job->dumpCompleted = false; VIR_FREE(job->error); g_clear_pointer(&job->current, qemuDomainJobInfoFree); - qemuMigrationParamsFree(job->migParams); - job->migParams = NULL; + job->cb->freeJobPrivate(job);
If this function is supposed to be in `virjob.c`, then the callback function should be just called with `job->privateData` which will help you drop one level of indirection by skipping qemuJobFreePrivate() and calling qemuJobFreePrivateData() directly. The function would take `void *opaque`. [...] Skipping rest of the diff from `qemu_domainjob.c` due to the confusion described above, I'll illustrate it on the header file below.
diff --git a/src/qemu/qemu_domainjob.h b/src/qemu/qemu_domainjob.h index 9d2ee14584..b0e840adc8 100644 --- a/src/qemu/qemu_domainjob.h +++ b/src/qemu/qemu_domainjob.h @@ -156,6 +156,23 @@ qemuDomainJobInfoCopy(qemuDomainJobInfoPtr info);
typedef struct _qemuDomainJobObj qemuDomainJobObj; typedef qemuDomainJobObj *qemuDomainJobObjPtr; + +typedef void *(*qemuDomainObjPrivateJobAlloc)(void); +typedef void (*qemuDomainObjPrivateJobFree)(void *); +typedef int (*qemuDomainObjPrivateJobFormat)(virBufferPtr, + qemuDomainJobObjPtr); +typedef int (*qemuDomainObjPrivateJobParse)(xmlXPathContextPtr, + qemuDomainJobObjPtr); + +typedef struct _qemuDomainObjPrivateJobCallbacks qemuDomainObjPrivateJobCallbacks; +typedef qemuDomainObjPrivateJobCallbacks *qemuDomainObjPrivateJobCallbacksPtr; +struct _qemuDomainObjPrivateJobCallbacks { + qemuDomainObjPrivateJobAlloc allocJobPrivate; + qemuDomainObjPrivateJobFree freeJobPrivate; + qemuDomainObjPrivateJobFormat formatJob; + qemuDomainObjPrivateJobParse parseJob; +}; +
So this is going to be part of `virjob.c`, right?
struct _qemuDomainJobObj { virCond cond; /* Use to coordinate jobs */
@@ -182,14 +199,11 @@ struct _qemuDomainJobObj { qemuDomainJobInfoPtr current; /* async job progress data */ qemuDomainJobInfoPtr completed; /* statistics data of a recently completed job */ bool abortJob; /* abort of the job requested */ - bool spiceMigration; /* we asked for spice migration and we - * should wait for it to finish */ - bool spiceMigrated; /* spice migration completed */ char *error; /* job event completion error */ - bool dumpCompleted; /* dump completed */ - - qemuMigrationParamsPtr migParams; unsigned long apiFlags; /* flags passed to the API which started the async job */ + + void *privateData; /* job specific collection of data */ + qemuDomainObjPrivateJobCallbacksPtr cb; };
Same as this.
const char *qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job, @@ -264,7 +278,9 @@ bool qemuDomainTrackJob(qemuDomainJob job);
void qemuDomainObjFreeJob(qemuDomainJobObjPtr job);
-int qemuDomainObjInitJob(qemuDomainJobObjPtr job); +int +qemuDomainObjInitJob(qemuDomainJobObjPtr job, + qemuDomainObjPrivateJobCallbacksPtr cb);
bool qemuDomainJobAllowed(qemuDomainJobObjPtr jobs, qemuDomainJob newJob);
@@ -275,3 +291,17 @@ qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, int qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, xmlXPathContextPtr ctxt); + +void * +qemuJobAllocPrivate(void); + +void +qemuJobFreePrivate(void *opaque); + +int +qemuDomainFormatJobPrivate(virBufferPtr buf, + qemuDomainJobObjPtr job); + +int +qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, + qemuDomainJobObjPtr job);
But these are going to stay in the qemu code, IIRC. See why it is confusing? The rest looks fine from a quick look. Let's see what others think. Have a nice day, Martin

On Tue, Jul 14, 2020 at 7:59 PM Martin Kletzander <mkletzan@redhat.com> wrote:
On Mon, Jul 13, 2020 at 11:33:40PM +0530, Prathamesh Chavan wrote:
To remove dependecy of `qemuDomainJob` on job specific paramters, a `privateData` pointer is introduced. To handle it, structure of callback functions is also introduced.
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- The static callback functions structure was declared in `qemu_domain.c` Due to this, all callback functions (present in `qemu_domainobj.c`) were exposed using the .h file to allow their access by the `qemu_domain.c` file.
src/qemu/qemu_domain.c | 9 ++- src/qemu/qemu_domain.h | 10 ++++ src/qemu/qemu_domainjob.c | 94 ++++++++++++++++++++++++-------- src/qemu/qemu_domainjob.h | 44 ++++++++++++--- src/qemu/qemu_driver.c | 3 +- src/qemu/qemu_migration.c | 28 +++++++--- src/qemu/qemu_migration_params.c | 9 ++- src/qemu/qemu_process.c | 15 +++-- 8 files changed, 165 insertions(+), 47 deletions(-)
So the biggest issue I have with this is that it is impossible to see which of these functions are going to end up in `src/hypervisor/virjob.c` and which of them will stay qemu-specific in `src/qemu/qemu_domainjob.c`.
I would suggest either:
1) marking them as such in some understandable way or
2) leaving qemu-specific code in `qemu_driver.c`
3) creating yet another file for what is going to become `virjob.c`
Otherwise I'm getting confused with some of the things, why are they there etc.
But doing this rightaway would mean we are again moving back somestuff, which we just brought in this file. (Such as the PrivateXML[Parse,Format]Job functions). What I had in mind, was to deal with this segregation, while the creation of the new file happens. But for more clarity, we can have the code reside in the same file, and spilt into two sections, where all the code residing in the beginning of the file (all the structs and functions) will be the ones, which we plan on moving, and all the code residing in the lower half, will be the one which will persist. The other way of dealing this could be to move these things back to `qemu_domain.c`
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 10d2033db1..a02865dc59 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -88,6 +88,13 @@ VIR_ENUM_IMPL(qemuDomainNamespace, "mount", );
+static qemuDomainObjPrivateJobCallbacks qemuPrivateJobCallbacks = { + .allocJobPrivate = &qemuJobAllocPrivate, + .freeJobPrivate = &qemuJobFreePrivate, + .formatJob = &qemuDomainFormatJobPrivate, + .parseJob = &qemuDomainParseJobPrivate, +}; + /** * qemuDomainObjFromDomain: * @domain: Domain pointer that has to be looked up @@ -1585,7 +1592,7 @@ qemuDomainObjPrivateAlloc(void *opaque) if (VIR_ALLOC(priv) < 0) return NULL;
- if (qemuDomainObjInitJob(&priv->job) < 0) { + if (qemuDomainObjInitJob(&priv->job, &qemuPrivateJobCallbacks) < 0) { virReportSystemError(errno, "%s", _("Unable to init qemu driver mutexes")); goto error; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index e524fd0002..bb9b414a46 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -492,6 +492,16 @@ struct _qemuDomainXmlNsDef { char **capsdel; };
+typedef struct _qemuDomainJobPrivate qemuDomainJobPrivate; +typedef qemuDomainJobPrivate *qemuDomainJobPrivatePtr; +struct _qemuDomainJobPrivate { + bool spiceMigration; /* we asked for spice migration and we + * should wait for it to finish */ + bool spiceMigrated; /* spice migration completed */ + bool dumpCompleted; /* dump completed */ + qemuMigrationParamsPtr migParams; +}; + int qemuDomainObjStartWorker(virDomainObjPtr dom); void qemuDomainObjStopWorker(virDomainObjPtr dom);
diff --git a/src/qemu/qemu_domainjob.c b/src/qemu/qemu_domainjob.c index d96d5334a3..fe160afe79 100644 --- a/src/qemu/qemu_domainjob.c +++ b/src/qemu/qemu_domainjob.c @@ -159,23 +159,32 @@ qemuDomainEventEmitJobCompleted(virQEMUDriverPtr driver, virObjectEventStateQueue(driver->domainEventState, event); }
- -int -qemuDomainObjInitJob(qemuDomainJobObjPtr job) +void * +qemuJobAllocPrivate(void) { - memset(job, 0, sizeof(*job)); - - if (virCondInit(&job->cond) < 0) - return -1; + qemuDomainJobPrivatePtr priv; + if (VIR_ALLOC(priv) < 0) + return NULL; + return (void *)priv; +}
- if (virCondInit(&job->asyncCond) < 0) { - virCondDestroy(&job->cond); - return -1; - }
- return 0; +static void +qemuJobFreePrivateData(qemuDomainJobPrivatePtr priv) +{ + priv->spiceMigration = false; + priv->spiceMigrated = false; + priv->dumpCompleted = false; + qemuMigrationParamsFree(priv->migParams); + priv->migParams = NULL; }
+void +qemuJobFreePrivate(void *opaque) +{ + qemuDomainJobObjPtr job = (qemuDomainJobObjPtr) opaque; + qemuJobFreePrivateData(job->privateData); +}
static void qemuDomainObjResetJob(qemuDomainJobObjPtr job) @@ -207,14 +216,11 @@ qemuDomainObjResetAsyncJob(qemuDomainJobObjPtr job) job->phase = 0; job->mask = QEMU_JOB_DEFAULT_MASK; job->abortJob = false; - job->spiceMigration = false; - job->spiceMigrated = false; - job->dumpCompleted = false; VIR_FREE(job->error); g_clear_pointer(&job->current, qemuDomainJobInfoFree); - qemuMigrationParamsFree(job->migParams); - job->migParams = NULL; + job->cb->freeJobPrivate(job);
If this function is supposed to be in `virjob.c`, then the callback function should be just called with `job->privateData` which will help you drop one level of indirection by skipping qemuJobFreePrivate() and calling qemuJobFreePrivateData() directly. The function would take `void *opaque`.
Yes, thanks for pointing this out. I think while splitting the patch, I rewrote some parts, and this slipped in again. I remember Erik had pointed this out earlier.
[...]
Skipping rest of the diff from `qemu_domainjob.c` due to the confusion described above, I'll illustrate it on the header file below.
diff --git a/src/qemu/qemu_domainjob.h b/src/qemu/qemu_domainjob.h index 9d2ee14584..b0e840adc8 100644 --- a/src/qemu/qemu_domainjob.h +++ b/src/qemu/qemu_domainjob.h @@ -156,6 +156,23 @@ qemuDomainJobInfoCopy(qemuDomainJobInfoPtr info);
typedef struct _qemuDomainJobObj qemuDomainJobObj; typedef qemuDomainJobObj *qemuDomainJobObjPtr; + +typedef void *(*qemuDomainObjPrivateJobAlloc)(void); +typedef void (*qemuDomainObjPrivateJobFree)(void *); +typedef int (*qemuDomainObjPrivateJobFormat)(virBufferPtr, + qemuDomainJobObjPtr); +typedef int (*qemuDomainObjPrivateJobParse)(xmlXPathContextPtr, + qemuDomainJobObjPtr); + +typedef struct _qemuDomainObjPrivateJobCallbacks qemuDomainObjPrivateJobCallbacks; +typedef qemuDomainObjPrivateJobCallbacks *qemuDomainObjPrivateJobCallbacksPtr; +struct _qemuDomainObjPrivateJobCallbacks { + qemuDomainObjPrivateJobAlloc allocJobPrivate; + qemuDomainObjPrivateJobFree freeJobPrivate; + qemuDomainObjPrivateJobFormat formatJob; + qemuDomainObjPrivateJobParse parseJob; +}; +
So this is going to be part of `virjob.c`, right?
Yes.
struct _qemuDomainJobObj { virCond cond; /* Use to coordinate jobs */
@@ -182,14 +199,11 @@ struct _qemuDomainJobObj { qemuDomainJobInfoPtr current; /* async job progress data */ qemuDomainJobInfoPtr completed; /* statistics data of a recently completed job */ bool abortJob; /* abort of the job requested */ - bool spiceMigration; /* we asked for spice migration and we - * should wait for it to finish */ - bool spiceMigrated; /* spice migration completed */ char *error; /* job event completion error */ - bool dumpCompleted; /* dump completed */ - - qemuMigrationParamsPtr migParams; unsigned long apiFlags; /* flags passed to the API which started the async job */ + + void *privateData; /* job specific collection of data */ + qemuDomainObjPrivateJobCallbacksPtr cb; };
Same as this.
Yes, even this shall be moved to the common jobs file and the structures will be renamed accordingly.
const char *qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job, @@ -264,7 +278,9 @@ bool qemuDomainTrackJob(qemuDomainJob job);
void qemuDomainObjFreeJob(qemuDomainJobObjPtr job);
-int qemuDomainObjInitJob(qemuDomainJobObjPtr job); +int +qemuDomainObjInitJob(qemuDomainJobObjPtr job, + qemuDomainObjPrivateJobCallbacksPtr cb);
bool qemuDomainJobAllowed(qemuDomainJobObjPtr jobs, qemuDomainJob newJob);
@@ -275,3 +291,17 @@ qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, int qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, xmlXPathContextPtr ctxt); + +void * +qemuJobAllocPrivate(void); + +void +qemuJobFreePrivate(void *opaque); + +int +qemuDomainFormatJobPrivate(virBufferPtr buf, + qemuDomainJobObjPtr job); + +int +qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, + qemuDomainJobObjPtr job);
But these are going to stay in the qemu code, IIRC. See why it is confusing?
The rest looks fine from a quick look. Let's see what others think.
Have a nice day, Martin

On 7/13/20 8:03 PM, Prathamesh Chavan wrote:
To remove dependecy of `qemuDomainJob` on job specific paramters, a `privateData` pointer is introduced. To handle it, structure of callback functions is also introduced.
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- The static callback functions structure was declared in `qemu_domain.c` Due to this, all callback functions (present in `qemu_domainobj.c`) were exposed using the .h file to allow their access by the `qemu_domain.c` file.
Yeah, well callbacks should be static thus should live in the qemu_domain.c too. Also, the private data struct is defined in qemu_domain.h and thus callbacks which allocate/free/format/parse should live in the corresponding .c file.
src/qemu/qemu_domain.c | 9 ++- src/qemu/qemu_domain.h | 10 ++++ src/qemu/qemu_domainjob.c | 94 ++++++++++++++++++++++++-------- src/qemu/qemu_domainjob.h | 44 ++++++++++++--- src/qemu/qemu_driver.c | 3 +- src/qemu/qemu_migration.c | 28 +++++++--- src/qemu/qemu_migration_params.c | 9 ++- src/qemu/qemu_process.c | 15 +++-- 8 files changed, 165 insertions(+), 47 deletions(-)
This looks almost perfect.
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 10d2033db1..a02865dc59 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -88,6 +88,13 @@ VIR_ENUM_IMPL(qemuDomainNamespace, "mount", );
+static qemuDomainObjPrivateJobCallbacks qemuPrivateJobCallbacks = { + .allocJobPrivate = &qemuJobAllocPrivate, + .freeJobPrivate = &qemuJobFreePrivate, + .formatJob = &qemuDomainFormatJobPrivate, + .parseJob = &qemuDomainParseJobPrivate, +};
I think we will need one callback more - resetJobPrivate. More below. Also, there is no need to put ampersand before functions. Compilers are wise enough to tell that we need the address of the functions.
+ /** * qemuDomainObjFromDomain: * @domain: Domain pointer that has to be looked up @@ -1585,7 +1592,7 @@ qemuDomainObjPrivateAlloc(void *opaque) if (VIR_ALLOC(priv) < 0) return NULL;
- if (qemuDomainObjInitJob(&priv->job) < 0) { + if (qemuDomainObjInitJob(&priv->job, &qemuPrivateJobCallbacks) < 0) { virReportSystemError(errno, "%s", _("Unable to init qemu driver mutexes")); goto error; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index e524fd0002..bb9b414a46 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -492,6 +492,16 @@ struct _qemuDomainXmlNsDef { char **capsdel; };
+typedef struct _qemuDomainJobPrivate qemuDomainJobPrivate; +typedef qemuDomainJobPrivate *qemuDomainJobPrivatePtr; +struct _qemuDomainJobPrivate { + bool spiceMigration; /* we asked for spice migration and we + * should wait for it to finish */ + bool spiceMigrated; /* spice migration completed */ + bool dumpCompleted; /* dump completed */ + qemuMigrationParamsPtr migParams; +}; + int qemuDomainObjStartWorker(virDomainObjPtr dom); void qemuDomainObjStopWorker(virDomainObjPtr dom);
diff --git a/src/qemu/qemu_domainjob.c b/src/qemu/qemu_domainjob.c index d96d5334a3..fe160afe79 100644 --- a/src/qemu/qemu_domainjob.c +++ b/src/qemu/qemu_domainjob.c @@ -159,23 +159,32 @@ qemuDomainEventEmitJobCompleted(virQEMUDriverPtr driver, virObjectEventStateQueue(driver->domainEventState, event); }
- -int -qemuDomainObjInitJob(qemuDomainJobObjPtr job) +void * +qemuJobAllocPrivate(void) { - memset(job, 0, sizeof(*job)); - - if (virCondInit(&job->cond) < 0) - return -1; + qemuDomainJobPrivatePtr priv; + if (VIR_ALLOC(priv) < 0) + return NULL; + return (void *)priv;
Or plain: g_new0(qemuDomainJobPrivate, 1)
+}
- if (virCondInit(&job->asyncCond) < 0) { - virCondDestroy(&job->cond); - return -1; - }
- return 0; +static void +qemuJobFreePrivateData(qemuDomainJobPrivatePtr priv) +{ + priv->spiceMigration = false; + priv->spiceMigrated = false; + priv->dumpCompleted = false; + qemuMigrationParamsFree(priv->migParams); + priv->migParams = NULL;
See, this is what previously qemuDomainObjResetAsyncJob() was doing. And while qemuDomainObjResetAsyncJob() is called from qemuDomainObjFreeJob() it is also called from qemuDomainObjBeginJobInternal() and other places. Therefore, naming this Free() is probably not the best idea. It should be named qemuJobResetPrivate() or something, esp. beacuse it doesn't really free the private data (it doesn't call free(priv)), it just clears/resets them.
}
+void +qemuJobFreePrivate(void *opaque) +{ + qemuDomainJobObjPtr job = (qemuDomainJobObjPtr) opaque; + qemuJobFreePrivateData(job->privateData);
And this will actually free the data.
+}
static void qemuDomainObjResetJob(qemuDomainJobObjPtr job) @@ -207,14 +216,11 @@ qemuDomainObjResetAsyncJob(qemuDomainJobObjPtr job) job->phase = 0; job->mask = QEMU_JOB_DEFAULT_MASK; job->abortJob = false; - job->spiceMigration = false; - job->spiceMigrated = false; - job->dumpCompleted = false; VIR_FREE(job->error); g_clear_pointer(&job->current, qemuDomainJobInfoFree); - qemuMigrationParamsFree(job->migParams); - job->migParams = NULL; + job->cb->freeJobPrivate(job);
This needs to call the resetJobPrivate() callback then.
job->apiFlags = 0; + job->cb = NULL;
Ooops, we definitely do not want to this. Because if we did, then the second time this is called we would dereference a NULL pointer when trying to call any of the callbacks (resetJobPrivate() for instance).
}
void @@ -229,7 +235,7 @@ qemuDomainObjRestoreJob(virDomainObjPtr obj, job->asyncJob = priv->job.asyncJob; job->asyncOwner = priv->job.asyncOwner; job->phase = priv->job.phase; - job->migParams = g_steal_pointer(&priv->job.migParams); + job->privateData = g_steal_pointer(&priv->job.privateData);
Okay, I have to admit, this took me a while to figure out. And it is sort of corect. BUT, after this the priv->job.privateData is going to be NULL (because that's how g_steal_pointer() works). And I don't think the code is prepared for that. So what we need to do is to allocate new private data here.
job->apiFlags = priv->job.apiFlags;
qemuDomainObjResetJob(&priv->job); @@ -1239,14 +1245,24 @@ qemuDomainObjPrivateXMLFormatNBDMigration(virBufferPtr buf, return 0; }
+int +qemuDomainFormatJobPrivate(virBufferPtr buf, + qemuDomainJobObjPtr job) +{ + qemuDomainJobPrivatePtr priv = job->privateData; + if (priv->migParams) + qemuMigrationParamsFormat(buf, priv->migParams); + return 0; +}
int qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, virDomainObjPtr vm) { + qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobObjPtr jobObj = &priv->job; g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); - qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainJob job = priv->job.active;
if (!qemuDomainTrackJob(job)) @@ -1273,8 +1289,8 @@ qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, qemuDomainObjPrivateXMLFormatNBDMigration(&childBuf, vm) < 0) return -1;
- if (priv->job.migParams) - qemuMigrationParamsFormat(&childBuf, priv->job.migParams); + if (jobObj->cb->formatJob(&childBuf, jobObj) < 0) + return -1;
virXMLFormatElement(buf, "job", &attrBuf, &childBuf);
@@ -1366,12 +1382,22 @@ qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm, return 0; }
+int +qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, + qemuDomainJobObjPtr job) +{ + qemuDomainJobPrivatePtr jobPriv = job->privateData; + if (qemuMigrationParamsParse(ctxt, &jobPriv->migParams) < 0) + return -1; + return 0; +}
int qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, xmlXPathContextPtr ctxt) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobObjPtr job = &priv->job; VIR_XPATH_NODE_AUTORESTORE(ctxt); g_autofree char *tmp = NULL;
@@ -1420,8 +1446,32 @@ qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, if (qemuDomainObjPrivateXMLParseJobNBD(vm, ctxt) < 0) return -1;
- if (qemuMigrationParamsParse(ctxt, &priv->job.migParams) < 0) + if (job->cb->parseJob(ctxt, job) < 0) + return -1; + + return 0; +} + + +int +qemuDomainObjInitJob(qemuDomainJobObjPtr job, + qemuDomainObjPrivateJobCallbacksPtr cb) +{ + memset(job, 0, sizeof(*job)); + job->cb = cb; + + if (!(job->privateData = job->cb->allocJobPrivate())) { + qemuDomainObjFreeJob(job);
This call is needless - alloc failed there is nothing to free.
+ return -1; + } + + if (virCondInit(&job->cond) < 0) + return -1; + + if (virCondInit(&job->asyncCond) < 0) { + virCondDestroy(&job->cond); return -1;
But if any of these calls fail, then we have allocated data the needs freeing. I think we want this to be squashed in: diff --git c/src/qemu/qemu_domain.c w/src/qemu/qemu_domain.c index a02865dc59..b0ed562d25 100644 --- c/src/qemu/qemu_domain.c +++ w/src/qemu/qemu_domain.c @@ -88,11 +88,72 @@ VIR_ENUM_IMPL(qemuDomainNamespace, "mount", ); + +static void * +qemuJobAllocPrivate(void) +{ + return g_new0(qemuDomainJobPrivate, 1); +} + + +static void +qemuJobFreePrivate(void *opaque) +{ + qemuDomainJobPrivatePtr priv = opaque; + + if (!priv) + return; + + qemuMigrationParamsFree(priv->migParams); + VIR_FREE(priv); +} + + +static void +qemuJobResetPrivate(void *opaque) +{ + qemuDomainJobPrivatePtr priv = opaque; + + priv->spiceMigration = false; + priv->spiceMigrated = false; + priv->dumpCompleted = false; + qemuMigrationParamsFree(priv->migParams); + priv->migParams = NULL; +} + + +static int +qemuDomainFormatJobPrivate(virBufferPtr buf, + qemuDomainJobObjPtr job) +{ + qemuDomainJobPrivatePtr priv = job->privateData; + + if (priv->migParams) + qemuMigrationParamsFormat(buf, priv->migParams); + + return 0; +} + + +static int +qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, + qemuDomainJobObjPtr job) +{ + qemuDomainJobPrivatePtr priv = job->privateData; + + if (qemuMigrationParamsParse(ctxt, &priv->migParams) < 0) + return -1; + + return 0; +} + + static qemuDomainObjPrivateJobCallbacks qemuPrivateJobCallbacks = { - .allocJobPrivate = &qemuJobAllocPrivate, - .freeJobPrivate = &qemuJobFreePrivate, - .formatJob = &qemuDomainFormatJobPrivate, - .parseJob = &qemuDomainParseJobPrivate, + .allocJobPrivate = qemuJobAllocPrivate, + .freeJobPrivate = qemuJobFreePrivate, + .resetJobPrivate = qemuJobResetPrivate, + .formatJob = qemuDomainFormatJobPrivate, + .parseJob = qemuDomainParseJobPrivate, }; /** diff --git c/src/qemu/qemu_domainjob.c w/src/qemu/qemu_domainjob.c index fe160afe79..64381d8f78 100644 --- c/src/qemu/qemu_domainjob.c +++ w/src/qemu/qemu_domainjob.c @@ -159,33 +159,6 @@ qemuDomainEventEmitJobCompleted(virQEMUDriverPtr driver, virObjectEventStateQueue(driver->domainEventState, event); } -void * -qemuJobAllocPrivate(void) -{ - qemuDomainJobPrivatePtr priv; - if (VIR_ALLOC(priv) < 0) - return NULL; - return (void *)priv; -} - - -static void -qemuJobFreePrivateData(qemuDomainJobPrivatePtr priv) -{ - priv->spiceMigration = false; - priv->spiceMigrated = false; - priv->dumpCompleted = false; - qemuMigrationParamsFree(priv->migParams); - priv->migParams = NULL; -} - -void -qemuJobFreePrivate(void *opaque) -{ - qemuDomainJobObjPtr job = (qemuDomainJobObjPtr) opaque; - qemuJobFreePrivateData(job->privateData); -} - static void qemuDomainObjResetJob(qemuDomainJobObjPtr job) { @@ -218,12 +191,12 @@ qemuDomainObjResetAsyncJob(qemuDomainJobObjPtr job) job->abortJob = false; VIR_FREE(job->error); g_clear_pointer(&job->current, qemuDomainJobInfoFree); - job->cb->freeJobPrivate(job); + job->cb->resetJobPrivate(job->privateData); job->apiFlags = 0; - job->cb = NULL; } -void + +int qemuDomainObjRestoreJob(virDomainObjPtr obj, qemuDomainJobObjPtr job) { @@ -238,8 +211,13 @@ qemuDomainObjRestoreJob(virDomainObjPtr obj, job->privateData = g_steal_pointer(&priv->job.privateData); job->apiFlags = priv->job.apiFlags; + if (!(priv->job.privateData = priv->job.cb->allocJobPrivate())) + return -1; + job->cb = priv->job.cb; + qemuDomainObjResetJob(&priv->job); qemuDomainObjResetAsyncJob(&priv->job); + return 0; } void @@ -247,6 +225,7 @@ qemuDomainObjFreeJob(qemuDomainJobObjPtr job) { qemuDomainObjResetJob(job); qemuDomainObjResetAsyncJob(job); + job->cb->freeJobPrivate(job->privateData); g_clear_pointer(&job->current, qemuDomainJobInfoFree); g_clear_pointer(&job->completed, qemuDomainJobInfoFree); virCondDestroy(&job->cond); @@ -1245,15 +1224,6 @@ qemuDomainObjPrivateXMLFormatNBDMigration(virBufferPtr buf, return 0; } -int -qemuDomainFormatJobPrivate(virBufferPtr buf, - qemuDomainJobObjPtr job) -{ - qemuDomainJobPrivatePtr priv = job->privateData; - if (priv->migParams) - qemuMigrationParamsFormat(buf, priv->migParams); - return 0; -} int qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, @@ -1382,16 +1352,6 @@ qemuDomainObjPrivateXMLParseJobNBD(virDomainObjPtr vm, return 0; } -int -qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, - qemuDomainJobObjPtr job) -{ - qemuDomainJobPrivatePtr jobPriv = job->privateData; - if (qemuMigrationParamsParse(ctxt, &jobPriv->migParams) < 0) - return -1; - return 0; -} - int qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, xmlXPathContextPtr ctxt) @@ -1460,15 +1420,16 @@ qemuDomainObjInitJob(qemuDomainJobObjPtr job, memset(job, 0, sizeof(*job)); job->cb = cb; - if (!(job->privateData = job->cb->allocJobPrivate())) { - qemuDomainObjFreeJob(job); + if (!(job->privateData = job->cb->allocJobPrivate())) return -1; - } - if (virCondInit(&job->cond) < 0) + if (virCondInit(&job->cond) < 0) { + job->cb->freeJobPrivate(job->privateData); return -1; + } if (virCondInit(&job->asyncCond) < 0) { + job->cb->freeJobPrivate(job->privateData); virCondDestroy(&job->cond); return -1; } diff --git c/src/qemu/qemu_domainjob.h w/src/qemu/qemu_domainjob.h index b0e840adc8..d2c599cd68 100644 --- c/src/qemu/qemu_domainjob.h +++ w/src/qemu/qemu_domainjob.h @@ -159,6 +159,7 @@ typedef qemuDomainJobObj *qemuDomainJobObjPtr; typedef void *(*qemuDomainObjPrivateJobAlloc)(void); typedef void (*qemuDomainObjPrivateJobFree)(void *); +typedef void (*qemuDomainObjPrivateJobReset)(void *); typedef int (*qemuDomainObjPrivateJobFormat)(virBufferPtr, qemuDomainJobObjPtr); typedef int (*qemuDomainObjPrivateJobParse)(xmlXPathContextPtr, @@ -169,6 +170,7 @@ typedef qemuDomainObjPrivateJobCallbacks *qemuDomainObjPrivateJobCallbacksPtr; struct _qemuDomainObjPrivateJobCallbacks { qemuDomainObjPrivateJobAlloc allocJobPrivate; qemuDomainObjPrivateJobFree freeJobPrivate; + qemuDomainObjPrivateJobReset resetJobPrivate; qemuDomainObjPrivateJobFormat formatJob; qemuDomainObjPrivateJobParse parseJob; }; @@ -248,8 +250,8 @@ void qemuDomainObjSetJobPhase(virQEMUDriverPtr driver, int phase); void qemuDomainObjSetAsyncJobMask(virDomainObjPtr obj, unsigned long long allowedJobs); -void qemuDomainObjRestoreJob(virDomainObjPtr obj, - qemuDomainJobObjPtr job); +int qemuDomainObjRestoreJob(virDomainObjPtr obj, + qemuDomainJobObjPtr job); void qemuDomainObjDiscardAsyncJob(virQEMUDriverPtr driver, virDomainObjPtr obj); void qemuDomainObjReleaseAsyncJob(virDomainObjPtr obj); @@ -291,17 +293,3 @@ qemuDomainObjPrivateXMLFormatJob(virBufferPtr buf, int qemuDomainObjPrivateXMLParseJob(virDomainObjPtr vm, xmlXPathContextPtr ctxt); - -void * -qemuJobAllocPrivate(void); - -void -qemuJobFreePrivate(void *opaque); - -int -qemuDomainFormatJobPrivate(virBufferPtr buf, - qemuDomainJobObjPtr job); - -int -qemuDomainParseJobPrivate(xmlXPathContextPtr ctxt, - qemuDomainJobObjPtr job); Michal

To remove dependecy of `qemuDomainJobInfo` on job specific paramters, a `privateData` pointer is introduced. To handle it, structure of callback functions is also introduced. Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- src/qemu/qemu_backup.c | 15 +++-- src/qemu/qemu_domain.h | 18 ++++++ src/qemu/qemu_domainjob.c | 98 +++++++++++++++++++++++++------- src/qemu/qemu_domainjob.h | 31 +++++----- src/qemu/qemu_driver.c | 18 +++--- src/qemu/qemu_migration.c | 14 +++-- src/qemu/qemu_migration_cookie.c | 7 ++- src/qemu/qemu_process.c | 11 +++- 8 files changed, 154 insertions(+), 58 deletions(-) diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index b711f8f623..a0832b4587 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -529,6 +529,7 @@ qemuBackupJobTerminate(virDomainObjPtr vm, { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobInfoPrivatePtr jobInfoPriv; size_t i; qemuDomainJobInfoUpdateTime(priv->job.current); @@ -536,10 +537,13 @@ qemuBackupJobTerminate(virDomainObjPtr vm, g_clear_pointer(&priv->job.completed, qemuDomainJobInfoFree); priv->job.completed = qemuDomainJobInfoCopy(priv->job.current); - priv->job.completed->stats.backup.total = priv->backup->push_total; - priv->job.completed->stats.backup.transferred = priv->backup->push_transferred; - priv->job.completed->stats.backup.tmp_used = priv->backup->pull_tmp_used; - priv->job.completed->stats.backup.tmp_total = priv->backup->pull_tmp_total; + + jobInfoPriv = priv->job.completed->privateData; + + jobInfoPriv->stats.backup.total = priv->backup->push_total; + jobInfoPriv->stats.backup.transferred = priv->backup->push_transferred; + jobInfoPriv->stats.backup.tmp_used = priv->backup->pull_tmp_used; + jobInfoPriv->stats.backup.tmp_total = priv->backup->pull_tmp_total; priv->job.completed->status = jobstatus; priv->job.completed->errmsg = g_strdup(priv->backup->errmsg); @@ -1069,7 +1073,8 @@ qemuBackupGetJobInfoStats(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainJobInfoPtr jobInfo) { - qemuDomainBackupStats *stats = &jobInfo->stats.backup; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; + qemuDomainBackupStats *stats = &jobInfoPriv->stats.backup; qemuDomainObjPrivatePtr priv = vm->privateData; qemuMonitorJobInfoPtr *blockjobs = NULL; size_t nblockjobs = 0; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index bb9b414a46..7fcbefd0c0 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -502,6 +502,24 @@ struct _qemuDomainJobPrivate { qemuMigrationParamsPtr migParams; }; +typedef struct _qemuDomainBackupStats qemuDomainBackupStats; +struct _qemuDomainBackupStats { + unsigned long long transferred; + unsigned long long total; + unsigned long long tmp_used; + unsigned long long tmp_total; +}; + +typedef struct _qemuDomainJobInfoPrivate qemuDomainJobInfoPrivate; +typedef qemuDomainJobInfoPrivate *qemuDomainJobInfoPrivatePtr; +struct _qemuDomainJobInfoPrivate { + union { + qemuMonitorMigrationStats mig; + qemuMonitorDumpStats dump; + qemuDomainBackupStats backup; + } stats; +}; + int qemuDomainObjStartWorker(virDomainObjPtr dom); void qemuDomainObjStopWorker(virDomainObjPtr dom); diff --git a/src/qemu/qemu_domainjob.c b/src/qemu/qemu_domainjob.c index fe160afe79..bb086db2b7 100644 --- a/src/qemu/qemu_domainjob.c +++ b/src/qemu/qemu_domainjob.c @@ -63,6 +63,7 @@ VIR_ENUM_IMPL(qemuDomainAsyncJob, "backup", ); + const char * qemuDomainAsyncJobPhaseToString(qemuDomainAsyncJob job, int phase G_GNUC_UNUSED) @@ -115,27 +116,78 @@ qemuDomainAsyncJobPhaseFromString(qemuDomainAsyncJob job, return -1; } +static void +qemuJobInfoFreePrivateData(qemuDomainJobInfoPrivatePtr priv) +{ + g_free(&priv->stats); +} + +static void +qemuJobInfoFreePrivate(void *opaque) +{ + qemuDomainJobInfoPtr jobInfo = (qemuDomainJobInfoPtr) opaque; + qemuJobInfoFreePrivateData(jobInfo->privateData); +} void qemuDomainJobInfoFree(qemuDomainJobInfoPtr info) { + info->cb->freeJobInfoPrivate(info); g_free(info->errmsg); g_free(info); } +static void * +qemuDomainJobInfoPrivateAlloc(void) +{ + qemuDomainJobInfoPrivatePtr retPriv = g_new0(qemuDomainJobInfoPrivate, 1); + return (void *)retPriv; +} + +static void +qemuDomainJobInfoPrivateCopy(qemuDomainJobInfoPtr src, + qemuDomainJobInfoPtr dest) +{ + memcpy(dest->privateData, src->privateData, + sizeof(qemuDomainJobInfoPrivate)); +} + +static qemuDomainJobInfoPtr +qemuDomainJobInfoAlloc(qemuDomainObjPrivateJobInfoCallbacksPtr cb) +{ + qemuDomainJobInfoPtr ret = g_new0(qemuDomainJobInfo, 1); + ret->cb = cb; + ret->privateData = ret->cb->allocJobInfoPrivate(); + return ret; +} + +static void +qemuDomainCurrentJobInfoInit(qemuDomainJobObjPtr job, + qemuDomainObjPrivateJobInfoCallbacksPtr cb) +{ + job->current = qemuDomainJobInfoAlloc(cb); + job->current->status = QEMU_DOMAIN_JOB_STATUS_ACTIVE; +} qemuDomainJobInfoPtr qemuDomainJobInfoCopy(qemuDomainJobInfoPtr info) { - qemuDomainJobInfoPtr ret = g_new0(qemuDomainJobInfo, 1); + qemuDomainJobInfoPtr ret = qemuDomainJobInfoAlloc(info->cb); memcpy(ret, info, sizeof(*info)); + ret->cb->copyJobInfoPrivate(info, ret); ret->errmsg = g_strdup(info->errmsg); return ret; } +static qemuDomainObjPrivateJobInfoCallbacks qemuJobInfoPrivateCallbacks = { + .allocJobInfoPrivate = &qemuDomainJobInfoPrivateAlloc, + .freeJobInfoPrivate = &qemuJobInfoFreePrivate, + .copyJobInfoPrivate = &qemuDomainJobInfoPrivateCopy, +}; + void qemuDomainEventEmitJobCompleted(virQEMUDriverPtr driver, virDomainObjPtr vm) @@ -285,6 +337,7 @@ int qemuDomainJobInfoUpdateDowntime(qemuDomainJobInfoPtr jobInfo) { unsigned long long now; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; if (!jobInfo->stopped) return 0; @@ -298,8 +351,8 @@ qemuDomainJobInfoUpdateDowntime(qemuDomainJobInfoPtr jobInfo) return 0; } - jobInfo->stats.mig.downtime = now - jobInfo->stopped; - jobInfo->stats.mig.downtime_set = true; + jobInfoPriv->stats.mig.downtime = now - jobInfo->stopped; + jobInfoPriv->stats.mig.downtime_set = true; return 0; } @@ -334,38 +387,39 @@ int qemuDomainJobInfoToInfo(qemuDomainJobInfoPtr jobInfo, virDomainJobInfoPtr info) { + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; info->type = qemuDomainJobStatusToType(jobInfo->status); info->timeElapsed = jobInfo->timeElapsed; switch (jobInfo->statsType) { case QEMU_DOMAIN_JOB_STATS_TYPE_MIGRATION: - info->memTotal = jobInfo->stats.mig.ram_total; - info->memRemaining = jobInfo->stats.mig.ram_remaining; - info->memProcessed = jobInfo->stats.mig.ram_transferred; - info->fileTotal = jobInfo->stats.mig.disk_total + + info->memTotal = jobInfoPriv->stats.mig.ram_total; + info->memRemaining = jobInfoPriv->stats.mig.ram_remaining; + info->memProcessed = jobInfoPriv->stats.mig.ram_transferred; + info->fileTotal = jobInfoPriv->stats.mig.disk_total + jobInfo->mirrorStats.total; - info->fileRemaining = jobInfo->stats.mig.disk_remaining + + info->fileRemaining = jobInfoPriv->stats.mig.disk_remaining + (jobInfo->mirrorStats.total - jobInfo->mirrorStats.transferred); - info->fileProcessed = jobInfo->stats.mig.disk_transferred + + info->fileProcessed = jobInfoPriv->stats.mig.disk_transferred + jobInfo->mirrorStats.transferred; break; case QEMU_DOMAIN_JOB_STATS_TYPE_SAVEDUMP: - info->memTotal = jobInfo->stats.mig.ram_total; - info->memRemaining = jobInfo->stats.mig.ram_remaining; - info->memProcessed = jobInfo->stats.mig.ram_transferred; + info->memTotal = jobInfoPriv->stats.mig.ram_total; + info->memRemaining = jobInfoPriv->stats.mig.ram_remaining; + info->memProcessed = jobInfoPriv->stats.mig.ram_transferred; break; case QEMU_DOMAIN_JOB_STATS_TYPE_MEMDUMP: - info->memTotal = jobInfo->stats.dump.total; - info->memProcessed = jobInfo->stats.dump.completed; + info->memTotal = jobInfoPriv->stats.dump.total; + info->memProcessed = jobInfoPriv->stats.dump.completed; info->memRemaining = info->memTotal - info->memProcessed; break; case QEMU_DOMAIN_JOB_STATS_TYPE_BACKUP: - info->fileTotal = jobInfo->stats.backup.total; - info->fileProcessed = jobInfo->stats.backup.transferred; + info->fileTotal = jobInfoPriv->stats.backup.total; + info->fileProcessed = jobInfoPriv->stats.backup.transferred; info->fileRemaining = info->fileTotal - info->fileProcessed; break; @@ -387,7 +441,8 @@ qemuDomainMigrationJobInfoToParams(qemuDomainJobInfoPtr jobInfo, virTypedParameterPtr *params, int *nparams) { - qemuMonitorMigrationStats *stats = &jobInfo->stats.mig; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; + qemuMonitorMigrationStats *stats = &jobInfoPriv->stats.mig; qemuDomainMirrorStatsPtr mirrorStats = &jobInfo->mirrorStats; virTypedParameterPtr par = NULL; int maxpar = 0; @@ -564,7 +619,8 @@ qemuDomainDumpJobInfoToParams(qemuDomainJobInfoPtr jobInfo, virTypedParameterPtr *params, int *nparams) { - qemuMonitorDumpStats *stats = &jobInfo->stats.dump; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; + qemuMonitorDumpStats *stats = &jobInfoPriv->stats.dump; virTypedParameterPtr par = NULL; int maxpar = 0; int npar = 0; @@ -607,7 +663,8 @@ qemuDomainBackupJobInfoToParams(qemuDomainJobInfoPtr jobInfo, virTypedParameterPtr *params, int *nparams) { - qemuDomainBackupStats *stats = &jobInfo->stats.backup; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; + qemuDomainBackupStats *stats = &jobInfoPriv->stats.backup; g_autoptr(virTypedParamList) par = g_new0(virTypedParamList, 1); if (virTypedParamListAddInt(par, jobInfo->operation, @@ -890,8 +947,7 @@ qemuDomainObjBeginJobInternal(virQEMUDriverPtr driver, qemuDomainAsyncJobTypeToString(asyncJob), obj, obj->def->name); qemuDomainObjResetAsyncJob(&priv->job); - priv->job.current = g_new0(qemuDomainJobInfo, 1); - priv->job.current->status = QEMU_DOMAIN_JOB_STATUS_ACTIVE; + qemuDomainCurrentJobInfoInit(&priv->job, &qemuJobInfoPrivateCallbacks); priv->job.asyncJob = asyncJob; priv->job.asyncOwner = virThreadSelfID(); priv->job.asyncOwnerAPI = virThreadJobGet(); diff --git a/src/qemu/qemu_domainjob.h b/src/qemu/qemu_domainjob.h index b0e840adc8..3c55cf29ed 100644 --- a/src/qemu/qemu_domainjob.h +++ b/src/qemu/qemu_domainjob.h @@ -107,16 +107,22 @@ struct _qemuDomainMirrorStats { unsigned long long total; }; -typedef struct _qemuDomainBackupStats qemuDomainBackupStats; -struct _qemuDomainBackupStats { - unsigned long long transferred; - unsigned long long total; - unsigned long long tmp_used; - unsigned long long tmp_total; -}; - typedef struct _qemuDomainJobInfo qemuDomainJobInfo; typedef qemuDomainJobInfo *qemuDomainJobInfoPtr; + +typedef void *(*qemuDomainObjJobInfoPrivateAlloc)(void); +typedef void (*qemuDomainObjJobInfoPrivateFree)(void *); +typedef void (*qemuDomainObjJobInfoPrivateCopy)(qemuDomainJobInfoPtr, + qemuDomainJobInfoPtr); + +typedef struct _qemuDomainObjPrivateJobInfoCallbacks qemuDomainObjPrivateJobInfoCallbacks; +typedef qemuDomainObjPrivateJobInfoCallbacks *qemuDomainObjPrivateJobInfoCallbacksPtr; +struct _qemuDomainObjPrivateJobInfoCallbacks { + qemuDomainObjJobInfoPrivateAlloc allocJobInfoPrivate; + qemuDomainObjJobInfoPrivateFree freeJobInfoPrivate; + qemuDomainObjJobInfoPrivateCopy copyJobInfoPrivate; +}; + struct _qemuDomainJobInfo { qemuDomainJobStatus status; virDomainJobOperation operation; @@ -136,14 +142,11 @@ struct _qemuDomainJobInfo { bool timeDeltaSet; /* Raw values from QEMU */ qemuDomainJobStatsType statsType; - union { - qemuMonitorMigrationStats mig; - qemuMonitorDumpStats dump; - qemuDomainBackupStats backup; - } stats; qemuDomainMirrorStats mirrorStats; - char *errmsg; /* optional error message for failed completed jobs */ + + void *privateData; /* job specific collection of info */ + qemuDomainObjPrivateJobInfoCallbacksPtr cb; }; void diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d9c5f21f21..058e15e864 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3702,6 +3702,7 @@ qemuDumpWaitForCompletion(virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainJobPrivatePtr jobPriv = priv->job.privateData; + qemuDomainJobInfoPrivatePtr jobInfoPriv = priv->job.current->privateData; VIR_DEBUG("Waiting for dump completion"); while (!jobPriv->dumpCompleted && !priv->job.abortJob) { @@ -3709,7 +3710,7 @@ qemuDumpWaitForCompletion(virDomainObjPtr vm) return -1; } - if (priv->job.current->stats.dump.status == QEMU_MONITOR_DUMP_STATUS_FAILED) { + if (jobInfoPriv->stats.dump.status == QEMU_MONITOR_DUMP_STATUS_FAILED) { if (priv->job.error) virReportError(VIR_ERR_OPERATION_FAILED, _("memory-only dump failed: %s"), @@ -13527,6 +13528,7 @@ qemuDomainGetJobInfoDumpStats(virQEMUDriverPtr driver, { qemuDomainObjPrivatePtr priv = vm->privateData; qemuMonitorDumpStats stats = { 0 }; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; int rc; if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0) @@ -13537,33 +13539,33 @@ qemuDomainGetJobInfoDumpStats(virQEMUDriverPtr driver, if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0) return -1; - jobInfo->stats.dump = stats; + jobInfoPriv->stats.dump = stats; if (qemuDomainJobInfoUpdateTime(jobInfo) < 0) return -1; - switch (jobInfo->stats.dump.status) { + switch (jobInfoPriv->stats.dump.status) { case QEMU_MONITOR_DUMP_STATUS_NONE: case QEMU_MONITOR_DUMP_STATUS_FAILED: case QEMU_MONITOR_DUMP_STATUS_LAST: virReportError(VIR_ERR_OPERATION_FAILED, _("dump query failed, status=%d"), - jobInfo->stats.dump.status); + jobInfoPriv->stats.dump.status); return -1; break; case QEMU_MONITOR_DUMP_STATUS_ACTIVE: jobInfo->status = QEMU_DOMAIN_JOB_STATUS_ACTIVE; VIR_DEBUG("dump active, bytes written='%llu' remaining='%llu'", - jobInfo->stats.dump.completed, - jobInfo->stats.dump.total - - jobInfo->stats.dump.completed); + jobInfoPriv->stats.dump.completed, + jobInfoPriv->stats.dump.total - + jobInfoPriv->stats.dump.completed); break; case QEMU_MONITOR_DUMP_STATUS_COMPLETED: jobInfo->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED; VIR_DEBUG("dump completed, bytes written='%llu'", - jobInfo->stats.dump.completed); + jobInfoPriv->stats.dump.completed); break; } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 2c7bf349c3..0c4136ef8a 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1439,7 +1439,8 @@ qemuMigrationSrcWaitForSpice(virDomainObjPtr vm) static void qemuMigrationUpdateJobType(qemuDomainJobInfoPtr jobInfo) { - switch ((qemuMonitorMigrationStatus) jobInfo->stats.mig.status) { + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; + switch ((qemuMonitorMigrationStatus) jobInfoPriv->stats.mig.status) { case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY: jobInfo->status = QEMU_DOMAIN_JOB_STATUS_POSTCOPY; break; @@ -1486,6 +1487,7 @@ qemuMigrationAnyFetchStats(virQEMUDriverPtr driver, char **error) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; qemuMonitorMigrationStats stats; int rv; @@ -1497,7 +1499,7 @@ qemuMigrationAnyFetchStats(virQEMUDriverPtr driver, if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0) return -1; - jobInfo->stats.mig = stats; + jobInfoPriv->stats.mig = stats; return 0; } @@ -1539,12 +1541,13 @@ qemuMigrationJobCheckStatus(virQEMUDriverPtr driver, { qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainJobInfoPtr jobInfo = priv->job.current; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; char *error = NULL; bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT); int ret = -1; if (!events || - jobInfo->stats.mig.status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) { + jobInfoPriv->stats.mig.status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) { if (qemuMigrationAnyFetchStats(driver, vm, asyncJob, jobInfo, &error) < 0) return -1; } @@ -3013,6 +3016,7 @@ qemuMigrationSrcConfirmPhase(virQEMUDriverPtr driver, /* Update times with the values sent by the destination daemon */ if (mig->jobInfo && jobInfo) { int reason; + qemuDomainJobInfoPrivatePtr jobInfoPriv = mig->jobInfo->privateData; /* We need to refresh migration statistics after a completed post-copy * migration since priv->job.completed contains obsolete data from the @@ -3027,8 +3031,8 @@ qemuMigrationSrcConfirmPhase(virQEMUDriverPtr driver, qemuDomainJobInfoUpdateTime(jobInfo); jobInfo->timeDeltaSet = mig->jobInfo->timeDeltaSet; jobInfo->timeDelta = mig->jobInfo->timeDelta; - jobInfo->stats.mig.downtime_set = mig->jobInfo->stats.mig.downtime_set; - jobInfo->stats.mig.downtime = mig->jobInfo->stats.mig.downtime; + jobInfoPriv->stats.mig.downtime_set = jobInfoPriv->stats.mig.downtime_set; + jobInfoPriv->stats.mig.downtime = jobInfoPriv->stats.mig.downtime; } if (flags & VIR_MIGRATE_OFFLINE) diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c index 81b557e0a8..a3e3ff95e8 100644 --- a/src/qemu/qemu_migration_cookie.c +++ b/src/qemu/qemu_migration_cookie.c @@ -641,7 +641,8 @@ static void qemuMigrationCookieStatisticsXMLFormat(virBufferPtr buf, qemuDomainJobInfoPtr jobInfo) { - qemuMonitorMigrationStats *stats = &jobInfo->stats.mig; + qemuDomainJobInfoPrivatePtr jobInfoPriv = jobInfo->privateData; + qemuMonitorMigrationStats *stats = &jobInfoPriv->stats.mig; virBufferAddLit(buf, "<statistics>\n"); virBufferAdjustIndent(buf, 2); @@ -1043,14 +1044,16 @@ qemuMigrationCookieStatisticsXMLParse(xmlXPathContextPtr ctxt) { qemuDomainJobInfoPtr jobInfo = NULL; qemuMonitorMigrationStats *stats; + qemuDomainJobInfoPrivatePtr jobInfoPriv; VIR_XPATH_NODE_AUTORESTORE(ctxt); if (!(ctxt->node = virXPathNode("./statistics", ctxt))) return NULL; jobInfo = g_new0(qemuDomainJobInfo, 1); + jobInfoPriv = jobInfo->privateData; - stats = &jobInfo->stats.mig; + stats = &jobInfoPriv->stats.mig; jobInfo->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED; virXPathULongLong("string(./started[1])", ctxt, &jobInfo->started); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index af060b3180..eb9b980a6a 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1641,6 +1641,7 @@ qemuProcessHandleMigrationStatus(qemuMonitorPtr mon G_GNUC_UNUSED, virQEMUDriverPtr driver = opaque; virObjectEventPtr event = NULL; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + qemuDomainJobInfoPrivatePtr jobInfoPriv; int reason; virObjectLock(vm); @@ -1650,12 +1651,14 @@ qemuProcessHandleMigrationStatus(qemuMonitorPtr mon G_GNUC_UNUSED, qemuMonitorMigrationStatusTypeToString(status)); priv = vm->privateData; + jobInfoPriv = priv->job.current->privateData; + if (priv->job.asyncJob == QEMU_ASYNC_JOB_NONE) { VIR_DEBUG("got MIGRATION event without a migration job"); goto cleanup; } - priv->job.current->stats.mig.status = status; + jobInfoPriv->stats.mig.status = status; virDomainObjBroadcast(vm); if (status == QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY && @@ -1723,6 +1726,7 @@ qemuProcessHandleDumpCompleted(qemuMonitorPtr mon G_GNUC_UNUSED, { qemuDomainObjPrivatePtr priv; qemuDomainJobPrivatePtr jobPriv; + qemuDomainJobInfoPrivatePtr jobInfoPriv; virObjectLock(vm); @@ -1731,18 +1735,19 @@ qemuProcessHandleDumpCompleted(qemuMonitorPtr mon G_GNUC_UNUSED, priv = vm->privateData; jobPriv = priv->job.privateData; + jobInfoPriv = priv->job.current->privateData; if (priv->job.asyncJob == QEMU_ASYNC_JOB_NONE) { VIR_DEBUG("got DUMP_COMPLETED event without a dump_completed job"); goto cleanup; } jobPriv->dumpCompleted = true; - priv->job.current->stats.dump = *stats; + jobInfoPriv->stats.dump = *stats; priv->job.error = g_strdup(error); /* Force error if extracting the DUMP_COMPLETED status failed */ if (!error && status < 0) { priv->job.error = g_strdup(virGetLastErrorMessage()); - priv->job.current->stats.dump.status = QEMU_MONITOR_DUMP_STATUS_FAILED; + jobInfoPriv->stats.dump.status = QEMU_MONITOR_DUMP_STATUS_FAILED; } virDomainObjBroadcast(vm); -- 2.25.1

On 7/13/20 8:03 PM, Prathamesh Chavan wrote:
To remove dependecy of `qemuDomainJobInfo` on job specific paramters, a `privateData` pointer is introduced. To handle it, structure of callback functions is also introduced.
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- src/qemu/qemu_backup.c | 15 +++-- src/qemu/qemu_domain.h | 18 ++++++ src/qemu/qemu_domainjob.c | 98 +++++++++++++++++++++++++------- src/qemu/qemu_domainjob.h | 31 +++++----- src/qemu/qemu_driver.c | 18 +++--- src/qemu/qemu_migration.c | 14 +++-- src/qemu/qemu_migration_cookie.c | 7 ++- src/qemu/qemu_process.c | 11 +++- 8 files changed, 154 insertions(+), 58 deletions(-)
I'm not exactly sure why this is needed. Can you shed more light into it please? Michal

Currently, domainJobInfo also uses "stats" as one of the job specific parameters. To remove this dependency, a privateData structure is introduced. The plan is to even have this structure renamed as `virDomainJobInfoInternal` as there already exists a `virDomainJobInfo'. On Tue, Jul 14, 2020 at 8:16 PM Michal Privoznik <mprivozn@redhat.com> wrote:
On 7/13/20 8:03 PM, Prathamesh Chavan wrote:
To remove dependecy of `qemuDomainJobInfo` on job specific paramters, a `privateData` pointer is introduced. To handle it, structure of callback functions is also introduced.
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com> --- src/qemu/qemu_backup.c | 15 +++-- src/qemu/qemu_domain.h | 18 ++++++ src/qemu/qemu_domainjob.c | 98 +++++++++++++++++++++++++------- src/qemu/qemu_domainjob.h | 31 +++++----- src/qemu/qemu_driver.c | 18 +++--- src/qemu/qemu_migration.c | 14 +++-- src/qemu/qemu_migration_cookie.c | 7 ++- src/qemu/qemu_process.c | 11 +++- 8 files changed, 154 insertions(+), 58 deletions(-)
I'm not exactly sure why this is needed. Can you shed more light into it please?
Michal

On 7/14/20 5:14 PM, Prathamesh Chavan wrote:
Currently, domainJobInfo also uses "stats" as one of the job specific parameters. To remove this dependency, a privateData structure is introduced.
The plan is to even have this structure renamed as `virDomainJobInfoInternal` as there already exists a `virDomainJobInfo'.
I see. Well, I'm not that sure about virDomainJobInfoInternal (mostly because this qemuDomainJobInfo structure looks too qemu specific). How about moving it under qemuDomainJobObj privateData? I mean, qemuDomainJobPrivate structure you propose in 3/4? Michal

On Tue, Jul 14, 2020 at 10:25 PM Michal Privoznik <mprivozn@redhat.com> wrote:
On 7/14/20 5:14 PM, Prathamesh Chavan wrote:
Currently, domainJobInfo also uses "stats" as one of the job specific parameters. To remove this dependency, a privateData structure is introduced.
The plan is to even have this structure renamed as `virDomainJobInfoInternal` as there already exists a `virDomainJobInfo'.
I see. Well, I'm not that sure about virDomainJobInfoInternal (mostly because this qemuDomainJobInfo structure looks too qemu specific). How about moving it under qemuDomainJobObj privateData? I mean, qemuDomainJobPrivate structure you propose in 3/4?
Yes, this can be done. This shall be sufficient to remove qemu_domainjob dependency on other files. Also, since libxl simply uses the virDomainJobInfo, I think we can skip creating the virDomainJobInfoInternal altogether. Thanks.

On Tue, Jul 14, 2020 at 10:25 PM Michal Privoznik <mprivozn@redhat.com> wrote:
On 7/14/20 5:14 PM, Prathamesh Chavan wrote:
Currently, domainJobInfo also uses "stats" as one of the job specific parameters. To remove this dependency, a privateData structure is introduced.
The plan is to even have this structure renamed as `virDomainJobInfoInternal` as there already exists a `virDomainJobInfo'.
I see. Well, I'm not that sure about virDomainJobInfoInternal (mostly because this qemuDomainJobInfo structure looks too qemu specific). How about moving it under qemuDomainJobObj privateData? I mean, qemuDomainJobPrivate structure you propose in 3/4?
The qemuDomainJobInfo is surely quite qemu specific. 1. The libxl, for the purpose of storing jobinfo, uses the generic `virDomainJobInfo` structure. 2. The qemuDomainJob stores two jobinfo at an instance: current and completed. And due to this, it would be difficult to split the structure, and store part of it in qemuDomainJob. I'm still looking into how this can be tackled. Maybe now is the time we decide on the way we want our future structure `virDomainJob` to look like. Thanks, Prathamesh Chavan
participants (3)
-
Martin Kletzander
-
Michal Privoznik
-
Prathamesh Chavan