| From d33c240d47dab4fd15123d9e73fc8810cbc6ed6a Mon Sep 17 00:00:00 2001 |
| From: Tianyu Lan <Tianyu.Lan@microsoft.com> |
| Date: Sat, 25 Jan 2020 16:50:47 -0500 |
| Subject: hv_balloon: Balloon up according to request page number |
| |
| From: Tianyu Lan <Tianyu.Lan@microsoft.com> |
| |
| commit d33c240d47dab4fd15123d9e73fc8810cbc6ed6a upstream. |
| |
| Current code has assumption that balloon request memory size aligns |
| with 2MB. But actually Hyper-V doesn't guarantee such alignment. When |
| balloon driver receives non-aligned balloon request, it produces warning |
| and balloon up more memory than requested in order to keep 2MB alignment. |
| Remove the warning and balloon up memory according to actual requested |
| memory size. |
| |
| Fixes: f6712238471a ("hv: hv_balloon: avoid memory leak on alloc_error of 2MB memory block") |
| Cc: stable@vger.kernel.org |
| Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com> |
| Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com> |
| Reviewed-by: Michael Kelley <mikelley@microsoft.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/hv/hv_balloon.c | 13 +++---------- |
| 1 file changed, 3 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/hv/hv_balloon.c |
| +++ b/drivers/hv/hv_balloon.c |
| @@ -1215,10 +1215,7 @@ static unsigned int alloc_balloon_pages( |
| unsigned int i = 0; |
| struct page *pg; |
| |
| - if (num_pages < alloc_unit) |
| - return 0; |
| - |
| - for (i = 0; (i * alloc_unit) < num_pages; i++) { |
| + for (i = 0; i < num_pages / alloc_unit; i++) { |
| if (bl_resp->hdr.size + sizeof(union dm_mem_page_range) > |
| PAGE_SIZE) |
| return i * alloc_unit; |
| @@ -1252,7 +1249,7 @@ static unsigned int alloc_balloon_pages( |
| |
| } |
| |
| - return num_pages; |
| + return i * alloc_unit; |
| } |
| |
| static void balloon_up(struct work_struct *dummy) |
| @@ -1267,9 +1264,6 @@ static void balloon_up(struct work_struc |
| long avail_pages; |
| unsigned long floor; |
| |
| - /* The host balloons pages in 2M granularity. */ |
| - WARN_ON_ONCE(num_pages % PAGES_IN_2M != 0); |
| - |
| /* |
| * We will attempt 2M allocations. However, if we fail to |
| * allocate 2M chunks, we will go back to 4k allocations. |
| @@ -1279,14 +1273,13 @@ static void balloon_up(struct work_struc |
| avail_pages = si_mem_available(); |
| floor = compute_balloon_floor(); |
| |
| - /* Refuse to balloon below the floor, keep the 2M granularity. */ |
| + /* Refuse to balloon below the floor. */ |
| if (avail_pages < num_pages || avail_pages - num_pages < floor) { |
| pr_warn("Balloon request will be partially fulfilled. %s\n", |
| avail_pages < num_pages ? "Not enough memory." : |
| "Balloon floor reached."); |
| |
| num_pages = avail_pages > floor ? (avail_pages - floor) : 0; |
| - num_pages -= num_pages % PAGES_IN_2M; |
| } |
| |
| while (!done) { |