virtio: balloon: leak / fill balloon across S4

commit e562966dba 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>
This commit is contained in:
Amit Shah 2012-02-29 17:42:51 +05:30 committed by Rusty Russell
parent 5ffca28a4a
commit 4eb05d562e

View File

@ -367,29 +367,45 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int virtballoon_freeze(struct virtio_device *vdev) static int virtballoon_freeze(struct virtio_device *vdev)
{ {
struct virtio_balloon *vb = vdev->priv;
/* /*
* The kthread is already frozen by the PM core before this * The kthread is already frozen by the PM core before this
* function is called. * function is called.
*/ */
while (vb->num_pages)
leak_balloon(vb, vb->num_pages);
update_balloon_size(vb);
/* Ensure we don't get any more requests from the host */ /* Ensure we don't get any more requests from the host */
vdev->config->reset(vdev); vdev->config->reset(vdev);
vdev->config->del_vqs(vdev); vdev->config->del_vqs(vdev);
return 0; return 0;
} }
static int restore_common(struct virtio_device *vdev)
{
struct virtio_balloon *vb = vdev->priv;
int ret;
ret = init_vqs(vdev->priv);
if (ret)
return ret;
fill_balloon(vb, towards_target(vb));
update_balloon_size(vb);
return 0;
}
static int virtballoon_thaw(struct virtio_device *vdev) static int virtballoon_thaw(struct virtio_device *vdev)
{ {
return init_vqs(vdev->priv); return restore_common(vdev);
} }
static int virtballoon_restore(struct virtio_device *vdev) static int virtballoon_restore(struct virtio_device *vdev)
{ {
struct virtio_balloon *vb = vdev->priv; struct virtio_balloon *vb = vdev->priv;
struct page *page, *page2;
/* We're starting from a clean slate */
vb->num_pages = 0;
/* /*
* If a request wasn't complete at the time of freezing, this * If a request wasn't complete at the time of freezing, this
@ -397,12 +413,7 @@ static int virtballoon_restore(struct virtio_device *vdev)
*/ */
vb->need_stats_update = 0; vb->need_stats_update = 0;
/* We don't have these pages in the balloon anymore! */ return restore_common(vdev);
list_for_each_entry_safe(page, page2, &vb->pages, lru) {
list_del(&page->lru);
totalram_pages++;
}
return init_vqs(vdev->priv);
} }
#endif #endif