[libvirt] [PATCH v3 REBASE 13/16] qemu: support getting disks stats during stopping block jobs

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Thu Aug 24 06:56:50 UTC 2017


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    | 12 +++++++++++-
 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(+), 7 deletions(-)

diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 415768d..73e32b2 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -234,6 +234,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 ce0a080..d517719 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -332,6 +332,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 d012fd0..ec5e0b1 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12943,6 +12943,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 c7af1ac..afe1804 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -658,6 +658,7 @@ qemuMigrationDriveMirrorCancelled(virQEMUDriverPtr driver,
     size_t completed = 0;
     int status;
     bool failed = false;
+    qemuDomainObjPrivatePtr priv = vm->privateData;
 
  retry:
     for (i = 0; i < vm->def->ndisks; i++) {
@@ -687,8 +688,14 @@ qemuMigrationDriveMirrorCancelled(virQEMUDriverPtr driver,
             active++;
         }
 
-        if (status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
+        if (status == VIR_DOMAIN_BLOCK_JOB_COMPLETED) {
+            qemuMonitorMigrationStatsPtr stats = &priv->job.current->stats;
+
+            stats->disk_transferred += diskPriv->blockJobLength;
+            stats->disk_total += diskPriv->blockJobLength;
+
             completed++;
+        }
     }
 
     /* Updating completed block job drops the lock thus we have to recheck
@@ -1389,6 +1396,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 19082d8..a4d2dae 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1514,13 +1514,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 31f7e97..09d93ad 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -176,6 +176,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,
@@ -375,7 +376,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 b8a6815..3fbb5fb 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -908,7 +908,7 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
     }
 
  out:
-    qemuMonitorEmitBlockJob(mon, device, type, event);
+    qemuMonitorEmitBlockJob(mon, device, type, event, len);
 }
 
 static void
@@ -2990,8 +2990,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 ca075e7..2228298 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -979,6 +979,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                           const char *diskAlias,
                           int type,
                           int status,
+                          unsigned long long len,
                           void *opaque)
 {
     virQEMUDriverPtr driver = opaque;
@@ -1000,6 +1001,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 df3ef0a..c514bf9 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -1934,6 +1934,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




More information about the libvir-list mailing list