[PATCH v2 09/10] qemu: fix race on legacy block completion and quering stats

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Fri Nov 13 06:53:37 UTC 2020


At the time when we query qemu for block stats backing chain in qemu and
libvirt can be different and this will result in messy block stats. I guess
this can be noticable under load when thread that process events is busy so
that it can take some time before block job events are processed.

The modern block job have same issue I guess but I don't know them well enough
to apply this fix too. Also the approach for them can be different as there is
option to use autofinalize = no.

Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
---
 src/qemu/qemu_driver.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 25466f6..05917eb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18458,8 +18458,9 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
     int count_index = -1;
     size_t visited = 0;
     bool visitBacking = !!(privflags & QEMU_DOMAIN_STATS_BACKING);
+    bool refresh = true;
 
-    if (HAVE_JOB(privflags) && virDomainObjIsActive(dom)) {
+    while (HAVE_JOB(privflags) && virDomainObjIsActive(dom) && refresh) {
         qemuDomainObjEnterMonitor(driver, dom);
 
         rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats, visitBacking);
@@ -18481,6 +18482,27 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
         /* failure to retrieve stats is fine at this point */
         if (rc < 0 || (fetchnodedata && !nodedata))
             virResetLastError();
+
+        refresh = false;
+        if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
+            for (i = 0; i < dom->def->ndisks; i++) {
+                virDomainDiskDefPtr disk = dom->def->disks[i];
+                g_autoptr(qemuBlockJobData) job = qemuBlockJobDiskGetJob(disk);
+
+                if (!job)
+                    continue;
+
+                /*
+                 * If block job is completed then backing chain at time
+                 * of quering stats in qemu and current backing chain in
+                 * libvirt can be different. We need to sync them.
+                 */
+                if (job->newstate == QEMU_BLOCKJOB_STATE_COMPLETED) {
+                    qemuBlockJobUpdate(dom, job, QEMU_ASYNC_JOB_NONE);
+                    refresh = true;
+                }
+            }
+        }
     }
 
     if (nodedata &&
-- 
1.8.3.1




More information about the libvir-list mailing list