* [PATCH] kvm tools: Add 'kvm stat' command
@ 2011-08-15 14:32 Sasha Levin
2011-08-15 14:33 ` [PATCH] kvm tools: Use correct data type for pid Sasha Levin
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Sasha Levin @ 2011-08-15 14:32 UTC (permalink / raw)
To: penberg; +Cc: mingo, asias.hejun, prasadjoshi124, gorcunov, kvm, Sasha Levin
This patch adds 'kvm stat' command that allows retrieving statistics out of
a running guest.
Currently the only supported statistics are memory statistics, available using the
'--memory' parameter.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
tools/kvm/Documentation/kvm-stat.txt | 19 ++++++
tools/kvm/Makefile | 1 +
tools/kvm/builtin-stat.c | 79 +++++++++++++++++++++++++
tools/kvm/command-list.txt | 1 +
tools/kvm/include/kvm/builtin-stat.h | 7 ++
tools/kvm/include/kvm/kvm.h | 1 +
tools/kvm/kvm-cmd.c | 2 +
tools/kvm/virtio/balloon.c | 108 ++++++++++++++++++++++++++++++++-
8 files changed, 214 insertions(+), 4 deletions(-)
create mode 100644 tools/kvm/Documentation/kvm-stat.txt
create mode 100644 tools/kvm/builtin-stat.c
create mode 100644 tools/kvm/include/kvm/builtin-stat.h
diff --git a/tools/kvm/Documentation/kvm-stat.txt b/tools/kvm/Documentation/kvm-stat.txt
new file mode 100644
index 0000000..ce5ab54
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-stat.txt
@@ -0,0 +1,19 @@
+kvm-stat(1)
+================
+
+NAME
+----
+kvm-stat - Print statistics about a running instance
+
+SYNOPSIS
+--------
+[verse]
+'kvm [command] [-n instance] [-p instance pid] [--all]'
+
+DESCRIPTION
+-----------
+The command prints statistics about a running instance.
+For a list of running instances see 'kvm list'.
+
+Commands:
+ --memory, -m Display memory statistics
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 3a06e10..85bbce7 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -24,6 +24,7 @@ OBJS += builtin-balloon.o
OBJS += builtin-debug.o
OBJS += builtin-help.o
OBJS += builtin-list.o
+OBJS += builtin-stat.o
OBJS += builtin-pause.o
OBJS += builtin-resume.o
OBJS += builtin-run.o
diff --git a/tools/kvm/builtin-stat.c b/tools/kvm/builtin-stat.c
new file mode 100644
index 0000000..d9bc75d
--- /dev/null
+++ b/tools/kvm/builtin-stat.c
@@ -0,0 +1,79 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-stat.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static bool mem;
+static bool all;
+static u64 instance_pid;
+static const char *instance_name;
+
+static const char * const stat_usage[] = {
+ "kvm stat [command] [--all] [-n name] [-p pid]",
+ NULL
+};
+
+static const struct option stat_options[] = {
+ OPT_GROUP("Commands options:"),
+ OPT_BOOLEAN('m', "memory", &mem, "Display memory statistics"),
+ OPT_GROUP("Instance options:"),
+ OPT_BOOLEAN('a', "all", &all, "All instances"),
+ OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+ OPT_U64('p', "pid", &instance_pid, "Instance pid"),
+ OPT_END()
+};
+
+static void parse_stat_options(int argc, const char **argv)
+{
+ while (argc != 0) {
+ argc = parse_options(argc, argv, stat_options, stat_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ if (argc != 0)
+ kvm_stat_help();
+ }
+}
+
+void kvm_stat_help(void)
+{
+ usage_with_options(stat_usage, stat_options);
+}
+
+static int do_memstat(const char *name, int pid)
+{
+ printf("Sending memstat command to %s, output should be on the targets' terminal.\n", name);
+ return kill(pid, SIGKVMMEMSTAT);
+}
+
+int kvm_cmd_stat(int argc, const char **argv, const char *prefix)
+{
+ parse_stat_options(argc, argv);
+
+ if (!mem)
+ usage_with_options(stat_usage, stat_options);
+
+ if (mem && all)
+ return kvm__enumerate_instances(do_memstat);
+
+ if (instance_name == NULL &&
+ instance_pid == 0)
+ kvm_stat_help();
+
+ if (instance_name)
+ instance_pid = kvm__get_pid_by_instance(instance_name);
+
+ if (instance_pid <= 0)
+ die("Failed locating instance");
+
+ if (mem) {
+ printf("Sending memstat command to designated instance, output should be on the targets' terminal.\n");
+
+ return kill(instance_pid, SIGKVMMEMSTAT);
+ }
+
+ return 0;
+}
diff --git a/tools/kvm/command-list.txt b/tools/kvm/command-list.txt
index 6a49d0a..f201d75 100644
--- a/tools/kvm/command-list.txt
+++ b/tools/kvm/command-list.txt
@@ -10,3 +10,4 @@ kvm-list common
kvm-debug common
kvm-balloon common
kvm-stop common
+kvm-stat common
diff --git a/tools/kvm/include/kvm/builtin-stat.h b/tools/kvm/include/kvm/builtin-stat.h
new file mode 100644
index 0000000..e3ce292
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-stat.h
@@ -0,0 +1,7 @@
+#ifndef KVM__STAT_H
+#define KVM__STAT_H
+
+int kvm_cmd_stat(int argc, const char **argv, const char *prefix);
+void kvm_stat_help(void);
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
index d4fe2a1..c2d815c 100644
--- a/tools/kvm/include/kvm/kvm.h
+++ b/tools/kvm/include/kvm/kvm.h
@@ -22,6 +22,7 @@
#define SIGKVMDELMEM (SIGRTMIN + 3)
#define SIGKVMSTOP (SIGRTMIN + 4)
#define SIGKVMRESUME (SIGRTMIN + 5)
+#define SIGKVMMEMSTAT (SIGRTMIN + 6)
struct kvm {
int sys_fd; /* For system ioctls(), i.e. /dev/kvm */
diff --git a/tools/kvm/kvm-cmd.c b/tools/kvm/kvm-cmd.c
index 4e3ea22..8fc6d22 100644
--- a/tools/kvm/kvm-cmd.c
+++ b/tools/kvm/kvm-cmd.c
@@ -12,6 +12,7 @@
#include "kvm/builtin-list.h"
#include "kvm/builtin-version.h"
#include "kvm/builtin-stop.h"
+#include "kvm/builtin-stat.h"
#include "kvm/builtin-help.h"
#include "kvm/kvm-cmd.h"
#include "kvm/builtin-run.h"
@@ -26,6 +27,7 @@ struct cmd_struct kvm_commands[] = {
{ "version", kvm_cmd_version, NULL, 0 },
{ "--version", kvm_cmd_version, NULL, 0 },
{ "stop", kvm_cmd_stop, kvm_stop_help, 0 },
+ { "stat", kvm_cmd_stat, kvm_stat_help, 0 },
{ "help", kvm_cmd_help, NULL, 0 },
{ "run", kvm_cmd_run, kvm_run_help, 0 },
{ NULL, NULL, NULL, 0 },
diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c
index 983a114..c5853a5 100644
--- a/tools/kvm/virtio/balloon.c
+++ b/tools/kvm/virtio/balloon.c
@@ -21,10 +21,11 @@
#include <sys/stat.h>
#include <pthread.h>
-#define NUM_VIRT_QUEUES 2
+#define NUM_VIRT_QUEUES 3
#define VIRTIO_BLN_QUEUE_SIZE 128
#define VIRTIO_BLN_INFLATE 0
#define VIRTIO_BLN_DEFLATE 1
+#define VIRTIO_BLN_STATS 2
struct bln_dev {
struct pci_device_header pci_hdr;
@@ -41,6 +42,12 @@ struct bln_dev {
struct virt_queue vqs[NUM_VIRT_QUEUES];
struct thread_pool__job jobs[NUM_VIRT_QUEUES];
+ struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
+ struct virtio_balloon_stat *cur_stat;
+ u32 cur_stat_head;
+ u16 stat_count;
+ int stat_waitfd;
+
struct virtio_balloon_config config;
};
@@ -127,7 +134,7 @@ static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, stru
if (queue == &bdev->vqs[VIRTIO_BLN_INFLATE]) {
madvise(guest_ptr, 1 << VIRTIO_BALLOON_PFN_SHIFT, MADV_DONTNEED);
bdev->config.actual++;
- } else {
+ } else if (queue == &bdev->vqs[VIRTIO_BLN_DEFLATE]) {
bdev->config.actual--;
}
}
@@ -137,10 +144,46 @@ static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, stru
return true;
}
+static bool virtio_bln_do_stat_request(struct kvm *kvm, struct bln_dev *bdev, struct virt_queue *queue)
+{
+ struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
+ u16 out, in, head;
+ struct virtio_balloon_stat *stat;
+ u64 wait_val = 1;
+
+ head = virt_queue__get_iov(queue, iov, &out, &in, kvm);
+ stat = iov[0].iov_base;
+
+ /* Initial empty stat buffer */
+ if (bdev->cur_stat == NULL) {
+ bdev->cur_stat = stat;
+ bdev->cur_stat_head = head;
+
+ return true;
+ }
+
+ memcpy(bdev->stats, stat, iov[0].iov_len);
+
+ bdev->stat_count = iov[0].iov_len / sizeof(struct virtio_balloon_stat);
+ bdev->cur_stat = stat;
+ bdev->cur_stat_head = head;
+
+ if (write(bdev->stat_waitfd, &wait_val, sizeof(wait_val)) <= 0)
+ return -EFAULT;
+
+ return 1;
+}
+
static void virtio_bln_do_io(struct kvm *kvm, void *param)
{
struct virt_queue *vq = param;
+ if (vq == &bdev.vqs[VIRTIO_BLN_STATS]) {
+ virtio_bln_do_stat_request(kvm, &bdev, vq);
+ virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, kvm);
+ return;
+ }
+
while (virt_queue__available(vq)) {
virtio_bln_do_io_request(kvm, &bdev, vq);
virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, kvm);
@@ -218,15 +261,70 @@ static struct ioport_operations virtio_bln_io_ops = {
.io_out = virtio_bln_pci_io_out,
};
+static int virtio_bln__collect_stats(void)
+{
+ u64 tmp;
+
+ virt_queue__set_used_elem(&bdev.vqs[VIRTIO_BLN_STATS], bdev.cur_stat_head,
+ sizeof(struct virtio_balloon_stat));
+ virt_queue__trigger_irq(&bdev.vqs[VIRTIO_BLN_STATS], bdev.pci_hdr.irq_line,
+ &bdev.isr, kvm);
+
+ if (read(bdev.stat_waitfd, &tmp, sizeof(tmp)) <= 0)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int virtio_bln__print_stats(void)
+{
+ u16 i;
+
+ if (virtio_bln__collect_stats() < 0)
+ return -EFAULT;
+
+ printf("\n\n\t*** Guest memory statistics ***\n\n");
+ for (i = 0; i < bdev.stat_count; i++) {
+ switch (bdev.stats[i].tag) {
+ case VIRTIO_BALLOON_S_SWAP_IN:
+ printf("The amount of memory that has been swapped in (in bytes):");
+ break;
+ case VIRTIO_BALLOON_S_SWAP_OUT:
+ printf("The amount of memory that has been swapped out to disk (in bytes):");
+ break;
+ case VIRTIO_BALLOON_S_MAJFLT:
+ printf("The number of major page faults that have occurred:");
+ break;
+ case VIRTIO_BALLOON_S_MINFLT:
+ printf("The number of minor page faults that have occurred:");
+ break;
+ case VIRTIO_BALLOON_S_MEMFREE:
+ printf("The amount of memory not being used for any purpose (in bytes):");
+ break;
+ case VIRTIO_BALLOON_S_MEMTOT:
+ printf("The total amount of memory available (in bytes):");
+ break;
+ }
+ printf("%llu\n", bdev.stats[i].val);
+ }
+ printf("\n");
+
+ return 0;
+}
+
static void handle_sigmem(int sig)
{
if (sig == SIGKVMADDMEM) {
bdev.config.num_pages += 256;
- } else {
+ } else if (sig == SIGKVMDELMEM) {
if (bdev.config.num_pages < 256)
return;
bdev.config.num_pages -= 256;
+ } else if (sig == SIGKVMMEMSTAT) {
+ virtio_bln__print_stats();
+
+ return;
}
/* Notify that the configuration space has changed */
@@ -241,6 +339,7 @@ void virtio_bln__init(struct kvm *kvm)
signal(SIGKVMADDMEM, handle_sigmem);
signal(SIGKVMDELMEM, handle_sigmem);
+ signal(SIGKVMMEMSTAT, handle_sigmem);
bdev_base_addr = ioport__register(IOPORT_EMPTY, &virtio_bln_io_ops, IOPORT_SIZE, &bdev);
@@ -262,7 +361,8 @@ void virtio_bln__init(struct kvm *kvm)
bdev.pci_hdr.irq_pin = pin;
bdev.pci_hdr.irq_line = line;
- bdev.host_features = 0;
+ bdev.host_features = 1 << VIRTIO_BALLOON_F_STATS_VQ;
+ bdev.stat_waitfd = eventfd(0, 0);
memset(&bdev.config, 0, sizeof(struct virtio_balloon_config));
pci__register(&bdev.pci_hdr, dev);
--
1.7.6
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH] kvm tools: Use correct data type for pid
2011-08-15 14:32 [PATCH] kvm tools: Add 'kvm stat' command Sasha Levin
@ 2011-08-15 14:33 ` Sasha Levin
2011-08-15 14:55 ` [PATCH] kvm tools: Add 'kvm stat' command Pekka Enberg
2011-08-16 3:09 ` walimis
2 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2011-08-15 14:33 UTC (permalink / raw)
To: penberg; +Cc: mingo, asias.hejun, prasadjoshi124, gorcunov, kvm, Sasha Levin
This patch fixes an error where pids used u64 instead of pid_t, causing them
to never be negative.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
tools/kvm/builtin-balloon.c | 4 ++--
tools/kvm/builtin-debug.c | 4 ++--
tools/kvm/builtin-pause.c | 4 ++--
tools/kvm/builtin-resume.c | 4 ++--
tools/kvm/builtin-stat.c | 4 ++--
tools/kvm/builtin-stop.c | 4 ++--
tools/kvm/include/kvm/kvm.h | 2 +-
tools/kvm/kvm.c | 5 +++--
8 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/tools/kvm/builtin-balloon.c b/tools/kvm/builtin-balloon.c
index cb7d552..7329063 100644
--- a/tools/kvm/builtin-balloon.c
+++ b/tools/kvm/builtin-balloon.c
@@ -8,7 +8,7 @@
#include <kvm/parse-options.h>
#include <kvm/kvm.h>
-static u64 instance_pid;
+static pid_t instance_pid;
static const char *instance_name;
static u64 inflate;
static u64 deflate;
@@ -21,7 +21,7 @@ static const char * const balloon_usage[] = {
static const struct option balloon_options[] = {
OPT_GROUP("Instance options:"),
OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
- OPT_U64('p', "pid", &instance_pid, "Instance pid"),
+ OPT_INTEGER('p', "pid", &instance_pid, "Instance pid"),
OPT_GROUP("Balloon options:"),
OPT_U64('i', "inflate", &inflate, "Amount to inflate"),
OPT_U64('d', "deflate", &deflate, "Amount to deflate"),
diff --git a/tools/kvm/builtin-debug.c b/tools/kvm/builtin-debug.c
index 43da16d..4be12cc 100644
--- a/tools/kvm/builtin-debug.c
+++ b/tools/kvm/builtin-debug.c
@@ -9,7 +9,7 @@
#include <signal.h>
static bool all;
-static u64 instance_pid;
+static pid_t instance_pid;
static const char *instance_name;
static const char * const debug_usage[] = {
@@ -21,7 +21,7 @@ static const struct option debug_options[] = {
OPT_GROUP("General options:"),
OPT_BOOLEAN('a', "all", &all, "Debug all instances"),
OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
- OPT_U64('p', "pid", &instance_pid, "Instance pid"),
+ OPT_INTEGER('p', "pid", &instance_pid, "Instance pid"),
OPT_END()
};
diff --git a/tools/kvm/builtin-pause.c b/tools/kvm/builtin-pause.c
index e4efb08..7b644ff 100644
--- a/tools/kvm/builtin-pause.c
+++ b/tools/kvm/builtin-pause.c
@@ -9,7 +9,7 @@
#include <signal.h>
static bool all;
-static u64 instance_pid;
+static pid_t instance_pid;
static const char *instance_name;
static const char * const pause_usage[] = {
@@ -21,7 +21,7 @@ static const struct option pause_options[] = {
OPT_GROUP("General options:"),
OPT_BOOLEAN('a', "all", &all, "Pause all instances"),
OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
- OPT_U64('p', "pid", &instance_pid, "Instance pid"),
+ OPT_INTEGER('p', "pid", &instance_pid, "Instance pid"),
OPT_END()
};
diff --git a/tools/kvm/builtin-resume.c b/tools/kvm/builtin-resume.c
index 0c11cec..70de0fc 100644
--- a/tools/kvm/builtin-resume.c
+++ b/tools/kvm/builtin-resume.c
@@ -9,7 +9,7 @@
#include <signal.h>
static bool all;
-static u64 instance_pid;
+static pid_t instance_pid;
static const char *instance_name;
static const char * const resume_usage[] = {
@@ -21,7 +21,7 @@ static const struct option resume_options[] = {
OPT_GROUP("General options:"),
OPT_BOOLEAN('a', "all", &all, "Resume all instances"),
OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
- OPT_U64('p', "pid", &instance_pid, "Instance pid"),
+ OPT_INTEGER('p', "pid", &instance_pid, "Instance pid"),
OPT_END()
};
diff --git a/tools/kvm/builtin-stat.c b/tools/kvm/builtin-stat.c
index d9bc75d..be12d15 100644
--- a/tools/kvm/builtin-stat.c
+++ b/tools/kvm/builtin-stat.c
@@ -10,7 +10,7 @@
static bool mem;
static bool all;
-static u64 instance_pid;
+static pid_t instance_pid;
static const char *instance_name;
static const char * const stat_usage[] = {
@@ -24,7 +24,7 @@ static const struct option stat_options[] = {
OPT_GROUP("Instance options:"),
OPT_BOOLEAN('a', "all", &all, "All instances"),
OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
- OPT_U64('p', "pid", &instance_pid, "Instance pid"),
+ OPT_INTEGER('p', "pid", &instance_pid, "Instance pid"),
OPT_END()
};
diff --git a/tools/kvm/builtin-stop.c b/tools/kvm/builtin-stop.c
index d16618a..fd0500e 100644
--- a/tools/kvm/builtin-stop.c
+++ b/tools/kvm/builtin-stop.c
@@ -9,7 +9,7 @@
#include <signal.h>
static bool all;
-static u64 instance_pid;
+static pid_t instance_pid;
static const char *instance_name;
static const char * const stop_usage[] = {
@@ -21,7 +21,7 @@ static const struct option stop_options[] = {
OPT_GROUP("General options:"),
OPT_BOOLEAN('a', "all", &all, "Stop all instances"),
OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
- OPT_U64('p', "pid", &instance_pid, "Instance pid"),
+ OPT_INTEGER('p', "pid", &instance_pid, "Instance pid"),
OPT_END()
};
diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
index c2d815c..d471cee 100644
--- a/tools/kvm/include/kvm/kvm.h
+++ b/tools/kvm/include/kvm/kvm.h
@@ -73,7 +73,7 @@ bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
void kvm__pause(void);
void kvm__continue(void);
void kvm__notify_paused(void);
-int kvm__get_pid_by_instance(const char *name);
+pid_t kvm__get_pid_by_instance(const char *name);
int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
void kvm__remove_pidfile(const char *name);
diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
index 30aef3a..bbfdea2 100644
--- a/tools/kvm/kvm.c
+++ b/tools/kvm/kvm.c
@@ -142,9 +142,10 @@ void kvm__remove_pidfile(const char *name)
unlink(full_name);
}
-int kvm__get_pid_by_instance(const char *name)
+pid_t kvm__get_pid_by_instance(const char *name)
{
- int fd, pid;
+ int fd;
+ pid_t pid;
char pid_str[10], pid_file[PATH_MAX];
sprintf(pid_file, "%s/%s/%s.pid", HOME_DIR, KVM_PID_FILE_PATH, name);
--
1.7.6
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] kvm tools: Add 'kvm stat' command
2011-08-15 14:32 [PATCH] kvm tools: Add 'kvm stat' command Sasha Levin
2011-08-15 14:33 ` [PATCH] kvm tools: Use correct data type for pid Sasha Levin
@ 2011-08-15 14:55 ` Pekka Enberg
2011-08-16 3:10 ` walimis
2011-08-16 3:09 ` walimis
2 siblings, 1 reply; 6+ messages in thread
From: Pekka Enberg @ 2011-08-15 14:55 UTC (permalink / raw)
To: Sasha Levin; +Cc: mingo, asias.hejun, prasadjoshi124, gorcunov, kvm
On Mon, 15 Aug 2011, Sasha Levin wrote:
> +static int do_memstat(const char *name, int pid)
> +{
> + printf("Sending memstat command to %s, output should be on the targets' terminal.\n", name);
> + return kill(pid, SIGKVMMEMSTAT);
> +}
I applied the patch but I think we should come up with a mechanism to
transport the output back to the command. Doing the printout in the guest
terminal isn't going to work in the long run.
Pekka
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] kvm tools: Add 'kvm stat' command
2011-08-15 14:32 [PATCH] kvm tools: Add 'kvm stat' command Sasha Levin
2011-08-15 14:33 ` [PATCH] kvm tools: Use correct data type for pid Sasha Levin
2011-08-15 14:55 ` [PATCH] kvm tools: Add 'kvm stat' command Pekka Enberg
@ 2011-08-16 3:09 ` walimis
2 siblings, 0 replies; 6+ messages in thread
From: walimis @ 2011-08-16 3:09 UTC (permalink / raw)
To: Sasha Levin; +Cc: penberg, mingo, asias.hejun, prasadjoshi124, gorcunov, kvm
On Mon, Aug 15, 2011 at 05:32:59PM +0300, Sasha Levin wrote:
>This patch adds 'kvm stat' command that allows retrieving statistics out of
>a running guest.
>
>Currently the only supported statistics are memory statistics, available using the
>'--memory' parameter.
>
>Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
>---
> tools/kvm/Documentation/kvm-stat.txt | 19 ++++++
> tools/kvm/Makefile | 1 +
> tools/kvm/builtin-stat.c | 79 +++++++++++++++++++++++++
> tools/kvm/command-list.txt | 1 +
> tools/kvm/include/kvm/builtin-stat.h | 7 ++
> tools/kvm/include/kvm/kvm.h | 1 +
> tools/kvm/kvm-cmd.c | 2 +
> tools/kvm/virtio/balloon.c | 108 ++++++++++++++++++++++++++++++++-
> 8 files changed, 214 insertions(+), 4 deletions(-)
> create mode 100644 tools/kvm/Documentation/kvm-stat.txt
> create mode 100644 tools/kvm/builtin-stat.c
> create mode 100644 tools/kvm/include/kvm/builtin-stat.h
>
>diff --git a/tools/kvm/Documentation/kvm-stat.txt b/tools/kvm/Documentation/kvm-stat.txt
>new file mode 100644
>index 0000000..ce5ab54
>--- /dev/null
>+++ b/tools/kvm/Documentation/kvm-stat.txt
>@@ -0,0 +1,19 @@
>+kvm-stat(1)
>+================
>+
>+NAME
>+----
>+kvm-stat - Print statistics about a running instance
>+
>+SYNOPSIS
>+--------
>+[verse]
>+'kvm [command] [-n instance] [-p instance pid] [--all]'
>+
>+DESCRIPTION
>+-----------
>+The command prints statistics about a running instance.
>+For a list of running instances see 'kvm list'.
>+
>+Commands:
>+ --memory, -m Display memory statistics
>diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
>index 3a06e10..85bbce7 100644
>--- a/tools/kvm/Makefile
>+++ b/tools/kvm/Makefile
>@@ -24,6 +24,7 @@ OBJS += builtin-balloon.o
> OBJS += builtin-debug.o
> OBJS += builtin-help.o
> OBJS += builtin-list.o
>+OBJS += builtin-stat.o
> OBJS += builtin-pause.o
> OBJS += builtin-resume.o
> OBJS += builtin-run.o
>diff --git a/tools/kvm/builtin-stat.c b/tools/kvm/builtin-stat.c
>new file mode 100644
>index 0000000..d9bc75d
>--- /dev/null
>+++ b/tools/kvm/builtin-stat.c
>@@ -0,0 +1,79 @@
>+#include <kvm/util.h>
>+#include <kvm/kvm-cmd.h>
>+#include <kvm/builtin-stat.h>
>+#include <kvm/kvm.h>
>+#include <kvm/parse-options.h>
>+
>+#include <stdio.h>
>+#include <string.h>
>+#include <signal.h>
>+
>+static bool mem;
>+static bool all;
>+static u64 instance_pid;
>+static const char *instance_name;
>+
>+static const char * const stat_usage[] = {
>+ "kvm stat [command] [--all] [-n name] [-p pid]",
>+ NULL
>+};
>+
>+static const struct option stat_options[] = {
>+ OPT_GROUP("Commands options:"),
>+ OPT_BOOLEAN('m', "memory", &mem, "Display memory statistics"),
>+ OPT_GROUP("Instance options:"),
>+ OPT_BOOLEAN('a', "all", &all, "All instances"),
>+ OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
>+ OPT_U64('p', "pid", &instance_pid, "Instance pid"),
>+ OPT_END()
>+};
>+
>+static void parse_stat_options(int argc, const char **argv)
>+{
>+ while (argc != 0) {
>+ argc = parse_options(argc, argv, stat_options, stat_usage,
>+ PARSE_OPT_STOP_AT_NON_OPTION);
>+ if (argc != 0)
>+ kvm_stat_help();
>+ }
>+}
>+
>+void kvm_stat_help(void)
>+{
>+ usage_with_options(stat_usage, stat_options);
>+}
>+
>+static int do_memstat(const char *name, int pid)
>+{
>+ printf("Sending memstat command to %s, output should be on the targets' terminal.\n", name);
>+ return kill(pid, SIGKVMMEMSTAT);
>+}
>+
>+int kvm_cmd_stat(int argc, const char **argv, const char *prefix)
>+{
>+ parse_stat_options(argc, argv);
>+
>+ if (!mem)
>+ usage_with_options(stat_usage, stat_options);
>+
>+ if (mem && all)
>+ return kvm__enumerate_instances(do_memstat);
>+
>+ if (instance_name == NULL &&
>+ instance_pid == 0)
>+ kvm_stat_help();
>+
>+ if (instance_name)
>+ instance_pid = kvm__get_pid_by_instance(instance_name);
>+
>+ if (instance_pid <= 0)
>+ die("Failed locating instance");
>+
>+ if (mem) {
>+ printf("Sending memstat command to designated instance, output should be on the targets' terminal.\n");
>+
>+ return kill(instance_pid, SIGKVMMEMSTAT);
>+ }
>+
>+ return 0;
>+}
>diff --git a/tools/kvm/command-list.txt b/tools/kvm/command-list.txt
>index 6a49d0a..f201d75 100644
>--- a/tools/kvm/command-list.txt
>+++ b/tools/kvm/command-list.txt
>@@ -10,3 +10,4 @@ kvm-list common
> kvm-debug common
> kvm-balloon common
> kvm-stop common
>+kvm-stat common
>diff --git a/tools/kvm/include/kvm/builtin-stat.h b/tools/kvm/include/kvm/builtin-stat.h
>new file mode 100644
>index 0000000..e3ce292
>--- /dev/null
>+++ b/tools/kvm/include/kvm/builtin-stat.h
>@@ -0,0 +1,7 @@
>+#ifndef KVM__STAT_H
>+#define KVM__STAT_H
>+
>+int kvm_cmd_stat(int argc, const char **argv, const char *prefix);
>+void kvm_stat_help(void);
>+
>+#endif
>diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
>index d4fe2a1..c2d815c 100644
>--- a/tools/kvm/include/kvm/kvm.h
>+++ b/tools/kvm/include/kvm/kvm.h
>@@ -22,6 +22,7 @@
> #define SIGKVMDELMEM (SIGRTMIN + 3)
> #define SIGKVMSTOP (SIGRTMIN + 4)
> #define SIGKVMRESUME (SIGRTMIN + 5)
>+#define SIGKVMMEMSTAT (SIGRTMIN + 6)
>
> struct kvm {
> int sys_fd; /* For system ioctls(), i.e. /dev/kvm */
>diff --git a/tools/kvm/kvm-cmd.c b/tools/kvm/kvm-cmd.c
>index 4e3ea22..8fc6d22 100644
>--- a/tools/kvm/kvm-cmd.c
>+++ b/tools/kvm/kvm-cmd.c
>@@ -12,6 +12,7 @@
> #include "kvm/builtin-list.h"
> #include "kvm/builtin-version.h"
> #include "kvm/builtin-stop.h"
>+#include "kvm/builtin-stat.h"
> #include "kvm/builtin-help.h"
> #include "kvm/kvm-cmd.h"
> #include "kvm/builtin-run.h"
>@@ -26,6 +27,7 @@ struct cmd_struct kvm_commands[] = {
> { "version", kvm_cmd_version, NULL, 0 },
> { "--version", kvm_cmd_version, NULL, 0 },
> { "stop", kvm_cmd_stop, kvm_stop_help, 0 },
>+ { "stat", kvm_cmd_stat, kvm_stat_help, 0 },
> { "help", kvm_cmd_help, NULL, 0 },
> { "run", kvm_cmd_run, kvm_run_help, 0 },
> { NULL, NULL, NULL, 0 },
>diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c
>index 983a114..c5853a5 100644
>--- a/tools/kvm/virtio/balloon.c
>+++ b/tools/kvm/virtio/balloon.c
>@@ -21,10 +21,11 @@
> #include <sys/stat.h>
> #include <pthread.h>
>
>-#define NUM_VIRT_QUEUES 2
>+#define NUM_VIRT_QUEUES 3
> #define VIRTIO_BLN_QUEUE_SIZE 128
> #define VIRTIO_BLN_INFLATE 0
> #define VIRTIO_BLN_DEFLATE 1
>+#define VIRTIO_BLN_STATS 2
>
> struct bln_dev {
> struct pci_device_header pci_hdr;
>@@ -41,6 +42,12 @@ struct bln_dev {
> struct virt_queue vqs[NUM_VIRT_QUEUES];
> struct thread_pool__job jobs[NUM_VIRT_QUEUES];
>
>+ struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
>+ struct virtio_balloon_stat *cur_stat;
>+ u32 cur_stat_head;
>+ u16 stat_count;
>+ int stat_waitfd;
>+
> struct virtio_balloon_config config;
> };
>
>@@ -127,7 +134,7 @@ static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, stru
> if (queue == &bdev->vqs[VIRTIO_BLN_INFLATE]) {
> madvise(guest_ptr, 1 << VIRTIO_BALLOON_PFN_SHIFT, MADV_DONTNEED);
> bdev->config.actual++;
>- } else {
>+ } else if (queue == &bdev->vqs[VIRTIO_BLN_DEFLATE]) {
> bdev->config.actual--;
> }
> }
>@@ -137,10 +144,46 @@ static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, stru
> return true;
> }
>
>+static bool virtio_bln_do_stat_request(struct kvm *kvm, struct bln_dev *bdev, struct virt_queue *queue)
>+{
>+ struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
>+ u16 out, in, head;
>+ struct virtio_balloon_stat *stat;
>+ u64 wait_val = 1;
>+
>+ head = virt_queue__get_iov(queue, iov, &out, &in, kvm);
>+ stat = iov[0].iov_base;
>+
>+ /* Initial empty stat buffer */
>+ if (bdev->cur_stat == NULL) {
>+ bdev->cur_stat = stat;
>+ bdev->cur_stat_head = head;
>+
>+ return true;
>+ }
>+
>+ memcpy(bdev->stats, stat, iov[0].iov_len);
>+
>+ bdev->stat_count = iov[0].iov_len / sizeof(struct virtio_balloon_stat);
>+ bdev->cur_stat = stat;
>+ bdev->cur_stat_head = head;
>+
>+ if (write(bdev->stat_waitfd, &wait_val, sizeof(wait_val)) <= 0)
>+ return -EFAULT;
>+
>+ return 1;
>+}
>+
> static void virtio_bln_do_io(struct kvm *kvm, void *param)
> {
> struct virt_queue *vq = param;
>
>+ if (vq == &bdev.vqs[VIRTIO_BLN_STATS]) {
>+ virtio_bln_do_stat_request(kvm, &bdev, vq);
>+ virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, kvm);
>+ return;
>+ }
>+
> while (virt_queue__available(vq)) {
> virtio_bln_do_io_request(kvm, &bdev, vq);
> virt_queue__trigger_irq(vq, bdev.pci_hdr.irq_line, &bdev.isr, kvm);
>@@ -218,15 +261,70 @@ static struct ioport_operations virtio_bln_io_ops = {
> .io_out = virtio_bln_pci_io_out,
> };
>
>+static int virtio_bln__collect_stats(void)
>+{
>+ u64 tmp;
>+
>+ virt_queue__set_used_elem(&bdev.vqs[VIRTIO_BLN_STATS], bdev.cur_stat_head,
>+ sizeof(struct virtio_balloon_stat));
>+ virt_queue__trigger_irq(&bdev.vqs[VIRTIO_BLN_STATS], bdev.pci_hdr.irq_line,
>+ &bdev.isr, kvm);
>+
>+ if (read(bdev.stat_waitfd, &tmp, sizeof(tmp)) <= 0)
>+ return -EFAULT;
>+
>+ return 0;
>+}
>+
>+static int virtio_bln__print_stats(void)
>+{
>+ u16 i;
>+
>+ if (virtio_bln__collect_stats() < 0)
>+ return -EFAULT;
>+
>+ printf("\n\n\t*** Guest memory statistics ***\n\n");
>+ for (i = 0; i < bdev.stat_count; i++) {
>+ switch (bdev.stats[i].tag) {
>+ case VIRTIO_BALLOON_S_SWAP_IN:
>+ printf("The amount of memory that has been swapped in (in bytes):");
>+ break;
>+ case VIRTIO_BALLOON_S_SWAP_OUT:
>+ printf("The amount of memory that has been swapped out to disk (in bytes):");
>+ break;
>+ case VIRTIO_BALLOON_S_MAJFLT:
>+ printf("The number of major page faults that have occurred:");
>+ break;
>+ case VIRTIO_BALLOON_S_MINFLT:
>+ printf("The number of minor page faults that have occurred:");
>+ break;
>+ case VIRTIO_BALLOON_S_MEMFREE:
>+ printf("The amount of memory not being used for any purpose (in bytes):");
>+ break;
>+ case VIRTIO_BALLOON_S_MEMTOT:
>+ printf("The total amount of memory available (in bytes):");
>+ break;
>+ }
>+ printf("%llu\n", bdev.stats[i].val);
>+ }
>+ printf("\n");
>+
>+ return 0;
>+}
>+
> static void handle_sigmem(int sig)
> {
> if (sig == SIGKVMADDMEM) {
> bdev.config.num_pages += 256;
>- } else {
>+ } else if (sig == SIGKVMDELMEM) {
> if (bdev.config.num_pages < 256)
> return;
>
> bdev.config.num_pages -= 256;
>+ } else if (sig == SIGKVMMEMSTAT) {
>+ virtio_bln__print_stats();
>+
>+ return;
> }
>
> /* Notify that the configuration space has changed */
>@@ -241,6 +339,7 @@ void virtio_bln__init(struct kvm *kvm)
>
> signal(SIGKVMADDMEM, handle_sigmem);
> signal(SIGKVMDELMEM, handle_sigmem);
>+ signal(SIGKVMMEMSTAT, handle_sigmem);
We also should add SIG_IGN in builtin-run for this signal.
walimis
>
> bdev_base_addr = ioport__register(IOPORT_EMPTY, &virtio_bln_io_ops, IOPORT_SIZE, &bdev);
>
>@@ -262,7 +361,8 @@ void virtio_bln__init(struct kvm *kvm)
>
> bdev.pci_hdr.irq_pin = pin;
> bdev.pci_hdr.irq_line = line;
>- bdev.host_features = 0;
>+ bdev.host_features = 1 << VIRTIO_BALLOON_F_STATS_VQ;
>+ bdev.stat_waitfd = eventfd(0, 0);
> memset(&bdev.config, 0, sizeof(struct virtio_balloon_config));
>
> pci__register(&bdev.pci_hdr, dev);
>--
>1.7.6
>
>--
>To unsubscribe from this list: send the line "unsubscribe kvm" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] kvm tools: Add 'kvm stat' command
2011-08-15 14:55 ` [PATCH] kvm tools: Add 'kvm stat' command Pekka Enberg
@ 2011-08-16 3:10 ` walimis
2011-08-16 5:48 ` Pekka Enberg
0 siblings, 1 reply; 6+ messages in thread
From: walimis @ 2011-08-16 3:10 UTC (permalink / raw)
To: Pekka Enberg
Cc: Sasha Levin, mingo, asias.hejun, prasadjoshi124, gorcunov, kvm
On Mon, Aug 15, 2011 at 05:55:39PM +0300, Pekka Enberg wrote:
>On Mon, 15 Aug 2011, Sasha Levin wrote:
>>+static int do_memstat(const char *name, int pid)
>>+{
>>+ printf("Sending memstat command to %s, output should be on the targets' terminal.\n", name);
>>+ return kill(pid, SIGKVMMEMSTAT);
>>+}
>
>I applied the patch but I think we should come up with a mechanism to
>transport the output back to the command. Doing the printout in the
netlink or unix socket?
walimis
>guest terminal isn't going to work in the long run.
>
> Pekka
>--
>To unsubscribe from this list: send the line "unsubscribe kvm" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] kvm tools: Add 'kvm stat' command
2011-08-16 3:10 ` walimis
@ 2011-08-16 5:48 ` Pekka Enberg
0 siblings, 0 replies; 6+ messages in thread
From: Pekka Enberg @ 2011-08-16 5:48 UTC (permalink / raw)
To: walimis; +Cc: Sasha Levin, mingo, asias.hejun, prasadjoshi124, gorcunov, kvm
On Tue, Aug 16, 2011 at 6:10 AM, walimis <walimisdev@gmail.com> wrote:
> On Mon, Aug 15, 2011 at 05:55:39PM +0300, Pekka Enberg wrote:
>>On Mon, 15 Aug 2011, Sasha Levin wrote:
>>>+static int do_memstat(const char *name, int pid)
>>>+{
>>>+ printf("Sending memstat command to %s, output should be on the targets' terminal.\n", name);
>>>+ return kill(pid, SIGKVMMEMSTAT);
>>>+}
>>
>>I applied the patch but I think we should come up with a mechanism to
>>transport the output back to the command. Doing the printout in the
> netlink or unix socket?
I don't know! Ingo? Someone? What are the benefits of netlink over sockets?
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2011-08-16 5:48 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-08-15 14:32 [PATCH] kvm tools: Add 'kvm stat' command Sasha Levin
2011-08-15 14:33 ` [PATCH] kvm tools: Use correct data type for pid Sasha Levin
2011-08-15 14:55 ` [PATCH] kvm tools: Add 'kvm stat' command Pekka Enberg
2011-08-16 3:10 ` walimis
2011-08-16 5:48 ` Pekka Enberg
2011-08-16 3:09 ` walimis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox