diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 1afc344691..d61fcf2e0a 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -378,7 +378,11 @@ struct _qemuBlockStats { long long flush_total_times; unsigned long long capacity; unsigned long long physical; + + /* value of wr_highest_offset is valid if it's non 0 or + * if wr_highest_offset_valid is true */ unsigned long long wr_highest_offset; + bool wr_highest_offset_valid; }; int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 0dff8e8c9e..d144f293b4 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1699,6 +1699,8 @@ qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev, { qemuBlockStatsPtr bstats = NULL; virJSONValuePtr stats; + virJSONValuePtr parent; + virJSONValuePtr parentstats; int ret = -1; int nstats = 0; char *entry_name = qemuDomainStorageAlias(dev_name, depth); @@ -1735,8 +1737,12 @@ qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev, QEMU_MONITOR_BLOCK_STAT_GET("flush_total_time_ns", bstats->flush_total_times, false); #undef QEMU_MONITOR_BLOCK_STAT_GET - /* it's ok to not have this information here. Just skip silently. */ - qemuMonitorJSONDevGetBlockExtent(dev, &bstats->wr_highest_offset); + if ((parent = virJSONValueObjectGetObject(dev, "parent")) && + (parentstats = virJSONValueObjectGetObject(parent, "stats"))) { + if (virJSONValueObjectGetNumberUlong(parentstats, "wr_highest_offset", + &bstats->wr_highest_offset) == 0) + bstats->wr_highest_offset_valid = true; + } if (virHashAddEntry(hash, entry_name, bstats) < 0) goto cleanup; diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 0623275dc2..e72083e518 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1538,16 +1538,20 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockStatsInfo(const void *data) qemuMonitorTestAddItem(test, "query-blockstats", reply) < 0) goto cleanup; -#define CHECK0(var, value) \ +#define CHECK0FULL(var, value, varformat, valformat) \ if (stats->var != value) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ - "Invalid " #var " value: %lld, expected %d", \ + "Invalid " #var " value: " varformat \ + ", expected " valformat, \ stats->var, value); \ goto cleanup; \ } +#define CHECK0(var, value) CHECK0FULL(var, value, "%lld", "%d") + #define CHECK(NAME, RD_REQ, RD_BYTES, RD_TOTAL_TIMES, WR_REQ, WR_BYTES, \ - WR_TOTAL_TIMES, FLUSH_REQ, FLUSH_TOTAL_TIMES) \ + WR_TOTAL_TIMES, FLUSH_REQ, FLUSH_TOTAL_TIMES, \ + WR_HIGHEST_OFFSET, WR_HIGHEST_OFFSET_VALID) \ if (!(stats = virHashLookup(blockstats, NAME))) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ "block stats for device '%s' is missing", NAME); \ @@ -1560,7 +1564,9 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockStatsInfo(const void *data) CHECK0(wr_bytes, WR_BYTES) \ CHECK0(wr_total_times, WR_TOTAL_TIMES) \ CHECK0(flush_req, FLUSH_REQ) \ - CHECK0(flush_total_times, FLUSH_TOTAL_TIMES) + CHECK0(flush_total_times, FLUSH_TOTAL_TIMES) \ + CHECK0FULL(wr_highest_offset, WR_HIGHEST_OFFSET, "%llu", "%llu") \ + CHECK0FULL(wr_highest_offset_valid, WR_HIGHEST_OFFSET_VALID, "%d", "%d") if (qemuMonitorGetAllBlockStatsInfo(qemuMonitorTestGetMonitor(test), &blockstats, false) < 0) @@ -1572,9 +1578,9 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockStatsInfo(const void *data) goto cleanup; } - CHECK("virtio-disk0", 1279, 28505088, 640616474, 174, 2845696, 530699221, 0, 0) - CHECK("virtio-disk1", 85, 348160, 8232156, 0, 0, 0, 0, 0) - CHECK("ide0-1-0", 16, 49250, 1004952, 0, 0, 0, 0, 0) + CHECK("virtio-disk0", 1279, 28505088, 640616474, 174, 2845696, 530699221, 0, 0, 5256018944ULL, true) + CHECK("virtio-disk1", 85, 348160, 8232156, 0, 0, 0, 0, 0, 0ULL, true) + CHECK("ide0-1-0", 16, 49250, 1004952, 0, 0, 0, 0, 0, 0ULL, true) if (qemuMonitorJSONGetBlockExtent(qemuMonitorTestGetMonitor(test), "virtio-disk0", &extent) < 0) @@ -1613,6 +1619,7 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockStatsInfo(const void *data) #undef CHECK #undef CHECK0 +#undef CHECK0FULL cleanup: qemuMonitorTestFree(test); diff --git a/tests/qemumonitortest.c b/tests/qemumonitortest.c index 01259625a8..12308f9c35 100644 --- a/tests/qemumonitortest.c +++ b/tests/qemumonitortest.c @@ -93,12 +93,14 @@ struct blockInfoData { static const struct blockInfoData testBlockInfoData[] = { -/* NAME, rd_req, rd_bytes, wr_req, wr_bytes, rd_total_time, wr_total_time, flush_req, flush_total_time */ - {"vda", {11, 12, 13, 14, 15, 16, 17, 18, 0, 0, 0}}, - {"vdb", {21, 22, 23, 24, 25, 26, 27, 28, 0, 0, 0}}, - {"vdc", {31, 32, 33, -1, 35, 36, 37, 38, 0, 0, 0}}, - {"vdd", {-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0}}, - {"vde", {41, 42, 43, 44, 45, 46, 47, 48, 0, 0, 0}} +/* NAME, rd_req, rd_bytes, wr_req, wr_bytes, rd_total_time, wr_total_time, + * flush_req, flush_total_time, capacity, physical, wr_highest_offset, + * wr_highest_offset_valid*/ + {"vda", {11, 12, 13, 14, 15, 16, 17, 18, 0, 0, 0, false}}, + {"vdb", {21, 22, 23, 24, 25, 26, 27, 28, 0, 0, 0, false}}, + {"vdc", {31, 32, 33, -1, 35, 36, 37, 38, 0, 0, 0, false}}, + {"vdd", {-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, false}}, + {"vde", {41, 42, 43, 44, 45, 46, 47, 48, 0, 0, 0, false}} }; static const char testBlockInfoReply[] =