From: walimis <walimisdev@gmail.com>
To: Sasha Levin <levinsasha928@gmail.com>
Cc: penberg@kernel.org, mingo@elte.hu, asias.hejun@gmail.com,
prasadjoshi124@gmail.com, gorcunov@gmail.com,
kvm@vger.kernel.org
Subject: Re: [PATCH] kvm tools: Add 'kvm stat' command
Date: Tue, 16 Aug 2011 11:09:04 +0800 [thread overview]
Message-ID: <20110816030904.GA25779@walimis-desktop> (raw)
In-Reply-To: <1313418780-4171-1-git-send-email-levinsasha928@gmail.com>
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
prev parent reply other threads:[~2011-08-16 3:25 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
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 message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110816030904.GA25779@walimis-desktop \
--to=walimisdev@gmail.com \
--cc=asias.hejun@gmail.com \
--cc=gorcunov@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=levinsasha928@gmail.com \
--cc=mingo@elte.hu \
--cc=penberg@kernel.org \
--cc=prasadjoshi124@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox