From: Luiz Capitulino <lcapitulino@redhat.com>
To: qemu-devel@nongnu.org
Cc: aliguori@us.ibm.com, mdroth@linux.vnet.ibm.com,
dietmar@proxmox.com, agl@us.ibm.com
Subject: [Qemu-devel] [PATCH 2/3] balloon: re-enable balloon stats
Date: Fri, 14 Dec 2012 13:49:41 -0200 [thread overview]
Message-ID: <1355500182-12743-3-git-send-email-lcapitulino@redhat.com> (raw)
In-Reply-To: <1355500182-12743-1-git-send-email-lcapitulino@redhat.com>
The statistics are now available through device properties via a
polling mechanism. First a client has to enable polling, then it
can query each stat individually.
The following control properties are introduced:
o stats-polling-interval: a value greater than zero enables polling
in the specified interval (in seconds). When value equals zero,
polling is disabled. If polling is already enabled and a value
greater than zero is written, the polling interval time is changed
o stats-last-update: last stats update timestamp, in seconds.
The following stats properties are introduced, all values are in bytes:
o stat-swap-in
o stat-swap-out
o stat-major-faults
o stat-minor-faults
o stat-free-memory
o stat-total-memory
Please, refer to the documentation introduced by the next commit for
more information and examples.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
hw/virtio-balloon.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 176 insertions(+), 2 deletions(-)
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 4398025..47e35b1 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -22,6 +22,8 @@
#include "virtio-balloon.h"
#include "kvm.h"
#include "exec-memory.h"
+#include "qemu-timer.h"
+#include "qapi/qapi-visit-core.h"
#if defined(__linux__)
#include <sys/mman.h>
@@ -36,6 +38,9 @@ typedef struct VirtIOBalloon
uint64_t stats[VIRTIO_BALLOON_S_NR];
VirtQueueElement stats_vq_elem;
size_t stats_vq_offset;
+ QEMUTimer *stats_timer;
+ int64_t stats_last_update;
+ int64_t stats_poll_interval;
DeviceState *qdev;
} VirtIOBalloon;
@@ -53,6 +58,16 @@ static void balloon_page(void *addr, int deflate)
#endif
}
+static const char *balloon_stat_names[] = {
+ [VIRTIO_BALLOON_S_SWAP_IN] = "stat-swap-in",
+ [VIRTIO_BALLOON_S_SWAP_OUT] = "stat-swap-out",
+ [VIRTIO_BALLOON_S_MAJFLT] = "stat-major-faults",
+ [VIRTIO_BALLOON_S_MINFLT] = "stat-minor-faults",
+ [VIRTIO_BALLOON_S_MEMFREE] = "stat-free-memory",
+ [VIRTIO_BALLOON_S_MEMTOT] = "stat-total-memory",
+ [VIRTIO_BALLOON_S_NR] = NULL
+};
+
/*
* reset_stats - Mark all items in the stats array as unset
*
@@ -67,6 +82,138 @@ static inline void reset_stats(VirtIOBalloon *dev)
for (i = 0; i < VIRTIO_BALLOON_S_NR; dev->stats[i++] = -1);
}
+static bool balloon_stats_supported(const VirtIOBalloon *s)
+{
+ return s->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ);
+}
+
+static bool balloon_stats_enabled(const VirtIOBalloon *s)
+{
+ return s->stats_poll_interval > 0;
+}
+
+static void balloon_stats_destroy_timer(VirtIOBalloon *s)
+{
+ if (balloon_stats_enabled(s)) {
+ qemu_del_timer(s->stats_timer);
+ qemu_free_timer(s->stats_timer);
+ s->stats_timer = NULL;
+ s->stats_poll_interval = 0;
+ }
+}
+
+static void balloon_stats_change_timer(VirtIOBalloon *s, int secs)
+{
+ qemu_mod_timer(s->stats_timer, qemu_get_clock_ms(vm_clock) + secs * 1000);
+}
+
+static void balloon_stats_poll_cb(void *opaque)
+{
+ VirtIOBalloon *s = opaque;
+
+ if (!balloon_stats_supported(s)) {
+ /* re-schedule */
+ balloon_stats_change_timer(s, s->stats_poll_interval);
+ return;
+ }
+
+ virtqueue_push(s->svq, &s->stats_vq_elem, s->stats_vq_offset);
+ virtio_notify(&s->vdev, s->svq);
+}
+
+static void balloon_stats_get_last_update(Object *obj, struct Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ VirtIOBalloon *s = opaque;
+ visit_type_int(v, &s->stats_last_update, name, errp);
+}
+
+static void balloon_stats_get_stat(Object *obj, struct Visitor *v,
+ void *opaque, const char *name, Error **errp)
+{
+ VirtIOBalloon *s = opaque;
+ int i;
+
+ for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
+ if (!strcmp(balloon_stat_names[i], name)) {
+ break;
+ }
+ }
+
+ if (i == VIRTIO_BALLOON_S_NR) {
+ error_setg(errp, "invalid stat name '%s'", name);
+ return;
+ }
+
+ if (s->stats[i] == -1) {
+ /*
+ * Possible reasons for this error:
+ *
+ * - The timer hasn't been enabled
+ * - The guest hasn't loaded its balloon driver
+ * - The guest's balloon driver doesn't support memory stats
+ * - The guest's balloon driver doesn't support this stat
+ * - The guest's balloon driver didn't send this stat for
+ * whatever reason
+ */
+ error_setg(errp,
+ "guest didn't update '%s' (does the guest support it?)", name);
+ return;
+ }
+
+ visit_type_int(v, (int64_t *) &s->stats[i], name, errp);
+}
+
+static void balloon_stats_get_poll_interval(Object *obj, struct Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ VirtIOBalloon *s = opaque;
+ visit_type_int(v, &s->stats_poll_interval, name, errp);
+}
+
+static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ VirtIOBalloon *s = opaque;
+ int64_t value;
+
+ visit_type_int(v, &value, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+
+ if (value < 0) {
+ error_setg(errp, "timer value must be positive");
+ return;
+ }
+
+ if (value == s->stats_poll_interval) {
+ return;
+ }
+
+ if (value == 0) {
+ /* timer=0 disables the timer */
+ balloon_stats_destroy_timer(s);
+ return;
+ }
+
+ if (balloon_stats_enabled(s)) {
+ /* timer interval change */
+ s->stats_poll_interval = value;
+ balloon_stats_change_timer(s, value);
+ return;
+ }
+
+ /* create a new timer */
+ g_assert(s->stats_timer == NULL);
+ s->stats_timer = qemu_new_timer_ms(vm_clock, balloon_stats_poll_cb, s);
+ s->stats_poll_interval = value;
+ balloon_stats_change_timer(s, 0);
+}
+
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOBalloon *s = to_virtio_balloon(vdev);
@@ -107,9 +254,10 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
VirtQueueElement *elem = &s->stats_vq_elem;
VirtIOBalloonStat stat;
size_t offset = 0;
+ qemu_timeval tv;
if (!virtqueue_pop(vq, elem)) {
- return;
+ goto out;
}
/* Initialize the stats to get rid of any stale values. This is only
@@ -128,6 +276,18 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
s->stats[tag] = val;
}
s->stats_vq_offset = offset;
+
+ if (qemu_gettimeofday(&tv) < 0) {
+ fprintf(stderr, "warning: %s: failed to get time of day\n", __func__);
+ goto out;
+ }
+
+ s->stats_last_update = tv.tv_sec;
+
+out:
+ if (balloon_stats_enabled(s)) {
+ balloon_stats_change_timer(s, s->stats_poll_interval);
+ }
}
static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
@@ -212,7 +372,7 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
VirtIODevice *virtio_balloon_init(DeviceState *dev)
{
VirtIOBalloon *s;
- int ret;
+ int i, ret;
s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
VIRTIO_ID_BALLOON,
@@ -239,6 +399,19 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
register_savevm(dev, "virtio-balloon", -1, 1,
virtio_balloon_save, virtio_balloon_load, s);
+ for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
+ object_property_add(OBJECT(dev), balloon_stat_names[i], "int",
+ balloon_stats_get_stat, NULL, NULL, s, NULL);
+ }
+
+ object_property_add(OBJECT(dev), "stats-last-update", "int",
+ balloon_stats_get_last_update, NULL, NULL, s, NULL);
+
+ object_property_add(OBJECT(dev), "stats-polling-interval", "int",
+ balloon_stats_get_poll_interval,
+ balloon_stats_set_poll_interval,
+ NULL, s, NULL);
+
return &s->vdev;
}
@@ -246,6 +419,7 @@ void virtio_balloon_exit(VirtIODevice *vdev)
{
VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
+ balloon_stats_destroy_timer(s);
qemu_remove_balloon_handler(s);
unregister_savevm(s->qdev, "virtio-balloon", s);
virtio_cleanup(vdev);
--
1.8.0
next prev parent reply other threads:[~2012-12-14 15:49 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-14 15:49 [Qemu-devel] [PATCH v2 0/3] re-enable balloon stats Luiz Capitulino
2012-12-14 15:49 ` [Qemu-devel] [PATCH 1/3] balloon: drop old stats code & API Luiz Capitulino
2012-12-17 10:13 ` Dietmar Maurer
2012-12-17 11:57 ` Luiz Capitulino
2012-12-17 12:23 ` Dietmar Maurer
2012-12-17 12:33 ` Luiz Capitulino
2012-12-17 12:36 ` Dietmar Maurer
2012-12-17 12:39 ` Luiz Capitulino
2012-12-18 21:34 ` Eric Blake
2012-12-19 5:18 ` Dietmar Maurer
2012-12-19 11:27 ` Luiz Capitulino
2012-12-20 18:36 ` Eric Blake
2012-12-14 15:49 ` Luiz Capitulino [this message]
2012-12-14 15:49 ` [Qemu-devel] [PATCH 3/3] docs: document virtio-balloon stats Luiz Capitulino
2012-12-15 7:19 ` [Qemu-devel] [PATCH v2 0/3] re-enable balloon stats Dietmar Maurer
2012-12-17 11:52 ` Luiz Capitulino
2012-12-17 12:17 ` Dietmar Maurer
2012-12-17 12:22 ` Luiz Capitulino
2012-12-17 12:26 ` Dietmar Maurer
2012-12-17 12:38 ` Luiz Capitulino
2012-12-17 12:39 ` Dietmar Maurer
-- strict thread matches above, loose matches on Subject: below --
2013-01-18 19:29 [Qemu-devel] [PATCH v3 " Luiz Capitulino
2013-01-18 19:29 ` [Qemu-devel] [PATCH 2/3] balloon: " Luiz Capitulino
2013-01-18 20:04 ` Eric Blake
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=1355500182-12743-3-git-send-email-lcapitulino@redhat.com \
--to=lcapitulino@redhat.com \
--cc=agl@us.ibm.com \
--cc=aliguori@us.ibm.com \
--cc=dietmar@proxmox.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
/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;
as well as URLs for NNTP newsgroup(s).