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:
parent
4fe975fe4e
commit
c7523b410a
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user