Support the new request for vm's free page information, response with a page bitmap. QEMU can make use of this free page bitmap to speed up the live migration process by skipping process the free pages. Signed-off-by: Liang Li <liang.z.li@xxxxxxxxx> Cc: Michael S. Tsirkin <mst@xxxxxxxxxx> Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx> Cc: Cornelia Huck <cornelia.huck@xxxxxxxxxx> Cc: Amit Shah <amit.shah@xxxxxxxxxx> --- drivers/virtio/virtio_balloon.c | 64 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 5a30ca0..5237d50 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -46,8 +46,12 @@ static int oom_pages = OOM_VBALLOON_DEFAULT_PAGES; module_param(oom_pages, int, S_IRUSR | S_IWUSR); MODULE_PARM_DESC(oom_pages, "pages to free on OOM"); +extern void get_free_pages(unsigned long *free_page_bitmap, unsigned long len); +extern unsigned long get_max_pfn(void); + enum balloon_req_id { BALLOON_DROP_CACHE, + BALLOON_GET_FREE_PAGES, }; struct balloon_req_hdr { @@ -85,6 +89,9 @@ struct virtio_balloon { /* Used to record the processed pfn range */ unsigned long min_pfn, max_pfn, start_pfn, end_pfn; struct balloon_req_hdr req_hdr; + /* Free page bitmap and length to tell the host */ + unsigned long *free_pages; + unsigned long free_bmap_len; /* * The pages we've told the Host we're not using are enqueued * at vb_dev_info->pages list. @@ -370,6 +377,41 @@ static void update_balloon_stats(struct virtio_balloon *vb) pages_to_bytes(available)); } +static int reset_free_page_bmap(struct virtio_balloon *vb, + unsigned long *max_pfn) +{ + int err = 0; + unsigned long bitmap_bytes; + + *max_pfn = get_max_pfn(); + bitmap_bytes = ALIGN(*max_pfn, BITS_PER_LONG) / BITS_PER_BYTE; + + if (bitmap_bytes < vb->free_bmap_len) + memset(vb->free_pages, 0, bitmap_bytes); + else { + kfree(vb->free_pages); + vb->free_bmap_len = bitmap_bytes; + vb->free_pages = kzalloc(bitmap_bytes, GFP_KERNEL); + } + + if (!vb->free_pages) { + err = -ENOMEM; + vb->free_bmap_len = 0; + } + + return err; +} + +static void update_free_pages_stats(struct virtio_balloon *vb) +{ + unsigned long max_pfn; + + if (!reset_free_page_bmap(vb, &max_pfn)) + get_free_pages(vb->free_pages, max_pfn); + else + dev_err(&vb->vdev->dev, "%s failure: No memory!\n", __func__); +} + /* * While most virtqueues communicate guest-initiated requests to the hypervisor, * the stats queue operates in reverse. The driver initializes the virtqueue @@ -511,10 +553,11 @@ static void update_balloon_size_func(struct work_struct *work) static void misc_handle_rq(struct virtio_balloon *vb) { struct virtqueue *vq; - struct scatterlist sg_out; + struct scatterlist sg_out, sg[2]; unsigned int len; struct balloon_req_hdr *ptr_hdr; struct scatterlist sg_in; + struct balloon_bmap_hdr hdr; vq = vb->misc_vq; ptr_hdr = virtqueue_get_buf(vq, &len); @@ -532,6 +575,18 @@ static void misc_handle_rq(struct virtio_balloon *vb) sg_init_one(&sg_in, &vb->req_hdr, sizeof(vb->req_hdr)); virtqueue_add_inbuf(vq, &sg_in, 1, &vb->req_hdr, GFP_KERNEL); break; + case BALLOON_GET_FREE_PAGES: + update_free_pages_stats(vb); + sg_init_table(sg, 2); + + hdr.id = cpu_to_virtio32(vb->vdev, BALLOON_GET_FREE_PAGES); + hdr.page_shift = cpu_to_virtio32(vb->vdev, PAGE_SHIFT); + hdr.start_pfn = cpu_to_virtio64(vb->vdev, 0); + hdr.bmap_len = cpu_to_virtio64(vb->vdev, vb->free_bmap_len); + sg_set_buf(&sg[0], &hdr, sizeof(hdr)); + sg_set_buf(&sg[1], vb->free_pages, vb->free_bmap_len); + virtqueue_add_outbuf(vq, &sg[0], 2, vb, GFP_KERNEL); + break; default: break; } @@ -689,6 +744,12 @@ static int virtballoon_probe(struct virtio_device *vdev) err = -ENOMEM; goto out; } + vb->free_bmap_len = ALIGN(get_max_pfn(), BITS_PER_LONG) / BITS_PER_BYTE; + vb->free_pages = kzalloc(vb->free_bmap_len, GFP_KERNEL); + if (!vb->free_pages) { + err = -ENOMEM; + goto out; + } mutex_init(&vb->balloon_lock); init_waitqueue_head(&vb->acked); vb->vdev = vdev; @@ -750,6 +811,7 @@ static void virtballoon_remove(struct virtio_device *vdev) remove_common(vb); kfree(vb->page_bitmap); + kfree(vb->free_pages); kfree(vb); } -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html