From f225e560de930d8ab56de5f9284a6c2414786138 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 23 Sep 2009 13:51:05 +0100 Subject: [PATCH] Add API for issuing 'info blockstats' command * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add a new qemuMonitorGetBlockStatsInfo() command * src/qemu/qemu_driver.c: Remove directly use of blockstats in favour of calling qemuMonitorGetBlockStatsInfo() --- src/qemu/qemu_driver.c | 95 +++---------------------------- src/qemu/qemu_monitor_text.c | 105 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 8 +++ 3 files changed, 121 insertions(+), 87 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 545cecf3ae..24253bc4be 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5957,10 +5957,7 @@ qemudDomainBlockStats (virDomainPtr dom, struct _virDomainBlockStats *stats) { struct qemud_driver *driver = dom->conn->privateData; - char *dummy, *info = NULL; - const char *p, *eol; const char *qemu_dev_name = NULL; - size_t len; int i, ret = -1; virDomainObjPtr vm; virDomainDiskDefPtr disk = NULL; @@ -5997,95 +5994,19 @@ qemudDomainBlockStats (virDomainPtr dom, qemu_dev_name = qemudDiskDeviceName(dom->conn, disk); if (!qemu_dev_name) goto cleanup; - len = strlen (qemu_dev_name); - if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - "%s", _("'info blockstats' command failed")); - goto cleanup; - } - DEBUG ("%s: info blockstats reply: %s", vm->def->name, info); - - /* 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 ")) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, - "%s", - _("'info blockstats' not supported by this qemu")); + if (qemuMonitorGetBlockStatsInfo(vm, qemu_dev_name, + &stats->rd_req, + &stats->rd_bytes, + &stats->wr_req, + &stats->wr_bytes, + &stats->errs) < 0) goto cleanup; - } - - stats->rd_req = -1; - stats->rd_bytes = -1; - stats->wr_req = -1; - stats->wr_bytes = -1; - stats->errs = -1; - - /* 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; - - while (*p) { - if (STREQLEN (p, qemu_dev_name, len) - && p[len] == ':' && p[len+1] == ' ') { - - eol = strchr (p, '\n'); - if (!eol) - eol = p + strlen (p); - - p += len+2; /* Skip to first label. */ - - while (*p) { - if (STRPREFIX (p, "rd_bytes=")) { - p += 9; - if (virStrToLong_ll (p, &dummy, 10, &stats->rd_bytes) == -1) - DEBUG ("%s: error reading rd_bytes: %s", - vm->def->name, p); - } else if (STRPREFIX (p, "wr_bytes=")) { - p += 9; - if (virStrToLong_ll (p, &dummy, 10, &stats->wr_bytes) == -1) - DEBUG ("%s: error reading wr_bytes: %s", - vm->def->name, p); - } else if (STRPREFIX (p, "rd_operations=")) { - p += 14; - if (virStrToLong_ll (p, &dummy, 10, &stats->rd_req) == -1) - DEBUG ("%s: error reading rd_req: %s", - vm->def->name, p); - } else if (STRPREFIX (p, "wr_operations=")) { - p += 14; - if (virStrToLong_ll (p, &dummy, 10, &stats->wr_req) == -1) - DEBUG ("%s: error reading wr_req: %s", - vm->def->name, p); - } else - DEBUG ("%s: unknown block stat near %s", vm->def->name, p); - - /* Skip to next label. */ - p = strchr (p, ' '); - if (!p || p >= eol) break; - p++; - } - ret = 0; - goto cleanup; - } - /* Skip to next line. */ - p = strchr (p, '\n'); - if (!p) break; - p++; - } + ret = 0; - /* If we reach here then the device was not found. */ - qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, - _("device not found: %s (%s)"), path, qemu_dev_name); - cleanup: +cleanup: VIR_FREE(qemu_dev_name); - VIR_FREE(info); if (vm) virDomainObjUnlock(vm); return ret; diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 93e0d40470..bad2e25df3 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -671,6 +671,111 @@ cleanup: } +int qemuMonitorGetBlockStatsInfo(const virDomainObjPtr vm, + const char *devname, + long long *rd_req, + long long *rd_bytes, + long long *wr_req, + long long *wr_bytes, + long long *errs) +{ + char *info = NULL; + int ret = -1; + char *dummy; + const char *p, *eol; + int devnamelen = strlen(devname); + + if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) { + qemudReportError (NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("'info blockstats' command failed")); + goto cleanup; + } + DEBUG ("%s: info blockstats reply: %s", vm->def->name, info); + + /* 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 ")) { + qemudReportError (NULL, NULL, NULL, VIR_ERR_NO_SUPPORT, + "%s", + _("'info blockstats' not supported by this qemu")); + goto cleanup; + } + + *rd_req = -1; + *rd_bytes = -1; + *wr_req = -1; + *wr_bytes = -1; + *errs = -1; + + /* 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; + + while (*p) { + if (STREQLEN (p, devname, devnamelen) + && p[devnamelen] == ':' && p[devnamelen+1] == ' ') { + + eol = strchr (p, '\n'); + if (!eol) + eol = p + strlen (p); + + p += devnamelen+2; /* Skip to first label. */ + + while (*p) { + if (STRPREFIX (p, "rd_bytes=")) { + p += 9; + if (virStrToLong_ll (p, &dummy, 10, rd_bytes) == -1) + DEBUG ("%s: error reading rd_bytes: %s", + vm->def->name, p); + } else if (STRPREFIX (p, "wr_bytes=")) { + p += 9; + if (virStrToLong_ll (p, &dummy, 10, wr_bytes) == -1) + DEBUG ("%s: error reading wr_bytes: %s", + vm->def->name, p); + } else if (STRPREFIX (p, "rd_operations=")) { + p += 14; + if (virStrToLong_ll (p, &dummy, 10, rd_req) == -1) + DEBUG ("%s: error reading rd_req: %s", + vm->def->name, p); + } else if (STRPREFIX (p, "wr_operations=")) { + p += 14; + if (virStrToLong_ll (p, &dummy, 10, wr_req) == -1) + DEBUG ("%s: error reading wr_req: %s", + vm->def->name, p); + } else + DEBUG ("%s: unknown block stat near %s", vm->def->name, p); + + /* Skip to next label. */ + p = strchr (p, ' '); + if (!p || p >= eol) break; + p++; + } + ret = 0; + goto cleanup; + } + + /* Skip to next line. */ + p = strchr (p, '\n'); + if (!p) break; + p++; + } + + /* If we reach here then the device was not found. */ + qemudReportError (NULL, NULL, NULL, VIR_ERR_INVALID_ARG, + _("no stats found for device %s"), devname); + + cleanup: + VIR_FREE(info); + return ret; +} + + int qemuMonitorSetVNCPassword(const virDomainObjPtr vm, const char *password) { diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index fedc101fd9..11256cb11f 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -75,6 +75,14 @@ int qemuMonitorGetCPUInfo(const virDomainObjPtr vm, int **pids); int qemuMonitorGetBalloonInfo(const virDomainObjPtr vm, unsigned long *currmem); +int qemuMonitorGetBlockStatsInfo(const virDomainObjPtr vm, + const char *devname, + long long *rd_req, + long long *rd_bytes, + long long *wr_req, + long long *wr_bytes, + long long *errs); + int qemuMonitorSetVNCPassword(const virDomainObjPtr vm, const char *password); -- GitLab