1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

Implements domainMemStats in the qemu driver

Support for memory statistics reporting is accepted for qemu inclusion.
Statistics are reported via the monitor command 'info balloon' as a comma
seprated list:

(qemu) info balloon
balloon: actual=1024,mem_swapped_in=0,mem_swapped_out=0,major_page_faults=88,minor_page_faults=105535,free_mem=1017065472,total_mem=1045229568

Libvirt, qemu, and the guest operating system may support a subset of the
statistics defined by the virtio spec.  Thus, only statistics recognized by
components will be reported.

* src/qemu/qemu_driver.c src/qemu/qemu_monitor_text.[ch]: implement the
  new entry point by using info balloon monitor command
This commit is contained in:
Adam Litke 2009-12-20 13:36:28 +01:00 committed by Daniel Veillard
parent 4fe975fe4e
commit c7523b410a
3 changed files with 124 additions and 1 deletions

View File

@ -6235,6 +6235,43 @@ qemudDomainInterfaceStats (virDomainPtr dom,
}
#endif
static int
qemudDomainMemoryStats (virDomainPtr dom,
struct _virDomainMemoryStat *stats,
unsigned int nr_stats)
{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
unsigned int ret = -1;
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
qemuDriverUnlock(driver);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
if (virDomainObjIsActive(vm)) {
qemuDomainObjPrivatePtr priv = vm->privateData;
qemuDomainObjEnterMonitor(vm);
ret = qemuMonitorTextGetMemoryStats(priv->mon, stats, nr_stats);
qemuDomainObjExitMonitor(vm);
} else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
}
cleanup:
if (vm)
virDomainObjUnlock(vm);
return ret;
}
static int
qemudDomainBlockPeek (virDomainPtr dom,
const char *path,
@ -7930,7 +7967,7 @@ static virDriver qemuDriver = {
NULL, /* domainMigrateFinish */
qemudDomainBlockStats, /* domainBlockStats */
qemudDomainInterfaceStats, /* domainInterfaceStats */
NULL, /* domainMemoryStats */
qemudDomainMemoryStats, /* domainMemoryStats */
qemudDomainBlockPeek, /* domainBlockPeek */
qemudDomainMemoryPeek, /* domainMemoryPeek */
nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */

View File

@ -454,6 +454,65 @@ error:
return 0;
}
static int parseMemoryStat(char **text, unsigned int tag,
const char *search, virDomainMemoryStatPtr stat)
{
char *dummy;
unsigned long long value;
if (STRPREFIX (*text, search)) {
*text += strlen(search);
if (virStrToLong_ull (*text, &dummy, 10, &value)) {
DEBUG ("error reading %s: %s", search, *text);
return 0;
}
/* Convert bytes to kilobytes for libvirt */
switch (tag) {
case VIR_DOMAIN_MEMORY_STAT_SWAP_IN:
case VIR_DOMAIN_MEMORY_STAT_SWAP_OUT:
case VIR_DOMAIN_MEMORY_STAT_UNUSED:
case VIR_DOMAIN_MEMORY_STAT_AVAILABLE:
value = value >> 10;
}
stat->tag = tag;
stat->val = value;
return 1;
}
return 0;
}
/* The reply from the 'info balloon' command may contain additional memory
* statistics in the form: '[,<tag>=<val>]*'
*/
static int qemuMonitorParseExtraBalloonInfo(char *text,
virDomainMemoryStatPtr stats,
unsigned int nr_stats)
{
char *p = text;
unsigned int nr_stats_found = 0;
while (*p && nr_stats_found < nr_stats) {
if (parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_SWAP_IN,
",mem_swapped_in=", &stats[nr_stats_found]) ||
parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_SWAP_OUT,
",mem_swapped_out=", &stats[nr_stats_found]) ||
parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT,
",major_page_faults=", &stats[nr_stats_found]) ||
parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT,
",minor_page_faults=", &stats[nr_stats_found]) ||
parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_UNUSED,
",free_mem=", &stats[nr_stats_found]) ||
parseMemoryStat(&p, VIR_DOMAIN_MEMORY_STAT_AVAILABLE,
",total_mem=", &stats[nr_stats_found]))
nr_stats_found++;
/* Skip to the next label */
p = strchr (p, ',');
if (!p) break;
}
return nr_stats_found;
}
/* The reply from QEMU contains 'ballon: actual=421' where value is in MB */
@ -499,6 +558,30 @@ cleanup:
return ret;
}
int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
virDomainMemoryStatPtr stats,
unsigned int nr_stats)
{
char *reply = NULL;
int ret = 0;
char *offset;
if (qemuMonitorCommand(mon, "info balloon", &reply) < 0) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("could not query memory balloon statistics"));
return -1;
}
if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) {
if ((offset = strchr(reply, ',')) != NULL) {
ret = qemuMonitorParseExtraBalloonInfo(offset, stats, nr_stats);
}
}
VIR_FREE(reply);
return ret;
}
int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,

View File

@ -45,6 +45,9 @@ int qemuMonitorTextGetCPUInfo(qemuMonitorPtr mon,
int **pids);
int qemuMonitorTextGetBalloonInfo(qemuMonitorPtr mon,
unsigned long *currmem);
int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
virDomainMemoryStatPtr stats,
unsigned int nr_stats);
int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
const char *devname,
long long *rd_req,