123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /* Virtio balloon implementation, inspired by Dor Loar and Marcelo
- * Tosatti's implementations.
- *
- * Copyright 2008 Rusty Russell IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- //#define DEBUG
- #include <linux/virtio.h>
- #include <linux/virtio_balloon.h>
- #include <linux/swap.h>
- #include <linux/kthread.h>
- #include <linux/freezer.h>
- #include <linux/delay.h>
- struct virtio_balloon
- {
- struct virtio_device *vdev;
- struct virtqueue *inflate_vq, *deflate_vq;
- /* Where the ballooning thread waits for config to change. */
- wait_queue_head_t config_change;
- /* The thread servicing the balloon. */
- struct task_struct *thread;
- /* Waiting for host to ack the pages we released. */
- struct completion acked;
- /* Do we have to tell Host *before* we reuse pages? */
- bool tell_host_first;
- /* The pages we've told the Host we're not using. */
- unsigned int num_pages;
- struct list_head pages;
- /* The array of pfns we tell the Host about. */
- unsigned int num_pfns;
- u32 pfns[256];
- };
- static struct virtio_device_id id_table[] = {
- { VIRTIO_ID_BALLOON, VIRTIO_DEV_ANY_ID },
- { 0 },
- };
- static void balloon_ack(struct virtqueue *vq)
- {
- struct virtio_balloon *vb;
- unsigned int len;
- vb = vq->vq_ops->get_buf(vq, &len);
- if (vb)
- complete(&vb->acked);
- }
- static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
- {
- struct scatterlist sg;
- sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
- init_completion(&vb->acked);
- /* We should always be able to add one buffer to an empty queue. */
- if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) != 0)
- BUG();
- vq->vq_ops->kick(vq);
- /* When host has read buffer, this completes via balloon_ack */
- wait_for_completion(&vb->acked);
- }
- static void fill_balloon(struct virtio_balloon *vb, size_t num)
- {
- /* We can only do one array worth at a time. */
- num = min(num, ARRAY_SIZE(vb->pfns));
- for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
- struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY);
- if (!page) {
- if (printk_ratelimit())
- dev_printk(KERN_INFO, &vb->vdev->dev,
- "Out of puff! Can't get %zu pages\n",
- num);
- /* Sleep for at least 1/5 of a second before retry. */
- msleep(200);
- break;
- }
- vb->pfns[vb->num_pfns] = page_to_pfn(page);
- totalram_pages--;
- vb->num_pages++;
- list_add(&page->lru, &vb->pages);
- }
- /* Didn't get any? Oh well. */
- if (vb->num_pfns == 0)
- return;
- tell_host(vb, vb->inflate_vq);
- }
- static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
- {
- unsigned int i;
- for (i = 0; i < num; i++) {
- __free_page(pfn_to_page(pfns[i]));
- totalram_pages++;
- }
- }
- static void leak_balloon(struct virtio_balloon *vb, size_t num)
- {
- struct page *page;
- /* We can only do one array worth at a time. */
- num = min(num, ARRAY_SIZE(vb->pfns));
- for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
- page = list_first_entry(&vb->pages, struct page, lru);
- list_del(&page->lru);
- vb->pfns[vb->num_pfns] = page_to_pfn(page);
- vb->num_pages--;
- }
- if (vb->tell_host_first) {
- tell_host(vb, vb->deflate_vq);
- release_pages_by_pfn(vb->pfns, vb->num_pfns);
- } else {
- release_pages_by_pfn(vb->pfns, vb->num_pfns);
- tell_host(vb, vb->deflate_vq);
- }
- }
- static void virtballoon_changed(struct virtio_device *vdev)
- {
- struct virtio_balloon *vb = vdev->priv;
- wake_up(&vb->config_change);
- }
- static inline s64 towards_target(struct virtio_balloon *vb)
- {
- u32 v;
- vb->vdev->config->get(vb->vdev,
- offsetof(struct virtio_balloon_config, num_pages),
- &v, sizeof(v));
- return (s64)v - vb->num_pages;
- }
- static void update_balloon_size(struct virtio_balloon *vb)
- {
- __le32 actual = cpu_to_le32(vb->num_pages);
- vb->vdev->config->set(vb->vdev,
- offsetof(struct virtio_balloon_config, actual),
- &actual, sizeof(actual));
- }
- static int balloon(void *_vballoon)
- {
- struct virtio_balloon *vb = _vballoon;
- set_freezable();
- while (!kthread_should_stop()) {
- s64 diff;
- try_to_freeze();
- wait_event_interruptible(vb->config_change,
- (diff = towards_target(vb)) != 0
- || kthread_should_stop());
- if (diff > 0)
- fill_balloon(vb, diff);
- else if (diff < 0)
- leak_balloon(vb, -diff);
- update_balloon_size(vb);
- }
- return 0;
- }
- static int virtballoon_probe(struct virtio_device *vdev)
- {
- struct virtio_balloon *vb;
- int err;
- vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
- if (!vb) {
- err = -ENOMEM;
- goto out;
- }
- INIT_LIST_HEAD(&vb->pages);
- vb->num_pages = 0;
- init_waitqueue_head(&vb->config_change);
- vb->vdev = vdev;
- /* We expect two virtqueues. */
- vb->inflate_vq = vdev->config->find_vq(vdev, 0, balloon_ack);
- if (IS_ERR(vb->inflate_vq)) {
- err = PTR_ERR(vb->inflate_vq);
- goto out_free_vb;
- }
- vb->deflate_vq = vdev->config->find_vq(vdev, 1, balloon_ack);
- if (IS_ERR(vb->deflate_vq)) {
- err = PTR_ERR(vb->deflate_vq);
- goto out_del_inflate_vq;
- }
- vb->thread = kthread_run(balloon, vb, "vballoon");
- if (IS_ERR(vb->thread)) {
- err = PTR_ERR(vb->thread);
- goto out_del_deflate_vq;
- }
- vb->tell_host_first
- = virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
- return 0;
- out_del_deflate_vq:
- vdev->config->del_vq(vb->deflate_vq);
- out_del_inflate_vq:
- vdev->config->del_vq(vb->inflate_vq);
- out_free_vb:
- kfree(vb);
- out:
- return err;
- }
- static void virtballoon_remove(struct virtio_device *vdev)
- {
- struct virtio_balloon *vb = vdev->priv;
- kthread_stop(vb->thread);
- /* There might be pages left in the balloon: free them. */
- while (vb->num_pages)
- leak_balloon(vb, vb->num_pages);
- /* Now we reset the device so we can clean up the queues. */
- vdev->config->reset(vdev);
- vdev->config->del_vq(vb->deflate_vq);
- vdev->config->del_vq(vb->inflate_vq);
- kfree(vb);
- }
- static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST };
- static struct virtio_driver virtio_balloon = {
- .feature_table = features,
- .feature_table_size = ARRAY_SIZE(features),
- .driver.name = KBUILD_MODNAME,
- .driver.owner = THIS_MODULE,
- .id_table = id_table,
- .probe = virtballoon_probe,
- .remove = __devexit_p(virtballoon_remove),
- .config_changed = virtballoon_changed,
- };
- static int __init init(void)
- {
- return register_virtio_driver(&virtio_balloon);
- }
- static void __exit fini(void)
- {
- unregister_virtio_driver(&virtio_balloon);
- }
- module_init(init);
- module_exit(fini);
- MODULE_DEVICE_TABLE(virtio, id_table);
- MODULE_DESCRIPTION("Virtio balloon driver");
- MODULE_LICENSE("GPL");
|