]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Fix reporting of physical capacity for block devices
authorPeter Krempa <pkrempa@redhat.com>
Fri, 7 Aug 2015 09:01:49 +0000 (11:01 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Fri, 7 Aug 2015 11:28:50 +0000 (13:28 +0200)
Qemu reports physical size 0 for block devices. As 15fa84acbb55ebfee6a4
changed the behavior of qemuDomainGetBlockInfo to just query the monitor
this created a regression since we didn't report the size correctly any
more.

This patch adds code to refresh the physical size of a block device by
opening it and seeking to the end and uses it both in
qemuDomainGetBlockInfo and also in qemuDomainGetStatsOneBlock that was
broken since it was introduced in this respect.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1250982

src/libvirt_private.syms
src/qemu/qemu_driver.c
src/util/virstoragefile.c
src/util/virstoragefile.h

index 0517c24acc68d09842d3624769a5a7b0338e4daa..5d320b73066ee779eebed211cb776105c78ac1e3 100644 (file)
@@ -2156,6 +2156,7 @@ virStorageSourceParseRBDColonString;
 virStorageSourcePoolDefFree;
 virStorageSourcePoolModeTypeFromString;
 virStorageSourcePoolModeTypeToString;
+virStorageSourceUpdateBlockPhysicalSize;
 virStorageTypeFromString;
 virStorageTypeToString;
 
index 7a984a86ab3a06e613396f4f59d56779e10a06e8..6998e1205a4730dc1528fa9f4a5acfdfb865e48a 100644 (file)
@@ -11827,8 +11827,16 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
         info->allocation = entry->wr_highest_offset;
     }
 
+    if (entry->physical) {
+        info->physical = entry->physical;
+    } else {
+        if (virStorageSourceUpdateBlockPhysicalSize(disk->src, true) < 0)
+            goto endjob;
+
+        info->physical = disk->src->physical;
+    }
+
     info->capacity = entry->capacity;
-    info->physical = entry->physical;
 
     ret = 0;
 
@@ -19274,9 +19282,15 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
     if (entry->capacity)
         QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
                                  "capacity", entry->capacity);
-    if (entry->physical)
+    if (entry->physical) {
         QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
                                  "physical", entry->physical);
+    } else {
+        if (virStorageSourceUpdateBlockPhysicalSize(src, false) == 0) {
+            QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
+                                     "physical", src->physical);
+        }
+    }
 
     ret = 0;
  cleanup:
index 6c3017cef9e2568e2c8b6bfe79fc4344bedf08ad..2aa1d90d65817ca2c46aaf23250ab4cc85699195 100644 (file)
@@ -2587,6 +2587,45 @@ virStorageSourceNewFromBacking(virStorageSourcePtr parent)
 }
 
 
+/**
+ * @src: disk source definiton structure
+ * @report: report libvirt errors if set to true
+ *
+ * Updates src->physical for block devices since qemu doesn't report the current
+ * size correctly for them. Returns 0 on success, -1 on error.
+ */
+int
+virStorageSourceUpdateBlockPhysicalSize(virStorageSourcePtr src,
+                                        bool report)
+{
+    int fd = -1;
+    off_t end;
+    int ret = -1;
+
+    if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_BLOCK)
+        return 0;
+
+    if ((fd = open(src->path, O_RDONLY)) < 0) {
+        if (report)
+            virReportSystemError(errno, _("failed to open block device '%s'"),
+                                 src->path);
+        return -1;
+    }
+
+    if ((end = lseek(fd, 0, SEEK_END)) == (off_t) -1) {
+        if (report)
+            virReportSystemError(errno,
+                                 _("failed to seek to end of '%s'"), src->path);
+    } else {
+        src->physical = end;
+        ret = 0;
+    }
+
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+
+
 static char *
 virStorageFileCanonicalizeFormatPath(char **components,
                                      size_t ncomponents,
index aa17a00e54508e1f017396752cb02d8c9bdc460c..b98fe2587181ecb4d45f650773da0b65e5b055ec 100644 (file)
@@ -362,6 +362,8 @@ bool virStorageSourceIsLocalStorage(virStorageSourcePtr src);
 bool virStorageSourceIsEmpty(virStorageSourcePtr src);
 void virStorageSourceFree(virStorageSourcePtr def);
 void virStorageSourceBackingStoreClear(virStorageSourcePtr def);
+int virStorageSourceUpdateBlockPhysicalSize(virStorageSourcePtr src,
+                                            bool report);
 virStorageSourcePtr virStorageSourceNewFromBacking(virStorageSourcePtr parent);
 virStorageSourcePtr virStorageSourceCopy(const virStorageSource *src,
                                          bool backingChain)