public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [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