]> git.proxmox.com Git - pve-qemu-kvm.git/blame - debian/patches/virtio-balloon-re-enable-balloon-stats.patch
bump version to 1.3-10
[pve-qemu-kvm.git] / debian / patches / virtio-balloon-re-enable-balloon-stats.patch
CommitLineData
904a90cc
DM
1From: Luiz Capitulino <lcapitulino@redhat.com>
2Subject: [Qemu-devel] [PATCH 2/3] virtio-balloon: re-enable balloon stats
3
4The statistics are now available through device properties via a
5polling mechanism. First a client has to enable polling, then it
6can query each stat individually.
7
8The following control properties are introduced:
9
10 o stats-polling-interval: a value greater than zero enables polling
11 in the specified interval (in seconds). When value equals zero,
12 polling is disabled. If polling is already enabled and a value
13 greater than zero is written, the polling interval time is changed
14
15 o stats-last-update: last stats update timestamp, in seconds.
16
17The following stats properties are introduced, all values are in bytes:
18
19 o stat-swap-in
20 o stat-swap-out
21 o stat-major-faults
22 o stat-minor-faults
23 o stat-free-memory
24 o stat-total-memory
25
26Please, refer to the documentation introduced by the next commit for
27more information and examples.
28
29Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
30---
31 hw/virtio-balloon.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++-
32 1 file changed, 165 insertions(+), 2 deletions(-)
33
34diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
35index 4398025..4bab2ae 100644
36--- a/hw/virtio-balloon.c
37+++ b/hw/virtio-balloon.c
38@@ -22,6 +22,8 @@
39 #include "virtio-balloon.h"
40 #include "kvm.h"
41 #include "exec-memory.h"
42+#include "qemu-timer.h"
43+#include "qapi/qapi-visit-core.h"
44
45 #if defined(__linux__)
46 #include <sys/mman.h>
47@@ -36,6 +38,9 @@ typedef struct VirtIOBalloon
48 uint64_t stats[VIRTIO_BALLOON_S_NR];
49 VirtQueueElement stats_vq_elem;
50 size_t stats_vq_offset;
51+ QEMUTimer *stats_timer;
52+ int64_t stats_last_update;
53+ int64_t stats_poll_interval;
54 DeviceState *qdev;
55 } VirtIOBalloon;
56
57@@ -53,6 +58,16 @@ static void balloon_page(void *addr, int deflate)
58 #endif
59 }
60
61+static const char *balloon_stat_names[] = {
62+ [VIRTIO_BALLOON_S_SWAP_IN] = "stat-swap-in",
63+ [VIRTIO_BALLOON_S_SWAP_OUT] = "stat-swap-out",
64+ [VIRTIO_BALLOON_S_MAJFLT] = "stat-major-faults",
65+ [VIRTIO_BALLOON_S_MINFLT] = "stat-minor-faults",
66+ [VIRTIO_BALLOON_S_MEMFREE] = "stat-free-memory",
67+ [VIRTIO_BALLOON_S_MEMTOT] = "stat-total-memory",
68+ [VIRTIO_BALLOON_S_NR] = NULL
69+};
70+
71 /*
72 * reset_stats - Mark all items in the stats array as unset
73 *
74@@ -67,6 +82,127 @@ static inline void reset_stats(VirtIOBalloon *dev)
75 for (i = 0; i < VIRTIO_BALLOON_S_NR; dev->stats[i++] = -1);
76 }
77
78+static bool balloon_stats_supported(const VirtIOBalloon *s)
79+{
80+ return s->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ);
81+}
82+
83+static bool balloon_stats_enabled(const VirtIOBalloon *s)
84+{
85+ return s->stats_poll_interval > 0;
86+}
87+
88+static void balloon_stats_destroy_timer(VirtIOBalloon *s)
89+{
90+ if (balloon_stats_enabled(s)) {
91+ qemu_del_timer(s->stats_timer);
92+ qemu_free_timer(s->stats_timer);
93+ s->stats_timer = NULL;
94+ s->stats_poll_interval = 0;
95+ }
96+}
97+
98+static void balloon_stats_change_timer(VirtIOBalloon *s, int secs)
99+{
100+ qemu_mod_timer(s->stats_timer, qemu_get_clock_ms(vm_clock) + secs * 1000);
101+}
102+
103+static void balloon_stats_poll_cb(void *opaque)
104+{
105+ VirtIOBalloon *s = opaque;
106+
107+ virtqueue_push(s->svq, &s->stats_vq_elem, s->stats_vq_offset);
108+ virtio_notify(&s->vdev, s->svq);
109+}
110+
111+static void balloon_stats_get_last_update(Object *obj, struct Visitor *v,
112+ void *opaque, const char *name,
113+ Error **errp)
114+{
115+ VirtIOBalloon *s = opaque;
116+ visit_type_int(v, &s->stats_last_update, name, errp);
117+}
118+
119+static void balloon_stats_get_stat(Object *obj, struct Visitor *v,
120+ void *opaque, const char *name, Error **errp)
121+{
122+ VirtIOBalloon *s = opaque;
123+ int i;
124+
125+ for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
126+ if (!strcmp(balloon_stat_names[i], name)) {
127+ break;
128+ }
129+ }
130+
131+ if (i == VIRTIO_BALLOON_S_NR) {
132+ error_setg(errp, "invalid stat name '%s'", name);
133+ return;
134+ }
135+
136+ if (s->stats[i] == -1) {
137+ error_setg(errp,
138+ "timer hasn't been enabled or guest doesn't support '%s'", name);
139+ return;
140+ }
141+
142+ visit_type_int(v, (int64_t *) &s->stats[i], name, errp);
143+}
144+
145+static void balloon_stats_get_poll_interval(Object *obj, struct Visitor *v,
146+ void *opaque, const char *name,
147+ Error **errp)
148+{
149+ VirtIOBalloon *s = opaque;
150+ visit_type_int(v, &s->stats_poll_interval, name, errp);
151+}
152+
153+static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v,
154+ void *opaque, const char *name,
155+ Error **errp)
156+{
157+ VirtIOBalloon *s = opaque;
158+ int64_t value;
159+
160+ if (!balloon_stats_supported(s)) {
161+ error_setg(errp, "guest doesn\'t support balloon stats");
162+ return;
163+ }
164+
165+ visit_type_int(v, &value, name, errp);
166+ if (error_is_set(errp)) {
167+ return;
168+ }
169+
170+ if (value < 0) {
171+ error_setg(errp, "timer value must be positive");
172+ return;
173+ }
174+
175+ if (value == s->stats_poll_interval) {
176+ return;
177+ }
178+
179+ if (value == 0) {
180+ /* timer=0 disables the timer */
181+ balloon_stats_destroy_timer(s);
182+ return;
183+ }
184+
185+ if (balloon_stats_enabled(s)) {
186+ /* timer interval change */
187+ s->stats_poll_interval = value;
188+ balloon_stats_change_timer(s, value);
189+ return;
190+ }
191+
192+ /* create a new timer */
193+ g_assert(s->stats_timer == NULL);
194+ s->stats_timer = qemu_new_timer_ms(vm_clock, balloon_stats_poll_cb, s);
195+ s->stats_poll_interval = value;
196+ balloon_stats_change_timer(s, 0);
197+}
198+
199 static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
200 {
201 VirtIOBalloon *s = to_virtio_balloon(vdev);
202@@ -107,9 +243,10 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
203 VirtQueueElement *elem = &s->stats_vq_elem;
204 VirtIOBalloonStat stat;
205 size_t offset = 0;
206+ qemu_timeval tv;
207
208 if (!virtqueue_pop(vq, elem)) {
209- return;
210+ goto out;
211 }
212
213 /* Initialize the stats to get rid of any stale values. This is only
214@@ -128,6 +265,18 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
215 s->stats[tag] = val;
216 }
217 s->stats_vq_offset = offset;
218+
219+ if (qemu_gettimeofday(&tv) < 0) {
220+ fprintf(stderr, "warning: %s: failed to get time of day\n", __func__);
221+ goto out;
222+ }
223+
224+ s->stats_last_update = tv.tv_sec;
225+
226+out:
227+ if (balloon_stats_enabled(s)) {
228+ balloon_stats_change_timer(s, s->stats_poll_interval);
229+ }
230 }
231
232 static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
233@@ -212,7 +361,7 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
234 VirtIODevice *virtio_balloon_init(DeviceState *dev)
235 {
236 VirtIOBalloon *s;
237- int ret;
238+ int i, ret;
239
240 s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
241 VIRTIO_ID_BALLOON,
242@@ -239,6 +388,19 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
243 register_savevm(dev, "virtio-balloon", -1, 1,
244 virtio_balloon_save, virtio_balloon_load, s);
245
246+ for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
247+ object_property_add(OBJECT(dev), balloon_stat_names[i], "int",
248+ balloon_stats_get_stat, NULL, NULL, s, NULL);
249+ }
250+
251+ object_property_add(OBJECT(dev), "stats-last-update", "int",
252+ balloon_stats_get_last_update, NULL, NULL, s, NULL);
253+
254+ object_property_add(OBJECT(dev), "stats-polling-interval", "int",
255+ balloon_stats_get_poll_interval,
256+ balloon_stats_set_poll_interval,
257+ NULL, s, NULL);
258+
259 return &s->vdev;
260 }
261
262@@ -246,6 +408,7 @@ void virtio_balloon_exit(VirtIODevice *vdev)
263 {
264 VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
265
266+ balloon_stats_destroy_timer(s);
267 qemu_remove_balloon_handler(s);
268 unregister_savevm(s->qdev, "virtio-balloon", s);
269 virtio_cleanup(vdev);
270--
2711.8.0
272
273
274
275