diff options
| author | K. Y. Srinivasan <kys@microsoft.com> | 2013-03-15 15:25:41 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-15 15:11:50 -0400 |
| commit | c51af826cf062af3c49a99a05a33236d93c57e72 (patch) | |
| tree | f1f61f8e04b17a16820d61a311059cc6a6efaec6 /drivers/hv | |
| parent | 6571b2dab4eb6c7061160490db984dbc01e5626d (diff) | |
Drivers: hv: balloon: Execute hot-add code in a separate context
Execute the hot-add operation in a separate work context.
This allows us to decouple the pressure reporting activity from the
"hot-add" activity. Testing has shown that this makes the guest more
responsive to hot add requests.
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 | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 8dc406ccf10f..13fda3807bfb 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c | |||
| @@ -417,6 +417,11 @@ struct balloon_state { | |||
| 417 | struct work_struct wrk; | 417 | struct work_struct wrk; |
| 418 | }; | 418 | }; |
| 419 | 419 | ||
| 420 | struct hot_add_wrk { | ||
| 421 | union dm_mem_page_range ha_page_range; | ||
| 422 | struct work_struct wrk; | ||
| 423 | }; | ||
| 424 | |||
| 420 | static bool hot_add; | 425 | static bool hot_add; |
| 421 | static bool do_hot_add; | 426 | static bool do_hot_add; |
| 422 | /* | 427 | /* |
| @@ -469,6 +474,11 @@ struct hv_dynmem_device { | |||
| 469 | struct balloon_state balloon_wrk; | 474 | struct balloon_state balloon_wrk; |
| 470 | 475 | ||
| 471 | /* | 476 | /* |
| 477 | * State to execute the "hot-add" operation. | ||
| 478 | */ | ||
| 479 | struct hot_add_wrk ha_wrk; | ||
| 480 | |||
| 481 | /* | ||
| 472 | * This thread handles hot-add | 482 | * This thread handles hot-add |
| 473 | * requests from the host as well as notifying | 483 | * requests from the host as well as notifying |
| 474 | * the host with regards to memory pressure in | 484 | * the host with regards to memory pressure in |
| @@ -486,7 +496,7 @@ struct hv_dynmem_device { | |||
| 486 | 496 | ||
| 487 | static struct hv_dynmem_device dm_device; | 497 | static struct hv_dynmem_device dm_device; |
| 488 | 498 | ||
| 489 | static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg) | 499 | static void hot_add_req(struct work_struct *dummy) |
| 490 | { | 500 | { |
| 491 | 501 | ||
| 492 | struct dm_hot_add_response resp; | 502 | struct dm_hot_add_response resp; |
| @@ -509,8 +519,8 @@ static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg) | |||
| 509 | resp.page_count = 0; | 519 | resp.page_count = 0; |
| 510 | resp.result = 0; | 520 | resp.result = 0; |
| 511 | 521 | ||
| 512 | dm->state = DM_INITIALIZED; | 522 | dm_device.state = DM_INITIALIZED; |
| 513 | vmbus_sendpacket(dm->dev->channel, &resp, | 523 | vmbus_sendpacket(dm_device.dev->channel, &resp, |
| 514 | sizeof(struct dm_hot_add_response), | 524 | sizeof(struct dm_hot_add_response), |
| 515 | (unsigned long)NULL, | 525 | (unsigned long)NULL, |
| 516 | VM_PKT_DATA_INBAND, 0); | 526 | VM_PKT_DATA_INBAND, 0); |
| @@ -771,7 +781,6 @@ static int dm_thread_func(void *dm_dev) | |||
| 771 | { | 781 | { |
| 772 | struct hv_dynmem_device *dm = dm_dev; | 782 | struct hv_dynmem_device *dm = dm_dev; |
| 773 | int t; | 783 | int t; |
| 774 | unsigned long scan_start; | ||
| 775 | 784 | ||
| 776 | while (!kthread_should_stop()) { | 785 | while (!kthread_should_stop()) { |
| 777 | t = wait_for_completion_timeout(&dm_device.config_event, 1*HZ); | 786 | t = wait_for_completion_timeout(&dm_device.config_event, 1*HZ); |
| @@ -783,19 +792,6 @@ static int dm_thread_func(void *dm_dev) | |||
| 783 | if (t == 0) | 792 | if (t == 0) |
| 784 | post_status(dm); | 793 | post_status(dm); |
| 785 | 794 | ||
| 786 | scan_start = jiffies; | ||
| 787 | switch (dm->state) { | ||
| 788 | |||
| 789 | case DM_HOT_ADD: | ||
| 790 | hot_add_req(dm, (struct dm_hot_add *)recv_buffer); | ||
| 791 | break; | ||
| 792 | default: | ||
| 793 | break; | ||
| 794 | } | ||
| 795 | |||
| 796 | if (!time_in_range(jiffies, scan_start, scan_start + HZ)) | ||
| 797 | post_status(dm); | ||
| 798 | |||
| 799 | } | 795 | } |
| 800 | 796 | ||
| 801 | return 0; | 797 | return 0; |
| @@ -869,6 +865,8 @@ static void balloon_onchannelcallback(void *context) | |||
| 869 | struct dm_header *dm_hdr; | 865 | struct dm_header *dm_hdr; |
| 870 | struct hv_dynmem_device *dm = hv_get_drvdata(dev); | 866 | struct hv_dynmem_device *dm = hv_get_drvdata(dev); |
| 871 | struct dm_balloon *bal_msg; | 867 | struct dm_balloon *bal_msg; |
| 868 | struct dm_hot_add *ha_msg; | ||
| 869 | union dm_mem_page_range *ha_pg_range; | ||
| 872 | 870 | ||
| 873 | memset(recv_buffer, 0, sizeof(recv_buffer)); | 871 | memset(recv_buffer, 0, sizeof(recv_buffer)); |
| 874 | vmbus_recvpacket(dev->channel, recv_buffer, | 872 | vmbus_recvpacket(dev->channel, recv_buffer, |
| @@ -905,8 +903,13 @@ static void balloon_onchannelcallback(void *context) | |||
| 905 | break; | 903 | break; |
| 906 | 904 | ||
| 907 | case DM_MEM_HOT_ADD_REQUEST: | 905 | case DM_MEM_HOT_ADD_REQUEST: |
| 906 | if (dm->state == DM_HOT_ADD) | ||
| 907 | pr_warn("Currently hot-adding\n"); | ||
| 908 | dm->state = DM_HOT_ADD; | 908 | dm->state = DM_HOT_ADD; |
| 909 | complete(&dm->config_event); | 909 | ha_msg = (struct dm_hot_add *)recv_buffer; |
| 910 | ha_pg_range = &ha_msg->range; | ||
| 911 | dm_device.ha_wrk.ha_page_range = *ha_pg_range; | ||
| 912 | schedule_work(&dm_device.ha_wrk.wrk); | ||
| 910 | break; | 913 | break; |
| 911 | 914 | ||
| 912 | case DM_INFO_MESSAGE: | 915 | case DM_INFO_MESSAGE: |
| @@ -950,6 +953,7 @@ static int balloon_probe(struct hv_device *dev, | |||
| 950 | init_completion(&dm_device.host_event); | 953 | init_completion(&dm_device.host_event); |
| 951 | init_completion(&dm_device.config_event); | 954 | init_completion(&dm_device.config_event); |
| 952 | INIT_WORK(&dm_device.balloon_wrk.wrk, balloon_up); | 955 | INIT_WORK(&dm_device.balloon_wrk.wrk, balloon_up); |
| 956 | INIT_WORK(&dm_device.ha_wrk.wrk, hot_add_req); | ||
| 953 | 957 | ||
| 954 | dm_device.thread = | 958 | dm_device.thread = |
| 955 | kthread_run(dm_thread_func, &dm_device, "hv_balloon"); | 959 | kthread_run(dm_thread_func, &dm_device, "hv_balloon"); |
| @@ -1062,6 +1066,7 @@ static int balloon_remove(struct hv_device *dev) | |||
| 1062 | pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned); | 1066 | pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned); |
| 1063 | 1067 | ||
| 1064 | cancel_work_sync(&dm->balloon_wrk.wrk); | 1068 | cancel_work_sync(&dm->balloon_wrk.wrk); |
| 1069 | cancel_work_sync(&dm->ha_wrk.wrk); | ||
| 1065 | vmbus_close(dev->channel); | 1070 | vmbus_close(dev->channel); |
| 1066 | kthread_stop(dm->thread); | 1071 | kthread_stop(dm->thread); |
| 1067 | kfree(send_buffer); | 1072 | kfree(send_buffer); |
