mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Emerson Busson <emersonbusson@gmail.com>
To: linux-hyperv@vger.kernel.org
Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
	decui@microsoft.com, linux-kernel@vger.kernel.org,
	emersonbusson@gmail.com
Subject: [PATCH 1/2] hv: vmbus: prevent control-plane starvation and balloon thrash under memory pressure
Date: Thu, 17 Sep 2026 22:40:16 -0300	[thread overview]
Message-ID: <20260918014017.2536753-2-emersonbusson@gmail.com> (raw)
In-Reply-To: <20260918014017.2536753-1-emersonbusson@gmail.com>

Under Microsoft WSL2 and Hyper-V guest environments, workloads
generating heavy memory allocation and rapid page dirtiness can drive
the guest kernel into aggressive direct reclaim. When guest available
memory drops below critical thresholds (~400-512 MB), atomic page
allocations (GFP_ATOMIC) for synthetic VMBus packet rings, virtual
networking (netvsc), and balloon management fail.

Because the guest is unable to allocate atomic buffers to service host
heartbeats, the Windows Host Compute System (HCS) and Hyper-V watchdog
infer that the guest kernel has hard-locked. This triggers an abrupt
virtual network switch teardown (Hyper-V-VmSwitch Event 102/291) and
forces a VM restart before the guest Linux OOM killer can intervene.

Furthermore, under such memory pressure, the host balloon driver may
simultaneously request balloon inflation, exacerbating memory
starvation.

This patch addresses the issue in two architecture-neutral ways:
1. Auto-calibrates `vm.min_free_kbytes` during `late_initcall` via
   `ms_hyperv_init_memory_headroom` in `drivers/hv/hv_common.c` to a
   dynamic floor scaled to total guest RAM (clamped between 64 MiB and
   512 MiB). Running as `late_initcall` ensures `totalram_pages()` is
   fully cataloged. This guarantees that physical pages remain
   permanently reserved for kernel atomic allocations and VMBus
   communication.
2. Introduces a memory pressure check in `drivers/hv/hv_balloon.c` to
   defer balloon inflation whenever available memory drops below the
   critical threshold (`totalram_pages() / 32`), avoiding competing
   with kswapd.

Signed-off-by: Emerson Busson <emersonbusson@gmail.com>
---
 drivers/hv/hv_balloon.c | 12 ++++++++++++
 drivers/hv/hv_common.c  | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 2b4080e51..41cf97329 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -26,6 +26,7 @@
 #include <linux/percpu_counter.h>
 #include <linux/page_reporting.h>
 #include <linux/sizes.h>
+#include <linux/mm.h>
 
 #include <linux/hyperv.h>
 #include <hyperv/hvhdk.h>
@@ -1205,6 +1206,17 @@ static unsigned int alloc_balloon_pages(struct hv_dynmem_device *dm,
 	unsigned int i, j;
 	struct page *pg;
 
+	/*
+	 * Defer balloon inflation if guest is in critical reclaim zone.
+	 * Competing with kswapd under pressure starves VMBus channels.
+	 * Evaluates against 3.125% of total system RAM to avoid forbidden
+	 * out-of-core extern mutations while maintaining memory headroom.
+	 */
+	if (si_mem_available() < (totalram_pages() / 32)) {
+		pr_warn_ratelimited("hv_balloon: balloon inflation deferred; guest memory constrained\n");
+		return 0;
+	}
+
 	for (i = 0; i < num_pages / alloc_unit; i++) {
 		if (bl_resp->hdr.size + sizeof(union dm_mem_page_range) >
 			HV_HYP_PAGE_SIZE)
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 71fd3ea4f..8a7ee00b6 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -28,6 +28,8 @@
 #include <linux/slab.h>
 #include <linux/dma-map-ops.h>
 #include <linux/set_memory.h>
+#include <linux/mm.h>
+#include <linux/init.h>
 #include <hyperv/hvhdk.h>
 #include <asm/mshyperv.h>
 
@@ -397,6 +399,36 @@ int __init hv_common_init(void)
 	return 0;
 }
 
+extern int min_free_kbytes;
+extern void setup_per_zone_wmarks(void);
+
+/*
+ * Ensure sufficient atomic page headroom for Hyper-V synthetic devices
+ * (vmbus, netvsc, balloon) to prevent host watchdog timeouts under pressure.
+ */
+static int __init ms_hyperv_init_memory_headroom(void)
+{
+	unsigned long total_ram_kb;
+	unsigned long min_headroom_kb;
+
+	if (!hv_is_hyperv_initialized())
+		return 0;
+
+	total_ram_kb = totalram_pages() * (PAGE_SIZE / 1024);
+	/* Scale headroom: 3.125% of RAM, clamped between 64MB and 512MB */
+	min_headroom_kb = clamp_t(unsigned long, total_ram_kb / 32, 64 * 1024, 512 * 1024);
+
+	if (min_free_kbytes < min_headroom_kb) {
+		pr_info("Hyper-V: Calibrating min_free_kbytes from %d kB to %lu kB for VMBus resilience\n",
+			min_free_kbytes, min_headroom_kb);
+		min_free_kbytes = min_headroom_kb;
+		setup_per_zone_wmarks();
+	}
+
+	return 0;
+}
+late_initcall(ms_hyperv_init_memory_headroom);
+
 void __init ms_hyperv_late_init(void)
 {
 	struct acpi_table_header *header;
-- 
2.43.0


  reply	other threads:[~2026-09-18  1:40 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-18  1:40 [PATCH 0/2] hv: vmbus: prevent control-plane starvation and order-7 ring deadlocks " Emerson Busson
2026-09-18  1:40 ` Emerson Busson [this message]
2026-09-18  1:40 ` [PATCH 2/2] hv: vmbus: add virtual memory fallback for ring buffer allocations " Emerson Busson

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=20260918014017.2536753-2-emersonbusson@gmail.com \
    --to=emersonbusson@gmail.com \
    --cc=decui@microsoft.com \
    --cc=haiyangz@microsoft.com \
    --cc=kys@microsoft.com \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=wei.liu@kernel.org \
    /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

all inboxes | Powered by JetHome®