On 09/01/2014 11:05 AM, Jiri Denemark wrote:
Job statistics data were tracked in several structures and
variables.
Let's make a new qemuDomainJobInfo structure which can be used as a
single source of statistics data as a preparation for storing data about
completed a job.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_domain.c | 157 ++++++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_domain.h | 24 ++++++-
src/qemu/qemu_driver.c | 119 ++++-------------------------------
src/qemu/qemu_migration.c | 72 ++++++++-------------
4 files changed, 213 insertions(+), 159 deletions(-)
Curious why the decision to use "Ptr" instead of inline struct for
current & completed? When I saw an alloc in the middle of a structure
and then a few free's along the way I began to wonder and attempt to
research the various paths to make sure all accesses knew/checked that
the impending deref would be OK - I marked those I found... I think one
or two may need double check since I assume you know the overall code
paths better. I see there's a path from qemuProcessReconnect() - that's
the libvirtd restart path right? So when the VIR_ALLOC() is done for
current/completed - who's address space is that? Wouldn't that be
address space from the "old" libvirtd?
Maybe I'm overthinking it on a Friday :-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index e9506e0..2c709e9 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -163,11 +163,9 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
job->asyncOwner = 0;
job->phase = 0;
job->mask = DEFAULT_JOB_MASK;
- job->start = 0;
job->dump_memory_only = false;
job->asyncAbort = false;
- memset(&job->status, 0, sizeof(job->status));
- memset(&job->info, 0, sizeof(job->info));
+ VIR_FREE(job->current);
This was one of those free paths where there were multiple callers and I
wasn't 100% other accesses needed to be checked w/r/t to this occurring
before an unchecked access in some other path...
}
void
@@ -200,6 +198,7 @@ qemuDomainObjTransferJob(virDomainObjPtr obj)
static void
qemuDomainObjFreeJob(qemuDomainObjPrivatePtr priv)
{
+ VIR_FREE(priv->job.current);
virCondDestroy(&priv->job.cond);
virCondDestroy(&priv->job.asyncCond);
}
@@ -211,6 +210,150 @@ qemuDomainTrackJob(qemuDomainJob job)
}
+int
+qemuDomainJobInfoUpdateTime(qemuDomainJobInfoPtr jobInfo)
+{
+ unsigned long long now;
+
+ if (!jobInfo->started)
+ return 0;
any chance jobInfo == NULL? I think the only path where the caller
doesn't check for current (or completed) is qemuMigrationUpdateJobStatus
+
+ if (virTimeMillisNow(&now) < 0)
+ return -1;
+
+ jobInfo->timeElapsed = now - jobInfo->started;
+ return 0;
+}
+
+int
+qemuDomainJobInfoToInfo(qemuDomainJobInfoPtr jobInfo,
+ virDomainJobInfoPtr info)
+{
Called with job.current checked
+ info->timeElapsed = jobInfo->timeElapsed;
+ info->timeRemaining = jobInfo->timeRemaining;
+
+ info->memTotal = jobInfo->status.ram_total;
+ info->memRemaining = jobInfo->status.ram_remaining;
+ info->memProcessed = jobInfo->status.ram_transferred;
+
+ info->fileTotal = jobInfo->status.disk_total;
+ info->fileRemaining = jobInfo->status.disk_remaining;
+ info->fileProcessed = jobInfo->status.disk_transferred;
+
+ info->dataTotal = info->memTotal + info->fileTotal;
+ info->dataRemaining = info->memRemaining + info->fileRemaining;
+ info->dataProcessed = info->memProcessed + info->fileProcessed;
+
+ return 0;
+}
+
+int
+qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo,
+ int *type,
+ virTypedParameterPtr *params,
+ int *nparams)
+{
Called with job.current (and .completed) checked...
+ qemuMonitorMigrationStatus *status = &jobInfo->status;
+ virTypedParameterPtr par = NULL;
+ int maxpar = 0;
+ int npar = 0;
+
+ if (virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_TIME_ELAPSED,
+ jobInfo->timeElapsed) < 0)
+ goto error;
+
+ if (jobInfo->type == VIR_DOMAIN_JOB_BOUNDED &&
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_TIME_REMAINING,
+ jobInfo->timeRemaining) < 0)
+ goto error;
+
+ if (status->downtime_set &&
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_DOWNTIME,
+ status->downtime) < 0)
+ goto error;
+
+ if (virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_DATA_TOTAL,
+ status->ram_total +
+ status->disk_total) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_DATA_PROCESSED,
+ status->ram_transferred +
+ status->disk_transferred) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_DATA_REMAINING,
+ status->ram_remaining +
+ status->disk_remaining) < 0)
+ goto error;
+
+ if (virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_MEMORY_TOTAL,
+ status->ram_total) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_MEMORY_PROCESSED,
+ status->ram_transferred) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_MEMORY_REMAINING,
+ status->ram_remaining) < 0)
+ goto error;
+
+ if (status->ram_duplicate_set) {
+ if (virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_MEMORY_CONSTANT,
+ status->ram_duplicate) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_MEMORY_NORMAL,
+ status->ram_normal) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES,
+ status->ram_normal_bytes) < 0)
I have a note in patch 2 about ram_normal and ram_normal_bytes vis-a-vis
qemu_monitor_json.c not checking status on their fetch and my latest
coverity run complaining about it.
+ goto error;
+ }
+
+ if (virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_DISK_TOTAL,
+ status->disk_total) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_DISK_PROCESSED,
+ status->disk_transferred) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_DISK_REMAINING,
+ status->disk_remaining) < 0)
+ goto error;
+
+ if (status->xbzrle_set) {
+ if (virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_COMPRESSION_CACHE,
+ status->xbzrle_cache_size) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_COMPRESSION_BYTES,
+ status->xbzrle_bytes) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_COMPRESSION_PAGES,
+ status->xbzrle_pages) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES,
+ status->xbzrle_cache_miss) < 0 ||
+ virTypedParamsAddULLong(&par, &npar, &maxpar,
+ VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW,
+ status->xbzrle_overflow) < 0)
+ goto error;
+ }
+
+ *type = jobInfo->type;
+ *params = par;
+ *nparams = npar;
+ return 0;
+
+ error:
+ virTypedParamsFree(par, npar);
+ return -1;
+}
+
+
static void *
qemuDomainObjPrivateAlloc(void)
{
@@ -1071,7 +1214,7 @@ qemuDomainObjBeginJobInternal(virQEMUDriverPtr driver,
unsigned long long then;
bool nested = job == QEMU_JOB_ASYNC_NESTED;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
- int ret;
+ int ret = -1;
VIR_DEBUG("Starting %s: %s (async=%s vm=%p name=%s)",
job == QEMU_JOB_ASYNC ? "async job" : "job",
Just a note after this there's a
priv->jobs_queued++;
which can be decremented at cleanup; however, if virTimeMillisNow()
fails, then there's a return -1 *and* a virObjectUnref(obj) before the
virObjectRef(obj)...
@@ -1127,9 +1270,11 @@ qemuDomainObjBeginJobInternal(virQEMUDriverPtr
driver,
qemuDomainAsyncJobTypeToString(asyncJob),
obj, obj->def->name);
qemuDomainObjResetAsyncJob(priv);
+ if (VIR_ALLOC(priv->job.current) < 0)
+ goto cleanup;
If this fails - what are the chances some other path will check/access
current without checking for it being NULL? Perhaps low and there's
going to be other problems anyway in a low memory situation...
priv->job.asyncJob = asyncJob;
priv->job.asyncOwner = virThreadSelfID();
- priv->job.start = now;
+ priv->job.current->started = now;
}
if (qemuDomainTrackJob(job))
@@ -1163,6 +1308,8 @@ qemuDomainObjBeginJobInternal(virQEMUDriverPtr driver,
virReportSystemError(errno,
"%s", _("cannot acquire job mutex"));
}
+
+ cleanup:
priv->jobs_queued--;
virObjectUnref(obj);
virObjectUnref(cfg);
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 8736889..119590e 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -100,6 +100,18 @@ typedef enum {
} qemuDomainAsyncJob;
VIR_ENUM_DECL(qemuDomainAsyncJob)
+typedef struct _qemuDomainJobInfo qemuDomainJobInfo;
+typedef qemuDomainJobInfo *qemuDomainJobInfoPtr;
+struct _qemuDomainJobInfo {
+ virDomainJobType type;
+ unsigned long long started; /* When the async job started */
+ /* Computed values */
+ unsigned long long timeElapsed;
+ unsigned long long timeRemaining;
+ /* Raw values from QEMU */
+ qemuMonitorMigrationStatus status;
+};
+
struct qemuDomainJobObj {
virCond cond; /* Use to coordinate jobs */
qemuDomainJob active; /* Currently running job */
@@ -110,10 +122,8 @@ struct qemuDomainJobObj {
unsigned long long asyncOwner; /* Thread which set current async job */
int phase; /* Job phase (mainly for migrations) */
unsigned long long mask; /* Jobs allowed during async job */
- unsigned long long start; /* When the async job started */
bool dump_memory_only; /* use dump-guest-memory to do dump */
- qemuMonitorMigrationStatus status; /* Raw async job progress data */
- virDomainJobInfo info; /* Processed async job progress data */
+ qemuDomainJobInfoPtr current; /* async job progress data */
bool asyncAbort; /* abort of async job requested */
};
@@ -378,4 +388,12 @@ bool qemuDomainDefCheckABIStability(virQEMUDriverPtr driver,
bool qemuDomainAgentAvailable(qemuDomainObjPrivatePtr priv,
bool reportError);
+int qemuDomainJobInfoUpdateTime(qemuDomainJobInfoPtr jobInfo);
+int qemuDomainJobInfoToInfo(qemuDomainJobInfoPtr jobInfo,
+ virDomainJobInfoPtr info);
+int qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo,
+ int *type,
+ virTypedParameterPtr *params,
+ int *nparams);
+
Should any of these new defs need to have/use the ATTRIBUTE_NONNULL()
for params?
#endif /* __QEMU_DOMAIN_H__ */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 239a300..265315d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2655,15 +2655,13 @@ qemuDomainGetControlInfo(virDomainPtr dom,
if (priv->monError) {
info->state = VIR_DOMAIN_CONTROL_ERROR;
} else if (priv->job.active) {
- if (!priv->monStart) {
+ if (virTimeMillisNow(&info->stateTime) < 0)
+ goto cleanup;
+ if (priv->job.current) {
info->state = VIR_DOMAIN_CONTROL_JOB;
- if (virTimeMillisNow(&info->stateTime) < 0)
- goto cleanup;
- info->stateTime -= priv->job.start;
+ info->stateTime -= priv->job.current->started;
} else {
info->state = VIR_DOMAIN_CONTROL_OCCUPIED;
- if (virTimeMillisNow(&info->stateTime) < 0)
- goto cleanup;
info->stateTime -= priv->monStart;
}
} else {
@@ -3110,8 +3108,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
goto endjob;
}
- memset(&priv->job.info, 0, sizeof(priv->job.info));
- priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
+ priv->job.current->type = VIR_DOMAIN_JOB_UNBOUNDED;
Assumes current-> exists, but occurs after BeginAsyncJob() is
successful, so it seems safe.
/* Pause */
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
@@ -3460,6 +3457,7 @@ static int qemuDumpToFd(virQEMUDriverPtr driver, virDomainObjPtr
vm,
fd) < 0)
return -1;
+ VIR_FREE(priv->job.current);
priv->job.dump_memory_only = true;
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
@@ -11616,17 +11614,15 @@ static int qemuDomainGetJobInfo(virDomainPtr dom,
goto cleanup;
if (virDomainObjIsActive(vm)) {
- if (priv->job.asyncJob && !priv->job.dump_memory_only) {
- memcpy(info, &priv->job.info, sizeof(*info));
-
+ if (priv->job.current) {
Here there is a check for job.current before usage
/* Refresh elapsed time again just to ensure it
* is fully updated. This is primarily for benefit
* of incoming migration which we don't currently
* monitor actively in the background thread
*/
- if (virTimeMillisNow(&info->timeElapsed) < 0)
+ if (qemuDomainJobInfoUpdateTime(priv->job.current) < 0 ||
+ qemuDomainJobInfoToInfo(priv->job.current, info) < 0)
goto cleanup;
- info->timeElapsed -= priv->job.start;
} else {
memset(info, 0, sizeof(*info));
info->type = VIR_DOMAIN_JOB_NONE;
@@ -11655,9 +11651,6 @@ qemuDomainGetJobStats(virDomainPtr dom,
{
virDomainObjPtr vm;
qemuDomainObjPrivatePtr priv;
- virTypedParameterPtr par = NULL;
- int maxpar = 0;
- int npar = 0;
int ret = -1;
virCheckFlags(0, -1);
@@ -11676,7 +11669,7 @@ qemuDomainGetJobStats(virDomainPtr dom,
goto cleanup;
}
- if (!priv->job.asyncJob || priv->job.dump_memory_only) {
+ if (!priv->job.current) {
*type = VIR_DOMAIN_JOB_NONE;
*params = NULL;
*nparams = 0;
Here there is a check for job.current before usage below
@@ -11689,102 +11682,16 @@ qemuDomainGetJobStats(virDomainPtr dom,
* of incoming migration which we don't currently
* monitor actively in the background thread
*/
- if (virTimeMillisNow(&priv->job.info.timeElapsed) < 0)
+ if (qemuDomainJobInfoUpdateTime(priv->job.current) < 0 ||
+ qemuDomainJobInfoToParams(priv->job.current,
+ type, params, nparams) < 0)
goto cleanup;
- priv->job.info.timeElapsed -= priv->job.start;
- if (virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_TIME_ELAPSED,
- priv->job.info.timeElapsed) < 0)
- goto cleanup;
-
- if (priv->job.info.type == VIR_DOMAIN_JOB_BOUNDED &&
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_TIME_REMAINING,
- priv->job.info.timeRemaining) < 0)
- goto cleanup;
-
- if (priv->job.status.downtime_set &&
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_DOWNTIME,
- priv->job.status.downtime) < 0)
- goto cleanup;
-
- if (virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_DATA_TOTAL,
- priv->job.info.dataTotal) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_DATA_PROCESSED,
- priv->job.info.dataProcessed) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_DATA_REMAINING,
- priv->job.info.dataRemaining) < 0)
- goto cleanup;
-
- if (virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_MEMORY_TOTAL,
- priv->job.info.memTotal) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_MEMORY_PROCESSED,
- priv->job.info.memProcessed) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_MEMORY_REMAINING,
- priv->job.info.memRemaining) < 0)
- goto cleanup;
-
- if (priv->job.status.ram_duplicate_set) {
- if (virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_MEMORY_CONSTANT,
- priv->job.status.ram_duplicate) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_MEMORY_NORMAL,
- priv->job.status.ram_normal) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES,
- priv->job.status.ram_normal_bytes) < 0)
- goto cleanup;
- }
-
- if (virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_DISK_TOTAL,
- priv->job.info.fileTotal) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_DISK_PROCESSED,
- priv->job.info.fileProcessed) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_DISK_REMAINING,
- priv->job.info.fileRemaining) < 0)
- goto cleanup;
-
- if (priv->job.status.xbzrle_set) {
- if (virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_COMPRESSION_CACHE,
- priv->job.status.xbzrle_cache_size) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_COMPRESSION_BYTES,
- priv->job.status.xbzrle_bytes) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_COMPRESSION_PAGES,
- priv->job.status.xbzrle_pages) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES,
- priv->job.status.xbzrle_cache_miss) < 0 ||
- virTypedParamsAddULLong(&par, &npar, &maxpar,
- VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW,
- priv->job.status.xbzrle_overflow) < 0)
- goto cleanup;
- }
-
- *type = priv->job.info.type;
- *params = par;
- *nparams = npar;
ret = 0;
cleanup:
if (vm)
virObjectUnlock(vm);
- if (ret < 0)
- virTypedParamsFree(par, npar);
return ret;
}
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 9cfb77e..64adab4 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1723,8 +1723,9 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
qemuDomainAsyncJob asyncJob)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- int ret;
qemuMonitorMigrationStatus status;
+ qemuDomainJobInfoPtr jobInfo;
+ int ret;
memset(&status, 0, sizeof(status));
@@ -1738,62 +1739,40 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
qemuDomainObjExitMonitor(driver, vm);
- priv->job.status = status;
-
- if (ret < 0 || virTimeMillisNow(&priv->job.info.timeElapsed) < 0)
+ if (ret < 0 ||
+ qemuDomainJobInfoUpdateTime(priv->job.current) < 0)
Here (and below) it's assumed job.current is valid.
return -1;
- priv->job.info.timeElapsed -= priv->job.start;
-
ret = -1;
- switch (priv->job.status.status) {
- case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
- priv->job.info.type = VIR_DOMAIN_JOB_NONE;
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("%s: %s"), job, _("is not active"));
- break;
-
+ jobInfo = priv->job.current;
+ switch (status.status) {
+ case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
+ jobInfo->type = VIR_DOMAIN_JOB_COMPLETED;
+ /* fall through */
case QEMU_MONITOR_MIGRATION_STATUS_SETUP:
- ret = 0;
- break;
-
case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
- priv->job.info.fileTotal = priv->job.status.disk_total;
- priv->job.info.fileRemaining = priv->job.status.disk_remaining;
- priv->job.info.fileProcessed = priv->job.status.disk_transferred;
-
- priv->job.info.memTotal = priv->job.status.ram_total;
- priv->job.info.memRemaining = priv->job.status.ram_remaining;
- priv->job.info.memProcessed = priv->job.status.ram_transferred;
-
- priv->job.info.dataTotal =
- priv->job.status.ram_total + priv->job.status.disk_total;
- priv->job.info.dataRemaining =
- priv->job.status.ram_remaining + priv->job.status.disk_remaining;
- priv->job.info.dataProcessed =
- priv->job.status.ram_transferred +
- priv->job.status.disk_transferred;
-
ret = 0;
break;
- case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
- priv->job.info.type = VIR_DOMAIN_JOB_COMPLETED;
- ret = 0;
+ case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
+ jobInfo->type = VIR_DOMAIN_JOB_NONE;
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("%s: %s"), job, _("is not active"));
break;
case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
- priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
+ jobInfo->type = VIR_DOMAIN_JOB_FAILED;
virReportError(VIR_ERR_OPERATION_FAILED,
_("%s: %s"), job, _("unexpectedly failed"));
break;
case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED:
- priv->job.info.type = VIR_DOMAIN_JOB_CANCELLED;
+ jobInfo->type = VIR_DOMAIN_JOB_CANCELLED;
virReportError(VIR_ERR_OPERATION_ABORTED,
_("%s: %s"), job, _("canceled by client"));
break;
}
+ jobInfo->status = status;
return ret;
}
@@ -1803,11 +1782,14 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
* QEMU reports failed migration.
*/
static int
-qemuMigrationWaitForCompletion(virQEMUDriverPtr driver, virDomainObjPtr vm,
+qemuMigrationWaitForCompletion(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob,
- virConnectPtr dconn, bool abort_on_error)
+ virConnectPtr dconn,
+ bool abort_on_error)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
+ qemuDomainJobInfoPtr jobInfo = priv->job.current;
Hopefully nothing has cleared or could clear this before this point...
const char *job;
int pauseReason;
@@ -1825,9 +1807,9 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver,
virDomainObjPtr vm,
job = _("job");
}
- priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
+ jobInfo->type = VIR_DOMAIN_JOB_UNBOUNDED;
- while (priv->job.info.type == VIR_DOMAIN_JOB_UNBOUNDED) {
+ while (jobInfo->type == VIR_DOMAIN_JOB_UNBOUNDED) {
/* Poll every 50ms for progress & to allow cancellation */
struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
@@ -1856,13 +1838,13 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virObjectLock(vm);
}
- if (priv->job.info.type == VIR_DOMAIN_JOB_COMPLETED) {
+ if (jobInfo->type == VIR_DOMAIN_JOB_COMPLETED) {
return 0;
- } else if (priv->job.info.type == VIR_DOMAIN_JOB_UNBOUNDED) {
+ } else if (jobInfo->type == VIR_DOMAIN_JOB_UNBOUNDED) {
/* The migration was aborted by us rather than QEMU itself so let's
* update the job type and notify the caller to send migrate_cancel.
*/
- priv->job.info.type = VIR_DOMAIN_JOB_FAILED;
+ jobInfo->type = VIR_DOMAIN_JOB_FAILED;
return -2;
} else {
return -1;
@@ -4912,7 +4894,7 @@ qemuMigrationJobStart(virQEMUDriverPtr driver,
JOB_MASK(QEMU_JOB_MIGRATION_OP));
}
- priv->job.info.type = VIR_DOMAIN_JOB_UNBOUNDED;
+ priv->job.current->type = VIR_DOMAIN_JOB_UNBOUNDED;
This assumption of current-> should be OK since a failure from
qemuDomainObjBeginAsyncJob() wouldn't go through here.
return 0;
}
In general - I'm AOK with the code - my main concern has to do with
alloc'd memory...
John