linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: lantianyu1986@gmail.com
To: kys@microsoft.com, haiyangz@microsoft.com,
	sthemmin@microsoft.com, sashal@kernel.org,
	michael.h.kelley@microsoft.com, david@redhat.com
Cc: Tianyu Lan <Tianyu.Lan@microsoft.com>,
	linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org,
	vkuznets@redhat.com, eric.devolder@oracle.com
Subject: [RFC PATCH V2 10/10] x86/Hyper-V: Workaround Hyper-V unballoon msg bug
Date: Tue,  7 Jan 2020 21:09:50 +0800	[thread overview]
Message-ID: <20200107130950.2983-11-Tianyu.Lan@microsoft.com> (raw)
In-Reply-To: <20200107130950.2983-1-Tianyu.Lan@microsoft.com>

From: Tianyu Lan <Tianyu.Lan@microsoft.com>

Hyper-V sends unballoon msg instead of mem hot add msg in some
case. System doesn't receive balloon msg before unballoon msg
and this will cause balloon_down() to produce warning of
free non-exist memory. Workaround the issue via treating
unballoon msg as mem hot-add msg when mem hot-add is
enabled.

Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
---
 drivers/hv/hv_balloon.c | 116 +++++++++++++++++++++++++++---------------------
 1 file changed, 66 insertions(+), 50 deletions(-)

diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 5aaae62955bf..7f3e7ab22d5d 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -486,6 +486,9 @@ union dm_msg_info {
 	struct {
 		__u32 num_pages;
 	} balloon_state;
+	struct {
+		struct dm_unballoon_request *request;
+	} unballoon_state;
 	struct {
 		union dm_mem_page_range ha_page_range;
 		union dm_mem_page_range ha_region_range;
@@ -1155,6 +1158,21 @@ static unsigned long process_hot_add(unsigned long pg_start,
 		return pfn_cnt;
 	}
 
+	if ((rg_start == 0) && (!dm_device.host_specified_ha_region)) {
+		/*
+		 * The host has not specified the hot-add region.
+		 * Based on the hot-add page range being specified,
+		 * compute a hot-add region that can cover the pages
+		 * that need to be hot-added while ensuring the alignment
+		 * and size requirements of Linux as it relates to hot-add.
+		 */
+		rg_size = (pfn_cnt / HA_CHUNK) * HA_CHUNK;
+		if (pfn_cnt % HA_CHUNK)
+			rg_size += HA_CHUNK;
+
+		rg_start = (pg_start / HA_CHUNK) * HA_CHUNK;
+	}
+
 	if (!dm_device.host_specified_ha_region) {
 		covered = pfn_covered(pg_start, pfn_cnt);
 		if (covered < 0)
@@ -1488,28 +1506,6 @@ static void hot_add_req(union dm_msg_info *msg_info)
 	rg_start = msg_info->hot_add.ha_region_range.finfo.start_page;
 	rg_sz = msg_info->hot_add.ha_region_range.finfo.page_cnt;
 
-	if ((rg_start == 0) && (!dm->host_specified_ha_region)) {
-		unsigned long region_size;
-		unsigned long region_start;
-
-		/*
-		 * The host has not specified the hot-add region.
-		 * Based on the hot-add page range being specified,
-		 * compute a hot-add region that can cover the pages
-		 * that need to be hot-added while ensuring the alignment
-		 * and size requirements of Linux as it relates to hot-add.
-		 */
-		region_start = pg_start;
-		region_size = (pfn_cnt / HA_CHUNK) * HA_CHUNK;
-		if (pfn_cnt % HA_CHUNK)
-			region_size += HA_CHUNK;
-
-		region_start = (pg_start / HA_CHUNK) * HA_CHUNK;
-
-		rg_start = region_start;
-		rg_sz = region_size;
-	}
-
 	if (do_hot_add)
 		resp.page_count = process_hot_add(pg_start, pfn_cnt,
 						rg_start, rg_sz);
@@ -1823,41 +1819,37 @@ static void balloon_up(union dm_msg_info *msg_info)
 
 }
 
-static void dm_msg_work(struct work_struct *dummy)
-{
-	union dm_msg_info *msg_info = &dm_device.dm_wrk.dm_msg;
-
-	switch (dm_device.dm_wrk.msg_type) {
-	case DM_BALLOON_REQUEST:
-		balloon_up(msg_info);
-		break;
-	case DM_MEM_HOT_ADD_REQUEST:
-		hot_add_req(msg_info);
-		break;
-	case DM_MEM_HOT_REMOVE_REQUEST:
-		hot_remove_req(msg_info);
-		break;
-	default:
-		return;
-	}
-}
-
-static void balloon_down(struct hv_dynmem_device *dm,
-			struct dm_unballoon_request *req)
+static void balloon_down(union dm_msg_info *msg_info)
 {
+	struct dm_unballoon_request *req = msg_info->unballoon_state.request;
 	union dm_mem_page_range *range_array = req->range_array;
+	struct hv_dynmem_device *dm = &dm_device;
+	unsigned int prev_pages_ballooned = dm->num_pages_ballooned;
 	int range_count = req->range_count;
 	struct dm_unballoon_response resp;
 	int i;
-	unsigned int prev_pages_ballooned = dm->num_pages_ballooned;
 
 	for (i = 0; i < range_count; i++) {
-		free_balloon_pages(dm, &range_array[i]);
-		complete(&dm_device.config_event);
+		/*
+		 * Hyper-V has a bug that send unballoon msg instead
+		 * of hot add msg even if there is no balloon msg sent
+		 * before. Treat all unballoon msgs as hot add msgs
+		 * if hot add capability is enabled.
+		 */
+		if (IS_ENABLED(CONFIG_MEMORY_HOTPLUG) && do_hot_add) {
+			dm->host_specified_ha_region = false;
+			dm->num_pages_added +=
+				process_hot_add(range_array[i].finfo.start_page,
+				range_array[i].finfo.page_cnt, 0, 0);
+		} else {
+			free_balloon_pages(dm, &range_array[i]);
+			complete(&dm_device.config_event);
+		}
 	}
 
-	pr_debug("Freed %u ballooned pages.\n",
-		prev_pages_ballooned - dm->num_pages_ballooned);
+	if (!do_hot_add)
+		pr_debug("Freed %u ballooned pages.\n",
+			prev_pages_ballooned - dm->num_pages_ballooned);
 
 	if (req->more_pages == 1)
 		return;
@@ -1875,6 +1867,28 @@ static void balloon_down(struct hv_dynmem_device *dm,
 	dm->state = DM_INITIALIZED;
 }
 
+static void dm_msg_work(struct work_struct *dummy)
+{
+	union dm_msg_info *msg_info = &dm_device.dm_wrk.dm_msg;
+
+	switch (dm_device.dm_wrk.msg_type) {
+	case DM_BALLOON_REQUEST:
+		balloon_up(msg_info);
+		break;
+	case DM_UNBALLOON_REQUEST:
+		balloon_down(msg_info);
+		break;
+	case DM_MEM_HOT_ADD_REQUEST:
+		hot_add_req(msg_info);
+		break;
+	case DM_MEM_HOT_REMOVE_REQUEST:
+		hot_remove_req(msg_info);
+		break;
+	default:
+		return;
+	}
+}
+
 static void balloon_onchannelcallback(void *context);
 
 static int dm_thread_func(void *dm_dev)
@@ -2024,8 +2038,10 @@ static void balloon_onchannelcallback(void *context)
 			}
 
 			dm->state = DM_BALLOON_DOWN;
-			balloon_down(dm,
-				 (struct dm_unballoon_request *)recv_buffer);
+			dm_wrk->msg_type = DM_UNBALLOON_REQUEST;
+			msg_info->unballoon_state.request
+				= (struct dm_unballoon_request *)recv_buffer;
+			schedule_work(&dm_wrk->wrk);
 			break;
 
 		case DM_MEM_HOT_ADD_REQUEST:
-- 
2.14.5


      parent reply	other threads:[~2020-01-07 13:10 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-07 13:09 [RFC PATCH V2 00/10] x86/Hyper-V: Add Dynamic memory hot-remove function lantianyu1986
2020-01-07 13:09 ` [RFC PATCH V2 1/10] mm/resource: Move child to new resource when release mem region lantianyu1986
2020-01-20 18:34   ` Michael Kelley
2020-01-20 19:20   ` Michael Kelley
2020-01-07 13:09 ` [RFC PATCH V2 2/10] mm: expose is_mem_section_removable() symbol lantianyu1986
2020-01-07 13:36   ` Michal Hocko
2020-01-10 13:41     ` David Hildenbrand
2020-01-13 14:49       ` [EXTERNAL] " Tianyu Lan
2020-01-13 15:01         ` David Hildenbrand
2020-01-14  9:50         ` Michal Hocko
2020-01-17 16:35           ` Tianyu Lan
2020-01-20 14:14             ` Michal Hocko
2020-01-07 13:09 ` [RFC PATCH V2 3/10] x86/Hyper-V/Balloon: Replace hot-add and balloon up works with a common work lantianyu1986
2020-01-20 19:12   ` Michael Kelley
2020-01-07 13:09 ` [RFC PATCH V2 4/10] x86/Hyper-V/Balloon: Convert spin lock ha_lock to mutex lantianyu1986
2020-01-07 13:09 ` [RFC PATCH V2 5/10] x86/Hyper-V/Balloon: Avoid releasing ha_lock when traverse ha_region_list lantianyu1986
2020-01-07 13:09 ` [RFC PATCH V2 6/10] x86/Hyper-V/Balloon: Enable mem hot-remove capability lantianyu1986
2020-01-07 13:09 ` [RFC PATCH V2 7/10] x86/Hyper-V/Balloon: Handle mem hot-remove request lantianyu1986
2020-01-07 13:09 ` [RFC PATCH V2 8/10] x86/Hyper-V/Balloon: Handle request with non-aligned page number lantianyu1986
2020-01-07 13:09 ` [RFC PATCH V2 9/10] x86/Hyper-V/Balloon: Hot add mem in the gaps of hot add region lantianyu1986
2020-01-07 13:09 ` lantianyu1986 [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200107130950.2983-11-Tianyu.Lan@microsoft.com \
    --to=lantianyu1986@gmail.com \
    --cc=Tianyu.Lan@microsoft.com \
    --cc=david@redhat.com \
    --cc=eric.devolder@oracle.com \
    --cc=haiyangz@microsoft.com \
    --cc=kys@microsoft.com \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michael.h.kelley@microsoft.com \
    --cc=sashal@kernel.org \
    --cc=sthemmin@microsoft.com \
    --cc=vkuznets@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).