aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/virtio/virtio_balloon.c
diff options
context:
space:
mode:
authorAmit Shah <amit.shah@redhat.com>2012-02-29 07:12:51 -0500
committerRusty Russell <rusty@rustcorp.com.au>2012-02-29 17:58:41 -0500
commit4eb05d562ea1ea34ff607aa877aefbf05b21c140 (patch)
treeac0d2afc54f208fce7c91a4f0c3704d95e5d9561 /drivers/virtio/virtio_balloon.c
parent5ffca28a4ac7abb8a254fafe6bd03b2f83667df7 (diff)
virtio: balloon: leak / fill balloon across S4
commit e562966dbaf49e7804097cd991e5d3a8934fc148 added support for S4 to the balloon driver. The freeze function did nothing to free the pages, since reclaiming the pages from the host to immediately give them back (if S4 was successful) seemed wasteful. Also, if S4 wasn't successful, the guest would have to re-fill the balloon. On restore, the pages were supposed to be marked freed and the free page counters were incremented to reflect the balloon was totally deflated. However, this wasn't done right. The pages that were earlier taken away from the guest during a balloon inflation operation were just shown as used pages after a successful restore from S4. Just a fancy way of leaking lots of memory. Instead of trying that, just leak the balloon on freeze and fill it on restore/thaw paths. This works properly now. The optimisation to not leak can be added later on after a bit of refactoring of the code. Signed-off-by: Amit Shah <amit.shah@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/virtio/virtio_balloon.c')
-rw-r--r--drivers/virtio/virtio_balloon.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 95aeedf198f8..958e5129c601 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -367,29 +367,45 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev)
367#ifdef CONFIG_PM 367#ifdef CONFIG_PM
368static int virtballoon_freeze(struct virtio_device *vdev) 368static int virtballoon_freeze(struct virtio_device *vdev)
369{ 369{
370 struct virtio_balloon *vb = vdev->priv;
371
370 /* 372 /*
371 * The kthread is already frozen by the PM core before this 373 * The kthread is already frozen by the PM core before this
372 * function is called. 374 * function is called.
373 */ 375 */
374 376
377 while (vb->num_pages)
378 leak_balloon(vb, vb->num_pages);
379 update_balloon_size(vb);
380
375 /* Ensure we don't get any more requests from the host */ 381 /* Ensure we don't get any more requests from the host */
376 vdev->config->reset(vdev); 382 vdev->config->reset(vdev);
377 vdev->config->del_vqs(vdev); 383 vdev->config->del_vqs(vdev);
378 return 0; 384 return 0;
379} 385}
380 386
387static int restore_common(struct virtio_device *vdev)
388{
389 struct virtio_balloon *vb = vdev->priv;
390 int ret;
391
392 ret = init_vqs(vdev->priv);
393 if (ret)
394 return ret;
395
396 fill_balloon(vb, towards_target(vb));
397 update_balloon_size(vb);
398 return 0;
399}
400
381static int virtballoon_thaw(struct virtio_device *vdev) 401static int virtballoon_thaw(struct virtio_device *vdev)
382{ 402{
383 return init_vqs(vdev->priv); 403 return restore_common(vdev);
384} 404}
385 405
386static int virtballoon_restore(struct virtio_device *vdev) 406static int virtballoon_restore(struct virtio_device *vdev)
387{ 407{
388 struct virtio_balloon *vb = vdev->priv; 408 struct virtio_balloon *vb = vdev->priv;
389 struct page *page, *page2;
390
391 /* We're starting from a clean slate */
392 vb->num_pages = 0;
393 409
394 /* 410 /*
395 * If a request wasn't complete at the time of freezing, this 411 * If a request wasn't complete at the time of freezing, this
@@ -397,12 +413,7 @@ static int virtballoon_restore(struct virtio_device *vdev)
397 */ 413 */
398 vb->need_stats_update = 0; 414 vb->need_stats_update = 0;
399 415
400 /* We don't have these pages in the balloon anymore! */ 416 return restore_common(vdev);
401 list_for_each_entry_safe(page, page2, &vb->pages, lru) {
402 list_del(&page->lru);
403 totalram_pages++;
404 }
405 return init_vqs(vdev->priv);
406} 417}
407#endif 418#endif
408 419