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); |