]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/virtio-balloon-re-enable-balloon-stats.patch
c980b054c29eeda82b6a451f5029e0be27ff00c5
[pve-qemu-kvm.git] / debian / patches / virtio-balloon-re-enable-balloon-stats.patch
1 From: Luiz Capitulino <lcapitulino@redhat.com>
2 Subject: [Qemu-devel] [PATCH 2/3] virtio-balloon: re-enable balloon stats
3
4 The statistics are now available through device properties via a
5 polling mechanism. First a client has to enable polling, then it
6 can query each stat individually.
7
8 The 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
17 The 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
26 Please, refer to the documentation introduced by the next commit for
27 more information and examples.
28
29 Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
30 ---
31 hw/virtio-balloon.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++-
32 1 file changed, 165 insertions(+), 2 deletions(-)
33
34 diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
35 index 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 --
271 1.8.0
272
273
274
275