diff options
| author | K. Y. Srinivasan <kys@microsoft.com> | 2013-03-15 15:25:40 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-15 15:11:50 -0400 |
| commit | 6571b2dab4eb6c7061160490db984dbc01e5626d (patch) | |
| tree | eababb8049da4fcb1d41e7e458228e41638ee333 /drivers/hv | |
| parent | 7a64b864a0989302b5f6869f8b65b630b10bd9db (diff) | |
Drivers: hv: balloon: Execute balloon inflation in a separate context
Execute the balloon inflation operation in a separate work context.
This allows us to decouple the pressure reporting activity from the
ballooning activity. Testing has shown that this decoupling makes the
guest more reponsive.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv')
| -rw-r--r-- | drivers/hv/hv_balloon.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 7fb72dd05ba2..8dc406ccf10f 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c | |||
| @@ -412,6 +412,11 @@ struct dm_info_msg { | |||
| 412 | * End protocol definitions. | 412 | * End protocol definitions. |
| 413 | */ | 413 | */ |
| 414 | 414 | ||
| 415 | struct balloon_state { | ||
| 416 | __u32 num_pages; | ||
| 417 | struct work_struct wrk; | ||
| 418 | }; | ||
| 419 | |||
| 415 | static bool hot_add; | 420 | static bool hot_add; |
| 416 | static bool do_hot_add; | 421 | static bool do_hot_add; |
| 417 | /* | 422 | /* |
| @@ -459,7 +464,12 @@ struct hv_dynmem_device { | |||
| 459 | unsigned int num_pages_ballooned; | 464 | unsigned int num_pages_ballooned; |
| 460 | 465 | ||
| 461 | /* | 466 | /* |
| 462 | * This thread handles both balloon/hot-add | 467 | * State to manage the ballooning (up) operation. |
| 468 | */ | ||
| 469 | struct balloon_state balloon_wrk; | ||
| 470 | |||
| 471 | /* | ||
| 472 | * This thread handles hot-add | ||
| 463 | * requests from the host as well as notifying | 473 | * requests from the host as well as notifying |
| 464 | * the host with regards to memory pressure in | 474 | * the host with regards to memory pressure in |
| 465 | * the guest. | 475 | * the guest. |
| @@ -657,9 +667,9 @@ static int alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages, | |||
| 657 | 667 | ||
| 658 | 668 | ||
| 659 | 669 | ||
| 660 | static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req) | 670 | static void balloon_up(struct work_struct *dummy) |
| 661 | { | 671 | { |
| 662 | int num_pages = req->num_pages; | 672 | int num_pages = dm_device.balloon_wrk.num_pages; |
| 663 | int num_ballooned = 0; | 673 | int num_ballooned = 0; |
| 664 | struct dm_balloon_response *bl_resp; | 674 | struct dm_balloon_response *bl_resp; |
| 665 | int alloc_unit; | 675 | int alloc_unit; |
| @@ -684,14 +694,14 @@ static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req) | |||
| 684 | 694 | ||
| 685 | 695 | ||
| 686 | num_pages -= num_ballooned; | 696 | num_pages -= num_ballooned; |
| 687 | num_ballooned = alloc_balloon_pages(dm, num_pages, | 697 | num_ballooned = alloc_balloon_pages(&dm_device, num_pages, |
| 688 | bl_resp, alloc_unit, | 698 | bl_resp, alloc_unit, |
| 689 | &alloc_error); | 699 | &alloc_error); |
| 690 | 700 | ||
| 691 | if ((alloc_error) || (num_ballooned == num_pages)) { | 701 | if ((alloc_error) || (num_ballooned == num_pages)) { |
| 692 | bl_resp->more_pages = 0; | 702 | bl_resp->more_pages = 0; |
| 693 | done = true; | 703 | done = true; |
| 694 | dm->state = DM_INITIALIZED; | 704 | dm_device.state = DM_INITIALIZED; |
| 695 | } | 705 | } |
| 696 | 706 | ||
| 697 | /* | 707 | /* |
| @@ -719,7 +729,7 @@ static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req) | |||
| 719 | pr_info("Balloon response failed\n"); | 729 | pr_info("Balloon response failed\n"); |
| 720 | 730 | ||
| 721 | for (i = 0; i < bl_resp->range_count; i++) | 731 | for (i = 0; i < bl_resp->range_count; i++) |
| 722 | free_balloon_pages(dm, | 732 | free_balloon_pages(&dm_device, |
| 723 | &bl_resp->range_array[i]); | 733 | &bl_resp->range_array[i]); |
| 724 | 734 | ||
| 725 | done = true; | 735 | done = true; |
| @@ -775,9 +785,6 @@ static int dm_thread_func(void *dm_dev) | |||
| 775 | 785 | ||
| 776 | scan_start = jiffies; | 786 | scan_start = jiffies; |
| 777 | switch (dm->state) { | 787 | switch (dm->state) { |
| 778 | case DM_BALLOON_UP: | ||
| 779 | balloon_up(dm, (struct dm_balloon *)recv_buffer); | ||
| 780 | break; | ||
| 781 | 788 | ||
| 782 | case DM_HOT_ADD: | 789 | case DM_HOT_ADD: |
| 783 | hot_add_req(dm, (struct dm_hot_add *)recv_buffer); | 790 | hot_add_req(dm, (struct dm_hot_add *)recv_buffer); |
| @@ -861,6 +868,7 @@ static void balloon_onchannelcallback(void *context) | |||
| 861 | struct dm_message *dm_msg; | 868 | struct dm_message *dm_msg; |
| 862 | struct dm_header *dm_hdr; | 869 | struct dm_header *dm_hdr; |
| 863 | struct hv_dynmem_device *dm = hv_get_drvdata(dev); | 870 | struct hv_dynmem_device *dm = hv_get_drvdata(dev); |
| 871 | struct dm_balloon *bal_msg; | ||
| 864 | 872 | ||
| 865 | memset(recv_buffer, 0, sizeof(recv_buffer)); | 873 | memset(recv_buffer, 0, sizeof(recv_buffer)); |
| 866 | vmbus_recvpacket(dev->channel, recv_buffer, | 874 | vmbus_recvpacket(dev->channel, recv_buffer, |
| @@ -882,8 +890,12 @@ static void balloon_onchannelcallback(void *context) | |||
| 882 | break; | 890 | break; |
| 883 | 891 | ||
| 884 | case DM_BALLOON_REQUEST: | 892 | case DM_BALLOON_REQUEST: |
| 893 | if (dm->state == DM_BALLOON_UP) | ||
| 894 | pr_warn("Currently ballooning\n"); | ||
| 895 | bal_msg = (struct dm_balloon *)recv_buffer; | ||
| 885 | dm->state = DM_BALLOON_UP; | 896 | dm->state = DM_BALLOON_UP; |
| 886 | complete(&dm->config_event); | 897 | dm_device.balloon_wrk.num_pages = bal_msg->num_pages; |
| 898 | schedule_work(&dm_device.balloon_wrk.wrk); | ||
| 887 | break; | 899 | break; |
| 888 | 900 | ||
| 889 | case DM_UNBALLOON_REQUEST: | 901 | case DM_UNBALLOON_REQUEST: |
| @@ -937,6 +949,7 @@ static int balloon_probe(struct hv_device *dev, | |||
| 937 | dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7; | 949 | dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7; |
| 938 | init_completion(&dm_device.host_event); | 950 | init_completion(&dm_device.host_event); |
| 939 | init_completion(&dm_device.config_event); | 951 | init_completion(&dm_device.config_event); |
| 952 | INIT_WORK(&dm_device.balloon_wrk.wrk, balloon_up); | ||
| 940 | 953 | ||
| 941 | dm_device.thread = | 954 | dm_device.thread = |
| 942 | kthread_run(dm_thread_func, &dm_device, "hv_balloon"); | 955 | kthread_run(dm_thread_func, &dm_device, "hv_balloon"); |
| @@ -1048,6 +1061,7 @@ static int balloon_remove(struct hv_device *dev) | |||
| 1048 | if (dm->num_pages_ballooned != 0) | 1061 | if (dm->num_pages_ballooned != 0) |
| 1049 | pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned); | 1062 | pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned); |
| 1050 | 1063 | ||
| 1064 | cancel_work_sync(&dm->balloon_wrk.wrk); | ||
| 1051 | vmbus_close(dev->channel); | 1065 | vmbus_close(dev->channel); |
| 1052 | kthread_stop(dm->thread); | 1066 | kthread_stop(dm->thread); |
| 1053 | kfree(send_buffer); | 1067 | kfree(send_buffer); |
