Let's store disks stats for completed mirror jobs in current
job info. So on getting migration job stats thru API
we take records for completed jobs from current job info
and records for still active jobs by querying qemu process.
As we need to keep disks stats for completed mirror jobs
in current job let's zero out migration stats conditionally
in fetching function.
---
src/qemu/qemu_blockjob.c | 1 +
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 3 +++
src/qemu/qemu_migration.c | 11 +++++++++++
src/qemu/qemu_monitor.c | 5 +++--
src/qemu/qemu_monitor.h | 4 +++-
src/qemu/qemu_monitor_json.c | 4 +---
src/qemu/qemu_process.c | 3 +++
tests/qemumonitorjsontest.c | 1 +
9 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 0601e68..f517999 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -232,6 +232,7 @@ qemuBlockJobSyncBegin(virDomainDiskDefPtr disk)
VIR_DEBUG("disk=%s", disk->dst);
diskPriv->blockJobSync = true;
diskPriv->blockJobStatus = -1;
+ diskPriv->blockJobLength = 0;
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 564da49..b002184 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -323,6 +323,7 @@ struct _qemuDomainDiskPrivate {
/* for some synchronous block jobs, we need to notify the owner */
int blockJobType; /* type of the block job from the event */
int blockJobStatus; /* status of the finished block job */
+ unsigned long long blockJobLength; /* length of the finished block job */
bool blockJobSync; /* the block job needs synchronized termination */
bool migrating; /* the disk is being migrated */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1539e15..9a706d5 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12781,6 +12781,9 @@ qemuDomainGetJobStatsInternal(virQEMUDriverPtr driver,
jobInfo->status == QEMU_DOMAIN_JOB_STATUS_MIGRATING ||
jobInfo->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY) {
+ /* Disks stats accounting presumes that fetching migration
+ * stats will not touch disk stats records if disks are migrated via nbd.
+ */
if (events && jobInfo->status != QEMU_DOMAIN_JOB_STATUS_ACTIVE
&&
qemuMigrationFetchMigrationStats(driver, vm, QEMU_ASYNC_JOB_NONE,
&jobInfo->stats, false) < 0)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 16f1265..43d87a0 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -654,6 +654,7 @@ qemuMigrationDriveMirrorCancelled(virQEMUDriverPtr driver,
size_t active = 0;
int status;
bool failed = false;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
@@ -681,6 +682,13 @@ qemuMigrationDriveMirrorCancelled(virQEMUDriverPtr driver,
default:
active++;
}
+
+ if (status == VIR_DOMAIN_BLOCK_JOB_COMPLETED) {
+ qemuMonitorMigrationStatsPtr stats = &priv->job.current->stats;
+
+ stats->disk_transferred += diskPriv->blockJobLength;
+ stats->disk_total += diskPriv->blockJobLength;
+ }
}
if (failed) {
@@ -1357,6 +1365,9 @@ qemuMigrationFetchMigrationStats(virQEMUDriverPtr driver,
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1;
+ if (copy)
+ memset(&statsCopy, 0, sizeof(statsCopy));
+
rv = qemuMonitorGetMigrationStats(priv->mon, copy ? &statsCopy : stats);
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 1d40d52..06a5cf8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1504,13 +1504,14 @@ int
qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
const char *diskAlias,
int type,
- int status)
+ int status,
+ unsigned long long len)
{
int ret = -1;
VIR_DEBUG("mon=%p", mon);
QEMU_MONITOR_CALLBACK(mon, ret, domainBlockJob, mon->vm,
- diskAlias, type, status);
+ diskAlias, type, status, len);
return ret;
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 12f98be..a71c344 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -175,6 +175,7 @@ typedef int (*qemuMonitorDomainBlockJobCallback)(qemuMonitorPtr mon,
const char *diskAlias,
int type,
int status,
+ unsigned long long len,
void *opaque);
typedef int (*qemuMonitorDomainTrayChangeCallback)(qemuMonitorPtr mon,
virDomainObjPtr vm,
@@ -374,7 +375,8 @@ int qemuMonitorEmitPMSuspend(qemuMonitorPtr mon);
int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
const char *diskAlias,
int type,
- int status);
+ int status,
+ unsigned long long len);
int qemuMonitorEmitBalloonChange(qemuMonitorPtr mon,
unsigned long long actual);
int qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index aeb777d..67874ea 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -902,7 +902,7 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
}
out:
- qemuMonitorEmitBlockJob(mon, device, type, event);
+ qemuMonitorEmitBlockJob(mon, device, type, event, len);
}
static void
@@ -2965,8 +2965,6 @@ int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon,
NULL);
virJSONValuePtr reply = NULL;
- memset(stats, 0, sizeof(*stats));
-
if (!cmd)
return -1;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f5cd00b..283bf83 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -965,6 +965,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
const char *diskAlias,
int type,
int status,
+ unsigned long long len,
void *opaque)
{
virQEMUDriverPtr driver = opaque;
@@ -986,6 +987,8 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
/* We have a SYNC API waiting for this event, dispatch it back */
diskPriv->blockJobType = type;
diskPriv->blockJobStatus = status;
+ diskPriv->blockJobLength = len;
+
virDomainObjBroadcast(vm);
} else {
/* there is no waiting SYNC API, dispatch the update to a thread */
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index e9f9d47..873fcd7 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -1923,6 +1923,7 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStats(const void
*data)
"}") < 0)
goto cleanup;
+ memset(&stats, 0, sizeof(stats));
if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test), &stats)
< 0)
goto cleanup;
--
1.8.3.1