diff options
Diffstat (limited to 'drivers/virtio/virtio_balloon.c')
-rw-r--r-- | drivers/virtio/virtio_balloon.c | 119 |
1 files changed, 107 insertions, 12 deletions
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 9dd588042880..bfec7c29486d 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -24,11 +24,12 @@ | |||
24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
25 | #include <linux/freezer.h> | 25 | #include <linux/freezer.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/slab.h> | ||
27 | 28 | ||
28 | struct virtio_balloon | 29 | struct virtio_balloon |
29 | { | 30 | { |
30 | struct virtio_device *vdev; | 31 | struct virtio_device *vdev; |
31 | struct virtqueue *inflate_vq, *deflate_vq; | 32 | struct virtqueue *inflate_vq, *deflate_vq, *stats_vq; |
32 | 33 | ||
33 | /* Where the ballooning thread waits for config to change. */ | 34 | /* Where the ballooning thread waits for config to change. */ |
34 | wait_queue_head_t config_change; | 35 | wait_queue_head_t config_change; |
@@ -49,6 +50,10 @@ struct virtio_balloon | |||
49 | /* The array of pfns we tell the Host about. */ | 50 | /* The array of pfns we tell the Host about. */ |
50 | unsigned int num_pfns; | 51 | unsigned int num_pfns; |
51 | u32 pfns[256]; | 52 | u32 pfns[256]; |
53 | |||
54 | /* Memory statistics */ | ||
55 | int need_stats_update; | ||
56 | struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; | ||
52 | }; | 57 | }; |
53 | 58 | ||
54 | static struct virtio_device_id id_table[] = { | 59 | static struct virtio_device_id id_table[] = { |
@@ -98,7 +103,8 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) | |||
98 | num = min(num, ARRAY_SIZE(vb->pfns)); | 103 | num = min(num, ARRAY_SIZE(vb->pfns)); |
99 | 104 | ||
100 | for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { | 105 | for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { |
101 | struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY); | 106 | struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | |
107 | __GFP_NOMEMALLOC | __GFP_NOWARN); | ||
102 | if (!page) { | 108 | if (!page) { |
103 | if (printk_ratelimit()) | 109 | if (printk_ratelimit()) |
104 | dev_printk(KERN_INFO, &vb->vdev->dev, | 110 | dev_printk(KERN_INFO, &vb->vdev->dev, |
@@ -154,6 +160,72 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) | |||
154 | } | 160 | } |
155 | } | 161 | } |
156 | 162 | ||
163 | static inline void update_stat(struct virtio_balloon *vb, int idx, | ||
164 | u16 tag, u64 val) | ||
165 | { | ||
166 | BUG_ON(idx >= VIRTIO_BALLOON_S_NR); | ||
167 | vb->stats[idx].tag = tag; | ||
168 | vb->stats[idx].val = val; | ||
169 | } | ||
170 | |||
171 | #define pages_to_bytes(x) ((u64)(x) << PAGE_SHIFT) | ||
172 | |||
173 | static void update_balloon_stats(struct virtio_balloon *vb) | ||
174 | { | ||
175 | unsigned long events[NR_VM_EVENT_ITEMS]; | ||
176 | struct sysinfo i; | ||
177 | int idx = 0; | ||
178 | |||
179 | all_vm_events(events); | ||
180 | si_meminfo(&i); | ||
181 | |||
182 | update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_IN, | ||
183 | pages_to_bytes(events[PSWPIN])); | ||
184 | update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_OUT, | ||
185 | pages_to_bytes(events[PSWPOUT])); | ||
186 | update_stat(vb, idx++, VIRTIO_BALLOON_S_MAJFLT, events[PGMAJFAULT]); | ||
187 | update_stat(vb, idx++, VIRTIO_BALLOON_S_MINFLT, events[PGFAULT]); | ||
188 | update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMFREE, | ||
189 | pages_to_bytes(i.freeram)); | ||
190 | update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMTOT, | ||
191 | pages_to_bytes(i.totalram)); | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * While most virtqueues communicate guest-initiated requests to the hypervisor, | ||
196 | * the stats queue operates in reverse. The driver initializes the virtqueue | ||
197 | * with a single buffer. From that point forward, all conversations consist of | ||
198 | * a hypervisor request (a call to this function) which directs us to refill | ||
199 | * the virtqueue with a fresh stats buffer. Since stats collection can sleep, | ||
200 | * we notify our kthread which does the actual work via stats_handle_request(). | ||
201 | */ | ||
202 | static void stats_request(struct virtqueue *vq) | ||
203 | { | ||
204 | struct virtio_balloon *vb; | ||
205 | unsigned int len; | ||
206 | |||
207 | vb = vq->vq_ops->get_buf(vq, &len); | ||
208 | if (!vb) | ||
209 | return; | ||
210 | vb->need_stats_update = 1; | ||
211 | wake_up(&vb->config_change); | ||
212 | } | ||
213 | |||
214 | static void stats_handle_request(struct virtio_balloon *vb) | ||
215 | { | ||
216 | struct virtqueue *vq; | ||
217 | struct scatterlist sg; | ||
218 | |||
219 | vb->need_stats_update = 0; | ||
220 | update_balloon_stats(vb); | ||
221 | |||
222 | vq = vb->stats_vq; | ||
223 | sg_init_one(&sg, vb->stats, sizeof(vb->stats)); | ||
224 | if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) < 0) | ||
225 | BUG(); | ||
226 | vq->vq_ops->kick(vq); | ||
227 | } | ||
228 | |||
157 | static void virtballoon_changed(struct virtio_device *vdev) | 229 | static void virtballoon_changed(struct virtio_device *vdev) |
158 | { | 230 | { |
159 | struct virtio_balloon *vb = vdev->priv; | 231 | struct virtio_balloon *vb = vdev->priv; |
@@ -190,8 +262,11 @@ static int balloon(void *_vballoon) | |||
190 | try_to_freeze(); | 262 | try_to_freeze(); |
191 | wait_event_interruptible(vb->config_change, | 263 | wait_event_interruptible(vb->config_change, |
192 | (diff = towards_target(vb)) != 0 | 264 | (diff = towards_target(vb)) != 0 |
265 | || vb->need_stats_update | ||
193 | || kthread_should_stop() | 266 | || kthread_should_stop() |
194 | || freezing(current)); | 267 | || freezing(current)); |
268 | if (vb->need_stats_update) | ||
269 | stats_handle_request(vb); | ||
195 | if (diff > 0) | 270 | if (diff > 0) |
196 | fill_balloon(vb, diff); | 271 | fill_balloon(vb, diff); |
197 | else if (diff < 0) | 272 | else if (diff < 0) |
@@ -204,10 +279,10 @@ static int balloon(void *_vballoon) | |||
204 | static int virtballoon_probe(struct virtio_device *vdev) | 279 | static int virtballoon_probe(struct virtio_device *vdev) |
205 | { | 280 | { |
206 | struct virtio_balloon *vb; | 281 | struct virtio_balloon *vb; |
207 | struct virtqueue *vqs[2]; | 282 | struct virtqueue *vqs[3]; |
208 | vq_callback_t *callbacks[] = { balloon_ack, balloon_ack }; | 283 | vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_request }; |
209 | const char *names[] = { "inflate", "deflate" }; | 284 | const char *names[] = { "inflate", "deflate", "stats" }; |
210 | int err; | 285 | int err, nvqs; |
211 | 286 | ||
212 | vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL); | 287 | vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL); |
213 | if (!vb) { | 288 | if (!vb) { |
@@ -219,14 +294,31 @@ static int virtballoon_probe(struct virtio_device *vdev) | |||
219 | vb->num_pages = 0; | 294 | vb->num_pages = 0; |
220 | init_waitqueue_head(&vb->config_change); | 295 | init_waitqueue_head(&vb->config_change); |
221 | vb->vdev = vdev; | 296 | vb->vdev = vdev; |
297 | vb->need_stats_update = 0; | ||
222 | 298 | ||
223 | /* We expect two virtqueues. */ | 299 | /* We expect two virtqueues: inflate and deflate, |
224 | err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); | 300 | * and optionally stat. */ |
301 | nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2; | ||
302 | err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names); | ||
225 | if (err) | 303 | if (err) |
226 | goto out_free_vb; | 304 | goto out_free_vb; |
227 | 305 | ||
228 | vb->inflate_vq = vqs[0]; | 306 | vb->inflate_vq = vqs[0]; |
229 | vb->deflate_vq = vqs[1]; | 307 | vb->deflate_vq = vqs[1]; |
308 | if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { | ||
309 | struct scatterlist sg; | ||
310 | vb->stats_vq = vqs[2]; | ||
311 | |||
312 | /* | ||
313 | * Prime this virtqueue with one buffer so the hypervisor can | ||
314 | * use it to signal us later. | ||
315 | */ | ||
316 | sg_init_one(&sg, vb->stats, sizeof vb->stats); | ||
317 | if (vb->stats_vq->vq_ops->add_buf(vb->stats_vq, | ||
318 | &sg, 1, 0, vb) < 0) | ||
319 | BUG(); | ||
320 | vb->stats_vq->vq_ops->kick(vb->stats_vq); | ||
321 | } | ||
230 | 322 | ||
231 | vb->thread = kthread_run(balloon, vb, "vballoon"); | 323 | vb->thread = kthread_run(balloon, vb, "vballoon"); |
232 | if (IS_ERR(vb->thread)) { | 324 | if (IS_ERR(vb->thread)) { |
@@ -264,9 +356,12 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev) | |||
264 | kfree(vb); | 356 | kfree(vb); |
265 | } | 357 | } |
266 | 358 | ||
267 | static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST }; | 359 | static unsigned int features[] = { |
360 | VIRTIO_BALLOON_F_MUST_TELL_HOST, | ||
361 | VIRTIO_BALLOON_F_STATS_VQ, | ||
362 | }; | ||
268 | 363 | ||
269 | static struct virtio_driver virtio_balloon = { | 364 | static struct virtio_driver virtio_balloon_driver = { |
270 | .feature_table = features, | 365 | .feature_table = features, |
271 | .feature_table_size = ARRAY_SIZE(features), | 366 | .feature_table_size = ARRAY_SIZE(features), |
272 | .driver.name = KBUILD_MODNAME, | 367 | .driver.name = KBUILD_MODNAME, |
@@ -279,12 +374,12 @@ static struct virtio_driver virtio_balloon = { | |||
279 | 374 | ||
280 | static int __init init(void) | 375 | static int __init init(void) |
281 | { | 376 | { |
282 | return register_virtio_driver(&virtio_balloon); | 377 | return register_virtio_driver(&virtio_balloon_driver); |
283 | } | 378 | } |
284 | 379 | ||
285 | static void __exit fini(void) | 380 | static void __exit fini(void) |
286 | { | 381 | { |
287 | unregister_virtio_driver(&virtio_balloon); | 382 | unregister_virtio_driver(&virtio_balloon_driver); |
288 | } | 383 | } |
289 | module_init(init); | 384 | module_init(init); |
290 | module_exit(fini); | 385 | module_exit(fini); |