]>
Commit | Line | Data |
---|---|---|
96f4a076 DM |
1 | From lcapitulino@redhat.com Fri Dec 14 16:49:58 2012 |
2 | Received: from rt.proxmox.com (192.168.2.18) by lisa.maurer-it.com | |
3 | (192.168.2.121) with Microsoft SMTP Server id 14.2.328.9; Fri, 14 Dec 2012 | |
4 | 16:49:58 +0100 | |
5 | Received: from proxmox.maurer-it.com (proxmox.maurer-it.com | |
6 | [192.168.2.110]) by rt.proxmox.com (Postfix) with ESMTP id 9D849206E234 for | |
7 | <dietmar@proxmox.com>; Fri, 14 Dec 2012 16:49:58 +0100 (CET) | |
8 | Received: from proxmox.maurer-it.com (localhost.localdomain [127.0.0.1]) by | |
9 | proxmox.maurer-it.com (Proxmox) with ESMTP id 6DC3526A0912 for | |
10 | <dietmar@proxmox.com>; Fri, 14 Dec 2012 16:49:58 +0100 (CET) | |
11 | Received-SPF: pass (redhat.com: Sender is authorized to use | |
12 | 'lcapitulino@redhat.com' in 'mfrom' identity (mechanism | |
13 | 'include:spf-1.redhat.com' matched)) receiver=proxmox.maurer-it.com; | |
14 | identity=mailfrom; envelope-from="lcapitulino@redhat.com"; | |
15 | helo=mx1.redhat.com; client-ip=209.132.183.28 | |
16 | Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by | |
17 | proxmox.maurer-it.com (Proxmox) with ESMTP id 7B90426A090F for | |
18 | <dietmar@proxmox.com>; Fri, 14 Dec 2012 16:49:55 +0100 (CET) | |
19 | Received: from int-mx12.intmail.prod.int.phx2.redhat.com | |
20 | (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com | |
21 | (8.14.4/8.14.4) with ESMTP id qBEFnl3Y014706 (version=TLSv1/SSLv3 | |
22 | cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 14 Dec 2012 10:49:47 | |
23 | -0500 | |
24 | Received: from localhost (ovpn-113-80.phx2.redhat.com [10.3.113.80]) by | |
25 | int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id | |
26 | qBEFnkfm012128; Fri, 14 Dec 2012 10:49:46 -0500 | |
904a90cc | 27 | From: Luiz Capitulino <lcapitulino@redhat.com> |
96f4a076 DM |
28 | To: <qemu-devel@nongnu.org> |
29 | CC: <eblake@redhat.com>, <aliguori@us.ibm.com>, <agl@us.ibm.com>, | |
30 | <mdroth@linux.vnet.ibm.com>, <dietmar@proxmox.com> | |
31 | Subject: [PATCH 2/3] balloon: re-enable balloon stats | |
32 | Date: Fri, 14 Dec 2012 13:49:41 -0200 | |
33 | Message-ID: <1355500182-12743-3-git-send-email-lcapitulino@redhat.com> | |
34 | In-Reply-To: <1355500182-12743-1-git-send-email-lcapitulino@redhat.com> | |
35 | References: <1355500182-12743-1-git-send-email-lcapitulino@redhat.com> | |
36 | X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 | |
37 | X-Proxmox-CTCH-Refid: | |
38 | str=0001.0A0C0203.50CB4AA5.008C:SCFSTAT2484459,ss=1,re=-4.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0 | |
39 | x-proxmoxspam-level: Spam detection results: 0 AWL | |
40 | -0.200 From: address is in the auto white-list RCVD_IN_DNSWL_HI | |
41 | -5 Sender listed at http://www.dnswl.org/, high trust SPF_HELO_PASS | |
42 | -0.001 SPF: HELO matches SPF record SPF_PASS -0.001 SPF: | |
43 | sender matches SPF record T_RP_MATCHES_RCVD -0.01 Envelope sender | |
44 | domain matches handover relay domain | |
45 | Content-Type: text/plain | |
46 | Return-Path: lcapitulino@redhat.com | |
47 | X-MS-Exchange-Organization-AuthSource: lisa.maurer-it.com | |
48 | X-MS-Exchange-Organization-AuthAs: Anonymous | |
49 | MIME-Version: 1.0 | |
50 | Content-Transfer-Encoding: 8bit | |
904a90cc DM |
51 | |
52 | The statistics are now available through device properties via a | |
53 | polling mechanism. First a client has to enable polling, then it | |
54 | can query each stat individually. | |
55 | ||
56 | The following control properties are introduced: | |
57 | ||
58 | o stats-polling-interval: a value greater than zero enables polling | |
59 | in the specified interval (in seconds). When value equals zero, | |
60 | polling is disabled. If polling is already enabled and a value | |
61 | greater than zero is written, the polling interval time is changed | |
62 | ||
63 | o stats-last-update: last stats update timestamp, in seconds. | |
64 | ||
65 | The following stats properties are introduced, all values are in bytes: | |
66 | ||
67 | o stat-swap-in | |
68 | o stat-swap-out | |
69 | o stat-major-faults | |
70 | o stat-minor-faults | |
71 | o stat-free-memory | |
72 | o stat-total-memory | |
73 | ||
74 | Please, refer to the documentation introduced by the next commit for | |
75 | more information and examples. | |
76 | ||
77 | Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com> | |
78 | --- | |
96f4a076 DM |
79 | hw/virtio-balloon.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++- |
80 | 1 file changed, 176 insertions(+), 2 deletions(-) | |
904a90cc DM |
81 | |
82 | diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c | |
96f4a076 | 83 | index 4398025..47e35b1 100644 |
904a90cc DM |
84 | --- a/hw/virtio-balloon.c |
85 | +++ b/hw/virtio-balloon.c | |
86 | @@ -22,6 +22,8 @@ | |
87 | #include "virtio-balloon.h" | |
88 | #include "kvm.h" | |
89 | #include "exec-memory.h" | |
90 | +#include "qemu-timer.h" | |
91 | +#include "qapi/qapi-visit-core.h" | |
92 | ||
93 | #if defined(__linux__) | |
94 | #include <sys/mman.h> | |
95 | @@ -36,6 +38,9 @@ typedef struct VirtIOBalloon | |
96 | uint64_t stats[VIRTIO_BALLOON_S_NR]; | |
97 | VirtQueueElement stats_vq_elem; | |
98 | size_t stats_vq_offset; | |
99 | + QEMUTimer *stats_timer; | |
100 | + int64_t stats_last_update; | |
101 | + int64_t stats_poll_interval; | |
102 | DeviceState *qdev; | |
103 | } VirtIOBalloon; | |
104 | ||
105 | @@ -53,6 +58,16 @@ static void balloon_page(void *addr, int deflate) | |
106 | #endif | |
107 | } | |
108 | ||
109 | +static const char *balloon_stat_names[] = { | |
110 | + [VIRTIO_BALLOON_S_SWAP_IN] = "stat-swap-in", | |
111 | + [VIRTIO_BALLOON_S_SWAP_OUT] = "stat-swap-out", | |
112 | + [VIRTIO_BALLOON_S_MAJFLT] = "stat-major-faults", | |
113 | + [VIRTIO_BALLOON_S_MINFLT] = "stat-minor-faults", | |
114 | + [VIRTIO_BALLOON_S_MEMFREE] = "stat-free-memory", | |
115 | + [VIRTIO_BALLOON_S_MEMTOT] = "stat-total-memory", | |
116 | + [VIRTIO_BALLOON_S_NR] = NULL | |
117 | +}; | |
118 | + | |
119 | /* | |
120 | * reset_stats - Mark all items in the stats array as unset | |
121 | * | |
96f4a076 | 122 | @@ -67,6 +82,138 @@ static inline void reset_stats(VirtIOBalloon *dev) |
904a90cc DM |
123 | for (i = 0; i < VIRTIO_BALLOON_S_NR; dev->stats[i++] = -1); |
124 | } | |
125 | ||
126 | +static bool balloon_stats_supported(const VirtIOBalloon *s) | |
127 | +{ | |
128 | + return s->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ); | |
129 | +} | |
130 | + | |
131 | +static bool balloon_stats_enabled(const VirtIOBalloon *s) | |
132 | +{ | |
133 | + return s->stats_poll_interval > 0; | |
134 | +} | |
135 | + | |
136 | +static void balloon_stats_destroy_timer(VirtIOBalloon *s) | |
137 | +{ | |
138 | + if (balloon_stats_enabled(s)) { | |
139 | + qemu_del_timer(s->stats_timer); | |
140 | + qemu_free_timer(s->stats_timer); | |
141 | + s->stats_timer = NULL; | |
142 | + s->stats_poll_interval = 0; | |
143 | + } | |
144 | +} | |
145 | + | |
146 | +static void balloon_stats_change_timer(VirtIOBalloon *s, int secs) | |
147 | +{ | |
148 | + qemu_mod_timer(s->stats_timer, qemu_get_clock_ms(vm_clock) + secs * 1000); | |
149 | +} | |
150 | + | |
151 | +static void balloon_stats_poll_cb(void *opaque) | |
152 | +{ | |
153 | + VirtIOBalloon *s = opaque; | |
154 | + | |
96f4a076 DM |
155 | + if (!balloon_stats_supported(s)) { |
156 | + /* re-schedule */ | |
157 | + balloon_stats_change_timer(s, s->stats_poll_interval); | |
158 | + return; | |
159 | + } | |
160 | + | |
904a90cc DM |
161 | + virtqueue_push(s->svq, &s->stats_vq_elem, s->stats_vq_offset); |
162 | + virtio_notify(&s->vdev, s->svq); | |
163 | +} | |
164 | + | |
165 | +static void balloon_stats_get_last_update(Object *obj, struct Visitor *v, | |
166 | + void *opaque, const char *name, | |
167 | + Error **errp) | |
168 | +{ | |
169 | + VirtIOBalloon *s = opaque; | |
170 | + visit_type_int(v, &s->stats_last_update, name, errp); | |
171 | +} | |
172 | + | |
173 | +static void balloon_stats_get_stat(Object *obj, struct Visitor *v, | |
174 | + void *opaque, const char *name, Error **errp) | |
175 | +{ | |
176 | + VirtIOBalloon *s = opaque; | |
177 | + int i; | |
178 | + | |
179 | + for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) { | |
180 | + if (!strcmp(balloon_stat_names[i], name)) { | |
181 | + break; | |
182 | + } | |
183 | + } | |
184 | + | |
185 | + if (i == VIRTIO_BALLOON_S_NR) { | |
186 | + error_setg(errp, "invalid stat name '%s'", name); | |
187 | + return; | |
188 | + } | |
189 | + | |
190 | + if (s->stats[i] == -1) { | |
96f4a076 DM |
191 | + /* |
192 | + * Possible reasons for this error: | |
193 | + * | |
194 | + * - The timer hasn't been enabled | |
195 | + * - The guest hasn't loaded its balloon driver | |
196 | + * - The guest's balloon driver doesn't support memory stats | |
197 | + * - The guest's balloon driver doesn't support this stat | |
198 | + * - The guest's balloon driver didn't send this stat for | |
199 | + * whatever reason | |
200 | + */ | |
904a90cc | 201 | + error_setg(errp, |
96f4a076 | 202 | + "guest didn't update '%s' (does the guest support it?)", name); |
904a90cc DM |
203 | + return; |
204 | + } | |
205 | + | |
206 | + visit_type_int(v, (int64_t *) &s->stats[i], name, errp); | |
207 | +} | |
208 | + | |
209 | +static void balloon_stats_get_poll_interval(Object *obj, struct Visitor *v, | |
210 | + void *opaque, const char *name, | |
211 | + Error **errp) | |
212 | +{ | |
213 | + VirtIOBalloon *s = opaque; | |
214 | + visit_type_int(v, &s->stats_poll_interval, name, errp); | |
215 | +} | |
216 | + | |
217 | +static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v, | |
218 | + void *opaque, const char *name, | |
219 | + Error **errp) | |
220 | +{ | |
221 | + VirtIOBalloon *s = opaque; | |
222 | + int64_t value; | |
223 | + | |
904a90cc DM |
224 | + visit_type_int(v, &value, name, errp); |
225 | + if (error_is_set(errp)) { | |
226 | + return; | |
227 | + } | |
228 | + | |
229 | + if (value < 0) { | |
230 | + error_setg(errp, "timer value must be positive"); | |
231 | + return; | |
232 | + } | |
233 | + | |
234 | + if (value == s->stats_poll_interval) { | |
235 | + return; | |
236 | + } | |
237 | + | |
238 | + if (value == 0) { | |
239 | + /* timer=0 disables the timer */ | |
240 | + balloon_stats_destroy_timer(s); | |
241 | + return; | |
242 | + } | |
243 | + | |
244 | + if (balloon_stats_enabled(s)) { | |
245 | + /* timer interval change */ | |
246 | + s->stats_poll_interval = value; | |
247 | + balloon_stats_change_timer(s, value); | |
248 | + return; | |
249 | + } | |
250 | + | |
251 | + /* create a new timer */ | |
252 | + g_assert(s->stats_timer == NULL); | |
253 | + s->stats_timer = qemu_new_timer_ms(vm_clock, balloon_stats_poll_cb, s); | |
254 | + s->stats_poll_interval = value; | |
255 | + balloon_stats_change_timer(s, 0); | |
256 | +} | |
257 | + | |
258 | static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) | |
259 | { | |
260 | VirtIOBalloon *s = to_virtio_balloon(vdev); | |
96f4a076 | 261 | @@ -107,9 +254,10 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) |
904a90cc DM |
262 | VirtQueueElement *elem = &s->stats_vq_elem; |
263 | VirtIOBalloonStat stat; | |
264 | size_t offset = 0; | |
265 | + qemu_timeval tv; | |
266 | ||
267 | if (!virtqueue_pop(vq, elem)) { | |
268 | - return; | |
269 | + goto out; | |
270 | } | |
271 | ||
272 | /* Initialize the stats to get rid of any stale values. This is only | |
96f4a076 | 273 | @@ -128,6 +276,18 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) |
904a90cc DM |
274 | s->stats[tag] = val; |
275 | } | |
276 | s->stats_vq_offset = offset; | |
277 | + | |
278 | + if (qemu_gettimeofday(&tv) < 0) { | |
279 | + fprintf(stderr, "warning: %s: failed to get time of day\n", __func__); | |
280 | + goto out; | |
281 | + } | |
282 | + | |
283 | + s->stats_last_update = tv.tv_sec; | |
284 | + | |
285 | +out: | |
286 | + if (balloon_stats_enabled(s)) { | |
287 | + balloon_stats_change_timer(s, s->stats_poll_interval); | |
288 | + } | |
289 | } | |
290 | ||
291 | static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) | |
96f4a076 | 292 | @@ -212,7 +372,7 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id) |
904a90cc DM |
293 | VirtIODevice *virtio_balloon_init(DeviceState *dev) |
294 | { | |
295 | VirtIOBalloon *s; | |
296 | - int ret; | |
297 | + int i, ret; | |
298 | ||
299 | s = (VirtIOBalloon *)virtio_common_init("virtio-balloon", | |
300 | VIRTIO_ID_BALLOON, | |
96f4a076 | 301 | @@ -239,6 +399,19 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev) |
904a90cc DM |
302 | register_savevm(dev, "virtio-balloon", -1, 1, |
303 | virtio_balloon_save, virtio_balloon_load, s); | |
304 | ||
305 | + for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) { | |
306 | + object_property_add(OBJECT(dev), balloon_stat_names[i], "int", | |
307 | + balloon_stats_get_stat, NULL, NULL, s, NULL); | |
308 | + } | |
309 | + | |
310 | + object_property_add(OBJECT(dev), "stats-last-update", "int", | |
311 | + balloon_stats_get_last_update, NULL, NULL, s, NULL); | |
312 | + | |
313 | + object_property_add(OBJECT(dev), "stats-polling-interval", "int", | |
314 | + balloon_stats_get_poll_interval, | |
315 | + balloon_stats_set_poll_interval, | |
316 | + NULL, s, NULL); | |
317 | + | |
318 | return &s->vdev; | |
319 | } | |
320 | ||
96f4a076 | 321 | @@ -246,6 +419,7 @@ void virtio_balloon_exit(VirtIODevice *vdev) |
904a90cc DM |
322 | { |
323 | VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev); | |
324 | ||
325 | + balloon_stats_destroy_timer(s); | |
326 | qemu_remove_balloon_handler(s); | |
327 | unregister_savevm(s->qdev, "virtio-balloon", s); | |
328 | virtio_cleanup(vdev); | |
329 | -- | |
330 | 1.8.0 | |
331 | ||
332 | ||
333 |