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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxx>
---
 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




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux