mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 07:17:44 +00:00
latency: Update monitor functions for new latency fields
The mainly changes are: 1) Update qemuMonitorGetBlockStatsInfo and it's children (Text/JSON) functions to return the value of new latency fields. 2) Add new function qemuMonitorGetBlockStatsParamsNumber, which is to count how many parameters the underlying QEMU supports. 3) Update virDomainBlockStats in src/qemu/qemu_driver.c to be compatible with the changes by 1).
This commit is contained in:
parent
efa7fc9f75
commit
2f58ba8996
@ -7242,8 +7242,12 @@ qemudDomainBlockStats (virDomainPtr dom,
|
|||||||
disk->info.alias,
|
disk->info.alias,
|
||||||
&stats->rd_req,
|
&stats->rd_req,
|
||||||
&stats->rd_bytes,
|
&stats->rd_bytes,
|
||||||
|
NULL,
|
||||||
&stats->wr_req,
|
&stats->wr_req,
|
||||||
&stats->wr_bytes,
|
&stats->wr_bytes,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
&stats->errs);
|
&stats->errs);
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
|
||||||
|
@ -1201,8 +1201,12 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
const char *devname,
|
const char *devname,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
long long *rd_bytes,
|
long long *rd_bytes,
|
||||||
|
long long *rd_total_times,
|
||||||
long long *wr_req,
|
long long *wr_req,
|
||||||
long long *wr_bytes,
|
long long *wr_bytes,
|
||||||
|
long long *wr_total_times,
|
||||||
|
long long *flush_req,
|
||||||
|
long long *flush_total_times,
|
||||||
long long *errs)
|
long long *errs)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -1217,16 +1221,47 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
if (mon->json)
|
if (mon->json)
|
||||||
ret = qemuMonitorJSONGetBlockStatsInfo(mon, devname,
|
ret = qemuMonitorJSONGetBlockStatsInfo(mon, devname,
|
||||||
rd_req, rd_bytes,
|
rd_req, rd_bytes,
|
||||||
|
rd_total_times,
|
||||||
wr_req, wr_bytes,
|
wr_req, wr_bytes,
|
||||||
|
wr_total_times,
|
||||||
|
flush_req,
|
||||||
|
flush_total_times,
|
||||||
errs);
|
errs);
|
||||||
else
|
else
|
||||||
ret = qemuMonitorTextGetBlockStatsInfo(mon, devname,
|
ret = qemuMonitorTextGetBlockStatsInfo(mon, devname,
|
||||||
rd_req, rd_bytes,
|
rd_req, rd_bytes,
|
||||||
|
rd_total_times,
|
||||||
wr_req, wr_bytes,
|
wr_req, wr_bytes,
|
||||||
|
wr_total_times,
|
||||||
|
flush_req,
|
||||||
|
flush_total_times,
|
||||||
errs);
|
errs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 0 and update @nparams with the number of block stats
|
||||||
|
* QEMU supports if success. Return -1 if failure.
|
||||||
|
*/
|
||||||
|
int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon,
|
||||||
|
int *nparams)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
VIR_DEBUG("mon=%p nparams=%p", mon, nparams);
|
||||||
|
|
||||||
|
if (!mon) {
|
||||||
|
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||||
|
_("monitor must not be NULL"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mon->json)
|
||||||
|
ret = qemuMonitorJSONGetBlockStatsParamsNumber(mon, nparams);
|
||||||
|
else
|
||||||
|
ret = qemuMonitorTextGetBlockStatsParamsNumber(mon, nparams);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
|
int qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
const char *devname,
|
||||||
unsigned long long *extent)
|
unsigned long long *extent)
|
||||||
|
@ -212,9 +212,15 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
const char *devname,
|
const char *devname,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
long long *rd_bytes,
|
long long *rd_bytes,
|
||||||
|
long long *rd_total_times,
|
||||||
long long *wr_req,
|
long long *wr_req,
|
||||||
long long *wr_bytes,
|
long long *wr_bytes,
|
||||||
|
long long *wr_total_times,
|
||||||
|
long long *flush_req,
|
||||||
|
long long *flush_total_times,
|
||||||
long long *errs);
|
long long *errs);
|
||||||
|
int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon,
|
||||||
|
int *nparams);
|
||||||
|
|
||||||
int qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
|
int qemuMonitorGetBlockExtent(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
const char *devname,
|
||||||
|
@ -1318,8 +1318,12 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
const char *devname,
|
const char *devname,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
long long *rd_bytes,
|
long long *rd_bytes,
|
||||||
|
long long *rd_total_times,
|
||||||
long long *wr_req,
|
long long *wr_req,
|
||||||
long long *wr_bytes,
|
long long *wr_bytes,
|
||||||
|
long long *wr_total_times,
|
||||||
|
long long *flush_req,
|
||||||
|
long long *flush_total_times,
|
||||||
long long *errs)
|
long long *errs)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -1330,7 +1334,17 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
virJSONValuePtr reply = NULL;
|
virJSONValuePtr reply = NULL;
|
||||||
virJSONValuePtr devices;
|
virJSONValuePtr devices;
|
||||||
|
|
||||||
*rd_req = *rd_bytes = *wr_req = *wr_bytes = *errs = 0;
|
*rd_req = *rd_bytes = -1;
|
||||||
|
*wr_req = *wr_bytes = *errs = -1;
|
||||||
|
|
||||||
|
if (rd_total_times)
|
||||||
|
*rd_total_times = -1;
|
||||||
|
if (wr_total_times)
|
||||||
|
*wr_total_times = -1;
|
||||||
|
if (flush_req)
|
||||||
|
*flush_req = -1;
|
||||||
|
if (flush_total_times)
|
||||||
|
*flush_total_times = -1;
|
||||||
|
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
return -1;
|
return -1;
|
||||||
@ -1396,6 +1410,15 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
"rd_operations");
|
"rd_operations");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
if (rd_total_times &&
|
||||||
|
virJSONValueObjectHasKey(stats, "rd_total_times_ns") &&
|
||||||
|
(virJSONValueObjectGetNumberLong(stats, "rd_total_times_ns",
|
||||||
|
rd_total_times) < 0)) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot read %s statistic"),
|
||||||
|
"rd_total_times_ns");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
if (virJSONValueObjectGetNumberLong(stats, "wr_bytes", wr_bytes) < 0) {
|
if (virJSONValueObjectGetNumberLong(stats, "wr_bytes", wr_bytes) < 0) {
|
||||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot read %s statistic"),
|
_("cannot read %s statistic"),
|
||||||
@ -1408,6 +1431,33 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
"wr_operations");
|
"wr_operations");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
if (wr_total_times &&
|
||||||
|
virJSONValueObjectHasKey(stats, "wr_total_times_ns") &&
|
||||||
|
(virJSONValueObjectGetNumberLong(stats, "wr_total_times_ns",
|
||||||
|
wr_total_times) < 0)) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot read %s statistic"),
|
||||||
|
"wr_total_times_ns");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (flush_req &&
|
||||||
|
virJSONValueObjectHasKey(stats, "flush_operations") &&
|
||||||
|
(virJSONValueObjectGetNumberLong(stats, "flush_operations",
|
||||||
|
flush_req) < 0)) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot read %s statistic"),
|
||||||
|
"flush_operations");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (flush_total_times &&
|
||||||
|
virJSONValueObjectHasKey(stats, "flush_total_times_ns") &&
|
||||||
|
(virJSONValueObjectGetNumberLong(stats, "flush_total_times_ns",
|
||||||
|
flush_total_times) < 0)) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot read %s statistic"),
|
||||||
|
"flush_total_times_ns");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
@ -1424,6 +1474,78 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int qemuMonitorJSONGetBlockStatsParamsNumber(qemuMonitorPtr mon,
|
||||||
|
int *nparams)
|
||||||
|
{
|
||||||
|
int ret, i, num = 0;
|
||||||
|
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-blockstats",
|
||||||
|
NULL);
|
||||||
|
virJSONValuePtr reply = NULL;
|
||||||
|
virJSONValuePtr devices = NULL;
|
||||||
|
virJSONValuePtr dev = NULL;
|
||||||
|
virJSONValuePtr stats = NULL;
|
||||||
|
|
||||||
|
if (!cmd)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = qemuMonitorJSONCommand(mon, cmd, &reply);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
ret = qemuMonitorJSONCheckError(cmd, reply);
|
||||||
|
if (ret < 0)
|
||||||
|
goto cleanup;
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
devices = virJSONValueObjectGet(reply, "return");
|
||||||
|
if (!devices || devices->type != VIR_JSON_TYPE_ARRAY) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("blockstats reply was missing device list"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = virJSONValueArrayGet(devices, 0);
|
||||||
|
|
||||||
|
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("blockstats device entry was not in expected format"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((stats = virJSONValueObjectGet(dev, "stats")) == NULL ||
|
||||||
|
stats->type != VIR_JSON_TYPE_OBJECT) {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("blockstats stats entry was not in expected format"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < stats->data.object.npairs; i++) {
|
||||||
|
const char *key = stats->data.object.pairs[i].key;
|
||||||
|
|
||||||
|
if (STREQ(key, "rd_bytes") ||
|
||||||
|
STREQ(key, "rd_operations") ||
|
||||||
|
STREQ(key, "rd_total_times_ns") ||
|
||||||
|
STREQ(key, "wr_bytes") ||
|
||||||
|
STREQ(key, "wr_operations") ||
|
||||||
|
STREQ(key, "wr_total_times_ns") ||
|
||||||
|
STREQ(key, "flush_operations") ||
|
||||||
|
STREQ(key, "flush_total_times_ns")) {
|
||||||
|
num++;
|
||||||
|
} else {
|
||||||
|
/* wr_highest_offset is parsed by qemuMonitorJSONGetBlockExtent. */
|
||||||
|
if (STRNEQ(key, "wr_highest_offset"))
|
||||||
|
VIR_DEBUG("Missed block stat: %s", key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*nparams = num;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virJSONValueFree(cmd);
|
||||||
|
virJSONValueFree(reply);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
|
int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
const char *devname,
|
||||||
unsigned long long *extent)
|
unsigned long long *extent)
|
||||||
|
@ -64,9 +64,15 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
const char *devname,
|
const char *devname,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
long long *rd_bytes,
|
long long *rd_bytes,
|
||||||
|
long long *rd_total_times,
|
||||||
long long *wr_req,
|
long long *wr_req,
|
||||||
long long *wr_bytes,
|
long long *wr_bytes,
|
||||||
|
long long *wr_total_times,
|
||||||
|
long long *flush_req,
|
||||||
|
long long *flush_total_times,
|
||||||
long long *errs);
|
long long *errs);
|
||||||
|
int qemuMonitorJSONGetBlockStatsParamsNumber(qemuMonitorPtr mon,
|
||||||
|
int *nparams);
|
||||||
int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
|
int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
const char *devname,
|
||||||
unsigned long long *extent);
|
unsigned long long *extent);
|
||||||
|
@ -708,8 +708,12 @@ int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
const char *devname,
|
const char *devname,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
long long *rd_bytes,
|
long long *rd_bytes,
|
||||||
|
long long *rd_total_times,
|
||||||
long long *wr_req,
|
long long *wr_req,
|
||||||
long long *wr_bytes,
|
long long *wr_bytes,
|
||||||
|
long long *wr_total_times,
|
||||||
|
long long *flush_req,
|
||||||
|
long long *flush_total_times,
|
||||||
long long *errs)
|
long long *errs)
|
||||||
{
|
{
|
||||||
char *info = NULL;
|
char *info = NULL;
|
||||||
@ -736,11 +740,17 @@ int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
*rd_req = -1;
|
*rd_req = *rd_bytes = -1;
|
||||||
*rd_bytes = -1;
|
*wr_req = *wr_bytes = *errs = -1;
|
||||||
*wr_req = -1;
|
|
||||||
*wr_bytes = -1;
|
if (rd_total_times)
|
||||||
*errs = -1;
|
*rd_total_times = -1;
|
||||||
|
if (wr_total_times)
|
||||||
|
*wr_total_times = -1;
|
||||||
|
if (flush_req)
|
||||||
|
*flush_req = -1;
|
||||||
|
if (flush_total_times)
|
||||||
|
*flush_total_times = -1;
|
||||||
|
|
||||||
/* The output format for both qemu & KVM is:
|
/* The output format for both qemu & KVM is:
|
||||||
* blockdevice: rd_bytes=% wr_bytes=% rd_operations=% wr_operations=%
|
* blockdevice: rd_bytes=% wr_bytes=% rd_operations=% wr_operations=%
|
||||||
@ -768,23 +778,44 @@ int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if (STRPREFIX (p, "rd_bytes=")) {
|
if (STRPREFIX (p, "rd_bytes=")) {
|
||||||
p += 9;
|
p += strlen("rd_bytes=");
|
||||||
if (virStrToLong_ll (p, &dummy, 10, rd_bytes) == -1)
|
if (virStrToLong_ll (p, &dummy, 10, rd_bytes) == -1)
|
||||||
VIR_DEBUG ("error reading rd_bytes: %s", p);
|
VIR_DEBUG ("error reading rd_bytes: %s", p);
|
||||||
} else if (STRPREFIX (p, "wr_bytes=")) {
|
} else if (STRPREFIX (p, "wr_bytes=")) {
|
||||||
p += 9;
|
p += strlen("wr_bytes=");
|
||||||
if (virStrToLong_ll (p, &dummy, 10, wr_bytes) == -1)
|
if (virStrToLong_ll (p, &dummy, 10, wr_bytes) == -1)
|
||||||
VIR_DEBUG ("error reading wr_bytes: %s", p);
|
VIR_DEBUG ("error reading wr_bytes: %s", p);
|
||||||
} else if (STRPREFIX (p, "rd_operations=")) {
|
} else if (STRPREFIX (p, "rd_operations=")) {
|
||||||
p += 14;
|
p += strlen("rd_operations=");
|
||||||
if (virStrToLong_ll (p, &dummy, 10, rd_req) == -1)
|
if (virStrToLong_ll (p, &dummy, 10, rd_req) == -1)
|
||||||
VIR_DEBUG ("error reading rd_req: %s", p);
|
VIR_DEBUG ("error reading rd_req: %s", p);
|
||||||
} else if (STRPREFIX (p, "wr_operations=")) {
|
} else if (STRPREFIX (p, "wr_operations=")) {
|
||||||
p += 14;
|
p += strlen("wr_operations=");
|
||||||
if (virStrToLong_ll (p, &dummy, 10, wr_req) == -1)
|
if (virStrToLong_ll (p, &dummy, 10, wr_req) == -1)
|
||||||
VIR_DEBUG ("error reading wr_req: %s", p);
|
VIR_DEBUG ("error reading wr_req: %s", p);
|
||||||
} else
|
} else if (rd_total_times &&
|
||||||
|
STRPREFIX (p, "rd_total_times_ns=")) {
|
||||||
|
p += strlen("rd_total_times_ns=");
|
||||||
|
if (virStrToLong_ll (p, &dummy, 10, rd_total_times) == -1)
|
||||||
|
VIR_DEBUG ("error reading rd_total_times: %s", p);
|
||||||
|
} else if (wr_total_times &&
|
||||||
|
STRPREFIX (p, "wr_total_times_ns=")) {
|
||||||
|
p += strlen("wr_total_times_ns=");
|
||||||
|
if (virStrToLong_ll (p, &dummy, 10, wr_total_times) == -1)
|
||||||
|
VIR_DEBUG ("error reading wr_total_times: %s", p);
|
||||||
|
} else if (flush_req &&
|
||||||
|
STRPREFIX (p, "flush_operations=")) {
|
||||||
|
p += strlen("flush_operations=");
|
||||||
|
if (virStrToLong_ll (p, &dummy, 10, flush_req) == -1)
|
||||||
|
VIR_DEBUG ("error reading flush_req: %s", p);
|
||||||
|
} else if (flush_total_times &&
|
||||||
|
STRPREFIX (p, "flush_total_times_ns=")) {
|
||||||
|
p += strlen("flush_total_times_ns=");
|
||||||
|
if (virStrToLong_ll (p, &dummy, 10, flush_total_times) == -1)
|
||||||
|
VIR_DEBUG ("error reading flush_total_times: %s", p);
|
||||||
|
} else {
|
||||||
VIR_DEBUG ("unknown block stat near %s", p);
|
VIR_DEBUG ("unknown block stat near %s", p);
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip to next label. */
|
/* Skip to next label. */
|
||||||
p = strchr (p, ' ');
|
p = strchr (p, ' ');
|
||||||
@ -810,6 +841,76 @@ int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qemuMonitorTextGetBlockStatsParamsNumber(qemuMonitorPtr mon,
|
||||||
|
int *nparams)
|
||||||
|
{
|
||||||
|
char *info = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
int num = 0;
|
||||||
|
const char *p, *eol;
|
||||||
|
|
||||||
|
if (qemuMonitorHMPCommand (mon, "info blockstats", &info) < 0) {
|
||||||
|
qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||||
|
"%s", _("'info blockstats' command failed"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the command isn't supported then qemu prints the supported
|
||||||
|
* info commands, so the output starts "info ". Since this is
|
||||||
|
* unlikely to be the name of a block device, we can use this
|
||||||
|
* to detect if qemu supports the command.
|
||||||
|
*/
|
||||||
|
if (strstr(info, "\ninfo ")) {
|
||||||
|
qemuReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
|
"%s",
|
||||||
|
_("'info blockstats' not supported by this qemu"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The output format for both qemu & KVM is:
|
||||||
|
* blockdevice: rd_bytes=% wr_bytes=% rd_operations=% wr_operations=%
|
||||||
|
* (repeated for each block device)
|
||||||
|
* where '%' is a 64 bit number.
|
||||||
|
*/
|
||||||
|
p = info;
|
||||||
|
|
||||||
|
eol = strchr (p, '\n');
|
||||||
|
if (!eol)
|
||||||
|
eol = p + strlen (p);
|
||||||
|
|
||||||
|
/* Skip the device name and following ":", and spaces (e.g.
|
||||||
|
* "floppy0: ")
|
||||||
|
*/
|
||||||
|
p = strchr(p, ' ');
|
||||||
|
p++;
|
||||||
|
|
||||||
|
while (*p) {
|
||||||
|
if (STRPREFIX (p, "rd_bytes=") ||
|
||||||
|
STRPREFIX (p, "wr_bytes=") ||
|
||||||
|
STRPREFIX (p, "rd_operations=") ||
|
||||||
|
STRPREFIX (p, "wr_operations=") ||
|
||||||
|
STRPREFIX (p, "rd_total_times_ns=") ||
|
||||||
|
STRPREFIX (p, "wr_total_times_ns=") ||
|
||||||
|
STRPREFIX (p, "flush_operations=") ||
|
||||||
|
STRPREFIX (p, "flush_total_times_ns=")) {
|
||||||
|
num++;
|
||||||
|
} else {
|
||||||
|
VIR_DEBUG ("unknown block stat near %s", p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip to next label. */
|
||||||
|
p = strchr (p, ' ');
|
||||||
|
if (!p || p >= eol) break;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*nparams = num;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(info);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int qemuMonitorTextGetBlockExtent(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
int qemuMonitorTextGetBlockExtent(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||||
const char *devname ATTRIBUTE_UNUSED,
|
const char *devname ATTRIBUTE_UNUSED,
|
||||||
|
@ -61,9 +61,15 @@ int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
|
|||||||
const char *devname,
|
const char *devname,
|
||||||
long long *rd_req,
|
long long *rd_req,
|
||||||
long long *rd_bytes,
|
long long *rd_bytes,
|
||||||
|
long long *rd_total_times,
|
||||||
long long *wr_req,
|
long long *wr_req,
|
||||||
long long *wr_bytes,
|
long long *wr_bytes,
|
||||||
|
long long *wr_total_times,
|
||||||
|
long long *flush_req,
|
||||||
|
long long *flush_total_times,
|
||||||
long long *errs);
|
long long *errs);
|
||||||
|
int qemuMonitorTextGetBlockStatsParamsNumber(qemuMonitorPtr mon,
|
||||||
|
int *nparams);
|
||||||
int qemuMonitorTextGetBlockExtent(qemuMonitorPtr mon,
|
int qemuMonitorTextGetBlockExtent(qemuMonitorPtr mon,
|
||||||
const char *devname,
|
const char *devname,
|
||||||
unsigned long long *extent);
|
unsigned long long *extent);
|
||||||
|
Loading…
Reference in New Issue
Block a user