提交 7b11f5e5 编写于 作者: E Eric Blake

getstats: prepare monitor collection for recursion

A future patch will allow recursion into backing chains when
collecting block stats.  This patch should not change behavior,
but merely moves out the common code that will be reused once
recursion is enabled, and adds the parameter that will turn on
recursion.

* src/qemu/qemu_monitor.h (qemuMonitorGetAllBlockStatsInfo)
(qemuMonitorBlockStatsUpdateCapacity): Add recursion parameter,
although it is ignored for now.
* src/qemu/qemu_monitor.h (qemuMonitorGetAllBlockStatsInfo)
(qemuMonitorBlockStatsUpdateCapacity): Likewise.
* src/qemu/qemu_monitor_json.h
(qemuMonitorJSONGetAllBlockStatsInfo)
(qemuMonitorJSONBlockStatsUpdateCapacity): Likewise.
* src/qemu/qemu_monitor_json.c
(qemuMonitorJSONGetAllBlockStatsInfo)
(qemuMonitorJSONBlockStatsUpdateCapacity): Add parameter, and
split...
(qemuMonitorJSONGetOneBlockStatsInfo)
(qemuMonitorJSONBlockStatsUpdateCapacityOne): ...into helpers.
(qemuMonitorJSONGetBlockStatsInfo): Update caller.
* src/qemu/qemu_driver.c (qemuDomainGetStatsBlock): Update caller.
* src/qemu/qemu_migration.c (qemuMigrationCookieAddNBD): Likewise.
Signed-off-by: NEric Blake <eblake@redhat.com>
上级 89646e69
...@@ -18552,8 +18552,9 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver, ...@@ -18552,8 +18552,9 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
abbreviated = true; /* it's ok, just go ahead silently */ abbreviated = true; /* it's ok, just go ahead silently */
} else { } else {
qemuDomainObjEnterMonitor(driver, dom); qemuDomainObjEnterMonitor(driver, dom);
rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats); rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats, false);
ignore_value(qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats)); ignore_value(qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats,
false));
qemuDomainObjExitMonitor(driver, dom); qemuDomainObjExitMonitor(driver, dom);
if (rc < 0) { if (rc < 0) {
......
...@@ -571,7 +571,8 @@ qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig, ...@@ -571,7 +571,8 @@ qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig,
goto cleanup; goto cleanup;
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats) < 0) { if (qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats,
false) < 0) {
qemuDomainObjExitMonitor(driver, vm); qemuDomainObjExitMonitor(driver, vm);
goto cleanup; goto cleanup;
} }
......
...@@ -1783,16 +1783,16 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon, ...@@ -1783,16 +1783,16 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
return ret; return ret;
} }
/* Fills the first 'nstats' block stats. 'stats' must be an array.
* Returns <0 on error, otherwise the number of block stats retrieved. /* Creates a hash table in 'ret_stats' with all block stats.
* if 'dev_name' is != NULL, look for this device only and skip * Returns <0 on error, 0 on success.
* any other. In that case return value cannot be greater than 1.
*/ */
int int
qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon, qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
virHashTablePtr *ret_stats) virHashTablePtr *ret_stats,
bool backingChain)
{ {
VIR_DEBUG("mon=%p ret_stats=%p", mon, ret_stats); VIR_DEBUG("mon=%p ret_stats=%p, backing=%d", mon, ret_stats, backingChain);
if (!mon->json) { if (!mon->json) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
...@@ -1800,15 +1800,17 @@ qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon, ...@@ -1800,15 +1800,17 @@ qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
return -1; return -1;
} }
return qemuMonitorJSONGetAllBlockStatsInfo(mon, ret_stats); return qemuMonitorJSONGetAllBlockStatsInfo(mon, ret_stats, backingChain);
} }
/* Updates "stats" to fill virtual and physical size of the image */ /* Updates "stats" to fill virtual and physical size of the image */
int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon, int
virHashTablePtr stats) qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon,
virHashTablePtr stats,
bool backingChain)
{ {
VIR_DEBUG("mon=%p, stats=%p", mon, stats); VIR_DEBUG("mon=%p, stats=%p, backing=%d", mon, stats, backingChain);
if (!mon->json) { if (!mon->json) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
...@@ -1816,7 +1818,7 @@ int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon, ...@@ -1816,7 +1818,7 @@ int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon,
return -1; return -1;
} }
return qemuMonitorJSONBlockStatsUpdateCapacity(mon, stats); return qemuMonitorJSONBlockStatsUpdateCapacity(mon, stats, backingChain);
} }
......
...@@ -382,11 +382,13 @@ struct _qemuBlockStats { ...@@ -382,11 +382,13 @@ struct _qemuBlockStats {
}; };
int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon, int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
virHashTablePtr *ret_stats) virHashTablePtr *ret_stats,
bool backingChain)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon, int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon,
virHashTablePtr stats) virHashTablePtr stats,
bool backingChain)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon, int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon,
......
...@@ -1627,7 +1627,7 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon, ...@@ -1627,7 +1627,7 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
if (flush_total_times) if (flush_total_times)
*flush_total_times = -1; *flush_total_times = -1;
if (qemuMonitorJSONGetAllBlockStatsInfo(mon, &blockstats) < 0) if (qemuMonitorJSONGetAllBlockStatsInfo(mon, &blockstats, false) < 0)
goto cleanup; goto cleanup;
if (!(stats = virHashLookup(blockstats, dev_name))) { if (!(stats = virHashLookup(blockstats, dev_name))) {
...@@ -1693,8 +1693,105 @@ qemuMonitorJSONDevGetBlockExtent(virJSONValuePtr dev, ...@@ -1693,8 +1693,105 @@ qemuMonitorJSONDevGetBlockExtent(virJSONValuePtr dev,
} }
int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon, static int
virHashTablePtr *ret_stats) qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
const char *dev_name,
virHashTablePtr hash,
bool backingChain ATTRIBUTE_UNUSED)
{
qemuBlockStatsPtr bstats = NULL;
virJSONValuePtr stats;
int ret = -1;
if (VIR_ALLOC(bstats) < 0)
goto cleanup;
if ((stats = virJSONValueObjectGet(dev, "stats")) == NULL ||
stats->type != VIR_JSON_TYPE_OBJECT) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("blockstats stats entry was not "
"in expected format"));
goto cleanup;
}
if (virJSONValueObjectGetNumberLong(stats, "rd_bytes",
&bstats->rd_bytes) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"rd_bytes");
goto cleanup;
}
if (virJSONValueObjectGetNumberLong(stats, "rd_operations",
&bstats->rd_req) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"rd_operations");
goto cleanup;
}
if (virJSONValueObjectHasKey(stats, "rd_total_time_ns") &&
(virJSONValueObjectGetNumberLong(stats, "rd_total_time_ns",
&bstats->rd_total_times) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"rd_total_time_ns");
goto cleanup;
}
if (virJSONValueObjectGetNumberLong(stats, "wr_bytes",
&bstats->wr_bytes) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"wr_bytes");
goto cleanup;
}
if (virJSONValueObjectGetNumberLong(stats, "wr_operations",
&bstats->wr_req) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"wr_operations");
goto cleanup;
}
if (virJSONValueObjectHasKey(stats, "wr_total_time_ns") &&
(virJSONValueObjectGetNumberLong(stats, "wr_total_time_ns",
&bstats->wr_total_times) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"wr_total_time_ns");
goto cleanup;
}
if (virJSONValueObjectHasKey(stats, "flush_operations") &&
(virJSONValueObjectGetNumberLong(stats, "flush_operations",
&bstats->flush_req) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"flush_operations");
goto cleanup;
}
if (virJSONValueObjectHasKey(stats, "flush_total_time_ns") &&
(virJSONValueObjectGetNumberLong(stats, "flush_total_time_ns",
&bstats->flush_total_times) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"flush_total_time_ns");
goto cleanup;
}
/* it's ok to not have this information here. Just skip silently. */
qemuMonitorJSONDevGetBlockExtent(dev, &bstats->wr_highest_offset);
if (virHashAddEntry(hash, dev_name, bstats) < 0)
goto cleanup;
bstats = NULL;
ret = 0;
cleanup:
VIR_FREE(bstats);
return ret;
}
int
qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
virHashTablePtr *ret_stats,
bool backingChain)
{ {
int ret = -1; int ret = -1;
int rc; int rc;
...@@ -1702,7 +1799,6 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon, ...@@ -1702,7 +1799,6 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
virJSONValuePtr cmd; virJSONValuePtr cmd;
virJSONValuePtr reply = NULL; virJSONValuePtr reply = NULL;
virJSONValuePtr devices; virJSONValuePtr devices;
qemuBlockStatsPtr bstats = NULL;
virHashTablePtr hash = NULL; virHashTablePtr hash = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("query-blockstats", NULL))) if (!(cmd = qemuMonitorJSONMakeCommand("query-blockstats", NULL)))
...@@ -1726,12 +1822,8 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon, ...@@ -1726,12 +1822,8 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
for (i = 0; i < virJSONValueArraySize(devices); i++) { for (i = 0; i < virJSONValueArraySize(devices); i++) {
virJSONValuePtr dev = virJSONValueArrayGet(devices, i); virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
virJSONValuePtr stats;
const char *dev_name; const char *dev_name;
if (VIR_ALLOC(bstats) < 0)
goto cleanup;
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) { if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("blockstats device entry was not " _("blockstats device entry was not "
...@@ -1749,81 +1841,10 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon, ...@@ -1749,81 +1841,10 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
if (STRPREFIX(dev_name, QEMU_DRIVE_HOST_PREFIX)) if (STRPREFIX(dev_name, QEMU_DRIVE_HOST_PREFIX))
dev_name += strlen(QEMU_DRIVE_HOST_PREFIX); dev_name += strlen(QEMU_DRIVE_HOST_PREFIX);
if ((stats = virJSONValueObjectGet(dev, "stats")) == NULL || if (qemuMonitorJSONGetOneBlockStatsInfo(dev, dev_name, hash,
stats->type != VIR_JSON_TYPE_OBJECT) { backingChain) < 0)
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("blockstats stats entry was not "
"in expected format"));
goto cleanup;
}
if (virJSONValueObjectGetNumberLong(stats, "rd_bytes",
&bstats->rd_bytes) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"rd_bytes");
goto cleanup;
}
if (virJSONValueObjectGetNumberLong(stats, "rd_operations",
&bstats->rd_req) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"rd_operations");
goto cleanup;
}
if (virJSONValueObjectHasKey(stats, "rd_total_time_ns") &&
(virJSONValueObjectGetNumberLong(stats, "rd_total_time_ns",
&bstats->rd_total_times) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"rd_total_time_ns");
goto cleanup;
}
if (virJSONValueObjectGetNumberLong(stats, "wr_bytes",
&bstats->wr_bytes) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"wr_bytes");
goto cleanup; goto cleanup;
}
if (virJSONValueObjectGetNumberLong(stats, "wr_operations",
&bstats->wr_req) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"wr_operations");
goto cleanup;
}
if (virJSONValueObjectHasKey(stats, "wr_total_time_ns") &&
(virJSONValueObjectGetNumberLong(stats, "wr_total_time_ns",
&bstats->wr_total_times) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"wr_total_time_ns");
goto cleanup;
}
if (virJSONValueObjectHasKey(stats, "flush_operations") &&
(virJSONValueObjectGetNumberLong(stats, "flush_operations",
&bstats->flush_req) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"flush_operations");
goto cleanup;
}
if (virJSONValueObjectHasKey(stats, "flush_total_time_ns") &&
(virJSONValueObjectGetNumberLong(stats, "flush_total_time_ns",
&bstats->flush_total_times) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot read %s statistic"),
"flush_total_time_ns");
goto cleanup;
}
/* it's ok to not have this information here. Just skip silently. */
qemuMonitorJSONDevGetBlockExtent(dev, &bstats->wr_highest_offset);
if (virHashAddEntry(hash, dev_name, bstats) < 0)
goto cleanup;
bstats = NULL;
} }
*ret_stats = hash; *ret_stats = hash;
...@@ -1831,7 +1852,6 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon, ...@@ -1831,7 +1852,6 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
ret = 0; ret = 0;
cleanup: cleanup:
VIR_FREE(bstats);
virHashFree(hash); virHashFree(hash);
virJSONValueFree(cmd); virJSONValueFree(cmd);
virJSONValueFree(reply); virJSONValueFree(reply);
...@@ -1839,8 +1859,45 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon, ...@@ -1839,8 +1859,45 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
} }
int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon, static int
virHashTablePtr stats) qemuMonitorJSONBlockStatsUpdateCapacityOne(virJSONValuePtr image,
const char *dev_name,
virHashTablePtr stats,
bool backingChain ATTRIBUTE_UNUSED)
{
qemuBlockStatsPtr bstats;
int ret = -1;
if (!(bstats = virHashLookup(stats, dev_name))) {
if (VIR_ALLOC(bstats) < 0)
goto cleanup;
if (virHashAddEntry(stats, dev_name, bstats) < 0) {
VIR_FREE(bstats);
goto cleanup;
}
}
/* After this point, we ignore failures; the stats were
* zero-initialized when created which is a sane fallback. */
ret = 0;
if (virJSONValueObjectGetNumberUlong(image, "virtual-size",
&bstats->capacity) < 0)
goto cleanup;
/* if actual-size is missing, image is not thin provisioned */
if (virJSONValueObjectGetNumberUlong(image, "actual-size",
&bstats->physical) < 0)
bstats->physical = bstats->capacity;
cleanup:
return ret;
}
int
qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
virHashTablePtr stats,
bool backingChain)
{ {
int ret = -1; int ret = -1;
int rc; int rc;
...@@ -1869,7 +1926,6 @@ int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon, ...@@ -1869,7 +1926,6 @@ int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
virJSONValuePtr dev = virJSONValueArrayGet(devices, i); virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
virJSONValuePtr inserted; virJSONValuePtr inserted;
virJSONValuePtr image; virJSONValuePtr image;
qemuBlockStatsPtr bstats;
const char *dev_name; const char *dev_name;
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) { if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
...@@ -1894,24 +1950,9 @@ int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon, ...@@ -1894,24 +1950,9 @@ int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
!(image = virJSONValueObjectGet(inserted, "image"))) !(image = virJSONValueObjectGet(inserted, "image")))
continue; continue;
if (!(bstats = virHashLookup(stats, dev_name))) { if (qemuMonitorJSONBlockStatsUpdateCapacityOne(image, dev_name, stats,
if (VIR_ALLOC(bstats) < 0) backingChain) < 0)
goto cleanup; goto cleanup;
if (virHashAddEntry(stats, dev_name, bstats) < 0) {
VIR_FREE(bstats);
goto cleanup;
}
}
if (virJSONValueObjectGetNumberUlong(image, "virtual-size",
&bstats->capacity) < 0)
continue;
/* if actual-size is missing, image is not thin provisioned */
if (virJSONValueObjectGetNumberUlong(image, "actual-size",
&bstats->physical) < 0)
bstats->physical = bstats->capacity;
} }
ret = 0; ret = 0;
......
...@@ -80,9 +80,11 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon, ...@@ -80,9 +80,11 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
long long *flush_total_times, long long *flush_total_times,
long long *errs); long long *errs);
int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon, int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
virHashTablePtr *ret_stats); virHashTablePtr *ret_stats,
bool backingChain);
int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon, int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
virHashTablePtr stats); virHashTablePtr stats,
bool backingChain);
int qemuMonitorJSONGetBlockStatsParamsNumber(qemuMonitorPtr mon, int qemuMonitorJSONGetBlockStatsParamsNumber(qemuMonitorPtr mon,
int *nparams); int *nparams);
int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon, int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册